diff options
Diffstat (limited to 'src/gui/painting')
24 files changed, 804 insertions, 6411 deletions
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 528559c..34d1779 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -103,12 +103,6 @@ win32 { painting/qprinterinfo_win.cpp \ painting/qregion_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 { @@ -362,8 +356,4 @@ embedded { SOURCES += painting/qwindowsurface_qws.cpp } -win32:contains(QT_CONFIG, direct3d) { - HEADERS += painting/qwindowsurface_d3d_p.h - SOURCES += painting/qwindowsurface_d3d.cpp -} diff --git a/src/gui/painting/qbezier.cpp b/src/gui/painting/qbezier.cpp index 8317dd8..7ed521e 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; @@ -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/qcolor.cpp b/src/gui/painting/qcolor.cpp index 5d7d4ab..24d167e 100644 --- a/src/gui/painting/qcolor.cpp +++ b/src/gui/painting/qcolor.cpp @@ -1387,7 +1387,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; @@ -1441,7 +1441,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); diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index c11837a..ec4737c 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -157,46 +157,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 +168,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 +308,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 +316,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 +345,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 +354,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 +369,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 +379,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 +387,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 +395,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 +403,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 +412,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 +422,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 +432,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 +442,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 +452,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 +462,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 +472,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 +482,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 +534,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 +546,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 +581,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); + 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 = 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; - - 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 +618,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 +649,12 @@ 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]; + FetchPixelProc fetch = (format != QImage::Format_Invalid) ? FetchPixelProc(qt_fetchPixel<format>) : fetchPixelProc[data->texture.format]; int image_width = data->texture.width; int image_height = data->texture.height; @@ -853,130 +687,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 +749,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 +797,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 +841,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 }, }; @@ -3220,8 +2926,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); @@ -3267,28 +2972,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) { @@ -3366,45 +3050,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); @@ -3455,13 +3211,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; } @@ -4707,8 +4462,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; } @@ -4770,8 +4524,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, @@ -4786,8 +4539,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, @@ -4802,8 +4554,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, @@ -4818,8 +4569,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, @@ -4834,8 +4584,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, @@ -4850,8 +4599,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, @@ -4866,8 +4614,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, @@ -4882,8 +4629,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, @@ -4898,13 +4644,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); @@ -4958,13 +4702,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; } @@ -5020,8 +4763,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; } @@ -5091,8 +4833,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) @@ -5106,8 +4847,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) @@ -5121,8 +4861,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) @@ -5136,8 +4875,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) @@ -5151,8 +4889,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) @@ -5166,8 +4903,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) @@ -5181,8 +4917,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) @@ -5196,8 +4931,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) @@ -5211,19 +4945,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; } @@ -5402,8 +5134,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; } @@ -5606,8 +5337,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) @@ -5621,8 +5351,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) @@ -5636,8 +5365,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) @@ -5651,8 +5379,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, @@ -5667,8 +5394,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) @@ -5682,8 +5408,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) @@ -5697,8 +5422,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) @@ -5712,8 +5436,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) @@ -5727,18 +5450,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; } @@ -5924,13 +5645,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; } @@ -6052,8 +5772,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; } @@ -6202,8 +5921,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, @@ -6218,8 +5936,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, @@ -6234,8 +5951,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, @@ -6250,8 +5966,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, @@ -6266,8 +5981,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, @@ -6282,8 +5996,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, @@ -6298,8 +6011,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, @@ -6314,8 +6026,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, @@ -6330,18 +6041,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; } @@ -6475,8 +6184,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; } @@ -6626,8 +6334,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, @@ -6642,8 +6349,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, @@ -6658,8 +6364,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, @@ -6674,8 +6379,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, @@ -6690,8 +6394,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, @@ -6706,8 +6409,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, @@ -6722,8 +6424,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, @@ -6738,8 +6439,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, @@ -6754,36 +6454,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 */ @@ -7150,8 +6824,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); } } @@ -7199,8 +6872,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); } } @@ -7261,6 +6933,12 @@ static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer, void qt_build_pow_tables() { qreal smoothing = 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; if (SystemParametersInfo(0x200C /* SPI_GETFONTSMOOTHINGCONTRAST */, 0, &winSmooth, 0)) @@ -7405,7 +7083,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); } } } @@ -7446,7 +7124,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); } } diff --git a/src/gui/painting/qmatrix.cpp b/src/gui/painting/qmatrix.cpp index 4439d52..31abcad 100644 --- a/src/gui/painting/qmatrix.cpp +++ b/src/gui/painting/qmatrix.cpp @@ -208,9 +208,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 +224,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 +239,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 +260,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 +981,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 +1066,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); } /*! diff --git a/src/gui/painting/qmatrix.h b/src/gui/painting/qmatrix.h index bf53c32..1e5fbb4 100644 --- a/src/gui/painting/qmatrix.h +++ b/src/gui/painting/qmatrix.h @@ -99,7 +99,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 +121,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,8 +161,8 @@ 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); } /***************************************************************************** diff --git a/src/gui/painting/qpaintengine_d3d.cpp b/src/gui/painting/qpaintengine_d3d.cpp deleted file mode 100644 index bb81623..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: Qt Software Information (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 qt-sales@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 8fa5cf6..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: Qt Software Information (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 qt-sales@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_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index ba1e27c..295abc5 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -509,16 +509,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); @@ -618,22 +622,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()) ) ; } diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 65d87fa..d9c7937 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -6057,22 +6057,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; diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index e1f5eea..d471aaa 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -1299,10 +1299,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 +1329,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); } @@ -2000,7 +2000,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 void QPainterPath::translated(const QPointF &offset) + \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 diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h index 6cd2af8..e343a28 100644 --- a/src/gui/painting/qpainterpath.h +++ b/src/gui/painting/qpainterpath.h @@ -147,6 +147,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; @@ -365,6 +371,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/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp index 297cdd3..9ef3eb7 100644 --- a/src/gui/painting/qpathclipper.cpp +++ b/src/gui/painting/qpathclipper.cpp @@ -138,11 +138,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); @@ -202,13 +202,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); @@ -250,11 +250,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; @@ -315,11 +315,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; @@ -922,7 +922,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) @@ -951,7 +951,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); @@ -1080,7 +1080,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; @@ -1232,10 +1232,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); @@ -1400,7 +1400,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/qpolygon.cpp b/src/gui/painting/qpolygon.cpp index 87dae0f..769c095 100644 --- a/src/gui/painting/qpolygon.cpp +++ b/src/gui/painting/qpolygon.cpp @@ -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 @@ -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() */ /*! diff --git a/src/gui/painting/qpolygon.h b/src/gui/painting/qpolygon.h index e5e0bd1..c52f48c 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/qprinter.cpp b/src/gui/painting/qprinter.cpp index 4f3e71c..5161e32 100644 --- a/src/gui/painting/qprinter.cpp +++ b/src/gui/painting/qprinter.cpp @@ -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; + } } } diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp index b894c62..5fffc72 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; @@ -1018,7 +1018,7 @@ void QDashStroker::processCurrentSubpath() sumLength += dashes[i]; } - if (qFuzzyCompare(sumLength + 1, qreal(1))) + if (qFuzzyIsNull(sumLength)) return; Q_ASSERT(dashCount > 0); diff --git a/src/gui/painting/qtessellator.cpp b/src/gui/painting/qtessellator.cpp index e02f02d..ce5ab74 100644 --- a/src/gui/painting/qtessellator.cpp +++ b/src/gui/painting/qtessellator.cpp @@ -1436,7 +1436,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/qtransform.cpp b/src/gui/painting/qtransform.cpp index af27fd5..d06107f 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -238,11 +238,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 +256,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 +272,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 +287,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 +314,7 @@ QTransform QTransform::adjoint() const return QTransform(h11, h12, h13, h21, h22, h23, - h31, h32, h33); + h31, h32, h33, true); } /*! @@ -327,7 +324,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 +342,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 +353,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 +368,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 +393,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; @@ -437,7 +433,7 @@ 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; else @@ -456,7 +452,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; @@ -489,8 +485,8 @@ 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) + QTransform transform(sx, 0, 0, 0, sy, 0, 0, 0, 1, true); + if (sx == 1. && sy == 1.) transform.m_dirty = TxNone; else transform.m_dirty = TxScale; @@ -505,7 +501,7 @@ QTransform QTransform::fromScale(qreal sx, qreal sy) */ QTransform & QTransform::shear(qreal sh, qreal sv) { - switch(type()) { + switch(inline_type()) { case TxNone: case TxTranslate: affine._m12 = sv; @@ -574,7 +570,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; @@ -646,7 +642,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; @@ -730,11 +726,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 +808,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; } /*! @@ -976,7 +1040,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 +1091,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 +1162,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 +1221,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 +1309,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 +1339,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 +1384,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; if (t == TxTranslate) { @@ -1337,7 +1407,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); } }; @@ -1475,7 +1545,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; @@ -1483,15 +1553,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]; @@ -1524,7 +1590,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 }; @@ -1698,7 +1764,10 @@ void QTransform::setMatrix(qreal m11, qreal m12, qreal m13, 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); @@ -1765,7 +1834,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; @@ -1836,7 +1908,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); } @@ -1850,7 +1922,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); @@ -1879,25 +1951,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); } diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h index c76409b..aac7c31 100644 --- a/src/gui/painting/qtransform.h +++ b/src/gui/painting/qtransform.h @@ -159,6 +159,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 +186,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 +213,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 diff --git a/src/gui/painting/qwindowsurface_d3d.cpp b/src/gui/painting/qwindowsurface_d3d.cpp deleted file mode 100644 index 2b7f633..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: Qt Software Information (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 qt-sales@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_d3d_p.h b/src/gui/painting/qwindowsurface_d3d_p.h deleted file mode 100644 index 9cdfe29..0000000 --- a/src/gui/painting/qwindowsurface_d3d_p.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (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 qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWINDOWSURFACE_D3D_P_H -#define QWINDOWSURFACE_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 the QLibrary class. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// - -#include <qglobal.h> -#include "private/qwindowsurface_p.h" - -QT_BEGIN_NAMESPACE - -class QPaintDevice; -class QPoint; -class QRegion; -class QWidget; -struct QD3DWindowSurfacePrivate; - -class QD3DWindowSurface : public QWindowSurface -{ -public: - QD3DWindowSurface(QWidget *widget); - ~QD3DWindowSurface(); - - 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); - -private: - QD3DWindowSurfacePrivate *d_ptr; -}; - -QT_END_NAMESPACE - -#endif // QWINDOWSURFACE_D3D_P_H |