diff options
author | David Boddie <dboddie@trolltech.com> | 2010-06-16 10:44:02 (GMT) |
---|---|---|
committer | David Boddie <dboddie@trolltech.com> | 2010-06-16 10:44:02 (GMT) |
commit | 9e7f0b9e45cef278c8874539257b4038a0aa6615 (patch) | |
tree | 6f66ec8ea599e348ea550da76612cb3873478a21 /src/gui/painting | |
parent | 700a4826cf6bd755df000cb16c259343efb695cd (diff) | |
parent | 5b5785bc564ccea9f6868d02be3d1080cb5039b9 (diff) | |
download | Qt-9e7f0b9e45cef278c8874539257b4038a0aa6615.zip Qt-9e7f0b9e45cef278c8874539257b4038a0aa6615.tar.gz Qt-9e7f0b9e45cef278c8874539257b4038a0aa6615.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-1 into 4.7
Diffstat (limited to 'src/gui/painting')
-rw-r--r-- | src/gui/painting/qgrayraster.c | 35 | ||||
-rw-r--r-- | src/gui/painting/qgrayraster_p.h | 4 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_raster.cpp | 118 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_x11.cpp | 5 | ||||
-rw-r--r-- | src/gui/painting/qpainter.cpp | 16 | ||||
-rw-r--r-- | src/gui/painting/qrasterdefs_p.h | 6 | ||||
-rw-r--r-- | src/gui/painting/qtransform.cpp | 2 |
7 files changed, 154 insertions, 32 deletions
diff --git a/src/gui/painting/qgrayraster.c b/src/gui/painting/qgrayraster.c index ff2469c..5e7c67a 100644 --- a/src/gui/painting/qgrayraster.c +++ b/src/gui/painting/qgrayraster.c @@ -156,6 +156,7 @@ #define ErrRaster_Invalid_Outline -1 #define ErrRaster_Invalid_Argument -3 #define ErrRaster_Memory_Overflow -4 +#define ErrRaster_OutOfMemory -6 #define QT_FT_BEGIN_HEADER #define QT_FT_END_HEADER @@ -222,7 +223,6 @@ #define DOWNSCALE( x ) ( (x) << ( 6 - PIXEL_BITS ) ) #endif - /*************************************************************************/ /* */ /* TYPE DEFINITIONS */ @@ -1757,8 +1757,7 @@ #ifdef DEBUG_GRAYS fprintf( stderr, "Rotten glyph!\n" ); #endif - /* == Raster_Err_OutOfMemory in qblackraster.c */ - return -6; + return ErrRaster_OutOfMemory; } if ( bottom-top >= ras.band_size ) @@ -1784,7 +1783,7 @@ static int - gray_raster_render( PRaster raster, + gray_raster_render( QT_FT_Raster raster, const QT_FT_Raster_Params* params ) { const QT_FT_Outline* outline = (const QT_FT_Outline*)params->source; @@ -1795,6 +1794,12 @@ if ( !raster || !raster->buffer || !raster->buffer_size ) return ErrRaster_Invalid_Argument; + // If raster object and raster buffer are allocated, but + // raster size isn't of the minimum size, indicate out of + // memory. + if (raster && raster->buffer && raster->buffer_size < MINIMUM_POOL_SIZE ) + return ErrRaster_OutOfMemory; + /* return immediately if the outline is empty */ if ( outline->n_points == 0 || outline->n_contours <= 0 ) return 0; @@ -1874,19 +1879,15 @@ /**** a static object. *****/ static int - gray_raster_new( void * memory, - QT_FT_Raster* araster ) + gray_raster_new( QT_FT_Raster* araster ) { - if (memory) - fprintf(stderr, "gray_raster_new(), memory ignored"); - memory = malloc(sizeof(TRaster)); - if (!memory) { + *araster = malloc(sizeof(TRaster)); + if (!*araster) { *araster = 0; return ErrRaster_Memory_Overflow; } - QT_FT_MEM_ZERO(memory, sizeof(TRaster)); + QT_FT_MEM_ZERO(*araster, sizeof(TRaster)); - *araster = (QT_FT_Raster) memory; return 0; } @@ -1905,10 +1906,9 @@ { PRaster rast = (PRaster)raster; - if ( raster ) { - if ( pool_base && pool_size >= (long)sizeof ( TWorker ) + 2048 ) + if ( pool_base && ( pool_size >= MINIMUM_POOL_SIZE ) ) { PWorker worker = (PWorker)pool_base; @@ -1923,6 +1923,13 @@ rast->band_size = (int)( rast->buffer_size / ( sizeof ( TCell ) * 8 ) ); } + else if ( pool_base) + { // Case when there is a raster pool allocated, but it + // doesn't have the minimum size (and so memory will be reallocated) + rast->buffer = pool_base; + rast->worker = NULL; + rast->buffer_size = pool_size; + } else { rast->buffer = NULL; diff --git a/src/gui/painting/qgrayraster_p.h b/src/gui/painting/qgrayraster_p.h index 4463fc9..ad595b8 100644 --- a/src/gui/painting/qgrayraster_p.h +++ b/src/gui/painting/qgrayraster_p.h @@ -89,6 +89,10 @@ #define QT_FT_EXPORT_VAR( x ) extern x #endif +/* Minimum buffer size for raster object, that accounts + for TWorker and TCell sizes.*/ +#define MINIMUM_POOL_SIZE 4096 + QT_FT_EXPORT_VAR( const QT_FT_Raster_Funcs ) qt_ft_grays_raster; diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 48974e8..f10f12f 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -68,6 +68,7 @@ // #include <private/qrasterizer_p.h> #include <private/qimage_p.h> #include <private/qstatictext_p.h> +#include "qmemrotate_p.h" #include "qpaintengine_raster_p.h" // #include "qbezier_p.h" @@ -344,7 +345,7 @@ void QRasterPaintEngine::init() // The antialiasing raster. d->grayRaster.reset(new QT_FT_Raster); Q_CHECK_PTR(d->grayRaster.data()); - if (qt_ft_grays_raster.raster_new(0, d->grayRaster.data())) + if (qt_ft_grays_raster.raster_new(d->grayRaster.data())) QT_THROW(std::bad_alloc()); // an error creating the raster is caused by a bad malloc @@ -2521,6 +2522,58 @@ QRectF qt_mapRect_non_normalizing(const QRectF &r, const QTransform &t) return QRectF(r.topLeft() * t, r.bottomRight() * t); } +namespace { + enum RotationType { + Rotation90, + Rotation180, + Rotation270, + NoRotation + }; + + inline RotationType qRotationType(const QTransform &transform) + { + QTransform::TransformationType type = transform.type(); + + if (type > QTransform::TxRotate) + return NoRotation; + + if (type == QTransform::TxRotate && qFuzzyIsNull(transform.m11()) && qFuzzyCompare(transform.m12(), qreal(-1)) + && qFuzzyCompare(transform.m21(), qreal(1)) && qFuzzyIsNull(transform.m22())) + return Rotation90; + + if (type == QTransform::TxScale && qFuzzyCompare(transform.m11(), qreal(-1)) && qFuzzyIsNull(transform.m12()) + && qFuzzyIsNull(transform.m21()) && qFuzzyCompare(transform.m22(), qreal(-1))) + return Rotation180; + + if (type == QTransform::TxRotate && qFuzzyIsNull(transform.m11()) && qFuzzyCompare(transform.m12(), qreal(1)) + && qFuzzyCompare(transform.m21(), qreal(-1)) && qFuzzyIsNull(transform.m22())) + return Rotation270; + + return NoRotation; + } + + template <typename T> void memRotate(RotationType type, const T *srcBase, int w, int h, int sbpl, T *dstBase, int dbpl) + { + switch (type) { + case Rotation90: + qt_memrotate90(srcBase, w, h, sbpl, dstBase, dbpl); + break; + case Rotation180: + qt_memrotate180(srcBase, w, h, sbpl, dstBase, dbpl); + break; + case Rotation270: + qt_memrotate270(srcBase, w, h, sbpl, dstBase, dbpl); + break; + case NoRotation: + break; + } + } + + inline bool isPixelAligned(const QRectF &rect) { + return QRectF(rect.toRect()) == rect; + } +} + /*! \reimp */ @@ -2582,6 +2635,58 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe const QClipData *clip = d->clip(); + if (s->matrix.type() > QTransform::TxTranslate + && !stretch_sr + && (!clip || clip->hasRectClip) + && s->intOpacity == 256 + && (d->rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver + || d->rasterBuffer->compositionMode == QPainter::CompositionMode_Source) + && d->rasterBuffer->format == img.format() + && (d->rasterBuffer->format == QImage::Format_RGB16 + || d->rasterBuffer->format == QImage::Format_RGB32 + || (d->rasterBuffer->format == QImage::Format_ARGB32_Premultiplied + && d->rasterBuffer->compositionMode == QPainter::CompositionMode_Source))) + { + RotationType rotationType = qRotationType(s->matrix); + + if (rotationType != NoRotation && img.rect().contains(sr.toAlignedRect())) { + QRectF transformedTargetRect = s->matrix.mapRect(r); + + if ((!(s->renderHints & QPainter::SmoothPixmapTransform) && !(s->renderHints & QPainter::Antialiasing)) + || (isPixelAligned(transformedTargetRect) && isPixelAligned(sr))) + { + QRect clippedTransformedTargetRect = transformedTargetRect.toRect().intersected(clip ? clip->clipRect : d->deviceRect); + if (clippedTransformedTargetRect.isNull()) + return; + + QRectF clippedTargetRect = s->matrix.inverted().mapRect(QRectF(clippedTransformedTargetRect)); + + QRect clippedSourceRect + = QRectF(sr.x() + clippedTargetRect.x() - r.x(), sr.y() + clippedTargetRect.y() - r.y(), + clippedTargetRect.width(), clippedTargetRect.height()).toRect(); + + uint dbpl = d->rasterBuffer->bytesPerLine(); + uint sbpl = img.bytesPerLine(); + + uchar *dst = d->rasterBuffer->buffer(); + uint bpp = img.depth() >> 3; + + const uchar *srcBase = img.bits() + clippedSourceRect.y() * sbpl + clippedSourceRect.x() * bpp; + uchar *dstBase = dst + clippedTransformedTargetRect.y() * dbpl + clippedTransformedTargetRect.x() * bpp; + + uint cw = clippedSourceRect.width(); + uint ch = clippedSourceRect.height(); + + if (d->rasterBuffer->format == QImage::Format_RGB16) + memRotate(rotationType, (quint16 *)srcBase, cw, ch, sbpl, (quint16 *)dstBase, dbpl); + else + memRotate(rotationType, (quint32 *)srcBase, cw, ch, sbpl, (quint32 *)dstBase, dbpl); + + return; + } + } + } + if (s->matrix.type() > QTransform::TxTranslate || stretch_sr) { if (s->flags.fast_images) { @@ -3684,6 +3789,7 @@ void QRasterPaintEngine::drawEllipse(const QRectF &rect) if (((qpen_style(s->lastPen) == Qt::SolidLine && s->flags.fast_pen) || (qpen_style(s->lastPen) == Qt::NoPen && !s->flags.antialiased)) && qMax(rect.width(), rect.height()) < QT_RASTER_COORD_LIMIT + && !rect.isEmpty() && s->matrix.type() <= QTransform::TxScale) // no shear { ensureBrush(); @@ -4080,7 +4186,11 @@ void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline, return; } - const int rasterPoolInitialSize = 8192; + // Initial size for raster pool is MINIMUM_POOL_SIZE so as to + // minimize memory reallocations. However if initial size for + // raster pool is changed for lower value, reallocations will + // occur normally. + const int rasterPoolInitialSize = MINIMUM_POOL_SIZE; int rasterPoolSize = rasterPoolInitialSize; unsigned char *rasterPoolBase; #if defined(Q_WS_WIN64) @@ -4124,7 +4234,7 @@ void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline, error = qt_ft_grays_raster.raster_render(*grayRaster.data(), &rasterParams); // Out of memory, reallocate some more and try again... - if (error == -6) { // -6 is Result_err_OutOfMemory + if (error == -6) { // ErrRaster_OutOfMemory from qgrayraster.c int new_size = rasterPoolSize * 2; if (new_size > 1024 * 1024) { qWarning("QPainter: Rasterization of primitive failed"); @@ -4150,7 +4260,7 @@ void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline, Q_CHECK_PTR(rasterPoolBase); // note: we just freed the old rasterPoolBase. I hope it's not fatal. qt_ft_grays_raster.raster_done(*grayRaster.data()); - qt_ft_grays_raster.raster_new(0, grayRaster.data()); + qt_ft_grays_raster.raster_new(grayRaster.data()); qt_ft_grays_raster.raster_reset(*grayRaster.data(), rasterPoolBase, rasterPoolSize); } else { done = true; diff --git a/src/gui/painting/qpaintengine_x11.cpp b/src/gui/painting/qpaintengine_x11.cpp index b8ad9b3..910b2df 100644 --- a/src/gui/painting/qpaintengine_x11.cpp +++ b/src/gui/painting/qpaintengine_x11.cpp @@ -1453,6 +1453,11 @@ void QX11PaintEngine::drawEllipse(const QRectF &rect) void QX11PaintEngine::drawEllipse(const QRect &rect) { + if (rect.isEmpty()) { + drawRects(&rect, 1); + return; + } + Q_D(QX11PaintEngine); QRect devclip(SHRT_MIN, SHRT_MIN, SHRT_MAX*2 - 1, SHRT_MAX*2 - 1); QRect r(rect); diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 97f754d..d17c711 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -1564,7 +1564,6 @@ void QPainter::initFrom(const QWidget *widget) d->engine->setDirty(QPaintEngine::DirtyBrush); d->engine->setDirty(QPaintEngine::DirtyFont); } - d->state->layoutDirection = widget->layoutDirection(); } @@ -1874,7 +1873,7 @@ bool QPainter::begin(QPaintDevice *pd) QWidget *widget = static_cast<QWidget *>(d->original_device); initFrom(widget); } else { - d->state->layoutDirection = QApplication::layoutDirection(); + d->state->layoutDirection = Qt::LayoutDirectionAuto; // make sure we have a font compatible with the paintdevice d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device()); } @@ -4239,8 +4238,6 @@ void QPainter::drawEllipse(const QRectF &r) return; QRectF rect(r.normalized()); - if (rect.isEmpty()) - return; if (d->extended) { d->extended->drawEllipse(rect); @@ -4282,8 +4279,6 @@ void QPainter::drawEllipse(const QRect &r) return; QRect rect(r.normalized()); - if (rect.isEmpty()) - return; if (d->extended) { d->extended->drawEllipse(rect); @@ -8056,7 +8051,10 @@ start_lengthVariant: Sets the layout direction used by the painter when drawing text, to the specified \a direction. - \sa layoutDirection(), drawText(), {QPainter#Settings}{Settings} + The default is Qt::LayoutDirectionAuto, which will implicitly determine the + direction from the text drawn. + + \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings} */ void QPainter::setLayoutDirection(Qt::LayoutDirection direction) { @@ -8068,12 +8066,12 @@ void QPainter::setLayoutDirection(Qt::LayoutDirection direction) /*! Returns the layout direction used by the painter when drawing text. - \sa setLayoutDirection(), drawText(), {QPainter#Settings}{Settings} + \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings} */ Qt::LayoutDirection QPainter::layoutDirection() const { Q_D(const QPainter); - return d->state ? d->state->layoutDirection : Qt::LeftToRight; + return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto; } QPainterState::QPainterState(const QPainterState *s) diff --git a/src/gui/painting/qrasterdefs_p.h b/src/gui/painting/qrasterdefs_p.h index c33fa57..19a0b16 100644 --- a/src/gui/painting/qrasterdefs_p.h +++ b/src/gui/painting/qrasterdefs_p.h @@ -81,7 +81,6 @@ QT_FT_BEGIN_HEADER - /*************************************************************************/ /* */ /* <Section> */ @@ -837,7 +836,7 @@ QT_FT_BEGIN_HEADER /* A handle (pointer) to a raster object. Each object can be used */ /* independently to convert an outline into a bitmap or pixmap. */ /* */ - typedef struct QT_FT_RasterRec_* QT_FT_Raster; + typedef struct TRaster_ *QT_FT_Raster; /*************************************************************************/ @@ -1118,8 +1117,7 @@ QT_FT_BEGIN_HEADER /* ignored by a given raster implementation. */ /* */ typedef int - (*QT_FT_Raster_NewFunc)( void* memory, - QT_FT_Raster* raster ); + (*QT_FT_Raster_NewFunc)( QT_FT_Raster* raster ); #define QT_FT_Raster_New_Func QT_FT_Raster_NewFunc diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index 423cce9..47b7758 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -1626,7 +1626,7 @@ static QPainterPath mapProjective(const QTransform &transform, const QPainterPat QPainterPath QTransform::map(const QPainterPath &path) const { TransformationType t = inline_type(); - if (t == TxNone || path.isEmpty()) + if (t == TxNone || path.elementCount() == 0) return path; if (t >= TxProject) |