diff options
Diffstat (limited to 'src/gui/painting')
99 files changed, 6708 insertions, 9144 deletions
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 528559c..feef15a 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -46,7 +46,7 @@ HEADERS += \ SOURCES += \ painting/qbezier.cpp \ - painting/qblendfunctions.cpp \ + painting/qblendfunctions.cpp \ painting/qbrush.cpp \ painting/qcolor.cpp \ painting/qcolor_p.cpp \ @@ -57,6 +57,7 @@ SOURCES += \ painting/qmatrix.cpp \ painting/qmemrotate.cpp \ painting/qoutlinemapper.cpp \ + painting/qpaintdevice.cpp \ painting/qpaintengine.cpp \ painting/qpaintengine_alpha.cpp \ painting/qpaintengine_preview.cpp \ @@ -75,13 +76,10 @@ SOURCES += \ painting/qstroker.cpp \ painting/qstylepainter.cpp \ painting/qtessellator.cpp \ - painting/qwindowsurface.cpp \ painting/qtextureglyphcache.cpp \ painting/qtransform.cpp \ + painting/qwindowsurface.cpp \ - DEFINES += QT_RASTER_IMAGEENGINE - win32:DEFINES += QT_RASTER_PAINTENGINE - embedded:DEFINES += QT_RASTER_PAINTENGINE SOURCES += \ painting/qpaintengine_raster.cpp \ painting/qdrawhelper.cpp \ @@ -100,15 +98,9 @@ win32 { painting/qcolormap_win.cpp \ painting/qpaintdevice_win.cpp \ painting/qprintengine_win.cpp \ - painting/qprinterinfo_win.cpp \ - painting/qregion_win.cpp + painting/qprinterinfo_win.cpp + !win32-borland:!wince*:LIBS += -lmsimg32 - contains(QT_CONFIG, direct3d) { - HEADERS += painting/qpaintengine_d3d_p.h - SOURCES += painting/qpaintengine_d3d.cpp - RESOURCES += painting/qpaintengine_d3d.qrc - LIBS += -ldxguid - } } embedded { @@ -132,10 +124,6 @@ embedded { painting/qwindowsurface_raster.cpp \ } -wince* { - SOURCES -= painting/qregion_win.cpp -} - unix:x11 { HEADERS += \ painting/qpaintengine_x11_p.h @@ -162,14 +150,14 @@ unix:x11 { painting/qprintengine_mac.mm \ } -unix:!mac { +unix:!mac:!symbian { HEADERS += \ painting/qprinterinfo_unix_p.h SOURCES += \ painting/qprinterinfo_unix.cpp } -win32|x11|mac|embedded { +win32|x11|mac|embedded|symbian { SOURCES += painting/qbackingstore.cpp HEADERS += painting/qbackingstore_p.h } @@ -186,6 +174,12 @@ embedded { painting/qpaintdevice_qws.cpp } +symbian { + SOURCES += \ + painting/qregion_s60.cpp \ + painting/qcolormap_s60.cpp +} + x11|embedded { contains(QT_CONFIG,qtopia) { DEFINES += QT_NO_CUPS QT_NO_LPR @@ -231,7 +225,7 @@ contains(QMAKE_MAC_XARCH, no) { win32-g++|!win32:!*-icc* { mmx { - mmx_compiler.commands = $$QMAKE_CXX -c -Winline + mmx_compiler.commands = $$QMAKE_CXX -c -Winline mac { mmx_compiler.commands += -Xarch_i386 -mmmx @@ -362,8 +356,27 @@ embedded { SOURCES += painting/qwindowsurface_qws.cpp } -win32:contains(QT_CONFIG, direct3d) { - HEADERS += painting/qwindowsurface_d3d_p.h - SOURCES += painting/qwindowsurface_d3d.cpp + + +symbian { + HEADERS += painting/qwindowsurface_s60_p.h + SOURCES += painting/qwindowsurface_s60.cpp + armccIfdefBlock = \ + "$${LITERAL_HASH}if defined(ARMV6)" \ + "MACRO QT_HAVE_ARMV6" \ + "SOURCEPATH painting" \ + "SOURCE qblendfunctions_armv6_rvct.s" \ + "SOURCE qdrawhelper_armv6_rvct.s" \ + "$${LITERAL_HASH}endif" + + MMP_RULES += armccIfdefBlock + QMAKE_CXXFLAGS.ARMCC *= -O3 +} + +contains(QT_CONFIG, zlib) { + INCLUDEPATH += ../3rdparty/zlib +} else:!contains(QT_CONFIG, no-zlib) { + unix:LIBS_PRIVATE += -lz +# win32:LIBS += libz.lib } diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index b428b1f..e82f36e 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -39,6 +39,9 @@ ** ****************************************************************************/ + +#include "qplatformdefs.h" + #include "qbackingstore_p.h" #include <QtCore/qglobal.h> @@ -556,7 +559,8 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up } const QPoint offset = widget->mapTo(tlw, QPoint()); - if (qt_region_strictContains(dirty, widget->rect().translated(offset))) { + const QRect widgetRect = widget->d_func()->effectiveRectFor(widget->rect()); + if (qt_region_strictContains(dirty, widgetRect.translated(offset))) { if (updateImmediately) sendUpdateRequest(tlw, updateImmediately); return; // Already dirty. @@ -564,7 +568,10 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up if (invalidateBuffer) { const bool eventAlreadyPosted = !dirty.isEmpty(); - dirty += rgn.translated(offset); + if (widget->d_func()->graphicsEffect) + dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect()).translated(offset); + else + dirty += rgn.translated(offset); if (!eventAlreadyPosted || updateImmediately) sendUpdateRequest(tlw, updateImmediately); return; @@ -577,8 +584,12 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up } if (widget->d_func()->inDirtyList) { - if (!qt_region_strictContains(widget->d_func()->dirty, widget->rect())) - widget->d_func()->dirty += rgn; + if (!qt_region_strictContains(widget->d_func()->dirty, widgetRect)) { + if (widget->d_func()->graphicsEffect) + widget->d_func()->dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect()); + else + widget->d_func()->dirty += rgn; + } } else { addDirtyWidget(widget, rgn); } @@ -622,7 +633,8 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget, bool upd return; } - const QRect translatedRect(rect.translated(widget->mapTo(tlw, QPoint()))); + const QRect widgetRect = widget->d_func()->effectiveRectFor(rect); + const QRect translatedRect(widgetRect.translated(widget->mapTo(tlw, QPoint()))); if (qt_region_strictContains(dirty, translatedRect)) { if (updateImmediately) sendUpdateRequest(tlw, updateImmediately); @@ -644,8 +656,8 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget, bool upd } if (widget->d_func()->inDirtyList) { - if (!qt_region_strictContains(widget->d_func()->dirty, rect)) - widget->d_func()->dirty += rect; + if (!qt_region_strictContains(widget->d_func()->dirty, widgetRect)) + widget->d_func()->dirty += widgetRect; } else { addDirtyWidget(widget, rect); } @@ -761,7 +773,7 @@ void QWidgetBackingStore::paintWindowDecoration() engine->setSystemClip(decorationRegion.translated(tlwOffset)); QPainter painter(windowSurface->paintDevice()); - painter.setFont(qApp->font()); + painter.setFont(QApplication::font()); painter.translate(tlwOffset); const int numDirty = managerPrivate->dirtyRegions.size(); @@ -829,6 +841,10 @@ QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel) QWidgetBackingStore::~QWidgetBackingStore() { + for (int c = 0; c < dirtyWidgets.size(); ++c) { + resetWidget(dirtyWidgets.at(c)); + } + delete windowSurface; windowSurface = 0; delete dirtyOnScreenWidgets; @@ -840,7 +856,7 @@ QWidgetBackingStore::~QWidgetBackingStore() void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) { Q_Q(QWidget); - if (!q->isVisible()) + if (!q->isVisible() || (dx == 0 && dy == 0)) return; QWidget *tlw = q->window(); @@ -877,7 +893,7 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) && !isOverlapped(sourceRect) && !isOverlapped(destRect); if (!accelerateMove) { - QRegion parentR(parentRect); + QRegion parentR(effectiveRectFor(parentRect)); if (!extra || !extra->hasMask) { parentR -= newRect; } else { @@ -1350,7 +1366,7 @@ void QWidgetBackingStore::flush(QWidget *widget, QWindowSurface *surface) static inline bool discardInvalidateBufferRequest(QWidget *widget, QTLWExtra *tlwExtra) { Q_ASSERT(widget); - if (qApp && qApp->closingDown()) + if (QApplication::closingDown()) return true; if (!tlwExtra || tlwExtra->inTopLevelResize || !tlwExtra->backingStore) @@ -1381,7 +1397,7 @@ void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const Q const QRect newWidgetRect(q->rect()); const QRect oldWidgetRect(0, 0, oldSize.width(), oldSize.height()); - if (!staticContents) { + if (!staticContents || graphicsEffect) { QRegion staticChildren; QWidgetBackingStore *bs = 0; if (offset.isNull() && (bs = maybeBackingStore())) @@ -1401,19 +1417,19 @@ void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const Q return; // Invalidate newly exposed area of the parent. - if (extra && extra->hasMask) { + if (!graphicsEffect && extra && extra->hasMask) { QRegion parentExpose(extra->mask.translated(oldPos)); parentExpose &= QRect(oldPos, oldSize); if (hasStaticChildren) parentExpose -= data.crect; // Offset is unchanged, safe to do this. q->parentWidget()->d_func()->invalidateBuffer(parentExpose); } else { - if (hasStaticChildren) { + if (hasStaticChildren && !graphicsEffect) { QRegion parentExpose(QRect(oldPos, oldSize)); parentExpose -= data.crect; // Offset is unchanged, safe to do this. q->parentWidget()->d_func()->invalidateBuffer(parentExpose); } else { - q->parentWidget()->d_func()->invalidateBuffer(QRect(oldPos, oldSize)); + q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(QRect(oldPos, oldSize))); } } return; @@ -1471,7 +1487,7 @@ void QWidgetPrivate::invalidateBuffer(const QRegion &rgn) QRegion wrgn(rgn); wrgn &= clipRect(); - if (extra && extra->hasMask) + if (!graphicsEffect && extra && extra->hasMask) wrgn &= extra->mask; if (wrgn.isEmpty()) return; @@ -1499,7 +1515,7 @@ void QWidgetPrivate::invalidateBuffer(const QRect &rect) if (wRect.isEmpty()) return; - if (!extra || !extra->hasMask) { + if (graphicsEffect || !extra || !extra->hasMask) { tlwExtra->backingStore->markDirty(wRect, q, false, true); return; } @@ -1528,7 +1544,8 @@ void QWidgetPrivate::repaint_sys(const QRegion &rgn) // QGLWidget does not support partial updates if: // 1) The context is double buffered // 2) The context is single buffered and auto-fill background is enabled. - const bool noPartialUpdateSupport = (engine && engine->type() == QPaintEngine::OpenGL) + const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL + || engine->type() == QPaintEngine::OpenGL2)) && (usesDoubleBufferedGLContext || q->autoFillBackground()); QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn); diff --git a/src/gui/painting/qbackingstore_p.h b/src/gui/painting/qbackingstore_p.h index 9645303..f55cfcd 100644 --- a/src/gui/painting/qbackingstore_p.h +++ b/src/gui/painting/qbackingstore_p.h @@ -144,9 +144,13 @@ private: inline void addDirtyWidget(QWidget *widget, const QRegion &rgn) { if (widget && !widget->d_func()->inDirtyList && !widget->data->in_destructor) { - widget->d_func()->dirty = rgn; + QWidgetPrivate *widgetPrivate = widget->d_func(); + if (widgetPrivate->graphicsEffect) + widgetPrivate->dirty = widgetPrivate->effectiveRectFor(rgn.boundingRect()); + else + widgetPrivate->dirty = rgn; dirtyWidgets.append(widget); - widget->d_func()->inDirtyList = true; + widgetPrivate->inDirtyList = true; } } diff --git a/src/gui/painting/qbezier.cpp b/src/gui/painting/qbezier.cpp index 4ee54f4..fe1766e 100644 --- a/src/gui/painting/qbezier.cpp +++ b/src/gui/painting/qbezier.cpp @@ -127,13 +127,13 @@ static inline void flattenBezierWithoutInflections(QBezier &bez, qreal dy = bez.y2 - bez.y1; qreal normalized = qSqrt(dx * dx + dy * dy); - if (qFuzzyCompare(normalized + 1, 1)) + if (qFuzzyIsNull(normalized)) break; qreal d = qAbs(dx * (bez.y3 - bez.y2) - dy * (bez.x3 - bez.x2)); qreal t = qSqrt(4. / 3. * normalized * flatness / d); - if (t > 1 || qFuzzyCompare(t, (qreal)1.)) + if (t > 1 || qFuzzyIsNull(t - (qreal)1.)) break; bez.parameterSplitLeft(t, &left); p->append(bez.pt1()); @@ -144,19 +144,19 @@ static inline void flattenBezierWithoutInflections(QBezier &bez, static inline int quadraticRoots(qreal a, qreal b, qreal c, qreal *x1, qreal *x2) { - if (qFuzzyCompare(a + 1, 1)) { - if (qFuzzyCompare(b + 1, 1)) + if (qFuzzyIsNull(a)) { + if (qFuzzyIsNull(b)) return 0; *x1 = *x2 = (-c / b); return 1; } else { const qreal det = b * b - 4 * a * c; - if (qFuzzyCompare(det + 1, 1)) { + if (qFuzzyIsNull(det)) { *x1 = *x2 = -b / (2 * a); return 1; } if (det > 0) { - if (qFuzzyCompare(b + 1, 1)) { + if (qFuzzyIsNull(b)) { *x2 = qSqrt(-c / a); *x1 = -(*x2); return 2; @@ -187,7 +187,7 @@ static inline bool findInflections(qreal a, qreal b, qreal c, *t1 = r2; *t2 = r1; } - if (!qFuzzyCompare(a + 1, 1)) + if (!qFuzzyIsNull(a)) *tCups = 0.5 * (-b / a); else *tCups = 2; @@ -243,7 +243,7 @@ void QBezier::addToPolygonMixed(QPolygonF *polygon) const qreal b = 6 * (ay * cx - ax * cy); qreal c = 2 * (by * cx - bx * cy); - if ((qFuzzyCompare(a + 1, 1) && qFuzzyCompare(b + 1, 1)) || + if ((qFuzzyIsNull(a) && qFuzzyIsNull(b)) || (b * b - 4 * a *c) < 0) { QBezier bez(*this); flattenBezierWithoutInflections(bez, polygon); @@ -447,7 +447,7 @@ static ShiftResult shift(const QBezier *orig, QBezier *shifted, qreal offset, qr qreal r = 1.0 + prev_normal.x() * next_normal.x() + prev_normal.y() * next_normal.y(); - if (qFuzzyCompare(r + 1, 1)) { + if (qFuzzyIsNull(r)) { points_shifted[i] = points[i] + offset * prev_normal; } else { qreal k = offset / r; @@ -477,12 +477,12 @@ static bool addCircle(const QBezier *b, qreal offset, QBezier *o) normals[0] = QPointF(b->y2 - b->y1, b->x1 - b->x2); qreal dist = qSqrt(normals[0].x()*normals[0].x() + normals[0].y()*normals[0].y()); - if (qFuzzyCompare(dist + 1, 1)) + if (qFuzzyIsNull(dist)) return false; normals[0] /= dist; normals[2] = QPointF(b->y4 - b->y3, b->x3 - b->x4); dist = qSqrt(normals[2].x()*normals[2].x() + normals[2].y()*normals[2].y()); - if (qFuzzyCompare(dist + 1, 1)) + if (qFuzzyIsNull(dist)) return false; normals[2] /= dist; @@ -673,10 +673,10 @@ static int IntersectBB(const QBezier &a, const QBezier &b) #ifdef QDEBUG_BEZIER static QDebug operator<<(QDebug dbg, const QBezier &bz) { - dbg <<"["<<bz.x1<<", "<<bz.y1<<"], " - <<"["<<bz.x2<<", "<<bz.y2<<"], " - <<"["<<bz.x3<<", "<<bz.y3<<"], " - <<"["<<bz.x4<<", "<<bz.y4<<"]"; + dbg << '[' << bz.x1<< ", " << bz.y1 << "], " + << '[' << bz.x2 <<", " << bz.y2 << "], " + << '[' << bz.x3 <<", " << bz.y3 << "], " + << '[' << bz.x4 <<", " << bz.y4 << ']'; return dbg; } #endif @@ -1022,7 +1022,7 @@ int QBezier::stationaryYPoints(qreal &t0, qreal &t1) const QList<qreal> result; - if (qFuzzyCompare(reciprocal + 1, 1)) { + if (qFuzzyIsNull(reciprocal)) { t0 = -b / (2 * a); return 1; } else if (reciprocal > 0) { diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp index 08f6783..8b25a91 100644 --- a/src/gui/painting/qblendfunctions.cpp +++ b/src/gui/painting/qblendfunctions.cpp @@ -104,6 +104,37 @@ struct Blend_RGB16_on_RGB16_ConstAlpha { quint32 m_ialpha; }; +struct Blend_ARGB24_on_RGB16_SourceAlpha { + inline void write(quint16 *dst, const qargb8565 &src) { + const uint alpha = src.alpha(); + if (alpha) { + quint16 s = src.rawValue16(); + if (alpha < 255) + s += BYTE_MUL_RGB16(*dst, 255 - alpha); + *dst = s; + } + } +}; + +struct Blend_ARGB24_on_RGB16_SourceAndConstAlpha { + inline Blend_ARGB24_on_RGB16_SourceAndConstAlpha(quint32 alpha) { + m_alpha = (alpha * 255) >> 8; + } + + inline void write(quint16 *dst, qargb8565 src) { + src = src.byte_mul(src.alpha(m_alpha)); + const uint alpha = src.alpha(); + if (alpha) { + quint16 s = src.rawValue16(); + if (alpha < 255) + s += BYTE_MUL_RGB16(*dst, 255 - alpha); + *dst = s; + } + } + + quint32 m_alpha; +}; + struct Blend_ARGB32_on_RGB16_SourceAlpha { inline void write(quint16 *dst, quint32 src) { const quint8 alpha = qAlpha(src); @@ -237,6 +268,32 @@ void qt_scale_image_rgb16_on_rgb16(uchar *destPixels, int dbpl, } } +void qt_scale_image_argb24_on_rgb16(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + const QRectF &targetRect, + const QRectF &sourceRect, + const QRect &clip, + int const_alpha) +{ +#ifdef QT_DEBUG_DRAW + printf("qt_scale_argb24_on_rgb16: dst=(%p, %d), src=(%p, %d), target=(%d, %d), [%d x %d], src=(%d, %d) [%d x %d] alpha=%d\n", + destPixels, dbpl, srcPixels, sbpl, + targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), + sourceRect.x(), sourceRect.y(), sourceRect.width(), sourceRect.height(), + const_alpha); +#endif + if (const_alpha == 256) { + Blend_ARGB24_on_RGB16_SourceAlpha noAlpha; + qt_scale_image_16bit<qargb8565>(destPixels, dbpl, srcPixels, sbpl, + targetRect, sourceRect, clip, noAlpha); + } else { + Blend_ARGB24_on_RGB16_SourceAndConstAlpha constAlpha(const_alpha); + qt_scale_image_16bit<qargb8565>(destPixels, dbpl, srcPixels, sbpl, + targetRect, sourceRect, clip, constAlpha); + } +} + + void qt_scale_image_argb32_on_rgb16(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, const QRectF &targetRect, @@ -317,9 +374,9 @@ template <typename T> void qt_blend_argb24_on_rgb16(uchar *destPixels, int dbpl, const uchar *src = srcPixels + y * sbpl; const uchar *srcEnd = src + srcOffset; while (src < srcEnd) { -#if defined(QT_ARCH_ARM) || defined(QT_ARCH_POWERPC) || defined(QT_ARCH_SH) || (defined(QT_ARCH_WINDOWSCE) && !defined(_X86_)) +#if defined(QT_ARCH_ARM) || defined(QT_ARCH_POWERPC) || defined(QT_ARCH_SH) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_WINDOWSCE) && !defined(_X86_)) // non-16-bit aligned memory access is not possible on PowerPC, - // ARM <v6 (QT_ARCH_ARMV6) & SH + // ARM <v6 (QT_ARCH_ARMV6) & SH & AVR32 quint16 spix = (quint16(src[2])<<8) + src[1]; #else quint16 spix = *(quint16 *) (src + 1); @@ -513,11 +570,10 @@ static void qt_blend_argb32_on_argb32(uchar *destPixels, int dbpl, for (int y=0; y<h; ++y) { for (int x=0; x<w; ++x) { uint s = src[x]; - if ((s & 0xff000000) == 0xff000000) + if (s >= 0xff000000) dst[x] = s; - else { + else if (s != 0) dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); - } } dst = (quint32 *)(((uchar *) dst) + dbpl); src = (const quint32 *)(((const uchar *) src) + sbpl); @@ -737,7 +793,350 @@ void qt_scale_image_argb32_on_argb32(uchar *destPixels, int dbpl, } } +struct QTransformImageVertex +{ + qreal x, y, u, v; // destination coordinates (x, y) and source coordinates (u, v) +}; + +template <class SrcT, class DestT, class Blender> +void qt_transform_image_rasterize(DestT *destPixels, int dbpl, + const SrcT *srcPixels, int sbpl, + const QTransformImageVertex &topLeft, const QTransformImageVertex &bottomLeft, + const QTransformImageVertex &topRight, const QTransformImageVertex &bottomRight, + const QRect &sourceRect, + const QRect &clip, + qreal topY, qreal bottomY, + int dudx, int dvdx, int dudy, int dvdy, int u0, int v0, + Blender blender) +{ + int fromY = qMax(qRound(topY), clip.top()); + int toY = qMin(qRound(bottomY), clip.top() + clip.height()); + if (fromY >= toY) + return; + + qreal leftSlope = (bottomLeft.x - topLeft.x) / (bottomLeft.y - topLeft.y); + qreal rightSlope = (bottomRight.x - topRight.x) / (bottomRight.y - topRight.y); + int dx_l = int(leftSlope * 0x10000); + int dx_r = int(rightSlope * 0x10000); + int x_l = int((topLeft.x + (0.5 + fromY - topLeft.y) * leftSlope + 0.5) * 0x10000); + int x_r = int((topRight.x + (0.5 + fromY - topRight.y) * rightSlope + 0.5) * 0x10000); + + int fromX, toX, x1, x2, u, v, i, ii; + DestT *line; + for (int y = fromY; y < toY; ++y) { + line = reinterpret_cast<DestT *>(reinterpret_cast<uchar *>(destPixels) + y * dbpl); + + fromX = qMax(x_l >> 16, clip.left()); + toX = qMin(x_r >> 16, clip.left() + clip.width()); + if (fromX < toX) { + // Because of rounding, we can get source coordinates outside the source image. + // Clamp these coordinates to the source rect to avoid segmentation fault and + // garbage on the screen. + + // Find the first pixel on the current scan line where the source coordinates are within the source rect. + x1 = fromX; + u = x1 * dudx + y * dudy + u0; + v = x1 * dvdx + y * dvdy + v0; + for (; x1 < toX; ++x1) { + int uu = u >> 16; + int vv = v >> 16; + if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width() + && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) { + break; + } + u += dudx; + v += dvdx; + } + + // Find the last pixel on the current scan line where the source coordinates are within the source rect. + x2 = toX; + u = (x2 - 1) * dudx + y * dudy + u0; + v = (x2 - 1) * dvdx + y * dvdy + v0; + for (; x2 > x1; --x2) { + int uu = u >> 16; + int vv = v >> 16; + if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width() + && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) { + break; + } + u -= dudx; + v -= dvdx; + } + + // Set up values at the beginning of the scan line. + u = fromX * dudx + y * dudy + u0; + v = fromX * dvdx + y * dvdy + v0; + line += fromX; + + // Beginning of the scan line, with per-pixel checks. + i = x1 - fromX; + while (i) { + int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1); + int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1); + blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + vv * sbpl)[uu]); + u += dudx; + v += dvdx; + ++line; + --i; + } + + // Middle of the scan line, without checks. + // Manual loop unrolling. + i = x2 - x1; + ii = i >> 3; + while (ii) { + blender.write(&line[0], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; + blender.write(&line[1], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; + blender.write(&line[2], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; + blender.write(&line[3], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; + blender.write(&line[4], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; + blender.write(&line[5], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; + blender.write(&line[6], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; + blender.write(&line[7], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; + line += 8; + --ii; + } + switch (i & 7) { + case 7: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; + case 6: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; + case 5: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; + case 4: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; + case 3: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; + case 2: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; + case 1: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; + } + + // End of the scan line, with per-pixel checks. + i = toX - x2; + while (i) { + int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1); + int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1); + blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + vv * sbpl)[uu]); + u += dudx; + v += dvdx; + ++line; + --i; + } + } + x_l += dx_l; + x_r += dx_r; + } +} + +template <class SrcT, class DestT, class Blender> +void qt_transform_image(DestT *destPixels, int dbpl, + const SrcT *srcPixels, int sbpl, + const QRectF &targetRect, + const QRectF &sourceRect, + const QRect &clip, + const QTransform &targetRectTransform, + Blender blender) +{ + enum Corner + { + TopLeft, + TopRight, + BottomRight, + BottomLeft + }; + + // map source rectangle to destination. + QTransformImageVertex v[4]; + v[TopLeft].u = v[BottomLeft].u = sourceRect.left(); + v[TopLeft].v = v[TopRight].v = sourceRect.top(); + v[TopRight].u = v[BottomRight].u = sourceRect.right(); + v[BottomLeft].v = v[BottomRight].v = sourceRect.bottom(); + targetRectTransform.map(targetRect.left(), targetRect.top(), &v[TopLeft].x, &v[TopLeft].y); + targetRectTransform.map(targetRect.right(), targetRect.top(), &v[TopRight].x, &v[TopRight].y); + targetRectTransform.map(targetRect.left(), targetRect.bottom(), &v[BottomLeft].x, &v[BottomLeft].y); + targetRectTransform.map(targetRect.right(), targetRect.bottom(), &v[BottomRight].x, &v[BottomRight].y); + + // find topmost vertex. + int topmost = 0; + for (int i = 1; i < 4; ++i) { + if (v[i].y < v[topmost].y) + topmost = i; + } + // rearrange array such that topmost vertex is at index 0. + switch (topmost) { + case 1: + { + QTransformImageVertex t = v[0]; + for (int i = 0; i < 3; ++i) + v[i] = v[i+1]; + v[3] = t; + } + break; + case 2: + qSwap(v[0], v[2]); + qSwap(v[1], v[3]); + break; + case 3: + { + QTransformImageVertex t = v[3]; + for (int i = 3; i > 0; --i) + v[i] = v[i-1]; + v[0] = t; + } + break; + } + + // if necessary, swap vertex 1 and 3 such that 1 is to the left of 3. + qreal dx1 = v[1].x - v[0].x; + qreal dy1 = v[1].y - v[0].y; + qreal dx2 = v[3].x - v[0].x; + qreal dy2 = v[3].y - v[0].y; + if (dx1 * dy2 - dx2 * dy1 > 0) + qSwap(v[1], v[3]); + + QTransformImageVertex u = {v[1].x - v[0].x, v[1].y - v[0].y, v[1].u - v[0].u, v[1].v - v[0].v}; + QTransformImageVertex w = {v[2].x - v[0].x, v[2].y - v[0].y, v[2].u - v[0].u, v[2].v - v[0].v}; + + qreal det = u.x * w.y - u.y * w.x; + if (det == 0) + return; + + qreal invDet = 1.0 / det; + qreal m11, m12, m21, m22, mdx, mdy; + + m11 = (u.u * w.y - u.y * w.u) * invDet; + m12 = (u.x * w.u - u.u * w.x) * invDet; + m21 = (u.v * w.y - u.y * w.v) * invDet; + m22 = (u.x * w.v - u.v * w.x) * invDet; + mdx = v[0].u - m11 * v[0].x - m12 * v[0].y; + mdy = v[0].v - m21 * v[0].x - m22 * v[0].y; + + int dudx = int(m11 * 0x10000); + int dvdx = int(m21 * 0x10000); + int dudy = int(m12 * 0x10000); + int dvdy = int(m22 * 0x10000); + int u0 = qCeil((0.5 * m11 + 0.5 * m12 + mdx) * 0x10000) - 1; + int v0 = qCeil((0.5 * m21 + 0.5 * m22 + mdy) * 0x10000) - 1; + + int x1 = qFloor(sourceRect.left()); + int y1 = qFloor(sourceRect.top()); + int x2 = qCeil(sourceRect.right()); + int y2 = qCeil(sourceRect.bottom()); + QRect sourceRectI(x1, y1, x2 - x1, y2 - y1); + + // rasterize trapezoids. + if (v[1].y < v[3].y) { + qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[0], v[3], sourceRectI, clip, v[0].y, v[1].y, dudx, dvdx, dudy, dvdy, u0, v0, blender); + qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[0], v[3], sourceRectI, clip, v[1].y, v[3].y, dudx, dvdx, dudy, dvdy, u0, v0, blender); + qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[3], v[2], sourceRectI, clip, v[3].y, v[2].y, dudx, dvdx, dudy, dvdy, u0, v0, blender); + } else { + qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[0], v[3], sourceRectI, clip, v[0].y, v[3].y, dudx, dvdx, dudy, dvdy, u0, v0, blender); + qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[3], v[2], sourceRectI, clip, v[3].y, v[1].y, dudx, dvdx, dudy, dvdy, u0, v0, blender); + qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[3], v[2], sourceRectI, clip, v[1].y, v[2].y, dudx, dvdx, dudy, dvdy, u0, v0, blender); + } +} + +void qt_transform_image_rgb16_on_rgb16(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + const QRectF &targetRect, + const QRectF &sourceRect, + const QRect &clip, + const QTransform &targetRectTransform, + int const_alpha) +{ + if (const_alpha == 256) { + Blend_RGB16_on_RGB16_NoAlpha noAlpha; + qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl, + reinterpret_cast<const quint16 *>(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, noAlpha); + } else { + Blend_RGB16_on_RGB16_ConstAlpha constAlpha(const_alpha); + qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl, + reinterpret_cast<const quint16 *>(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, constAlpha); + } +} + +void qt_transform_image_argb24_on_rgb16(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + const QRectF &targetRect, + const QRectF &sourceRect, + const QRect &clip, + const QTransform &targetRectTransform, + int const_alpha) +{ + if (const_alpha == 256) { + Blend_ARGB24_on_RGB16_SourceAlpha noAlpha; + qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl, + reinterpret_cast<const qargb8565 *>(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, noAlpha); + } else { + Blend_ARGB24_on_RGB16_SourceAndConstAlpha constAlpha(const_alpha); + qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl, + reinterpret_cast<const qargb8565 *>(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, constAlpha); + } +} + + +void qt_transform_image_argb32_on_rgb16(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + const QRectF &targetRect, + const QRectF &sourceRect, + const QRect &clip, + const QTransform &targetRectTransform, + int const_alpha) +{ + if (const_alpha == 256) { + Blend_ARGB32_on_RGB16_SourceAlpha noAlpha; + qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl, + reinterpret_cast<const quint32 *>(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, noAlpha); + } else { + Blend_ARGB32_on_RGB16_SourceAndConstAlpha constAlpha(const_alpha); + qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl, + reinterpret_cast<const quint32 *>(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, constAlpha); + } +} + + +void qt_transform_image_rgb32_on_rgb32(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + const QRectF &targetRect, + const QRectF &sourceRect, + const QRect &clip, + const QTransform &targetRectTransform, + int const_alpha) +{ + if (const_alpha == 256) { + Blend_RGB32_on_RGB32_NoAlpha noAlpha; + qt_transform_image(reinterpret_cast<quint32 *>(destPixels), dbpl, + reinterpret_cast<const quint32 *>(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, noAlpha); + } else { + Blend_RGB32_on_RGB32_ConstAlpha constAlpha(const_alpha); + qt_transform_image(reinterpret_cast<quint32 *>(destPixels), dbpl, + reinterpret_cast<const quint32 *>(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, constAlpha); + } +} +void qt_transform_image_argb32_on_argb32(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + const QRectF &targetRect, + const QRectF &sourceRect, + const QRect &clip, + const QTransform &targetRectTransform, + int const_alpha) +{ + if (const_alpha == 256) { + Blend_ARGB32_on_ARGB32_SourceAlpha sourceAlpha; + qt_transform_image(reinterpret_cast<quint32 *>(destPixels), dbpl, + reinterpret_cast<const quint32 *>(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, sourceAlpha); + } else { + Blend_ARGB32_on_ARGB32_SourceAndConstAlpha constAlpha(const_alpha); + qt_transform_image(reinterpret_cast<quint32 *>(destPixels), dbpl, + reinterpret_cast<const quint32 *>(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, constAlpha); + } +} SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] = { { // Format_Invalid @@ -875,7 +1274,7 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] = 0, // Format_ARGB32, qt_scale_image_argb32_on_rgb16, // Format_ARGB32_Premultiplied, qt_scale_image_rgb16_on_rgb16, // Format_RGB16, - 0, // Format_ARGB8565_Premultiplied, + qt_scale_image_argb24_on_rgb16, // Format_ARGB8565_Premultiplied, 0, // Format_RGB666, 0, // Format_ARGB6666_Premultiplied, 0, // Format_RGB555, @@ -1322,5 +1721,295 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] = } }; +SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFormats] = { + { // Format_Invalid + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_Mono + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_MonoLSB + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_Indexed8 + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_RGB32 + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + qt_transform_image_rgb32_on_rgb32, // Format_RGB32, + 0, // Format_ARGB32, + qt_transform_image_argb32_on_argb32, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_ARGB32 + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_ARGB32_Premultiplied + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + qt_transform_image_rgb32_on_rgb32, // Format_RGB32, + 0, // Format_ARGB32, + qt_transform_image_argb32_on_argb32, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_RGB16 + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + qt_transform_image_argb32_on_rgb16, // Format_ARGB32_Premultiplied, + qt_transform_image_rgb16_on_rgb16, // Format_RGB16, + qt_transform_image_argb24_on_rgb16, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_ARGB8565_Premultiplied + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_RGB666 + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_ARGB6666_Premultiplied + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_RGB555 + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_ARGB8555_Premultiplied + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_RGB888 + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_RGB444 + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_ARGB4444_Premultiplied + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + } +}; QT_END_NAMESPACE diff --git a/src/gui/painting/qblendfunctions_armv6_rvct.s b/src/gui/painting/qblendfunctions_armv6_rvct.s new file mode 100644 index 0000000..0d413cb --- /dev/null +++ b/src/gui/painting/qblendfunctions_armv6_rvct.s @@ -0,0 +1,222 @@ +;/**************************************************************************** +;** +;** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +;** Contact: Nokia Corporation (qt-info@nokia.com) +;** +;** This file is part of the QtGui module of the Qt Toolkit. +;** +;** $QT_BEGIN_LICENSE:LGPL$ +;** No Commercial Usage +;** This file contains pre-release code and may not be distributed. +;** You may use this file in accordance with the terms and conditions +;** contained in the either Technology Preview License Agreement or the +;** Beta Release License Agreement. +;** +;** GNU Lesser General Public License Usage +;** Alternatively, this file may be used under the terms of the GNU Lesser +;** General Public License version 2.1 as published by the Free Software +;** Foundation and appearing in the file LICENSE.LGPL included in the +;** packaging of this file. Please review the following information to +;** ensure the GNU Lesser General Public License version 2.1 requirements +;** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +;** +;** In addition, as a special exception, Nokia gives you certain +;** additional rights. These rights are described in the Nokia Qt LGPL +;** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +;** package. +;** +;** GNU General Public License Usage +;** Alternatively, this file may be used under the terms of the GNU +;** General Public License version 3.0 as published by the Free Software +;** Foundation and appearing in the file LICENSE.GPL included in the +;** packaging of this file. Please review the following information to +;** ensure the GNU General Public License version 3.0 requirements will be +;** met: http://www.gnu.org/copyleft/gpl.html. +;** +;** If you are unsure which license is appropriate for your use, please +;** contact the sales department at http://qt.nokia.com/contact. +;** $QT_END_LICENSE$ +;** +;****************************************************************************/ + +; +; W A R N I N G +; ------------- +; +; This file is not part of the Qt API. It exists purely as an +; implementation detail. This header file may change from version to +; version without notice, or even be removed. +; +; We mean it. +; + + + ARM + PRESERVE8 + + INCLUDE qdrawhelper_armv6_rvct.inc + + +;----------------------------------------------------------------------------- +; qt_blend_rgb32_on_rgb32_arm +; +; @brief +; +; @param dest Destination pixels (r0) +; @param dbpl Destination bytes per line (r1) +; @param src Source pixels (r2) +; @param sbpl Source bytes per line (r3) +; @param w Width (s0 -> r4) +; @param h Height (s1 -> r5) +; @param const_alpha Constant alpha (s2 -> r6) +; +;--------------------------------------------------------------------------- +qt_blend_rgb32_on_rgb32_armv6 Function + stmfd sp!, {r4-r12, r14} + + ; read arguments off the stack + add r8, sp, #10 * 4 + ldmia r8, {r9-r11} + + ; Reorganize registers + + mov r4, r10 + mov r5, r1 + mov r6, r3 + + mov r1, r2 + mov r2, r9 + mov r3, r11 + + ; Now we have registers + ; @param dest Destination pixels (r0) + ; @param src Source pixels (r1) + ; @param w Width (r2) + ; @param const_alpha Constant alpha (r3) + ; @param h Height (r4) + ; @param dbpl Destination bytes per line (r5) + ; @param sbpl Source bytes per line (r6) + + cmp r3, #256 ; test if we have fully opaque constant alpha value + bne rgb32_blend_const_alpha ; branch if not + +rgb32_blend_loop + + subs r4, r4, #1 + bmi rgb32_blend_exit ; while(h--) + +rgb321 PixCpySafe r0, r1, r2 + + add r0, r0, r5 ; dest = dest + dbpl + add r1, r1, r6 ; src = src + sbpl + + b rgb32_blend_loop + + +rgb32_blend_const_alpha + + ;ldr r14, =ComponentHalf ; load 0x800080 to r14 + mov r14, #0x800000 + add r14, r14, #0x80 + + sub r3, r3, #1 ; const_alpha -= 1; + +rgb32_blend_loop_const_alpha + + subs r4, r4, #1 + bmi rgb32_blend_exit ; while(h--) + +rgb322 BlendRowSafe PixelSourceOverConstAlpha + + add r0, r0, r5 ; dest = dest + dbpl + add r1, r1, r6 ; src = src + sbpl + + b rgb32_blend_loop_const_alpha + +rgb32_blend_exit + + ldmfd sp!, {r4-r12, pc} ; pop and return + + + +;----------------------------------------------------------------------------- +; qt_blend_argb32_on_argb32_arm +; +; @brief +; +; @param dest Destination pixels (r0) +; @param dbpl Destination bytes per line (r1) +; @param src Source pixels (r2) +; @param sbpl Source bytes per line (r3) +; @param w Width (s0 -> r4) +; @param h Height (s1 -> r5) +; @param const_alpha Constant alpha (s2 -> r6) +; +;--------------------------------------------------------------------------- +qt_blend_argb32_on_argb32_armv6 Function + stmfd sp!, {r4-r12, r14} + + ; read arguments off the stack + add r8, sp, #10 * 4 + ldmia r8, {r9-r11} + + ; Reorganize registers + + mov r4, r10 + mov r5, r1 + mov r6, r3 + + mov r1, r2 + mov r2, r9 + mov r3, r11 + + ; Now we have registers + ; @param dest Destination pixels (r0) + ; @param src Source pixels (r1) + ; @param w Width (r2) + ; @param const_alpha Constant alpha (r3) + ; @param h Height (r4) + ; @param dbpl Destination bytes per line (r5) + ; @param sbpl Source bytes per line (r6) + + ;ldr r14, =ComponentHalf ; load 0x800080 to r14 + mov r14, #0x800000 + add r14, r14, #0x80 + + cmp r3, #256 ; test if we have fully opaque constant alpha value + bne argb32_blend_const_alpha ; branch if not + +argb32_blend_loop + + subs r4, r4, #1 + bmi argb32_blend_exit ; while(h--) + +argb321 BlendRowSafe PixelSourceOver + + add r0, r0, r5 ; dest = dest + dbpl + add r1, r1, r6 ; src = src + sbpl + + b argb32_blend_loop + +argb32_blend_const_alpha + + sub r3, r3, #1 ; const_alpha -= 1; + +argb32_blend_loop_const_alpha + + subs r4, r4, #1 + bmi argb32_blend_exit ; while(h--) + +argb322 BlendRowSafe PixelSourceOverConstAlpha + + add r0, r0, r5 ; dest = dest + dbpl + add r1, r1, r6 ; src = src + sbpl + + b argb32_blend_loop_const_alpha + +argb32_blend_exit + + ldmfd sp!, {r4-r12, pc} ; pop and return + + + END ; File end diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index 5224dc3..1de641b 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -217,11 +217,11 @@ struct QTexturedBrushData : public QBrushData // returns true if the brush has a pixmap (or bitmap) set as the // brush texture, false otherwise -bool qHasPixmapTexture(const QBrush& brush) +bool Q_GUI_EXPORT qHasPixmapTexture(const QBrush& brush) { if (brush.style() != Qt::TexturePattern) return false; - QTexturedBrushData *tx_data = static_cast<QTexturedBrushData *>(brush.d); + QTexturedBrushData *tx_data = static_cast<QTexturedBrushData *>(brush.d.data()); return tx_data->m_has_pixmap_texture; } @@ -230,10 +230,35 @@ struct QGradientBrushData : public QBrushData QGradient gradient; }; +struct QBrushDataPointerDeleter +{ + static inline void deleteData(QBrushData *d) + { + switch (d->style) { + case Qt::TexturePattern: + delete static_cast<QTexturedBrushData*>(d); + break; + case Qt::LinearGradientPattern: + case Qt::RadialGradientPattern: + case Qt::ConicalGradientPattern: + delete static_cast<QGradientBrushData*>(d); + break; + default: + delete d; + } + } + + static inline void cleanup(QBrushData *d) + { + if (d && !d->ref.deref()) { + deleteData(d); + } + } +}; /*! \class QBrush - \ingroup multimedia + \ingroup painting \ingroup shared \brief The QBrush class defines the fill pattern of shapes drawn @@ -364,20 +389,20 @@ void QBrush::init(const QColor &color, Qt::BrushStyle style) { switch(style) { case Qt::NoBrush: - d = nullBrushInstance(); + d.reset(nullBrushInstance()); d->ref.ref(); if (d->color != color) setColor(color); return; case Qt::TexturePattern: - d = new QTexturedBrushData; + d.reset(new QTexturedBrushData); break; case Qt::LinearGradientPattern: case Qt::RadialGradientPattern: case Qt::ConicalGradientPattern: - d = new QGradientBrushData; + d.reset(new QGradientBrushData); break; default: - d = new QBrushData; + d.reset(new QBrushData); break; } d->ref = 1; @@ -391,8 +416,8 @@ void QBrush::init(const QColor &color, Qt::BrushStyle style) */ QBrush::QBrush() + : d(nullBrushInstance()) { - d = nullBrushInstance(); Q_ASSERT(d); d->ref.ref(); } @@ -435,7 +460,7 @@ QBrush::QBrush(Qt::BrushStyle style) if (qbrush_check_type(style)) init(Qt::black, style); else { - d = nullBrushInstance(); + d.reset(nullBrushInstance()); d->ref.ref(); } } @@ -451,7 +476,7 @@ QBrush::QBrush(const QColor &color, Qt::BrushStyle style) if (qbrush_check_type(style)) init(color, style); else { - d = nullBrushInstance(); + d.reset(nullBrushInstance()); d->ref.ref(); } } @@ -468,7 +493,7 @@ QBrush::QBrush(Qt::GlobalColor color, Qt::BrushStyle style) if (qbrush_check_type(style)) init(color, style); else { - d = nullBrushInstance(); + d.reset(nullBrushInstance()); d->ref.ref(); } } @@ -510,8 +535,8 @@ QBrush::QBrush(Qt::GlobalColor color, const QPixmap &pixmap) */ QBrush::QBrush(const QBrush &other) + : d(other.d.data()) { - d = other.d; d->ref.ref(); } @@ -535,7 +560,7 @@ QBrush::QBrush(const QGradient &gradient) }; init(QColor(), enum_table[gradient.type()]); - QGradientBrushData *grad = static_cast<QGradientBrushData *>(d); + QGradientBrushData *grad = static_cast<QGradientBrushData *>(d.data()); grad->gradient = gradient; } @@ -545,24 +570,11 @@ QBrush::QBrush(const QGradient &gradient) QBrush::~QBrush() { - if (!d->ref.deref()) - cleanUp(d); } void QBrush::cleanUp(QBrushData *x) { - switch (x->style) { - case Qt::TexturePattern: - delete static_cast<QTexturedBrushData*>(x); - break; - case Qt::LinearGradientPattern: - case Qt::RadialGradientPattern: - case Qt::ConicalGradientPattern: - delete static_cast<QGradientBrushData*>(x); - break; - default: - delete x; - } + QBrushDataPointerDeleter::deleteData(x); } @@ -571,38 +583,36 @@ void QBrush::detach(Qt::BrushStyle newStyle) if (newStyle == d->style && d->ref == 1) return; - QBrushData *x; + QScopedPointer<QBrushData> x; switch(newStyle) { case Qt::TexturePattern: { QTexturedBrushData *tbd = new QTexturedBrushData; if (d->style == Qt::TexturePattern) { - QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d); + QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data()); if (data->m_has_pixmap_texture) tbd->setPixmap(data->pixmap()); else tbd->setImage(data->image()); } - x = tbd; + x.reset(tbd); break; } case Qt::LinearGradientPattern: case Qt::RadialGradientPattern: case Qt::ConicalGradientPattern: - x = new QGradientBrushData; - static_cast<QGradientBrushData *>(x)->gradient = - static_cast<QGradientBrushData *>(d)->gradient; + x.reset(new QGradientBrushData); + static_cast<QGradientBrushData *>(x.data())->gradient = + static_cast<QGradientBrushData *>(d.data())->gradient; break; default: - x = new QBrushData; + x.reset(new QBrushData); break; } x->ref = 1; x->style = newStyle; x->color = d->color; x->transform = d->transform; - if (!d->ref.deref()) - cleanUp(d); - d = x; + d.reset(x.take()); } @@ -615,10 +625,11 @@ void QBrush::detach(Qt::BrushStyle newStyle) QBrush &QBrush::operator=(const QBrush &b) { + if (d == b.d) + return *this; + b.d->ref.ref(); - if (!d->ref.deref()) - cleanUp(d); - d = b.d; + d.reset(b.d.data()); return *this; } @@ -713,7 +724,7 @@ QPixmap *QBrush::pixmap() const { if (d->style != Qt::TexturePattern) return 0; - QTexturedBrushData *data = static_cast<QTexturedBrushData*>(d); + QTexturedBrushData *data = static_cast<QTexturedBrushData*>(d.data()); QPixmap &pixmap = data->pixmap(); return pixmap.isNull() ? 0 : &pixmap; } @@ -730,7 +741,7 @@ QPixmap *QBrush::pixmap() const QPixmap QBrush::texture() const { return d->style == Qt::TexturePattern - ? ((QTexturedBrushData*) d)->pixmap() + ? (static_cast<QTexturedBrushData *>(d.data()))->pixmap() : QPixmap(); } @@ -748,7 +759,7 @@ void QBrush::setTexture(const QPixmap &pixmap) { if (!pixmap.isNull()) { detach(Qt::TexturePattern); - QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d); + QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data()); data->setPixmap(pixmap); } else { detach(Qt::NoBrush); @@ -771,7 +782,7 @@ void QBrush::setTexture(const QPixmap &pixmap) QImage QBrush::textureImage() const { return d->style == Qt::TexturePattern - ? ((QTexturedBrushData *) d)->image() + ? (static_cast<QTexturedBrushData *>(d.data()))->image() : QImage(); } @@ -796,7 +807,7 @@ void QBrush::setTextureImage(const QImage &image) { if (!image.isNull()) { detach(Qt::TexturePattern); - QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d); + QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data()); data->setImage(image); } else { detach(Qt::NoBrush); @@ -812,7 +823,7 @@ const QGradient *QBrush::gradient() const if (d->style == Qt::LinearGradientPattern || d->style == Qt::RadialGradientPattern || d->style == Qt::ConicalGradientPattern) { - return &static_cast<const QGradientBrushData *>(d)->gradient; + return &static_cast<const QGradientBrushData *>(d.data())->gradient; } return 0; } @@ -846,7 +857,9 @@ bool QBrush::isOpaque() const return false; return true; } else if (d->style == Qt::TexturePattern) { - return !texture().hasAlpha(); + return qHasPixmapTexture(*this) + ? !texture().hasAlphaChannel() && !texture().isQBitmap() + : !textureImage().hasAlphaChannel(); } return false; @@ -923,16 +936,16 @@ bool QBrush::operator==(const QBrush &b) const if (b.d->style == d->style && b.d->color == d->color) { switch (d->style) { case Qt::TexturePattern: { - QPixmap &us = ((QTexturedBrushData *) d)->pixmap(); - QPixmap &them = ((QTexturedBrushData *) b.d)->pixmap(); + QPixmap &us = (static_cast<QTexturedBrushData *>(d.data()))->pixmap(); + QPixmap &them = (static_cast<QTexturedBrushData *>(b.d.data()))->pixmap(); return ((us.isNull() && them.isNull()) || us.cacheKey() == them.cacheKey()); } case Qt::LinearGradientPattern: case Qt::RadialGradientPattern: case Qt::ConicalGradientPattern: { - QGradientBrushData *d1 = static_cast<QGradientBrushData *>(d); - QGradientBrushData *d2 = static_cast<QGradientBrushData *>(b.d); + QGradientBrushData *d1 = static_cast<QGradientBrushData *>(d.data()); + QGradientBrushData *d2 = static_cast<QGradientBrushData *>(b.d.data()); return d1->gradient == d2->gradient; } default: @@ -1151,7 +1164,7 @@ QDataStream &operator>>(QDataStream &s, QBrush &b) /*! \class QGradient - \ingroup multimedia + \ingroup painting \ingroup shared \brief The QGradient class is used in combination with QBrush to @@ -1515,7 +1528,7 @@ bool QGradient::operator==(const QGradient &gradient) /*! \class QLinearGradient - \ingroup multimedia + \ingroup painting \brief The QLinearGradient class is used in combination with QBrush to specify a linear gradient brush. @@ -1694,7 +1707,7 @@ void QLinearGradient::setFinalStop(const QPointF &stop) /*! \class QRadialGradient - \ingroup multimedia + \ingroup painting \brief The QRadialGradient class is used in combination with QBrush to specify a radial gradient brush. @@ -1951,7 +1964,7 @@ void QRadialGradient::setFocalPoint(const QPointF &focalPoint) /*! \class QConicalGradient - \ingroup multimedia + \ingroup painting \brief The QConicalGradient class is used in combination with QBrush to specify a conical gradient brush. diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h index 264def3..2412ab7 100644 --- a/src/gui/painting/qbrush.h +++ b/src/gui/painting/qbrush.h @@ -45,12 +45,22 @@ #include <QtCore/qpair.h> #include <QtCore/qpoint.h> #include <QtCore/qvector.h> +#include <QtCore/qscopedpointer.h> #include <QtGui/qcolor.h> #include <QtGui/qmatrix.h> #include <QtGui/qtransform.h> #include <QtGui/qimage.h> #include <QtGui/qpixmap.h> +#if defined(Q_OS_VXWORKS) +# if defined(m_data) +# undef m_data +# endif +# if defined(m_type) +# undef m_type +# endif +#endif + QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -61,6 +71,7 @@ struct QBrushData; class QPixmap; class QGradient; class QVariant; +struct QBrushDataPointerDeleter; class Q_GUI_EXPORT QBrush { @@ -123,15 +134,15 @@ private: friend class QRasterPaintEnginePrivate; friend struct QSpanData; friend class QPainter; - friend bool qHasPixmapTexture(const QBrush& brush); + friend bool Q_GUI_EXPORT qHasPixmapTexture(const QBrush& brush); void detach(Qt::BrushStyle newStyle); void init(const QColor &color, Qt::BrushStyle bs); - QBrushData *d; + QScopedPointer<QBrushData, QBrushDataPointerDeleter> d; void cleanUp(QBrushData *x); public: inline bool isDetached() const; - typedef QBrushData * DataPtr; + typedef QScopedPointer<QBrushData, QBrushDataPointerDeleter> DataPtr; inline DataPtr &data_ptr() { return d; } }; diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp index 8cc8226..395995c 100644 --- a/src/gui/painting/qcolor.cpp +++ b/src/gui/painting/qcolor.cpp @@ -66,9 +66,9 @@ QT_BEGIN_NAMESPACE \class QColor \brief The QColor class provides colors based on RGB, HSV or CMYK values. - \ingroup multimedia + \ingroup painting \ingroup appearance - \mainclass + A color is normally specified in terms of RGB (red, green, and blue) components, but it is also possible to specify it in terms @@ -237,6 +237,15 @@ QT_BEGIN_NAMESPACE alpha-channel to feature \l {QColor#Alpha-Blended Drawing}{alpha-blended drawing}. + \section1 The HSL Color Model + + HSL is similar to HSV. Instead of value parameter from HSV, + HSL has the lightness parameter. + The lightness parameter goes from black to color and from color to white. + If you go outside at the night its black or dark gray. At day its colorful but + if you look in a really strong light a things they are going to white and + wash out. + \section1 The CMYK Color Model While the RGB and HSV color models are used for display on @@ -437,6 +446,9 @@ QColor::QColor(Spec spec) case Cmyk: setCmyk(0, 0, 0, 0); break; + case Hsl: + setHsl(0, 0, 0, 0); + break; } } @@ -678,6 +690,113 @@ void QColor::setHsv(int h, int s, int v, int a) } /*! + Sets the contents pointed to by \a h, \a s, \a l, and \a a, to the hue, + saturation, lightness, and alpha-channel (transparency) components of the + color's HSL value. + + These components can be retrieved individually using the hueHslF(), + saturationHslF(), lightnessF() and alphaF() functions. + + \sa setHsl() +*/ +void QColor::getHslF(qreal *h, qreal *s, qreal *l, qreal *a) const +{ + if (!h || !s || !l) + return; + + if (cspec != Invalid && cspec != Hsl) { + toHsl().getHslF(h, s, l, a); + return; + } + + *h = ct.ahsl.hue == USHRT_MAX ? -1.0 : ct.ahsl.hue / 36000.0; + *s = ct.ahsl.saturation / qreal(USHRT_MAX); + *l = ct.ahsl.lightness / qreal(USHRT_MAX); + + if (a) + *a = ct.ahsl.alpha / qreal(USHRT_MAX); +} + +/*! + Sets the contents pointed to by \a h, \a s, \a l, and \a a, to the hue, + saturation, lightness, and alpha-channel (transparency) components of the + color's HSL value. + + These components can be retrieved individually using the hueHsl(), + saturationHsl(), lightness() and alpha() functions. + + \sa setHsl() +*/ +void QColor::getHsl(int *h, int *s, int *l, int *a) const +{ + if (!h || !s || !l) + return; + + if (cspec != Invalid && cspec != Hsl) { + toHsl().getHsl(h, s, l, a); + return; + } + + *h = ct.ahsl.hue == USHRT_MAX ? -1 : ct.ahsl.hue / 100; + *s = ct.ahsl.saturation >> 8; + *l = ct.ahsl.lightness >> 8; + + if (a) + *a = ct.ahsl.alpha >> 8; +} + +/*! + Sets a HSL color lightness; \a h is the hue, \a s is the saturation, \a l is + the lightness and \a a is the alpha component of the HSL color. + + All the values must be in the range 0.0-1.0. + + \sa getHslF(), setHsl() +*/ +void QColor::setHslF(qreal h, qreal s, qreal l, qreal a) +{ + if (((h < 0.0 || h > 1.0) && h != -1.0) + || (s < 0.0 || s > 1.0) + || (l < 0.0 || l > 1.0) + || (a < 0.0 || a > 1.0)) { + qWarning("QColor::setHsvF: HSV parameters out of range"); + return; + } + + cspec = Hsl; + ct.ahsl.alpha = qRound(a * USHRT_MAX); + ct.ahsl.hue = h == -1.0 ? USHRT_MAX : qRound(h * 36000); + ct.ahsl.saturation = qRound(s * USHRT_MAX); + ct.ahsl.lightness = qRound(l * USHRT_MAX); + ct.ahsl.pad = 0; +} + +/*! + Sets a HSL color value; \a h is the hue, \a s is the saturation, \a l is + the lightness and \a a is the alpha component of the HSL color. + + The saturation, value and alpha-channel values must be in the range 0-255, + and the hue value must be greater than -1. + + \sa getHsl(), setHslF() +*/ +void QColor::setHsl(int h, int s, int l, int a) +{ + if (h < -1 || (uint)s > 255 || (uint)l > 255 || (uint)a > 255) { + qWarning("QColor::setHsv: HSV parameters out of range"); + invalidate(); + return; + } + + cspec = Hsl; + ct.ahsl.alpha = a * 0x101; + ct.ahsl.hue = h == -1 ? USHRT_MAX : (h % 360) * 100; + ct.ahsl.saturation = s * 0x101; + ct.ahsl.lightness = l * 0x101; + ct.ahsl.pad = 0; +} + +/*! Sets the contents pointed to by \a r, \a g, \a b, and \a a, to the red, green, blue, and alpha-channel (transparency) components of the color's RGB value. @@ -1082,11 +1201,25 @@ void QColor::setBlueF(qreal blue) /*! Returns the hue color component of this color. - \sa hueF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color + The color is implicitly converted to HSV. + + \sa hsvHue(), hueF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color Model} */ + int QColor::hue() const { + return hsvHue(); +} + +/*! + Returns the hue color component of this color. + + \sa hueF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color + Model} +*/ +int QColor::hsvHue() const +{ if (cspec != Invalid && cspec != Hsv) return toHsv().hue(); return ct.ahsv.hue == USHRT_MAX ? -1 : ct.ahsv.hue / 100; @@ -1095,11 +1228,25 @@ int QColor::hue() const /*! Returns the saturation color component of this color. - \sa saturationF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color + The color is implicitly converted to HSV. + + \sa hsvSaturation(), saturationF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color Model} */ + int QColor::saturation() const { + return hsvSaturation(); +} + +/*! + Returns the saturation color component of this color. + + \sa saturationF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color + Model} +*/ +int QColor::hsvSaturation() const +{ if (cspec != Invalid && cspec != Hsv) return toHsv().saturation(); return ct.ahsv.saturation >> 8; @@ -1121,11 +1268,24 @@ int QColor::value() const /*! Returns the hue color component of this color. - \sa hue(), getHsvF(), {QColor#The HSV Color Model}{The HSV Color + The color is implicitly converted to HSV. + + \sa hsvHueF(), hue(), getHsvF(), {QColor#The HSV Color Model}{The HSV Color Model} */ qreal QColor::hueF() const { + return hsvHueF(); +} + +/*! + Returns the hue color component of this color. + + \sa hue(), getHsvF(), {QColor#The HSV Color Model}{The HSV Color + Model} +*/ +qreal QColor::hsvHueF() const +{ if (cspec != Invalid && cspec != Hsv) return toHsv().hueF(); return ct.ahsv.hue == USHRT_MAX ? -1.0 : ct.ahsv.hue / 36000.0; @@ -1134,11 +1294,24 @@ qreal QColor::hueF() const /*! Returns the saturation color component of this color. - \sa saturation() getHsvF(), {QColor#The HSV Color Model}{The HSV Color + The color is implicitly converted to HSV. + + \sa hsvSaturationF(), saturation() getHsvF(), {QColor#The HSV Color Model}{The HSV Color Model} */ qreal QColor::saturationF() const { + return hsvSaturationF(); +} + +/*! + Returns the saturation color component of this color. + + \sa saturation() getHsvF(), {QColor#The HSV Color Model}{The HSV Color + Model} +*/ +qreal QColor::hsvSaturationF() const +{ if (cspec != Invalid && cspec != Hsv) return toHsv().saturationF(); return ct.ahsv.saturation / qreal(USHRT_MAX); @@ -1158,6 +1331,79 @@ qreal QColor::valueF() const } /*! + Returns the hue color component of this color. + + \sa hueHslF(), getHsl() +*/ +int QColor::hslHue() const +{ + if (cspec != Invalid && cspec != Hsl) + return toHsl().hslHue(); + return ct.ahsl.hue == USHRT_MAX ? -1 : ct.ahsl.hue / 100; +} + +/*! + Returns the saturation color component of this color. + + \sa saturationF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color + Model} +*/ +int QColor::hslSaturation() const +{ + if (cspec != Invalid && cspec != Hsl) + return toHsl().hslSaturation(); + return ct.ahsl.saturation >> 8; +} + +/*! + Returns the lightness color component of this color. + + \sa lightnessF(), getHsl() +*/ +int QColor::lightness() const +{ + if (cspec != Invalid && cspec != Hsl) + return toHsl().lightness(); + return ct.ahsl.lightness >> 8; +} + +/*! + Returns the hue color component of this color. + + \sa hue(), getHslF() +*/ +qreal QColor::hslHueF() const +{ + if (cspec != Invalid && cspec != Hsl) + return toHsl().hslHueF(); + return ct.ahsl.hue == USHRT_MAX ? -1.0 : ct.ahsl.hue / 36000.0; +} + +/*! + Returns the saturation color component of this color. + + \sa saturationHsl() getHslF() +*/ +qreal QColor::hslSaturationF() const +{ + if (cspec != Invalid && cspec != Hsl) + return toHsl().hslSaturationF(); + return ct.ahsl.saturation / qreal(USHRT_MAX); +} + +/*! + Returns the lightness color component of this color. + + \sa value() getHslF() +*/ +qreal QColor::lightnessF() const +{ + if (cspec != Invalid && cspec != Hsl) + return toHsl().lightnessF(); + return ct.ahsl.lightness / qreal(USHRT_MAX); +} + +/*! Returns the cyan color component of this color. \sa cyanF(), getCmyk(), {QColor#The CMYK Color Model}{The CMYK @@ -1337,6 +1583,53 @@ QColor QColor::toRgb() const } break; } + case Hsl: + { + if (ct.ahsl.saturation == 0 || ct.ahsl.hue == USHRT_MAX) { + // achromatic case + color.ct.argb.red = color.ct.argb.green = color.ct.argb.blue = ct.ahsl.lightness; + } else if (ct.ahsl.lightness == 0) { + // lightness 0 + color.ct.argb.red = color.ct.argb.green = color.ct.argb.blue = 0; + } else { + // chromatic case + const qreal h = ct.ahsl.hue == 36000 ? 0 : ct.ahsl.hue / 36000.; + const qreal s = ct.ahsl.saturation / qreal(USHRT_MAX); + const qreal l = ct.ahsl.lightness / qreal(USHRT_MAX); + + qreal temp2; + if (l < qreal(0.5)) + temp2 = l * (qreal(1.0) + s); + else + temp2 = l + s - (l * s); + + const qreal temp1 = (qreal(2.0) * l) - temp2; + qreal temp3[3] = { h + (qreal(1.0) / qreal(3.0)), + h, + h - (qreal(1.0) / qreal(3.0)) }; + + for (int i = 0; i != 3; ++i) { + if (temp3[i] < qreal(0.0)) + temp3[i] += qreal(1.0); + else if (temp3[i] > qreal(1.0)) + temp3[i] -= qreal(1.0); + + const qreal sixtemp3 = temp3[i] * qreal(6.0); + if (sixtemp3 < qreal(1.0)) + color.ct.array[i+1] = qRound((temp1 + (temp2 - temp1) * sixtemp3) * USHRT_MAX); + else if ((temp3[i] * qreal(2.0)) < qreal(1.0)) + color.ct.array[i+1] = qRound(temp2 * USHRT_MAX); + else if ((temp3[i] * qreal(3.0)) < qreal(2.0)) + color.ct.array[i+1] = qRound((temp1 + (temp2 -temp1) * (qreal(2.0) /qreal(3.0) - temp3[i]) * qreal(6.0)) * USHRT_MAX); + else + color.ct.array[i+1] = qRound(temp1 * USHRT_MAX); + } + color.ct.argb.red = color.ct.argb.red == 1 ? 0 : color.ct.argb.red; + color.ct.argb.green = color.ct.argb.green == 1 ? 0 : color.ct.argb.green; + color.ct.argb.blue = color.ct.argb.blue == 1 ? 0 : color.ct.argb.blue; + } + break; + } case Cmyk: { const qreal c = ct.acmyk.cyan / qreal(USHRT_MAX); @@ -1387,7 +1680,7 @@ QColor QColor::toHsv() const const qreal min = Q_MIN_3(r, g, b); const qreal delta = max - min; color.ct.ahsv.value = qRound(max * USHRT_MAX); - if (qFuzzyCompare(delta + 1, 1)) { + if (qFuzzyIsNull(delta)) { // achromatic case, hue is undefined color.ct.ahsv.hue = USHRT_MAX; color.ct.ahsv.saturation = 0; @@ -1414,6 +1707,62 @@ QColor QColor::toHsv() const } /*! + Creates and returns an HSL QColor based on this color. + + \sa fromHsl(), convertTo(), isValid() +*/ +QColor QColor::toHsl() const +{ + if (!isValid() || cspec == Hsl) + return *this; + + if (cspec != Rgb) + return toRgb().toHsl(); + + QColor color; + color.cspec = Hsl; + color.ct.ahsl.alpha = ct.argb.alpha; + color.ct.ahsl.pad = 0; + + const qreal r = ct.argb.red / qreal(USHRT_MAX); + const qreal g = ct.argb.green / qreal(USHRT_MAX); + const qreal b = ct.argb.blue / qreal(USHRT_MAX); + const qreal max = Q_MAX_3(r, g, b); + const qreal min = Q_MIN_3(r, g, b); + const qreal delta = max - min; + const qreal delta2 = max + min; + const qreal lightness = qreal(0.5) * delta2; + color.ct.ahsl.lightness = qRound(lightness * USHRT_MAX); + if (qFuzzyIsNull(delta)) { + // achromatic case, hue is undefined + color.ct.ahsl.hue = 0; + color.ct.ahsl.saturation = 0; + } else { + // chromatic case + qreal hue = 0; + if (lightness < qreal(0.5)) + color.ct.ahsl.saturation = qRound((delta / delta2) * USHRT_MAX); + else + color.ct.ahsl.saturation = qRound((delta / (qreal(2.0) - delta2)) * USHRT_MAX); + if (qFuzzyCompare(r, max)) { + hue = ((g - b) /delta); + } else if (qFuzzyCompare(g, max)) { + hue = (2.0 + (b - r) / delta); + } else if (qFuzzyCompare(b, max)) { + hue = (4.0 + (r - g) / delta); + } else { + Q_ASSERT_X(false, "QColor::toHsv", "internal error"); + } + hue *= 60.0; + if (hue < 0.0) + hue += 360.0; + color.ct.ahsl.hue = qRound(hue * 100); + } + + return color; +} + +/*! Creates and returns a CMYK QColor based on this color. \sa fromCmyk(), convertTo(), isValid(), {QColor#The CMYK Color @@ -1441,7 +1790,7 @@ QColor QColor::toCmyk() const // cmy -> cmyk const qreal k = qMin(c, qMin(m, y)); - if (!qFuzzyCompare(k,1)) { + if (!qFuzzyIsNull(k - 1)) { c = (c - k) / (1.0 - k); m = (m - k) / (1.0 - k); y = (y - k) / (1.0 - k); @@ -1466,6 +1815,8 @@ QColor QColor::convertTo(QColor::Spec colorSpec) const return toHsv(); case Cmyk: return toCmyk(); + case Hsl: + return toHsl(); case Invalid: break; } @@ -1627,6 +1978,70 @@ QColor QColor::fromHsvF(qreal h, qreal s, qreal v, qreal a) } /*! + Static convenience function that returns a QColor constructed from the HSV + color values, \a h (hue), \a s (saturation), \a l (lightness), and \a a + (alpha-channel, i.e. transparency). + + The value of \a s, \a l, and \a a must all be in the range 0-255; the value + of \a h must be in the range 0-359. + + \sa toHsl(), fromHslF(), isValid() +*/ +QColor QColor::fromHsl(int h, int s, int l, int a) +{ + if (((h < 0 || h >= 360) && h != -1) + || s < 0 || s > 255 + || l < 0 || l > 255 + || a < 0 || a > 255) { + qWarning("QColor::fromHsv: HSV parameters out of range"); + return QColor(); + } + + QColor color; + color.cspec = Hsl; + color.ct.ahsl.alpha = a * 0x101; + color.ct.ahsl.hue = h == -1 ? USHRT_MAX : (h % 360) * 100; + color.ct.ahsl.saturation = s * 0x101; + color.ct.ahsl.lightness = l * 0x101; + color.ct.ahsl.pad = 0; + return color; +} + +/*! + \overload + + Static convenience function that returns a QColor constructed from the HSV + color values, \a h (hue), \a s (saturation), \a l (lightness), and \a a + (alpha-channel, i.e. transparency). + + All the values must be in the range 0.0-1.0. + + \sa toHsl(), fromHsl(), isValid() +*/ +QColor QColor::fromHslF(qreal h, qreal s, qreal l, qreal a) +{ + if (((h < 0.0 || h > 1.0) && h != -1.0) + || (s < 0.0 || s > 1.0) + || (l < 0.0 || l > 1.0) + || (a < 0.0 || a > 1.0)) { + qWarning("QColor::fromHsvF: HSV parameters out of range"); + return QColor(); + } + + QColor color; + color.cspec = Hsl; + color.ct.ahsl.alpha = qRound(a * USHRT_MAX); + color.ct.ahsl.hue = (h == -1.0) ? USHRT_MAX : qRound(h * 36000); + if (color.ct.ahsl.hue == 36000) + color.ct.ahsl.hue = 0; + color.ct.ahsl.saturation = qRound(s * USHRT_MAX); + color.ct.ahsl.lightness = qRound(l * USHRT_MAX); + color.ct.ahsl.pad = 0; + return color; +} + + +/*! Sets the contents pointed to by \a c, \a m, \a y, \a k, and \a a, to the cyan, magenta, yellow, black, and alpha-channel (transparency) components of the color's CMYK value. @@ -1917,14 +2332,26 @@ QColor &QColor::operator=(Qt::GlobalColor color) */ bool QColor::operator==(const QColor &color) const { - return (cspec == color.cspec - && ct.argb.alpha == color.ct.argb.alpha - && ((cspec == QColor::Hsv - && ((ct.argb.red % 36000) == (color.ct.argb.red % 36000))) - || (ct.argb.red == color.ct.argb.red)) - && ct.argb.green == color.ct.argb.green - && ct.argb.blue == color.ct.argb.blue - && ct.argb.pad == color.ct.argb.pad); + if (cspec == Hsl && cspec == color.cspec) { + return (ct.argb.alpha == color.ct.argb.alpha + && ((((ct.ahsl.hue % 36000) == (color.ct.ahsl.hue % 36000))) + || (ct.ahsl.hue == color.ct.ahsl.hue)) + && (qAbs(ct.ahsl.saturation - color.ct.ahsl.saturation) < 50 + || ct.ahsl.lightness == 0 + || color.ct.ahsl.lightness == 0 + || ct.ahsl.lightness == USHRT_MAX + || color.ct.ahsl.lightness == USHRT_MAX) + && (qAbs(ct.ahsl.lightness - color.ct.ahsl.lightness)) < 50); + } else { + return (cspec == color.cspec + && ct.argb.alpha == color.ct.argb.alpha + && (((cspec == QColor::Hsv) + && ((ct.ahsv.hue % 36000) == (color.ct.ahsv.hue % 36000))) + || (ct.ahsv.hue == color.ct.ahsv.hue)) + && ct.argb.green == color.ct.argb.green + && ct.argb.blue == color.ct.argb.blue + && ct.argb.pad == color.ct.argb.pad); + } } /*! @@ -2022,12 +2449,14 @@ QDebug operator<<(QDebug dbg, const QColor &c) if (!c.isValid()) dbg.nospace() << "QColor(Invalid)"; else if (c.spec() == QColor::Rgb) - dbg.nospace() << "QColor(ARGB " << c.alphaF() << ", " << c.redF() << ", " << c.greenF() << ", " << c.blueF() << ")"; + dbg.nospace() << "QColor(ARGB " << c.alphaF() << ", " << c.redF() << ", " << c.greenF() << ", " << c.blueF() << ')'; else if (c.spec() == QColor::Hsv) - dbg.nospace() << "QColor(AHSV " << c.alphaF() << ", " << c.hueF() << ", " << c.saturationF() << ", " << c.valueF() << ")"; + dbg.nospace() << "QColor(AHSV " << c.alphaF() << ", " << c.hueF() << ", " << c.saturationF() << ", " << c.valueF() << ')'; else if (c.spec() == QColor::Cmyk) dbg.nospace() << "QColor(ACMYK " << c.alphaF() << ", " << c.cyanF() << ", " << c.magentaF() << ", " << c.yellowF() << ", " - << c.blackF()<< ")"; + << c.blackF()<< ')'; + else if (c.spec() == QColor::Hsl) + dbg.nospace() << "QColor(AHSL " << c.alphaF() << ", " << c.hslHueF() << ", " << c.hslSaturationF() << ", " << c.lightnessF() << ')'; return dbg.space(); #else @@ -2116,9 +2545,7 @@ QDataStream &operator>>(QDataStream &stream, QColor &color) return stream; } -#endif - - +#endif // QT_NO_DATASTREAM /***************************************************************************** diff --git a/src/gui/painting/qcolor.h b/src/gui/painting/qcolor.h index a95f721..92654c1 100644 --- a/src/gui/painting/qcolor.h +++ b/src/gui/painting/qcolor.h @@ -67,7 +67,7 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QColor &); class Q_GUI_EXPORT QColor { public: - enum Spec { Invalid, Rgb, Hsv, Cmyk }; + enum Spec { Invalid, Rgb, Hsv, Cmyk, Hsl }; QColor(); QColor(Qt::GlobalColor color); @@ -122,10 +122,14 @@ public: int hue() const; // 0 <= hue < 360 int saturation() const; + int hsvHue() const; // 0 <= hue < 360 + int hsvSaturation() const; int value() const; qreal hueF() const; // 0.0 <= hueF < 360.0 qreal saturationF() const; + qreal hsvHueF() const; // 0.0 <= hueF < 360.0 + qreal hsvSaturationF() const; qreal valueF() const; void getHsv(int *h, int *s, int *v, int *a = 0) const; @@ -150,9 +154,24 @@ public: void getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a = 0); void setCmykF(qreal c, qreal m, qreal y, qreal k, qreal a = 1.0); + int hslHue() const; // 0 <= hue < 360 + int hslSaturation() const; + int lightness() const; + + qreal hslHueF() const; // 0.0 <= hueF < 360.0 + qreal hslSaturationF() const; + qreal lightnessF() const; + + void getHsl(int *h, int *s, int *l, int *a = 0) const; + void setHsl(int h, int s, int l, int a = 255); + + void getHslF(qreal *h, qreal *s, qreal *l, qreal *a = 0) const; + void setHslF(qreal h, qreal s, qreal l, qreal a = 1.0); + QColor toRgb() const; QColor toHsv() const; QColor toCmyk() const; + QColor toHsl() const; QColor convertTo(Spec colorSpec) const; @@ -168,6 +187,9 @@ public: static QColor fromCmyk(int c, int m, int y, int k, int a = 255); static QColor fromCmykF(qreal c, qreal m, qreal y, qreal k, qreal a = 1.0); + static QColor fromHsl(int h, int s, int l, int a = 255); + static QColor fromHslF(qreal h, qreal s, qreal l, qreal a = 1.0); + QColor light(int f = 150) const; QColor lighter(int f = 150) const; QColor dark(int f = 200) const; @@ -234,6 +256,14 @@ private: ushort yellow; ushort black; } acmyk; + struct { + ushort alpha; + ushort hue; + ushort saturation; + ushort lightness; + ushort pad; + } ahsl; + ushort array[5]; } ct; friend class QColormap; diff --git a/src/gui/painting/qcolor_p.cpp b/src/gui/painting/qcolor_p.cpp index 1fb32fe..fe014df 100644 --- a/src/gui/painting/qcolor_p.cpp +++ b/src/gui/painting/qcolor_p.cpp @@ -49,7 +49,7 @@ #include "qrgb.h" #include "qstringlist.h" -#if defined(Q_OS_WINCE) +#if defined(Q_WS_WINCE) #include "qguifunctions_wince.h" #endif QT_BEGIN_NAMESPACE diff --git a/src/gui/painting/qcolormap.qdoc b/src/gui/painting/qcolormap.qdoc new file mode 100644 index 0000000..b4cb2f3 --- /dev/null +++ b/src/gui/painting/qcolormap.qdoc @@ -0,0 +1,152 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \class QColormap + \ingroup painting + + \brief The QColormap class maps device independent QColors to device + dependent pixel values. +*/ + +/*! \enum QColormap::Mode + + This enum describes how QColormap maps device independent RGB + values to device dependent pixel values. + + \value Direct Pixel values are derived directly from the RGB + values, also known as "True Color." + + \value Indexed Pixel values represent indexes into a vector of + available colors, i.e. QColormap uses the index of the color that + most closely matches an RGB value. + + \value Gray Similar to \c Indexed, pixel values represent a vector + of available gray tones. QColormap uses the index of the gray + tone that most closely matches the computed gray tone of an RGB + value. +*/ + +/*! + \fn QColormap QColormap::instance(int screen) + + Returns the colormap for the specified \a screen. If \a screen is + -1, this function returns the colormap for the default screen. +*/ + +/*! + \fn QColormap::QColormap(const QColormap &colormap) + + Constructs a copy of another \a colormap. +*/ + +/*! + \fn QColormap::~QColormap() + + Destroys the colormap. +*/ + +/*! + \fn int QColormap::size() const + + Returns the size of the colormap for \c Indexed and \c Gray modes; + Returns -1 for \c Direct mode. + + \sa colormap() +*/ + +/*! + \fn uint QColormap::pixel(const QColor &color) const + + Returns a device dependent pixel value for the \a color. + + \sa colorAt() +*/ + +/*! + \fn int QColormap::depth() const + + Returns the depth of the device. + + \sa size() +*/ + +/*! + \fn QColormap::Mode QColormap::mode() const + + Returns the mode of this colormap. + + \sa QColormap::Mode +*/ + +/*! + \fn const QColor QColormap::colorAt(uint pixel) const + + Returns a QColor for the \a pixel. + + \sa pixel() +*/ + +/*! + \fn const QVector<QColor> QColormap::colormap() const + + Returns a vector of colors which represents the devices colormap + for \c Indexed and \c Gray modes. This function returns an empty + vector for \c Direct mode. + + \sa size() +*/ + +/*! \fn HPALETTE QColormap::hPal() + + This function is only available on Windows. + + Returns an handle to the HPALETTE used by this colormap. If no + HPALETTE is being used, this function returns zero. +*/ + +/*! \since 4.2 + + \fn QColormap &QColormap::operator=(const QColormap &colormap) + + Assigns the given \a colormap to \e this color map and returns + a reference to \e this color map. +*/ diff --git a/src/gui/painting/qcolormap_s60.cpp b/src/gui/painting/qcolormap_s60.cpp new file mode 100644 index 0000000..7a27c94 --- /dev/null +++ b/src/gui/painting/qcolormap_s60.cpp @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcolormap.h" +#include "qcolor.h" + +QT_BEGIN_NAMESPACE + +class QColormapPrivate +{ +public: + inline QColormapPrivate() + : ref(1) + { } + + QAtomicInt ref; +}; + +void QColormap::initialize() +{ +} + +void QColormap::cleanup() +{ +} + +QColormap QColormap::instance(int) +{ + return QColormap(); +} + +QColormap::QColormap() : d(new QColormapPrivate) +{} + +QColormap::QColormap(const QColormap &colormap) :d (colormap.d) +{ d->ref.ref(); } + +QColormap::~QColormap() +{ + if (!d->ref.deref()) + delete d; +} + +QColormap::Mode QColormap::mode() const +{ return QColormap::Direct; } + +int QColormap::depth() const +{ + return 32; +} + +int QColormap::size() const +{ + return -1; +} + +uint QColormap::pixel(const QColor &color) const +{ return color.rgba(); } + +const QColor QColormap::colorAt(uint pixel) const +{ return QColor(pixel); } + +const QVector<QColor> QColormap::colormap() const +{ return QVector<QColor>(); } + +QColormap &QColormap::operator=(const QColormap &colormap) +{ qAtomicAssign(d, colormap.d); return *this; } + +QT_END_NAMESPACE diff --git a/src/gui/painting/qcolormap_win.cpp b/src/gui/painting/qcolormap_win.cpp index 13ad246..6052fc9 100644 --- a/src/gui/painting/qcolormap_win.cpp +++ b/src/gui/painting/qcolormap_win.cpp @@ -44,7 +44,7 @@ #include "qvector.h" #include "qt_windows.h" -#if defined(Q_OS_WINCE) +#if defined(Q_WS_WINCE) #include "qguifunctions_wince.h" #endif diff --git a/src/gui/painting/qcssutil.cpp b/src/gui/painting/qcssutil.cpp index e83d750..7a541c5 100644 --- a/src/gui/painting/qcssutil.cpp +++ b/src/gui/painting/qcssutil.cpp @@ -353,7 +353,7 @@ void qDrawBorder(QPainter *p, const QRect &rect, const QCss::BorderStyle *styles qNormalizeRadii(rect, radii, &tlr, &trr, &blr, &brr); // Drawn in increasing order of precendence - if (styles[BottomEdge] != BorderStyle_None) { + if (styles[BottomEdge] != BorderStyle_None && borders[BottomEdge] > 0) { qreal dw1 = (blr.width() || paintsOver(styles, colors, BottomEdge, LeftEdge)) ? 0 : borders[LeftEdge]; qreal dw2 = (brr.width() || paintsOver(styles, colors, BottomEdge, RightEdge)) ? 0 : borders[RightEdge]; qreal x1 = br.x() + blr.width(); @@ -365,7 +365,7 @@ void qDrawBorder(QPainter *p, const QRect &rect, const QCss::BorderStyle *styles if (blr.width() || brr.width()) qDrawRoundedCorners(p, x1, y1, x2, y2, blr, brr, BottomEdge, styles[BottomEdge], colors[BottomEdge]); } - if (styles[RightEdge] != BorderStyle_None) { + if (styles[RightEdge] != BorderStyle_None && borders[RightEdge] > 0) { qreal dw1 = (trr.height() || paintsOver(styles, colors, RightEdge, TopEdge)) ? 0 : borders[TopEdge]; qreal dw2 = (brr.height() || paintsOver(styles, colors, RightEdge, BottomEdge)) ? 0 : borders[BottomEdge]; qreal x1 = br.x() + br.width() - borders[RightEdge]; @@ -377,7 +377,7 @@ void qDrawBorder(QPainter *p, const QRect &rect, const QCss::BorderStyle *styles if (trr.height() || brr.height()) qDrawRoundedCorners(p, x1, y1, x2, y2, trr, brr, RightEdge, styles[RightEdge], colors[RightEdge]); } - if (styles[LeftEdge] != BorderStyle_None) { + if (styles[LeftEdge] != BorderStyle_None && borders[LeftEdge] > 0) { qreal dw1 = (tlr.height() || paintsOver(styles, colors, LeftEdge, TopEdge)) ? 0 : borders[TopEdge]; qreal dw2 = (blr.height() || paintsOver(styles, colors, LeftEdge, BottomEdge)) ? 0 : borders[BottomEdge]; qreal x1 = br.x(); @@ -389,7 +389,7 @@ void qDrawBorder(QPainter *p, const QRect &rect, const QCss::BorderStyle *styles if (tlr.height() || blr.height()) qDrawRoundedCorners(p, x1, y1, x2, y2, tlr, blr, LeftEdge, styles[LeftEdge], colors[LeftEdge]); } - if (styles[TopEdge] != BorderStyle_None) { + if (styles[TopEdge] != BorderStyle_None && borders[TopEdge] > 0) { qreal dw1 = (tlr.width() || paintsOver(styles, colors, TopEdge, LeftEdge)) ? 0 : borders[LeftEdge]; qreal dw2 = (trr.width() || paintsOver(styles, colors, TopEdge, RightEdge)) ? 0 : borders[RightEdge]; qreal x1 = br.x() + tlr.width(); diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 1f0280e..ab192c5 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -38,15 +38,18 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + #include <private/qdrawhelper_p.h> #include <private/qpaintengine_raster_p.h> #include <private/qpainter_p.h> #include <private/qdrawhelper_x86_p.h> +#include <private/qdrawhelper_armv6_p.h> #include <private/qmath_p.h> #include <qmath.h> QT_BEGIN_NAMESPACE + #define MASK(src, a) src = BYTE_MUL(src, a) #if defined(Q_OS_IRIX) && defined(Q_CC_GNU) && __GNUC__ == 3 && __GNUC__ < 4 && QT_POINTER_SIZE == 8 @@ -157,46 +160,9 @@ static uint * QT_FASTCALL destFetchRGB16(uint *buffer, QRasterBuffer *rasterBuff return buffer; } -#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL) -template <typename EnumType, int value> -class QEnumToType -{ -public: - inline EnumType operator()() const - { - return EnumType(value); - } -}; -template <QImage::Format format> -class QImageFormatToType -{ -public: - inline QImage::Format operator()() const - { - return format; - } -}; -// Would have used QEnumToType instead of creating a specialized version for QImageFormatToType, -// but that causes internal compiler error on VC6 -#define Q_TEMPLATE_IMAGEFORMAT_FIX(format) , const QImageFormatToType<format> &imageFormatType -#define Q_TEMPLATE_IMAGEFORMAT_CALL(format) , QImageFormatToType<format>() -#define Q_TEMPLATE_ENUM_FIX(Type, Value) , const QEnumToType<Type, Value> &enumTemplateType -#define Q_TEMPLATE_ENUM_CALL(Type, Value) , QEnumToType<Type, Value>() -#define Q_TEMPLATE_FIX(Type) , const QTypeInfo<Type> &templateType -#define Q_TEMPLATE_CALL(Type) , QTypeInfo<Type>() -#else -#define Q_TEMPLATE_IMAGEFORMAT_FIX(format) -#define Q_TEMPLATE_IMAGEFORMAT_CALL(format) -#define Q_TEMPLATE_ENUM_FIX(Type, Value) -#define Q_TEMPLATE_ENUM_CALL(Type, Value) -#define Q_TEMPLATE_FIX(Type) -#define Q_TEMPLATE_CALL(Type) -#endif - template <class DST> Q_STATIC_TEMPLATE_FUNCTION uint * QT_FASTCALL destFetch(uint *buffer, QRasterBuffer *rasterBuffer, - int x, int y, int length - Q_TEMPLATE_FIX(DST)) + int x, int y, int length) { const DST *src = reinterpret_cast<DST*>(rasterBuffer->scanLine(y)) + x; quint32 *dest = reinterpret_cast<quint32*>(buffer); @@ -205,28 +171,7 @@ Q_STATIC_TEMPLATE_FUNCTION uint * QT_FASTCALL destFetch(uint *buffer, QRasterBuf return buffer; } -#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL) -#define DEST_FETCH_DECL(DST) \ - static uint * QT_FASTCALL destFetch_##DST(uint *buffer, \ - QRasterBuffer *rasterBuffer, \ - int x, int y, int length) \ - { \ - return destFetch<DST>(buffer, rasterBuffer, x, y, length Q_TEMPLATE_CALL(DST)); \ - } - -DEST_FETCH_DECL(qargb8565) -DEST_FETCH_DECL(qrgb666) -DEST_FETCH_DECL(qargb6666) -DEST_FETCH_DECL(qrgb555) -DEST_FETCH_DECL(qrgb888) -DEST_FETCH_DECL(qargb8555) -DEST_FETCH_DECL(qrgb444) -DEST_FETCH_DECL(qargb4444) -#undef DEST_FETCH_DECL -# define SPANFUNC_POINTER_DESTFETCH(Arg) destFetch_##Arg -#else // !VC6 && !VC2002 # define SPANFUNC_POINTER_DESTFETCH(Arg) destFetch<Arg> -#endif static const DestFetchProc destFetchProc[QImage::NImageFormats] = { @@ -366,8 +311,7 @@ static void QT_FASTCALL destStoreRGB16(QRasterBuffer *rasterBuffer, int x, int y template <class DST> Q_STATIC_TEMPLATE_FUNCTION void QT_FASTCALL destStore(QRasterBuffer *rasterBuffer, int x, int y, - const uint *buffer, int length - Q_TEMPLATE_FIX(DST)) + const uint *buffer, int length) { DST *dest = reinterpret_cast<DST*>(rasterBuffer->scanLine(y)) + x; const quint32p *src = reinterpret_cast<const quint32p*>(buffer); @@ -375,28 +319,7 @@ Q_STATIC_TEMPLATE_FUNCTION void QT_FASTCALL destStore(QRasterBuffer *rasterBuffe *dest++ = DST(*src++); } -#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL) -# define DEST_STORE_DECL(DST) \ - static void QT_FASTCALL destStore_##DST(QRasterBuffer *rasterBuffer, \ - int x, int y, \ - const uint *buffer, int length) \ - { \ - destStore<DST>(rasterBuffer, x, y, buffer, length Q_TEMPLATE_CALL(DST)); \ - } - -DEST_STORE_DECL(qargb8565) -DEST_STORE_DECL(qrgb555) -DEST_STORE_DECL(qrgb666) -DEST_STORE_DECL(qargb6666) -DEST_STORE_DECL(qargb8555) -DEST_STORE_DECL(qrgb888) -DEST_STORE_DECL(qrgb444) -DEST_STORE_DECL(qargb4444) -# undef DEST_FETCH_DECL -# define SPANFUNC_POINTER_DESTSTORE(DEST) destStore_##DEST -#else // !VC6 && !VC2002 # define SPANFUNC_POINTER_DESTSTORE(DEST) destStore<DEST> -#endif static const DestStoreProc destStoreProc[QImage::NImageFormats] = { @@ -425,10 +348,8 @@ static const DestStoreProc destStoreProc[QImage::NImageFormats] = We need 5 fetch methods per surface type: untransformed - transformed - transformed tiled - transformed bilinear - transformed bilinear tiled + transformed (tiled and not tiled) + transformed bilinear (tiled and not tiled) We don't need bounds checks for untransformed, but we need them for the other ones. @@ -436,14 +357,12 @@ static const DestStoreProc destStoreProc[QImage::NImageFormats] = */ template <QImage::Format format> -Q_STATIC_TEMPLATE_FUNCTION uint QT_FASTCALL qt_fetchPixel(const uchar *scanLine, int x, const QVector<QRgb> *rgb - Q_TEMPLATE_IMAGEFORMAT_FIX(format)); +Q_STATIC_TEMPLATE_FUNCTION uint QT_FASTCALL qt_fetchPixel(const uchar *scanLine, int x, const QVector<QRgb> *rgb); template<> Q_STATIC_TEMPLATE_SPECIALIZATION uint QT_FASTCALL qt_fetchPixel<QImage::Format_Mono>(const uchar *scanLine, - int x, const QVector<QRgb> *rgb - Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_Mono)) + int x, const QVector<QRgb> *rgb) { bool pixel = scanLine[x>>3] & (0x80 >> (x & 7)); if (rgb) return PREMUL(rgb->at(pixel ? 1 : 0)); @@ -453,8 +372,7 @@ uint QT_FASTCALL qt_fetchPixel<QImage::Format_Mono>(const uchar *scanLine, template<> Q_STATIC_TEMPLATE_SPECIALIZATION uint QT_FASTCALL qt_fetchPixel<QImage::Format_MonoLSB>(const uchar *scanLine, - int x, const QVector<QRgb> *rgb - Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_MonoLSB)) + int x, const QVector<QRgb> *rgb) { bool pixel = scanLine[x>>3] & (0x1 << (x & 7)); if (rgb) return PREMUL(rgb->at(pixel ? 1 : 0)); @@ -464,8 +382,7 @@ uint QT_FASTCALL qt_fetchPixel<QImage::Format_MonoLSB>(const uchar *scanLine, template<> Q_STATIC_TEMPLATE_SPECIALIZATION uint QT_FASTCALL qt_fetchPixel<QImage::Format_Indexed8>(const uchar *scanLine, - int x, const QVector<QRgb> *rgb - Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_Indexed8)) + int x, const QVector<QRgb> *rgb) { return PREMUL(rgb->at(scanLine[x])); } @@ -473,8 +390,7 @@ uint QT_FASTCALL qt_fetchPixel<QImage::Format_Indexed8>(const uchar *scanLine, template<> Q_STATIC_TEMPLATE_SPECIALIZATION uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB32>(const uchar *scanLine, - int x, const QVector<QRgb> * - Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB32)) + int x, const QVector<QRgb> *) { return PREMUL(((const uint *)scanLine)[x]); } @@ -482,8 +398,7 @@ uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB32>(const uchar *scanLine, template<> Q_STATIC_TEMPLATE_SPECIALIZATION uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB32_Premultiplied>(const uchar *scanLine, - int x, const QVector<QRgb> * - Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB32_Premultiplied)) + int x, const QVector<QRgb> *) { return ((const uint *)scanLine)[x]; } @@ -491,8 +406,7 @@ uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB32_Premultiplied>(const uchar template<> Q_STATIC_TEMPLATE_SPECIALIZATION uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB16>(const uchar *scanLine, - int x, const QVector<QRgb> * - Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_RGB16)) + int x, const QVector<QRgb> *) { return qConvertRgb16To32(((const ushort *)scanLine)[x]); } @@ -501,8 +415,7 @@ template<> Q_STATIC_TEMPLATE_SPECIALIZATION uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB8565_Premultiplied>(const uchar *scanLine, int x, - const QVector<QRgb> * - Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB8565_Premultiplied)) + const QVector<QRgb> *) { const qargb8565 color = reinterpret_cast<const qargb8565*>(scanLine)[x]; return qt_colorConvert<quint32, qargb8565>(color, 0); @@ -512,8 +425,7 @@ template<> Q_STATIC_TEMPLATE_SPECIALIZATION uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB666>(const uchar *scanLine, int x, - const QVector<QRgb> * - Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_RGB666)) + const QVector<QRgb> *) { const qrgb666 color = reinterpret_cast<const qrgb666*>(scanLine)[x]; return qt_colorConvert<quint32, qrgb666>(color, 0); @@ -523,8 +435,7 @@ template<> Q_STATIC_TEMPLATE_SPECIALIZATION uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB6666_Premultiplied>(const uchar *scanLine, int x, - const QVector<QRgb> * - Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB6666_Premultiplied)) + const QVector<QRgb> *) { const qargb6666 color = reinterpret_cast<const qargb6666*>(scanLine)[x]; return qt_colorConvert<quint32, qargb6666>(color, 0); @@ -534,8 +445,7 @@ template<> Q_STATIC_TEMPLATE_SPECIALIZATION uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB555>(const uchar *scanLine, int x, - const QVector<QRgb> * - Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_RGB555)) + const QVector<QRgb> *) { const qrgb555 color = reinterpret_cast<const qrgb555*>(scanLine)[x]; return qt_colorConvert<quint32, qrgb555>(color, 0); @@ -545,8 +455,7 @@ template<> Q_STATIC_TEMPLATE_SPECIALIZATION uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB8555_Premultiplied>(const uchar *scanLine, int x, - const QVector<QRgb> * - Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB8555_Premultiplied)) + const QVector<QRgb> *) { const qargb8555 color = reinterpret_cast<const qargb8555*>(scanLine)[x]; return qt_colorConvert<quint32, qargb8555>(color, 0); @@ -556,8 +465,7 @@ template<> Q_STATIC_TEMPLATE_SPECIALIZATION uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB888>(const uchar *scanLine, int x, - const QVector<QRgb> * - Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_RGB888)) + const QVector<QRgb> *) { const qrgb888 color = reinterpret_cast<const qrgb888*>(scanLine)[x]; return qt_colorConvert<quint32, qrgb888>(color, 0); @@ -567,8 +475,7 @@ template<> Q_STATIC_TEMPLATE_SPECIALIZATION uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB444>(const uchar *scanLine, int x, - const QVector<QRgb> * - Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_RGB444)) + const QVector<QRgb> *) { const qrgb444 color = reinterpret_cast<const qrgb444*>(scanLine)[x]; return qt_colorConvert<quint32, qrgb444>(color, 0); @@ -578,47 +485,24 @@ template<> Q_STATIC_TEMPLATE_SPECIALIZATION uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB4444_Premultiplied>(const uchar *scanLine, int x, - const QVector<QRgb> * - Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB4444_Premultiplied)) + const QVector<QRgb> *) { const qargb4444 color = reinterpret_cast<const qargb4444*>(scanLine)[x]; return qt_colorConvert<quint32, qargb4444>(color, 0); } -typedef uint (QT_FASTCALL *FetchPixelProc)(const uchar *scanLine, int x, const QVector<QRgb> *); - -#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL) - -// explicit template instantiations needed to compile with VC6 and VC2002 - -#define SPANFUNC_INSTANTIATION_FETCHPIXEL(Arg) \ - static inline uint fetchPixel_##Arg(const uchar * scanLine, int x, const QVector<QRgb> * rgb) \ -{ \ - return qt_fetchPixel<QImage::Arg>(scanLine, x, rgb Q_TEMPLATE_IMAGEFORMAT_CALL(QImage::Arg)); \ +template<> +Q_STATIC_TEMPLATE_SPECIALIZATION +uint QT_FASTCALL qt_fetchPixel<QImage::Format_Invalid>(const uchar *, + int , + const QVector<QRgb> *) +{ + return 0; } -SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_Mono); -SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_MonoLSB); -SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_Indexed8); -SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_ARGB32_Premultiplied); -SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_ARGB32); -SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_RGB16); -SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_ARGB8565_Premultiplied); -SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_RGB666); -SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_ARGB6666_Premultiplied); -SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_RGB555); -SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_ARGB8555_Premultiplied); -SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_RGB888); -SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_RGB444); -SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_ARGB4444_Premultiplied); - -#undef SPANFUNC_INSTANTIATION_FETCHPIXEL - -#define SPANFUNC_POINTER_FETCHPIXEL(Arg) fetchPixel_##Arg +typedef uint (QT_FASTCALL *FetchPixelProc)(const uchar *scanLine, int x, const QVector<QRgb> *); -#else // !VC6 && !VC2002 -# define SPANFUNC_POINTER_FETCHPIXEL(Arg) qt_fetchPixel<QImage::Arg> -#endif +#define SPANFUNC_POINTER_FETCHPIXEL(Arg) qt_fetchPixel<QImage::Arg> static const FetchPixelProc fetchPixelProc[QImage::NImageFormats] = @@ -653,11 +537,11 @@ enum TextureBlendType { template <QImage::Format format> Q_STATIC_TEMPLATE_FUNCTION const uint * QT_FASTCALL qt_fetchUntransformed(uint *buffer, const Operator *, const QSpanData *data, - int y, int x, int length Q_TEMPLATE_IMAGEFORMAT_FIX(format)) + int y, int x, int length) { const uchar *scanLine = data->texture.scanLine(y); for (int i = 0; i < length; ++i) - buffer[i] = qt_fetchPixel<format>(scanLine, x + i, data->texture.colorTable Q_TEMPLATE_IMAGEFORMAT_CALL(format)); + buffer[i] = qt_fetchPixel<format>(scanLine, x + i, data->texture.colorTable); return buffer; } @@ -665,13 +549,15 @@ template <> Q_STATIC_TEMPLATE_SPECIALIZATION const uint * QT_FASTCALL qt_fetchUntransformed<QImage::Format_ARGB32_Premultiplied>(uint *, const Operator *, const QSpanData *data, - int y, int x, int Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB32_Premultiplied)) + int y, int x, int) { const uchar *scanLine = data->texture.scanLine(y); return ((const uint *)scanLine) + x; } -static const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const QSpanData *data, +template<TextureBlendType blendType> /* either BlendTransformed or BlendTransformedTiled */ +Q_STATIC_TEMPLATE_FUNCTION +const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const QSpanData *data, int y, int x, int length) { FetchPixelProc fetch = fetchPixelProc[data->texture.format]; @@ -698,84 +584,23 @@ static const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, int px = fx >> 16; int py = fy >> 16; - bool out = (px < 0) || (px >= image_width) - || (py < 0) || (py >= image_height); - - const uchar *scanLine = data->texture.scanLine(py); - *b = out ? uint(0) : fetch(scanLine, px, data->texture.colorTable); - fx += fdx; - fy += fdy; - ++b; - } - } else { - const qreal fdx = data->m11; - const qreal fdy = data->m12; - const qreal fdw = data->m13; + if (blendType == BlendTransformedTiled) { + px %= image_width; + py %= image_height; + if (px < 0) px += image_width; + if (py < 0) py += image_height; - qreal fx = data->m21 * cy + data->m11 * cx + data->dx; - qreal fy = data->m22 * cy + data->m12 * cx + data->dy; - qreal fw = data->m23 * cy + data->m13 * cx + data->m33; - - while (b < end) { - const qreal iw = fw == 0 ? 1 : 1 / fw; - const qreal tx = fx * iw; - const qreal ty = fy * iw; - const int px = int(tx) - (tx < 0); - const int py = int(ty) - (ty < 0); - - bool out = (px < 0) || (px >= image_width) - || (py < 0) || (py >= image_height); - - const uchar *scanLine = data->texture.scanLine(py); - *b = out ? uint(0) : fetch(scanLine, px, data->texture.colorTable); - fx += fdx; - fy += fdy; - fw += fdw; - //force increment to avoid /0 - if (!fw) { - fw += fdw; + const uchar *scanLine = data->texture.scanLine(py); + *b = fetch(scanLine, px, data->texture.colorTable); + } else { + if ((px < 0) || (px >= image_width) + || (py < 0) || (py >= image_height)) { + *b = uint(0); + } else { + const uchar *scanLine = data->texture.scanLine(py); + *b = fetch(scanLine, px, data->texture.colorTable); + } } - ++b; - } - } - - return buffer; -} - -static const uint * QT_FASTCALL fetchTransformedTiled(uint *buffer, const Operator *, const QSpanData *data, - int y, int x, int length) -{ - FetchPixelProc fetch = fetchPixelProc[data->texture.format]; - - int image_width = data->texture.width; - int image_height = data->texture.height; - - const qreal cx = x + 0.5; - const qreal cy = y + 0.5; - - const uint *end = buffer + length; - uint *b = buffer; - if (data->fast_matrix) { - // The increment pr x in the scanline - int fdx = (int)(data->m11 * fixed_scale); - int fdy = (int)(data->m12 * fixed_scale); - - int fx = int((data->m21 * cy - + data->m11 * cx + data->dx) * fixed_scale); - int fy = int((data->m22 * cy - + data->m12 * cx + data->dy) * fixed_scale); - - while (b < end) { - int px = fx >> 16; - int py = fy >> 16; - - px %= image_width; - py %= image_height; - if (px < 0) px += image_width; - if (py < 0) py += image_height; - - const uchar *scanLine = data->texture.scanLine(py); - *b = fetch(scanLine, px, data->texture.colorTable); fx += fdx; fy += fdy; ++b; @@ -796,13 +621,23 @@ static const uint * QT_FASTCALL fetchTransformedTiled(uint *buffer, const Operat int px = int(tx) - (tx < 0); int py = int(ty) - (ty < 0); - px %= image_width; - py %= image_height; - if (px < 0) px += image_width; - if (py < 0) py += image_height; + if (blendType == BlendTransformedTiled) { + px %= image_width; + py %= image_height; + if (px < 0) px += image_width; + if (py < 0) py += image_height; - const uchar *scanLine = data->texture.scanLine(py); - *b = fetch(scanLine, px, data->texture.colorTable); + const uchar *scanLine = data->texture.scanLine(py); + *b = fetch(scanLine, px, data->texture.colorTable); + } else { + if ((px < 0) || (px >= image_width) + || (py < 0) || (py >= image_height)) { + *b = uint(0); + } else { + const uchar *scanLine = data->texture.scanLine(py); + *b = fetch(scanLine, px, data->texture.colorTable); + } + } fx += fdx; fy += fdy; fw += fdw; @@ -817,10 +652,20 @@ static const uint * QT_FASTCALL fetchTransformedTiled(uint *buffer, const Operat return buffer; } -static const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *, const QSpanData *data, - int y, int x, int length) +template<TextureBlendType blendType, QImage::Format format> /* blendType = BlendTransformedBilinear or BlendTransformedBilinearTiled */ +Q_STATIC_TEMPLATE_FUNCTION +const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *, const QSpanData *data, + int y, int x, int length) { - FetchPixelProc fetch = fetchPixelProc[data->texture.format]; +#ifdef Q_CC_RVCT // needed to avoid compiler crash in RVCT 2.2 + FetchPixelProc fetch; + if (format != QImage::Format_Invalid) + fetch = qt_fetchPixel<format>; + else + fetch = fetchPixelProc[data->texture.format]; +#else + FetchPixelProc fetch = (format != QImage::Format_Invalid) ? FetchPixelProc(qt_fetchPixel<format>) : fetchPixelProc[data->texture.format]; +#endif int image_width = data->texture.width; int image_height = data->texture.height; @@ -853,130 +698,27 @@ static const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Ope int idistx = 256 - distx; int idisty = 256 - disty; - x1 = qBound(0, x1, image_width - 1); - x2 = qBound(0, x2, image_width - 1); - y1 = qBound(0, y1, image_height - 1); - y2 = qBound(0, y2, image_height - 1); - - const uchar *s1 = data->texture.scanLine(y1); - const uchar *s2 = data->texture.scanLine(y2); - - uint tl = fetch(s1, x1, data->texture.colorTable); - uint tr = fetch(s1, x2, data->texture.colorTable); - uint bl = fetch(s2, x1, data->texture.colorTable); - uint br = fetch(s2, x2, data->texture.colorTable); - - uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); - uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); - *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); - - fx += fdx; - fy += fdy; - ++b; - } - } else { - const qreal fdx = data->m11; - const qreal fdy = data->m12; - const qreal fdw = data->m13; - - qreal fx = data->m21 * cy + data->m11 * cx + data->dx; - qreal fy = data->m22 * cy + data->m12 * cx + data->dy; - qreal fw = data->m23 * cy + data->m13 * cx + data->m33; - - while (b < end) { - const qreal iw = fw == 0 ? 1 : 1 / fw; - const qreal px = fx * iw - 0.5; - const qreal py = fy * iw - 0.5; - - int x1 = int(px) - (px < 0); - int x2 = x1 + 1; - int y1 = int(py) - (py < 0); - int y2 = y1 + 1; - - int distx = int((px - x1) * 256); - int disty = int((py - y1) * 256); - int idistx = 256 - distx; - int idisty = 256 - disty; - - x1 = qBound(0, x1, image_width - 1); - x2 = qBound(0, x2, image_width - 1); - y1 = qBound(0, y1, image_height - 1); - y2 = qBound(0, y2, image_height - 1); - - const uchar *s1 = data->texture.scanLine(y1); - const uchar *s2 = data->texture.scanLine(y2); - - uint tl = fetch(s1, x1, data->texture.colorTable); - uint tr = fetch(s1, x2, data->texture.colorTable); - uint bl = fetch(s2, x1, data->texture.colorTable); - uint br = fetch(s2, x2, data->texture.colorTable); - - uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); - uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); - *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); - - fx += fdx; - fy += fdy; - fw += fdw; - //force increment to avoid /0 - if (!fw) { - fw += fdw; + if (blendType == BlendTransformedBilinearTiled) { + x1 %= image_width; + x2 %= image_width; + y1 %= image_height; + y2 %= image_height; + + if (x1 < 0) x1 += image_width; + if (x2 < 0) x2 += image_width; + if (y1 < 0) y1 += image_height; + if (y2 < 0) y2 += image_height; + + Q_ASSERT(x1 >= 0 && x1 < image_width); + Q_ASSERT(x2 >= 0 && x2 < image_width); + Q_ASSERT(y1 >= 0 && y1 < image_height); + Q_ASSERT(y2 >= 0 && y2 < image_height); + } else { + x1 = qBound(0, x1, image_width - 1); + x2 = qBound(0, x2, image_width - 1); + y1 = qBound(0, y1, image_height - 1); + y2 = qBound(0, y2, image_height - 1); } - ++b; - } - } - - return buffer; -} - -static const uint * QT_FASTCALL fetchTransformedBilinearTiled(uint *buffer, const Operator *, const QSpanData *data, - int y, int x, int length) -{ - FetchPixelProc fetch = fetchPixelProc[data->texture.format]; - - int image_width = data->texture.width; - int image_height = data->texture.height; - - const qreal cx = x + 0.5; - const qreal cy = y + 0.5; - - const uint *end = buffer + length; - uint *b = buffer; - if (data->fast_matrix) { - // The increment pr x in the scanline - int fdx = (int)(data->m11 * fixed_scale); - int fdy = (int)(data->m12 * fixed_scale); - - int fx = int((data->m21 * cy + data->m11 * cx + data->dx) * fixed_scale); - int fy = int((data->m22 * cy + data->m12 * cx + data->dy) * fixed_scale); - - fx -= half_point; - fy -= half_point; - while (b < end) { - int x1 = (fx >> 16); - int x2 = x1 + 1; - int y1 = (fy >> 16); - int y2 = y1 + 1; - - int distx = ((fx - (x1 << 16)) >> 8); - int disty = ((fy - (y1 << 16)) >> 8); - int idistx = 256 - distx; - int idisty = 256 - disty; - - x1 %= image_width; - x2 %= image_width; - y1 %= image_height; - y2 %= image_height; - - if (x1 < 0) x1 += image_width; - if (x2 < 0) x2 += image_width; - if (y1 < 0) y1 += image_height; - if (y2 < 0) y2 += image_height; - - Q_ASSERT(x1 >= 0 && x1 < image_width); - Q_ASSERT(x2 >= 0 && x2 < image_width); - Q_ASSERT(y1 >= 0 && y1 < image_height); - Q_ASSERT(y2 >= 0 && y2 < image_height); const uchar *s1 = data->texture.scanLine(y1); const uchar *s2 = data->texture.scanLine(y2); @@ -1018,20 +760,27 @@ static const uint * QT_FASTCALL fetchTransformedBilinearTiled(uint *buffer, cons int idistx = 256 - distx; int idisty = 256 - disty; - x1 %= image_width; - x2 %= image_width; - y1 %= image_height; - y2 %= image_height; - - if (x1 < 0) x1 += image_width; - if (x2 < 0) x2 += image_width; - if (y1 < 0) y1 += image_height; - if (y2 < 0) y2 += image_height; - - Q_ASSERT(x1 >= 0 && x1 < image_width); - Q_ASSERT(x2 >= 0 && x2 < image_width); - Q_ASSERT(y1 >= 0 && y1 < image_height); - Q_ASSERT(y2 >= 0 && y2 < image_height); + if (blendType == BlendTransformedBilinearTiled) { + x1 %= image_width; + x2 %= image_width; + y1 %= image_height; + y2 %= image_height; + + if (x1 < 0) x1 += image_width; + if (x2 < 0) x2 += image_width; + if (y1 < 0) y1 += image_height; + if (y2 < 0) y2 += image_height; + + Q_ASSERT(x1 >= 0 && x1 < image_width); + Q_ASSERT(x2 >= 0 && x2 < image_width); + Q_ASSERT(y1 >= 0 && y1 < image_height); + Q_ASSERT(y2 >= 0 && y2 < image_height); + } else { + x1 = qBound(0, x1, image_width - 1); + x2 = qBound(0, x2, image_width - 1); + y1 = qBound(0, y1, image_height - 1); + y2 = qBound(0, y2, image_height - 1); + } const uchar *s1 = data->texture.scanLine(y1); const uchar *s2 = data->texture.scanLine(y2); @@ -1059,39 +808,7 @@ static const uint * QT_FASTCALL fetchTransformedBilinearTiled(uint *buffer, cons return buffer; } -#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL) - -// explicit template instantiations needed to compile with VC6 and VC2002 - -#define SPANFUNC_POINTER_FETCHUNTRANSFORMED(Arg) \ - const uint *qt_fetchUntransformed_##Arg(uint *buffer, const Operator *op, const QSpanData *data, \ - int y, int x, int length) \ -{ \ - return qt_fetchUntransformed<QImage::Arg>(buffer, op, data, y, x, length Q_TEMPLATE_IMAGEFORMAT_CALL(QImage::Arg)); \ -} - -SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_Mono); -SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_MonoLSB); -SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_Indexed8); -SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_ARGB32_Premultiplied); -SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_ARGB32); -SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_RGB16); -SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_ARGB8565_Premultiplied); -SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_RGB666); -SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_ARGB6666_Premultiplied); -SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_RGB555); -SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_ARGB8555_Premultiplied); -SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_RGB888); -SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_RGB444); -SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_ARGB4444_Premultiplied); - -#undef SPANFUNC_POINTER_FETCHUNTRANSFORMED - -#define SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Arg) qt_fetchUntransformed_##Arg - -#else // !VC6 && !VC2002 -# define SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Arg) qt_fetchUntransformed<QImage::Arg> -#endif +#define SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Arg) qt_fetchUntransformed<QImage::Arg> static const SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = { // Untransformed @@ -1135,75 +852,75 @@ static const SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = { // Transformed { 0, // Invalid - fetchTransformed, // Mono - fetchTransformed, // MonoLsb - fetchTransformed, // Indexed8 - fetchTransformed, // RGB32 - fetchTransformed, // ARGB32 - fetchTransformed, // ARGB32_Premultiplied - fetchTransformed, // RGB16 - fetchTransformed, // ARGB8565_Premultiplied - fetchTransformed, // RGB666 - fetchTransformed, // ARGB6666_Premultiplied - fetchTransformed, // RGB555 - fetchTransformed, // ARGB8555_Premultiplied - fetchTransformed, // RGB888 - fetchTransformed, // RGB444 - fetchTransformed, // ARGB4444_Premultiplied + fetchTransformed<BlendTransformed>, // Mono + fetchTransformed<BlendTransformed>, // MonoLsb + fetchTransformed<BlendTransformed>, // Indexed8 + fetchTransformed<BlendTransformed>, // RGB32 + fetchTransformed<BlendTransformed>, // ARGB32 + fetchTransformed<BlendTransformed>, // ARGB32_Premultiplied + fetchTransformed<BlendTransformed>, // RGB16 + fetchTransformed<BlendTransformed>, // ARGB8565_Premultiplied + fetchTransformed<BlendTransformed>, // RGB666 + fetchTransformed<BlendTransformed>, // ARGB6666_Premultiplied + fetchTransformed<BlendTransformed>, // RGB555 + fetchTransformed<BlendTransformed>, // ARGB8555_Premultiplied + fetchTransformed<BlendTransformed>, // RGB888 + fetchTransformed<BlendTransformed>, // RGB444 + fetchTransformed<BlendTransformed>, // ARGB4444_Premultiplied }, { 0, // TransformedTiled - fetchTransformedTiled, // Mono - fetchTransformedTiled, // MonoLsb - fetchTransformedTiled, // Indexed8 - fetchTransformedTiled, // RGB32 - fetchTransformedTiled, // ARGB32 - fetchTransformedTiled, // ARGB32_Premultiplied - fetchTransformedTiled, // RGB16 - fetchTransformedTiled, // ARGB8565_Premultiplied - fetchTransformedTiled, // RGB666 - fetchTransformedTiled, // ARGB6666_Premultiplied - fetchTransformedTiled, // RGB555 - fetchTransformedTiled, // ARGB8555_Premultiplied - fetchTransformedTiled, // RGB888 - fetchTransformedTiled, // RGB444 - fetchTransformedTiled, // ARGB4444_Premultiplied + fetchTransformed<BlendTransformedTiled>, // Mono + fetchTransformed<BlendTransformedTiled>, // MonoLsb + fetchTransformed<BlendTransformedTiled>, // Indexed8 + fetchTransformed<BlendTransformedTiled>, // RGB32 + fetchTransformed<BlendTransformedTiled>, // ARGB32 + fetchTransformed<BlendTransformedTiled>, // ARGB32_Premultiplied + fetchTransformed<BlendTransformedTiled>, // RGB16 + fetchTransformed<BlendTransformedTiled>, // ARGB8565_Premultiplied + fetchTransformed<BlendTransformedTiled>, // RGB666 + fetchTransformed<BlendTransformedTiled>, // ARGB6666_Premultiplied + fetchTransformed<BlendTransformedTiled>, // RGB555 + fetchTransformed<BlendTransformedTiled>, // ARGB8555_Premultiplied + fetchTransformed<BlendTransformedTiled>, // RGB888 + fetchTransformed<BlendTransformedTiled>, // RGB444 + fetchTransformed<BlendTransformedTiled>, // ARGB4444_Premultiplied }, { 0, // Bilinear - fetchTransformedBilinear, // Mono - fetchTransformedBilinear, // MonoLsb - fetchTransformedBilinear, // Indexed8 - fetchTransformedBilinear, // RGB32 - fetchTransformedBilinear, // ARGB32 - fetchTransformedBilinear, // ARGB32_Premultiplied - fetchTransformedBilinear, // RGB16 - fetchTransformedBilinear, // ARGB8565_Premultiplied - fetchTransformedBilinear, // RGB666 - fetchTransformedBilinear, // ARGB6666_Premultiplied - fetchTransformedBilinear, // RGB555 - fetchTransformedBilinear, // ARGB8555_Premultiplied - fetchTransformedBilinear, // RGB888 - fetchTransformedBilinear, // RGB444 - fetchTransformedBilinear // ARGB4444_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // Mono + fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // MonoLsb + fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // Indexed8 + fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_ARGB32_Premultiplied>, // RGB32 + fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_ARGB32>, // ARGB32 + fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_ARGB32_Premultiplied>, // ARGB32_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB16 + fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // ARGB8565_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB666 + fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // ARGB6666_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB555 + fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // ARGB8555_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB888 + fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB444 + fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid> // ARGB4444_Premultiplied }, { 0, // BilinearTiled - fetchTransformedBilinearTiled, // Mono - fetchTransformedBilinearTiled, // MonoLsb - fetchTransformedBilinearTiled, // Indexed8 - fetchTransformedBilinearTiled, // RGB32 - fetchTransformedBilinearTiled, // ARGB32 - fetchTransformedBilinearTiled, // ARGB32_Premultiplied - fetchTransformedBilinearTiled, // RGB16 - fetchTransformedBilinearTiled, // ARGB8565_Premultiplied - fetchTransformedBilinearTiled, // RGB666 - fetchTransformedBilinearTiled, // ARGB6666_Premultiplied - fetchTransformedBilinearTiled, // RGB555 - fetchTransformedBilinearTiled, // ARGB8555_Premultiplied - fetchTransformedBilinearTiled, // RGB888 - fetchTransformedBilinearTiled, // RGB444 - fetchTransformedBilinearTiled // ARGB4444_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // Mono + fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // MonoLsb + fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // Indexed8 + fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_ARGB32_Premultiplied>, // RGB32 + fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_ARGB32>, // ARGB32 + fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_ARGB32_Premultiplied>, // ARGB32_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB16 + fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // ARGB8565_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB666 + fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // ARGB6666_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB555 + fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // ARGB8555_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB888 + fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB444 + fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid> // ARGB4444_Premultiplied }, }; @@ -1497,7 +1214,32 @@ static const uint * QT_FASTCALL fetchConicalGradient(uint *buffer, const Operato return b; } - +#if defined(Q_CC_RVCT) +// Force ARM code generation for comp_func_* -methods +# pragma push +# pragma arm +# if defined(QT_HAVE_ARMV6) +static __forceinline void preload(const uint *start) +{ + asm( "pld [start]" ); +} +static const uint L2CacheLineLength = 32; +static const uint L2CacheLineLengthInInts = L2CacheLineLength/sizeof(uint); +# define PRELOAD_INIT(x) preload(x); +# define PRELOAD_INIT2(x,y) PRELOAD_INIT(x) PRELOAD_INIT(y) +# define PRELOAD_COND(x) if (((uint)&x[i])%L2CacheLineLength == 0) preload(&x[i] + L2CacheLineLengthInInts); +// Two consecutive preloads stall, so space them out a bit by using different modulus. +# define PRELOAD_COND2(x,y) if (((uint)&x[i])%L2CacheLineLength == 0) preload(&x[i] + L2CacheLineLengthInInts); \ + if (((uint)&y[i])%L2CacheLineLength == 16) preload(&y[i] + L2CacheLineLengthInInts); +# endif // QT_HAVE_ARMV6 +#endif // Q_CC_RVCT + +#if !defined(Q_CC_RVCT) || !defined(QT_HAVE_ARMV6) +# define PRELOAD_INIT(x) +# define PRELOAD_INIT2(x,y) +# define PRELOAD_COND(x) +# define PRELOAD_COND2(x,y) +#endif /* The constant alpha factor describes an alpha factor that gets applied to the result of the composition operation combining it with the destination. @@ -1530,8 +1272,11 @@ static void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint QT_MEMFILL_UINT(dest, length, 0); } else { int ialpha = 255 - const_alpha; - for (int i = 0; i < length; ++i) + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) dest[i] = BYTE_MUL(dest[i], ialpha); + } } } @@ -1541,8 +1286,11 @@ static void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, ui QT_MEMFILL_UINT(dest, length, 0); } else { int ialpha = 255 - const_alpha; - for (int i = 0; i < length; ++i) + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) dest[i] = BYTE_MUL(dest[i], ialpha); + } } } @@ -1557,8 +1305,11 @@ static void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint colo } else { int ialpha = 255 - const_alpha; color = BYTE_MUL(color, const_alpha); - for (int i = 0; i < length; ++i) + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) dest[i] = color + BYTE_MUL(dest[i], ialpha); + } } } @@ -1568,8 +1319,11 @@ static void QT_FASTCALL comp_func_Source(uint *dest, const uint *src, int length ::memcpy(dest, src, length * sizeof(uint)); } else { int ialpha = 255 - const_alpha; - for (int i = 0; i < length; ++i) + PRELOAD_INIT2(dest, src) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) dest[i] = INTERPOLATE_PIXEL_255(src[i], const_alpha, dest[i], ialpha); + } } } @@ -1594,20 +1348,26 @@ static void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint } else { if (const_alpha != 255) color = BYTE_MUL(color, const_alpha); - for (int i = 0; i < length; ++i) + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) dest[i] = color + BYTE_MUL(dest[i], qAlpha(~color)); + } } } static void QT_FASTCALL comp_func_SourceOver(uint *dest, const uint *src, int length, uint const_alpha) { + PRELOAD_INIT2(dest, src) if (const_alpha == 255) { for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint s = src[i]; dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s)); } } else { for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint s = BYTE_MUL(src[i], const_alpha); dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s)); } @@ -1623,7 +1383,9 @@ static void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, { if (const_alpha != 255) color = BYTE_MUL(color, const_alpha); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; dest[i] = d + BYTE_MUL(color, qAlpha(~d)); } @@ -1631,13 +1393,16 @@ static void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, static void QT_FASTCALL comp_func_DestinationOver(uint *dest, const uint *src, int length, uint const_alpha) { + PRELOAD_INIT2(dest, src) if (const_alpha == 255) { for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; dest[i] = d + BYTE_MUL(src[i], qAlpha(~d)); } } else { for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = BYTE_MUL(src[i], const_alpha); dest[i] = d + BYTE_MUL(s, qAlpha(~d)); @@ -1651,13 +1416,17 @@ static void QT_FASTCALL comp_func_DestinationOver(uint *dest, const uint *src, i */ static void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha) { + PRELOAD_INIT(dest) if (const_alpha == 255) { - for (int i = 0; i < length; ++i) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) dest[i] = BYTE_MUL(color, qAlpha(dest[i])); + } } else { color = BYTE_MUL(color, const_alpha); uint cia = 255 - const_alpha; for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(d), d, cia); } @@ -1666,12 +1435,16 @@ static void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint co static void QT_FASTCALL comp_func_SourceIn(uint *dest, const uint *src, int length, uint const_alpha) { + PRELOAD_INIT2(dest, src) if (const_alpha == 255) { - for (int i = 0; i < length; ++i) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) dest[i] = BYTE_MUL(src[i], qAlpha(dest[i])); + } } else { uint cia = 255 - const_alpha; for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = BYTE_MUL(src[i], const_alpha); dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, cia); @@ -1690,19 +1463,25 @@ static void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, ui if (const_alpha != 255) { a = BYTE_MUL(a, const_alpha) + 255 - const_alpha; } + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) dest[i] = BYTE_MUL(dest[i], a); } } static void QT_FASTCALL comp_func_DestinationIn(uint *dest, const uint *src, int length, uint const_alpha) { + PRELOAD_INIT2(dest, src) if (const_alpha == 255) { - for (int i = 0; i < length; ++i) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) dest[i] = BYTE_MUL(dest[i], qAlpha(src[i])); + } } else { int cia = 255 - const_alpha; for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint a = BYTE_MUL(qAlpha(src[i]), const_alpha) + cia; dest[i] = BYTE_MUL(dest[i], a); } @@ -1716,13 +1495,17 @@ static void QT_FASTCALL comp_func_DestinationIn(uint *dest, const uint *src, int static void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha) { + PRELOAD_INIT(dest) if (const_alpha == 255) { - for (int i = 0; i < length; ++i) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) dest[i] = BYTE_MUL(color, qAlpha(~dest[i])); + } } else { color = BYTE_MUL(color, const_alpha); int cia = 255 - const_alpha; for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, cia); } @@ -1731,12 +1514,16 @@ static void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint c static void QT_FASTCALL comp_func_SourceOut(uint *dest, const uint *src, int length, uint const_alpha) { + PRELOAD_INIT2(dest, src) if (const_alpha == 255) { - for (int i = 0; i < length; ++i) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) dest[i] = BYTE_MUL(src[i], qAlpha(~dest[i])); + } } else { int cia = 255 - const_alpha; for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint s = BYTE_MUL(src[i], const_alpha); uint d = dest[i]; dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, cia); @@ -1754,18 +1541,25 @@ static void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, u uint a = qAlpha(~color); if (const_alpha != 255) a = BYTE_MUL(a, const_alpha) + 255 - const_alpha; - for (int i = 0; i < length; ++i) + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) dest[i] = BYTE_MUL(dest[i], a); + } } static void QT_FASTCALL comp_func_DestinationOut(uint *dest, const uint *src, int length, uint const_alpha) { + PRELOAD_INIT2(dest, src) if (const_alpha == 255) { - for (int i = 0; i < length; ++i) + for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) dest[i] = BYTE_MUL(dest[i], qAlpha(~src[i])); + } } else { int cia = 255 - const_alpha; for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint sia = BYTE_MUL(qAlpha(~src[i]), const_alpha) + cia; dest[i] = BYTE_MUL(dest[i], sia); } @@ -1784,20 +1578,26 @@ static void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint color = BYTE_MUL(color, const_alpha); } uint sia = qAlpha(~color); - for (int i = 0; i < length; ++i) + PRELOAD_INIT(dest) + for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(dest[i]), dest[i], sia); + } } static void QT_FASTCALL comp_func_SourceAtop(uint *dest, const uint *src, int length, uint const_alpha) { + PRELOAD_INIT2(dest, src) if (const_alpha == 255) { for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint s = src[i]; uint d = dest[i]; dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s)); } } else { for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint s = BYTE_MUL(src[i], const_alpha); uint d = dest[i]; dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s)); @@ -1817,7 +1617,9 @@ static void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, color = BYTE_MUL(color, const_alpha); a = qAlpha(color) + 255 - const_alpha; } + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; dest[i] = INTERPOLATE_PIXEL_255(d, a, color, qAlpha(~d)); } @@ -1825,8 +1627,10 @@ static void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, static void QT_FASTCALL comp_func_DestinationAtop(uint *dest, const uint *src, int length, uint const_alpha) { + PRELOAD_INIT2(dest, src) if (const_alpha == 255) { for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint s = src[i]; uint d = dest[i]; dest[i] = INTERPOLATE_PIXEL_255(d, qAlpha(s), s, qAlpha(~d)); @@ -1834,6 +1638,7 @@ static void QT_FASTCALL comp_func_DestinationAtop(uint *dest, const uint *src, i } else { int cia = 255 - const_alpha; for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint s = BYTE_MUL(src[i], const_alpha); uint d = dest[i]; uint a = qAlpha(s) + cia; @@ -1854,7 +1659,9 @@ static void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, color = BYTE_MUL(color, const_alpha); uint sia = qAlpha(~color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, sia); } @@ -1862,14 +1669,17 @@ static void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, static void QT_FASTCALL comp_func_XOR(uint *dest, const uint *src, int length, uint const_alpha) { + PRELOAD_INIT2(dest, src) if (const_alpha == 255) { for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s)); } } else { for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = BYTE_MUL(src[i], const_alpha); dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s)); @@ -1920,7 +1730,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Plus_impl(uint *dest, int { uint s = color; + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; #define MIX(mask) (qMin(((qint64(s)&mask) + (qint64(d)&mask)), qint64(mask))) d = (MIX(AMASK) | MIX(RMASK) | MIX(GMASK) | MIX(BMASK)); @@ -1940,7 +1752,9 @@ static void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Plus_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -1976,7 +1790,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Multiply_impl(uint *dest, int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -2002,7 +1818,9 @@ static void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint co template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Multiply_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -2040,7 +1858,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Screen_impl(uint *dest, i int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -2066,7 +1886,9 @@ static void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint colo template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Screen_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -2115,7 +1937,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Overlay_impl(uint *dest, int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -2141,7 +1965,9 @@ static void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint col template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Overlay_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -2184,7 +2010,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Darken_impl(uint *dest, i int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -2210,7 +2038,9 @@ static void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint colo template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Darken_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -2253,7 +2083,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Lighten_impl(uint *dest, int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -2279,7 +2111,9 @@ static void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint col template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Lighten_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -2332,7 +2166,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorDodge_impl(uint *des int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -2358,7 +2194,9 @@ static void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorDodge_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -2411,7 +2249,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorBurn_impl(uint *dest int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -2437,7 +2277,9 @@ static void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint c template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorBurn_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -2487,7 +2329,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_HardLight_impl(uint *dest int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -2513,7 +2357,9 @@ static void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint c template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_HardLight_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -2572,7 +2418,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_SoftLight_impl(uint *dest int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -2598,7 +2446,9 @@ static void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint c template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_SoftLight_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -2641,7 +2491,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Difference_impl(uint *des int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -2667,7 +2519,9 @@ static void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Difference_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -2704,7 +2558,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void QT_FASTCALL comp_func_solid_Exclusion_imp int sg = qGreen(color); int sb = qBlue(color); + PRELOAD_INIT(dest) for (int i = 0; i < length; ++i) { + PRELOAD_COND(dest) uint d = dest[i]; int da = qAlpha(d); @@ -2730,7 +2586,9 @@ static void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint c template <typename T> Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Exclusion_impl(uint *dest, const uint *src, int length, const T &coverage) { + PRELOAD_INIT2(dest, src) for (int i = 0; i < length; ++i) { + PRELOAD_COND2(dest, src) uint d = dest[i]; uint s = src[i]; @@ -2756,6 +2614,11 @@ static void QT_FASTCALL comp_func_Exclusion(uint *dest, const uint *src, int len comp_func_Exclusion_impl(dest, src, length, QPartialCoverage(const_alpha)); } +#if defined(Q_CC_RVCT) +// Restore pragma state from previous #pragma arm +# pragma pop +#endif + static void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest, int length, uint color, @@ -3219,8 +3082,7 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData) } template <class T> -Q_STATIC_TEMPLATE_FUNCTION void blendColor(int count, const QSpan *spans, void *userData - Q_TEMPLATE_FIX(T)) +Q_STATIC_TEMPLATE_FUNCTION void blendColor(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); Operator op = getOperator(data, spans, count); @@ -3266,28 +3128,7 @@ Q_STATIC_TEMPLATE_FUNCTION void blendColor(int count, const QSpan *spans, void * blend_color_generic(count, spans, userData); } -#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL) -#define BLEND_COLOR_DECL(DST) \ - static void blendColor_##DST(int count, \ - const QSpan *spans, \ - void *userData) \ - { \ - blendColor<DST>(count, spans, userData Q_TEMPLATE_CALL(DST)); \ - } - -BLEND_COLOR_DECL(qargb8565) -BLEND_COLOR_DECL(qrgb666) -BLEND_COLOR_DECL(qargb6666) -BLEND_COLOR_DECL(qrgb555) -BLEND_COLOR_DECL(qargb8555) -BLEND_COLOR_DECL(qrgb888) -BLEND_COLOR_DECL(qrgb444) -BLEND_COLOR_DECL(qargb4444) -#undef DEST_FETCH_DECL -#define SPANFUNC_POINTER_BLENDCOLOR(DST) blendColor_##DST -#else // !VC6 && !VC2002 -# define SPANFUNC_POINTER_BLENDCOLOR(DST) blendColor<DST> -#endif +#define SPANFUNC_POINTER_BLENDCOLOR(DST) blendColor<DST> static void blend_color_rgb16(int count, const QSpan *spans, void *userData) { @@ -3365,45 +3206,117 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData) blend_color_generic(count, spans, userData); } -template <SpanMethod spanMethod> -Q_STATIC_TEMPLATE_FUNCTION void blend_src_generic(int count, const QSpan *spans, void *userData - Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod)) +template <typename T> +void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handler) { - QSpanData *data = reinterpret_cast<QSpanData *>(userData); - - uint buffer[buffer_size]; - uint src_buffer[buffer_size]; - Operator op = getOperator(data, spans, count); - uint const_alpha = 256; if (data->type == QSpanData::Texture) const_alpha = data->texture.const_alpha; - while (count--) { + int coverage = 0; + while (count) { int x = spans->x; - int length = spans->len; - const int coverage = (spans->coverage * const_alpha) >> 8; + const int y = spans->y; + int right = x + spans->len; + + // compute length of adjacent spans + for (int i = 1; i < count && spans[i].y == y && spans[i].x == right; ++i) + right += spans[i].len; + int length = right - x; + while (length) { int l = qMin(buffer_size, length); - const uint *src = op.src_fetch(src_buffer, &op, data, spans->y, x, l); - if (spanMethod == RegularSpans) { - uint *dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; - op.func(dest, src, l, coverage); - if (op.dest_store) - op.dest_store(data->rasterBuffer, x, spans->y, dest, l); - } else { - drawBufferSpan(data, src, l, x, spans->y, l, coverage); - } - x += l; length -= l; + + int process_length = l; + int process_x = x; + + const uint *src = handler.fetch(process_x, y, process_length); + int offset = 0; + while (l > 0) { + if (x == spans->x) // new span? + coverage = (spans->coverage * const_alpha) >> 8; + + int right = spans->x + spans->len; + int len = qMin(l, right - x); + + handler.process(x, y, len, coverage, src, offset); + + l -= len; + x += len; + offset += len; + + if (x == right) { // done with current span? + ++spans; + --count; + } + } + handler.store(process_x, y, process_length); } - ++spans; } } +struct QBlendBase +{ + QBlendBase(QSpanData *d, Operator o) + : data(d) + , op(o) + , dest(0) + { + } + + QSpanData *data; + Operator op; + + uint *dest; + + uint buffer[buffer_size]; + uint src_buffer[buffer_size]; +}; + +template <SpanMethod spanMethod> +class BlendSrcGeneric : public QBlendBase +{ +public: + BlendSrcGeneric(QSpanData *d, Operator o) + : QBlendBase(d, o) + { + } + + const uint *fetch(int x, int y, int len) + { + if (spanMethod == RegularSpans) + dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, y, len) : buffer; + + return op.src_fetch(src_buffer, &op, data, y, x, len); + } + + void process(int x, int y, int len, int coverage, const uint *src, int offset) + { + if (spanMethod == RegularSpans) + op.func(dest + offset, src + offset, len, coverage); + else + drawBufferSpan(data, src + offset, len, x, y, len, coverage); + } + + void store(int x, int y, int len) + { + if (spanMethod == RegularSpans && op.dest_store) { + op.dest_store(data->rasterBuffer, x, y, dest, len); + } + } +}; + +template <SpanMethod spanMethod> +Q_STATIC_TEMPLATE_FUNCTION void blend_src_generic(int count, const QSpan *spans, void *userData) +{ + QSpanData *data = reinterpret_cast<QSpanData *>(userData); + BlendSrcGeneric<spanMethod> blend(data, getOperator(data, spans, count)); + handleSpans(count, spans, data, blend); +} + template <SpanMethod spanMethod> -Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_generic(int count, const QSpan *spans, void *userData - Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod)) +Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_generic(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); @@ -3454,13 +3367,12 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_generic(int count, const QSp } template <SpanMethod spanMethod> -Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_argb(int count, const QSpan *spans, void *userData - Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod)) +Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_argb(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); if (data->texture.format != QImage::Format_ARGB32_Premultiplied && data->texture.format != QImage::Format_RGB32) { - blend_untransformed_generic<spanMethod>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, spanMethod)); + blend_untransformed_generic<spanMethod>(count, spans, userData); return; } @@ -4706,8 +4618,7 @@ void QT_FASTCALL blendUntransformed(int count, const QSpan *spans, void *userDat if (mode != QPainter::CompositionMode_SourceOver && mode != QPainter::CompositionMode_Source) { - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); return; } @@ -4769,8 +4680,7 @@ static void blend_untransformed_rgb888(int count, const QSpan *spans, blendUntransformed<qrgb888, qrgb888>(count, spans, userData); else #endif - blend_untransformed_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_untransformed_generic<RegularSpans>(count, spans, userData); } static void blend_untransformed_argb6666(int count, const QSpan *spans, @@ -4785,8 +4695,7 @@ static void blend_untransformed_argb6666(int count, const QSpan *spans, blendUntransformed<qargb6666, qrgb666>(count, spans, userData); else #endif - blend_untransformed_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_untransformed_generic<RegularSpans>(count, spans, userData); } static void blend_untransformed_rgb666(int count, const QSpan *spans, @@ -4801,8 +4710,7 @@ static void blend_untransformed_rgb666(int count, const QSpan *spans, blendUntransformed<qrgb666, qrgb666>(count, spans, userData); else #endif - blend_untransformed_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_untransformed_generic<RegularSpans>(count, spans, userData); } static void blend_untransformed_argb8565(int count, const QSpan *spans, @@ -4817,8 +4725,7 @@ static void blend_untransformed_argb8565(int count, const QSpan *spans, blendUntransformed<qargb8565, qrgb565>(count, spans, userData); else #endif - blend_untransformed_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_untransformed_generic<RegularSpans>(count, spans, userData); } static void blend_untransformed_rgb565(int count, const QSpan *spans, @@ -4833,8 +4740,7 @@ static void blend_untransformed_rgb565(int count, const QSpan *spans, blendUntransformed<qrgb565, qrgb565>(count, spans, userData); else #endif - blend_untransformed_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_untransformed_generic<RegularSpans>(count, spans, userData); } static void blend_untransformed_argb8555(int count, const QSpan *spans, @@ -4849,8 +4755,7 @@ static void blend_untransformed_argb8555(int count, const QSpan *spans, blendUntransformed<qargb8555, qrgb555>(count, spans, userData); else #endif - blend_untransformed_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_untransformed_generic<RegularSpans>(count, spans, userData); } static void blend_untransformed_rgb555(int count, const QSpan *spans, @@ -4865,8 +4770,7 @@ static void blend_untransformed_rgb555(int count, const QSpan *spans, blendUntransformed<qrgb555, qrgb555>(count, spans, userData); else #endif - blend_untransformed_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_untransformed_generic<RegularSpans>(count, spans, userData); } static void blend_untransformed_argb4444(int count, const QSpan *spans, @@ -4881,8 +4785,7 @@ static void blend_untransformed_argb4444(int count, const QSpan *spans, blendUntransformed<qargb4444, qrgb444>(count, spans, userData); else #endif - blend_untransformed_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_untransformed_generic<RegularSpans>(count, spans, userData); } static void blend_untransformed_rgb444(int count, const QSpan *spans, @@ -4897,13 +4800,11 @@ static void blend_untransformed_rgb444(int count, const QSpan *spans, blendUntransformed<qrgb444, qrgb444>(count, spans, userData); else #endif - blend_untransformed_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_untransformed_generic<RegularSpans>(count, spans, userData); } template <SpanMethod spanMethod> -Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_generic(int count, const QSpan *spans, void *userData - Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod)) +Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_generic(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); @@ -4957,13 +4858,12 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_generic(int count, const QSpan *span } template <SpanMethod spanMethod> -Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_argb(int count, const QSpan *spans, void *userData - Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod)) +Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_argb(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); if (data->texture.format != QImage::Format_ARGB32_Premultiplied && data->texture.format != QImage::Format_RGB32) { - blend_tiled_generic<spanMethod>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, spanMethod)); + blend_tiled_generic<spanMethod>(count, spans, userData); return; } @@ -5019,8 +4919,7 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTiled(int count, const QSpan *spans, void * if (mode != QPainter::CompositionMode_SourceOver && mode != QPainter::CompositionMode_Source) { - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); return; } @@ -5052,30 +4951,60 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTiled(int count, const QSpan *spans, void * if (sy < 0) sy += image_height; - while (length) { - int l = qMin(image_width - sx, length); - if (buffer_size < l) - l = buffer_size; - - DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; - const SRC *src = (SRC*)data->texture.scanLine(sy) + sx; - if (modeSource && coverage == 255) { + if (modeSource && coverage == 255) { + // Copy the first texture block + length = image_width; + while (length) { + int l = qMin(image_width - sx, length); + if (buffer_size < l) + l = buffer_size; + DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; + const SRC *src = (SRC*)data->texture.scanLine(sy) + sx; qt_memconvert<DST, SRC>(dest, src, l); - } else if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && - (quintptr(dest) & 3) == (quintptr(src) & 3)) - { - blendUntransformed_dest24(dest, src, coverage, l); - } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && - (quintptr(dest) & 3) == (quintptr(src) & 3)) - { - blendUntransformed_dest16(dest, src, coverage, l); - } else { - blendUntransformed_unaligned(dest, src, coverage, l); + length -= l; + sx = 0; } - x += l; - length -= l; - sx = 0; + // Now use the rasterBuffer as the source of the texture, + // We can now progressively copy larger blocks + // - Less cpu time in code figuring out what to copy + // We are dealing with one block of data + // - More likely to fit in the cache + // - can use memcpy + int copy_image_width = image_width; + length = spans->len - image_width; + DST *src = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; + DST *dest = src + copy_image_width; + while (copy_image_width < length) { + qt_memconvert(dest, src, copy_image_width); + dest += copy_image_width; + length -= copy_image_width; + copy_image_width *= 2; + } + qt_memconvert(dest, src, length); + } else { + while (length) { + int l = qMin(image_width - sx, length); + if (buffer_size < l) + l = buffer_size; + DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; + const SRC *src = (SRC*)data->texture.scanLine(sy) + sx; + if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && + (quintptr(dest) & 3) == (quintptr(src) & 3)) + { + blendUntransformed_dest24(dest, src, coverage, l); + } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && + (quintptr(dest) & 3) == (quintptr(src) & 3)) + { + blendUntransformed_dest16(dest, src, coverage, l); + } else { + blendUntransformed_unaligned(dest, src, coverage, l); + } + + x += l; + length -= l; + sx = 0; + } } ++spans; } @@ -5090,8 +5019,7 @@ static void blend_tiled_rgb888(int count, const QSpan *spans, void *userData) blendTiled<qrgb888, qrgb888>(count, spans, userData); else #endif - blend_tiled_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_tiled_generic<RegularSpans>(count, spans, userData); } static void blend_tiled_argb6666(int count, const QSpan *spans, void *userData) @@ -5105,8 +5033,7 @@ static void blend_tiled_argb6666(int count, const QSpan *spans, void *userData) blendTiled<qargb6666, qrgb666>(count, spans, userData); else #endif - blend_tiled_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_tiled_generic<RegularSpans>(count, spans, userData); } static void blend_tiled_rgb666(int count, const QSpan *spans, void *userData) @@ -5120,8 +5047,7 @@ static void blend_tiled_rgb666(int count, const QSpan *spans, void *userData) blendTiled<qrgb666, qrgb666>(count, spans, userData); else #endif - blend_tiled_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_tiled_generic<RegularSpans>(count, spans, userData); } static void blend_tiled_argb8565(int count, const QSpan *spans, void *userData) @@ -5135,8 +5061,7 @@ static void blend_tiled_argb8565(int count, const QSpan *spans, void *userData) blendTiled<qargb8565, qrgb565>(count, spans, userData); else #endif - blend_tiled_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_tiled_generic<RegularSpans>(count, spans, userData); } static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData) @@ -5150,8 +5075,7 @@ static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData) blendTiled<qrgb565, qrgb565>(count, spans, userData); else #endif - blend_tiled_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_tiled_generic<RegularSpans>(count, spans, userData); } static void blend_tiled_argb8555(int count, const QSpan *spans, void *userData) @@ -5165,8 +5089,7 @@ static void blend_tiled_argb8555(int count, const QSpan *spans, void *userData) blendTiled<qargb8555, qrgb555>(count, spans, userData); else #endif - blend_tiled_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_tiled_generic<RegularSpans>(count, spans, userData); } static void blend_tiled_rgb555(int count, const QSpan *spans, void *userData) @@ -5180,8 +5103,7 @@ static void blend_tiled_rgb555(int count, const QSpan *spans, void *userData) blendTiled<qrgb555, qrgb555>(count, spans, userData); else #endif - blend_tiled_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_tiled_generic<RegularSpans>(count, spans, userData); } static void blend_tiled_argb4444(int count, const QSpan *spans, void *userData) @@ -5195,8 +5117,7 @@ static void blend_tiled_argb4444(int count, const QSpan *spans, void *userData) blendTiled<qargb4444, qrgb444>(count, spans, userData); else #endif - blend_tiled_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_tiled_generic<RegularSpans>(count, spans, userData); } static void blend_tiled_rgb444(int count, const QSpan *spans, void *userData) @@ -5210,19 +5131,17 @@ static void blend_tiled_rgb444(int count, const QSpan *spans, void *userData) blendTiled<qrgb444, qrgb444>(count, spans, userData); else #endif - blend_tiled_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_tiled_generic<RegularSpans>(count, spans, userData); } template <SpanMethod spanMethod> -Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_argb(int count, const QSpan *spans, void *userData - Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod)) +Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_argb(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); if (data->texture.format != QImage::Format_ARGB32_Premultiplied && data->texture.format != QImage::Format_RGB32) { - blend_src_generic<spanMethod>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, spanMethod)); + blend_src_generic<spanMethod>(count, spans, userData); return; } @@ -5401,8 +5320,7 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedBilinear(int count, const QSpan if (mode != QPainter::CompositionMode_SourceOver) { - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); return; } @@ -5605,8 +5523,7 @@ static void blend_transformed_bilinear_rgb888(int count, const QSpan *spans, voi blendTransformedBilinear<qrgb888, qrgb888>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_bilinear_argb6666(int count, const QSpan *spans, void *userData) @@ -5620,8 +5537,7 @@ static void blend_transformed_bilinear_argb6666(int count, const QSpan *spans, v blendTransformedBilinear<qargb6666, qrgb666>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_bilinear_rgb666(int count, const QSpan *spans, void *userData) @@ -5635,8 +5551,7 @@ static void blend_transformed_bilinear_rgb666(int count, const QSpan *spans, voi blendTransformedBilinear<qrgb666, qrgb666>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_bilinear_argb8565(int count, const QSpan *spans, void *userData) @@ -5650,8 +5565,7 @@ static void blend_transformed_bilinear_argb8565(int count, const QSpan *spans, v blendTransformedBilinear<qargb8565, qrgb565>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_bilinear_rgb565(int count, const QSpan *spans, @@ -5666,8 +5580,7 @@ static void blend_transformed_bilinear_rgb565(int count, const QSpan *spans, blendTransformedBilinear<qrgb565, qargb8565>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_bilinear_argb8555(int count, const QSpan *spans, void *userData) @@ -5681,8 +5594,7 @@ static void blend_transformed_bilinear_argb8555(int count, const QSpan *spans, v blendTransformedBilinear<qargb8555, qrgb555>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_bilinear_rgb555(int count, const QSpan *spans, void *userData) @@ -5696,8 +5608,7 @@ static void blend_transformed_bilinear_rgb555(int count, const QSpan *spans, voi blendTransformedBilinear<qrgb555, qrgb555>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_bilinear_argb4444(int count, const QSpan *spans, void *userData) @@ -5711,8 +5622,7 @@ static void blend_transformed_bilinear_argb4444(int count, const QSpan *spans, v blendTransformedBilinear<qargb4444, qrgb444>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_bilinear_rgb444(int count, const QSpan *spans, void *userData) @@ -5726,18 +5636,16 @@ static void blend_transformed_bilinear_rgb444(int count, const QSpan *spans, voi blendTransformedBilinear<qrgb444, qrgb444>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } template <SpanMethod spanMethod> -Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_tiled_argb(int count, const QSpan *spans, void *userData - Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod)) +Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_tiled_argb(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); if (data->texture.format != QImage::Format_ARGB32_Premultiplied && data->texture.format != QImage::Format_RGB32) { - blend_src_generic<spanMethod>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, spanMethod)); + blend_src_generic<spanMethod>(count, spans, userData); return; } @@ -5923,13 +5831,12 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_tiled_argb(int count, } template <SpanMethod spanMethod> -Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *spans, void *userData - Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod)) +Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); if (data->texture.format != QImage::Format_ARGB32_Premultiplied && data->texture.format != QImage::Format_RGB32) { - blend_src_generic<spanMethod>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, spanMethod)); + blend_src_generic<spanMethod>(count, spans, userData); return; } @@ -6051,8 +5958,7 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformed(int count, const QSpan *spans, QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; if (mode != QPainter::CompositionMode_SourceOver) { - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); return; } @@ -6201,8 +6107,7 @@ static void blend_transformed_rgb888(int count, const QSpan *spans, blendTransformed<qrgb888, qrgb888>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_argb6666(int count, const QSpan *spans, @@ -6217,8 +6122,7 @@ static void blend_transformed_argb6666(int count, const QSpan *spans, blendTransformed<qargb6666, qrgb666>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_rgb666(int count, const QSpan *spans, @@ -6233,8 +6137,7 @@ static void blend_transformed_rgb666(int count, const QSpan *spans, blendTransformed<qrgb666, qrgb666>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_argb8565(int count, const QSpan *spans, @@ -6249,8 +6152,7 @@ static void blend_transformed_argb8565(int count, const QSpan *spans, blendTransformed<qargb8565, qrgb565>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_rgb565(int count, const QSpan *spans, @@ -6265,8 +6167,7 @@ static void blend_transformed_rgb565(int count, const QSpan *spans, blendTransformed<qrgb565, qrgb565>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_argb8555(int count, const QSpan *spans, @@ -6281,8 +6182,7 @@ static void blend_transformed_argb8555(int count, const QSpan *spans, blendTransformed<qargb8555, qrgb555>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_rgb555(int count, const QSpan *spans, @@ -6297,8 +6197,7 @@ static void blend_transformed_rgb555(int count, const QSpan *spans, blendTransformed<qrgb555, qrgb555>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_argb4444(int count, const QSpan *spans, @@ -6313,8 +6212,7 @@ static void blend_transformed_argb4444(int count, const QSpan *spans, blendTransformed<qargb4444, qrgb444>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_rgb444(int count, const QSpan *spans, @@ -6329,18 +6227,16 @@ static void blend_transformed_rgb444(int count, const QSpan *spans, blendTransformed<qrgb444, qrgb444>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } template <SpanMethod spanMethod> -Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_tiled_argb(int count, const QSpan *spans, void *userData - Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod)) +Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_tiled_argb(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); if (data->texture.format != QImage::Format_ARGB32_Premultiplied && data->texture.format != QImage::Format_RGB32) { - blend_src_generic<spanMethod>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, spanMethod)); + blend_src_generic<spanMethod>(count, spans, userData); return; } @@ -6474,8 +6370,7 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedTiled(int count, const QSpan *sp QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; if (mode != QPainter::CompositionMode_SourceOver) { - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); return; } @@ -6625,8 +6520,7 @@ static void blend_transformed_tiled_rgb888(int count, const QSpan *spans, blendTransformedTiled<qrgb888, qrgb888>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_tiled_argb6666(int count, const QSpan *spans, @@ -6641,8 +6535,7 @@ static void blend_transformed_tiled_argb6666(int count, const QSpan *spans, blendTransformedTiled<qargb6666, qrgb666>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_tiled_rgb666(int count, const QSpan *spans, @@ -6657,8 +6550,7 @@ static void blend_transformed_tiled_rgb666(int count, const QSpan *spans, blendTransformedTiled<qrgb666, qrgb666>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_tiled_argb8565(int count, const QSpan *spans, @@ -6673,8 +6565,7 @@ static void blend_transformed_tiled_argb8565(int count, const QSpan *spans, blendTransformedTiled<qargb8565, qrgb565>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_tiled_rgb565(int count, const QSpan *spans, @@ -6689,8 +6580,7 @@ static void blend_transformed_tiled_rgb565(int count, const QSpan *spans, blendTransformedTiled<qrgb565, qrgb565>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_tiled_argb8555(int count, const QSpan *spans, @@ -6705,8 +6595,7 @@ static void blend_transformed_tiled_argb8555(int count, const QSpan *spans, blendTransformedTiled<qargb8555, qrgb555>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_tiled_rgb555(int count, const QSpan *spans, @@ -6721,8 +6610,7 @@ static void blend_transformed_tiled_rgb555(int count, const QSpan *spans, blendTransformedTiled<qrgb555, qrgb555>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_tiled_argb4444(int count, const QSpan *spans, @@ -6737,8 +6625,7 @@ static void blend_transformed_tiled_argb4444(int count, const QSpan *spans, blendTransformedTiled<qargb4444, qrgb444>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } static void blend_transformed_tiled_rgb444(int count, const QSpan *spans, @@ -6753,36 +6640,10 @@ static void blend_transformed_tiled_rgb444(int count, const QSpan *spans, blendTransformedTiled<qrgb444, qrgb444>(count, spans, userData); else #endif - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } -#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL) - -// explicit template instantiations needed to compile with VC6 and VC2002 - -#define SPANFUNC_INSTANTIATION(Name, Arg) \ -static inline void Name##_##Arg(int count, const QSpan *spans, void *userData) \ -{ \ - Name<Arg>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, Arg)); \ -} - -SPANFUNC_INSTANTIATION(blend_untransformed_generic, RegularSpans); -SPANFUNC_INSTANTIATION(blend_untransformed_argb, RegularSpans); -SPANFUNC_INSTANTIATION(blend_tiled_generic, RegularSpans); -SPANFUNC_INSTANTIATION(blend_tiled_argb, RegularSpans); -SPANFUNC_INSTANTIATION(blend_src_generic, RegularSpans); -SPANFUNC_INSTANTIATION(blend_transformed_argb, RegularSpans); -SPANFUNC_INSTANTIATION(blend_transformed_tiled_argb, RegularSpans); -SPANFUNC_INSTANTIATION(blend_transformed_bilinear_argb, RegularSpans); -SPANFUNC_INSTANTIATION(blend_transformed_bilinear_tiled_argb, RegularSpans); -#undef SPANFUNC_INSTANTIATION - -#define SPANFUNC_POINTER(Name, Arg) Name##_##Arg - -#else // !VC6 && !VC2002 # define SPANFUNC_POINTER(Name, Arg) Name<Arg> -#endif /* Image formats here are target formats */ @@ -7149,8 +7010,7 @@ static void qt_gradient_quint32(int count, const QSpan *spans, void *userData) } } else { - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } } @@ -7198,8 +7058,7 @@ static void qt_gradient_quint16(int count, const QSpan *spans, void *userData) data->solid.color = oldColor; } else { - blend_src_generic<RegularSpans>(count, spans, userData - Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans)); + blend_src_generic<RegularSpans>(count, spans, userData); } } @@ -7258,7 +7117,13 @@ static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer, } void qt_build_pow_tables() { - qreal smoothing = 1.7; + qreal smoothing = qreal(1.7); + +#ifdef Q_WS_MAC + // decided by testing a few things on an iMac, should probably get this from the + // system... + smoothing = 2.0; +#endif #ifdef Q_WS_WIN int winSmooth; @@ -7274,15 +7139,15 @@ void qt_build_pow_tables() { } #else for (int i=0; i<256; ++i) { - qt_pow_rgb_gamma[i] = uchar(qRound(pow(i / 255.0, smoothing) * 255)); - qt_pow_rgb_invgamma[i] = uchar(qRound(pow(i / 255.0, 1 / smoothing) * 255)); + qt_pow_rgb_gamma[i] = uchar(qRound(pow(i / qreal(255.0), smoothing) * 255)); + qt_pow_rgb_invgamma[i] = uchar(qRound(pow(i / qreal(255.), 1 / smoothing) * 255)); } #endif #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) const qreal gray_gamma = 2.31; for (int i=0; i<256; ++i) - qt_pow_gamma[i] = uint(qRound(pow(i / 255.0, gray_gamma) * 2047)); + qt_pow_gamma[i] = uint(qRound(pow(i / qreal(255.), gray_gamma) * 2047)); for (int i=0; i<2048; ++i) qt_pow_invgamma[i] = uchar(qRound(pow(i / 2047.0, 1 / gray_gamma) * 255)); #endif @@ -7404,7 +7269,7 @@ static void qt_alphamapblit_quint32(QRasterBuffer *rasterBuffer, #endif { int ialpha = 255 - coverage; - dest[i] = BYTE_MUL(c, uint(coverage)) + BYTE_MUL(dest[i], ialpha); + dest[i] = INTERPOLATE_PIXEL_255(c, coverage, dest[i], ialpha); } } } @@ -7445,7 +7310,7 @@ static void qt_alphamapblit_quint32(QRasterBuffer *rasterBuffer, #endif { int ialpha = 255 - coverage; - dest[xp] = BYTE_MUL(c, uint(coverage)) + BYTE_MUL(dest[xp], ialpha); + dest[xp] = INTERPOLATE_PIXEL_255(c, coverage, dest[xp], ialpha); } } @@ -7547,13 +7412,13 @@ inline void qt_rectfill_template(QRasterBuffer *rasterBuffer, QT_RECTFILL(quint32) QT_RECTFILL(quint16) QT_RECTFILL(qargb8565) -QT_RECTFILL(qrgb666); -QT_RECTFILL(qargb6666); +QT_RECTFILL(qrgb666) +QT_RECTFILL(qargb6666) QT_RECTFILL(qrgb555) QT_RECTFILL(qargb8555) QT_RECTFILL(qrgb888) -QT_RECTFILL(qrgb444); -QT_RECTFILL(qargb4444); +QT_RECTFILL(qrgb444) +QT_RECTFILL(qargb4444) #undef QT_RECTFILL @@ -8031,6 +7896,96 @@ static uint detectCPUFeatures() #endif } +#if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6) +// Move these to qdrawhelper_arm.c when all +// functions are implemented using arm assembly. +static CompositionFunctionSolid qt_functionForModeSolid_ARMv6[numCompositionFunctions] = { + comp_func_solid_SourceOver, + comp_func_solid_DestinationOver, + comp_func_solid_Clear, + comp_func_solid_Source, + comp_func_solid_Destination, + comp_func_solid_SourceIn, + comp_func_solid_DestinationIn, + comp_func_solid_SourceOut, + comp_func_solid_DestinationOut, + comp_func_solid_SourceAtop, + comp_func_solid_DestinationAtop, + comp_func_solid_XOR, + comp_func_solid_Plus, + comp_func_solid_Multiply, + comp_func_solid_Screen, + comp_func_solid_Overlay, + comp_func_solid_Darken, + comp_func_solid_Lighten, + comp_func_solid_ColorDodge, + comp_func_solid_ColorBurn, + comp_func_solid_HardLight, + comp_func_solid_SoftLight, + comp_func_solid_Difference, + comp_func_solid_Exclusion, + rasterop_solid_SourceOrDestination, + rasterop_solid_SourceAndDestination, + rasterop_solid_SourceXorDestination, + rasterop_solid_NotSourceAndNotDestination, + rasterop_solid_NotSourceOrNotDestination, + rasterop_solid_NotSourceXorDestination, + rasterop_solid_NotSource, + rasterop_solid_NotSourceAndDestination, + rasterop_solid_SourceAndNotDestination +}; + +static CompositionFunction qt_functionForMode_ARMv6[numCompositionFunctions] = { + comp_func_SourceOver_armv6, + comp_func_DestinationOver, + comp_func_Clear, + comp_func_Source_armv6, + comp_func_Destination, + comp_func_SourceIn, + comp_func_DestinationIn, + comp_func_SourceOut, + comp_func_DestinationOut, + comp_func_SourceAtop, + comp_func_DestinationAtop, + comp_func_XOR, + comp_func_Plus, + comp_func_Multiply, + comp_func_Screen, + comp_func_Overlay, + comp_func_Darken, + comp_func_Lighten, + comp_func_ColorDodge, + comp_func_ColorBurn, + comp_func_HardLight, + comp_func_SoftLight, + comp_func_Difference, + comp_func_Exclusion, + rasterop_SourceOrDestination, + rasterop_SourceAndDestination, + rasterop_SourceXorDestination, + rasterop_NotSourceAndNotDestination, + rasterop_NotSourceOrNotDestination, + rasterop_NotSourceXorDestination, + rasterop_NotSource, + rasterop_NotSourceAndDestination, + rasterop_SourceAndNotDestination +}; + +static void qt_blend_color_argb_armv6(int count, const QSpan *spans, void *userData) +{ + QSpanData *data = reinterpret_cast<QSpanData *>(userData); + + CompositionFunctionSolid func = qt_functionForModeSolid_ARMv6[data->rasterBuffer->compositionMode]; + while (count--) { + uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x; + func(target, spans->len, data->solid.color, spans->coverage); + ++spans; + } +} + +#endif // Q_CC_RVCT && QT_HAVE_ARMV6 + + void qInitDrawhelperAsm() { static uint features = 0xffffffff; @@ -8146,6 +8101,20 @@ void qInitDrawhelperAsm() #endif // QT_NO_DEBUG +#if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6) + functionForModeAsm = qt_functionForMode_ARMv6; + functionForModeSolidAsm = qt_functionForModeSolid_ARMv6; + + qt_memfill32 = qt_memfill32_armv6; + + qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_armv6; + + qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6; + qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6; + qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6; + qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6; +#endif // Q_CC_RVCT && QT_HAVE_ARMV6 + if (functionForModeSolidAsm) { const int destinationMode = QPainter::CompositionMode_Destination; functionForModeSolidAsm[destinationMode] = functionForModeSolid_C[destinationMode]; diff --git a/src/gui/painting/qdrawhelper_armv6_p.h b/src/gui/painting/qdrawhelper_armv6_p.h new file mode 100644 index 0000000..9f3e062 --- /dev/null +++ b/src/gui/painting/qdrawhelper_armv6_p.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDRAWHELPER_ARMV6_P_H +#define QDRAWHELPER_ARMV6_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <private/qdrawhelper_p.h> + +QT_BEGIN_NAMESPACE + +#if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6) + +extern "C" void qt_blend_rgb32_on_rgb32_armv6(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + +extern "C" void qt_blend_argb32_on_argb32_armv6(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + +extern "C" void qt_memfill32_armv6(quint32 *dest, quint32 value, int count); + +extern "C" void comp_func_Source_armv6(uint *dest, const uint *src, int length, uint const_alpha); +extern "C" void comp_func_SourceOver_armv6(uint *dest, const uint *src, int length, uint const_alpha); + +#endif // QT_HAVE_ARMV6 + +QT_END_NAMESPACE + +#endif // QDRAWHELPER_ARMV6_P_H diff --git a/src/gui/painting/qdrawhelper_armv6_rvct.inc b/src/gui/painting/qdrawhelper_armv6_rvct.inc new file mode 100644 index 0000000..1aabbf5 --- /dev/null +++ b/src/gui/painting/qdrawhelper_armv6_rvct.inc @@ -0,0 +1,496 @@ +;/**************************************************************************** +;** +;** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +;** Contact: Nokia Corporation (qt-info@nokia.com) +;** +;** This file is part of the QtGui module of the Qt Toolkit. +;** +;** $QT_BEGIN_LICENSE:LGPL$ +;** No Commercial Usage +;** This file contains pre-release code and may not be distributed. +;** You may use this file in accordance with the terms and conditions +;** contained in the either Technology Preview License Agreement or the +;** Beta Release License Agreement. +;** +;** GNU Lesser General Public License Usage +;** Alternatively, this file may be used under the terms of the GNU Lesser +;** General Public License version 2.1 as published by the Free Software +;** Foundation and appearing in the file LICENSE.LGPL included in the +;** packaging of this file. Please review the following information to +;** ensure the GNU Lesser General Public License version 2.1 requirements +;** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +;** +;** In addition, as a special exception, Nokia gives you certain +;** additional rights. These rights are described in the Nokia Qt LGPL +;** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +;** package. +;** +;** GNU General Public License Usage +;** Alternatively, this file may be used under the terms of the GNU +;** General Public License version 3.0 as published by the Free Software +;** Foundation and appearing in the file LICENSE.GPL included in the +;** packaging of this file. Please review the following information to +;** ensure the GNU General Public License version 3.0 requirements will be +;** met: http://www.gnu.org/copyleft/gpl.html. +;** +;** If you are unsure which license is appropriate for your use, please +;** contact the sales department at http://qt.nokia.com/contact. +;** $QT_END_LICENSE$ +;** +;****************************************************************************/ + +; +; W A R N I N G +; ------------- +; +; This file is not part of the Qt API. It exists purely as an +; implementation detail. This header file may change from version to +; version without notice, or even be removed. +; +; We mean it. +; + +;----------------------------------------------------------------------------- +; Globals. +; Earch marcro expects that caller has loaded 0x800080 to r14. +;----------------------------------------------------------------------------- + +ComponentHalf EQU 0x800080 + +;----------------------------------------------------------------------------- +; ARM assembly implementations of accelerated graphics operations. +; +; Conventions: +; +; - r0 = Target buffer pointer +; - r1 = Source buffer pointer +; - r2 = Length of the buffer to blend +; - r3 = Constant alpha for source buffer +; +;----------------------------------------------------------------------------- + +; A macro for transparently defining ARM functions + MACRO +$func Function + AREA Function_$func, CODE + GLOBAL $func + ALIGN 4 + CODE32 +$func + MEND + + +;----------------------------------------------------------------------------- +; Armv6 boosted implementation of BYTE_MUL(...) function found in qdrawhelper_p.h. +; +; @param dst Destination register where to store the result +; @param x Value to multiply +; @param a Multiplicator byte +; @param r14 Component half 0x800080 +; +; @note Trashes x, r8 +;----------------------------------------------------------------------------- + MACRO + ByteMul $dst, $x, $a + + ; static inline uint BYTE_MUL(uint x, uint a) + + ; uint r8 = (x & 0xff00ff) * a + 0x800080 + uxtb16 r8, $x ; r8 = r8 & 0x00FF00FF + mla r8, r8, $a, r14 + + ; x = ((r >> 8) & 0xff00ff) * a + 0x800080 + uxtb16 $x, $x, ror #8 + mla $x, $x, $a, r14 + + + ; r8 = (r8 + ((r8 >> 8) & 0xff00ff) ) >> 8 + ; r8 &= 0xff00ff + uxtab16 r8, r8, r8, ror #8 + uxtb16 r8, r8, ror #8 + + ; x = x + ((x >>8) & 0xff00ff) + uxtab16 $x, $x, $x, ror #8 + + ; x &= 0xff00ff00 + ; x |= r8 + uxtb16 $x, $x, ror #8 + orr $dst, r8, $x, lsl #8 + + MEND + +;----------------------------------------------------------------------------- +; Armv6 boosted implementation of INTERPOLATE_PIXEL_255(...) function found in +; qdrawhelper_p.h. +; +; @param dst Destination register where to store the result +; @param x First value to multiply +; @param a Multiplicator byte for first value +; @param y Second value to multiply +; @param b Multiplicator byte for second value +; @param r14 Component half 0x800080 +; +; +; @note Trashes x, r8, r14 +;----------------------------------------------------------------------------- + MACRO + InterpolatePixel255 $dst, $x, $a, $y, $b + + ; static inline uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) + + ; First calculate the parts where we need 0x800080 + + ; uint r8 = (((x & 0xff00ff) * a) + 0x800080) + uxtb16 r8, $x ; r8 = r8 & 0x00FF00FF + mla r8, r8, $a, r14 + + ; x = ((((x >> 8) & 0xff00ff) * a) + 0x800080) + uxtb16 $x, $x, ror #8 + mla $x, $x, $a, r14 + + ; Now we are trashing r14 to free it for other purposes + + ; uint r14 = (y & 0xff00ff) * b + uxtb16 r14, $y ; r14 = y & 0x00FF00FF + mul r14, r14, $b + + ; r8 = r8 + r14 + add r8, r8, r14 + + ; r8 = (r8 + ((r8 >> 8) & 0xff00ff) ) >> 8 + ; r8 &= 0xff00ff + uxtab16 r8, r8, r8, ror #8 + uxtb16 r8, r8, ror #8 + + ; r14 = ((y >> 8) & 0xff00ff) * b + uxtb16 r14, $y, ror #8 ; r14 = ((y >> 8) & 0xFF00FF) + mul r14, r14, $b + + ; x = x + r14 + add $x, $x, r14 + + ; x = x + ((x >>8) & 0xff00ff) + uxtab16 $x, $x, $x, ror #8 + + ; x &= 0xff00ff00 + ; x |= r8 + uxtb16 $x, $x, ror #8 + orr $dst, r8, $x, lsl #8 + + MEND + +;----------------------------------------------------------------------------- +; +;----------------------------------------------------------------------------- + MACRO +$label Blend4Pixels $BlendPixel + + ; Blend first 4 pixels + + ldmia r1!, {r4-r7} + ldm r0, {r9-r12} + +b4p1_$label $BlendPixel r9, r4, r3 +b4p2_$label $BlendPixel r10, r5, r3 +b4p3_$label $BlendPixel r11, r6, r3 +b4p4_$label $BlendPixel r12, r7, r3 + + stmia r0!, {r9-r12} + + MEND + +;----------------------------------------------------------------------------- +; +;----------------------------------------------------------------------------- + MACRO +$label Blend8Pixels $BlendPixel + +b8p1_$label Blend4Pixels $BlendPixel +b8p2_$label Blend4Pixels $BlendPixel + + MEND + +;----------------------------------------------------------------------------- +; +;----------------------------------------------------------------------------- + MACRO +$label Blend16Pixels $BlendPixel + +b16p1_$label Blend8Pixels $BlendPixel +b16p2_$label Blend8Pixels $BlendPixel + + MEND + +;----------------------------------------------------------------------------- +; +;----------------------------------------------------------------------------- + MACRO +$label Blend32Pixels $BlendPixel + +b32p1_$label Blend16Pixels $BlendPixel +b32p2_$label Blend16Pixels $BlendPixel + + MEND + +;----------------------------------------------------------------------------- +; A macro for source over compositing one row of pixels and saving the results +; to destination buffer. +; +; @param dest Destination buffer (r0) +; @param src Source buffer (r1) +; @param length Length (r2) +; @param const_alpha Constant alpha (r3) +; @param r14 Component Half (0x800080) (r14) +; +; @note Advances r0, r1 +; @note Trashes r2, r4-r12 +;----------------------------------------------------------------------------- + MACRO +$label BlendRow $BlendPixel + + pld [r1] + +bloop_$label + ; Blend 32 pixels per loop iteration + subs r2, r2, #32 + bmi b_remaining_$label + +brp1_$label Blend32Pixels $BlendPixel + + b bloop_$label + +b_remaining_$label + + ; Remaining 31 pixels + + addmi r2, r2, #32 + + ; Blend 16 pixels + tst r2, #16 + beq b_remaining8_$label + +brp2_$label Blend16Pixels $BlendPixel + +b_remaining8_$label + + ; Blend 8 pixels + tst r2, #8 + beq b_remaining4_$label + +brp3_$label Blend8Pixels $BlendPixel + +b_remaining4_$label + + ; Blend 4 pixels + tst r2, #4 + beq b_remaining3_$label + +brp4_$label Blend4Pixels $BlendPixel + +b_remaining3_$label + + ; Remaining 3 pixels + + tst r2, #2 + beq b_last_$label + + ldmia r1!, {r4-r5} + ldm r0, {r9-r10} + +brp5_$label $BlendPixel r9, r4, r3 +brp6_$label $BlendPixel r10, r5, r3 + + stmia r0!, {r9-r10} + +b_last_$label + + tst r2, #1 + beq bexit_$label + + ldr r4, [r1] + ldr r9, [r0] + +bpl_$label $BlendPixel r9, r4, r3 + + str r9, [r0] + +bexit_$label + + MEND + +;----------------------------------------------------------------------------- +; A macro for source over compositing one row of pixels and saving the results +; to destination buffer. Restores all registers. +; +; @param dest Destination buffer (r0) +; @param src Source buffer (r1) +; @param length Length (r2) +; @param const_alpha Constant alpha (r3) +; @param r14 Component Half (0x800080) (r14) +; +; @note Advances r0, r1 +; @note Trashes r2, r4-r12 +;----------------------------------------------------------------------------- + MACRO +$label BlendRowSafe $BlendPixel + + stmfd sp!, {r0-r6} ; Preserves registers only up to r6 + +brs_$label BlendRow $BlendPixel + + ldmfd sp!, {r0-r6} + + MEND + + +;----------------------------------------------------------------------------- +; Pix Copy. +; NOTE! Cache line size of ARM1136JF-S and ARM1136J-S is 32 bytes (8 pixels). +; +; @param dst Destination pixels (r0) +; @param src Source pixels (r1) +; @param len Length (r2) +; +; @note Trashes r3-r10 +;----------------------------------------------------------------------------- + MACRO +$label PixCpy $dst, $src, $len + + pld [$src] + +pcpy_loop_$label + ; Copy 8 pixels per loop iteration + pld [$src, #96] + subs $len, $len, #8 + ldmgeia $src!, {r3-r10} + stmgeia $dst!, {r3-r10} + bgt pcpy_loop_$label + +pcpy_remaining_$label + + ; Copy up to 7 remaining pixels + + ; Copy 4 pixels + tst $len, #4 + ldmneia $src!, {r3-r6} + stmneia $dst!, {r3-r6} + + tst $len, #2 + ldmneia $src!, {r3-r4} + stmneia $dst!, {r3-r4} + + tst $len, #1 + ldrne r3, [$src] + strne r3, [$dst] + + MEND + +;----------------------------------------------------------------------------- +; General Pix Copy. Maximum 8 pixels at time. Restores all registers. +; +; @param dst Destination pixels (r0) +; @param src Source pixels (r1) +; @param len Length (r2) +; +; @note Trashes r3-r10 +;----------------------------------------------------------------------------- + MACRO +$label PixCpySafe $dst, $src, $len + + stmfd sp!, {r0-r6} ; Preserves registers only up to r6 + +pcs_$label PixCpy $dst, $src, $len + + ldmfd sp!, {r0-r6} ; pop + + MEND + + +;----------------------------------------------------------------------------- +; A macro for source over compositing one pixel and saving the result to +; dst register. +; +; @param dst Destination register, must contain destination pixel upon entry +; @param src Source register, must contain source pixel upon entry +; @param const_alpha Constant source alpha +; @param r14 Component half 0x800080 +; +; @note Trashes const_alpha, r8 +;----------------------------------------------------------------------------- + MACRO +$label PixelSourceOver $dst, $src, $const_alpha + + ; Negate src and extract alpha + mvn $const_alpha, $src ; bitwise not + uxtb $const_alpha, $const_alpha, ror #24 ; r3 = ((r3 & 0xFF000000) >> 24); + + ;cmp $const_alpha, #255 ; test for full transparency ( negated ) + ;beq exit_$label + cmp $const_alpha, #0 ; test for full opacity ( negated ) + moveq $dst, $src + beq exit_$label + + ByteMul $dst, $dst, $const_alpha + add $dst, $src, $dst + +exit_$label + MEND + +;----------------------------------------------------------------------------- +; A macro for source over compositing one pixel and saving the result to +; dst register. +; +; @param dst Destination register, must contain destination pixel upon entry +; @param src Source register, must contain source pixel upon entry +; @param const_alpha Constant source alpha +; @param r14 Component half 0x800080 +; +; @note Trashes src, const_alpha, r8 +;----------------------------------------------------------------------------- + MACRO +$label PixelSourceOverConstAlpha $dst, $src, $const_alpha + + ; store alpha because we are going to trash it + stmfd sp!, {$const_alpha} + + ByteMul $src, $src, $const_alpha + + ; Negate src and extract alpha + mvn $const_alpha, $src ; bitwise not + uxtb $const_alpha, $const_alpha, ror #24 ; r3 = ((r3 & 0xFF000000) >> 24); + + ByteMul $dst, $dst, $const_alpha + + add $dst, $src, $dst + + ; recover alpha + ldmfd sp!, {$const_alpha} + + MEND + +;----------------------------------------------------------------------------- +; A macro for source over compositing one pixel and saving the result to +; a register. +; +; @param dst Destination register, must contain destination pixel upon entry +; @param src Source register, must contain source pixel upon entry +; @param const_alpha Constant source alpha +; @param r14 Component half 0x800080 +; +; @note Trashes src, r8 +;----------------------------------------------------------------------------- + MACRO +$label PixelSourceConstAlpha $dst, $src, $const_alpha + + ; store r2 and r14 because we are going to trash them + stmfd sp!, {r2, r14} + + rsb r2, $const_alpha, #255 + InterpolatePixel255 $dst, $src, $const_alpha, $dst, r2 + + ; recover r2 and r14 + ldmfd sp!, {r2, r14} + + MEND + + END ; File end diff --git a/src/gui/painting/qdrawhelper_armv6_rvct.s b/src/gui/painting/qdrawhelper_armv6_rvct.s new file mode 100644 index 0000000..51b67a4 --- /dev/null +++ b/src/gui/painting/qdrawhelper_armv6_rvct.s @@ -0,0 +1,177 @@ +;/**************************************************************************** +;** +;** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +;** Contact: Nokia Corporation (qt-info@nokia.com) +;** +;** This file is part of the QtGui module of the Qt Toolkit. +;** +;** $QT_BEGIN_LICENSE:LGPL$ +;** No Commercial Usage +;** This file contains pre-release code and may not be distributed. +;** You may use this file in accordance with the terms and conditions +;** contained in the either Technology Preview License Agreement or the +;** Beta Release License Agreement. +;** +;** GNU Lesser General Public License Usage +;** Alternatively, this file may be used under the terms of the GNU Lesser +;** General Public License version 2.1 as published by the Free Software +;** Foundation and appearing in the file LICENSE.LGPL included in the +;** packaging of this file. Please review the following information to +;** ensure the GNU Lesser General Public License version 2.1 requirements +;** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +;** +;** In addition, as a special exception, Nokia gives you certain +;** additional rights. These rights are described in the Nokia Qt LGPL +;** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +;** package. +;** +;** GNU General Public License Usage +;** Alternatively, this file may be used under the terms of the GNU +;** General Public License version 3.0 as published by the Free Software +;** Foundation and appearing in the file LICENSE.GPL included in the +;** packaging of this file. Please review the following information to +;** ensure the GNU General Public License version 3.0 requirements will be +;** met: http://www.gnu.org/copyleft/gpl.html. +;** +;** If you are unsure which license is appropriate for your use, please +;** contact the sales department at http://qt.nokia.com/contact. +;** $QT_END_LICENSE$ +;** +;****************************************************************************/ + +; +; W A R N I N G +; ------------- +; +; This file is not part of the Qt API. It exists purely as an +; implementation detail. This header file may change from version to +; version without notice, or even be removed. +; +; We mean it. +; + + ARM + PRESERVE8 + + INCLUDE qdrawhelper_armv6_rvct.inc + +;----------------------------------------------------------------------------- +; qt_memfill32_armv6 +; +; @brief Not yet in use! +; +; @param dest Destination buffer (r0) +; @param value Value (r1) +; @param count Count (r2) +; +;--------------------------------------------------------------------------- +qt_memfill32_armv6 Function + stmfd sp!, {r4-r12, r14} + + mov r3, r1 + mov r4, r1 + mov r5, r1 + mov r6, r1 + mov r7, r1 + mov r8, r1 + mov r9, r1 + +mfill_loop + ; Fill 32 pixels per loop iteration + subs r2, r2, #32 + stmgeia r0!, {r1, r3, r4, r5, r6, r7, r8, r9} + stmgeia r0!, {r1, r3, r4, r5, r6, r7, r8, r9} + stmgeia r0!, {r1, r3, r4, r5, r6, r7, r8, r9} + stmgeia r0!, {r1, r3, r4, r5, r6, r7, r8, r9} + bgt mfill_loop + +mfill_remaining + + ; Fill up to 31 remaining pixels + + ; Fill 16 pixels + tst r2, #16 + stmneia r0!, {r1, r3, r4, r5, r6, r7, r8, r9} + stmneia r0!, {r1, r3, r4, r5, r6, r7, r8, r9} + + ; Fill 8 pixels + tst r2, #8 + stmneia r0!, {r1, r3, r4, r5, r6, r7, r8, r9} + + ; Fill 4 pixels + tst r2, #4 + stmneia r0!, {r1, r3, r4, r5} + + ; Fill 2 pixels + tst r2, #2 + stmneia r0!, {r1, r3} + + ; Fill last one + tst r2, #1 + strne r1, [r0] + + ldmfd sp!, {r4-r12, pc} ; pop and return + +;----------------------------------------------------------------------------- +; comp_func_Source_arm +; +; @brief +; +; @param dest Destination buffer (r0) +; @param src Source buffer (r1) +; @param length Length (r2) +; @param const_alpha Constant alpha (r3) +; +;--------------------------------------------------------------------------- +comp_func_Source_armv6 Function + stmfd sp!, {r4-r12, r14} + + cmp r3, #255 ; if(r3 == 255) + bne src2 ; branch if not + +src1 PixCpy r0, r1, r2 + + ldmfd sp!, {r4-r12, pc} ; pop and return + +src2 + ;ldr r14, =ComponentHalf ; load 0x800080 to r14 + mov r14, #0x800000 + add r14, r14, #0x80 + +src22 BlendRow PixelSourceConstAlpha + + ldmfd sp!, {r4-r12, pc} ; pop and return + +;----------------------------------------------------------------------------- +; comp_func_SourceOver_arm +; +; @brief +; +; @param dest Destination buffer (r0) +; @param src Source buffer (r1) +; @param length Length (r2) +; @param const_alpha Constant alpha (r3) +; +;--------------------------------------------------------------------------- +comp_func_SourceOver_armv6 Function + stmfd sp!, {r4-r12, r14} + + ;ldr r14, =ComponentHalf ; load 0x800080 to r14 + mov r14, #0x800000 + add r14, r14, #0x80 + + cmp r3, #255 ; if(r3 == 255) + bne srcovr2 ; branch if not + +srcovr1 BlendRow PixelSourceOver + + ldmfd sp!, {r4-r12, pc} ; pop and return + +srcovr2 + +srcovr22 BlendRow PixelSourceOverConstAlpha + + ldmfd sp!, {r4-r12, pc} ; pop and return + + + END ; File end diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 71378ec..45a5440 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -87,7 +87,7 @@ QT_BEGIN_NAMESPACE #if defined(Q_CC_RVCT) // RVCT doesn't like static template functions # define Q_STATIC_TEMPLATE_FUNCTION -# define Q_STATIC_INLINE_FUNCTION inline +# define Q_STATIC_INLINE_FUNCTION static __forceinline #else # define Q_STATIC_TEMPLATE_FUNCTION static # define Q_STATIC_INLINE_FUNCTION static inline @@ -110,6 +110,7 @@ struct QSpanData; class QGradient; class QRasterBuffer; class QClipData; +class QRasterPaintEngineState; typedef QT_FT_SpanFunc ProcessSpans; typedef void (*BitmapBlitFunc)(QRasterBuffer *rasterBuffer, @@ -145,6 +146,14 @@ typedef void (*SrcOverScaleFunc)(uchar *destPixels, int dbpl, const QRect &clipRect, int const_alpha); +typedef void (*SrcOverTransformFunc)(uchar *destPixels, int dbpl, + const uchar *src, int spbl, + const QRectF &targetRect, + const QRectF &sourceRect, + const QRect &clipRect, + const QTransform &targetRectTransform, + int const_alpha); + struct DrawHelper { ProcessSpans blendColor; @@ -157,6 +166,7 @@ struct DrawHelper { extern SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats]; extern SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats]; +extern SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFormats]; extern DrawHelper qDrawHelper[QImage::NImageFormats]; @@ -293,26 +303,30 @@ struct QSpanData }; void init(QRasterBuffer *rb, const QRasterPaintEngine *pe); - void setup(const QBrush &brush, int alpha); + void setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode); void setupMatrix(const QTransform &matrix, int bilinear); void initTexture(const QImage *image, int alpha, QTextureData::Type = QTextureData::Plain, const QRect &sourceRect = QRect()); void adjustSpanMethods(); }; -static inline uint BYTE_MUL_RGB16(uint x, uint a) { +Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16(uint x, uint a) { a += 1; uint t = (((x & 0x07e0)*a) >> 8) & 0x07e0; t |= (((x & 0xf81f)*(a>>2)) >> 6) & 0xf81f; return t; } -static inline uint BYTE_MUL_RGB16_32(uint x, uint a) { +Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16_32(uint x, uint a) { uint t = (((x & 0xf81f07e0) >> 5)*a) & 0xf81f07e0; t |= (((x & 0x07e0f81f)*a) >> 5) & 0x07e0f81f; return t; } +#if defined(Q_CC_RVCT) +# pragma push +# pragma arm +#endif Q_STATIC_INLINE_FUNCTION uint BYTE_MUL(uint x, uint a) { uint t = (x & 0xff00ff) * a; t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; @@ -324,8 +338,11 @@ Q_STATIC_INLINE_FUNCTION uint BYTE_MUL(uint x, uint a) { x |= t; return x; } +#if defined(Q_CC_RVCT) +# pragma pop +#endif -static inline uint PREMUL(uint x) { +Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x) { uint a = x >> 24; uint t = (x & 0xff00ff) * a; t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; @@ -390,7 +407,7 @@ public: return qt_colorConvert<quint16, quint32>(data, 0); } - static inline quint32p fromRawData(quint32 v) + Q_STATIC_INLINE_FUNCTION quint32p fromRawData(quint32 v) { quint32p p; p.data = v; @@ -421,7 +438,7 @@ class qrgb565; class qargb8565 { public: - static inline bool hasAlpha() { return true; } + Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; } inline qargb8565() {} inline qargb8565(quint32 v); @@ -438,14 +455,15 @@ public: data[1] &= 0xdf; return *this; } - static inline quint8 alpha(quint8 a) { return (a + 1) >> 3; } - static inline quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } + Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; } + Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } inline qargb8565 byte_mul(quint8 a) const; inline qargb8565 operator+(qargb8565 v) const; inline bool operator==(const qargb8565 &v) const; inline quint32 rawValue() const; + inline quint16 rawValue16() const; private: friend class qrgb565; @@ -456,13 +474,13 @@ private: class qrgb565 { public: - static inline bool hasAlpha() { return false; } + Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; } qrgb565(int v = 0) : data(v) {} inline explicit qrgb565(quint32p v); inline explicit qrgb565(quint32 v); - inline explicit qrgb565(qargb8565 v); + inline explicit qrgb565(const qargb8565 &v); inline operator quint32() const; inline operator quint16() const; @@ -471,8 +489,8 @@ public: inline quint8 alpha() const { return 0xff; } inline qrgb565 truncedAlpha() { return *this; } - static inline quint8 alpha(quint8 a) { return (a + 1) >> 3; } - static inline quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } + Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; } + Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } inline qrgb565 byte_mul(quint8 a) const; @@ -568,6 +586,11 @@ quint32 qargb8565::rawValue() const return (data[2] << 16) | (data[1] << 8) | data[0]; } +quint16 qargb8565::rawValue16() const +{ + return (data[2] << 8) | data[1]; +} + qrgb565::qrgb565(quint32p v) { *this = qrgb565(quint32(v)); @@ -582,7 +605,7 @@ qrgb565::qrgb565(quint32 v) data = (r & 0xf800) | (g & 0x07e0)| (b & 0x001f); } -qrgb565::qrgb565(qargb8565 v) +qrgb565::qrgb565(const qargb8565 &v) { data = (v.data[2] << 8) | v.data[1]; } @@ -647,7 +670,7 @@ class qrgb555; class qargb8555 { public: - static inline bool hasAlpha() { return true; } + Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; } qargb8555() {} inline qargb8555(quint32 v); @@ -659,8 +682,8 @@ public: inline quint8 alpha() const { return data[0]; } inline qargb8555 truncedAlpha() { data[0] &= 0xf8; return *this; } - static inline quint8 alpha(quint8 a) { return (a + 1) >> 3; } - static inline quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } + Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; } + Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } inline qargb8555 operator+(qargb8555 v) const; inline qargb8555 byte_mul(quint8 a) const; @@ -677,7 +700,7 @@ private: class qrgb555 { public: - static inline bool hasAlpha() { return false; } + Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; } inline qrgb555(int v = 0) : data(v) {} @@ -726,8 +749,8 @@ public: inline quint8 alpha() const { return 0xff; } inline qrgb555 truncedAlpha() { return *this; } - static inline quint8 alpha(quint8 a) { return (a + 1) >> 3; } - static inline quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } + Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; } + Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } inline bool operator==(const qrgb555 &v) const { return v.data == data; } inline bool operator!=(const qrgb555 &v) const { return v.data != data; } @@ -875,7 +898,7 @@ class qrgb666; class qargb6666 { public: - static inline bool hasAlpha() { return true; } + Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; } inline qargb6666() {} inline qargb6666(quint32 v) { *this = qargb6666(quint32p(v)); } @@ -887,8 +910,8 @@ public: inline quint8 alpha() const; inline qargb6666 truncedAlpha() { return *this; } - static inline quint8 alpha(quint8 a) { return (a + 1) >> 2; } - static inline quint8 ialpha(quint8 a) { return (255 - a + 1) >> 2; } + Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 2; } + Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return (255 - a + 1) >> 2; } inline qargb6666 byte_mul(quint8 a) const; inline qargb6666 operator+(qargb6666 v) const; @@ -905,7 +928,7 @@ private: class qrgb666 { public: - static inline bool hasAlpha() { return false; } + Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; } inline qrgb666() {} inline qrgb666(quint32 v); @@ -915,8 +938,8 @@ public: inline quint8 alpha() const { return 0xff; } inline qrgb666 truncedAlpha() { return *this; } - static inline quint8 alpha(quint8 a) { return (a + 1) >> 2; } - static inline quint8 ialpha(quint8 a) { return (255 - a + 1) >> 2; } + Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 2; } + Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return (255 - a + 1) >> 2; } inline qrgb666 operator+(qrgb666 v) const; inline qrgb666 byte_mul(quint8 a) const; @@ -1073,7 +1096,7 @@ quint32 qargb6666::rawValue() const class qrgb888 { public: - static inline bool hasAlpha() { return false; } + Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; } inline qrgb888() {} inline qrgb888(quint32 v); @@ -1082,8 +1105,8 @@ public: inline quint8 alpha() const { return 0xff; } inline qrgb888 truncedAlpha() { return *this; } - static inline quint8 alpha(quint8 a) { return a; } - static inline quint8 ialpha(quint8 a) { return 255 - a; } + Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return a; } + Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 255 - a; } inline qrgb888 byte_mul(quint8 a) const; inline qrgb888 operator+(qrgb888 v) const; @@ -1262,7 +1285,7 @@ class qrgb444; class qargb4444 { public: - static inline bool hasAlpha() { return true; } + Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; } inline qargb4444() {} inline qargb4444(quint32 v) { *this = qargb4444(quint32p(v)); } @@ -1276,8 +1299,8 @@ public: inline quint8 alpha() const { return ((data & 0xf000) >> 8) | ((data & 0xf000) >> 12); } inline qargb4444 truncedAlpha() { return *this; } - static inline quint8 alpha(quint8 a) { return (a + 1) >> 4; } - static inline quint8 ialpha(quint8 a) { return 0x10 - alpha(a); } + Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 4; } + Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x10 - alpha(a); } inline qargb4444 byte_mul(quint8 a) const; inline bool operator==(const qargb4444 &v) const { return data == v.data; } @@ -1293,7 +1316,7 @@ private: class qrgb444 { public: - static inline bool hasAlpha() { return false; } + Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; } inline qrgb444() {} inline qrgb444(quint32 v); @@ -1305,8 +1328,8 @@ public: inline qrgb444 operator+(qrgb444 v) const; inline quint8 alpha() const { return 0xff; } inline qrgb444 truncedAlpha() { return *this; } - static inline quint8 alpha(quint8 a) { return (a + 1) >> 4; } - static inline quint8 ialpha(quint8 a) { return 0x10 - alpha(a); } + Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 4; } + Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x10 - alpha(a); } inline qrgb444 byte_mul(quint8 a) const; inline bool operator==(const qrgb444 &v) const { return data == v.data; } @@ -1767,7 +1790,14 @@ do { \ } \ } while (0) +#if defined(Q_CC_RVCT) +# pragma push +# pragma arm +#endif Q_STATIC_INLINE_FUNCTION int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; } +#if defined(Q_CC_RVCT) +# pragma pop +#endif inline ushort qConvertRgb32To16(uint c) { @@ -1810,7 +1840,7 @@ inline int qBlue565(quint16 rgb) { } #if 1 -static inline uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { +Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; t >>= 8; t &= 0xff00ff; @@ -1821,7 +1851,11 @@ static inline uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { return x; } -static inline uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) { +#if defined(Q_CC_RVCT) +# pragma push +# pragma arm +#endif +Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) { uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; t &= 0xff00ff; @@ -1832,9 +1866,12 @@ static inline uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) { x |= t; return x; } +#if defined(Q_CC_RVCT) +# pragma pop +#endif #else // possible implementation for 64 bit -static inline uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { +Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a; t += (((ulong(y)) | ((ulong(y)) << 24)) & 0x00ff00ff00ff00ff) * b; t >>= 8; @@ -1842,7 +1879,7 @@ static inline uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { return (uint(t)) | (uint(t >> 24)); } -static inline uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) { +Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) { ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a; t += (((ulong(y)) | ((ulong(y)) << 24)) & 0x00ff00ff00ff00ff) * b; t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080); @@ -1857,7 +1894,7 @@ Q_STATIC_INLINE_FUNCTION uint BYTE_MUL(uint x, uint a) { return (uint(t)) | (uint(t >> 24)); } -static inline uint PREMUL(uint x) { +Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x) { uint a = x >> 24; ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a; t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080); diff --git a/src/gui/painting/qdrawutil.cpp b/src/gui/painting/qdrawutil.cpp index a9c1f6f..59a5063 100644 --- a/src/gui/painting/qdrawutil.cpp +++ b/src/gui/painting/qdrawutil.cpp @@ -1008,8 +1008,7 @@ void qDrawItem(QPainter *p, Qt::GUIStyle gs, ; #ifndef QT_NO_IMAGE_HEURISTIC_MASK } else { // color pixmap, no mask - QString k; - k.sprintf("$qt-drawitem-%llx", pm.cacheKey()); + QString k = QString::fromLatin1("$qt-drawitem-%1").arg(pm.cacheKey()); if (!QPixmapCache::find(k, pm)) { pm = pm.createHeuristicMask(); pm.setMask((QBitmap&)pm); @@ -1038,4 +1037,328 @@ void qDrawItem(QPainter *p, Qt::GUIStyle gs, #endif +/*! + \class QMargins + \since 4.6 + + Holds the borders used to split a pixmap into nine segments in order to + draw it, similar to \l{http://www.w3.org/TR/css3-background/} + {CSS3 border-images}. + + \sa Qt::TileRule, QTileRules +*/ + +/*! \fn QMargins::QMargins(int margin) + Constructs a QMargins with the top, left, bottom, and + right margins set to \a margin. +*/ + +/*! \fn QMargins::QMargins(int topMargin, int leftMargin, int bottomMargin, int rightMargin) + Constructs a QMargins with the given \a topMargin, \a leftMargin, + \a bottomMargin, and \a rightMargin. + */ + +/*! + \class QTileRules + \since 4.6 + + Holds the rules used to draw a pixmap or image split into nine segments, + similar to \l{http://www.w3.org/TR/css3-background/}{CSS3 border-images}. + + \sa Qt::TileRule, QMargins +*/ + +/*! \fn QTileRules::QTileRules(Qt::TileRule horizontalRule, Qt::TileRule verticalRule) + Constructs a QTileRules with the given \a horizontalRule and + \a verticalRule. + */ + +/*! \fn QTileRules::QTileRules(Qt::TileRule rule) + Constructs a QTileRules with the given \a rule used for both + the horizontal rule and the vertical rule. + */ + +/*! + \fn void qDrawBorderPixmap(QPainter *painter, const QRect &target, const QMargins &margins, const QPixmap &pixmap) + \since 4.6 + \relates QMargins + + Draws the given \a pixmap into the given \a target rectangle, using the + given \a painter. The pixmap will be split into nine segments and drawn + according to the \a margins structure. +*/ + +static inline void qVerticalRepeat(QPainter *painter, + const QRect &target, + const QPixmap &pixmap, + const QRect &source, + void (*drawPixmap)(QPainter*, + const QRect&, + const QPixmap&, + const QRect&)) +{ + const int x = target.x(); + const int width = target.width(); + const int height = source.height(); + const int bottom = target.bottom() - height; + int y = target.y(); + for (; y < bottom; y += height) + (*drawPixmap)(painter, QRect(x, y, width, height), pixmap, source); + const QRect remaining(source.x(), source.y(), source.width(), target.bottom() - y + 1); + (*drawPixmap)(painter, QRect(x, y, width, remaining.height()), pixmap, remaining); +} + +static inline void qHorizontalRepeat(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source, + void (*drawPixmap)(QPainter*, const QRect&, const QPixmap&, const QRect&)) +{ + const int y = target.y(); + const int width = source.width(); + const int height = target.height(); + const int right = target.right() - width; + int x = target.x(); + for (; x < right; x += width) + (*drawPixmap)(painter, QRect(x, y, width, height), pixmap, source); + const QRect remaining(source.x(), source.y(), target.right() - x + 1, source.height()); + (*drawPixmap)(painter, QRect(x, y, remaining.width(), height), pixmap, remaining); +} + +static inline void qVerticalRound(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source, + void (*drawPixmap)(QPainter*, const QRect&, const QPixmap&, const QRect&)) +{ + // qreal based - slow on non-fpu devices + const qreal x = target.x(); + const qreal width = target.width(); + const qreal verticalFactor = static_cast<qreal>(target.height()) / static_cast<qreal>(source.height()); + const qreal verticalIncrement = static_cast<qreal>(target.height()) / static_cast<int>(verticalFactor + 0.5); + const qreal bottom = target.bottom(); + for (qreal y = static_cast<qreal>(target.y()); y < bottom; y += verticalIncrement) + (*drawPixmap)(painter, QRectF(x, y, width, verticalIncrement).toRect(), pixmap, source); + +} + +static inline void qHorizontalRound(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source, + void (*drawPixmap)(QPainter*, const QRect&, const QPixmap&, const QRect&)) +{ + // qreal based - slow on non-fpu devices + const qreal y = target.y(); + const qreal height = target.height(); + const qreal horizontalFactor = static_cast<qreal>(target.width()) / static_cast<qreal>(source.width()); + const qreal horizontalIncrement = static_cast<qreal>(target.width()) / static_cast<int>(horizontalFactor + 0.5); + const qreal right = target.right(); + for (qreal x = target.x(); x < right; x += horizontalIncrement) + (*drawPixmap)(painter, QRectF(x, y, horizontalIncrement, height).toRect(), pixmap, source); +} + +static inline void qDrawPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source) +{ + painter->drawPixmap(target, pixmap, source); +} + +static inline void qDrawVerticallyRepeatedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source) +{ + qVerticalRepeat(painter, target, pixmap, source, qDrawPixmap); +} + +static inline void qDrawHorizontallyRepeatedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source) +{ + qHorizontalRepeat(painter, target, pixmap, source, qDrawPixmap); +} + +static inline void qDrawVerticallyRoundedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source) +{ + qVerticalRound(painter, target, pixmap, source, qDrawPixmap); +} + +static inline void qDrawHorizontallyRoundedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source) +{ + qHorizontalRound(painter, target, pixmap, source, qDrawPixmap); +} + +/*! + \since 4.6 + + Draws the indicated \a sourceRect rectangle from the given \a pixmap into + the given \a targetRect rectangle, using the given \a painter. The pixmap + will be split into nine segments according to the given \a targetMargins + and \a sourceMargins structures. Finally, the pixmap will be drawn + according to the given \a rules. + + This function is used to draw a scaled pixmap, similar to + \l{http://www.w3.org/TR/css3-background/}{CSS3 border-images} + + \sa Qt::TileRule, QTileRules, QMargins +*/ + +void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins, const QPixmap &pixmap, + const QRect &sourceRect, const QMargins &sourceMargins, const QTileRules &rules) +{ + // source center + const int sourceTop = sourceRect.top(); + const int sourceLeft = sourceRect.left(); + const int sourceCenterTop = sourceTop + sourceMargins.top; + const int sourceCenterLeft = sourceLeft + sourceMargins.left; + const int sourceCenterBottom = sourceRect.bottom() - sourceMargins.bottom + 1; + const int sourceCenterRight = sourceRect.right() - sourceMargins.right + 1; + const int sourceCenterWidth = sourceCenterRight - sourceMargins.left; + const int sourceCenterHeight = sourceCenterBottom - sourceMargins.top; + // target center + const int targetTop = targetRect.top(); + const int targetLeft = targetRect.left(); + const int targetCenterTop = targetTop + targetMargins.top; + const int targetCenterLeft = targetLeft + targetMargins.left; + const int targetCenterBottom = targetRect.bottom() - targetMargins.bottom + 1; + const int targetCenterRight = targetRect.right() - targetMargins.right + 1; + const int targetCenterWidth = targetCenterRight - targetCenterLeft; + const int targetCenterHeight = targetCenterBottom - targetCenterTop; + + // corners + if (targetMargins.top > 0 && targetMargins.left > 0 && sourceMargins.top > 0 && sourceMargins.left > 0) { // top left + const QRect targetTopLeftRect(targetLeft, targetTop, targetMargins.left, targetMargins.top); + const QRect sourceTopLeftRect(sourceLeft, sourceTop, sourceMargins.left, sourceMargins.top); + qDrawPixmap(painter, targetTopLeftRect, pixmap, sourceTopLeftRect); + } + if (targetMargins.top > 0 && targetMargins.right > 0 && sourceMargins.top > 0 && sourceMargins.right > 0) { // top right + const QRect targetTopRightRect(targetCenterRight, targetTop, targetMargins.right, targetMargins.top); + const QRect sourceTopRightRect(sourceCenterRight, sourceTop, sourceMargins.right, sourceMargins.top); + qDrawPixmap(painter, targetTopRightRect, pixmap, sourceTopRightRect); + } + if (targetMargins.bottom > 0 && targetMargins.left > 0 && sourceMargins.bottom > 0 && sourceMargins.left > 0) { // bottom left + const QRect targetBottomLeftRect(targetLeft, targetCenterBottom, targetMargins.left, targetMargins.bottom); + const QRect sourceBottomLeftRect(sourceLeft, sourceCenterBottom, sourceMargins.left, sourceMargins.bottom); + qDrawPixmap(painter, targetBottomLeftRect, pixmap, sourceBottomLeftRect); + } + if (targetMargins.bottom > 0 && targetMargins.right > 0 && sourceMargins.bottom > 0 && sourceMargins.right > 0) { // bottom right + const QRect targetBottomRightRect(targetCenterRight, targetCenterBottom, targetMargins.right, targetMargins.bottom); + const QRect sourceBottomRightRect(sourceCenterRight, sourceCenterBottom, sourceMargins.right, sourceMargins.bottom); + qDrawPixmap(painter, targetBottomRightRect, pixmap, sourceBottomRightRect); + } + + // horizontal edges + switch (rules.horizontal) { + case Qt::Stretch: + if (targetMargins.top > 0 && sourceMargins.top > 0) { // top + const QRect targetTopRect(targetCenterLeft, targetTop, targetCenterWidth, targetMargins.top); + const QRect sourceTopRect(sourceCenterLeft, sourceTop, sourceCenterWidth, sourceMargins.top); + qDrawPixmap(painter, targetTopRect, pixmap, sourceTopRect); + } + if (targetMargins.bottom > 0 && sourceMargins.bottom > 0) { // bottom + const QRect targetBottomRect(targetCenterLeft, targetCenterBottom, targetCenterWidth, targetMargins.bottom); + const QRect sourceBottomRect(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom); + qDrawPixmap(painter, targetBottomRect, pixmap, sourceBottomRect); + } + break; + case Qt::Repeat: + if (targetMargins.top > 0 && sourceMargins.top > 0) { // top + const QRect targetTopRect(targetCenterLeft, targetTop, targetCenterWidth, targetMargins.top); + const QRect sourceTopRect(sourceCenterLeft, sourceTop, sourceCenterWidth, sourceMargins.top); + qDrawHorizontallyRepeatedPixmap(painter, targetTopRect, pixmap, sourceTopRect); + } + if (targetMargins.bottom > 0 && sourceMargins.bottom > 0) { // bottom + const QRect targetBottomRect(targetCenterLeft, targetCenterBottom, targetCenterWidth, targetMargins.bottom); + const QRect sourceBottomRect(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom); + qDrawHorizontallyRepeatedPixmap(painter, targetBottomRect, pixmap, sourceBottomRect); + } + break; + case Qt::Round: + if (targetMargins.top > 0 && sourceMargins.top > 0) { // top + const QRect targetTopRect(targetCenterLeft, targetTop, targetCenterWidth, targetMargins.top); + const QRect sourceTopRect(sourceCenterLeft, sourceTop, sourceCenterWidth, sourceMargins.top); + qDrawHorizontallyRoundedPixmap(painter, targetTopRect, pixmap, sourceTopRect); + } + if (targetMargins.bottom > 0 && sourceMargins.bottom > 0) { // bottom + const QRect targetBottomRect(targetCenterLeft, targetCenterBottom, targetCenterWidth, targetMargins.bottom); + const QRect sourceBottomRect(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom); + qDrawHorizontallyRoundedPixmap(painter, targetBottomRect, pixmap, sourceBottomRect); + } + break; + } + + // vertical edges + switch (rules.vertical) { + case Qt::Stretch: + if (targetMargins.left > 0 && sourceMargins.left > 0) { // left + const QRect targetLeftRect(targetLeft, targetCenterTop, targetMargins.left, targetCenterHeight); + const QRect sourceLeftRect(sourceLeft, sourceCenterTop, sourceMargins.left, sourceCenterHeight); + qDrawPixmap(painter, targetLeftRect, pixmap, sourceLeftRect); + } + if (targetMargins.right > 0 && sourceMargins.right > 0) { // right + const QRect targetRightRect(targetCenterRight, targetCenterTop, targetMargins.right, targetCenterHeight); + const QRect sourceRightRect(sourceCenterRight, sourceCenterTop, sourceMargins.right, sourceCenterHeight); + qDrawPixmap(painter, targetRightRect, pixmap, sourceRightRect); + } + break; + case Qt::Repeat: + if (targetMargins.left > 0 && sourceMargins.left > 0) { // left + const QRect targetLeftRect(targetLeft, targetCenterTop, targetMargins.left, targetCenterHeight); + const QRect sourceLeftRect(sourceLeft, sourceCenterTop, sourceMargins.left, sourceCenterHeight); + qDrawVerticallyRepeatedPixmap(painter, targetLeftRect, pixmap, sourceLeftRect); + } + if (targetMargins.right > 0 && sourceMargins.right > 0) { // right + const QRect targetRightRect(targetCenterRight, targetCenterTop, targetMargins.right, targetCenterHeight); + const QRect sourceRightRect(sourceCenterRight, sourceCenterTop, sourceMargins.right, sourceCenterHeight); + qDrawVerticallyRepeatedPixmap(painter, targetRightRect, pixmap, sourceRightRect); + } + break; + case Qt::Round: + if (targetMargins.left > 0 && sourceMargins.left > 0) { // left + const QRect targetLeftRect(targetLeft, targetCenterTop, targetMargins.left, targetCenterHeight); + const QRect sourceLeftRect(sourceLeft, sourceCenterTop, sourceMargins.left, sourceCenterHeight); + qDrawVerticallyRoundedPixmap(painter, targetLeftRect, pixmap, sourceLeftRect); + } + if (targetMargins.right > 0 && sourceMargins.right > 0) { // right + const QRect targetRightRect(targetCenterRight, targetCenterTop, targetMargins.right, targetCenterHeight); + const QRect sourceRightRect(sourceCenterRight, sourceCenterTop, sourceMargins.right, sourceCenterHeight); + qDrawVerticallyRoundedPixmap(painter, targetRightRect, pixmap, sourceRightRect); + } + break; + } + + // center + if (targetCenterWidth > 0 && targetCenterHeight > 0 && sourceCenterWidth > 0 && sourceCenterHeight > 0) { + const QRect targetCenterRect(targetCenterLeft, targetCenterTop, targetCenterWidth, targetCenterHeight); + const QRect sourceCenterRect(sourceCenterLeft, sourceCenterTop, sourceCenterWidth, sourceCenterHeight); + switch (rules.horizontal) { + case Qt::Stretch: + switch (rules.vertical) { + case Qt::Stretch: // stretch stretch + qDrawPixmap(painter, targetCenterRect, pixmap, sourceCenterRect); + break; + case Qt::Repeat: // stretch repeat + qVerticalRepeat(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap); + break; + case Qt::Round: // stretch round + qVerticalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap); + break; + } + break; + case Qt::Repeat: + switch (rules.vertical) { + case Qt::Stretch: // repeat stretch + qHorizontalRepeat(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap); + break; + case Qt::Repeat: // repeat repeat + qVerticalRepeat(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawHorizontallyRepeatedPixmap); + break; + case Qt::Round: // repeat round + qVerticalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawHorizontallyRepeatedPixmap); + break; + } + break; + case Qt::Round: + switch (rules.vertical) { + case Qt::Stretch: // round stretch + qHorizontalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap); + break; + case Qt::Repeat: // round repeat + qHorizontalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawVerticallyRepeatedPixmap); + break; + case Qt::Round: // round round + qHorizontalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawVerticallyRoundedPixmap); + break; + } + break; + } + } +} + QT_END_NAMESPACE diff --git a/src/gui/painting/qdrawutil.h b/src/gui/painting/qdrawutil.h index 02b71a9..4135c19 100644 --- a/src/gui/painting/qdrawutil.h +++ b/src/gui/painting/qdrawutil.h @@ -44,6 +44,7 @@ #include <QtCore/qnamespace.h> #include <QtCore/qstring.h> // char*->QString conversion +#include <QtGui/qpixmap.h> QT_BEGIN_HEADER @@ -60,7 +61,6 @@ class QPoint; class QColor; class QBrush; class QRect; -class QPixmap; // // Standard shade drawing @@ -133,6 +133,49 @@ Q_GUI_EXPORT QT3_SUPPORT void qDrawArrow(QPainter *p, Qt::ArrowType type, Qt::GU const QPalette &pal, bool enabled); #endif +struct QMargins +{ + inline QMargins(int margin = 0) + : top(margin), + left(margin), + bottom(margin), + right(margin) {} + inline QMargins(int topMargin, int leftMargin, int bottomMargin, int rightMargin) + : top(topMargin), + left(leftMargin), + bottom(bottomMargin), + right(rightMargin) {} + int top; + int left; + int bottom; + int right; +}; + +struct QTileRules +{ + inline QTileRules(Qt::TileRule horizontalRule, Qt::TileRule verticalRule = Qt::Stretch) + : horizontal(horizontalRule), vertical(verticalRule) {} + inline QTileRules(Qt::TileRule rule = Qt::Stretch) + : horizontal(rule), vertical(rule) {} + Qt::TileRule horizontal; + Qt::TileRule vertical; +}; + +Q_GUI_EXPORT void qDrawBorderPixmap(QPainter *painter, + const QRect &targetRect, + const QMargins &targetMargins, + const QPixmap &pixmap, + const QRect &sourceRect, + const QMargins &sourceMargins, + const QTileRules &rules = QTileRules()); +inline void qDrawBorderPixmap(QPainter *painter, + const QRect &target, + const QMargins &margins, + const QPixmap &pixmap) +{ + qDrawBorderPixmap(painter, target, margins, pixmap, pixmap.rect(), margins); +} + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/painting/qemulationpaintengine.cpp b/src/gui/painting/qemulationpaintengine.cpp index 26bc3c0..ea4595a 100644 --- a/src/gui/painting/qemulationpaintengine.cpp +++ b/src/gui/painting/qemulationpaintengine.cpp @@ -99,9 +99,9 @@ void QEmulationPaintEngine::fill(const QVectorPath &path, const QBrush &brush) } else if (g->coordinateMode() == QGradient::ObjectBoundingMode) { QBrush copy = brush; QTransform mat = copy.transform(); - QRealRect r = path.controlPointRect(); - mat.translate(r.x1, r.y1); - mat.scale(r.x2 - r.x1, r.y2 - r.y1); + QRectF r = path.controlPointRect(); + mat.translate(r.x(), r.y()); + mat.scale(r.width(), r.height()); copy.setTransform(mat); real_engine->fill(path, copy); return; @@ -139,9 +139,9 @@ void QEmulationPaintEngine::stroke(const QVectorPath &path, const QPen &pen) return; } else if (g->coordinateMode() == QGradient::ObjectBoundingMode) { QTransform mat = brush.transform(); - QRealRect r = path.controlPointRect(); - mat.translate(r.x1, r.y1); - mat.scale(r.x2 - r.x1, r.y2 - r.y1); + QRectF r = path.controlPointRect(); + mat.translate(r.x(), r.y()); + mat.scale(r.width(), r.height()); brush.setTransform(mat); copy.setBrush(brush); real_engine->stroke(path, copy); diff --git a/src/gui/painting/qfixed_p.h b/src/gui/painting/qfixed_p.h index 3e5635b..70a92ab 100644 --- a/src/gui/painting/qfixed_p.h +++ b/src/gui/painting/qfixed_p.h @@ -181,8 +181,10 @@ inline bool operator<(int i, const QFixed &f) { return (i<<6) < f.value(); } inline bool operator>(const QFixed &f, int i) { return f.value() > (i<<6); } inline bool operator>(int i, const QFixed &f) { return (i<<6) > f.value(); } +#ifndef QT_NO_DEBUG_STREAM inline QDebug &operator<<(QDebug &dbg, const QFixed &f) { return dbg << f.toReal(); } +#endif struct QFixedPoint { QFixed x; diff --git a/src/gui/painting/qgraphicssystem.cpp b/src/gui/painting/qgraphicssystem.cpp index 38197e0..a7f5efb 100644 --- a/src/gui/painting/qgraphicssystem.cpp +++ b/src/gui/painting/qgraphicssystem.cpp @@ -44,7 +44,7 @@ #ifdef Q_WS_X11 # include <private/qpixmap_x11_p.h> #endif -#ifdef Q_WS_WIN +#if defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) # include <private/qpixmap_raster_p.h> #endif #ifdef Q_WS_MAC @@ -64,7 +64,7 @@ QPixmapData *QGraphicsSystem::createDefaultPixmapData(QPixmapData::PixelType typ #endif #if defined(Q_WS_X11) return new QX11PixmapData(type); -#elif defined(Q_WS_WIN) +#elif defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) return new QRasterPixmapData(type); #elif defined(Q_WS_MAC) return new QMacPixmapData(type); diff --git a/src/gui/painting/qgraphicssystemfactory.cpp b/src/gui/painting/qgraphicssystemfactory.cpp index 2a886ca..979456a 100644 --- a/src/gui/painting/qgraphicssystemfactory.cpp +++ b/src/gui/painting/qgraphicssystemfactory.cpp @@ -64,7 +64,11 @@ QGraphicsSystem *QGraphicsSystemFactory::create(const QString& key) if (system.isEmpty()) { system = QLatin1String("opengl"); } -#elif defined (QT_GRAPHICSSYSTEM_RASTER) && !defined(Q_WS_WIN) +#elif defined (QT_GRAPHICSSYSTEM_OPENVG) + if (system.isEmpty()) { + system = QLatin1String("openvg"); + } +#elif defined (QT_GRAPHICSSYSTEM_RASTER) && !defined(Q_WS_WIN) && !defined(Q_OS_SYMBIAN) if (system.isEmpty()) { system = QLatin1String("raster"); } diff --git a/src/gui/painting/qgraphicssystemfactory_p.h b/src/gui/painting/qgraphicssystemfactory_p.h index 31a05a5..128230d 100644 --- a/src/gui/painting/qgraphicssystemfactory_p.h +++ b/src/gui/painting/qgraphicssystemfactory_p.h @@ -63,7 +63,7 @@ QT_MODULE(Gui) class QGraphicsSystem; -class Q_GUI_EXPORT QGraphicsSystemFactory +class QGraphicsSystemFactory { public: static QStringList keys(); diff --git a/src/gui/painting/qgraphicssystemplugin_p.h b/src/gui/painting/qgraphicssystemplugin_p.h index 10479e4..528dafd 100644 --- a/src/gui/painting/qgraphicssystemplugin_p.h +++ b/src/gui/painting/qgraphicssystemplugin_p.h @@ -64,7 +64,7 @@ QT_MODULE(Gui) class QGraphicsSystem; -struct Q_GUI_EXPORT QGraphicsSystemFactoryInterface : public QFactoryInterface +struct QGraphicsSystemFactoryInterface : public QFactoryInterface { virtual QGraphicsSystem *create(const QString &key) = 0; }; diff --git a/src/gui/painting/qgrayraster.c b/src/gui/painting/qgrayraster.c index be3f18f..83f1cb9 100644 --- a/src/gui/painting/qgrayraster.c +++ b/src/gui/painting/qgrayraster.c @@ -134,7 +134,9 @@ #define ErrRaster_MemoryOverflow -4 - +#if defined(VXWORKS) +# include <vxWorksCommon.h> /* needed for setjmp.h */ +#endif #include <string.h> /* for qt_ft_memcpy() */ #include <setjmp.h> #include <limits.h> @@ -1875,6 +1877,10 @@ if (memory) fprintf(stderr, "gray_raster_new(), memory ignored"); memory = malloc(sizeof(TRaster)); + if (!memory) { + *araster = 0; + return ErrRaster_Memory_Overflow; + } QT_FT_MEM_ZERO(memory, sizeof(TRaster)); *araster = (QT_FT_Raster) memory; diff --git a/src/gui/painting/qmatrix.cpp b/src/gui/painting/qmatrix.cpp index 166e9f1..c8a3499 100644 --- a/src/gui/painting/qmatrix.cpp +++ b/src/gui/painting/qmatrix.cpp @@ -55,11 +55,15 @@ QT_BEGIN_NAMESPACE \class QMatrix \brief The QMatrix class specifies 2D transformations of a coordinate system. + \obsolete - \ingroup multimedia + \ingroup painting A matrix specifies how to translate, scale, shear or rotate the coordinate system, and is typically used when rendering graphics. + QMatrix, in contrast to QTransform, does not allow perspective + transformations. QTransform is the recommended transformation + class in Qt. A QMatrix object can be built using the setMatrix(), scale(), rotate(), translate() and shear() functions. Alternatively, it @@ -172,8 +176,8 @@ QT_BEGIN_NAMESPACE \snippet doc/src/snippets/matrix/matrix.cpp 2 \endtable - \sa QPainter, {The Coordinate System}, {demos/affine}{Affine - Transformations Demo}, {Transformations Example} + \sa QPainter, QTransform, {The Coordinate System}, + {demos/affine}{Affine Transformations Demo}, {Transformations Example} */ @@ -197,6 +201,10 @@ QT_BEGIN_NAMESPACE /***************************************************************************** QMatrix member functions *****************************************************************************/ +/*! + \fn QMatrix::QMatrix(Qt::Initialization) + \internal +*/ /*! Constructs an identity matrix. @@ -208,9 +216,13 @@ QT_BEGIN_NAMESPACE */ QMatrix::QMatrix() + : _m11(1.) + , _m12(0.) + , _m21(0.) + , _m22(1.) + , _dx(0.) + , _dy(0.) { - _m11 = _m22 = 1.0; - _m12 = _m21 = _dx = _dy = 0.0; } /*! @@ -220,12 +232,14 @@ QMatrix::QMatrix() \sa setMatrix() */ -QMatrix::QMatrix(qreal m11, qreal m12, qreal m21, qreal m22, - qreal dx, qreal dy) +QMatrix::QMatrix(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy) + : _m11(m11) + , _m12(m12) + , _m21(m21) + , _m22(m22) + , _dx(dx) + , _dy(dy) { - _m11 = m11; _m12 = m12; - _m21 = m21; _m22 = m22; - _dx = dx; _dy = dy; } @@ -233,8 +247,13 @@ QMatrix::QMatrix(qreal m11, qreal m12, qreal m21, qreal m22, Constructs a matrix that is a copy of the given \a matrix. */ QMatrix::QMatrix(const QMatrix &matrix) + : _m11(matrix._m11) + , _m12(matrix._m12) + , _m21(matrix._m21) + , _m22(matrix._m22) + , _dx(matrix._dx) + , _dy(matrix._dy) { - *this = matrix; } /*! @@ -249,12 +268,14 @@ QMatrix::QMatrix(const QMatrix &matrix) \sa QMatrix() */ -void QMatrix::setMatrix(qreal m11, qreal m12, qreal m21, qreal m22, - qreal dx, qreal dy) +void QMatrix::setMatrix(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy) { - _m11 = m11; _m12 = m12; - _m21 = m21; _m22 = m22; - _dx = dx; _dy = dy; + _m11 = m11; + _m12 = m12; + _m21 = m21; + _m22 = m22; + _dx = dx; + _dy = dy; } @@ -968,18 +989,17 @@ QMatrix QMatrix::inverted(bool *invertible) const if (determinant == 0.0) { if (invertible) *invertible = false; // singular matrix - QMatrix defaultMatrix; - return defaultMatrix; + return QMatrix(true); } else { // invertible matrix if (invertible) *invertible = true; qreal dinv = 1.0/determinant; - QMatrix imatrix((_m22*dinv), (-_m12*dinv), - (-_m21*dinv), (_m11*dinv), - ((_m21*_dy - _m22*_dx)*dinv), - ((_m12*_dx - _m11*_dy)*dinv)); - return imatrix; + return QMatrix((_m22*dinv), (-_m12*dinv), + (-_m21*dinv), (_m11*dinv), + ((_m21*_dy - _m22*_dx)*dinv), + ((_m12*_dx - _m11*_dy)*dinv), + true); } } @@ -1054,9 +1074,14 @@ QMatrix &QMatrix::operator *=(const QMatrix &m) QMatrix QMatrix::operator *(const QMatrix &m) const { - QMatrix result = *this; - result *= m; - return result; + qreal tm11 = _m11*m._m11 + _m12*m._m21; + qreal tm12 = _m11*m._m12 + _m12*m._m22; + qreal tm21 = _m21*m._m11 + _m22*m._m21; + qreal tm22 = _m21*m._m12 + _m22*m._m22; + + qreal tdx = _dx*m._m11 + _dy*m._m21 + m._dx; + qreal tdy = _dx*m._m12 + _dy*m._m22 + m._dy; + return QMatrix(tm11, tm12, tm21, tm22, tdx, tdy, true); } /*! @@ -1161,7 +1186,7 @@ QDebug operator<<(QDebug dbg, const QMatrix &m) << " 22=" << m.m22() << " dx=" << m.dx() << " dy=" << m.dy() - << ")"; + << ')'; return dbg.space(); } #endif @@ -1177,4 +1202,15 @@ QDebug operator<<(QDebug dbg, const QMatrix &m) Use the mapRect() function instead. */ + +/*! + \fn bool qFuzzyCompare(const QMatrix& m1, const QMatrix& m2) + + \relates QMatrix + \since 4.6 + + Returns true if \a m1 and \a m2 are equal, allowing for a small + fuzziness factor for floating-point comparisons; false otherwise. +*/ + QT_END_NAMESPACE diff --git a/src/gui/painting/qmatrix.h b/src/gui/painting/qmatrix.h index d8f809c..cd003f6 100644 --- a/src/gui/painting/qmatrix.h +++ b/src/gui/painting/qmatrix.h @@ -61,6 +61,7 @@ class QVariant; class Q_GUI_EXPORT QMatrix // 2D transform matrix { public: + inline explicit QMatrix(Qt::Initialization) {} QMatrix(); QMatrix(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy); @@ -99,7 +100,7 @@ public: QMatrix &shear(qreal sh, qreal sv); QMatrix &rotate(qreal a); - bool isInvertible() const { return !qFuzzyCompare(_m11*_m22 - _m12*_m21 + 1, 1); } + bool isInvertible() const { return !qFuzzyIsNull(_m11*_m22 - _m12*_m21); } qreal det() const { return _m11*_m22 - _m12*_m21; } QMatrix inverted(bool *invertible = 0) const; @@ -121,6 +122,20 @@ public: #endif private: + inline QMatrix(bool) + : _m11(1.) + , _m12(0.) + , _m21(0.) + , _m22(1.) + , _dx(0.) + , _dy(0.) {} + inline QMatrix(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy, bool) + : _m11(m11) + , _m12(m12) + , _m21(m21) + , _m22(m22) + , _dx(dx) + , _dy(dy) {} friend class QTransform; qreal _m11, _m12; qreal _m21, _m22; @@ -147,16 +162,29 @@ Q_GUI_EXPORT QPainterPath operator *(const QPainterPath &p, const QMatrix &m); inline bool QMatrix::isIdentity() const { - return qFuzzyCompare(_m11, 1) && qFuzzyCompare(_m22, 1) && qFuzzyCompare(_m12 + 1, 1) - && qFuzzyCompare(_m21 + 1, 1) && qFuzzyCompare(_dx + 1, 1) && qFuzzyCompare(_dy + 1, 1); + return qFuzzyIsNull(_m11 - 1) && qFuzzyIsNull(_m22 - 1) && qFuzzyIsNull(_m12) + && qFuzzyIsNull(_m21) && qFuzzyIsNull(_dx) && qFuzzyIsNull(_dy); } +inline bool qFuzzyCompare(const QMatrix& m1, const QMatrix& m2) +{ + return qFuzzyCompare(m1.m11(), m2.m11()) + && qFuzzyCompare(m1.m12(), m2.m12()) + && qFuzzyCompare(m1.m21(), m2.m21()) + && qFuzzyCompare(m1.m22(), m2.m22()) + && qFuzzyCompare(m1.dx(), m2.dx()) + && qFuzzyCompare(m1.dy(), m2.dy()); +} + + /***************************************************************************** QMatrix stream functions *****************************************************************************/ +#ifndef QT_NO_DATASTREAM Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QMatrix &); Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QMatrix &); +#endif #ifndef QT_NO_DEBUG_STREAM Q_GUI_EXPORT QDebug operator<<(QDebug, const QMatrix &); diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp index e90ba55..216b8c6 100644 --- a/src/gui/painting/qoutlinemapper.cpp +++ b/src/gui/painting/qoutlinemapper.cpp @@ -198,32 +198,8 @@ void QOutlineMapper::endOutline() m_m22 * e.y() + m_m12 * e.x() + m_dy); } } else { - // ## TODO: this case needs to be plain code polygonal paths - QPainterPath path; - if (m_element_types.isEmpty()) { - if (!m_elements.isEmpty()) - path.moveTo(m_elements.at(0)); - for (int i=1; i<m_elements.size(); ++i) - path.lineTo(m_elements.at(i)); - } else { - for (int i=0; i<m_elements.size(); ++i) { - switch (m_element_types.at(i)) { - case QPainterPath::MoveToElement: - path.moveTo(m_elements.at(i)); - break; - case QPainterPath::LineToElement: - path.lineTo(m_elements.at(i)); - break; - case QPainterPath::CurveToElement: - path.cubicTo(m_elements.at(i), m_elements.at(i+1), m_elements.at(i+2)); - i += 2; - break; - default: - Q_ASSERT(false); - break; - } - } - } + const QVectorPath vp((qreal *)m_elements.data(), m_elements.size(), m_element_types.data()); + QPainterPath path = vp.convertToPainterPath(); path = QTransform(m_m11, m_m12, m_m13, m_m21, m_m22, m_m23, m_dx, m_dy, m_m33).map(path); if (!(m_outline.flags & QT_FT_OUTLINE_EVEN_ODD_FILL)) path.setFillRule(Qt::WindingFill); diff --git a/src/gui/painting/qpaintdevice.cpp b/src/gui/painting/qpaintdevice.cpp new file mode 100644 index 0000000..6a2a4c4 --- /dev/null +++ b/src/gui/painting/qpaintdevice.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qpaintdevice.h" + +QT_BEGIN_NAMESPACE + +extern void qt_painter_removePaintDevice(QPaintDevice *); //qpainter.cpp + +QPaintDevice::QPaintDevice() +{ + painters = 0; +} + +QPaintDevice::~QPaintDevice() +{ + if (paintingActive()) + qWarning("QPaintDevice: Cannot destroy paint device that is being " + "painted"); + qt_painter_removePaintDevice(this); +} + + +int QPaintDevice::metric(PaintDeviceMetric) const +{ + qWarning("QPaintDevice::metrics: Device has no metric information"); + return 0; +} + +QT_END_NAMESPACE diff --git a/src/gui/painting/qpaintdevice.qdoc b/src/gui/painting/qpaintdevice.qdoc new file mode 100644 index 0000000..2d6f273 --- /dev/null +++ b/src/gui/painting/qpaintdevice.qdoc @@ -0,0 +1,289 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \class QPaintDevice + \brief The QPaintDevice class is the base class of objects that + can be painted. + + \ingroup painting + + A paint device is an abstraction of a two-dimensional space that + can be drawn using a QPainter. Its default coordinate system has + its origin located at the top-left position. X increases to the + right and Y increases downwards. The unit is one pixel. + + The drawing capabilities of QPaintDevice are currently implemented + by the QWidget, QImage, QPixmap, QGLPixelBuffer, QPicture, and + QPrinter subclasses. + + To implement support for a new backend, you must derive from + QPaintDevice and reimplement the virtual paintEngine() function to + tell QPainter which paint engine should be used to draw on this + particular device. Note that you also must create a corresponding + paint engine to be able to draw on the device, i.e derive from + QPaintEngine and reimplement its virtual functions. + + \warning Qt requires that a QApplication object exists before + any paint devices can be created. Paint devices access window + system resources, and these resources are not initialized before + an application object is created. + + The QPaintDevice class provides several functions returning the + various device metrics: The depth() function returns its bit depth + (number of bit planes). The height() function returns its height + in default coordinate system units (e.g. pixels for QPixmap and + QWidget) while heightMM() returns the height of the device in + millimeters. Similiarily, the width() and widthMM() functions + return the width of the device in default coordinate system units + and in millimeters, respectively. Alternatively, the protected + metric() function can be used to retrieve the metric information + by specifying the desired PaintDeviceMetric as argument. + + The logicalDpiX() and logicalDpiY() functions return the + horizontal and vertical resolution of the device in dots per + inch. The physicalDpiX() and physicalDpiY() functions also return + the resolution of the device in dots per inch, but note that if + the logical and vertical resolution differ, the corresponding + QPaintEngine must handle the mapping. Finally, the numColors() + function returns the number of different colors available for the + paint device. + + \sa QPaintEngine, QPainter, {The Coordinate System}, {The Paint + System} +*/ + +/*! + \enum QPaintDevice::PaintDeviceMetric + + Describes the various metrics of a paint device. + + \value PdmWidth The width of the paint device in default + coordinate system units (e.g. pixels for QPixmap and QWidget). See + also width(). + + \value PdmHeight The height of the paint device in default + coordinate system units (e.g. pixels for QPixmap and QWidget). See + also height(). + + \value PdmWidthMM The width of the paint device in millimeters. See + also widthMM(). + + \value PdmHeightMM The height of the paint device in millimeters. See + also heightMM(). + + \value PdmNumColors The number of different colors available for + the paint device. See also numColors(). + + \value PdmDepth The bit depth (number of bit planes) of the paint + device. See also depth(). + + \value PdmDpiX The horizontal resolution of the device in dots per + inch. See also logicalDpiX(). + + \value PdmDpiY The vertical resolution of the device in dots per inch. See + also logicalDpiY(). + + \value PdmPhysicalDpiX The horizontal resolution of the device in + dots per inch. See also physicalDpiX(). + + \value PdmPhysicalDpiY The vertical resolution of the device in + dots per inch. See also physicalDpiY(). + + \sa metric() +*/ + +/*! + \fn QPaintDevice::QPaintDevice() + + Constructs a paint device. This constructor can be invoked only from + subclasses of QPaintDevice. +*/ + +/*! + \fn QPaintDevice::~QPaintDevice() + + Destroys the paint device and frees window system resources. +*/ + +/*! + \fn int QPaintDevice::devType() const + + \internal + + Returns the device type identifier, which is QInternal::Widget + if the device is a QWidget, QInternal::Pixmap if it's a + QPixmap, QInternal::Printer if it's a QPrinter, + QInternal::Picture if it's a QPicture, or + QInternal::UnknownDevice in other cases. +*/ + +/*! + \fn bool QPaintDevice::paintingActive() const + + Returns true if the device is currently being painted on, i.e. someone has + called QPainter::begin() but not yet called QPainter::end() for + this device; otherwise returns false. + + \sa QPainter::isActive() +*/ + +/*! + \fn QPaintEngine *QPaintDevice::paintEngine() const + + Returns a pointer to the paint engine used for drawing on the + device. +*/ + +/*! + \fn int QPaintDevice::metric(PaintDeviceMetric metric) const + + Returns the metric information for the given paint device \a metric. + + \sa PaintDeviceMetric +*/ + +/*! + \fn int QPaintDevice::width() const + + Returns the width of the paint device in default coordinate system + units (e.g. pixels for QPixmap and QWidget). + + \sa widthMM() +*/ + +/*! + \fn int QPaintDevice::height() const + + Returns the height of the paint device in default coordinate + system units (e.g. pixels for QPixmap and QWidget). + + \sa heightMM() +*/ + +/*! + \fn int QPaintDevice::widthMM() const + + Returns the width of the paint device in millimeters. Due to platform + limitations it may not be possible to use this function to determine + the actual physical size of a widget on the screen. + + \sa width() +*/ + +/*! + \fn int QPaintDevice::heightMM() const + + Returns the height of the paint device in millimeters. Due to platform + limitations it may not be possible to use this function to determine + the actual physical size of a widget on the screen. + + \sa height() +*/ + +/*! + \fn int QPaintDevice::numColors() const + + Returns the number of different colors available for the paint + device. Since this value is an int, it will not be sufficient to represent + the number of colors on 32 bit displays, in this case INT_MAX is + returned instead. +*/ + +/*! + \fn int QPaintDevice::depth() const + + Returns the bit depth (number of bit planes) of the paint device. +*/ + +/*! + \fn int QPaintDevice::logicalDpiX() const + + Returns the horizontal resolution of the device in dots per inch, + which is used when computing font sizes. For X11, this is usually + the same as could be computed from widthMM(). + + Note that if the logicalDpiX() doesn't equal the physicalDpiX(), + the corresponding QPaintEngine must handle the resolution mapping. + + \sa logicalDpiY(), physicalDpiX() +*/ + +/*! + \fn int QPaintDevice::logicalDpiY() const + + Returns the vertical resolution of the device in dots per inch, + which is used when computing font sizes. For X11, this is usually + the same as could be computed from heightMM(). + + Note that if the logicalDpiY() doesn't equal the physicalDpiY(), + the corresponding QPaintEngine must handle the resolution mapping. + + \sa logicalDpiX(), physicalDpiY() +*/ + +/*! + \fn int QPaintDevice::physicalDpiX() const + + Returns the horizontal resolution of the device in dots per inch. + For example, when printing, this resolution refers to the physical + printer's resolution. The logical DPI on the other hand, refers to + the resolution used by the actual paint engine. + + Note that if the physicalDpiX() doesn't equal the logicalDpiX(), + the corresponding QPaintEngine must handle the resolution mapping. + + \sa physicalDpiY(), logicalDpiX() +*/ + +/*! + \fn int QPaintDevice::physicalDpiY() const + + Returns the horizontal resolution of the device in dots per inch. + For example, when printing, this resolution refers to the physical + printer's resolution. The logical DPI on the other hand, refers to + the resolution used by the actual paint engine. + + Note that if the physicalDpiY() doesn't equal the logicalDpiY(), + the corresponding QPaintEngine must handle the resolution mapping. + + \sa physicalDpiX(), logicalDpiY() +*/ diff --git a/src/gui/painting/qpaintdevice_mac.cpp b/src/gui/painting/qpaintdevice_mac.cpp index da68091..24b6b61 100644 --- a/src/gui/painting/qpaintdevice_mac.cpp +++ b/src/gui/painting/qpaintdevice_mac.cpp @@ -57,34 +57,6 @@ QT_BEGIN_NAMESPACE Internal variables and functions *****************************************************************************/ - -/***************************************************************************** - External functions - *****************************************************************************/ - -extern void qt_painter_removePaintDevice(QPaintDevice *); //qpainter.cpp - -/***************************************************************************** - QPaintDevice member functions - *****************************************************************************/ -QPaintDevice::QPaintDevice() -{ - painters = 0; -} - -QPaintDevice::~QPaintDevice() -{ - if(paintingActive()) - qWarning("QPaintDevice: Cannot destroy paint device that is being " - "painted, be sure to QPainter::end() painters"); - qt_painter_removePaintDevice(this); -} - -int QPaintDevice::metric(PaintDeviceMetric) const -{ - return 0; -} - /*! \internal */ float qt_mac_defaultDpi_x() { @@ -142,21 +114,16 @@ Q_GUI_EXPORT CGContextRef qt_mac_cg_context(const QPaintDevice *pdev) if (pdev->devType() == QInternal::Pixmap) { const QPixmap *pm = static_cast<const QPixmap*>(pdev); CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pdev); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) uint flags = kCGImageAlphaPremultipliedFirst; #ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - flags |= kCGBitmapByteOrder32Host; -#endif -#else - CGImageAlphaInfo flags = kCGImageAlphaPremultipliedFirst; + flags |= kCGBitmapByteOrder32Host; #endif CGContextRef ret = 0; // It would make sense to put this into a mac #ifdef'ed // virtual function in the QPixmapData at some point if (pm->data->classId() == QPixmapData::MacClass) { - const QMacPixmapData *pmData = static_cast<const QMacPixmapData*>(pm->data); + const QMacPixmapData *pmData = static_cast<const QMacPixmapData*>(pm->data.data()); ret = CGBitmapContextCreate(pmData->pixels, pmData->w, pmData->h, 8, pmData->bytesPerRow, colorspace, flags); diff --git a/src/gui/painting/qpaintdevice_qws.cpp b/src/gui/painting/qpaintdevice_qws.cpp index f302304..8438f46 100644 --- a/src/gui/painting/qpaintdevice_qws.cpp +++ b/src/gui/painting/qpaintdevice_qws.cpp @@ -48,39 +48,6 @@ QT_BEGIN_NAMESPACE -QPaintDevice::QPaintDevice() -{ - painters = 0; -} - -extern void qt_painter_removePaintDevice(QPaintDevice *); //qpainter.cpp - - -QPaintDevice::~QPaintDevice() -{ - if (paintingActive()) - qWarning("QPaintDevice: Cannot destroy paint device that is being " - "painted"); - qt_painter_removePaintDevice(this); -} - - -int QPaintDevice::metric(PaintDeviceMetric m) const -{ - qWarning("QPaintDevice::metrics: Device has no metric information"); - if (m == PdmDpiX) { - return 72; - } else if (m == PdmDpiY) { - return 72; - } else if (m == PdmNumColors) { - // FIXME: does this need to be a real value? - return 256; - } else { - qDebug("Unrecognised metric %d!",m); - return 0; - } -} - QWSDisplay *QPaintDevice::qwsDisplay() { return qt_fbdpy; diff --git a/src/gui/painting/qpaintdevice_win.cpp b/src/gui/painting/qpaintdevice_win.cpp index 8779a96..453b561 100644 --- a/src/gui/painting/qpaintdevice_win.cpp +++ b/src/gui/painting/qpaintdevice_win.cpp @@ -50,27 +50,6 @@ QT_BEGIN_NAMESPACE -QPaintDevice::QPaintDevice() -{ - painters = 0; -} - -extern void qt_painter_removePaintDevice(QPaintDevice *); //qpainter.cpp - -QPaintDevice::~QPaintDevice() -{ - if (paintingActive()) - qWarning("QPaintDevice: Cannot destroy paint device that is being " - "painted. Be sure to QPainter::end() painters!"); - qt_painter_removePaintDevice(this); -} - -int QPaintDevice::metric(PaintDeviceMetric) const -{ - qWarning("QPaintDevice::metrics: Device has no metric information"); - return 0; -} - HDC QPaintDevice::getDC() const { return 0; diff --git a/src/gui/painting/qpaintdevice_x11.cpp b/src/gui/painting/qpaintdevice_x11.cpp index ea8463b..4b6bcb5 100644 --- a/src/gui/painting/qpaintdevice_x11.cpp +++ b/src/gui/painting/qpaintdevice_x11.cpp @@ -49,21 +49,6 @@ QT_BEGIN_NAMESPACE -QPaintDevice::QPaintDevice() -{ - painters = 0; -} - -extern void qt_painter_removePaintDevice(QPaintDevice *); //qpainter.cpp - -QPaintDevice::~QPaintDevice() -{ - if (paintingActive()) - qWarning("QPaintDevice: Cannot destroy paint device that is being " - "painted"); - qt_painter_removePaintDevice(this); -} - /*! \internal Returns the X11 Drawable of the paint device. 0 is returned if it @@ -96,12 +81,6 @@ const Q_GUI_EXPORT QX11Info *qt_x11Info(const QPaintDevice *pd) return 0; } -int QPaintDevice::metric(PaintDeviceMetric) const -{ - qWarning("QPaintDevice::metrics: Device has no metric information"); - return 0; -} - #ifdef QT3_SUPPORT diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp index 993757b..525959b 100644 --- a/src/gui/painting/qpaintengine.cpp +++ b/src/gui/painting/qpaintengine.cpp @@ -49,6 +49,7 @@ #include <private/qtextengine_p.h> #include <qvarlengtharray.h> #include <private/qfontengine_p.h> +#include <private/qpaintengineex_p.h> QT_BEGIN_NAMESPACE @@ -144,7 +145,7 @@ QFont QTextItem::font() const /*! \class QPaintEngine - \ingroup multimedia + \ingroup painting \brief The QPaintEngine class provides an abstract definition of how QPainter draws to a given device on a given platform. @@ -302,6 +303,9 @@ void QPaintEngine::syncState() { Q_ASSERT(state); updateState(*state); + + if (isExtended()) + static_cast<QPaintEngineEx *>(this)->sync(); } static QPaintEngine *qt_polygon_recursion = 0; @@ -713,7 +717,6 @@ QPaintEngine::QPaintEngine(QPaintEnginePrivate &dptr, PaintEngineFeatures caps) */ QPaintEngine::~QPaintEngine() { - delete d_ptr; } /*! @@ -1004,8 +1007,7 @@ void QPaintEnginePrivate::drawBoxTextItem(const QPointF &p, const QTextItemInt & const int size = qRound(ti.fontEngine->ascent()); QVarLengthArray<QFixedPoint> positions; QVarLengthArray<glyph_t> glyphs; - QTransform matrix; - matrix.translate(p.x(), p.y() - size); + QTransform matrix = QTransform::fromTranslate(p.x(), p.y() - size); ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); if (glyphs.size() == 0) return; diff --git a/src/gui/painting/qpaintengine.h b/src/gui/painting/qpaintengine.h index 96074e7..5cd17fe 100644 --- a/src/gui/painting/qpaintengine.h +++ b/src/gui/painting/qpaintengine.h @@ -44,6 +44,7 @@ #include <QtCore/qnamespace.h> #include <QtCore/qobjectdefs.h> +#include <QtCore/qscopedpointer.h> #include <QtGui/qpainter.h> QT_BEGIN_HEADER @@ -210,6 +211,7 @@ public: Direct3D, Pdf, OpenVG, + OpenGL2, User = 50, // first user type id MaxUser = 100 // last user type id @@ -239,7 +241,7 @@ protected: uint selfDestruct : 1; uint extended : 1; - QPaintEnginePrivate *d_ptr; + QScopedPointer<QPaintEnginePrivate> d_ptr; private: void setAutoDestruct(bool autoDestr) { selfDestruct = autoDestr; } diff --git a/src/gui/painting/qpaintengine_d3d.cpp b/src/gui/painting/qpaintengine_d3d.cpp deleted file mode 100644 index 6fd94cf..0000000 --- a/src/gui/painting/qpaintengine_d3d.cpp +++ /dev/null @@ -1,4576 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <qdebug.h> -#include "qpaintengine_d3d_p.h" - -#include "private/qdrawhelper_p.h" -#include "private/qfont_p.h" -#include "private/qfontengine_p.h" -#include "private/qpaintengine_p.h" -#include "private/qtessellator_p.h" -#include <private/qbezier_p.h> -#include <private/qpainter_p.h> -#include <private/qpixmap_raster_p.h> -#include <private/qpolygonclipper_p.h> -#include <qbuffer.h> -#include <qcache.h> -#include <qdir.h> -#include <qfileinfo.h> -#include <qlibrary.h> -#include <qlibraryinfo.h> -#include <qmath.h> -#include <qpaintdevice.h> -#include <qpixmapcache.h> - -#include <qwidget.h> -#include <d3d9.h> -#include <d3dx9.h> - -#include <mmintrin.h> -#include <xmmintrin.h> - -QT_BEGIN_NAMESPACE - -#ifndef M_PI - #define M_PI 3.14159265358979323846 -#endif - -#define QD3D_MASK_MARGIN 1 -#define QD3D_BATCH_SIZE 256 - -// for the ClearType detection stuff.. -#ifndef SPI_GETFONTSMOOTHINGTYPE -#define SPI_GETFONTSMOOTHINGTYPE 0x200A -#endif - -#ifndef FE_FONTSMOOTHINGCLEARTYPE -#define FE_FONTSMOOTHINGCLEARTYPE 0x0002 -#endif - -//#include <performance.h> -#define PM_INIT -#define PM_MEASURE(A) -#define PM_DISPLAY - -//debugging -//#define QT_DEBUG_VERTEXBUFFER_ACCESS -//#define QT_DEBUG_D3D -//#define QT_DEBUG_D3D_CALLS - -#define QD3D_SET_MARK(output) \ - D3DPERF_SetMarker(0, QString(output).utf16()); - -#define QT_VERTEX_RESET_LIMIT 24576 -#define QT_VERTEX_BUF_SIZE 32768 -#define QD3DFVF_CSVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX2 | D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEXCOORDSIZE4(1)) - -// this is a different usage of the effect framework than intended, -// but it's convenient for us to use (See effect file) -#define PASS_STENCIL_ODDEVEN 0 -#define PASS_STENCIL_WINDING 1 -#define PASS_STENCIL_DRAW 2 -#define PASS_STENCIL_DRAW_DIRECT 3 -#define PASS_STENCIL_CLIP 4 -#define PASS_STENCIL_NOSTENCILCHECK 5 -#define PASS_STENCIL_NOSTENCILCHECK_DIRECT 6 -#define PASS_TEXT 7 -#define PASS_CLEARTYPE_TEXT 8 -#define PASS_ALIASED_LINES 9 -#define PASS_ALIASED_LINES_DIRECT 10 - -#define PASS_AA_CREATEMASK 0 -#define PASS_AA_DRAW 1 -#define PASS_AA_DRAW_DIRECT 2 - -#define D3D_STAGE_COUNT 2 -#define D3D_RENDER_STATES 210 -#define D3D_TEXTURE_STATES 33 -#define D3D_SAMPLE_STATES 14 - - -typedef HRESULT (APIENTRY *PFND3DXCREATEBUFFER)(DWORD, LPD3DXBUFFER *); -typedef HRESULT (APIENTRY *PFND3DXCREATEEFFECT)(LPDIRECT3DDEVICE9, LPCVOID, UINT, CONST D3DXMACRO *, - LPD3DXINCLUDE, DWORD, LPD3DXEFFECTPOOL, - LPD3DXEFFECT *, LPD3DXBUFFER *); -typedef D3DXMATRIX *(APIENTRY *PFND3DXMATRIXORTHOOFFCENTERLH)(D3DMATRIX *, FLOAT, FLOAT, - FLOAT, FLOAT, FLOAT, FLOAT); -typedef IDirect3D9 *(APIENTRY *PFNDIRECT3DCREATE9)(uint); - -static PFNDIRECT3DCREATE9 pDirect3DCreate9 = 0; -static PFND3DXCREATEBUFFER pD3DXCreateBuffer = 0; -static PFND3DXCREATEEFFECT pD3DXCreateEffect = 0; -static PFND3DXMATRIXORTHOOFFCENTERLH pD3DXMatrixOrthoOffCenterLH = 0; - - -class QD3DSurfaceManager : public QObject { - Q_OBJECT - -public: - enum QD3DSurfaceManagerStatus { - NoStatus = 0, - NeedsResetting = 0x01, - MaxSizeChanged = 0x02 - }; - - QD3DSurfaceManager(); - ~QD3DSurfaceManager(); - - void init(LPDIRECT3D9 object); - - void setPaintDevice(QPaintDevice *pd); - - int status() const; - void reset(); - - LPDIRECT3DSURFACE9 renderTarget(); - - LPDIRECT3DSURFACE9 surface(QPaintDevice *pd); - LPDIRECT3DSWAPCHAIN9 swapChain(QPaintDevice *pd); - void releasePaintDevice(QPaintDevice *pd); - - LPDIRECT3DDEVICE9 device(); - void cleanup(); - - QSize maxSize() const; - -private: - struct D3DSwapChain { - QSize size; - LPDIRECT3DSWAPCHAIN9 swapchain; - LPDIRECT3DSURFACE9 surface; - }; - - void updateMaxSize(); - void initPresentParameters(D3DPRESENT_PARAMETERS *params); - D3DSwapChain *createSwapChain(QWidget *w); - - QSize m_max_size; - int m_status; - QMap<QPaintDevice *, D3DSwapChain *> m_swapchains; - - LPDIRECT3DDEVICE9 m_device; - QPaintDevice *m_pd; - HWND m_dummy; - D3DSwapChain *m_current; - -private Q_SLOTS: - void cleanupPaintDevice(QObject *); -}; - -struct vertex { - D3DVECTOR pos; - DWORD color; - FLOAT s0, t0, r0, q0; - FLOAT s1, t1, r1, q1; -}; - -struct QD3DMaskPosition { - int x, y, channel; -}; - - -struct QD3DBatchItem { - enum QD3DBatchInfo { - BI_WINDING = 0x0001, - BI_AA = 0x0002, - BI_BRECT = 0x0004, - BI_MASKFULL = 0x0008, - BI_TEXT = 0x0010, - BI_MASK = 0x0020, - BI_CLIP = 0x0040, - BI_SCISSOR = 0x0080, - - BI_PIXMAP = 0x0100, - BI_IMAGE = 0x0200, - BI_COMPLEXBRUSH = 0x0400, - - BI_CLEARCLIP = 0x0800, // clip nothing (filling the clip mask with 0) - BI_TRANSFORM = 0x1000, - BI_MASKSCISSOR = 0x2000, - BI_FASTLINE = 0x4000, - BI_COSMETICPEN = 0x8000 - }; - - int m_info; - - int m_count; - int m_offset; - - QD3DMaskPosition m_maskpos; - qreal m_xoffset; - qreal m_yoffset; - qreal m_opacity; - - QPixmap m_pixmap; - QRectF m_brect; - QBrush m_brush; - - IDirect3DTexture9 *m_texture; - - qreal m_width; - qreal m_distance; - - QTransform m_matrix; - QPainter::CompositionMode m_cmode; - - QVector<int> m_pointstops; -}; - -struct QD3DBatch { - int m_item_index; - QD3DBatchItem items[QD3D_BATCH_SIZE]; -}; - -class QD3DStateManager; -class QD3DFontCache; -class QD3DDrawHelper; -class QD3DGradientCache; - -class QDirect3DPaintEnginePrivate : public QPaintEnginePrivate -{ - Q_DECLARE_PUBLIC(QDirect3DPaintEngine) - -public: - enum RenderTechnique { - RT_NoTechnique, - RT_Antialiased, - RT_Aliased, - }; - - QDirect3DPaintEnginePrivate() - : m_d3d_object(0) - , m_d3d_device(0) - , m_txop(QTransform::TxNone) - , m_effect(0) - , m_flush_on_end(0) - { init(); } - - ~QDirect3DPaintEnginePrivate(); - - bool init(); - void initDevice(); - - inline QD3DBatchItem *nextBatchItem(); - - QPolygonF brushCoordinates(const QRectF &r, bool stroke, qreal *fp) const; - void fillAliasedPath(QPainterPath path, const QRectF &brect, const QTransform &txform); - void fillAntialiasedPath(const QPainterPath &path, const QRectF &brect, - const QTransform &txform, bool stroke); - void fillPath(const QPainterPath &path, QRectF brect); - - void strokePath(const QPainterPath &path, QRectF brect, bool simple = false); - QPainterPath strokePathFastPen(const QPainterPath &path); - void strokeAliasedPath(QPainterPath path, const QRectF &brect, const QTransform &txform); - - void flushBatch(); - int flushAntialiased(int offset); - void flushAliased(QD3DBatchItem *item, int offset); - void flushText(QD3DBatchItem *item, int offset); - void flushLines(QD3DBatchItem *item, int offset); - - void updateTransform(const QTransform &matrix); - void updatePen(const QPen &pen); - void updateBrush(const QBrush &pen); - void updateClipRegion(const QRegion &clipregion, Qt::ClipOperation op = Qt::ReplaceClip); - void updateClipPath(const QPainterPath &clipregion, Qt::ClipOperation op = Qt::ReplaceClip); - void updateFont(const QFont &font); - - void setRenderTechnique(RenderTechnique technique); - - QPointF transformPoint(const QPointF &p, qreal *w) const; - - bool prepareBatch(QD3DBatchItem *item, int offset); - void prepareItem(QD3DBatchItem *item); - void cleanupItem(QD3DBatchItem *item); - void setCompositionMode(QPainter::CompositionMode mode); - - void verifyTexture(const QPixmap &pixmap); - - bool isFastRect(const QRectF &rect); - - void releaseDC(); - - void cleanup(); - bool testCaps(); - - QPixmap getPattern(Qt::BrushStyle style) const; - - // clipping - QPainterPath m_sysclip_path; - QPainterPath m_clip_path; - QRegion m_sysclip_region; - QRegion m_clip_region; - - qreal m_opacity; - D3DCOLOR m_opacity_color; - - int m_current_state; - - ID3DXEffect* m_effect; - - RenderTechnique m_current_technique; - - QTransform m_matrix; - qreal m_inv_scale; - - QPen m_pen; - Qt::BrushStyle m_pen_brush_style; - QTransform m_inv_pen_matrix; - D3DCOLOR m_pen_color; - qreal m_pen_width; - - QBrush m_brush; - Qt::BrushStyle m_brush_style; - QTransform m_inv_brush_matrix; - D3DCOLOR m_brush_color; - QTransform m_brush_origin; - - uint m_clipping_enabled : 1; - uint m_has_complex_clipping : 1; - uint m_cleartype_text: 1; - uint m_has_pen : 1; - uint m_has_cosmetic_pen : 1; - uint m_has_brush : 1; - uint m_has_fast_pen : 1; - uint m_has_aa_fast_pen : 1; - uint m_flush_on_end : 1; - uint m_supports_d3d : 1; - - QTransform::TransformationType m_txop; - - QPainter::CompositionMode m_cmode; - - QD3DSurfaceManager m_surface_manager; - QSize m_surface_size; - - LPDIRECT3D9 m_d3d_object; - LPDIRECT3DDEVICE9 m_d3d_device; - IDirect3DSurface9 *m_current_surface; - bool m_in_scene; - - QD3DGradientCache *m_gradient_cache; - QD3DDrawHelper *m_draw_helper; - QD3DBatch m_batch; - QD3DStateManager *m_statemanager; - - HDC m_dc; - IDirect3DSurface9 *m_dcsurface; - - QMap<Qt::BrushStyle, QPixmap> m_patterns; -}; - - -class QD3DStateManager : public ID3DXEffectStateManager { -public: - QD3DStateManager(LPDIRECT3DDEVICE9 pDevice, ID3DXEffect *effect); - void reset(); - - inline void startStateBlock(); - inline void endStateBlock(); - - inline void setCosmeticPen(bool enabled); - inline void setBrushMode(int mode); - inline void setTexture(LPDIRECT3DBASETEXTURE9 pTexture); - inline void setTexture(LPDIRECT3DBASETEXTURE9 pTexture, QGradient::Spread spread); - inline void setTransformation(const QTransform *matrix = 0); - inline void setProjection(const D3DXMATRIX *pMatrix); - inline void setMaskChannel(int channel); - inline void setMaskOffset(qreal x, qreal y); - inline void setFocalDistance(const qreal &fd); - - inline void beginPass(int pass); - inline void endPass(); - - STDMETHOD(QueryInterface)(REFIID iid, LPVOID *ppv); - STDMETHOD_(ULONG, AddRef)(); - STDMETHOD_(ULONG, Release)(); - - STDMETHOD(SetTransform)(D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX *pMatrix); - STDMETHOD(SetMaterial)(CONST D3DMATERIAL9 *pMaterial); - STDMETHOD(SetLight)(DWORD Index, CONST D3DLIGHT9 *pLight); - STDMETHOD(LightEnable)(DWORD Index, BOOL Enable); - STDMETHOD(SetRenderState)(D3DRENDERSTATETYPE State, DWORD Value); - STDMETHOD(SetTexture)(DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture); - STDMETHOD(SetTextureStageState)(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value); - STDMETHOD(SetSamplerState)(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value); - STDMETHOD(SetNPatchMode)(FLOAT NumSegments); - STDMETHOD(SetFVF)(DWORD FVF); - STDMETHOD(SetVertexShader)(LPDIRECT3DVERTEXSHADER9 pShader); - STDMETHOD(SetVertexShaderConstantF)(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount); - STDMETHOD(SetVertexShaderConstantI)(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount); - STDMETHOD(SetVertexShaderConstantB)(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount); - STDMETHOD(SetPixelShader)(LPDIRECT3DPIXELSHADER9 pShader); - STDMETHOD(SetPixelShaderConstantF)(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount); - STDMETHOD(SetPixelShaderConstantI)(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount); - STDMETHOD(SetPixelShaderConstantB)(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount); -private: - LPDIRECT3DVERTEXSHADER9 m_vertexshader; - LPDIRECT3DPIXELSHADER9 m_pixelshader; - - LPDIRECT3DBASETEXTURE9 m_textures[D3D_STAGE_COUNT]; - DWORD m_texturestates[D3D_STAGE_COUNT][D3D_TEXTURE_STATES]; - DWORD m_samplerstates[D3D_STAGE_COUNT][D3D_SAMPLE_STATES]; - DWORD m_renderstate[D3D_RENDER_STATES]; - - qreal m_radgradfd; - - bool m_cosmetic_pen; - int m_pass; - int m_maskchannel; - int m_brushmode; - LPDIRECT3DBASETEXTURE9 m_texture; - D3DXMATRIX m_projection; - - D3DXMATRIX m_d3dIdentityMatrix; - bool m_isIdentity; - QTransform m_transformation; - - LPDIRECT3DDEVICE9 m_pDevice; - ID3DXEffect *m_effect; - - LONG m_refs; - bool m_changed; - qreal m_xoffset, m_yoffset; - static int m_mask_channels[4][4]; -}; - -// -// font cache stuff -// - -struct QD3DGlyphCoord { - // stores the offset and size of a glyph texture - qreal x; - qreal y; - qreal width; - qreal height; - qreal log_width; - qreal log_height; - QFixed x_offset; - QFixed y_offset; -}; - -struct QD3DFontTexture { - int x_offset; // current glyph offset within the texture - int y_offset; - int width; - int height; - IDirect3DTexture9 *texture; -}; - -typedef QHash<glyph_t, QD3DGlyphCoord*> QD3DGlyphHash; -typedef QHash<QFontEngine*, QD3DGlyphHash*> QD3DFontGlyphHash; -typedef QHash<quint64, QD3DFontTexture*> QD3DFontTexHash; - -class QD3DGlyphCache : public QObject -{ - Q_OBJECT -public: - QD3DGlyphCache() - : QObject(0) - , current_cache(0) {} - ~QD3DGlyphCache(); - QD3DGlyphCoord *lookup(QFontEngine *, glyph_t); - void cacheGlyphs(QDirect3DPaintEngine *, const QTextItemInt &, const QVarLengthArray<glyph_t> &, - bool); - void cleanCache(); - inline QD3DFontTexture *fontTexture(QFontEngine *engine) { - return font_textures.constFind(reinterpret_cast<quint64>(engine)).value(); - } - -public slots: - void fontEngineDestroyed(QObject *); - -private: - QImage clearTypeGlyph(QFontEngine *, glyph_t glyph); - QD3DGlyphHash *current_cache; - QD3DFontTexHash font_textures; - QD3DFontGlyphHash font_cache; -}; - -QD3DGlyphCache::~QD3DGlyphCache() -{ -} - -QD3DGlyphCoord *QD3DGlyphCache::lookup(QFontEngine *, glyph_t g) -{ - Q_ASSERT(current_cache != 0); - QD3DGlyphHash::const_iterator it = current_cache->constFind(g); - if (it == current_cache->constEnd()) - return 0; - return it.value(); -} - -void QD3DGlyphCache::cleanCache() -{ - QList<quint64> keys = font_textures.keys(); - for (int i=0; i<keys.size(); ++i) - font_textures.value(keys.at(i))->texture->Release(); - - qDeleteAll(font_textures); - qDeleteAll(font_cache); - font_textures.clear(); - font_cache.clear(); - current_cache = 0; -} - -void QD3DGlyphCache::fontEngineDestroyed(QObject *object) -{ -// qDebug() << "=> font engine destroyed: " << object; - QFontEngine *engine = static_cast<QFontEngine *>(object); - - QD3DFontGlyphHash::iterator cache_it = font_cache.find(engine); - if (cache_it != font_cache.end()) { - QD3DGlyphHash *cache = font_cache.take(engine); - delete cache; - } - - quint64 font_key = reinterpret_cast<quint64>(engine); - QD3DFontTexture *tex = font_textures.take(font_key); - if (tex) { - tex->texture->Release(); - delete tex; - } -} - -QImage QD3DGlyphCache::clearTypeGlyph(QFontEngine *engine, glyph_t glyph) -{ - glyph_metrics_t gm = engine->boundingBox(glyph); - int glyph_x = qFloor(gm.x.toReal()); - int glyph_y = qFloor(gm.y.toReal()); - int glyph_width = qCeil((gm.x + gm.width).toReal()) - glyph_x + 2; - int glyph_height = qCeil((gm.y + gm.height).toReal()) - glyph_y + 2; - - if (glyph_width + glyph_x <= 0 || glyph_height <= 0) - return QImage(); - QImage im(glyph_width + glyph_x, glyph_height, QImage::Format_ARGB32_Premultiplied); - im.fill(0xff000000); // solid black - QPainter p(&im); - - p.setPen(Qt::white); - p.setBrush(Qt::NoBrush); - - QTextItemInt ti; - ti.ascent = engine->ascent(); - ti.descent = engine->descent(); - ti.width = glyph_width; - ti.fontEngine = engine; - - QGlyphLayoutArray<1> glyphLayout; - ti.glyphs = glyphLayout; - ti.glyphs.glyphs[0] = glyph; - ti.glyphs.advances_x[0] = glyph_width; - p.drawTextItem(QPointF(-glyph_x, -glyph_y), ti); - p.end(); - return im; -} - -#if 0 -static void dump_font_texture(QD3DFontTexture *tex) -{ - QColor color(Qt::red); - D3DLOCKED_RECT rect; - if (FAILED(tex->texture->LockRect(0, &rect, 0, 0))) { - qDebug() << "debug: unable to lock texture rect."; - return; - } - -// cleartype version -// uint *tex_data = (uint *) rect.pBits; -// QImage im(tex->width, tex->height, QImage::Format_ARGB32); -// for (int y=0; y<tex->height; ++y) { -// for (int x=0; x<tex->width; ++x) { -// im.setPixel(x, y, ((*(tex_data+x+y*tex->width)))); -// } -// } - uchar *tex_data = (uchar *) rect.pBits; - QImage im(rect.Pitch, tex->height, QImage::Format_ARGB32); - for (int y=0; y<tex->height; ++y) { - for (int x=0; x<rect.Pitch; ++x) { - uchar val = ((*(tex_data+x+y*rect.Pitch))); - im.setPixel(x, y, 0xff000000 | (val << 16) | (val << 8) | val); - } - } - tex->texture->UnlockRect(0); - static int i= 0; - im.save(QString("tx%1.png").arg(i++)); -} -#endif - -void QD3DGlyphCache::cacheGlyphs(QDirect3DPaintEngine *engine, const QTextItemInt &ti, - const QVarLengthArray<glyph_t> &glyphs, bool clearType) -{ - IDirect3DDevice9 *device = engine->d_func()->m_d3d_device; - QD3DFontGlyphHash::const_iterator cache_it = font_cache.constFind(ti.fontEngine); - QD3DGlyphHash *cache = 0; - if (cache_it == font_cache.constEnd()) { - cache = new QD3DGlyphHash; - font_cache.insert(ti.fontEngine, cache); - connect(ti.fontEngine, SIGNAL(destroyed(QObject *)), SLOT(fontEngineDestroyed(QObject *))); - } else { - cache = cache_it.value(); - } - - current_cache = cache; - - D3DFORMAT tex_format = clearType ? D3DFMT_A8R8G8B8 : D3DFMT_A8; - quint64 font_key = reinterpret_cast<quint64>(ti.fontEngine); - QD3DFontTexHash::const_iterator it = font_textures.constFind(font_key); - QD3DFontTexture *font_tex = 0; - if (it == font_textures.constEnd()) { - // alloc a new texture, put it into the cache - int tex_height = qCeil(ti.ascent.toReal() + ti.descent.toReal()) + 5; - int tex_width = tex_height * 30; // ### - IDirect3DTexture9 *tex; - if (FAILED(device->CreateTexture(tex_width, tex_height, 1, 0, - tex_format, D3DPOOL_MANAGED, &tex, NULL))) - { - qWarning("QD3DGlyphCache::cacheGlyphs(): can't allocate font texture (%dx%d).", - tex_width, tex_height); - return; - } else { -// qDebug() << "=> new font texture: " << QSize(tex_width,tex_height); - font_tex = new QD3DFontTexture; - font_tex->texture = tex; - font_tex->x_offset = 0; - font_tex->y_offset = 0; - font_tex->width = tex_width; - font_tex->height = tex_height; - font_textures.insert(font_key, font_tex); - } - } else { - font_tex = it.value(); - // make it current render target.. - } - - // cache each glyph - for (int i=0; i<glyphs.size(); ++i) { - QD3DGlyphHash::const_iterator it = cache->constFind(glyphs[i]); - if (it == cache->constEnd()) { - glyph_metrics_t metrics = ti.fontEngine->boundingBox(glyphs[i]); - int glyph_width = qCeil(metrics.width.toReal()) + 5; - int glyph_height = qCeil(ti.ascent.toReal() + ti.descent.toReal()) + 5; - if (font_tex->x_offset + glyph_width > font_tex->width) { - // no room on the current line, start new glyph strip - int strip_height = glyph_height; - font_tex->x_offset = 0; - font_tex->y_offset += strip_height; - if (font_tex->y_offset >= font_tex->height) { - // if no room in the current texture - realloc a larger texture - int old_tex_height = font_tex->height; - font_tex->height += strip_height; - - IDirect3DTexture9 *new_tex; - if (FAILED(device->CreateTexture(font_tex->width, font_tex->height, 1, 0, - tex_format, D3DPOOL_MANAGED, &new_tex, NULL))) - { - qWarning("QD3DGlyphCache(): can't re-allocate font texture."); - return; - } else { -// qDebug() << " -> new glyph strip added:" << QSize(font_tex->width,font_tex->height); - - D3DLOCKED_RECT new_rect, old_rect; - if (FAILED(font_tex->texture->LockRect(0, &old_rect, 0, D3DLOCK_READONLY))) { - qDebug() << "QD3DGlyphCache: unable to lock texture rect."; - return; - } - if (FAILED(new_tex->LockRect(0, &new_rect, 0, 0))) { - qDebug() << "QD3DGlyphCache: unable to lock texture rect."; - return; - } - memcpy(new_rect.pBits, old_rect.pBits, new_rect.Pitch * old_tex_height); - font_tex->texture->UnlockRect(0); - new_tex->UnlockRect(0); - engine->d_func()->flushBatch(); - font_tex->texture->Release(); - font_tex->texture = new_tex; - } - - // update the texture coords and the y offset for the existing glyphs in - // the cache, because of the texture size change - QD3DGlyphHash::iterator it = cache->begin(); - while (it != cache->end()) { - it.value()->height = (it.value()->height * old_tex_height) / font_tex->height; - it.value()->y = (it.value()->y * old_tex_height) / font_tex->height; - ++it; - } - } - } - QD3DGlyphCoord *d3d_glyph = new QD3DGlyphCoord; - d3d_glyph->x = qreal(font_tex->x_offset) / font_tex->width; - d3d_glyph->y = qreal(font_tex->y_offset) / font_tex->height; - d3d_glyph->width = qreal(glyph_width) / font_tex->width; - d3d_glyph->height = qreal(glyph_height) / font_tex->height; - d3d_glyph->log_width = d3d_glyph->width * font_tex->width; - d3d_glyph->log_height = d3d_glyph->height * font_tex->height; - d3d_glyph->x_offset = -metrics.x; - d3d_glyph->y_offset = metrics.y; - - QImage glyph_im; - if (clearType) - glyph_im = clearTypeGlyph(ti.fontEngine, glyphs[i]); - else - glyph_im = ti.fontEngine->alphaMapForGlyph(glyphs[i]).convertToFormat(QImage::Format_Indexed8); - - // write glyph to texture - D3DLOCKED_RECT rect; - RECT glyph_rect = { font_tex->x_offset, font_tex->y_offset, - font_tex->x_offset + glyph_im.width(), - font_tex->y_offset + glyph_im.height() }; - -// qDebug() << " > new glyph char added:" << QSize(glyph_im.width(), glyph_im.height()); - if (FAILED(font_tex->texture->LockRect(0, &rect, &glyph_rect, 0))) { - qDebug() << "QD3DGlyphCache: unable to lock texture rect."; - return; - } - - // ### unify these loops - if (clearType) { - int ppl = rect.Pitch / 4; - uint *tex_data = (uint *) rect.pBits; - for (int y=0; y<glyph_im.height(); ++y) { - uint *s = (uint *) glyph_im.scanLine(y); - for (int x=0; x<glyph_im.width(); ++x) { - tex_data[ppl*y + x] = *s; - ++s; - } - } - } else { - int ppl = rect.Pitch; - uchar *tex_data = (uchar *) rect.pBits; - for (int y=0; y<glyph_im.height(); ++y) { - uchar *s = (uchar *) glyph_im.scanLine(y); - for (int x=0; x<glyph_im.width(); ++x) { - tex_data[ppl*y + x] = *s; - ++s; - } - } - } - font_tex->texture->UnlockRect(0); - - // debug -// dump_font_texture(font_tex); - - if (font_tex->x_offset + glyph_width > font_tex->width) { - font_tex->x_offset = 0; - font_tex->y_offset += glyph_height; - } else { - font_tex->x_offset += glyph_width; - } - - cache->insert(glyphs[i], d3d_glyph); - } - } -} - -Q_GLOBAL_STATIC(QD3DGlyphCache, qd3d_glyph_cache) - -// -// end font caching stuff -// - - -// -// D3D image cache stuff -// - -// ### keep the GL stuff in mind.. -typedef void (*_qt_image_cleanup_hook_64)(qint64); -extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64; - -static void qd3d_image_cleanup(qint64 key); - -class QD3DImage -{ -public: - QD3DImage(IDirect3DDevice9 *device, const QImage &image); - ~QD3DImage(); - - IDirect3DTexture9 *texture; -}; - -static QList<IDirect3DTexture9 *> qd3d_release_list; - -QD3DImage::QD3DImage(IDirect3DDevice9 *device, const QImage &image) -{ - texture = 0; - Q_ASSERT(device); - QImage im = image.convertToFormat(QImage::Format_ARGB32); - if (FAILED(device->CreateTexture(im.width(), im.height(), 1, 0, - D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, 0))) { - qWarning("QD3DImage(): unable to create Direct3D texture."); - return; - } -// qDebug(" -> created image texture: %p - 0x%08x%08x",texture,uint (image.cacheKey() >> 32),uint (image.cacheKey() & 0xffffffff)); - D3DLOCKED_RECT rect; - if (FAILED(texture->LockRect(0, &rect, 0, 0))) { - qDebug() << "QD3DImage: unable to lock texture rect."; - return; - } - DWORD *dst = (DWORD *) rect.pBits; - DWORD *src = (DWORD *) im.scanLine(0); - - Q_ASSERT((rect.Pitch/4) == (im.bytesPerLine()/4)); - memcpy(dst, src, rect.Pitch*im.height()); - texture->UnlockRect(0); -} - -QD3DImage::~QD3DImage() -{ - if (texture) - qd3d_release_list.append(texture); -} - -static int qd3d_cache_limit = 64*1024; // cache ~64 MB worth of textures -typedef QCache<quint64, QD3DImage> QD3DImageCache; - -class QD3DImageManager -{ -public: - QD3DImageManager() { - // ### GL does the same! - qt_image_cleanup_hook_64 = qd3d_image_cleanup; - cache.setMaxCost(qd3d_cache_limit); - } - ~QD3DImageManager() { -// qDebug() << "unhooking d3d image cache"; - qt_image_cleanup_hook_64 = 0; - cache.clear(); - } - - IDirect3DTexture9 *lookup(IDirect3DDevice9 *device, const QImage &image); - void remove(quint64 key); - -private: - QD3DImageCache cache; -}; - -IDirect3DTexture9 *QD3DImageManager::lookup(IDirect3DDevice9 *device, const QImage &image) -{ - QD3DImage *tex_image = 0; - - tex_image = cache.object(image.cacheKey()); - if (!tex_image) { - // to avoid cache thrashing we remove images from the cache - // that have the same serial no as the cached image, since - // that image is most likely destoyed already, and we got a - // stale cache entry - uint serial = (uint) (image.cacheKey() >> 32); - QList<quint64> keys = cache.keys(); - for (int i=0; i<keys.size(); ++i) { - if ((uint)(keys.at(i) >> 32) == serial) { - cache.remove(keys.at(i)); - break; - } - } -// qDebug(" => cached: %d, adding cache image: 0x%08x%08x",cache.size(), uint (image.cacheKey() >> 32),uint (image.cacheKey() & 0xffffffff)); - // add cache entry - int cost = image.width()*image.height()*4/1024; - if (cache.totalCost() + cost > cache.maxCost()) { - // no room for new entries? kick out half the cached images - int old_max_cost = cache.maxCost(); - cache.setMaxCost(old_max_cost/2); - cache.setMaxCost(old_max_cost); - } - tex_image = new QD3DImage(device, image); - cache.insert(image.cacheKey(), tex_image, cost); -// qDebug() << "==> total cache cost: " << cache.totalCost() << cost; - } - - return tex_image->texture; -} - -void QD3DImageManager::remove(quint64 key) -{ -// QList<quint64> keys = cache.keys(); -// if (keys.contains(key)) -// qDebug() << "entery removed from cache"; - cache.remove(key); -} - -Q_GLOBAL_STATIC(QD3DImageManager, qd3d_image_cache) - -static void qd3d_image_cleanup(qint64 key) -{ -// qDebug() << "qd3d_image_cleanup:"; -// qDebug(" => key: 0x%08x%08x", (uint) (key >> 32), (uint)(key & 0xffffffff)); - qd3d_image_cache()->remove(key); -} - -// -// end D3D image cache stuff -// - -class QD3DDrawHelper : public QTessellator -{ -public: - QD3DDrawHelper(QDirect3DPaintEnginePrivate *pe); - ~QD3DDrawHelper(); - - bool needsFlushing() const; - QD3DMaskPosition allocateMaskPosition(const QRectF &brect, bool *breakbatch); - - void setClipPath(const QPainterPath &path, QD3DBatchItem **item); - - void queueAntialiasedMask(const QPolygonF &poly, QD3DBatchItem **item, const QRectF &brect); - QRectF queueAliasedMask(const QPainterPath &path, QD3DBatchItem **item, D3DCOLOR color); - - void queueRect(const QRectF &rect, QD3DBatchItem *item, D3DCOLOR color, const QPolygonF &trect); - void queueRect(const QRectF &rect, QD3DBatchItem *item, D3DCOLOR color); - - void queueTextGlyph(const QRectF &rect, const qreal *tex_coords, QD3DBatchItem *item, - D3DCOLOR color); - - void queueAntialiasedLines(const QPainterPath &path, QD3DBatchItem **item, const QRectF &brect); - void queueAliasedLines(const QLineF *lines, int lineCount, QD3DBatchItem **item); - - int drawAntialiasedMask(int offset, int maxoffset); - void drawAliasedMask(int offset); - void drawAntialiasedBoundingRect(QD3DBatchItem *item); - void drawAliasedBoundingRect(QD3DBatchItem *item); - void drawTextItem(QD3DBatchItem *item); - void drawAliasedLines(QD3DBatchItem *item); - - void setMaskSize(QSize size); - - void beforeReset(); - void afterReset(); - - IDirect3DSurface9 *freeMaskSurface(); - - inline void lockVertexBuffer(); - inline void unlockVertexBuffer(); - - inline int index() { return m_index; } - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - enum VertexBufferAccess { - CLEAR = 0x00, - READ = 0x01, - WRITE = 0x02 - }; - int accesscontrol[QT_VERTEX_BUF_SIZE]; -#endif - -private: - void addTrap(const Trapezoid &trap); - void tessellate(const QPolygonF &poly); - inline void lineToStencil(qreal x, qreal y); - inline void curveToStencil(const QPointF &cp1, const QPointF &cp2, const QPointF &ep); - QRectF pathToVertexArrays(const QPainterPath &path); - void resetMask(); - - QDirect3DPaintEnginePrivate *m_pe; - - qreal m_xoffset, m_yoffset; - int m_startindex; - int m_index; - int m_height, m_width; - LPDIRECT3DVERTEXBUFFER9 m_d3dvbuff; - vertex *m_vbuff; - QD3DBatchItem *m_item; - QRectF m_boundingRect; - - qreal max_x; - qreal max_y; - qreal min_x; - qreal min_y; - qreal firstx; - qreal firsty; - - QPointF tess_lastpoint; - int tess_index; - - bool m_locked; - IDirect3DTexture9 *m_mask; - IDirect3DSurface9 *m_maskSurface; - IDirect3DSurface9 *m_depthStencilSurface; - - D3DCOLOR m_color; - bool m_clearmask; - bool m_isLine; - bool m_firstPoint; - - QD3DMaskPosition m_mask_position; - int m_mask_offsetX2; - int m_mask_offsetY2; -}; - -QD3DStateManager::QD3DStateManager(LPDIRECT3DDEVICE9 pDevice, ID3DXEffect *effect) - : m_pDevice(pDevice), m_effect(effect), m_refs(0) -{ - if (FAILED(D3DXMatrixIdentity(&m_d3dIdentityMatrix))) { - qWarning("QDirect3DPaintEngine: D3DXMatrixIdentity failed"); - } - reset(); -} - -void QD3DStateManager::reset() -{ - m_radgradfd = -1; - - m_cosmetic_pen = false; - m_pass = -1; - m_maskchannel = -1; - m_brushmode = -1; - m_texture = 0; - m_xoffset = INT_MAX; - m_yoffset = INT_MAX; - - m_vertexshader = 0; - m_pixelshader = 0; - - m_isIdentity = true; - m_transformation = QTransform(); - m_effect->SetMatrix("g_mTransformation", &m_d3dIdentityMatrix); - - ZeroMemory(&m_projection, sizeof(D3DMATRIX)); - ZeroMemory(m_textures, sizeof(LPDIRECT3DBASETEXTURE9) * D3D_STAGE_COUNT); - FillMemory(m_samplerstates, sizeof(DWORD) * D3D_SAMPLE_STATES * D3D_STAGE_COUNT, 0xFFFFFFFE); - FillMemory(m_texturestates, sizeof(DWORD) * D3D_TEXTURE_STATES * D3D_STAGE_COUNT, 0xFFFFFFFE); - FillMemory(m_renderstate, sizeof(DWORD) * D3D_RENDER_STATES, 0xFFFFFFFE); -} - -inline void QD3DStateManager::beginPass(int pass) -{ - if (pass != m_pass) { - if (m_pass != -1) - m_effect->EndPass(); - m_effect->BeginPass(pass); - m_pass = pass; - } -} - -inline void QD3DStateManager::endPass() -{ - if (m_pass != -1) { - m_pass = -1; - m_effect->EndPass(); - } -} - -inline void QD3DStateManager::startStateBlock() { - m_changed = false; -} - -inline void QD3DStateManager::setCosmeticPen(bool enabled) -{ - if (enabled != m_cosmetic_pen) { - m_effect->SetBool("g_mCosmeticPen", enabled); - m_cosmetic_pen = enabled; - m_changed = true; - } -} - -inline void QD3DStateManager::setBrushMode(int mode) -{ - if (mode != m_brushmode) { - m_effect->SetInt("g_mBrushMode", mode); - m_brushmode = mode; - m_changed = true; - } -} - -inline void QD3DStateManager::setTexture(LPDIRECT3DBASETEXTURE9 pTexture) -{ - SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER); - SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER); - - if (pTexture != m_texture) { - m_texture = pTexture; - m_effect->SetTexture("g_mTexture", pTexture); - m_changed = true; - } -} - -inline void QD3DStateManager::setTexture(LPDIRECT3DBASETEXTURE9 pTexture, QGradient::Spread spread) -{ - switch(spread) { - case QGradient::RepeatSpread: - SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); - SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); - break; - case QGradient::ReflectSpread: - SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR); - SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR); - break; - default: - SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - break; - }; - - if (pTexture != m_texture) { - m_texture = pTexture; - m_effect->SetTexture("g_mTexture", pTexture); - m_changed = true; - } -} - -inline void QD3DStateManager::setTransformation(const QTransform *matrix) -{ - if (matrix) { - if (*matrix != m_transformation) { - D3DXMATRIX dxmatrix(matrix->m11(), matrix->m12(), 0, matrix->m13(), - matrix->m21(), matrix->m22(), 0, matrix->m23(), - 0, 0, 1, 0, - matrix->dx(), matrix->dy(), 0, 1); - m_effect->SetMatrix("g_mTransformation", &dxmatrix); - m_transformation = *matrix; - m_changed = true; - m_isIdentity = false; - } - } else if (!m_isIdentity) { - m_effect->SetMatrix("g_mTransformation", &m_d3dIdentityMatrix); - m_transformation = QTransform(); - m_changed = true; - m_isIdentity = true; - } -} - -inline void QD3DStateManager::setProjection(const D3DXMATRIX *pMatrix) -{ - if (*pMatrix != m_projection) { - m_effect->SetMatrix("g_mViewProjection", pMatrix); - m_projection = *pMatrix; - m_changed = true; - } -} - -inline void QD3DStateManager::setFocalDistance(const qreal &fd) -{ - if (fd != m_radgradfd) { - m_effect->SetFloat("g_mFocalDist", fd); - m_changed = true; - m_radgradfd = fd; - } -} - -inline void QD3DStateManager::setMaskOffset(qreal x, qreal y) -{ - if (x != m_xoffset || y != m_yoffset) { - float offset[2] = {x, y}; - m_effect->SetFloatArray("g_mMaskOffset", offset, 2); - m_xoffset = x; - m_yoffset = y; - m_changed = true; - } -} - -inline void QD3DStateManager::setMaskChannel(int channel) -{ - if (m_maskchannel != channel) { - m_effect->SetIntArray("g_mChannel", m_mask_channels[channel], 4); - m_maskchannel = channel; - m_changed = true; - } -} - -inline void QD3DStateManager::endStateBlock() -{ - if (m_changed) { - m_effect->CommitChanges(); - m_changed = false; - } -} - -STDMETHODIMP QD3DStateManager::QueryInterface(REFIID iid, LPVOID *ppv) -{ - if(iid == IID_IUnknown || iid == IID_ID3DXEffectStateManager) - { - *ppv = this; - ++m_refs; - return NOERROR; - } - *ppv = NULL; - return ResultFromScode(E_NOINTERFACE); -} - -STDMETHODIMP_(ULONG) QD3DStateManager::AddRef(void) -{ - return (ULONG)InterlockedIncrement( &m_refs ); -} - - -STDMETHODIMP_(ULONG) QD3DStateManager::Release(void) -{ - if( 0L == InterlockedDecrement( &m_refs ) ) { - delete this; - return 0L; - } - - return m_refs; -} -STDMETHODIMP QD3DStateManager::SetTransform(D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX *pMatrix) -{ - return m_pDevice->SetTransform(State, pMatrix); -} - -STDMETHODIMP QD3DStateManager::SetMaterial(CONST D3DMATERIAL9 *pMaterial) -{ - return m_pDevice->SetMaterial(pMaterial); -} - -STDMETHODIMP QD3DStateManager::SetLight(DWORD Index, CONST D3DLIGHT9 *pLight) -{ - return m_pDevice->SetLight(Index, pLight); -} - -STDMETHODIMP QD3DStateManager::LightEnable(DWORD Index, BOOL Enable) -{ - return m_pDevice->LightEnable(Index, Enable); -} - -STDMETHODIMP QD3DStateManager::SetRenderState(D3DRENDERSTATETYPE State, DWORD Value) -{ - if (State < D3D_RENDER_STATES) { - if (m_renderstate[State] == Value) - return S_OK; - m_renderstate[State] = Value; - } - return m_pDevice->SetRenderState(State, Value); -} - -STDMETHODIMP QD3DStateManager::SetTexture(DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture) -{ - if (Stage < D3D_STAGE_COUNT) { - if (m_textures[Stage] == pTexture) - return S_OK; - m_textures[Stage] = pTexture; - } - return m_pDevice->SetTexture(Stage, pTexture); -} - -STDMETHODIMP QD3DStateManager::SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) -{ - if (Stage < D3D_STAGE_COUNT && Type < D3D_TEXTURE_STATES) { - if (m_texturestates[Stage][Type] == Value) - return S_OK; - m_texturestates[Stage][Type] = Value; - } - return m_pDevice->SetTextureStageState(Stage, Type, Value); -} - -STDMETHODIMP QD3DStateManager::SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) -{ - if (Sampler < D3D_STAGE_COUNT && Type < D3D_SAMPLE_STATES) { - if (m_samplerstates[Sampler][Type] == Value) - return S_OK; - m_samplerstates[Sampler][Type] = Value; - } - return m_pDevice->SetSamplerState(Sampler, Type, Value); -} - -STDMETHODIMP QD3DStateManager::SetNPatchMode(FLOAT NumSegments) -{ - return m_pDevice->SetNPatchMode(NumSegments); -} - -STDMETHODIMP QD3DStateManager::SetFVF(DWORD FVF) -{ - return m_pDevice->SetFVF(FVF); -} - -STDMETHODIMP QD3DStateManager::SetVertexShader(LPDIRECT3DVERTEXSHADER9 pShader) -{ - if (m_vertexshader == pShader) - return S_OK; - m_vertexshader = pShader; - return m_pDevice->SetVertexShader(pShader); -} - -STDMETHODIMP QD3DStateManager::SetVertexShaderConstantF(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount) -{ - return m_pDevice->SetVertexShaderConstantF(RegisterIndex, pConstantData, RegisterCount); -} - -STDMETHODIMP QD3DStateManager::SetVertexShaderConstantI(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount) -{ - return m_pDevice->SetVertexShaderConstantI(RegisterIndex, pConstantData, RegisterCount); -} - -STDMETHODIMP QD3DStateManager::SetVertexShaderConstantB(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount) -{ - return m_pDevice->SetVertexShaderConstantB(RegisterIndex, pConstantData, RegisterCount); -} - -STDMETHODIMP QD3DStateManager::SetPixelShader(LPDIRECT3DPIXELSHADER9 pShader) -{ - if (m_pixelshader == pShader) - return S_OK; - m_pixelshader = pShader; - return m_pDevice->SetPixelShader(pShader); -} - -STDMETHODIMP QD3DStateManager::SetPixelShaderConstantF(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount) -{ - return m_pDevice->SetPixelShaderConstantF(RegisterIndex, pConstantData, RegisterCount); -} - -STDMETHODIMP QD3DStateManager::SetPixelShaderConstantI(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount) -{ - return m_pDevice->SetPixelShaderConstantI(RegisterIndex, pConstantData, RegisterCount); -} - -STDMETHODIMP QD3DStateManager::SetPixelShaderConstantB(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount) -{ - return m_pDevice->SetPixelShaderConstantB(RegisterIndex, pConstantData, RegisterCount); -} - -#define QD3D_GRADIENT_CACHE_SIZE 60 -#define QD3D_GRADIENT_PALETTE_SIZE 1024 - -class QD3DGradientCache -{ - struct CacheInfo - { - inline CacheInfo(QGradientStops s, qreal op) : - stops(s), opacity(op) {} - - IDirect3DTexture9 *texture; - QGradientStops stops; - qreal opacity; - }; - - typedef QMultiHash<quint64, CacheInfo> QD3DGradientColorTableHash; - -public: - QD3DGradientCache(LPDIRECT3DDEVICE9 device); - ~QD3DGradientCache(); - - inline IDirect3DTexture9 *getBuffer(const QGradientStops &stops, qreal opacity); - -protected: - inline void generateGradientColorTable(const QGradientStops& s, - uint *colorTable, - int size, qreal opacity) const; - IDirect3DTexture9 *addCacheElement(quint64 hash_val, const QGradientStops &stops, qreal opacity); - void cleanCache(); - - QD3DGradientColorTableHash cache; - LPDIRECT3DDEVICE9 m_device; -}; - -QD3DGradientCache::QD3DGradientCache(LPDIRECT3DDEVICE9 device) - : m_device(device) -{ - -} - -QD3DGradientCache::~QD3DGradientCache() -{ - cleanCache(); -} - -inline IDirect3DTexture9 *QD3DGradientCache::getBuffer(const QGradientStops &stops, qreal opacity) -{ - quint64 hash_val = 0; - - for (int i = 0; i < stops.size() && i <= 2; i++) - hash_val += stops[i].second.rgba(); - - QD3DGradientColorTableHash::const_iterator it = cache.constFind(hash_val); - - if (it == cache.constEnd()) - return addCacheElement(hash_val, stops, opacity); - else { - do { - const CacheInfo &cache_info = it.value(); - if (cache_info.stops == stops && cache_info.opacity == opacity) { - return cache_info.texture; - } - ++it; - } while (it != cache.constEnd() && it.key() == hash_val); - // an exact match for these stops and opacity was not found, create new cache - return addCacheElement(hash_val, stops, opacity); - } -} - -void QD3DGradientCache::generateGradientColorTable(const QGradientStops& s, uint *colorTable, int size, qreal opacity) const -{ - int pos = 0; - qreal fpos = 0.0; - qreal incr = 1.0 / qreal(size); - QVector<uint> colors(s.size()); - - for (int i = 0; i < s.size(); ++i) - colors[i] = s[i].second.rgba(); - - uint alpha = qRound(opacity * 255); - while (fpos < s.first().first) { - colorTable[pos] = ARGB_COMBINE_ALPHA(colors[0], alpha); - pos++; - fpos += incr; - } - - for (int i = 0; i < s.size() - 1; ++i) { - qreal delta = 1/(s[i+1].first - s[i].first); - while (fpos < s[i+1].first && pos < size) { - int dist = int(256 * ((fpos - s[i].first) * delta)); - int idist = 256 - dist; - uint current_color = ARGB_COMBINE_ALPHA(colors[i], alpha); - uint next_color = ARGB_COMBINE_ALPHA(colors[i+1], alpha); -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - colorTable[pos] = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist); -#else - uint c = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist); - colorTable[pos] = ( (c << 24) & 0xff000000) - | ((c >> 24) & 0x000000ff) - | ((c << 8) & 0x00ff0000) - | ((c >> 8) & 0x0000ff00); -#endif // Q_BYTE_ORDER - ++pos; - fpos += incr; - } - } - for (;pos < size; ++pos) - colorTable[pos] = colors[s.size() - 1]; -} - -IDirect3DTexture9 *QD3DGradientCache::addCacheElement(quint64 hash_val, const QGradientStops &stops, qreal opacity) -{ - if (cache.size() == QD3D_GRADIENT_CACHE_SIZE) { - int elem_to_remove = qrand() % QD3D_GRADIENT_CACHE_SIZE; - uint key = cache.keys()[elem_to_remove]; - - // need to call release on each removed cache entry: - QD3DGradientColorTableHash::const_iterator it = cache.constFind(key); - do { - it.value().texture->Release(); - } while (++it != cache.constEnd() && it.key() == key); - - cache.remove(key); // may remove more than 1, but OK - } - - CacheInfo cache_entry(stops, opacity); - uint buffer[QD3D_GRADIENT_PALETTE_SIZE]; - generateGradientColorTable(stops, buffer, QD3D_GRADIENT_PALETTE_SIZE, opacity); - - if (FAILED(m_device->CreateTexture(QD3D_GRADIENT_PALETTE_SIZE, 1, 1, 0, - D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &cache_entry.texture, 0))) { - qWarning("QD3DGradientCache::addCacheElement(): unable to create Direct3D texture."); - return 0; - } - - D3DLOCKED_RECT rect; - if (FAILED(cache_entry.texture->LockRect(0, &rect, 0, 0))) { - qDebug() << "QD3DGradientCache::addCacheElement(): unable to lock texture rect."; - return 0; - } - memcpy(rect.pBits, buffer, rect.Pitch); - cache_entry.texture->UnlockRect(0); - - return cache.insert(hash_val, cache_entry).value().texture; -} - -void QD3DGradientCache::cleanCache() -{ - QD3DGradientColorTableHash::const_iterator it = cache.constBegin(); - for (; it != cache.constEnd(); ++it) { - const CacheInfo &cache_info = it.value(); - cache_info.texture->Release(); - } - cache.clear(); -} - -QD3DSurfaceManager::QD3DSurfaceManager() : - m_status(NoStatus), m_dummy(0), m_device(0), m_pd(0), m_current(0) -{ - -} - -QD3DSurfaceManager::~QD3DSurfaceManager() -{ -} - -void QD3DSurfaceManager::setPaintDevice(QPaintDevice *pd) -{ - m_status = NoStatus; - m_pd = pd; - m_current = 0; - - if (m_device->TestCooperativeLevel() != D3D_OK) { - m_status = NeedsResetting; - return; - } - - m_current = m_swapchains.value(pd, 0); - QWidget *w = static_cast<QWidget*>(pd); - - if (m_current) { - if (m_current->size != w->size()) { - m_swapchains.remove(pd); - m_current->surface->Release(); - m_current->swapchain->Release(); - delete m_current; - m_current = 0; - } - } - - if (!m_current) { - m_current = createSwapChain(w); - updateMaxSize(); - } -} - -int QD3DSurfaceManager::status() const -{ - return m_status; -} - -void QD3DSurfaceManager::reset() -{ - QList<QPaintDevice *> pds = m_swapchains.keys(); - - QMap<QPaintDevice *, D3DSwapChain *>::const_iterator i = m_swapchains.constBegin(); - while (i != m_swapchains.constEnd()) { - i.value()->surface->Release(); - i.value()->swapchain->Release(); - ++i; - } - qDeleteAll(m_swapchains.values()); - m_swapchains.clear(); - - D3DPRESENT_PARAMETERS params; - initPresentParameters(¶ms); - params.hDeviceWindow = m_dummy; - - HRESULT res = m_device->Reset(¶ms); - if (FAILED(res)) { - switch (res) { - case D3DERR_DEVICELOST: - qWarning("QDirect3DPaintEngine: Reset failed (D3DERR_DEVICELOST)"); - break; - case D3DERR_DRIVERINTERNALERROR: - qWarning("QDirect3DPaintEngine: Reset failed (D3DERR_DRIVERINTERNALERROR)"); - break; - case D3DERR_OUTOFVIDEOMEMORY: - qWarning("QDirect3DPaintEngine: Reset failed (D3DERR_OUTOFVIDEOMEMORY)"); - break; - default: - qWarning("QDirect3DPaintEngine: Reset failed"); - }; - } - - for (int i=0; i<pds.count(); ++i) { - QWidget *w = static_cast<QWidget*>(pds.at(i)); - createSwapChain(w); - } - - // reset the mask as well - m_status = MaxSizeChanged; - - setPaintDevice(m_pd); - updateMaxSize(); -} - -LPDIRECT3DSURFACE9 QD3DSurfaceManager::renderTarget() -{ - return m_current ? m_current->surface : 0; -} - -LPDIRECT3DSURFACE9 QD3DSurfaceManager::surface(QPaintDevice *pd) -{ - D3DSwapChain *swapchain = m_swapchains.value(pd, 0); - return swapchain ? swapchain->surface : 0; -} - -LPDIRECT3DSWAPCHAIN9 QD3DSurfaceManager::swapChain(QPaintDevice *pd) -{ - D3DSwapChain *swapchain = m_swapchains.value(pd, 0); - return swapchain ? swapchain->swapchain : 0; -} - -void QD3DSurfaceManager::releasePaintDevice(QPaintDevice *pd) -{ - D3DSwapChain *swapchain = m_swapchains.take(pd); - - if (swapchain) { - swapchain->surface->Release(); - swapchain->swapchain->Release(); - delete swapchain; - if (swapchain == m_current) - m_current = 0; - } -} - -LPDIRECT3DDEVICE9 QD3DSurfaceManager::device() -{ - return m_device; -} - -void QD3DSurfaceManager::cleanup() -{ - QPixmapCache::clear(); - qd3d_glyph_cache()->cleanCache(); - - // release doomed textures - for (int k=0; k<qd3d_release_list.size(); ++k) - qd3d_release_list.at(k)->Release(); - qd3d_release_list.clear(); - - QMap<QPaintDevice *, D3DSwapChain *>::const_iterator i = m_swapchains.constBegin(); - while (i != m_swapchains.constEnd()) { - i.value()->surface->Release(); - i.value()->swapchain->Release(); - ++i; - } - qDeleteAll(m_swapchains.values()); - - if (m_device) - m_device->Release(); - - DestroyWindow(m_dummy); - QString cname(QLatin1String("qt_d3d_dummy")); - QT_WA({ - UnregisterClass((TCHAR*)cname.utf16(), (HINSTANCE)qWinAppInst()); - } , { - UnregisterClassA(cname.toLatin1(), (HINSTANCE)qWinAppInst()); - }); -} - -QSize QD3DSurfaceManager::maxSize() const -{ - return m_max_size; -} - -extern "C" { - LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); -}; - -void QD3DSurfaceManager::init(LPDIRECT3D9 object) -{ - QString cname(QLatin1String("qt_d3d_dummy")); - uint style = CS_DBLCLKS | CS_SAVEBITS; - ATOM atom; - QT_WA({ - WNDCLASS wc; - wc.style = style; - wc.lpfnWndProc = (WNDPROC)QtWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = (HINSTANCE)qWinAppInst(); - wc.hIcon = 0; - wc.hCursor = 0; - wc.hbrBackground = 0; - wc.lpszMenuName = 0; - wc.lpszClassName = (TCHAR*)cname.utf16(); - atom = RegisterClass(&wc); - } , { - WNDCLASSA wc; - wc.style = style; - wc.lpfnWndProc = (WNDPROC)QtWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = (HINSTANCE)qWinAppInst(); - wc.hIcon = 0; - wc.hCursor = 0; - wc.hbrBackground = 0; - wc.lpszMenuName = 0; - QByteArray tempArray = cname.toLatin1(); - wc.lpszClassName = tempArray; - atom = RegisterClassA(&wc); - }); - - QT_WA({ - const TCHAR *className = (TCHAR*)cname.utf16(); - m_dummy = CreateWindow(className, className, 0, - 0, 0, 1, 1, - 0, 0, qWinAppInst(), 0); - } , { - m_dummy = CreateWindowA(cname.toLatin1(), cname.toLatin1(), 0, - 0, 0, 1, 1, - 0, 0, qWinAppInst(), 0); - }); - - D3DPRESENT_PARAMETERS params; - initPresentParameters(¶ms); - params.hDeviceWindow = m_dummy; - - HRESULT res = object->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, 0, - D3DCREATE_PUREDEVICE|D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_NOWINDOWCHANGES|D3DCREATE_FPU_PRESERVE, - ¶ms, &m_device); - - if (FAILED(res) || m_device == 0) - qWarning("QDirect3DPaintEngine: failed to create Direct3D device (error=0x%x).", res); -} - -void QD3DSurfaceManager::updateMaxSize() -{ - int w = 0, h = 0; - QMap<QPaintDevice *, D3DSwapChain *>::const_iterator i = m_swapchains.constBegin(); - while (i != m_swapchains.constEnd()) { - - int nw = i.key()->width(); - if (nw > w) - w = nw; - - int nh = i.key()->height(); - if (nh > h) - h = nh; - - ++i; - } - - QSize newsize = QSize(w, h); - if (newsize != m_max_size) { - m_status |= MaxSizeChanged; - m_max_size = newsize; - } -} - -void QD3DSurfaceManager::initPresentParameters(D3DPRESENT_PARAMETERS *params) -{ - ZeroMemory(params, sizeof(D3DPRESENT_PARAMETERS)); - params->Windowed = true; - params->SwapEffect = D3DSWAPEFFECT_COPY; - params->BackBufferFormat = D3DFMT_UNKNOWN; - params->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; - params->Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; -} - -QD3DSurfaceManager::D3DSwapChain *QD3DSurfaceManager::createSwapChain(QWidget *w) -{ - D3DPRESENT_PARAMETERS params; - initPresentParameters(¶ms); - params.hDeviceWindow = w->winId(); - D3DSwapChain *swapchain = new D3DSwapChain(); - swapchain->size = w->size(); - if (FAILED(m_device->CreateAdditionalSwapChain(¶ms, &swapchain->swapchain))) - qWarning("QDirect3DPaintEngine: CreateAdditionalSwapChain failed"); - if (FAILED(swapchain->swapchain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &swapchain->surface))) - qWarning("QDirect3DPaintEngine: GetBackBuffer failed"); - m_swapchains.insert(w, swapchain); - connect(w, SIGNAL(destroyed(QObject *)), SLOT(cleanupPaintDevice(QObject *))); - - // init with background color - QColor bg = w->palette().color(QPalette::Background); - m_device->ColorFill(swapchain->surface, 0, D3DCOLOR_ARGB(bg.alpha(), bg.red(),bg.green(),bg.blue())); - - return swapchain; -} - -void QD3DSurfaceManager::cleanupPaintDevice(QObject *object) -{ - QWidget *w = static_cast<QWidget *>(object); - releasePaintDevice(w); -} - -int QD3DStateManager::m_mask_channels[4][4] = - {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}}; - -QD3DDrawHelper::QD3DDrawHelper(QDirect3DPaintEnginePrivate *pe) - : m_pe(pe), m_d3dvbuff(0), m_maskSurface(0), m_depthStencilSurface(0), - m_locked(false), m_mask(0), m_startindex(0), m_index(0), m_vbuff(0), m_clearmask(true), - m_isLine(false), m_firstPoint(true) -{ - resetMask(); -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - memset(accesscontrol, 0, QT_VERTEX_BUF_SIZE * sizeof(VertexBufferAccess)); -#endif - - // create vertex buffer - afterReset(); -} - -QD3DDrawHelper::~QD3DDrawHelper() -{ - if (m_maskSurface) - m_maskSurface->Release(); - - if (m_mask) - m_mask->Release(); - - if (m_depthStencilSurface) - m_depthStencilSurface->Release(); - - if (m_d3dvbuff) - m_d3dvbuff->Release(); -} - -inline void QD3DDrawHelper::lockVertexBuffer() -{ - if (!m_locked) { - DWORD lockflags = D3DLOCK_NOOVERWRITE; - if (m_startindex >= QT_VERTEX_RESET_LIMIT) { - m_startindex = 0; - m_index = 0; - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - for (int i=0; i<QT_VERTEX_BUF_SIZE; ++i) { - if (accesscontrol[i] != (WRITE|READ) && accesscontrol[i] != CLEAR) - qDebug() << "Vertex Buffer: Access Error"; - } - memset(accesscontrol, 0, QT_VERTEX_BUF_SIZE * sizeof(VertexBufferAccess)); -#endif - - lockflags = D3DLOCK_DISCARD; - } - - if (FAILED(m_d3dvbuff->Lock(0, 0, (void**)&m_vbuff, lockflags))) { - qWarning() << "QDirect3DPaintEngine: unable to lock vertex buffer."; - } - m_locked = true; - } -} - -inline void QD3DDrawHelper::unlockVertexBuffer() -{ - if (m_locked) { - if (FAILED(m_d3dvbuff->Unlock())) { - qWarning() << "QDirect3DPaintEngine: unable to unlock vertex buffer."; - } - m_locked = false; - } -} - -void QD3DDrawHelper::setClipPath(const QPainterPath &path, QD3DBatchItem **item) -{ - lockVertexBuffer(); - - m_item = *item; - m_item->m_maskpos.x = m_item->m_maskpos.y = 0; - m_item->m_maskpos.channel = 3; - m_item->m_info |= QD3DBatchItem::BI_CLIP; - - bool winding = (path.fillRule() == Qt::WindingFill); - if (winding) - m_item->m_info |= QD3DBatchItem::BI_WINDING; - - if (!path.isEmpty()) { - m_item->m_info |= QD3DBatchItem::BI_MASK; - m_item->m_info &= ~QD3DBatchItem::BI_AA; - m_color = 0; - QRectF brect = pathToVertexArrays(path); - queueRect(brect, m_item, 0); - } - - *item = m_item; -} - - - -void QD3DDrawHelper::queueAntialiasedMask(const QPolygonF &poly, QD3DBatchItem **item, const QRectF &brect) -{ - lockVertexBuffer(); - - m_item = *item; - m_item->m_info |= QD3DBatchItem::BI_MASK; - setWinding(m_item->m_info & QD3DBatchItem::BI_WINDING); - - int xoffset = m_item->m_maskpos.x; - int yoffset = m_item->m_maskpos.y; - - int x = brect.left(); - int y = brect.top(); - - m_item->m_xoffset = (xoffset - x) + 1; - m_item->m_yoffset = (yoffset - y) + 1; - - m_boundingRect = brect; - tessellate(poly); - - *item = m_item; -} - -QRectF QD3DDrawHelper::queueAliasedMask(const QPainterPath &path, QD3DBatchItem **item, D3DCOLOR color) -{ - lockVertexBuffer(); - - m_color = color; - m_item = *item; - m_item->m_info |= QD3DBatchItem::BI_MASK; - - bool winding = (path.fillRule() == Qt::WindingFill); - if (winding) - m_item->m_info |= QD3DBatchItem::BI_WINDING; - - QRectF result = pathToVertexArrays(path); - *item = m_item; - return result; -} - -// used for drawing aliased transformed rects directly -// don't use for antialiased or masked drawing -void QD3DDrawHelper::queueRect(const QRectF &rect, QD3DBatchItem *item, D3DCOLOR color, const QPolygonF &trect) -{ - lockVertexBuffer(); - - qreal zval = (item->m_info & QD3DBatchItem::BI_CLIP) ? 0.0f : 0.5f; - item->m_info |= QD3DBatchItem::BI_BRECT; - - // if the item does not have a mask, the offset is different - if (!(item->m_info & QD3DBatchItem::BI_MASK)) { - item->m_offset = m_index; - item->m_count = (item->m_info & QD3DBatchItem::BI_AA) ? 0 : -2; - } - - qreal x1 = rect.left(); - qreal y1 = rect.top(); - qreal x2 = rect.right(); - qreal y2 = rect.bottom(); - - QPointF tc = trect.at(0); - vertex v1 = { {x1, y1, zval} , color, - tc.x(), tc.y(), 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f }; - - tc = trect.at(1); - vertex v2 = { {x2, y1, zval} , color, - tc.x(), tc.y(), 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f}; - - tc = trect.at(2); - vertex v3 = { {x2, y2, zval} , color, - tc.x(), tc.y(), 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f};; - - tc = trect.at(3); - vertex v4 = { {x1, y2, zval} , color, - tc.x(), tc.y(), 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f}; - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - for (int i=m_index; i<(m_index + 4); ++i) { - if ((m_index + 4) > QT_VERTEX_BUF_SIZE) - qDebug() << "Vertex Buffer: Buffer overflow"; - if (accesscontrol[i] != CLEAR) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[i] |= WRITE; - } -#endif - - m_vbuff[m_index++] = v1; - m_vbuff[m_index++] = v2; - m_vbuff[m_index++] = v3; - m_vbuff[m_index++] = v4; - - m_startindex = m_index; -} - - -QD3DMaskPosition QD3DDrawHelper::allocateMaskPosition(const QRectF &brect, bool *breakbatch) -{ - int w = brect.width(); - int h = brect.height(); - - w += 3; - h += 3; - - if (w > m_width) - w = m_width; - if (h > m_height) - h = m_height; - - *breakbatch = false; - - if ((m_height - m_mask_offsetY2) >= h && (m_width - m_mask_position.x) >= w) { - m_mask_position.y = m_mask_offsetY2; - } else if ((m_width - m_mask_offsetX2) >= w) { - m_mask_position.y = QD3D_MASK_MARGIN; - m_mask_position.x = m_mask_offsetX2; - } else if (m_mask_position.channel < 3) { - ++m_mask_position.channel; - m_mask_position.x = m_mask_position.y = QD3D_MASK_MARGIN; - m_mask_offsetX2 = m_mask_offsetY2 = QD3D_MASK_MARGIN; - } else { - resetMask(); - *breakbatch = true; - } - - int newoffset = m_mask_position.x + w; - if (m_mask_offsetX2 < newoffset) - m_mask_offsetX2 = newoffset; - m_mask_offsetY2 = (m_mask_position.y + h); - - return m_mask_position; - -} - -void QD3DDrawHelper::queueRect(const QRectF &rect, QD3DBatchItem *item, D3DCOLOR color) -{ - lockVertexBuffer(); - - QRectF brect; - item->m_info |= QD3DBatchItem::BI_BRECT; - qreal zval = (item->m_info & QD3DBatchItem::BI_CLIP) ? 0.0f : 0.5f; - - if (item->m_info & QD3DBatchItem::BI_AA) { - int xoffset = item->m_maskpos.x; - int yoffset = item->m_maskpos.y; - - int x = rect.left(); - int y = rect.top(); - - brect = QRectF(x, y, rect.width() + 1, rect.height() + 1); - - item->m_xoffset = (xoffset - x) + 1; - item->m_yoffset = (yoffset - y) + 1; - - // if the item does not have a mask, the offset is different - if (!(item->m_info & QD3DBatchItem::BI_MASK)) { - item->m_offset = m_index; - item->m_count = 0; - } - } else { - brect = rect; - - if (!(item->m_info & QD3DBatchItem::BI_MASK)) { - item->m_offset = m_index; - item->m_count = -2; - } - } - - qreal left = brect.left(); - qreal right = brect.right(); - qreal top = brect.top(); - qreal bottom = brect.bottom(); - - vertex v1 = { {left, bottom, zval}, color, - 0.f, 0.f, 0.f, 0.f, - 0.f, 0.f, 0.f, 0.f}; - vertex v2 = { {left, top, zval}, color, - 0.f, 0.f, 0.f, 0.f, - 0.f, 0.f, 0.f, 0.f}; - vertex v3 = { {right, top, zval}, color, - 0.f, 0.f, 0.f, 0.f, - 0.f, 0.f, 0.f, 0.f}; - vertex v4 = { {right, bottom, zval}, color, - 0.f, 0.f, 0.f, 0.f, - 0.f, 0.f, 0.f, 0.f}; - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - for (int i=m_index; i<(m_index + 4); ++i) { - if ((m_index + 4) > QT_VERTEX_BUF_SIZE) - qDebug() << "Vertex Buffer: Buffer overflow"; - if (accesscontrol[i] != CLEAR) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[i] |= WRITE; - } -#endif - - m_vbuff[m_index++] = v1; - m_vbuff[m_index++] = v2; - m_vbuff[m_index++] = v3; - m_vbuff[m_index++] = v4; - - m_startindex = m_index; -} - -void QD3DDrawHelper::queueAntialiasedLines(const QPainterPath &path, QD3DBatchItem **item, const QRectF &brect) -{ - lockVertexBuffer(); - - m_item = *item; - m_item->m_info |= QD3DBatchItem::BI_MASK; - setWinding(m_item->m_info & QD3DBatchItem::BI_WINDING); - - int xoffset = m_item->m_maskpos.x; - int yoffset = m_item->m_maskpos.y; - int x = brect.left(); - int y = brect.top(); - - m_item->m_xoffset = (xoffset - x) + 1; - m_item->m_yoffset = (yoffset - y) + 1; - - m_boundingRect = brect; - - m_xoffset = (x - xoffset) + 0.5f; - m_yoffset = (y - yoffset) + 0.5f; - - QPointF last; - for (int i = 0; i < path.elementCount(); ++i) { - QPainterPath::Element element = path.elementAt(i); - - //Q_ASSERT(!element.isCurveTo()); - - if (element.isLineTo()) - QTessellator::tessellateRect(last, element, m_item->m_width); - - last = element; - } - - m_item->m_offset = m_startindex; - m_item->m_count = ( m_index - m_startindex ) / 3; - m_startindex = m_index; - - *item = m_item; -} - -void QD3DDrawHelper::queueAliasedLines(const QLineF *lines, int lineCount, QD3DBatchItem **item) -{ - lockVertexBuffer(); - - m_item = *item; - m_item->m_info |= QD3DBatchItem::BI_FASTLINE; - - for (int i=0; i<lineCount; ++i) { - const QLineF line = lines[i]; - qreal p1x = line.p1().x(); - qreal p1y = line.p1().y(); - qreal p2x = line.p2().x(); - qreal p2y = line.p2().y(); - - vertex v1 = { {p1x, p1y, m_pe->m_pen_width} , m_pe->m_pen_color, - -1.f, -1.f, p2x, p2y, - 0.f, 0.f, 0.f, 0.f }; - vertex v2 = { {p1x, p1y, m_pe->m_pen_width} , m_pe->m_pen_color, - 1.f, -1.f, p2x, p2y, - 0.f, 0.f, 0.f, 0.f }; - vertex v3 = { {p1x, p1y, m_pe->m_pen_width} , m_pe->m_pen_color, - 1.f, 1.f, p2x, p2y, - 0.f, 0.f, 0.f, 0.f }; - vertex v4 = { {p1x, p1y, m_pe->m_pen_width} , m_pe->m_pen_color, - -1.f, 1.f, p2x, p2y, - 0.f, 0.f, 0.f, 0.f }; - - m_vbuff[m_index++] = v1; - m_vbuff[m_index++] = v2; - m_vbuff[m_index++] = v4; - m_vbuff[m_index++] = v4; - m_vbuff[m_index++] = v2; - m_vbuff[m_index++] = v3; - - if (m_index >= (QT_VERTEX_BUF_SIZE - 16)) { - m_item->m_offset = m_startindex; - m_item->m_count = ( m_index - m_startindex ) / 2; - m_startindex = m_index; - - QD3DBatchItem itemcopy = *m_item; - m_item = m_pe->nextBatchItem(); - *m_item = itemcopy; - - lockVertexBuffer(); - } - } - - m_item->m_offset = m_startindex; - m_item->m_count = ( m_index - m_startindex ) - 2; - m_startindex = m_index; - - *item = m_item; -} - -void QD3DDrawHelper::queueTextGlyph(const QRectF &rect, const qreal *tex_coords, - QD3DBatchItem *item, D3DCOLOR color) -{ - lockVertexBuffer(); - - qreal x1 = rect.left(); - qreal y1 = rect.top(); - qreal x2 = rect.right(); - qreal y2 = rect.bottom(); - - vertex v1 = { {x1, y1, 0.5f}, color, - tex_coords[0], tex_coords[1], 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f}; - vertex v2 = { {x2, y1, 0.5f}, color, - tex_coords[2], tex_coords[1], 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f}; - vertex v3 = { {x2, y2, 0.5f}, color, - tex_coords[2], tex_coords[3], 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f}; - vertex v4 = { {x1, y1, 0.5f}, color, - tex_coords[0], tex_coords[1], 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f}; - vertex v5 = { {x2, y2, 0.5f}, color, - tex_coords[2], tex_coords[3], 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f}; - vertex v6 = { {x1, y2, 0.5f}, color, - tex_coords[0], tex_coords[3], 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f}; - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - for (int i=m_index; i<(m_index + 6); ++i) { - if ((m_index + 6) > QT_VERTEX_BUF_SIZE) - qDebug() << "Vertex Buffer: Buffer overflow"; - if (accesscontrol[i] != CLEAR) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[i] |= WRITE; - } -#endif - - m_vbuff[m_index++] = v1; - m_vbuff[m_index++] = v2; - m_vbuff[m_index++] = v3; - m_vbuff[m_index++] = v4; - m_vbuff[m_index++] = v5; - m_vbuff[m_index++] = v6; - - m_startindex = m_index; - ++item->m_count; -} - -bool QD3DDrawHelper::needsFlushing() const -{ - return (m_pe->m_batch.m_item_index >= QD3D_BATCH_SIZE || m_startindex >= QT_VERTEX_RESET_LIMIT); -} - -void QD3DDrawHelper::setMaskSize(QSize size) -{ - m_width = size.width(); - m_height = size.height(); - - if (m_maskSurface) - m_maskSurface->Release(); - - if (m_mask) - m_mask->Release(); - - if (FAILED(m_pe->m_d3d_device->CreateTexture(m_width, m_height, 1, D3DUSAGE_RENDERTARGET, - D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_mask, NULL))) { - qWarning() << "QDirect3DPaintEngine: CreateTexture() failed."; - } - - if (m_depthStencilSurface) - m_depthStencilSurface->Release(); - - if (FAILED(m_pe->m_d3d_device->CreateDepthStencilSurface(m_width, m_height, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, - TRUE, &m_depthStencilSurface, NULL))) { - qWarning() << "QDirect3DPaintEngine: CreateDepthStencilSurface() failed."; - } - - m_pe->m_d3d_device->SetDepthStencilSurface(m_depthStencilSurface); - m_pe->m_d3d_device->Clear(0, 0, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0, 0.0f, 0); - - if (FAILED(m_mask->GetSurfaceLevel(0, &m_maskSurface))) { - qWarning() << "QDirect3DPaintEngine: GetSurfaceLevel() failed."; - } - - m_pe->m_d3d_device->ColorFill(m_maskSurface, 0, D3DCOLOR_ARGB(0,0,0,0)); - D3DXMATRIX projMatrix; - pD3DXMatrixOrthoOffCenterLH(&projMatrix, 0, m_width, m_height, 0, 0, 1); - m_pe->m_effect->SetMatrix("g_mMaskProjection", &projMatrix); - m_pe->m_effect->SetTexture("g_mAAMask", m_mask); -} - -void QD3DDrawHelper::beforeReset() -{ - resetMask(); - m_clearmask = true; - - if (m_maskSurface) { - m_maskSurface->Release(); - m_maskSurface = 0; - } - - if (m_mask) { - m_mask->Release(); - m_mask = 0; - } - - if (m_depthStencilSurface) { - m_depthStencilSurface->Release(); - m_depthStencilSurface = 0; - } - - if (m_d3dvbuff) - m_d3dvbuff->Release(); -} - -void QD3DDrawHelper::afterReset() -{ - if (FAILED(m_pe->m_d3d_device->CreateVertexBuffer(QT_VERTEX_BUF_SIZE*sizeof(vertex), D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, - QD3DFVF_CSVERTEX, - D3DPOOL_DEFAULT, &m_d3dvbuff, NULL))) { - qWarning() << "QDirect3DPaintEngine: failed to create vertex buffer."; - } - - m_pe->m_d3d_device->SetStreamSource(0, m_d3dvbuff, 0, sizeof(vertex)); - m_pe->m_d3d_device->SetFVF(QD3DFVF_CSVERTEX); - - m_startindex = 0; - m_index = 0; -} - -IDirect3DSurface9 *QD3DDrawHelper::freeMaskSurface() -{ - // we need to make sure the mask is cleared when it's used for something else - resetMask(); - m_clearmask = true; - - return m_maskSurface; -} - -int QD3DDrawHelper::drawAntialiasedMask(int offset, int maxoffset) -{ - int newoffset = offset; - QD3DBatchItem *item = &(m_pe->m_batch.items[offset]); - - // set mask as render target - if (FAILED(m_pe->m_d3d_device->SetRenderTarget(0, m_maskSurface))) - qWarning() << "QDirect3DPaintEngine: SetRenderTarget failed!"; - - if (m_clearmask) { - m_pe->m_d3d_device->Clear(0, 0, D3DCLEAR_TARGET,D3DCOLOR_ARGB(0,0,0,0), 0, 0); - m_clearmask = false; - } - - // fill the mask - m_pe->m_statemanager->beginPass(PASS_AA_CREATEMASK); - for (; newoffset<maxoffset; ++newoffset) { - item = &(m_pe->m_batch.items[newoffset]); - if (!(item->m_info & QD3DBatchItem::BI_AA) || !(item->m_info & QD3DBatchItem::BI_MASK)) { - break; - } else if (item->m_info & QD3DBatchItem::BI_MASKFULL) { - item->m_info &= ~QD3DBatchItem::BI_MASKFULL; - m_clearmask = true; - break; - } - - m_pe->m_statemanager->startStateBlock(); - if (item->m_info & QD3DBatchItem::BI_MASKSCISSOR) { - RECT rect; - QRectF srect = item->m_brect.adjusted(item->m_xoffset, item->m_yoffset, - item->m_xoffset, item->m_yoffset); - rect.left = qMax(qRound(srect.left()), 0); - rect.top = qMax(qRound(srect.top()), 0); - rect.bottom = qMin(m_height, qRound(srect.bottom())); - rect.right = qMin(m_width, qRound(srect.right())); - m_pe->m_d3d_device->SetScissorRect(&rect); - m_pe->m_statemanager->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); - } - m_pe->m_statemanager->setMaskChannel(item->m_maskpos.channel); - m_pe->m_statemanager->endStateBlock(); - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - int vbstart = item->m_offset; - for (int i=vbstart; i<(vbstart + (item->m_count * 3)); ++i) { - if (accesscontrol[i] != WRITE) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[i] |= READ; - } -#endif - - m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLELIST, item->m_offset, item->m_count); - - if (item->m_info & QD3DBatchItem::BI_MASKSCISSOR) { - m_pe->m_statemanager->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); - } - } - m_pe->m_statemanager->endPass(); - - return newoffset; -} - -void QD3DDrawHelper::drawAliasedMask(int offset) -{ - QD3DBatchItem *item = &(m_pe->m_batch.items[offset]); - if (item->m_info & QD3DBatchItem::BI_MASK) { - m_pe->m_statemanager->beginPass( (item->m_info & QD3DBatchItem::BI_WINDING) ? PASS_STENCIL_WINDING : PASS_STENCIL_ODDEVEN ); - int prev_stop = 0; - for (int i=0; i<item->m_pointstops.count(); ++i) { - int stop = item->m_pointstops.at(i); - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - int vbstart = (item->m_offset + prev_stop); - for (int j=vbstart; j<(vbstart+(stop - prev_stop)); ++j) { - if (accesscontrol[j] != WRITE) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[j] |= READ; - } -#endif - m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLEFAN, item->m_offset + prev_stop, (stop - prev_stop) - 2); - prev_stop = stop; - } - m_pe->m_statemanager->endPass(); - } -} - -void QD3DDrawHelper::drawTextItem(QD3DBatchItem *item) -{ -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - int vbstart = item->m_offset; - for (int j=vbstart; j<(vbstart + ((item->m_count * 2) * 3)); ++j) { - if (accesscontrol[j] != WRITE) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[j] |= READ; - } -#endif - m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLELIST, item->m_offset, item->m_count*2); -} - -void QD3DDrawHelper::drawAliasedLines(QD3DBatchItem *item) -{ - m_pe->m_statemanager->setCosmeticPen(item->m_info & QD3DBatchItem::BI_COSMETICPEN); - if (item->m_info & QD3DBatchItem::BI_TRANSFORM) { - m_pe->m_statemanager->setTransformation(&item->m_matrix); - } else { - m_pe->m_statemanager->setTransformation(); - } - int pass = (item->m_info & QD3DBatchItem::BI_MASK) - ? PASS_ALIASED_LINES - : PASS_ALIASED_LINES_DIRECT; - m_pe->m_statemanager->beginPass(pass); - m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLELIST, item->m_offset, (item->m_count + 2) / 3); - m_pe->m_statemanager->endPass(); -} - -void QD3DDrawHelper::drawAntialiasedBoundingRect(QD3DBatchItem *item) -{ - if (item->m_info & QD3DBatchItem::BI_SCISSOR) { - RECT rect; - rect.left = qMax(qRound(item->m_brect.left()), 0); - rect.top = qMax(qRound(item->m_brect.top()), 0); - rect.bottom = qMin(m_height, qRound(item->m_brect.bottom())); - rect.right = qMin(m_width, qRound(item->m_brect.right())); - m_pe->m_d3d_device->SetScissorRect(&rect); - m_pe->m_statemanager->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); - } - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - int vbstart = item->m_offset + (item->m_count * 3); - for (int j=vbstart; j<(vbstart + 4); ++j) { - if (accesscontrol[j] != WRITE) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[j] |= READ; - } -#endif - - m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLEFAN, item->m_offset + (item->m_count * 3), 2); - - if (item->m_info & QD3DBatchItem::BI_SCISSOR) { - m_pe->m_statemanager->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); - } -} - -void QD3DDrawHelper::drawAliasedBoundingRect(QD3DBatchItem *item) -{ -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - int vbstart = (item->m_offset + item->m_count + 2); - for (int j=vbstart; j<(vbstart + 4); ++j) { - if (accesscontrol[j] != WRITE) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[j] |= READ; - } -#endif - - m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLEFAN, item->m_offset + item->m_count + 2, 2); -} - -void QD3DDrawHelper::addTrap(const Trapezoid &trap) -{ - qreal topLeftY = Q27Dot5ToDouble(trap.topLeft->y) - m_yoffset; - qreal topLeftX = Q27Dot5ToDouble(trap.topLeft->x) - m_xoffset; - qreal topRightY = Q27Dot5ToDouble(trap.topRight->y) - m_yoffset; - qreal topRightX = Q27Dot5ToDouble(trap.topRight->x) - m_xoffset; - qreal top = Q27Dot5ToDouble(trap.top) - m_yoffset; - qreal bottom = Q27Dot5ToDouble(trap.bottom) - m_yoffset; - - Q27Dot5 _h = trap.topLeft->y - trap.bottomLeft->y; - Q27Dot5 _w = trap.topLeft->x - trap.bottomLeft->x; - qreal _leftA = (qreal)_w/_h; - qreal _leftB = topLeftX - _leftA * topLeftY; - - _h = trap.topRight->y - trap.bottomRight->y; - _w = trap.topRight->x - trap.bottomRight->x; - qreal _rightA = (qreal)_w/_h; - qreal _rightB = topRightX - _rightA * topRightY; - - qreal invLeftA = qFuzzyCompare(_leftA + 1, 1) ? 0.0 : 1.0 / _leftA; - qreal invRightA = qFuzzyCompare(_rightA + 1, 1) ? 0.0 : 1.0 / _rightA; - - vertex v1 = { {1.f, top - 1.f, 0.5f}, 0.f, - top, bottom, invLeftA, -invRightA, - _leftA, _leftB, _rightA, _rightB}; - vertex v2 = { {0.f, top - 1.f, 0.5f}, 0.f, - top, bottom, invLeftA, -invRightA, - _leftA, _leftB, _rightA, _rightB}; - vertex v3 = { {0.f, bottom + 1.f, 0.5f}, 0.f, - top, bottom, invLeftA, -invRightA, - _leftA, _leftB, _rightA, _rightB}; - - vertex v4 = { {1.f, top - 1.f, 0.5f}, 0.f, - top, bottom, invLeftA, -invRightA, - _leftA, _leftB, _rightA, _rightB}; - vertex v5 = { {0.f, bottom + 1.f, 0.5f}, 0.f, - top, bottom, invLeftA, -invRightA, - _leftA, _leftB, _rightA, _rightB}; - vertex v6 = { {1.f, bottom + 1.f, 0.5f}, 0.f, - top, bottom, invLeftA, -invRightA, - _leftA, _leftB, _rightA, _rightB}; - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - for (int i=m_index; i<(m_index + 6); ++i) { - if ((m_index + 6) > QT_VERTEX_BUF_SIZE) - qDebug() << "Vertex Buffer: Buffer overflow"; - if (accesscontrol[i] != CLEAR) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[i] |= WRITE; - } -#endif - - m_vbuff[m_index++] = v1; - m_vbuff[m_index++] = v2; - m_vbuff[m_index++] = v3; - m_vbuff[m_index++] = v4; - m_vbuff[m_index++] = v5; - m_vbuff[m_index++] = v6; - - // check if buffer is full - if (m_index >= (QT_VERTEX_BUF_SIZE - 16)) { - m_item->m_offset = m_startindex; - m_item->m_count = ( m_index - m_startindex ) / 3; - m_startindex = m_index; - - QD3DBatchItem itemcopy = *m_item; - m_item = m_pe->nextBatchItem(); - *m_item = itemcopy; - m_item->m_info &= ~QD3DBatchItem::BI_MASKFULL; - - lockVertexBuffer(); - } -} - -void QD3DDrawHelper::tessellate(const QPolygonF &poly) { - int xoffset = m_item->m_maskpos.x; - int yoffset = m_item->m_maskpos.y; - - int x = m_boundingRect.left(); - int y = m_boundingRect.top(); - m_xoffset = (x - xoffset) + 0.5f; - m_yoffset = (y - yoffset) + 0.5f; - - QTessellator::tessellate(poly.data(), poly.count()); - - m_item->m_offset = m_startindex; - m_item->m_count = ( m_index - m_startindex ) / 3; - m_startindex = m_index; -} - -inline void QD3DDrawHelper::lineToStencil(qreal x, qreal y) -{ - QPointF lastPt = tess_lastpoint; - tess_lastpoint = QPointF(x, y); - - if (m_isLine && m_firstPoint) - return; - - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - if (m_index > QT_VERTEX_BUF_SIZE) - qDebug() << "Vertex Buffer: Buffer overflow"; - if (accesscontrol[m_index] != CLEAR) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[m_index] |= WRITE; -#endif - - vertex v; - if (m_isLine) { - vertex v1 = { {lastPt.x(), lastPt.y(), m_pe->m_pen_width }, m_color, - -1.f, -1.f, x, y, - 0.f, 0.f, 0.f, 0.f}; - vertex v2 = { {lastPt.x(), lastPt.y(), m_pe->m_pen_width }, m_color, - 1.f, -1.f, x, y, - 0.f, 0.f, 0.f, 0.f}; - vertex v3 = { {lastPt.x(), lastPt.y(), m_pe->m_pen_width }, m_color, - 1.f, 1.f, x, y, - 0.f, 0.f, 0.f, 0.f}; - vertex v4 = { {lastPt.x(), lastPt.y(), m_pe->m_pen_width }, m_color, - -1.f, 1.f, x, y, - 0.f, 0.f, 0.f, 0.f}; - m_vbuff[m_index++] = v1; - m_vbuff[m_index++] = v2; - m_vbuff[m_index++] = v4; - m_vbuff[m_index++] = v4; - m_vbuff[m_index++] = v2; - m_vbuff[m_index++] = v3; - } else { - vertex v1 = { {x, y, 0.5f}, m_color, - 0.f, 0.f, 0.f, 0.f, - 0.f, 0.f, 0.f, 0.f}; - m_vbuff[m_index++] = v1; - v = v1; - } - ++tess_index; - - // check if buffer is full - if (m_index >= (QT_VERTEX_BUF_SIZE - 16)) { - int firstindex = m_startindex; - if (!m_item->m_pointstops.isEmpty()) - firstindex = m_item->m_pointstops.last(); - - vertex first = m_vbuff[firstindex]; - - // finish current polygon - m_item->m_pointstops.append(tess_index); - m_item->m_offset = m_startindex; - m_startindex = m_index; - - // copy item - QD3DBatchItem itemcopy = *m_item; - m_item = m_pe->nextBatchItem(); - *m_item = itemcopy; - - // start new polygon - lockVertexBuffer(); - m_item->m_pointstops.clear(); - if (!m_isLine) { - tess_index = 2; - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - if (accesscontrol[m_index] != CLEAR) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[m_index] |= WRITE; -#endif - - m_vbuff[m_index++] = first; - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - if (accesscontrol[m_index] != CLEAR) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[m_index] |= WRITE; -#endif - - m_vbuff[m_index++] = v; - } else { - tess_index = 0; - } - } - - if (x > max_x) - max_x = x; - else if (x < min_x) - min_x = x; - if (y > max_y) - max_y = y; - else if (y < min_y) - min_y = y; -} - -inline void QD3DDrawHelper::curveToStencil(const QPointF &cp1, const QPointF &cp2, - const QPointF &ep) -{ - qreal inverseScale = 0.5f; - qreal inverseScaleHalf = inverseScale / 2; - - QBezier beziers[32]; - beziers[0] = QBezier::fromPoints(tess_lastpoint, cp1, cp2, ep); - QBezier *b = beziers; - while (b >= beziers) { - // check if we can pop the top bezier curve from the stack - qreal l = qAbs(b->x4 - b->x1) + qAbs(b->y4 - b->y1); - qreal d; - if (l > inverseScale) { - d = qAbs( (b->x4 - b->x1)*(b->y1 - b->y2) - (b->y4 - b->y1)*(b->x1 - b->x2) ) - + qAbs( (b->x4 - b->x1)*(b->y1 - b->y3) - (b->y4 - b->y1)*(b->x1 - b->x3) ); - d /= l; - } else { - d = qAbs(b->x1 - b->x2) + qAbs(b->y1 - b->y2) + - qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3); - } - if (d < inverseScaleHalf || b == beziers + 31) { - // good enough, we pop it off and add the endpoint - lineToStencil(b->x4, b->y4); - --b; - } else { - // split, second half of the polygon goes lower into the stack - b->split(b+1, b); - ++b; - } - } -} - -QRectF QD3DDrawHelper::pathToVertexArrays(const QPainterPath &path) -{ - m_isLine = (m_item->m_info & QD3DBatchItem::BI_FASTLINE); - const QPainterPath::Element &first = path.elementAt(0); - firstx = first.x; - firsty = first.y; - min_x = max_x = firstx; - min_y = max_y = firsty; - - m_firstPoint = true; - tess_index = 0; - m_item->m_pointstops.clear(); - lineToStencil(firstx, firsty); - m_firstPoint = false; - - for (int i=1; i<path.elementCount(); ++i) { - const QPainterPath::Element &e = path.elementAt(i); - switch (e.type) { - case QPainterPath::MoveToElement: - m_item->m_pointstops.append(tess_index); - m_firstPoint = true; - lineToStencil(e.x, e.y); - m_firstPoint = false; - break; - case QPainterPath::LineToElement: - lineToStencil(e.x, e.y); - break; - case QPainterPath::CurveToElement: - curveToStencil(e, path.elementAt(i+1), path.elementAt(i+2)); - i+=2; - break; - default: - break; - } - } - - if (!m_isLine) - lineToStencil(firstx, firsty); - - m_item->m_pointstops.append(tess_index); - - m_item->m_offset = m_startindex; - m_item->m_count = ( m_index - m_startindex ) - 2; - m_startindex = m_index; - - QRectF result; - result.setLeft(min_x); - result.setRight(max_x); - result.setTop(min_y); - result.setBottom(max_y); - - if (m_isLine) - result.adjust(0,0,1,1); - - return result; -} - -void QD3DDrawHelper::resetMask() -{ - m_mask_position.x = m_mask_position.y = QD3D_MASK_MARGIN; - m_mask_position.channel = 0; - m_mask_offsetX2 = m_mask_offsetY2 = QD3D_MASK_MARGIN; -} - - -static inline QPainterPath strokeForPath(const QPainterPath &path, const QPen &cpen) { - QPainterPathStroker stroker; - if (cpen.style() == Qt::CustomDashLine) - stroker.setDashPattern(cpen.dashPattern()); - else - stroker.setDashPattern(cpen.style()); - - stroker.setCapStyle(cpen.capStyle()); - stroker.setJoinStyle(cpen.joinStyle()); - stroker.setMiterLimit(cpen.miterLimit()); - stroker.setWidth(cpen.widthF()); - - QPainterPath stroke = stroker.createStroke(path); - stroke.setFillRule(Qt::WindingFill); - return stroke; -} - - -QDirect3DPaintEnginePrivate::~QDirect3DPaintEnginePrivate() -{ - -} - -void QDirect3DPaintEnginePrivate::updateClipPath(const QPainterPath &path, Qt::ClipOperation op) -{ - //#### remove me - QRegion r(path.toFillPolygon().toPolygon(), path.fillRule()); - updateClipRegion(r, op); - -/* if (m_draw_helper->needsFlushing()) - flushBatch(); - - if (op == Qt::IntersectClip && !has_clipping) - op = Qt::ReplaceClip; - - // switch to paths - if (!m_has_complex_clipping) { - m_clip_path = QPainterPath(); - m_clip_path.addRegion(m_clip_region); - m_clip_region = QRegion(); - m_sysclip_path = QPainterPath(); - m_sysclip_path.addRegion(m_sysclip_region); - m_sysclip_region = QRegion(); - m_has_complex_clipping = true; - } - - QPainterPath cpath = m_matrix.map(path); - - QD3DBatchItem *item = &m_batch.items[m_batch.m_item_index++]; - item->m_info = QD3DBatchItem::BI_COMPLEXCLIP; - - switch (op) { - case Qt::UniteClip: - has_clipping = true; - m_clip_path = m_clip_path.united(cpath); - break; - case Qt::ReplaceClip: - has_clipping = true; - m_clip_path = cpath; - break; - case Qt::NoClip: - m_has_complex_clipping = false; - has_clipping = false; - item->m_info |= QD3DBatchItem::BI_CLEARCLIP; - break; - default: // intersect clip - has_clipping = true; - m_clip_path = m_clip_path.intersected(cpath); - break; - } - - if (!m_sysclip_path.isEmpty()) { - item->m_info &= ~QD3DBatchItem::BI_CLEARCLIP; - if (has_clipping) - m_clip_path = m_clip_path.intersected(m_sysclip_path); - else - m_clip_path = m_sysclip_path; - } - - // update the aliased clipping mask - m_draw_helper->setClipPath(m_clip_path, item); - - // update the antialiased clipping mask - if (m_draw_helper->needsFlushing()) - flushBatch(); - - QD3DBatchItem *aaitem = &m_batch.items[m_batch.m_item_index++]; - aaitem->m_info = item->m_info|QD3DBatchItem::BI_AA; - m_draw_helper->setClipPath(m_clip_path, aaitem); */ -} - -extern QPainterPath qt_regionToPath(const QRegion ®ion); - -void QDirect3DPaintEnginePrivate::updateClipRegion(const QRegion &clipregion, Qt::ClipOperation op) -{ - if (m_draw_helper->needsFlushing()) - flushBatch(); - if (m_has_complex_clipping) { - QPainterPath path = qt_regionToPath(clipregion); - updateClipPath(path, op); - return; - } - - if (op == Qt::IntersectClip && m_clip_region.isEmpty()) - op = Qt::ReplaceClip; - - QRegion cregion = m_matrix.map(clipregion); - - QD3DBatchItem *item = nextBatchItem(); - item->m_info &= ~QD3DBatchItem::BI_AA; - - switch (op) { - case Qt::UniteClip: - m_clip_region = m_clip_region.united(cregion); - break; - case Qt::ReplaceClip: - m_clip_region = cregion; - break; - case Qt::NoClip: - m_clip_region = QRegion(); - item->m_info |= QD3DBatchItem::BI_CLEARCLIP; - break; - default: // intersect clip - m_clip_region = m_clip_region.intersected(cregion); - break; - } - - QRegion crgn = m_clip_region; - if (!m_sysclip_region.isEmpty()) { - item->m_info &= ~QD3DBatchItem::BI_CLEARCLIP; - if (!crgn.isEmpty()) - crgn = crgn.intersected(m_sysclip_region); - else - crgn = m_sysclip_region; - } - - QPainterPath path = qt_regionToPath(crgn); - m_draw_helper->setClipPath(path, &item); -} - -void QDirect3DPaintEnginePrivate::updateFont(const QFont &) -{ -} - -void QDirect3DPaintEnginePrivate::setRenderTechnique(RenderTechnique technique) -{ - if (m_current_technique != technique) { - if (m_current_technique != RT_NoTechnique) - m_effect->End(); - - if (technique == RT_Aliased) { - m_effect->SetTechnique("Aliased"); - m_effect->Begin(0,D3DXFX_DONOTSAVESTATE); - } else if (technique == RT_Antialiased) { - m_effect->SetTechnique("Antialiased"); - m_effect->Begin(0,D3DXFX_DONOTSAVESTATE); - } - } - - m_current_technique = technique; -} - -/*QPolygonF QDirect3DPaintEnginePrivate::transformedRect(const QRectF &brect) const -{ - QPolygonF poly(brect); - return m_matrix.map(poly); -} - -QPolygonF QDirect3DPaintEnginePrivate::calcTextureCoords(const QPolygonF &trect) const -{ - QPolygonF result(4); - QRectF brect = trect.boundingRect(); - qreal angle = atan(trect.at(0).x() - -} - -QPolygonF QDirect3DPaintEnginePrivate::offsetTextureCoords(const QRectF &brect, const QPolygonF &trect) const -{ - -}*/ - -inline QD3DBatchItem *QDirect3DPaintEnginePrivate::nextBatchItem() -{ - if (m_draw_helper->needsFlushing()) - flushBatch(); - - QD3DBatchItem *item = &m_batch.items[m_batch.m_item_index++]; - item->m_info = m_current_state; - item->m_cmode = m_cmode; - return item; -} - -qreal calculateAngle(qreal dx, qreal dy) -{ - qreal angle; - - if (qFuzzyCompare(dx + 1, 1)) { - angle = (dy < 0) ? -M_PI/2 : M_PI/2; - } else { - angle = atanf(dy/dx); - if (dx < 0) - angle += M_PI; - } - - return angle; -} - -QPolygonF QDirect3DPaintEnginePrivate::brushCoordinates(const QRectF &r, bool stroke, qreal *fd) const -{ - QBrush brush; - QTransform matrix; - Qt::BrushStyle style; - - if (stroke) { - brush = m_pen.brush(); - matrix = m_inv_pen_matrix; - style = m_pen_brush_style; - } else { - brush = m_brush; - matrix = m_inv_brush_matrix; - style = m_brush_style; - } - - QPolygonF bpoly; - switch(style) { - case Qt::TexturePattern: { - QTransform totxcoords; - QRectF adj_brect = r.adjusted(-0.5f, -0.5f, -0.5f, -0.5f); - totxcoords.scale(1.0f/brush.texture().width(), - 1.0f/brush.texture().height()); - bpoly = matrix.map(QPolygonF(adj_brect)); - bpoly = totxcoords.map(bpoly); - break; } - case Qt::LinearGradientPattern: { - const QLinearGradient *g = static_cast<const QLinearGradient *>(brush.gradient()); - QPointF start = g->start(); - QPointF stop = g->finalStop(); - qreal dx = stop.x() - start.x(); - qreal dy = stop.y() - start.y(); - qreal length = sqrt(dx * dx + dy * dy); - qreal angle = calculateAngle(dx, dy); - QTransform totxcoords; - QRectF adj_brect = r.adjusted(-0.5f, -0.5f, -0.5f, -0.5f); - totxcoords.scale(1.0f/length, 1.0f/length); - totxcoords.rotateRadians(-angle); - totxcoords.translate(-start.x(), -start.y()); - bpoly = matrix.map(QPolygonF(adj_brect)); - bpoly = totxcoords.map(bpoly); - break; } - case Qt::ConicalGradientPattern: { - const QConicalGradient *g = static_cast<const QConicalGradient *>(brush.gradient()); - QPointF center = g->center(); - qreal angle = g->angle(); - QTransform totxcoords; - totxcoords.rotate(angle); - totxcoords.translate(-center.x(), -center.y()); - bpoly = matrix.map(QPolygonF(r)); - bpoly = totxcoords.map(bpoly); - break; } - case Qt::RadialGradientPattern: { - const QRadialGradient *g = static_cast<const QRadialGradient *>(brush.gradient()); - QPointF center = g->center(); - QPointF focalpoint = g->focalPoint(); - qreal dx = focalpoint.x() - center.x(); - qreal dy = focalpoint.y() - center.y(); - qreal radius = g->radius(); - *fd = sqrt(dx * dx + dy * dy) / radius; - qreal angle = calculateAngle(dx, dy); - QTransform totxcoords; - totxcoords.scale(1.0f/radius, 1.0f/radius); - totxcoords.rotateRadians(-angle); - totxcoords.translate(-center.x(), -center.y()); - bpoly = matrix.map(QPolygonF(r)); - bpoly = totxcoords.map(bpoly); - break; } - default: { - QTransform totxcoords; - QRectF adj_brect = r.adjusted(-0.5f, -0.5f, -0.5f, -0.5f); - QPixmap pat = getPattern(style); - totxcoords.scale(1.0f/pat.width(), - 1.0f/pat.height()); - bpoly = matrix.map(QPolygonF(adj_brect)); - bpoly = totxcoords.map(bpoly); } - }; - - return bpoly; -} - -void QDirect3DPaintEnginePrivate::strokeAliasedPath(QPainterPath path, const QRectF &brect, const QTransform &txform) -{ - D3DCOLOR solid_color; - QD3DBatchItem *item = nextBatchItem(); - - if (!txform.isIdentity()) - path = txform.map(path); - - QRectF trect; - QPolygonF txcoord; - - solid_color = m_pen_color; - bool has_complex_brush = false; - if (m_pen_brush_style != Qt::SolidPattern) { - has_complex_brush = true; - item->m_brush = m_pen.brush(); - item->m_info |= QD3DBatchItem::BI_COMPLEXBRUSH; - item->m_opacity = m_opacity; - } - - if (m_has_fast_pen) { - item->m_info |= QD3DBatchItem::BI_FASTLINE; - if (m_pen_brush_style == Qt::SolidPattern) { - m_draw_helper->queueAliasedMask(path, &item, solid_color); - item->m_info &= ~QD3DBatchItem::BI_MASK; // bypass stencil buffer - return; - } - } - - QRectF txrect = m_draw_helper->queueAliasedMask(path, &item, 0); - - if (has_complex_brush) { - trect = brect; - txcoord = brushCoordinates(brect, true, &item->m_distance); - item->m_info |= QD3DBatchItem::BI_TRANSFORM; - item->m_matrix = m_matrix; - } else { - trect = txrect; - static const QPolygonF empty_poly(4); - txcoord = empty_poly; - } - - m_draw_helper->queueRect(trect, item, solid_color, txcoord); -} - -void QDirect3DPaintEnginePrivate::fillAliasedPath(QPainterPath path, const QRectF &brect, const QTransform &txform) -{ - D3DCOLOR solid_color; - QD3DBatchItem *item = nextBatchItem(); - - if (!txform.isIdentity()) - path = txform.map(path); - - QRectF trect; - QPolygonF txcoord; - - solid_color = m_brush_color; - bool has_complex_brush = false; - if (m_brush_style != Qt::SolidPattern) { - has_complex_brush = true; - item->m_brush = m_brush; - item->m_info |= QD3DBatchItem::BI_COMPLEXBRUSH; - item->m_opacity = m_opacity; - } - - QRectF txrect = m_draw_helper->queueAliasedMask(path, &item, 0); - - if (has_complex_brush) { - trect = brect; - txcoord = brushCoordinates(brect, false, &item->m_distance); - item->m_info |= QD3DBatchItem::BI_TRANSFORM; - item->m_matrix = m_matrix; - } else { - trect = txrect; - static const QPolygonF empty_poly(4); - txcoord = empty_poly; - } - - m_draw_helper->queueRect(trect, item, solid_color, txcoord); -} - -void QDirect3DPaintEnginePrivate::fillAntialiasedPath(const QPainterPath &path, const QRectF &brect, - const QTransform &txform, bool stroke) -{ - D3DCOLOR solid_color; - bool winding = (path.fillRule() == Qt::WindingFill); - QPolygonF poly; - QRectF txrect; - QPainterPath tpath; - - if (m_has_aa_fast_pen && stroke) { - tpath = txform.map(path); - txrect = tpath.controlPointRect(); - txrect.adjust(-(m_pen_width/2),-(m_pen_width/2), m_pen_width, m_pen_width); - } else { - poly = path.toFillPolygon(txform); - txrect = poly.boundingRect(); - } - - // brect = approx. bounding rect before transformation - // txrect = exact bounding rect after transformation - // trect = the rectangle to be drawn - // txcoord = the texture coordinates - // adj_txrect = adjusted rect to include aliased outline - - bool use_scissor = false; - if (txrect.left() < 0) { - txrect.adjust(-txrect.left(),0,0,0); - use_scissor = true; - } - if (txrect.top() < 0) { - txrect.adjust(0,-txrect.top(),0,0); - use_scissor = true; - } - - if (!txrect.isValid()) - return; - - QD3DBatchItem *item = nextBatchItem(); - - QRectF adj_txrect = txrect.adjusted(-1,-1,1,1); - QRectF trect; - QPolygonF txcoord; - - bool has_complex_brush = false; - if (stroke) { - solid_color = m_pen_color; - if (m_pen_brush_style != Qt::SolidPattern) { - has_complex_brush = true; - item->m_brush = m_pen.brush(); - } - item->m_width = m_pen_width; - } else { - solid_color = m_brush_color; - if (m_brush_style != Qt::SolidPattern) { - has_complex_brush = true; - item->m_brush = m_brush; - } - } - - qreal focaldist = 0; - if (has_complex_brush) { - trect = brect; - txcoord = brushCoordinates(brect, stroke, &focaldist); - } else { - trect = adj_txrect; - static const QPolygonF empty_poly(4); - txcoord = empty_poly; - } - - bool maskfull; - item->m_maskpos = m_draw_helper->allocateMaskPosition(txrect, &maskfull); - if (maskfull) - item->m_info |= QD3DBatchItem::BI_MASKFULL; - item->m_distance = focaldist; - - if (winding) - item->m_info |= QD3DBatchItem::BI_WINDING; - - if (has_complex_brush) { - item->m_info |= QD3DBatchItem::BI_SCISSOR|QD3DBatchItem::BI_COMPLEXBRUSH| - QD3DBatchItem::BI_TRANSFORM; - item->m_brect = adj_txrect; - item->m_matrix = m_matrix; - item->m_opacity = m_opacity; - } - if (use_scissor) { - item->m_info |= QD3DBatchItem::BI_MASKSCISSOR; - item->m_brect = adj_txrect; - } - - if (m_has_aa_fast_pen && stroke) { - m_draw_helper->queueAntialiasedLines(tpath, &item, txrect); - } else { - m_draw_helper->queueAntialiasedMask(poly, &item, txrect); - } - - m_draw_helper->queueRect(trect, item, solid_color, txcoord); -} - -QPainterPath QDirect3DPaintEnginePrivate::strokePathFastPen(const QPainterPath &path) -{ - QPainterPath result; - QBezier beziers[32]; - for (int i=0; i<path.elementCount(); ++i) { - const QPainterPath::Element &e = path.elementAt(i); - switch (e.type) { - case QPainterPath::MoveToElement: - result.moveTo(e.x, e.y); - break; - case QPainterPath::LineToElement: - result.lineTo(e.x, e.y); - break; - - case QPainterPath::CurveToElement: - { - QPointF sp = path.elementAt(i-1); - QPointF cp2 = path.elementAt(i+1); - QPointF ep = path.elementAt(i+2); - i+=2; - - qreal inverseScaleHalf = m_inv_scale / 2; - beziers[0] = QBezier::fromPoints(sp, e, cp2, ep); - QBezier *b = beziers; - while (b >= beziers) { - // check if we can pop the top bezier curve from the stack - qreal l = qAbs(b->x4 - b->x1) + qAbs(b->y4 - b->y1); - qreal d; - if (l > m_inv_scale) { - d = qAbs( (b->x4 - b->x1)*(b->y1 - b->y2) - - (b->y4 - b->y1)*(b->x1 - b->x2) ) - + qAbs( (b->x4 - b->x1)*(b->y1 - b->y3) - - (b->y4 - b->y1)*(b->x1 - b->x3) ); - d /= l; - } else { - d = qAbs(b->x1 - b->x2) + qAbs(b->y1 - b->y2) + - qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3); - } - if (d < inverseScaleHalf || b == beziers + 31) { - // good enough, we pop it off and add the endpoint - result.lineTo(b->x4, b->y4); - --b; - } else { - // split, second half of the polygon goes lower into the stack - b->split(b+1, b); - ++b; - } - } - } // case CurveToElement - default: - break; - } // end of switch - } - return result; -} - -void QDirect3DPaintEnginePrivate::strokePath(const QPainterPath &path, QRectF brect, bool simple) -{ - QTransform txform; - QPainterPath tpath; - - if (m_has_fast_pen || m_has_aa_fast_pen) { - if (!simple) - tpath = strokePathFastPen(path); - else - tpath = path; //already only lines - } else { - tpath = strokeForPath(path, m_pen); - } - - if (tpath.isEmpty()) - return; - - //brect is null if the path is not transformed - if (brect.isNull()) - txform = m_matrix; - - if (!brect.isNull()) { - // brect is set when the path is transformed already, - // this is the case when we have a cosmetic pen. - brect.adjust(-(m_pen_width/2),-(m_pen_width/2), m_pen_width, m_pen_width); - } - - if (brect.isNull()) - brect = tpath.controlPointRect(); - brect.adjust(-m_inv_scale,-m_inv_scale,m_inv_scale,m_inv_scale); //adjust for antialiasing - - if (m_current_state & QD3DBatchItem::BI_AA) { - fillAntialiasedPath(tpath, brect, txform, true); - } else { - strokeAliasedPath(tpath, brect, txform); - } -} - -void QDirect3DPaintEnginePrivate::fillPath(const QPainterPath &path, QRectF brect) -{ - QTransform txform; - - //brect is null if the path is not transformed - if (brect.isNull()) - txform = m_matrix; - - if (brect.isNull()) - brect = path.controlPointRect(); - brect.adjust(-m_inv_scale,-m_inv_scale,m_inv_scale,m_inv_scale); //adjust for antialiasing - - if (m_current_state & QD3DBatchItem::BI_AA) { - fillAntialiasedPath(path, brect, txform, false); - } else { - fillAliasedPath(path, brect, txform); - } -} - - -bool QDirect3DPaintEnginePrivate::init() -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEnginePrivate::init()"; -#endif - - m_draw_helper = 0; - m_gradient_cache = 0; - m_dc = 0; - m_dcsurface = 0; - - m_supports_d3d = false; - m_current_state = 0; - m_in_scene = false; - m_has_fast_pen = false; - m_has_aa_fast_pen = false; - m_has_pen = false; - m_has_brush = false; - m_pen_color = 0; - m_brush_color = 0; - m_current_surface = 0; - m_batch.m_item_index = 0; - m_current_technique = RT_NoTechnique; - - if (!pDirect3DCreate9) { - QLibrary d3d_lib(QLatin1String("d3d9.dll")); - pDirect3DCreate9 = (PFNDIRECT3DCREATE9) d3d_lib.resolve("Direct3DCreate9"); - if (!pDirect3DCreate9) { - qWarning("QDirect3DPaintEngine: failed to resolve symbols from d3d9.dll.\n" - "Make sure you have the DirectX run-time installed."); - return false; - } - } - - if (!pD3DXCreateBuffer || !pD3DXCreateEffect || !pD3DXMatrixOrthoOffCenterLH) { - QLibrary d3dx_lib(QLatin1String("d3dx9_32.dll")); - pD3DXCreateBuffer = (PFND3DXCREATEBUFFER) d3dx_lib.resolve("D3DXCreateBuffer"); - pD3DXCreateEffect = (PFND3DXCREATEEFFECT) d3dx_lib.resolve("D3DXCreateEffect"); - pD3DXMatrixOrthoOffCenterLH = (PFND3DXMATRIXORTHOOFFCENTERLH) - d3dx_lib.resolve("D3DXMatrixOrthoOffCenterLH"); - if (!(pD3DXCreateBuffer && pD3DXCreateEffect && pD3DXMatrixOrthoOffCenterLH)) { - qWarning("QDirect3DPaintEngine: failed to resolve symbols from d3dx9_32.dll.\n" - "Make sure you have the DirectX run-time installed."); - return false; - } - } - - if (!m_d3d_object) { - m_d3d_object = pDirect3DCreate9(D3D_SDK_VERSION); - if (!m_d3d_object) { - qWarning("QDirect3DPaintEngine: failed to create Direct3D object.\n" - "Direct3D support in Qt will be disabled."); - return false; - } - } - - m_supports_d3d = testCaps(); - if (!m_supports_d3d) - return false; - - m_surface_manager.init(m_d3d_object); - m_d3d_device = m_surface_manager.device(); - - if (!m_d3d_device) - return false; - - /* load shaders */ - QFile file(QLatin1String(":/qpaintengine_d3d.fx")); - QByteArray fxFile; - if (file.open(QFile::ReadOnly)) - fxFile = file.readAll(); - - if (fxFile.size() > 0) { - LPD3DXBUFFER compout; - pD3DXCreateBuffer(4096, &compout); - DWORD dwShaderFlags = D3DXFX_NOT_CLONEABLE|D3DXFX_DONOTSAVESTATE|D3DXSHADER_OPTIMIZATION_LEVEL3; - if(FAILED(pD3DXCreateEffect(m_d3d_device, fxFile.constData(), fxFile.size(), - NULL, NULL, dwShaderFlags, NULL, &m_effect, &compout))) { - qWarning("QDirect3DPaintEngine: failed to compile effect file"); - if (compout) - qWarning((char *)compout->GetBufferPointer()); - m_supports_d3d = false; - return false; - } - if (m_effect) { - m_statemanager = new QD3DStateManager(m_d3d_device, m_effect); - m_effect->SetStateManager(m_statemanager); - m_draw_helper = new QD3DDrawHelper(this); - initDevice(); - m_gradient_cache = new QD3DGradientCache(m_d3d_device); - } - } else { - return false; - } - - return true; -} - -QPixmap QDirect3DPaintEnginePrivate::getPattern(Qt::BrushStyle style) const -{ - if (!m_patterns.contains(style)) { - QImage img(16,16,QImage::Format_ARGB32); - img.fill(0); - QPainter p(&img); - p.setBrush(QBrush(Qt::white, style)); - p.setPen(Qt::NoPen); - p.drawRect(0,0,16,16); - p.end(); - QPixmap pattern(QPixmap::fromImage(img)); - QDirect3DPaintEnginePrivate *ct = const_cast<QDirect3DPaintEnginePrivate *>(this); - ct->verifyTexture(pattern); - ct->m_patterns.insert(style, pattern); - } - - return m_patterns.value(style); -} - -bool QDirect3DPaintEnginePrivate::testCaps() -{ - D3DCAPS9 caps; - if (FAILED(m_d3d_object->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps))) - return false; - - if ((caps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) - && (caps.DevCaps & D3DDEVCAPS_PUREDEVICE) - && (caps.RasterCaps & D3DPRASTERCAPS_SCISSORTEST) - && (caps.StencilCaps & D3DSTENCILCAPS_TWOSIDED)) - return true; -#if 0 - qDebug() << "Direct3D caps:"; - qDebug() << "D3DPRESENT_INTERVAL_IMMEDIATE:" << ((caps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) != 0); - qDebug() << "D3DDEVCAPS_PUREDEVICE:" << ((caps.DevCaps & D3DDEVCAPS_PUREDEVICE) != 0); - qDebug() << "D3DPRASTERCAPS_SCISSORTEST:" << ((caps.RasterCaps & D3DPRASTERCAPS_SCISSORTEST) != 0); - qDebug() << "D3DSTENCILCAPS_TWOSIDED:" << ((caps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) != 0); -#endif - return false; -} - -void QDirect3DPaintEnginePrivate::initDevice() -{ - m_statemanager->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - m_statemanager->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); - m_statemanager->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); - m_statemanager->SetRenderState(D3DRS_LIGHTING, FALSE); - m_statemanager->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - m_statemanager->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - m_statemanager->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTALPHA); -} - -void QDirect3DPaintEnginePrivate::updatePen(const QPen &pen) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::updatePen"; -#endif - m_pen = pen; - m_has_cosmetic_pen = false; - m_has_pen = (m_pen.style() != Qt::NoPen); - if (m_has_pen) { - m_pen_brush_style = m_pen.brush().style(); - - if (m_pen_brush_style >= Qt::SolidPattern && m_pen_brush_style <= Qt::DiagCrossPattern) { - int a, r, g, b; - m_pen.color().getRgb(&r, &g, &b, &a); - m_pen_color = D3DCOLOR_ARGB((int)(a * m_opacity),r,g,b); - } else { - m_pen_color = m_opacity_color; - } - - m_has_cosmetic_pen = m_pen.isCosmetic(); - - if (m_pen_brush_style != Qt::NoBrush && - m_pen_brush_style != Qt::SolidPattern) { - bool ok; - m_inv_pen_matrix = m_pen.brush().transform().inverted(&ok); - if (!ok) - qWarning() << "QDirect3DPaintEngine: No inverse matix for pen brush matrix."; - } - - m_pen_width = m_pen.widthF(); - if (m_pen_width == 0.0f) - m_pen_width = 1.0f; - } -} - -void QDirect3DPaintEnginePrivate::updateBrush(const QBrush &brush) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::updateBrush"; -#endif - m_brush = brush; - m_brush_style = m_brush.style(); - m_has_brush = (m_brush_style != Qt::NoBrush); - if (m_has_brush) { - if (m_brush_style >= Qt::SolidPattern && m_brush_style <= Qt::DiagCrossPattern) { - int a, r, g, b; - m_brush.color().getRgb(&r, &g, &b, &a); - m_brush_color = D3DCOLOR_ARGB((int)(a * m_opacity),r,g,b); - } else { - m_brush_color = m_opacity_color; - } - - if (m_brush_style != Qt::SolidPattern) { - bool ok; - m_inv_brush_matrix = (m_brush.transform() * m_brush_origin).inverted(&ok); - if (!ok) - qWarning() << "QDirect3DPaintEngine: No inverse matix for brush matrix."; - - // make sure the texture is loaded as a texture - if (m_brush_style == Qt::TexturePattern) - verifyTexture(m_brush.texture()); - - - } - } -} - -void QDirect3DPaintEnginePrivate::updateTransform(const QTransform &matrix) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::updateTransform"; -#endif - m_matrix = matrix; - m_inv_scale = qMax(1 / qMax( qMax(qAbs(m_matrix.m11()), qAbs(m_matrix.m22())), - qMax(qAbs(m_matrix.m12()), qAbs(m_matrix.m21())) ), 0.0001); - m_txop = matrix.type(); -} - -int QDirect3DPaintEnginePrivate::flushAntialiased(int offset) -{ - // fills the mask (returns number of items added to the mask) - int newoffset = m_draw_helper->drawAntialiasedMask(offset, m_batch.m_item_index); - - // set the render target to the current output surface - if (FAILED(m_d3d_device->SetRenderTarget(0, m_current_surface))) - qWarning() << "QDirect3DPaintEngine: SetRenderTarget failed!"; - - // draw the bounding boxes (using the mask generated by drawAntialiasedMask) - for (int i=offset; i<newoffset; ++i) { - QD3DBatchItem *item = &(m_batch.items[i]); - int pass = (item->m_info & QD3DBatchItem::BI_COMPLEXBRUSH) ? PASS_AA_DRAW : PASS_AA_DRAW_DIRECT; - m_statemanager->beginPass(pass); - prepareItem(item); - if (item->m_info & QD3DBatchItem::BI_BRECT) - m_draw_helper->drawAntialiasedBoundingRect(item); - cleanupItem(item); - } - - m_statemanager->endPass(); - - return newoffset; -} - -bool QDirect3DPaintEnginePrivate::prepareBatch(QD3DBatchItem *item, int offset) -{ - if (item->m_info & QD3DBatchItem::BI_CLIP) { - setRenderTechnique(RT_Aliased); - if (item->m_info & QD3DBatchItem::BI_CLEARCLIP) { - m_d3d_device->Clear(0, 0, D3DCLEAR_ZBUFFER, 0, 0.0f, 0); - return true; - } - - m_draw_helper->drawAliasedMask(offset); - m_d3d_device->Clear(0, 0, D3DCLEAR_ZBUFFER, 0, 1.0f, 0); - if (item->m_info & QD3DBatchItem::BI_BRECT) { - m_statemanager->beginPass(PASS_STENCIL_CLIP); - m_draw_helper->drawAliasedBoundingRect(item); - m_statemanager->endPass(); - } - - return true; - } - - if (item->m_info & QD3DBatchItem::BI_AA) { - setRenderTechnique(RT_Antialiased); - } else { - setRenderTechnique(RT_Aliased); - } - - return false; -} - -void QDirect3DPaintEnginePrivate::prepareItem(QD3DBatchItem *item) { - // pixmap - int brushmode = 0; - m_statemanager->startStateBlock(); - if ((item->m_info & QD3DBatchItem::BI_PIXMAP) || (item->m_info & QD3DBatchItem::BI_IMAGE)) { - QRasterPixmapData *data = static_cast<QRasterPixmapData*>(item->m_pixmap.data); - IDirect3DTexture9 *tex = (item->m_info & QD3DBatchItem::BI_PIXMAP) ? - data->texture : item->m_texture; - m_statemanager->setTexture(tex); - brushmode = 5; - } - - if (item->m_info & QD3DBatchItem::BI_AA) { - m_statemanager->setMaskChannel(item->m_maskpos.channel); - m_statemanager->setMaskOffset(item->m_xoffset, item->m_yoffset); - } - - if (item->m_info & QD3DBatchItem::BI_COMPLEXBRUSH) { - const QBrush brush = item->m_brush; - switch (brush.style()) { - case Qt::TexturePattern: { - QRasterPixmapData *data = static_cast<QRasterPixmapData*>(brush.texture().data); - m_statemanager->setTexture(data->texture, QGradient::RepeatSpread); - brushmode = 1; - break; - } - case Qt::LinearGradientPattern: - m_statemanager->setTexture(m_gradient_cache-> - getBuffer(brush.gradient()->stops(), item->m_opacity), - brush.gradient()->spread()); - brushmode = 2; - break; - case Qt::ConicalGradientPattern: - m_statemanager->setTexture(m_gradient_cache-> - getBuffer(brush.gradient()->stops(), item->m_opacity), - brush.gradient()->spread()); - brushmode = 3; - break; - case Qt::RadialGradientPattern: - m_statemanager->setTexture(m_gradient_cache-> - getBuffer(brush.gradient()->stops(), item->m_opacity), - brush.gradient()->spread()); - m_statemanager->setFocalDistance(item->m_distance); - brushmode = 4; - break; - default: { - QRasterPixmapData *data = static_cast<QRasterPixmapData*>(getPattern(brush.style()).data); - m_statemanager->setTexture(data->texture, QGradient::RepeatSpread); - brushmode = 5; - } - }; - } - - if (item->m_info & QD3DBatchItem::BI_TRANSFORM) { - m_statemanager->setTransformation(&item->m_matrix); - } else { - m_statemanager->setTransformation(); - } - - m_statemanager->setBrushMode(brushmode); - setCompositionMode(item->m_cmode); - m_statemanager->endStateBlock(); -} - - -void QDirect3DPaintEnginePrivate::releaseDC() -{ - if (m_dc) { - m_dcsurface->ReleaseDC(m_dc); - m_dcsurface = 0; - m_dc = 0; - } -} - - -void QDirect3DPaintEnginePrivate::cleanupItem(QD3DBatchItem *item) -{ - if (item->m_info & QD3DBatchItem::BI_PIXMAP) - item->m_pixmap = QPixmap(); - item->m_brush = QBrush(); -} - -void QDirect3DPaintEnginePrivate::verifyTexture(const QPixmap &pm) -{ - QRasterPixmapData *pmData = static_cast<QRasterPixmapData*>(pm.data); - if (!pmData->texture) { - QImage im = pmData->image; - // bitmaps are drawn with the current pen color - if (im.depth() == 1) { - QVector<QRgb> colors(2); - colors[0] = 0; - colors[1] = m_pen.color().rgba(); - im.setColorTable(colors); - } - im = im.convertToFormat(QImage::Format_ARGB32); - if (FAILED(m_d3d_device->CreateTexture(im.width(), im.height(), 1, 0, - D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pmData->texture, 0))) - { - qWarning("QDirect3DPaintEngine: unable to create Direct3D texture from pixmap."); - return; - } - D3DLOCKED_RECT rect; - if (FAILED(pmData->texture->LockRect(0, &rect, 0, 0))) { - qDebug() << "QDirect3DPaintEngine: unable to lock texture rect."; - return; - } - DWORD *dst = (DWORD *) rect.pBits; - DWORD *src = (DWORD *) im.scanLine(0); - - Q_ASSERT((rect.Pitch/4) == (im.bytesPerLine()/4)); - memcpy(dst, src, rect.Pitch*im.height()); - pmData->texture->UnlockRect(0); - } -} - -bool QDirect3DPaintEnginePrivate::isFastRect(const QRectF &rect) -{ - if (m_matrix.type() < QTransform::TxRotate) { - QRectF r = m_matrix.mapRect(rect); - return r.topLeft().toPoint() == r.topLeft() - && r.bottomRight().toPoint() == r.bottomRight(); - } - - return false; -} - -void QDirect3DPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode mode) -{ - switch(mode) { - case QPainter::CompositionMode_SourceOver: - default: - m_statemanager->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - m_statemanager->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); - }; -} - -void QDirect3DPaintEnginePrivate::cleanup() -{ - // clean batch - for(int i=0; i<QD3D_BATCH_SIZE; ++i) { - m_batch.items[i].m_brush = QBrush(); - m_batch.items[i].m_pixmap = QPixmap(); - } - - m_surface_manager.cleanup(); - m_patterns.clear(); - - delete m_gradient_cache; - delete m_draw_helper; - - if (m_effect) - m_effect->Release(); - - if (m_d3d_object) - m_d3d_object->Release(); - - m_effect = 0; - m_d3d_object = 0; - m_gradient_cache = 0; - m_draw_helper = 0; -} - -void QDirect3DPaintEnginePrivate::flushAliased(QD3DBatchItem *item, int offset) -{ - m_draw_helper->drawAliasedMask(offset); - - if (item->m_info & QD3DBatchItem::BI_BRECT) { - int pass = (item->m_info & QD3DBatchItem::BI_MASK) ? PASS_STENCIL_DRAW_DIRECT : PASS_STENCIL_NOSTENCILCHECK_DIRECT; - if (item->m_info & (QD3DBatchItem::BI_COMPLEXBRUSH|QD3DBatchItem::BI_IMAGE|QD3DBatchItem::BI_PIXMAP) ) - pass = (item->m_info & QD3DBatchItem::BI_MASK) ? PASS_STENCIL_DRAW : PASS_STENCIL_NOSTENCILCHECK; - m_statemanager->beginPass(pass); - prepareItem(item); - m_draw_helper->drawAliasedBoundingRect(item); - cleanupItem(item); - m_statemanager->endPass(); - } -} - -void QDirect3DPaintEnginePrivate::flushText(QD3DBatchItem *item, int) -{ - prepareItem(item); - m_statemanager->setTexture(item->m_texture); - m_statemanager->setBrushMode(1); -// m_statemanager->SetRenderState(D3DRS_BLENDFACTOR, item->m_brush.color().rgba()); - m_statemanager->beginPass(m_cleartype_text ? PASS_CLEARTYPE_TEXT : PASS_TEXT); - m_draw_helper->drawTextItem(item); - m_statemanager->endPass(); - cleanupItem(item); -} - -void QDirect3DPaintEnginePrivate::flushLines(QD3DBatchItem *item, int) -{ - m_draw_helper->drawAliasedLines(item); - - if (item->m_info & QD3DBatchItem::BI_BRECT) { - int pass = (item->m_info & QD3DBatchItem::BI_COMPLEXBRUSH) ? PASS_STENCIL_DRAW : PASS_STENCIL_DRAW_DIRECT; - m_statemanager->beginPass(pass); - prepareItem(item); - m_draw_helper->drawAliasedBoundingRect(item); - cleanupItem(item); - m_statemanager->endPass(); - } -} - -void QDirect3DPaintEnginePrivate::flushBatch() -{ -// static int dbgcounter = 0; -// ++dbgcounter; -// qDebug() << " -> flush" << dbgcounter; - - int offset = 0; - m_draw_helper->unlockVertexBuffer(); - releaseDC(); - - // iterate over all items in the batch - while (offset != m_batch.m_item_index) { - QD3DBatchItem *item = &(m_batch.items[offset]); - - if (prepareBatch(item, offset)) { - ++offset; - continue; - } - - if (item->m_info & QD3DBatchItem::BI_FASTLINE) { - flushLines(item, offset++); - } else if (item->m_info & QD3DBatchItem::BI_AA) { - offset = flushAntialiased(offset); - } else if (item->m_info & QD3DBatchItem::BI_TEXT) { - flushText(item, offset++); - } else { - flushAliased(item, offset++); - } - } - - // reset batch - m_batch.m_item_index = 0; - - // release doomed textures - for (int i=0; i<qd3d_release_list.size(); ++i) - qd3d_release_list.at(i)->Release(); - qd3d_release_list.clear(); -} - -QDirect3DPaintEngine::QDirect3DPaintEngine() - : QPaintEngine(*(new QDirect3DPaintEnginePrivate), - PaintEngineFeatures(AllFeatures & ~ObjectBoundingModeGradients)) -{ } - -QDirect3DPaintEngine::~QDirect3DPaintEngine() -{ -} - -bool QDirect3DPaintEngine::begin(QPaintDevice *device) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::begin"; -#endif - Q_D(QDirect3DPaintEngine); - setActive(true); - - QSize old_size = d->m_surface_size; - d->m_surface_size = QRect(0, 0, device->width(), device->height()).size(); - - d->m_current_state = 0; - d->m_inv_scale = 1; - d->m_opacity = 1.0f; - d->m_opacity_color = D3DCOLOR_ARGB(255,255,255,255); - d->m_matrix = QTransform(); - d->m_brush_origin = QTransform(); - d->m_txop = QTransform::TxNone; - d->m_cmode = QPainter::CompositionMode_SourceOver; - - Q_ASSERT(device && device->devType() == QInternal::Widget); - if (d->m_d3d_device == 0) { - qWarning() << "QDirect3DPaintEngine: No Device!"; - return false; - } - - d->m_cleartype_text = false; -// QT_WA({ -// UINT result; -// BOOL ok; -// ok = SystemParametersInfoW(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0); -// if (ok) -// d->m_cleartype_text = (result == FE_FONTSMOOTHINGCLEARTYPE); -// }, { -// UINT result; -// BOOL ok; -// ok = SystemParametersInfoA(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0); -// if (ok) -// d->m_cleartype_text = (result == FE_FONTSMOOTHINGCLEARTYPE); -// }); - - d->m_surface_manager.setPaintDevice(device); - int status = d->m_surface_manager.status(); - if (status & QD3DSurfaceManager::NeedsResetting) { - d->m_effect->OnLostDevice(); - d->m_draw_helper->beforeReset(); - d->m_statemanager->reset(); - d->m_surface_manager.reset(); - d->m_draw_helper->afterReset(); - d->m_effect->OnResetDevice(); - d->initDevice(); - } - - LPDIRECT3DSURFACE9 newsurface = d->m_surface_manager.renderTarget(); - if (d->m_current_surface != newsurface) { - d->m_current_surface = newsurface; - if (FAILED(d->m_d3d_device->SetRenderTarget(0, newsurface))) - qWarning() << "QDirect3DPaintEngine: SetRenderTarget failed!"; - } - - status = d->m_surface_manager.status(); - if (status & QD3DSurfaceManager::MaxSizeChanged) { - QSize maxsize = d->m_surface_manager.maxSize(); - d->m_draw_helper->setMaskSize(maxsize); - int masksize[2] = {maxsize.width(), maxsize.height()}; - d->m_effect->SetIntArray("g_mMaskSize", masksize, 2); - } - - if (old_size != d->m_surface_size) { - D3DXMATRIX projMatrix; - pD3DXMatrixOrthoOffCenterLH(&projMatrix, 0, d->m_surface_size.width(), d->m_surface_size.height(), 0, 0.0f, 1.0f); - d->m_statemanager->setProjection(&projMatrix); - } - - if (!d->m_in_scene) { - if (FAILED(d->m_d3d_device->BeginScene())) { - qWarning() << "QDirect3DPaintEngine: BeginScene() failed."; - return false; - } - QWidget *widget = static_cast<QWidget *>(device); - if (widget->autoFillBackground() == true) { - QColor color = widget->palette().brush(widget->backgroundRole()).color(); - RECT rect = {0, 0, widget->width(), widget->height()}; - d->m_d3d_device->ColorFill(d->m_current_surface, &rect, - D3DCOLOR_ARGB(color.alpha(), color.red(), color.green(), color.blue())); - } - d->m_in_scene = true; - } - - // set system clip - d->m_clipping_enabled = false; - d->m_has_complex_clipping = false; - - d->m_sysclip_region = systemClip(); - QVector<QRect> rects = d->m_sysclip_region.rects(); - if (rects.count() == 1 && rects.at(0).size() == d->m_surface_size) - d->m_sysclip_region = QRegion(); - - d->updateClipRegion(QRegion(), Qt::NoClip); - - return true; -} - -void QDirect3DPaintEngine::drawEllipse(const QRectF &rect) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawEllipse (float)"; -#endif - QPaintEngine::drawEllipse(rect); -} - -void QDirect3DPaintEngine::drawEllipse(const QRect &rect) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawEllipse"; -#endif - QPaintEngine::drawEllipse(rect); -} - -void QDirect3DPaintEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr, - Qt::ImageConversionFlags) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawImage"; -#endif - - Q_D(QDirect3DPaintEngine); - int width = image.width(); - int height = image.height(); - - // transform rectangle - QPolygonF txrect(QRectF(sr.left() / width, sr.top() / height, - sr.width() / width, sr.height() / height)); - - QD3DBatchItem *item = d->nextBatchItem(); - item->m_info = QD3DBatchItem::BI_IMAGE | QD3DBatchItem::BI_TRANSFORM; - item->m_texture = qd3d_image_cache()->lookup(d->m_d3d_device, image); - item->m_matrix = d->m_matrix; - d->m_draw_helper->queueRect(r.adjusted(-0.5f,-0.5f,-0.5f,-0.5f), item, d->m_opacity_color, txrect); -} - -void QDirect3DPaintEngine::drawLines(const QLineF *lines, int lineCount) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawLines (float)"; -#endif - Q_D(QDirect3DPaintEngine); - - if (!d->m_has_pen) - return; - - if (d->m_has_fast_pen && (d->m_pen_brush_style == Qt::SolidPattern)) { - QD3DBatchItem *item = d->nextBatchItem(); - if (d->m_pen.isCosmetic()) - item->m_info |= QD3DBatchItem::BI_COSMETICPEN; - item->m_info |= QD3DBatchItem::BI_TRANSFORM; - item->m_matrix = d->m_matrix; - d->m_draw_helper->queueAliasedLines(lines, lineCount, &item); - } else { - QRectF brect; - QPainterPath path; - - // creates a path with the lines - path.moveTo(lines[0].x1(), lines[0].y1()); - qreal lastx = lines[0].x2(); - qreal lasty = lines[0].y2(); - path.lineTo(lastx, lasty); - - for (int i=1; i<lineCount; ++i) { - qreal x = lines[i].x1(); - qreal y = lines[i].y1(); - if (lastx != x || lasty != y) { - path.moveTo(x, y); - } - path.lineTo(lines[i].x2(), lines[i].y2()); - } - - if (d->m_has_cosmetic_pen) { - brect = path.controlPointRect(); - path = d->m_matrix.map(path); - } - - d->strokePath(path, brect, true); - } -} - -void QDirect3DPaintEngine::drawLines(const QLine *lines, int lineCount) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawLines"; -#endif - QPaintEngine::drawLines(lines, lineCount); -} - -void QDirect3DPaintEngine::drawPath(const QPainterPath &path) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawPath"; -#endif - Q_D(QDirect3DPaintEngine); - - if (path.isEmpty()) - return; - - QRectF brect; - QPainterPath tpath; - - if (d->m_has_cosmetic_pen) { - brect = path.controlPointRect(); - tpath = d->m_matrix.map(path); - } else { - tpath = path; - } - - if (d->m_has_brush) - d->fillPath(tpath, brect); - - if (d->m_has_pen) - d->strokePath(tpath, brect); -} - - -QPointF QDirect3DPaintEnginePrivate::transformPoint(const QPointF &p, qreal *w) const -{ - (*w) = 1.0f; - qreal fx = p.x(); - qreal fy = p.y(); - qreal nx = m_matrix.m11()*fx + m_matrix.m21()*fy + m_matrix.m31(); - qreal ny = m_matrix.m12()*fx + m_matrix.m22()*fy + m_matrix.m32(); - if (!m_matrix.isAffine()) { - *w = m_matrix.m13()*fx + m_matrix.m23()*fy + m_matrix.m33(); - //*w = 1/(*w); - nx = nx/(*w); - ny = ny/(*w); - } - return QPointF(nx, ny); -} - -void QDirect3DPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawPixmap"; -#endif - Q_D(QDirect3DPaintEngine); - - if (d->m_draw_helper->needsFlushing()) - d->flushBatch(); - - int width = pm.width(); - int height = pm.height(); - - // transform rectangle - QPolygonF txrect(QRectF(sr.left() / width, sr.top() / height, - sr.width() / width, sr.height() / height)); - - QD3DBatchItem *item = d->nextBatchItem(); - item->m_info = QD3DBatchItem::BI_PIXMAP|QD3DBatchItem::BI_TRANSFORM; - - item->m_pixmap = pm; - d->verifyTexture(item->m_pixmap); - - item->m_matrix = d->m_matrix; - d->m_draw_helper->queueRect(r.adjusted(-0.5f,-0.5f,-0.5f,-0.5f), item, d->m_opacity_color, txrect); -} - -void QDirect3DPaintEngine::drawPoints(const QPointF *points, int pointCount) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawPoints (float)"; -#endif - QPaintEngine::drawPoints(points, pointCount); -} - -void QDirect3DPaintEngine::drawPoints(const QPoint *points, int pointCount) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawPoints"; -#endif - QPaintEngine::drawPoints(points, pointCount); -} - -void QDirect3DPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawPolygon"; -#endif - Q_D(QDirect3DPaintEngine); - - if (d->m_has_brush && mode != PolylineMode) { - QPainterPath path; - path.setFillRule(mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill); - path.moveTo(points[0]); - for (int i=1; i<pointCount; ++i) - path.lineTo(points[i]); - if (path.isEmpty()) - return; - d->fillPath(path, QRectF()); - } - - if (d->m_has_pen) { - QPainterPath path(points[0]); - for (int i = 1; i < pointCount; ++i) - path.lineTo(points[i]); - if (mode != PolylineMode) - path.lineTo(points[0]); - - if (path.isEmpty()) - return; - QRectF brect; - if (d->m_has_cosmetic_pen) { - brect = path.controlPointRect(); - path = d->m_matrix.map(path); - } - - d->strokePath(path, brect); - } -} - -void QDirect3DPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawPolygon"; -#endif - QPaintEngine::drawPolygon(points, pointCount, mode); -} - -void QDirect3DPaintEngine::drawRects(const QRectF *rects, int rectCount) -{ - Q_D(QDirect3DPaintEngine); -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawRects (float)"; -#endif - for (int i=0; i<rectCount; ++i) { - if ((d->m_brush_style == Qt::SolidPattern) && - (!(d->m_current_state & QD3DBatchItem::BI_AA) || d->isFastRect(rects[i]))) { - QD3DBatchItem *item = d->nextBatchItem(); - item->m_info |= QD3DBatchItem::BI_TRANSFORM; - item->m_info &= ~QD3DBatchItem::BI_AA; - item->m_matrix = d->m_matrix; - const QRectF rect = rects[i]; - d->m_draw_helper->queueRect(rect, item, d->m_brush_color); - - if (d->m_has_pen) { - if (d->m_has_fast_pen && (d->m_pen_brush_style == Qt::SolidPattern)) { - QLineF lines[4]; - qreal x1 = rect.x(); - qreal y1 = rect.y(); - qreal x2 = rect.width() + x1; - qreal y2 = rect.height() + y1; - lines[0] = QLineF(x1, y1, x2, y1); - lines[1] = QLineF(x2, y1, x2, y2); - lines[2] = QLineF(x2, y2, x1, y2); - lines[3] = QLineF(x1, y2, x1, y1); - QD3DBatchItem *item = d->nextBatchItem(); - if (d->m_pen.isCosmetic()) - item->m_info |= QD3DBatchItem::BI_COSMETICPEN; - item->m_info |= QD3DBatchItem::BI_TRANSFORM; - item->m_matrix = d->m_matrix; - d->m_draw_helper->queueAliasedLines(lines, 4, &item); - } else { - QPainterPath path; - QRectF brect; - - path.addRect(rects[i]); - if (d->m_has_cosmetic_pen) { - brect = path.controlPointRect(); - path = d->m_matrix.map(path); - } - - d->strokePath(path, brect, true); - } - } - } else { - QPainterPath path; - QRectF brect; - - path.addRect(rects[i]); - if (d->m_has_cosmetic_pen) { - brect = path.controlPointRect(); - path = d->m_matrix.map(path); - } - - if (d->m_has_brush) - d->fillPath(path, brect); - - if (d->m_has_pen) - d->strokePath(path, brect, true); - } - } -} - -void QDirect3DPaintEngine::drawRects(const QRect *rects, int rectCount) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawRects"; -#endif - QPaintEngine::drawRects(rects, rectCount); -} - - -void QDirect3DPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) -{ - Q_D(QDirect3DPaintEngine); - -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawTextItem"; -#endif -// if (d->m_matrix.isScaling() || (d->m_pen_brush_style >= Qt::LinearGradientPattern -// && d->m_pen_brush_style <= Qt::ConicalGradientPattern)) { -// QPaintEngine::drawTextItem(p, textItem); -// return; -// } - - const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); - QVarLengthArray<QFixedPoint> positions; - QVarLengthArray<glyph_t> glyphs; - QTransform matrix; - matrix.translate(p.x(), p.y()); - ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); - - qd3d_glyph_cache()->cacheGlyphs(this, ti, glyphs, d->m_cleartype_text); - QD3DFontTexture *font_tex = qd3d_glyph_cache()->fontTexture(ti.fontEngine); - - QD3DBatchItem *item = d->nextBatchItem(); - d->m_draw_helper->lockVertexBuffer(); - - item->m_info = QD3DBatchItem::BI_TEXT - | (d->m_current_state & ~QD3DBatchItem::BI_AA) | QD3DBatchItem::BI_TRANSFORM; - item->m_texture = font_tex->texture; - item->m_offset = d->m_draw_helper->index(); - item->m_matrix = d->m_matrix; - item->m_count = 0; - item->m_brush = d->m_pen.brush(); - - for (int i=0; i< glyphs.size(); ++i) { - QD3DGlyphCoord *g = qd3d_glyph_cache()->lookup(ti.fontEngine, glyphs[i]); - - // we don't cache glyphs with no width/height - if (!g) - continue; - - // texture coords - qreal tex_coords[] = { g->x, g->y, g->x + g->width, g->y + g->height }; - QPointF logical_pos(qRound((positions[i].x - g->x_offset).toReal()) - 0.5f, - qRound((positions[i].y + g->y_offset).toReal()) - 0.5f); - - QRectF glyph_rect(logical_pos, QSizeF(g->log_width, g->log_height)); - d->m_draw_helper->queueTextGlyph(glyph_rect, tex_coords, item, d->m_pen_color); - } -} - -void QDirect3DPaintEngine::drawTiledPixmap(const QRectF &rect, const QPixmap &pixmap, const QPointF &p) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawTiledPixmap"; -#endif - QPaintEngine::drawTiledPixmap(rect, pixmap, p); -} - -bool QDirect3DPaintEngine::end() -{ - Q_D(QDirect3DPaintEngine); - - d->flushBatch(); - - if (d->m_flush_on_end) { - QPaintDevice *pdev = paintDevice(); - LPDIRECT3DSWAPCHAIN9 swapchain = swapChain(pdev); - - - QWidget *w = 0; - if (pdev->devType() == QInternal::Widget) { - w = static_cast<QWidget *>(pdev); - } - - if (w && swapchain) { - QRect br = w->rect(); - QRect wbr = br;//.translated(-w->pos()); - - RECT destrect; - destrect.left = wbr.x(); - destrect.top = wbr.y(); - destrect.right = destrect.left + wbr.width(); - destrect.bottom = destrect.top + wbr.height(); - - RECT srcrect; - srcrect.left = br.x();// + w->x(); - srcrect.top = br.y();// + w->y(); - srcrect.right = wbr.width() + srcrect.left; - srcrect.bottom = wbr.height() + srcrect.top; - int devwidth = w->width(); - int devheight = w->height(); - - if (devwidth <= srcrect.right) { - int diff = srcrect.right - devwidth; - srcrect.right -= diff; - destrect.right -= diff; - if (srcrect.right <= srcrect.left) - return false; - } - if (devheight <= srcrect.bottom) { - int diff = srcrect.bottom - devheight; - srcrect.bottom -= diff; - destrect.bottom -= diff; - if (srcrect.bottom <= srcrect.top) - return false; - } - - if (FAILED(swapchain->Present(&srcrect, &destrect, w->winId(), 0, 0))) - qWarning("QDirect3DPaintEngine: failed to present back buffer."); - } - } - - - return true; -} - -void QDirect3DPaintEngine::updateState(const QPaintEngineState &state) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::updateState"; -#endif - Q_D(QDirect3DPaintEngine); - - bool update_fast_pen = false; - DirtyFlags flags = state.state(); - - if (flags & DirtyOpacity) { - d->m_opacity = state.opacity(); - if (d->m_opacity > 1.0f) - d->m_opacity = 1.0f; - if (d->m_opacity < 0.f) - d->m_opacity = 0.f; - uint c = (d->m_opacity * 255); - d->m_opacity_color = D3DCOLOR_ARGB(c,c,c,c); - flags |= (DirtyPen | DirtyBrush); - } - - if (flags & DirtyCompositionMode) { - d->m_cmode = state.compositionMode(); - } - - if (flags & DirtyTransform) { - d->updateTransform(state.transform()); - update_fast_pen = true; - } - - if (flags & DirtyHints) { - if (state.renderHints() & QPainter::Antialiasing) - d->m_current_state |= QD3DBatchItem::BI_AA; - else - d->m_current_state &= ~QD3DBatchItem::BI_AA; - update_fast_pen = true; - } - - if (flags & DirtyFont) { - d->updateFont(state.font()); - } - - if (state.state() & DirtyClipEnabled) { - if (state.isClipEnabled() && !d->m_clipping_enabled) { - d->m_clipping_enabled = true; - if (d->m_has_complex_clipping) - d->updateClipPath(painter()->clipPath(), Qt::ReplaceClip); - else - d->updateClipRegion(painter()->clipRegion(), Qt::ReplaceClip); - } else if (!state.isClipEnabled() && d->m_clipping_enabled) { - d->m_clipping_enabled = false; - if (d->m_has_complex_clipping) - d->updateClipPath(QPainterPath(), Qt::NoClip); - else - d->updateClipRegion(QRegion(), Qt::NoClip); - } - } - - if (flags & DirtyClipRegion) { - d->updateClipRegion(state.clipRegion(), state.clipOperation()); - } - - if (flags & DirtyClipPath) { - d->updateClipPath(state.clipPath(), state.clipOperation()); - } - - if (flags & DirtyBrushOrigin) { - d->m_brush_origin = QTransform(); - d->m_brush_origin.translate(-state.brushOrigin().x(), - -state.brushOrigin().y()); - flags |= DirtyBrush; - } - - if (flags & DirtyPen) { - d->updatePen(state.pen()); - update_fast_pen = true; - } - - if (flags & DirtyBrush) - d->updateBrush(state.brush()); - - if (update_fast_pen && d->m_has_pen) { - if (d->m_current_state & QD3DBatchItem::BI_AA) { - d->m_has_fast_pen = false; - d->m_has_aa_fast_pen = ((d->m_txop <= QTransform::TxTranslate) || d->m_has_cosmetic_pen) - && (d->m_pen_width <= 1.0f) - && (d->m_pen.style() == Qt::SolidLine); - } else { - d->m_has_aa_fast_pen = false; - d->m_has_fast_pen = ((d->m_txop <= QTransform::TxTranslate) || d->m_has_cosmetic_pen) - && (d->m_pen.style() == Qt::SolidLine) - && (d->m_pen.capStyle() == Qt::SquareCap); - } - } -} - -void QDirect3DPaintEngine::cleanup() -{ - Q_D(QDirect3DPaintEngine); - d->cleanup(); -} - -void QDirect3DPaintEngine::scroll(QPaintDevice *pd, const RECT &srcrect, const RECT &destrect) -{ - Q_D(QDirect3DPaintEngine); - LPDIRECT3DSURFACE9 srcsurf = d->m_surface_manager.surface(pd); - LPDIRECT3DSURFACE9 masksurf = d->m_draw_helper->freeMaskSurface(); - if (FAILED(d->m_d3d_device->StretchRect(srcsurf, &srcrect, masksurf, &srcrect, D3DTEXF_NONE))) - qWarning("QDirect3DPaintEngine: StretchRect failed."); - if (FAILED(d->m_d3d_device->StretchRect(masksurf, &srcrect, srcsurf, &destrect, D3DTEXF_NONE))) - qWarning("QDirect3DPaintEngine: StretchRect failed."); -} - -LPDIRECT3DSWAPCHAIN9 QDirect3DPaintEngine::swapChain(QPaintDevice *pd) -{ - Q_D(QDirect3DPaintEngine); - - if (d->m_in_scene) { - if (d->m_d3d_device == 0) { - qWarning("QDirect3DPaintEngine: No device!"); - return false; - } - - d->setRenderTechnique(QDirect3DPaintEnginePrivate::RT_NoTechnique); - if (FAILED(d->m_d3d_device->EndScene())) - qWarning("QDirect3DPaintEngine: failed to end scene."); - - d->m_in_scene = false; - } - - return d->m_surface_manager.swapChain(pd); -} - -void QDirect3DPaintEngine::releaseSwapChain(QPaintDevice *pd) -{ - Q_D(QDirect3DPaintEngine); - d->m_surface_manager.releasePaintDevice(pd); -} - -HDC QDirect3DPaintEngine::getDC() const -{ - QDirect3DPaintEnginePrivate *d = const_cast<QDirect3DPaintEnginePrivate *>(d_func()); - - if (!d->m_dc && d->m_current_surface) { - d->m_dcsurface = d->m_current_surface; - if (FAILED(d->m_current_surface->GetDC(&d->m_dc))) - qWarning() << "QDirect3DPaintEngine::getDC() failed!"; - } - - return d->m_dc; -} - -void QDirect3DPaintEngine::setFlushOnEnd(bool flushOnEnd) -{ - Q_D(QDirect3DPaintEngine); - - d->m_flush_on_end = flushOnEnd; -} - -bool QDirect3DPaintEngine::hasDirect3DSupport() -{ - Q_D(QDirect3DPaintEngine); - return d->m_supports_d3d; -} - -QT_END_NAMESPACE - -#include "qpaintengine_d3d.moc" diff --git a/src/gui/painting/qpaintengine_d3d.fx b/src/gui/painting/qpaintengine_d3d.fx deleted file mode 100644 index 1148b2a..0000000 --- a/src/gui/painting/qpaintengine_d3d.fx +++ /dev/null @@ -1,608 +0,0 @@ -bool g_mCosmeticPen; -int4 g_mChannel; -float2 g_mMaskOffset; -int2 g_mMaskSize; -float4x4 g_mMaskProjection; -float4x4 g_mViewProjection; -float4x4 g_mTransformation; -texture g_mAAMask; -texture g_mTexture; -int g_mBrushMode; -float g_mFocalDist; - -#define M_PI 3.14159265358979323846 - -sampler PixmapSampler = sampler_state -{ - texture = <g_mTexture>; - MIPFILTER = NONE; - MINFILTER = LINEAR; - MAGFILTER = LINEAR; -}; - -sampler TextSampler = sampler_state -{ - texture = <g_mTexture>; - MIPFILTER = NONE; - MINFILTER = POINT; - MAGFILTER = POINT; -}; - -sampler AAMaskSampler = sampler_state -{ - texture = <g_mAAMask>; - AddressU = WRAP; - AddressV = WRAP; - AddressW = WRAP; - MIPFILTER = NONE; - MINFILTER = POINT; - MAGFILTER = POINT; -}; - -struct VS_FULL -{ - float4 Position : POSITION; - float4 Diffuse : COLOR0; - float4 TexCoords0 : TEXCOORD0; - float4 TexCoords1 : TEXCOORD1; -}; - -VS_FULL TrapezoidVS( float4 Position : POSITION, - float4 Diffuse : COLOR0, - float4 TexCoords0 : TEXCOORD0, - float4 TexCoords1 : TEXCOORD1) -{ - VS_FULL Output; - - float a = (TexCoords1.x * Position.x) + (TexCoords1.z * (1.0 - Position.x) ); // left or right a - float b = (TexCoords1.y * Position.x) + (TexCoords1.w * (1.0 - Position.x) ); // left or right b - float d = 1.0 - (Position.x * 2); - - Position.x = (a * Position.y + b) + ( sqrt( abs(a * a) ) * d ); - //Position.x += step(abs(a), 0) * d; - Position.x += (0.5 * d); - - Output.Position = mul(Position, g_mMaskProjection); - Output.Diffuse = Diffuse; - Output.TexCoords0 = TexCoords0; - Output.TexCoords1 = TexCoords1; - - return Output; -} - -struct PS_OUTPUT -{ - float4 Color : COLOR0; -}; - -PS_OUTPUT TrapezoidPS(VS_FULL In, float2 pixelPos : VPOS) -{ - PS_OUTPUT Out; - - float top = max(pixelPos.y - 0.5, In.TexCoords0.x); - float bottom = min(pixelPos.y + 0.5, In.TexCoords0.y); - - float area = bottom - top; - - float left = pixelPos.x - 0.5; - float right = pixelPos.x + 0.5; - - // use line equations to compute intersections of left/right edges with top/bottom of truncated pixel - // vecX: x = (left, top), y = (left, bottom), z = (right, top), w = (right, bottom) - float4 vecX = In.TexCoords1.xxzz * float2(top, bottom).xyxy + In.TexCoords1.yyww; - - float2 invA = In.TexCoords0.zw; - - // transform right line to left to be able to use same calculations for both - vecX.zw = 2 * pixelPos.x - vecX.zw; - - float2 topX = float2(vecX.x, vecX.z); - float2 bottomX = float2(vecX.y, vecX.w); - - // transform lines such that top intersection is to the right of bottom intersection - float2 topXTemp = max(topX, bottomX); - float2 bottomXTemp = min(topX, bottomX); - - // make sure line slope reflects mirrored lines - invA = lerp(invA, -invA, step(topX, bottomX)); - - float2 vecLeftRight = float2(left, right); - - // compute the intersections of the lines with the left and right edges of the pixel - // intersectY: x = (left_line, left), y = (left_line, right), z = (right_line, left), w = (right_line, right) - float4 intersectY = top + (vecLeftRight.xyxy - topXTemp.xxyy) * invA.xxyy; - - float2 temp = lerp(area - 0.5 * (right - bottomXTemp) * (bottom - intersectY.yw), // left < bottom < right < top - (0.5 * (topXTemp + bottomXTemp) - left) * area, // left < bottom < top < right - step(topXTemp, right)); - - float2 excluded = 0.5 * (intersectY.xz - top) * (topXTemp - left); // bottom < left < top < right - - excluded = lerp(0.5 * (intersectY.yw + intersectY.xz) - top, // bottom < left < right < top - excluded, step(topXTemp, right)); - - excluded = lerp(temp, // left < bottom < right (see calculation of temp) - excluded, step(bottomXTemp, left)); - - excluded = lerp(float2(area, area), // right < bottom < top - excluded, step(bottomXTemp, right)); - - excluded *= step(left, topXTemp); - - float result = (area - excluded.x - excluded.y) * step(top, bottom); - Out.Color.r = result * g_mChannel[0]; - Out.Color.g = result * g_mChannel[1]; - Out.Color.b = result * g_mChannel[2]; - Out.Color.a = result * g_mChannel[3]; - - return Out; -} - -VS_FULL ViewProjectionVS( float4 Position : POSITION, - float4 Diffuse : COLOR0, - float4 TexCoords0 : TEXCOORD0, - float4 TexCoords1 : TEXCOORD1) -{ - VS_FULL Output; - - Output.Position = mul(Position, g_mTransformation); - Output.Position = mul(Output.Position, g_mViewProjection); - Output.Diffuse = Diffuse; - Output.TexCoords0 = TexCoords0; - Output.TexCoords1 = TexCoords1; - - return Output; -} - -PS_OUTPUT DirectMaskPS(VS_FULL In, float2 pixelPos : VPOS) -{ - PS_OUTPUT Out; - Out.Color = In.Diffuse; - - float2 maskcoords = ( (pixelPos + g_mMaskOffset) - 0.5 ) / g_mMaskSize; - float2 clipcoords = (pixelPos - 0.5) / g_mMaskSize; - - float4 c = tex2D(AAMaskSampler, maskcoords.xy) * Out.Color.a; - Out.Color.a = c.r * g_mChannel[0]; - Out.Color.a += c.g * g_mChannel[1]; - Out.Color.a += c.b * g_mChannel[2]; - Out.Color.a += c.a * g_mChannel[3]; - - return Out; -} - -PS_OUTPUT MaskPS(VS_FULL In, float2 pixelPos : VPOS) -{ - PS_OUTPUT Out; - - if (g_mBrushMode == 1) { - float x = In.TexCoords0.x; - float y = In.TexCoords0.y; - x = x - int(x); - y = y - int(y); - Out.Color = tex2D(PixmapSampler, float2(x, y)); - Out.Color.a = Out.Color.a * In.Diffuse.a; - } else if (g_mBrushMode == 2) { - Out.Color = tex1D(PixmapSampler, In.TexCoords0.x); - } else if (g_mBrushMode == 3) { - float t = atan2(In.TexCoords0.y, -In.TexCoords0.x) / (2 * M_PI); - Out.Color = tex1D(PixmapSampler, t + 0.5); - } else if (g_mBrushMode == 4) { - float2 tc = float2(In.TexCoords0.x, abs(In.TexCoords0.y)); - float a = (tc.x - g_mFocalDist) / tc.y; - float b = g_mFocalDist; - - float A = 1 + (a * a); - float B = 2.0 * a * b; - float C = (b * b) - 1; - - float y = (-B + sqrt(B*B - 4.0*A*C)) / (2.0*A); - Out.Color = tex1D(PixmapSampler, (tc.y / y) ); - } else if (g_mBrushMode == 5) { - Out.Color = tex2D(PixmapSampler, In.TexCoords0.xy); - Out.Color = Out.Color * In.Diffuse; - } else { - Out.Color = In.Diffuse; - } - - float2 maskcoords = ( (pixelPos + g_mMaskOffset) - 0.5 ) / g_mMaskSize; - - float4 c = tex2D(AAMaskSampler, maskcoords.xy) * Out.Color.a; - Out.Color.a = c.r * g_mChannel[0]; - Out.Color.a += c.g * g_mChannel[1]; - Out.Color.a += c.b * g_mChannel[2]; - Out.Color.a += c.a * g_mChannel[3]; - - return Out; -} - -struct VS_NORMAL -{ - float4 Position : POSITION; - float4 Diffuse : COLOR0; - float4 TexCoords : TEXCOORD0; -}; - -VS_NORMAL MaskProjectionVS(VS_NORMAL In) -{ - VS_NORMAL Output; - - Output.Position = mul(In.Position, g_mMaskProjection); - Output.Diffuse = In.Diffuse; - Output.TexCoords = In.TexCoords; - - return Output; -} - -float4 DirectSimplePS(float4 Color : COLOR0) : COLOR0 -{ - return Color; -} - -float4 SimplePS(float4 Color : COLOR0, float4 TexCoords : TEXCOORD0) : COLOR0 -{ - if (g_mBrushMode == 1) { - float opacity = Color.a; - float x = TexCoords.x; - float y = TexCoords.y; - x = x - int(x); - y = y - int(y); - Color = tex2D(PixmapSampler, float2(x, y)); - Color.a = Color.a * opacity; - } else if (g_mBrushMode == 2) { - Color = tex1D(PixmapSampler, TexCoords.x); - } else if (g_mBrushMode == 3) { - float t = atan2(TexCoords.y, -TexCoords.x) / (2 * M_PI); - Color = tex1D(PixmapSampler, t + 0.5); - } else if (g_mBrushMode == 4) { - float2 tc = float2(TexCoords.x, abs(TexCoords.y)); - float a = (tc.x - g_mFocalDist) / tc.y; - float b = g_mFocalDist; - - float A = 1 + (a * a); - float B = 2.0 * a * b; - float C = (b * b) - 1; - - float y = (-B + sqrt(B*B - 4.0*A*C)) / (2.0*A); - Color = tex1D(PixmapSampler, (tc.y / y) ); - } else if (g_mBrushMode == 5) { - Color = tex2D(PixmapSampler, TexCoords.xy) * Color; - } - - return Color; -} - -float4 TextPS(float4 Color : COLOR0, float4 TexCoords : TEXCOORD0) : COLOR0 -{ - Color.a *= tex2D(TextSampler, TexCoords.xy).a; - return Color; -} - -float4 ClearTypePS(float4 Color : COLOR0, float4 TexCoords : TEXCOORD0) : COLOR0 -{ -// if (g_mUsePixmap) { -// float4 MaskColor = tex2D(PixmapSampler, TexCoords.xy); -// Color = float4(1.0, 0.0, 0.0, 1.0); -// Color.a = (1 - MaskColor.a) + MaskColor.a * Color.a; -// Color.r = (1.0 - MaskColor.r) + (MaskColor.r * Color.r); -// Color.g = (1.0 - MaskColor.g) + (MaskColor.g * Color.g); -// Color.b = (1.0 - MaskColor.b) + (MaskColor.b * Color.b); -// Color = MaskColor; - return tex2D(PixmapSampler, TexCoords.xy); -} - -VS_NORMAL NoTxAliasedVS(VS_NORMAL In) -{ - VS_NORMAL Output; - - Output.Position = mul(In.Position, g_mViewProjection); - Output.Diffuse = In.Diffuse; - Output.TexCoords = In.TexCoords; - - return Output; -} - -VS_NORMAL AliasedVS(VS_NORMAL In) -{ - VS_NORMAL Output; - - Output.Position = mul(In.Position, g_mTransformation); - Output.Position = mul(Output.Position, g_mViewProjection); - Output.Diffuse = In.Diffuse; - Output.TexCoords = In.TexCoords; - - return Output; -} - -VS_NORMAL AliasedLinesVS(VS_NORMAL In) -{ - VS_NORMAL Output; - - float4 start = float4(In.Position.x, In.Position.y, 0.5, In.Position.w); - float4 end = float4(In.TexCoords.z, In.TexCoords.w, 0.5, In.Position.w); - if (g_mCosmeticPen) { - start = mul(start, g_mTransformation); - end = mul(end, g_mTransformation); - } - - float2 line_vec = end - start; - float2 vec = normalize(line_vec); - float2 norm = float2(-vec.y, vec.x); - - float pen_width = In.Position.z; - norm = norm * pen_width * 0.5; - vec = vec * pen_width * 0.5; - - Output.Position.w = In.Position.w; - Output.Position.x = start.x + (vec.x * In.TexCoords.x); - Output.Position.x = Output.Position.x + (norm.x * In.TexCoords.y); - Output.Position.x = Output.Position.x + (line_vec.x * step(0, In.TexCoords.x)); - Output.Position.y = start.y + (vec.y * In.TexCoords.x); - Output.Position.y = Output.Position.y + (norm.y * In.TexCoords.y); - Output.Position.y = Output.Position.y + (line_vec.y * step(0, In.TexCoords.x)); - Output.Position.z = 0.5; - - if (!g_mCosmeticPen) { - Output.Position = mul(Output.Position, g_mTransformation); - } - Output.Position = mul(Output.Position, g_mViewProjection); - - Output.Diffuse = In.Diffuse; - Output.TexCoords = In.TexCoords; - - return Output; -} - - -technique Antialiased -{ - pass PASS_AA_CREATEMASK - { - StencilEnable = False; - ZWriteEnable = False; - ColorWriteEnable = 0x0f; - ZEnable = False; - - SrcBlend = One; - DestBlend = One; - - VertexShader = compile vs_3_0 TrapezoidVS(); - PixelShader = compile ps_3_0 TrapezoidPS(); - } - - pass PASS_AA_DRAW - { - StencilEnable = False; - ZFunc = Greater; - ZWriteEnable = False; - ZEnable = True; - ColorWriteEnable = 0x0f; - - VertexShader = compile vs_3_0 ViewProjectionVS(); - PixelShader = compile ps_3_0 MaskPS(); - } - - pass PASS_AA_DRAW_DIRECT - { - StencilEnable = False; - ZFunc = Greater; - ZEnable = True; - ZWriteEnable = False; - ColorWriteEnable = 0x0f; - - VertexShader = compile vs_3_0 ViewProjectionVS(); - PixelShader = compile ps_3_0 DirectMaskPS(); - } -} - -technique Aliased -{ - pass PASS_STENCIL_ODDEVEN - { - TwoSidedStencilMode = False; - StencilEnable = True; - StencilPass = Invert; - StencilFunc = Always; - ColorWriteEnable = 0; - - ZEnable = False; - ZWriteEnable = False; - - VertexShader = compile vs_1_1 NoTxAliasedVS(); - PixelShader = compile ps_2_0 DirectSimplePS(); - } - - pass PASS_STENCIL_WINDING - { - TwoSidedStencilMode = True; - StencilEnable = True; - StencilRef = 0; - StencilMask = 0xFFFFFFFF; - - CCW_StencilPass = Incr; - CCW_StencilFunc = Always; - - StencilPass = Decr; - StencilFunc = Always; - - ColorWriteEnable = 0; - - ZEnable = False; - ZWriteEnable = False; - - VertexShader = compile vs_1_1 NoTxAliasedVS(); - PixelShader = compile ps_2_0 DirectSimplePS(); - } - - pass PASS_STENCIL_DRAW - { - TwoSidedStencilMode = False; - StencilEnable = True; - StencilFunc = NotEqual; - StencilMask = 0xFFFFFFFF; - StencilRef = 0; - StencilPass = Zero; - StencilFail = Zero; - StencilZFail = Zero; - - ColorWriteEnable = 0x0f; - ZEnable = True; - ZWriteEnable = False; - ZFunc = Greater; - - VertexShader = compile vs_1_1 AliasedVS(); - PixelShader = compile ps_2_0 SimplePS(); - } - - pass PASS_STENCIL_DRAW_DIRECT - { - TwoSidedStencilMode = False; - StencilEnable = True; - StencilFunc = NotEqual; - StencilMask = 0xFFFFFFFF; - StencilRef = 0; - StencilPass = Zero; - StencilFail = Zero; - StencilZFail = Zero; - - ColorWriteEnable = 0x0f; - ZEnable = True; - ZWriteEnable = False; - ZFunc = Greater; - - VertexShader = compile vs_1_1 AliasedVS(); - PixelShader = compile ps_2_0 DirectSimplePS(); - } - - pass PASS_STENCIL_CLIP - { - TwoSidedStencilMode = False; - StencilEnable = True; - StencilFunc = NotEqual; - StencilMask = 0xFFFFFFFF; - StencilRef = 0; - StencilPass = Zero; - StencilFail = Zero; - StencilZFail = Zero; - - ColorWriteEnable = 0; - ZEnable = True; - ZWriteEnable = True; - ZFunc = Always; - - VertexShader = compile vs_1_1 NoTxAliasedVS(); - PixelShader = compile ps_2_0 DirectSimplePS(); - } - - pass PASS_STENCIL_NOSTENCILCHECK - { - StencilEnable = False; - - ZEnable = True; - ZWriteEnable = False; - ZFunc = Greater; - - ColorWriteEnable = 0x0f; - - SrcBlend = SrcAlpha; - DestBlend = InvSrcAlpha; - - VertexShader = compile vs_1_1 AliasedVS(); - PixelShader = compile ps_2_0 SimplePS(); - } - - pass PASS_STENCIL_NOSTENCILCHECK_DIRECT - { - StencilEnable = False; - - ZEnable = True; - ZWriteEnable = False; - ZFunc = Greater; - - ColorWriteEnable = 0x0f; - - SrcBlend = SrcAlpha; - DestBlend = InvSrcAlpha; - - VertexShader = compile vs_1_1 AliasedVS(); - PixelShader = compile ps_2_0 DirectSimplePS(); - } - - pass PASS_TEXT - { - StencilEnable = False; - - ZEnable = True; - ZWriteEnable = False; - ZFunc = Greater; - - ColorWriteEnable = 0x0f; - - SrcBlend = SrcAlpha; - DestBlend = InvSrcAlpha; - - VertexShader = compile vs_1_1 AliasedVS(); - PixelShader = compile ps_2_0 TextPS(); - } - - pass PASS_CLEARTYPE_TEXT - { - StencilEnable = False; - - ZEnable = True; - ZWriteEnable = False; - ZFunc = Greater; - - ColorWriteEnable = 0x0f; - -// SrcBlend = SrcAlpha; -// DestBlend = InvSrcAlpha; - -// SrcBlend = DestColor; -// DestBlend = Zero; - SrcBlend = BlendFactor; - DestBlend = InvSrcColor; - -// SrcBlend = Zero; -// DestBlend = SrcColor; - -// SrcBlend = One; -// DestBlend = Zero; - - VertexShader = compile vs_3_0 AliasedVS(); - PixelShader = compile ps_3_0 ClearTypePS(); - } - - pass PASS_ALIASED_LINES - { - TwoSidedStencilMode = False; - StencilEnable = True; - StencilPass = Invert; - StencilFunc = Always; - ColorWriteEnable = 0; - - ZEnable = False; - ZWriteEnable = False; - - VertexShader = compile vs_1_1 AliasedLinesVS(); - PixelShader = compile ps_2_0 DirectSimplePS(); - } - - pass PASS_ALIASED_LINES_DIRECT - { - StencilEnable = False; - - ZEnable = True; - ZWriteEnable = False; - ZFunc = Greater; - - ColorWriteEnable = 0x0f; - - SrcBlend = SrcAlpha; - DestBlend = InvSrcAlpha; - - VertexShader = compile vs_1_1 AliasedLinesVS(); - PixelShader = compile ps_2_0 DirectSimplePS(); - } -} - diff --git a/src/gui/painting/qpaintengine_d3d.qrc b/src/gui/painting/qpaintengine_d3d.qrc deleted file mode 100644 index c106f2b..0000000 --- a/src/gui/painting/qpaintengine_d3d.qrc +++ /dev/null @@ -1,5 +0,0 @@ -<!DOCTYPE RCC><RCC version="1.0"> -<qresource> - <file>qpaintengine_d3d.fx</file> -</qresource> -</RCC> diff --git a/src/gui/painting/qpaintengine_d3d_p.h b/src/gui/painting/qpaintengine_d3d_p.h deleted file mode 100644 index e366a41..0000000 --- a/src/gui/painting/qpaintengine_d3d_p.h +++ /dev/null @@ -1,120 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPAINTENGINE_D3D_P_H -#define QPAINTENGINE_D3D_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "QtGui/qpaintengine.h" -#include <d3d9.h> - -QT_BEGIN_NAMESPACE - -class QDirect3DPaintEnginePrivate; -class QDirect3DPaintEngine : public QPaintEngine -{ - Q_DECLARE_PRIVATE(QDirect3DPaintEngine) -public: - QDirect3DPaintEngine(); - ~QDirect3DPaintEngine(); - bool begin(QPaintDevice *device); - - void drawEllipse(const QRectF &rect); - void drawEllipse(const QRect &rect); - - void drawImage(const QRectF &rectangle, const QImage &image, const QRectF &sr, - Qt::ImageConversionFlags flags = Qt::AutoColor); - - void drawLines(const QLineF *lines, int lineCount); - void drawLines(const QLine *lines, int lineCount); - - void drawPath(const QPainterPath &path); - - void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); - - void drawPoints(const QPointF *points, int pointCount); - void drawPoints(const QPoint *points, int pointCount); - - void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); - void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode); - - void drawRects(const QRectF *rects, int rectCount); - void drawRects(const QRect * rects, int rectCount); - - void drawTextItem(const QPointF &p, const QTextItem &textItem); - - void drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr); - - bool end(); - - Type type() const { return Direct3D; } - void updateState(const QPaintEngineState &state); - - void cleanup(); - - HDC getDC() const; - void setFlushOnEnd(bool flushOnEnd); - bool hasDirect3DSupport(); - -public: - void scroll(QPaintDevice *pd, const RECT &srcrect, const RECT &destrect); - LPDIRECT3DSWAPCHAIN9 swapChain(QPaintDevice *pd); - void releaseSwapChain(QPaintDevice *pd); - -private: - Q_DISABLE_COPY(QDirect3DPaintEngine) - friend class QPixmap; - friend class QD3DGlyphCache; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/gui/painting/qpaintengine_mac.cpp b/src/gui/painting/qpaintengine_mac.cpp index 40ab95e..934b385 100644 --- a/src/gui/painting/qpaintengine_mac.cpp +++ b/src/gui/painting/qpaintengine_mac.cpp @@ -102,14 +102,9 @@ QMacCGContext::QMacCGContext(QPainter *p) extern CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice); CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pe->paintDevice()); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) uint flags = kCGImageAlphaPremultipliedFirst; #ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - flags |= kCGBitmapByteOrder32Host; -#endif -#else - CGImageAlphaInfo flags = kCGImageAlphaPremultipliedFirst; + flags |= kCGBitmapByteOrder32Host; #endif const QImage *image = (const QImage *) pe->paintDevice(); @@ -131,8 +126,8 @@ QMacCGContext::QMacCGContext(QPainter *p) QPainterState *state = static_cast<QPainterState *>(pe->state); Q_ASSERT(state); - if (!state->redirection_offset.isNull()) - CGContextTranslateCTM(context, -state->redirection_offset.x(), -state->redirection_offset.y()); + if (!state->redirectionMatrix.isIdentity()) + CGContextTranslateCTM(context, state->redirectionMatrix.dx(), state->redirectionMatrix.dy()); } } CGContextRetain(context); @@ -528,23 +523,12 @@ static void qt_mac_dispose_pattern(void *info) inline static QPaintEngine::PaintEngineFeatures qt_mac_cg_features() { - QPaintEngine::PaintEngineFeatures ret(QPaintEngine::AllFeatures - & ~QPaintEngine::PaintOutsidePaintEvent - & ~QPaintEngine::PerspectiveTransform - & ~QPaintEngine::ConicalGradientFill - & ~QPaintEngine::LinearGradientFill - & ~QPaintEngine::RadialGradientFill - & ~QPaintEngine::BrushStroke); - -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - ; - } else -#endif - { - ret &= ~QPaintEngine::BlendModes; - } - return ret; + return QPaintEngine::PaintEngineFeatures(QPaintEngine::AllFeatures & ~QPaintEngine::PaintOutsidePaintEvent + & ~QPaintEngine::PerspectiveTransform + & ~QPaintEngine::ConicalGradientFill + & ~QPaintEngine::LinearGradientFill + & ~QPaintEngine::RadialGradientFill + & ~QPaintEngine::BrushStroke); } QCoreGraphicsPaintEngine::QCoreGraphicsPaintEngine() @@ -994,22 +978,8 @@ void QCoreGraphicsPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, co CGContextSetFillColorWithColor(d->hd, cgColorForQColor(col, d->pdev)); image = qt_mac_create_imagemask(pm, sr); } else if (differentSize) { -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - QCFType<CGImageRef> img = pm.toMacCGImageRef(); - image = CGImageCreateWithImageInRect(img, CGRectMake(qRound(sr.x()), qRound(sr.y()), qRound(sr.width()), qRound(sr.height()))); - } else -#endif - { - const int sx = qRound(sr.x()), sy = qRound(sr.y()), sw = qRound(sr.width()), sh = qRound(sr.height()); - const QMacPixmapData *pmData = static_cast<const QMacPixmapData*>(pm.data); - quint32 *pantherData = pmData->pixels + sy * (pmData->bytesPerRow / 4) + sx; - QCFType<CGDataProviderRef> provider = CGDataProviderCreateWithData(0, pantherData, sw*sh*pmData->bytesPerRow, 0); - image = CGImageCreate(sw, sh, 8, 32, pmData->bytesPerRow, - macGenericColorSpace(), - kCGImageAlphaPremultipliedFirst, provider, 0, 0, - kCGRenderingIntentDefault); - } + QCFType<CGImageRef> img = pm.toMacCGImageRef(); + image = CGImageCreateWithImageInRect(img, CGRectMake(qRound(sr.x()), qRound(sr.y()), qRound(sr.width()), qRound(sr.height()))); } else { image = (CGImageRef)pm.macCGHandle(); } @@ -1031,11 +1001,7 @@ CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imag else image = new QImage(img); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) uint cgflags = kCGImageAlphaNone; -#else - CGImageAlphaInfo cgflags = kCGImageAlphaNone; -#endif switch (image->format()) { case QImage::Format_ARGB32_Premultiplied: cgflags = kCGImageAlphaPremultipliedFirst; @@ -1048,9 +1014,8 @@ CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imag default: break; } -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) && defined(kCGBitmapByteOrder32Host) //only needed because CGImage.h added symbols in the minor version - if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - cgflags |= kCGBitmapByteOrder32Host; +#if defined(kCGBitmapByteOrder32Host) //only needed because CGImage.h added symbols in the minor version + cgflags |= kCGBitmapByteOrder32Host; #endif QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(image, static_cast<const QImage *>(image)->bits(), @@ -1078,27 +1043,9 @@ void QCoreGraphicsPaintEngine::drawImage(const QRectF &r, const QImage &img, con const QImage *image; QCFType<CGImageRef> cgimage = qt_mac_createCGImageFromQImage(img, &image); CGRect rect = CGRectMake(r.x(), r.y(), r.width(), r.height()); - if (QRectF(0, 0, img.width(), img.height()) != sr) { -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - cgimage = CGImageCreateWithImageInRect(cgimage, CGRectMake(sr.x(), sr.y(), - sr.width(), sr.height())); - } else -#endif - { - int sx = qRound(sr.x()); - int sy = qRound(sr.y()); - int sw = qRound(sr.width()); - int sh = qRound(sr.height()); - // Make another CGImage based on the part that we need. - const uchar *pantherData = image->scanLine(sy) + sx * sizeof(uint); - QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(0, pantherData, - sw * sh * image->bytesPerLine(), 0); - cgimage = CGImageCreate(sw, sh, 8, 32, image->bytesPerLine(), - macGenericColorSpace(), - CGImageGetAlphaInfo(cgimage), dataProvider, 0, false, kCGRenderingIntentDefault); - } - } + if (QRectF(0, 0, img.width(), img.height()) != sr) + cgimage = CGImageCreateWithImageInRect(cgimage, CGRectMake(sr.x(), sr.y(), + sr.width(), sr.height())); qt_mac_drawCGImage(d->hd, &rect, cgimage); } @@ -1434,8 +1381,13 @@ QCoreGraphicsPaintEngine::updateRenderHints(QPainter::RenderHints hints) { Q_D(QCoreGraphicsPaintEngine); CGContextSetShouldAntialias(d->hd, hints & QPainter::Antialiasing); - CGContextSetInterpolationQuality(d->hd, (hints & QPainter::SmoothPixmapTransform) ? - kCGInterpolationHigh : kCGInterpolationNone); + static const CGFloat ScaleFactor = qt_mac_get_scalefactor(); + if (ScaleFactor > 1.) { + CGContextSetInterpolationQuality(d->hd, kCGInterpolationHigh); + } else { + CGContextSetInterpolationQuality(d->hd, (hints & QPainter::SmoothPixmapTransform) ? + kCGInterpolationHigh : kCGInterpolationNone); + } CGContextSetShouldSmoothFonts(d->hd, hints & QPainter::TextAntialiasing); } diff --git a/src/gui/painting/qpaintengine_mac_p.h b/src/gui/painting/qpaintengine_mac_p.h index e1503ce..cffd1a7 100644 --- a/src/gui/painting/qpaintengine_mac_p.h +++ b/src/gui/painting/qpaintengine_mac_p.h @@ -58,9 +58,6 @@ #include "private/qpaintengine_p.h" #include "private/qpolygonclipper_p.h" #include "QtCore/qhash.h" -#ifndef QT_MAC_NO_QUICKDRAW -#include <private/qwidget_p.h> -#endif typedef struct CGColorSpace *CGColorSpaceRef; QT_BEGIN_NAMESPACE @@ -69,108 +66,6 @@ extern int qt_defaultDpi(); extern int qt_defaultDpiX(); extern int qt_defaultDpiY(); -#ifndef QT_MAC_NO_QUICKDRAW -class QMacSavedPortInfo -{ - RgnHandle clip; - GWorldPtr world; - GDHandle handle; - PenState pen; //go pennstate - RGBColor back, fore; - bool valid_gworld; - void init(); - -public: - inline QMacSavedPortInfo() { init(); } - inline QMacSavedPortInfo(QPaintDevice *pd) { init(); setPaintDevice(pd); } - inline QMacSavedPortInfo(QPaintDevice *pd, const QRect &r) - { init(); setPaintDevice(pd); setClipRegion(r); } - inline QMacSavedPortInfo(QPaintDevice *pd, const QRegion &r) - { init(); setPaintDevice(pd); setClipRegion(r); } - ~QMacSavedPortInfo(); - static inline bool setClipRegion(const QRect &r); - static inline bool setClipRegion(const QRegion &r); - static inline bool setPaintDevice(QPaintDevice *); -}; - -inline bool -QMacSavedPortInfo::setClipRegion(const QRect &rect) -{ - Rect r; - SetRect(&r, rect.x(), rect.y(), rect.right()+1, rect.bottom()+1); - ClipRect(&r); - return true; -} - -inline bool -QMacSavedPortInfo::setClipRegion(const QRegion &r) -{ - if(r.isEmpty()) - return setClipRegion(QRect()); - QMacSmartQuickDrawRegion rgn(r.toQDRgn()); - SetClip(rgn); - return true; -} - -inline bool -QMacSavedPortInfo::setPaintDevice(QPaintDevice *pd) -{ - if(!pd) - return false; - bool ret = true; - extern GrafPtr qt_mac_qd_context(const QPaintDevice *); // qpaintdevice_mac.cpp - if(pd->devType() == QInternal::Widget) - SetPortWindowPort(qt_mac_window_for(static_cast<QWidget*>(pd))); - else if(pd->devType() == QInternal::Pixmap || pd->devType() == QInternal::Printer) - SetGWorld((GrafPtr)qt_mac_qd_context(pd), 0); //set the gworld - return ret; -} - -inline void -QMacSavedPortInfo::init() -{ - GetBackColor(&back); - GetForeColor(&fore); - GetGWorld(&world, &handle); - valid_gworld = true; - clip = NewRgn(); - GetClip(clip); - GetPenState(&pen); -} - -inline QMacSavedPortInfo::~QMacSavedPortInfo() -{ - bool set_state = false; - if(valid_gworld) { - set_state = IsValidPort(world); - if(set_state) - SetGWorld(world,handle); //always do this one first - } else { - setPaintDevice(qt_mac_safe_pdev); - } - if(set_state) { - SetClip(clip); - SetPenState(&pen); - RGBForeColor(&fore); - RGBBackColor(&back); - } - DisposeRgn(clip); -} -#else -class QMacSavedPortInfo -{ -public: - inline QMacSavedPortInfo() { } - inline QMacSavedPortInfo(QPaintDevice *) { } - inline QMacSavedPortInfo(QPaintDevice *, const QRect &) { } - inline QMacSavedPortInfo(QPaintDevice *, const QRegion &) { } - ~QMacSavedPortInfo() { } - static inline bool setClipRegion(const QRect &) { return false; } - static inline bool setClipRegion(const QRegion &) { return false; } - static inline bool setPaintDevice(QPaintDevice *) { return false; } -}; -#endif - class QCoreGraphicsPaintEnginePrivate; class QCoreGraphicsPaintEngine : public QPaintEngine { @@ -233,6 +128,8 @@ protected: friend class QMacPrintEngine; friend class QMacPrintEnginePrivate; friend void qt_mac_display_change_callbk(CGDirectDisplayID, CGDisplayChangeSummaryFlags, void *); + friend void qt_color_profile_changed(CFNotificationCenterRef center, void *, + CFStringRef , const void *, CFDictionaryRef); QCoreGraphicsPaintEngine(QPaintEnginePrivate &dptr); private: diff --git a/src/gui/painting/qpaintengine_p.h b/src/gui/painting/qpaintengine_p.h index 74fd313..c18bd6c 100644 --- a/src/gui/painting/qpaintengine_p.h +++ b/src/gui/painting/qpaintengine_p.h @@ -72,6 +72,7 @@ public: QPaintDevice *pdev; QPaintEngine *q_ptr; QRegion systemClip; + QRect systemRect; QRegion systemViewport; QTransform systemTransform; QWidget *currentClipWidget; @@ -117,9 +118,6 @@ public: virtual void systemStateChanged() { } void drawBoxTextItem(const QPointF &p, const QTextItemInt &ti); - -private: - QRect systemRect; }; QT_END_NAMESPACE diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 7fce65e..86b2d0f 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -91,6 +91,8 @@ # include <private/qfontengine_qpf_p.h> # endif # include <private/qabstractfontengine_p.h> +#elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) +# include <private/qfontengine_s60_p.h> #endif #if defined(Q_WS_WIN64) @@ -110,10 +112,6 @@ extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // #define qt_swap_int(x, y) { int tmp = (x); (x) = (y); (y) = tmp; } #define qt_swap_qreal(x, y) { qreal tmp = (x); (x) = (y); (y) = tmp; } -#ifdef Q_WS_WIN -static bool qt_enable_16bit_colors = false; -#endif - // #define QT_DEBUG_DRAW #ifdef QT_DEBUG_DRAW void dumpClip(int width, int height, QClipData *clip); @@ -139,7 +137,6 @@ extern bool qt_cleartype_enabled; * Span functions */ static void qt_span_fill_clipRect(int count, const QSpan *spans, void *userData); -static void qt_span_fill_clipRegion(int count, const QSpan *spans, void *userData); static void qt_span_fill_clipped(int count, const QSpan *spans, void *userData); static void qt_span_clip(int count, const QSpan *spans, void *userData); static void qt_merge_clip(const QClipData *c1, const QClipData *c2, QClipData *result); @@ -347,31 +344,36 @@ void QRasterPaintEngine::init() #else (unsigned char *) malloc(d->rasterPoolSize); #endif + Q_CHECK_PTR(d->rasterPoolBase); // The antialiasing raster. - d->grayRaster = new QT_FT_Raster; - qt_ft_grays_raster.raster_new(0, d->grayRaster); - qt_ft_grays_raster.raster_reset(*d->grayRaster, d->rasterPoolBase, d->rasterPoolSize); + d->grayRaster.reset(new QT_FT_Raster); + Q_CHECK_PTR(d->grayRaster.data()); + if (qt_ft_grays_raster.raster_new(0, d->grayRaster.data())) + QT_THROW(std::bad_alloc()); // an error creating the raster is caused by a bad malloc + + + qt_ft_grays_raster.raster_reset(*d->grayRaster.data(), d->rasterPoolBase, d->rasterPoolSize); - d->rasterizer = new QRasterizer; - d->rasterBuffer = new QRasterBuffer(); - d->outlineMapper = new QOutlineMapper; + d->rasterizer.reset(new QRasterizer); + d->rasterBuffer.reset(new QRasterBuffer()); + d->outlineMapper.reset(new QOutlineMapper); d->outlinemapper_xform_dirty = true; d->basicStroker.setMoveToHook(qt_ft_outline_move_to); d->basicStroker.setLineToHook(qt_ft_outline_line_to); d->basicStroker.setCubicToHook(qt_ft_outline_cubic_to); - d->dashStroker = 0; - d->baseClip = 0; + d->baseClip.reset(new QClipData(d->device->height())); + d->baseClip->setClipRect(QRect(0, 0, d->device->width(), d->device->height())); - d->image_filler.init(d->rasterBuffer, this); + d->image_filler.init(d->rasterBuffer.data(), this); d->image_filler.type = QSpanData::Texture; - d->image_filler_xform.init(d->rasterBuffer, this); + d->image_filler_xform.init(d->rasterBuffer.data(), this); d->image_filler_xform.type = QSpanData::Texture; - d->solid_color_filler.init(d->rasterBuffer, this); + d->solid_color_filler.init(d->rasterBuffer.data(), this); d->solid_color_filler.type = QSpanData::Solid; d->deviceDepth = d->device->depth(); @@ -440,13 +442,7 @@ QRasterPaintEngine::~QRasterPaintEngine() free(d->rasterPoolBase); #endif - qt_ft_grays_raster.raster_done(*d->grayRaster); - delete d->grayRaster; - - delete d->rasterBuffer; - delete d->outlineMapper; - delete d->rasterizer; - delete d->dashStroker; + qt_ft_grays_raster.raster_done(*d->grayRaster.data()); } /*! @@ -482,13 +478,13 @@ bool QRasterPaintEngine::begin(QPaintDevice *device) d->rasterizer->setClipRect(d->deviceRect); - s->penData.init(d->rasterBuffer, this); - s->penData.setup(s->pen.brush(), s->intOpacity); + s->penData.init(d->rasterBuffer.data(), this); + s->penData.setup(s->pen.brush(), s->intOpacity, s->composition_mode); s->stroker = &d->basicStroker; d->basicStroker.setClipRect(d->deviceRect); - s->brushData.init(d->rasterBuffer, this); - s->brushData.setup(s->brush, s->intOpacity); + s->brushData.init(d->rasterBuffer.data(), this); + s->brushData.setup(s->brush, s->intOpacity, s->composition_mode); d->rasterBuffer->compositionMode = QPainter::CompositionMode_SourceOver; @@ -509,16 +505,20 @@ bool QRasterPaintEngine::begin(QPaintDevice *device) if (d->mono_surface) d->glyphCacheType = QFontEngineGlyphCache::Raster_Mono; -#ifdef Q_WS_WIN - else if (qt_cleartype_enabled) { +#if defined(Q_WS_WIN) + else if (qt_cleartype_enabled) +#elif defined (Q_WS_MAC) + else if (true) +#else + else if (false) +#endif + { QImage::Format format = static_cast<QImage *>(d->device)->format(); if (format == QImage::Format_ARGB32_Premultiplied || format == QImage::Format_RGB32) d->glyphCacheType = QFontEngineGlyphCache::Raster_RGBMask; else d->glyphCacheType = QFontEngineGlyphCache::Raster_A8; - } -#endif - else + } else d->glyphCacheType = QFontEngineGlyphCache::Raster_A8; setActive(true); @@ -530,19 +530,14 @@ bool QRasterPaintEngine::begin(QPaintDevice *device) */ bool QRasterPaintEngine::end() { - Q_D(QRasterPaintEngine); #ifdef QT_DEBUG_DRAW + Q_D(QRasterPaintEngine); qDebug() << "QRasterPaintEngine::end devRect:" << d->deviceRect; if (d->baseClip) { dumpClip(d->rasterBuffer->width(), d->rasterBuffer->height(), d->baseClip); } #endif - if (d->baseClip) { - delete d->baseClip; - d->baseClip = 0; - } - return true; } @@ -552,8 +547,7 @@ bool QRasterPaintEngine::end() void QRasterPaintEngine::releaseBuffer() { Q_D(QRasterPaintEngine); - delete d->rasterBuffer; - d->rasterBuffer = new QRasterBuffer; + d->rasterBuffer.reset(new QRasterBuffer); } /*! @@ -618,22 +612,22 @@ void QRasterPaintEngine::updateMatrix(const QTransform &matrix) d->isPlain45DegreeRotation = false; if (txop >= QTransform::TxRotate) { d->isPlain45DegreeRotation = - (qFuzzyCompare(matrix.m11() + 1, qreal(1)) - && qFuzzyCompare(matrix.m12(), qreal(1)) - && qFuzzyCompare(matrix.m21(), qreal(-1)) - && qFuzzyCompare(matrix.m22() + 1, qreal(1)) + (qFuzzyIsNull(matrix.m11()) + && qFuzzyIsNull(matrix.m12() - qreal(1)) + && qFuzzyIsNull(matrix.m21() + qreal(1)) + && qFuzzyIsNull(matrix.m22()) ) || - (qFuzzyCompare(matrix.m11(), qreal(-1)) - && qFuzzyCompare(matrix.m12() + 1, qreal(1)) - && qFuzzyCompare(matrix.m21() + 1, qreal(1)) - && qFuzzyCompare(matrix.m22(), qreal(-1)) + (qFuzzyIsNull(matrix.m11() + qreal(1)) + && qFuzzyIsNull(matrix.m12()) + && qFuzzyIsNull(matrix.m21()) + && qFuzzyIsNull(matrix.m22() + qreal(1)) ) || - (qFuzzyCompare(matrix.m11() + 1, qreal(1)) - && qFuzzyCompare(matrix.m12(), qreal(-1)) - && qFuzzyCompare(matrix.m21(), qreal(1)) - && qFuzzyCompare(matrix.m22() + 1, qreal(1)) + (qFuzzyIsNull(matrix.m11()) + && qFuzzyIsNull(matrix.m12() + qreal(1)) + && qFuzzyIsNull(matrix.m21() - qreal(1)) + && qFuzzyIsNull(matrix.m22()) ) ; } @@ -769,7 +763,7 @@ void QRasterPaintEngine::updatePen(const QPen &pen) s->strokeFlags = 0; s->penData.clip = d->clip(); - s->penData.setup(pen_style == Qt::NoPen ? QBrush() : pen.brush(), s->intOpacity); + s->penData.setup(pen_style == Qt::NoPen ? QBrush() : pen.brush(), s->intOpacity, s->composition_mode); if (s->strokeFlags & QRasterPaintEngine::DirtyTransform || pen.brush().transform().type() >= QTransform::TxNone) { @@ -798,7 +792,7 @@ void QRasterPaintEngine::updatePen(const QPen &pen) s->stroker = &d->basicStroker; } else if (pen_style != Qt::NoPen) { if (!d->dashStroker) - d->dashStroker = new QDashStroker(&d->basicStroker); + d->dashStroker.reset(new QDashStroker(&d->basicStroker)); if (pen.isCosmetic()) { d->dashStroker->setClipRect(d->deviceRect); } else { @@ -808,7 +802,7 @@ void QRasterPaintEngine::updatePen(const QPen &pen) } d->dashStroker->setDashPattern(pen.dashPattern()); d->dashStroker->setDashOffset(pen.dashOffset()); - s->stroker = d->dashStroker; + s->stroker = d->dashStroker.data(); } else { s->stroker = 0; } @@ -869,7 +863,7 @@ void QRasterPaintEngine::updateBrush(const QBrush &brush) QRasterPaintEngineState *s = state(); // must set clip prior to setup, as setup uses it... s->brushData.clip = d->clip(); - s->brushData.setup(brush, s->intOpacity); + s->brushData.setup(brush, s->intOpacity, s->composition_mode); if (s->fillFlags & DirtyTransform || brush.transform().type() >= QTransform::TxNone) d_func()->updateMatrixData(&s->brushData, brush, d->brushMatrix()); @@ -1024,6 +1018,7 @@ void QRasterPaintEnginePrivate::drawImage(const QPointF &pt, { if (alpha == 0 || !clip.isValid()) return; + Q_ASSERT(img.depth() >= 8); int srcBPL = img.bytesPerLine(); @@ -1092,11 +1087,10 @@ void QRasterPaintEnginePrivate::systemStateChanged() if (!systemClip.isEmpty()) { QRegion clippedDeviceRgn = systemClip & clipRect; deviceRect = clippedDeviceRgn.boundingRect(); - delete baseClip; - baseClip = new QClipData(device->height()); baseClip->setClipRegion(clippedDeviceRgn); } else { deviceRect = clipRect; + baseClip->setClipRect(deviceRect); } #ifdef QT_DEBUG_DRAW qDebug() << "systemStateChanged" << this << "deviceRect" << deviceRect << clipRect << systemClip; @@ -1171,6 +1165,25 @@ static void checkClipRatios(QRasterPaintEnginePrivate *d) } #endif +static void qrasterpaintengine_state_setNoClip(QRasterPaintEngineState *s) +{ + if (s->flags.has_clip_ownership) + delete s->clip; + s->clip = 0; + s->flags.has_clip_ownership = false; +} + +static void qrasterpaintengine_dirty_clip(QRasterPaintEnginePrivate *d, QRasterPaintEngineState *s) +{ + s->fillFlags |= QPaintEngine::DirtyClipPath; + s->strokeFlags |= QPaintEngine::DirtyClipPath; + s->pixmapFlags |= QPaintEngine::DirtyClipPath; + + d->solid_color_filler.clip = d->clip(); + d->solid_color_filler.adjustSpanMethods(); +} + + /*! \internal */ @@ -1182,12 +1195,12 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) if (path.elements()) { for (int i=0; i<path.elementCount(); ++i) { qDebug() << " - " << path.elements()[i] - << "(" << path.points()[i*2] << ", " << path.points()[i*2+1] << ")"; + << '(' << path.points()[i*2] << ", " << path.points()[i*2+1] << ')'; } } else { for (int i=0; i<path.elementCount(); ++i) { qDebug() << " ---- " - << "(" << path.points()[i*2] << ", " << path.points()[i*2+1] << ")"; + << '(' << path.points()[i*2] << ", " << path.points()[i*2+1] << ')'; } } #endif @@ -1219,13 +1232,10 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) } if (op == Qt::NoClip) { - if (s->flags.has_clip_ownership) - delete s->clip; - s->clip = 0; - s->flags.has_clip_ownership = false; + qrasterpaintengine_state_setNoClip(s); } else { - QClipData *base = d->baseClip; + QClipData *base = d->baseClip.data(); // Intersect with current clip when available... if (op == Qt::IntersectClip && s->clip) @@ -1264,17 +1274,7 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) s->clip = newClip; s->flags.has_clip_ownership = true; } - - s->fillFlags |= DirtyClipPath; - s->strokeFlags |= DirtyClipPath; - s->pixmapFlags |= DirtyClipPath; - - d->solid_color_filler.clip = d->clip(); - d->solid_color_filler.adjustSpanMethods(); - -#ifdef QT_CLIPPING_RATIOS - checkClipRatios(d); -#endif + qrasterpaintengine_dirty_clip(d, s); } @@ -1292,10 +1292,7 @@ void QRasterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op) QRasterPaintEngineState *s = state(); if (op == Qt::NoClip) { - if (s->flags.has_clip_ownership) - delete s->clip; - s->clip = d->baseClip; - s->flags.has_clip_ownership = false; + qrasterpaintengine_state_setNoClip(s); } else if (op == Qt::UniteClip || s->matrix.type() > QTransform::TxScale) { QPaintEngineEx::clip(rect, op); @@ -1341,37 +1338,63 @@ void QRasterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op) return; } } - - s->brushData.clip = d->clip(); - s->penData.clip = d->clip(); - - s->fillFlags |= DirtyClipPath; - s->strokeFlags |= DirtyClipPath; - s->pixmapFlags |= DirtyClipPath; - - d->solid_color_filler.clip = d->clip(); - d->solid_color_filler.adjustSpanMethods(); - - -#ifdef QT_CLIPPING_RATIOS - checkClipRatios(d); -#endif + qrasterpaintengine_dirty_clip(d, s); } + /*! \internal */ void QRasterPaintEngine::clip(const QRegion ®ion, Qt::ClipOperation op) { - QPaintEngineEx::clip(region, op); -} +#ifdef QT_DEBUG_DRAW + qDebug() << "QRasterPaintEngine::clip(): " << region << op; +#endif -/*! - \internal -*/ -void QRasterPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op) -{ - QPaintEngineEx::clip(path, op); + Q_D(QRasterPaintEngine); + + if (region.numRects() == 1) { + clip(region.boundingRect(), op); + return; + } + + QRasterPaintEngineState *s = state(); + const QClipData *clip = d->clip(); + const QClipData *baseClip = d->baseClip.data(); + + if (op == Qt::NoClip) { + qrasterpaintengine_state_setNoClip(s); + } else if (s->matrix.type() > QTransform::TxScale + || op == Qt::UniteClip + || (op == Qt::IntersectClip && !clip->hasRectClip && !clip->hasRegionClip) + || (op == Qt::ReplaceClip && !baseClip->hasRectClip && !baseClip->hasRegionClip)) { + QPaintEngineEx::clip(region, op); + } else { + const QClipData *curClip; + QClipData *newClip; + + if (op == Qt::IntersectClip) + curClip = clip; + else + curClip = baseClip; + + if (s->flags.has_clip_ownership) { + newClip = s->clip; + Q_ASSERT(newClip); + } else { + newClip = new QClipData(d->rasterBuffer->height()); + s->clip = newClip; + s->flags.has_clip_ownership = true; + } + + QRegion r = s->matrix.map(region); + if (curClip->hasRectClip) + newClip->setClipRegion(r & curClip->clipRect); + else if (curClip->hasRegionClip) + newClip->setClipRegion(r & clip->clipRegion); + + qrasterpaintengine_dirty_clip(d, s); + } } /*! @@ -1405,7 +1428,7 @@ void QRasterPaintEngine::fillPath(const QPainterPath &path, QSpanData *fillData) } ensureOutlineMapper(); - d->rasterize(d->outlineMapper->convertPath(path), blend, fillData, d->rasterBuffer); + d->rasterize(d->outlineMapper->convertPath(path), blend, fillData, d->rasterBuffer.data()); } static void fillRect_normalized(const QRect &r, QSpanData *data, @@ -1413,7 +1436,7 @@ static void fillRect_normalized(const QRect &r, QSpanData *data, { int x1, x2, y1, y2; - bool rectClipped = false; + bool rectClipped = true; if (data->clip) { x1 = qMax(r.x(), data->clip->xmin); @@ -1643,34 +1666,6 @@ void QRasterPaintEngine::drawRects(const QRectF *rects, int rectCount) QPaintEngineEx::drawRects(rects, rectCount); } -void QRasterPaintEnginePrivate::strokeProjective(const QPainterPath &path) -{ - Q_Q(QRasterPaintEngine); - QRasterPaintEngineState *s = q->state(); - - const QPen &pen = s->lastPen; - QPainterPathStroker pathStroker; - pathStroker.setWidth(pen.width() == 0 ? qreal(1) : pen.width()); - pathStroker.setCapStyle(pen.capStyle()); - pathStroker.setJoinStyle(pen.joinStyle()); - pathStroker.setMiterLimit(pen.miterLimit()); - pathStroker.setDashOffset(pen.dashOffset()); - - if (qpen_style(pen) == Qt::CustomDashLine) - pathStroker.setDashPattern(pen.dashPattern()); - else - pathStroker.setDashPattern(qpen_style(pen)); - - outlineMapper->setMatrix(QTransform()); - const QPainterPath stroke = pen.isCosmetic() - ? pathStroker.createStroke(s->matrix.map(path)) - : s->matrix.map(pathStroker.createStroke(path)); - - rasterize(outlineMapper->convertPath(stroke), s->penData.blend, &s->penData, rasterBuffer); - outlinemapper_xform_dirty = true; -} - - /*! \internal @@ -1735,6 +1730,8 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) const QLineF *lines = reinterpret_cast<const QLineF *>(path.points()); for (int i = 0; i < lineCount; ++i) { + if (path.shape() == QVectorPath::LinesHint) + dashOffset = s->lastPen.dashOffset(); if (lines[i].p1() == lines[i].p2()) { if (s->lastPen.capStyle() != Qt::FlatCap) { QPointF p = lines[i].p1(); @@ -1762,12 +1759,17 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) static inline QRect toNormalizedFillRect(const QRectF &rect) { - const int x1 = qRound(rect.x()); - const int y1 = qRound(rect.y()); - const int x2 = qRound(rect.right()); - const int y2 = qRound(rect.bottom()); + int x1 = qRound(rect.x() + aliasedCoordinateDelta); + int y1 = qRound(rect.y() + aliasedCoordinateDelta); + int x2 = qRound(rect.right() + aliasedCoordinateDelta); + int y2 = qRound(rect.bottom() + aliasedCoordinateDelta); - return QRect(x1, y1, x2 - x1, y2 - y1).normalized(); + if (x2 < x1) + qSwap(x1, x2); + if (y2 < y1) + qSwap(y1, y2); + + return QRect(x1, y1, x2 - x1, y2 - y1); } /*! @@ -1797,9 +1799,8 @@ void QRasterPaintEngine::fill(const QVectorPath &path, const QBrush &brush) if (path.shape() == QVectorPath::RectangleHint) { if (!s->flags.antialiased && s->matrix.type() <= QTransform::TxScale) { const qreal *p = path.points(); - const QPointF offs(aliasedCoordinateDelta, aliasedCoordinateDelta); - QPointF tl = QPointF(p[0], p[1]) * s->matrix + offs; - QPointF br = QPointF(p[4], p[5]) * s->matrix + offs; + QPointF tl = QPointF(p[0], p[1]) * s->matrix; + QPointF br = QPointF(p[4], p[5]) * s->matrix; fillRect_normalized(toNormalizedFillRect(QRectF(tl, br)), &s->brushData, d); return; } @@ -1839,8 +1840,7 @@ void QRasterPaintEngine::fill(const QVectorPath &path, const QBrush &brush) } // ### Optimize for non transformed ellipses and rectangles... - QRealRect r = path.controlPointRect(); - QRectF cpRect(r.x1, r.y1, r.x2 - r.x1, r.y2 - r.y1); + QRectF cpRect = path.controlPointRect(); const QRect deviceRect = s->matrix.mapRect(cpRect).toRect(); ProcessSpans blend = d->getBrushFunc(deviceRect, &s->brushData); @@ -1858,7 +1858,7 @@ void QRasterPaintEngine::fill(const QVectorPath &path, const QBrush &brush) // } ensureOutlineMapper(); - d->rasterize(d->outlineMapper->convertPath(path), blend, &s->brushData, d->rasterBuffer); + d->rasterize(d->outlineMapper->convertPath(path), blend, &s->brushData, d->rasterBuffer.data()); } void QRasterPaintEngine::fillRect(const QRectF &r, QSpanData *data) @@ -1928,73 +1928,15 @@ void QRasterPaintEngine::fillRect(const QRectF &r, const QColor &color) QRasterPaintEngineState *s = state(); d->solid_color_filler.solid.color = PREMUL(ARGB_COMBINE_ALPHA(color.rgba(), s->intOpacity)); + if ((d->solid_color_filler.solid.color & 0xff000000) == 0 + && s->composition_mode == QPainter::CompositionMode_SourceOver) { + return; + } d->solid_color_filler.clip = d->clip(); d->solid_color_filler.adjustSpanMethods(); - fillRect(r, &d->solid_color_filler); } -/*! - \reimp -*/ -void QRasterPaintEngine::drawPath(const QPainterPath &path) -{ -#ifdef QT_DEBUG_DRAW - QRectF bounds = path.boundingRect(); - qDebug(" - QRasterPaintEngine::drawPath(), [%.2f, %.2f, %.2f, %.2f]", - bounds.x(), bounds.y(), bounds.width(), bounds.height()); -#endif - - if (path.isEmpty()) - return; - - // Filling.., - Q_D(QRasterPaintEngine); - QRasterPaintEngineState *s = state(); - - ensureBrush(); - if (s->brushData.blend) { - ensureOutlineMapper(); - fillPath(path, &s->brushData); - } - - // Stroking... - ensurePen(); - if (!s->penData.blend) - return; - { - if (s->matrix.type() >= QTransform::TxProject) { - d->strokeProjective(path); - } else { - Q_ASSERT(s->stroker); - d->outlineMapper->beginOutline(Qt::WindingFill); - qreal txscale = 1; - if (s->pen.isCosmetic() || (qt_scaleForTransform(s->matrix, &txscale) && txscale != 1)) { - const qreal strokeWidth = d->basicStroker.strokeWidth(); - const QRectF clipRect = d->dashStroker ? d->dashStroker->clipRect() : QRectF(); - if (d->dashStroker) - d->dashStroker->setClipRect(d->deviceRect); - d->basicStroker.setStrokeWidth(strokeWidth * txscale); - d->outlineMapper->setMatrix(QTransform()); - s->stroker->strokePath(path, d->outlineMapper, s->matrix); - d->outlinemapper_xform_dirty = true; - d->basicStroker.setStrokeWidth(strokeWidth); - if (d->dashStroker) - d->dashStroker->setClipRect(clipRect); - } else { - ensureOutlineMapper(); - s->stroker->strokePath(path, d->outlineMapper, QTransform()); - } - d->outlineMapper->endOutline(); - - ProcessSpans blend = d->getPenFunc(d->outlineMapper->controlPointRect, - &s->penData); - d->rasterize(d->outlineMapper->outline(), blend, &s->penData, d->rasterBuffer); - } - } - -} - static inline bool isAbove(const QPointF *a, const QPointF *b) { return a->y() < b->y(); @@ -2083,7 +2025,7 @@ void QRasterPaintEngine::fillPolygon(const QPointF *points, int pointCount, Poly // scanconvert. ProcessSpans brushBlend = d->getBrushFunc(d->outlineMapper->controlPointRect, &s->brushData); - d->rasterize(outline, brushBlend, &s->brushData, d->rasterBuffer); + d->rasterize(outline, brushBlend, &s->brushData, d->rasterBuffer.data()); } /*! @@ -2179,7 +2121,7 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg // scanconvert. ProcessSpans brushBlend = d->getBrushFunc(d->outlineMapper->controlPointRect, &s->brushData); - d->rasterize(d->outlineMapper->outline(), brushBlend, &s->brushData, d->rasterBuffer); + d->rasterize(d->outlineMapper->outline(), brushBlend, &s->brushData, d->rasterBuffer.data()); d->outlineMapper->setCoordinateRounding(false); } } @@ -2426,7 +2368,7 @@ void QRasterPaintEngine::drawPixmap(const QPointF &pos, const QPixmap &pixmap) #endif if (pixmap.data->classId() == QPixmapData::RasterClass) { - const QImage &image = ((QRasterPixmapData *) pixmap.data)->image; + const QImage &image = static_cast<QRasterPixmapData *>(pixmap.data.data())->image; if (image.depth() == 1) { Q_D(QRasterPaintEngine); QRasterPaintEngineState *s = state(); @@ -2464,7 +2406,7 @@ void QRasterPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, cons #endif if (pixmap.data->classId() == QPixmapData::RasterClass) { - const QImage &image = ((QRasterPixmapData *) pixmap.data)->image; + const QImage &image = static_cast<QRasterPixmapData *>(pixmap.data.data())->image; if (image.depth() == 1) { Q_D(QRasterPaintEngine); QRasterPaintEngineState *s = state(); @@ -2550,10 +2492,7 @@ void QRasterPaintEngine::drawImage(const QPointF &p, const QImage &img) const QClipData *clip = d->clip(); QPointF pt(p.x() + s->matrix.dx(), p.y() + s->matrix.dy()); - // ### TODO: remove this eventually... - static bool NO_BLEND_FUNC = !qgetenv("QT_NO_BLEND_FUNCTIONS").isNull(); - - if (s->flags.fast_images && !NO_BLEND_FUNC) { + if (s->flags.fast_images) { SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()]; if (func) { if (!clip) { @@ -2566,6 +2505,8 @@ void QRasterPaintEngine::drawImage(const QPointF &p, const QImage &img) } } + + d->image_filler.clip = clip; d->image_filler.initTexture(&img, s->intOpacity, QTextureData::Plain, img.rect()); if (!d->image_filler.blend) @@ -2594,11 +2535,51 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe qDebug() << " - QRasterPaintEngine::drawImage(), r=" << r << " sr=" << sr << " image=" << img.size() << "depth=" << img.depth(); #endif + if (r.isEmpty()) + return; + Q_D(QRasterPaintEngine); QRasterPaintEngineState *s = state(); const bool aa = s->flags.antialiased || s->flags.bilinear; - if (!aa && sr.size() == QSize(1, 1)) { - fillRect(r, QColor::fromRgba(img.pixel(sr.x(), sr.y()))); + int sr_l = qFloor(sr.left()); + int sr_r = qCeil(sr.right()) - 1; + int sr_t = qFloor(sr.top()); + int sr_b = qCeil(sr.bottom()) - 1; + + if (!aa && sr_l == sr_r && sr_t == sr_b) { + // as fillRect will apply the aliased coordinate delta we need to + // subtract it here as we don't use it for image drawing + QTransform old = s->matrix; + s->matrix = s->matrix * QTransform::fromTranslate(-aliasedCoordinateDelta, -aliasedCoordinateDelta); + + // Do whatever fillRect() does, but without premultiplying the color if it's already premultiplied. + QRgb color = img.pixel(sr_l, sr_t); + switch (img.format()) { + case QImage::Format_ARGB32_Premultiplied: + case QImage::Format_ARGB8565_Premultiplied: + case QImage::Format_ARGB6666_Premultiplied: + case QImage::Format_ARGB8555_Premultiplied: + case QImage::Format_ARGB4444_Premultiplied: + // Combine premultiplied color with the opacity set on the painter. + d->solid_color_filler.solid.color = + ((((color & 0x00ff00ff) * s->intOpacity) >> 8) & 0x00ff00ff) + | ((((color & 0xff00ff00) >> 8) * s->intOpacity) & 0xff00ff00); + break; + default: + d->solid_color_filler.solid.color = PREMUL(ARGB_COMBINE_ALPHA(color, s->intOpacity)); + break; + } + + if ((d->solid_color_filler.solid.color & 0xff000000) == 0 + && s->composition_mode == QPainter::CompositionMode_SourceOver) { + return; + } + + d->solid_color_filler.clip = d->clip(); + d->solid_color_filler.adjustSpanMethods(); + fillRect(r, &d->solid_color_filler); + + s->matrix = old; return; } @@ -2609,14 +2590,24 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe if (s->matrix.type() > QTransform::TxTranslate || stretch_sr) { if (s->flags.fast_images) { - SrcOverScaleFunc func = qScaleFunctions[d->rasterBuffer->format][img.format()]; - if (func && (!clip || clip->hasRectClip)) { - func(d->rasterBuffer->buffer(), d->rasterBuffer->bytesPerLine(), - img.bits(), img.bytesPerLine(), - qt_mapRect_non_normalizing(r, s->matrix), sr, - !clip ? d->deviceRect : clip->clipRect, - s->intOpacity); - return; + if (s->matrix.type() > QTransform::TxScale) { + SrcOverTransformFunc func = qTransformFunctions[d->rasterBuffer->format][img.format()]; + if (func && (!clip || clip->hasRectClip)) { + func(d->rasterBuffer->buffer(), d->rasterBuffer->bytesPerLine(), img.bits(), + img.bytesPerLine(), r, sr, !clip ? d->deviceRect : clip->clipRect, + s->matrix, s->intOpacity); + return; + } + } else { + SrcOverScaleFunc func = qScaleFunctions[d->rasterBuffer->format][img.format()]; + if (func && (!clip || clip->hasRectClip)) { + func(d->rasterBuffer->buffer(), d->rasterBuffer->bytesPerLine(), + img.bits(), img.bytesPerLine(), + qt_mapRect_non_normalizing(r, s->matrix), sr, + !clip ? d->deviceRect : clip->clipRect, + s->intOpacity); + return; + } } } @@ -2725,7 +2716,7 @@ void QRasterPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, QImage image; if (pixmap.data->classId() == QPixmapData::RasterClass) { - image = ((QRasterPixmapData *) pixmap.data)->image; + image = static_cast<QRasterPixmapData *>(pixmap.data.data())->image; } else { image = pixmap.toImage(); } @@ -2799,7 +2790,7 @@ void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx if (!s->penData.blend) return; - QRasterBuffer *rb = d->rasterBuffer; + QRasterBuffer *rb = d->rasterBuffer.data(); const QRect rect(rx, ry, w, h); const QClipData *clip = d->clip(); @@ -3092,7 +3083,7 @@ bool QRasterPaintEnginePrivate::isUnclipped_normalized(const QRect &r) const if (cl->clipRect == deviceRect) return true; - if (cl->hasRegionClip) { + if (cl->hasRectClip) { // inline contains() for performance (we know the rects are normalized) const QRect &r1 = cl->clipRect; return (r.left() >= r1.left() && r.right() <= r1.right() @@ -3206,7 +3197,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte ensurePen(); ensureState(); -#if defined (Q_WS_WIN) || defined(Q_WS_MAC) +#if defined (Q_WS_WIN) || defined(Q_WS_MAC) || (defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)) bool drawCached = true; @@ -3221,7 +3212,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte // ### cases we should delegate painting to the font engine // ### directly... -#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE) QFontEngine::Type fontEngineType = ti.fontEngine->type(); // qDebug() << "type" << fontEngineType << s->matrix.type(); if ((fontEngineType == QFontEngine::Win && !((QFontEngineWin *) ti.fontEngine)->ttf && s->matrix.type() > QTransform::TxTranslate) @@ -3239,7 +3230,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte return; } -#else // Q_WS_WIN || Q_WS_MAC +#else // Q_WS_WIN || Q_WS_MAC || Q_OS_SYMBIAN && QT_NO_FREETYPE QFontEngine *fontEngine = ti.fontEngine; @@ -3259,7 +3250,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte } #endif // Q_WS_QWS -#if (defined(Q_WS_X11) || defined(Q_WS_QWS)) && !defined(QT_NO_FREETYPE) +#if (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE) #if defined(Q_WS_QWS) && !defined(QT_NO_QWS_QPF2) if (fontEngine->type() == QFontEngine::QPF2) { @@ -3331,6 +3322,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte break; default: Q_ASSERT(false); + depth = 0; }; for(int i = 0; i < glyphs.size(); i++) { @@ -3358,6 +3350,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte break; default: Q_ASSERT(false); + pitch = 0; }; alphaPenBlt(glyph->data, pitch, depth, @@ -3501,8 +3494,8 @@ void QRasterPaintEngine::drawLines(const QLine *lines, int lineCount) int m22 = int(s->matrix.m22()); int dx = qFloor(s->matrix.dx() + aliasedCoordinateDelta); int dy = qFloor(s->matrix.dy() + aliasedCoordinateDelta); - int dashOffset = int(s->lastPen.dashOffset()); for (int i=0; i<lineCount; ++i) { + int dashOffset = int(s->lastPen.dashOffset()); if (s->flags.int_xform) { const QLine &l = lines[i]; int x1 = l.x1() * m11 + dx; @@ -3601,8 +3594,8 @@ void QRasterPaintEngine::drawLines(const QLineF *lines, int lineCount) ? LineDrawNormal : LineDrawIncludeLastPixel; - int dashOffset = int(s->lastPen.dashOffset()); for (int i=0; i<lineCount; ++i) { + int dashOffset = int(s->lastPen.dashOffset()); QLineF line = (lines[i] * s->matrix).translated(aliasedCoordinateDelta, aliasedCoordinateDelta); const QRectF brect(QPointF(line.x1(), line.y1()), QPointF(line.x2(), line.y2())); @@ -3922,7 +3915,7 @@ static void qt_merge_clip(const QClipData *c1, const QClipData *c2, QClipData *r // find required length int max = qMax(c1_spans[c1_count - 1].x + c1_spans[c1_count - 1].len, - c2_spans[c2_count - 1].x + c2_spans[c2_count - 1].len); + c2_spans[c2_count - 1].x + c2_spans[c2_count - 1].len); buffer.resize(max); memset(buffer.data(), 0, buffer.size() * sizeof(short)); @@ -4059,7 +4052,7 @@ void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline, rasterParams.flags |= (QT_FT_RASTER_FLAG_AA | QT_FT_RASTER_FLAG_DIRECT); rasterParams.gray_spans = callback; - error = qt_ft_grays_raster.raster_render(*grayRaster, &rasterParams); + 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 @@ -4084,10 +4077,11 @@ void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline, #else (unsigned char *) malloc(rasterPoolSize); #endif + Q_CHECK_PTR(rasterPoolBase); // note: we just freed the old rasterPoolBase. I hope it's not fatal. - qt_ft_grays_raster.raster_done(*grayRaster); - qt_ft_grays_raster.raster_new(0, grayRaster); - qt_ft_grays_raster.raster_reset(*grayRaster, rasterPoolBase, rasterPoolSize); + qt_ft_grays_raster.raster_done(*grayRaster.data()); + qt_ft_grays_raster.raster_new(0, grayRaster.data()); + qt_ft_grays_raster.raster_reset(*grayRaster.data(), rasterPoolBase, rasterPoolSize); } else { done = true; } @@ -4101,7 +4095,7 @@ void QRasterPaintEnginePrivate::recalculateFastImages() s->flags.fast_images = !(s->renderHints & QPainter::SmoothPixmapTransform) && rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver - && s->matrix.type() <= QTransform::TxScale; + && s->matrix.type() <= QTransform::TxShear; } @@ -4121,6 +4115,8 @@ QImage QRasterBuffer::colorizeBitmap(const QImage &image, const QColor &color) for (int y=0; y<height; ++y) { uchar *source = sourceImage.scanLine(y); QRgb *target = reinterpret_cast<QRgb *>(dest.scanLine(y)); + if (!source || !target) + QT_THROW(std::bad_alloc()); // we must have run out of memory for (int x=0; x < width; ++x) target[x] = (source[x>>3] >> (x&7)) & 1 ? fg : bg; } @@ -4206,8 +4202,14 @@ int QCustomRasterPaintDevice::bytesPerLine() const { return (width() * depth() + 7) / 8; } -#endif // Q_WS_QWS +#elif defined(Q_OS_SYMBIAN) + +void QRasterBuffer::prepareBuffer(int /* width */, int /* height */) +{ +} + +#endif // Q_OS_SYMBIAN /*! \class QCustomRasterPaintDevice @@ -4290,7 +4292,7 @@ QClipData::QClipData(int height) clipSpanHeight = height; m_clipLines = 0; - allocated = height; + allocated = 0; m_spans = 0; xmin = xmax = ymin = ymax = 0; count = 0; @@ -4312,94 +4314,112 @@ void QClipData::initialize() if (m_spans) return; - m_clipLines = (ClipLine *)calloc(sizeof(ClipLine), clipSpanHeight); - m_spans = (QSpan *)malloc(clipSpanHeight*sizeof(QSpan)); + if (!m_clipLines) + m_clipLines = (ClipLine *)calloc(sizeof(ClipLine), clipSpanHeight); + + Q_CHECK_PTR(m_clipLines); + QT_TRY { + m_spans = (QSpan *)malloc(clipSpanHeight*sizeof(QSpan)); + allocated = clipSpanHeight; + Q_CHECK_PTR(m_spans); + + QT_TRY { + if (hasRectClip) { + int y = 0; + while (y < ymin) { + m_clipLines[y].spans = 0; + m_clipLines[y].count = 0; + ++y; + } - if (hasRectClip) { - int y = 0; - while (y < ymin) { - m_clipLines[y].spans = 0; - m_clipLines[y].count = 0; - ++y; - } + const int len = clipRect.width(); + count = 0; + while (y < ymax) { + QSpan *span = m_spans + count; + span->x = xmin; + span->len = len; + span->y = y; + span->coverage = 255; + ++count; - const int len = clipRect.width(); - count = 0; - while (y < ymax) { - QSpan *span = m_spans + count; - span->x = xmin; - span->len = len; - span->y = y; - span->coverage = 255; - ++count; - - m_clipLines[y].spans = span; - m_clipLines[y].count = 1; - ++y; - } + m_clipLines[y].spans = span; + m_clipLines[y].count = 1; + ++y; + } - while (y < clipSpanHeight) { - m_clipLines[y].spans = 0; - m_clipLines[y].count = 0; - ++y; - } - } else if (hasRegionClip) { + while (y < clipSpanHeight) { + m_clipLines[y].spans = 0; + m_clipLines[y].count = 0; + ++y; + } + } else if (hasRegionClip) { - const QVector<QRect> rects = clipRegion.rects(); - const int numRects = rects.size(); + const QVector<QRect> rects = clipRegion.rects(); + const int numRects = rects.size(); - { // resize - const int maxSpans = (ymax - ymin) * numRects; - if (maxSpans > allocated) { - m_spans = (QSpan *)realloc(m_spans, maxSpans * sizeof(QSpan)); - allocated = maxSpans; - } - } + { // resize + const int maxSpans = (ymax - ymin) * numRects; + if (maxSpans > allocated) { + m_spans = q_check_ptr((QSpan *)realloc(m_spans, maxSpans * sizeof(QSpan))); + allocated = maxSpans; + } + } - int y = 0; - int firstInBand = 0; - while (firstInBand < numRects) { - const int currMinY = rects.at(firstInBand).y(); - const int currMaxY = currMinY + rects.at(firstInBand).height(); + int y = 0; + int firstInBand = 0; + count = 0; + while (firstInBand < numRects) { + const int currMinY = rects.at(firstInBand).y(); + const int currMaxY = currMinY + rects.at(firstInBand).height(); + + while (y < currMinY) { + m_clipLines[y].spans = 0; + m_clipLines[y].count = 0; + ++y; + } - while (y < currMinY) { - m_clipLines[y].spans = 0; - m_clipLines[y].count = 0; - ++y; - } + int lastInBand = firstInBand; + while (lastInBand + 1 < numRects && rects.at(lastInBand+1).top() == y) + ++lastInBand; - int lastInBand = firstInBand; - while (lastInBand + 1 < numRects && rects.at(lastInBand+1).top() == y) - ++lastInBand; + while (y < currMaxY) { - while (y < currMaxY) { + m_clipLines[y].spans = m_spans + count; + m_clipLines[y].count = lastInBand - firstInBand + 1; - m_clipLines[y].spans = m_spans + count; - m_clipLines[y].count = lastInBand - firstInBand + 1; + for (int r = firstInBand; r <= lastInBand; ++r) { + const QRect &currRect = rects.at(r); + QSpan *span = m_spans + count; + span->x = currRect.x(); + span->len = currRect.width(); + span->y = y; + span->coverage = 255; + ++count; + } + ++y; + } - for (int r = firstInBand; r <= lastInBand; ++r) { - const QRect &currRect = rects.at(r); - QSpan *span = m_spans + count; - span->x = currRect.x(); - span->len = currRect.width(); - span->y = y; - span->coverage = 255; - ++count; + firstInBand = lastInBand + 1; } - ++y; - } - firstInBand = lastInBand + 1; - } + Q_ASSERT(count <= allocated); - Q_ASSERT(count <= allocated); + while (y < clipSpanHeight) { + m_clipLines[y].spans = 0; + m_clipLines[y].count = 0; + ++y; + } - while (y < clipSpanHeight) { - m_clipLines[y].spans = 0; - m_clipLines[y].count = 0; - ++y; + } + } QT_CATCH(...) { + free(m_spans); // have to free m_spans again or someone might think that we were successfully initialized. + m_spans = 0; + QT_RETHROW; } - + } QT_CATCH(...) { + free(m_clipLines); // same for clipLines + m_clipLines = 0; + QT_RETHROW; } } @@ -4418,20 +4438,37 @@ void QClipData::fixup() ymax = m_spans[count-1].y + 1; xmin = INT_MAX; xmax = 0; + + bool isRect = true; + int left = m_spans[0].x; + int right = m_spans[0].x + m_spans[0].len; + for (int i = 0; i < count; ++i) { -// qDebug() << " " << spans[i].x << spans[i].y << spans[i].len << spans[i].coverage; if (m_spans[i].y != y) { + if (m_spans[i].y != y + 1 && y != -1) { + isRect = false; + } y = m_spans[i].y; m_clipLines[y].spans = m_spans+i; m_clipLines[y].count = 0; // qDebug() << " new line: y=" << y; } ++m_clipLines[y].count; + int sl = (int) m_spans[i].x; + int sr = sl + m_spans[i].len; + xmin = qMin(xmin, (int)m_spans[i].x); xmax = qMax(xmax, (int)m_spans[i].x + m_spans[i].len); + + if (sl != left || sr != right) + isRect = false; + } +// qDebug("xmin=%d,xmax=%d,ymin=%d,ymax=%d %s", xmin, xmax, ymin, ymax, isRect ? "rectangular" : ""); + + if (isRect) { + hasRectClip = true; + clipRect.setRect(xmin, ymin, xmax - xmin, ymax - ymin); } - ++xmax; -// qDebug("xmin=%d,xmax=%d,ymin=%d,ymax=%d", xmin, xmax, ymin, ymax); } /* @@ -4439,11 +4476,12 @@ void QClipData::fixup() */ void QClipData::setClipRect(const QRect &rect) { - if (rect == clipRect) + if (hasRectClip && rect == clipRect) return; // qDebug() << "setClipRect" << clipSpanHeight << count << allocated << rect; hasRectClip = true; + hasRegionClip = false; clipRect = rect; xmin = rect.x(); @@ -4452,7 +4490,7 @@ void QClipData::setClipRect(const QRect &rect) ymax = qMin(rect.y() + rect.height(), clipSpanHeight); if (m_spans) { - delete m_spans; + free(m_spans); m_spans = 0; } @@ -4470,6 +4508,7 @@ void QClipData::setClipRegion(const QRegion ®ion) } hasRegionClip = true; + hasRectClip = false; clipRegion = region; { // set bounding rect @@ -4481,7 +4520,7 @@ void QClipData::setClipRegion(const QRegion ®ion) } if (m_spans) { - delete m_spans; + free(m_spans); m_spans = 0; } @@ -4614,104 +4653,6 @@ static int qt_intersect_spans(QT_FT_Span *spans, int numSpans, return n; } -/* - \internal - Clip spans to \a{clip}-region. - Returns number of unclipped spans -*/ -static int qt_intersect_spans(QT_FT_Span *spans, int numSpans, - int *currSpan, - QT_FT_Span *outSpans, int maxOut, - const QRegion &clip) -{ - const QVector<QRect> rects = clip.rects(); - const int numRects = rects.size(); - - int r = 0; - short miny, minx, maxx, maxy; - { - const QRect &rect = rects[0]; - miny = rect.top(); - minx = rect.left(); - maxx = rect.right(); - maxy = rect.bottom(); - } - - // TODO: better mapping of currY and startRect - - int n = 0; - int i = *currSpan; - int currY = spans[i].y; - while (i < numSpans) { - - if (spans[i].y != currY && r != 0) { - currY = spans[i].y; - r = 0; - const QRect &rect = rects[r]; - miny = rect.top(); - minx = rect.left(); - maxx = rect.right(); - maxy = rect.bottom(); - } - - if (spans[i].y < miny) { - ++i; - continue; - } - - if (spans[i].y > maxy || spans[i].x > maxx) { - if (++r >= numRects) { - ++i; - continue; - } - - const QRect &rect = rects[r]; - miny = rect.top(); - minx = rect.left(); - maxx = rect.right(); - maxy = rect.bottom(); - continue; - } - - if (spans[i].x + spans[i].len <= minx) { - ++i; - continue; - } - - outSpans[n].y = spans[i].y; - outSpans[n].coverage = spans[i].coverage; - - if (spans[i].x < minx) { - const ushort cutaway = minx - spans[i].x; - outSpans[n].len = qMin(spans[i].len - cutaway, maxx - minx + 1); - outSpans[n].x = minx; - if (outSpans[n].len == spans[i].len - cutaway) { - ++i; - } else { - // span wider than current rect - spans[i].len -= outSpans[n].len + cutaway; - spans[i].x = maxx + 1; - } - } else { // span starts inside current rect - outSpans[n].x = spans[i].x; - outSpans[n].len = qMin(spans[i].len, - ushort(maxx - spans[i].x + 1)); - if (outSpans[n].len == spans[i].len) { - ++i; - } else { - // span wider than current rect - spans[i].len -= outSpans[n].len; - spans[i].x = maxx + 1; - } - } - - if (++n >= maxOut) - break; - } - - *currSpan = i; - return n; -} static void qt_span_fill_clipRect(int count, const QSpan *spans, void *userData) @@ -4729,29 +4670,6 @@ static void qt_span_fill_clipRect(int count, const QSpan *spans, fillData->unclipped_blend(count, spans, fillData); } -static void qt_span_fill_clipRegion(int count, const QSpan *spans, - void *userData) -{ - QSpanData *fillData = reinterpret_cast<QSpanData *>(userData); - Q_ASSERT(fillData->blend && fillData->unclipped_blend); - - Q_ASSERT(fillData->clip); - Q_ASSERT(!fillData->clip->clipRegion.isEmpty()); - - const int NSPANS = 256; - QSpan cspans[NSPANS]; - int currentClip = 0; - while (currentClip < count) { - const int unclipped = qt_intersect_spans(const_cast<QSpan*>(spans), - count, ¤tClip, - &cspans[0], NSPANS, - fillData->clip->clipRegion); - if (unclipped > 0) - fillData->unclipped_blend(unclipped, cspans, fillData); - } - -} - static void qt_span_clip(int count, const QSpan *spans, void *userData) { ClipData *clipData = reinterpret_cast<ClipData *>(userData); @@ -4776,8 +4694,8 @@ static void qt_span_clip(int count, const QSpan *spans, void *userData) &newspans, newClip->allocated - newClip->count); newClip->count = newspans - newClip->m_spans; if (spans < end) { + newClip->m_spans = q_check_ptr((QSpan *)realloc(newClip->m_spans, newClip->allocated*2*sizeof(QSpan))); newClip->allocated *= 2; - newClip->m_spans = (QSpan *)realloc(newClip->m_spans, newClip->allocated*sizeof(QSpan)); } } } @@ -5024,7 +4942,7 @@ void QSpanData::init(QRasterBuffer *rb, const QRasterPaintEngine *pe) extern QImage qt_imageForBrush(int brushStyle, bool invert); -void QSpanData::setup(const QBrush &brush, int alpha) +void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode) { Qt::BrushStyle brushStyle = qbrush_style(brush); switch (brushStyle) { @@ -5032,6 +4950,10 @@ void QSpanData::setup(const QBrush &brush, int alpha) type = Solid; QColor c = qbrush_color(brush); solid.color = PREMUL(ARGB_COMBINE_ALPHA(c.rgba(), alpha)); + if ((solid.color & 0xff000000) == 0 + && compositionMode == QPainter::CompositionMode_SourceOver) { + type = None; + } break; } @@ -5172,8 +5094,6 @@ void QSpanData::adjustSpanMethods() blend = unclipped_blend; } else if (clip->hasRectClip) { blend = clip->clipRect.isEmpty() ? 0 : qt_span_fill_clipRect; - } else if (clip->hasRegionClip) { - blend = clip->clipRegion.isEmpty() ? 0 : qt_span_fill_clipRegion; } else { blend = qt_span_fill_clipped; } @@ -5330,6 +5250,13 @@ static void drawLine_midpoint_i(int x1, int y1, int x2, int y2, ProcessSpans spa dy = -dy; } + int x_lower_limit = - 128; + if (x1 < x_lower_limit) { + int cy = dy * (x_lower_limit - x1) / dx + y1; + drawLine_midpoint_i(x_lower_limit, cy, x2, y2, span_func, data, style, devRect); + return; + } + if (style == LineDrawNormal) --x2; @@ -5467,6 +5394,13 @@ static void drawLine_midpoint_i(int x1, int y1, int x2, int y2, ProcessSpans spa dx = -dx; } + int y_lower_limit = - 128; + if (y1 < y_lower_limit) { + int cx = dx * (y_lower_limit - y1) / dy + x1; + drawLine_midpoint_i(cx, y_lower_limit, x2, y2, span_func, data, style, devRect); + return; + } + if (style == LineDrawNormal) --y2; @@ -6154,7 +6088,7 @@ void dumpClip(int width, int height, QClipData *clip) int y1 = 0; for (int i = 0; i < clip->count; ++i) { - QSpan *span = clip->spans + i; + QSpan *span = clip->spans() + i; for (int j = 0; j < span->len; ++j) clipImg.setPixel(span->x + j, span->y, 0xffffff00); x0 = qMin(x0, int(span->x)); @@ -6172,7 +6106,7 @@ void dumpClip(int width, int height, QClipData *clip) Q_ASSERT(x1 >= 0); fprintf(stderr,"clip %d: %d %d - %d %d\n", counter, x0, y0, x1, y1); - clipImg.save(QString(QLatin1String("clip-%0.png")).arg(counter++)); + clipImg.save(QString::fromLatin1("clip-%0.png").arg(counter++)); } #endif diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index b662e6b..c31a087 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -62,6 +62,7 @@ #include "private/qstroker_p.h" #include "private/qpainter_p.h" #include "private/qtextureglyphcache_p.h" +#include "private/qoutlinemapper_p.h" #include <stdlib.h> @@ -165,7 +166,6 @@ public: void updateMatrix(const QTransform &matrix); - void drawPath(const QPainterPath &path); void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode); void fillPath(const QPainterPath &path, QSpanData *fillData); @@ -202,7 +202,6 @@ public: void clip(const QVectorPath &path, Qt::ClipOperation op); void clip(const QRect &rect, Qt::ClipOperation op); void clip(const QRegion ®ion, Qt::ClipOperation op); - void clip(const QPainterPath &path, Qt::ClipOperation op); enum ClipType { RectClip, @@ -328,14 +327,13 @@ public: inline const QClipData *clip() const; - void strokeProjective(const QPainterPath &path); void initializeRasterizer(QSpanData *data); void recalculateFastImages(); QPaintDevice *device; - QOutlineMapper *outlineMapper; - QRasterBuffer *rasterBuffer; + QScopedPointer<QOutlineMapper> outlineMapper; + QScopedPointer<QRasterBuffer> rasterBuffer; #if defined (Q_WS_WIN) HDC hdc; @@ -346,9 +344,9 @@ public: QRect deviceRect; QStroker basicStroker; - QDashStroker *dashStroker; + QScopedPointer<QDashStroker> dashStroker; - QT_FT_Raster *grayRaster; + QScopedPointer<QT_FT_Raster> grayRaster; unsigned long rasterPoolSize; unsigned char *rasterPoolBase; @@ -360,7 +358,7 @@ public: QFontEngineGlyphCache::Type glyphCacheType; - QClipData *baseClip; + QScopedPointer<QClipData> baseClip; int deviceDepth; @@ -371,11 +369,11 @@ public: uint isPlain45DegreeRotation : 1; #endif - QRasterizer *rasterizer; + QScopedPointer<QRasterizer> rasterizer; }; -class QClipData { +class Q_GUI_EXPORT QClipData { public: QClipData(int height); ~QClipData(); @@ -482,7 +480,7 @@ private: /******************************************************************************* * QRasterBuffer */ -class QRasterBuffer +class Q_GUI_EXPORT QRasterBuffer { public: QRasterBuffer() : m_width(0), m_height(0), m_buffer(0) { init(); } @@ -542,7 +540,7 @@ inline const QClipData *QRasterPaintEnginePrivate::clip() const { Q_Q(const QRasterPaintEngine); if (q->state() && q->state()->clip && q->state()->clip->enabled) return q->state()->clip; - return baseClip; + return baseClip.data(); } diff --git a/src/gui/painting/qpaintengine_x11.cpp b/src/gui/painting/qpaintengine_x11.cpp index edf29c5..d906b69 100644 --- a/src/gui/painting/qpaintengine_x11.cpp +++ b/src/gui/painting/qpaintengine_x11.cpp @@ -271,7 +271,7 @@ void QXRenderTessellator::addTrap(const Trapezoid &trap) { if (size == allocated) { allocated = qMax(2*allocated, 64); - traps = (XTrapezoid *)realloc(traps, allocated * sizeof(XTrapezoid)); + traps = q_check_ptr((XTrapezoid *)realloc(traps, allocated * sizeof(XTrapezoid))); } traps[size].top = Q27Dot5ToXFixed(trap.top); traps[size].bottom = Q27Dot5ToXFixed(trap.bottom); @@ -482,7 +482,7 @@ bool QX11PaintEngine::begin(QPaintDevice *pdev) d->picture = (::Picture)w->x11PictureHandle(); } else if (pdev->devType() == QInternal::Pixmap) { const QPixmap *pm = static_cast<const QPixmap *>(pdev); - QX11PixmapData *data = static_cast<QX11PixmapData*>(pm->data); + QX11PixmapData *data = static_cast<QX11PixmapData*>(pm->data.data()); if (X11->use_xrender && data->depth() != 32 && data->x11_mask) data->convertToARGB32(); d->picture = (::Picture)static_cast<const QPixmap *>(pdev)->x11PictureHandle(); @@ -1365,7 +1365,7 @@ void QX11PaintEngine::updateBrush(const QBrush &brush, const QPointF &origin) XRenderPictureAttributes attrs; attrs.repeat = true; XRenderChangePicture(d->dpy, d->brush_pm.x11PictureHandle(), CPRepeat, &attrs); - QX11PixmapData *data = static_cast<QX11PixmapData*>(d->brush_pm.data); + QX11PixmapData *data = static_cast<QX11PixmapData*>(d->brush_pm.data.data()); if (data->mask_picture) XRenderChangePicture(d->dpy, data->mask_picture, CPRepeat, &attrs); } @@ -1402,13 +1402,13 @@ void QX11PaintEngine::updateBrush(const QBrush &brush, const QPointF &origin) mask |= GCTile; #ifndef QT_NO_XRENDER if (d->pdev_depth == 32 && d->brush_pm.depth() != 32) { - QX11PixmapData *brushData = static_cast<QX11PixmapData*>(d->brush_pm.data); + QX11PixmapData *brushData = static_cast<QX11PixmapData*>(d->brush_pm.data.data()); brushData->convertToARGB32(); } #endif vals.tile = (d->brush_pm.depth() == d->pdev_depth ? d->brush_pm.handle() - : static_cast<QX11PixmapData*>(d->brush_pm.data)->x11ConvertToDefaultDepth()); + : static_cast<QX11PixmapData*>(d->brush_pm.data.data())->x11ConvertToDefaultDepth()); s = FillTiled; #if !defined(QT_NO_XRENDER) d->current_brush = d->cbrush.texture().x11PictureHandle(); @@ -1915,7 +1915,7 @@ void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &px, const QRect QPixmap::x11SetDefaultScreen(pixmap.x11Info().screen()); #ifndef QT_NO_XRENDER - ::Picture src_pict = static_cast<QX11PixmapData*>(pixmap.data)->picture; + ::Picture src_pict = static_cast<QX11PixmapData*>(pixmap.data.data())->picture; if (src_pict && d->picture) { const int pDepth = pixmap.depth(); if (pDepth == 1 && (d->has_alpha_pen)) { @@ -1934,7 +1934,7 @@ void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &px, const QRect bool mono_dst = d->pdev_depth == 1; bool restore_clip = false; - if (static_cast<QX11PixmapData*>(pixmap.data)->x11_mask) { // pixmap has a mask + if (static_cast<QX11PixmapData*>(pixmap.data.data())->x11_mask) { // pixmap has a mask QBitmap comb(sw, sh); GC cgc = XCreateGC(d->dpy, comb.handle(), 0, 0); XSetForeground(d->dpy, cgc, 0); @@ -1951,7 +1951,7 @@ void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &px, const QRect XSetFillStyle(d->dpy, cgc, FillOpaqueStippled); XSetTSOrigin(d->dpy, cgc, -sx, -sy); XSetStipple(d->dpy, cgc, - static_cast<QX11PixmapData*>(pixmap.data)->x11_mask); + static_cast<QX11PixmapData*>(pixmap.data.data())->x11_mask); XFillRectangle(d->dpy, comb.handle(), cgc, 0, 0, sw, sh); XFreeGC(d->dpy, cgc); @@ -1994,8 +1994,8 @@ void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &px, const QRect if (d->pdev->devType() == QInternal::Pixmap) { const QPixmap *px = static_cast<const QPixmap*>(d->pdev); - Pixmap src_mask = static_cast<QX11PixmapData*>(pixmap.data)->x11_mask; - Pixmap dst_mask = static_cast<QX11PixmapData*>(px->data)->x11_mask; + Pixmap src_mask = static_cast<QX11PixmapData*>(pixmap.data.data())->x11_mask; + Pixmap dst_mask = static_cast<QX11PixmapData*>(px->data.data())->x11_mask; if (dst_mask) { GC cgc = XCreateGC(d->dpy, dst_mask, 0, 0); if (src_mask) { // copy src mask into dst mask @@ -2214,7 +2214,7 @@ void QX11PaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, co #endif } else #endif // !QT_NO_XRENDER - if (pixmap.depth() > 1 && !static_cast<QX11PixmapData*>(pixmap.data)->x11_mask) { + if (pixmap.depth() > 1 && !static_cast<QX11PixmapData*>(pixmap.data.data())->x11_mask) { XSetTile(d->dpy, d->gc, pixmap.handle()); XSetFillStyle(d->dpy, d->gc, FillTiled); XSetTSOrigin(d->dpy, d->gc, x-sx, y-sy); @@ -2459,15 +2459,23 @@ void QX11PaintEngine::drawFreetype(const QPointF &p, const QTextItemInt &ti) XRectangle rects[rectcount]; int num_rects = 0; + QPoint delta(qRound(d->matrix.dx()), qRound(d->matrix.dy())); + QRect clip(d->polygonClipper.boundingRect()); for (int i=0; i < path.elementCount(); i+=5) { int x = qRound(path.elementAt(i).x); int y = qRound(path.elementAt(i).y); int w = qRound(path.elementAt(i+1).x) - x; int h = qRound(path.elementAt(i+2).y) - y; - rects[num_rects].x = x + qRound(d->matrix.dx()); - rects[num_rects].y = y + qRound(d->matrix.dy()); - rects[num_rects].width = w; - rects[num_rects].height = h; + + QRect rect = QRect(x + delta.x(), y + delta.y(), w, h); + rect = rect.intersected(clip); + if (rect.isEmpty()) + continue; + + rects[num_rects].x = short(rect.x()); + rects[num_rects].y = short(rect.y()); + rects[num_rects].width = ushort(rect.width()); + rects[num_rects].height = ushort(rect.height()); ++num_rects; if (num_rects == rectcount) { XFillRectangles(d->dpy, d->hd, d->gc, rects, num_rects); diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 3c82414..c2703bc 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -42,6 +42,7 @@ #include "qpaintengineex_p.h" #include "qpainter_p.h" #include "qstroker_p.h" +#include "qbezier_p.h" #include <private/qpainterpath_p.h> #include <qvarlengtharray.h> @@ -56,15 +57,15 @@ QT_BEGIN_NAMESPACE * */ -const QRealRect &QVectorPath::controlPointRect() const +QRectF QVectorPath::controlPointRect() const { if (m_hints & ControlPointRect) - return m_cp_rect; + return QRectF(QPointF(m_cp_rect.x1, m_cp_rect.y1), QPointF(m_cp_rect.x2, m_cp_rect.y2)); if (m_count == 0) { m_cp_rect.x1 = m_cp_rect.x2 = m_cp_rect.y1 = m_cp_rect.y2 = 0; m_hints |= ControlPointRect; - return m_cp_rect; + return QRectF(QPointF(m_cp_rect.x1, m_cp_rect.y1), QPointF(m_cp_rect.x2, m_cp_rect.y2)); } Q_ASSERT(m_points && m_count > 0); @@ -88,7 +89,41 @@ const QRealRect &QVectorPath::controlPointRect() const } m_hints |= ControlPointRect; - return m_cp_rect; + return QRectF(QPointF(m_cp_rect.x1, m_cp_rect.y1), QPointF(m_cp_rect.x2, m_cp_rect.y2)); +} + +QPainterPath QVectorPath::convertToPainterPath() const +{ + QPainterPath path; + + if (m_count == 0) + return path; + + const QPointF *points = (const QPointF *) m_points; + + if (m_elements) { + for (int i=0; i<m_count; ++i) { + switch (m_elements[i]) { + case QPainterPath::MoveToElement: + path.moveTo(points[i]); + break; + case QPainterPath::LineToElement: + path.lineTo(points[i]); + break; + case QPainterPath::CurveToElement: + path.cubicTo(points[i], points[i+1], points[i+2]); + break; + default: + break; + } + } + } else { + path.moveTo(points[0]); + for (int i=1; i<m_count; ++i) + path.lineTo(points[i]); + } + + return path; } const QVectorPath &qtVectorPathForPath(const QPainterPath &path) @@ -100,12 +135,10 @@ const QVectorPath &qtVectorPathForPath(const QPainterPath &path) #ifndef QT_NO_DEBUG_STREAM QDebug Q_GUI_EXPORT &operator<<(QDebug &s, const QVectorPath &path) { - QRealRect vectorPathBounds = path.controlPointRect(); - QRectF rf(vectorPathBounds.x1, vectorPathBounds.y1, - vectorPathBounds.x2 - vectorPathBounds.x1, vectorPathBounds.y2 - vectorPathBounds.y1); + QRectF rf = path.controlPointRect(); s << "QVectorPath(size:" << path.elementCount() << " hints:" << hex << path.hints() - << rf << ")"; + << rf << ')'; return s; } #endif @@ -138,6 +171,69 @@ QPaintEngineExPrivate::~QPaintEngineExPrivate() } +void QPaintEngineExPrivate::replayClipOperations() +{ + Q_Q(QPaintEngineEx); + + QPainter *p = q->painter(); + if (!p || !p->d_ptr) + return; + + QList<QPainterClipInfo> clipInfo = p->d_ptr->state->clipInfo; + + QTransform transform = q->state()->matrix; + + for (int i = 0; i < clipInfo.size(); ++i) { + const QPainterClipInfo &info = clipInfo.at(i); + + if (info.matrix != q->state()->matrix) { + q->state()->matrix = info.matrix; + q->transformChanged(); + } + + switch (info.clipType) { + case QPainterClipInfo::RegionClip: + q->clip(info.region, info.operation); + break; + case QPainterClipInfo::PathClip: + q->clip(info.path, info.operation); + break; + case QPainterClipInfo::RectClip: + q->clip(info.rect, info.operation); + break; + case QPainterClipInfo::RectFClip: { + qreal right = info.rectf.x() + info.rectf.width(); + qreal bottom = info.rectf.y() + info.rectf.height(); + qreal pts[] = { info.rectf.x(), info.rectf.y(), + right, info.rectf.y(), + right, bottom, + info.rectf.x(), bottom }; + QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint); + q->clip(vp, info.operation); + break; + } + } + } + + if (transform != q->state()->matrix) { + q->state()->matrix = transform; + q->transformChanged(); + } +} + + +bool QPaintEngineExPrivate::hasClipOperations() const +{ + Q_Q(const QPaintEngineEx); + + QPainter *p = q->painter(); + if (!p || !p->d_ptr) + return false; + + QList<QPainterClipInfo> clipInfo = p->d_ptr->state->clipInfo; + + return !clipInfo.isEmpty(); +} /******************************************************************************* * @@ -244,13 +340,18 @@ static void qpaintengineex_cubicTo(qreal c1x, qreal c1y, qreal c2x, qreal c2y, q ((StrokeHandler *) data)->types.add(QPainterPath::CurveToDataElement); } +QPaintEngineEx::QPaintEngineEx() + : QPaintEngine(*new QPaintEngineExPrivate, AllFeatures) +{ + extended = true; +} + QPaintEngineEx::QPaintEngineEx(QPaintEngineExPrivate &data) : QPaintEngine(data, AllFeatures) { extended = true; } - QPainterState *QPaintEngineEx::createState(QPainterState *orig) const { if (!orig) @@ -318,7 +419,6 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) const qreal *lastPoint = points + (pointCount<<1); - d->activeStroker->begin(d->strokeHandler); d->strokeHandler->types.reset(); d->strokeHandler->pts.reset(); @@ -327,13 +427,13 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) if (d->stroker.capStyle() == Qt::RoundCap || d->stroker.joinStyle() == Qt::RoundJoin) flags |= QVectorPath::CurvedShapeHint; - // ### Perspective Xforms are currently not supported... qreal txscale = 1; if (!(pen.isCosmetic() || (qt_scaleForTransform(state()->matrix, &txscale) && txscale != 1))) { // We include cosmetic pens in this case to avoid having to // change the current transform. Normal transformed, // non-cosmetic pens will be transformed as part of fill // later, so they are also covered here.. + d->activeStroker->begin(d->strokeHandler); if (types) { while (points < lastPoint) { switch (*types) { @@ -382,69 +482,75 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) QVectorPath strokePath(d->strokeHandler->pts.data(), d->strokeHandler->types.size(), d->strokeHandler->types.data(), - QVectorPath::WindingFill); + flags); fill(strokePath, pen.brush()); } else { const qreal strokeWidth = d->stroker.strokeWidth(); d->stroker.setStrokeWidth(strokeWidth * txscale); // For cosmetic pens we need a bit of trickery... We to process xform the input points - if (types) { - while (points < lastPoint) { - switch (*types) { - case QPainterPath::MoveToElement: { - QPointF pt = (*(QPointF *) points) * state()->matrix; - d->activeStroker->moveTo(pt.x(), pt.y()); - points += 2; - ++types; - break; + if (state()->matrix.type() >= QTransform::TxProject) { + QPainterPath painterPath = state()->matrix.map(path.convertToPainterPath()); + d->activeStroker->strokePath(painterPath, d->strokeHandler, QTransform()); + } else { + d->activeStroker->begin(d->strokeHandler); + if (types) { + while (points < lastPoint) { + switch (*types) { + case QPainterPath::MoveToElement: { + QPointF pt = (*(QPointF *) points) * state()->matrix; + d->activeStroker->moveTo(pt.x(), pt.y()); + points += 2; + ++types; + break; + } + case QPainterPath::LineToElement: { + QPointF pt = (*(QPointF *) points) * state()->matrix; + d->activeStroker->lineTo(pt.x(), pt.y()); + points += 2; + ++types; + break; + } + case QPainterPath::CurveToElement: { + QPointF c1 = ((QPointF *) points)[0] * state()->matrix; + QPointF c2 = ((QPointF *) points)[1] * state()->matrix; + QPointF e = ((QPointF *) points)[2] * state()->matrix; + d->activeStroker->cubicTo(c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y()); + points += 6; + types += 3; + flags |= QVectorPath::CurvedShapeHint; + break; + } + default: + break; + } } - case QPainterPath::LineToElement: { - QPointF pt = (*(QPointF *) points) * state()->matrix; + if (path.hasImplicitClose()) { + QPointF pt = * ((QPointF *) path.points()) * state()->matrix; d->activeStroker->lineTo(pt.x(), pt.y()); - points += 2; - ++types; - break; - } - case QPainterPath::CurveToElement: { - QPointF c1 = ((QPointF *) points)[0] * state()->matrix; - QPointF c2 = ((QPointF *) points)[1] * state()->matrix; - QPointF e = ((QPointF *) points)[2] * state()->matrix; - d->activeStroker->cubicTo(c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y()); - points += 6; - types += 3; - flags |= QVectorPath::CurvedShapeHint; - break; } - default: - break; - } - } - if (path.hasImplicitClose()) { - QPointF pt = * ((QPointF *) path.points()) * state()->matrix; - d->activeStroker->lineTo(pt.x(), pt.y()); - } - } else { - QPointF p = ((QPointF *)points)[0] * state()->matrix; - d->activeStroker->moveTo(p.x(), p.y()); - points += 2; - ++types; - while (points < lastPoint) { + } else { QPointF p = ((QPointF *)points)[0] * state()->matrix; - d->activeStroker->lineTo(p.x(), p.y()); + d->activeStroker->moveTo(p.x(), p.y()); points += 2; ++types; + while (points < lastPoint) { + QPointF p = ((QPointF *)points)[0] * state()->matrix; + d->activeStroker->lineTo(p.x(), p.y()); + points += 2; + ++types; + } + if (path.hasImplicitClose()) + d->activeStroker->lineTo(p.x(), p.y()); } - if (path.hasImplicitClose()) - d->activeStroker->lineTo(p.x(), p.y()); + d->activeStroker->end(); } - d->activeStroker->end(); d->stroker.setStrokeWidth(strokeWidth); QVectorPath strokePath(d->strokeHandler->pts.data(), d->strokeHandler->types.size(), d->strokeHandler->types.data(), - QVectorPath::WindingFill); + flags); QTransform xform = state()->matrix; state()->matrix = QTransform(); @@ -483,6 +589,9 @@ void QPaintEngineEx::clip(const QRect &r, Qt::ClipOperation op) void QPaintEngineEx::clip(const QRegion ®ion, Qt::ClipOperation op) { + if (region.numRects() == 1) + clip(region.boundingRect(), op); + QVector<QRect> rects = region.rects(); if (rects.size() <= 32) { qreal pts[2*32*4]; @@ -777,8 +886,7 @@ void QPaintEngineEx::drawImage(const QPointF &pos, const QImage &image) void QPaintEngineEx::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s) { QBrush brush(state()->pen.color(), pixmap); - QTransform xform; - xform.translate(-s.x(), -s.y()); + QTransform xform = QTransform::fromTranslate(r.x() - s.x(), r.y() - s.y()); brush.setTransform(xform); qreal pts[] = { r.x(), r.y(), diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h index eeb7647..a252b5e 100644 --- a/src/gui/painting/qpaintengineex_p.h +++ b/src/gui/painting/qpaintengineex_p.h @@ -55,10 +55,10 @@ #include <QtGui/qpaintengine.h> -#include "qpaintengine_p.h" -#include "qstroker_p.h" -#include "qpainter_p.h" -#include "qvectorpath_p.h" +#include <private/qpaintengine_p.h> +#include <private/qstroker_p.h> +#include <private/qpainter_p.h> +#include <private/qvectorpath_p.h> QT_BEGIN_HEADER @@ -139,29 +139,13 @@ public: QDebug Q_GUI_EXPORT &operator<<(QDebug &, const QVectorPath &path); #endif -class Q_GUI_EXPORT QPaintEngineExPrivate : public QPaintEnginePrivate -{ -public: - QPaintEngineExPrivate(); - ~QPaintEngineExPrivate(); - - QStroker stroker; - QDashStroker dasher; - StrokeHandler *strokeHandler; - QStrokerOps *activeStroker; - QPen strokerPen; - - QRect exDeviceRect; -}; - class QPixmapFilter; class Q_GUI_EXPORT QPaintEngineEx : public QPaintEngine { Q_DECLARE_PRIVATE(QPaintEngineEx) public: - inline QPaintEngineEx() - : QPaintEngine(*new QPaintEngineExPrivate, AllFeatures) { extended = true; } + QPaintEngineEx(); virtual QPainterState *createState(QPainterState *orig) const; @@ -218,12 +202,35 @@ public: inline QPainterState *state() { return static_cast<QPainterState *>(QPaintEngine::state); } inline const QPainterState *state() const { return static_cast<const QPainterState *>(QPaintEngine::state); } + virtual void sync() {} + + virtual void beginNativePainting() {} + virtual void endNativePainting() {} + virtual QPixmapFilter *createPixmapFilter(int /*type*/) const { return 0; } protected: QPaintEngineEx(QPaintEngineExPrivate &data); }; +class Q_GUI_EXPORT QPaintEngineExPrivate : public QPaintEnginePrivate +{ + Q_DECLARE_PUBLIC(QPaintEngineEx) +public: + QPaintEngineExPrivate(); + ~QPaintEngineExPrivate(); + + void replayClipOperations(); + bool hasClipOperations() const; + + QStroker stroker; + QDashStroker dasher; + StrokeHandler *strokeHandler; + QStrokerOps *activeStroker; + QPen strokerPen; + + QRect exDeviceRect; +}; inline uint QVectorPath::polygonFlags(QPaintEngine::PolygonDrawMode mode) { switch (mode) { diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 4255635..d82e7ee 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -75,9 +75,6 @@ QT_BEGIN_NAMESPACE #define QGradient_StretchToDevice 0x10000000 #define QPaintEngine_OpaqueBackground 0x40000000 -// use the same rounding as in qrasterizer.cpp (6 bit fixed point) -static const qreal aliasedCoordinateDelta = 0.5 - 0.015625; - // #define QT_DEBUG_DRAW #ifdef QT_DEBUG_DRAW bool qt_show_painter_debug_output = true; @@ -184,7 +181,7 @@ void QPainterPrivate::checkEmulation() extended = emulationEngine; extended->setState(state); } - } else if (emulationEngine && emulationEngine != extended) { + } else if (emulationEngine == extended) { extended = emulationEngine->real_engine; } } @@ -259,14 +256,16 @@ bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev) // in 99% of all cases). E.g: A renders B which renders C which renders D. sp->d_ptr->d_ptrs_size = 4; sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *)); + Q_CHECK_PTR(sp->d_ptr->d_ptrs); } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) { // However, to support corner cases we grow the array dynamically if needed. sp->d_ptr->d_ptrs_size <<= 1; const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *); - sp->d_ptr->d_ptrs = (QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize); + sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize)); } - sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr; - q->d_ptr = sp->d_ptr; + sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data(); + q->d_ptr.take(); + q->d_ptr.reset(sp->d_ptr.data()); Q_ASSERT(q->d_ptr->state); @@ -281,10 +280,14 @@ bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev) q->d_ptr->state->wh = q->d_ptr->state->vh = widget->height(); // Update matrix. - if (q->d_ptr->state->WxF) - q->d_ptr->state->worldMatrix.translate(-offset.x(), -offset.y()); - else - q->d_ptr->state->redirection_offset = offset; + if (q->d_ptr->state->WxF) { + q->d_ptr->state->redirectionMatrix *= q->d_ptr->state->worldMatrix; + q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y()); + q->d_ptr->state->worldMatrix = QTransform(); + q->d_ptr->state->WxF = false; + } else { + q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y()); + } q->d_ptr->updateMatrix(); QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func(); @@ -315,7 +318,8 @@ void QPainterPrivate::detachPainterPrivate(QPainter *q) d_ptrs[refcount - 1] = 0; q->restore(); - q->d_ptr = original; + q->d_ptr.take(); + q->d_ptr.reset(original); if (emulationEngine) { extended = emulationEngine->real_engine; @@ -410,7 +414,7 @@ void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperatio bool old_txinv = txinv; QTransform old_invMatrix = invMatrix; txinv = true; - invMatrix = QTransform().translate(-state->redirection_offset.x(), -state->redirection_offset.y()); + invMatrix = QTransform(); QPainterPath clipPath = q->clipPath(); QRectF r = clipPath.boundingRect().intersected(absPathRect); absPathRect = r.toAlignedRect(); @@ -634,20 +638,7 @@ void QPainterPrivate::updateMatrix() state->matrix *= viewTransform(); txinv = false; // no inverted matrix - if (!state->redirection_offset.isNull()) { - // We want to translate in dev space so we do the adding of the redirection - // offset manually. - if (state->matrix.isAffine()) { - state->matrix = QTransform(state->matrix.m11(), state->matrix.m12(), - state->matrix.m21(), state->matrix.m22(), - state->matrix.dx()-state->redirection_offset.x(), - state->matrix.dy()-state->redirection_offset.y()); - } else { - QTransform temp; - temp.translate(-state->redirection_offset.x(), -state->redirection_offset.y()); - state->matrix *= temp; - } - } + state->matrix *= state->redirectionMatrix; if (extended) extended->transformChanged(); else @@ -662,18 +653,7 @@ void QPainterPrivate::updateInvMatrix() { Q_ASSERT(txinv == false); txinv = true; // creating inverted matrix - QTransform m; - - if (state->VxF) - m = viewTransform(); - - if (state->WxF) { - if (state->VxF) - m = state->worldMatrix * m; - else - m = state->worldMatrix; - } - invMatrix = m.inverted(); // invert matrix + invMatrix = state->matrix.inverted(); } void QPainterPrivate::updateEmulationSpecifier(QPainterState *s) @@ -944,8 +924,8 @@ void QPainterPrivate::updateState(QPainterState *newState) \brief The QPainter class performs low-level painting on widgets and other paint devices. - \ingroup multimedia - \mainclass + \ingroup painting + \reentrant QPainter provides highly optimized functions to do most of the @@ -1025,7 +1005,7 @@ void QPainterPrivate::updateState(QPainterState *newState) \o brushOrigin() defines the origin of the tiled brushes, normally the origin of widget's background. - \o viewport(), window(), worldMatrix() make up the painter's coordinate + \o viewport(), window(), worldTransform() make up the painter's coordinate transformation system. For more information, see the \l {Coordinate Transformations} section and the \l {The Coordinate System} documentation. @@ -1036,7 +1016,7 @@ void QPainterPrivate::updateState(QPainterState *newState) \o layoutDirection() defines the layout direction used by the painter when drawing text. - \o matrixEnabled() tells whether world transformation is enabled. + \o worldMatrixEnabled() tells whether world transformation is enabled. \o viewTransformEnabled() tells whether view transformation is enabled. @@ -1232,15 +1212,15 @@ void QPainterPrivate::updateState(QPainterState *newState) \endtable All the tranformation operations operate on the transformation - worldMatrix(). A matrix transforms a point in the plane to another + worldTransform(). A matrix transforms a point in the plane to another point. For more information about the transformation matrix, see - the \l {The Coordinate System} and QMatrix documentation. + the \l {The Coordinate System} and QTransform documentation. - The setWorldMatrix() function can replace or add to the currently - set worldMatrix(). The resetMatrix() function resets any + The setWorldTransform() function can replace or add to the currently + set worldTransform(). The resetTransform() function resets any transformations that were made using translate(), scale(), - shear(), rotate(), setWorldMatrix(), setViewport() and setWindow() - functions. The deviceMatrix() returns the matrix that transforms + shear(), rotate(), setWorldTransform(), setViewport() and setWindow() + functions. The deviceTransform() returns the matrix that transforms from logical coordinates to device coordinates of the platform dependent paint device. The latter function is only needed when using platform painting commands on the platform dependent handle, @@ -1249,11 +1229,11 @@ void QPainterPrivate::updateState(QPainterState *newState) When drawing with QPainter, we specify points using logical coordinates which then are converted into the physical coordinates of the paint device. The mapping of the logical coordinates to the - physical coordinates are handled by QPainter's combinedMatrix(), a - combination of viewport() and window() and worldMatrix(). The + physical coordinates are handled by QPainter's combinedTransform(), a + combination of viewport() and window() and worldTransform(). The viewport() represents the physical coordinates specifying an arbitrary rectangle, the window() describes the same rectangle in - logical coordinates, and the worldMatrix() is identical with the + logical coordinates, and the worldTransform() is identical with the transformation matrix. See also \l {The Coordinate System} documentation. @@ -1374,8 +1354,8 @@ void QPainterPrivate::updateState(QPainterState *newState) */ QPainter::QPainter() + : d_ptr(new QPainterPrivate(this)) { - d_ptr = new QPainterPrivate(this); } /*! @@ -1407,7 +1387,7 @@ QPainter::QPainter(QPaintDevice *pd) { Q_ASSERT(pd != 0); if (!QPainterPrivate::attachPainterPrivate(this, pd)) { - d_ptr = new QPainterPrivate(this); + d_ptr.reset(new QPainterPrivate(this)); begin(pd); } Q_ASSERT(d_ptr); @@ -1419,11 +1399,14 @@ QPainter::QPainter(QPaintDevice *pd) QPainter::~QPainter() { d_ptr->inDestructor = true; - if (isActive()) - end(); - else if (d_ptr->refcount > 1) - d_ptr->detachPainterPrivate(this); - + QT_TRY { + if (isActive()) + end(); + else if (d_ptr->refcount > 1) + d_ptr->detachPainterPrivate(this); + } QT_CATCH(...) { + // don't throw anything in the destructor. + } if (d_ptr) { // Make sure we haven't messed things up. Q_ASSERT(d_ptr->inDestructor); @@ -1431,7 +1414,6 @@ QPainter::~QPainter() Q_ASSERT(d_ptr->refcount == 1); if (d_ptr->d_ptrs) free(d_ptr->d_ptrs); - delete d_ptr; } } @@ -1572,10 +1554,8 @@ void QPainter::restore() // replay the list of clip states, for (int i=0; i<d->state->clipInfo.size(); ++i) { const QPainterClipInfo &info = d->state->clipInfo.at(i); - tmp->matrix.setMatrix(info.matrix.m11(), info.matrix.m12(), info.matrix.m13(), - info.matrix.m21(), info.matrix.m22(), info.matrix.m23(), - info.matrix.dx() - d->state->redirection_offset.x(), - info.matrix.dy() - d->state->redirection_offset.y(), info.matrix.m33()); + tmp->matrix = info.matrix; + tmp->matrix *= d->state->redirectionMatrix; tmp->clipOperation = info.operation; if (info.clipType == QPainterClipInfo::RectClip) { tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform; @@ -1689,12 +1669,12 @@ bool QPainter::begin(QPaintDevice *pd) d->state->painter = this; d->states.push_back(d->state); - d->state->redirection_offset = redirectionOffset; + d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y()); d->state->brushOrigin = QPointF(); if (!d->engine) { qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType()); - return true; + return false; } // Slip a painter state into the engine before we do any other operations @@ -1723,7 +1703,8 @@ bool QPainter::begin(QPaintDevice *pd) // Adjust offset for alien widgets painting outside the paint event. if (!inPaintEvent && paintOutsidePaintEvent && !widget->internalWinId() && widget->testAttribute(Qt::WA_WState_Created)) { - d->state->redirection_offset -= widget->mapTo(widget->nativeParentWidget(), QPoint()); + const QPoint offset = widget->mapTo(widget->nativeParentWidget(), QPoint()); + d->state->redirectionMatrix.translate(offset.x(), offset.y()); } break; } @@ -1805,11 +1786,12 @@ bool QPainter::begin(QPaintDevice *pd) d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight); } - d->state->redirection_offset += d->engine->coordinateOffset(); + const QPoint coordinateOffset = d->engine->coordinateOffset(); + d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y()); Q_ASSERT(d->engine->isActive()); - if (!d->state->redirection_offset.isNull()) + if (!d->state->redirectionMatrix.isIdentity()) d->updateMatrix(); Q_ASSERT(d->engine->isActive()); @@ -1907,6 +1889,45 @@ QPaintEngine *QPainter::paintEngine() const return d->engine; } +/*! + Flushes the painting pipeline and prepares for the user issuing + native painting commands. Must be followed by a call to + endNativePainting(). + + \sa endNativePainting() +*/ +void QPainter::beginNativePainting() +{ + Q_D(QPainter); + if (!d->engine) { + qWarning("QPainter::beginNativePainting: Painter not active"); + return; + } + + if (d->extended) + d->extended->beginNativePainting(); +} + +/*! + Restores the painter after manually issuing native painting commands. + Lets the painter restore any native state that it relies on before + calling any other painter commands. + + \sa beginNativePainting() +*/ +void QPainter::endNativePainting() +{ + Q_D(const QPainter); + if (!d->engine) { + qWarning("QPainter::beginNativePainting: Painter not active"); + return; + } + + if (d->extended) + d->extended->endNativePainting(); + else + d->engine->syncState(); +} /*! Returns the font metrics for the painter if the painter is @@ -2581,7 +2602,9 @@ void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op) QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint); d->state->clipEnabled = true; d->extended->clip(vp, op); - d->state->clipInfo << QPainterClipInfo(rect, op, combinedTransform()); + if (op == Qt::ReplaceClip || op == Qt::NoClip) + d->state->clipInfo.clear(); + d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix); d->state->clipOperation = op; return; } @@ -2627,7 +2650,9 @@ void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op) if (d->extended) { d->state->clipEnabled = true; d->extended->clip(rect, op); - d->state->clipInfo << QPainterClipInfo(rect, op, combinedTransform()); + if (op == Qt::ReplaceClip || op == Qt::NoClip) + d->state->clipInfo.clear(); + d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix); d->state->clipOperation = op; return; } @@ -2636,7 +2661,7 @@ void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op) d->state->clipOperation = op; if (op == Qt::NoClip || op == Qt::ReplaceClip) d->state->clipInfo.clear(); - d->state->clipInfo << QPainterClipInfo(rect, op, combinedTransform()); + d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix); d->state->clipEnabled = true; d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled; d->updateState(d->state); @@ -2680,7 +2705,9 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op) if (d->extended) { d->state->clipEnabled = true; d->extended->clip(r, op); - d->state->clipInfo << QPainterClipInfo(r, op, combinedTransform()); + if (op == Qt::NoClip || op == Qt::ReplaceClip) + d->state->clipInfo.clear(); + d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix); d->state->clipOperation = op; return; } @@ -2689,7 +2716,7 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op) d->state->clipOperation = op; if (op == Qt::NoClip || op == Qt::ReplaceClip) d->state->clipInfo.clear(); - d->state->clipInfo << QPainterClipInfo(r, op, combinedTransform()); + d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix); d->state->clipEnabled = true; d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled; d->updateState(d->state); @@ -2697,6 +2724,7 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op) /*! \since 4.2 + \obsolete Sets the transformation matrix to \a matrix and enables transformations. @@ -2735,7 +2763,7 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op) and window-viewport conversion, see \l {The Coordinate System} documentation. - \sa worldMatrixEnabled(), QMatrix + \sa setWorldTransform(), QTransform */ void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine) @@ -2745,6 +2773,7 @@ void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine) /*! \since 4.2 + \obsolete Returns the world transformation matrix. @@ -2794,6 +2823,7 @@ const QMatrix &QPainter::matrix() const /*! \since 4.2 + \obsolete Returns the transformation matrix combining the current window/viewport and world transformation. @@ -2801,7 +2831,7 @@ const QMatrix &QPainter::matrix() const It is advisable to use combinedTransform() instead of this function to preserve the properties of perspective transformations. - \sa setWorldMatrix(), setWindow(), setViewport() + \sa setWorldTransform(), setWindow(), setViewport() */ QMatrix QPainter::combinedMatrix() const { @@ -2810,6 +2840,8 @@ QMatrix QPainter::combinedMatrix() const /*! + \obsolete + Returns the matrix that transforms from logical coordinates to device coordinates of the platform dependent paint device. @@ -2837,6 +2869,8 @@ const QMatrix &QPainter::deviceMatrix() const } /*! + \obsolete + Resets any transformations that were made using translate(), scale(), shear(), rotate(), setWorldMatrix(), setViewport() and setWindow(). @@ -2861,7 +2895,7 @@ void QPainter::resetMatrix() transformations if \a enable is false. The world transformation matrix is not changed. - \sa worldMatrixEnabled(), worldMatrix(), {QPainter#Coordinate + \sa worldMatrixEnabled(), worldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations} */ @@ -2890,7 +2924,7 @@ void QPainter::setWorldMatrixEnabled(bool enable) Returns true if world transformation is enabled; otherwise returns false. - \sa setWorldMatrixEnabled(), worldMatrix(), {The Coordinate System} + \sa setWorldMatrixEnabled(), worldTransform(), {The Coordinate System} */ bool QPainter::worldMatrixEnabled() const @@ -2932,7 +2966,7 @@ bool QPainter::matrixEnabled() const /*! Scales the coordinate system by (\a{sx}, \a{sy}). - \sa setWorldMatrix() {QPainter#Coordinate Transformations}{Coordinate + \sa setWorldTransform() {QPainter#Coordinate Transformations}{Coordinate Transformations} */ @@ -2956,7 +2990,7 @@ void QPainter::scale(qreal sx, qreal sy) /*! Shears the coordinate system by (\a{sh}, \a{sv}). - \sa setWorldMatrix(), {QPainter#Coordinate Transformations}{Coordinate + \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations} */ @@ -2982,7 +3016,7 @@ void QPainter::shear(qreal sh, qreal sv) Rotates the coordinate system the given \a angle clockwise. - \sa setWorldMatrix(), {QPainter#Coordinate Transformations}{Coordinate + \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations} */ @@ -3007,7 +3041,7 @@ void QPainter::rotate(qreal a) Translates the coordinate system by the given \a offset; i.e. the given \a offset is added to points. - \sa setWorldMatrix(), {QPainter#Coordinate Transformations}{Coordinate + \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations} */ void QPainter::translate(const QPointF &offset) @@ -3077,7 +3111,9 @@ void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op) if (d->extended) { d->state->clipEnabled = true; d->extended->clip(path, op); - d->state->clipInfo << QPainterClipInfo(path, op, combinedTransform()); + if (op == Qt::NoClip || op == Qt::ReplaceClip) + d->state->clipInfo.clear(); + d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix); d->state->clipOperation = op; return; } @@ -3086,7 +3122,7 @@ void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op) d->state->clipOperation = op; if (op == Qt::NoClip || op == Qt::ReplaceClip) d->state->clipInfo.clear(); - d->state->clipInfo << QPainterClipInfo(path, op, combinedTransform()); + d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix); d->state->clipEnabled = true; d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled; d->updateState(d->state); @@ -5699,7 +5735,6 @@ void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justif engine.justify(line); } QFixed x = QFixed::fromReal(p.x()); - QFixed ox = x; for (int i = 0; i < nItems; ++i) { int item = visualOrder[i]; @@ -6083,22 +6118,22 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti) const QTransform &m = d->state->matrix; if (d->state->matrix.type() < QTransform::TxShear) { bool isPlain90DegreeRotation = - (qFuzzyCompare(m.m11() + 1, qreal(1)) - && qFuzzyCompare(m.m12(), qreal(1)) - && qFuzzyCompare(m.m21(), qreal(-1)) - && qFuzzyCompare(m.m22() + 1, qreal(1)) + (qFuzzyIsNull(m.m11()) + && qFuzzyIsNull(m.m12() - qreal(1)) + && qFuzzyIsNull(m.m21() + qreal(1)) + && qFuzzyIsNull(m.m22()) ) || - (qFuzzyCompare(m.m11(), qreal(-1)) - && qFuzzyCompare(m.m12() + 1, qreal(1)) - && qFuzzyCompare(m.m21() + 1, qreal(1)) - && qFuzzyCompare(m.m22(), qreal(-1)) + (qFuzzyIsNull(m.m11() + qreal(1)) + && qFuzzyIsNull(m.m12()) + && qFuzzyIsNull(m.m21()) + && qFuzzyIsNull(m.m22() + qreal(1)) ) || - (qFuzzyCompare(m.m11() + 1, qreal(1)) - && qFuzzyCompare(m.m12(), qreal(-1)) - && qFuzzyCompare(m.m21(), qreal(1)) - && qFuzzyCompare(m.m22() + 1, qreal(1)) + (qFuzzyIsNull(m.m11()) + && qFuzzyIsNull(m.m12() + qreal(1)) + && qFuzzyIsNull(m.m21() - qreal(1)) + && qFuzzyIsNull(m.m22()) ) ; aa = !isPlain90DegreeRotation; @@ -6789,7 +6824,7 @@ QPainter::RenderHints QPainter::renderHints() const Returns true if view transformation is enabled; otherwise returns false. - \sa setViewTransformEnabled(), worldMatrix() + \sa setViewTransformEnabled(), worldTransform() */ bool QPainter::viewTransformEnabled() const @@ -6945,7 +6980,7 @@ QRect QPainter::viewport() const /*! \fn void QPainter::resetXForm() \compat - Use resetMatrix() instead. + Use resetTransform() instead. */ /*! \fn void QPainter::setViewXForm(bool enabled) @@ -6991,14 +7026,16 @@ void QPainter::setViewTransformEnabled(bool enable) #ifdef QT3_SUPPORT /*! - Use the worldMatrix() combined with QMatrix::dx() instead. + \obsolete + + Use the worldTransform() combined with QTransform::dx() instead. \oldcode QPainter painter(this); qreal x = painter.translationX(); \newcode QPainter painter(this); - qreal x = painter.worldMatrix().dx(); + qreal x = painter.worldTransform().dx(); \endcode */ qreal QPainter::translationX() const @@ -7012,14 +7049,16 @@ qreal QPainter::translationX() const } /*! - Use the worldMatrix() combined with QMatrix::dy() instead. + \obsolete + + Use the worldTransform() combined with QTransform::dy() instead. \oldcode QPainter painter(this); qreal y = painter.translationY(); \newcode QPainter painter(this); - qreal y = painter.worldMatrix().dy(); + qreal y = painter.worldTransform().dy(); \endcode */ qreal QPainter::translationY() const @@ -7117,7 +7156,7 @@ QPolygon QPainter::xForm(const QPolygon &a) const QPolygon transformed = painter.xForm(polygon, index, count) \newcode QPainter painter(this); - QPolygon transformed = polygon.mid(index, count) * painter.combinedMatrix(); + QPolygon transformed = polygon.mid(index, count) * painter.combinedTransform(); \endcode */ @@ -7132,15 +7171,16 @@ QPolygon QPainter::xForm(const QPolygon &av, int index, int npoints) const /*! \fn QPoint QPainter::xFormDev(const QPoint &point) const \overload + \obsolete - Use combinedTransform() combined with QMatrix::inverted() instead. + Use combinedTransform() combined with QTransform::inverted() instead. \oldcode QPainter painter(this); QPoint transformed = painter.xFormDev(point); \newcode QPainter painter(this); - QPoint transformed = point * painter.combinedMatrix().inverted(); + QPoint transformed = point * painter.combinedTransform().inverted(); \endcode */ @@ -7159,15 +7199,17 @@ QPoint QPainter::xFormDev(const QPoint &p) const /*! \fn QRect QPainter::xFormDev(const QRect &rectangle) const \overload + \obsolete - Use mapRect() combined with QMatrix::inverted() instead. + Use combinedTransform() combined with QTransform::inverted() instead. \oldcode QPainter painter(this); QRect transformed = painter.xFormDev(rectangle); \newcode QPainter painter(this); - QRect transformed = painter.combinedMatrix().inverted(rectangle); + QRegion region = QRegion(rectangle) * painter.combinedTransform().inverted(); + QRect transformed = region.boundingRect(); \endcode */ @@ -7187,16 +7229,16 @@ QRect QPainter::xFormDev(const QRect &r) const \overload \fn QPoint QPainter::xFormDev(const QPolygon &polygon) const - \overload + \obsolete - Use combinedMatrix() combined with QMatrix::inverted() instead. + Use combinedTransform() combined with QTransform::inverted() instead. \oldcode QPainter painter(this); QPolygon transformed = painter.xFormDev(rectangle); \newcode QPainter painter(this); - QPolygon transformed = polygon * painter.combinedMatrix().inverted(); + QPolygon transformed = polygon * painter.combinedTransform().inverted(); \endcode */ @@ -7215,15 +7257,16 @@ QPolygon QPainter::xFormDev(const QPolygon &a) const /*! \fn QPolygon QPainter::xFormDev(const QPolygon &polygon, int index, int count) const \overload + \obsolete - Use combinedMatrix() combined with QPolygon::mid() and QMatrix::inverted() instead. + Use combinedTransform() combined with QPolygon::mid() and QTransform::inverted() instead. \oldcode QPainter painter(this); QPolygon transformed = painter.xFormDev(polygon, index, count); \newcode QPainter painter(this); - QPolygon transformed = polygon.mid(index, count) * painter.combinedMatrix().inverted(); + QPolygon transformed = polygon.mid(index, count) * painter.combinedTransform().inverted(); \endcode */ @@ -7418,8 +7461,21 @@ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset) void qt_painter_removePaintDevice(QPaintDevice *dev) { - QMutexLocker locker(globalRedirectionsMutex()); - if(QPaintDeviceRedirectionList *redirections = globalRedirections()) { + QMutex *mutex = 0; + QT_TRY { + mutex = globalRedirectionsMutex(); + } QT_CATCH(...) { + // ignore the missing mutex, since we could be called from + // a destructor, and destructors shall not throw + } + QMutexLocker locker(mutex); + QPaintDeviceRedirectionList *redirections = 0; + QT_TRY { + redirections = globalRedirections(); + } QT_CATCH(...) { + // do nothing - code below is safe with redirections being 0. + } + if (redirections) { for (int i = 0; i < redirections->size(); ) { if(redirections->at(i) == dev || redirections->at(i).replacement == dev) redirections->removeAt(i); @@ -7486,67 +7542,63 @@ void qt_format_text(const QFont &fnt, const QRectF &_r, if (!painter) tf |= Qt::TextDontPrint; - int maxUnderlines = 0; + uint maxUnderlines = 0; int numUnderlines = 0; - int underlinePositionStack[32]; - int *underlinePositions = underlinePositionStack; + QVarLengthArray<int, 32> underlinePositions(1); QFontMetricsF fm(fnt); - QString text = str; + int offset = 0; +start_lengthVariant: + bool hasMoreLengthVariants = false; // compatible behaviour to the old implementation. Replace // tabs by spaces - QChar *chr = text.data(); - const QChar *end = chr + str.length(); bool has_tab = false; - while (chr != end) { - if (*chr == QLatin1Char('\r') || (singleline && *chr == QLatin1Char('\n'))) { - *chr = QLatin1Char(' '); - } else if (*chr == QLatin1Char('\n')) { - *chr = QChar::LineSeparator; - } else if (*chr == QLatin1Char('&')) { + int old_offset = offset; + for (; offset < text.length(); offset++) { + QChar chr = text.at(offset); + if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) { + text[offset] = QLatin1Char(' '); + } else if (chr == QLatin1Char('\n')) { + chr = QChar::LineSeparator; + } else if (chr == QLatin1Char('&')) { ++maxUnderlines; - } else if (*chr == QLatin1Char('\t')) { - has_tab = true; - } - ++chr; - } - if (has_tab) { - if (!expandtabs) { - chr = text.data(); - while (chr != end) { - if (*chr == QLatin1Char('\t')) - *chr = QLatin1Char(' '); - ++chr; + } else if (chr == QLatin1Char('\t')) { + if (!expandtabs) { + text[offset] = QLatin1Char(' '); + } else if (!tabarraylen && !tabstops) { + tabstops = qRound(fm.width(QLatin1Char('x'))*8); } - } else if (!tabarraylen && !tabstops) { - tabstops = qRound(fm.width(QLatin1Char('x'))*8); + has_tab = true; + } else if (chr == QChar(ushort(0x9c))) { + // string with multiple length variants + hasMoreLengthVariants = true; + break; } } - if (hidemnmemonic || showmnemonic) { - if (maxUnderlines > 32) - underlinePositions = new int[maxUnderlines]; - QChar *cout = text.data(); + int length = offset - old_offset; + if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) { + underlinePositions.resize(maxUnderlines + 1); + + QChar *cout = text.data() + old_offset; QChar *cin = cout; - int l = str.length(); + int l = length; while (l) { if (*cin == QLatin1Char('&')) { ++cin; + --length; --l; if (!l) break; if (*cin != QLatin1Char('&') && !hidemnmemonic) - underlinePositions[numUnderlines++] = cout - text.unicode(); + underlinePositions[numUnderlines++] = cout - text.data() - old_offset; } *cout = *cin; ++cout; ++cin; --l; } - int newlen = cout - text.unicode(); - if (newlen != text.length()) - text.resize(newlen); } // no need to do extra work for underlines if we don't paint @@ -7557,13 +7609,12 @@ void qt_format_text(const QFont &fnt, const QRectF &_r, qreal height = 0; qreal width = 0; - QStackTextEngine engine(text, fnt); + QString finalText = text.mid(old_offset, length); + QStackTextEngine engine(finalText, fnt); if (option) { engine.option = *option; } - - engine.option.setTextDirection(layout_direction); if (tf & Qt::AlignJustify) engine.option.setAlignment(Qt::AlignJustify); @@ -7577,9 +7628,9 @@ void qt_format_text(const QFont &fnt, const QRectF &_r, engine.forceJustification = true; QTextLayout textLayout(&engine); textLayout.setCacheEnabled(true); - textLayout.engine()->underlinePositions = underlinePositions; + textLayout.engine()->underlinePositions = underlinePositions.data(); - if (text.isEmpty()) { + if (finalText.isEmpty()) { height = fm.height(); width = 0; tf |= Qt::TextDontPrint; @@ -7644,6 +7695,11 @@ void qt_format_text(const QFont &fnt, const QRectF &_r, } } QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height); + + if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) { + offset++; + goto start_lengthVariant; + } if (brect) *brect = bounds; @@ -7670,9 +7726,6 @@ void qt_format_text(const QFont &fnt, const QRectF &_r, painter->restore(); } } - - if (underlinePositions != underlinePositionStack) - delete [] underlinePositions; } /*! @@ -7705,7 +7758,7 @@ QPainterState::QPainterState(const QPainterState *s) clipRegion(s->clipRegion), clipPath(s->clipPath), clipOperation(s->clipOperation), renderHints(s->renderHints), clipInfo(s->clipInfo), - worldMatrix(s->worldMatrix), matrix(s->matrix), redirection_offset(s->redirection_offset), + worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix), wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh), vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh), opacity(s->opacity), WxF(s->WxF), VxF(s->VxF), @@ -8127,7 +8180,7 @@ void bitBlt(QPaintDevice *dst, int dx, int dy, \row \o QPaintEngine::DirtyClipRegion \o clipRegion() \row \o QPaintEngine::DirtyCompositionMode \o compositionMode() \row \o QPaintEngine::DirtyFont \o font() - \row \o QPaintEngine::DirtyTransform \o matrix() + \row \o QPaintEngine::DirtyTransform \o transform() \row \o QPaintEngine::DirtyClipEnabled \o isClipEnabled() \row \o QPaintEngine::DirtyPen \o pen() \row \o QPaintEngine::DirtyHints \o renderHints() @@ -8246,10 +8299,14 @@ QFont QPaintEngineState::font() const /*! \since 4.2 + \obsolete Returns the matrix in the current paint engine state. + \note It is advisable to use transform() instead of this function to + preserve the properties of perspective transformations. + This variable should only be used when the state() returns a combination which includes the QPaintEngine::DirtyTransform flag. @@ -8430,11 +8487,7 @@ qreal QPaintEngineState::opacity() const If \a combine is true, the specified \a transform is combined with the current matrix; otherwise it replaces the current matrix. - This function has been added for compatibility with setMatrix(), - but as with setMatrix() the preferred method of setting a - transformation on the painter is through setWorldTransform(). - - \sa transform() + \sa transform() setWorldTransform() */ void QPainter::setTransform(const QTransform &transform, bool combine ) @@ -8444,6 +8497,8 @@ void QPainter::setTransform(const QTransform &transform, bool combine ) /*! Returns the world transformation matrix. + + \sa worldTransform() */ const QTransform & QPainter::transform() const @@ -8554,7 +8609,7 @@ const QTransform & QPainter::worldTransform() const Returns the transformation matrix combining the current window/viewport and world transformation. - \sa setWorldMatrix(), setWindow(), setViewport() + \sa setWorldTransform(), setWindow(), setViewport() */ QTransform QPainter::combinedTransform() const diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index 1ce7f24..0dd7b7b 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -45,6 +45,7 @@ #include <QtCore/qnamespace.h> #include <QtCore/qrect.h> #include <QtCore/qpoint.h> +#include <QtCore/qscopedpointer.h> #include <QtGui/qpixmap.h> #include <QtGui/qimage.h> #include <QtGui/qtextoption.h> @@ -78,6 +79,8 @@ class QTextItem; class QMatrix; class QTransform; +class QPainterPrivateDeleter; + class Q_GUI_EXPORT QPainter { Q_DECLARE_PRIVATE(QPainter) @@ -420,6 +423,9 @@ public: static QPaintDevice *redirected(const QPaintDevice *device, QPoint *offset = 0); static void restoreRedirected(const QPaintDevice *device); + void beginNativePainting(); + void endNativePainting(); + #ifdef QT3_SUPPORT inline QT3_SUPPORT void setBackgroundColor(const QColor &color) { setBackground(color); } @@ -497,7 +503,7 @@ private: Q_DISABLE_COPY(QPainter) friend class Q3Painter; - QPainterPrivate *d_ptr; + QScopedPointer<QPainterPrivate> d_ptr; friend class QFontEngine; friend class QFontEngineBox; @@ -507,6 +513,7 @@ private: friend class QFontEngineXLFD; friend class QWSManager; friend class QPaintEngine; + friend class QPaintEngineExPrivate; friend class QOpenGLPaintEngine; friend class QX11PaintEngine; friend class QX11PaintEnginePrivate; diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h index d3dd1b4..8843737 100644 --- a/src/gui/painting/qpainter_p.h +++ b/src/gui/painting/qpainter_p.h @@ -63,7 +63,7 @@ #include "QtGui/qpaintengine.h" #include <QtCore/qhash.h> -#include "qpen_p.h" +#include <private/qpen_p.h> QT_BEGIN_NAMESPACE @@ -92,8 +92,8 @@ inline Qt::PenJoinStyle qpen_joinStyle(const QPen &p) { return data_ptr(p)->join // QBrush inline functions... inline QBrush::DataPtr &data_ptr(const QBrush &p) { return const_cast<QBrush &>(p).data_ptr(); } inline bool qbrush_fast_equals(const QBrush &a, const QBrush &b) { return data_ptr(a) == data_ptr(b); } -inline Qt::BrushStyle qbrush_style(const QBrush &b) { return data_ptr(b)->style; }; -inline const QColor &qbrush_color(const QBrush &b) { return data_ptr(b)->color; }; +inline Qt::BrushStyle qbrush_style(const QBrush &b) { return data_ptr(b)->style; } +inline const QColor &qbrush_color(const QBrush &b) { return data_ptr(b)->color; } inline bool qbrush_has_transform(const QBrush &b) { return data_ptr(b)->transform.type() > QTransform::TxNone; } class QPainterClipInfo @@ -158,7 +158,7 @@ public: QList<QPainterClipInfo> clipInfo; // ### Make me smaller and faster to copy around... QTransform worldMatrix; // World transformation matrix, not window and viewport QTransform matrix; // Complete transformation matrix, - QPoint redirection_offset; + QTransform redirectionMatrix; int wx, wy, ww, wh; // window rectangle int vx, vy, vw, vh; // viewport rectangle qreal opacity; diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index ff133b6..8d3cfab 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -73,6 +73,17 @@ QT_BEGIN_NAMESPACE +struct QPainterPathPrivateDeleter +{ + static inline void cleanup(QPainterPathPrivate *d) + { + // note - we must up-cast to QPainterPathData since QPainterPathPrivate + // has a non-virtual destructor! + if (d && !d->ref.deref()) + delete static_cast<QPainterPathData *>(d); + } +}; + // This value is used to determine the length of control point vectors // when approximating arc segments as curves. The factor is multiplied // with the radius of the circle. @@ -153,7 +164,7 @@ static void qt_debug_path(const QPainterPath &path) /*! \class QPainterPath - \ingroup multimedia + \ingroup painting \ingroup shared \brief The QPainterPath class provides a container for painting operations, @@ -506,10 +517,10 @@ QPainterPath::QPainterPath() \sa operator=() */ QPainterPath::QPainterPath(const QPainterPath &other) - : d_ptr(other.d_ptr) + : d_ptr(other.d_ptr.data()) { - if (d_func()) - d_func()->ref.ref(); + if (d_ptr) + d_ptr->ref.ref(); } /*! @@ -530,9 +541,7 @@ QPainterPath::QPainterPath(const QPointF &startPoint) void QPainterPath::detach_helper() { QPainterPathPrivate *data = new QPainterPathData(*d_func()); - if (d_ptr && !d_ptr->ref.deref()) - delete d_ptr; - d_ptr = data; + d_ptr.reset(data); } /*! @@ -544,9 +553,7 @@ void QPainterPath::ensureData_helper() data->elements.reserve(16); QPainterPath::Element e = { 0, 0, QPainterPath::MoveToElement }; data->elements << e; - if (d_ptr && !d_ptr->ref.deref()) - delete d_ptr; - d_ptr = data; + d_ptr.reset(data); Q_ASSERT(d_ptr != 0); } @@ -563,9 +570,7 @@ QPainterPath &QPainterPath::operator=(const QPainterPath &other) QPainterPathPrivate *data = other.d_func(); if (data) data->ref.ref(); - if (d_ptr && !d_ptr->ref.deref()) - delete d_ptr; - d_ptr = data; + d_ptr.reset(data); } return *this; } @@ -575,8 +580,6 @@ QPainterPath &QPainterPath::operator=(const QPainterPath &other) */ QPainterPath::~QPainterPath() { - if (d_func() && !d_func()->ref.deref()) - delete d_func(); } /*! @@ -1299,10 +1302,10 @@ static QRectF qt_painterpath_bezier_extrema(const QBezier &b) qreal bx = QT_BEZIER_B(b, x); qreal cx = QT_BEZIER_C(b, x); // specialcase quadratic curves to avoid div by zero - if (qFuzzyCompare(ax + 1, 1)) { + if (qFuzzyIsNull(ax)) { // linear curves are covered by initialization. - if (!qFuzzyCompare(bx + 1, 1)) { + if (!qFuzzyIsNull(bx)) { qreal t = -cx / bx; QT_BEZIER_CHECK_T(b, t); } @@ -1329,10 +1332,10 @@ static QRectF qt_painterpath_bezier_extrema(const QBezier &b) qreal cy = QT_BEZIER_C(b, y); // specialcase quadratic curves to avoid div by zero - if (qFuzzyCompare(ay + 1, 1)) { + if (qFuzzyIsNull(ay)) { // linear curves are covered by initialization. - if (!qFuzzyCompare(by + 1, 1)) { + if (!qFuzzyIsNull(by)) { qreal t = -cy / by; QT_BEZIER_CHECK_T(b, t); } @@ -1517,12 +1520,6 @@ QList<QPolygonF> QPainterPath::toSubpathPolygons(const QMatrix &matrix) const return toSubpathPolygons(QTransform(matrix)); } -static inline bool rect_intersects(const QRectF &r1, const QRectF &r2) -{ - return qMax(r1.left(), r2.left()) <= qMin(r1.right(), r2.right()) - && qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), r2.bottom()); -} - /*! Converts the path into a list of polygons using the QTransform \a matrix, and returns the list. @@ -1575,7 +1572,7 @@ QList<QPolygonF> QPainterPath::toFillPolygons(const QTransform &matrix) const continue; QRectF cbounds = bounds.at(j); for (int i=0; i<count; ++i) { - if (rect_intersects(cbounds, bounds.at(i))) { + if (cbounds.intersects(bounds.at(i))) { isects[j] << i; } } @@ -2000,7 +1997,63 @@ bool QPainterPath::intersects(const QRectF &rect) const return false; } +/*! + Translates all elements in the path by (\a{dx}, \a{dy}). + + \since 4.6 + \sa translated() +*/ +void QPainterPath::translate(qreal dx, qreal dy) +{ + if (!d_ptr || (dx == 0 && dy == 0)) + return; + + int elementsLeft = d_ptr->elements.size(); + if (elementsLeft <= 0) + return; + + detach(); + QPainterPath::Element *element = d_func()->elements.data(); + Q_ASSERT(element); + while (elementsLeft--) { + element->x += dx; + element->y += dy; + ++element; + } +} + +/*! + \fn void QPainterPath::translate(const QPointF &offset) + \overload + \since 4.6 + + Translates all elements in the path by the given \a offset. + + \sa translated() +*/ + +/*! + Returns a copy of the path that is translated by (\a{dx}, \a{dy}). + + \since 4.6 + \sa translate() +*/ +QPainterPath QPainterPath::translated(qreal dx, qreal dy) const +{ + QPainterPath copy(*this); + copy.translate(dx, dy); + return copy; +} + +/*! + \fn QPainterPath QPainterPath::translated(const QPointF &offset) const; + \overload + \since 4.6 + + Returns a copy of the path that is translated by the given \a offset. + \sa translate() +*/ /*! \fn bool QPainterPath::contains(const QRectF &rectangle) const @@ -2310,7 +2363,7 @@ QDataStream &operator>>(QDataStream &s, QPainterPath &p) p.d_func()->dirtyControlBounds = true; return s; } -#endif +#endif // QT_NO_DATASTREAM /******************************************************************************* @@ -2340,7 +2393,7 @@ void qt_path_stroke_cubic_to(qfixed c1x, qfixed c1y, /*! \since 4.1 \class QPainterPathStroker - \ingroup multimedia + \ingroup painting \brief The QPainterPathStroker class is used to generate fillable outlines for a given painter path. @@ -2408,7 +2461,6 @@ QPainterPathStroker::QPainterPathStroker() */ QPainterPathStroker::~QPainterPathStroker() { - delete d_ptr; } @@ -2867,7 +2919,7 @@ qreal QPainterPath::angleAtPercent(qreal t) const return QLineF(0, 0, m1, m2).angle(); } -#if defined(Q_OS_WINCE) +#if defined(Q_WS_WINCE) #pragma warning( disable : 4056 4756 ) #endif @@ -3100,7 +3152,7 @@ void QPainterPath::addRoundRect(const QRectF &r, int xRnd, int yRnd) Set operations on paths will treat the paths as areas. Non-closed paths will be treated as implicitly closed. - \sa intersected(), subtracted(), subtractedInverted() + \sa intersected(), subtracted() */ QPainterPath QPainterPath::united(const QPainterPath &p) const { @@ -3215,6 +3267,8 @@ void QPainterPath::setDirty(bool dirty) { d_func()->dirtyBounds = dirty; d_func()->dirtyControlBounds = dirty; + delete d_func()->pathConverter; + d_func()->pathConverter = 0; } void QPainterPath::computeBoundingRect() const @@ -3292,7 +3346,7 @@ QDebug operator<<(QDebug s, const QPainterPath &p) s.nospace() << "QPainterPath: Element count=" << p.elementCount() << endl; const char *types[] = {"MoveTo", "LineTo", "CurveTo", "CurveToData"}; for (int i=0; i<p.elementCount(); ++i) { - s.nospace() << " -> " << types[p.elementAt(i).type] << "(x=" << p.elementAt(i).x << ", y=" << p.elementAt(i).y << ")" << endl; + s.nospace() << " -> " << types[p.elementAt(i).type] << "(x=" << p.elementAt(i).x << ", y=" << p.elementAt(i).y << ')' << endl; } return s; diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h index 03e01eb..9d472e8 100644 --- a/src/gui/painting/qpainterpath.h +++ b/src/gui/painting/qpainterpath.h @@ -47,6 +47,7 @@ #include <QtCore/qrect.h> #include <QtCore/qline.h> #include <QtCore/qvector.h> +#include <QtCore/qscopedpointer.h> QT_BEGIN_HEADER @@ -56,6 +57,7 @@ QT_MODULE(Gui) class QFont; class QPainterPathPrivate; +struct QPainterPathPrivateDeleter; class QPainterPathData; class QPainterPathStrokerPrivate; class QPolygonF; @@ -147,6 +149,12 @@ public: bool contains(const QRectF &rect) const; bool intersects(const QRectF &rect) const; + void translate(qreal dx, qreal dy); + inline void translate(const QPointF &offset); + + QPainterPath translated(qreal dx, qreal dy) const; + inline QPainterPath translated(const QPointF &offset) const; + QRectF boundingRect() const; QRectF controlPointRect() const; @@ -195,7 +203,7 @@ public: QPainterPath &operator-=(const QPainterPath &other); private: - QPainterPathPrivate *d_ptr; + QScopedPointer<QPainterPathPrivate, QPainterPathPrivateDeleter> d_ptr; inline void ensureData() { if (!d_ptr) ensureData_helper(); } void ensureData_helper(); @@ -205,7 +213,7 @@ private: void computeBoundingRect() const; void computeControlPointRect() const; - QPainterPathData *d_func() const { return reinterpret_cast<QPainterPathData *>(d_ptr); } + QPainterPathData *d_func() const { return reinterpret_cast<QPainterPathData *>(d_ptr.data()); } friend class QPainterPathData; friend class QPainterPathStroker; @@ -229,6 +237,7 @@ public: friend class QPainterPathStrokerPrivate; friend class QMatrix; friend class QTransform; + friend struct QPainterPathPrivateDeleter; #ifndef QT_NO_DATASTREAM friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QPainterPath &); friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QPainterPath &); @@ -279,7 +288,7 @@ public: private: friend class QX11PaintEngine; - QPainterPathStrokerPrivate *d_ptr; + QScopedPointer<QPainterPathStrokerPrivate> d_ptr; }; inline void QPainterPath::moveTo(qreal x, qreal y) @@ -292,9 +301,9 @@ inline void QPainterPath::lineTo(qreal x, qreal y) lineTo(QPointF(x, y)); } -inline void QPainterPath::arcTo(qreal x, qreal y, qreal w, qreal h, qreal startAngle, qreal arcLenght) +inline void QPainterPath::arcTo(qreal x, qreal y, qreal w, qreal h, qreal startAngle, qreal arcLength) { - arcTo(QRectF(x, y, w, h), startAngle, arcLenght); + arcTo(QRectF(x, y, w, h), startAngle, arcLength); } inline void QPainterPath::arcMoveTo(qreal x, qreal y, qreal w, qreal h, qreal angle) @@ -365,6 +374,12 @@ inline void QPainterPath::addText(qreal x, qreal y, const QFont &f, const QStrin addText(QPointF(x, y), f, text); } +inline void QPainterPath::translate(const QPointF &offset) +{ translate(offset.x(), offset.y()); } + +inline QPainterPath QPainterPath::translated(const QPointF &offset) const +{ return translated(offset.x(), offset.y()); } + inline bool QPainterPath::isEmpty() const { return !d_ptr || (d_ptr->elements.size() == 1 && d_ptr->elements.first().type == MoveToElement); diff --git a/src/gui/painting/qpainterpath_p.h b/src/gui/painting/qpainterpath_p.h index ac42904..bb455cf 100644 --- a/src/gui/painting/qpainterpath_p.h +++ b/src/gui/painting/qpainterpath_p.h @@ -124,7 +124,7 @@ private: Q_DISABLE_COPY(QVectorPathConverter) }; -class Q_GUI_EXPORT QPainterPathData : public QPainterPathPrivate +class QPainterPathData : public QPainterPathPrivate { public: QPainterPathData() : diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp index 3e5a8f1..2befd86 100644 --- a/src/gui/painting/qpathclipper.cpp +++ b/src/gui/painting/qpathclipper.cpp @@ -151,11 +151,11 @@ bool QIntersectionFinder::linesIntersect(const QLineF &a, const QLineF &b) const const qreal par = pDelta.x() * qDelta.y() - pDelta.y() * qDelta.x(); - if (qFuzzyCompare(par + 1, 1)) { + if (qFuzzyIsNull(par)) { const QPointF normal(-pDelta.y(), pDelta.x()); // coinciding? - if (qFuzzyCompare(dot(normal, q1 - p1) + 1, 1)) { + if (qFuzzyIsNull(dot(normal, q1 - p1))) { const qreal dp = dot(pDelta, pDelta); const qreal tq1 = dot(pDelta, q1 - p1); @@ -217,13 +217,13 @@ void QIntersectionFinder::intersectBeziers(const QBezier &one, const QBezier &tw qreal alpha_q = t.at(i).second; QPointF pt; - if (qFuzzyCompare(alpha_p + 1, 1)) { + if (qFuzzyIsNull(alpha_p)) { pt = one.pt1(); - } else if (qFuzzyCompare(alpha_p, 1)) { + } else if (qFuzzyIsNull(alpha_p - 1)) { pt = one.pt4(); - } else if (qFuzzyCompare(alpha_q + 1, 1)) { + } else if (qFuzzyIsNull(alpha_q)) { pt = two.pt1(); - } else if (qFuzzyCompare(alpha_q, 1)) { + } else if (qFuzzyIsNull(alpha_q - 1)) { pt = two.pt4(); } else { pt = one.pointAt(alpha_p); @@ -265,11 +265,11 @@ void QIntersectionFinder::intersectLines(const QLineF &a, const QLineF &b, QData const qreal par = pDelta.x() * qDelta.y() - pDelta.y() * qDelta.x(); - if (qFuzzyCompare(par + 1, 1)) { + if (qFuzzyIsNull(par)) { const QPointF normal(-pDelta.y(), pDelta.x()); // coinciding? - if (qFuzzyCompare(dot(normal, q1 - p1) + 1, 1)) { + if (qFuzzyIsNull(dot(normal, q1 - p1))) { const qreal invDp = 1 / dot(pDelta, pDelta); const qreal tq1 = dot(pDelta, q1 - p1) * invDp; @@ -330,11 +330,11 @@ void QIntersectionFinder::intersectLines(const QLineF &a, const QLineF &b, QData if (tp<0 || tp>1 || tq<0 || tq>1) return; - const bool p_zero = qFuzzyCompare(tp + 1, 1); - const bool p_one = qFuzzyCompare(tp, 1); + const bool p_zero = qFuzzyIsNull(tp); + const bool p_one = qFuzzyIsNull(tp - 1); - const bool q_zero = qFuzzyCompare(tq + 1, 1); - const bool q_one = qFuzzyCompare(tq, 1); + const bool q_zero = qFuzzyIsNull(tq); + const bool q_one = qFuzzyIsNull(tq - 1); if ((q_zero || q_one) && (p_zero || p_one)) return; @@ -937,7 +937,7 @@ qreal QWingedEdge::delta(int vertex, int a, int b) const qreal result = b_angle - a_angle; - if (qFuzzyCompare(result + 1, 1) || qFuzzyCompare(result, 128)) + if (qFuzzyIsNull(result) || qFuzzyCompare(result, 128)) return 0; if (result < 0) @@ -966,7 +966,7 @@ static inline QPointF tangentAt(const QWingedEdge &list, int vi, int ei) if (ep->bezier) { normal = ep->bezier->derivedAt(t); - if (qFuzzyCompare(normal.x() + 1, 1) && qFuzzyCompare(normal.y() + 1, 1)) + if (qFuzzyIsNull(normal.x()) && qFuzzyIsNull(normal.y())) normal = ep->bezier->secondDerivedAt(t); } else { const QPointF a = *list.vertex(ep->first); @@ -1095,7 +1095,7 @@ QWingedEdge::TraversalStatus QWingedEdge::findInsertStatus(int vi, int ei) const qDebug() << "Delta to edge" << status.edge << d2 << ", angles: " << op->angle << op->invAngle; #endif - if (!(qFuzzyCompare(d2 + 1, 1) && isLeftOf(*this, vi, status.edge, ei)) + if (!(qFuzzyIsNull(d2) && isLeftOf(*this, vi, status.edge, ei)) && (d2 < d || (qFuzzyCompare(d2, d) && isLeftOf(*this, vi, status.edge, position)))) { position = status.edge; d = d2; @@ -1247,10 +1247,10 @@ int QWingedEdge::addEdge(int fi, int si, const QBezier *bezier, qreal t0, qreal QPointF aTangent = bezier->derivedAt(t0); QPointF bTangent = -bezier->derivedAt(t1); - if (qFuzzyCompare(aTangent.x() + 1, 1) && qFuzzyCompare(aTangent.y() + 1, 1)) + if (qFuzzyIsNull(aTangent.x()) && qFuzzyIsNull(aTangent.y())) aTangent = bezier->secondDerivedAt(t0); - if (qFuzzyCompare(bTangent.x() + 1, 1) && qFuzzyCompare(bTangent.y() + 1, 1)) + if (qFuzzyIsNull(bTangent.x()) && qFuzzyIsNull(bTangent.y())) bTangent = bezier->secondDerivedAt(t1); ep->angle = computeAngle(aTangent); @@ -1415,7 +1415,7 @@ static void addLineTo(QPainterPath &path, const QPointF &point) const QPointF p(-d1.y(), d1.x()); - if (qFuzzyCompare(dot(p, d2) + 1, 1)) { + if (qFuzzyIsNull(dot(p, d2))) { path.setElementPositionAt(elementCount - 1, point.x(), point.y()); return; } diff --git a/src/gui/painting/qpathclipper_p.h b/src/gui/painting/qpathclipper_p.h index 641ecdd..e9569bb 100644 --- a/src/gui/painting/qpathclipper_p.h +++ b/src/gui/painting/qpathclipper_p.h @@ -160,8 +160,6 @@ public: Direction directionTo(int vertex) const; int vertex(Direction direction) const; - bool isBezier() const; - private: int m_next[2][2]; }; @@ -347,11 +345,6 @@ inline int QPathEdge::vertex(Direction direction) const return direction == Backward ? first : second; } -inline bool QPathEdge::isBezier() const -{ - return bezier >= 0; -} - inline QPathVertex::QPathVertex(const QPointF &p, int e) : edge(e) , x(p.x()) diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index 21d44ef..e60f50f 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -48,6 +48,10 @@ #include "qprinterinfo.h" #include <qnumeric.h> +#ifdef Q_OS_UNIX +#include "private/qcore_unix_p.h" // overrides QT_OPEN +#endif + QT_BEGIN_NAMESPACE extern int qt_defaultDpi(); @@ -309,7 +313,7 @@ QByteArray QPdf::generatePath(const QPainterPath &path, const QTransform &matrix Qt::FillRule fillRule = path.fillRule(); - const char *op = 0; + const char *op = ""; switch (flags) { case ClipPath: op = (fillRule == Qt::WindingFill) ? "W n\n" : "W* n\n"; @@ -346,7 +350,7 @@ QByteArray QPdf::generateDashes(const QPen &pen) { QByteArray result; ByteStream s(&result); - s << "["; + s << '['; QVector<qreal> dasharray = pen.dashPattern(); qreal w = pen.widthF(); @@ -357,7 +361,7 @@ QByteArray QPdf::generateDashes(const QPen &pen) if (dw < 0.0001) dw = 0.0001; s << dw; } - s << "]"; + s << ']'; //qDebug() << "dasharray: pen has" << dasharray; //qDebug() << " => " << result; return result; @@ -915,17 +919,17 @@ const char *QPdf::paperSizeToString(QPrinter::PaperSize paperSize) QByteArray QPdf::stripSpecialCharacters(const QByteArray &string) { QByteArray s = string; - s.replace(" ", ""); - s.replace("(", ""); - s.replace(")", ""); - s.replace("<", ""); - s.replace(">", ""); - s.replace("[", ""); - s.replace("]", ""); - s.replace("{", ""); - s.replace("}", ""); - s.replace("/", ""); - s.replace("%", ""); + s.replace(' ', ""); + s.replace('(', ""); + s.replace(')', ""); + s.replace('<', ""); + s.replace('>', ""); + s.replace('[', ""); + s.replace(']', ""); + s.replace('{', ""); + s.replace('}', ""); + s.replace('/', ""); + s.replace('%', ""); return s; } @@ -1467,10 +1471,10 @@ void QPdfBaseEngine::setProperty(PrintEnginePropertyKey key, const QVariant &val { QList<QVariant> margins(value.toList()); Q_ASSERT(margins.size() == 4); - d->leftMargin = margins.at(0).toDouble(); - d->topMargin = margins.at(1).toDouble(); - d->rightMargin = margins.at(2).toDouble(); - d->bottomMargin = margins.at(3).toDouble(); + d->leftMargin = margins.at(0).toReal(); + d->topMargin = margins.at(1).toReal(); + d->rightMargin = margins.at(2).toReal(); + d->bottomMargin = margins.at(3).toReal(); d->hasCustomPageMargins = true; break; } @@ -1572,7 +1576,7 @@ QVariant QPdfBaseEngine::property(PrintEnginePropertyKey key) const margins << d->leftMargin << d->topMargin << d->rightMargin << d->bottomMargin; } else { - const int defaultMargin = 10; // ~3.5 mm + const qreal defaultMargin = 10; // ~3.5 mm margins << defaultMargin << defaultMargin << defaultMargin << defaultMargin; } @@ -1652,7 +1656,7 @@ static void closeAllOpenFds() #endif // leave stdin/out/err untouched while(--i > 2) - ::close(i); + QT_CLOSE(i); } #endif @@ -1686,7 +1690,7 @@ bool QPdfBaseEnginePrivate::openPrintDevice() if (!printerName.isEmpty()) pr = printerName; int fds[2]; - if (pipe(fds) != 0) { + if (qt_safe_pipe(fds) != 0) { qWarning("QPdfPrinter: Could not open pipe to print"); return false; } @@ -1705,9 +1709,9 @@ bool QPdfBaseEnginePrivate::openPrintDevice() (void)execlp("true", "true", (char *)0); (void)execl("/bin/true", "true", (char *)0); (void)execl("/usr/bin/true", "true", (char *)0); - ::exit(0); + ::_exit(0); } - dup2(fds[0], 0); + qt_safe_dup2(fds[0], 0, 0); closeAllOpenFds(); @@ -1769,19 +1773,22 @@ bool QPdfBaseEnginePrivate::openPrintDevice() (void)execv("/bin/lpr", lprargs); (void)execv("/usr/bin/lp", lpargs); (void)execv("/usr/bin/lpr", lprargs); + + delete []lpargs; + delete []lprargs; } // if we couldn't exec anything, close the fd, // wait for a second so the parent process (the // child of the GUI process) has exited. then // exit. - ::close(0); + QT_CLOSE(0); (void)::sleep(1); - ::exit(0); + ::_exit(0); } // parent process - ::close(fds[0]); + QT_CLOSE(fds[0]); fd = fds[1]; - (void)::waitpid(pid, 0, 0); + (void)qt_safe_waitpid(pid, 0, 0); if (fd < 0) return false; @@ -1928,14 +1935,13 @@ void QPdfBaseEnginePrivate::drawTextItem(const QPointF &p, const QTextItemInt &t #ifdef Q_WS_WIN if (ti.fontEngine->type() == QFontEngine::Win) { QFontEngineWin *fe = static_cast<QFontEngineWin *>(ti.fontEngine); - size = fe->tm.w.tmHeight; + size = fe->tm.tmHeight; } #endif QVarLengthArray<glyph_t> glyphs; QVarLengthArray<QFixedPoint> positions; - QTransform m; - m.translate(p.x(), p.y()); + QTransform m = QTransform::fromTranslate(p.x(), p.y()); ti.fontEngine->getGlyphPositions(ti.glyphs, m, ti.flags, glyphs, positions); if (glyphs.size() == 0) diff --git a/src/gui/painting/qpdf_p.h b/src/gui/painting/qpdf_p.h index 1f0ef14..2da8d8a 100644 --- a/src/gui/painting/qpdf_p.h +++ b/src/gui/painting/qpdf_p.h @@ -158,7 +158,7 @@ namespace QPdf { QByteArray stripSpecialCharacters(const QByteArray &string); -}; +} class QPdfPage : public QPdf::ByteStream diff --git a/src/gui/painting/qpen.cpp b/src/gui/painting/qpen.cpp index d7b2341..24606a9 100644 --- a/src/gui/painting/qpen.cpp +++ b/src/gui/painting/qpen.cpp @@ -52,9 +52,9 @@ typedef QPenPrivate QPenData; /*! \class QPen - \ingroup multimedia + \ingroup painting \ingroup shared - \mainclass + \brief The QPen class defines how a QPainter should draw lines and outlines of shapes. @@ -978,7 +978,7 @@ QDebug operator<<(QDebug dbg, const QPen &p) dbg.nospace() << "QPen(" << p.width() << ',' << p.brush() << ',' << int(p.style()) << ',' << int(p.capStyle()) << ',' << int(p.joinStyle()) << ',' << p.dashPattern() - << "," << p.dashOffset() + << ',' << p.dashOffset() << ',' << p.miterLimit() << ')'; return dbg.space(); #else diff --git a/src/gui/painting/qpolygon.cpp b/src/gui/painting/qpolygon.cpp index 663dd09..d23af90 100644 --- a/src/gui/painting/qpolygon.cpp +++ b/src/gui/painting/qpolygon.cpp @@ -91,7 +91,7 @@ static void qt_polygon_isect_line(const QPointF &p1, const QPointF &p2, const QP \reentrant - \ingroup multimedia + \ingroup painting \ingroup shared A QPolygon object is a QVector<QPoint>. The easiest way to add @@ -208,10 +208,15 @@ QPolygon::QPolygon(int nPoints, const int *points) /*! Translates all points in the polygon by (\a{dx}, \a{dy}). + + \sa translated() */ void QPolygon::translate(int dx, int dy) { + if (dx == 0 && dy == 0) + return; + register QPoint *p = data(); register int i = size(); QPoint pt(dx, dy); @@ -226,8 +231,32 @@ void QPolygon::translate(int dx, int dy) \overload Translates all points in the polygon by the given \a offset. + + \sa translated() +*/ + +/*! + Returns a copy of the polygon that is translated by (\a{dx}, \a{dy}). + + \since 4.6 + \sa translate() */ +QPolygon QPolygon::translated(int dx, int dy) const +{ + QPolygon copy(*this); + copy.translate(dx, dy); + return copy; +} + +/*! + \fn void QPolygon::translated(const QPoint &offset) const + \overload + \since 4.6 + + Returns a copy of the polygon that is translated by the given \a offset. + \sa translate() +*/ /*! Extracts the coordinates of the point at the given \a index to @@ -460,7 +489,7 @@ QDebug operator<<(QDebug dbg, const QPolygon &a) floating point precision. \reentrant - \ingroup multimedia + \ingroup painting \ingroup shared A QPolygonF is a QVector<QPointF>. The easiest way to add points @@ -565,10 +594,15 @@ QPolygonF::QPolygonF(const QPolygon &a) /*! Translate all points in the polygon by the given \a offset. + + \sa translated() */ void QPolygonF::translate(const QPointF &offset) { + if (offset.isNull()) + return; + register QPointF *p = data(); register int i = size(); while (i--) { @@ -582,6 +616,31 @@ void QPolygonF::translate(const QPointF &offset) \overload Translates all points in the polygon by (\a{dx}, \a{dy}). + + \sa translated() +*/ + +/*! + Returns a copy of the polygon that is translated by the given \a offset. + + \since 4.6 + \sa translate() +*/ +QPolygonF QPolygonF::translated(const QPointF &offset) const +{ + QPolygonF copy(*this); + copy.translate(offset); + return copy; +} + +/*! + \fn void QPolygonF::translated(qreal dx, qreal dy) const + \overload + \since 4.6 + + Returns a copy of the polygon that is translated by (\a{dx}, \a{dy}). + + \sa translate() */ /*! @@ -683,7 +742,7 @@ QDataStream &operator>>(QDataStream &s, QPolygon &a) QVector<QPoint> &v = a; return s >> v; } -#endif +#endif // QT_NO_DATASTREAM /***************************************************************************** QPolygonF stream functions diff --git a/src/gui/painting/qpolygon.h b/src/gui/painting/qpolygon.h index 3803432..22d063c 100644 --- a/src/gui/painting/qpolygon.h +++ b/src/gui/painting/qpolygon.h @@ -71,6 +71,10 @@ public: void translate(int dx, int dy); void translate(const QPoint &offset); + + QPolygon translated(int dx, int dy) const; + inline QPolygon translated(const QPoint &offset) const; + QRect boundingRect() const; void point(int i, int *x, int *y) const; @@ -120,6 +124,9 @@ inline QPoint QPolygon::point(int index) const inline void QPolygon::translate(const QPoint &offset) { translate(offset.x(), offset.y()); } +inline QPolygon QPolygon::translated(const QPoint &offset) const +{ return translated(offset.x(), offset.y()); } + class QRectF; class Q_GUI_EXPORT QPolygonF : public QVector<QPointF> @@ -136,6 +143,9 @@ public: inline void translate(qreal dx, qreal dy); void translate(const QPointF &offset); + inline QPolygonF translated(qreal dx, qreal dy) const; + QPolygonF translated(const QPointF &offset) const; + QPolygon toPolygon() const; bool isClosed() const { return !isEmpty() && first() == last(); } @@ -166,6 +176,9 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QPolygonF &array); inline void QPolygonF::translate(qreal dx, qreal dy) { translate(QPointF(dx, dy)); } +inline QPolygonF QPolygonF::translated(qreal dx, qreal dy) const +{ return translated(QPointF(dx, dy)); } + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/painting/qprintengine_mac.mm b/src/gui/painting/qprintengine_mac.mm index 456ed1e..5a15dc2 100644 --- a/src/gui/painting/qprintengine_mac.mm +++ b/src/gui/painting/qprintengine_mac.mm @@ -92,16 +92,8 @@ bool QMacPrintEngine::begin(QPaintDevice *dev) } OSStatus status = noErr; #ifndef QT_MAC_USE_COCOA -# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - status = d->shouldSuppressStatus() ? PMSessionBeginCGDocumentNoDialog(d->session, d->settings, d->format) - : PMSessionBeginCGDocument(d->session, d->settings, d->format); - } else -# endif - { - status = d->shouldSuppressStatus() ? PMSessionBeginDocumentNoDialog(d->session, d->settings, d->format) - : PMSessionBeginDocument(d->session, d->settings, d->format); - } + status = d->shouldSuppressStatus() ? PMSessionBeginCGDocumentNoDialog(d->session, d->settings, d->format) + : PMSessionBeginCGDocument(d->session, d->settings, d->format); #else status = PMSessionBeginCGDocumentNoDialog(d->session, d->settings, d->format); #endif @@ -468,23 +460,6 @@ void QMacPrintEnginePrivate::initialize() #endif #ifndef QT_MAC_USE_COCOA -# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_4) -# endif - { - if(paintEngine->type() == QPaintEngine::CoreGraphics) { - CFStringRef strings[1] = { kPMGraphicsContextCoreGraphics }; - QCFType<CFArrayRef> contextArray = CFArrayCreate(kCFAllocatorDefault, - reinterpret_cast<const void **>(strings), - 1, &kCFTypeArrayCallBacks); - OSStatus err = PMSessionSetDocumentFormatGeneration(session, kPMDocumentFormatPDF, - contextArray, 0); - if(err != noErr) { - qWarning("QMacPrintEngine::initialize: Cannot set format generation to PDF: %ld", err); - state = QPrinter::Error; - } - } - } if (!settingsOK || !formatOK) { qWarning("QMacPrintEngine::initialize: Unable to initialize QPainter"); state = QPrinter::Error; @@ -551,19 +526,7 @@ bool QMacPrintEnginePrivate::newPage_helper() CGContextRef cgContext; OSStatus err = noErr; -#ifndef QT_MAC_USE_COCOA -# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - err = PMSessionGetCGGraphicsContext(session, &cgContext); - } else -# endif - { - err = PMSessionGetGraphicsContext(session, kPMGraphicsContextCoreGraphics, - reinterpret_cast<void **>(&cgContext)); - } -#else err = PMSessionGetCGGraphicsContext(session, &cgContext); -#endif if(err != noErr) { qWarning("QMacPrintEngine::newPage: Cannot retrieve CoreGraphics context: %ld", long(err)); state = QPrinter::Error; diff --git a/src/gui/painting/qprintengine_pdf.cpp b/src/gui/painting/qprintengine_pdf.cpp index af39f7e..17a8ae6 100644 --- a/src/gui/painting/qprintengine_pdf.cpp +++ b/src/gui/painting/qprintengine_pdf.cpp @@ -423,7 +423,7 @@ int QPdfEnginePrivate::addConstantAlphaObject(int brushAlpha, int penAlpha) object = addXrefEntry(-1); QByteArray alphaDef; QPdf::ByteStream s(&alphaDef); - s << "<<\n/ca " << (brushAlpha/qreal(255.)) << "\n"; + s << "<<\n/ca " << (brushAlpha/qreal(255.)) << '\n'; s << "/CA " << (penAlpha/qreal(255.)) << "\n>>"; xprintf("%s\nendobj\n", alphaDef.constData()); alphaCache.insert(QPair<uint, uint>(brushAlpha, penAlpha), object); @@ -655,7 +655,7 @@ void QPdfEnginePrivate::drawTextItem(const QPointF &p, const QTextItemInt &ti) #ifdef Q_WS_WIN if (ti.fontEngine->type() == QFontEngine::Win) { QFontEngineWin *fe = static_cast<QFontEngineWin *>(ti.fontEngine); - size = fe->tm.w.tmHeight; + size = fe->tm.tmHeight; } #endif int synthesized = ti.fontEngine->synthesized(); @@ -1010,7 +1010,7 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font) s << (char)('A' + (tag % 26)); tag /= 26; } - s << "+" << properties.postscriptName << "\n" + s << '+' << properties.postscriptName << "\n" "/Flags " << 4 << "\n" "/FontBBox [" << properties.boundingBox.x()*scale diff --git a/src/gui/painting/qprintengine_ps.cpp b/src/gui/painting/qprintengine_ps.cpp index a22427e..189988b 100644 --- a/src/gui/painting/qprintengine_ps.cpp +++ b/src/gui/painting/qprintengine_ps.cpp @@ -167,7 +167,7 @@ static QByteArray wrapDSC(const QByteArray &str) } wrapped += "\n%%+" + tmp; } - return wrapped + "\n"; + return wrapped + '\n'; } // ----------------------------- Internal class declarations ----------------------------- @@ -422,7 +422,7 @@ void QPSPrintEnginePrivate::drawImageHelper(qreal x, qreal y, qreal w, qreal h, << size << " string readstring\n"; ps_r7(*currentPage, out, out.size()); *currentPage << " pop def\n"; - *currentPage << width << ' ' << height << "[" << scaleX << " 0 0 " << scaleY << " 0 0]sl " + *currentPage << width << ' ' << height << '[' << scaleX << " 0 0 " << scaleY << " 0 0]sl " << bits << (!mask.isNull() ? "mask " : "false ") << x << ' ' << y << " di\n"; } @@ -529,7 +529,7 @@ void QPSPrintEnginePrivate::emitHeader(bool finished) else s << "\n%%BoundingBox: 0 0 " << w << h; } - s << "\n" << wrapDSC("%%Creator: " + creator.toUtf8()); + s << '\n' << wrapDSC("%%Creator: " + creator.toUtf8()); if (!title.isEmpty()) s << wrapDSC("%%Title: " + title.toUtf8()); #ifndef QT_NO_DATESTRING @@ -549,7 +549,7 @@ void QPSPrintEnginePrivate::emitHeader(bool finished) "% Prolog copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).\n" "% You may copy this prolog in any way that is directly related to this document.\n" "% For other use of this prolog, see your licensing agreement for Qt.\n" - << ps_header << "\n"; + << ps_header << '\n'; s << "/pageinit {\n"; @@ -560,12 +560,12 @@ void QPSPrintEnginePrivate::emitHeader(bool finished) s << mtop*scale << mleft*scale << "translate\n"; } if (orientation == QPrinter::Portrait) { - s << "% " << printer->widthMM() << "*" << printer->heightMM() + s << "% " << printer->widthMM() << '*' << printer->heightMM() << "mm (portrait)\n0 " << height*scale - << "translate " << scale << "-" << scale << "scale } def\n"; + << "translate " << scale << '-' << scale << "scale } def\n"; } else { - s << "% " << printer->heightMM() << "*" << printer->widthMM() - << " mm (landscape)\n 90 rotate " << scale << "-" << scale << "scale } def\n"; + s << "% " << printer->heightMM() << '*' << printer->widthMM() + << " mm (landscape)\n 90 rotate " << scale << '-' << scale << "scale } def\n"; } s << "%%EndProlog\n"; @@ -619,8 +619,8 @@ void QPSPrintEnginePrivate::flushPage(bool last) QPdf::ByteStream e(&trailer); buffer << "%%Page: " << pageCount << pageCount << "\n" - << "%%BeginPageSetup\n" - << "QI\n"; + "%%BeginPageSetup\n" + "QI\n"; if (hugeDocument) { for (QHash<QFontEngine::FaceId, QFontSubset *>::const_iterator it = fonts.constBegin(); it != fonts.constEnd(); ++it) { @@ -776,8 +776,8 @@ bool QPSPrintEngine::end() d->flushPage(true); QByteArray trailer; QPdf::ByteStream s(&trailer); - s << "%%Trailer\n"; - s << "%%Pages: " << d->pageCount - 1 << "\n" << + s << "%%Trailer\n" + "%%Pages: " << d->pageCount - 1 << '\n' << wrapDSC("%%DocumentFonts: " + d->fontsUsed); s << "%%EOF\n"; d->outDevice->write(trailer); diff --git a/src/gui/painting/qprintengine_win.cpp b/src/gui/painting/qprintengine_win.cpp index 38c14eb..05bddaa 100644 --- a/src/gui/painting/qprintengine_win.cpp +++ b/src/gui/painting/qprintengine_win.cpp @@ -199,33 +199,18 @@ bool QWin32PrintEngine::begin(QPaintDevice *pdev) if (d->printToFile && d->fileName.isEmpty()) d->fileName = d->port; - QT_WA({ - d->devModeW()->dmCopies = d->num_copies; - DOCINFO di; - memset(&di, 0, sizeof(DOCINFO)); - di.cbSize = sizeof(DOCINFO); - di.lpszDocName = reinterpret_cast<const wchar_t *>(d->docName.utf16()); - if (d->printToFile && !d->fileName.isEmpty()) - di.lpszOutput = reinterpret_cast<const wchar_t *>(d->fileName.utf16()); - if (ok && StartDoc(d->hdc, &di) == SP_ERROR) { - qErrnoWarning("QWin32PrintEngine::begin: StartDoc failed"); - ok = false; - } - } , { - d->devModeA()->dmCopies = d->num_copies; - DOCINFOA di; - memset(&di, 0, sizeof(DOCINFOA)); - di.cbSize = sizeof(DOCINFOA); - QByteArray docNameA = d->docName.toLocal8Bit(); - di.lpszDocName = docNameA.data(); - QByteArray outfileA = d->fileName.toLocal8Bit(); - if (d->printToFile && !d->fileName.isEmpty()) - di.lpszOutput = outfileA; - if (ok && StartDocA(d->hdc, &di) == SP_ERROR) { - qErrnoWarning("QWin32PrintEngine::begin: StartDoc failed"); - ok = false; - } - }); + d->devMode->dmCopies = d->num_copies; + + DOCINFO di; + memset(&di, 0, sizeof(DOCINFO)); + di.cbSize = sizeof(DOCINFO); + di.lpszDocName = reinterpret_cast<const wchar_t *>(d->docName.utf16()); + if (d->printToFile && !d->fileName.isEmpty()) + di.lpszOutput = reinterpret_cast<const wchar_t *>(d->fileName.utf16()); + if (ok && StartDoc(d->hdc, &di) == SP_ERROR) { + qErrnoWarning("QWin32PrintEngine::begin: StartDoc failed"); + ok = false; + } if (StartPage(d->hdc) <= 0) { qErrnoWarning("QWin32PrintEngine::begin: StartPage failed"); @@ -317,11 +302,6 @@ bool QWin32PrintEngine::newPage() bool success = false; if (d->hdc && d->state == QPrinter::Active) { -// bool restorePainter = false; -// if ((qWinVersion()& Qt::WV_DOS_based) && painter && painter->isActive()) { -// painter->save(); // EndPage/StartPage ruins the DC -// restorePainter = true; -// } if (EndPage(d->hdc) != SP_ERROR) { // reinitialize the DC before StartPage if needed, // because resetdc is disabled between calls to the StartPage and EndPage functions @@ -337,16 +317,10 @@ bool QWin32PrintEngine::newPage() } success = (StartPage(d->hdc) != SP_ERROR); } - if (!success) + if (!success) { d->state = QPrinter::Aborted; - -// if (qWinVersion() & Qt::WV_DOS_based) -// if (restorePainter) { -// painter->restore(); -// } - - if (!success) return false; + } } return true; } @@ -369,7 +343,7 @@ void QWin32PrintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem QRgb brushColor = state->pen().brush().color().rgb(); bool fallBack = state->pen().brush().style() != Qt::SolidPattern || qAlpha(brushColor) != 0xff - || QT_WA_INLINE(d->txop >= QTransform::TxProject, d->txop >= QTransform::TxScale) + || d->txop >= QTransform::TxProject || ti.fontEngine->type() != QFontEngine::Win; @@ -380,17 +354,10 @@ void QWin32PrintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem SelectObject(d->hdc, fe->hfont); if (GetDeviceCaps(d->hdc, TECHNOLOGY) != DT_CHARSTREAM) { - QT_WA({ - TCHAR n[64]; - GetTextFaceW(d->hdc, 64, n); - fallBack = QString::fromUtf16((ushort *)n) - != QString::fromUtf16((ushort *)fe->logfont.lfFaceName); - } , { - char an[64]; - GetTextFaceA(d->hdc, 64, an); - fallBack = QString::fromLocal8Bit(an) - != QString::fromLocal8Bit(((LOGFONTA*)(&fe->logfont))->lfFaceName); - }); + wchar_t n[64]; + GetTextFace(d->hdc, 64, n); + fallBack = QString::fromWCharArray(n) + != QString::fromWCharArray(fe->logfont.lfFaceName); } } @@ -663,8 +630,7 @@ void QWin32PrintEngine::drawPixmap(const QRectF &targetRect, qreal scaleX = 1.0f; qreal scaleY = 1.0f; - QTransform scaleMatrix; - scaleMatrix.scale(r.width() / pixmap.width(), r.height() / pixmap.height()); + QTransform scaleMatrix = QTransform::fromScale(r.width() / pixmap.width(), r.height() / pixmap.height()); QTransform adapted = QPixmap::trueMatrix(d->painterMatrix * scaleMatrix, pixmap.width(), pixmap.height()); @@ -984,22 +950,14 @@ void QWin32PrintEnginePrivate::queryDefault() * Strings "windows" and "device" are specified in the MSDN under EnumPrinters() */ QString noPrinters(QLatin1String("qt_no_printers")); - QString output; - QT_WA({ - ushort buffer[256]; - GetProfileStringW(L"windows", L"device", - reinterpret_cast<const wchar_t *>(noPrinters.utf16()), - reinterpret_cast<wchar_t *>(buffer), 256); - output = QString::fromUtf16(buffer); - if (output.isEmpty() || output == noPrinters) // no printers - return; - }, { - char buffer[256]; - GetProfileStringA("windows", "device", noPrinters.toLatin1(), buffer, 256); - output = QString::fromLocal8Bit(buffer); - if (output.isEmpty() || output == noPrinters) // no printers - return; - }); + wchar_t buffer[256]; + GetProfileString(L"windows", L"device", + reinterpret_cast<const wchar_t *>(noPrinters.utf16()), + buffer, 256); + QString output = QString::fromWCharArray(buffer); + if (output.isEmpty() || output == noPrinters) // no printers + return; + QStringList info = output.split(QLatin1Char(',')); if (info.size() > 0) { if (name.isEmpty()) @@ -1031,13 +989,7 @@ void QWin32PrintEnginePrivate::initialize() txop = QTransform::TxNone; - bool ok; - QT_WA( { - ok = OpenPrinterW((LPWSTR)name.utf16(), (LPHANDLE)&hPrinter, 0); - }, { - ok = OpenPrinterA((LPSTR)name.toLatin1().data(), (LPHANDLE)&hPrinter, 0); - } ); - + bool ok = OpenPrinter((LPWSTR)name.utf16(), (LPHANDLE)&hPrinter, 0); if (!ok) { qErrnoWarning("QWin32PrintEngine::initialize: OpenPrinter failed"); return; @@ -1046,22 +998,10 @@ void QWin32PrintEnginePrivate::initialize() // Fetch the PRINTER_INFO_2 with DEVMODE data containing the // printer settings. DWORD infoSize, numBytes; - ok = true; - QT_WA( { - GetPrinterW(hPrinter, 2, NULL, 0, &infoSize); - hMem = GlobalAlloc(GHND, infoSize); - pInfo = GlobalLock(hMem); - if (!GetPrinterW(hPrinter, 2, (LPBYTE)pInfo, infoSize, &numBytes)) { - ok = false; - } - }, { - GetPrinterA(hPrinter, 2, NULL, 0, &infoSize); - hMem = GlobalAlloc(GHND, infoSize); - pInfo = GlobalLock(hMem); - if (!GetPrinterA(hPrinter, 2, (LPBYTE)pInfo, infoSize, &numBytes)) { - ok = false; - } - }); + GetPrinter(hPrinter, 2, NULL, 0, &infoSize); + hMem = GlobalAlloc(GHND, infoSize); + pInfo = (PRINTER_INFO_2*) GlobalLock(hMem); + ok = GetPrinter(hPrinter, 2, (LPBYTE)pInfo, infoSize, &numBytes); if (!ok) { qErrnoWarning("QWin32PrintEngine::initialize: GetPrinter failed"); @@ -1074,28 +1014,15 @@ void QWin32PrintEnginePrivate::initialize() return; } - QT_WA( { - devMode = pInfoW()->pDevMode; - }, { - devMode = pInfoA()->pDevMode; - } ); - - QT_WA( { - hdc = CreateDC(reinterpret_cast<const wchar_t *>(program.utf16()), - reinterpret_cast<const wchar_t *>(name.utf16()), 0, devModeW()); - }, { - hdc = CreateDCA(program.toLatin1(), name.toLatin1(), 0, devModeA()); - } ); + devMode = pInfo->pDevMode; + hdc = CreateDC(reinterpret_cast<const wchar_t *>(program.utf16()), + reinterpret_cast<const wchar_t *>(name.utf16()), 0, devMode); Q_ASSERT(hPrinter); Q_ASSERT(pInfo); if (devMode) { - QT_WA( { - num_copies = devModeW()->dmCopies; - }, { - num_copies = devModeA()->dmCopies; - } ); + num_copies = devMode->dmCopies; } initHDC(); @@ -1213,28 +1140,18 @@ void QWin32PrintEnginePrivate::release() QList<QVariant> QWin32PrintEnginePrivate::queryResolutions() const { // Read the supported resolutions of the printer. - DWORD numRes; - LONG *enumRes; - DWORD errRes; QList<QVariant> list; - QT_WA({ - numRes = DeviceCapabilities(reinterpret_cast<const wchar_t *>(name.utf16()), - reinterpret_cast<const wchar_t *>(port.utf16()), - DC_ENUMRESOLUTIONS, 0, 0); - if (numRes == (DWORD)-1) - return list; - enumRes = (LONG*)malloc(numRes * 2 * sizeof(LONG)); - errRes = DeviceCapabilities(reinterpret_cast<const wchar_t *>(name.utf16()), - reinterpret_cast<const wchar_t *>(port.utf16()), - DC_ENUMRESOLUTIONS, (LPWSTR)enumRes, 0); - }, { - numRes = DeviceCapabilitiesA(name.toLocal8Bit(), port.toLocal8Bit(), DC_ENUMRESOLUTIONS, 0, 0); - if (numRes == (DWORD)-1) - return list; - enumRes = (LONG*)malloc(numRes * 2 * sizeof(LONG)); - errRes = DeviceCapabilitiesA(name.toLocal8Bit(), port.toLocal8Bit(), DC_ENUMRESOLUTIONS, (LPSTR)enumRes, 0); - }); + DWORD numRes = DeviceCapabilities(reinterpret_cast<const wchar_t *>(name.utf16()), + reinterpret_cast<const wchar_t *>(port.utf16()), + DC_ENUMRESOLUTIONS, 0, 0); + if (numRes == (DWORD)-1) + return list; + + LONG *enumRes = (LONG*)malloc(numRes * 2 * sizeof(LONG)); + DWORD errRes = DeviceCapabilities(reinterpret_cast<const wchar_t *>(name.utf16()), + reinterpret_cast<const wchar_t *>(port.utf16()), + DC_ENUMRESOLUTIONS, (LPWSTR)enumRes, 0); if (errRes == (DWORD)-1) { qErrnoWarning("QWin32PrintEngine::queryResolutions: DeviceCapabilities failed"); @@ -1242,7 +1159,8 @@ QList<QVariant> QWin32PrintEnginePrivate::queryResolutions() const } for (uint i=0; i<numRes; ++i) - list.append(int(enumRes[i*2])); + list.append(int(enumRes[i * 2])); + return list; } @@ -1286,9 +1204,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & { if (!d->devMode) break; - short collate = value.toBool() ? DMCOLLATE_TRUE : DMCOLLATE_FALSE; - QT_WA( { d->devModeW()->dmCollate = collate; }, - { d->devModeA()->dmCollate = collate; } ); + d->devMode->dmCollate = value.toBool() ? DMCOLLATE_TRUE : DMCOLLATE_FALSE; d->doReinit(); } break; @@ -1297,8 +1213,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & { if (!d->devMode) break; - int cm = value.toInt() == QPrinter::Color ? DMCOLOR_COLOR : DMCOLOR_MONOCHROME; - QT_WA( { d->devModeW()->dmColor = cm; }, { d->devModeA()->dmColor = cm; } ); + d->devMode->dmColor = (value.toInt() == QPrinter::Color) ? DMCOLOR_COLOR : DMCOLOR_MONOCHROME; d->doReinit(); } break; @@ -1324,8 +1239,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & if (!d->devMode) break; d->num_copies = value.toInt(); - QT_WA( { d->devModeW()->dmCopies = d->num_copies; }, - { d->devModeA()->dmCopies = d->num_copies; }); + d->devMode->dmCopies = d->num_copies; d->doReinit(); break; @@ -1334,14 +1248,8 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & if (!d->devMode) break; int orientation = value.toInt() == QPrinter::Landscape ? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT; - int old_orientation; - QT_WA( { - old_orientation = d->devModeW()->dmOrientation; - d->devModeW()->dmOrientation = orientation; - }, { - old_orientation = d->devModeA()->dmOrientation; - d->devModeA()->dmOrientation = orientation; - } ); + int old_orientation = d->devMode->dmOrientation; + d->devMode->dmOrientation = orientation; if (d->has_custom_paper_size && old_orientation != orientation) d->paper_size = QSizeF(d->paper_size.height(), d->paper_size.width()); d->doReinit(); @@ -1360,11 +1268,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & case PPK_PaperSize: if (!d->devMode) break; - QT_WA( { - d->devModeW()->dmPaperSize = mapPaperSizeDevmode(QPrinter::PaperSize(value.toInt())); - }, { - d->devModeA()->dmPaperSize = mapPaperSizeDevmode(QPrinter::PaperSize(value.toInt())); - } ); + d->devMode->dmPaperSize = mapPaperSizeDevmode(QPrinter::PaperSize(value.toInt())); d->has_custom_paper_size = (QPrinter::PaperSize(value.toInt()) == QPrinter::Custom); d->doReinit(); break; @@ -1379,11 +1283,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & if (v.contains(value)) dmMapped = mapPaperSourceDevmode(QPrinter::PaperSource(value.toInt())); - QT_WA( { - d->devModeW()->dmDefaultSource = dmMapped; - }, { - d->devModeA()->dmDefaultSource = dmMapped; - } ); + d->devMode->dmDefaultSource = dmMapped; d->doReinit(); } break; @@ -1417,11 +1317,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & if (!d->devMode) break; d->has_custom_paper_size = false; - QT_WA( { - d->devModeW()->dmPaperSize = value.toInt(); - }, { - d->devModeA()->dmPaperSize = value.toInt(); - } ); + d->devMode->dmPaperSize = value.toInt(); d->doReinit(); break; @@ -1431,33 +1327,28 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & d->paper_size = value.toSizeF(); if (!d->devMode) break; - int orientation; - QT_WA( { - orientation = d->devModeW()->dmOrientation; - DWORD needed = 0; - DWORD returned = 0; - if (!EnumForms(d->hPrinter, 1, 0, 0, &needed, &returned)) { - BYTE *forms = (BYTE *) malloc(needed); - if (EnumForms(d->hPrinter, 1, forms, needed, &needed, &returned)) { - for (DWORD i=0; i< returned; ++i) { - FORM_INFO_1 *formArray = reinterpret_cast<FORM_INFO_1 *>(forms); - // the form sizes are specified in 1000th of a mm, - // convert the size to Points - QSizeF size((formArray[i].Size.cx * 72/25.4)/1000.0, - (formArray[i].Size.cy * 72/25.4)/1000.0); - if (qAbs(d->paper_size.width() - size.width()) <= 2 - && qAbs(d->paper_size.height() - size.height()) <= 2) - { - d->devModeW()->dmPaperSize = i+1; - break; - } + int orientation = d->devMode->dmOrientation; + DWORD needed = 0; + DWORD returned = 0; + if (!EnumForms(d->hPrinter, 1, 0, 0, &needed, &returned)) { + BYTE *forms = (BYTE *) malloc(needed); + if (EnumForms(d->hPrinter, 1, forms, needed, &needed, &returned)) { + for (DWORD i=0; i< returned; ++i) { + FORM_INFO_1 *formArray = reinterpret_cast<FORM_INFO_1 *>(forms); + // the form sizes are specified in 1000th of a mm, + // convert the size to Points + QSizeF size((formArray[i].Size.cx * 72/25.4)/1000.0, + (formArray[i].Size.cy * 72/25.4)/1000.0); + if (qAbs(d->paper_size.width() - size.width()) <= 2 + && qAbs(d->paper_size.height() - size.height()) <= 2) + { + d->devMode->dmPaperSize = i + 1; + break; } } - free(forms); } - }, { - orientation = d->devModeA()->dmOrientation; - } ); + free(forms); + } if (orientation != DMORIENT_PORTRAIT) d->paper_size = QSizeF(d->paper_size.height(), d->paper_size.width()); break; @@ -1469,10 +1360,10 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & Q_ASSERT(margins.size() == 4); int left, top, right, bottom; // specified in 1/100 mm - left = (margins.at(0).toDouble()*25.4/72.0) * 100; - top = (margins.at(1).toDouble()*25.4/72.0) * 100; - right = (margins.at(2).toDouble()*25.4/72.0) * 100; - bottom = (margins.at(3).toDouble()*25.4/72.0) * 100; + left = (margins.at(0).toReal()*25.4/72.0) * 100; + top = (margins.at(1).toReal()*25.4/72.0) * 100; + right = (margins.at(2).toReal()*25.4/72.0) * 100; + bottom = (margins.at(3).toReal()*25.4/72.0) * 100; d->setPageMargins(left, top, right, bottom); break; } @@ -1497,13 +1388,7 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const if (!d->devMode) { value = QPrinter::Color; } else { - int mode; - QT_WA( { - mode = d->devModeW()->dmColor; - }, { - mode = d->devModeA()->dmColor; - } ); - value = mode == DMCOLOR_COLOR ? QPrinter::Color : QPrinter::GrayScale; + value = (d->devMode->dmColor == DMCOLOR_COLOR) ? QPrinter::Color : QPrinter::GrayScale; } } break; @@ -1525,9 +1410,7 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const if (!d->devMode) { value = QPrinter::Portrait; } else { - int o; - QT_WA( { o = d->devModeW()->dmOrientation; }, { o = d->devModeA()->dmOrientation; } ); - value = o == DMORIENT_LANDSCAPE ? QPrinter::Landscape : QPrinter::Portrait; + value = (d->devMode->dmOrientation == DMORIENT_LANDSCAPE) ? QPrinter::Landscape : QPrinter::Portrait; } } break; @@ -1561,11 +1444,7 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const if (!d->devMode) { value = QPrinter::A4; } else { - QT_WA( { - value = mapDevmodePaperSize(d->devModeW()->dmPaperSize); - }, { - value = mapDevmodePaperSize(d->devModeA()->dmPaperSize); - } ); + value = mapDevmodePaperSize(d->devMode->dmPaperSize); } } break; @@ -1584,11 +1463,7 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const if (!d->devMode) { value = QPrinter::Auto; } else { - QT_WA( { - value = mapDevmodePaperSource(d->devModeW()->dmDefaultSource); - }, { - value = mapDevmodePaperSource(d->devModeA()->dmDefaultSource); - } ); + value = mapDevmodePaperSource(d->devMode->dmDefaultSource); } break; @@ -1609,38 +1484,21 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const if (!d->devMode) { value = -1; } else { - QT_WA( { - value = d->devModeW()->dmPaperSize; - }, { - value = d->devModeA()->dmPaperSize; - } ); + value = d->devMode->dmPaperSize; } break; case PPK_PaperSources: { - int available, count; - WORD *data; - - QT_WA({ - available = DeviceCapabilitiesW((const WCHAR *)d->name.utf16(), (const WCHAR *)d->port.utf16(), DC_BINS, 0, - d->devModeW()); - }, { - available = DeviceCapabilitiesA(d->name.toLatin1(), d->port.toLatin1(), DC_BINS, 0, - d->devModeA()); - }); + int available = DeviceCapabilities((const wchar_t *)d->name.utf16(), + (const wchar_t *)d->port.utf16(), DC_BINS, 0, d->devMode); if (available <= 0) break; - data = (WORD *) malloc(available * sizeof(WORD)); - QT_WA({ - count = DeviceCapabilitiesW((const WCHAR *)d->name.utf16(), (const WCHAR *)d->port.utf16(), DC_BINS, (WCHAR *)data, - d->devModeW()); - }, { - count = DeviceCapabilitiesA(d->name.toLatin1(), d->port.toLatin1(), DC_BINS, - (char *) data, d->devModeA()); - }); + wchar_t *data = new wchar_t[available]; + int count = DeviceCapabilities((const wchar_t *)d->name.utf16(), + (const wchar_t *)d->port.utf16(), DC_BINS, data, d->devMode); QList<QVariant> out; for (int i=0; i<count; ++i) { @@ -1649,7 +1507,8 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const out << (int) src; } value = out; - free(data); + + delete [] data; } break; @@ -1694,24 +1553,23 @@ void QWin32PrintEngine::releaseDC(HDC) const HGLOBAL *QWin32PrintEnginePrivate::createDevNames() { - QT_WA( { - int size = sizeof(DEVNAMES) - + program.length() * 2 + 2 - + name.length() * 2 + 2 - + port.length() * 2 + 2; - HGLOBAL *hGlobal = (HGLOBAL *) GlobalAlloc(GMEM_MOVEABLE, size); - DEVNAMES *dn = (DEVNAMES*) GlobalLock(hGlobal); + int size = sizeof(DEVNAMES) + + program.length() * 2 + 2 + + name.length() * 2 + 2 + + port.length() * 2 + 2; + HGLOBAL *hGlobal = (HGLOBAL *) GlobalAlloc(GMEM_MOVEABLE, size); + DEVNAMES *dn = (DEVNAMES*) GlobalLock(hGlobal); - dn->wDriverOffset = sizeof(DEVNAMES) / sizeof(TCHAR); - dn->wDeviceOffset = dn->wDriverOffset + program.length() + 1; - dn->wOutputOffset = dn->wDeviceOffset + name.length() + 1; + dn->wDriverOffset = sizeof(DEVNAMES) / sizeof(wchar_t); + dn->wDeviceOffset = dn->wDriverOffset + program.length() + 1; + dn->wOutputOffset = dn->wDeviceOffset + name.length() + 1; - memcpy((ushort*)dn + dn->wDriverOffset, program.utf16(), program.length() * 2 + 2); - memcpy((ushort*)dn + dn->wDeviceOffset, name.utf16(), name.length() * 2 + 2); - memcpy((ushort*)dn + dn->wOutputOffset, port.utf16(), port.length() * 2 + 2); - dn->wDefault = 0; + memcpy((ushort*)dn + dn->wDriverOffset, program.utf16(), program.length() * 2 + 2); + memcpy((ushort*)dn + dn->wDeviceOffset, name.utf16(), name.length() * 2 + 2); + memcpy((ushort*)dn + dn->wOutputOffset, port.utf16(), port.length() * 2 + 2); + dn->wDefault = 0; - GlobalUnlock(hGlobal); + GlobalUnlock(hGlobal); // printf("QPrintDialogWinPrivate::createDevNames()\n" // " -> wDriverOffset: %d\n" @@ -1722,89 +1580,46 @@ HGLOBAL *QWin32PrintEnginePrivate::createDevNames() // dn->wOutputOffset); // printf("QPrintDialogWinPrivate::createDevNames(): %s, %s, %s\n", -// QString::fromUtf16((ushort*)(dn) + dn->wDriverOffset).latin1(), -// QString::fromUtf16((ushort*)(dn) + dn->wDeviceOffset).latin1(), -// QString::fromUtf16((ushort*)(dn) + dn->wOutputOffset).latin1()); - - return hGlobal; - }, { - int size = sizeof(DEVNAMES) - + program.length() + 2 - + name.length() + 2 - + port.length() + 2; - HGLOBAL *hGlobal = (HGLOBAL *) GlobalAlloc(GMEM_MOVEABLE, size); - DEVNAMES *dn = (DEVNAMES*) GlobalLock(hGlobal); - - dn->wDriverOffset = sizeof(DEVNAMES); - dn->wDeviceOffset = dn->wDriverOffset + program.length() + 1; - dn->wOutputOffset = dn->wDeviceOffset + name.length() + 1; - - memcpy((char*)dn + dn->wDriverOffset, program.toLatin1(), program.length() + 2); - memcpy((char*)dn + dn->wDeviceOffset, name.toLatin1(), name.length() + 2); - memcpy((char*)dn + dn->wOutputOffset, port.toLatin1(), port.length() + 2); - dn->wDefault = 0; - - GlobalUnlock(hGlobal); - return hGlobal; - } ); +// QString::fromWCharArray((wchar_t*)(dn) + dn->wDriverOffset).latin1(), +// QString::fromWCharArray((wchar_t*)(dn) + dn->wDeviceOffset).latin1(), +// QString::fromWCharArray((wchar_t*)(dn) + dn->wOutputOffset).latin1()); + + return hGlobal; } void QWin32PrintEnginePrivate::readDevnames(HGLOBAL globalDevnames) { if (globalDevnames) { - QT_WA( { - DEVNAMES *dn = (DEVNAMES*) GlobalLock(globalDevnames); - name = QString::fromUtf16((ushort*)(dn) + dn->wDeviceOffset); - port = QString::fromUtf16((ushort*)(dn) + dn->wOutputOffset); - program = QString::fromUtf16((ushort*)(dn) + dn->wDriverOffset); - GlobalUnlock(globalDevnames); - }, { - DEVNAMES *dn = (DEVNAMES*) GlobalLock(globalDevnames); - name = QString::fromLatin1((char*)(dn) + dn->wDeviceOffset); - port = QString::fromLatin1((char*)(dn) + dn->wOutputOffset); - program = QString::fromLatin1((char*)(dn) + dn->wDriverOffset); - GlobalUnlock(globalDevnames); - } ); + DEVNAMES *dn = (DEVNAMES*) GlobalLock(globalDevnames); + name = QString::fromWCharArray((wchar_t*)(dn) + dn->wDeviceOffset); + port = QString::fromWCharArray((wchar_t*)(dn) + dn->wOutputOffset); + program = QString::fromWCharArray((wchar_t*)(dn) + dn->wDriverOffset); + GlobalUnlock(globalDevnames); } } void QWin32PrintEnginePrivate::readDevmode(HGLOBAL globalDevmode) { if (globalDevmode) { - QT_WA( { - DEVMODE *dm = (DEVMODE*) GlobalLock(globalDevmode); - release(); - globalDevMode = globalDevmode; - devMode = dm; - hdc = CreateDC(reinterpret_cast<const wchar_t *>(program.utf16()), - reinterpret_cast<const wchar_t *>(name.utf16()), 0, dm); - - num_copies = devModeW()->dmCopies; - if (!OpenPrinterW((LPWSTR)name.utf16(), (LPHANDLE)&hPrinter, 0)) - qWarning("QPrinter: OpenPrinter() failed after reading DEVMODE."); - }, { - DEVMODEA *dm = (DEVMODEA*) GlobalLock(globalDevmode); - release(); - globalDevMode = globalDevmode; - devMode = dm; - hdc = CreateDCA(program.toLatin1(), name.toLatin1(), 0, dm); - - num_copies = devModeA()->dmCopies; - if (!OpenPrinterA((LPSTR)name.toLatin1().data(), (LPHANDLE)&hPrinter, 0)) - qWarning("QPrinter: OpenPrinter() failed after reading DEVMODE."); - } ); + DEVMODE *dm = (DEVMODE*) GlobalLock(globalDevmode); + release(); + globalDevMode = globalDevmode; + devMode = dm; + hdc = CreateDC(reinterpret_cast<const wchar_t *>(program.utf16()), + reinterpret_cast<const wchar_t *>(name.utf16()), 0, dm); + + num_copies = devMode->dmCopies; + if (!OpenPrinter((wchar_t*)name.utf16(), &hPrinter, 0)) + qWarning("QPrinter: OpenPrinter() failed after reading DEVMODE."); } if (hdc) initHDC(); } -static void draw_text_item_win(const QPointF &_pos, const QTextItemInt &ti, HDC hdc, +static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC hdc, bool convertToText, const QTransform &xform, const QPointF &topLeft) { - - // Make sure we translate for systems that can't handle world transforms - QPointF pos(QT_WA_INLINE(_pos, _pos + QPointF(xform.dx(), xform.dy()))); QFontEngine *fe = ti.fontEngine; QPointF baseline_pos = xform.inverted().map(xform.map(pos) - topLeft); @@ -1816,12 +1631,10 @@ static void draw_text_item_win(const QPointF &_pos, const QTextItemInt &ti, HDC HFONT hfont; bool ttf = false; - bool useTextOutA = false; if (winfe) { hfont = winfe->hfont; ttf = winfe->ttf; - useTextOutA = winfe->useTextOutA; } else { hfont = (HFONT)GetStockObject(ANSI_VAR_FONT); } @@ -1831,154 +1644,115 @@ static void draw_text_item_win(const QPointF &_pos, const QTextItemInt &ti, HDC wchar_t *convertedGlyphs = (wchar_t *)ti.chars; QGlyphLayout glyphs = ti.glyphs; - if (!(ti.flags & QTextItem::RightToLeft) && useTextOutA) { - qreal x = pos.x(); - qreal y = pos.y(); - - // hack to get symbol fonts working on Win95. See also QFontEngine constructor - // can only happen if !ttf - for(int i = 0; i < glyphs.numGlyphs; i++) { - QString str(QChar(glyphs.glyphs[i])); - QT_WA({ - TextOutW(hdc, qRound(x + glyphs.offsets[i].x.toReal()), - qRound(y + glyphs.offsets[i].y.toReal()), - (LPWSTR)str.utf16(), str.length()); - } , { - QByteArray cstr = str.toLocal8Bit(); - TextOutA(hdc, qRound(x + glyphs.offsets[i].x.toReal()), - qRound(y + glyphs.offsets[i].y.toReal()), - cstr.data(), cstr.length()); - }); - x += glyphs.effectiveAdvance(i).toReal(); - } - } else { - bool fast = !has_kerning && !(ti.flags & QTextItem::RightToLeft); - for(int i = 0; fast && i < glyphs.numGlyphs; i++) { - if (glyphs.offsets[i].x != 0 || glyphs.offsets[i].y != 0 || glyphs.justifications[i].space_18d6 != 0 - || glyphs.attributes[i].dontPrint) { - fast = false; - break; - } + bool fast = !has_kerning && !(ti.flags & QTextItem::RightToLeft); + for (int i = 0; fast && i < glyphs.numGlyphs; i++) { + if (glyphs.offsets[i].x != 0 || glyphs.offsets[i].y != 0 || glyphs.justifications[i].space_18d6 != 0 + || glyphs.attributes[i].dontPrint) { + fast = false; + break; } + } #if !defined(Q_OS_WINCE) - // Scale, rotate and translate here. This is only valid for systems > Windows Me. - // We should never get here on Windows Me or lower if the transformation specifies - // scaling or rotation. - QT_WA({ - XFORM win_xform; - win_xform.eM11 = xform.m11(); - win_xform.eM12 = xform.m12(); - win_xform.eM21 = xform.m21(); - win_xform.eM22 = xform.m22(); - win_xform.eDx = xform.dx(); - win_xform.eDy = xform.dy(); - SetGraphicsMode(hdc, GM_ADVANCED); - SetWorldTransform(hdc, &win_xform); - }, { - // nothing - }); + // Scale, rotate and translate here. + XFORM win_xform; + win_xform.eM11 = xform.m11(); + win_xform.eM12 = xform.m12(); + win_xform.eM21 = xform.m21(); + win_xform.eM22 = xform.m22(); + win_xform.eDx = xform.dx(); + win_xform.eDy = xform.dy(); + + SetGraphicsMode(hdc, GM_ADVANCED); + SetWorldTransform(hdc, &win_xform); #endif - if (fast) { - // fast path - QVarLengthArray<wchar_t> g(glyphs.numGlyphs); - for (int i = 0; i < glyphs.numGlyphs; ++i) - g[i] = glyphs.glyphs[i]; - ExtTextOutW(hdc, - qRound(baseline_pos.x() + glyphs.offsets[0].x.toReal()), - qRound(baseline_pos.y() + glyphs.offsets[0].y.toReal()), - options, 0, convertToText ? convertedGlyphs : g.data(), glyphs.numGlyphs, 0); - } else { - QVarLengthArray<QFixedPoint> positions; - QVarLengthArray<glyph_t> _glyphs; - - QTransform matrix; - matrix.translate(baseline_pos.x(), baseline_pos.y()); - ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, - _glyphs, positions); - if (_glyphs.size() == 0) { - SelectObject(hdc, old_font); - return; - } - - convertToText = convertToText && glyphs.numGlyphs == _glyphs.size(); - - bool outputEntireItem = (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) - && QSysInfo::WindowsVersion != QSysInfo::WV_NT - && _glyphs.size() > 0; + if (fast) { + // fast path + QVarLengthArray<wchar_t> g(glyphs.numGlyphs); + for (int i = 0; i < glyphs.numGlyphs; ++i) + g[i] = glyphs.glyphs[i]; + ExtTextOut(hdc, + qRound(baseline_pos.x() + glyphs.offsets[0].x.toReal()), + qRound(baseline_pos.y() + glyphs.offsets[0].y.toReal()), + options, 0, convertToText ? convertedGlyphs : g.data(), glyphs.numGlyphs, 0); + } else { + QVarLengthArray<QFixedPoint> positions; + QVarLengthArray<glyph_t> _glyphs; + + QTransform matrix = QTransform::fromTranslate(baseline_pos.x(), baseline_pos.y()); + ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, + _glyphs, positions); + if (_glyphs.size() == 0) { + SelectObject(hdc, old_font); + return; + } - if (outputEntireItem) { - options |= ETO_PDY; - QVarLengthArray<INT> glyphDistances(_glyphs.size() * 2); - QVarLengthArray<wchar_t> g(_glyphs.size()); - for (int i=0; i<_glyphs.size() - 1; ++i) { - glyphDistances[i * 2] = qRound(positions[i + 1].x) - qRound(positions[i].x); - glyphDistances[i * 2 + 1] = qRound(positions[i + 1].y) - qRound(positions[i].y); - g[i] = _glyphs[i]; - } - glyphDistances[(_glyphs.size() - 1) * 2] = 0; - glyphDistances[(_glyphs.size() - 1) * 2 + 1] = 0; - g[_glyphs.size() - 1] = _glyphs[_glyphs.size() - 1]; - ExtTextOutW(hdc, qRound(positions[0].x), qRound(positions[0].y), options, 0, - convertToText ? convertedGlyphs : g.data(), _glyphs.size(), - glyphDistances.data()); - } else { - int i = 0; - while(i < _glyphs.size()) { - wchar_t g = _glyphs[i]; - - ExtTextOutW(hdc, qRound(positions[i].x), - qRound(positions[i].y), options, 0, - convertToText ? convertedGlyphs + i : &g, 1, 0); - ++i; - } + convertToText = convertToText && glyphs.numGlyphs == _glyphs.size(); + bool outputEntireItem = _glyphs.size() > 0; + + if (outputEntireItem) { + options |= ETO_PDY; + QVarLengthArray<INT> glyphDistances(_glyphs.size() * 2); + QVarLengthArray<wchar_t> g(_glyphs.size()); + for (int i=0; i<_glyphs.size() - 1; ++i) { + glyphDistances[i * 2] = qRound(positions[i + 1].x) - qRound(positions[i].x); + glyphDistances[i * 2 + 1] = qRound(positions[i + 1].y) - qRound(positions[i].y); + g[i] = _glyphs[i]; + } + glyphDistances[(_glyphs.size() - 1) * 2] = 0; + glyphDistances[(_glyphs.size() - 1) * 2 + 1] = 0; + g[_glyphs.size() - 1] = _glyphs[_glyphs.size() - 1]; + ExtTextOut(hdc, qRound(positions[0].x), qRound(positions[0].y), options, 0, + convertToText ? convertedGlyphs : g.data(), _glyphs.size(), + glyphDistances.data()); + } else { + int i = 0; + while(i < _glyphs.size()) { + wchar_t g = _glyphs[i]; + + ExtTextOut(hdc, qRound(positions[i].x), + qRound(positions[i].y), options, 0, + convertToText ? convertedGlyphs + i : &g, 1, 0); + ++i; } } + } #if !defined(Q_OS_WINCE) - QT_WA({ - XFORM win_xform; - win_xform.eM11 = win_xform.eM22 = 1.0; - win_xform.eM12 = win_xform.eM21 = win_xform.eDx = win_xform.eDy = 0.0; - SetWorldTransform(hdc, &win_xform); - }, { - // nothing - }); + win_xform.eM11 = win_xform.eM22 = 1.0; + win_xform.eM12 = win_xform.eM21 = win_xform.eDx = win_xform.eDy = 0.0; + SetWorldTransform(hdc, &win_xform); #endif - } + SelectObject(hdc, old_font); } void QWin32PrintEnginePrivate::updateCustomPaperSize() { - QT_WA( { - uint paperSize = devModeW()->dmPaperSize; - if (paperSize > 0 && mapDevmodePaperSize(paperSize) == QPrinter::Custom) { - has_custom_paper_size = true; - DWORD needed = 0; - DWORD returned = 0; - if (!EnumForms(hPrinter, 1, 0, 0, &needed, &returned)) { - BYTE *forms = (BYTE *) malloc(needed); - if (EnumForms(hPrinter, 1, forms, needed, &needed, &returned)) { - if (paperSize <= returned) { - FORM_INFO_1 *formArray = (FORM_INFO_1 *) forms; - int width = formArray[paperSize-1].Size.cx; // 1/1000 of a mm - int height = formArray[paperSize-1].Size.cy; // 1/1000 of a mm - paper_size = QSizeF((width*72/25.4)/1000.0, (height*72/25.4)/1000.0); - } else { - has_custom_paper_size = false; - } + uint paperSize = devMode->dmPaperSize; + if (paperSize > 0 && mapDevmodePaperSize(paperSize) == QPrinter::Custom) { + has_custom_paper_size = true; + DWORD needed = 0; + DWORD returned = 0; + if (!EnumForms(hPrinter, 1, 0, 0, &needed, &returned)) { + BYTE *forms = (BYTE *) malloc(needed); + if (EnumForms(hPrinter, 1, forms, needed, &needed, &returned)) { + if (paperSize <= returned) { + FORM_INFO_1 *formArray = (FORM_INFO_1 *) forms; + int width = formArray[paperSize - 1].Size.cx; // 1/1000 of a mm + int height = formArray[paperSize - 1].Size.cy; // 1/1000 of a mm + paper_size = QSizeF((width * 72 /25.4) / 1000.0, (height * 72 / 25.4) / 1000.0); + } else { + has_custom_paper_size = false; } - free(forms); } - } else { - has_custom_paper_size = false; + free(forms); } - }, { - // Not supported under Win98 - } ); + } else { + has_custom_paper_size = false; + } } QT_END_NAMESPACE diff --git a/src/gui/painting/qprintengine_win_p.h b/src/gui/painting/qprintengine_win_p.h index 92ddac2..472a55b 100644 --- a/src/gui/painting/qprintengine_win_p.h +++ b/src/gui/painting/qprintengine_win_p.h @@ -169,18 +169,8 @@ public: void readDevmode(HGLOBAL globalDevmode); void readDevnames(HGLOBAL globalDevnames); - inline DEVMODEW *devModeW() const { return (DEVMODEW*) devMode; } - inline DEVMODEA *devModeA() const { return (DEVMODEA*) devMode; } - - inline PRINTER_INFO_2W *pInfoW() { return (PRINTER_INFO_2W*) pInfo; }; - inline PRINTER_INFO_2A *pInfoA() { return (PRINTER_INFO_2A*) pInfo; }; - inline bool resetDC() { - QT_WA( { - hdc = ResetDCW(hdc, devModeW()); - }, { - hdc = ResetDCA(hdc, devModeA()); - } ); + hdc = ResetDC(hdc, devMode); return hdc != 0; } @@ -202,8 +192,8 @@ public: HANDLE hPrinter; HGLOBAL globalDevMode; - void *devMode; - void *pInfo; + DEVMODE *devMode; + PRINTER_INFO_2 *pInfo; HGLOBAL hMem; HDC hdc; diff --git a/src/gui/painting/qprinter.cpp b/src/gui/painting/qprinter.cpp index bbd41db..882e6bc 100644 --- a/src/gui/painting/qprinter.cpp +++ b/src/gui/painting/qprinter.cpp @@ -268,8 +268,8 @@ void QPrinterPrivate::addToManualSetList(QPrintEngine::PrintEnginePropertyKey ke \brief The QPrinter class is a paint device that paints on a printer. - \ingroup multimedia - \mainclass + \ingroup printing + This device represents a series of pages of printed output, and is used in almost exactly the same way as other paint devices such as @@ -712,7 +712,6 @@ QPrinter::~QPrinter() #ifndef QT_NO_PRINTPREVIEWWIDGET delete d->previewEngine; #endif - delete d; } /*! @@ -793,7 +792,8 @@ QPrinter::OutputFormat QPrinter::outputFormat() const -/*! \reimp */ +/*! \internal +*/ int QPrinter::devType() const { return QInternal::Printer; @@ -834,11 +834,15 @@ void QPrinter::setPrinterName(const QString &name) #endif QList<QPrinterInfo> prnList = QPrinterInfo::availablePrinters(); - d->validPrinter = false; - for (int i = 0; i < prnList.size(); ++i) { - if (prnList[i].printerName() == name) { - d->validPrinter = true; - break; + if (name.isEmpty()) { + d->validPrinter = d->outputFormat == QPrinter::PdfFormat || d->outputFormat == QPrinter::PostScriptFormat; + } else { + d->validPrinter = false; + for (int i = 0; i < prnList.size(); ++i) { + if (prnList[i].printerName() == name) { + d->validPrinter = true; + break; + } } } @@ -1304,6 +1308,9 @@ void QPrinter::setNumCopies(int numCopies) Returns true if collation is turned on when multiple copies is selected. Returns false if it is turned off when multiple copies is selected. + When collating is turned off the printing of each individual page will be repeated + the numCopies() amount before the next page is started. With collating turned on + all pages are printed before the next copy of those pages is started. \sa setCollateCopies() */ @@ -1657,10 +1664,10 @@ void QPrinter::getPageMargins(qreal *left, qreal *top, qreal *right, qreal *bott Q_ASSERT(left && top && right && bottom); const qreal multiplier = qt_multiplierForUnit(unit, resolution()); QList<QVariant> margins(d->printEngine->property(QPrintEngine::PPK_PageMargins).toList()); - *left = margins.at(0).toDouble() / multiplier; - *top = margins.at(1).toDouble() / multiplier; - *right = margins.at(2).toDouble() / multiplier; - *bottom = margins.at(3).toDouble() / multiplier; + *left = margins.at(0).toReal() / multiplier; + *top = margins.at(1).toReal() / multiplier; + *right = margins.at(2).toReal() / multiplier; + *bottom = margins.at(3).toReal() / multiplier; } /*! @@ -2154,8 +2161,8 @@ bool QPrinter::collateCopiesEnabled() const } /*! - Use QPrintDialog::addEnabledOption(QPrintDialog::PrintCollateCopies) - or QPrintDialog::setEnabledOptions(QPrintDialog::enabledOptions() + Use QPrintDialog::setOption(QPrintDialog::PrintCollateCopies) + or QPrintDialog::setOptions(QPrintDialog::options() & ~QPrintDialog::PrintCollateCopies) instead, depending on \a enable. */ @@ -2196,7 +2203,7 @@ bool QPrinter::isOptionEnabled( PrinterOption option ) const \class QPrintEngine \reentrant - \ingroup multimedia + \ingroup printing \brief The QPrintEngine class defines an interface for how QPrinter interacts with a given printing subsystem. diff --git a/src/gui/painting/qprinter.h b/src/gui/painting/qprinter.h index 14799e3..46419f4 100644 --- a/src/gui/painting/qprinter.h +++ b/src/gui/painting/qprinter.h @@ -42,8 +42,9 @@ #ifndef QPRINTER_H #define QPRINTER_H -#include <QtGui/qpaintdevice.h> #include <QtCore/qstring.h> +#include <QtCore/qscopedpointer.h> +#include <QtGui/qpaintdevice.h> QT_BEGIN_HEADER @@ -288,7 +289,7 @@ private: Q_DISABLE_COPY(QPrinter) - QPrinterPrivate *d_ptr; + QScopedPointer<QPrinterPrivate> d_ptr; friend class QPrintDialogPrivate; friend class QAbstractPrintDialog; diff --git a/src/gui/painting/qprinterinfo.h b/src/gui/painting/qprinterinfo.h index 162c729..2467fc6 100644 --- a/src/gui/painting/qprinterinfo.h +++ b/src/gui/painting/qprinterinfo.h @@ -53,6 +53,7 @@ QT_MODULE(Gui) #ifndef QT_NO_PRINTER class QPrinterInfoPrivate; +class QPrinterInfoPrivateDeleter; class Q_GUI_EXPORT QPrinterInfo { Q_DECLARE_PRIVATE(QPrinterInfo) @@ -76,7 +77,7 @@ public: private: QPrinterInfo(const QString& name); - QPrinterInfoPrivate* d_ptr; + QScopedPointer<QPrinterInfoPrivate, QPrinterInfoPrivateDeleter> d_ptr; }; #endif // QT_NO_PRINTER diff --git a/src/gui/painting/qprinterinfo.qdoc b/src/gui/painting/qprinterinfo.qdoc new file mode 100644 index 0000000..13d76f6 --- /dev/null +++ b/src/gui/painting/qprinterinfo.qdoc @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \class QPrinterInfo + + \brief The QPrinterInfo class gives access to information about + existing printers. + + \ingroup printing + + Use the static functions to generate a list of QPrinterInfo + objects. Each QPrinterInfo object in the list represents a single + printer and can be queried for name, supported paper sizes, and + whether or not it is the default printer. + + \since 4.4 +*/ + +/*! + \fn QList<QPrinterInfo> QPrinterInfo::availablePrinters() + + Returns a list of available printers on the system. +*/ + +/*! + \fn QPrinterInfo QPrinterInfo::defaultPrinter() + + Returns the default printer on the system. + + The return value should be checked using isNull() before being + used, in case there is no default printer. + + \sa isNull() +*/ + +/*! + \fn QPrinterInfo::QPrinterInfo() + + Constructs an empty QPrinterInfo object. + + \sa isNull() +*/ + +/*! + \fn QPrinterInfo::QPrinterInfo(const QPrinterInfo& src) + + Constructs a copy of \a src. +*/ + +/*! + \fn QPrinterInfo::QPrinterInfo(const QPrinter& printer) + + Constructs a QPrinterInfo object from \a printer. +*/ + +/*! + \fn QPrinterInfo::~QPrinterInfo() + + Destroys the QPrinterInfo object. References to the values in the + object become invalid. +*/ + +/*! + \fn QPrinterInfo& QPrinterInfo::operator=(const QPrinterInfo& src) + + Sets the QPrinterInfo object to be equal to \a src. +*/ + +/*! + \fn QString QPrinterInfo::printerName() const + + Returns the name of the printer. + + \sa QPrinter::setPrinterName() +*/ + +/*! + \fn bool QPrinterInfo::isNull() const + + Returns whether this QPrinterInfo object holds a printer definition. + + An empty QPrinterInfo object could result for example from calling + defaultPrinter() when there are no printers on the system. +*/ + +/*! + \fn bool QPrinterInfo::isDefault() const + + Returns whether this printer is the default printer. +*/ + +/*! + \fn QList< QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const + \since 4.4 + + Returns a list of supported paper sizes by the printer. + + Not all printer drivers support this query, so the list may be empty. + On Mac OS X 10.3, this function always returns an empty list. +*/ diff --git a/src/gui/painting/qprinterinfo_mac.cpp b/src/gui/painting/qprinterinfo_mac.cpp index 014a234..ee0042e 100644 --- a/src/gui/painting/qprinterinfo_mac.cpp +++ b/src/gui/painting/qprinterinfo_mac.cpp @@ -65,6 +65,16 @@ private: static QPrinterInfoPrivate nullQPrinterInfoPrivate; +class QPrinterInfoPrivateDeleter +{ +public: + static inline void cleanup(QPrinterInfoPrivate *d) + { + if (d != &nullQPrinterInfoPrivate) + delete d; + } +}; + extern QPrinter::PaperSize qSizeFTopaperSize(const QSizeF& size); ///////////////////////////////////////////////////////////////////////////// @@ -106,8 +116,8 @@ QPrinterInfo QPrinterInfo::defaultPrinter(){ ///////////////////////////////////////////////////////////////////////////// QPrinterInfo::QPrinterInfo(const QPrinter& prn) + : d_ptr(&nullQPrinterInfoPrivate) { - d_ptr = &nullQPrinterInfoPrivate; QList<QPrinterInfo> list = availablePrinters(); for (int c = 0; c < list.size(); ++c) { if (prn.printerName() == list[c].printerName()) { @@ -115,39 +125,33 @@ QPrinterInfo::QPrinterInfo(const QPrinter& prn) return; } } - - *this = QPrinterInfo(); } QPrinterInfo::~QPrinterInfo() { - if (d_ptr != &nullQPrinterInfoPrivate) - delete d_ptr; } QPrinterInfo::QPrinterInfo() + : d_ptr(&nullQPrinterInfoPrivate) { - d_ptr = &nullQPrinterInfoPrivate; } QPrinterInfo::QPrinterInfo(const QString& name) + : d_ptr(new QPrinterInfoPrivate(name)) { - d_ptr = new QPrinterInfoPrivate(name); d_ptr->q_ptr = this; } QPrinterInfo::QPrinterInfo(const QPrinterInfo& src) + : d_ptr(&nullQPrinterInfoPrivate) { - d_ptr = &nullQPrinterInfoPrivate; *this = src; } QPrinterInfo& QPrinterInfo::operator=(const QPrinterInfo& src) { Q_ASSERT(d_ptr); - if (d_ptr != &nullQPrinterInfoPrivate) - delete d_ptr; - d_ptr = new QPrinterInfoPrivate(*src.d_ptr); + d_ptr.reset(new QPrinterInfoPrivate(*src.d_ptr)); d_ptr->q_ptr = this; return *this; } @@ -172,16 +176,9 @@ bool QPrinterInfo::isDefault() const QList<QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const { -#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4) - return QList<QPrinter::PaperSize>(); -#else - if (QSysInfo::MacintoshVersion <= QSysInfo::MV_10_4) - return QList<QPrinter::PaperSize>(); - const Q_D(QPrinterInfo); - PMPrinter cfPrn = PMPrinterCreateFromPrinterID( - QCFString::toCFStringRef(d->m_name)); + PMPrinter cfPrn = PMPrinterCreateFromPrinterID(QCFString::toCFStringRef(d->m_name)); if (!cfPrn) return QList<QPrinter::PaperSize>(); @@ -211,7 +208,6 @@ QList<QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const PMRelease(cfPrn); return paperList; -#endif // MAC_OS_X_VERSION_MAX_ALLOWED } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gui/painting/qprinterinfo_unix.cpp b/src/gui/painting/qprinterinfo_unix.cpp index c35d2c8..78919d2 100644 --- a/src/gui/painting/qprinterinfo_unix.cpp +++ b/src/gui/painting/qprinterinfo_unix.cpp @@ -82,6 +82,16 @@ private: static QPrinterInfoPrivate nullQPrinterInfoPrivate; +class QPrinterInfoPrivateDeleter +{ +public: + static inline void cleanup(QPrinterInfoPrivate *d) + { + if (d != &nullQPrinterInfoPrivate) + delete d; + } +}; + ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// @@ -822,7 +832,7 @@ QList<QPrinterInfo> QPrinterInfo::availablePrinters() for (int i = 0; i < cupsPrinterCount; ++i) { QString printerName(QString::fromLocal8Bit(cupsPrinters[i].name)); if (cupsPrinters[i].instance) - printerName += QLatin1String("/") + QString::fromLocal8Bit(cupsPrinters[i].instance); + printerName += QLatin1Char('/') + QString::fromLocal8Bit(cupsPrinters[i].instance); list.append(QPrinterInfo(printerName)); if (cupsPrinters[i].is_default) list[i].d_ptr->m_default = true; @@ -867,19 +877,19 @@ QPrinterInfo QPrinterInfo::defaultPrinter() } QPrinterInfo::QPrinterInfo() + : d_ptr(&nullQPrinterInfoPrivate) { - d_ptr = &nullQPrinterInfoPrivate; } QPrinterInfo::QPrinterInfo(const QPrinterInfo& src) + : d_ptr(&nullQPrinterInfoPrivate) { - d_ptr = &nullQPrinterInfoPrivate; *this = src; } QPrinterInfo::QPrinterInfo(const QPrinter& printer) + : d_ptr(new QPrinterInfoPrivate(printer.printerName())) { - d_ptr = new QPrinterInfoPrivate(printer.printerName()); Q_D(QPrinterInfo); d->q_ptr = this; @@ -893,7 +903,7 @@ QPrinterInfo::QPrinterInfo(const QPrinter& printer) for (int i = 0; i < cupsPrinterCount; ++i) { QString printerName(QString::fromLocal8Bit(cupsPrinters[i].name)); if (cupsPrinters[i].instance) - printerName += QLatin1String("/") + QString::fromLocal8Bit(cupsPrinters[i].instance); + printerName += QLatin1Char('/') + QString::fromLocal8Bit(cupsPrinters[i].instance); if (printerName == printer.printerName()) { if (cupsPrinters[i].is_default) d->m_default = true; @@ -929,28 +939,23 @@ QPrinterInfo::QPrinterInfo(const QPrinter& printer) #endif // Printer not found. - delete d; - d_ptr = &nullQPrinterInfoPrivate; + d_ptr.reset(&nullQPrinterInfoPrivate); } QPrinterInfo::QPrinterInfo(const QString& name) + : d_ptr(new QPrinterInfoPrivate(name)) { - d_ptr = new QPrinterInfoPrivate(name); d_ptr->q_ptr = this; } QPrinterInfo::~QPrinterInfo() { - if (d_ptr != &nullQPrinterInfoPrivate) - delete d_ptr; } QPrinterInfo& QPrinterInfo::operator=(const QPrinterInfo& src) { Q_ASSERT(d_ptr); - if (d_ptr != &nullQPrinterInfoPrivate) - delete d_ptr; - d_ptr = new QPrinterInfoPrivate(*src.d_ptr); + d_ptr.reset(new QPrinterInfoPrivate(*src.d_ptr)); d_ptr->q_ptr = this; return *this; } diff --git a/src/gui/painting/qprinterinfo_win.cpp b/src/gui/painting/qprinterinfo_win.cpp index 2b6fa42..f834d5c 100644 --- a/src/gui/painting/qprinterinfo_win.cpp +++ b/src/gui/painting/qprinterinfo_win.cpp @@ -43,7 +43,7 @@ #include <qstringlist.h> -#include <windows.h> +#include <qt_windows.h> QT_BEGIN_NAMESPACE @@ -69,6 +69,16 @@ private: static QPrinterInfoPrivate nullQPrinterInfoPrivate; +class QPrinterInfoPrivateDeleter +{ +public: + static inline void cleanup(QPrinterInfoPrivate *d) + { + if (d != &nullQPrinterInfoPrivate) + delete d; + } +}; + ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// @@ -79,45 +89,24 @@ QList<QPrinterInfo> QPrinterInfo::availablePrinters() DWORD needed = 0; DWORD returned = 0; - QT_WA({ - if (!EnumPrintersW(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, - 4, 0, 0, &needed, &returned)) - { - buffer = new BYTE[needed]; - if (!EnumPrintersW(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS , NULL, - 4, buffer, needed, &needed, &returned)) - { - delete [] buffer; - return printers; - } - PPRINTER_INFO_4 infoList = reinterpret_cast<PPRINTER_INFO_4>(buffer); - QPrinterInfo defPrn = defaultPrinter(); - for (uint i = 0; i < returned; ++i) { - printers.append(QPrinterInfo(QString::fromUtf16(reinterpret_cast<const ushort*>(infoList[i].pPrinterName)))); - if (printers.at(i).printerName() == defPrn.printerName()) - printers[i].d_ptr->m_default = true; - } - delete [] buffer; - } - }, { - // In Windows 98 networked printers are served through the local connection - if (!EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 5, 0, 0, &needed, &returned)) { - buffer = new BYTE[needed]; - if (!EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 5, buffer, needed, &needed, &returned)) { - delete [] buffer; - return printers; - } - - PPRINTER_INFO_5 infoList = reinterpret_cast<PPRINTER_INFO_5>(buffer); - QPrinterInfo defPrn = defaultPrinter(); - for (uint i = 0; i < returned; ++i) { - printers.append(QPrinterInfo(QString::fromLocal8Bit(reinterpret_cast<const char*>(infoList[i].pPrinterName)))); - if (printers.at(i).printerName() == defPrn.printerName()) - printers[i].d_ptr->m_default = true; - } - delete [] buffer; - } - }); + if ( !EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, 0, 0, &needed, &returned)) + { + buffer = new BYTE[needed]; + if (!EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS , NULL, + 4, buffer, needed, &needed, &returned)) + { + delete [] buffer; + return printers; + } + PPRINTER_INFO_4 infoList = reinterpret_cast<PPRINTER_INFO_4>(buffer); + QPrinterInfo defPrn = defaultPrinter(); + for (uint i = 0; i < returned; ++i) { + printers.append(QPrinterInfo(QString::fromWCharArray(infoList[i].pPrinterName))); + if (printers.at(i).printerName() == defPrn.printerName()) + printers[i].d_ptr->m_default = true; + } + delete [] buffer; + } return printers; } @@ -125,18 +114,9 @@ QList<QPrinterInfo> QPrinterInfo::availablePrinters() QPrinterInfo QPrinterInfo::defaultPrinter() { QString noPrinters(QLatin1String("qt_no_printers")); - QString output; - QT_WA({ - ushort buffer[256]; - GetProfileStringW(L"windows", L"device", - reinterpret_cast<const wchar_t *>(noPrinters.utf16()), - reinterpret_cast<wchar_t *>(buffer), 256); - output = QString::fromUtf16(buffer); - }, { - char buffer[256]; - GetProfileStringA("windows", "device", noPrinters.toLatin1(), buffer, 256); - output = QString::fromLocal8Bit(buffer); - }); + wchar_t buffer[256]; + GetProfileString(L"windows", L"device", (wchar_t*)noPrinters.utf16(), buffer, 256); + QString output = QString::fromWCharArray(buffer); // Filter out the name of the printer, which should be everything // before a comma. @@ -155,25 +135,25 @@ QPrinterInfo QPrinterInfo::defaultPrinter() ///////////////////////////////////////////////////////////////////////////// QPrinterInfo::QPrinterInfo() + : d_ptr(&nullQPrinterInfoPrivate) { - d_ptr = &nullQPrinterInfoPrivate; } QPrinterInfo::QPrinterInfo(const QString& name) + : d_ptr(new QPrinterInfoPrivate(name)) { - d_ptr = new QPrinterInfoPrivate(name); d_ptr->q_ptr = this; } QPrinterInfo::QPrinterInfo(const QPrinterInfo& src) + : d_ptr(&nullQPrinterInfoPrivate) { - d_ptr = &nullQPrinterInfoPrivate; *this = src; } QPrinterInfo::QPrinterInfo(const QPrinter& prn) + : d_ptr(&nullQPrinterInfoPrivate) { - d_ptr = &nullQPrinterInfoPrivate; QList<QPrinterInfo> list = availablePrinters(); for (int c = 0; c < list.size(); ++c) { if (prn.printerName() == list[c].printerName()) { @@ -187,16 +167,12 @@ QPrinterInfo::QPrinterInfo(const QPrinter& prn) QPrinterInfo::~QPrinterInfo() { - if (d_ptr != &nullQPrinterInfoPrivate) - delete d_ptr; } QPrinterInfo& QPrinterInfo::operator=(const QPrinterInfo& src) { Q_ASSERT(d_ptr); - if (d_ptr != &nullQPrinterInfoPrivate) - delete d_ptr; - d_ptr = new QPrinterInfoPrivate(*src.d_ptr); + d_ptr.reset(new QPrinterInfoPrivate(*src.d_ptr)); d_ptr->q_ptr = this; return *this; } @@ -222,26 +198,16 @@ bool QPrinterInfo::isDefault() const QList<QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const { const Q_D(QPrinterInfo); - DWORD size; - WORD* papers; QList<QPrinter::PaperSize> paperList; - QT_WA({ - size = DeviceCapabilitiesW(reinterpret_cast<const WCHAR*>(d->m_name.utf16()), - NULL, DC_PAPERS, NULL, NULL); - if ((int)size == -1) - return paperList; - papers = new WORD[size]; - size = DeviceCapabilitiesW(reinterpret_cast<const WCHAR*>(d->m_name.utf16()), - NULL, DC_PAPERS, reinterpret_cast<WCHAR*>(papers), NULL); - }, { - size = DeviceCapabilitiesA(d->m_name.toLatin1().data(), NULL, DC_PAPERS, NULL, NULL); - if ((int)size == -1) - return paperList; - papers = new WORD[size]; - size = DeviceCapabilitiesA(d->m_name.toLatin1().data(), NULL, DC_PAPERS, - reinterpret_cast<char*>(papers), NULL); - }); + DWORD size = DeviceCapabilities(reinterpret_cast<const wchar_t*>(d->m_name.utf16()), + NULL, DC_PAPERS, NULL, NULL); + if ((int)size == -1) + return paperList; + + wchar_t *papers = new wchar_t[size]; + size = DeviceCapabilities(reinterpret_cast<const wchar_t*>(d->m_name.utf16()), + NULL, DC_PAPERS, papers, NULL); for (int c = 0; c < (int)size; ++c) { paperList.append(mapDevmodePaperSize(papers[c])); diff --git a/src/gui/painting/qrasterizer.cpp b/src/gui/painting/qrasterizer.cpp index fe90221..2b73f9b 100644 --- a/src/gui/painting/qrasterizer.cpp +++ b/src/gui/painting/qrasterizer.cpp @@ -436,8 +436,9 @@ void QScanConverter::end() inline void QScanConverter::allocate(int size) { if (m_alloc < size) { - m_alloc = qMax(size, 2 * m_alloc); - m_intersections = (Intersection *)realloc(m_intersections, m_alloc * sizeof(Intersection)); + int newAlloc = qMax(size, 2 * m_alloc); + m_intersections = q_check_ptr((Intersection *)realloc(m_intersections, newAlloc * sizeof(Intersection))); + m_alloc = newAlloc; } } diff --git a/src/gui/painting/qrasterizer_p.h b/src/gui/painting/qrasterizer_p.h index e6a354d..4cfdbbf 100644 --- a/src/gui/painting/qrasterizer_p.h +++ b/src/gui/painting/qrasterizer_p.h @@ -65,7 +65,7 @@ struct QSpanData; class QRasterBuffer; class QRasterizerPrivate; -class QRasterizer +class Q_GUI_EXPORT QRasterizer { public: QRasterizer(); diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp index badc14a..d138663 100644 --- a/src/gui/painting/qregion.cpp +++ b/src/gui/painting/qregion.cpp @@ -49,7 +49,7 @@ #include <qdebug.h> -#if defined(Q_OS_UNIX) || defined(Q_OS_WINCE) +#if defined(Q_OS_UNIX) || defined(Q_WS_WIN) #include "qimage.h" #include "qbitmap.h" #include <stdlib.h> @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE \class QRegion \brief The QRegion class specifies a clip region for a painter. - \ingroup multimedia + \ingroup painting \ingroup shared QRegion is used with QPainter::setClipRegion() to limit the paint @@ -92,10 +92,6 @@ QT_BEGIN_NAMESPACE Example of using complex regions: \snippet doc/src/snippets/code/src_gui_painting_qregion.cpp 0 - \warning Due to window system limitations, the whole coordinate space for a - region is limited to the points between -32767 and 32767 on Windows - 95/98/ME. You can circumvent this limitation by using a QPainterPath. - \section1 Additional License Information On Embedded Linux, Windows CE and X11 platforms, parts of this class rely on @@ -450,9 +446,9 @@ QDebug operator<<(QDebug s, const QRegion &r) { QVector<QRect> rects = r.rects(); s.nospace() << "QRegion(size=" << rects.size() << "), " - << "bounds = " << r.boundingRect() << "\n"; + << "bounds = " << r.boundingRect() << '\n'; for (int i=0; i<rects.size(); ++i) - s << "- " << i << rects.at(i) << "\n"; + s << "- " << i << rects.at(i) << '\n'; return s; } #endif @@ -549,7 +545,7 @@ QRegion& QRegion::operator|=(const QRegion &r) \sa intersected() */ -#if !defined (Q_OS_UNIX) && !defined (Q_OS_WINCE) +#if !defined (Q_OS_UNIX) && !defined (Q_WS_WIN) QRegion& QRegion::operator+=(const QRect &r) { return operator+=(QRegion(r)); @@ -565,16 +561,14 @@ QRegion& QRegion::operator+=(const QRect &r) \sa intersected() */ -#if !defined(Q_WS_WIN) || defined(Q_OS_WINCE) QRegion& QRegion::operator&=(const QRegion &r) { return *this = *this & r; } -#endif /*! \overload \since 4.4 */ -#if defined (Q_OS_UNIX) || defined (Q_OS_WINCE) +#if defined (Q_OS_UNIX) || defined (Q_WS_WIN) QRegion& QRegion::operator&=(const QRect &r) { return *this = *this & r; @@ -595,10 +589,8 @@ QRegion& QRegion::operator&=(const QRect &r) \sa subtracted() */ -#if !defined(Q_WS_WIN) || defined(Q_OS_WINCE) QRegion& QRegion::operator-=(const QRegion &r) { return *this = *this - r; } -#endif /*! Applies the xored() function to this region and \a r and @@ -698,6 +690,8 @@ bool QRegion::intersects(const QRegion ®ion) const if (!rect_intersects(boundingRect(), region.boundingRect())) return false; + if (numRects() == 1 && region.numRects() == 1) + return true; const QVector<QRect> myRects = rects(); const QVector<QRect> otherRects = region.rects(); @@ -723,6 +717,8 @@ bool QRegion::intersects(const QRect &rect) const const QRect r = rect.normalized(); if (!rect_intersects(boundingRect(), r)) return false; + if (numRects() == 1) + return true; const QVector<QRect> myRects = rects(); for (QVector<QRect>::const_iterator it = myRects.constBegin(); it < myRects.constEnd(); ++it) @@ -731,7 +727,7 @@ bool QRegion::intersects(const QRect &rect) const return false; } -#if !defined (Q_OS_UNIX) && !defined (Q_OS_WINCE) +#if !defined (Q_OS_UNIX) && !defined (Q_WS_WIN) /*! \overload \since 4.4 @@ -1086,7 +1082,7 @@ Q_AUTOTEST_EXPORT QPainterPath qt_regionToPath(const QRegion ®ion) return result; } -#if defined(Q_OS_UNIX) || defined(Q_OS_WINCE) +#if defined(Q_OS_UNIX) || defined(Q_WS_WIN) //#define QT_REGION_DEBUG /* @@ -1601,7 +1597,7 @@ void QRegionPrivate::selfTest() const for (int i = 0; i < numRects; ++i) { const QRect r = rects.at(i); if ((r.width() * r.height()) > innerArea) - qDebug() << "selfTest(): innerRect" << innerRect << "<" << r; + qDebug() << "selfTest(): innerRect" << innerRect << '<' << r; } QRect r = rects.first(); @@ -1627,9 +1623,9 @@ QT_END_INCLUDE_NAMESPACE QT_BEGIN_INCLUDE_NAMESPACE # include "qregion_mac.cpp" QT_END_INCLUDE_NAMESPACE -#elif defined(Q_OS_WINCE) +#elif defined(Q_WS_WIN) QT_BEGIN_INCLUDE_NAMESPACE -# include "qregion_wince.cpp" +# include "qregion_win.cpp" QT_END_INCLUDE_NAMESPACE #elif defined(Q_WS_QWS) static QRegionPrivate qrp; @@ -3167,6 +3163,7 @@ static void InsertEdgeInET(EdgeTable *ET, EdgeTableEntry *ETE, int scanline, { tmpSLLBlock = (ScanLineListBlock *)malloc(sizeof(ScanLineListBlock)); + Q_CHECK_PTR(tmpSLLBlock); (*SLLBlock)->next = tmpSLLBlock; tmpSLLBlock->next = (ScanLineListBlock *)NULL; *SLLBlock = tmpSLLBlock; @@ -3553,6 +3550,8 @@ static void PtsToRegion(register int numFullPtBlocks, register int iCurPtBlock, * Scan converts a polygon by returning a run-length * encoding of the resultant bitmap -- the run-length * encoding is in the form of an array of rectangles. + * + * Can return 0 in case of errors. */ static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule) //Point *Pts; /* the pts */ @@ -3624,75 +3623,28 @@ static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule) } - if (rule == EvenOddRule) { - /* - * for each scanline - */ - for (y = ET.ymin; y < ET.ymax; ++y) { - - /* - * Add a new edge to the active edge table when we - * get to the next edge. - */ - if (pSLL && y == pSLL->scanline) { - loadAET(&AET, pSLL->edgelist); - pSLL = pSLL->next; - } - pPrevAET = &AET; - pAET = AET.next; - + QT_TRY { + if (rule == EvenOddRule) { /* - * for each active edge + * for each scanline */ - while (pAET) { - pts->setX(pAET->bres.minor_axis); - pts->setY(y); - ++pts; - ++iPts; + for (y = ET.ymin; y < ET.ymax; ++y) { /* - * send out the buffer + * Add a new edge to the active edge table when we + * get to the next edge. */ - if (iPts == NUMPTSTOBUFFER) { - tmpPtBlock = (POINTBLOCK *)malloc(sizeof(POINTBLOCK)); - tmpPtBlock->pts = reinterpret_cast<QPoint *>(tmpPtBlock->data); - curPtBlock->next = tmpPtBlock; - curPtBlock = tmpPtBlock; - pts = curPtBlock->pts; - ++numFullPtBlocks; - iPts = 0; + if (pSLL && y == pSLL->scanline) { + loadAET(&AET, pSLL->edgelist); + pSLL = pSLL->next; } - EVALUATEEDGEEVENODD(pAET, pPrevAET, y) - } - InsertionSort(&AET); - } - } else { - /* - * for each scanline - */ - for (y = ET.ymin; y < ET.ymax; ++y) { - /* - * Add a new edge to the active edge table when we - * get to the next edge. - */ - if (pSLL && y == pSLL->scanline) { - loadAET(&AET, pSLL->edgelist); - computeWAET(&AET); - pSLL = pSLL->next; - } - pPrevAET = &AET; - pAET = AET.next; - pWETE = pAET; + pPrevAET = &AET; + pAET = AET.next; - /* - * for each active edge - */ - while (pAET) { /* - * add to the buffer only those edges that - * are in the Winding active edge table. + * for each active edge */ - if (pWETE == pAET) { + while (pAET) { pts->setX(pAET->bres.minor_axis); pts->setY(y); ++pts; @@ -3702,7 +3654,8 @@ static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule) * send out the buffer */ if (iPts == NUMPTSTOBUFFER) { - tmpPtBlock = static_cast<POINTBLOCK *>(malloc(sizeof(POINTBLOCK))); + tmpPtBlock = (POINTBLOCK *)malloc(sizeof(POINTBLOCK)); + Q_CHECK_PTR(tmpPtBlock); tmpPtBlock->pts = reinterpret_cast<QPoint *>(tmpPtBlock->data); curPtBlock->next = tmpPtBlock; curPtBlock = tmpPtBlock; @@ -3710,21 +3663,81 @@ static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule) ++numFullPtBlocks; iPts = 0; } - pWETE = pWETE->nextWETE; + EVALUATEEDGEEVENODD(pAET, pPrevAET, y) } - EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) + InsertionSort(&AET); } - + } else { /* - * recompute the winding active edge table if - * we just resorted or have exited an edge. + * for each scanline */ - if (InsertionSort(&AET) || fixWAET) { - computeWAET(&AET); - fixWAET = false; + for (y = ET.ymin; y < ET.ymax; ++y) { + /* + * Add a new edge to the active edge table when we + * get to the next edge. + */ + if (pSLL && y == pSLL->scanline) { + loadAET(&AET, pSLL->edgelist); + computeWAET(&AET); + pSLL = pSLL->next; + } + pPrevAET = &AET; + pAET = AET.next; + pWETE = pAET; + + /* + * for each active edge + */ + while (pAET) { + /* + * add to the buffer only those edges that + * are in the Winding active edge table. + */ + if (pWETE == pAET) { + pts->setX(pAET->bres.minor_axis); + pts->setY(y); + ++pts; + ++iPts; + + /* + * send out the buffer + */ + if (iPts == NUMPTSTOBUFFER) { + tmpPtBlock = static_cast<POINTBLOCK *>(malloc(sizeof(POINTBLOCK))); + tmpPtBlock->pts = reinterpret_cast<QPoint *>(tmpPtBlock->data); + curPtBlock->next = tmpPtBlock; + curPtBlock = tmpPtBlock; + pts = curPtBlock->pts; + ++numFullPtBlocks; + iPts = 0; + } + pWETE = pWETE->nextWETE; + } + EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) + } + + /* + * recompute the winding active edge table if + * we just resorted or have exited an edge. + */ + if (InsertionSort(&AET) || fixWAET) { + computeWAET(&AET); + fixWAET = false; + } } } + } QT_CATCH(...) { + FreeStorage(SLLBlock.next); + PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region); + for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) { + tmpPtBlock = curPtBlock->next; + free(curPtBlock); + curPtBlock = tmpPtBlock; + } + free(pETEs); + return 0; // this function returns 0 in case of an error } + FreeStorage(SLLBlock.next); PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region); for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) { @@ -3829,7 +3842,7 @@ QRegion::QRegion(const QRect &r, RegionType t) #if defined(Q_WS_X11) d->rgn = 0; d->xrectangles = 0; -#elif defined(Q_OS_WINCE) +#elif defined(Q_WS_WIN) d->rgn = 0; #endif if (t == Rectangle) { @@ -3851,7 +3864,7 @@ QRegion::QRegion(const QPolygon &a, Qt::FillRule fillRule) #if defined(Q_WS_X11) d->rgn = 0; d->xrectangles = 0; -#elif defined(Q_OS_WINCE) +#elif defined(Q_WS_WIN) d->rgn = 0; #endif d->qt_rgn = PolygonRegion(a.constData(), a.size(), @@ -3881,7 +3894,7 @@ QRegion::QRegion(const QBitmap &bm) #if defined(Q_WS_X11) d->rgn = 0; d->xrectangles = 0; -#elif defined(Q_OS_WINCE) +#elif defined(Q_WS_WIN) d->rgn = 0; #endif d->qt_rgn = qt_bitmapToRegion(bm); @@ -3896,7 +3909,7 @@ void QRegion::cleanUp(QRegion::QRegionData *x) XDestroyRegion(x->rgn); if (x->xrectangles) free(x->xrectangles); -#elif defined(Q_OS_WINCE) +#elif defined(Q_WS_WIN) if (x->rgn) qt_win_dispose_rgn(x->rgn); #endif @@ -3923,16 +3936,15 @@ QRegion &QRegion::operator=(const QRegion &r) /*! \internal */ - QRegion QRegion::copy() const { QRegion r; - QRegionData *x = new QRegionData; + QScopedPointer<QRegionData> x(new QRegionData); x->ref = 1; #if defined(Q_WS_X11) x->rgn = 0; x->xrectangles = 0; -#elif defined(Q_OS_WINCE) +#elif defined(Q_WS_WIN) x->rgn = 0; #endif if (d->qt_rgn) @@ -3941,7 +3953,7 @@ QRegion QRegion::copy() const x->qt_rgn = new QRegionPrivate; if (!r.d->ref.deref()) cleanUp(r.d); - r.d = x; + r.d = x.take(); return r; } diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h index 67f1355..226e3fa 100644 --- a/src/gui/painting/qregion.h +++ b/src/gui/painting/qregion.h @@ -59,7 +59,7 @@ QT_MODULE(Gui) template <class T> class QVector; class QVariant; -#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_OS_WINCE) +#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) struct QRegionPrivate; #endif @@ -148,6 +148,7 @@ public: #elif defined(Q_WS_MAC) #if defined Q_WS_MAC32 RgnHandle toQDRgn() const; + RgnHandle toQDRgnForUpdate_sys() const; static QRegion fromQDRgn(RgnHandle shape); #endif #ifdef QT_MAC_USE_COCOA @@ -199,7 +200,7 @@ private: #elif defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) mutable RgnHandle unused; // Here for binary compatability reasons. ### Qt 5 remove. #endif -#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_OS_WINCE) +#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) QRegionPrivate *qt_rgn; #endif }; diff --git a/src/gui/painting/qregion_mac.cpp b/src/gui/painting/qregion_mac.cpp index 160622b..c887171 100644 --- a/src/gui/painting/qregion_mac.cpp +++ b/src/gui/painting/qregion_mac.cpp @@ -155,6 +155,43 @@ RgnHandle QRegion::toQDRgn() const } return rgnHandle; } + +/*! + \internal + Create's a RegionHandle, it's the caller's responsibility to release. + Returns 0 if the QRegion overflows. +*/ +RgnHandle QRegion::toQDRgnForUpdate_sys() const +{ + RgnHandle rgnHandle = qt_mac_get_rgn(); + if(d->qt_rgn && d->qt_rgn->numRects) { + RgnHandle tmp_rgn = qt_mac_get_rgn(); + int n = d->qt_rgn->numRects; + const QRect *qt_r = (n == 1) ? &d->qt_rgn->extents : d->qt_rgn->rects.constData(); + while (n--) { + + // detect overflow. Tested for use with HIViewSetNeedsDisplayInRegion + // in QWidgetPrivate::update_sys(). + enum { HIViewSetNeedsDisplayInRegionOverflow = 10000 }; // empirically determined conservative value + if (qt_r->right() > HIViewSetNeedsDisplayInRegionOverflow || qt_r->bottom() > HIViewSetNeedsDisplayInRegionOverflow) { + qt_mac_dispose_rgn(tmp_rgn); + qt_mac_dispose_rgn(rgnHandle); + return 0; + } + + SetRectRgn(tmp_rgn, + qMax(SHRT_MIN, qt_r->x()), + qMax(SHRT_MIN, qt_r->y()), + qMin(SHRT_MAX, qt_r->right() + 1), + qMin(SHRT_MAX, qt_r->bottom() + 1)); + UnionRgn(rgnHandle, tmp_rgn, rgnHandle); + ++qt_r; + } + qt_mac_dispose_rgn(tmp_rgn); + } + return rgnHandle; +} + #endif #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) diff --git a/src/gui/painting/qregion_s60.cpp b/src/gui/painting/qregion_s60.cpp new file mode 100644 index 0000000..5600ece --- /dev/null +++ b/src/gui/painting/qregion_s60.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbitmap.h" +#include "qbuffer.h" +#include "qimage.h" +#include "qpolygon.h" +#include "qregion.h" + +QT_BEGIN_NAMESPACE + +QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0 }; + +QT_END_NAMESPACE diff --git a/src/gui/painting/qregion_win.cpp b/src/gui/painting/qregion_win.cpp index 9b31e7b..d262198 100644 --- a/src/gui/painting/qregion_win.cpp +++ b/src/gui/painting/qregion_win.cpp @@ -39,27 +39,24 @@ ** ****************************************************************************/ +#include "qatomic.h" #include "qbitmap.h" #include "qbuffer.h" #include "qimage.h" #include "qpolygon.h" #include "qregion.h" #include "qt_windows.h" +#include "qpainterpath.h" QT_BEGIN_NAMESPACE +QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0 }; -/* - In Windows versions before Windows Vista CreateRectRgn - when called in a multi-threaded - environment - might return an invalid handle. This function works around this limitation - by verifying the handle with a quick GetRegionData() call and re-creates the region - if necessary. -*/ HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom) { const int tries = 10; for (int i = 0; i < tries; ++i) { - HRGN region; + HRGN region = 0; switch (type) { case QRegion::Rectangle: region = CreateRectRgn(left, top, right, bottom); @@ -80,497 +77,73 @@ HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, return 0; } -#ifndef Q_OS_WINCE -HRGN qt_tryCreatePolygonRegion(const QPolygon &a, Qt::FillRule fillRule) -{ - const int tries = 10; - for (int i = 0; i < tries; ++i) { - HRGN region = CreatePolygonRgn(reinterpret_cast<const POINT*>(a.data()), a.size(), - fillRule == Qt::OddEvenFill ? ALTERNATE : WINDING); - if (region) { - if (GetRegionData(region, 0, 0)) - return region; - else - DeleteObject(region); - } - } - return 0; -} -#endif - -QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0 }; - -QRegion::QRegion() - : d(&shared_empty) -{ - d->ref.ref(); -} - -#ifndef Q_OS_WINCE //implementation for WindowsCE in qregion_wce.cpp -QRegion::QRegion(const QRect &r, RegionType t) -{ - if (r.isEmpty()) { - d = &shared_empty; - d->ref.ref(); - } else { - d = new QRegionData; - d->ref = 1; - if (t == Rectangle) - d->rgn = qt_tryCreateRegion(t, r.left(), r.top(), r.x() + r.width(), r.y() + r.height()); - else if (t == Ellipse) { - // need to add 1 to width/height for the ellipse to have correct boundingrect. - d->rgn = qt_tryCreateRegion(t, r.x(), r.y(), r.x() + r.width() + 1, r.y() + r.height() + 1); - } - } -} -#endif - -#ifndef Q_OS_WINCE //implementation for WindowsCE in qregion_wce.cpp -QRegion::QRegion(const QPolygon &a, Qt::FillRule fillRule) -{ - if (a.size() < 3) { - d = &shared_empty; - d->ref.ref(); - } else { - d = new QRegionData; - d->ref = 1; - d->rgn = qt_tryCreatePolygonRegion(a, fillRule); - } -} -#endif - -QRegion::QRegion(const QRegion &r) -{ - d = r.d; - d->ref.ref(); -} - -HRGN qt_win_bitmapToRegion(const QBitmap& bitmap) -{ - HRGN region=0; - QImage image = bitmap.toImage(); - const int MAXRECT = 256; - struct RData { - RGNDATAHEADER header; - RECT rect[MAXRECT]; - }; - RData data; - -#define FlushSpans \ - { \ - data.header.dwSize = sizeof(RGNDATAHEADER); \ - data.header.iType = RDH_RECTANGLES; \ - data.header.nCount = n; \ - data.header.nRgnSize = 0; \ - data.header.rcBound.bottom = y; \ - HRGN r = ExtCreateRegion(0, \ - sizeof(RGNDATAHEADER)+n*sizeof(RECT),(RGNDATA*)&data); \ - if (region) { \ - CombineRgn(region, region, r, RGN_OR); \ - DeleteObject(r); \ - } else { \ - region = r; \ - } \ - data.header.rcBound.top = y; \ - } - -#define AddSpan \ - { \ - data.rect[n].left=prev1; \ - data.rect[n].top=y; \ - data.rect[n].right=x-1+1; \ - data.rect[n].bottom=y+1; \ - n++; \ - if (n == MAXRECT) { \ - FlushSpans \ - n=0; \ - } \ - } - - data.header.rcBound.top = 0; - data.header.rcBound.left = 0; - data.header.rcBound.right = image.width()-1; - int n = 0; - - int zero = 0x00; - - int x, y; - for (y = 0; y < image.height(); ++y) { - uchar *line = image.scanLine(y); - int w = image.width(); - uchar all=zero; - int prev1 = -1; - for (x = 0; x < w;) { - uchar byte = line[x/8]; - if (x > w - 8 || byte != all) { - for (int b = 8; b > 0 && x < w; --b) { - if (!(byte & 0x01) == !all) { - // More of the same - } else { - // A change. - if (all != zero) { - AddSpan; - all = zero; - } else { - prev1 = x; - all = ~zero; - } - } - byte >>= 1; - ++x; - } - } else { - x += 8; - } - } - if (all != zero) { - AddSpan; - } - } - if (n) { - FlushSpans; - } - - if (!region) { - // Surely there is some better way. - region = qt_tryCreateRegion(QRegion::Rectangle, 0,0,1,1); - CombineRgn(region, region, region, RGN_XOR); - } - return region; -} - -#ifndef Q_OS_WINCE //implementation for WindowsCE in qregion_wce.cpp -QRegion::QRegion(const QBitmap &bm) -{ - if (bm.isNull()) { - d = &shared_empty; - d->ref.ref(); - } else { - d = new QRegionData; - d->ref = 1; - d->rgn = qt_win_bitmapToRegion(bm); - } -} -#endif - -void QRegion::cleanUp(QRegion::QRegionData *x) -{ - if (x->rgn) - DeleteObject(x->rgn); - delete x; -} - -QRegion::~QRegion() -{ - if (!d->ref.deref()) - cleanUp(d); -} - -QRegion &QRegion::operator=(const QRegion &r) -{ - r.d->ref.ref(); - if (!d->ref.deref()) - cleanUp(d); - d = r.d; - return *this; -} - - -QRegion QRegion::copy() const -{ - QRegion r; - QRegionData *x = new QRegionData; - x->ref = 1; - if (d->rgn) { - x->rgn = qt_tryCreateRegion(QRegion::Rectangle, 0, 0, 2, 2); - CombineRgn(x->rgn, d->rgn, 0, RGN_COPY); - } else { - x->rgn = 0; - } - if (!r.d->ref.deref()) - cleanUp(r.d); - r.d = x; - return r; -} - -bool QRegion::isEmpty() const -{ - return (d == &shared_empty || boundingRect().isEmpty()); -} - - -bool QRegion::contains(const QPoint &p) const -{ - return d->rgn ? PtInRegion(d->rgn, p.x(), p.y()) : false; -} - -bool QRegion::contains(const QRect &r) const -{ - if (!d->rgn) - return false; - RECT rect; - SetRect(&rect, r.left(), r.top(), r.right(), r.bottom()); - return RectInRegion(d->rgn, &rect); -} - - -void QRegion::translate(int dx, int dy) -{ - if (!d->rgn || (dx == 0 && dy == 0)) - return; - detach(); - OffsetRgn(d->rgn, dx, dy); -} - - -#define RGN_NOP -1 - -// Duplicates of those in qregion.cpp -#define QRGN_OR 6 -#define QRGN_AND 7 -#define QRGN_SUB 8 -#define QRGN_XOR 9 - -/* - Performs the actual OR, AND, SUB and XOR operation between regions. - Sets the resulting region handle to 0 to indicate an empty region. -*/ - -QRegion QRegion::winCombine(const QRegion &r, int op) const +QRegion qt_region_from_HRGN(HRGN rgn) { - int both=RGN_NOP, - left=RGN_NOP, - right=RGN_NOP; - switch (op) { - case QRGN_OR: - both = RGN_OR; - left = right = RGN_COPY; - break; - case QRGN_AND: - both = RGN_AND; - break; - case QRGN_SUB: - both = RGN_DIFF; - left = RGN_COPY; - break; - case QRGN_XOR: - both = RGN_XOR; - left = right = RGN_COPY; - break; - default: - qWarning("QRegion: Internal error in winCombine"); - } - - int allCombineRgnResults = NULLREGION; - QRegion result; - result.detach(); - result.d->rgn = qt_tryCreateRegion(QRegion::Rectangle, 0, 0, 0, 0); - if (d->rgn && r.d->rgn) - allCombineRgnResults = CombineRgn(result.d->rgn, d->rgn, r.d->rgn, both); - else if (d->rgn && left != RGN_NOP) - allCombineRgnResults = CombineRgn(result.d->rgn, d->rgn, d->rgn, left); - else if (r.d->rgn && right != RGN_NOP) - allCombineRgnResults = CombineRgn(result.d->rgn, r.d->rgn, r.d->rgn, right); - - if (allCombineRgnResults == NULLREGION || allCombineRgnResults == ERROR) - result = QRegion(); - - //##### do not delete this. A null pointer is different from an empty region in SelectClipRgn in qpainter_win! (M) -// if (allCombineRgnResults == NULLREGION) { -// if (result.data->rgn) -// DeleteObject(result.data->rgn); -// result.data->rgn = 0; // empty region -// } - return result; -} - -QRegion QRegion::unite(const QRegion &r) const -{ - if (!d->rgn) - return r; - if (!r.d->rgn) - return *this; - return winCombine(r, QRGN_OR); -} - -QRegion QRegion::unite(const QRect &r) const -{ - return unite(QRegion(r)); -} - -QRegion QRegion::intersect(const QRegion &r) const -{ - if (!r.d->rgn || !d->rgn) - return QRegion(); - return winCombine(r, QRGN_AND); -} - -QRegion QRegion::subtract(const QRegion &r) const -{ - if (!r.d->rgn || !d->rgn) - return *this; - return winCombine(r, QRGN_SUB); -} - -QRegion QRegion::eor(const QRegion &r) const -{ - if (!d->rgn) - return r; - if (!r.d->rgn) - return *this; - return winCombine(r, QRGN_XOR); -} - - -QRect QRegion::boundingRect() const -{ - if (!d->rgn) - return QRect(); - RECT r; - if (GetRgnBox(d->rgn, &r) == NULLREGION) - return QRect(); - else - return QRect(r.left, r.top, r.right - r.left, r.bottom - r.top); -} - -QVector<QRect> QRegion::rects() const -{ - if (d->rgn == 0) - return QVector<QRect>(); - - int numBytes = GetRegionData(d->rgn, 0, 0); + int numBytes = GetRegionData(rgn, 0, 0); if (numBytes == 0) - return QVector<QRect>(); + return QRegion(); char *buf = new char[numBytes]; if (buf == 0) - return QVector<QRect>(); + return QRegion(); RGNDATA *rd = reinterpret_cast<RGNDATA*>(buf); - if (GetRegionData(d->rgn, numBytes, rd) == 0) { + if (GetRegionData(rgn, numBytes, rd) == 0) { delete [] buf; - return QVector<QRect>(); + return QRegion(); } - QVector<QRect> a(rd->rdh.nCount); + QRegion region; RECT *r = reinterpret_cast<RECT*>(rd->Buffer); - for (int i = 0; i < a.size(); ++i) { - a[i].setCoords(r->left, r->top, r->right - 1, r->bottom - 1); + for (uint i = 0; i < rd->rdh.nCount; ++i) { + QRect rect; + rect.setCoords(r->left, r->top, r->right - 1, r->bottom - 1); ++r; + region |= rect; } delete [] buf; - return a; -} - -void QRegion::setRects(const QRect *rects, int num) -{ - *this = QRegion(); - if (!rects || num == 0 || (num == 1 && rects->isEmpty())) - return; - for (int i = 0; i < num; ++i) - *this |= rects[i]; -} - -int QRegion::numRects() const -{ - if (d->rgn == 0) - return 0; - - const int numBytes = GetRegionData(d->rgn, 0, 0); - if (numBytes == 0) - return 0; - - char *buf = new char[numBytes]; - if (buf == 0) - return 0; - - RGNDATA *rd = reinterpret_cast<RGNDATA*>(buf); - if (GetRegionData(d->rgn, numBytes, rd) == 0) { - delete[] buf; - return 0; - } - - const int n = rd->rdh.nCount; - delete[] buf; - return n; + return region; } -bool QRegion::operator==(const QRegion &r) const +void qt_win_dispose_rgn(HRGN r) { - if (d == r.d) - return true; - if ((d->rgn == 0) ^ (r.d->rgn == 0)) // one is empty, not both - return false; - return d->rgn == 0 ? true // both empty - : EqualRgn(d->rgn, r.d->rgn); // both non-empty + if (r) + DeleteObject(r); } -QRegion& QRegion::operator+=(const QRegion &r) +static void qt_add_rect(HRGN &winRegion, QRect r) { - if (!r.d->rgn) - return *this; - - if (!d->rgn) { - *this = r; - return *this; + HRGN rgn = CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height()); + if (rgn) { + HRGN dest = CreateRectRgn(0,0,0,0); + int result = CombineRgn(dest, winRegion, rgn, RGN_OR); + if (result) { + DeleteObject(winRegion); + winRegion = dest; + } + DeleteObject(rgn); } - - detach(); - - int result; - result = CombineRgn(d->rgn, d->rgn, r.d->rgn, RGN_OR); - if (result == NULLREGION || result == ERROR) - *this = QRegion(); - - return *this; -} - -QRegion& QRegion::operator-=(const QRegion &r) -{ - if (!r.d->rgn || !d->rgn) - return *this; - - detach(); - - int result; - result = CombineRgn(d->rgn, d->rgn, r.d->rgn, RGN_DIFF); - if (result == NULLREGION || result == ERROR) - *this = QRegion(); - - return *this; } -QRegion& QRegion::operator&=(const QRegion &r) +void QRegion::ensureHandle() const { - if (!d->rgn) - return *this; - - if (!r.d->rgn) { - *this = QRegion(); - return *this; + if (d->rgn) + DeleteObject(d->rgn); + d->rgn = CreateRectRgn(0,0,0,0); + if (d->qt_rgn) { + if (d->qt_rgn->numRects == 1) { + QRect r = d->qt_rgn->extents; + qt_add_rect(d->rgn, r); + return; + } + for (int i = 0;i < d->qt_rgn->numRects;i++) { + QRect r = d->qt_rgn->rects.at(i); + qt_add_rect(d->rgn, r); + } } - - detach(); - - int result; - result = CombineRgn(d->rgn, d->rgn, r.d->rgn, RGN_AND); - if (result == NULLREGION || result == ERROR) - *this = QRegion(); - - return *this; -} - -bool qt_region_strictContains(const QRegion ®ion, const QRect &rect) -{ - Q_UNUSED(region); - Q_UNUSED(rect); - return false; } -void QRegion::ensureHandle() const -{ -} QT_END_NAMESPACE diff --git a/src/gui/painting/qregion_wince.cpp b/src/gui/painting/qregion_wince.cpp deleted file mode 100644 index 39d19b0..0000000 --- a/src/gui/painting/qregion_wince.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qatomic.h" -#include "qbitmap.h" -#include "qbuffer.h" -#include "qimage.h" -#include "qpolygon.h" -#include "qregion.h" -#include "qt_windows.h" -#include "qpainterpath.h" -#include "qguifunctions_wince.h" - -QT_BEGIN_NAMESPACE - -QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0 }; - -HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom) -{ - const int tries = 10; - for (int i = 0; i < tries; ++i) { - HRGN region; - switch (type) { - case QRegion::Rectangle: - region = CreateRectRgn(left, top, right, bottom); - break; - case QRegion::Ellipse: -#ifndef Q_OS_WINCE - region = CreateEllipticRgn(left, top, right, bottom); -#endif - break; - } - if (region) { - if (GetRegionData(region, 0, 0)) - return region; - else - DeleteObject(region); - } - } - return 0; -} - -void qt_win_dispose_rgn(HRGN r) -{ - if (r) - DeleteObject(r); -} - -static void qt_add_rect(HRGN &winRegion, QRect r) -{ - HRGN rgn = CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height()); - if (rgn) { - HRGN dest = CreateRectRgn(0,0,0,0); - int result = CombineRgn(dest, winRegion, rgn, RGN_OR); - if (result) { - DeleteObject(winRegion); - winRegion = dest; - } - } -} - -void QRegion::ensureHandle() const -{ - if (d->rgn) - DeleteObject(d->rgn); - d->rgn = CreateRectRgn(0,0,0,0); - if (d->qt_rgn) { - if (d->qt_rgn->numRects == 1) { - QRect r = d->qt_rgn->extents; - qt_add_rect(d->rgn, r); - return; - } - for (int i = 0;i < d->qt_rgn->numRects;i++) { - QRect r = d->qt_rgn->rects.at(i); - qt_add_rect(d->rgn, r); - } - } -} - - -QT_END_NAMESPACE diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp index 94f5e2e..196a365 100644 --- a/src/gui/painting/qstroker.cpp +++ b/src/gui/painting/qstroker.cpp @@ -763,7 +763,7 @@ template <class Iterator> bool qt_stroke_side(Iterator *it, qreal qt_t_for_arc_angle(qreal angle) { - if (qFuzzyCompare(angle + 1, qreal(1))) + if (qFuzzyIsNull(angle)) return 0; if (qFuzzyCompare(angle, qreal(90))) @@ -904,13 +904,13 @@ QPointF qt_curves_for_arc(const QRectF &rect, qreal startAngle, qreal sweepLengt } // avoid empty start segment - if (qFuzzyCompare(startT, qreal(1))) { + if (qFuzzyIsNull(startT - qreal(1))) { startT = 0; startSegment += delta; } // avoid empty end segment - if (qFuzzyCompare(endT + 1, qreal(1))) { + if (qFuzzyIsNull(endT)) { endT = 1; endSegment -= delta; } @@ -918,8 +918,8 @@ QPointF qt_curves_for_arc(const QRectF &rect, qreal startAngle, qreal sweepLengt startT = qt_t_for_arc_angle(startT * 90); endT = qt_t_for_arc_angle(endT * 90); - const bool splitAtStart = !qFuzzyCompare(startT + 1, qreal(1)); - const bool splitAtEnd = !qFuzzyCompare(endT, qreal(1)); + const bool splitAtStart = !qFuzzyIsNull(startT); + const bool splitAtEnd = !qFuzzyIsNull(endT - qreal(1)); const int end = endSegment + delta; @@ -1021,7 +1021,7 @@ void QDashStroker::processCurrentSubpath() longestLength = dashes[i]; } - if (qFuzzyCompare(sumLength + 1, qreal(1))) + if (qFuzzyIsNull(sumLength)) return; Q_ASSERT(dashCount > 0); diff --git a/src/gui/painting/qstylepainter.cpp b/src/gui/painting/qstylepainter.cpp index ce78200..7b83527 100644 --- a/src/gui/painting/qstylepainter.cpp +++ b/src/gui/painting/qstylepainter.cpp @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE elements inside a widget. \ingroup appearance - \ingroup multimedia + \ingroup painting QStylePainter extends QPainter with a set of high-level \c draw...() functions implemented on top of QStyle's API. The diff --git a/src/gui/painting/qtessellator.cpp b/src/gui/painting/qtessellator.cpp index 10c7b32..0fa1d51 100644 --- a/src/gui/painting/qtessellator.cpp +++ b/src/gui/painting/qtessellator.cpp @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE #ifdef DEBUG #define QDEBUG qDebug #else -#define QDEBUG if (1); else qDebug +#define QDEBUG if (1){} else qDebug #endif static const bool emit_clever = true; @@ -406,9 +406,9 @@ void QTessellatorPrivate::Scanline::init(int maxActiveEdges) if (!edges || maxActiveEdges > default_alloc) { max_edges = maxActiveEdges; int s = qMax(maxActiveEdges + 1, default_alloc + 1); - edges = (Edge **)realloc(edges, s*sizeof(Edge *)); - edge_table = (Edge *)realloc(edge_table, s*sizeof(Edge)); - old = (Edge **)realloc(old, s*sizeof(Edge *)); + edges = q_check_ptr((Edge **)realloc(edges, s*sizeof(Edge *))); + edge_table = q_check_ptr((Edge *)realloc(edge_table, s*sizeof(Edge))); + old = q_check_ptr((Edge **)realloc(old, s*sizeof(Edge *))); } size = 0; old_size = 0; @@ -566,8 +566,8 @@ void QTessellatorPrivate::Vertices::init(int maxVertices) { if (!storage || maxVertices > allocated) { int size = qMax((int)default_alloc, maxVertices); - storage = (Vertex *)realloc(storage, size*sizeof(Vertex)); - sorted = (Vertex **)realloc(sorted, size*sizeof(Vertex *)); + storage = q_check_ptr((Vertex *)realloc(storage, size*sizeof(Vertex))); + sorted = q_check_ptr((Vertex **)realloc(sorted, size*sizeof(Vertex *))); allocated = maxVertices; } } @@ -703,7 +703,6 @@ struct QCoincidingEdge { } }; - static void cancelEdges(QCoincidingEdge &e1, QCoincidingEdge &e2) { if (e1.before) { @@ -740,7 +739,7 @@ void QTessellatorPrivate::cancelCoincidingEdges() if (testListSize > tlSize - 2) { tlSize = qMax(tlSize*2, 16); - tl = (QCoincidingEdge *)realloc(tl, tlSize*sizeof(QCoincidingEdge)); + tl = q_check_ptr((QCoincidingEdge *)realloc(tl, tlSize*sizeof(QCoincidingEdge))); } if (n->flags & (LineBeforeStarts|LineBeforeHorizontal)) { tl[testListSize].start = n; @@ -1081,7 +1080,7 @@ void QTessellatorPrivate::addIntersection(const Edge *e1, const Edge *e2) yi = y; } QDEBUG() << " between edges " << e1->edge << "and" << e2->edge << "at point (" - << Q27Dot5ToDouble(yi) << ")"; + << Q27Dot5ToDouble(yi) << ')'; Intersection i1; i1.y = yi; @@ -1174,7 +1173,7 @@ void QTessellatorPrivate::addIntersections() for (int i = 0; i < scanline.size; ++i) { Edge *e = scanline.edges[i]; QDEBUG() << " " << i << e->edge << "isect=(" << e->intersect_left << e->intersect_right - << ")"; + << ')'; } #endif @@ -1240,8 +1239,8 @@ QRectF QTessellator::tessellate(const QPointF *points, int nPoints) QDEBUG() << " " << i << ": " << "point=" << d->vertices.position(d->vertices.sorted[i]) << "flags=" << d->vertices.sorted[i]->flags - << "pos=(" << Q27Dot5ToDouble(d->vertices.sorted[i]->x) << "/" - << Q27Dot5ToDouble(d->vertices.sorted[i]->y) << ")"; + << "pos=(" << Q27Dot5ToDouble(d->vertices.sorted[i]->x) << '/' + << Q27Dot5ToDouble(d->vertices.sorted[i]->y) << ')'; } #endif @@ -1271,9 +1270,9 @@ QRectF QTessellator::tessellate(const QPointF *points, int nPoints) for (int i = 0; i < d->scanline.size; ++i) { QDEBUG() << " " << d->scanline.edges[i]->edge << "p0= (" << Q27Dot5ToDouble(d->scanline.edges[i]->v0->x) - << "/" << Q27Dot5ToDouble(d->scanline.edges[i]->v0->y) + << '/' << Q27Dot5ToDouble(d->scanline.edges[i]->v0->y) << ") p1= (" << Q27Dot5ToDouble(d->scanline.edges[i]->v1->x) - << "/" << Q27Dot5ToDouble(d->scanline.edges[i]->v1->y) << ")" + << '/' << Q27Dot5ToDouble(d->scanline.edges[i]->v1->y) << ')' << "x=" << Q27Dot5ToDouble(d->scanline.edges[i]->positionAt(d->y)) << "isLeftOfNext=" << ((i < d->scanline.size - 1) @@ -1436,7 +1435,7 @@ void QTessellator::tessellateRect(const QPointF &a_, const QPointF &b_, qreal wi QPointF perp(pb.y() - pa.y(), pa.x() - pb.x()); qreal length = qSqrt(perp.x() * perp.x() + perp.y() * perp.y()); - if (qFuzzyCompare(length + 1, static_cast<qreal>(1))) + if (qFuzzyIsNull(length)) return; // need the half of the width diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index 444231d..ee523b8 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -157,6 +157,46 @@ void QTextureGlyphCache::populate(const QTextItemInt &ti, } +QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g) const +{ +#if defined(Q_WS_X11) + if (m_transform.type() > QTransform::TxTranslate) { + QFontEngineFT::GlyphFormat format = QFontEngineFT::Format_None; + QImage::Format imageFormat = QImage::Format_Invalid; + switch (m_type) { + case Raster_RGBMask: + format = QFontEngineFT::Format_A32; + imageFormat = QImage::Format_RGB32; + break; + case Raster_A8: + format = QFontEngineFT::Format_A8; + imageFormat = QImage::Format_Indexed8; + break; + case Raster_Mono: + format = QFontEngineFT::Format_Mono; + imageFormat = QImage::Format_Mono; + break; + }; + + QFontEngineFT *ft = static_cast<QFontEngineFT*> (m_current_textitem->fontEngine); + QFontEngineFT::QGlyphSet *gset = ft->loadTransformedGlyphSet(m_transform); + + if (gset && ft->loadGlyphs(gset, &g, 1, format)) { + QFontEngineFT::Glyph *glyph = gset->glyph_data.value(g); + const int bytesPerLine = (format == QFontEngineFT::Format_Mono ? ((glyph->width + 31) & ~31) >> 3 + : (glyph->width + 3) & ~3); + return QImage(glyph->data, glyph->width, glyph->height, bytesPerLine, imageFormat); + } + } else +#endif + if (m_type == QFontEngineGlyphCache::Raster_RGBMask) + return m_current_textitem->fontEngine->alphaRGBMapForGlyph(g, glyphMargin(), m_transform); + else + return m_current_textitem->fontEngine->alphaMapForGlyph(g, m_transform); + + return QImage(); +} + /************************************************************************ * QImageTextureGlyphCache */ @@ -198,34 +238,7 @@ int QImageTextureGlyphCache::glyphMargin() const void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g) { - QImage mask; -#if defined(Q_WS_X11) - if (m_transform.type() > QTransform::TxTranslate) { - QFontEngineFT::GlyphFormat format = QFontEngineFT::Format_None; - switch (m_type) { - case Raster_RGBMask: - format = QFontEngineFT::Format_A32; break; - case Raster_A8: - format = QFontEngineFT::Format_A8; break; - case Raster_Mono: - format = QFontEngineFT::Format_Mono; break; - }; - - QFontEngineFT *ft = static_cast<QFontEngineFT*> (m_current_textitem->fontEngine); - QFontEngineFT::QGlyphSet *gset = ft->loadTransformedGlyphSet(m_transform); - - if (gset && ft->loadGlyphs(gset, &g, 1, format)) { - QFontEngineFT::Glyph *glyph = gset->glyph_data.value(g); - const int bytesPerLine = (format == QFontEngineFT::Format_Mono ? ((glyph->width + 31) & ~31) >> 3 - : (glyph->width + 3) & ~3); - mask = QImage(glyph->data, glyph->width, glyph->height, bytesPerLine, m_image.format()); - } - } else -#endif - if (m_type == QFontEngineGlyphCache::Raster_RGBMask) - mask = m_current_textitem->fontEngine->alphaRGBMapForGlyph(g, glyphMargin(), m_transform); - else - mask = m_current_textitem->fontEngine->alphaMapForGlyph(g, m_transform); + QImage mask = textureMapForGlyph(g); #ifdef CACHE_DEBUG printf("fillTexture of %dx%d at %d,%d in the cache of %dx%d\n", c.w, c.h, c.x, c.y, m_image.width(), m_image.height()); diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h index 1035ed1..f14c790 100644 --- a/src/gui/painting/qtextureglyphcache_p.h +++ b/src/gui/painting/qtextureglyphcache_p.h @@ -60,6 +60,10 @@ #include <private/qfontengineglyphcache_p.h> +#if defined(Q_OS_VXWORKS) && defined(m_type) +# undef m_type +#endif + struct glyph_metrics_t; typedef unsigned int glyph_t; @@ -108,6 +112,8 @@ public: QHash<glyph_t, Coord> coords; + QImage textureMapForGlyph(glyph_t g) const; + protected: const QTextItemInt *m_current_textitem; @@ -116,11 +122,10 @@ protected: int m_cx; // current x int m_cy; // current y QFontEngineGlyphCache::Type m_type; - }; -class Q_GUI_EXPORT QImageTextureGlyphCache : public QTextureGlyphCache +class QImageTextureGlyphCache : public QTextureGlyphCache { public: QImageTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix) diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index 0da0a15..4f27596 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -48,11 +48,15 @@ #include "qvariant.h" #include <qmath.h> +#include <private/qbezier_p.h> + QT_BEGIN_NAMESPACE #define Q_NEAR_CLIP 0.000001 - +#ifdef MAP +# undef MAP +#endif #define MAP(x, y, nx, ny) \ do { \ qreal FX_ = x; \ @@ -76,7 +80,9 @@ QT_BEGIN_NAMESPACE nx = affine._m11 * FX_ + affine._m21 * FY_ + affine._dx; \ ny = affine._m12 * FX_ + affine._m22 * FY_ + affine._dy; \ if (t == TxProject) { \ - qreal w = 1./(m_13 * FX_ + m_23 * FY_ + m_33); \ + qreal w = (m_13 * FX_ + m_23 * FY_ + m_33); \ + if (w < qreal(Q_NEAR_CLIP)) w = qreal(Q_NEAR_CLIP); \ + w = 1./w; \ nx *= w; \ ny *= w; \ } \ @@ -87,7 +93,7 @@ QT_BEGIN_NAMESPACE \class QTransform \brief The QTransform class specifies 2D transformations of a coordinate system. \since 4.3 - \ingroup multimedia + \ingroup painting A transformation specifies how to translate, scale, shear, rotate or project the coordinate system, and is typically used when @@ -97,7 +103,7 @@ QT_BEGIN_NAMESPACE allowing perspective transformations. QTransform's toAffine() method allows casting QTransform to QMatrix. If a perspective transformation has been specified on the matrix, then the - conversion to an affine QMatrix will cause loss of data. + conversion will cause loss of data. QTransform is the recommended transformation class in Qt. @@ -121,11 +127,13 @@ QT_BEGIN_NAMESPACE which returns true if the matrix is non-singular (i.e. AB = BA = I). The inverted() function returns an inverted copy of \e this matrix if it is invertible (otherwise it returns the identity - matrix). In addition, QTransform provides the det() function - returning the matrix's determinant. + matrix), and adjoint() returns the matrix's classical adjoint. + In addition, QTransform provides the determinant() function which + returns the matrix's determinant. - Finally, the QTransform class supports matrix multiplication, and - objects of the class can be streamed as well as compared. + Finally, the QTransform class supports matrix multiplication, addition + and subtraction, and objects of the class can be streamed as well + as compared. \tableofcontents @@ -187,7 +195,7 @@ QT_BEGIN_NAMESPACE The various matrix elements can be set when constructing the matrix, or by using the setMatrix() function later on. They can also be manipulated using the translate(), rotate(), scale() and - shear() convenience functions, The currently set values can be + shear() convenience functions. The currently set values can be retrieved using the m11(), m12(), m13(), m21(), m22(), m23(), m31(), m32(), m33(), dx() and dy() functions. @@ -200,9 +208,9 @@ QT_BEGIN_NAMESPACE to 0) mapping a point to itself. Shearing is controlled by \c m12 and \c m21. Setting these elements to values different from zero will twist the coordinate system. Rotation is achieved by - carefully setting both the shearing factors and the scaling - factors. Perspective transformation is achieved by carefully setting - both the projection factors and the scaling factors. + setting both the shearing factors and the scaling factors. Perspective + transformation is achieved by setting both the projection factors and + the scaling factors. Here's the combined transformations example using basic matrix operations: @@ -230,6 +238,11 @@ QT_BEGIN_NAMESPACE */ /*! + \fn QTransform::QTransform(Qt::Initialization) + \internal +*/ + +/*! Constructs an identity matrix. All elements are set to zero except \c m11 and \c m22 (specifying @@ -238,11 +251,11 @@ QT_BEGIN_NAMESPACE \sa reset() */ QTransform::QTransform() - : m_13(0), m_23(0), m_33(1) + : affine(true) + , m_13(0), m_23(0), m_33(1) , m_type(TxNone) , m_dirty(TxNone) { - } /*! @@ -256,12 +269,11 @@ QTransform::QTransform() QTransform::QTransform(qreal h11, qreal h12, qreal h13, qreal h21, qreal h22, qreal h23, qreal h31, qreal h32, qreal h33) - : affine(h11, h12, h21, h22, h31, h32), - m_13(h13), m_23(h23), m_33(h33) + : affine(h11, h12, h21, h22, h31, h32, true) + , m_13(h13), m_23(h23), m_33(h33) , m_type(TxNone) , m_dirty(TxProject) { - } /*! @@ -273,12 +285,11 @@ QTransform::QTransform(qreal h11, qreal h12, qreal h13, */ QTransform::QTransform(qreal h11, qreal h12, qreal h21, qreal h22, qreal dx, qreal dy) - : affine(h11, h12, h21, h22, dx, dy), - m_13(0), m_23(0), m_33(1) + : affine(h11, h12, h21, h22, dx, dy, true) + , m_13(0), m_23(0), m_33(1) , m_type(TxNone) , m_dirty(TxShear) { - } /*! @@ -289,12 +300,11 @@ QTransform::QTransform(qreal h11, qreal h12, qreal h21, and 1 respectively. */ QTransform::QTransform(const QMatrix &mtx) - : affine(mtx), + : affine(mtx._m11, mtx._m12, mtx._m21, mtx._m22, mtx._dx, mtx._dy, true), m_13(0), m_23(0), m_33(1) , m_type(TxNone) , m_dirty(TxShear) { - } /*! @@ -317,7 +327,7 @@ QTransform QTransform::adjoint() const return QTransform(h11, h12, h13, h21, h22, h23, - h31, h32, h33); + h31, h32, h33, true); } /*! @@ -327,7 +337,7 @@ QTransform QTransform::transposed() const { QTransform t(affine._m11, affine._m21, affine._dx, affine._m12, affine._m22, affine._dy, - m_13, m_23, m_33); + m_13, m_23, m_33, true); t.m_type = m_type; t.m_dirty = m_dirty; return t; @@ -345,11 +355,10 @@ QTransform QTransform::transposed() const */ QTransform QTransform::inverted(bool *invertible) const { - QTransform invert; + QTransform invert(true); bool inv = true; - qreal det; - switch(type()) { + switch(inline_type()) { case TxNone: break; case TxTranslate: @@ -357,11 +366,11 @@ QTransform QTransform::inverted(bool *invertible) const invert.affine._dy = -affine._dy; break; case TxScale: - inv = !qFuzzyCompare(affine._m11 + 1, 1); - inv &= !qFuzzyCompare(affine._m22 + 1, 1); + inv = !qFuzzyIsNull(affine._m11); + inv &= !qFuzzyIsNull(affine._m22); if (inv) { - invert.affine._m11 = 1 / affine._m11; - invert.affine._m22 = 1 / affine._m22; + invert.affine._m11 = 1. / affine._m11; + invert.affine._m22 = 1. / affine._m22; invert.affine._dx = -affine._dx * invert.affine._m11; invert.affine._dy = -affine._dy * invert.affine._m22; } @@ -372,8 +381,8 @@ QTransform QTransform::inverted(bool *invertible) const break; default: // general case - det = determinant(); - inv = !qFuzzyCompare(det + 1, 1); + qreal det = determinant(); + inv = !qFuzzyIsNull(det); if (inv) invert = adjoint() / det; break; @@ -397,12 +406,12 @@ QTransform QTransform::inverted(bool *invertible) const \sa setMatrix() */ -QTransform & QTransform::translate(qreal dx, qreal dy) +QTransform &QTransform::translate(qreal dx, qreal dy) { if (dx == 0 && dy == 0) return *this; - switch(type()) { + switch(inline_type()) { case TxNone: affine._dx = dx; affine._dy = dy; @@ -424,7 +433,8 @@ QTransform & QTransform::translate(qreal dx, qreal dy) affine._dy += dy*affine._m22 + dx*affine._m12; break; } - m_dirty |= TxTranslate; + if (m_dirty < TxTranslate) + m_dirty = TxTranslate; return *this; } @@ -437,11 +447,12 @@ QTransform & QTransform::translate(qreal dx, qreal dy) */ QTransform QTransform::fromTranslate(qreal dx, qreal dy) { - QTransform transform(1, 0, 0, 1, dx, dy); + QTransform transform(1, 0, 0, 0, 1, 0, dx, dy, 1, true); if (dx == 0 && dy == 0) - transform.m_dirty = TxNone; + transform.m_type = TxNone; else - transform.m_dirty = TxTranslate; + transform.m_type = TxTranslate; + transform.m_dirty = TxNone; return transform; } @@ -456,7 +467,7 @@ QTransform & QTransform::scale(qreal sx, qreal sy) if (sx == 1 && sy == 1) return *this; - switch(type()) { + switch(inline_type()) { case TxNone: case TxTranslate: affine._m11 = sx; @@ -476,7 +487,8 @@ QTransform & QTransform::scale(qreal sx, qreal sy) affine._m22 *= sy; break; } - m_dirty |= TxScale; + if (m_dirty < TxScale) + m_dirty = TxScale; return *this; } @@ -489,11 +501,12 @@ QTransform & QTransform::scale(qreal sx, qreal sy) */ QTransform QTransform::fromScale(qreal sx, qreal sy) { - QTransform transform(sx, 0, 0, sy, 0, 0); - if (sx == 1 && sy == 1) - transform.m_dirty = TxNone; + QTransform transform(sx, 0, 0, 0, sy, 0, 0, 0, 1, true); + if (sx == 1. && sy == 1.) + transform.m_type = TxNone; else - transform.m_dirty = TxScale; + transform.m_type = TxScale; + transform.m_dirty = TxNone; return transform; } @@ -505,7 +518,10 @@ QTransform QTransform::fromScale(qreal sx, qreal sy) */ QTransform & QTransform::shear(qreal sh, qreal sv) { - switch(type()) { + if (sh == 0 && sv == 0) + return *this; + + switch(inline_type()) { case TxNone: case TxTranslate: affine._m12 = sv; @@ -533,7 +549,8 @@ QTransform & QTransform::shear(qreal sh, qreal sv) break; } } - m_dirty |= TxShear; + if (m_dirty < TxShear) + m_dirty = TxShear; return *this; } @@ -574,7 +591,7 @@ QTransform & QTransform::rotate(qreal a, Qt::Axis axis) } if (axis == Qt::ZAxis) { - switch(type()) { + switch(inline_type()) { case TxNone: case TxTranslate: affine._m11 = cosa; @@ -609,7 +626,8 @@ QTransform & QTransform::rotate(qreal a, Qt::Axis axis) break; } } - m_dirty |= TxRotate; + if (m_dirty < TxRotate) + m_dirty = TxRotate; } else { QTransform result; if (axis == Qt::YAxis) { @@ -646,7 +664,7 @@ QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis) qreal cosa = qCos(a); if (axis == Qt::ZAxis) { - switch(type()) { + switch(inline_type()) { case TxNone: case TxTranslate: affine._m11 = cosa; @@ -681,7 +699,8 @@ QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis) break; } } - m_dirty |= TxRotate; + if (m_dirty < TxRotate) + m_dirty = TxRotate; } else { QTransform result; if (axis == Qt::YAxis) { @@ -704,11 +723,15 @@ QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis) */ bool QTransform::operator==(const QTransform &o) const { -#define qFZ qFuzzyCompare - return qFZ(affine._m11, o.affine._m11) && qFZ(affine._m12, o.affine._m12) && qFZ(m_13, o.m_13) - && qFZ(affine._m21, o.affine._m21) && qFZ(affine._m22, o.affine._m22) && qFZ(m_23, o.m_23) - && qFZ(affine._dx, o.affine._dx) && qFZ(affine._dy, o.affine._dy) && qFZ(m_33, o.m_33); -#undef qFZ + return affine._m11 == o.affine._m11 && + affine._m12 == o.affine._m12 && + affine._m21 == o.affine._m21 && + affine._m22 == o.affine._m22 && + affine._dx == o.affine._dx && + affine._dy == o.affine._dy && + m_13 == o.m_13 && + m_23 == o.m_23 && + m_33 == o.m_33; } /*! @@ -730,11 +753,11 @@ bool QTransform::operator!=(const QTransform &o) const */ QTransform & QTransform::operator*=(const QTransform &o) { - const TransformationType otherType = o.type(); + const TransformationType otherType = o.inline_type(); if (otherType == TxNone) return *this; - const TransformationType thisType = type(); + const TransformationType thisType = inline_type(); if (thisType == TxNone) return operator=(o); @@ -812,9 +835,77 @@ QTransform & QTransform::operator*=(const QTransform &o) */ QTransform QTransform::operator*(const QTransform &m) const { - QTransform result = *this; - result *= m; - return result; + const TransformationType otherType = m.inline_type(); + if (otherType == TxNone) + return *this; + + const TransformationType thisType = inline_type(); + if (thisType == TxNone) + return m; + + QTransform t(true); + TransformationType type = qMax(thisType, otherType); + switch(type) { + case TxNone: + break; + case TxTranslate: + t.affine._dx = affine._dx + m.affine._dx; + t.affine._dy += affine._dy + m.affine._dy; + break; + case TxScale: + { + qreal m11 = affine._m11*m.affine._m11; + qreal m22 = affine._m22*m.affine._m22; + + qreal m31 = affine._dx*m.affine._m11 + m.affine._dx; + qreal m32 = affine._dy*m.affine._m22 + m.affine._dy; + + t.affine._m11 = m11; + t.affine._m22 = m22; + t.affine._dx = m31; t.affine._dy = m32; + break; + } + case TxRotate: + case TxShear: + { + qreal m11 = affine._m11*m.affine._m11 + affine._m12*m.affine._m21; + qreal m12 = affine._m11*m.affine._m12 + affine._m12*m.affine._m22; + + qreal m21 = affine._m21*m.affine._m11 + affine._m22*m.affine._m21; + qreal m22 = affine._m21*m.affine._m12 + affine._m22*m.affine._m22; + + qreal m31 = affine._dx*m.affine._m11 + affine._dy*m.affine._m21 + m.affine._dx; + qreal m32 = affine._dx*m.affine._m12 + affine._dy*m.affine._m22 + m.affine._dy; + + t.affine._m11 = m11; t.affine._m12 = m12; + t.affine._m21 = m21; t.affine._m22 = m22; + t.affine._dx = m31; t.affine._dy = m32; + break; + } + case TxProject: + { + qreal m11 = affine._m11*m.affine._m11 + affine._m12*m.affine._m21 + m_13*m.affine._dx; + qreal m12 = affine._m11*m.affine._m12 + affine._m12*m.affine._m22 + m_13*m.affine._dy; + qreal m13 = affine._m11*m.m_13 + affine._m12*m.m_23 + m_13*m.m_33; + + qreal m21 = affine._m21*m.affine._m11 + affine._m22*m.affine._m21 + m_23*m.affine._dx; + qreal m22 = affine._m21*m.affine._m12 + affine._m22*m.affine._m22 + m_23*m.affine._dy; + qreal m23 = affine._m21*m.m_13 + affine._m22*m.m_23 + m_23*m.m_33; + + qreal m31 = affine._dx*m.affine._m11 + affine._dy*m.affine._m21 + m_33*m.affine._dx; + qreal m32 = affine._dx*m.affine._m12 + affine._dy*m.affine._m22 + m_33*m.affine._dy; + qreal m33 = affine._dx*m.m_13 + affine._dy*m.m_23 + m_33*m.m_33; + + t.affine._m11 = m11; t.affine._m12 = m12; t.m_13 = m13; + t.affine._m21 = m21; t.affine._m22 = m22; t.m_23 = m23; + t.affine._dx = m31; t.affine._dy = m32; t.m_33 = m33; + } + } + + t.m_dirty = type; + t.m_type = type; + + return t; } /*! @@ -871,8 +962,8 @@ QTransform & QTransform::operator=(const QTransform &matrix) /*! Resets the matrix to an identity matrix, i.e. all elements are set - to zero, except \c m11 and \c m22 (specifying the scale) which are - set to 1. + to zero, except \c m11 and \c m22 (specifying the scale) and \c m33 + which are set to 1. \sa QTransform(), isIdentity(), {QTransform#Basic Matrix Operations}{Basic Matrix Operations} @@ -956,7 +1047,7 @@ QDebug operator<<(QDebug dbg, const QTransform &m) << " 31=" << m.m31() << " 32=" << m.m32() << " 33=" << m.m33() - << ")"; + << ')'; return dbg.space(); } #endif @@ -976,7 +1067,7 @@ QPoint QTransform::map(const QPoint &p) const qreal x = 0, y = 0; - TransformationType t = type(); + TransformationType t = inline_type(); switch(t) { case TxNone: x = fx; @@ -1027,7 +1118,7 @@ QPointF QTransform::map(const QPointF &p) const qreal x = 0, y = 0; - TransformationType t = type(); + TransformationType t = inline_type(); switch(t) { case TxNone: x = fx; @@ -1098,7 +1189,7 @@ QLine QTransform::map(const QLine &l) const qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0; - TransformationType t = type(); + TransformationType t = inline_type(); switch(t) { case TxNone: x1 = fx1; @@ -1157,7 +1248,7 @@ QLineF QTransform::map(const QLineF &l) const qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0; - TransformationType t = type(); + TransformationType t = inline_type(); switch(t) { case TxNone: x1 = fx1; @@ -1245,7 +1336,10 @@ static QPolygonF mapProjective(const QTransform &transform, const QPolygonF &pol */ QPolygonF QTransform::map(const QPolygonF &a) const { - TransformationType t = type(); + TransformationType t = inline_type(); + if (t <= TxTranslate) + return a.translated(affine._dx, affine._dy); + if (t >= QTransform::TxProject) return mapProjective(*this, a); @@ -1272,7 +1366,10 @@ QPolygonF QTransform::map(const QPolygonF &a) const */ QPolygon QTransform::map(const QPolygon &a) const { - TransformationType t = type(); + TransformationType t = inline_type(); + if (t <= TxTranslate) + return a.translated(qRound(affine._dx), qRound(affine._dy)); + if (t >= QTransform::TxProject) return mapProjective(*this, QPolygonF(a)).toPolygon(); @@ -1314,7 +1411,7 @@ extern QPainterPath qt_regionToPath(const QRegion ®ion); */ QRegion QTransform::map(const QRegion &r) const { - TransformationType t = type(); + TransformationType t = inline_type(); if (t == TxNone) return r; @@ -1341,7 +1438,7 @@ struct QHomogeneousCoordinate QHomogeneousCoordinate(qreal x_, qreal y_, qreal w_) : x(x_), y(y_), w(w_) {} const QPointF toPoint() const { - qreal iw = 1 / w; + qreal iw = 1. / w; return QPointF(x * iw, y * iw); } }; @@ -1397,27 +1494,12 @@ static inline bool lineTo_clipped(QPainterPath &path, const QTransform &transfor static inline bool cubicTo_clipped(QPainterPath &path, const QTransform &transform, const QPointF &a, const QPointF &b, const QPointF &c, const QPointF &d, bool needsMoveTo) { - const QHomogeneousCoordinate ha = mapHomogeneous(transform, a); - const QHomogeneousCoordinate hb = mapHomogeneous(transform, b); - const QHomogeneousCoordinate hc = mapHomogeneous(transform, c); - const QHomogeneousCoordinate hd = mapHomogeneous(transform, d); - - if (ha.w < Q_NEAR_CLIP && hb.w < Q_NEAR_CLIP && hc.w < Q_NEAR_CLIP && hd.w < Q_NEAR_CLIP) - return false; - - if (ha.w >= Q_NEAR_CLIP && hb.w >= Q_NEAR_CLIP && hc.w >= Q_NEAR_CLIP && hd.w >= Q_NEAR_CLIP) { - if (needsMoveTo) - path.moveTo(ha.toPoint()); + // Convert projective xformed curves to line + // segments so they can be transformed more accurately + QPolygonF segment = QBezier::fromPoints(a, b, c, d).toPolygon(); - path.cubicTo(hb.toPoint(), hc.toPoint(), hd.toPoint()); - return true; - } - - if (lineTo_clipped(path, transform, a, b, needsMoveTo)) - needsMoveTo = false; - if (lineTo_clipped(path, transform, b, c, needsMoveTo)) - needsMoveTo = false; - if (lineTo_clipped(path, transform, c, d, needsMoveTo)) + for (int i = 0; i < segment.size() - 1; ++i) + if (lineTo_clipped(path, transform, segment.at(i), segment.at(i+1), needsMoveTo)) needsMoveTo = false; return !needsMoveTo; @@ -1482,7 +1564,7 @@ static QPainterPath mapProjective(const QTransform &transform, const QPainterPat */ QPainterPath QTransform::map(const QPainterPath &path) const { - TransformationType t = type(); + TransformationType t = inline_type(); if (t == TxNone || path.isEmpty()) return path; @@ -1490,15 +1572,11 @@ QPainterPath QTransform::map(const QPainterPath &path) const return mapProjective(*this, path); QPainterPath copy = path; - copy.detach(); if (t == TxTranslate) { - for (int i=0; i<path.elementCount(); ++i) { - QPainterPath::Element &e = copy.d_ptr->elements[i]; - e.x += affine._dx; - e.y += affine._dy; - } + copy.translate(affine._dx, affine._dy); } else { + copy.detach(); // Full xform for (int i=0; i<path.elementCount(); ++i) { QPainterPath::Element &e = copy.d_ptr->elements[i]; @@ -1531,7 +1609,7 @@ QPainterPath QTransform::map(const QPainterPath &path) const */ QPolygon QTransform::mapToPolygon(const QRect &rect) const { - TransformationType t = type(); + TransformationType t = inline_type(); QPolygon a(4); qreal x[4] = { 0, 0, 0, 0 }, y[4] = { 0, 0, 0, 0 }; @@ -1685,7 +1763,7 @@ bool QTransform::quadToQuad(const QPolygonF &one, Sets the matrix elements to the specified values, \a m11, \a m12, \a m13 \a m21, \a m22, \a m23 \a m31, \a m32 and \a m33. Note that this function replaces the previous values. - QMatrix provides the translate(), rotate(), scale() and shear() + QTransform provides the translate(), rotate(), scale() and shear() convenience functions to manipulate the various matrix elements based on the currently defined coordinate system. @@ -1703,9 +1781,20 @@ void QTransform::setMatrix(qreal m11, qreal m12, qreal m13, m_dirty = TxProject; } +static inline bool needsPerspectiveClipping(const QRectF &rect, const QTransform &transform) +{ + const qreal wx = qMin(transform.m13() * rect.left(), transform.m13() * rect.right()); + const qreal wy = qMin(transform.m23() * rect.top(), transform.m23() * rect.bottom()); + + return wx + wy + transform.m33() < Q_NEAR_CLIP; +} + QRect QTransform::mapRect(const QRect &rect) const { - TransformationType t = type(); + TransformationType t = inline_type(); + if (t <= TxTranslate) + return rect.translated(qRound(affine._dx), qRound(affine._dy)); + if (t <= TxScale) { int x = qRound(affine._m11*rect.x() + affine._dx); int y = qRound(affine._m22*rect.y() + affine._dy); @@ -1720,7 +1809,7 @@ QRect QTransform::mapRect(const QRect &rect) const y -= h; } return QRect(x, y, w, h); - } else if (t < TxProject) { + } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) { // see mapToPolygon for explanations of the algorithm. qreal x = 0, y = 0; MAP(rect.left(), rect.top(), x, y); @@ -1772,7 +1861,10 @@ QRect QTransform::mapRect(const QRect &rect) const */ QRectF QTransform::mapRect(const QRectF &rect) const { - TransformationType t = type(); + TransformationType t = inline_type(); + if (t <= TxTranslate) + return rect.translated(affine._dx, affine._dy); + if (t <= TxScale) { qreal x = affine._m11*rect.x() + affine._dx; qreal y = affine._m22*rect.y() + affine._dy; @@ -1787,7 +1879,7 @@ QRectF QTransform::mapRect(const QRectF &rect) const y -= h; } return QRectF(x, y, w, h); - } else if (t < TxProject) { + } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) { qreal x = 0, y = 0; MAP(rect.x(), rect.y(), x, y); qreal xmin = x; @@ -1843,7 +1935,7 @@ QRectF QTransform::mapRect(const QRectF &rect) const */ void QTransform::map(qreal x, qreal y, qreal *tx, qreal *ty) const { - TransformationType t = type(); + TransformationType t = inline_type(); MAP(x, y, *tx, *ty); } @@ -1857,7 +1949,7 @@ void QTransform::map(qreal x, qreal y, qreal *tx, qreal *ty) const */ void QTransform::map(int x, int y, int *tx, int *ty) const { - TransformationType t = type(); + TransformationType t = inline_type(); qreal fx = 0, fy = 0; MAP(x, y, fx, fy); *tx = qRound(fx); @@ -1865,8 +1957,11 @@ void QTransform::map(int x, int y, int *tx, int *ty) const } /*! - Returns the QTransform cast to a QMatrix. - */ + Returns the QTransform as an affine matrix. + + \warning If a perspective transformation has been specified, + then the conversion will cause loss of data. +*/ const QMatrix &QTransform::toAffine() const { return affine; @@ -1886,25 +1981,41 @@ const QMatrix &QTransform::toAffine() const */ QTransform::TransformationType QTransform::type() const { - if (m_dirty >= m_type) { - if (m_dirty > TxShear && (!qFuzzyCompare(m_13 + 1, 1) || !qFuzzyCompare(m_23 + 1, 1) || !qFuzzyCompare(m_33, 1))) + if(m_dirty == TxNone || m_dirty < m_type) + return static_cast<TransformationType>(m_type); + + switch (static_cast<TransformationType>(m_dirty)) { + case TxProject: + if (!qFuzzyIsNull(m_13) || !qFuzzyIsNull(m_23) || !qFuzzyIsNull(m_33 - 1)) { m_type = TxProject; - else if (m_dirty > TxScale && (!qFuzzyCompare(affine._m12 + 1, 1) || !qFuzzyCompare(affine._m21 + 1, 1))) { + break; + } + case TxShear: + case TxRotate: + if (!qFuzzyIsNull(affine._m12) || !qFuzzyIsNull(affine._m21)) { const qreal dot = affine._m11 * affine._m12 + affine._m21 * affine._m22; - if (qFuzzyCompare(dot + 1, 1)) + if (qFuzzyIsNull(dot)) m_type = TxRotate; else m_type = TxShear; - } else if (m_dirty > TxTranslate && (!qFuzzyCompare(affine._m11, 1) || !qFuzzyCompare(affine._m22, 1))) + break; + } + case TxScale: + if (!qFuzzyIsNull(affine._m11 - 1) || !qFuzzyIsNull(affine._m22 - 1)) { m_type = TxScale; - else if (m_dirty > TxNone && (!qFuzzyCompare(affine._dx + 1, 1) || !qFuzzyCompare(affine._dy + 1, 1))) + break; + } + case TxTranslate: + if (!qFuzzyIsNull(affine._dx) || !qFuzzyIsNull(affine._dy)) { m_type = TxTranslate; - else - m_type = TxNone; - - m_dirty = TxNone; + break; + } + case TxNone: + m_type = TxNone; + break; } + m_dirty = TxNone; return static_cast<TransformationType>(m_type); } @@ -1928,8 +2039,9 @@ QTransform::operator QVariant() const /*! \fn qreal QTransform::det() const + \obsolete - Returns the matrix's determinant. + Returns the matrix's determinant. Use determinant() instead. */ @@ -2083,6 +2195,17 @@ QTransform::operator QVariant() const \sa reset() */ +/*! + \fn bool qFuzzyCompare(const QTransform& t1, const QTransform& t2) + + \relates QTransform + \since 4.6 + + Returns true if \a t1 and \a t2 are equal, allowing for a small + fuzziness factor for floating-point comparisons; false otherwise. +*/ + + // returns true if the transform is uniformly scaling // (same scale in x and y direction) // scale is set to the max of x and y scaling factors diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h index 4201e10..e6c1a4e 100644 --- a/src/gui/painting/qtransform.h +++ b/src/gui/painting/qtransform.h @@ -50,6 +50,10 @@ #include <QtCore/qpoint.h> #include <QtCore/qrect.h> +#if defined(Q_OS_VXWORKS) && defined(m_type) +# undef m_type +#endif + QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -71,6 +75,7 @@ public: TxProject = 0x10 }; + inline explicit QTransform(Qt::Initialization) : affine(Qt::Uninitialized) {} QTransform(); QTransform(qreal h11, qreal h12, qreal h13, qreal h21, qreal h22, qreal h23, @@ -159,6 +164,19 @@ public: static QTransform fromScale(qreal dx, qreal dy); private: + inline QTransform(qreal h11, qreal h12, qreal h13, + qreal h21, qreal h22, qreal h23, + qreal h31, qreal h32, qreal h33, bool) + : affine(h11, h12, h21, h22, h31, h32, true) + , m_13(h13), m_23(h23), m_33(h33) + , m_type(TxNone) + , m_dirty(TxProject) {} + inline QTransform(bool) + : affine(true) + , m_13(0), m_23(0), m_33(1) + , m_type(TxNone) + , m_dirty(TxNone) {} + inline TransformationType inline_type() const; QMatrix affine; qreal m_13; qreal m_23; @@ -173,18 +191,25 @@ private: Q_DECLARE_TYPEINFO(QTransform, Q_MOVABLE_TYPE); /******* inlines *****/ +inline QTransform::TransformationType QTransform::inline_type() const +{ + if (m_dirty == TxNone) + return static_cast<TransformationType>(m_type); + return type(); +} + inline bool QTransform::isAffine() const { - return type() < TxProject; + return inline_type() < TxProject; } inline bool QTransform::isIdentity() const { - return type() == TxNone; + return inline_type() == TxNone; } inline bool QTransform::isInvertible() const { - return !qFuzzyCompare(determinant() + 1, 1); + return !qFuzzyIsNull(determinant()); } inline bool QTransform::isScaling() const @@ -193,12 +218,12 @@ inline bool QTransform::isScaling() const } inline bool QTransform::isRotating() const { - return type() >= TxRotate; + return inline_type() >= TxRotate; } inline bool QTransform::isTranslating() const { - return type() >= TxTranslate; + return inline_type() >= TxTranslate; } inline qreal QTransform::determinant() const @@ -311,9 +336,25 @@ inline QTransform &QTransform::operator-=(qreal num) return *this; } +inline bool qFuzzyCompare(const QTransform& t1, const QTransform& t2) +{ + return qFuzzyCompare(t1.m11(), t2.m11()) + && qFuzzyCompare(t1.m12(), t2.m12()) + && qFuzzyCompare(t1.m13(), t2.m13()) + && qFuzzyCompare(t1.m21(), t2.m21()) + && qFuzzyCompare(t1.m22(), t2.m22()) + && qFuzzyCompare(t1.m23(), t2.m23()) + && qFuzzyCompare(t1.m31(), t2.m31()) + && qFuzzyCompare(t1.m32(), t2.m32()) + && qFuzzyCompare(t1.m33(), t2.m33()); +} + + /****** stream functions *******************/ +#ifndef QT_NO_DATASTREAM Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QTransform &); Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QTransform &); +#endif #ifndef QT_NO_DEBUG_STREAM Q_GUI_EXPORT QDebug operator<<(QDebug, const QTransform &); diff --git a/src/gui/painting/qvectorpath_p.h b/src/gui/painting/qvectorpath_p.h index a03a8e1..1e909d4 100644 --- a/src/gui/painting/qvectorpath_p.h +++ b/src/gui/painting/qvectorpath_p.h @@ -55,9 +55,9 @@ #include <QtGui/qpaintengine.h> -#include "qpaintengine_p.h" -#include "qstroker_p.h" -#include "qpainter_p.h" +#include <private/qpaintengine_p.h> +#include <private/qstroker_p.h> +#include <private/qpainter_p.h> QT_BEGIN_HEADER @@ -94,7 +94,7 @@ public: // Shape rendering specifiers... OddEvenFill = 0x1000, WindingFill = 0x2000, - ImplicitClose = 0x4000, + ImplicitClose = 0x4000 }; // ### Falcon: introduca a struct XY for points so lars is not so confused... @@ -112,7 +112,7 @@ public: { } - const QRealRect &controlPointRect() const; + QRectF controlPointRect() const; inline Hint shape() const { return (Hint) (m_hints & ShapeHintMask); } @@ -130,6 +130,8 @@ public: static inline uint polygonFlags(QPaintEngine::PolygonDrawMode mode); + QPainterPath convertToPainterPath() const; + private: Q_DISABLE_COPY(QVectorPath) diff --git a/src/gui/painting/qwindowsurface_d3d.cpp b/src/gui/painting/qwindowsurface_d3d.cpp deleted file mode 100644 index 8f9403f..0000000 --- a/src/gui/painting/qwindowsurface_d3d.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -//#define D3D_DEBUG_BACKBUFFER - -#include <QtGui/QPaintDevice> -#include <QtGui/QWidget> -#include "qdebug.h" - -#include "qpaintengine_d3d_p.h" -#include "qwindowsurface_d3d_p.h" -#include "private/qwidget_p.h" -#include "private/qbackingstore_p.h" - -#include <d3d9.h> - -QT_BEGIN_NAMESPACE - -extern QDirect3DPaintEngine *qt_d3dEngine(); - -struct QD3DWindowSurfacePrivate -{ - QSize m_lastSize; - QWidget *m_widget; -}; - -QD3DWindowSurface::QD3DWindowSurface(QWidget *window) - : QWindowSurface(window), d_ptr(new QD3DWindowSurfacePrivate) -{ - Q_ASSERT(window->isTopLevel()); - d_ptr->m_widget = window; -} - - -QD3DWindowSurface::~QD3DWindowSurface() -{ - delete d_ptr; -} - -QPaintDevice *QD3DWindowSurface::paintDevice() -{ - return d_ptr->m_widget; -} - - -void QD3DWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset) -{ - QPoint wOffset = qt_qwidget_data(widget)->wrect.topLeft(); - - QDirect3DPaintEngine *engine = qt_d3dEngine(); - LPDIRECT3DSWAPCHAIN9 swapchain = engine->swapChain(d_ptr->m_widget); - - if (swapchain) { - QRect br = rgn.boundingRect(); - QRect wbr = br.translated(-wOffset); - - RECT destrect; - destrect.left = wbr.x(); - destrect.top = wbr.y(); - destrect.right = destrect.left + wbr.width(); - destrect.bottom = destrect.top + wbr.height(); - - RECT srcrect; - srcrect.left = br.x() + offset.x(); - srcrect.top = br.y() + offset.y(); - srcrect.right = wbr.width() + srcrect.left; - srcrect.bottom = wbr.height() + srcrect.top; - int devwidth = d_ptr->m_lastSize.width(); - int devheight = d_ptr->m_lastSize.height(); - - if (devwidth <= srcrect.right) { - int diff = srcrect.right - devwidth; - srcrect.right -= diff; - destrect.right -= diff; - if (srcrect.right <= srcrect.left) - return; - } - if (devheight <= srcrect.bottom) { - int diff = srcrect.bottom - devheight; - srcrect.bottom -= diff; - destrect.bottom -= diff; - if (srcrect.bottom <= srcrect.top) - return; - } - - if (FAILED(swapchain->Present(&srcrect, &destrect, widget->winId(), 0, 0))) - qWarning("QDirect3DPaintEngine: failed to present back buffer."); - -#ifdef D3D_DEBUG_BACKBUFFER - qDebug() << widget << srcrect.left << srcrect.top << wbr.width() << wbr.height() << "Dest: " << destrect.left << destrect.top; - IDirect3DSurface9 *surface; - swapchain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &surface); - QString filename("C:\\test.bmp"); - D3DXSaveSurfaceToFile(filename.utf16(), D3DXIFF_BMP, surface, 0, 0); - surface->Release(); -#endif - } -} - -void QD3DWindowSurface::setGeometry(const QRect &rect) -{ - if (rect.isEmpty()) - qt_d3dEngine()->releaseSwapChain(d_ptr->m_widget); - - d_ptr->m_lastSize = rect.size(); - QWindowSurface::setGeometry(rect); -} - - -bool QD3DWindowSurface::scroll(const QRegion &area, int dx, int dy) -{ - QDirect3DPaintEngine *engine = qt_d3dEngine(); - QRect rect = area.boundingRect(); - - RECT destrect; - destrect.left = rect.x()+dx; - destrect.top = rect.y()+dy; - destrect.right = rect.width() + destrect.left; - destrect.bottom = rect.height() + destrect.top; - - RECT srcrect; - srcrect.left = rect.x(); - srcrect.top = rect.y(); - srcrect.right = rect.width() + srcrect.left; - srcrect.bottom = rect.height() + srcrect.top; - - engine->scroll(d_ptr->m_widget, srcrect, destrect); - return true; -} - -QT_END_NAMESPACE diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp index 2348cce..514dc72 100644 --- a/src/gui/painting/qwindowsurface_raster.cpp +++ b/src/gui/painting/qwindowsurface_raster.cpp @@ -43,6 +43,7 @@ #include <qglobal.h> // for Q_WS_WIN define (non-PCH) #ifdef Q_WS_WIN +#include <qlibrary.h> #include <qt_windows.h> #endif @@ -67,10 +68,6 @@ QT_BEGIN_NAMESPACE -#ifdef Q_WS_WIN -PtrUpdateLayeredWindowIndirect ptrUpdateLayeredWindowIndirect; -#endif - class QRasterWindowSurfacePrivate { public: @@ -82,9 +79,6 @@ public: uint translucentBackground : 1; #endif #endif -#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE) - uint canUseLayeredWindow : 1; -#endif uint inSetGeometry : 1; }; @@ -98,10 +92,6 @@ QRasterWindowSurface::QRasterWindowSurface(QWidget *window) && window->x11Info().depth() == 32; #endif #endif -#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE) - d_ptr->canUseLayeredWindow = ptrUpdateLayeredWindowIndirect - && (qt_widget_private(window)->data.window_flags & Qt::FramelessWindowHint); -#endif d_ptr->image = 0; d_ptr->inSetGeometry = false; setStaticContentsSupport(true); @@ -115,8 +105,6 @@ QRasterWindowSurface::~QRasterWindowSurface() #endif if (d_ptr->image) delete d_ptr->image; - - delete d_ptr; } @@ -127,11 +115,10 @@ QPaintDevice *QRasterWindowSurface::paintDevice() void QRasterWindowSurface::beginPaint(const QRegion &rgn) { -#if (defined(Q_WS_X11) && !defined(QT_NO_XRENDER)) || (defined(Q_WS_WIN) && !defined(Q_OS_WINCE)) +#if (defined(Q_WS_X11) && !defined(QT_NO_XRENDER)) || (defined(Q_WS_WIN) && !defined(Q_WS_WINCE)) if (!qt_widget_private(window())->isOpaque && window()->testAttribute(Qt::WA_TranslucentBackground)) { -#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE) - if (d_ptr->image->image.format() != QImage::Format_ARGB32_Premultiplied - && d_ptr->canUseLayeredWindow) +#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE) + if (d_ptr->image->image.format() != QImage::Format_ARGB32_Premultiplied) prepareBuffer(QImage::Format_ARGB32_Premultiplied, window()); #endif QPainter p(&d_ptr->image->image); @@ -159,8 +146,11 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi #ifdef Q_WS_WIN QRect br = rgn.boundingRect(); -#ifndef Q_OS_WINCE - if (!qt_widget_private(window())->isOpaque && d->canUseLayeredWindow && window()->testAttribute(Qt::WA_TranslucentBackground)) { +#ifndef Q_WS_WINCE + if (!qt_widget_private(window())->isOpaque + && window()->testAttribute(Qt::WA_TranslucentBackground) + && (qt_widget_private(window())->data.window_flags & Qt::FramelessWindowHint)) + { QRect r = window()->frameGeometry(); QPoint frameOffset = qt_widget_private(window())->frameStrut().topLeft(); QRect dirtyRect = br.translated(offset + frameOffset); @@ -168,12 +158,11 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi SIZE size = {r.width(), r.height()}; POINT ptDst = {r.x(), r.y()}; POINT ptSrc = {0, 0}; - Q_BLENDFUNCTION blend = {AC_SRC_OVER, 0, (int)(255.0 * window()->windowOpacity()), Q_AC_SRC_ALPHA}; + BLENDFUNCTION blend = {AC_SRC_OVER, 0, (int)(255.0 * window()->windowOpacity()), Q_AC_SRC_ALPHA}; RECT dirty = {dirtyRect.x(), dirtyRect.y(), dirtyRect.x() + dirtyRect.width(), dirtyRect.y() + dirtyRect.height()}; Q_UPDATELAYEREDWINDOWINFO info = {sizeof(info), NULL, &ptDst, &size, d->image->hdc, &ptSrc, 0, &blend, Q_ULW_ALPHA, &dirty}; - - (*ptrUpdateLayeredWindowIndirect)(window()->internalWinId(), &info); + ptrUpdateLayeredWindowIndirect(window()->internalWinId(), &info); } else #endif { @@ -296,6 +285,12 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi CGContextFlush(context); #endif #endif + +#ifdef Q_OS_SYMBIAN + Q_UNUSED(widget); + Q_UNUSED(rgn); + Q_UNUSED(offset); +#endif } void QRasterWindowSurface::setGeometry(const QRect &rect) @@ -304,11 +299,11 @@ void QRasterWindowSurface::setGeometry(const QRect &rect) Q_D(QRasterWindowSurface); d->inSetGeometry = true; if (d->image == 0 || d->image->width() < rect.width() || d->image->height() < rect.height()) { -#if (defined(Q_WS_X11) && !defined(QT_NO_XRENDER)) || (defined(Q_WS_WIN) && !defined(Q_OS_WINCE)) +#if (defined(Q_WS_X11) && !defined(QT_NO_XRENDER)) || (defined(Q_WS_WIN) && !defined(Q_WS_WINCE)) #ifndef Q_WS_WIN if (d_ptr->translucentBackground) #else - if (!qt_widget_private(window())->isOpaque && d->canUseLayeredWindow) + if (!qt_widget_private(window())->isOpaque) #endif prepareBuffer(QImage::Format_ARGB32_Premultiplied, window()); else diff --git a/src/gui/painting/qwindowsurface_raster_p.h b/src/gui/painting/qwindowsurface_raster_p.h index b74600a..a53a863 100644 --- a/src/gui/painting/qwindowsurface_raster_p.h +++ b/src/gui/painting/qwindowsurface_raster_p.h @@ -64,13 +64,6 @@ QT_BEGIN_NAMESPACE #define Q_ULW_ALPHA 0x00000002 // copied from ULW_ALPHA in winuser.h #define Q_AC_SRC_ALPHA 0x00000001 // copied from AC_SRC_ALPHA in winuser.h -struct Q_BLENDFUNCTION { - BYTE BlendOp; - BYTE BlendFlags; - BYTE SourceConstantAlpha; - BYTE AlphaFormat; -}; - struct Q_UPDATELAYEREDWINDOWINFO { DWORD cbSize; HDC hdcDst; @@ -79,12 +72,16 @@ struct Q_UPDATELAYEREDWINDOWINFO { HDC hdcSrc; const POINT *pptSrc; COLORREF crKey; - const Q_BLENDFUNCTION *pblend; + const BLENDFUNCTION *pblend; DWORD dwFlags; const RECT *prcDirty; }; +typedef BOOL (WINAPI *PtrUpdateLayeredWindow)(HWND hwnd, HDC hdcDst, const POINT *pptDst, + const SIZE *psize, HDC hdcSrc, const POINT *pptSrc, COLORREF crKey, + const BLENDFUNCTION *pblend, DWORD dwflags); typedef BOOL (WINAPI *PtrUpdateLayeredWindowIndirect)(HWND hwnd, const Q_UPDATELAYEREDWINDOWINFO *pULWInfo); +extern PtrUpdateLayeredWindow ptrUpdateLayeredWindow; extern PtrUpdateLayeredWindowIndirect ptrUpdateLayeredWindowIndirect; #endif @@ -112,7 +109,7 @@ public: private: void prepareBuffer(QImage::Format format, QWidget *widget); Q_DECLARE_PRIVATE(QRasterWindowSurface) - QRasterWindowSurfacePrivate *d_ptr; + QScopedPointer<QRasterWindowSurfacePrivate> d_ptr; }; QT_END_NAMESPACE diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp new file mode 100644 index 0000000..622b8de --- /dev/null +++ b/src/gui/painting/qwindowsurface_s60.cpp @@ -0,0 +1,237 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qglobal.h> // for Q_WS_WIN define (non-PCH) + +#include <QtGui/qpaintdevice.h> +#include <private/qwidget_p.h> +#include "qwindowsurface_s60_p.h" +#include "qt_s60_p.h" +#include "private/qdrawhelper_p.h" + +QT_BEGIN_NAMESPACE + +struct QS60WindowSurfacePrivate +{ + QImage device; + CFbsBitmap *bitmap; + uchar* bytes; + + // Since only one CFbsBitmap is allowed to be locked at a time, this is static. + static QS60WindowSurface* lockedSurface; +}; +QS60WindowSurface* QS60WindowSurfacePrivate::lockedSurface = NULL; + +QS60WindowSurface::QS60WindowSurface(QWidget* widget) + : QWindowSurface(widget), d_ptr(new QS60WindowSurfacePrivate) +{ + d_ptr->bytes = 0; + d_ptr->bitmap = 0; + + TDisplayMode mode = S60->screenDevice()->DisplayMode(); + bool isOpaque = qt_widget_private(widget)->isOpaque; + if (mode == EColor16MA && isOpaque) + mode = EColor16MU; // Faster since 16MU -> 16MA is typically accelerated + else if (mode == EColor16MU && !isOpaque) + mode = EColor16MA; // Try for transparency anyway + + + // We create empty CFbsBitmap here -> it will be resized in setGeometry + d_ptr->bitmap = q_check_ptr(new CFbsBitmap); // CBase derived object needs check on new + qt_symbian_throwIfError( d_ptr->bitmap->Create(TSize(0, 0), mode ) ); + + updatePaintDeviceOnBitmap(); + + setStaticContentsSupport(true); +} + +QS60WindowSurface::~QS60WindowSurface() +{ + if (QS60WindowSurfacePrivate::lockedSurface == this) + unlockBitmapHeap(); + + delete d_ptr->bitmap; + delete d_ptr; +} + +void QS60WindowSurface::beginPaint(const QRegion &rgn) +{ + if(!d_ptr->bitmap) + return; + + if (QS60WindowSurfacePrivate::lockedSurface) + unlockBitmapHeap(); + + QS60WindowSurfacePrivate::lockedSurface = this; + lockBitmapHeap(); + + if (!qt_widget_private(window())->isOpaque) { + QRgb *data = reinterpret_cast<QRgb *>(d_ptr->device.bits()); + const int row_stride = d_ptr->device.bytesPerLine() / 4; + + const QVector<QRect> rects = rgn.rects(); + for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) { + const int x_start = it->x(); + const int width = it->width(); + + const int y_start = it->y(); + const int height = it->height(); + + QRgb *row = data + row_stride * y_start; + for (int y = 0; y < height; ++y) { + qt_memfill(row + x_start, 0U, width); + row += row_stride; + } + } + } +} + +void QS60WindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &) +{ + const QVector<QRect> subRects = region.rects(); + for (int i = 0; i < subRects.count(); ++i) { + TRect tr = qt_QRect2TRect(subRects[i]); + widget->winId()->DrawNow(tr); + } +} + +bool QS60WindowSurface::scroll(const QRegion &area, int dx, int dy) +{ + QRect rect = area.boundingRect(); + + if (dx == 0 && dy == 0) + return false; + + if (d_ptr->device.isNull()) + return false; + + CFbsBitmapDevice *bitmapDevice = 0; + QT_TRAP_THROWING(bitmapDevice = CFbsBitmapDevice::NewL(d_ptr->bitmap)); + CBitmapContext *bitmapContext; + TInt err = bitmapDevice->CreateBitmapContext(bitmapContext); + if (err != KErrNone) { + CBase::Delete(bitmapDevice); + return false; + } + bitmapContext->CopyRect(TPoint(dx, dy), qt_QRect2TRect(rect)); + CBase::Delete(bitmapContext); + CBase::Delete(bitmapDevice); + return true; +} + +void QS60WindowSurface::endPaint(const QRegion & /* rgn */) +{ + if(!d_ptr->bitmap) + return; + + Q_ASSERT(QS60WindowSurfacePrivate::lockedSurface); + unlockBitmapHeap(); + QS60WindowSurfacePrivate::lockedSurface = NULL; +} + +QPaintDevice* QS60WindowSurface::paintDevice() +{ + return &d_ptr->device; +} + +void QS60WindowSurface::setGeometry(const QRect& rect) +{ + if (rect == geometry()) + return; + + QWindowSurface::setGeometry(rect); + + TRect nativeRect(qt_QRect2TRect(rect)); + qt_symbian_throwIfError(d_ptr->bitmap->Resize(nativeRect.Size())); + + if (!rect.isNull()) + updatePaintDeviceOnBitmap(); +} + +void QS60WindowSurface::lockBitmapHeap() +{ + if (!QS60WindowSurfacePrivate::lockedSurface) + return; + + // Get some local variables to make later code lines more clear to read + CFbsBitmap*& bitmap = QS60WindowSurfacePrivate::lockedSurface->d_ptr->bitmap; + QImage& device = QS60WindowSurfacePrivate::lockedSurface->d_ptr->device; + uchar*& bytes = QS60WindowSurfacePrivate::lockedSurface->d_ptr->bytes; + + bitmap->LockHeap(); + uchar *newBytes = (uchar*)bitmap->DataAddress(); + if (newBytes != bytes) { + bytes = newBytes; + + // Get some values for QImage creation + TDisplayMode mode = bitmap->DisplayMode(); + if (mode == EColor16MA + && qt_widget_private(QS60WindowSurfacePrivate::lockedSurface->window())->isOpaque) + mode = EColor16MU; + QImage::Format format = qt_TDisplayMode2Format( mode ); + TSize bitmapSize = bitmap->SizeInPixels(); + int bytesPerLine = CFbsBitmap::ScanLineLength( bitmapSize.iWidth, mode); + + device = QImage( bytes, bitmapSize.iWidth, bitmapSize.iHeight, bytesPerLine, format ); + } +} + +void QS60WindowSurface::unlockBitmapHeap() +{ + if (!QS60WindowSurfacePrivate::lockedSurface) + return; + + QS60WindowSurfacePrivate::lockedSurface->d_ptr->bitmap->UnlockHeap(); +} + +void QS60WindowSurface::updatePaintDeviceOnBitmap() +{ + // This forces the actual device to be updated based on CFbsBitmap + beginPaint(QRegion()); + endPaint(QRegion()); +} + +CFbsBitmap *QS60WindowSurface::symbianBitmap() const +{ + return d_ptr->bitmap; +} + +QT_END_NAMESPACE diff --git a/src/gui/painting/qwindowsurface_d3d_p.h b/src/gui/painting/qwindowsurface_s60_p.h index d9231d2..87dfd5e 100644 --- a/src/gui/painting/qwindowsurface_d3d_p.h +++ b/src/gui/painting/qwindowsurface_s60_p.h @@ -3,14 +3,14 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui module of the Qt Toolkit. +** This file is part of the QtGui of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser @@ -21,34 +21,34 @@ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. ** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ -#ifndef QWINDOWSURFACE_D3D_P_H -#define QWINDOWSURFACE_D3D_P_H +#ifndef QWINDOWSURFACE_S60_P_H +#define QWINDOWSURFACE_S60_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience -// of the QLibrary class. This header file may change from -// version to version without notice, or even be removed. +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. // // We mean it. // @@ -56,29 +56,40 @@ #include <qglobal.h> #include "private/qwindowsurface_p.h" +class CFbsBitmap; + QT_BEGIN_NAMESPACE -class QPaintDevice; -class QPoint; -class QRegion; -class QWidget; -struct QD3DWindowSurfacePrivate; +struct QS60WindowSurfacePrivate; -class QD3DWindowSurface : public QWindowSurface +class QS60WindowSurface : public QWindowSurface { public: - QD3DWindowSurface(QWidget *widget); - ~QD3DWindowSurface(); + QS60WindowSurface(QWidget *widget); + ~QS60WindowSurface(); QPaintDevice *paintDevice(); void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); - void setGeometry(const QRect &rect); bool scroll(const QRegion &area, int dx, int dy); + void beginPaint(const QRegion &); + void endPaint(const QRegion &); + + void setGeometry(const QRect &rect); + + static void lockBitmapHeap(); + static void unlockBitmapHeap(); + + CFbsBitmap *symbianBitmap() const; + +private: + void updatePaintDeviceOnBitmap(); + private: - QD3DWindowSurfacePrivate *d_ptr; + QS60WindowSurfacePrivate* d_ptr; + }; QT_END_NAMESPACE -#endif // QWINDOWSURFACE_D3D_P_H +#endif // QWINDOWSURFACE_S60_P_H diff --git a/src/gui/painting/qwindowsurface_x11.cpp b/src/gui/painting/qwindowsurface_x11.cpp index 2952c9d..c2d4f44 100644 --- a/src/gui/painting/qwindowsurface_x11.cpp +++ b/src/gui/painting/qwindowsurface_x11.cpp @@ -96,7 +96,7 @@ void QX11WindowSurface::beginPaint(const QRegion &rgn) #ifndef QT_NO_XRENDER if (d_ptr->translucentBackground) { if (d_ptr->device.depth() != 32) - static_cast<QX11PixmapData *>(d_ptr->device.data_ptr())->convertToARGB32(); + static_cast<QX11PixmapData *>(d_ptr->device.data_ptr().data())->convertToARGB32(); ::Picture src = X11->getSolidFill(d_ptr->device.x11Info().screen(), Qt::transparent); ::Picture dst = d_ptr->device.x11PictureHandle(); const QVector<QRect> rects = rgn.rects(); @@ -128,7 +128,7 @@ void QX11WindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint return; // qDebug() << "XSetClipRectangles"; // for (int i = 0; i < num; ++i) -// qDebug() << " " << i << rects[i].x << rects[i].x << rects[i].y << rects[i].width << rects[i].height; +// qDebug() << ' ' << i << rects[i].x << rects[i].x << rects[i].y << rects[i].width << rects[i].height; XSetClipRectangles(X11->display, gc, 0, 0, rects, num, YXBanded); XCopyArea(X11->display, d_ptr->device.handle(), widget->handle(), gc, br.x() + offset.x(), br.y() + offset.y(), br.width(), br.height(), wbr.x(), wbr.y()); @@ -154,7 +154,7 @@ void QX11WindowSurface::setGeometry(const QRect &rect) QX11PixmapData *oldData = static_cast<QX11PixmapData *>(d_ptr->device.pixmapData()); Q_ASSERT(oldData); - if (!oldData->uninit && hasStaticContents()) { + if (!(oldData->flags & QX11PixmapData::Uninitialized) && hasStaticContents()) { // Copy the content of the old pixmap into the new one. QX11PixmapData *newData = new QX11PixmapData(QPixmapData::PixmapType); newData->resize(size.width(), size.height()); @@ -175,7 +175,7 @@ void QX11WindowSurface::setGeometry(const QRect &rect) dx, dy, qMin(boundingRect.width(), size.width()), qMin(boundingRect.height(), size.height()), dx, dy); XFreeGC(X11->display, tmpGc); - newData->uninit = false; + newData->flags &= ~QX11PixmapData::Uninitialized; d_ptr->device = QPixmap(newData); } else { |