Changeset 846 for trunk/src/gui/painting


Ignore:
Timestamp:
May 5, 2011, 5:36:53 AM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
4 deleted
163 edited
8 copied

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/gui/painting/painting.pri

    r811 r846  
    9292        HEADERS +=                                      \
    9393                painting/qpaintengine_raster_p.h        \
     94                painting/qdrawhelper_p.h                \
     95                painting/qblendfunctions_p.h            \
    9496                painting/qrasterdefs_p.h                \
    9597                painting/qgrayraster_p.h
     
    124126    HEADERS += \
    125127        painting/qgraphicssystem_raster_p.h \
     128        painting/qgraphicssystem_runtime_p.h \
    126129        painting/qgraphicssystemfactory_p.h \
    127130        painting/qgraphicssystemplugin_p.h \
     
    130133    SOURCES += \
    131134        painting/qgraphicssystem_raster.cpp \
     135        painting/qgraphicssystem_runtime.cpp \
    132136        painting/qgraphicssystemfactory.cpp \
    133137        painting/qgraphicssystemplugin.cpp \
     
    210214}
    211215
    212 contains(QMAKE_MAC_XARCH, no) {
    213     DEFINES += QT_NO_MAC_XARCH
    214 } else:if(mmx|3dnow|sse|sse2|iwmmxt) {
     216if(mmx|3dnow|sse|sse2|iwmmxt) {
    215217    HEADERS += painting/qdrawhelper_x86_p.h \
    216218               painting/qdrawhelper_mmx_p.h \
    217                painting/qdrawhelper_sse_p.h
    218     mmx {
    219         DEFINES += QT_HAVE_MMX
    220         MMX_SOURCES += painting/qdrawhelper_mmx.cpp
    221     }
    222     3dnow {
    223         DEFINES += QT_HAVE_3DNOW
    224         MMX3DNOW_SOURCES += painting/qdrawhelper_mmx3dnow.cpp
    225         sse {
    226             SSE3DNOW_SOURCES += painting/qdrawhelper_sse3dnow.cpp
    227         }
    228     }
    229     sse {
    230         DEFINES += QT_HAVE_SSE
    231         SSE_SOURCES += painting/qdrawhelper_sse.cpp
    232 
    233         DEFINES += QT_HAVE_MMXEXT
    234     }
    235     sse2 {
    236         DEFINES += QT_HAVE_SSE2
    237         SSE2_SOURCES += painting/qdrawhelper_sse2.cpp
    238     }
    239     iwmmxt {
    240         DEFINES += QT_HAVE_IWMMXT
    241         IWMMXT_SOURCES += painting/qdrawhelper_iwmmxt.cpp
    242     }
    243 
    244     win32-g++|!win32:!*-icc* {
    245         mmx {
    246             os2:mmx_compiler.commands = $$QMAKE_RUN_CXX -Winline
    247             else:mmx_compiler.commands = $$QMAKE_CXX -c -Winline
    248 
    249             mac {
    250                 mmx_compiler.commands += -Xarch_i386 -mmmx
    251                 mmx_compiler.commands += -Xarch_x86_64 -mmmx
    252             } else {
    253                 mmx_compiler.commands += -mmmx
    254             }
    255 
    256             os2 {
    257                 mmx_compiler.commands = $$replace(mmx_compiler.commands, \\$src, ${QMAKE_FILE_IN})
    258                 mmx_compiler.commands = $$replace(mmx_compiler.commands, \\$obj, ${QMAKE_FILE_OUT})
    259             } else {
    260                 mmx_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
    261             }
    262             mmx_compiler.dependency_type = TYPE_C
    263             mmx_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
    264             mmx_compiler.input = MMX_SOURCES
    265             mmx_compiler.variable_out = OBJECTS
    266             mmx_compiler.name = compiling[mmx] ${QMAKE_FILE_IN}
    267             silent:mmx_compiler.commands = @echo compiling[mmx] ${QMAKE_FILE_IN} && $$mmx_compiler.commands
    268             QMAKE_EXTRA_COMPILERS += mmx_compiler
    269         }
    270         3dnow {
    271             os2:mmx3dnow_compiler.commands = $$QMAKE_RUN_CXX -Winline
    272             else:mmx3dnow_compiler.commands = $$QMAKE_CXX -c -Winline
    273 
    274             mac {
    275                 mmx3dnow_compiler.commands += -Xarch_i386 -m3dnow -Xarch_i386 -mmmx
    276                 mmx3dnow_compiler.commands += -Xarch_x86_64 -m3dnow -Xarch_x86_64 -mmmx
    277             } else {
    278                 mmx3dnow_compiler.commands += -m3dnow -mmmx
    279             }
    280 
    281             os2 {
    282                 mmx3dnow_compiler.commands = $$replace(mmx3dnow_compiler.commands, \\$src, ${QMAKE_FILE_IN})
    283                 mmx3dnow_compiler.commands = $$replace(mmx3dnow_compiler.commands, \\$obj, ${QMAKE_FILE_OUT})
    284             } else {
    285                 mmx3dnow_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
    286             }
    287             mmx3dnow_compiler.dependency_type = TYPE_C
    288             mmx3dnow_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
    289             mmx3dnow_compiler.input = MMX3DNOW_SOURCES
    290             mmx3dnow_compiler.variable_out = OBJECTS
    291             mmx3dnow_compiler.name = compiling[mmx3dnow] ${QMAKE_FILE_IN}
    292             silent:mmx3dnow_compiler.commands = @echo compiling[mmx3dnow] ${QMAKE_FILE_IN} && $$mmx3dnow_compiler.commands
    293             QMAKE_EXTRA_COMPILERS += mmx3dnow_compiler
    294             sse {
    295                 os2:sse3dnow_compiler.commands = $$QMAKE_RUN_CXX -Winline
    296                 else:sse3dnow_compiler.commands = $$QMAKE_CXX -c -Winline
    297 
    298                 mac {
    299                     sse3dnow_compiler.commands += -Xarch_i386 -m3dnow -Xarch_i386 -msse
    300                     sse3dnow_compiler.commands += -Xarch_x86_64 -m3dnow -Xarch_x86_64 -msse
    301                 } else:os2 {
    302                     # SSE data types (__m128i etc.) don't get 16-byte alignment on stack with GCC 4.4.4
    303                     # (compiler bug?), force it with -mstackrealign to avoid spontaneous SIGSEGVs
    304                     sse3dnow_compiler.commands += -m3dnow -msse -mstackrealign
    305                 } else {
    306                     sse3dnow_compiler.commands += -m3dnow -msse
    307                 }
    308 
    309                 os2 {
    310                     sse3dnow_compiler.commands = $$replace(sse3dnow_compiler.commands, \\$src, ${QMAKE_FILE_IN})
    311                     sse3dnow_compiler.commands = $$replace(sse3dnow_compiler.commands, \\$obj, ${QMAKE_FILE_OUT})
    312                 } else {
    313                     sse3dnow_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
    314                 }
    315                 sse3dnow_compiler.dependency_type = TYPE_C
    316                 sse3dnow_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
    317                 sse3dnow_compiler.input = SSE3DNOW_SOURCES
    318                 sse3dnow_compiler.variable_out = OBJECTS
    319                 sse3dnow_compiler.name = compiling[sse3dnow] ${QMAKE_FILE_IN}
    320                 silent:sse3dnow_compiler.commands = @echo compiling[sse3dnow] ${QMAKE_FILE_IN} && $$sse3dnow_compiler.commands
    321                 QMAKE_EXTRA_COMPILERS += sse3dnow_compiler
    322             }
    323         }
    324         sse {
    325             os2:sse_compiler.commands = $$QMAKE_RUN_CXX -Winline
    326             else:sse_compiler.commands = $$QMAKE_CXX -c -Winline
    327 
    328             mac {
    329                 sse_compiler.commands += -Xarch_i386 -msse
    330                 sse_compiler.commands += -Xarch_x86_64 -msse
    331             } else:os2 {
    332                 # SSE data types (__m128i etc.) don't get 16-byte alignment on stack with GCC 4.4.4
    333                 # (compiler bug?), force it with -mstackrealign to avoid spontaneous SIGSEGVs
    334                 sse_compiler.commands += -msse -mstackrealign
    335             } else {
    336                 sse_compiler.commands += -msse
    337             }
    338 
    339             os2 {
    340                 sse_compiler.commands = $$replace(sse_compiler.commands, \\$src, ${QMAKE_FILE_IN})
    341                 sse_compiler.commands = $$replace(sse_compiler.commands, \\$obj, ${QMAKE_FILE_OUT})
    342             } else {
    343                 sse_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
    344             }
    345             sse_compiler.dependency_type = TYPE_C
    346             sse_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
    347             sse_compiler.input = SSE_SOURCES
    348             sse_compiler.variable_out = OBJECTS
    349             sse_compiler.name = compiling[sse] ${QMAKE_FILE_IN}
    350             silent:sse_compiler.commands = @echo compiling[sse] ${QMAKE_FILE_IN} && $$sse_compiler.commands
    351             QMAKE_EXTRA_COMPILERS += sse_compiler
    352         }
    353         sse2 {
    354             os2:sse2_compiler.commands = $$QMAKE_RUN_CXX -Winline
    355             else:sse2_compiler.commands = $$QMAKE_CXX -c -Winline
    356 
    357             mac {
    358                 sse2_compiler.commands += -Xarch_i386 -msse2
    359                 sse2_compiler.commands += -Xarch_x86_64 -msse2
    360             } else:os2 {
    361                 # SSE data types (__m128i etc.) don't get 16-byte alignment on stack with GCC 4.4.4
    362                 # (compiler bug?), force it with -mstackrealign to avoid spontaneous SIGSEGVs
    363                 sse2_compiler.commands += -msse2 -mstackrealign
    364             } else {
    365                 sse2_compiler.commands += -msse2
    366             }
    367 
    368             os2 {
    369                 sse2_compiler.commands = $$replace(sse2_compiler.commands, \\$src, ${QMAKE_FILE_IN})
    370                 sse2_compiler.commands = $$replace(sse2_compiler.commands, \\$obj, ${QMAKE_FILE_OUT})
    371             } else {
    372                 sse2_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
    373             }
    374             sse2_compiler.dependency_type = TYPE_C
    375             sse2_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
    376             sse2_compiler.input = SSE2_SOURCES
    377             sse2_compiler.variable_out = OBJECTS
    378             sse2_compiler.name = compiling[sse2] ${QMAKE_FILE_IN}
    379             silent:sse2_compiler.commands = @echo compiling[sse2] ${QMAKE_FILE_IN} && $$sse2_compiler.commands
    380             QMAKE_EXTRA_COMPILERS += sse2_compiler
    381         }
    382         iwmmxt {
    383             os2:iwmmxt_compiler.commands = $$QMAKE_RUN_CXX -Winline
    384             else:iwmmxt_compiler.commands = $$QMAKE_CXX -c -Winline
    385             iwmmxt_compiler.commands += -mcpu=iwmmxt
    386             os2 {
    387                 iwmmxt_compiler.commands = $$replace(iwmmxt_compiler.commands, \\$src, ${QMAKE_FILE_IN})
    388                 iwmmxt_compiler.commands = $$replace(iwmmxt_compiler.commands, \\$obj, ${QMAKE_FILE_OUT})
    389             } else {
    390                 iwmmxt_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
    391             }
    392             iwmmxt_compiler.dependency_type = TYPE_C
    393             iwmmxt_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
    394             iwmmxt_compiler.input = IWMMXT_SOURCES
    395             iwmmxt_compiler.variable_out = OBJECTS
    396             iwmmxt_compiler.name = compiling[iwmmxt] ${QMAKE_FILE_IN}
    397             silent:iwmmxt_compiler.commands = @echo compiling[iwmmxt] ${QMAKE_FILE_IN} && $$iwmmxt_compiler.commands
    398             QMAKE_EXTRA_COMPILERS += iwmmxt_compiler
    399         }
    400     } else {
    401         mmx: SOURCES += $$MMX_SOURCES
    402         3dnow: SOURCES += $$MMX3DNOW_SOURCES
    403         3dnow:sse: SOURCES += $$SSE3DNOW_SOURCES
    404         sse: SOURCES += $$SSE_SOURCES
    405         sse2: SOURCES += $$SSE2_SOURCES
    406         iwmmxt: SOURCES += $$IWMMXT_SOURCES
    407     }
     219               painting/qdrawhelper_sse_p.h \
     220               painting/qdrawingprimitive_sse2_p.h
     221    MMX_SOURCES += painting/qdrawhelper_mmx.cpp
     222    MMX3DNOW_SOURCES += painting/qdrawhelper_mmx3dnow.cpp
     223    SSE3DNOW_SOURCES += painting/qdrawhelper_sse3dnow.cpp
     224    SSE_SOURCES += painting/qdrawhelper_sse.cpp
     225    SSE2_SOURCES += painting/qdrawhelper_sse2.cpp
     226    SSSE3_SOURCES += painting/qdrawhelper_ssse3.cpp
     227    IWMMXT_SOURCES += painting/qdrawhelper_iwmmxt.cpp
    408228}
    409229
     
    429249
    430250symbian {
    431         HEADERS += painting/qwindowsurface_s60_p.h
     251        HEADERS += painting/qwindowsurface_s60_p.h \
     252                    painting/qdrawhelper_arm_simd_p.h
    432253        SOURCES += painting/qwindowsurface_s60.cpp
    433254        armccIfdefBlock = \
    434255        "$${LITERAL_HASH}if defined(ARMV6)" \
     256        "MACRO QT_HAVE_ARM_SIMD" \
    435257        "SOURCEPATH     painting" \
    436         "SOURCE                 qblendfunctions_armv6_rvct.s" \
    437         "SOURCE                 qdrawhelper_armv6_rvct.s" \
     258        "SOURCE                 qdrawhelper_arm_simd.cpp" \
    438259        "$${LITERAL_HASH}endif"
    439260
     
    442263}
    443264
    444 neon {
    445     DEFINES += QT_HAVE_NEON
    446     HEADERS += painting/qdrawhelper_neon_p.h
    447     SOURCES += painting/qdrawhelper_neon.cpp
    448     QMAKE_CXXFLAGS *= -mfpu=neon
    449 }
    450 
    451 contains(QT_CONFIG, zlib) {
    452    INCLUDEPATH += ../3rdparty/zlib
    453 } else:!contains(QT_CONFIG, no-zlib) {
    454    unix:LIBS_PRIVATE += -lz
    455 #  win32:LIBS += libz.lib
    456 }
    457 
     265NEON_SOURCES += painting/qdrawhelper_neon.cpp
     266NEON_HEADERS += painting/qdrawhelper_neon_p.h
     267NEON_ASM += ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S
     268
     269include($$PWD/../../3rdparty/zlib_dependency.pri)
  • trunk/src/gui/painting/qbackingstore.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    264264    const QPoint pos(tlwOffset + widget->mapTo(tlw, rect.topLeft()));
    265265    const QRect tlwRect(QRect(pos, rect.size()));
    266     if (dirty.intersects(tlwRect))
     266    if (fullUpdatePending || dirty.intersects(tlwRect))
    267267        return false; // We don't want to scroll junk.
    268268    return windowSurface->scroll(tlwRect, dx, dy);
     
    353353    dirtyOnScreen += toClean;
    354354
    355 #ifdef Q_WS_QWS
     355#if defined(Q_WS_QWS) && !defined(Q_BACKINGSTORE_SUBSURFACES)
    356356    toClean.translate(tlwOffset);
    357357#endif
     
    403403    const QRect tlwRect(topLevelRect());
    404404    const QRect surfaceGeometry(windowSurface->geometry());
    405     if (surfaceGeometry != tlwRect && surfaceGeometry.size() != tlwRect.size()) {
     405    if (fullUpdatePending || (surfaceGeometry != tlwRect && surfaceGeometry.size() != tlwRect.size())) {
    406406        if (widgetDirty) {
    407407            const QRect dirtyTlwRect = QRect(QPoint(), tlwRect.size());
     
    447447/*!
    448448    Returns the static content inside the \a parent if non-zero; otherwise the static content
    449     for the entire backing store is returned. The content will be clipped to \a withingClipRect
     449    for the entire backing store is returned. The content will be clipped to \a withinClipRect
    450450    if non-empty.
    451451*/
     
    553553        if (!eventAlreadyPosted || updateImmediately)
    554554            sendUpdateRequest(widget, updateImmediately);
     555        return;
     556    }
     557
     558    if (fullUpdatePending) {
     559        if (updateImmediately)
     560            sendUpdateRequest(tlw, updateImmediately);
     561        return;
     562    }
     563
     564    if (!windowSurface->hasPartialUpdateSupport()) {
     565        fullUpdatePending = true;
     566        sendUpdateRequest(tlw, updateImmediately);
    555567        return;
    556568    }
     
    639651    }
    640652
     653    if (fullUpdatePending) {
     654        if (updateImmediately)
     655            sendUpdateRequest(tlw, updateImmediately);
     656        return;
     657    }
     658
     659    if (!windowSurface->hasPartialUpdateSupport()) {
     660        fullUpdatePending = true;
     661        sendUpdateRequest(tlw, updateImmediately);
     662        return;
     663    }
     664
    641665    const QRect widgetRect = widget->d_func()->effectiveRectFor(rect);
    642666    const QRect translatedRect(widgetRect.translated(widget->mapTo(tlw, QPoint())));
     
    834858QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel)
    835859    : tlw(topLevel), dirtyOnScreenWidgets(0), hasDirtyFromPreviousSync(false)
     860    , fullUpdatePending(0)
    836861{
    837862    windowSurface = tlw->windowSurface();
     
    885910    QRect clipR(pd->clipRect());
    886911#ifdef Q_WS_QWS
    887     QWidgetBackingStore *wbs = x->backingStore;
     912    QWidgetBackingStore *wbs = x->backingStore.data();
    888913    QWSWindowSurface *surface = static_cast<QWSWindowSurface*>(wbs->windowSurface);
    889914    clipR = clipR.intersected(surface->clipRegion().translated(-toplevelOffset).boundingRect());
     
    915940    } else {
    916941
    917         QWidgetBackingStore *wbs = x->backingStore;
     942        QWidgetBackingStore *wbs = x->backingStore.data();
    918943        QRegion childExpose(newRect & clipR);
    919944
     
    958983        return;
    959984
    960     QWidgetBackingStore *wbs = x->backingStore;
     985    QWidgetBackingStore *wbs = x->backingStore.data();
    961986    if (!wbs)
    962987        return;
     
    11231148                resetWidget(dirtyWidgets.at(i));
    11241149            dirtyWidgets.clear();
     1150            fullUpdatePending = false;
    11251151        }
    11261152        return;
     
    11331159    bool repaintAllWidgets = false;
    11341160
    1135     if (inTopLevelResize || surfaceGeometry != tlwRect) {
    1136         if ((inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) && !updatesDisabled) {
    1137             if (hasStaticContents()) {
    1138                 // Repaint existing dirty area and newly visible area.
    1139                 const QRect clipRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height());
    1140                 const QRegion staticRegion(staticContents(0, clipRect));
    1141                 QRegion newVisible(0, 0, tlwRect.width(), tlwRect.height());
    1142                 newVisible -= staticRegion;
    1143                 dirty += newVisible;
    1144                 windowSurface->setStaticContents(staticRegion);
    1145             } else {
    1146                 // Repaint everything.
    1147                 dirty = QRegion(0, 0, tlwRect.width(), tlwRect.height());
    1148                 for (int i = 0; i < dirtyWidgets.size(); ++i)
    1149                     resetWidget(dirtyWidgets.at(i));
    1150                 dirtyWidgets.clear();
    1151                 repaintAllWidgets = true;
    1152             }
    1153         }
     1161    if ((fullUpdatePending || inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) && !updatesDisabled) {
     1162        if (hasStaticContents()) {
     1163            // Repaint existing dirty area and newly visible area.
     1164            const QRect clipRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height());
     1165            const QRegion staticRegion(staticContents(0, clipRect));
     1166            QRegion newVisible(0, 0, tlwRect.width(), tlwRect.height());
     1167            newVisible -= staticRegion;
     1168            dirty += newVisible;
     1169            windowSurface->setStaticContents(staticRegion);
     1170        } else {
     1171            // Repaint everything.
     1172            dirty = QRegion(0, 0, tlwRect.width(), tlwRect.height());
     1173            for (int i = 0; i < dirtyWidgets.size(); ++i)
     1174                resetWidget(dirtyWidgets.at(i));
     1175            dirtyWidgets.clear();
     1176            repaintAllWidgets = true;
     1177        }
     1178    }
     1179
     1180    if (inTopLevelResize || surfaceGeometry != tlwRect)
    11541181        windowSurface->setGeometry(tlwRect);
    1155     }
    11561182
    11571183    if (updatesDisabled)
     
    12131239    dirtyWidgets.clear();
    12141240
     1241    fullUpdatePending = false;
     1242
    12151243    if (toClean.isEmpty()) {
    12161244        // Nothing to repaint. However, we might have newly exposed areas on the
     
    12671295        QWindowSurface *subSurface = w->windowSurface();
    12681296        BeginPaintInfo beginPaintInfo;
    1269         beginPaint(toBePainted, w, subSurface, &beginPaintInfo, false);
     1297
     1298        QPoint off = w->mapTo(tlw, QPoint());
     1299        toBePainted.translate(off);
     1300        beginPaint(toBePainted, w, subSurface, &beginPaintInfo, true);
     1301        toBePainted.translate(-off);
     1302
    12701303        if (beginPaintInfo.nothingToPaint)
    12711304            continue;
  • trunk/src/gui/painting/qbackingstore_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    9292    {
    9393        return !(dirtyWidgets.isEmpty() && dirty.isEmpty() && !hasDirtyFromPreviousSync
     94                 && !fullUpdatePending
    9495#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER)
    9596                 && !hasDirtyWindowDecoration()
     
    116117    QList<QWindowSurface*> subSurfaces;
    117118#endif
    118     bool hasDirtyFromPreviousSync;
     119    uint hasDirtyFromPreviousSync : 1;
     120    uint fullUpdatePending : 1;
    119121
    120122    QPoint tlwOffset;
  • trunk/src/gui/painting/qbezier.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    9494  \internal
    9595*/
    96 QPolygonF QBezier::toPolygon() const
     96QPolygonF QBezier::toPolygon(qreal bezier_flattening_threshold) const
    9797{
    9898    // flattening is done by splitting the bezier until we can replace the segment by a straight
     
    109109    QPolygonF polygon;
    110110    polygon.append(QPointF(x1, y1));
    111     addToPolygon(&polygon);
     111    addToPolygon(&polygon, bezier_flattening_threshold);
    112112    return polygon;
    113113}
    114114
    115 //0.5 is really low
    116 static const qreal flatness = 0.5;
    117 
    118 //based on "Fast, precise flattening of cubic Bezier path and offset curves"
    119 //      by T. F. Hain, A. L. Ahmad, S. V. R. Racherla and D. D. Langan
    120 static inline void flattenBezierWithoutInflections(QBezier &bez,
    121                                                    QPolygonF *&p)
    122 {
    123     QBezier left;
    124 
    125     while (1) {
    126         qreal dx = bez.x2 - bez.x1;
    127         qreal dy = bez.y2 - bez.y1;
    128 
    129         qreal normalized = qSqrt(dx * dx + dy * dy);
    130         if (qFuzzyIsNull(normalized))
    131            break;
    132 
    133         qreal d = qAbs(dx * (bez.y3 - bez.y2) - dy * (bez.x3 - bez.x2));
    134 
    135         qreal t = qSqrt(4. / 3. * normalized * flatness / d);
    136         if (t > 1 || qFuzzyIsNull(t - (qreal)1.))
    137             break;
    138         bez.parameterSplitLeft(t, &left);
    139         p->append(bez.pt1());
    140     }
    141 }
    142 
     115QBezier QBezier::mapBy(const QTransform &transform) const
     116{
     117    return QBezier::fromPoints(transform.map(pt1()), transform.map(pt2()), transform.map(pt3()), transform.map(pt4()));
     118}
     119
     120QBezier QBezier::getSubRange(qreal t0, qreal t1) const
     121{
     122    QBezier result;
     123    QBezier temp;
     124
     125    // cut at t1
     126    if (qFuzzyIsNull(t1 - qreal(1.))) {
     127        result = *this;
     128    } else {
     129        temp = *this;
     130        temp.parameterSplitLeft(t1, &result);
     131    }
     132
     133    // cut at t0
     134    if (!qFuzzyIsNull(t0))
     135        result.parameterSplitLeft(t0 / t1, &temp);
     136
     137    return result;
     138}
    143139
    144140static inline int quadraticRoots(qreal a, qreal b, qreal c,
     
    200196
    201197
    202 void QBezier::addToPolygon(QPolygonF *polygon) const
     198void QBezier::addToPolygon(QPolygonF *polygon, qreal bezier_flattening_threshold) const
    203199{
    204200    QBezier beziers[32];
     
    220216            l = 1.;
    221217        }
    222         if (d < flatness*l || b == beziers + 31) {
     218        if (d < bezier_flattening_threshold*l || b == beziers + 31) {
    223219            // good enough, we pop it off and add the endpoint
    224220            polygon->append(QPointF(b->x4, b->y4));
     
    228224            b->split(b+1, b);
    229225            ++b;
    230         }
    231     }
    232 }
    233 
    234 void QBezier::addToPolygonMixed(QPolygonF *polygon) const
    235 {
    236     qreal ax = -x1 + 3*x2 - 3*x3 + x4;
    237     qreal ay = -y1 + 3*y2 - 3*y3 + y4;
    238     qreal bx = 3*x1 - 6*x2 + 3*x3;
    239     qreal by = 3*y1 - 6*y2 + 3*y3;
    240     qreal cx = -3*x1 + 3*x2;
    241     qreal cy = -3*y1 + 2*y2;
    242     qreal a = 6 * (ay * bx - ax * by);
    243     qreal b = 6 * (ay * cx - ax * cy);
    244     qreal c = 2 * (by * cx - bx * cy);
    245 
    246     if ((qFuzzyIsNull(a) && qFuzzyIsNull(b)) ||
    247         (b * b - 4 * a *c) < 0) {
    248         QBezier bez(*this);
    249         flattenBezierWithoutInflections(bez, polygon);
    250         polygon->append(QPointF(x4, y4));
    251     } else {
    252         QBezier beziers[32];
    253         beziers[0] = *this;
    254         QBezier *b = beziers;
    255 
    256         while (b >= beziers) {
    257             // check if we can pop the top bezier curve from the stack
    258             qreal y4y1 = b->y4 - b->y1;
    259             qreal x4x1 = b->x4 - b->x1;
    260             qreal l = qAbs(x4x1) + qAbs(y4y1);
    261             qreal d;
    262             if (l > 1.) {
    263                 d = qAbs( (x4x1)*(b->y1 - b->y2) - (y4y1)*(b->x1 - b->x2) )
    264                     + qAbs( (x4x1)*(b->y1 - b->y3) - (y4y1)*(b->x1 - b->x3) );
    265             } else {
    266                 d = qAbs(b->x1 - b->x2) + qAbs(b->y1 - b->y2) +
    267                     qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3);
    268                 l = 1.;
    269             }
    270             if (d < .5*l || b == beziers + 31) {
    271                 // good enough, we pop it off and add the endpoint
    272                 polygon->append(QPointF(b->x4, b->y4));
    273                 --b;
    274             } else {
    275                 // split, second half of the polygon goes lower into the stack
    276                 b->split(b+1, b);
    277                 ++b;
    278             }
    279226        }
    280227    }
     
    347294}
    348295
    349 static inline QLineF qline_shifted(const QPointF &p1, const QPointF &p2, qreal offset)
    350 {
    351     QLineF l(p1, p2);
    352     QLineF ln = l.normalVector().unitVector();
    353     l.translate(ln.dx() * offset, ln.dy() * offset);
    354     return l;
    355 }
    356 
    357 static bool qbezier_is_line(QPointF *points, int pointCount)
    358 {
    359     Q_ASSERT(pointCount > 2);
    360 
    361     qreal dx13 = points[2].x() - points[0].x();
    362     qreal dy13 = points[2].y() - points[0].y();
    363 
    364     qreal dx12 = points[1].x() - points[0].x();
    365     qreal dy12 = points[1].y() - points[0].y();
    366 
    367     if (pointCount == 3) {
    368         return qFuzzyCompare(dx12 * dy13, dx13 * dy12);
    369     } else if (pointCount == 4) {
    370         qreal dx14 = points[3].x() - points[0].x();
    371         qreal dy14 = points[3].y() - points[0].y();
    372 
    373         return (qFuzzyCompare(dx12 * dy13, dx13 * dy12) && qFuzzyCompare(dx12 * dy14, dx14 * dy12));
    374     }
    375 
    376     return false;
    377 }
    378 
    379296static ShiftResult shift(const QBezier *orig, QBezier *shifted, qreal offset, qreal threshold)
    380297{
     
    406323    if (np == 1)
    407324        return Discard;
    408 
    409     // We need to specialcase lines of 3 or 4 points due to numerical
    410     // instability in intersections below
    411     if (np > 2 && qbezier_is_line(points, np)) {
    412         if (points[0] == points[np-1])
    413             return Discard;
    414 
    415         QLineF l = qline_shifted(points[0], points[np-1], offset);
    416         *shifted = QBezier::fromPoints(l.p1(), l.pointAt(qreal(0.33)), l.pointAt(qreal(0.66)), l.p2());
    417         return Ok;
    418     }
    419325
    420326    QRectF b = orig->bounds();
     
    589495}
    590496
    591 #if 0
    592 static inline bool IntersectBB(const QBezier &a, const QBezier &b)
    593 {
    594     return a.bounds().intersects(b.bounds());
    595 }
    596 #else
    597 static int IntersectBB(const QBezier &a, const QBezier &b)
    598 {
    599     // Compute bounding box for a
    600     qreal minax, maxax, minay, maxay;
    601     if (a.x1 > a.x4)     // These are the most likely to be extremal
    602         minax = a.x4, maxax = a.x1;
    603     else
    604         minax = a.x1, maxax = a.x4;
    605 
    606     if (a.x3 < minax)
    607         minax = a.x3;
    608     else if (a.x3 > maxax)
    609         maxax = a.x3;
    610 
    611     if (a.x2 < minax)
    612         minax = a.x2;
    613     else if (a.x2 > maxax)
    614         maxax = a.x2;
    615 
    616     if (a.y1 > a.y4)
    617         minay = a.y4, maxay = a.y1;
    618     else
    619         minay = a.y1, maxay = a.y4;
    620 
    621     if (a.y3 < minay)
    622         minay = a.y3;
    623     else if (a.y3 > maxay)
    624         maxay = a.y3;
    625 
    626     if (a.y2 < minay)
    627         minay = a.y2;
    628     else if (a.y2 > maxay)
    629         maxay = a.y2;
    630 
    631     // Compute bounding box for b
    632     qreal minbx, maxbx, minby, maxby;
    633     if (b.x1 > b.x4)
    634         minbx = b.x4, maxbx = b.x1;
    635     else
    636         minbx = b.x1, maxbx = b.x4;
    637 
    638     if (b.x3 < minbx)
    639         minbx = b.x3;
    640     else if (b.x3 > maxbx)
    641         maxbx = b.x3;
    642 
    643     if (b.x2 < minbx)
    644         minbx = b.x2;
    645     else if (b.x2 > maxbx)
    646         maxbx = b.x2;
    647 
    648     if (b.y1 > b.y4)
    649         minby = b.y4, maxby = b.y1;
    650     else
    651         minby = b.y1, maxby = b.y4;
    652 
    653     if (b.y3 < minby)
    654         minby = b.y3;
    655     else if (b.y3 > maxby)
    656         maxby = b.y3;
    657 
    658     if (b.y2 < minby)
    659         minby = b.y2;
    660     else if (b.y2 > maxby)
    661         maxby = b.y2;
    662 
    663     // Test bounding box of b against bounding box of a
    664     if ((minax > maxbx) || (minay > maxby)  // Not >= : need boundary case
    665         || (minbx > maxax) || (minby > maxay))
    666         return 0; // they don't intersect
    667     else
    668         return 1; // they intersect
    669 }
    670 #endif
    671 
    672 
    673497#ifdef QDEBUG_BEZIER
    674498static QDebug operator<<(QDebug dbg, const QBezier &bz)
     
    682506#endif
    683507
    684 static bool RecursivelyIntersect(const QBezier &a, qreal t0, qreal t1, int deptha,
    685                                  const QBezier &b, qreal u0, qreal u1, int depthb,
    686                                  QVector<QPair<qreal, qreal> > *t)
    687 {
    688 #ifdef QDEBUG_BEZIER
    689     static int I = 0;
    690     int currentD = I;
    691     fprintf(stderr, "%d) t0 = %lf, t1 = %lf, deptha = %d\n"
    692             "u0 = %lf, u1 = %lf, depthb = %d\n", I++, t0, t1, deptha,
    693             u0, u1, depthb);
    694 #endif
    695     if (deptha > 0) {
    696         QBezier A[2];
    697         a.split(&A[0], &A[1]);
    698         qreal tmid = (t0+t1)*0.5;
    699         //qDebug()<<"\t1)"<<A[0];
    700         //qDebug()<<"\t2)"<<A[1];
    701         deptha--;
    702         if (depthb > 0) {
    703             QBezier B[2];
    704             b.split(&B[0], &B[1]);
    705             //qDebug()<<"\t3)"<<B[0];
    706             //qDebug()<<"\t4)"<<B[1];
    707             qreal umid = (u0+u1)*0.5;
    708             depthb--;
    709             if (IntersectBB(A[0], B[0])) {
    710                 //fprintf(stderr, "\t 1 from %d\n", currentD);
    711                 if (RecursivelyIntersect(A[0], t0, tmid, deptha,
    712                                      B[0], u0, umid, depthb,
    713                                      t) && !t)
    714                     return true;
    715             }
    716             if (IntersectBB(A[1], B[0])) {
    717                 //fprintf(stderr, "\t 2 from %d\n", currentD);
    718                 if (RecursivelyIntersect(A[1], tmid, t1, deptha,
    719                                      B[0], u0, umid, depthb,
    720                                      t) && !t)
    721                     return true;
    722             }
    723             if (IntersectBB(A[0], B[1])) {
    724                 //fprintf(stderr, "\t 3 from %d\n", currentD);
    725                 if (RecursivelyIntersect(A[0], t0, tmid, deptha,
    726                                      B[1], umid, u1, depthb,
    727                                      t) && !t)
    728                     return true;
    729             }
    730             if (IntersectBB(A[1], B[1])) {
    731                 //fprintf(stderr, "\t 4 from %d\n", currentD);
    732                 if (RecursivelyIntersect(A[1], tmid, t1, deptha,
    733                                      B[1], umid, u1, depthb,
    734                                      t) && !t)
    735                     return true;
    736             }
    737             return t ? !t->isEmpty() : false;
    738         } else {
    739             if (IntersectBB(A[0], b)) {
    740                 //fprintf(stderr, "\t 5 from %d\n", currentD);
    741                 if (RecursivelyIntersect(A[0], t0, tmid, deptha,
    742                                      b, u0, u1, depthb,
    743                                      t) && !t)
    744                     return true;
    745             }
    746             if (IntersectBB(A[1], b)) {
    747                 //fprintf(stderr, "\t 6 from %d\n", currentD);
    748                 if (RecursivelyIntersect(A[1], tmid, t1, deptha,
    749                                      b, u0, u1, depthb,
    750                                      t) && !t)
    751                     return true;
    752             }
    753             return t ? !t->isEmpty() : false;
    754         }
    755     } else {
    756         if (depthb > 0) {
    757             QBezier B[2];
    758             b.split(&B[0], &B[1]);
    759             qreal umid = (u0 + u1)*0.5;
    760             depthb--;
    761             if (IntersectBB(a, B[0])) {
    762                 //fprintf(stderr, "\t 7 from %d\n", currentD);
    763                 if (RecursivelyIntersect(a, t0, t1, deptha,
    764                                      B[0], u0, umid, depthb,
    765                                      t) && !t)
    766                     return true;
    767             }
    768             if (IntersectBB(a, B[1])) {
    769                 //fprintf(stderr, "\t 8 from %d\n", currentD);
    770                 if (RecursivelyIntersect(a, t0, t1, deptha,
    771                                      B[1], umid, u1, depthb,
    772                                      t) && !t)
    773                     return true;
    774             }
    775             return t ? !t->isEmpty() : false;
    776         }
    777         else {
    778             // Both segments are fully subdivided; now do line segments
    779             qreal xlk = a.x4 - a.x1;
    780             qreal ylk = a.y4 - a.y1;
    781             qreal xnm = b.x4 - b.x1;
    782             qreal ynm = b.y4 - b.y1;
    783             qreal xmk = b.x1 - a.x1;
    784             qreal ymk = b.y1 - a.y1;
    785             qreal det = xnm * ylk - ynm * xlk;
    786             if (1.0 + det == 1.0) {
    787                 return false;
    788             } else {
    789                 qreal detinv = 1.0 / det;
    790                 qreal rs = (xnm * ymk - ynm *xmk) * detinv;
    791                 qreal rt = (xlk * ymk - ylk * xmk) * detinv;
    792                 if ((rs < 0.0) || (rs > 1.0) || (rt < 0.0) || (rt > 1.0))
    793                     return false;
    794 
    795                 if (t) {
    796                     const qreal alpha_a = t0 + rs * (t1 - t0);
    797                     const qreal alpha_b = u0 + rt * (u1 - u0);
    798 
    799                     *t << qMakePair(alpha_a, alpha_b);
    800                 }
    801 
    802                 return true;
    803             }
    804         }
    805     }
    806 }
    807 
    808 QVector< QPair<qreal, qreal> > QBezier::findIntersections(const QBezier &a, const QBezier &b)
    809 {
    810     QVector< QPair<qreal, qreal> > v(2);
    811     findIntersections(a, b, &v);
    812     return v;
    813 }
    814 
    815 bool QBezier::findIntersections(const QBezier &a, const QBezier &b,
    816                                 QVector<QPair<qreal, qreal> > *t)
    817 {
    818     if (IntersectBB(a, b)) {
    819         QPointF la1(qFabs((a.x3 - a.x2) - (a.x2 - a.x1)),
    820                     qFabs((a.y3 - a.y2) - (a.y2 - a.y1)));
    821         QPointF la2(qFabs((a.x4 - a.x3) - (a.x3 - a.x2)),
    822                     qFabs((a.y4 - a.y3) - (a.y3 - a.y2)));
    823         QPointF la;
    824         if (la1.x() > la2.x()) la.setX(la1.x()); else la.setX(la2.x());
    825         if (la1.y() > la2.y()) la.setY(la1.y()); else la.setY(la2.y());
    826         QPointF lb1(qFabs((b.x3 - b.x2) - (b.x2 - b.x1)),
    827                     qFabs((b.y3 - b.y2) - (b.y2 - b.y1)));
    828         QPointF lb2(qFabs((b.x4 - b.x3) - (b.x3 - b.x2)),
    829                     qFabs((b.y4 - b.y3) - (b.y3 - b.y2)));
    830         QPointF lb;
    831         if (lb1.x() > lb2.x()) lb.setX(lb1.x()); else lb.setX(lb2.x());
    832         if (lb1.y() > lb2.y()) lb.setY(lb1.y()); else lb.setY(lb2.y());
    833         qreal l0;
    834         if (la.x() > la.y())
    835             l0 = la.x();
    836         else
    837             l0 = la.y();
    838         int ra;
    839         if (l0 * 0.75 * M_SQRT2 + 1.0 == 1.0)
    840             ra = 0;
    841         else
    842             ra = qCeil(log4(M_SQRT2 * 6.0 / 8.0 * INV_EPS * l0));
    843         if (lb.x() > lb.y())
    844             l0 = lb.x();
    845         else
    846             l0 = lb.y();
    847         int rb;
    848         if (l0 * 0.75 * M_SQRT2 + 1.0 == 1.0)
    849             rb = 0;
    850         else
    851             rb = qCeil(log4(M_SQRT2 * 6.0 / 8.0 * INV_EPS * l0));
    852 
    853         // if qreal is float then halve the number of subdivisions
    854         if (sizeof(qreal) == 4) {
    855             ra /= 2;
    856             rb /= 2;
    857         }
    858 
    859         return RecursivelyIntersect(a, 0., 1., ra, b, 0., 1., rb, t);
    860     }
    861 
    862     //Don't sort here because it breaks the orders of corresponding
    863     //  intersections points. this way t's at the same locations correspond
    864     //  to the same intersection point.
    865     //qSort(parameters[0].begin(), parameters[0].end(), qLess<qreal>());
    866     //qSort(parameters[1].begin(), parameters[1].end(), qLess<qreal>());
    867 
    868     return false;
    869 }
    870 
    871508static inline void splitBezierAt(const QBezier &bez, qreal t,
    872509                                 QBezier *left, QBezier *right)
     
    895532    right->x4 = bez.x4;
    896533    right->y4 = bez.y4;
    897 }
    898 
    899 QVector< QList<QBezier> > QBezier::splitAtIntersections(QBezier &b)
    900 {
    901     QVector< QList<QBezier> > curves(2);
    902 
    903     QVector< QPair<qreal, qreal> > allInters = findIntersections(*this, b);
    904 
    905     QList<qreal> inters1;
    906     QList<qreal> inters2;
    907 
    908     for (int i = 0; i < allInters.size(); ++i) {
    909         inters1 << allInters[i].first;
    910         inters2 << allInters[i].second;
    911     }
    912 
    913     qSort(inters1.begin(), inters1.end(), qLess<qreal>());
    914     qSort(inters2.begin(), inters2.end(), qLess<qreal>());
    915 
    916     Q_ASSERT(inters1.count() == inters2.count());
    917 
    918     int i;
    919     for (i = 0; i < inters1.count(); ++i) {
    920         qreal t1 = inters1.at(i);
    921         qreal t2 = inters2.at(i);
    922 
    923         QBezier curve1, curve2;
    924         parameterSplitLeft(t1, &curve1);
    925         b.parameterSplitLeft(t2, &curve2);
    926         curves[0].append(curve1);
    927         curves[0].append(curve2);
    928     }
    929     curves[0].append(*this);
    930     curves[1].append(b);
    931 
    932     return curves;
    933534}
    934535
     
    1019620    const qreal c = -y1 + y2;
    1020621
     622    if (qFuzzyIsNull(a)) {
     623        if (qFuzzyIsNull(b))
     624            return 0;
     625
     626        t0 = -c / b;
     627        return t0 > 0 && t0 < 1;
     628    }
     629
    1021630    qreal reciprocal = b * b - 4 * a * c;
    1022 
    1023     QList<qreal> result;
    1024631
    1025632    if (qFuzzyIsNull(reciprocal)) {
    1026633        t0 = -b / (2 * a);
    1027         return 1;
     634        return t0 > 0 && t0 < 1;
    1028635    } else if (reciprocal > 0) {
    1029636        qreal temp = qSqrt(reciprocal);
     
    1100707}
    1101708
    1102 
    1103 static inline void bindInflectionPoint(const QBezier &bez, const qreal t,
    1104                                        qreal *tMinus , qreal *tPlus)
    1105 {
    1106     if (t <= 0) {
    1107         *tMinus = *tPlus = -1;
    1108         return;
    1109     } else if (t >= 1) {
    1110         *tMinus = *tPlus = 2;
    1111         return;
    1112     }
    1113 
    1114     QBezier left, right;
    1115     splitBezierAt(bez, t, &left, &right);
    1116 
    1117     qreal ax = -right.x1 + 3*right.x2 - 3*right.x3 + right.x4;
    1118     qreal ay = -right.y1 + 3*right.y2 - 3*right.y3 + right.y4;
    1119     qreal ex = 3 * (right.x2 - right.x3);
    1120     qreal ey = 3 * (right.y2 - right.y3);
    1121 
    1122     qreal s4 = qAbs(6 * (ey * ax - ex * ay) / qSqrt(ex * ex + ey * ey)) + 0.00001f;
    1123     qreal tf = qPow(qreal(9 * flatness / s4), qreal(1./3.));
    1124     *tMinus = t - (1 - t) * tf;
    1125     *tPlus  = t + (1 - t) * tf;
    1126 }
    1127 
    1128 void QBezier::addToPolygonIterative(QPolygonF *p) const
    1129 {
    1130     qreal t1, t2, tcusp;
    1131     qreal t1min, t1plus, t2min, t2plus;
    1132 
    1133     qreal ax = -x1 + 3*x2 - 3*x3 + x4;
    1134     qreal ay = -y1 + 3*y2 - 3*y3 + y4;
    1135     qreal bx = 3*x1 - 6*x2 + 3*x3;
    1136     qreal by = 3*y1 - 6*y2 + 3*y3;
    1137     qreal cx = -3*x1 + 3*x2;
    1138     qreal cy = -3*y1 + 2*y2;
    1139 
    1140     if (findInflections(6 * (ay * bx - ax * by),
    1141                         6 * (ay * cx - ax * cy),
    1142                         2 * (by * cx - bx * cy),
    1143                         &t1, &t2, &tcusp)) {
    1144         bindInflectionPoint(*this, t1, &t1min, &t1plus);
    1145         bindInflectionPoint(*this, t2, &t2min, &t2plus);
    1146 
    1147         QBezier tmpBez = *this;
    1148         QBezier left, right, bez1, bez2, bez3;
    1149         if (t1min > 0) {
    1150             if (t1min >= 1) {
    1151                 flattenBezierWithoutInflections(tmpBez, p);
    1152             } else {
    1153                 splitBezierAt(tmpBez, t1min, &left, &right);
    1154                 flattenBezierWithoutInflections(left, p);
    1155                 p->append(tmpBez.pointAt(t1min));
    1156 
    1157                 if (t2min < t1plus) {
    1158                     if (tcusp < 1) {
    1159                         p->append(tmpBez.pointAt(tcusp));
    1160                     }
    1161                     if (t2plus < 1) {
    1162                         splitBezierAt(tmpBez, t2plus, &left, &right);
    1163                         flattenBezierWithoutInflections(right, p);
    1164                     }
    1165                 } else if (t1plus < 1) {
    1166                     if (t2min < 1) {
    1167                         splitBezierAt(tmpBez, t2min, &bez3, &right);
    1168                         splitBezierAt(bez3, t1plus, &left, &bez2);
    1169 
    1170                         flattenBezierWithoutInflections(bez2, p);
    1171                         p->append(tmpBez.pointAt(t2min));
    1172 
    1173                         if (t2plus < 1) {
    1174                             splitBezierAt(tmpBez, t2plus, &left, &bez2);
    1175                             flattenBezierWithoutInflections(bez2, p);
    1176                         }
    1177                     } else {
    1178                         splitBezierAt(tmpBez, t1plus, &left, &bez2);
    1179                         flattenBezierWithoutInflections(bez2, p);
    1180                     }
    1181                 }
    1182             }
    1183         } else if (t1plus > 0) {
    1184             p->append(QPointF(x1, y1));
    1185             if (t2min < t1plus) {
    1186                 if (tcusp < 1) {
    1187                     p->append(tmpBez.pointAt(tcusp));
    1188                 }
    1189                 if (t2plus < 1) {
    1190                     splitBezierAt(tmpBez, t2plus, &left, &bez2);
    1191                     flattenBezierWithoutInflections(bez2, p);
    1192                 }
    1193             } else if (t1plus < 1) {
    1194                 if (t2min < 1) {
    1195                     splitBezierAt(tmpBez, t2min, &bez3, &right);
    1196                     splitBezierAt(bez3, t1plus, &left, &bez2);
    1197 
    1198                     flattenBezierWithoutInflections(bez2, p);
    1199 
    1200                     p->append(tmpBez.pointAt(t2min));
    1201                     if (t2plus < 1) {
    1202                         splitBezierAt(tmpBez, t2plus, &left, &bez2);
    1203                         flattenBezierWithoutInflections(bez2, p);
    1204                     }
    1205                 } else {
    1206                     splitBezierAt(tmpBez, t1plus, &left, &bez2);
    1207                     flattenBezierWithoutInflections(bez2, p);
    1208                 }
    1209             }
    1210         } else if (t2min > 0) {
    1211             if (t2min < 1) {
    1212                 splitBezierAt(tmpBez, t2min, &bez1, &right);
    1213                 flattenBezierWithoutInflections(bez1, p);
    1214                 p->append(tmpBez.pointAt(t2min));
    1215 
    1216                 if (t2plus < 1) {
    1217                     splitBezierAt(tmpBez, t2plus, &left, &bez2);
    1218                     flattenBezierWithoutInflections(bez2, p);
    1219                 }
    1220             } else {
    1221                 //### in here we should check whether the area of the
    1222                 //    triangle formed between pt1/pt2/pt3 is smaller
    1223                 //    or equal to 0 and then do iterative flattening
    1224                 //    if not we should fallback and do the recursive
    1225                 //    flattening.
    1226                 flattenBezierWithoutInflections(tmpBez, p);
    1227             }
    1228         } else if (t2plus > 0) {
    1229             p->append(QPointF(x1, y1));
    1230             if (t2plus < 1) {
    1231                 splitBezierAt(tmpBez, t2plus, &left, &bez2);
    1232                 flattenBezierWithoutInflections(bez2, p);
    1233             }
    1234         } else {
    1235             flattenBezierWithoutInflections(tmpBez, p);
    1236         }
    1237     } else {
    1238         QBezier bez = *this;
    1239         flattenBezierWithoutInflections(bez, p);
    1240     }
    1241 
    1242     p->append(QPointF(x4, y4));
    1243 }
    1244 
    1245709QT_END_NAMESPACE
  • trunk/src/gui/painting/qbezier_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6060#include "QtCore/qlist.h"
    6161#include "QtCore/qpair.h"
     62#include "QtGui/qtransform.h"
    6263
    6364QT_BEGIN_NAMESPACE
     
    7980    inline QPointF secondDerivedAt(qreal t) const;
    8081
    81     QPolygonF toPolygon() const;
    82     void addToPolygon(QPolygonF *p) const;
    83     void addToPolygonIterative(QPolygonF *p) const;
    84     void addToPolygonMixed(QPolygonF *p) const;
     82    QPolygonF toPolygon(qreal bezier_flattening_threshold = 0.5) const;
     83    void addToPolygon(QPolygonF *p, qreal bezier_flattening_threshold = 0.5) const;
     84
    8585    QRectF bounds() const;
    8686    qreal length(qreal error = 0.01) const;
     
    9797    QPointF pt4() const { return QPointF(x4, y4); }
    9898
     99    QBezier mapBy(const QTransform &transform) const;
     100
    99101    inline QPointF midPoint() const;
    100102    inline QLineF midTangent() const;
     
    105107    inline void parameterSplitLeft(qreal t, QBezier *left);
    106108    inline void split(QBezier *firstHalf, QBezier *secondHalf) const;
     109
    107110    int shifted(QBezier *curveSegments, int maxSegmets,
    108111                qreal offset, float threshold) const;
    109112
    110     QVector< QList<QBezier> > splitAtIntersections(QBezier &a);
    111 
    112113    QBezier bezierOnInterval(qreal t0, qreal t1) const;
    113 
    114     static QVector< QPair<qreal, qreal> > findIntersections(const QBezier &a,
    115                                                      const QBezier &b);
    116 
    117     static bool findIntersections(const QBezier &a, const QBezier &b,
    118                                   QVector<QPair<qreal, qreal> > *t);
     114    QBezier getSubRange(qreal t0, qreal t1) const;
    119115
    120116    qreal x1, y1, x2, y2, x3, y3, x4, y4;
  • trunk/src/gui/painting/qblendfunctions.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4141
    4242#include <qmath.h>
    43 #include "qdrawhelper_p.h"
     43#include "qblendfunctions_p.h"
    4444
    4545QT_BEGIN_NAMESPACE
     
    8989struct Blend_RGB16_on_RGB16_NoAlpha {
    9090    inline void write(quint16 *dst, quint16 src) { *dst = src; }
     91
     92    inline void flush(void *) {}
    9193};
    9294
     
    100102        *dst = BYTE_MUL_RGB16(src, m_alpha) + BYTE_MUL_RGB16(*dst, m_ialpha);
    101103    }
     104
     105    inline void flush(void *) {}
    102106
    103107    quint32 m_alpha;
     
    115119        }
    116120    }
     121
     122    inline void flush(void *) {}
    117123};
    118124
     
    133139    }
    134140
     141    inline void flush(void *) {}
     142
    135143    quint32 m_alpha;
    136144};
     
    146154        }
    147155    }
     156
     157    inline void flush(void *) {}
    148158};
    149159
     
    164174    }
    165175
     176    inline void flush(void *) {}
     177
    166178    quint32 m_alpha;
    167179};
    168 
    169 template <typename SRC, typename T>
    170 void qt_scale_image_16bit(uchar *destPixels, int dbpl,
    171                           const uchar *srcPixels, int sbpl,
    172                           const QRectF &targetRect,
    173                           const QRectF &srcRect,
    174                           const QRect &clip,
    175                           T blender)
    176 {
    177     qreal sx = targetRect.width() / (qreal) srcRect.width();
    178     qreal sy = targetRect.height() / (qreal) srcRect.height();
    179 
    180     int ix = 0x00010000 / sx;
    181     int iy = 0x00010000 / sy;
    182 
    183 //     qDebug() << "scale:" << endl
    184 //              << " - target" << targetRect << endl
    185 //              << " - source" << srcRect << endl
    186 //              << " - clip" << clip << endl
    187 //              << " - sx=" << sx << " sy=" << sy << " ix=" << ix << " iy=" << iy;
    188 
    189     int cx1 = clip.x();
    190     int cx2 = clip.x() + clip.width();
    191     int cy1 = clip.top();
    192     int cy2 = clip.y() + clip.height();
    193 
    194     int tx1 = qRound(targetRect.left());
    195     int tx2 = qRound(targetRect.right());
    196     int ty1 = qRound(targetRect.top());
    197     int ty2 = qRound(targetRect.bottom());
    198 
    199     if (tx2 < tx1)
    200         qSwap(tx2, tx1);
    201 
    202     if (ty2 < ty1)
    203         qSwap(ty2, ty1);
    204 
    205     if (tx1 < cx1)
    206         tx1 = cx1;
    207 
    208     if (tx2 >= cx2)
    209         tx2 = cx2;
    210 
    211     if (tx1 >= tx2)
    212         return;
    213 
    214     if (ty1 < cy1)
    215         ty1 = cy1;
    216 
    217     if (ty2 >= cy2)
    218        ty2 = cy2;
    219 
    220     if (ty1 >= ty2)
    221         return;
    222 
    223     int h = ty2 - ty1;
    224     int w = tx2 - tx1;
    225 
    226 
    227     quint32 basex;
    228     quint32 srcy;
    229 
    230     if (sx < 0) {
    231         int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * ix) + 1;
    232         basex = quint32(srcRect.right() * 65536) + dstx;
    233     } else {
    234         int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * ix) - 1;
    235         basex = quint32(srcRect.left() * 65536) + dstx;
    236     }
    237     if (sy < 0) {
    238         int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * iy) + 1;
    239         srcy = quint32(srcRect.bottom() * 65536) + dsty;
    240     } else {
    241         int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * iy) - 1;
    242         srcy = quint32(srcRect.top() * 65536) + dsty;
    243     }
    244 
    245     quint16 *dst = ((quint16 *) (destPixels + ty1 * dbpl)) + tx1;
    246 
    247     while (h--) {
    248         const SRC *src = (const SRC *) (srcPixels + (srcy >> 16) * sbpl);
    249         int srcx = basex;
    250         for (int x=0; x<w; ++x) {
    251             blender.write(&dst[x], src[srcx >> 16]);
    252             srcx += ix;
    253         }
    254         dst = (quint16 *)(((uchar *) dst) + dbpl);
    255         srcy += iy;
    256     }
    257 }
    258180
    259181void qt_scale_image_rgb16_on_rgb16(uchar *destPixels, int dbpl,
     
    333255}
    334256
    335 static void qt_blend_rgb16_on_rgb16(uchar *dst, int dbpl,
    336                                     const uchar *src, int sbpl,
    337                                     int w, int h,
    338                                     int const_alpha)
     257void qt_blend_rgb16_on_rgb16(uchar *dst, int dbpl,
     258                             const uchar *src, int sbpl,
     259                             int w, int h,
     260                             int const_alpha)
    339261{
    340262#ifdef QT_DEBUG_DRAW
     
    448370
    449371
    450 static void qt_blend_argb32_on_rgb16_const_alpha(uchar *destPixels, int dbpl,
    451                                                  const uchar *srcPixels, int sbpl,
    452                                                  int w, int h,
    453                                                  int const_alpha)
     372void qt_blend_argb32_on_rgb16_const_alpha(uchar *destPixels, int dbpl,
     373                                          const uchar *srcPixels, int sbpl,
     374                                          int w, int h,
     375                                          int const_alpha)
    454376{
    455377    quint16 *dst = (quint16 *) destPixels;
     
    644566struct Blend_RGB32_on_RGB32_NoAlpha {
    645567    inline void write(quint32 *dst, quint32 src) { *dst = src; }
     568
     569    inline void flush(void *) {}
    646570};
    647571
     
    656580    }
    657581
     582    inline void flush(void *) {}
     583
    658584    quint32 m_alpha;
    659585    quint32 m_ialpha;
     
    664590        *dst = src + BYTE_MUL(*dst, qAlpha(~src));
    665591    }
     592
     593    inline void flush(void *) {}
    666594};
    667595
     
    677605    }
    678606
     607    inline void flush(void *) {}
     608
    679609    quint32 m_alpha;
    680610    quint32 m_ialpha;
    681611};
    682 
    683 template <typename T> void qt_scale_image_32bit(uchar *destPixels, int dbpl,
    684                                                 const uchar *srcPixels, int sbpl,
    685                                                 const QRectF &targetRect,
    686                                                 const QRectF &srcRect,
    687                                                 const QRect &clip,
    688                                                 T blender)
    689 {
    690     qreal sx = targetRect.width() / (qreal) srcRect.width();
    691     qreal sy = targetRect.height() / (qreal) srcRect.height();
    692 
    693     int ix = 0x00010000 / sx;
    694     int iy = 0x00010000 / sy;
    695 
    696 //     qDebug() << "scale:" << endl
    697 //              << " - target" << targetRect << endl
    698 //              << " - source" << srcRect << endl
    699 //              << " - clip" << clip << endl
    700 //              << " - sx=" << sx << " sy=" << sy << " ix=" << ix << " iy=" << iy;
    701 
    702     int cx1 = clip.x();
    703     int cx2 = clip.x() + clip.width();
    704     int cy1 = clip.top();
    705     int cy2 = clip.y() + clip.height();
    706 
    707     int tx1 = qRound(targetRect.left());
    708     int tx2 = qRound(targetRect.right());
    709     int ty1 = qRound(targetRect.top());
    710     int ty2 = qRound(targetRect.bottom());
    711 
    712     if (tx2 < tx1)
    713         qSwap(tx2, tx1);
    714 
    715     if (ty2 < ty1)
    716         qSwap(ty2, ty1);
    717 
    718     if (tx1 < cx1)
    719         tx1 = cx1;
    720 
    721     if (tx2 >= cx2)
    722         tx2 = cx2;
    723 
    724     if (tx1 >= tx2)
    725         return;
    726 
    727     if (ty1 < cy1)
    728         ty1 = cy1;
    729 
    730     if (ty2 >= cy2)
    731        ty2 = cy2;
    732 
    733     if (ty1 >= ty2)
    734         return;
    735 
    736     int h = ty2 - ty1;
    737     int w = tx2 - tx1;
    738 
    739     quint32 basex;
    740     quint32 srcy;
    741 
    742     if (sx < 0) {
    743         int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * ix) + 1;
    744         basex = quint32(srcRect.right() * 65536) + dstx;
    745     } else {
    746         int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * ix) - 1;
    747         basex = quint32(srcRect.left() * 65536) + dstx;
    748     }
    749     if (sy < 0) {
    750         int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * iy) + 1;
    751         srcy = quint32(srcRect.bottom() * 65536) + dsty;
    752     } else {
    753         int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * iy) - 1;
    754         srcy = quint32(srcRect.top() * 65536) + dsty;
    755     }
    756 
    757     quint32 *dst = ((quint32 *) (destPixels + ty1 * dbpl)) + tx1;
    758 
    759     while (h--) {
    760         const uint *src = (const quint32 *) (srcPixels + (srcy >> 16) * sbpl);
    761         int srcx = basex;
    762         for (int x=0; x<w; ++x) {
    763             blender.write(&dst[x], src[srcx >> 16]);
    764             srcx += ix;
    765         }
    766         dst = (quint32 *)(((uchar *) dst) + dbpl);
    767         srcy += iy;
    768     }
    769 }
    770612
    771613void qt_scale_image_rgb32_on_rgb32(uchar *destPixels, int dbpl,
     
    819661}
    820662
    821 struct QTransformImageVertex
    822 {
    823     qreal x, y, u, v; // destination coordinates (x, y) and source coordinates (u, v)
    824 };
    825 
    826 template <class SrcT, class DestT, class Blender>
    827 void qt_transform_image_rasterize(DestT *destPixels, int dbpl,
    828                                   const SrcT *srcPixels, int sbpl,
    829                                   const QTransformImageVertex &topLeft, const QTransformImageVertex &bottomLeft,
    830                                   const QTransformImageVertex &topRight, const QTransformImageVertex &bottomRight,
    831                                   const QRect &sourceRect,
    832                                   const QRect &clip,
    833                                   qreal topY, qreal bottomY,
    834                                   int dudx, int dvdx, int dudy, int dvdy, int u0, int v0,
    835                                   Blender blender)
    836 {
    837     int fromY = qMax(qRound(topY), clip.top());
    838     int toY = qMin(qRound(bottomY), clip.top() + clip.height());
    839     if (fromY >= toY)
    840         return;
    841 
    842     qreal leftSlope = (bottomLeft.x - topLeft.x) / (bottomLeft.y - topLeft.y);
    843     qreal rightSlope = (bottomRight.x - topRight.x) / (bottomRight.y - topRight.y);
    844     int dx_l = int(leftSlope * 0x10000);
    845     int dx_r = int(rightSlope * 0x10000);
    846     int x_l = int((topLeft.x + (0.5 + fromY - topLeft.y) * leftSlope + 0.5) * 0x10000);
    847     int x_r = int((topRight.x + (0.5 + fromY - topRight.y) * rightSlope + 0.5) * 0x10000);
    848 
    849     int fromX, toX, x1, x2, u, v, i, ii;
    850     DestT *line;
    851     for (int y = fromY; y < toY; ++y) {
    852         line = reinterpret_cast<DestT *>(reinterpret_cast<uchar *>(destPixels) + y * dbpl);
    853 
    854         fromX = qMax(x_l >> 16, clip.left());
    855         toX = qMin(x_r >> 16, clip.left() + clip.width());
    856         if (fromX < toX) {
    857             // Because of rounding, we can get source coordinates outside the source image.
    858             // Clamp these coordinates to the source rect to avoid segmentation fault and
    859             // garbage on the screen.
    860 
    861             // Find the first pixel on the current scan line where the source coordinates are within the source rect.
    862             x1 = fromX;
    863             u = x1 * dudx + y * dudy + u0;
    864             v = x1 * dvdx + y * dvdy + v0;
    865             for (; x1 < toX; ++x1) {
    866                 int uu = u >> 16;
    867                 int vv = v >> 16;
    868                 if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width()
    869                     && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) {
    870                     break;
    871                 }
    872                 u += dudx;
    873                 v += dvdx;
    874             }
    875 
    876             // Find the last pixel on the current scan line where the source coordinates are within the source rect.
    877             x2 = toX;
    878             u = (x2 - 1) * dudx + y * dudy + u0;
    879             v = (x2 - 1) * dvdx + y * dvdy + v0;
    880             for (; x2 > x1; --x2) {
    881                 int uu = u >> 16;
    882                 int vv = v >> 16;
    883                 if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width()
    884                     && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) {
    885                     break;
    886                 }
    887                 u -= dudx;
    888                 v -= dvdx;
    889             }
    890 
    891             // Set up values at the beginning of the scan line.
    892             u = fromX * dudx + y * dudy + u0;
    893             v = fromX * dvdx + y * dvdy + v0;
    894             line += fromX;
    895 
    896             // Beginning of the scan line, with per-pixel checks.
    897             i = x1 - fromX;
    898             while (i) {
    899                 int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1);
    900                 int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1);
    901                 blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + vv * sbpl)[uu]);
    902                 u += dudx;
    903                 v += dvdx;
    904                 ++line;
    905                 --i;
    906             }
    907 
    908             // Middle of the scan line, without checks.
    909             // Manual loop unrolling.
    910             i = x2 - x1;
    911             ii = i >> 3;
    912             while (ii) {
    913                 blender.write(&line[0], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
    914                 blender.write(&line[1], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
    915                 blender.write(&line[2], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
    916                 blender.write(&line[3], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
    917                 blender.write(&line[4], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
    918                 blender.write(&line[5], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
    919                 blender.write(&line[6], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
    920                 blender.write(&line[7], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
    921                 line += 8;
    922                 --ii;
    923             }
    924             switch (i & 7) {
    925                 case 7: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
    926                 case 6: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
    927                 case 5: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
    928                 case 4: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
    929                 case 3: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
    930                 case 2: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
    931                 case 1: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
    932             }
    933 
    934             // End of the scan line, with per-pixel checks.
    935             i = toX - x2;
    936             while (i) {
    937                 int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1);
    938                 int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1);
    939                 blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + vv * sbpl)[uu]);
    940                 u += dudx;
    941                 v += dvdx;
    942                 ++line;
    943                 --i;
    944             }
    945         }
    946         x_l += dx_l;
    947         x_r += dx_r;
    948     }
    949 }
    950 
    951 template <class SrcT, class DestT, class Blender>
    952 void qt_transform_image(DestT *destPixels, int dbpl,
    953                         const SrcT *srcPixels, int sbpl,
    954                         const QRectF &targetRect,
    955                         const QRectF &sourceRect,
    956                         const QRect &clip,
    957                         const QTransform &targetRectTransform,
    958                         Blender blender)
    959 {
    960     enum Corner
    961     {
    962         TopLeft,
    963         TopRight,
    964         BottomRight,
    965         BottomLeft
    966     };
    967 
    968     // map source rectangle to destination.
    969     QTransformImageVertex v[4];
    970     v[TopLeft].u = v[BottomLeft].u = sourceRect.left();
    971     v[TopLeft].v = v[TopRight].v = sourceRect.top();
    972     v[TopRight].u = v[BottomRight].u = sourceRect.right();
    973     v[BottomLeft].v = v[BottomRight].v = sourceRect.bottom();
    974     targetRectTransform.map(targetRect.left(), targetRect.top(), &v[TopLeft].x, &v[TopLeft].y);
    975     targetRectTransform.map(targetRect.right(), targetRect.top(), &v[TopRight].x, &v[TopRight].y);
    976     targetRectTransform.map(targetRect.left(), targetRect.bottom(), &v[BottomLeft].x, &v[BottomLeft].y);
    977     targetRectTransform.map(targetRect.right(), targetRect.bottom(), &v[BottomRight].x, &v[BottomRight].y);
    978 
    979     // find topmost vertex.
    980     int topmost = 0;
    981     for (int i = 1; i < 4; ++i) {
    982         if (v[i].y < v[topmost].y)
    983             topmost = i;
    984     }
    985     // rearrange array such that topmost vertex is at index 0.
    986     switch (topmost) {
    987     case 1:
    988         {
    989             QTransformImageVertex t = v[0];
    990             for (int i = 0; i < 3; ++i)
    991                 v[i] = v[i+1];
    992             v[3] = t;
    993         }
    994         break;
    995     case 2:
    996         qSwap(v[0], v[2]);
    997         qSwap(v[1], v[3]);
    998         break;
    999     case 3:
    1000         {
    1001             QTransformImageVertex t = v[3];
    1002             for (int i = 3; i > 0; --i)
    1003                 v[i] = v[i-1];
    1004             v[0] = t;
    1005         }
    1006         break;
    1007     }
    1008 
    1009     // if necessary, swap vertex 1 and 3 such that 1 is to the left of 3.
    1010     qreal dx1 = v[1].x - v[0].x;
    1011     qreal dy1 = v[1].y - v[0].y;
    1012     qreal dx2 = v[3].x - v[0].x;
    1013     qreal dy2 = v[3].y - v[0].y;
    1014     if (dx1 * dy2 - dx2 * dy1 > 0)
    1015         qSwap(v[1], v[3]);
    1016 
    1017     QTransformImageVertex u = {v[1].x - v[0].x, v[1].y - v[0].y, v[1].u - v[0].u, v[1].v - v[0].v};
    1018     QTransformImageVertex w = {v[2].x - v[0].x, v[2].y - v[0].y, v[2].u - v[0].u, v[2].v - v[0].v};
    1019 
    1020     qreal det = u.x * w.y - u.y * w.x;
    1021     if (det == 0)
    1022         return;
    1023 
    1024     qreal invDet = 1.0 / det;
    1025     qreal m11, m12, m21, m22, mdx, mdy;
    1026 
    1027     m11 = (u.u * w.y - u.y * w.u) * invDet;
    1028     m12 = (u.x * w.u - u.u * w.x) * invDet;
    1029     m21 = (u.v * w.y - u.y * w.v) * invDet;
    1030     m22 = (u.x * w.v - u.v * w.x) * invDet;
    1031     mdx = v[0].u - m11 * v[0].x - m12 * v[0].y;
    1032     mdy = v[0].v - m21 * v[0].x - m22 * v[0].y;
    1033 
    1034     int dudx = int(m11 * 0x10000);
    1035     int dvdx = int(m21 * 0x10000);
    1036     int dudy = int(m12 * 0x10000);
    1037     int dvdy = int(m22 * 0x10000);
    1038     int u0 = qCeil((0.5 * m11 + 0.5 * m12 + mdx) * 0x10000) - 1;
    1039     int v0 = qCeil((0.5 * m21 + 0.5 * m22 + mdy) * 0x10000) - 1;
    1040 
    1041     int x1 = qFloor(sourceRect.left());
    1042     int y1 = qFloor(sourceRect.top());
    1043     int x2 = qCeil(sourceRect.right());
    1044     int y2 = qCeil(sourceRect.bottom());
    1045     QRect sourceRectI(x1, y1, x2 - x1, y2 - y1);
    1046 
    1047     // rasterize trapezoids.
    1048     if (v[1].y < v[3].y) {
    1049         qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[0], v[3], sourceRectI, clip, v[0].y, v[1].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
    1050         qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[0], v[3], sourceRectI, clip, v[1].y, v[3].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
    1051         qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[3], v[2], sourceRectI, clip, v[3].y, v[2].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
    1052     } else {
    1053         qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[0], v[3], sourceRectI, clip, v[0].y, v[3].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
    1054         qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[3], v[2], sourceRectI, clip, v[3].y, v[1].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
    1055         qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[3], v[2], sourceRectI, clip, v[1].y, v[2].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
    1056     }
    1057 }
    1058 
    1059663void qt_transform_image_rgb16_on_rgb16(uchar *destPixels, int dbpl,
    1060664                                       const uchar *srcPixels, int sbpl,
  • trunk/src/gui/painting/qbrush.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4949#include "qdebug.h"
    5050#include <QtCore/qcoreapplication.h>
     51#include "private/qstylehelper_p.h"
    5152
    5253QT_BEGIN_NAMESPACE
     
    9798QPixmap qt_pixmapForBrush(int brushStyle, bool invert)
    9899{
     100
    99101    QPixmap pm;
    100     QString key = QLatin1String("$qt-brush$") + QString::number(brushStyle)
    101                   + QString::number((int)invert);
     102    QString key = QLatin1Literal("$qt-brush$")
     103                  % HexString<uint>(brushStyle)
     104                  % QLatin1Char(invert ? '1' : '0');
    102105    if (!QPixmapCache::find(key, pm)) {
    103106        pm = QBitmap::fromData(QSize(8, 8), qt_patternForBrush(brushStyle, invert),
     
    330333    \endtable
    331334
    332     For more information about painting in general, see \l{The Paint
    333     System} documentation.
     335    For more information about painting in general, see the \l{Paint
     336    System}.
    334337
    335338    \sa Qt::BrushStyle, QPainter, QColor
     
    912915
    913916    Two brushes are different if they have different styles, colors or
    914     pixmaps.
     917    transforms or different pixmaps or gradients depending on the style.
    915918
    916919    \sa operator==()
     
    924927
    925928    Two brushes are equal if they have equal styles, colors and
    926     pixmaps.
     929    transforms and equal pixmaps or gradients depending on the style.
    927930
    928931    \sa operator!=()
     
    933936    if (b.d == d)
    934937        return true;
    935     if (b.d->style == d->style && b.d->color == d->color) {
    936         switch (d->style) {
    937         case Qt::TexturePattern: {
    938             QPixmap &us = (static_cast<QTexturedBrushData *>(d.data()))->pixmap();
    939             QPixmap &them = (static_cast<QTexturedBrushData *>(b.d.data()))->pixmap();
     938    if (b.d->style != d->style || b.d->color != d->color || b.d->transform != d->transform)
     939        return false;
     940    switch (d->style) {
     941    case Qt::TexturePattern:
     942        {
     943            const QPixmap &us = (static_cast<QTexturedBrushData *>(d.data()))->pixmap();
     944            const QPixmap &them = (static_cast<QTexturedBrushData *>(b.d.data()))->pixmap();
    940945            return ((us.isNull() && them.isNull()) || us.cacheKey() == them.cacheKey());
    941946        }
    942         case Qt::LinearGradientPattern:
    943         case Qt::RadialGradientPattern:
    944         case Qt::ConicalGradientPattern:
    945             {
    946                 QGradientBrushData *d1 = static_cast<QGradientBrushData *>(d.data());
    947                 QGradientBrushData *d2 = static_cast<QGradientBrushData *>(b.d.data());
    948                 return d1->gradient == d2->gradient;
    949             }
    950         default:
    951             return true;
     947    case Qt::LinearGradientPattern:
     948    case Qt::RadialGradientPattern:
     949    case Qt::ConicalGradientPattern:
     950        {
     951            const QGradientBrushData *d1 = static_cast<QGradientBrushData *>(d.data());
     952            const QGradientBrushData *d2 = static_cast<QGradientBrushData *>(b.d.data());
     953            return d1->gradient == d2->gradient;
    952954        }
    953     }
    954     return false;
     955    default:
     956        return true;
     957    }
    955958}
    956959
     
    10141017    reference to the \a stream.
    10151018
    1016     \sa {Format of the QDataStream Operators}
     1019    \sa {Serializing Qt Data Types}
    10171020*/
    10181021
     
    10821085    reference to the \a stream.
    10831086
    1084     \sa {Format of the QDataStream Operators}
     1087    \sa {Serializing Qt Data Types}
    10851088*/
    10861089
     
    12161219    \endtable
    12171220
    1218     The colors in a gradient is defined using stop points of the
    1219     QGradientStop type, i.e. a position and a color.  Use the
    1220     setColorAt() function to define a single stop
    1221     point. Alternatively, use the setStops() function to define
    1222     several stop points in one go. Note that the latter function \e
    1223     replaces the current set of stop points.
     1221    The colors in a gradient are defined using stop points of the
     1222    QGradientStop type; i.e., a position and a color. Use the setColorAt()
     1223    function to define a single stop point. Alternatively, use the
     1224    setStops() function to define several stop points in one go. Note that
     1225    the latter function \e replaces the current set of stop points.
    12241226
    12251227    It is the gradient's complete set of stop points (accessible
    12261228    through the stops() function) that describes how the gradient area
    1227     should be filled. If no stop points have been specified, a
    1228     gradient of black at 0 to white at 1 is used.
     1229    should be filled. If no stop points have been specified, a gradient
     1230    of black at 0 to white at 1 is used.
    12291231
    12301232    A diagonal linear gradient from black at (100, 100) to white at
  • trunk/src/gui/painting/qbrush.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qcolor.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    134134    maps the color to the hardware.
    135135
    136     For more information about painting in general, see \l{The Paint
     136    For more information about painting in general, see the \l{Paint
    137137    System} documentation.
    138138
     
    533533void QColor::setNamedColor(const QString &name)
    534534{
     535    if (!setColorFromString(name))
     536        qWarning("QColor::setNamedColor: Unknown color name '%s'", name.toLatin1().constData());
     537}
     538
     539/*!
     540   \since 4.7
     541
     542   Returns true if the \a name is a valid color name and can
     543   be used to construct a valid QColor object, otherwise returns
     544   false.
     545
     546   It uses the same algorithm used in setNamedColor().
     547
     548   \sa setNamedColor()
     549*/
     550bool QColor::isValidColor(const QString &name)
     551{
     552    return !name.isEmpty() && QColor().setColorFromString(name);
     553}
     554
     555bool QColor::setColorFromString(const QString &name)
     556{
    535557    if (name.isEmpty()) {
    536558        invalidate();
    537         return;
     559        return true;
    538560    }
    539561
     
    542564        if (qt_get_hex_rgb(name.constData(), name.length(), &rgb)) {
    543565            setRgb(rgb);
     566            return true;
    544567        } else {
    545568            invalidate();
     569            return false;
    546570        }
    547         return;
    548571    }
    549572
     
    552575    if (qt_get_named_rgb(name.constData(), name.length(), &rgb)) {
    553576        setRgba(rgb);
     577        return true;
    554578    } else
    555579#endif
     
    562586            && XParseColor(QX11Info::display(), QX11Info::appColormap(), name.toLatin1().constData(), &result)) {
    563587            setRgb(result.red >> 8, result.green >> 8, result.blue >> 8);
     588            return true;
    564589        } else
    565590#endif
    566591        {
    567             qWarning("QColor::setNamedColor: Unknown color name '%s'", name.toLatin1().constData());
    568592            invalidate();
     593            return false;
    569594        }
    570595    }
     
    24992524    Writes the \a color to the \a stream.
    25002525
    2501     \sa {Format of the QDataStream Operators}
     2526    \sa {Serializing Qt Data Types}
    25022527*/
    25032528QDataStream &operator<<(QDataStream &stream, const QColor &color)
     
    25352560    Reads the \a color from the \a stream.
    25362561
    2537     \sa { Format of the QDataStream Operators}
     2562    \sa {Serializing Qt Data Types}
    25382563*/
    25392564QDataStream &operator>>(QDataStream &stream, QColor &color)
     
    26932718*/
    26942719
    2695 /*! \fn void QColormap::initialize()
    2696   \internal
    2697 */
    2698 
    2699 /*! \fn void QColormap::cleanup()
    2700   \internal
    2701 */
    2702 
    27032720QT_END_NAMESPACE
  • trunk/src/gui/painting/qcolor.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    226226#endif
    227227
     228    static bool isValidColor(const QString &name);
     229
    228230private:
    229231#ifndef QT3_SUPPORT
     
    233235
    234236    void invalidate();
     237    bool setColorFromString(const QString &name);
    235238
    236239    Spec cspec;
  • trunk/src/gui/painting/qcolor_p.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qcolor_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qcolormap.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qcolormap.qdoc

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    77** This file is part of the documentation of the Qt Toolkit.
    88**
    9 ** $QT_BEGIN_LICENSE:LGPL$
     9** $QT_BEGIN_LICENSE:FDL$
    1010** Commercial Usage
    1111** Licensees holding valid Qt Commercial licenses may use this file in
    1212** accordance with the Qt Commercial License Agreement provided with the
    13 ** Software or, alternatively, in accordance with the terms contained in
    14 ** a written agreement between you and Nokia.
     13** Software or, alternatively, in accordance with the terms contained in a
     14** written agreement between you and Nokia.
    1515**
    16 ** GNU Lesser General Public License Usage
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
    18 ** General Public License version 2.1 as published by the Free Software
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
    20 ** packaging of this file.  Please review the following information to
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    23 **
    24 ** In addition, as a special exception, Nokia gives you certain additional
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    27 **
    28 ** GNU General Public License Usage
    29 ** Alternatively, this file may be used under the terms of the GNU
    30 ** General Public License version 3.0 as published by the Free Software
    31 ** Foundation and appearing in the file LICENSE.GPL included in the
    32 ** packaging of this file.  Please review the following information to
    33 ** ensure the GNU General Public License version 3.0 requirements will be
    34 ** met: http://www.gnu.org/copyleft/gpl.html.
     16** GNU Free Documentation License
     17** Alternatively, this file may be used under the terms of the GNU Free
     18** Documentation License version 1.3 as published by the Free Software
     19** Foundation and appearing in the file included in the packaging of this
     20** file.
    3521**
    3622** If you have questions regarding the use of this file, please contact
     
    151137    a reference to \e this color map.
    152138*/
     139
     140/*!
     141   \fn void QColormap::initialize()
     142   \internal
     143*/
     144
     145/*!
     146   \fn void QColormap::cleanup()
     147   \internal
     148*/
  • trunk/src/gui/painting/qcolormap_mac.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qcolormap_qws.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qcolormap_s60.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qcolormap_win.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qcolormap_x11.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qcssutil.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qcssutil_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qcups.cpp

    r778 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    378378        return false;
    379379    const char *ppdFile = _cupsGetPPD(printerName);
    380     if (ppdFile != 0)
     380    if (ppdFile)
    381381        unlink(ppdFile);
    382382    return (ppdFile != 0);
  • trunk/src/gui/painting/qcups_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6464#endif
    6565#include <cups/cups.h>
     66#include <cups/ppd.h>
    6667
    6768QT_BEGIN_NAMESPACE
  • trunk/src/gui/painting/qdatabuffer_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6161{
    6262public:
    63     QDataBuffer(int res = 64)
     63    QDataBuffer(int res)
    6464    {
    6565        capacity = res;
    66         buffer = (Type*) qMalloc(capacity * sizeof(Type));
     66        if (res)
     67            buffer = (Type*) qMalloc(capacity * sizeof(Type));
     68        else
     69            buffer = 0;
    6770        siz = 0;
    6871    }
     
    7073    ~QDataBuffer()
    7174    {
    72         qFree(buffer);
     75        if (buffer)
     76            qFree(buffer);
    7377    }
    7478
     
    8286    inline Type &at(int i) { Q_ASSERT(i >= 0 && i < siz); return buffer[i]; }
    8387    inline const Type &at(int i) const { Q_ASSERT(i >= 0 && i < siz); return buffer[i]; }
     88    inline Type &last() { Q_ASSERT(!isEmpty()); return buffer[siz-1]; }
    8489    inline const Type &last() const { Q_ASSERT(!isEmpty()); return buffer[siz-1]; }
     90    inline Type &first() { Q_ASSERT(!isEmpty()); return buffer[0]; }
    8591    inline const Type &first() const { Q_ASSERT(!isEmpty()); return buffer[0]; }
    8692
     
    8995        buffer[siz] = t;
    9096        ++siz;
     97    }
     98
     99    inline void pop_back() {
     100        Q_ASSERT(siz > 0);
     101        --siz;
    91102    }
    92103
     
    98109    inline void reserve(int size) {
    99110        if (size > capacity) {
     111            if (capacity == 0)
     112                capacity = 1;
    100113            while (capacity < size)
    101114                capacity *= 2;
     
    106119    inline void shrink(int size) {
    107120        capacity = size;
    108         buffer = (Type*) qRealloc(buffer, capacity * sizeof(Type));
     121        if (size)
     122            buffer = (Type*) qRealloc(buffer, capacity * sizeof(Type));
     123        else {
     124            qFree(buffer);
     125            buffer = 0;
     126        }
    109127    }
    110128
  • trunk/src/gui/painting/qdrawhelper.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4444#include <private/qpainter_p.h>
    4545#include <private/qdrawhelper_x86_p.h>
    46 #include <private/qdrawhelper_armv6_p.h>
     46#include <private/qdrawhelper_arm_simd_p.h>
    4747#include <private/qdrawhelper_neon_p.h>
    4848#include <private/qmath_p.h>
     
    7070*/
    7171
    72 static const int fixed_scale = 1 << 16;
    73 static const int half_point = 1 << 15;
     72enum {
     73    fixed_scale = 1 << 16,
     74    half_point = 1 << 15
     75};
    7476static const int buffer_size = 2048;
    7577
     
    175177# define SPANFUNC_POINTER_DESTFETCH(Arg) destFetch<Arg>
    176178
    177 static const DestFetchProc destFetchProc[QImage::NImageFormats] =
     179static DestFetchProc destFetchProc[QImage::NImageFormats] =
    178180{
    179181    0, // Format_Invalid
     
    323325# define SPANFUNC_POINTER_DESTSTORE(DEST) destStore<DEST>
    324326
    325 static const DestStoreProc destStoreProc[QImage::NImageFormats] =
     327static DestStoreProc destStoreProc[QImage::NImageFormats] =
    326328{
    327329    0, // Format_Invalid
     
    654656}
    655657
     658/** \internal
     659  interpolate 4 argb pixels with the distx and disty factor.
     660  distx and disty bust be between 0 and 16
     661 */
     662static inline uint interpolate_4_pixels_16(uint tl, uint tr, uint bl, uint br, int distx, int disty)
     663{
     664    uint distxy = distx * disty;
     665    //idistx * disty = (16-distx) * disty = 16*disty - distxy
     666    //idistx * idisty = (16-distx) * (16-disty) = 16*16 - 16*distx -16*dity + distxy
     667    uint tlrb = (tl & 0x00ff00ff)         * (16*16 - 16*distx - 16*disty + distxy);
     668    uint tlag = ((tl & 0xff00ff00) >> 8)  * (16*16 - 16*distx - 16*disty + distxy);
     669    uint trrb = ((tr & 0x00ff00ff)        * (distx*16 - distxy));
     670    uint trag = (((tr & 0xff00ff00) >> 8) * (distx*16 - distxy));
     671    uint blrb = ((bl & 0x00ff00ff)        * (disty*16 - distxy));
     672    uint blag = (((bl & 0xff00ff00) >> 8) * (disty*16 - distxy));
     673    uint brrb = ((br & 0x00ff00ff)        * (distxy));
     674    uint brag = (((br & 0xff00ff00) >> 8) * (distxy));
     675    return (((tlrb + trrb + blrb + brrb) >> 8) & 0x00ff00ff) | ((tlag + trag + blag + brag) & 0xff00ff00);
     676}
     677
     678#if defined(QT_ALWAYS_HAVE_SSE2)
     679#define interpolate_4_pixels_16_sse2(tl, tr, bl, br, distx, disty, colorMask, v_256, b)  \
     680{ \
     681    const __m128i dxdy = _mm_mullo_epi16 (distx, disty); \
     682    const __m128i distx_ = _mm_slli_epi16(distx, 4); \
     683    const __m128i disty_ = _mm_slli_epi16(disty, 4); \
     684    const __m128i idxidy =  _mm_add_epi16(dxdy, _mm_sub_epi16(v_256, _mm_add_epi16(distx_, disty_))); \
     685    const __m128i dxidy =  _mm_sub_epi16(distx_, dxdy); \
     686    const __m128i idxdy =  _mm_sub_epi16(disty_, dxdy); \
     687 \
     688    __m128i tlAG = _mm_srli_epi16(tl, 8); \
     689    __m128i tlRB = _mm_and_si128(tl, colorMask); \
     690    __m128i trAG = _mm_srli_epi16(tr, 8); \
     691    __m128i trRB = _mm_and_si128(tr, colorMask); \
     692    __m128i blAG = _mm_srli_epi16(bl, 8); \
     693    __m128i blRB = _mm_and_si128(bl, colorMask); \
     694    __m128i brAG = _mm_srli_epi16(br, 8); \
     695    __m128i brRB = _mm_and_si128(br, colorMask); \
     696 \
     697    tlAG = _mm_mullo_epi16(tlAG, idxidy); \
     698    tlRB = _mm_mullo_epi16(tlRB, idxidy); \
     699    trAG = _mm_mullo_epi16(trAG, dxidy); \
     700    trRB = _mm_mullo_epi16(trRB, dxidy); \
     701    blAG = _mm_mullo_epi16(blAG, idxdy); \
     702    blRB = _mm_mullo_epi16(blRB, idxdy); \
     703    brAG = _mm_mullo_epi16(brAG, dxdy); \
     704    brRB = _mm_mullo_epi16(brRB, dxdy); \
     705 \
     706    /* Add the values, and shift to only keep 8 significant bits per colors */ \
     707    __m128i rAG =_mm_add_epi16(_mm_add_epi16(tlAG, trAG), _mm_add_epi16(blAG, brAG)); \
     708    __m128i rRB =_mm_add_epi16(_mm_add_epi16(tlRB, trRB), _mm_add_epi16(blRB, brRB)); \
     709    rAG = _mm_andnot_si128(colorMask, rAG); \
     710    rRB = _mm_srli_epi16(rRB, 8); \
     711    _mm_storeu_si128((__m128i*)(b), _mm_or_si128(rAG, rRB)); \
     712}
     713#endif
     714
     715#if defined(QT_ALWAYS_HAVE_NEON)
     716#define interpolate_4_pixels_16_neon(tl, tr, bl, br, distx, disty, disty_, colorMask, invColorMask, v_256, b)  \
     717{ \
     718    const int16x8_t dxdy = vmulq_s16(distx, disty); \
     719    const int16x8_t distx_ = vshlq_n_s16(distx, 4); \
     720    const int16x8_t idxidy =  vaddq_s16(dxdy, vsubq_s16(v_256, vaddq_s16(distx_, disty_))); \
     721    const int16x8_t dxidy =  vsubq_s16(distx_, dxdy); \
     722    const int16x8_t idxdy =  vsubq_s16(disty_, dxdy); \
     723 \
     724    int16x8_t tlAG = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(tl), 8)); \
     725    int16x8_t tlRB = vandq_s16(tl, colorMask); \
     726    int16x8_t trAG = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(tr), 8)); \
     727    int16x8_t trRB = vandq_s16(tr, colorMask); \
     728    int16x8_t blAG = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(bl), 8)); \
     729    int16x8_t blRB = vandq_s16(bl, colorMask); \
     730    int16x8_t brAG = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(br), 8)); \
     731    int16x8_t brRB = vandq_s16(br, colorMask); \
     732 \
     733    int16x8_t rAG = vmulq_s16(tlAG, idxidy); \
     734    int16x8_t rRB = vmulq_s16(tlRB, idxidy); \
     735    rAG = vmlaq_s16(rAG, trAG, dxidy); \
     736    rRB = vmlaq_s16(rRB, trRB, dxidy); \
     737    rAG = vmlaq_s16(rAG, blAG, idxdy); \
     738    rRB = vmlaq_s16(rRB, blRB, idxdy); \
     739    rAG = vmlaq_s16(rAG, brAG, dxdy); \
     740    rRB = vmlaq_s16(rRB, brRB, dxdy); \
     741 \
     742    rAG = vandq_s16(invColorMask, rAG); \
     743    rRB = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(rRB), 8)); \
     744    vst1q_s16((int16_t*)(b), vorrq_s16(rAG, rRB)); \
     745}
     746#endif
     747
     748template<TextureBlendType blendType>
     749Q_STATIC_TEMPLATE_FUNCTION inline void fetchTransformedBilinear_pixelBounds(int max, int l1, int l2, int &v1, int &v2)
     750{
     751    if (blendType == BlendTransformedBilinearTiled) {
     752        v1 %= max;
     753        if (v1 < 0) v1 += max;
     754        v2 = v1 + 1;
     755        v2 %= max;
     756    } else {
     757        if (v1 < l1) {
     758            v2 = v1 = l1;
     759        } else if (v1 >= l2) {
     760            v2 = v1 = l2;
     761        } else {
     762            v2 = v1 + 1;
     763        }
     764    }
     765
     766    Q_ASSERT(v1 >= 0 && v1 < max);
     767    Q_ASSERT(v2 >= 0 && v2 < max);
     768}
     769
    656770template<TextureBlendType blendType, QImage::Format format> /* blendType = BlendTransformedBilinear or BlendTransformedBilinearTiled */
    657771Q_STATIC_TEMPLATE_FUNCTION
     
    672786    int image_height = data->texture.height;
    673787
     788    int image_x1 = data->texture.x1;
     789    int image_y1 = data->texture.y1;
     790    int image_x2 = data->texture.x2 - 1;
     791    int image_y2 = data->texture.y2 - 1;
     792
    674793    const qreal cx = x + 0.5;
    675794    const qreal cy = y + 0.5;
    676795
    677     const uint *end = buffer + length;
     796    uint *end = buffer + length;
    678797    uint *b = buffer;
    679798    if (data->fast_matrix) {
     
    689808        fx -= half_point;
    690809        fy -= half_point;
    691         while (b < end) {
    692             int x1 = (fx >> 16);
    693             int x2 = x1 + 1;
     810
     811        if (fdy == 0) { //simple scale, no rotation
    694812            int y1 = (fy >> 16);
    695             int y2 = y1 + 1;
    696 
    697             int distx = ((fx - (x1 << 16)) >> 8);
    698             int disty = ((fy - (y1 << 16)) >> 8);
    699             int idistx = 256 - distx;
    700             int idisty = 256 - disty;
    701 
    702             if (blendType == BlendTransformedBilinearTiled) {
    703                 x1 %= image_width;
    704                 x2 %= image_width;
    705                 y1 %= image_height;
    706                 y2 %= image_height;
    707 
    708                 if (x1 < 0) x1 += image_width;
    709                 if (x2 < 0) x2 += image_width;
    710                 if (y1 < 0) y1 += image_height;
    711                 if (y2 < 0) y2 += image_height;
    712 
    713                 Q_ASSERT(x1 >= 0 && x1 < image_width);
    714                 Q_ASSERT(x2 >= 0 && x2 < image_width);
    715                 Q_ASSERT(y1 >= 0 && y1 < image_height);
    716                 Q_ASSERT(y2 >= 0 && y2 < image_height);
    717             } else {
    718                 x1 = qBound(0, x1, image_width - 1);
    719                 x2 = qBound(0, x2, image_width - 1);
    720                 y1 = qBound(0, y1, image_height - 1);
    721                 y2 = qBound(0, y2, image_height - 1);
    722             }
    723 
     813            int y2;
     814            fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
    724815            const uchar *s1 = data->texture.scanLine(y1);
    725816            const uchar *s2 = data->texture.scanLine(y2);
    726817
    727             uint tl = fetch(s1, x1, data->texture.colorTable);
    728             uint tr = fetch(s1, x2, data->texture.colorTable);
    729             uint bl = fetch(s2, x1, data->texture.colorTable);
    730             uint br = fetch(s2, x2, data->texture.colorTable);
    731 
    732             uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
    733             uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
    734             *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
    735 
    736             fx += fdx;
    737             fy += fdy;
    738             ++b;
     818            if (fdx <= fixed_scale && fdx > 0) { // scale up on X
     819                int disty = (fy & 0x0000ffff) >> 8;
     820                int idisty = 256 - disty;
     821                int x = fx >> 16;
     822
     823                // The idea is first to do the interpolation between the row s1 and the row s2
     824                // into an intermediate buffer, then we interpolate between two pixel of this buffer.
     825
     826                // intermediate_buffer[0] is a buffer of red-blue component of the pixel, in the form 0x00RR00BB
     827                // intermediate_buffer[1] is the alpha-green component of the pixel, in the form 0x00AA00GG
     828                quint32 intermediate_buffer[2][buffer_size + 2];
     829                // count is the size used in the intermediate_buffer.
     830                int count = qCeil(length * data->m11) + 2; //+1 for the last pixel to interpolate with, and +1 for rounding errors.
     831                Q_ASSERT(count <= buffer_size + 2); //length is supposed to be <= buffer_size and data->m11 < 1 in this case
     832                int f = 0;
     833                int lim = count;
     834                if (blendType == BlendTransformedBilinearTiled) {
     835                    x %= image_width;
     836                    if (x < 0) x += image_width;
     837                } else {
     838                    lim = qMin(count, image_x2-x+1);
     839                    if (x < image_x1) {
     840                        Q_ASSERT(x <= image_x2);
     841                        uint t = fetch(s1, image_x1, data->texture.colorTable);
     842                        uint b = fetch(s2, image_x1, data->texture.colorTable);
     843                        quint32 rb = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
     844                        quint32 ag = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
     845                        do {
     846                            intermediate_buffer[0][f] = rb;
     847                            intermediate_buffer[1][f] = ag;
     848                            f++;
     849                            x++;
     850                        } while (x < image_x1 && f < lim);
     851                    }
     852                }
     853
     854                if (blendType != BlendTransformedBilinearTiled &&
     855                        (format == QImage::Format_ARGB32_Premultiplied || format == QImage::Format_RGB32)) {
     856#if defined(QT_ALWAYS_HAVE_SSE2)
     857                    const __m128i disty_ = _mm_set1_epi16(disty);
     858                    const __m128i idisty_ = _mm_set1_epi16(idisty);
     859                    const __m128i colorMask = _mm_set1_epi32(0x00ff00ff);
     860
     861                    lim -= 3;
     862                    for (; f < lim; x += 4, f += 4) {
     863                        // Load 4 pixels from s1, and split the alpha-green and red-blue component
     864                        __m128i top = _mm_loadu_si128((__m128i*)((const uint *)(s1)+x));
     865                        __m128i topAG = _mm_srli_epi16(top, 8);
     866                        __m128i topRB = _mm_and_si128(top, colorMask);
     867                        // Multiplies each colour component by idisty
     868                        topAG = _mm_mullo_epi16 (topAG, idisty_);
     869                        topRB = _mm_mullo_epi16 (topRB, idisty_);
     870
     871                        // Same for the s2 vector
     872                        __m128i bottom = _mm_loadu_si128((__m128i*)((const uint *)(s2)+x));
     873                        __m128i bottomAG = _mm_srli_epi16(bottom, 8);
     874                        __m128i bottomRB = _mm_and_si128(bottom, colorMask);
     875                        bottomAG = _mm_mullo_epi16 (bottomAG, disty_);
     876                        bottomRB = _mm_mullo_epi16 (bottomRB, disty_);
     877
     878                        // Add the values, and shift to only keep 8 significant bits per colors
     879                        __m128i rAG =_mm_add_epi16(topAG, bottomAG);
     880                        rAG = _mm_srli_epi16(rAG, 8);
     881                        _mm_storeu_si128((__m128i*)(&intermediate_buffer[1][f]), rAG);
     882                        __m128i rRB =_mm_add_epi16(topRB, bottomRB);
     883                        rRB = _mm_srli_epi16(rRB, 8);
     884                        _mm_storeu_si128((__m128i*)(&intermediate_buffer[0][f]), rRB);
     885                    }
     886#elif defined(QT_ALWAYS_HAVE_NEON)
     887                    const int16x8_t disty_ = vdupq_n_s16(disty);
     888                    const int16x8_t idisty_ = vdupq_n_s16(idisty);
     889                    const int16x8_t colorMask = vdupq_n_s16(0x00ff);
     890
     891                    lim -= 3;
     892                    for (; f < lim; x += 4, f += 4) {
     893                        // Load 4 pixels from s1, and split the alpha-green and red-blue component
     894                        int16x8_t top = vld1q_s16((int16_t*)((const uint *)(s1)+x));
     895                        int16x8_t topAG = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(top), 8));
     896                        int16x8_t topRB = vandq_s16(top, colorMask);
     897                        // Multiplies each colour component by idisty
     898                        topAG = vmulq_s16(topAG, idisty_);
     899                        topRB = vmulq_s16(topRB, idisty_);
     900
     901                        // Same for the s2 vector
     902                        int16x8_t bottom = vld1q_s16((int16_t*)((const uint *)(s2)+x));
     903                        int16x8_t bottomAG = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(bottom), 8));
     904                        int16x8_t bottomRB = vandq_s16(bottom, colorMask);
     905                        bottomAG = vmulq_s16(bottomAG, disty_);
     906                        bottomRB = vmulq_s16(bottomRB, disty_);
     907
     908                        // Add the values, and shift to only keep 8 significant bits per colors
     909                        int16x8_t rAG = vaddq_s16(topAG, bottomAG);
     910                        rAG = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(rAG), 8));
     911                        vst1q_s16((int16_t*)(&intermediate_buffer[1][f]), rAG);
     912                        int16x8_t rRB = vaddq_s16(topRB, bottomRB);
     913                        rRB = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(rRB), 8));
     914                        vst1q_s16((int16_t*)(&intermediate_buffer[0][f]), rRB);
     915                    }
     916#endif
     917                }
     918                for (; f < count; f++) { // Same as above but without sse2
     919                    if (blendType == BlendTransformedBilinearTiled) {
     920                        if (x >= image_width) x -= image_width;
     921                    } else {
     922                        x = qMin(x, image_x2);
     923                    }
     924
     925                    uint t = fetch(s1, x, data->texture.colorTable);
     926                    uint b = fetch(s2, x, data->texture.colorTable);
     927
     928                    intermediate_buffer[0][f] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
     929                    intermediate_buffer[1][f] = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
     930                    x++;
     931                }
     932                // Now interpolate the values from the intermediate_buffer to get the final result.
     933                fx &= fixed_scale - 1;
     934                Q_ASSERT((fx >> 16) == 0);
     935                while (b < end) {
     936                    register int x1 = (fx >> 16);
     937                    register int x2 = x1 + 1;
     938                    Q_ASSERT(x1 >= 0);
     939                    Q_ASSERT(x2 < count);
     940
     941                    register int distx = (fx & 0x0000ffff) >> 8;
     942                    register int idistx = 256 - distx;
     943                    int rb = ((intermediate_buffer[0][x1] * idistx + intermediate_buffer[0][x2] * distx) >> 8) & 0xff00ff;
     944                    int ag = (intermediate_buffer[1][x1] * idistx + intermediate_buffer[1][x2] * distx) & 0xff00ff00;
     945                    *b = rb | ag;
     946                    b++;
     947                    fx += fdx;
     948                }
     949            } else if ((fdx < 0 && fdx > -(fixed_scale / 8)) || fabs(data->m22) < (1./8.)) { // scale up more than 8x
     950                int y1 = (fy >> 16);
     951                int y2;
     952                fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
     953                const uchar *s1 = data->texture.scanLine(y1);
     954                const uchar *s2 = data->texture.scanLine(y2);
     955                int disty = (fy & 0x0000ffff) >> 8;
     956                int idisty = 256 - disty;
     957                while (b < end) {
     958                    int x1 = (fx >> 16);
     959                    int x2;
     960                    fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
     961                    uint tl = fetch(s1, x1, data->texture.colorTable);
     962                    uint tr = fetch(s1, x2, data->texture.colorTable);
     963                    uint bl = fetch(s2, x1, data->texture.colorTable);
     964                    uint br = fetch(s2, x2, data->texture.colorTable);
     965
     966                    int distx = (fx & 0x0000ffff) >> 8;
     967                    int idistx = 256 - distx;
     968
     969                    uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
     970                    uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
     971                    *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
     972
     973                    fx += fdx;
     974                    ++b;
     975                }
     976            } else { //scale down
     977                int y1 = (fy >> 16);
     978                int y2;
     979                fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
     980                const uchar *s1 = data->texture.scanLine(y1);
     981                const uchar *s2 = data->texture.scanLine(y2);
     982                int disty = (fy & 0x0000ffff) >> 12;
     983
     984                if (blendType != BlendTransformedBilinearTiled &&
     985                    (format == QImage::Format_ARGB32_Premultiplied || format == QImage::Format_RGB32)) {
     986
     987#define BILINEAR_DOWNSCALE_BOUNDS_PROLOG \
     988                    while (b < end) { \
     989                        int x1 = (fx >> 16); \
     990                        int x2; \
     991                        fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); \
     992                        if (x1 != x2) \
     993                            break; \
     994                        uint tl = fetch(s1, x1, data->texture.colorTable); \
     995                        uint tr = fetch(s1, x2, data->texture.colorTable); \
     996                        uint bl = fetch(s2, x1, data->texture.colorTable); \
     997                        uint br = fetch(s2, x2, data->texture.colorTable); \
     998                        int distx = (fx & 0x0000ffff) >> 12; \
     999                        *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); \
     1000                        fx += fdx; \
     1001                        ++b; \
     1002                    } \
     1003                    uint *boundedEnd; \
     1004                    if (fdx > 0) \
     1005                        boundedEnd = qMin(end, buffer + uint((image_x2 - (fx >> 16)) / data->m11)); \
     1006                    else \
     1007                        boundedEnd = qMin(end, buffer + uint((image_x1 - (fx >> 16)) / data->m11)); \
     1008                    boundedEnd -= 3;
     1009
     1010#if defined(QT_ALWAYS_HAVE_SSE2)
     1011                    BILINEAR_DOWNSCALE_BOUNDS_PROLOG
     1012
     1013                    const __m128i colorMask = _mm_set1_epi32(0x00ff00ff);
     1014                    const __m128i v_256 = _mm_set1_epi16(256);
     1015                    const __m128i v_disty = _mm_set1_epi16(disty);
     1016                    __m128i v_fdx = _mm_set1_epi32(fdx*4);
     1017
     1018                    ptrdiff_t secondLine = reinterpret_cast<const uint *>(s2) - reinterpret_cast<const uint *>(s1);
     1019
     1020                    union Vect_buffer { __m128i vect; quint32 i[4]; };
     1021                    Vect_buffer v_fx;
     1022
     1023                    for (int i = 0; i < 4; i++) {
     1024                        v_fx.i[i] = fx;
     1025                        fx += fdx;
     1026                    }
     1027
     1028                    while (b < boundedEnd) {
     1029
     1030                        Vect_buffer tl, tr, bl, br;
     1031
     1032                        for (int i = 0; i < 4; i++) {
     1033                            int x1 = v_fx.i[i] >> 16;
     1034                            const uint *addr_tl = reinterpret_cast<const uint *>(s1) + x1;
     1035                            const uint *addr_tr = addr_tl + 1;
     1036                            tl.i[i] = *addr_tl;
     1037                            tr.i[i] = *addr_tr;
     1038                            bl.i[i] = *(addr_tl+secondLine);
     1039                            br.i[i] = *(addr_tr+secondLine);
     1040                        }
     1041                        __m128i v_distx = _mm_srli_epi16(v_fx.vect, 12);
     1042                        v_distx = _mm_shufflehi_epi16(v_distx, _MM_SHUFFLE(2,2,0,0));
     1043                        v_distx = _mm_shufflelo_epi16(v_distx, _MM_SHUFFLE(2,2,0,0));
     1044
     1045                        interpolate_4_pixels_16_sse2(tl.vect, tr.vect, bl.vect, br.vect, v_distx, v_disty, colorMask, v_256, b);
     1046                        b+=4;
     1047                        v_fx.vect = _mm_add_epi32(v_fx.vect, v_fdx);
     1048                    }
     1049                    fx = v_fx.i[0];
     1050#elif defined(QT_ALWAYS_HAVE_NEON)
     1051                    BILINEAR_DOWNSCALE_BOUNDS_PROLOG
     1052
     1053                    const int16x8_t colorMask = vdupq_n_s16(0x00ff);
     1054                    const int16x8_t invColorMask = vmvnq_s16(colorMask);
     1055                    const int16x8_t v_256 = vdupq_n_s16(256);
     1056                    const int16x8_t v_disty = vdupq_n_s16(disty);
     1057                    const int16x8_t v_disty_ = vshlq_n_s16(v_disty, 4);
     1058                    int32x4_t v_fdx = vdupq_n_s32(fdx*4);
     1059
     1060                    ptrdiff_t secondLine = reinterpret_cast<const uint *>(s2) - reinterpret_cast<const uint *>(s1);
     1061
     1062                    union Vect_buffer { int32x4_t vect; quint32 i[4]; };
     1063                    Vect_buffer v_fx;
     1064
     1065                    for (int i = 0; i < 4; i++) {
     1066                        v_fx.i[i] = fx;
     1067                        fx += fdx;
     1068                    }
     1069
     1070                    const int32x4_t v_ffff_mask = vdupq_n_s32(0x0000ffff);
     1071
     1072                    while (b < boundedEnd) {
     1073
     1074                        Vect_buffer tl, tr, bl, br;
     1075
     1076                        Vect_buffer v_fx_shifted;
     1077                        v_fx_shifted.vect = vshrq_n_s32(v_fx.vect, 16);
     1078
     1079                        int32x4_t v_distx = vshrq_n_s32(vandq_s32(v_fx.vect, v_ffff_mask), 12);
     1080
     1081                        for (int i = 0; i < 4; i++) {
     1082                            int x1 = v_fx_shifted.i[i];
     1083                            const uint *addr_tl = reinterpret_cast<const uint *>(s1) + x1;
     1084                            const uint *addr_tr = addr_tl + 1;
     1085                            tl.i[i] = *addr_tl;
     1086                            tr.i[i] = *addr_tr;
     1087                            bl.i[i] = *(addr_tl+secondLine);
     1088                            br.i[i] = *(addr_tr+secondLine);
     1089                        }
     1090
     1091                        v_distx = vorrq_s32(v_distx, vshlq_n_s32(v_distx, 16));
     1092
     1093                        interpolate_4_pixels_16_neon(vreinterpretq_s16_s32(tl.vect), vreinterpretq_s16_s32(tr.vect), vreinterpretq_s16_s32(bl.vect), vreinterpretq_s16_s32(br.vect), vreinterpretq_s16_s32(v_distx), v_disty, v_disty_, colorMask, invColorMask, v_256, b);
     1094                        b+=4;
     1095                        v_fx.vect = vaddq_s32(v_fx.vect, v_fdx);
     1096                    }
     1097                    fx = v_fx.i[0];
     1098#endif
     1099                }
     1100
     1101                while (b < end) {
     1102                    int x1 = (fx >> 16);
     1103                    int x2;
     1104                    fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
     1105                    uint tl = fetch(s1, x1, data->texture.colorTable);
     1106                    uint tr = fetch(s1, x2, data->texture.colorTable);
     1107                    uint bl = fetch(s2, x1, data->texture.colorTable);
     1108                    uint br = fetch(s2, x2, data->texture.colorTable);
     1109                    int distx = (fx & 0x0000ffff) >> 12;
     1110                    *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty);
     1111                    fx += fdx;
     1112                    ++b;
     1113                }
     1114            }
     1115        } else { //rotation
     1116            if (fabs(data->m11) > 8 || fabs(data->m22) > 8) {
     1117                //if we are zooming more than 8 times, we use 8bit precision for the position.
     1118                while (b < end) {
     1119                    int x1 = (fx >> 16);
     1120                    int x2;
     1121                    int y1 = (fy >> 16);
     1122                    int y2;
     1123
     1124                    fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
     1125                    fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
     1126
     1127                    const uchar *s1 = data->texture.scanLine(y1);
     1128                    const uchar *s2 = data->texture.scanLine(y2);
     1129
     1130                    uint tl = fetch(s1, x1, data->texture.colorTable);
     1131                    uint tr = fetch(s1, x2, data->texture.colorTable);
     1132                    uint bl = fetch(s2, x1, data->texture.colorTable);
     1133                    uint br = fetch(s2, x2, data->texture.colorTable);
     1134
     1135                    int distx = (fx & 0x0000ffff) >> 8;
     1136                    int disty = (fy & 0x0000ffff) >> 8;
     1137                    int idistx = 256 - distx;
     1138                    int idisty = 256 - disty;
     1139
     1140                    uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
     1141                    uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
     1142                    *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
     1143
     1144                    fx += fdx;
     1145                    fy += fdy;
     1146                    ++b;
     1147                }
     1148            } else {
     1149                //we are zooming less than 8x, use 4bit precision
     1150                while (b < end) {
     1151                    int x1 = (fx >> 16);
     1152                    int x2;
     1153                    int y1 = (fy >> 16);
     1154                    int y2;
     1155
     1156                    fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
     1157                    fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
     1158
     1159                    const uchar *s1 = data->texture.scanLine(y1);
     1160                    const uchar *s2 = data->texture.scanLine(y2);
     1161
     1162                    uint tl = fetch(s1, x1, data->texture.colorTable);
     1163                    uint tr = fetch(s1, x2, data->texture.colorTable);
     1164                    uint bl = fetch(s2, x1, data->texture.colorTable);
     1165                    uint br = fetch(s2, x2, data->texture.colorTable);
     1166
     1167                    int distx = (fx & 0x0000ffff) >> 12;
     1168                    int disty = (fy & 0x0000ffff) >> 12;
     1169
     1170                    *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty);
     1171
     1172                    fx += fdx;
     1173                    fy += fdy;
     1174                    ++b;
     1175                }
     1176            }
    7391177        }
    7401178    } else {
     
    7531191
    7541192            int x1 = int(px) - (px < 0);
    755             int x2 = x1 + 1;
     1193            int x2;
    7561194            int y1 = int(py) - (py < 0);
    757             int y2 = y1 + 1;
     1195            int y2;
    7581196
    7591197            int distx = int((px - x1) * 256);
     
    7621200            int idisty = 256 - disty;
    7631201
    764             if (blendType == BlendTransformedBilinearTiled) {
    765                 x1 %= image_width;
    766                 x2 %= image_width;
    767                 y1 %= image_height;
    768                 y2 %= image_height;
    769 
    770                 if (x1 < 0) x1 += image_width;
    771                 if (x2 < 0) x2 += image_width;
    772                 if (y1 < 0) y1 += image_height;
    773                 if (y2 < 0) y2 += image_height;
    774 
    775                 Q_ASSERT(x1 >= 0 && x1 < image_width);
    776                 Q_ASSERT(x2 >= 0 && x2 < image_width);
    777                 Q_ASSERT(y1 >= 0 && y1 < image_height);
    778                 Q_ASSERT(y2 >= 0 && y2 < image_height);
    779             } else {
    780                 x1 = qBound(0, x1, image_width - 1);
    781                 x2 = qBound(0, x2, image_width - 1);
    782                 y1 = qBound(0, y1, image_height - 1);
    783                 y2 = qBound(0, y2, image_height - 1);
    784             }
     1202            fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
     1203            fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
    7851204
    7861205            const uchar *s1 = data->texture.scanLine(y1);
     
    12821701}
    12831702
    1284 static void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_alpha)
     1703void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_alpha)
    12851704{
    12861705    comp_func_Clear_impl(dest, length, const_alpha);
    12871706}
    12881707
    1289 static void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha)
     1708void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha)
    12901709{
    12911710    comp_func_Clear_impl(dest, length, const_alpha);
     
    12961715  dest = s * ca + d * cia
    12971716*/
    1298 static void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha)
     1717void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha)
    12991718{
    13001719    if (const_alpha == 255) {
     
    13111730}
    13121731
    1313 static void QT_FASTCALL comp_func_Source(uint *dest, const uint *src, int length, uint const_alpha)
     1732void QT_FASTCALL comp_func_Source(uint *dest, const uint *src, int length, uint const_alpha)
    13141733{
    13151734    if (const_alpha == 255) {
     
    13251744}
    13261745
    1327 static void QT_FASTCALL comp_func_solid_Destination(uint *, int, uint, uint)
    1328 {
    1329 }
    1330 
    1331 static void QT_FASTCALL comp_func_Destination(uint *, const uint *, int, uint)
     1746void QT_FASTCALL comp_func_solid_Destination(uint *, int, uint, uint)
     1747{
     1748}
     1749
     1750void QT_FASTCALL comp_func_Destination(uint *, const uint *, int, uint)
    13321751{
    13331752}
     
    13391758       = s * ca + d * (1 - sa*ca)
    13401759*/
    1341 static void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, uint const_alpha)
     1760void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, uint const_alpha)
    13421761{
    13431762    if ((const_alpha & qAlpha(color)) == 255) {
     
    13541773}
    13551774
    1356 static void QT_FASTCALL comp_func_SourceOver(uint *dest, const uint *src, int length, uint const_alpha)
     1775void QT_FASTCALL comp_func_SourceOver(uint *dest, const uint *src, int length, uint const_alpha)
    13571776{
    13581777    PRELOAD_INIT2(dest, src)
     
    13801799       = d + s * dia * ca
    13811800*/
    1382 static void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint color, uint const_alpha)
     1801void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint color, uint const_alpha)
    13831802{
    13841803    if (const_alpha != 255)
     
    13921811}
    13931812
    1394 static void QT_FASTCALL comp_func_DestinationOver(uint *dest, const uint *src, int length, uint const_alpha)
     1813void QT_FASTCALL comp_func_DestinationOver(uint *dest, const uint *src, int length, uint const_alpha)
    13951814{
    13961815    PRELOAD_INIT2(dest, src)
     
    14151834  dest = s * da * ca + d * cia
    14161835*/
    1417 static void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha)
     1836void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha)
    14181837{
    14191838    PRELOAD_INIT(dest)
     
    14341853}
    14351854
    1436 static void QT_FASTCALL comp_func_SourceIn(uint *dest, const uint *src, int length, uint const_alpha)
     1855void QT_FASTCALL comp_func_SourceIn(uint *dest, const uint *src, int length, uint const_alpha)
    14371856{
    14381857    PRELOAD_INIT2(dest, src)
     
    14581877       = d * (sa * ca + cia)
    14591878*/
    1460 static void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, uint color, uint const_alpha)
     1879void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, uint color, uint const_alpha)
    14611880{
    14621881    uint a = qAlpha(color);
     
    14711890}
    14721891
    1473 static void QT_FASTCALL comp_func_DestinationIn(uint *dest, const uint *src, int length, uint const_alpha)
     1892void QT_FASTCALL comp_func_DestinationIn(uint *dest, const uint *src, int length, uint const_alpha)
    14741893{
    14751894    PRELOAD_INIT2(dest, src)
     
    14941913*/
    14951914
    1496 static void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha)
     1915void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha)
    14971916{
    14981917    PRELOAD_INIT(dest)
     
    15131932}
    15141933
    1515 static void QT_FASTCALL comp_func_SourceOut(uint *dest, const uint *src, int length, uint const_alpha)
     1934void QT_FASTCALL comp_func_SourceOut(uint *dest, const uint *src, int length, uint const_alpha)
    15161935{
    15171936    PRELOAD_INIT2(dest, src)
     
    15371956       = d * (sia * ca + cia)
    15381957*/
    1539 static void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, uint color, uint const_alpha)
     1958void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, uint color, uint const_alpha)
    15401959{
    15411960    uint a = qAlpha(~color);
     
    15491968}
    15501969
    1551 static void QT_FASTCALL comp_func_DestinationOut(uint *dest, const uint *src, int length, uint const_alpha)
     1970void QT_FASTCALL comp_func_DestinationOut(uint *dest, const uint *src, int length, uint const_alpha)
    15521971{
    15531972    PRELOAD_INIT2(dest, src)
     
    15731992       = s*ca * da + d * (1 - sa*ca)
    15741993*/
    1575 static void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint color, uint const_alpha)
     1994void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint color, uint const_alpha)
    15761995{
    15771996    if (const_alpha != 255) {
     
    15862005}
    15872006
    1588 static void QT_FASTCALL comp_func_SourceAtop(uint *dest, const uint *src, int length, uint const_alpha)
     2007void QT_FASTCALL comp_func_SourceAtop(uint *dest, const uint *src, int length, uint const_alpha)
    15892008{
    15902009    PRELOAD_INIT2(dest, src)
     
    16112030       = s*ca * dia + d * (sa*ca + cia)
    16122031*/
    1613 static void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, uint color, uint const_alpha)
     2032void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, uint color, uint const_alpha)
    16142033{
    16152034    uint a = qAlpha(color);
     
    16262045}
    16272046
    1628 static void QT_FASTCALL comp_func_DestinationAtop(uint *dest, const uint *src, int length, uint const_alpha)
     2047void QT_FASTCALL comp_func_DestinationAtop(uint *dest, const uint *src, int length, uint const_alpha)
    16292048{
    16302049    PRELOAD_INIT2(dest, src)
     
    16542073       = s*ca * dia + d * (1 - sa*ca)
    16552074*/
    1656 static void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, uint const_alpha)
     2075void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, uint const_alpha)
    16572076{
    16582077    if (const_alpha != 255)
     
    16682087}
    16692088
    1670 static void QT_FASTCALL comp_func_XOR(uint *dest, const uint *src, int length, uint const_alpha)
     2089void QT_FASTCALL comp_func_XOR(uint *dest, const uint *src, int length, uint const_alpha)
    16712090{
    16722091    PRELOAD_INIT2(dest, src)
     
    16882107}
    16892108
    1690 static const uint AMASK = 0xff000000;
    1691 static const uint RMASK = 0x00ff0000;
    1692 static const uint GMASK = 0x0000ff00;
    1693 static const uint BMASK = 0x000000ff;
    1694 
    16952109struct QFullCoverage {
    16962110    inline void store(uint *dest, const uint src) const
     
    17352149        PRELOAD_COND(dest)
    17362150        uint d = dest[i];
    1737 #define MIX(mask) (qMin(((qint64(s)&mask) + (qint64(d)&mask)), qint64(mask)))
    1738         d = (MIX(AMASK) | MIX(RMASK) | MIX(GMASK) | MIX(BMASK));
    1739 #undef MIX
     2151        d = comp_func_Plus_one_pixel(d, s);
    17402152        coverage.store(&dest[i], d);
    17412153    }
    17422154}
    17432155
    1744 static void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, uint const_alpha)
     2156void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, uint const_alpha)
    17452157{
    17462158    if (const_alpha == 255)
     
    17592171        uint s = src[i];
    17602172
    1761 #define MIX(mask) (qMin(((qint64(s)&mask) + (qint64(d)&mask)), qint64(mask)))
    1762         d = (MIX(AMASK) | MIX(RMASK) | MIX(GMASK) | MIX(BMASK));
    1763 #undef MIX
     2173        d = comp_func_Plus_one_pixel(d, s);
    17642174
    17652175        coverage.store(&dest[i], d);
     
    17672177}
    17682178
    1769 static void QT_FASTCALL comp_func_Plus(uint *dest, const uint *src, int length, uint const_alpha)
     2179void QT_FASTCALL comp_func_Plus(uint *dest, const uint *src, int length, uint const_alpha)
    17702180{
    17712181    if (const_alpha == 255)
     
    18082218}
    18092219
    1810 static void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint color, uint const_alpha)
     2220void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint color, uint const_alpha)
    18112221{
    18122222    if (const_alpha == 255)
     
    18392249}
    18402250
    1841 static void QT_FASTCALL comp_func_Multiply(uint *dest, const uint *src, int length, uint const_alpha)
     2251void QT_FASTCALL comp_func_Multiply(uint *dest, const uint *src, int length, uint const_alpha)
    18422252{
    18432253    if (const_alpha == 255)
     
    18762286}
    18772287
    1878 static void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint color, uint const_alpha)
     2288void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint color, uint const_alpha)
    18792289{
    18802290    if (const_alpha == 255)
     
    19072317}
    19082318
    1909 static void QT_FASTCALL comp_func_Screen(uint *dest, const uint *src, int length, uint const_alpha)
     2319void QT_FASTCALL comp_func_Screen(uint *dest, const uint *src, int length, uint const_alpha)
    19102320{
    19112321    if (const_alpha == 255)
     
    19552365}
    19562366
    1957 static void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint color, uint const_alpha)
     2367void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint color, uint const_alpha)
    19582368{
    19592369    if (const_alpha == 255)
     
    19862396}
    19872397
    1988 static void QT_FASTCALL comp_func_Overlay(uint *dest, const uint *src, int length, uint const_alpha)
     2398void QT_FASTCALL comp_func_Overlay(uint *dest, const uint *src, int length, uint const_alpha)
    19892399{
    19902400    if (const_alpha == 255)
     
    20282438}
    20292439
    2030 static void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint color, uint const_alpha)
     2440void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint color, uint const_alpha)
    20312441{
    20322442    if (const_alpha == 255)
     
    20592469}
    20602470
    2061 static void QT_FASTCALL comp_func_Darken(uint *dest, const uint *src, int length, uint const_alpha)
     2471void QT_FASTCALL comp_func_Darken(uint *dest, const uint *src, int length, uint const_alpha)
    20622472{
    20632473    if (const_alpha == 255)
     
    21012511}
    21022512
    2103 static void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint color, uint const_alpha)
     2513void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint color, uint const_alpha)
    21042514{
    21052515    if (const_alpha == 255)
     
    21322542}
    21332543
    2134 static void QT_FASTCALL comp_func_Lighten(uint *dest, const uint *src, int length, uint const_alpha)
     2544void QT_FASTCALL comp_func_Lighten(uint *dest, const uint *src, int length, uint const_alpha)
    21352545{
    21362546    if (const_alpha == 255)
     
    21842594}
    21852595
    2186 static void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint color, uint const_alpha)
     2596void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint color, uint const_alpha)
    21872597{
    21882598    if (const_alpha == 255)
     
    22152625}
    22162626
    2217 static void QT_FASTCALL comp_func_ColorDodge(uint *dest, const uint *src, int length, uint const_alpha)
     2627void QT_FASTCALL comp_func_ColorDodge(uint *dest, const uint *src, int length, uint const_alpha)
    22182628{
    22192629    if (const_alpha == 255)
     
    22672677}
    22682678
    2269 static void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint color, uint const_alpha)
     2679void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint color, uint const_alpha)
    22702680{
    22712681    if (const_alpha == 255)
     
    22982708}
    22992709
    2300 static void QT_FASTCALL comp_func_ColorBurn(uint *dest, const uint *src, int length, uint const_alpha)
     2710void QT_FASTCALL comp_func_ColorBurn(uint *dest, const uint *src, int length, uint const_alpha)
    23012711{
    23022712    if (const_alpha == 255)
     
    23472757}
    23482758
    2349 static void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint color, uint const_alpha)
     2759void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint color, uint const_alpha)
    23502760{
    23512761    if (const_alpha == 255)
     
    23782788}
    23792789
    2380 static void QT_FASTCALL comp_func_HardLight(uint *dest, const uint *src, int length, uint const_alpha)
     2790void QT_FASTCALL comp_func_HardLight(uint *dest, const uint *src, int length, uint const_alpha)
    23812791{
    23822792    if (const_alpha == 255)
     
    24382848}
    24392849
    2440 static void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, uint const_alpha)
     2850void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, uint const_alpha)
    24412851{
    24422852    if (const_alpha == 255)
     
    24692879}
    24702880
    2471 static void QT_FASTCALL comp_func_SoftLight(uint *dest, const uint *src, int length, uint const_alpha)
     2881void QT_FASTCALL comp_func_SoftLight(uint *dest, const uint *src, int length, uint const_alpha)
    24722882{
    24732883    if (const_alpha == 255)
     
    25112921}
    25122922
    2513 static void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint color, uint const_alpha)
     2923void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint color, uint const_alpha)
    25142924{
    25152925    if (const_alpha == 255)
     
    25422952}
    25432953
    2544 static void QT_FASTCALL comp_func_Difference(uint *dest, const uint *src, int length, uint const_alpha)
     2954void QT_FASTCALL comp_func_Difference(uint *dest, const uint *src, int length, uint const_alpha)
    25452955{
    25462956    if (const_alpha == 255)
     
    25782988}
    25792989
    2580 static void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint color, uint const_alpha)
     2990void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint color, uint const_alpha)
    25812991{
    25822992    if (const_alpha == 255)
     
    26093019}
    26103020
    2611 static void QT_FASTCALL comp_func_Exclusion(uint *dest, const uint *src, int length, uint const_alpha)
     3021void QT_FASTCALL comp_func_Exclusion(uint *dest, const uint *src, int length, uint const_alpha)
    26123022{
    26133023    if (const_alpha == 255)
     
    26223032#endif
    26233033
    2624 static void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest,
    2625                                                            int length,
    2626                                                            uint color,
    2627                                                            uint const_alpha)
     3034void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest,
     3035                                                    int length,
     3036                                                    uint color,
     3037                                                    uint const_alpha)
    26283038{
    26293039    Q_UNUSED(const_alpha);
     
    26323042}
    26333043
    2634 static void QT_FASTCALL rasterop_SourceOrDestination(uint *dest,
    2635                                                      const uint *src,
    2636                                                      int length,
    2637                                                      uint const_alpha)
     3044void QT_FASTCALL rasterop_SourceOrDestination(uint *dest,
     3045                                              const uint *src,
     3046                                              int length,
     3047                                              uint const_alpha)
    26383048{
    26393049    Q_UNUSED(const_alpha);
     
    26423052}
    26433053
    2644 static void QT_FASTCALL rasterop_solid_SourceAndDestination(uint *dest,
    2645                                                             int length,
    2646                                                             uint color,
    2647                                                             uint const_alpha)
     3054void QT_FASTCALL rasterop_solid_SourceAndDestination(uint *dest,
     3055                                                     int length,
     3056                                                     uint color,
     3057                                                     uint const_alpha)
    26483058{
    26493059    Q_UNUSED(const_alpha);
     
    26533063}
    26543064
    2655 static void QT_FASTCALL rasterop_SourceAndDestination(uint *dest,
    2656                                                       const uint *src,
    2657                                                       int length,
    2658                                                       uint const_alpha)
     3065void QT_FASTCALL rasterop_SourceAndDestination(uint *dest,
     3066                                               const uint *src,
     3067                                               int length,
     3068                                               uint const_alpha)
    26593069{
    26603070    Q_UNUSED(const_alpha);
     
    26653075}
    26663076
    2667 static void QT_FASTCALL rasterop_solid_SourceXorDestination(uint *dest,
    2668                                                             int length,
    2669                                                             uint color,
    2670                                                             uint const_alpha)
     3077void QT_FASTCALL rasterop_solid_SourceXorDestination(uint *dest,
     3078                                                     int length,
     3079                                                     uint color,
     3080                                                     uint const_alpha)
    26713081{
    26723082    Q_UNUSED(const_alpha);
     
    26763086}
    26773087
    2678 static void QT_FASTCALL rasterop_SourceXorDestination(uint *dest,
    2679                                                       const uint *src,
    2680                                                       int length,
    2681                                                       uint const_alpha)
     3088void QT_FASTCALL rasterop_SourceXorDestination(uint *dest,
     3089                                               const uint *src,
     3090                                               int length,
     3091                                               uint const_alpha)
    26823092{
    26833093    Q_UNUSED(const_alpha);
     
    26883098}
    26893099
    2690 static void QT_FASTCALL rasterop_solid_NotSourceAndNotDestination(uint *dest,
    2691                                                                   int length,
    2692                                                                   uint color,
    2693                                                                   uint const_alpha)
     3100void QT_FASTCALL rasterop_solid_NotSourceAndNotDestination(uint *dest,
     3101                                                           int length,
     3102                                                           uint color,
     3103                                                           uint const_alpha)
    26943104{
    26953105    Q_UNUSED(const_alpha);
     
    27013111}
    27023112
    2703 static void QT_FASTCALL rasterop_NotSourceAndNotDestination(uint *dest,
    2704                                                             const uint *src,
    2705                                                             int length,
    2706                                                             uint const_alpha)
     3113void QT_FASTCALL rasterop_NotSourceAndNotDestination(uint *dest,
     3114                                                     const uint *src,
     3115                                                     int length,
     3116                                                     uint const_alpha)
    27073117{
    27083118    Q_UNUSED(const_alpha);
     
    27133123}
    27143124
    2715 static void QT_FASTCALL rasterop_solid_NotSourceOrNotDestination(uint *dest,
    2716                                                                  int length,
    2717                                                                  uint color,
    2718                                                                  uint const_alpha)
     3125void QT_FASTCALL rasterop_solid_NotSourceOrNotDestination(uint *dest,
     3126                                                          int length,
     3127                                                          uint color,
     3128                                                          uint const_alpha)
    27193129{
    27203130    Q_UNUSED(const_alpha);
     
    27263136}
    27273137
    2728 static void QT_FASTCALL rasterop_NotSourceOrNotDestination(uint *dest,
    2729                                                            const uint *src,
    2730                                                            int length,
    2731                                                            uint const_alpha)
     3138void QT_FASTCALL rasterop_NotSourceOrNotDestination(uint *dest,
     3139                                                    const uint *src,
     3140                                                    int length,
     3141                                                    uint const_alpha)
    27323142{
    27333143    Q_UNUSED(const_alpha);
     
    27383148}
    27393149
    2740 static void QT_FASTCALL rasterop_solid_NotSourceXorDestination(uint *dest,
    2741                                                                int length,
    2742                                                                uint color,
    2743                                                                uint const_alpha)
     3150void QT_FASTCALL rasterop_solid_NotSourceXorDestination(uint *dest,
     3151                                                        int length,
     3152                                                        uint color,
     3153                                                        uint const_alpha)
    27443154{
    27453155    Q_UNUSED(const_alpha);
     
    27513161}
    27523162
    2753 static void QT_FASTCALL rasterop_NotSourceXorDestination(uint *dest,
    2754                                                          const uint *src,
    2755                                                          int length,
    2756                                                          uint const_alpha)
     3163void QT_FASTCALL rasterop_NotSourceXorDestination(uint *dest,
     3164                                                  const uint *src,
     3165                                                  int length,
     3166                                                  uint const_alpha)
    27573167{
    27583168    Q_UNUSED(const_alpha);
     
    27633173}
    27643174
    2765 static void QT_FASTCALL rasterop_solid_NotSource(uint *dest, int length,
    2766                                                  uint color, uint const_alpha)
     3175void QT_FASTCALL rasterop_solid_NotSource(uint *dest, int length,
     3176                                          uint color, uint const_alpha)
    27673177{
    27683178    Q_UNUSED(const_alpha);
     
    27703180}
    27713181
    2772 static void QT_FASTCALL rasterop_NotSource(uint *dest, const uint *src,
    2773                                            int length, uint const_alpha)
     3182void QT_FASTCALL rasterop_NotSource(uint *dest, const uint *src,
     3183                                    int length, uint const_alpha)
    27743184{
    27753185    Q_UNUSED(const_alpha);
     
    27783188}
    27793189
    2780 static void QT_FASTCALL rasterop_solid_NotSourceAndDestination(uint *dest,
    2781                                                                int length,
    2782                                                                uint color,
    2783                                                                uint const_alpha)
     3190void QT_FASTCALL rasterop_solid_NotSourceAndDestination(uint *dest,
     3191                                                        int length,
     3192                                                        uint color,
     3193                                                        uint const_alpha)
    27843194{
    27853195    Q_UNUSED(const_alpha);
     
    27913201}
    27923202
    2793 static void QT_FASTCALL rasterop_NotSourceAndDestination(uint *dest,
    2794                                                          const uint *src,
    2795                                                          int length,
    2796                                                          uint const_alpha)
     3203void QT_FASTCALL rasterop_NotSourceAndDestination(uint *dest,
     3204                                                  const uint *src,
     3205                                                  int length,
     3206                                                  uint const_alpha)
    27973207{
    27983208    Q_UNUSED(const_alpha);
     
    28033213}
    28043214
    2805 static void QT_FASTCALL rasterop_solid_SourceAndNotDestination(uint *dest,
    2806                                                                int length,
    2807                                                                uint color,
    2808                                                                uint const_alpha)
     3215void QT_FASTCALL rasterop_solid_SourceAndNotDestination(uint *dest,
     3216                                                        int length,
     3217                                                        uint color,
     3218                                                        uint const_alpha)
    28093219{
    28103220    Q_UNUSED(const_alpha);
     
    28153225}
    28163226
    2817 static void QT_FASTCALL rasterop_SourceAndNotDestination(uint *dest,
    2818                                                          const uint *src,
    2819                                                          int length,
    2820                                                          uint const_alpha)
     3227void QT_FASTCALL rasterop_SourceAndNotDestination(uint *dest,
     3228                                                  const uint *src,
     3229                                                  int length,
     3230                                                  uint const_alpha)
    28213231{
    28223232    Q_UNUSED(const_alpha);
     
    28273237}
    28283238
    2829 static const CompositionFunctionSolid functionForModeSolid_C[] = {
     3239static CompositionFunctionSolid functionForModeSolid_C[] = {
    28303240        comp_func_solid_SourceOver,
    28313241        comp_func_solid_DestinationOver,
     
    28653275static const CompositionFunctionSolid *functionForModeSolid = functionForModeSolid_C;
    28663276
    2867 static const CompositionFunction functionForMode_C[] = {
     3277static CompositionFunction functionForMode_C[] = {
    28683278        comp_func_SourceOver,
    28693279        comp_func_DestinationOver,
     
    37014111inline quint32 alpha_4(const qargb8555 *src)
    37024112{
    3703     Q_ASSERT((long(src) & 0x3) == 0);
     4113    Q_ASSERT((quintptr(src) & 0x3) == 0);
    37044114    const quint8 *src8 = reinterpret_cast<const quint8*>(src);
    37054115    return src8[0] << 24 | src8[3] << 16 | src8[6] << 8 | src8[9];
     
    38844294inline void interpolate_pixel_2(DST *dest, const SRC *src, quint16 alpha)
    38854295{
    3886     Q_ASSERT((long(dest) & 0x3) == 0);
    3887     Q_ASSERT((long(src) & 0x3) == 0);
     4296    Q_ASSERT((quintptr(dest) & 0x3) == 0);
     4297    Q_ASSERT((quintptr(src) & 0x3) == 0);
    38884298
    38894299    const quint16 a = eff_alpha_2(alpha, dest);
     
    39584368                                const SRC *src, quint8 b)
    39594369{
    3960     Q_ASSERT((long(dest) & 0x3) == 0);
    3961     Q_ASSERT((long(src) & 0x3) == 0);
     4370    Q_ASSERT((quintptr(dest) & 0x3) == 0);
     4371    Q_ASSERT((quintptr(src) & 0x3) == 0);
    39624372
    39634373    Q_ASSERT(!SRC::hasAlpha());
     
    40074417inline void interpolate_pixel_4(DST *dest, const SRC *src, quint32 alpha)
    40084418{
    4009     Q_ASSERT((long(dest) & 0x3) == 0);
    4010     Q_ASSERT((long(src) & 0x3) == 0);
     4419    Q_ASSERT((quintptr(dest) & 0x3) == 0);
     4420    Q_ASSERT((quintptr(src) & 0x3) == 0);
    40114421
    40124422    const quint32 a = eff_alpha_4(alpha, dest);
     
    40274437                                quint32 alpha)
    40284438{
    4029     Q_ASSERT((long(dest) & 0x3) == 0);
    4030     Q_ASSERT((long(src) & 0x3) == 0);
     4439    Q_ASSERT((quintptr(dest) & 0x3) == 0);
     4440    Q_ASSERT((quintptr(src) & 0x3) == 0);
    40314441
    40324442    const quint32 a = eff_alpha_4(alpha, dest);
     
    41234533                                quint32 alpha)
    41244534{
    4125     Q_ASSERT((long(dest) & 0x3) == 0);
    4126     Q_ASSERT((long(src) & 0x3) == 0);
     4535    Q_ASSERT((quintptr(dest) & 0x3) == 0);
     4536    Q_ASSERT((quintptr(src) & 0x3) == 0);
    41274537
    41284538
     
    42194629                                quint32 alpha)
    42204630{
    4221     Q_ASSERT((long(dest) & 0x3) == 0);
    4222     Q_ASSERT((long(src) & 0x3) == 0);
     4631    Q_ASSERT((quintptr(dest) & 0x3) == 0);
     4632    Q_ASSERT((quintptr(src) & 0x3) == 0);
    42234633
    42244634    const quint32 a = eff_alpha_4(alpha, dest);
     
    42924702                                const SRC *src, quint8 b)
    42934703{
    4294     Q_ASSERT((long(dest) & 0x3) == 0);
    4295     Q_ASSERT((long(src) & 0x3) == 0);
     4704    Q_ASSERT((quintptr(dest) & 0x3) == 0);
     4705    Q_ASSERT((quintptr(src) & 0x3) == 0);
    42964706
    42974707    dest[0] = dest[0].byte_mul(a) + DST(src[0]).byte_mul(b);
     
    43044714inline void blend_sourceOver_4(DST *dest, const SRC *src)
    43054715{
    4306     Q_ASSERT((long(dest) & 0x3) == 0);
    4307     Q_ASSERT((long(src) & 0x3) == 0);
     4716    Q_ASSERT((quintptr(dest) & 0x3) == 0);
     4717    Q_ASSERT((quintptr(src) & 0x3) == 0);
    43084718
    43094719    const quint32 a = alpha_4(src);
     
    43204730inline void blend_sourceOver_4(qargb8565 *dest, const qargb8565 *src)
    43214731{
    4322     Q_ASSERT((long(dest) & 0x3) == 0);
    4323     Q_ASSERT((long(src) & 0x3) == 0);
     4732    Q_ASSERT((quintptr(dest) & 0x3) == 0);
     4733    Q_ASSERT((quintptr(src) & 0x3) == 0);
    43244734
    43254735    const quint32 a = alpha_4(src);
     
    43344744inline void blend_sourceOver_4(qargb8555 *dest, const qargb8555 *src)
    43354745{
    4336     Q_ASSERT((long(dest) & 0x3) == 0);
    4337     Q_ASSERT((long(src) & 0x3) == 0);
     4746    Q_ASSERT((quintptr(dest) & 0x3) == 0);
     4747    Q_ASSERT((quintptr(src) & 0x3) == 0);
    43384748
    43394749    const quint32 a = alpha_4(src);
     
    43484758inline void blend_sourceOver_4(qargb6666 *dest, const qargb6666 *src)
    43494759{
    4350     Q_ASSERT((long(dest) & 0x3) == 0);
    4351     Q_ASSERT((long(src) & 0x3) == 0);
     4760    Q_ASSERT((quintptr(dest) & 0x3) == 0);
     4761    Q_ASSERT((quintptr(src) & 0x3) == 0);
    43524762
    43534763    const quint32 a = alpha_4(src);
     
    44114821    Q_ASSERT(sizeof(DST) == 2);
    44124822    Q_ASSERT(sizeof(SRC) == 2);
    4413     Q_ASSERT((long(dest) & 0x3) == (long(src) & 0x3));
     4823    Q_ASSERT((quintptr(dest) & 0x3) == (quintptr(src) & 0x3));
    44144824    Q_ASSERT(coverage > 0);
    44154825
     
    44794889
    44804890        while (length >= 2) {
    4481             Q_ASSERT((long(dest) & 3) == 0);
    4482             Q_ASSERT((long(src) & 3) == 0);
     4891            Q_ASSERT((quintptr(dest) & 3) == 0);
     4892            Q_ASSERT((quintptr(src) & 3) == 0);
    44834893
    44844894            const quint16 a = alpha_2(src);
     
    45114921                                           quint8 coverage, int length)
    45124922{
    4513     Q_ASSERT((long(dest) & 0x3) == (long(src) & 0x3));
     4923    Q_ASSERT((quintptr(dest) & 0x3) == (quintptr(src) & 0x3));
    45144924    Q_ASSERT(sizeof(DST) == 3);
    45154925    Q_ASSERT(coverage > 0);
     
    45364946        if (SRC::hasAlpha()) {
    45374947            while (length >= 4) {
    4538                 const quint32 alpha = BYTE_MUL(uint(alpha_4(src)), uint(coverage));
     4948                const quint32 alpha = QT_PREPEND_NAMESPACE(BYTE_MUL)(uint(alpha_4(src)), uint(coverage));
    45394949                if (alpha)
    45404950                    interpolate_pixel_4(dest, src, alpha);
     
    47345144                                       void *userData)
    47355145{
    4736 #if defined(QT_QWS_DEPTH_16)
     5146#if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
    47375147    QSpanData *data = reinterpret_cast<QSpanData *>(userData);
    47385148
     
    49875397                copy_image_width *= 2;
    49885398            }
    4989             qt_memconvert(dest, src, length);
     5399            if (length > 0)
     5400                qt_memconvert(dest, src, length);
    49905401        } else {
    49915402            while (length) {
     
    50725483static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData)
    50735484{
    5074 #if defined(QT_QWS_DEPTH_16)
     5485#if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
    50755486    QSpanData *data = reinterpret_cast<QSpanData *>(userData);
    50765487
     
    51385549#endif
    51395550        blend_tiled_generic<RegularSpans>(count, spans, userData);
    5140 }
    5141 
    5142 
    5143 template <SpanMethod spanMethod>
    5144 Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_argb(int count, const QSpan *spans, void *userData)
    5145 {
    5146     QSpanData *data = reinterpret_cast<QSpanData *>(userData);
    5147     if (data->texture.format != QImage::Format_ARGB32_Premultiplied
    5148         && data->texture.format != QImage::Format_RGB32) {
    5149         blend_src_generic<spanMethod>(count, spans, userData);
    5150         return;
    5151     }
    5152 
    5153     CompositionFunction func = functionForMode[data->rasterBuffer->compositionMode];
    5154     uint buffer[buffer_size];
    5155 
    5156     int image_x1 = data->texture.x1;
    5157     int image_y1 = data->texture.y1;
    5158     int image_x2 = data->texture.x2;
    5159     int image_y2 = data->texture.y2;
    5160     const int scanline_offset = data->texture.bytesPerLine / 4;
    5161 
    5162     if (data->fast_matrix) {
    5163         // The increment pr x in the scanline
    5164         int fdx = (int)(data->m11 * fixed_scale);
    5165         int fdy = (int)(data->m12 * fixed_scale);
    5166 
    5167         while (count--) {
    5168             void *t = data->rasterBuffer->scanLine(spans->y);
    5169 
    5170             uint *target = ((uint *)t) + spans->x;
    5171             uint *image_bits = (uint *)data->texture.imageData;
    5172 
    5173             const qreal cx = spans->x + 0.5;
    5174             const qreal cy = spans->y + 0.5;
    5175 
    5176             int x = int((data->m21 * cy
    5177                          + data->m11 * cx + data->dx) * fixed_scale) - half_point;
    5178             int y = int((data->m22 * cy
    5179                          + data->m12 * cx + data->dy) * fixed_scale) - half_point;
    5180 
    5181             int length = spans->len;
    5182             const int coverage = (data->texture.const_alpha * spans->coverage) >> 8;
    5183             while (length) {
    5184                 int l = qMin(length, buffer_size);
    5185                 const uint *end = buffer + l;
    5186                 uint *b = buffer;
    5187                 while (b < end) {
    5188                     int x1 = (x >> 16);
    5189                     int x2 = x1 + 1;
    5190                     int y1 = (y >> 16);
    5191                     int y2 = y1 + 1;
    5192 
    5193                     int distx = ((x - (x1 << 16)) >> 8);
    5194                     int disty = ((y - (y1 << 16)) >> 8);
    5195                     int idistx = 256 - distx;
    5196                     int idisty = 256 - disty;
    5197 
    5198                     x1 = qBound(image_x1, x1, image_x2 - 1);
    5199                     x2 = qBound(image_x1, x2, image_x2 - 1);
    5200                     y1 = qBound(image_y1, y1, image_y2 - 1);
    5201                     y2 = qBound(image_y1, y2, image_y2 - 1);
    5202 
    5203                     int y1_offset = y1 * scanline_offset;
    5204                     int y2_offset = y2 * scanline_offset;
    5205 
    5206 #if defined(Q_IRIX_GCC3_3_WORKAROUND)
    5207                     uint tl = gccBug(image_bits[y1_offset + x1]);
    5208                     uint tr = gccBug(image_bits[y1_offset + x2]);
    5209                     uint bl = gccBug(image_bits[y2_offset + x1]);
    5210                     uint br = gccBug(image_bits[y2_offset + x2]);
    5211 #else
    5212                     uint tl = image_bits[y1_offset + x1];
    5213                     uint tr = image_bits[y1_offset + x2];
    5214                     uint bl = image_bits[y2_offset + x1];
    5215                     uint br = image_bits[y2_offset + x2];
    5216 #endif
    5217 
    5218                     uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
    5219                     uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
    5220                     *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
    5221                     ++b;
    5222 
    5223                     x += fdx;
    5224                     y += fdy;
    5225                 }
    5226                 if (spanMethod == RegularSpans)
    5227                     func(target, buffer, l, coverage);
    5228                 else
    5229                     drawBufferSpan(data, buffer, buffer_size,
    5230                                    spans->x + spans->len - length,
    5231                                    spans->y, l, coverage);
    5232                 target += l;
    5233                 length -= l;
    5234             }
    5235             ++spans;
    5236         }
    5237     } else {
    5238         const qreal fdx = data->m11;
    5239         const qreal fdy = data->m12;
    5240         const qreal fdw = data->m13;
    5241 
    5242         while (count--) {
    5243             void *t = data->rasterBuffer->scanLine(spans->y);
    5244 
    5245             uint *target = ((uint *)t) + spans->x;
    5246             uint *image_bits = (uint *)data->texture.imageData;
    5247 
    5248             const qreal cx = spans->x + 0.5;
    5249             const qreal cy = spans->y + 0.5;
    5250 
    5251             qreal x = data->m21 * cy + data->m11 * cx + data->dx;
    5252             qreal y = data->m22 * cy + data->m12 * cx + data->dy;
    5253             qreal w = data->m23 * cy + data->m13 * cx + data->m33;
    5254 
    5255             int length = spans->len;
    5256             const int coverage = (data->texture.const_alpha * spans->coverage) >> 8;
    5257             while (length) {
    5258                 int l = qMin(length, buffer_size);
    5259                 const uint *end = buffer + l;
    5260                 uint *b = buffer;
    5261                 while (b < end) {
    5262                     const qreal iw = w == 0 ? 1 : 1 / w;
    5263                     const qreal px = x * iw - 0.5;
    5264                     const qreal py = y * iw - 0.5;
    5265 
    5266                     int x1 = int(px) - (px < 0);
    5267                     int x2 = x1 + 1;
    5268                     int y1 = int(py) - (py < 0);
    5269                     int y2 = y1 + 1;
    5270 
    5271                     int distx = int((px - x1) * 256);
    5272                     int disty = int((py - y1) * 256);
    5273                     int idistx = 256 - distx;
    5274                     int idisty = 256 - disty;
    5275 
    5276                     x1 = qBound(image_x1, x1, image_x2 - 1);
    5277                     x2 = qBound(image_x1, x2, image_x2 - 1);
    5278                     y1 = qBound(image_y1, y1, image_y2 - 1);
    5279                     y2 = qBound(image_y1, y2, image_y2 - 1);
    5280 
    5281                     int y1_offset = y1 * scanline_offset;
    5282                     int y2_offset = y2 * scanline_offset;
    5283 
    5284 #if defined(Q_IRIX_GCC3_3_WORKAROUND)
    5285                     uint tl = gccBug(image_bits[y1_offset + x1]);
    5286                     uint tr = gccBug(image_bits[y1_offset + x2]);
    5287                     uint bl = gccBug(image_bits[y2_offset + x1]);
    5288                     uint br = gccBug(image_bits[y2_offset + x2]);
    5289 #else
    5290                     uint tl = image_bits[y1_offset + x1];
    5291                     uint tr = image_bits[y1_offset + x2];
    5292                     uint bl = image_bits[y2_offset + x1];
    5293                     uint br = image_bits[y2_offset + x2];
    5294 #endif
    5295 
    5296                     uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
    5297                     uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
    5298                     *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
    5299                     ++b;
    5300 
    5301                     x += fdx;
    5302                     y += fdy;
    5303                     w += fdw;
    5304                 }
    5305                 if (spanMethod == RegularSpans)
    5306                     func(target, buffer, l, coverage);
    5307                 else
    5308                     drawBufferSpan(data, buffer, buffer_size,
    5309                                    spans->x + spans->len - length,
    5310                                    spans->y, l, coverage);
    5311                 target += l;
    5312                 length -= l;
    5313             }
    5314             ++spans;
    5315         }
    5316     }
    53175551}
    53185552
     
    53665600                while (b < end) {
    53675601                    int x1 = (x >> 16);
    5368                     int x2 = x1 + 1;
     5602                    int x2;
    53695603                    int y1 = (y >> 16);
    5370                     int y2 = y1 + 1;
    5371 
    5372                     const int distx = ((x - (x1 << 16)) >> 8);
    5373                     const int disty = ((y - (y1 << 16)) >> 8);
    5374                     x1 = qBound(src_minx, x1, src_maxx);
    5375                     x2 = qBound(src_minx, x2, src_maxx);
    5376                     y1 = qBound(src_miny, y1, src_maxy);
    5377                     y2 = qBound(src_miny, y2, src_maxy);
    5378 
     5604                    int y2;
     5605
     5606                    const int distx = (x & 0x0000ffff) >> 8;
     5607                    const int disty = (y & 0x0000ffff) >> 8;
     5608
     5609                    if (x1 < src_minx) {
     5610                        x2 = x1 = src_minx;
     5611                    } else if (x1 >= src_maxx) {
     5612                        x2 = x1 = src_maxx;
     5613                    } else {
     5614                        x2 = x1 + 1;
     5615                    }
     5616                    if (y1 < src_miny) {
     5617                        y2 = y1 = src_miny;
     5618                    } else if (y1 >= src_maxy) {
     5619                        y2 = y1 = src_maxy;
     5620                    } else {
     5621                        y2 = y1 + 1;
     5622                    }
    53795623#if 0
    53805624                    if (x1 == x2) {
     
    54675711
    54685712                    int x1 = int(px) - (px < 0);
    5469                     int x2 = x1 + 1;
     5713                    int x2;
    54705714                    int y1 = int(py) - (py < 0);
    5471                     int y2 = y1 + 1;
     5715                    int y2;
    54725716
    54735717                    const int distx = int((px - x1) * 256);
    54745718                    const int disty = int((py - y1) * 256);
    54755719
    5476                     x1 = qBound(src_minx, x1, src_maxx);
    5477                     x2 = qBound(src_minx, x2, src_maxx);
    5478                     y1 = qBound(src_miny, y1, src_maxy);
    5479                     y2 = qBound(src_miny, y2, src_maxy);
     5720                    if (x1 < src_minx) {
     5721                        x2 = x1 = src_minx;
     5722                    } else if (x1 >= src_maxx) {
     5723                        x2 = x1 = src_maxx;
     5724                    } else {
     5725                        x2 = x1 + 1;
     5726                    }
     5727                    if (y1 < src_miny) {
     5728                        y2 = y1 = src_miny;
     5729                    } else if (y1 >= src_maxy) {
     5730                        y2 = y1 = src_maxy;
     5731                    } else {
     5732                        y2 = y1 + 1;
     5733                    }
    54805734
    54815735                    const SRC *src1 = (SRC*)data->texture.scanLine(y1);
     
    55775831                                              void *userData)
    55785832{
    5579 #if defined(QT_QWS_DEPTH_16)
     5833#if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
    55805834    QSpanData *data = reinterpret_cast<QSpanData *>(userData);
    55815835
     
    56435897#endif
    56445898        blend_src_generic<RegularSpans>(count, spans, userData);
    5645 }
    5646 
    5647 template <SpanMethod spanMethod>
    5648 Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_tiled_argb(int count, const QSpan *spans, void *userData)
    5649 {
    5650     QSpanData *data = reinterpret_cast<QSpanData *>(userData);
    5651     if (data->texture.format != QImage::Format_ARGB32_Premultiplied
    5652         && data->texture.format != QImage::Format_RGB32) {
    5653         blend_src_generic<spanMethod>(count, spans, userData);
    5654         return;
    5655     }
    5656 
    5657     CompositionFunction func = functionForMode[data->rasterBuffer->compositionMode];
    5658     uint buffer[buffer_size];
    5659 
    5660     int image_width = data->texture.width;
    5661     int image_height = data->texture.height;
    5662     const int scanline_offset = data->texture.bytesPerLine / 4;
    5663 
    5664     if (data->fast_matrix) {
    5665         // The increment pr x in the scanline
    5666         int fdx = (int)(data->m11 * fixed_scale);
    5667         int fdy = (int)(data->m12 * fixed_scale);
    5668 
    5669         while (count--) {
    5670             void *t = data->rasterBuffer->scanLine(spans->y);
    5671 
    5672             uint *target = ((uint *)t) + spans->x;
    5673             uint *image_bits = (uint *)data->texture.imageData;
    5674 
    5675             const qreal cx = spans->x + 0.5;
    5676             const qreal cy = spans->y + 0.5;
    5677 
    5678             int x = int((data->m21 * cy
    5679                          + data->m11 * cx + data->dx) * fixed_scale) - half_point;
    5680             int y = int((data->m22 * cy
    5681                          + data->m12 * cx + data->dy) * fixed_scale) - half_point;
    5682 
    5683             int length = spans->len;
    5684             const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
    5685             while (length) {
    5686                 int l = qMin(length, buffer_size);
    5687                 const uint *end = buffer + l;
    5688                 uint *b = buffer;
    5689                 while (b < end) {
    5690                     int x1 = (x >> 16);
    5691                     int x2 = (x1 + 1);
    5692                     int y1 = (y >> 16);
    5693                     int y2 = (y1 + 1);
    5694 
    5695                     int distx = ((x - (x1 << 16)) >> 8);
    5696                     int disty = ((y - (y1 << 16)) >> 8);
    5697                     int idistx = 256 - distx;
    5698                     int idisty = 256 - disty;
    5699 
    5700                     x1 %= image_width;
    5701                     x2 %= image_width;
    5702                     y1 %= image_height;
    5703                     y2 %= image_height;
    5704 
    5705                     if (x1 < 0) x1 += image_width;
    5706                     if (x2 < 0) x2 += image_width;
    5707                     if (y1 < 0) y1 += image_height;
    5708                     if (y2 < 0) y2 += image_height;
    5709 
    5710                     Q_ASSERT(x1 >= 0 && x1 < image_width);
    5711                     Q_ASSERT(x2 >= 0 && x2 < image_width);
    5712                     Q_ASSERT(y1 >= 0 && y1 < image_height);
    5713                     Q_ASSERT(y2 >= 0 && y2 < image_height);
    5714 
    5715                     int y1_offset = y1 * scanline_offset;
    5716                     int y2_offset = y2 * scanline_offset;
    5717 
    5718 #if defined(Q_IRIX_GCC3_3_WORKAROUND)
    5719                     uint tl = gccBug(image_bits[y1_offset + x1]);
    5720                     uint tr = gccBug(image_bits[y1_offset + x2]);
    5721                     uint bl = gccBug(image_bits[y2_offset + x1]);
    5722                     uint br = gccBug(image_bits[y2_offset + x2]);
    5723 #else
    5724                     uint tl = image_bits[y1_offset + x1];
    5725                     uint tr = image_bits[y1_offset + x2];
    5726                     uint bl = image_bits[y2_offset + x1];
    5727                     uint br = image_bits[y2_offset + x2];
    5728 #endif
    5729 
    5730                     uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
    5731                     uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
    5732                     *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
    5733                     ++b;
    5734                     x += fdx;
    5735                     y += fdy;
    5736                 }
    5737                 if (spanMethod == RegularSpans)
    5738                     func(target, buffer, l, coverage);
    5739                 else
    5740                     drawBufferSpan(data, buffer, buffer_size,
    5741                                    spans->x + spans->len - length,
    5742                                    spans->y, l, coverage);
    5743                 target += l;
    5744                 length -= l;
    5745             }
    5746             ++spans;
    5747         }
    5748     } else {
    5749         const qreal fdx = data->m11;
    5750         const qreal fdy = data->m12;
    5751         const qreal fdw = data->m13;
    5752         while (count--) {
    5753             void *t = data->rasterBuffer->scanLine(spans->y);
    5754 
    5755             uint *target = ((uint *)t) + spans->x;
    5756             uint *image_bits = (uint *)data->texture.imageData;
    5757 
    5758             const qreal cx = spans->x + 0.5;
    5759             const qreal cy = spans->y + 0.5;
    5760 
    5761             qreal x = data->m21 * cy + data->m11 * cx + data->dx;
    5762             qreal y = data->m22 * cy + data->m12 * cx + data->dy;
    5763             qreal w = data->m23 * cy + data->m13 * cx + data->m33;
    5764 
    5765             int length = spans->len;
    5766             const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
    5767             while (length) {
    5768                 int l = qMin(length, buffer_size);
    5769                 const uint *end = buffer + l;
    5770                 uint *b = buffer;
    5771                 while (b < end) {
    5772                     const qreal iw = w == 0 ? 1 : 1 / w;
    5773                     const qreal px = x * iw - 0.5;
    5774                     const qreal py = y * iw - 0.5;
    5775 
    5776                     int x1 = int(px) - (px < 0);
    5777                     int x2 = x1 + 1;
    5778                     int y1 = int(py) - (py < 0);
    5779                     int y2 = y1 + 1;
    5780 
    5781                     int distx = int((px - x1) * 256);
    5782                     int disty = int((py - y1) * 256);
    5783                     int idistx = 256 - distx;
    5784                     int idisty = 256 - disty;
    5785 
    5786                     x1 %= image_width;
    5787                     x2 %= image_width;
    5788                     y1 %= image_height;
    5789                     y2 %= image_height;
    5790 
    5791                     if (x1 < 0) x1 += image_width;
    5792                     if (x2 < 0) x2 += image_width;
    5793                     if (y1 < 0) y1 += image_height;
    5794                     if (y2 < 0) y2 += image_height;
    5795 
    5796                     Q_ASSERT(x1 >= 0 && x1 < image_width);
    5797                     Q_ASSERT(x2 >= 0 && x2 < image_width);
    5798                     Q_ASSERT(y1 >= 0 && y1 < image_height);
    5799                     Q_ASSERT(y2 >= 0 && y2 < image_height);
    5800 
    5801                     int y1_offset = y1 * scanline_offset;
    5802                     int y2_offset = y2 * scanline_offset;
    5803 
    5804 #if defined(Q_IRIX_GCC3_3_WORKAROUND)
    5805                     uint tl = gccBug(image_bits[y1_offset + x1]);
    5806                     uint tr = gccBug(image_bits[y1_offset + x2]);
    5807                     uint bl = gccBug(image_bits[y2_offset + x1]);
    5808                     uint br = gccBug(image_bits[y2_offset + x2]);
    5809 #else
    5810                     uint tl = image_bits[y1_offset + x1];
    5811                     uint tr = image_bits[y1_offset + x2];
    5812                     uint bl = image_bits[y2_offset + x1];
    5813                     uint br = image_bits[y2_offset + x2];
    5814 #endif
    5815 
    5816                     uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
    5817                     uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
    5818                     *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
    5819                     ++b;
    5820                     x += fdx;
    5821                     y += fdy;
    5822                     w += fdw;
    5823                 }
    5824                 if (spanMethod == RegularSpans)
    5825                     func(target, buffer, l, coverage);
    5826                 else
    5827                     drawBufferSpan(data, buffer, buffer_size,
    5828                                    spans->x + spans->len - length,
    5829                                    spans->y, l, coverage);
    5830                 target += l;
    5831                 length -= l;
    5832             }
    5833             ++spans;
    5834         }
    5835     }
    58365899}
    58375900
     
    61646227                                       void *userData)
    61656228{
    6166 #if defined(QT_QWS_DEPTH_16)
     6229#if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
    61676230    QSpanData *data = reinterpret_cast<QSpanData *>(userData);
    61686231
     
    64806543                    int py = int(ty) - (ty < 0);
    64816544
     6545                    px %= image_width;
     6546                    py %= image_height;
    64826547                    if (px < 0)
    64836548                        px += image_width;
     
    65776642                                           void *userData)
    65786643{
    6579 #if defined(QT_QWS_DEPTH_16)
     6644#if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
    65806645    QSpanData *data = reinterpret_cast<QSpanData *>(userData);
    65816646
     
    67386803        SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32
    67396804        SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32
    6740         SPANFUNC_POINTER(blend_transformed_bilinear_argb, RegularSpans), // ARGB32_Premultiplied
     6805        SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32_Premultiplied
    67416806        blend_transformed_bilinear_rgb565,
    67426807        blend_transformed_bilinear_argb8565,
     
    67576822        SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32
    67586823        SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32
    6759         SPANFUNC_POINTER(blend_transformed_bilinear_tiled_argb, RegularSpans), // ARGB32_Premultiplied
     6824        SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32_Premultiplied
    67606825        SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB16
    67616826        SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB8565_Premultiplied
     
    68566921        blend_src_generic<CallbackSpans>,   // RGB32
    68576922        blend_src_generic<CallbackSpans>,   // ARGB32
    6858         blend_transformed_bilinear_argb<CallbackSpans>, // ARGB32_Premultiplied
     6923        blend_src_generic<CallbackSpans>, // ARGB32_Premultiplied
    68596924        blend_src_generic<CallbackSpans>,   // RGB16
    68606925        blend_src_generic<CallbackSpans>,   // ARGB8565_Premultiplied
     
    68756940        blend_src_generic<CallbackSpans>,   // RGB32
    68766941        blend_src_generic<CallbackSpans>,   // ARGB32
    6877         blend_transformed_bilinear_tiled_argb<CallbackSpans>, // ARGB32_Premultiplied
     6942        blend_src_generic<CallbackSpans>, // ARGB32_Premultiplied
    68786943        blend_src_generic<CallbackSpans>,   // RGB16
    68796944        blend_src_generic<CallbackSpans>,   // ARGB8565_Premultiplied
     
    71357200    if (SystemParametersInfo(0x200C /* SPI_GETFONTSMOOTHINGCONTRAST */, 0, &winSmooth, 0))
    71367201        smoothing = winSmooth / 1000.0;
     7202
     7203    // Safeguard ourselves against corrupt registry values...
     7204    if (smoothing > 5 || smoothing < 1)
     7205        smoothing = 1.4;
     7206
    71377207#endif
    71387208
     
    77217791qt_memfill16_func qt_memfill16 = qt_memfill16_setup;
    77227792
    7723 enum CPUFeatures {
    7724     None        = 0,
    7725     MMX         = 0x1,
    7726     MMXEXT      = 0x2,
    7727     MMX3DNOW    = 0x4,
    7728     MMX3DNOWEXT = 0x8,
    7729     SSE         = 0x10,
    7730     SSE2        = 0x20,
    7731     CMOV        = 0x40,
    7732     IWMMXT      = 0x80,
    7733     NEON        = 0x100
    7734 };
    7735 
    7736 static uint detectCPUFeatures()
    7737 {
    7738 #if defined (Q_OS_WINCE)
    7739 #if defined (ARM)
    7740     if (IsProcessorFeaturePresent(PF_ARM_INTEL_WMMX))
    7741         return IWMMXT;
    7742 #elif defined(_X86_)
    7743     uint features = 0;
    7744 #if defined QT_HAVE_MMX
    7745     if (IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE))
    7746         features |= MMX;
    7747 #endif
    7748 #if defined QT_HAVE_3DNOW
    7749     if (IsProcessorFeaturePresent(PF_3DNOW_INSTRUCTIONS_AVAILABLE))
    7750         features |= MMX3DNOW;
    7751 #endif
    7752     return features;
    7753 #endif
    7754     return 0;
    7755 #elif defined(QT_HAVE_IWMMXT)
    7756     // runtime detection only available when running as a previlegied process
    7757     static const bool doIWMMXT = !qgetenv("QT_NO_IWMMXT").toInt();
    7758     return doIWMMXT ? IWMMXT : 0;
    7759 #elif defined(QT_HAVE_NEON)
    7760     static const bool doNEON = !qgetenv("QT_NO_NEON").toInt();
    7761     return doNEON ? NEON : 0;
    7762 #else
    7763     uint features = 0;
    7764 #if defined(__x86_64__) || defined(Q_OS_WIN64)
    7765     features = MMX|SSE|SSE2|CMOV;
    7766 #elif defined(__ia64__)
    7767     features = MMX|SSE|SSE2;
    7768 #elif defined(__i386__) || defined(_M_IX86)
    7769     unsigned int extended_result = 0;
    7770     uint result = 0;
    7771     /* see p. 118 of amd64 instruction set manual Vol3 */
    7772 #if defined(Q_CC_GNU)
    7773     asm ("push %%ebx\n"
    7774          "pushf\n"
    7775          "pop %%eax\n"
    7776          "mov %%eax, %%ebx\n"
    7777          "xor $0x00200000, %%eax\n"
    7778          "push %%eax\n"
    7779          "popf\n"
    7780          "pushf\n"
    7781          "pop %%eax\n"
    7782          "xor %%edx, %%edx\n"
    7783          "xor %%ebx, %%eax\n"
    7784          "jz 1f\n"
    7785 
    7786          "mov $0x00000001, %%eax\n"
    7787          "cpuid\n"
    7788          "1:\n"
    7789          "pop %%ebx\n"
    7790          "mov %%edx, %0\n"
    7791         : "=r" (result)
    7792         :
    7793         : "%eax", "%ecx", "%edx"
    7794         );
    7795 
    7796     asm ("push %%ebx\n"
    7797          "pushf\n"
    7798          "pop %%eax\n"
    7799          "mov %%eax, %%ebx\n"
    7800          "xor $0x00200000, %%eax\n"
    7801          "push %%eax\n"
    7802          "popf\n"
    7803          "pushf\n"
    7804          "pop %%eax\n"
    7805          "xor %%edx, %%edx\n"
    7806          "xor %%ebx, %%eax\n"
    7807          "jz 2f\n"
    7808 
    7809          "mov $0x80000000, %%eax\n"
    7810          "cpuid\n"
    7811          "cmp $0x80000000, %%eax\n"
    7812          "jbe 2f\n"
    7813          "mov $0x80000001, %%eax\n"
    7814          "cpuid\n"
    7815          "2:\n"
    7816          "pop %%ebx\n"
    7817          "mov %%edx, %0\n"
    7818         : "=r" (extended_result)
    7819         :
    7820         : "%eax", "%ecx", "%edx"
    7821         );
    7822 #elif defined (Q_OS_WIN)
    7823     _asm {
    7824         push eax
    7825         push ebx
    7826         push ecx
    7827         push edx
    7828         pushfd
    7829         pop eax
    7830         mov ebx, eax
    7831         xor eax, 00200000h
    7832         push eax
    7833         popfd
    7834         pushfd
    7835         pop eax
    7836         mov edx, 0
    7837         xor eax, ebx
    7838         jz skip
    7839 
    7840         mov eax, 1
    7841         cpuid
    7842         mov result, edx
    7843     skip:
    7844         pop edx
    7845         pop ecx
    7846         pop ebx
    7847         pop eax
    7848     }
    7849 
    7850     _asm {
    7851         push eax
    7852         push ebx
    7853         push ecx
    7854         push edx
    7855         pushfd
    7856         pop eax
    7857         mov ebx, eax
    7858         xor eax, 00200000h
    7859         push eax
    7860         popfd
    7861         pushfd
    7862         pop eax
    7863         mov edx, 0
    7864         xor eax, ebx
    7865         jz skip2
    7866 
    7867         mov eax, 80000000h
    7868         cpuid
    7869         cmp eax, 80000000h
    7870         jbe skip2
    7871         mov eax, 80000001h
    7872         cpuid
    7873         mov extended_result, edx
    7874     skip2:
    7875         pop edx
    7876         pop ecx
    7877         pop ebx
    7878         pop eax
    7879     }
    7880 #endif
    7881 
    7882     // result now contains the standard feature bits
    7883     if (result & (1u << 15))
    7884         features |= CMOV;
    7885     if (result & (1u << 23))
    7886         features |= MMX;
    7887     if (extended_result & (1u << 22))
    7888         features |= MMXEXT;
    7889     if (extended_result & (1u << 31))
    7890         features |= MMX3DNOW;
    7891     if (extended_result & (1u << 30))
    7892         features |= MMX3DNOWEXT;
    7893     if (result & (1u << 25))
    7894         features |= SSE;
    7895     if (result & (1u << 26))
    7896         features |= SSE2;
    7897 #endif // i386
    7898 
    7899     if (qgetenv("QT_NO_MMX").toInt())
    7900         features ^= MMX;
    7901     if (qgetenv("QT_NO_MMXEXT").toInt())
    7902         features ^= MMXEXT;
    7903     if (qgetenv("QT_NO_3DNOW").toInt())
    7904         features ^= MMX3DNOW;
    7905     if (qgetenv("QT_NO_3DNOWEXT").toInt())
    7906         features ^= MMX3DNOWEXT;
    7907     if (qgetenv("QT_NO_SSE").toInt())
    7908         features ^= SSE;
    7909     if (qgetenv("QT_NO_SSE2").toInt())
    7910         features ^= SSE2;
    7911 
    7912     return features;
    7913 #endif
    7914 }
    7915 
    7916 #if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6)
    7917 // Move these to qdrawhelper_arm.c when all
    7918 // functions are implemented using arm assembly.
    7919 static CompositionFunctionSolid qt_functionForModeSolid_ARMv6[numCompositionFunctions] = {
    7920         comp_func_solid_SourceOver,
    7921         comp_func_solid_DestinationOver,
    7922         comp_func_solid_Clear,
    7923         comp_func_solid_Source,
    7924         comp_func_solid_Destination,
    7925         comp_func_solid_SourceIn,
    7926         comp_func_solid_DestinationIn,
    7927         comp_func_solid_SourceOut,
    7928         comp_func_solid_DestinationOut,
    7929         comp_func_solid_SourceAtop,
    7930         comp_func_solid_DestinationAtop,
    7931         comp_func_solid_XOR,
    7932         comp_func_solid_Plus,
    7933         comp_func_solid_Multiply,
    7934         comp_func_solid_Screen,
    7935         comp_func_solid_Overlay,
    7936         comp_func_solid_Darken,
    7937         comp_func_solid_Lighten,
    7938         comp_func_solid_ColorDodge,
    7939         comp_func_solid_ColorBurn,
    7940         comp_func_solid_HardLight,
    7941         comp_func_solid_SoftLight,
    7942         comp_func_solid_Difference,
    7943         comp_func_solid_Exclusion,
    7944         rasterop_solid_SourceOrDestination,
    7945         rasterop_solid_SourceAndDestination,
    7946         rasterop_solid_SourceXorDestination,
    7947         rasterop_solid_NotSourceAndNotDestination,
    7948         rasterop_solid_NotSourceOrNotDestination,
    7949         rasterop_solid_NotSourceXorDestination,
    7950         rasterop_solid_NotSource,
    7951         rasterop_solid_NotSourceAndDestination,
    7952         rasterop_solid_SourceAndNotDestination
    7953 };
    7954 
    7955 static CompositionFunction qt_functionForMode_ARMv6[numCompositionFunctions] = {
    7956         comp_func_SourceOver_armv6,
    7957         comp_func_DestinationOver,
    7958         comp_func_Clear,
    7959         comp_func_Source_armv6,
    7960         comp_func_Destination,
    7961         comp_func_SourceIn,
    7962         comp_func_DestinationIn,
    7963         comp_func_SourceOut,
    7964         comp_func_DestinationOut,
    7965         comp_func_SourceAtop,
    7966         comp_func_DestinationAtop,
    7967         comp_func_XOR,
    7968         comp_func_Plus,
    7969         comp_func_Multiply,
    7970         comp_func_Screen,
    7971         comp_func_Overlay,
    7972         comp_func_Darken,
    7973         comp_func_Lighten,
    7974         comp_func_ColorDodge,
    7975         comp_func_ColorBurn,
    7976         comp_func_HardLight,
    7977         comp_func_SoftLight,
    7978         comp_func_Difference,
    7979         comp_func_Exclusion,
    7980         rasterop_SourceOrDestination,
    7981         rasterop_SourceAndDestination,
    7982         rasterop_SourceXorDestination,
    7983         rasterop_NotSourceAndNotDestination,
    7984         rasterop_NotSourceOrNotDestination,
    7985         rasterop_NotSourceXorDestination,
    7986         rasterop_NotSource,
    7987         rasterop_NotSourceAndDestination,
    7988         rasterop_SourceAndNotDestination
    7989 };
    7990 
    7991 static void qt_blend_color_argb_armv6(int count, const QSpan *spans, void *userData)
    7992 {
    7993     QSpanData *data = reinterpret_cast<QSpanData *>(userData);
    7994 
    7995     CompositionFunctionSolid func = qt_functionForModeSolid_ARMv6[data->rasterBuffer->compositionMode];
    7996     while (count--) {
    7997         uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x;
    7998         func(target, spans->len, data->solid.color, spans->coverage);
    7999         ++spans;
    8000     }
    8001 }
    8002 
    8003 #endif // Q_CC_RVCT && QT_HAVE_ARMV6
    8004 
    8005 
    80067793void qInitDrawhelperAsm()
    80077794{
    8008     static uint features = 0xffffffff;
    8009     if (features != 0xffffffff)
    8010         return;
    8011     features = detectCPUFeatures();
    80127795
    80137796    qt_memfill32 = qt_memfill_template<quint32, quint32>;
     
    80177800    CompositionFunctionSolid *functionForModeSolidAsm = 0;
    80187801
    8019 #ifdef QT_NO_DEBUG
     7802    const uint features = qDetectCPUFeatures();
    80207803    if (false) {
    80217804#ifdef QT_HAVE_SSE2
     
    80397822#endif
    80407823#endif // SSE
    8041 #if defined(QT_HAVE_MMXEXT) && defined(QT_HAVE_SSE)
    8042     } else if (features & MMXEXT) {
    8043         qt_memfill32 = qt_memfill32_sse;
    8044         qDrawHelper[QImage::Format_RGB16].bitmapBlit = qt_bitmapblit16_sse;
    8045 # ifdef QT_HAVE_3DNOW
    8046         if (features & MMX3DNOW) {
    8047             qt_memfill32 = qt_memfill32_sse3dnow;
    8048             qDrawHelper[QImage::Format_RGB16].bitmapBlit = qt_bitmapblit16_sse3dnow;
    8049         }
    8050 # endif // 3DNOW
    8051 #endif // MMXEXT
    80527824    }
    80537825#ifdef QT_HAVE_MMX
    80547826    if (features & MMX) {
    80557827        functionForModeAsm = qt_functionForMode_MMX;
     7828
    80567829        functionForModeSolidAsm = qt_functionForModeSolid_MMX;
    80577830        qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_mmx;
     
    80807853    }
    80817854#endif // MMX
     7855
     7856#ifdef QT_HAVE_SSE
     7857    if (features & SSE) {
     7858        extern void qt_blend_rgb32_on_rgb32_sse(uchar *destPixels, int dbpl,
     7859                                                const uchar *srcPixels, int sbpl,
     7860                                                int w, int h,
     7861                                                int const_alpha);
     7862        extern void qt_blend_argb32_on_argb32_sse(uchar *destPixels, int dbpl,
     7863                                                  const uchar *srcPixels, int sbpl,
     7864                                                  int w, int h,
     7865                                                  int const_alpha);
     7866
     7867        qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse;
     7868        qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse;
     7869        qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse;
     7870        qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse;
     7871    }
     7872#endif // SSE
     7873
     7874#ifdef QT_HAVE_SSE2
     7875    if (features & SSE2) {
     7876        extern void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl,
     7877                                                 const uchar *srcPixels, int sbpl,
     7878                                                 int w, int h,
     7879                                                 int const_alpha);
     7880        extern void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl,
     7881                                                   const uchar *srcPixels, int sbpl,
     7882                                                   int w, int h,
     7883                                                   int const_alpha);
     7884
     7885        qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2;
     7886        qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2;
     7887        qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2;
     7888        qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2;
     7889    }
     7890
     7891#ifdef QT_HAVE_SSSE3
     7892    if (features & SSSE3) {
     7893        extern void qt_blend_argb32_on_argb32_ssse3(uchar *destPixels, int dbpl,
     7894                                                    const uchar *srcPixels, int sbpl,
     7895                                                    int w, int h,
     7896                                                    int const_alpha);
     7897
     7898        qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_ssse3;
     7899        qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_ssse3;
     7900    }
     7901#endif // SSSE3
     7902
     7903#endif // SSE2
    80827904
    80837905#ifdef QT_HAVE_SSE
     
    80977919#ifdef QT_HAVE_SSE2
    80987920        if (features & SSE2) {
    8099             extern void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl,
    8100                                                      const uchar *srcPixels, int sbpl,
    8101                                                      int w, int h,
    8102                                                      int const_alpha);
    8103             extern void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl,
    8104                                                        const uchar *srcPixels, int sbpl,
    8105                                                        int w, int h,
    8106                                                        int const_alpha);
    8107 
    8108 
    8109             qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2;
    8110             qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2;
    8111             qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2;
    8112             qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2;
    8113         } else
     7921            extern void QT_FASTCALL comp_func_SourceOver_sse2(uint *destPixels,
     7922                                                              const uint *srcPixels,
     7923                                                              int length,
     7924                                                              uint const_alpha);
     7925            extern void QT_FASTCALL comp_func_solid_SourceOver_sse2(uint *destPixels, int length, uint color, uint const_alpha);
     7926            extern void QT_FASTCALL comp_func_Plus_sse2(uint *dst, const uint *src, int length, uint const_alpha);
     7927            extern void QT_FASTCALL comp_func_Source_sse2(uint *dst, const uint *src, int length, uint const_alpha);
     7928
     7929            functionForModeAsm[0] = comp_func_SourceOver_sse2;
     7930            functionForModeAsm[QPainter::CompositionMode_Source] = comp_func_Source_sse2;
     7931            functionForModeAsm[QPainter::CompositionMode_Plus] = comp_func_Plus_sse2;
     7932            functionForModeSolidAsm[0] = comp_func_solid_SourceOver_sse2;
     7933        }
    81147934#endif
    8115         {
    8116             extern void qt_blend_rgb32_on_rgb32_sse(uchar *destPixels, int dbpl,
    8117                                                     const uchar *srcPixels, int sbpl,
    8118                                                     int w, int h,
    8119                                                     int const_alpha);
    8120             extern void qt_blend_argb32_on_argb32_sse(uchar *destPixels, int dbpl,
    8121                                                       const uchar *srcPixels, int sbpl,
    8122                                                       int w, int h,
    8123                                                       int const_alpha);
    8124 
    8125 
    8126             qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse;
    8127             qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse;
    8128             qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse;
    8129             qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse;
    8130         }
    8131 }
    8132 #endif // SSE
     7935    }
     7936#elif defined(QT_HAVE_SSE2)
     7937    // this is the special case when SSE2 is usable but MMX/SSE is not usable (e.g.: Windows x64 + visual studio)
     7938    if (features & SSE2) {
     7939        functionForModeAsm = qt_functionForMode_onlySSE2;
     7940        functionForModeSolidAsm = qt_functionForModeSolid_onlySSE2;
     7941    }
     7942#endif
    81337943
    81347944#ifdef QT_HAVE_IWMMXT
     
    81407950#endif // IWMMXT
    81417951
    8142 #endif // QT_NO_DEBUG
    8143 
    8144 #if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6)
    8145         functionForModeAsm = qt_functionForMode_ARMv6;
    8146         functionForModeSolidAsm = qt_functionForModeSolid_ARMv6;
    8147 
    8148         qt_memfill32 = qt_memfill32_armv6;
    8149 
    8150         qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_armv6;
    8151 
    8152         qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6;
    8153         qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6;
    8154         qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6;
    8155         qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6;
     7952#if defined(QT_HAVE_ARM_SIMD)
     7953    qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_arm_simd;
     7954    qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_arm_simd;
     7955    qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_arm_simd;
     7956    qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_arm_simd;
    81567957#elif defined(QT_HAVE_NEON)
    8157         if (features & NEON) {
    8158             qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
    8159             qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
    8160             qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
    8161             qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
    8162         }
     7958    if (features & NEON) {
     7959        qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
     7960        qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
     7961        qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
     7962        qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
     7963        qBlendFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_rgb16_neon;
     7964        qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB16] = qt_blend_rgb16_on_argb32_neon;
     7965        qBlendFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_blend_rgb16_on_rgb16_neon;
     7966
     7967        qScaleFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_rgb16_neon;
     7968        qScaleFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_scale_image_rgb16_on_rgb16_neon;
     7969
     7970        qTransformFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_transform_image_argb32_on_rgb16_neon;
     7971        qTransformFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_transform_image_rgb16_on_rgb16_neon;
     7972
     7973        qDrawHelper[QImage::Format_RGB16].alphamapBlit = qt_alphamapblit_quint16_neon;
     7974
     7975        functionForMode_C[QPainter::CompositionMode_SourceOver] = qt_blend_argb32_on_argb32_scanline_neon;
     7976        functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_neon;
     7977        functionForMode_C[QPainter::CompositionMode_Plus] = comp_func_Plus_neon;
     7978        destFetchProc[QImage::Format_RGB16] = qt_destFetchRGB16_neon;
     7979        destStoreProc[QImage::Format_RGB16] = qt_destStoreRGB16_neon;
     7980
     7981        qMemRotateFunctions[QImage::Format_RGB16][0] = qt_memrotate90_16_neon;
     7982        qMemRotateFunctions[QImage::Format_RGB16][2] = qt_memrotate270_16_neon;
     7983        qt_memfill32 = qt_memfill32_neon;
     7984    }
    81637985#endif
    81647986
     
    81747996        functionForModeSolid = functionForModeSolidAsm;
    81757997    }
    8176     if (functionForModeAsm) {
    8177         const int destinationMode = QPainter::CompositionMode_Destination;
    8178         functionForModeAsm[destinationMode] = functionForMode_C[destinationMode];
    8179 
    8180         // use the default qdrawhelper implementation for the
    8181         // extended composition modes
    8182         for (int mode = 12; mode < numCompositionFunctions; ++mode)
    8183             functionForModeAsm[mode] = functionForMode_C[mode];
    8184 
     7998    if (functionForModeAsm)
    81857999        functionForMode = functionForModeAsm;
    8186     }
    81878000
    81888001    qt_build_pow_tables();
  • trunk/src/gui/painting/qdrawhelper_iwmmxt.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    107107    comp_func_Clear<QIWMMXTIntrinsics>,
    108108    comp_func_Source<QIWMMXTIntrinsics>,
    109     0,
     109    comp_func_Destination,
    110110    comp_func_SourceIn<QIWMMXTIntrinsics>,
    111111    comp_func_DestinationIn<QIWMMXTIntrinsics>,
     
    114114    comp_func_SourceAtop<QIWMMXTIntrinsics>,
    115115    comp_func_DestinationAtop<QIWMMXTIntrinsics>,
    116     comp_func_XOR<QIWMMXTIntrinsics>
     116    comp_func_XOR<QIWMMXTIntrinsics>,
     117    comp_func_Plus,
     118    comp_func_Multiply,
     119    comp_func_Screen,
     120    comp_func_Overlay,
     121    comp_func_Darken,
     122    comp_func_Lighten,
     123    comp_func_ColorDodge,
     124    comp_func_ColorBurn,
     125    comp_func_HardLight,
     126    comp_func_SoftLight,
     127    comp_func_Difference,
     128    comp_func_Exclusion,
     129    rasterop_SourceOrDestination,
     130    rasterop_SourceAndDestination,
     131    rasterop_SourceXorDestination,
     132    rasterop_NotSourceAndNotDestination,
     133    rasterop_NotSourceOrNotDestination,
     134    rasterop_NotSourceXorDestination,
     135    rasterop_NotSource,
     136    rasterop_NotSourceAndDestination,
     137    rasterop_SourceAndNotDestination
    117138};
    118139
  • trunk/src/gui/painting/qdrawhelper_mmx.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7878    comp_func_Clear<QMMXIntrinsics>,
    7979    comp_func_Source<QMMXIntrinsics>,
    80     0,
     80    comp_func_Destination,
    8181    comp_func_SourceIn<QMMXIntrinsics>,
    8282    comp_func_DestinationIn<QMMXIntrinsics>,
     
    8686    comp_func_DestinationAtop<QMMXIntrinsics>,
    8787    comp_func_XOR<QMMXIntrinsics>,
     88    comp_func_Plus,
     89    comp_func_Multiply,
     90    comp_func_Screen,
     91    comp_func_Overlay,
     92    comp_func_Darken,
     93    comp_func_Lighten,
     94    comp_func_ColorDodge,
     95    comp_func_ColorBurn,
     96    comp_func_HardLight,
     97    comp_func_SoftLight,
     98    comp_func_Difference,
     99    comp_func_Exclusion,
     100    rasterop_SourceOrDestination,
     101    rasterop_SourceAndDestination,
     102    rasterop_SourceXorDestination,
     103    rasterop_NotSourceAndNotDestination,
     104    rasterop_NotSourceOrNotDestination,
     105    rasterop_NotSourceXorDestination,
     106    rasterop_NotSource,
     107    rasterop_NotSourceAndDestination,
     108    rasterop_SourceAndNotDestination
    88109};
    89110
  • trunk/src/gui/painting/qdrawhelper_mmx3dnow.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8686    comp_func_Clear<QMMX3DNOWIntrinsics>,
    8787    comp_func_Source<QMMX3DNOWIntrinsics>,
    88     0,
     88    comp_func_Destination,
    8989    comp_func_SourceIn<QMMX3DNOWIntrinsics>,
    9090    comp_func_DestinationIn<QMMX3DNOWIntrinsics>,
     
    9393    comp_func_SourceAtop<QMMX3DNOWIntrinsics>,
    9494    comp_func_DestinationAtop<QMMX3DNOWIntrinsics>,
    95     comp_func_XOR<QMMX3DNOWIntrinsics>
     95    comp_func_XOR<QMMX3DNOWIntrinsics>,
     96    comp_func_Plus,
     97    comp_func_Multiply,
     98    comp_func_Screen,
     99    comp_func_Overlay,
     100    comp_func_Darken,
     101    comp_func_Lighten,
     102    comp_func_ColorDodge,
     103    comp_func_ColorBurn,
     104    comp_func_HardLight,
     105    comp_func_SoftLight,
     106    comp_func_Difference,
     107    comp_func_Exclusion,
     108    rasterop_SourceOrDestination,
     109    rasterop_SourceAndDestination,
     110    rasterop_SourceXorDestination,
     111    rasterop_NotSourceAndNotDestination,
     112    rasterop_NotSourceOrNotDestination,
     113    rasterop_NotSourceXorDestination,
     114    rasterop_NotSource,
     115    rasterop_NotSourceAndDestination,
     116    rasterop_SourceAndNotDestination
    96117};
    97118
  • trunk/src/gui/painting/qdrawhelper_mmx_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qdrawhelper_neon.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4141
    4242#include <private/qdrawhelper_p.h>
     43#include <private/qblendfunctions_p.h>
     44#include <private/qmath_p.h>
    4345
    4446#ifdef QT_HAVE_NEON
    4547
    4648#include <private/qdrawhelper_neon_p.h>
     49#include <private/qpaintengine_raster_p.h>
    4750#include <arm_neon.h>
    4851
    4952QT_BEGIN_NAMESPACE
     53
     54void qt_memfill32_neon(quint32 *dest, quint32 value, int count)
     55{
     56    const int epilogueSize = count % 16;
     57    if (count >= 16) {
     58        quint32 *const neonEnd = dest + count - epilogueSize;
     59        register uint32x4_t valueVector1 asm ("q0") = vdupq_n_u32(value);
     60        register uint32x4_t valueVector2 asm ("q1") = valueVector1;
     61        while (dest != neonEnd) {
     62            asm volatile (
     63                "vst2.32     { d0, d1, d2, d3 }, [%[DST]] !\n\t"
     64                "vst2.32     { d0, d1, d2, d3 }, [%[DST]] !\n\t"
     65                : [DST]"+r" (dest)
     66                : [VALUE1]"w"(valueVector1), [VALUE2]"w"(valueVector2)
     67                : "memory"
     68            );
     69        }
     70    }
     71
     72    switch (epilogueSize)
     73    {
     74    case 15:     *dest++ = value;
     75    case 14:     *dest++ = value;
     76    case 13:     *dest++ = value;
     77    case 12:     *dest++ = value;
     78    case 11:     *dest++ = value;
     79    case 10:     *dest++ = value;
     80    case 9:      *dest++ = value;
     81    case 8:      *dest++ = value;
     82    case 7:      *dest++ = value;
     83    case 6:      *dest++ = value;
     84    case 5:      *dest++ = value;
     85    case 4:      *dest++ = value;
     86    case 3:      *dest++ = value;
     87    case 2:      *dest++ = value;
     88    case 1:      *dest++ = value;
     89    }
     90}
    5091
    5192static inline uint16x8_t qvdiv_255_u16(uint16x8_t x, uint16x8_t half)
     
    86127
    87128    return vaddq_u16(src16, qvbyte_mul_u16(dst16, alpha16, half));
     129}
     130
     131extern "C" void
     132pixman_composite_over_8888_0565_asm_neon (int32_t   w,
     133                                          int32_t   h,
     134                                          uint16_t *dst,
     135                                          int32_t   dst_stride,
     136                                          uint32_t *src,
     137                                          int32_t   src_stride);
     138
     139extern "C" void
     140pixman_composite_over_8888_8888_asm_neon (int32_t   w,
     141                                          int32_t   h,
     142                                          uint32_t *dst,
     143                                          int32_t   dst_stride,
     144                                          uint32_t *src,
     145                                          int32_t   src_stride);
     146
     147extern "C" void
     148pixman_composite_src_0565_8888_asm_neon (int32_t   w,
     149                                         int32_t   h,
     150                                         uint32_t *dst,
     151                                         int32_t   dst_stride,
     152                                         uint16_t *src,
     153                                         int32_t   src_stride);
     154
     155extern "C" void
     156pixman_composite_over_n_8_0565_asm_neon (int32_t    w,
     157                                         int32_t    h,
     158                                         uint16_t  *dst,
     159                                         int32_t    dst_stride,
     160                                         uint32_t   src,
     161                                         int32_t    unused,
     162                                         uint8_t   *mask,
     163                                         int32_t    mask_stride);
     164
     165extern "C" void
     166pixman_composite_scanline_over_asm_neon (int32_t         w,
     167                                         const uint32_t *dst,
     168                                         const uint32_t *src);
     169
     170extern "C" void
     171pixman_composite_src_0565_0565_asm_neon (int32_t   w,
     172                                         int32_t   h,
     173                                         uint16_t *dst,
     174                                         int32_t   dst_stride,
     175                                         uint16_t *src,
     176                                         int32_t   src_stride);
     177
     178// qblendfunctions.cpp
     179void qt_blend_argb32_on_rgb16_const_alpha(uchar *destPixels, int dbpl,
     180                                          const uchar *srcPixels, int sbpl,
     181                                          int w, int h,
     182                                          int const_alpha);
     183
     184void qt_blend_rgb16_on_argb32_neon(uchar *destPixels, int dbpl,
     185                                   const uchar *srcPixels, int sbpl,
     186                                   int w, int h,
     187                                   int const_alpha)
     188{
     189    dbpl /= 4;
     190    sbpl /= 2;
     191
     192    quint32 *dst = (quint32 *) destPixels;
     193    quint16 *src = (quint16 *) srcPixels;
     194
     195    if (const_alpha != 256) {
     196        quint8 a = (255 * const_alpha) >> 8;
     197        quint8 ia = 255 - a;
     198
     199        while (h--) {
     200            for (int x=0; x<w; ++x)
     201                dst[x] = INTERPOLATE_PIXEL_255(qt_colorConvert(src[x], dst[x]), a, dst[x], ia);
     202            dst += dbpl;
     203            src += sbpl;
     204        }
     205        return;
     206    }
     207
     208    pixman_composite_src_0565_8888_asm_neon(w, h, dst, dbpl, src, sbpl);
     209}
     210
     211// qblendfunctions.cpp
     212void qt_blend_rgb16_on_rgb16(uchar *dst, int dbpl,
     213                             const uchar *src, int sbpl,
     214                             int w, int h,
     215                             int const_alpha);
     216
     217template <int N>
     218static inline void scanLineBlit16(quint16 *dst, quint16 *src, int dstride)
     219{
     220    if (N >= 2) {
     221        ((quint32 *)dst)[0] = ((quint32 *)src)[0];
     222        __builtin_prefetch(dst + dstride, 1, 0);
     223    }
     224    for (int i = 1; i < N/2; ++i)
     225        ((quint32 *)dst)[i] = ((quint32 *)src)[i];
     226    if (N & 1)
     227        dst[N-1] = src[N-1];
     228}
     229
     230template <int Width>
     231static inline void blockBlit16(quint16 *dst, quint16 *src, int dstride, int sstride, int h)
     232{
     233    union {
     234        quintptr address;
     235        quint16 *pointer;
     236    } u;
     237
     238    u.pointer = dst;
     239
     240    if (u.address & 2) {
     241        while (h--) {
     242            // align dst
     243            dst[0] = src[0];
     244            if (Width > 1)
     245                scanLineBlit16<Width-1>(dst + 1, src + 1, dstride);
     246            dst += dstride;
     247            src += sstride;
     248        }
     249    } else {
     250        while (h--) {
     251            scanLineBlit16<Width>(dst, src, dstride);
     252
     253            dst += dstride;
     254            src += sstride;
     255        }
     256    }
     257}
     258
     259void qt_blend_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl,
     260                                  const uchar *srcPixels, int sbpl,
     261                                  int w, int h,
     262                                  int const_alpha)
     263{
     264    // testing show that the default memcpy is faster for widths 150 and up
     265    if (const_alpha != 256 || w >= 150) {
     266        qt_blend_rgb16_on_rgb16(destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
     267        return;
     268    }
     269
     270    int dstride = dbpl / 2;
     271    int sstride = sbpl / 2;
     272
     273    quint16 *dst = (quint16 *) destPixels;
     274    quint16 *src = (quint16 *) srcPixels;
     275
     276    switch (w) {
     277#define BLOCKBLIT(n) case n: blockBlit16<n>(dst, src, dstride, sstride, h); return;
     278    BLOCKBLIT(1);
     279    BLOCKBLIT(2);
     280    BLOCKBLIT(3);
     281    BLOCKBLIT(4);
     282    BLOCKBLIT(5);
     283    BLOCKBLIT(6);
     284    BLOCKBLIT(7);
     285    BLOCKBLIT(8);
     286    BLOCKBLIT(9);
     287    BLOCKBLIT(10);
     288    BLOCKBLIT(11);
     289    BLOCKBLIT(12);
     290    BLOCKBLIT(13);
     291    BLOCKBLIT(14);
     292    BLOCKBLIT(15);
     293#undef BLOCKBLIT
     294    default:
     295        break;
     296    }
     297
     298    pixman_composite_src_0565_0565_asm_neon (w, h, dst, dstride, src, sstride);
     299}
     300
     301extern "C" void blend_8_pixels_argb32_on_rgb16_neon(quint16 *dst, const quint32 *src, int const_alpha);
     302
     303void qt_blend_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
     304                                   const uchar *srcPixels, int sbpl,
     305                                   int w, int h,
     306                                   int const_alpha)
     307{
     308    quint16 *dst = (quint16 *) destPixels;
     309    quint32 *src = (quint32 *) srcPixels;
     310
     311    if (const_alpha != 256) {
     312        for (int y=0; y<h; ++y) {
     313            int i = 0;
     314            for (; i < w-7; i += 8)
     315                blend_8_pixels_argb32_on_rgb16_neon(&dst[i], &src[i], const_alpha);
     316
     317            if (i < w) {
     318                int tail = w - i;
     319
     320                quint16 dstBuffer[8];
     321                quint32 srcBuffer[8];
     322
     323                for (int j = 0; j < tail; ++j) {
     324                    dstBuffer[j] = dst[i + j];
     325                    srcBuffer[j] = src[i + j];
     326                }
     327
     328                blend_8_pixels_argb32_on_rgb16_neon(dstBuffer, srcBuffer, const_alpha);
     329
     330                for (int j = 0; j < tail; ++j) {
     331                    dst[i + j] = dstBuffer[j];
     332                    src[i + j] = srcBuffer[j];
     333                }
     334            }
     335
     336            dst = (quint16 *)(((uchar *) dst) + dbpl);
     337            src = (quint32 *)(((uchar *) src) + sbpl);
     338        }
     339        return;
     340    }
     341
     342    pixman_composite_over_8888_0565_asm_neon(w, h, dst, dbpl / 2, src, sbpl / 4);
     343}
     344
     345void qt_blend_argb32_on_argb32_scanline_neon(uint *dest, const uint *src, int length, uint const_alpha)
     346{
     347    if (const_alpha == 255) {
     348        pixman_composite_scanline_over_asm_neon(length, dest, src);
     349    } else {
     350        qt_blend_argb32_on_argb32_neon((uchar *)dest, 4 * length, (uchar *)src, 4 * length, length, 1, (const_alpha * 256) / 255);
     351    }
    88352}
    89353
     
    98362    uint16x8_t full = vdupq_n_u16(0xff);
    99363    if (const_alpha == 256) {
    100         for (int y = 0; y < h; ++y) {
    101             int x = 0;
    102             for (; x < w-3; x += 4) {
    103                 uint32x4_t src32 = vld1q_u32((uint32_t *)&src[x]);
    104                 if ((src[x] & src[x+1] & src[x+2] & src[x+3]) >= 0xff000000) {
    105                     // all opaque
    106                     vst1q_u32((uint32_t *)&dst[x], src32);
    107                 } else if (src[x] | src[x+1] | src[x+2] | src[x+3]) {
    108                     uint32x4_t dst32 = vld1q_u32((uint32_t *)&dst[x]);
    109 
    110                     const uint8x16_t src8 = vreinterpretq_u8_u32(src32);
    111                     const uint8x16_t dst8 = vreinterpretq_u8_u32(dst32);
    112 
    113                     const uint8x8_t src8_low = vget_low_u8(src8);
    114                     const uint8x8_t dst8_low = vget_low_u8(dst8);
    115 
    116                     const uint8x8_t src8_high = vget_high_u8(src8);
    117                     const uint8x8_t dst8_high = vget_high_u8(dst8);
    118 
    119                     const uint16x8_t src16_low = vmovl_u8(src8_low);
    120                     const uint16x8_t dst16_low = vmovl_u8(dst8_low);
    121 
    122                     const uint16x8_t src16_high = vmovl_u8(src8_high);
    123                     const uint16x8_t dst16_high = vmovl_u8(dst8_high);
    124 
    125                     const uint16x8_t result16_low = qvsource_over_u16(src16_low, dst16_low, half, full);
    126                     const uint16x8_t result16_high = qvsource_over_u16(src16_high, dst16_high, half, full);
    127 
    128                     const uint32x2_t result32_low = vreinterpret_u32_u8(vmovn_u16(result16_low));
    129                     const uint32x2_t result32_high = vreinterpret_u32_u8(vmovn_u16(result16_high));
    130 
    131                     vst1q_u32((uint32_t *)&dst[x], vcombine_u32(result32_low, result32_high));
    132                 }
    133             }
    134             for (; x<w; ++x) {
    135                 uint s = src[x];
    136                 if (s >= 0xff000000)
    137                     dst[x] = s;
    138                 else if (s != 0)
    139                     dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s));
    140             }
    141             dst = (quint32 *)(((uchar *) dst) + dbpl);
    142             src = (const quint32 *)(((const uchar *) src) + sbpl);
    143         }
     364        pixman_composite_over_8888_8888_asm_neon(w, h, (uint32_t *)destPixels, dbpl / 4, (uint32_t *)srcPixels, sbpl / 4);
    144365    } else if (const_alpha != 0) {
    145366        const_alpha = (const_alpha * 255) >> 8;
     
    255476}
    256477
     478void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer,
     479                                  int x, int y, quint32 color,
     480                                  const uchar *bitmap,
     481                                  int mapWidth, int mapHeight, int mapStride,
     482                                  const QClipData *)
     483{
     484    quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x;
     485    const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16);
     486
     487    uchar *mask = const_cast<uchar *>(bitmap);
     488
     489    pixman_composite_over_n_8_0565_asm_neon(mapWidth, mapHeight, dest, destStride, color, 0, mask, mapStride);
     490}
     491
     492extern "C" void blend_8_pixels_rgb16_on_rgb16_neon(quint16 *dst, const quint16 *src, int const_alpha);
     493
     494template <typename SRC, typename BlendFunc>
     495struct Blend_on_RGB16_SourceAndConstAlpha_Neon {
     496    Blend_on_RGB16_SourceAndConstAlpha_Neon(BlendFunc blender, int const_alpha)
     497        : m_index(0)
     498        , m_blender(blender)
     499        , m_const_alpha(const_alpha)
     500    {
     501    }
     502
     503    inline void write(quint16 *dst, quint32 src)
     504    {
     505        srcBuffer[m_index++] = src;
     506
     507        if (m_index == 8) {
     508            m_blender(dst - 7, srcBuffer, m_const_alpha);
     509            m_index = 0;
     510        }
     511    }
     512
     513    inline void flush(quint16 *dst)
     514    {
     515        if (m_index > 0) {
     516            quint16 dstBuffer[8];
     517            for (int i = 0; i < m_index; ++i)
     518                dstBuffer[i] = dst[i - m_index];
     519
     520            m_blender(dstBuffer, srcBuffer, m_const_alpha);
     521
     522            for (int i = 0; i < m_index; ++i)
     523                dst[i - m_index] = dstBuffer[i];
     524
     525            m_index = 0;
     526        }
     527    }
     528
     529    SRC srcBuffer[8];
     530
     531    int m_index;
     532    BlendFunc m_blender;
     533    int m_const_alpha;
     534};
     535
     536template <typename SRC, typename BlendFunc>
     537Blend_on_RGB16_SourceAndConstAlpha_Neon<SRC, BlendFunc>
     538Blend_on_RGB16_SourceAndConstAlpha_Neon_create(BlendFunc blender, int const_alpha)
     539{
     540    return Blend_on_RGB16_SourceAndConstAlpha_Neon<SRC, BlendFunc>(blender, const_alpha);
     541}
     542
     543void qt_scale_image_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
     544                                         const uchar *srcPixels, int sbpl,
     545                                         const QRectF &targetRect,
     546                                         const QRectF &sourceRect,
     547                                         const QRect &clip,
     548                                         int const_alpha)
     549{
     550    if (const_alpha == 0)
     551        return;
     552
     553    qt_scale_image_16bit<quint32>(destPixels, dbpl, srcPixels, sbpl, targetRect, sourceRect, clip,
     554        Blend_on_RGB16_SourceAndConstAlpha_Neon_create<quint32>(blend_8_pixels_argb32_on_rgb16_neon, const_alpha));
     555}
     556
     557void qt_scale_image_rgb16_on_rgb16(uchar *destPixels, int dbpl,
     558                                   const uchar *srcPixels, int sbpl,
     559                                   const QRectF &targetRect,
     560                                   const QRectF &sourceRect,
     561                                   const QRect &clip,
     562                                   int const_alpha);
     563
     564void qt_scale_image_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl,
     565                                        const uchar *srcPixels, int sbpl,
     566                                        const QRectF &targetRect,
     567                                        const QRectF &sourceRect,
     568                                        const QRect &clip,
     569                                        int const_alpha)
     570{
     571    if (const_alpha == 0)
     572        return;
     573
     574    if (const_alpha == 256) {
     575        qt_scale_image_rgb16_on_rgb16(destPixels, dbpl, srcPixels, sbpl, targetRect, sourceRect, clip, const_alpha);
     576        return;
     577    }
     578
     579    qt_scale_image_16bit<quint16>(destPixels, dbpl, srcPixels, sbpl, targetRect, sourceRect, clip,
     580        Blend_on_RGB16_SourceAndConstAlpha_Neon_create<quint16>(blend_8_pixels_rgb16_on_rgb16_neon, const_alpha));
     581}
     582
     583extern void qt_transform_image_rgb16_on_rgb16(uchar *destPixels, int dbpl,
     584                                              const uchar *srcPixels, int sbpl,
     585                                              const QRectF &targetRect,
     586                                              const QRectF &sourceRect,
     587                                              const QRect &clip,
     588                                              const QTransform &targetRectTransform,
     589                                              int const_alpha);
     590
     591void qt_transform_image_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl,
     592                                            const uchar *srcPixels, int sbpl,
     593                                            const QRectF &targetRect,
     594                                            const QRectF &sourceRect,
     595                                            const QRect &clip,
     596                                            const QTransform &targetRectTransform,
     597                                            int const_alpha)
     598{
     599    if (const_alpha == 0)
     600        return;
     601
     602    if (const_alpha == 256) {
     603        qt_transform_image_rgb16_on_rgb16(destPixels, dbpl, srcPixels, sbpl, targetRect, sourceRect, clip, targetRectTransform, const_alpha);
     604        return;
     605    }
     606
     607    qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl,
     608                       reinterpret_cast<const quint16 *>(srcPixels), sbpl, targetRect, sourceRect, clip, targetRectTransform,
     609        Blend_on_RGB16_SourceAndConstAlpha_Neon_create<quint16>(blend_8_pixels_rgb16_on_rgb16_neon, const_alpha));
     610}
     611
     612void qt_transform_image_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
     613                                             const uchar *srcPixels, int sbpl,
     614                                             const QRectF &targetRect,
     615                                             const QRectF &sourceRect,
     616                                             const QRect &clip,
     617                                             const QTransform &targetRectTransform,
     618                                             int const_alpha)
     619{
     620    if (const_alpha == 0)
     621        return;
     622
     623    qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl,
     624                       reinterpret_cast<const quint32 *>(srcPixels), sbpl, targetRect, sourceRect, clip, targetRectTransform,
     625        Blend_on_RGB16_SourceAndConstAlpha_Neon_create<quint32>(blend_8_pixels_argb32_on_rgb16_neon, const_alpha));
     626}
     627
     628static inline void convert_8_pixels_rgb16_to_argb32(quint32 *dst, const quint16 *src)
     629{
     630    asm volatile (
     631        "vld1.16     { d0, d1 }, [%[SRC]]\n\t"
     632
     633        /* convert 8 r5g6b5 pixel data from {d0, d1} to planar 8-bit format
     634           and put data into d4 - red, d3 - green, d2 - blue */
     635        "vshrn.u16   d4,  q0,  #8\n\t"
     636        "vshrn.u16   d3,  q0,  #3\n\t"
     637        "vsli.u16    q0,  q0,  #5\n\t"
     638        "vsri.u8     d4,  d4,  #5\n\t"
     639        "vsri.u8     d3,  d3,  #6\n\t"
     640        "vshrn.u16   d2,  q0,  #2\n\t"
     641
     642        /* fill d5 - alpha with 0xff */
     643        "mov         r2, #255\n\t"
     644        "vdup.8      d5, r2\n\t"
     645
     646        "vst4.8      { d2, d3, d4, d5 }, [%[DST]]"
     647        : : [DST]"r" (dst), [SRC]"r" (src)
     648        : "memory", "r2", "d0", "d1", "d2", "d3", "d4", "d5"
     649    );
     650}
     651
     652uint * QT_FASTCALL qt_destFetchRGB16_neon(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
     653{
     654    const ushort *data = (const ushort *)rasterBuffer->scanLine(y) + x;
     655
     656    int i = 0;
     657    for (; i < length - 7; i += 8)
     658        convert_8_pixels_rgb16_to_argb32(&buffer[i], &data[i]);
     659
     660    if (i < length) {
     661        quint16 srcBuffer[8];
     662        quint32 dstBuffer[8];
     663
     664        int tail = length - i;
     665        for (int j = 0; j < tail; ++j)
     666            srcBuffer[j] = data[i + j];
     667
     668        convert_8_pixels_rgb16_to_argb32(dstBuffer, srcBuffer);
     669
     670        for (int j = 0; j < tail; ++j)
     671            buffer[i + j] = dstBuffer[j];
     672    }
     673
     674    return buffer;
     675}
     676
     677static inline void convert_8_pixels_argb32_to_rgb16(quint16 *dst, const quint32 *src)
     678{
     679    asm volatile (
     680        "vld4.8      { d0, d1, d2, d3 }, [%[SRC]]\n\t"
     681
     682        /* convert to r5g6b5 and store it into {d28, d29} */
     683        "vshll.u8    q14, d2, #8\n\t"
     684        "vshll.u8    q8,  d1, #8\n\t"
     685        "vshll.u8    q9,  d0, #8\n\t"
     686        "vsri.u16    q14, q8, #5\n\t"
     687        "vsri.u16    q14, q9, #11\n\t"
     688
     689        "vst1.16     { d28, d29 }, [%[DST]]"
     690        : : [DST]"r" (dst), [SRC]"r" (src)
     691        : "memory", "d0", "d1", "d2", "d3", "d16", "d17", "d18", "d19", "d28", "d29"
     692    );
     693}
     694
     695void QT_FASTCALL qt_destStoreRGB16_neon(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length)
     696{
     697    quint16 *data = (quint16*)rasterBuffer->scanLine(y) + x;
     698
     699    int i = 0;
     700    for (; i < length - 7; i += 8)
     701        convert_8_pixels_argb32_to_rgb16(&data[i], &buffer[i]);
     702
     703    if (i < length) {
     704        quint32 srcBuffer[8];
     705        quint16 dstBuffer[8];
     706
     707        int tail = length - i;
     708        for (int j = 0; j < tail; ++j)
     709            srcBuffer[j] = buffer[i + j];
     710
     711        convert_8_pixels_argb32_to_rgb16(dstBuffer, srcBuffer);
     712
     713        for (int j = 0; j < tail; ++j)
     714            data[i + j] = dstBuffer[j];
     715    }
     716}
     717
     718void QT_FASTCALL comp_func_solid_SourceOver_neon(uint *destPixels, int length, uint color, uint const_alpha)
     719{
     720    if ((const_alpha & qAlpha(color)) == 255) {
     721        QT_MEMFILL_UINT(destPixels, length, color);
     722    } else {
     723        if (const_alpha != 255)
     724            color = BYTE_MUL(color, const_alpha);
     725
     726        const quint32 minusAlphaOfColor = qAlpha(~color);
     727        int x = 0;
     728
     729        uint32_t *dst = (uint32_t *) destPixels;
     730        const uint32x4_t colorVector = vdupq_n_u32(color);
     731        uint16x8_t half = vdupq_n_u16(0x80);
     732        const uint16x8_t minusAlphaOfColorVector = vdupq_n_u16(minusAlphaOfColor);
     733
     734        for (; x < length-3; x += 4) {
     735            uint32x4_t dstVector = vld1q_u32(&dst[x]);
     736
     737            const uint8x16_t dst8 = vreinterpretq_u8_u32(dstVector);
     738
     739            const uint8x8_t dst8_low = vget_low_u8(dst8);
     740            const uint8x8_t dst8_high = vget_high_u8(dst8);
     741
     742            const uint16x8_t dst16_low = vmovl_u8(dst8_low);
     743            const uint16x8_t dst16_high = vmovl_u8(dst8_high);
     744
     745            const uint16x8_t result16_low = qvbyte_mul_u16(dst16_low, minusAlphaOfColorVector, half);
     746            const uint16x8_t result16_high = qvbyte_mul_u16(dst16_high, minusAlphaOfColorVector, half);
     747
     748            const uint32x2_t result32_low = vreinterpret_u32_u8(vmovn_u16(result16_low));
     749            const uint32x2_t result32_high = vreinterpret_u32_u8(vmovn_u16(result16_high));
     750
     751            uint32x4_t blendedPixels = vcombine_u32(result32_low, result32_high);
     752            uint32x4_t colorPlusBlendedPixels = vaddq_u32(colorVector, blendedPixels);
     753            vst1q_u32(&dst[x], colorPlusBlendedPixels);
     754        }
     755
     756        for (;x < length; ++x)
     757            destPixels[x] = color + BYTE_MUL(destPixels[x], minusAlphaOfColor);
     758    }
     759}
     760
     761void QT_FASTCALL comp_func_Plus_neon(uint *dst, const uint *src, int length, uint const_alpha)
     762{
     763    if (const_alpha == 255) {
     764        uint *const end = dst + length;
     765        uint *const neonEnd = end - 3;
     766
     767        while (dst < neonEnd) {
     768            asm volatile (
     769                "vld2.8     { d0, d1 }, [%[SRC]] !\n\t"
     770                "vld2.8     { d2, d3 }, [%[DST]]\n\t"
     771                "vqadd.u8 q0, q0, q1\n\t"
     772                "vst2.8     { d0, d1 }, [%[DST]] !\n\t"
     773                : [DST]"+r" (dst), [SRC]"+r" (src)
     774                :
     775                : "memory", "d0", "d1", "d2", "d3", "q0", "q1"
     776            );
     777        }
     778
     779        while (dst != end) {
     780            *dst = comp_func_Plus_one_pixel(*dst, *src);
     781            ++dst;
     782            ++src;
     783        }
     784    } else {
     785        int x = 0;
     786        const int one_minus_const_alpha = 255 - const_alpha;
     787        const uint16x8_t constAlphaVector = vdupq_n_u16(const_alpha);
     788        const uint16x8_t oneMinusconstAlphaVector = vdupq_n_u16(one_minus_const_alpha);
     789
     790        const uint16x8_t half = vdupq_n_u16(0x80);
     791        for (; x < length - 3; x += 4) {
     792            const uint32x4_t src32 = vld1q_u32((uint32_t *)&src[x]);
     793            const uint8x16_t src8 = vreinterpretq_u8_u32(src32);
     794            uint8x16_t dst8 = vld1q_u8((uint8_t *)&dst[x]);
     795            uint8x16_t result = vqaddq_u8(dst8, src8);
     796
     797            uint16x8_t result_low = vmovl_u8(vget_low_u8(result));
     798            uint16x8_t result_high = vmovl_u8(vget_high_u8(result));
     799
     800            uint16x8_t dst_low = vmovl_u8(vget_low_u8(dst8));
     801            uint16x8_t dst_high = vmovl_u8(vget_high_u8(dst8));
     802
     803            result_low = qvinterpolate_pixel_255(result_low, constAlphaVector, dst_low, oneMinusconstAlphaVector, half);
     804            result_high = qvinterpolate_pixel_255(result_high, constAlphaVector, dst_high, oneMinusconstAlphaVector, half);
     805
     806            const uint32x2_t result32_low = vreinterpret_u32_u8(vmovn_u16(result_low));
     807            const uint32x2_t result32_high = vreinterpret_u32_u8(vmovn_u16(result_high));
     808            vst1q_u32((uint32_t *)&dst[x], vcombine_u32(result32_low, result32_high));
     809        }
     810
     811        for (; x < length; ++x)
     812            dst[x] = comp_func_Plus_one_pixel_const_alpha(dst[x], src[x], const_alpha, one_minus_const_alpha);
     813    }
     814}
     815
     816static const int tileSize = 32;
     817
     818extern "C" void qt_rotate90_16_neon(quint16 *dst, const quint16 *src, int sstride, int dstride, int count);
     819
     820void qt_memrotate90_16_neon(const uchar *srcPixels, int w, int h, int sstride, uchar *destPixels, int dstride)
     821{
     822    const ushort *src = (const ushort *)srcPixels;
     823    ushort *dest = (ushort *)destPixels;
     824
     825    sstride /= sizeof(ushort);
     826    dstride /= sizeof(ushort);
     827
     828    const int pack = sizeof(quint32) / sizeof(ushort);
     829    const int unaligned =
     830        qMin(uint((quintptr(dest) & (sizeof(quint32)-1)) / sizeof(ushort)), uint(h));
     831    const int restX = w % tileSize;
     832    const int restY = (h - unaligned) % tileSize;
     833    const int unoptimizedY = restY % pack;
     834    const int numTilesX = w / tileSize + (restX > 0);
     835    const int numTilesY = (h - unaligned) / tileSize + (restY >= pack);
     836
     837    for (int tx = 0; tx < numTilesX; ++tx) {
     838        const int startx = w - tx * tileSize - 1;
     839        const int stopx = qMax(startx - tileSize, 0);
     840
     841        if (unaligned) {
     842            for (int x = startx; x >= stopx; --x) {
     843                ushort *d = dest + (w - x - 1) * dstride;
     844                for (int y = 0; y < unaligned; ++y) {
     845                    *d++ = src[y * sstride + x];
     846                }
     847            }
     848        }
     849
     850        for (int ty = 0; ty < numTilesY; ++ty) {
     851            const int starty = ty * tileSize + unaligned;
     852            const int stopy = qMin(starty + tileSize, h - unoptimizedY);
     853
     854            int x = startx;
     855            // qt_rotate90_16_neon writes to eight rows, four pixels at a time
     856            for (; x >= stopx + 7; x -= 8) {
     857                ushort *d = dest + (w - x - 1) * dstride + starty;
     858                const ushort *s = &src[starty * sstride + x - 7];
     859                qt_rotate90_16_neon(d, s, sstride * 2, dstride * 2, stopy - starty);
     860            }
     861
     862            for (; x >= stopx; --x) {
     863                quint32 *d = reinterpret_cast<quint32*>(dest + (w - x - 1) * dstride + starty);
     864                for (int y = starty; y < stopy; y += pack) {
     865                    quint32 c = src[y * sstride + x];
     866                    for (int i = 1; i < pack; ++i) {
     867                        const int shift = (sizeof(int) * 8 / pack * i);
     868                        const ushort color = src[(y + i) * sstride + x];
     869                        c |= color << shift;
     870                    }
     871                    *d++ = c;
     872                }
     873            }
     874        }
     875
     876        if (unoptimizedY) {
     877            const int starty = h - unoptimizedY;
     878            for (int x = startx; x >= stopx; --x) {
     879                ushort *d = dest + (w - x - 1) * dstride + starty;
     880                for (int y = starty; y < h; ++y) {
     881                    *d++ = src[y * sstride + x];
     882                }
     883            }
     884        }
     885    }
     886}
     887
     888extern "C" void qt_rotate270_16_neon(quint16 *dst, const quint16 *src, int sstride, int dstride, int count);
     889
     890void qt_memrotate270_16_neon(const uchar *srcPixels, int w, int h,
     891                             int sstride,
     892                             uchar *destPixels, int dstride)
     893{
     894    const ushort *src = (const ushort *)srcPixels;
     895    ushort *dest = (ushort *)destPixels;
     896
     897    sstride /= sizeof(ushort);
     898    dstride /= sizeof(ushort);
     899
     900    const int pack = sizeof(quint32) / sizeof(ushort);
     901    const int unaligned =
     902        qMin(uint((long(dest) & (sizeof(quint32)-1)) / sizeof(ushort)), uint(h));
     903    const int restX = w % tileSize;
     904    const int restY = (h - unaligned) % tileSize;
     905    const int unoptimizedY = restY % pack;
     906    const int numTilesX = w / tileSize + (restX > 0);
     907    const int numTilesY = (h - unaligned) / tileSize + (restY >= pack);
     908
     909    for (int tx = 0; tx < numTilesX; ++tx) {
     910        const int startx = tx * tileSize;
     911        const int stopx = qMin(startx + tileSize, w);
     912
     913        if (unaligned) {
     914            for (int x = startx; x < stopx; ++x) {
     915                ushort *d = dest + x * dstride;
     916                for (int y = h - 1; y >= h - unaligned; --y) {
     917                    *d++ = src[y * sstride + x];
     918                }
     919            }
     920        }
     921
     922        for (int ty = 0; ty < numTilesY; ++ty) {
     923            const int starty = h - 1 - unaligned - ty * tileSize;
     924            const int stopy = qMax(starty - tileSize, unoptimizedY);
     925
     926            int x = startx;
     927            // qt_rotate90_16_neon writes to eight rows, four pixels at a time
     928            for (; x < stopx - 7; x += 8) {
     929                ushort *d = dest + x * dstride + h - 1 - starty;
     930                const ushort *s = &src[starty * sstride + x];
     931                qt_rotate90_16_neon(d + 7 * dstride, s, -sstride * 2, -dstride * 2, starty - stopy);
     932            }
     933
     934            for (; x < stopx; ++x) {
     935                quint32 *d = reinterpret_cast<quint32*>(dest + x * dstride
     936                                                        + h - 1 - starty);
     937                for (int y = starty; y > stopy; y -= pack) {
     938                    quint32 c = src[y * sstride + x];
     939                    for (int i = 1; i < pack; ++i) {
     940                        const int shift = (sizeof(int) * 8 / pack * i);
     941                        const ushort color = src[(y - i) * sstride + x];
     942                        c |= color << shift;
     943                    }
     944                    *d++ = c;
     945                }
     946            }
     947        }
     948        if (unoptimizedY) {
     949            const int starty = unoptimizedY - 1;
     950            for (int x = startx; x < stopx; ++x) {
     951                ushort *d = dest + x * dstride + h - 1 - starty;
     952                for (int y = starty; y >= 0; --y) {
     953                    *d++ = src[y * sstride + x];
     954                }
     955            }
     956        }
     957    }
     958}
     959
    257960QT_END_NAMESPACE
    258961
  • trunk/src/gui/painting/qdrawhelper_neon_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7070                                  int const_alpha);
    7171
     72void qt_blend_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
     73                                   const uchar *srcPixels, int sbpl,
     74                                   int w, int h,
     75                                   int const_alpha);
     76
     77void qt_blend_argb32_on_argb32_scanline_neon(uint *dest,
     78                                             const uint *src,
     79                                             int length,
     80                                             uint const_alpha);
     81
     82void qt_blend_rgb16_on_argb32_neon(uchar *destPixels, int dbpl,
     83                                   const uchar *srcPixels, int sbpl,
     84                                   int w, int h,
     85                                   int const_alpha);
     86
     87void qt_blend_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl,
     88                                  const uchar *srcPixels, int sbpl,
     89                                  int w, int h,
     90                                  int const_alpha);
     91
     92void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer,
     93                                  int x, int y, quint32 color,
     94                                  const uchar *bitmap,
     95                                  int mapWidth, int mapHeight, int mapStride,
     96                                  const QClipData *clip);
     97
     98void qt_scale_image_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
     99                                         const uchar *srcPixels, int sbpl,
     100                                         const QRectF &targetRect,
     101                                         const QRectF &sourceRect,
     102                                         const QRect &clip,
     103                                         int const_alpha);
     104
     105void qt_scale_image_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl,
     106                                        const uchar *srcPixels, int sbpl,
     107                                        const QRectF &targetRect,
     108                                        const QRectF &sourceRect,
     109                                        const QRect &clip,
     110                                        int const_alpha);
     111
     112void qt_transform_image_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
     113                                             const uchar *srcPixels, int sbpl,
     114                                             const QRectF &targetRect,
     115                                             const QRectF &sourceRect,
     116                                             const QRect &clip,
     117                                             const QTransform &targetRectTransform,
     118                                             int const_alpha);
     119
     120void qt_transform_image_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl,
     121                                            const uchar *srcPixels, int sbpl,
     122                                            const QRectF &targetRect,
     123                                            const QRectF &sourceRect,
     124                                            const QRect &clip,
     125                                            const QTransform &targetRectTransform,
     126                                            int const_alpha);
     127
     128void qt_memfill32_neon(quint32 *dest, quint32 value, int count);
     129void qt_memrotate90_16_neon(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl);
     130void qt_memrotate270_16_neon(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl);
     131
     132uint * QT_FASTCALL qt_destFetchRGB16_neon(uint *buffer,
     133                                          QRasterBuffer *rasterBuffer,
     134                                          int x, int y, int length);
     135
     136void QT_FASTCALL qt_destStoreRGB16_neon(QRasterBuffer *rasterBuffer,
     137                                        int x, int y, const uint *buffer, int length);
     138
     139void QT_FASTCALL comp_func_solid_SourceOver_neon(uint *destPixels, int length, uint color, uint const_alpha);
     140void QT_FASTCALL comp_func_Plus_neon(uint *dst, const uint *src, int length, uint const_alpha);
     141
    72142#endif // QT_HAVE_NEON
    73143
  • trunk/src/gui/painting/qdrawhelper_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6363#endif
    6464#include "private/qrasterdefs_p.h"
     65#include <private/qsimd_p.h>
    6566
    6667#ifdef Q_WS_QWS
    6768#include "QtGui/qscreen_qws.h"
    68 #endif
    69 
    70 // Disable MMX and SSE on Mac/PPC builds, or if the compiler
    71 // does not support -Xarch argument passing
    72 #if defined(QT_NO_MAC_XARCH) || (defined(Q_OS_DARWIN) && (defined(__ppc__) || defined(__ppc64__)))
    73 #undef QT_HAVE_SSE2
    74 #undef QT_HAVE_SSE
    75 #undef QT_HAVE_3DNOW
    76 #undef QT_HAVE_MMX
    7769#endif
    7870
     
    9385#  define Q_STATIC_INLINE_FUNCTION static inline
    9486#endif
     87
     88static const uint AMASK = 0xff000000;
     89static const uint RMASK = 0x00ff0000;
     90static const uint GMASK = 0x0000ff00;
     91static const uint BMASK = 0x000000ff;
    9592
    9693/*******************************************************************************
     
    155152                                     int const_alpha);
    156153
     154typedef void (*MemRotateFunc)(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl);
    157155
    158156struct DrawHelper {
     
    168166extern SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats];
    169167extern SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFormats];
     168extern MemRotateFunc qMemRotateFunctions[QImage::NImageFormats][3];
    170169
    171170extern DrawHelper qDrawHelper[QImage::NImageFormats];
     
    310309};
    311310
    312 
    313 Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16(uint x, uint a) {
    314     a += 1;
    315     uint t = (((x & 0x07e0)*a) >> 8) & 0x07e0;
    316     t |= (((x & 0xf81f)*(a>>2)) >> 6) & 0xf81f;
    317     return t;
    318 }
    319 
    320 Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16_32(uint x, uint a) {
    321     uint t = (((x & 0xf81f07e0) >> 5)*a) & 0xf81f07e0;
    322     t |= (((x & 0x07e0f81f)*a) >> 5) & 0x07e0f81f;
    323     return t;
     311#if defined(Q_CC_RVCT)
     312#  pragma push
     313#  pragma arm
     314#endif
     315Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) {
     316    uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
     317    t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
     318    t &= 0xff00ff;
     319
     320    x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
     321    x = (x + ((x >> 8) & 0xff00ff) + 0x800080);
     322    x &= 0xff00ff00;
     323    x |= t;
     324    return x;
     325}
     326#if defined(Q_CC_RVCT)
     327#  pragma pop
     328#endif
     329
     330#if QT_POINTER_SIZE == 8 // 64-bit versions
     331
     332Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
     333    quint64 t = (((quint64(x)) | ((quint64(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
     334    t += (((quint64(y)) | ((quint64(y)) << 24)) & 0x00ff00ff00ff00ff) * b;
     335    t >>= 8;
     336    t &= 0x00ff00ff00ff00ff;
     337    return (uint(t)) | (uint(t >> 24));
     338}
     339
     340Q_STATIC_INLINE_FUNCTION uint BYTE_MUL(uint x, uint a) {
     341    quint64 t = (((quint64(x)) | ((quint64(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
     342    t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080) >> 8;
     343    t &= 0x00ff00ff00ff00ff;
     344    return (uint(t)) | (uint(t >> 24));
     345}
     346
     347Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x) {
     348    uint a = x >> 24;
     349    quint64 t = (((quint64(x)) | ((quint64(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
     350    t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080) >> 8;
     351    t &= 0x000000ff00ff00ff;
     352    return (uint(t)) | (uint(t >> 24)) | (a << 24);
     353}
     354
     355#else // 32-bit versions
     356
     357Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
     358    uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
     359    t >>= 8;
     360    t &= 0xff00ff;
     361
     362    x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
     363    x &= 0xff00ff00;
     364    x |= t;
     365    return x;
    324366}
    325367
     
    354396    x |= t | (a << 24);
    355397    return x;
     398}
     399#endif
     400
     401
     402Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16(uint x, uint a) {
     403    a += 1;
     404    uint t = (((x & 0x07e0)*a) >> 8) & 0x07e0;
     405    t |= (((x & 0xf81f)*(a>>2)) >> 6) & 0xf81f;
     406    return t;
     407}
     408
     409Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16_32(uint x, uint a) {
     410    uint t = (((x & 0xf81f07e0) >> 5)*a) & 0xf81f07e0;
     411    t |= (((x & 0x07e0f81f)*a) >> 5) & 0x07e0f81f;
     412    return t;
    356413}
    357414
     
    16281685QT_TRIVIAL_MEMCONVERT_IMPL(qrgb666)
    16291686QT_TRIVIAL_MEMCONVERT_IMPL(quint16)
    1630 #ifdef Q_WS_QWS
    16311687QT_TRIVIAL_MEMCONVERT_IMPL(qrgb565)
    1632 #endif
    16331688QT_TRIVIAL_MEMCONVERT_IMPL(qargb8565)
    16341689QT_TRIVIAL_MEMCONVERT_IMPL(qargb8555)
     
    16501705    }
    16511706
    1652     const int align = (long(dest) & 3);
     1707    const int align = (quintptr(dest) & 3);
    16531708    switch (align) {
    16541709    case 1: *dest++ = qrgb666(*src++); --count;
     
    17271782QT_RECTCONVERT_TRIVIAL_IMPL(qargb6666)
    17281783QT_RECTCONVERT_TRIVIAL_IMPL(qrgb666)
    1729 #ifdef Q_WS_QWS
    17301784QT_RECTCONVERT_TRIVIAL_IMPL(qrgb565)
    1731 #endif
    17321785QT_RECTCONVERT_TRIVIAL_IMPL(qargb8565)
    17331786QT_RECTCONVERT_TRIVIAL_IMPL(quint16)
     
    18421895    return (b << 3) | (b >> 2);
    18431896}
    1844 
    1845 #if 1
    1846 Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
    1847     uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
    1848     t >>= 8;
    1849     t &= 0xff00ff;
    1850 
    1851     x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
    1852     x &= 0xff00ff00;
    1853     x |= t;
    1854     return x;
    1855 }
    1856 
    1857 #if defined(Q_CC_RVCT)
    1858 #  pragma push
    1859 #  pragma arm
    1860 #endif
    1861 Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) {
    1862     uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
    1863     t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
    1864     t &= 0xff00ff;
    1865 
    1866     x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
    1867     x = (x + ((x >> 8) & 0xff00ff) + 0x800080);
    1868     x &= 0xff00ff00;
    1869     x |= t;
    1870     return x;
    1871 }
    1872 #if defined(Q_CC_RVCT)
    1873 #  pragma pop
    1874 #endif
    1875 #else
    1876 // possible implementation for 64 bit
    1877 Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
    1878     ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
    1879     t += (((ulong(y)) | ((ulong(y)) << 24)) & 0x00ff00ff00ff00ff) * b;
    1880     t >>= 8;
    1881     t &= 0x00ff00ff00ff00ff;
    1882     return (uint(t)) | (uint(t >> 24));
    1883 }
    1884 
    1885 Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) {
    1886     ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
    1887     t += (((ulong(y)) | ((ulong(y)) << 24)) & 0x00ff00ff00ff00ff) * b;
    1888     t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080);
    1889     t &= 0x00ff00ff00ff00ff;
    1890     return (uint(t)) | (uint(t >> 24));
    1891 }
    1892 
    1893 Q_STATIC_INLINE_FUNCTION uint BYTE_MUL(uint x, uint a) {
    1894     ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
    1895     t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080);
    1896     t &= 0x00ff00ff00ff00ff;
    1897     return (uint(t)) | (uint(t >> 24));
    1898 }
    1899 
    1900 Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x) {
    1901     uint a = x >> 24;
    1902     ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
    1903     t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080);
    1904     t &= 0x00ff00ff00ff00ff;
    1905     return (uint(t)) | (uint(t >> 24)) | 0xff000000;
    1906 }
    1907 #endif
    19081897
    19091898const uint qt_bayer_matrix[16][16] = {
     
    19461935
    19471936
     1937#if QT_POINTER_SIZE == 8 // 64-bit versions
     1938#define AMIX(mask) (qMin(((qint64(s)&mask) + (qint64(d)&mask)), qint64(mask)))
     1939#define MIX(mask) (qMin(((qint64(s)&mask) + (qint64(d)&mask)), qint64(mask)))
     1940#else // 32 bits
     1941// The mask for alpha can overflow over 32 bits
     1942#define AMIX(mask) quint32(qMin(((qint64(s)&mask) + (qint64(d)&mask)), qint64(mask)))
     1943#define MIX(mask) (qMin(((quint32(s)&mask) + (quint32(d)&mask)), quint32(mask)))
     1944#endif
     1945
     1946inline int comp_func_Plus_one_pixel_const_alpha(uint d, const uint s, const uint const_alpha, const uint one_minus_const_alpha)
     1947{
     1948    const int result = (AMIX(AMASK) | MIX(RMASK) | MIX(GMASK) | MIX(BMASK));
     1949    return INTERPOLATE_PIXEL_255(result, const_alpha, d, one_minus_const_alpha);
     1950}
     1951
     1952inline int comp_func_Plus_one_pixel(uint d, const uint s)
     1953{
     1954    const int result = (AMIX(AMASK) | MIX(RMASK) | MIX(GMASK) | MIX(BMASK));
     1955    return result;
     1956}
     1957
     1958#undef MIX
     1959#undef AMIX
     1960
     1961// prototypes of all the composition functions
     1962void QT_FASTCALL comp_func_SourceOver(uint *dest, const uint *src, int length, uint const_alpha);
     1963void QT_FASTCALL comp_func_DestinationOver(uint *dest, const uint *src, int length, uint const_alpha);
     1964void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha);
     1965void QT_FASTCALL comp_func_Source(uint *dest, const uint *src, int length, uint const_alpha);
     1966void QT_FASTCALL comp_func_Destination(uint *, const uint *, int, uint);
     1967void QT_FASTCALL comp_func_SourceIn(uint *dest, const uint *src, int length, uint const_alpha);
     1968void QT_FASTCALL comp_func_DestinationIn(uint *dest, const uint *src, int length, uint const_alpha);
     1969void QT_FASTCALL comp_func_SourceOut(uint *dest, const uint *src, int length, uint const_alpha);
     1970void QT_FASTCALL comp_func_DestinationOut(uint *dest, const uint *src, int length, uint const_alpha);
     1971void QT_FASTCALL comp_func_SourceAtop(uint *dest, const uint *src, int length, uint const_alpha);
     1972void QT_FASTCALL comp_func_DestinationAtop(uint *dest, const uint *src, int length, uint const_alpha);
     1973void QT_FASTCALL comp_func_XOR(uint *dest, const uint *src, int length, uint const_alpha);
     1974void QT_FASTCALL comp_func_Plus(uint *dest, const uint *src, int length, uint const_alpha);
     1975void QT_FASTCALL comp_func_Multiply(uint *dest, const uint *src, int length, uint const_alpha);
     1976void QT_FASTCALL comp_func_Screen(uint *dest, const uint *src, int length, uint const_alpha);
     1977void QT_FASTCALL comp_func_Overlay(uint *dest, const uint *src, int length, uint const_alpha);
     1978void QT_FASTCALL comp_func_Darken(uint *dest, const uint *src, int length, uint const_alpha);
     1979void QT_FASTCALL comp_func_Lighten(uint *dest, const uint *src, int length, uint const_alpha);
     1980void QT_FASTCALL comp_func_ColorDodge(uint *dest, const uint *src, int length, uint const_alpha);
     1981void QT_FASTCALL comp_func_ColorBurn(uint *dest, const uint *src, int length, uint const_alpha);
     1982void QT_FASTCALL comp_func_HardLight(uint *dest, const uint *src, int length, uint const_alpha);
     1983void QT_FASTCALL comp_func_SoftLight(uint *dest, const uint *src, int length, uint const_alpha);
     1984void QT_FASTCALL comp_func_Difference(uint *dest, const uint *src, int length, uint const_alpha);
     1985void QT_FASTCALL comp_func_Exclusion(uint *dest, const uint *src, int length, uint const_alpha);
     1986void QT_FASTCALL rasterop_SourceOrDestination(uint *dest, const uint *src, int length, uint const_alpha);
     1987void QT_FASTCALL rasterop_SourceAndDestination(uint *dest, const uint *src, int length, uint const_alpha);
     1988void QT_FASTCALL rasterop_SourceXorDestination(uint *dest, const uint *src, int length, uint const_alpha);
     1989void QT_FASTCALL rasterop_NotSourceAndNotDestination(uint *dest, const uint *src, int length, uint const_alpha);
     1990void QT_FASTCALL rasterop_NotSourceOrNotDestination(uint *dest, const uint *src, int length, uint const_alpha);
     1991void QT_FASTCALL rasterop_NotSourceXorDestination(uint *dest, const uint *src, int length, uint const_alpha);
     1992void QT_FASTCALL rasterop_NotSource(uint *dest, const uint *src, int length, uint const_alpha);
     1993void QT_FASTCALL rasterop_NotSourceAndDestination(uint *dest, const uint *src, int length, uint const_alpha);
     1994void QT_FASTCALL rasterop_SourceAndNotDestination(uint *dest, const uint *src, int length, uint const_alpha);
     1995
     1996// prototypes of all the solid composition functions
     1997void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, uint const_alpha);
     1998void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint color, uint const_alpha);
     1999void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint color, uint const_alpha);
     2000void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha);
     2001void QT_FASTCALL comp_func_solid_Destination(uint *dest, int length, uint color, uint const_alpha);
     2002void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha);
     2003void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, uint color, uint const_alpha);
     2004void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha);
     2005void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, uint color, uint const_alpha);
     2006void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint color, uint const_alpha);
     2007void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, uint color, uint const_alpha);
     2008void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, uint const_alpha);
     2009void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, uint const_alpha);
     2010void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint color, uint const_alpha);
     2011void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint color, uint const_alpha);
     2012void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint color, uint const_alpha);
     2013void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint color, uint const_alpha);
     2014void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint color, uint const_alpha);
     2015void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint color, uint const_alpha);
     2016void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint color, uint const_alpha);
     2017void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint color, uint const_alpha);
     2018void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, uint const_alpha);
     2019void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint color, uint const_alpha);
     2020void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint color, uint const_alpha);
     2021void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest, int length, uint color, uint const_alpha);
     2022void QT_FASTCALL rasterop_solid_SourceAndDestination(uint *dest, int length, uint color, uint const_alpha);
     2023void QT_FASTCALL rasterop_solid_SourceXorDestination(uint *dest, int length, uint color, uint const_alpha);
     2024void QT_FASTCALL rasterop_solid_NotSourceAndNotDestination(uint *dest, int length, uint color, uint const_alpha);
     2025void QT_FASTCALL rasterop_solid_NotSourceOrNotDestination(uint *dest, int length, uint color, uint const_alpha);
     2026void QT_FASTCALL rasterop_solid_NotSourceXorDestination(uint *dest, int length, uint color, uint const_alpha);
     2027void QT_FASTCALL rasterop_solid_NotSource(uint *dest, int length, uint color, uint const_alpha);
     2028void QT_FASTCALL rasterop_solid_NotSourceAndDestination(uint *dest, int length, uint color, uint const_alpha);
     2029void QT_FASTCALL rasterop_solid_SourceAndNotDestination(uint *dest, int length, uint color, uint const_alpha);
     2030
    19482031QT_END_NAMESPACE
    19492032
  • trunk/src/gui/painting/qdrawhelper_sse.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7878    comp_func_Clear<QSSEIntrinsics>,
    7979    comp_func_Source<QSSEIntrinsics>,
    80     0,
     80    comp_func_Destination,
    8181    comp_func_SourceIn<QSSEIntrinsics>,
    8282    comp_func_DestinationIn<QSSEIntrinsics>,
     
    8585    comp_func_SourceAtop<QSSEIntrinsics>,
    8686    comp_func_DestinationAtop<QSSEIntrinsics>,
    87     comp_func_XOR<QSSEIntrinsics>
     87    comp_func_XOR<QSSEIntrinsics>,
     88    comp_func_Plus,
     89    comp_func_Multiply,
     90    comp_func_Screen,
     91    comp_func_Overlay,
     92    comp_func_Darken,
     93    comp_func_Lighten,
     94    comp_func_ColorDodge,
     95    comp_func_ColorBurn,
     96    comp_func_HardLight,
     97    comp_func_SoftLight,
     98    comp_func_Difference,
     99    comp_func_Exclusion,
     100    rasterop_SourceOrDestination,
     101    rasterop_SourceAndDestination,
     102    rasterop_SourceXorDestination,
     103    rasterop_NotSourceAndNotDestination,
     104    rasterop_NotSourceOrNotDestination,
     105    rasterop_NotSourceXorDestination,
     106    rasterop_NotSource,
     107    rasterop_NotSourceAndDestination,
     108    rasterop_SourceAndNotDestination
    88109};
    89110
  • trunk/src/gui/painting/qdrawhelper_sse2.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4444#ifdef QT_HAVE_SSE2
    4545
     46#include <private/qdrawingprimitive_sse2_p.h>
    4647#include <private/qpaintengine_raster_p.h>
    4748
    48 #ifdef QT_LINUXBASE
    49 // this is an evil hack - the posix_memalign declaration in LSB
    50 // is wrong - see http://bugs.linuxbase.org/show_bug.cgi?id=2431
    51 #  define posix_memalign _lsb_hack_posix_memalign
    52 #  include <emmintrin.h>
    53 #  undef posix_memalign
    54 #else
    55 #  include <emmintrin.h>
    56 #endif
    57 
    5849QT_BEGIN_NAMESPACE
    59 
    60 /*
    61  * Multiply the components of pixelVector by alphaChannel
    62  * Each 32bits components of alphaChannel must be in the form 0x00AA00AA
    63  * colorMask must have 0x00ff00ff on each 32 bits component
    64  * half must have the value 128 (0x80) for each 32 bits compnent
    65  */
    66 #define BYTE_MUL_SSE2(result, pixelVector, alphaChannel, colorMask, half) \
    67 { \
    68     /* 1. separate the colors in 2 vectors so each color is on 16 bits \
    69        (in order to be multiplied by the alpha \
    70        each 32 bit of dstVectorAG are in the form 0x00AA00GG \
    71        each 32 bit of dstVectorRB are in the form 0x00RR00BB */\
    72     __m128i pixelVectorAG = _mm_srli_epi16(pixelVector, 8); \
    73     __m128i pixelVectorRB = _mm_and_si128(pixelVector, colorMask); \
    74  \
    75     /* 2. multiply the vectors by the alpha channel */\
    76     pixelVectorAG = _mm_mullo_epi16(pixelVectorAG, alphaChannel); \
    77     pixelVectorRB = _mm_mullo_epi16(pixelVectorRB, alphaChannel); \
    78  \
    79     /* 3. devide by 255, that's the tricky part. \
    80        we do it like for BYTE_MUL(), with bit shift: X/255 ~= (X + X/256 + rounding)/256 */ \
    81     /** so first (X + X/256 + rounding) */\
    82     pixelVectorRB = _mm_add_epi16(pixelVectorRB, _mm_srli_epi16(pixelVectorRB, 8)); \
    83     pixelVectorRB = _mm_add_epi16(pixelVectorRB, half); \
    84     pixelVectorAG = _mm_add_epi16(pixelVectorAG, _mm_srli_epi16(pixelVectorAG, 8)); \
    85     pixelVectorAG = _mm_add_epi16(pixelVectorAG, half); \
    86  \
    87     /** second devide by 256 */\
    88     pixelVectorRB = _mm_srli_epi16(pixelVectorRB, 8); \
    89     /** for AG, we could >> 8 to divide followed by << 8 to put the \
    90         bytes in the correct position. By masking instead, we execute \
    91         only one instruction */\
    92     pixelVectorAG = _mm_andnot_si128(colorMask, pixelVectorAG); \
    93  \
    94     /* 4. combine the 2 pairs of colors */ \
    95     result = _mm_or_si128(pixelVectorAG, pixelVectorRB); \
    96 }
    97 
    98 /*
    99  * Each 32bits components of alphaChannel must be in the form 0x00AA00AA
    100  * oneMinusAlphaChannel must be 255 - alpha for each 32 bits component
    101  * colorMask must have 0x00ff00ff on each 32 bits component
    102  * half must have the value 128 (0x80) for each 32 bits compnent
    103  */
    104 #define INTERPOLATE_PIXEL_255_SSE2(result, srcVector, dstVector, alphaChannel, oneMinusAlphaChannel, colorMask, half) { \
    105     /* interpolate AG */\
    106     __m128i srcVectorAG = _mm_srli_epi16(srcVector, 8); \
    107     __m128i dstVectorAG = _mm_srli_epi16(dstVector, 8); \
    108     __m128i srcVectorAGalpha = _mm_mullo_epi16(srcVectorAG, alphaChannel); \
    109     __m128i dstVectorAGoneMinusAlphalpha = _mm_mullo_epi16(dstVectorAG, oneMinusAlphaChannel); \
    110     __m128i finalAG = _mm_add_epi16(srcVectorAGalpha, dstVectorAGoneMinusAlphalpha); \
    111     finalAG = _mm_add_epi16(finalAG, _mm_srli_epi16(finalAG, 8)); \
    112     finalAG = _mm_add_epi16(finalAG, half); \
    113     finalAG = _mm_andnot_si128(colorMask, finalAG); \
    114  \
    115     /* interpolate RB */\
    116     __m128i srcVectorRB = _mm_and_si128(srcVector, colorMask); \
    117     __m128i dstVectorRB = _mm_and_si128(dstVector, colorMask); \
    118     __m128i srcVectorRBalpha = _mm_mullo_epi16(srcVectorRB, alphaChannel); \
    119     __m128i dstVectorRBoneMinusAlphalpha = _mm_mullo_epi16(dstVectorRB, oneMinusAlphaChannel); \
    120     __m128i finalRB = _mm_add_epi16(srcVectorRBalpha, dstVectorRBoneMinusAlphalpha); \
    121     finalRB = _mm_add_epi16(finalRB, _mm_srli_epi16(finalRB, 8)); \
    122     finalRB = _mm_add_epi16(finalRB, half); \
    123     finalRB = _mm_srli_epi16(finalRB, 8); \
    124  \
    125     /* combine */\
    126     result = _mm_or_si128(finalAG, finalRB); \
    127 }
    12850
    12951void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl,
     
    13355{
    13456    const quint32 *src = (const quint32 *) srcPixels;
    135     quint32 *dst = (uint *) destPixels;
     57    quint32 *dst = (quint32 *) destPixels;
    13658    if (const_alpha == 256) {
    13759        const __m128i alphaMask = _mm_set1_epi32(0xff000000);
     
    14163        const __m128i colorMask = _mm_set1_epi32(0x00ff00ff);
    14264        for (int y = 0; y < h; ++y) {
    143             int x = 0;
    144             for (; x < w-3; x += 4) {
    145                 const __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]);
    146                 const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask);
    147                 if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) {
    148                     // all opaque
    149                     _mm_storeu_si128((__m128i *)&dst[x], srcVector);
    150                 } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) != 0xffff) {
    151                     // not fully transparent
    152                     // result = s + d * (1-alpha)
    153 
    154                     // extract the alpha channel on 2 x 16 bits
    155                     // so we have room for the multiplication
    156                     // each 32 bits will be in the form 0x00AA00AA
    157                     // with A being the 1 - alpha
    158                     __m128i alphaChannel = _mm_srli_epi32(srcVector, 24);
    159                     alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16));
    160                     alphaChannel = _mm_sub_epi16(one, alphaChannel);
    161 
    162                     const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]);
    163                     __m128i destMultipliedByOneMinusAlpha;
    164                     BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half);
    165 
    166                     // result = s + d * (1-alpha)
    167                     const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha);
    168                     _mm_storeu_si128((__m128i *)&dst[x], result);
    169                 }
    170             }
    171             for (; x<w; ++x) {
    172                 uint s = src[x];
    173                 if (s >= 0xff000000)
    174                     dst[x] = s;
    175                 else if (s != 0)
    176                     dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s));
    177             }
     65            BLEND_SOURCE_OVER_ARGB32_SSE2(dst, src, w, nullVector, half, one, colorMask, alphaMask);
    17866            dst = (quint32 *)(((uchar *) dst) + dbpl);
    17967            src = (const quint32 *)(((const uchar *) src) + sbpl);
     
    19078        const __m128i constAlphaVector = _mm_set1_epi16(const_alpha);
    19179        for (int y = 0; y < h; ++y) {
    192             int x = 0;
    193             for (; x < w-3; x += 4) {
    194                 __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]);
    195                 if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVector, nullVector)) != 0xffff) {
    196                     BYTE_MUL_SSE2(srcVector, srcVector, constAlphaVector, colorMask, half);
    197 
    198                     __m128i alphaChannel = _mm_srli_epi32(srcVector, 24);
    199                     alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16));
    200                     alphaChannel = _mm_sub_epi16(one, alphaChannel);
    201 
    202                     const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]);
    203                     __m128i destMultipliedByOneMinusAlpha;
    204                     BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half);
    205 
    206                     const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha);
    207                     _mm_storeu_si128((__m128i *)&dst[x], result);
    208                 }
    209             }
    210             for (; x<w; ++x) {
    211                 quint32 s = src[x];
    212                 if (s != 0) {
    213                     s = BYTE_MUL(s, const_alpha);
    214                     dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s));
    215                 }
    216             }
     80            BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_SSE2(dst, src, w, nullVector, half, one, colorMask, constAlphaVector)
    21781            dst = (quint32 *)(((uchar *) dst) + dbpl);
    21882            src = (const quint32 *)(((const uchar *) src) + sbpl);
     
    23397{
    23498    const quint32 *src = (const quint32 *) srcPixels;
    235     quint32 *dst = (uint *) destPixels;
     99    quint32 *dst = (quint32 *) destPixels;
    236100    if (const_alpha != 256) {
    237101        if (const_alpha != 0) {
     
    246110            for (int y = 0; y < h; ++y) {
    247111                int x = 0;
     112
     113                // First, align dest to 16 bytes:
     114                ALIGNMENT_PROLOGUE_16BYTES(dst, x, w) {
     115                    quint32 s = src[x];
     116                    s = BYTE_MUL(s, const_alpha);
     117                    dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], one_minus_const_alpha);
     118                }
     119
    248120                for (; x < w-3; x += 4) {
    249121                    __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]);
    250122                    if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVector, nullVector)) != 0xffff) {
    251                         const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]);
     123                        const __m128i dstVector = _mm_load_si128((__m128i *)&dst[x]);
    252124                        __m128i result;
    253125                        INTERPOLATE_PIXEL_255_SSE2(result, srcVector, dstVector, constAlphaVector, oneMinusConstAlpha, colorMask, half);
    254                         _mm_storeu_si128((__m128i *)&dst[x], result);
     126                        _mm_store_si128((__m128i *)&dst[x], result);
    255127                    }
    256128                }
     
    269141}
    270142
     143void QT_FASTCALL comp_func_SourceOver_sse2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha)
     144{
     145    Q_ASSERT(const_alpha < 256);
     146
     147    const quint32 *src = (const quint32 *) srcPixels;
     148    quint32 *dst = (quint32 *) destPixels;
     149
     150    const __m128i nullVector = _mm_set1_epi32(0);
     151    const __m128i half = _mm_set1_epi16(0x80);
     152    const __m128i one = _mm_set1_epi16(0xff);
     153    const __m128i colorMask = _mm_set1_epi32(0x00ff00ff);
     154    if (const_alpha == 255) {
     155        const __m128i alphaMask = _mm_set1_epi32(0xff000000);
     156        BLEND_SOURCE_OVER_ARGB32_SSE2(dst, src, length, nullVector, half, one, colorMask, alphaMask);
     157    } else {
     158        const __m128i constAlphaVector = _mm_set1_epi16(const_alpha);
     159        BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_SSE2(dst, src, length, nullVector, half, one, colorMask, constAlphaVector);
     160    }
     161}
     162
     163void QT_FASTCALL comp_func_Plus_sse2(uint *dst, const uint *src, int length, uint const_alpha)
     164{
     165    int x = 0;
     166
     167    if (const_alpha == 255) {
     168        // 1) Prologue: align destination on 16 bytes
     169        ALIGNMENT_PROLOGUE_16BYTES(dst, x, length)
     170            dst[x] = comp_func_Plus_one_pixel(dst[x], src[x]);
     171
     172        // 2) composition with SSE2
     173        for (; x < length - 3; x += 4) {
     174            const __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]);
     175            const __m128i dstVector = _mm_load_si128((__m128i *)&dst[x]);
     176
     177            const __m128i result = _mm_adds_epu8(srcVector, dstVector);
     178            _mm_store_si128((__m128i *)&dst[x], result);
     179        }
     180
     181        // 3) Epilogue:
     182        for (; x < length; ++x)
     183            dst[x] = comp_func_Plus_one_pixel(dst[x], src[x]);
     184    } else {
     185        const int one_minus_const_alpha = 255 - const_alpha;
     186        const __m128i constAlphaVector = _mm_set1_epi16(const_alpha);
     187        const __m128i oneMinusConstAlpha =  _mm_set1_epi16(one_minus_const_alpha);
     188
     189        // 1) Prologue: align destination on 16 bytes
     190        ALIGNMENT_PROLOGUE_16BYTES(dst, x, length)
     191            dst[x] = comp_func_Plus_one_pixel_const_alpha(dst[x], src[x], const_alpha, one_minus_const_alpha);
     192
     193        const __m128i half = _mm_set1_epi16(0x80);
     194        const __m128i colorMask = _mm_set1_epi32(0x00ff00ff);
     195        // 2) composition with SSE2
     196        for (; x < length - 3; x += 4) {
     197            const __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]);
     198            const __m128i dstVector = _mm_load_si128((__m128i *)&dst[x]);
     199
     200            __m128i result = _mm_adds_epu8(srcVector, dstVector);
     201            INTERPOLATE_PIXEL_255_SSE2(result, result, dstVector, constAlphaVector, oneMinusConstAlpha, colorMask, half)
     202            _mm_store_si128((__m128i *)&dst[x], result);
     203        }
     204
     205        // 3) Epilogue:
     206        for (; x < length; ++x)
     207            dst[x] = comp_func_Plus_one_pixel_const_alpha(dst[x], src[x], const_alpha, one_minus_const_alpha);
     208    }
     209}
     210
     211void QT_FASTCALL comp_func_Source_sse2(uint *dst, const uint *src, int length, uint const_alpha)
     212{
     213    if (const_alpha == 255) {
     214        ::memcpy(dst, src, length * sizeof(uint));
     215    } else {
     216        const int ialpha = 255 - const_alpha;
     217
     218        int x = 0;
     219
     220        // 1) prologue, align on 16 bytes
     221        ALIGNMENT_PROLOGUE_16BYTES(dst, x, length)
     222            dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], ialpha);
     223
     224        // 2) interpolate pixels with SSE2
     225        const __m128i half = _mm_set1_epi16(0x80);
     226        const __m128i colorMask = _mm_set1_epi32(0x00ff00ff);
     227        const __m128i constAlphaVector = _mm_set1_epi16(const_alpha);
     228        const __m128i oneMinusConstAlpha =  _mm_set1_epi16(ialpha);
     229        for (; x < length - 3; x += 4) {
     230            const __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]);
     231            __m128i dstVector = _mm_load_si128((__m128i *)&dst[x]);
     232            INTERPOLATE_PIXEL_255_SSE2(dstVector, srcVector, dstVector, constAlphaVector, oneMinusConstAlpha, colorMask, half)
     233            _mm_store_si128((__m128i *)&dst[x], dstVector);
     234        }
     235
     236        // 3) Epilogue
     237        for (; x < length; ++x)
     238            dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], ialpha);
     239    }
     240}
     241
    271242void qt_memfill32_sse2(quint32 *dest, quint32 value, int count)
    272243{
     
    296267    int n = (count128 + 3) / 4;
    297268    switch (count128 & 0x3) {
    298     case 0: do { _mm_store_si128(dst128++, value128);
    299     case 3:      _mm_store_si128(dst128++, value128);
    300     case 2:      _mm_store_si128(dst128++, value128);
    301     case 1:      _mm_store_si128(dst128++, value128);
     269    case 0: do { _mm_stream_si128(dst128++, value128);
     270    case 3:      _mm_stream_si128(dst128++, value128);
     271    case 2:      _mm_stream_si128(dst128++, value128);
     272    case 1:      _mm_stream_si128(dst128++, value128);
    302273    } while (--n > 0);
    303274    }
     
    312283    }
    313284}
     285
     286void QT_FASTCALL comp_func_solid_SourceOver_sse2(uint *destPixels, int length, uint color, uint const_alpha)
     287{
     288    if ((const_alpha & qAlpha(color)) == 255) {
     289        qt_memfill32_sse2(destPixels, color, length);
     290    } else {
     291        if (const_alpha != 255)
     292            color = BYTE_MUL(color, const_alpha);
     293
     294        const quint32 minusAlphaOfColor = qAlpha(~color);
     295        int x = 0;
     296
     297        quint32 *dst = (quint32 *) destPixels;
     298        const __m128i colorVector = _mm_set1_epi32(color);
     299        const __m128i colorMask = _mm_set1_epi32(0x00ff00ff);
     300        const __m128i half = _mm_set1_epi16(0x80);
     301        const __m128i minusAlphaOfColorVector = _mm_set1_epi16(minusAlphaOfColor);
     302
     303        ALIGNMENT_PROLOGUE_16BYTES(dst, x, length)
     304            destPixels[x] = color + BYTE_MUL(destPixels[x], minusAlphaOfColor);
     305
     306        for (; x < length-3; x += 4) {
     307            __m128i dstVector = _mm_load_si128((__m128i *)&dst[x]);
     308            BYTE_MUL_SSE2(dstVector, dstVector, minusAlphaOfColorVector, colorMask, half);
     309            dstVector = _mm_add_epi8(colorVector, dstVector);
     310            _mm_store_si128((__m128i *)&dst[x], dstVector);
     311        }
     312        for (;x < length; ++x)
     313            destPixels[x] = color + BYTE_MUL(destPixels[x], minusAlphaOfColor);
     314    }
     315}
     316
     317CompositionFunctionSolid qt_functionForModeSolid_onlySSE2[numCompositionFunctions] = {
     318    comp_func_solid_SourceOver_sse2,
     319    comp_func_solid_DestinationOver,
     320    comp_func_solid_Clear,
     321    comp_func_solid_Source,
     322    comp_func_solid_Destination,
     323    comp_func_solid_SourceIn,
     324    comp_func_solid_DestinationIn,
     325    comp_func_solid_SourceOut,
     326    comp_func_solid_DestinationOut,
     327    comp_func_solid_SourceAtop,
     328    comp_func_solid_DestinationAtop,
     329    comp_func_solid_XOR,
     330    comp_func_solid_Plus,
     331    comp_func_solid_Multiply,
     332    comp_func_solid_Screen,
     333    comp_func_solid_Overlay,
     334    comp_func_solid_Darken,
     335    comp_func_solid_Lighten,
     336    comp_func_solid_ColorDodge,
     337    comp_func_solid_ColorBurn,
     338    comp_func_solid_HardLight,
     339    comp_func_solid_SoftLight,
     340    comp_func_solid_Difference,
     341    comp_func_solid_Exclusion,
     342    rasterop_solid_SourceOrDestination,
     343    rasterop_solid_SourceAndDestination,
     344    rasterop_solid_SourceXorDestination,
     345    rasterop_solid_NotSourceAndNotDestination,
     346    rasterop_solid_NotSourceOrNotDestination,
     347    rasterop_solid_NotSourceXorDestination,
     348    rasterop_solid_NotSource,
     349    rasterop_solid_NotSourceAndDestination,
     350    rasterop_solid_SourceAndNotDestination
     351};
     352
     353CompositionFunction qt_functionForMode_onlySSE2[numCompositionFunctions] = {
     354    comp_func_SourceOver_sse2,
     355    comp_func_DestinationOver,
     356    comp_func_Clear,
     357    comp_func_Source_sse2,
     358    comp_func_Destination,
     359    comp_func_SourceIn,
     360    comp_func_DestinationIn,
     361    comp_func_SourceOut,
     362    comp_func_DestinationOut,
     363    comp_func_SourceAtop,
     364    comp_func_DestinationAtop,
     365    comp_func_XOR,
     366    comp_func_Plus_sse2,
     367    comp_func_Multiply,
     368    comp_func_Screen,
     369    comp_func_Overlay,
     370    comp_func_Darken,
     371    comp_func_Lighten,
     372    comp_func_ColorDodge,
     373    comp_func_ColorBurn,
     374    comp_func_HardLight,
     375    comp_func_SoftLight,
     376    comp_func_Difference,
     377    comp_func_Exclusion,
     378    rasterop_SourceOrDestination,
     379    rasterop_SourceAndDestination,
     380    rasterop_SourceXorDestination,
     381    rasterop_NotSourceAndNotDestination,
     382    rasterop_NotSourceOrNotDestination,
     383    rasterop_NotSourceXorDestination,
     384    rasterop_NotSource,
     385    rasterop_NotSourceAndDestination,
     386    rasterop_SourceAndNotDestination
     387};
    314388
    315389void qt_memfill16_sse2(quint16 *dest, quint16 value, int count)
  • trunk/src/gui/painting/qdrawhelper_sse3dnow.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8686    comp_func_Clear<QSSE3DNOWIntrinsics>,
    8787    comp_func_Source<QSSE3DNOWIntrinsics>,
    88     0,
     88    comp_func_Destination,
    8989    comp_func_SourceIn<QSSE3DNOWIntrinsics>,
    9090    comp_func_DestinationIn<QSSE3DNOWIntrinsics>,
     
    9393    comp_func_SourceAtop<QSSE3DNOWIntrinsics>,
    9494    comp_func_DestinationAtop<QSSE3DNOWIntrinsics>,
    95     comp_func_XOR<QSSE3DNOWIntrinsics>
     95    comp_func_XOR<QSSE3DNOWIntrinsics>,
     96    comp_func_Plus,
     97    comp_func_Multiply,
     98    comp_func_Screen,
     99    comp_func_Overlay,
     100    comp_func_Darken,
     101    comp_func_Lighten,
     102    comp_func_ColorDodge,
     103    comp_func_ColorBurn,
     104    comp_func_HardLight,
     105    comp_func_SoftLight,
     106    comp_func_Difference,
     107    comp_func_Exclusion,
     108    rasterop_SourceOrDestination,
     109    rasterop_SourceAndDestination,
     110    rasterop_SourceXorDestination,
     111    rasterop_NotSourceAndNotDestination,
     112    rasterop_NotSourceOrNotDestination,
     113    rasterop_NotSourceXorDestination,
     114    rasterop_NotSource,
     115    rasterop_NotSourceAndDestination,
     116    rasterop_SourceAndNotDestination
    96117};
    97118
  • trunk/src/gui/painting/qdrawhelper_sse_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qdrawhelper_x86_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    123123                                 int w, int h,
    124124                                 int const_alpha);
     125
     126extern CompositionFunction qt_functionForMode_onlySSE2[];
     127extern CompositionFunctionSolid qt_functionForModeSolid_onlySSE2[];
    125128#endif // QT_HAVE_SSE2
    126129
  • trunk/src/gui/painting/qdrawutil.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4949#include <qvarlengtharray.h>
    5050#include <qmath.h>
     51#include <private/qstylehelper_p.h>
    5152
    5253QT_BEGIN_NAMESPACE
     
    10191020#ifndef QT_NO_IMAGE_HEURISTIC_MASK
    10201021            } else {                                // color pixmap, no mask
    1021                 QString k = QString::fromLatin1("$qt-drawitem-%1").arg(pm.cacheKey());
     1022                QString k = QLatin1Literal("$qt-drawitem")
     1023                              % HexString<qint64>(pm.cacheKey());
     1024
    10221025                if (!QPixmapCache::find(k, pm)) {
    10231026                    pm = pm.createHeuristicMask();
     
    10821085*/
    10831086
    1084 typedef QVarLengthArray<QDrawPixmaps::Data, 16> QDrawPixmapsDataArray;
     1087typedef QVarLengthArray<QPainter::PixmapFragment, 16> QPixmapFragmentsArray;
    10851088
    10861089/*!
     
    11031106                       const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints)
    11041107{
    1105     QDrawPixmaps::Data d;
     1108    QPainter::PixmapFragment d;
    11061109    d.opacity = 1.0;
    11071110    d.rotation = 0.0;
    11081111
    1109     QDrawPixmapsDataArray opaqueData;
    1110     QDrawPixmapsDataArray translucentData;
     1112    QPixmapFragmentsArray opaqueData;
     1113    QPixmapFragmentsArray translucentData;
    11111114
    11121115    // source center
     
    11381141    yTarget.resize(rows + 1);
    11391142
     1143    bool oldAA = painter->testRenderHint(QPainter::Antialiasing);
     1144    if (painter->paintEngine()->type() != QPaintEngine::OpenGL
     1145        && painter->paintEngine()->type() != QPaintEngine::OpenGL2
     1146        && oldAA && painter->combinedTransform().type() != QTransform::TxNone) {
     1147        painter->setRenderHint(QPainter::Antialiasing, false);
     1148    }
     1149
    11401150    xTarget[0] = targetRect.left();
    11411151    xTarget[1] = targetCenterLeft;
     
    11831193    // corners
    11841194    if (targetMargins.top() > 0 && targetMargins.left() > 0 && sourceMargins.top() > 0 && sourceMargins.left() > 0) { // top left
    1185         d.point.setX(0.5 * (xTarget[1] + xTarget[0]));
    1186         d.point.setY(0.5 * (yTarget[1] + yTarget[0]));
    1187         d.source = QRectF(sourceRect.left(), sourceRect.top(), sourceMargins.left(), sourceMargins.top());
    1188         d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.source.width();
    1189         d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.source.height();
     1195        d.x = (0.5 * (xTarget[1] + xTarget[0]));
     1196        d.y = (0.5 * (yTarget[1] + yTarget[0]));
     1197        d.sourceLeft = sourceRect.left();
     1198        d.sourceTop = sourceRect.top();
     1199        d.width = sourceMargins.left();
     1200        d.height = sourceMargins.top();
     1201        d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width;
     1202        d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height;
    11901203        if (hints & QDrawBorderPixmap::OpaqueTopLeft)
    11911204            opaqueData.append(d);
     
    11941207    }
    11951208    if (targetMargins.top() > 0 && targetMargins.right() > 0 && sourceMargins.top() > 0 && sourceMargins.right() > 0) { // top right
    1196         d.point.setX(0.5 * (xTarget[columns] + xTarget[columns - 1]));
    1197         d.point.setY(0.5 * (yTarget[1] + yTarget[0]));
    1198         d.source = QRectF(sourceCenterRight, sourceRect.top(), sourceMargins.right(), sourceMargins.top());
    1199         d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.source.width();
    1200         d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.source.height();
     1209        d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1]));
     1210        d.y = (0.5 * (yTarget[1] + yTarget[0]));
     1211        d.sourceLeft = sourceCenterRight;
     1212        d.sourceTop = sourceRect.top();
     1213        d.width = sourceMargins.right();
     1214        d.height = sourceMargins.top();
     1215        d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width;
     1216        d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height;
    12011217        if (hints & QDrawBorderPixmap::OpaqueTopRight)
    12021218            opaqueData.append(d);
     
    12051221    }
    12061222    if (targetMargins.bottom() > 0 && targetMargins.left() > 0 && sourceMargins.bottom() > 0 && sourceMargins.left() > 0) { // bottom left
    1207         d.point.setX(0.5 * (xTarget[1] + xTarget[0]));
    1208         d.point.setY(0.5 * (yTarget[rows] + yTarget[rows - 1]));
    1209         d.source = QRectF(sourceRect.left(), sourceCenterBottom, sourceMargins.left(), sourceMargins.bottom());
    1210         d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.source.width();
    1211         d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.source.height();
     1223        d.x = (0.5 * (xTarget[1] + xTarget[0]));
     1224        d.y =(0.5 * (yTarget[rows] + yTarget[rows - 1]));
     1225        d.sourceLeft = sourceRect.left();
     1226        d.sourceTop = sourceCenterBottom;
     1227        d.width = sourceMargins.left();
     1228        d.height = sourceMargins.bottom();
     1229        d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width;
     1230        d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height;
    12121231        if (hints & QDrawBorderPixmap::OpaqueBottomLeft)
    12131232            opaqueData.append(d);
     
    12161235    }
    12171236    if (targetMargins.bottom() > 0 && targetMargins.right() > 0 && sourceMargins.bottom() > 0 && sourceMargins.right() > 0) { // bottom right
    1218         d.point.setX(0.5 * (xTarget[columns] + xTarget[columns - 1]));
    1219         d.point.setY(0.5 * (yTarget[rows] + yTarget[rows - 1]));
    1220         d.source = QRectF(sourceCenterRight, sourceCenterBottom, sourceMargins.right(), sourceMargins.bottom());
    1221         d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.source.width();
    1222         d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.source.height();
     1237        d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1]));
     1238        d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1]));
     1239        d.sourceLeft = sourceCenterRight;
     1240        d.sourceTop = sourceCenterBottom;
     1241        d.width = sourceMargins.right();
     1242        d.height = sourceMargins.bottom();
     1243        d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width;
     1244        d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height;
    12231245        if (hints & QDrawBorderPixmap::OpaqueBottomRight)
    12241246            opaqueData.append(d);
     
    12301252    if (targetCenterWidth > 0 && sourceCenterWidth > 0) {
    12311253        if (targetMargins.top() > 0 && sourceMargins.top() > 0) { // top
    1232             QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueTop ? opaqueData : translucentData;
    1233             d.source = QRectF(sourceCenterLeft, sourceRect.top(), sourceCenterWidth, sourceMargins.top());
    1234             d.point.setY(0.5 * (yTarget[1] + yTarget[0]));
    1235             d.scaleX = dx / d.source.width();
    1236             d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.source.height();
     1254            QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueTop ? opaqueData : translucentData;
     1255            d.sourceLeft = sourceCenterLeft;
     1256            d.sourceTop = sourceRect.top();
     1257            d.width = sourceCenterWidth;
     1258            d.height = sourceMargins.top();
     1259            d.y = (0.5 * (yTarget[1] + yTarget[0]));
     1260            d.scaleX = dx / d.width;
     1261            d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height;
    12371262            for (int i = 1; i < columns - 1; ++i) {
    1238                 d.point.setX(0.5 * (xTarget[i + 1] + xTarget[i]));
     1263                d.x = (0.5 * (xTarget[i + 1] + xTarget[i]));
    12391264                data.append(d);
    12401265            }
    12411266            if (rules.horizontal == Qt::RepeatTile)
    1242                 data[data.size() - 1].source.setWidth((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
     1267                data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
    12431268        }
    12441269        if (targetMargins.bottom() > 0 && sourceMargins.bottom() > 0) { // bottom
    1245             QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueBottom ? opaqueData : translucentData;
    1246             d.source = QRectF(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom());;
    1247             d.point.setY(0.5 * (yTarget[rows] + yTarget[rows - 1]));
    1248             d.scaleX = dx / d.source.width();
    1249             d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.source.height();
     1270            QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueBottom ? opaqueData : translucentData;
     1271            d.sourceLeft = sourceCenterLeft;
     1272            d.sourceTop = sourceCenterBottom;
     1273            d.width = sourceCenterWidth;
     1274            d.height = sourceMargins.bottom();
     1275            d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1]));
     1276            d.scaleX = dx / d.width;
     1277            d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height;
    12501278            for (int i = 1; i < columns - 1; ++i) {
    1251                 d.point.setX(0.5 * (xTarget[i + 1] + xTarget[i]));
     1279                d.x = (0.5 * (xTarget[i + 1] + xTarget[i]));
    12521280                data.append(d);
    12531281            }
    12541282            if (rules.horizontal == Qt::RepeatTile)
    1255                 data[data.size() - 1].source.setWidth((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
     1283                data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
    12561284        }
    12571285    }
     
    12601288    if (targetCenterHeight > 0 && sourceCenterHeight > 0) {
    12611289        if (targetMargins.left() > 0 && sourceMargins.left() > 0) { // left
    1262             QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueLeft ? opaqueData : translucentData;
    1263             d.source = QRectF(sourceRect.left(), sourceCenterTop, sourceMargins.left(), sourceCenterHeight);
    1264             d.point.setX(0.5 * (xTarget[1] + xTarget[0]));
    1265             d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.source.width();
    1266             d.scaleY = dy / d.source.height();
     1290            QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueLeft ? opaqueData : translucentData;
     1291            d.sourceLeft = sourceRect.left();
     1292            d.sourceTop = sourceCenterTop;
     1293            d.width = sourceMargins.left();
     1294            d.height = sourceCenterHeight;
     1295            d.x = (0.5 * (xTarget[1] + xTarget[0]));
     1296            d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width;
     1297            d.scaleY = dy / d.height;
    12671298            for (int i = 1; i < rows - 1; ++i) {
    1268                 d.point.setY(0.5 * (yTarget[i + 1] + yTarget[i]));
     1299                d.y = (0.5 * (yTarget[i + 1] + yTarget[i]));
    12691300                data.append(d);
    12701301            }
    12711302            if (rules.vertical == Qt::RepeatTile)
    1272                 data[data.size() - 1].source.setHeight((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
     1303                data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
    12731304        }
    12741305        if (targetMargins.right() > 0 && sourceMargins.right() > 0) { // right
    1275             QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueRight ? opaqueData : translucentData;
    1276             d.source = QRectF(sourceCenterRight, sourceCenterTop, sourceMargins.right(), sourceCenterHeight);
    1277             d.point.setX(0.5 * (xTarget[columns] + xTarget[columns - 1]));
    1278             d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.source.width();
    1279             d.scaleY = dy / d.source.height();
     1306            QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueRight ? opaqueData : translucentData;
     1307            d.sourceLeft = sourceCenterRight;
     1308            d.sourceTop = sourceCenterTop;
     1309            d.width = sourceMargins.right();
     1310            d.height = sourceCenterHeight;
     1311            d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1]));
     1312            d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width;
     1313            d.scaleY = dy / d.height;
    12801314            for (int i = 1; i < rows - 1; ++i) {
    1281                 d.point.setY(0.5 * (yTarget[i + 1] + yTarget[i]));
     1315                d.y = (0.5 * (yTarget[i + 1] + yTarget[i]));
    12821316                data.append(d);
    12831317            }
    12841318            if (rules.vertical == Qt::RepeatTile)
    1285                 data[data.size() - 1].source.setHeight((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
     1319                data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
    12861320        }
    12871321    }
     
    12891323    // center
    12901324    if (targetCenterWidth > 0 && targetCenterHeight > 0 && sourceCenterWidth > 0 && sourceCenterHeight > 0) {
    1291         QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueCenter ? opaqueData : translucentData;
    1292         d.source = QRectF(sourceCenterLeft, sourceCenterTop, sourceCenterWidth, sourceCenterHeight);
    1293         d.scaleX = dx / d.source.width();
    1294         d.scaleY = dy / d.source.height();
     1325        QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueCenter ? opaqueData : translucentData;
     1326        d.sourceLeft = sourceCenterLeft;
     1327        d.sourceTop = sourceCenterTop;
     1328        d.width = sourceCenterWidth;
     1329        d.height = sourceCenterHeight;
     1330        d.scaleX = dx / d.width;
     1331        d.scaleY = dy / d.height;
    12951332
    12961333        qreal repeatWidth = (xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX;
     
    12981335
    12991336        for (int j = 1; j < rows - 1; ++j) {
    1300             d.point.setY(0.5 * (yTarget[j + 1] + yTarget[j]));
     1337            d.y = (0.5 * (yTarget[j + 1] + yTarget[j]));
    13011338            for (int i = 1; i < columns - 1; ++i) {
    1302                 d.point.setX(0.5 * (xTarget[i + 1] + xTarget[i]));
     1339                d.x = (0.5 * (xTarget[i + 1] + xTarget[i]));
    13031340                data.append(d);
    13041341            }
    13051342            if (rules.horizontal == Qt::RepeatTile)
    1306                 data[data.size() - 1].source.setWidth(repeatWidth);
     1343                data[data.size() - 1].width = repeatWidth;
    13071344        }
    13081345        if (rules.vertical == Qt::RepeatTile) {
    13091346            for (int i = 1; i < columns - 1; ++i)
    1310                 data[data.size() - i].source.setHeight(repeatHeight);
     1347                data[data.size() - i].height = repeatHeight;
    13111348        }
    13121349    }
    13131350
    13141351    if (opaqueData.size())
    1315         qDrawPixmaps(painter, opaqueData.data(), opaqueData.size(), pixmap, QDrawPixmaps::OpaqueHint);
     1352        painter->drawPixmapFragments(opaqueData.data(), opaqueData.size(), pixmap, QPainter::OpaqueHint);
    13161353    if (translucentData.size())
    1317         qDrawPixmaps(painter, translucentData.data(), translucentData.size(), pixmap);
    1318 }
    1319 
    1320 /*!
    1321     \class QDrawPixmaps::Data
    1322     \since 4.6
    1323     \internal
    1324 
    1325     This structure is used with the qDrawPixmaps() function.
    1326 
    1327     QPointF point:  Specifies the center of the target rectangle.
    1328     QRectF source:  Specifies the source rectangle in the pixmap passed into the qDrawPixmaps() call.
    1329     qreal scaleX:   Specifies the horizontal scale of the target rectangle.
    1330     qreal scaleY:   Specifies the vertical scale of the target rectangle.
    1331     qreal rotation: Specifies the rotation of the target rectangle in degrees.
    1332                     The target rectangle is rotated after scaling.
    1333     qreal opacity:  Specifies the opacity of the rectangle.
    1334 */
    1335 
    1336 /*!
    1337     \enum QDrawPixmaps::DrawingHint
    1338     \internal
    1339 */
    1340 
    1341 /*!
    1342     \internal
    1343     \since 4.6
    1344 
    1345     This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap, at multiple positions
    1346     with different scale, rotation and opacity on \a painter. \a drawingData is an array of \a
    1347     dataCount elements specifying the parameters used to draw each pixmap instance.
    1348     This can be used for example to implement a particle system.
    1349 */
    1350 void qDrawPixmaps(QPainter *painter, const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints)
    1351 {
    1352     QPaintEngine *engine = painter->paintEngine();
    1353     if (!engine)
    1354         return;
    1355 
    1356     if (engine->isExtended()) {
    1357         static_cast<QPaintEngineEx *>(engine)->drawPixmaps(drawingData, dataCount, pixmap, hints);
    1358     } else {
    1359         qreal oldOpacity = painter->opacity();
    1360         QTransform oldTransform = painter->transform();
    1361 
    1362         for (int i = 0; i < dataCount; ++i) {
    1363             QTransform transform = oldTransform;
    1364             qreal xOffset = 0;
    1365             qreal yOffset = 0;
    1366             if (drawingData[i].rotation == 0) {
    1367                 xOffset = drawingData[i].point.x();
    1368                 yOffset = drawingData[i].point.y();
    1369             } else {
    1370                 transform.translate(drawingData[i].point.x(), drawingData[i].point.y());
    1371                 transform.rotate(drawingData[i].rotation);
    1372             }
    1373             painter->setTransform(transform);
    1374             painter->setOpacity(oldOpacity * drawingData[i].opacity);
    1375 
    1376             qreal w = drawingData[i].scaleX * drawingData[i].source.width();
    1377             qreal h = drawingData[i].scaleY * drawingData[i].source.height();
    1378             painter->drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, drawingData[i].source);
    1379         }
    1380 
    1381         painter->setOpacity(oldOpacity);
    1382         painter->setTransform(oldTransform);
    1383     }
     1354        painter->drawPixmapFragments(translucentData.data(), translucentData.size(), pixmap);
     1355
     1356    if (oldAA)
     1357        painter->setRenderHint(QPainter::Antialiasing, true);
    13841358}
    13851359
  • trunk/src/gui/painting/qdrawutil.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    189189}
    190190
    191 // For internal use only.
    192 namespace QDrawPixmaps
    193 {
    194     struct Data
    195     {
    196         QPointF point;
    197         QRectF source;
    198         qreal scaleX;
    199         qreal scaleY;
    200         qreal rotation;
    201         qreal opacity;
    202     };
    203 
    204     enum DrawingHint
    205     {
    206         OpaqueHint = 0x01
    207     };
    208 
    209     Q_DECLARE_FLAGS(DrawingHints, DrawingHint)
    210 }
    211 
    212 // This function is private and may change without notice. Do not use outside Qt!!!
    213 Q_GUI_EXPORT void qDrawPixmaps(QPainter *painter, const QDrawPixmaps::Data *drawingData,
    214                                int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints = 0);
    215 
    216191QT_END_NAMESPACE
    217192
  • trunk/src/gui/painting/qemulationpaintengine.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    173173        fillBGRect(rect);
    174174    }
     175
     176    QPainterState *s = state();
     177    Qt::BrushStyle style = qbrush_style(s->pen.brush());
     178    if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern)
     179    {
     180        QPen savedPen = s->pen;
     181        QGradient g = *s->pen.brush().gradient();
     182
     183        if (g.coordinateMode() > QGradient::LogicalMode) {
     184            QTransform mat = s->pen.brush().transform();
     185            if (g.coordinateMode() == QGradient::StretchToDeviceMode) {
     186                mat.scale(real_engine->painter()->device()->width(), real_engine->painter()->device()->height());
     187            } else if (g.coordinateMode() == QGradient::ObjectBoundingMode) {
     188                const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
     189                QRectF r(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
     190                mat.translate(r.x(), r.y());
     191                mat.scale(r.width(), r.height());
     192            }
     193            g.setCoordinateMode(QGradient::LogicalMode);
     194            QBrush brush(g);
     195            brush.setTransform(mat);
     196            s->pen.setBrush(brush);
     197            penChanged();
     198            real_engine->drawTextItem(p, textItem);
     199            s->pen = savedPen;
     200            penChanged();
     201            return;
     202        }
     203    }
     204
    175205    real_engine->drawTextItem(p, textItem);
     206}
     207
     208void QEmulationPaintEngine::drawStaticTextItem(QStaticTextItem *item)
     209{
     210    real_engine->drawStaticTextItem(item);
    176211}
    177212
     
    234269}
    235270
     271void QEmulationPaintEngine::beginNativePainting()
     272{
     273    real_engine->beginNativePainting();
     274}
     275
     276void QEmulationPaintEngine::endNativePainting()
     277{
     278    real_engine->endNativePainting();
     279}
    236280
    237281void QEmulationPaintEngine::fillBGRect(const QRectF &r)
  • trunk/src/gui/painting/qemulationpaintengine_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7979    virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr);
    8080    virtual void drawTextItem(const QPointF &p, const QTextItem &textItem);
     81    virtual void drawStaticTextItem(QStaticTextItem *item);
    8182    virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s);
    8283    virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags);
     
    9293
    9394    virtual void setState(QPainterState *s);
     95
     96    virtual void beginNativePainting();
     97    virtual void endNativePainting();
    9498
    9599    virtual uint flags() const {return QPaintEngineEx::IsEmulationEngine | QPaintEngineEx::DoNotEmulate;}
  • trunk/src/gui/painting/qfixed_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qgraphicssystem.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5454# include <private/qpixmap_mac_p.h>
    5555#endif
    56 #ifdef Q_WS_S60
     56#ifdef Q_OS_SYMBIAN
    5757# include <private/qpixmap_s60_p.h>
    5858#endif
     
    7777#elif defined(Q_WS_MAC)
    7878    return new QMacPixmapData(type);
    79 #elif defined(Q_WS_S60)
     79#elif defined(Q_OS_SYMBIAN)
    8080    return new QS60PixmapData(type);   
    8181#elif !defined(Q_WS_QWS)
     
    8585}
    8686
     87QPixmapData *QGraphicsSystem::createPixmapData(QPixmapData *origin)
     88{
     89    return createPixmapData(origin->pixelType());
     90}
    8791
    8892QT_END_NAMESPACE
  • trunk/src/gui/painting/qgraphicssystem_mac.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qgraphicssystem_mac_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qgraphicssystem_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6565public:
    6666    virtual QPixmapData *createPixmapData(QPixmapData::PixelType type) const = 0;
     67    virtual QPixmapData *createPixmapData(QPixmapData *origin);
    6768    virtual QWindowSurface *createWindowSurface(QWidget *widget) const = 0;
    6869
  • trunk/src/gui/painting/qgraphicssystem_qws.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5050{
    5151    if (screen->pixmapDataFactory())
    52         return screen->pixmapDataFactory()->create(type); //### For 4.4 compatability
     52        return screen->pixmapDataFactory()->create(type); //### For 4.4 compatibility
    5353    else
    5454        return new QRasterPixmapData(type);
  • trunk/src/gui/painting/qgraphicssystem_qws_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qgraphicssystem_raster.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qgraphicssystem_raster_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qgraphicssystemfactory.cpp

    r706 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4747#include "qapplication.h"
    4848#include "qgraphicssystem_raster_p.h"
     49#include "qgraphicssystem_runtime_p.h"
    4950#include "qdebug.h"
    5051
    5152QT_BEGIN_NAMESPACE
    5253
    53 #if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
     54#ifndef QT_NO_LIBRARY
    5455Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
    5556    (QGraphicsSystemFactoryInterface_iid, QLatin1String("/graphicssystems"), Qt::CaseInsensitive))
     
    6970        system = QLatin1String("openvg");
    7071    }
    71 #elif defined (QT_GRAPHICSSYSTEM_RASTER) && !defined(Q_WS_WIN) && !defined(Q_WS_PM) && !defined(Q_OS_SYMBIAN)
     72#elif defined (QT_GRAPHICSSYSTEM_RUNTIME)
     73    if (system.isEmpty()) {
     74        system = QLatin1String("runtime");
     75    }
     76#elif defined (QT_GRAPHICSSYSTEM_RASTER) && !defined(Q_WS_WIN) && !defined(Q_OS_SYMBIAN) && !defined(Q_WS_PM)
    7277    if (system.isEmpty()) {
    7378        system = QLatin1String("raster");
     
    7782    if (system == QLatin1String("raster"))
    7883        return new QRasterGraphicsSystem;
     84    else if (system == QLatin1String("runtime"))
     85        return new QRuntimeGraphicsSystem;
    7986    else if (system.isEmpty() || system == QLatin1String("native"))
    8087        return 0;
    8188
    82 #if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
     89#ifndef QT_NO_LIBRARY
    8390    if (!ret) {
    8491        if (QGraphicsSystemFactoryInterface *factory = qobject_cast<QGraphicsSystemFactoryInterface*>(loader()->instance(system)))
     
    101108QStringList QGraphicsSystemFactory::keys()
    102109{
    103 #if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
     110#ifndef QT_NO_LIBRARY
    104111    QStringList list = loader()->keys();
    105112#else
  • trunk/src/gui/painting/qgraphicssystemfactory_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qgraphicssystemplugin.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qgraphicssystemplugin_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qgrayraster.c

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    157157#define ErrRaster_Invalid_Argument  -3
    158158#define ErrRaster_Memory_Overflow   -4
     159#define ErrRaster_OutOfMemory       -6
    159160
    160161#define QT_FT_BEGIN_HEADER
     
    223224#endif
    224225
    225 
    226226  /*************************************************************************/
    227227  /*                                                                       */
     
    234234
    235235  typedef int   TCoord;   /* integer scanline/pixel coordinate */
    236   typedef long  TPos;     /* sub-pixel coordinate              */
     236  typedef int   TPos;     /* sub-pixel coordinate              */
    237237
    238238  /* determine the type used to store cell areas.  This normally takes at */
     
    318318    int        ycount;
    319319
     320    int        skip_spans;
    320321  } TWorker, *PWorker;
    321322
     
    325326    void*    buffer;
    326327    long     buffer_size;
     328    long     buffer_allocated_size;
    327329    int      band_size;
    328330    void*    memory;
     
    331333  } TRaster, *PRaster;
    332334
    333 
     335  int q_gray_rendered_spans(TRaster *raster)
     336  {
     337    if ( raster && raster->worker )
     338      return raster->worker->skip_spans > 0 ? 0 : -raster->worker->skip_spans;
     339    return 0;
     340  }
    334341
    335342  /*************************************************************************/
     
    539546  {
    540547    TCoord  ex1, ex2, fx1, fx2, delta;
    541     long    p, first, dx;
     548    int     p, first, dx;
    542549    int     incr, lift, mod, rem;
    543550
     
    644651    TCoord  ey1, ey2, fy1, fy2;
    645652    TPos    dx, dy, x, x2;
    646     long    p, first;
     653    int     p, first;
    647654    int     delta, rem, mod, lift, incr;
    648655
     
    976983    if ( dx < 0 )
    977984      dx = -dx;
    978     dy = DOWNSCALE( ras.y ) + to->y - 3 * ( control1->x + control2->y );
     985    dy = DOWNSCALE( ras.y ) + to->y - 3 * ( control1->y + control2->y );
    979986    if ( dy < 0 )
    980987      dy = -dy;
     
    11831190    QT_FT_Span*  span;
    11841191    int       coverage;
     1192    int       skip;
    11851193
    11861194
     
    12331241      if ( ras.num_gray_spans >= QT_FT_MAX_GRAY_SPANS )
    12341242      {
    1235         if ( ras.render_span )
    1236           ras.render_span( ras.num_gray_spans, ras.gray_spans,
     1243        if ( ras.render_span && ras.num_gray_spans > ras.skip_spans )
     1244        {
     1245          skip = ras.skip_spans > 0 ? ras.skip_spans : 0;
     1246          ras.render_span( ras.num_gray_spans - skip,
     1247                           ras.gray_spans + skip,
    12371248                           ras.render_span_data );
     1249        }
     1250
     1251        ras.skip_spans -= ras.num_gray_spans;
     1252
    12381253        /* ras.render_span( span->y, ras.gray_spans, count ); */
    12391254
     
    13601375  /*    outline        :: A pointer to the source target.                  */
    13611376  /*                                                                       */
    1362   /*    func_interface :: A table of `emitters', i.e,. function pointers   */
    1363   /*                      called during decomposition to indicate path     */
    1364   /*                      operations.                                      */
    1365   /*                                                                       */
    13661377  /*    user           :: A typeless pointer which is passed to each       */
    13671378  /*                      emitter during the decomposition.  It can be     */
     
    13741385  static
    13751386  int  QT_FT_Outline_Decompose( const QT_FT_Outline*        outline,
    1376                              const QT_FT_Outline_Funcs*  func_interface,
    13771387                             void*                    user )
    13781388  {
    13791389#undef SCALED
    1380 #if 0
    1381 #define SCALED( x )  ( ( (x) << shift ) - delta )
    1382 #else
    13831390#define SCALED( x )  (x)
    1384 #endif
    13851391
    13861392    QT_FT_Vector   v_last;
     
    13961402    int   error;
    13971403    char  tag;       /* current point's state           */
    1398 
    1399 #if 0
    1400     int   shift = func_interface->shift;
    1401     TPos  delta = func_interface->delta;
    1402 #endif
    1403 
    14041404
    14051405    first = 0;
     
    14561456      }
    14571457
    1458       error = func_interface->move_to( &v_start, user );
     1458      error = gray_move_to( &v_start, user );
    14591459      if ( error )
    14601460        goto Exit;
     
    14761476            vec.y = SCALED( point->y );
    14771477
    1478             error = func_interface->line_to( &vec, user );
     1478            error = gray_line_to( &vec, user );
    14791479            if ( error )
    14801480              goto Exit;
     
    15031503              if ( tag == QT_FT_CURVE_TAG_ON )
    15041504              {
    1505                 error = func_interface->conic_to( &v_control, &vec,
     1505                error = gray_conic_to( &v_control, &vec,
    15061506                                                  user );
    15071507                if ( error )
     
    15161516              v_middle.y = ( v_control.y + vec.y ) / 2;
    15171517
    1518               error = func_interface->conic_to( &v_control, &v_middle,
     1518              error = gray_conic_to( &v_control, &v_middle,
    15191519                                                user );
    15201520              if ( error )
     
    15251525            }
    15261526
    1527             error = func_interface->conic_to( &v_control, &v_start,
     1527            error = gray_conic_to( &v_control, &v_start,
    15281528                                              user );
    15291529            goto Close;
     
    15561556              vec.y = SCALED( point->y );
    15571557
    1558               error = func_interface->cubic_to( &vec1, &vec2, &vec, user );
     1558              error = gray_cubic_to( &vec1, &vec2, &vec, user );
    15591559              if ( error )
    15601560                goto Exit;
     
    15621562            }
    15631563
    1564             error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );
     1564            error = gray_cubic_to( &vec1, &vec2, &v_start, user );
    15651565            goto Close;
    15661566          }
     
    15691569
    15701570      /* close the contour with a line segment */
    1571       error = func_interface->line_to( &v_start, user );
     1571      error = gray_line_to( &v_start, user );
    15721572
    15731573   Close:
     
    15971597  gray_convert_glyph_inner( RAS_ARG )
    15981598  {
    1599     static
    1600     const QT_FT_Outline_Funcs  func_interface =
    1601     {
    1602       (QT_FT_Outline_MoveTo_Func) gray_move_to,
    1603       (QT_FT_Outline_LineTo_Func) gray_line_to,
    1604       (QT_FT_Outline_ConicTo_Func)gray_conic_to,
    1605       (QT_FT_Outline_CubicTo_Func)gray_cubic_to,
    1606       0,
    1607       0
    1608     };
    1609 
    16101599    volatile int  error = 0;
    16111600
    16121601    if ( qt_ft_setjmp( ras.jump_buffer ) == 0 )
    16131602    {
    1614       error = QT_FT_Outline_Decompose( &ras.outline, &func_interface, &ras );
     1603      error = QT_FT_Outline_Decompose( &ras.outline, &ras );
    16151604      gray_record_cell( RAS_VAR );
    16161605    }
     
    16311620    int volatile     n, num_bands;
    16321621    TPos volatile    min, max, max_y;
    1633     QT_FT_BBox*         clip;
     1622    QT_FT_BBox*      clip;
     1623    int              skip;
    16341624
    16351625    ras.num_gray_spans = 0;
     
    17011691          PCell  cells_max;
    17021692          int    yindex;
    1703           long   cell_start, cell_end, cell_mod;
     1693          int    cell_start, cell_end, cell_mod;
    17041694
    17051695
     
    17581748          fprintf( stderr, "Rotten glyph!\n" );
    17591749#endif
    1760           /* == Raster_Err_OutOfMemory in qblackraster.c */
    1761           return -6;
     1750          return ErrRaster_OutOfMemory;
    17621751        }
    17631752
     
    17731762    }
    17741763
    1775     if ( ras.render_span && ras.num_gray_spans > 0 )
    1776         ras.render_span( ras.num_gray_spans,
    1777                          ras.gray_spans, ras.render_span_data );
     1764    if ( ras.render_span && ras.num_gray_spans > ras.skip_spans )
     1765    {
     1766        skip = ras.skip_spans > 0 ? ras.skip_spans : 0;
     1767        ras.render_span( ras.num_gray_spans - skip,
     1768                         ras.gray_spans + skip,
     1769                         ras.render_span_data );
     1770    }
     1771
     1772    ras.skip_spans -= ras.num_gray_spans;
    17781773
    17791774    if ( ras.band_shoot > 8 && ras.band_size > 16 )
     
    17851780
    17861781  static int
    1787   gray_raster_render( PRaster                  raster,
     1782  gray_raster_render( QT_FT_Raster                  raster,
    17881783                      const QT_FT_Raster_Params*  params )
    17891784  {
     
    17951790    if ( !raster || !raster->buffer || !raster->buffer_size )
    17961791      return ErrRaster_Invalid_Argument;
     1792
     1793    if ( raster->worker )
     1794      raster->worker->skip_spans = params->skip_spans;
     1795
     1796    // If raster object and raster buffer are allocated, but
     1797    // raster size isn't of the minimum size, indicate out of
     1798    // memory.
     1799    if (raster->buffer_allocated_size < MINIMUM_POOL_SIZE )
     1800      return ErrRaster_OutOfMemory;
    17971801
    17981802    /* return immediately if the outline is empty */
     
    18751879
    18761880  static int
    1877   gray_raster_new( void *  memory,
    1878                    QT_FT_Raster*  araster )
    1879   {
    1880     if (memory)
    1881       fprintf(stderr, "gray_raster_new(), memory ignored");
    1882     memory = malloc(sizeof(TRaster));
    1883     if (!memory) {
     1881  gray_raster_new( QT_FT_Raster*  araster )
     1882  {
     1883    *araster = malloc(sizeof(TRaster));
     1884    if (!*araster) {
    18841885        *araster = 0;
    18851886        return ErrRaster_Memory_Overflow;
    18861887    }
    1887     QT_FT_MEM_ZERO(memory, sizeof(TRaster));
    1888 
    1889     *araster = (QT_FT_Raster) memory;
     1888    QT_FT_MEM_ZERO(*araster, sizeof(TRaster));
     1889
    18901890    return 0;
    18911891  }
     
    19061906    PRaster  rast = (PRaster)raster;
    19071907
    1908 
    19091908    if ( raster )
    19101909    {
    1911       if ( pool_base && pool_size >= (long)sizeof ( TWorker ) + 2048 )
     1910      if ( pool_base && ( pool_size >= MINIMUM_POOL_SIZE ) )
    19121911      {
    19131912        PWorker  worker = (PWorker)pool_base;
     
    19241923                                     ( sizeof ( TCell ) * 8 ) );
    19251924      }
     1925      else if ( pool_base)
     1926      { // Case when there is a raster pool allocated, but it
     1927        // doesn't have the minimum size (and so memory will be reallocated)
     1928          rast->buffer = pool_base;
     1929          rast->worker = NULL;
     1930          rast->buffer_size = pool_size;
     1931      }
    19261932      else
    19271933      {
     
    19301936        rast->worker      = NULL;
    19311937      }
     1938      rast->buffer_allocated_size = pool_size;
    19321939    }
    19331940  }
  • trunk/src/gui/painting/qgrayraster_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    9090#endif
    9191
     92/* Minimum buffer size for raster object, that accounts
     93   for TWorker and TCell sizes.*/
     94#define MINIMUM_POOL_SIZE 4096
     95
    9296  QT_FT_EXPORT_VAR( const QT_FT_Raster_Funcs )  qt_ft_grays_raster;
    9397
  • trunk/src/gui/painting/qimagescale.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    305305}
    306306
    307 /* FIXME: NEED to optimise ScaleAARGBA - currently its "ok" but needs work*/
     307/* FIXME: NEED to optimize ScaleAARGBA - currently its "ok" but needs work*/
    308308
    309309/* scale by area sampling */
  • trunk/src/gui/painting/qimagescale_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qmath_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qmatrix.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    104104    QPaintDevice has its origin located at the top-left position. The
    105105    \e x values increase to the right; \e y values increase
    106     downward. For a complete description, see the \l {The Coordinate
     106    downward. For a complete description, see the \l {Coordinate
    107107    System}{coordinate system} documentation.
    108108
     
    177177    \endtable
    178178
    179     \sa QPainter, QTransform, {The Coordinate System},
     179    \sa QPainter, QTransform, {Coordinate System},
    180180    {demos/affine}{Affine Transformations Demo}, {Transformations Example}
    181181*/
     
    11361136    reference to the stream.
    11371137
    1138     \sa {Format of the QDataStream Operators}
     1138    \sa {Serializing Qt Data Types}
    11391139*/
    11401140
     
    11621162    reference to the stream.
    11631163
    1164     \sa {Format of the QDataStream Operators}
     1164    \sa {Serializing Qt Data Types}
    11651165*/
    11661166
  • trunk/src/gui/painting/qmatrix.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qmemrotate.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    595595}
    596596
     597void qt_memrotate90_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
     598{
     599    qt_memrotate90((const ushort *)srcPixels, w, h, sbpl, (ushort *)destPixels, dbpl);
     600}
     601
     602void qt_memrotate180_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
     603{
     604    qt_memrotate180((const ushort *)srcPixels, w, h, sbpl, (ushort *)destPixels, dbpl);
     605}
     606
     607void qt_memrotate270_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
     608{
     609    qt_memrotate270((const ushort *)srcPixels, w, h, sbpl, (ushort *)destPixels, dbpl);
     610}
     611
     612void qt_memrotate90_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
     613{
     614    qt_memrotate90((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl);
     615}
     616
     617void qt_memrotate180_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
     618{
     619    qt_memrotate180((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl);
     620}
     621
     622void qt_memrotate270_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
     623{
     624    qt_memrotate270((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl);
     625}
     626
     627MemRotateFunc qMemRotateFunctions[QImage::NImageFormats][3] =
     628// 90, 180, 270
     629{
     630    { 0, 0, 0 },      // Format_Invalid,
     631    { 0, 0, 0 },      // Format_Mono,
     632    { 0, 0, 0 },      // Format_MonoLSB,
     633    { 0, 0, 0 },      // Format_Indexed8,
     634    { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 },      // Format_RGB32,
     635    { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 },      // Format_ARGB32,
     636    { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 },      // Format_ARGB32_Premultiplied,
     637    { qt_memrotate90_16, qt_memrotate180_16, qt_memrotate270_16 },      // Format_RGB16,
     638    { 0, 0, 0 },      // Format_ARGB8565_Premultiplied,
     639    { 0, 0, 0 },      // Format_RGB666,
     640    { 0, 0, 0 },      // Format_ARGB6666_Premultiplied,
     641    { 0, 0, 0 },      // Format_RGB555,
     642    { 0, 0, 0 },      // Format_ARGB8555_Premultiplied,
     643    { 0, 0, 0 },      // Format_RGB888,
     644    { 0, 0, 0 },      // Format_RGB444,
     645    { 0, 0, 0 }       // Format_ARGB4444_Premultiplied,
     646};
     647
    597648QT_END_NAMESPACE
  • trunk/src/gui/painting/qmemrotate_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8383
    8484void Q_GUI_EXPORT qt_memrotate90(const quint32*, int, int, int, quint32*, int);
     85void Q_GUI_QWS_EXPORT qt_memrotate180(const quint32*, int, int, int, quint32*, int);
     86void Q_GUI_QWS_EXPORT qt_memrotate270(const quint32*, int, int, int, quint32*, int);
    8587
    86 QT_DECL_MEMROTATE(quint32, quint32);
    8788QT_DECL_MEMROTATE(quint32, quint16);
    8889QT_DECL_MEMROTATE(quint16, quint32);
  • trunk/src/gui/painting/qoutlinemapper.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    155155
    156156        m_elements.resize(count);
    157         memcpy(m_elements.data(), path.points(), count* sizeof(QPointF));
     157        if (count)
     158            memcpy(m_elements.data(), path.points(), count* sizeof(QPointF));
    158159
    159160        m_element_types.resize(0);
     
    234235
    235236    // Check for out of dev bounds...
    236     const bool do_clip = (controlPointRect.left() < -QT_RASTER_COORD_LIMIT
     237    const bool do_clip = !m_in_clip_elements && ((controlPointRect.left() < -QT_RASTER_COORD_LIMIT
    237238                          || controlPointRect.right() > QT_RASTER_COORD_LIMIT
    238239                          || controlPointRect.top() < -QT_RASTER_COORD_LIMIT
    239240                          || controlPointRect.bottom() > QT_RASTER_COORD_LIMIT
    240241                          || controlPointRect.width() > QT_RASTER_COORD_LIMIT
    241                           || controlPointRect.height() > QT_RASTER_COORD_LIMIT);
     242                          || controlPointRect.height() > QT_RASTER_COORD_LIMIT));
    242243
    243244    if (do_clip) {
     
    353354    // this part of code hardly every used, it shouldn't matter.
    354355
     356    m_in_clip_elements = true;
     357
    355358    QPainterPath path;
     359
     360    if (!(m_outline.flags & QT_FT_OUTLINE_EVEN_ODD_FILL))
     361        path.setFillRule(Qt::WindingFill);
     362
    356363    if (types) {
    357364        for (int i=0; i<element_count; ++i) {
     
    389396        convertPath(clippedPath);
    390397    m_txop = old_txop;
     398
     399    m_in_clip_elements = false;
    391400}
    392401
  • trunk/src/gui/painting/qoutlinemapper_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8888{
    8989public:
    90     QOutlineMapper()
    91         : m_round_coords(false)
     90    QOutlineMapper() :
     91        m_element_types(0),
     92        m_elements(0),
     93        m_elements_dev(0),
     94        m_points(0),
     95        m_tags(0),
     96        m_contours(0),
     97        m_polygon_dev(0),
     98        m_in_clip_elements(false),
     99        m_round_coords(false)
    92100    {
    93101    }
     
    229237
    230238    bool m_valid;
     239    bool m_in_clip_elements;
    231240
    232241private:
  • trunk/src/gui/painting/qpaintbuffer.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4646#include <private/qemulationpaintengine_p.h>
    4747#include <private/qimage_p.h>
     48#include <qstatictext.h>
     49#include <private/qstatictext_p.h>
    4850
    4951#include <QDebug>
     
    268270#endif
    269271
    270     if (painter && !painter->isActive())
    271         return;
     272    processCommands(painter, frameStartIndex(frame), frameEndIndex(frame));
     273
     274#ifdef QPAINTBUFFER_DEBUG_DRAW
     275    qDebug() << "QPaintBuffer::draw() -------------------------------- DONE!";
     276#endif
     277}
     278
     279int QPaintBuffer::frameStartIndex(int frame) const
     280{
     281    return (frame == 0) ? 0 : d_ptr->frames.at(frame - 1);
     282}
     283
     284int QPaintBuffer::frameEndIndex(int frame) const
     285{
     286    return (frame == d_ptr->frames.size()) ? d_ptr->commands.size() : d_ptr->frames.at(frame);
     287}
     288
     289int QPaintBuffer::processCommands(QPainter *painter, int begin, int end) const
     290{
     291    if (!painter || !painter->isActive())
     292        return 0;
    272293
    273294    QPaintEngineEx *xengine = painter->paintEngine()->isExtended()
     
    275296    if (xengine) {
    276297        QPaintEngineExReplayer player;
    277         player.draw(*this, painter, frame);
     298        player.processCommands(*this, painter, begin, end);
    278299    } else {
    279300        QPainterReplayer player;
    280         player.draw(*this, painter, frame);
    281     }
    282 
    283 #ifdef QPAINTBUFFER_DEBUG_DRAW
    284     qDebug() << "QPaintBuffer::draw() -------------------------------- DONE!";
    285 #endif
    286 }
    287 
     301        player.processCommands(*this, painter, begin, end);
     302    }
     303
     304    int depth = 0;
     305    for (int i = begin; i < end; ++i) {
     306        const QPaintBufferCommand &cmd = d_ptr->commands.at(i);
     307        if (cmd.id == QPaintBufferPrivate::Cmd_Save)
     308            ++depth;
     309        else if (cmd.id == QPaintBufferPrivate::Cmd_Restore)
     310            --depth;
     311    }
     312    return depth;
     313}
     314
     315#ifndef QT_NO_DEBUG_STREAM
     316QString QPaintBuffer::commandDescription(int command) const
     317{
     318    QString desc;
     319    QDebug debug(&desc);
     320
     321    const QPaintBufferCommand &cmd = d_ptr->commands.at(command);
     322
     323    switch (cmd.id) {
     324    case QPaintBufferPrivate::Cmd_Save: {
     325        debug << "Cmd_Save";
     326        break; }
     327
     328    case QPaintBufferPrivate::Cmd_Restore: {
     329        debug << "Cmd_Restore";
     330        break; }
     331
     332    case QPaintBufferPrivate::Cmd_SetBrush: {
     333        QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.offset));
     334        debug << "Cmd_SetBrush: " << brush;
     335        break; }
     336
     337    case QPaintBufferPrivate::Cmd_SetBrushOrigin: {
     338        debug << "Cmd_SetBrushOrigin: " << d_ptr->variants.at(cmd.offset).toPointF();
     339        break; }
     340
     341    case QPaintBufferPrivate::Cmd_SetCompositionMode: {
     342        QPainter::CompositionMode mode = (QPainter::CompositionMode) cmd.extra;
     343        debug << "ExCmd_SetCompositionMode, mode: " << mode;
     344        break; }
     345
     346    case QPaintBufferPrivate::Cmd_SetOpacity: {
     347        debug << "ExCmd_SetOpacity: " << d_ptr->variants.at(cmd.offset).toDouble();
     348        break; }
     349
     350    case QPaintBufferPrivate::Cmd_DrawVectorPath: {
     351        debug << "ExCmd_DrawVectorPath: size: " << cmd.size
     352//                 << ", hints:" << d->ints[cmd.offset2+cmd.size]
     353                 << "pts/elms:" << cmd.offset << cmd.offset2;
     354        break; }
     355
     356    case QPaintBufferPrivate::Cmd_StrokeVectorPath: {
     357        QPen pen = qVariantValue<QPen>(d_ptr->variants.at(cmd.extra));
     358        debug << "ExCmd_StrokeVectorPath: size: " << cmd.size
     359//                 << ", hints:" << d->ints[cmd.offset2+cmd.size]
     360                 << "pts/elms:" << cmd.offset << cmd.offset2 << pen;
     361        break; }
     362
     363    case QPaintBufferPrivate::Cmd_FillVectorPath: {
     364        QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.extra));
     365        debug << "ExCmd_FillVectorPath: size: " << cmd.size
     366//                 << ", hints:" << d->ints[cmd.offset2+cmd.size]
     367                 << "pts/elms:" << cmd.offset << cmd.offset2 << brush;
     368        break; }
     369
     370    case QPaintBufferPrivate::Cmd_FillRectBrush: {
     371        QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.extra));
     372        QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset);
     373        debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush;
     374        break; }
     375
     376    case QPaintBufferPrivate::Cmd_FillRectColor: {
     377        QColor color = qVariantValue<QColor>(d_ptr->variants.at(cmd.extra));
     378        QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset);
     379        debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color;
     380        break; }
     381
     382    case QPaintBufferPrivate::Cmd_DrawPolygonF: {
     383        debug << "ExCmd_DrawPolygonF, offset: " << cmd.offset << " size: " << cmd.size
     384                 << " mode: " << cmd.extra
     385                 << d_ptr->floats.at(cmd.offset)
     386                 << d_ptr->floats.at(cmd.offset+1);
     387        break; }
     388
     389    case QPaintBufferPrivate::Cmd_DrawPolygonI: {
     390        debug << "ExCmd_DrawPolygonI, offset: " << cmd.offset << " size: " << cmd.size
     391                 << " mode: " << cmd.extra
     392                 << d_ptr->ints.at(cmd.offset)
     393                 << d_ptr->ints.at(cmd.offset+1);
     394        break; }
     395
     396    case QPaintBufferPrivate::Cmd_DrawEllipseF: {
     397        debug << "ExCmd_DrawEllipseF, offset: " << cmd.offset;
     398        break; }
     399
     400    case QPaintBufferPrivate::Cmd_DrawLineF: {
     401        debug << "ExCmd_DrawLineF, offset: " << cmd.offset << " size: " << cmd.size;
     402        break; }
     403
     404    case QPaintBufferPrivate::Cmd_DrawLineI: {
     405        debug << "ExCmd_DrawLineI, offset: " << cmd.offset << " size: " << cmd.size;
     406        break; }
     407
     408    case QPaintBufferPrivate::Cmd_DrawPointsF: {
     409        debug << "ExCmd_DrawPointsF, offset: " << cmd.offset << " size: " << cmd.size;
     410        break; }
     411
     412    case QPaintBufferPrivate::Cmd_DrawPointsI: {
     413        debug << "ExCmd_DrawPointsI, offset: " << cmd.offset << " size: " << cmd.size;
     414        break; }
     415
     416    case QPaintBufferPrivate::Cmd_DrawPolylineF: {
     417        debug << "ExCmd_DrawPolylineF, offset: " << cmd.offset << " size: " << cmd.size;
     418        break; }
     419
     420    case QPaintBufferPrivate::Cmd_DrawPolylineI: {
     421        debug << "ExCmd_DrawPolylineI, offset: " << cmd.offset << " size: " << cmd.size;
     422        break; }
     423
     424    case QPaintBufferPrivate::Cmd_DrawRectF: {
     425        debug << "ExCmd_DrawRectF, offset: " << cmd.offset << " size: " << cmd.size;
     426        break; }
     427
     428    case QPaintBufferPrivate::Cmd_DrawRectI: {
     429        debug << "ExCmd_DrawRectI, offset: " << cmd.offset << " size: " << cmd.size;
     430        break; }
     431
     432    case QPaintBufferPrivate::Cmd_SetClipEnabled: {
     433        bool clipEnabled = d_ptr->variants.at(cmd.offset).toBool();
     434        debug << "ExCmd_SetClipEnabled:" << clipEnabled;
     435        break; }
     436
     437    case QPaintBufferPrivate::Cmd_ClipVectorPath: {
     438        QVectorPathCmd path(d_ptr, cmd);
     439        debug << "ExCmd_ClipVectorPath:" << path().elementCount();
     440        break; }
     441
     442    case QPaintBufferPrivate::Cmd_ClipRect: {
     443        QRect rect(QPoint(d_ptr->ints.at(cmd.offset), d_ptr->ints.at(cmd.offset + 1)),
     444                   QPoint(d_ptr->ints.at(cmd.offset + 2), d_ptr->ints.at(cmd.offset + 3)));
     445        debug << "ExCmd_ClipRect:" << rect << cmd.extra;
     446        break; }
     447
     448    case QPaintBufferPrivate::Cmd_ClipRegion: {
     449        QRegion region(d_ptr->variants.at(cmd.offset).value<QRegion>());
     450        debug << "ExCmd_ClipRegion:" << region.boundingRect() << cmd.extra;
     451        break; }
     452
     453    case QPaintBufferPrivate::Cmd_SetPen: {
     454        QPen pen = qVariantValue<QPen>(d_ptr->variants.at(cmd.offset));
     455        debug << "Cmd_SetPen: " << pen;
     456        break; }
     457
     458    case QPaintBufferPrivate::Cmd_SetTransform: {
     459        QTransform xform = qVariantValue<QTransform>(d_ptr->variants.at(cmd.offset));
     460        debug << "Cmd_SetTransform, offset: " << cmd.offset << xform;
     461        break; }
     462
     463    case QPaintBufferPrivate::Cmd_SetRenderHints: {
     464        debug << "Cmd_SetRenderHints, hints: " << cmd.extra;
     465        break; }
     466
     467    case QPaintBufferPrivate::Cmd_SetBackgroundMode: {
     468        debug << "Cmd_SetBackgroundMode: " << cmd.extra;
     469        break; }
     470
     471    case QPaintBufferPrivate::Cmd_DrawConvexPolygonF: {
     472        debug << "Cmd_DrawConvexPolygonF, offset: " << cmd.offset << " size: " << cmd.size;
     473        break; }
     474
     475    case QPaintBufferPrivate::Cmd_DrawConvexPolygonI: {
     476        debug << "Cmd_DrawConvexPolygonI, offset: " << cmd.offset << " size: " << cmd.size;
     477        break; }
     478
     479    case QPaintBufferPrivate::Cmd_DrawEllipseI: {
     480        debug << "Cmd_DrawEllipseI, offset: " << cmd.offset;
     481        break; }
     482
     483    case QPaintBufferPrivate::Cmd_DrawPixmapRect: {
     484        QPixmap pm(d_ptr->variants.at(cmd.offset).value<QPixmap>());
     485        QRectF r(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1),
     486                 d_ptr->floats.at(cmd.extra+2), d_ptr->floats.at(cmd.extra+3));
     487
     488        QRectF sr(d_ptr->floats.at(cmd.extra+4), d_ptr->floats.at(cmd.extra+5),
     489                  d_ptr->floats.at(cmd.extra+6), d_ptr->floats.at(cmd.extra+7));
     490        debug << "Cmd_DrawPixmapRect:" << r << sr << pm.size();
     491        break; }
     492
     493    case QPaintBufferPrivate::Cmd_DrawPixmapPos: {
     494        QPixmap pm(d_ptr->variants.at(cmd.offset).value<QPixmap>());
     495        QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
     496        debug << "Cmd_DrawPixmapPos:" << pos << pm.size();
     497        break; }
     498
     499    case QPaintBufferPrivate::Cmd_DrawTiledPixmap: {
     500        QPixmap pm(d_ptr->variants.at(cmd.offset).value<QPixmap>());
     501        QRectF r(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1),
     502                 d_ptr->floats.at(cmd.extra+2), d_ptr->floats.at(cmd.extra+3));
     503
     504        QPointF offset(d_ptr->floats.at(cmd.extra+4), d_ptr->floats.at(cmd.extra+5));
     505        debug << "Cmd_DrawTiledPixmap:" << r << offset << pm.size();
     506        break; }
     507
     508    case QPaintBufferPrivate::Cmd_DrawImageRect: {
     509        QImage image(d_ptr->variants.at(cmd.offset).value<QImage>());
     510        QRectF r(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1),
     511                 d_ptr->floats.at(cmd.extra+2), d_ptr->floats.at(cmd.extra+3));
     512        QRectF sr(d_ptr->floats.at(cmd.extra+4), d_ptr->floats.at(cmd.extra+5),
     513                  d_ptr->floats.at(cmd.extra+6), d_ptr->floats.at(cmd.extra+7));
     514        debug << "Cmd_DrawImageRect:" << r << sr << image.size();
     515        break; }
     516
     517    case QPaintBufferPrivate::Cmd_DrawImagePos: {
     518        QImage image(d_ptr->variants.at(cmd.offset).value<QImage>());
     519        QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
     520        debug << "Cmd_DrawImagePos:" << pos << image.size();
     521        break; }
     522
     523    case QPaintBufferPrivate::Cmd_DrawText: {
     524        QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
     525        QList<QVariant> variants(d_ptr->variants.at(cmd.offset).value<QList<QVariant> >());
     526
     527        QFont font(variants.at(0).value<QFont>());
     528        QString text(variants.at(1).value<QString>());
     529
     530        debug << "Cmd_DrawText:" << pos << text << font.family();
     531        break; }
     532
     533    case QPaintBufferPrivate::Cmd_DrawTextItem: {
     534        QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
     535        QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(d_ptr->variants.at(cmd.offset)));
     536        QTextItemInt &ti = (*tiCopy)();
     537        QString text(ti.text());
     538
     539        QFont font(ti.font());
     540        font.setUnderline(false);
     541        font.setStrikeOut(false);
     542        font.setOverline(false);
     543
     544        const QTextItemInt &si = static_cast<const QTextItemInt &>(ti);
     545        qreal justificationWidth = 0;
     546        if (si.justified)
     547            justificationWidth = si.width.toReal();
     548
     549        debug << "Cmd_DrawTextItem:" << pos << " " << text;
     550        break; }
     551    case QPaintBufferPrivate::Cmd_SystemStateChanged: {
     552        QRegion systemClip(d_ptr->variants.at(cmd.offset).value<QRegion>());
     553
     554        debug << "Cmd_SystemStateChanged:" << systemClip;
     555        break; }
     556    case QPaintBufferPrivate::Cmd_Translate: {
     557        QPointF delta(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
     558        debug << "Cmd_Translate:" << delta;
     559        break; }
     560    case QPaintBufferPrivate::Cmd_DrawStaticText: {
     561        debug << "Cmd_DrawStaticText";
     562        break; }
     563    }
     564
     565    return desc;
     566}
     567#endif
    288568
    289569QRectF QPaintBuffer::boundingRect() const
     
    307587        q->buffer->addCommand(QPaintBufferPrivate::Cmd_SystemStateChanged, QVariant(systemClip));
    308588    }
     589
     590    QTransform last;
    309591};
    310592
     
    493775void QPaintBufferEngine::transformChanged()
    494776{
     777    Q_D(QPaintBufferEngine);
     778    const QTransform &transform = state()->matrix;
     779
     780    QTransform delta;
     781
     782    bool invertible = false;
     783    if (transform.type() <= QTransform::TxScale && transform.type() == d->last.type())
     784        delta = transform * d->last.inverted(&invertible);
     785
     786    d->last = transform;
     787
     788    if (invertible && delta.type() == QTransform::TxNone)
     789        return;
     790
     791    if (invertible && delta.type() == QTransform::TxTranslate) {
     792#ifdef QPAINTBUFFER_DEBUG_DRAW
     793        qDebug() << "QPaintBufferEngine: transformChanged (translate only) " << state()->matrix;
     794#endif
     795        QPaintBufferCommand *cmd =
     796            buffer->addCommand(QPaintBufferPrivate::Cmd_Translate);
     797
     798        qreal data[] = { delta.dx(), delta.dy() };
     799        cmd->extra = buffer->addData((qreal *) data, 2);
     800        return;
     801    }
     802
    495803    // ### accumulate, like in QBrush case...
    496804    if (!buffer->commands.isEmpty()
     
    9611269}
    9621270
     1271void QPaintBufferEngine::drawStaticTextItem(QStaticTextItem *staticTextItem)
     1272{
     1273    QVariantList variants;
     1274
     1275    variants << QVariant(staticTextItem->font);
     1276    for (int i=0; i<staticTextItem->numGlyphs; ++i) {
     1277        variants.append(staticTextItem->glyphs[i]);
     1278        variants.append(staticTextItem->glyphPositions[i].toPointF());
     1279    }
     1280
     1281    buffer->addCommand(QPaintBufferPrivate::Cmd_DrawStaticText, QVariant(variants));
     1282}
     1283
    9631284void QPaintBufferEngine::drawTextItem(const QPointF &pos, const QTextItem &ti)
    9641285{
     
    10001321void QPaintBufferEngine::setState(QPainterState *s)
    10011322{
     1323    Q_D(QPaintBufferEngine);
    10021324    if (m_begin_detected) {
    10031325#ifdef QPAINTBUFFER_DEBUG_DRAW
     
    10171339        buffer->addCommand(QPaintBufferPrivate::Cmd_Restore);
    10181340    }
     1341
     1342    d->last = s->matrix;
    10191343
    10201344    QPaintEngineEx::setState(s);
     
    10661390}
    10671391
    1068 void QPainterReplayer::draw(const QPaintBuffer &buffer, QPainter *_painter, int frame)
     1392void QPainterReplayer::processCommands(const QPaintBuffer &buffer, QPainter *p, int begin, int end)
    10691393{
    10701394    d = buffer.d_ptr;
    1071     setupTransform(_painter);
    1072 
    1073     int frameStart = (frame == 0) ? 0 : d->frames.at(frame-1);
    1074     int frameEnd = (frame == d->frames.size()) ? d->commands.size() : d->frames.at(frame);
    1075 
    1076     for (int cmdIndex=frameStart; cmdIndex<frameEnd; ++cmdIndex) {
     1395    painter = p;
     1396
     1397    for (int cmdIndex = begin; cmdIndex < end; ++cmdIndex) {
    10771398        const QPaintBufferCommand &cmd = d->commands.at(cmdIndex);
    10781399        process(cmd);
     
    11381459        painter->setTransform(xform * m_world_matrix);
    11391460        break; }
     1461
     1462    case QPaintBufferPrivate::Cmd_Translate: {
     1463        QPointF delta(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
     1464#ifdef QPAINTBUFFER_DEBUG_DRAW
     1465        qDebug() << " -> Cmd_Translate, offset: " << cmd.offset << delta;
     1466#endif
     1467        painter->translate(delta.x(), delta.y());
     1468        return;
     1469    }
    11401470
    11411471    case QPaintBufferPrivate::Cmd_SetCompositionMode: {
     
    14261756        painter->setClipRegion(region, Qt::ClipOperation(cmd.extra));
    14271757        break; }
     1758       
     1759    case QPaintBufferPrivate::Cmd_DrawStaticText: {
     1760           
     1761            QVariantList variants(d->variants.at(cmd.offset).value<QVariantList>());
     1762           
     1763            QFont font = variants.at(0).value<QFont>();
     1764
     1765            QVector<quint32> glyphs;
     1766            QVector<QPointF> positions;
     1767
     1768            for (int i=0; i<(variants.size() - 1) / 2; ++i) {
     1769                glyphs.append(variants.at(i*2 + 1).toUInt());
     1770                positions.append(variants.at(i*2 + 2).toPointF());
     1771            }
     1772
     1773            painter->setFont(font);
     1774
     1775            qt_draw_glyphs(painter, glyphs.constData(), positions.constData(), glyphs.size());
     1776           
     1777        break;
     1778    }
    14281779
    14291780    case QPaintBufferPrivate::Cmd_DrawText: {
     
    17712122    quint64 cacheKey;
    17722123};
     2124
     2125struct QPaintBufferCacheEntryV2
     2126{
     2127    enum Type {
     2128        ImageKey,
     2129        PixmapKey
     2130    };
     2131
     2132    struct Flags {
     2133        uint type : 8;
     2134        uint key : 24;
     2135    };
     2136
     2137    union {
     2138        Flags flags;
     2139        uint bits;
     2140    };
     2141};
     2142
    17732143QT_END_NAMESPACE
    17742144Q_DECLARE_METATYPE(QPaintBufferCacheEntry)
     2145Q_DECLARE_METATYPE(QPaintBufferCacheEntryV2)
    17752146QT_BEGIN_NAMESPACE
    17762147
     
    17832154{
    17842155    return stream >> entry.type >> entry.cacheKey;
     2156}
     2157
     2158QDataStream &operator<<(QDataStream &stream, const QPaintBufferCacheEntryV2 &entry)
     2159{
     2160    return stream << entry.bits;
     2161}
     2162
     2163QDataStream &operator>>(QDataStream &stream, QPaintBufferCacheEntryV2 &entry)
     2164{
     2165    return stream >> entry.bits;
    17852166}
    17862167
     
    17892170    qRegisterMetaType<QPaintBufferCacheEntry>();
    17902171    qRegisterMetaTypeStreamOperators<QPaintBufferCacheEntry>("QPaintBufferCacheEntry");
     2172    qRegisterMetaType<QPaintBufferCacheEntryV2>();
     2173    qRegisterMetaTypeStreamOperators<QPaintBufferCacheEntryV2>("QPaintBufferCacheEntryV2");
    17912174
    17922175    return 0; // something
     
    17972180QDataStream &operator<<(QDataStream &stream, const QPaintBuffer &buffer)
    17982181{
     2182    QHash<qint64, uint> pixmapKeys;
     2183    QHash<qint64, uint> imageKeys;
     2184
    17992185    QHash<qint64, QPixmap> pixmaps;
    18002186    QHash<qint64, QImage> images;
     
    18052191        if (v.type() == QVariant::Image) {
    18062192            const QImage image(v.value<QImage>());
    1807             images[image.cacheKey()] = image;
    1808 
    1809             QPaintBufferCacheEntry entry;
    1810             entry.type = QVariant::Image;
    1811             entry.cacheKey = image.cacheKey();
     2193
     2194            QPaintBufferCacheEntryV2 entry;
     2195            entry.flags.type = QPaintBufferCacheEntryV2::ImageKey;
     2196
     2197            QHash<qint64, uint>::iterator it = imageKeys.find(image.cacheKey());
     2198            if (it != imageKeys.end()) {
     2199                entry.flags.key = *it;
     2200            } else {
     2201                imageKeys[image.cacheKey()] = entry.flags.key = images.size();
     2202                images[images.size()] = image;
     2203            }
     2204
    18122205            variants[i] = QVariant::fromValue(entry);
    18132206        } else if (v.type() == QVariant::Pixmap) {
    18142207            const QPixmap pixmap(v.value<QPixmap>());
    1815             pixmaps[pixmap.cacheKey()] = pixmap;
    1816 
    1817             QPaintBufferCacheEntry entry;
    1818             entry.type = QVariant::Pixmap;
    1819             entry.cacheKey = pixmap.cacheKey();
     2208
     2209            QPaintBufferCacheEntryV2 entry;
     2210            entry.flags.type = QPaintBufferCacheEntryV2::PixmapKey;
     2211
     2212            QHash<qint64, uint>::iterator it = pixmapKeys.find(pixmap.cacheKey());
     2213            if (it != pixmapKeys.end()) {
     2214                entry.flags.key = *it;
     2215            } else {
     2216                pixmapKeys[pixmap.cacheKey()] = entry.flags.key = pixmaps.size();
     2217                pixmaps[pixmaps.size()] = pixmap;
     2218            }
     2219
    18202220            variants[i] = QVariant::fromValue(entry);
    18212221        }
     
    18592259            else
    18602260                variants[i] = QVariant(pixmaps.value(entry.cacheKey));
     2261        } else if (v.canConvert<QPaintBufferCacheEntryV2>()) {
     2262            QPaintBufferCacheEntryV2 entry = v.value<QPaintBufferCacheEntryV2>();
     2263
     2264            if (entry.flags.type == QPaintBufferCacheEntryV2::ImageKey)
     2265                variants[i] = QVariant(images.value(entry.flags.key));
     2266            else if (entry.flags.type == QPaintBufferCacheEntryV2::PixmapKey)
     2267                variants[i] = QVariant(pixmaps.value(entry.flags.key));
     2268            else
     2269                qWarning() << "operator<<(QDataStream &stream, QPaintBuffer &buffer): unrecognized cache entry type:" << entry.flags.type;
    18612270        }
    18622271    }
  • trunk/src/gui/painting/qpaintbuffer_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7979
    8080    void draw(QPainter *painter, int frame = 0) const;
     81
     82    int frameStartIndex(int frame) const;
     83    int frameEndIndex(int frame) const;
     84    int processCommands(QPainter *painter, int begin, int end) const;
     85#ifndef QT_NO_DEBUG_STREAM
     86    QString commandDescription(int command) const;
     87#endif
     88
    8189    void setBoundingRect(const QRectF &rect);
    8290    QRectF boundingRect() const;
     
    184192
    185193        Cmd_SystemStateChanged,
     194        Cmd_Translate,
     195        Cmd_DrawStaticText,
     196
     197        // new commands must be added above this line
    186198
    187199        Cmd_LastCommand
     
    314326    void setupTransform(QPainter *painter);
    315327    virtual void process(const QPaintBufferCommand &cmd);
    316     void draw(const QPaintBuffer &buffer, QPainter *painter, int frame);
     328    void processCommands(const QPaintBuffer &buffer, QPainter *painter, int begin, int end);
    317329
    318330protected:
     
    395407
    396408    virtual void drawTextItem(const QPointF &pos, const QTextItem &ti);
     409    virtual void drawStaticTextItem(QStaticTextItem *staticTextItem);
    397410
    398411    virtual void setState(QPainterState *s);
  • trunk/src/gui/painting/qpaintdevice.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qpaintdevice.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qpaintdevice.qdoc

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    77** This file is part of the documentation of the Qt Toolkit.
    88**
    9 ** $QT_BEGIN_LICENSE:LGPL$
     9** $QT_BEGIN_LICENSE:FDL$
    1010** Commercial Usage
    1111** Licensees holding valid Qt Commercial licenses may use this file in
    1212** accordance with the Qt Commercial License Agreement provided with the
    13 ** Software or, alternatively, in accordance with the terms contained in
    14 ** a written agreement between you and Nokia.
    15 **
    16 ** GNU Lesser General Public License Usage
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
    18 ** General Public License version 2.1 as published by the Free Software
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
    20 ** packaging of this file.  Please review the following information to
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    23 **
    24 ** In addition, as a special exception, Nokia gives you certain additional
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    27 **
    28 ** GNU General Public License Usage
    29 ** Alternatively, this file may be used under the terms of the GNU
    30 ** General Public License version 3.0 as published by the Free Software
    31 ** Foundation and appearing in the file LICENSE.GPL included in the
    32 ** packaging of this file.  Please review the following information to
    33 ** ensure the GNU General Public License version 3.0 requirements will be
    34 ** met: http://www.gnu.org/copyleft/gpl.html.
     13** Software or, alternatively, in accordance with the terms contained in a
     14** written agreement between you and Nokia.
     15**
     16** GNU Free Documentation License
     17** Alternatively, this file may be used under the terms of the GNU Free
     18** Documentation License version 1.3 as published by the Free Software
     19** Foundation and appearing in the file included in the packaging of this
     20** file.
    3521**
    3622** If you have questions regarding the use of this file, please contact
     
    8874    paint device.
    8975
    90     \sa QPaintEngine, QPainter, {The Coordinate System}, {The Paint
    91     System}
     76    \sa QPaintEngine, QPainter, {Coordinate System}, {Paint System}
    9277*/
    9378
  • trunk/src/gui/painting/qpaintdevice_mac.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qpaintdevice_qws.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qpaintdevice_win.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qpaintdevice_x11.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qpaintengine.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    173173  advantage of each to the fullest.
    174174
    175   \sa QPainter, QPaintDevice::paintEngine(), {The Paint System}
     175  \sa QPainter, QPaintDevice::paintEngine(), {Paint System}
    176176*/
    177177
     
    993993    \internal
    994994
    995     Retreives the rect for drawing within the backing store. This
     995    Retrieves the rect for drawing within the backing store. This
    996996    function should ONLY be used by the backing store.
    997997 */
  • trunk/src/gui/painting/qpaintengine.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qpaintengine_alpha.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qpaintengine_alpha_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qpaintengine_mac.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    119119            QTransform native = p->deviceTransform();
    120120            QTransform logical = p->combinedTransform();
     121
    121122            if (p->hasClipping()) {
    122123                QRegion r = p->clipRegion();
    123                 r.translate(native.dx() - logical.dx(), native.dy() - logical.dy());
     124                r.translate(native.dx(), native.dy());
    124125                if (clip.isEmpty())
    125126                    clip = r;
     
    129130            qt_mac_clip_cg(context, clip, 0);
    130131
    131             QPainterState *state = static_cast<QPainterState *>(pe->state);
    132             Q_ASSERT(state);
    133             if (!state->redirectionMatrix.isIdentity())
    134                 CGContextTranslateCTM(context, state->redirectionMatrix.dx(), state->redirectionMatrix.dy());
     132            CGContextTranslateCTM(context, native.dx(), native.dy());
    135133        }
    136134    }
     
    13931391                                         kCGInterpolationHigh : kCGInterpolationNone);
    13941392    }
    1395     CGContextSetShouldSmoothFonts(d->hd, hints & QPainter::TextAntialiasing);
     1393    bool textAntialiasing = (hints & QPainter::TextAntialiasing) == QPainter::TextAntialiasing;
     1394    if (!textAntialiasing || d->disabledSmoothFonts) {
     1395        d->disabledSmoothFonts = !textAntialiasing;
     1396        CGContextSetShouldSmoothFonts(d->hd, textAntialiasing);
     1397    }
    13961398}
    13971399
  • trunk/src/gui/painting/qpaintengine_mac_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    149149public:
    150150    QCoreGraphicsPaintEnginePrivate()
    151         : hd(0), shading(0), stackCount(0), complexXForm(false)
     151        : hd(0), shading(0), stackCount(0), complexXForm(false), disabledSmoothFonts(false)
    152152    {
    153153    }
     
    169169    int stackCount;
    170170    bool complexXForm;
     171    bool disabledSmoothFonts;
    171172    enum { CosmeticNone, CosmeticTransformPath, CosmeticSetPenWidth } cosmeticPen;
    172173
  • trunk/src/gui/painting/qpaintengine_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qpaintengine_preview.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qpaintengine_preview_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qpaintengine_raster.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4141
    4242#include <QtCore/qglobal.h>
     43#include <QtCore/qmutex.h>
    4344
    4445#define QT_FT_BEGIN_HEADER
     
    6869//   #include <private/qrasterizer_p.h>
    6970#include <private/qimage_p.h>
     71#include <private/qstatictext_p.h>
     72#include "qmemrotate_p.h"
    7073
    7174#include "qpaintengine_raster_p.h"
     
    251254#endif
    252255
     256QRasterPaintEnginePrivate::QRasterPaintEnginePrivate() :
     257    QPaintEngineExPrivate(),
     258    cachedLines(0)
     259{
     260}
    253261
    254262
     
    336344#endif
    337345
    338     d->rasterPoolSize = 8192;
    339     d->rasterPoolBase =
    340 #if defined(Q_WS_WIN64)
    341         // We make use of setjmp and longjmp in qgrayraster.c which requires
    342         // 16-byte alignment, hence we hardcode this requirement here..
    343         (unsigned char *) _aligned_malloc(d->rasterPoolSize, sizeof(void*) * 2);
    344 #else
    345         (unsigned char *) malloc(d->rasterPoolSize);
    346 #endif
    347     Q_CHECK_PTR(d->rasterPoolBase);
    348 
    349346    // The antialiasing raster.
    350347    d->grayRaster.reset(new QT_FT_Raster);
    351348    Q_CHECK_PTR(d->grayRaster.data());
    352     if (qt_ft_grays_raster.raster_new(0, d->grayRaster.data()))
     349    if (qt_ft_grays_raster.raster_new(d->grayRaster.data()))
    353350        QT_THROW(std::bad_alloc()); // an error creating the raster is caused by a bad malloc
    354351
    355 
    356     qt_ft_grays_raster.raster_reset(*d->grayRaster.data(), d->rasterPoolBase, d->rasterPoolSize);
    357352
    358353    d->rasterizer.reset(new QRasterizer);
     
    437432    Q_D(QRasterPaintEngine);
    438433
    439 #if defined(Q_WS_WIN64)
    440     _aligned_free(d->rasterPoolBase);
    441 #else
    442     free(d->rasterPoolBase);
    443 #endif
    444 
    445434    qt_ft_grays_raster.raster_done(*d->grayRaster.data());
    446435}
     
    455444    if (device->devType() == QInternal::Pixmap) {
    456445        QPixmap *pixmap = static_cast<QPixmap *>(device);
    457         if (pixmap->data->classId() == QPixmapData::RasterClass)
    458             d->device = pixmap->data->buffer();
     446        QPixmapData *pd = pixmap->pixmapData();
     447        if (pd->classId() == QPixmapData::RasterClass)
     448            d->device = pd->buffer();
    459449    } else {
    460450        d->device = device;
     
    471461    QRasterPaintEngineState *s = state();
    472462    ensureOutlineMapper();
    473     d->outlineMapper->m_clip_rect = d->deviceRect.adjusted(-10, -10, 10, 10);
    474 
    475     // This is the upp
    476     QRect bounds(-QT_RASTER_COORD_LIMIT, -QT_RASTER_COORD_LIMIT,
    477                  QT_RASTER_COORD_LIMIT*2 - 1, QT_RASTER_COORD_LIMIT * 2 - 1);
    478     d->outlineMapper->m_clip_rect = bounds.intersected(d->outlineMapper->m_clip_rect);
    479 
     463    d->outlineMapper->m_clip_rect = d->deviceRect;
     464
     465    if (d->outlineMapper->m_clip_rect.width() > QT_RASTER_COORD_LIMIT)
     466        d->outlineMapper->m_clip_rect.setWidth(QT_RASTER_COORD_LIMIT);
     467    if (d->outlineMapper->m_clip_rect.height() > QT_RASTER_COORD_LIMIT)
     468        d->outlineMapper->m_clip_rect.setHeight(QT_RASTER_COORD_LIMIT);
    480469
    481470    d->rasterizer->setClipRect(d->deviceRect);
     
    887876        updateMatrix(s->matrix);
    888877
    889     if (s->dirty & (DirtyPen|DirtyCompositionMode)) {
     878    if (s->dirty & (DirtyPen|DirtyCompositionMode|DirtyOpacity)) {
    890879        const QPainter::CompositionMode mode = s->composition_mode;
    891880        s->flags.fast_text = (s->penData.type == QSpanData::Solid)
     881                       && s->intOpacity == 256
    892882                       && (mode == QPainter::CompositionMode_Source
    893883                           || (mode == QPainter::CompositionMode_SourceOver
     
    913903    s->strokeFlags |= DirtyOpacity;
    914904    s->pixmapFlags |= DirtyOpacity;
     905    s->dirty |= DirtyOpacity;
    915906    s->intOpacity = (int) (s->opacity * 256);
    916907}
     
    11151106    bool bilinear = q->state()->flags.bilinear;
    11161107
    1117     if (b.d->transform.type() > QTransform::TxNone) { // FALCON: optimise
     1108    if (b.d->transform.type() > QTransform::TxNone) { // FALCON: optimize
    11181109        spanData->setupMatrix(b.transform() * m, bilinear);
    11191110    } else {
     
    12221213    if (op != Qt::UniteClip && (op != Qt::IntersectClip || !s->clip
    12231214                                || s->clip->hasRectClip || s->clip->hasRegionClip)) {
    1224         if (s->matrix.type() <= QTransform::TxTranslate
     1215        if (s->matrix.type() <= QTransform::TxScale
    12251216            && ((path.shape() == QVectorPath::RectangleHint)
    12261217                || (isRect(points, path.elementCount())
     
    12341225
    12351226            QRectF r(points[0], points[1], points[4]-points[0], points[5]-points[1]);
    1236             clip(r.toRect(), op);
    1237             return;
     1227            if (setClipRectInDeviceCoords(s->matrix.mapRect(r).toRect(), op))
     1228                return;
    12381229        }
    12391230    }
     
    12961287#endif
    12971288
    1298     Q_D(QRasterPaintEngine);
    12991289    QRasterPaintEngineState *s = state();
    13001290
     
    13061296        return;
    13071297
    1308     } else if (op == Qt::ReplaceClip || s->clip == 0) {
     1298    } else if (!setClipRectInDeviceCoords(s->matrix.mapRect(rect), op)) {
     1299        QPaintEngineEx::clip(rect, op);
     1300        return;
     1301    }
     1302}
     1303
     1304
     1305bool QRasterPaintEngine::setClipRectInDeviceCoords(const QRect &r, Qt::ClipOperation op)
     1306{
     1307    Q_D(QRasterPaintEngine);
     1308    QRect clipRect = r & d->deviceRect;
     1309    QRasterPaintEngineState *s = state();
     1310
     1311    if (op == Qt::ReplaceClip || s->clip == 0) {
    13091312
    13101313        // No current clip, hence we intersect with sysclip and be
    13111314        // done with it...
    1312         QRect clipRect = s->matrix.mapRect(rect) & d->deviceRect;
    13131315        QRegion clipRegion = systemClip();
    13141316        QClipData *clip = new QClipData(d->rasterBuffer->height());
     
    13261328        s->flags.has_clip_ownership = true;
    13271329
    1328     } else { // intersect clip with current clip
     1330    } else if (op == Qt::IntersectClip){ // intersect clip with current clip
    13291331        QClipData *base = s->clip;
    13301332
    13311333        Q_ASSERT(base);
    13321334        if (base->hasRectClip || base->hasRegionClip) {
    1333             QRect clipRect = s->matrix.mapRect(rect) & d->deviceRect;
    13341335            if (!s->flags.has_clip_ownership) {
    13351336                s->clip = new QClipData(d->rasterBuffer->height());
     
    13421343            s->clip->enabled = true;
    13431344        } else {
    1344             QPaintEngineEx::clip(rect, op);
    1345             return;
    1346         }
    1347     }
     1345            return false;
     1346        }
     1347    } else {
     1348        return false;
     1349    }
     1350
    13481351    qrasterpaintengine_dirty_clip(d, s);
     1352    return true;
    13491353}
    13501354
     
    17251729            int n = qFloor(dashOffset / patternLength);
    17261730            dashOffset -= n * patternLength;
    1727             while (dashOffset > pattern.at(dashIndex)) {
     1731            while (dashOffset >= pattern.at(dashIndex)) {
    17281732                dashOffset -= pattern.at(dashIndex);
    1729                 dashIndex = (dashIndex + 1) % pattern.size();
     1733                if (++dashIndex >= pattern.size())
     1734                    dashIndex = 0;
    17301735                inDash = !inDash;
    17311736            }
     
    17381743
    17391744        for (int i = 0; i < lineCount; ++i) {
    1740             dashOffset = s->lastPen.dashOffset();
    17411745            if (lines[i].p1() == lines[i].p2()) {
    17421746                if (s->lastPen.capStyle() != Qt::FlatCap) {
     
    18121816        if (s->flags.tx_noshear) {
    18131817            d->initializeRasterizer(&s->brushData);
    1814             // ### Is normalizing really nessesary here?
     1818            // ### Is normalizing really necessary here?
    18151819            const qreal *p = path.points();
    18161820            QRectF r = QRectF(p[0], p[1], p[2] - p[0], p[7] - p[1]).normalized();
     
    23722376#endif
    23732377
    2374     if (pixmap.data->classId() == QPixmapData::RasterClass) {
    2375         const QImage &image = static_cast<QRasterPixmapData *>(pixmap.data.data())->image;
     2378    QPixmapData *pd = pixmap.pixmapData();
     2379    if (pd->classId() == QPixmapData::RasterClass) {
     2380        const QImage &image = static_cast<QRasterPixmapData *>(pd)->image;
    23762381        if (image.depth() == 1) {
    23772382            Q_D(QRasterPaintEngine);
     
    24122417#endif
    24132418
    2414     if (pixmap.data->classId() == QPixmapData::RasterClass) {
    2415         const QImage &image = static_cast<QRasterPixmapData *>(pixmap.data.data())->image;
     2419    QPixmapData* pd = pixmap.pixmapData();
     2420    if (pd->classId() == QPixmapData::RasterClass) {
     2421        const QImage &image = static_cast<QRasterPixmapData *>(pd)->image;
    24162422        if (image.depth() == 1) {
    24172423            Q_D(QRasterPaintEngine);
     
    24302436        }
    24312437    } else {
    2432         const QImage image = pixmap.toImage();
     2438        QRect clippedSource = sr.toAlignedRect().intersected(pixmap.rect());
     2439        const QImage image = pd->toImage(clippedSource);
     2440        QRectF translatedSource = sr.translated(-clippedSource.topLeft());
    24332441        if (image.depth() == 1) {
    24342442            Q_D(QRasterPaintEngine);
     
    24412449                return;
    24422450            } else {
    2443                 drawImage(r, d->rasterBuffer->colorizeBitmap(image, s->pen.color()), sr);
     2451                drawImage(r, d->rasterBuffer->colorizeBitmap(image, s->pen.color()), translatedSource);
    24442452            }
    24452453        } else {
    2446             drawImage(r, image, sr);
     2454            drawImage(r, image, translatedSource);
    24472455        }
    24482456    }
     
    25322540}
    25332541
     2542namespace {
     2543    enum RotationType {
     2544        Rotation90,
     2545        Rotation180,
     2546        Rotation270,
     2547        NoRotation
     2548    };
     2549
     2550    inline RotationType qRotationType(const QTransform &transform)
     2551    {
     2552        QTransform::TransformationType type = transform.type();
     2553
     2554        if (type > QTransform::TxRotate)
     2555            return NoRotation;
     2556
     2557        if (type == QTransform::TxRotate && qFuzzyIsNull(transform.m11()) && qFuzzyCompare(transform.m12(), qreal(-1))
     2558            && qFuzzyCompare(transform.m21(), qreal(1)) && qFuzzyIsNull(transform.m22()))
     2559            return Rotation90;
     2560
     2561        if (type == QTransform::TxScale && qFuzzyCompare(transform.m11(), qreal(-1)) && qFuzzyIsNull(transform.m12())
     2562            && qFuzzyIsNull(transform.m21()) && qFuzzyCompare(transform.m22(), qreal(-1)))
     2563            return Rotation180;
     2564
     2565        if (type == QTransform::TxRotate && qFuzzyIsNull(transform.m11()) && qFuzzyCompare(transform.m12(), qreal(1))
     2566            && qFuzzyCompare(transform.m21(), qreal(-1)) && qFuzzyIsNull(transform.m22()))
     2567            return Rotation270;
     2568
     2569        return NoRotation;
     2570    }
     2571
     2572    inline bool isPixelAligned(const QRectF &rect) {
     2573        return QRectF(rect.toRect()) == rect;
     2574    }
     2575}
     2576
    25342577/*!
    25352578    \reimp
     
    25522595    int sr_b = qCeil(sr.bottom()) - 1;
    25532596
    2554     if (!s->flags.antialiased && sr_l == sr_r && sr_t == sr_b) {
     2597    if (s->matrix.type() <= QTransform::TxScale && !s->flags.antialiased && sr_l == sr_r && sr_t == sr_b) {
    25552598        // as fillRect will apply the aliased coordinate delta we need to
    25562599        // subtract it here as we don't use it for image drawing
     
    25932636    const QClipData *clip = d->clip();
    25942637
     2638    if (s->matrix.type() > QTransform::TxTranslate
     2639        && !stretch_sr
     2640        && (!clip || clip->hasRectClip)
     2641        && s->intOpacity == 256
     2642        && (d->rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver
     2643            || d->rasterBuffer->compositionMode == QPainter::CompositionMode_Source)
     2644        && d->rasterBuffer->format == img.format()
     2645        && (d->rasterBuffer->format == QImage::Format_RGB16
     2646            || d->rasterBuffer->format == QImage::Format_RGB32
     2647            || (d->rasterBuffer->format == QImage::Format_ARGB32_Premultiplied
     2648                && d->rasterBuffer->compositionMode == QPainter::CompositionMode_Source)))
     2649    {
     2650        RotationType rotationType = qRotationType(s->matrix);
     2651
     2652        if (rotationType != NoRotation && qMemRotateFunctions[d->rasterBuffer->format][rotationType] && img.rect().contains(sr.toAlignedRect())) {
     2653            QRectF transformedTargetRect = s->matrix.mapRect(r);
     2654
     2655            if ((!(s->renderHints & QPainter::SmoothPixmapTransform) && !(s->renderHints & QPainter::Antialiasing))
     2656                || (isPixelAligned(transformedTargetRect) && isPixelAligned(sr)))
     2657            {
     2658                QRect clippedTransformedTargetRect = transformedTargetRect.toRect().intersected(clip ? clip->clipRect : d->deviceRect);
     2659                if (clippedTransformedTargetRect.isNull())
     2660                    return;
     2661
     2662                QRectF clippedTargetRect = s->matrix.inverted().mapRect(QRectF(clippedTransformedTargetRect));
     2663
     2664                QRect clippedSourceRect
     2665                    = QRectF(sr.x() + clippedTargetRect.x() - r.x(), sr.y() + clippedTargetRect.y() - r.y(),
     2666                            clippedTargetRect.width(), clippedTargetRect.height()).toRect();
     2667
     2668                uint dbpl = d->rasterBuffer->bytesPerLine();
     2669                uint sbpl = img.bytesPerLine();
     2670
     2671                uchar *dst = d->rasterBuffer->buffer();
     2672                uint bpp = img.depth() >> 3;
     2673
     2674                const uchar *srcBase = img.bits() + clippedSourceRect.y() * sbpl + clippedSourceRect.x() * bpp;
     2675                uchar *dstBase = dst + clippedTransformedTargetRect.y() * dbpl + clippedTransformedTargetRect.x() * bpp;
     2676
     2677                uint cw = clippedSourceRect.width();
     2678                uint ch = clippedSourceRect.height();
     2679
     2680                qMemRotateFunctions[d->rasterBuffer->format][rotationType](srcBase, cw, ch, sbpl, dstBase, dbpl);
     2681
     2682                return;
     2683            }
     2684        }
     2685    }
     2686
    25952687    if (s->matrix.type() > QTransform::TxTranslate || stretch_sr) {
    25962688
    2597         if (s->flags.fast_images) {
     2689        QRectF targetBounds = s->matrix.mapRect(r);
     2690        bool exceedsPrecision = targetBounds.width() > 0xffff
     2691                                || targetBounds.height() > 0xffff;
     2692
     2693        if (s->flags.fast_images && !exceedsPrecision) {
    25982694            if (s->matrix.type() > QTransform::TxScale) {
    25992695                SrcOverTransformFunc func = qTransformFunctions[d->rasterBuffer->format][img.format()];
     
    27172813    QImage image;
    27182814
    2719     if (pixmap.data->classId() == QPixmapData::RasterClass) {
    2720         image = static_cast<QRasterPixmapData *>(pixmap.data.data())->image;
     2815    QPixmapData *pd = pixmap.pixmapData();
     2816    if (pd->classId() == QPixmapData::RasterClass) {
     2817        image = static_cast<QRasterPixmapData *>(pd)->image;
    27212818    } else {
    27222819        image = pixmap.toImage();
     
    30033100}
    30043101
    3005 void QRasterPaintEngine::drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti)
     3102void QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
     3103                                          const QFixedPoint *positions, QFontEngine *fontEngine)
    30063104{
    30073105    Q_D(QRasterPaintEngine);
    30083106    QRasterPaintEngineState *s = state();
    30093107
    3010     QVarLengthArray<QFixedPoint> positions;
    3011     QVarLengthArray<glyph_t> glyphs;
    3012     QTransform matrix = s->matrix;
    3013     matrix.translate(p.x(), p.y());
    3014     ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
    3015 
    3016     QFontEngineGlyphCache::Type glyphType = ti.fontEngine->glyphFormat >= 0 ? QFontEngineGlyphCache::Type(ti.fontEngine->glyphFormat) : d->glyphCacheType;
     3108    QFontEngineGlyphCache::Type glyphType = fontEngine->glyphFormat >= 0 ? QFontEngineGlyphCache::Type(fontEngine->glyphFormat) : d->glyphCacheType;
    30173109
    30183110    QImageTextureGlyphCache *cache =
    3019         (QImageTextureGlyphCache *) ti.fontEngine->glyphCache(0, glyphType, s->matrix);
     3111        static_cast<QImageTextureGlyphCache *>(fontEngine->glyphCache(0, glyphType, s->matrix));
    30203112    if (!cache) {
    30213113        cache = new QImageTextureGlyphCache(glyphType, s->matrix);
    3022         ti.fontEngine->setGlyphCache(0, cache);
    3023     }
    3024 
    3025     cache->populate(ti, glyphs, positions);
     3114        fontEngine->setGlyphCache(0, cache);
     3115    }
     3116
     3117    cache->populate(fontEngine, numGlyphs, glyphs, positions);
    30263118
    30273119    const QImage &image = cache->image();
     
    30413133
    30423134    const uchar *bits = image.bits();
    3043     for (int i=0; i<glyphs.size(); ++i) {
     3135    for (int i=0; i<numGlyphs; ++i) {
    30443136        const QTextureGlyphCache::Coord &c = cache->coords.value(glyphs[i]);
    30453137        int x = qFloor(positions[i].x + offs) + c.baseLineX - margin;
     
    30893181        TSize glyphBitmapSize;
    30903182        fe->getCharacterData(glyphs[i], tmetrics, glyphBitmapBytes, glyphBitmapSize);
    3091         const glyph_metrics_t metrics = ti.fontEngine->boundingBox(glyphs[i]);
    3092         const int x = qFloor(positions[i].x + metrics.x + aliasDelta);
    3093         const int y = qFloor(positions[i].y + metrics.y + aliasDelta);
    3094 
     3183        const int x = qFloor(positions[i].x + tmetrics.HorizBearingX() + aliasDelta);
     3184        const int y = qFloor(positions[i].y - tmetrics.HorizBearingY() + aliasDelta);
    30953185        alphaPenBlt(glyphBitmapBytes, glyphBitmapSize.iWidth, 8, x, y, glyphBitmapSize.iWidth, glyphBitmapSize.iHeight);
    30963186    }
     
    31043194
    31053195/*!
    3106  * Returns true if the rectangle is completly within the current clip
     3196 * Returns true if the rectangle is completely within the current clip
    31073197 * state of the paint engine.
    31083198 */
     
    32193309
    32203310/*!
     3311   \reimp
     3312*/
     3313void QRasterPaintEngine::drawStaticTextItem(QStaticTextItem *textItem)
     3314{
     3315    ensurePen();
     3316    ensureState();
     3317
     3318    drawCachedGlyphs(textItem->numGlyphs, textItem->glyphs, textItem->glyphPositions,
     3319                     textItem->fontEngine());
     3320}
     3321
     3322/*!
    32213323    \reimp
    32223324*/
     
    32663368#endif
    32673369    if (drawCached) {
    3268         drawCachedGlyphs(p, ti);
     3370        QRasterPaintEngineState *s = state();
     3371
     3372        QVarLengthArray<QFixedPoint> positions;
     3373        QVarLengthArray<glyph_t> glyphs;
     3374
     3375        QTransform matrix = s->matrix;
     3376        matrix.translate(p.x(), p.y());
     3377
     3378        ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
     3379
     3380        drawCachedGlyphs(glyphs.size(), glyphs.constData(), positions.constData(), ti.fontEngine);
    32693381        return;
    32703382    }
     
    33733485
    33743486    for(int i = 0; i < glyphs.size(); i++) {
    3375         QFontEngineFT::Glyph *glyph = gset->glyph_data.value(glyphs[i]);
     3487        QFontEngineFT::Glyph *glyph = gset->getGlyph(glyphs[i]);
    33763488
    33773489        if (!glyph || glyph->format != neededFormat) {
     
    36093721            *dashOffset = 0;
    36103722            *inDash = !(*inDash);
    3611             *dashIndex = (*dashIndex + 1) % pattern.size();
     3723            if (++*dashIndex >= pattern.size())
     3724                *dashIndex = 0;
    36123725            length -= dash;
    36133726            l.setLength(dash);
     
    36153728        }
    36163729
    3617         if (rasterize && dash != 0)
     3730        if (rasterize && dash > 0)
    36183731            rasterizer->rasterizeLine(l.p1(), l.p2(), width / dash, squareCap);
    36193732    }
     
    36763789         || (qpen_style(s->lastPen) == Qt::NoPen && !s->flags.antialiased))
    36773790        && qMax(rect.width(), rect.height()) < QT_RASTER_COORD_LIMIT
     3791        && !rect.isEmpty()
    36783792        && s->matrix.type() <= QTransform::TxScale) // no shear
    36793793    {
     
    40494163}
    40504164
     4165extern "C" {
     4166    int q_gray_rendered_spans(QT_FT_Raster raster);
     4167}
     4168
    40514169void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline,
    40524170                                          ProcessSpans callback,
     
    40714189        return;
    40724190    }
     4191
     4192    // Initial size for raster pool is MINIMUM_POOL_SIZE so as to
     4193    // minimize memory reallocations. However if initial size for
     4194    // raster pool is changed for lower value, reallocations will
     4195    // occur normally.
     4196    const int rasterPoolInitialSize = MINIMUM_POOL_SIZE;
     4197    int rasterPoolSize = rasterPoolInitialSize;
     4198    unsigned char *rasterPoolBase;
     4199#if defined(Q_WS_WIN64)
     4200    rasterPoolBase =
     4201        // We make use of setjmp and longjmp in qgrayraster.c which requires
     4202        // 16-byte alignment, hence we hardcode this requirement here..
     4203        (unsigned char *) _aligned_malloc(rasterPoolSize, sizeof(void*) * 2);
     4204#else
     4205    unsigned char rasterPoolOnStack[rasterPoolInitialSize];
     4206    rasterPoolBase = rasterPoolOnStack;
     4207#endif
     4208    Q_CHECK_PTR(rasterPoolBase);
     4209
     4210    qt_ft_grays_raster.raster_reset(*grayRaster.data(), rasterPoolBase, rasterPoolSize);
    40734211
    40744212    void *data = userData;
     
    40934231    int error;
    40944232
     4233    int rendered_spans = 0;
     4234
    40954235    while (!done) {
    40964236
    40974237        rasterParams.flags |= (QT_FT_RASTER_FLAG_AA | QT_FT_RASTER_FLAG_DIRECT);
    40984238        rasterParams.gray_spans = callback;
     4239        rasterParams.skip_spans = rendered_spans;
    40994240        error = qt_ft_grays_raster.raster_render(*grayRaster.data(), &rasterParams);
    41004241
    41014242        // Out of memory, reallocate some more and try again...
    4102         if (error == -6) { // -6 is Result_err_OutOfMemory
     4243        if (error == -6) { // ErrRaster_OutOfMemory from qgrayraster.c
    41034244            int new_size = rasterPoolSize * 2;
    41044245            if (new_size > 1024 * 1024) {
    41054246                qWarning("QPainter: Rasterization of primitive failed");
    4106                 return;
     4247                break;
    41074248            }
     4249
     4250            rendered_spans += q_gray_rendered_spans(*grayRaster.data());
    41084251
    41094252#if defined(Q_WS_WIN64)
    41104253            _aligned_free(rasterPoolBase);
    41114254#else
    4112             free(rasterPoolBase);
     4255            if (rasterPoolBase != rasterPoolOnStack) // initially on the stack
     4256                free(rasterPoolBase);
    41134257#endif
    41144258
     
    41254269
    41264270            qt_ft_grays_raster.raster_done(*grayRaster.data());
    4127             qt_ft_grays_raster.raster_new(0, grayRaster.data());
     4271            qt_ft_grays_raster.raster_new(grayRaster.data());
    41284272            qt_ft_grays_raster.raster_reset(*grayRaster.data(), rasterPoolBase, rasterPoolSize);
    41294273        } else {
     
    41314275        }
    41324276    }
     4277
     4278#if defined(Q_WS_WIN64)
     4279    _aligned_free(rasterPoolBase);
     4280#else
     4281    if (rasterPoolBase != rasterPoolOnStack) // initially on the stack
     4282        free(rasterPoolBase);
     4283#endif
    41334284}
    41344285
     
    48124963            hash_val += stops[i].second.rgba();
    48134964
     4965        QMutexLocker lock(&mutex);
    48144966        QGradientColorTableHash::const_iterator it = cache.constFind(hash_val);
    48154967
     
    48454997
    48464998    QGradientColorTableHash cache;
     4999    QMutex mutex;
    48475000};
    48485001
  • trunk/src/gui/painting/qpaintengine_raster_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    204204    void clip(const QRegion &region, Qt::ClipOperation op);
    205205
     206    void drawStaticTextItem(QStaticTextItem *textItem);
     207
    206208    enum ClipType {
    207209        RectClip,
     
    258260    void drawBitmap(const QPointF &pos, const QImage &image, QSpanData *fill);
    259261
    260     void drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti);
     262    void drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions,
     263                          QFontEngine *fontEngine);
    261264
    262265#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
    263266    void drawGlyphsS60(const QPointF &p, const QTextItemInt &ti);
    264267#endif // Q_OS_SYMBIAN && QT_NO_FREETYPE
     268
     269    bool setClipRectInDeviceCoords(const QRect &r, Qt::ClipOperation op);
    265270
    266271    inline void ensureBrush(const QBrush &brush) {
     
    298303    Q_DECLARE_PUBLIC(QRasterPaintEngine)
    299304public:
     305    QRasterPaintEnginePrivate();
    300306
    301307    void rasterizeLine_dashed(QLineF line, qreal width,
     
    352358
    353359    QScopedPointer<QT_FT_Raster> grayRaster;
    354     unsigned long rasterPoolSize;
    355     unsigned char *rasterPoolBase;
    356360
    357361    QDataBuffer<QLineF> cachedLines;
  • trunk/src/gui/painting/qpaintengine_s60.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6060    Q_D(QS60PaintEngine);
    6161
    62     pixmapData->beginDataAccess();
    63     bool ret = QRasterPaintEngine::begin(device);
    64     // Make sure QPaintEngine::paintDevice() returns the proper device.
    65     // QRasterPaintEngine changes pdev to QImage in case of RasterClass QPixmapData
    66     // which is incorrect in Symbian.
    67     d->pdev = device;
    68     return ret;
     62    if (pixmapData->classId() == QPixmapData::RasterClass) {
     63        pixmapData->beginDataAccess();
     64        bool ret = QRasterPaintEngine::begin(device);
     65        // Make sure QPaintEngine::paintDevice() returns the proper device.
     66        // QRasterPaintEngine changes pdev to QImage in case of RasterClass QPixmapData
     67        // which is incorrect in Symbian.
     68        d->pdev = device;
     69        return ret;
     70    }
     71
     72    return QRasterPaintEngine::begin(device);
    6973}
    7074
    7175bool QS60PaintEngine::end()
    7276{
    73     bool ret = QRasterPaintEngine::end();
    74     pixmapData->endDataAccess();
    75     return ret;
     77    if (pixmapData->classId() == QPixmapData::RasterClass) {
     78        bool ret = QRasterPaintEngine::end();
     79        pixmapData->endDataAccess();
     80        return ret;
     81    }
     82    return QRasterPaintEngine::end();
    7683}
    7784
    7885void QS60PaintEngine::drawPixmap(const QPointF &p, const QPixmap &pm)
    7986{
    80     QS60PixmapData *srcData = static_cast<QS60PixmapData *>(pm.pixmapData());
    81     srcData->beginDataAccess();
    82     QRasterPaintEngine::drawPixmap(p, pm);
    83     srcData->endDataAccess();
     87    if (pm.pixmapData()->classId() == QPixmapData::RasterClass) {
     88        QS60PixmapData *srcData = static_cast<QS60PixmapData *>(pm.pixmapData());
     89        srcData->beginDataAccess();
     90        QRasterPaintEngine::drawPixmap(p, pm);
     91        srcData->endDataAccess();
     92    } else {
     93        QRasterPaintEngine::drawPixmap(p, pm);
     94    }
    8495}
    8596
    8697void QS60PaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
    8798{
    88     QS60PixmapData *srcData = static_cast<QS60PixmapData *>(pm.pixmapData());
    89     srcData->beginDataAccess();
    90     QRasterPaintEngine::drawPixmap(r, pm, sr);
    91     srcData->endDataAccess();
     99    if (pm.pixmapData()->classId() == QPixmapData::RasterClass) {
     100        QS60PixmapData *srcData = static_cast<QS60PixmapData *>(pm.pixmapData());
     101        srcData->beginDataAccess();
     102        QRasterPaintEngine::drawPixmap(r, pm, sr);
     103        srcData->endDataAccess();
     104    } else {
     105        QRasterPaintEngine::drawPixmap(r, pm, sr);
     106    }
    92107}
    93108
    94109void QS60PaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr)
    95110{
    96     QS60PixmapData *srcData = static_cast<QS60PixmapData *>(pm.pixmapData());
    97     srcData->beginDataAccess();
    98     QRasterPaintEngine::drawTiledPixmap(r, pm, sr);
    99     srcData->endDataAccess();
     111    if (pm.pixmapData()->classId() == QPixmapData::RasterClass) {
     112        QS60PixmapData *srcData = static_cast<QS60PixmapData *>(pm.pixmapData());
     113        srcData->beginDataAccess();
     114        QRasterPaintEngine::drawTiledPixmap(r, pm, sr);
     115        srcData->endDataAccess();
     116    } else {
     117        QRasterPaintEngine::drawTiledPixmap(r, pm, sr);
     118    }
    100119}
    101120
  • trunk/src/gui/painting/qpaintengine_s60_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qpaintengine_x11.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8080#endif
    8181
     82#include <private/qstylehelper_p.h>
     83
    8284QT_BEGIN_NAMESPACE
    8385
     
    225227{
    226228    QPixmap pm;
    227     QString key = QLatin1String("$qt-alpha-brush$") + QString::number(alpha) + QString::number(screen);
     229    QString key = QLatin1Literal("$qt-alpha-brush$")
     230                  % HexString<uchar>(alpha)
     231                  % HexString<int>(screen);
     232
    228233    if (!QPixmapCache::find(key, pm)) {
    229234        // #### why not use a mono image here????
     
    316321    }
    317322    // none found, replace one
    318     int i = rand() % 16;
     323    int i = qrand() % 16;
    319324
    320325    if (X11->pattern_fills[i].screen != screen && X11->pattern_fills[i].picture) {
     
    14491454void QX11PaintEngine::drawEllipse(const QRect &rect)
    14501455{
     1456    if (rect.isEmpty()) {
     1457        drawRects(&rect, 1);
     1458        return;
     1459    }
     1460
    14511461    Q_D(QX11PaintEngine);
    14521462    QRect devclip(SHRT_MIN, SHRT_MIN, SHRT_MAX*2 - 1, SHRT_MAX*2 - 1);
     
    19071917
    19081918    QPixmap pixmap = qt_toX11Pixmap(px);
     1919    if(pixmap.isNull())
     1920        return;
    19091921
    19101922    if ((d->xinfo && d->xinfo->screen() != pixmap.x11Info().screen())
  • trunk/src/gui/painting/qpaintengine_x11_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qpaintengineex.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    150150
    151151struct StrokeHandler {
     152    StrokeHandler(int reserve) : pts(reserve), types(reserve) {}
    152153    QDataBuffer<qreal> pts;
    153154    QDataBuffer<QPainterPath::ElementType> types;
     
    395396
    396397    if (!d->strokeHandler) {
    397         d->strokeHandler = new StrokeHandler;
     398        d->strokeHandler = new StrokeHandler(path.elementCount()+4);
    398399        d->stroker.setMoveToHook(qpaintengineex_moveTo);
    399400        d->stroker.setLineToHook(qpaintengineex_lineTo);
     
    461462        // non-cosmetic pens will be transformed as part of fill
    462463        // later, so they are also covered here..
     464        d->activeStroker->setCurveThresholdFromTransform(state()->matrix);
    463465        d->activeStroker->begin(d->strokeHandler);
    464466        if (types) {
     
    493495            d->activeStroker->moveTo(points[0], points[1]);
    494496            points += 2;
    495             ++types;
    496497            while (points < lastPoint) {
    497498                d->activeStroker->lineTo(points[0], points[1]);
    498499                points += 2;
    499                 ++types;
    500500            }
    501501            if (path.hasImplicitClose())
     
    518518            d->activeStroker->strokePath(painterPath, d->strokeHandler, QTransform());
    519519        } else {
     520            d->activeStroker->setCurveThresholdFromTransform(QTransform());
    520521            d->activeStroker->begin(d->strokeHandler);
    521522            if (types) {
     
    559560                d->activeStroker->moveTo(p.x(), p.y());
    560561                points += 2;
    561                 ++types;
    562562                while (points < lastPoint) {
    563563                    QPointF p = ((QPointF *)points)[0] * state()->matrix;
    564564                    d->activeStroker->lineTo(p.x(), p.y());
    565565                    points += 2;
    566                     ++types;
    567566                }
    568567                if (path.hasImplicitClose())
     
    608607    qreal right = r.x() + r.width();
    609608    qreal bottom = r.y() + r.height();
    610     qreal pts[] = { r.x(), r.y(),
    611                     right, r.y(),
     609    qreal pts[] = { qreal(r.x()), qreal(r.y()),
     610                    right, qreal(r.y()),
    612611                    right, bottom,
    613                     r.x(), bottom,
    614                     r.x(), r.y() };
     612                    qreal(r.x()), bottom,
     613                    qreal(r.x()), qreal(r.y()) };
    615614    QVectorPath vp(pts, 5, 0, QVectorPath::RectangleHint);
    616615    clip(vp, op);
     
    712711        qreal right = r.x() + r.width();
    713712        qreal bottom = r.y() + r.height();
    714         qreal pts[] = { r.x(), r.y(),
    715                         right, r.y(),
     713        qreal pts[] = { qreal(r.x()), qreal(r.y()),
     714                        right, qreal(r.y()),
    716715                        right, bottom,
    717                         r.x(), bottom,
    718                         r.x(), r.y() };
     716                        qreal(r.x()), bottom,
     717                        qreal(r.x()), qreal(r.y()) };
    719718        QVectorPath vp(pts, 5, 0, QVectorPath::RectangleHint);
    720719        draw(vp);
     
    770769        x1, y2 - yRadius,
    771770        x1, y1 + yRadius,                   // LineTo
    772         x1, y1 + KAPPA * yRadius,           // CurveTo
     771        x1, y1 + (1 - KAPPA) * yRadius,           // CurveTo
    773772        x1 + (1 - KAPPA) * xRadius, y1,
    774773        x1 + xRadius, y1
     
    833832    int point_count = 0;
    834833    x.points[0] = qt_curves_for_arc(r, 0, -360, x.points + 1, &point_count);
    835     QVectorPath vp((qreal *) pts, 13, qpaintengineex_ellipse_types, QVectorPath::EllipseHint);
     834    QVectorPath vp((qreal *) pts, point_count, qpaintengineex_ellipse_types, QVectorPath::EllipseHint);
    836835    draw(vp);
    837836}
     
    894893                pts[++oset] = points[i].x();
    895894                pts[++oset] = points[i].y();
    896                 pts[++oset] = points[i].x() + 1/63;
     895                pts[++oset] = points[i].x() + 1/63.;
    897896                pts[++oset] = points[i].y();
    898897            }
     
    904903    } else {
    905904        for (int i=0; i<pointCount; ++i) {
    906             qreal pts[] = { points[i].x(), points[i].y(), points[i].x() +1/63., points[i].y() };
     905            qreal pts[] = { qreal(points[i].x()), qreal(points[i].y()),
     906                            qreal(points[i].x() +1/63.), qreal(points[i].y()) };
    907907            QVectorPath path(pts, 2, 0);
    908908            stroke(path, pen);
     
    971971}
    972972
    973 void QPaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints /*hints*/)
    974 {
     973void QPaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount,
     974                                         const QPixmap &pixmap, QPainter::PixmapFragmentHints /*hints*/)
     975{
     976    if (pixmap.isNull())
     977        return;
     978
    975979    qreal oldOpacity = state()->opacity;
    976980    QTransform oldTransform = state()->matrix;
    977981
    978     for (int i = 0; i < dataCount; ++i) {
     982    for (int i = 0; i < fragmentCount; ++i) {
    979983        QTransform transform = oldTransform;
    980         transform.translate(drawingData[i].point.x(), drawingData[i].point.y());
    981         transform.rotate(drawingData[i].rotation);
    982         state()->opacity = oldOpacity * drawingData[i].opacity;
     984        transform.translate(fragments[i].x, fragments[i].y);
     985        transform.rotate(fragments[i].rotation);
     986        state()->opacity = oldOpacity * fragments[i].opacity;
    983987        state()->matrix = transform;
    984988        opacityChanged();
    985989        transformChanged();
    986990
    987         qreal w = drawingData[i].scaleX * drawingData[i].source.width();
    988         qreal h = drawingData[i].scaleY * drawingData[i].source.height();
    989         drawPixmap(QRectF(-0.5 * w, -0.5 * h, w, h), pixmap, drawingData[i].source);
     991        qreal w = fragments[i].scaleX * fragments[i].width;
     992        qreal h = fragments[i].scaleY * fragments[i].height;
     993        QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
     994                          fragments[i].width, fragments[i].height);
     995        drawPixmap(QRectF(-0.5 * w, -0.5 * h, w, h), pixmap, sourceRect);
    990996    }
    991997
  • trunk/src/gui/painting/qpaintengineex_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7171class QPainterState;
    7272class QPaintEngineExPrivate;
     73class QStaticTextItem;
    7374struct StrokeHandler;
    7475
     
    197198    virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s);
    198199
    199     virtual void drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QFlags<QDrawPixmaps::DrawingHint> hints);
     200    virtual void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap,
     201                                     QFlags<QPainter::PixmapFragmentHint> hints);
    200202
    201203    virtual void updateState(const QPaintEngineState &state);
     204
     205    virtual void drawStaticTextItem(QStaticTextItem *) = 0;
    202206
    203207    virtual void setState(QPainterState *s);
  • trunk/src/gui/painting/qpainter.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    3939**
    4040****************************************************************************/
     41
    4142// QtCore
    4243#include <qdebug.h>
     
    7071#include <private/qpaintengine_raster_p.h>
    7172#include <private/qmath_p.h>
     73#include <qstatictext.h>
     74#include <private/qstatictext_p.h>
     75#include <private/qstylehelper_p.h>
    7276
    7377QT_BEGIN_NAMESPACE
     
    8791                    int tabstops, int* tabarray, int tabarraylen,
    8892                    QPainter *painter);
     93static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
     94                                   QTextCharFormat::UnderlineStyle underlineStyle,
     95                                   const QTextItem::RenderFlags flags, qreal width,
     96                                   const QTextCharFormat &charFormat);
     97// Helper function to calculate left most position, width and flags for decoration drawing
     98static void drawDecorationForGlyphs(QPainter *painter, const glyph_t *glyphArray,
     99                                    const QFixedPoint *positions, int glyphCount,
     100                                    QFontEngine *fontEngine, const QFont &font,
     101                                    const QTextCharFormat &charFormat);
    89102
    90103static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush)
     
    684697        skip = false;
    685698
    686         QBrush penBrush = s->pen.brush();
    687         Qt::BrushStyle brushStyle = s->brush.style();
    688         Qt::BrushStyle penBrushStyle = penBrush.style();
     699        QBrush penBrush = (qpen_style(s->pen) == Qt::NoPen) ? QBrush(Qt::NoBrush) : qpen_brush(s->pen);
     700        Qt::BrushStyle brushStyle = qbrush_style(s->brush);
     701        Qt::BrushStyle penBrushStyle = qbrush_style(penBrush);
    689702        alpha = (penBrushStyle != Qt::NoBrush
    690703                 && (penBrushStyle < Qt::LinearGradientPattern && penBrush.color().alpha() != 255)
     
    968981    device on which the painter paints, and paintEngine() returns the
    969982    paint engine that the painter is currently operating on. For more
    970     information, see \l {The Paint System} documentation.
     983    information, see the \l {Paint System}.
    971984
    972985    Sometimes it is desirable to make someone else paint on an unusual
     
    10131026    \o viewport(), window(), worldTransform() make up the painter's coordinate
    10141027        transformation system. For more information, see the \l
    1015         {Coordinate Transformations} section and the \l {The Coordinate
     1028        {Coordinate Transformations} section and the \l {Coordinate
    10161029        System} documentation.
    10171030
     
    12201233    worldTransform(). A matrix transforms a point in the plane to another
    12211234    point. For more information about the transformation matrix, see
    1222     the \l {The Coordinate System} and QTransform documentation.
     1235    the \l {Coordinate System} and QTransform documentation.
    12231236
    12241237    The setWorldTransform() function can replace or add to the currently
     
    12421255    transformation matrix.
    12431256
    1244     See also \l {The Coordinate System} documentation.
     1257    See also \l {Coordinate System}
    12451258
    12461259    \section1 Clipping
     
    15611574        d->engine->setDirty(QPaintEngine::DirtyFont);
    15621575    }
    1563     d->state->layoutDirection = widget->layoutDirection();
    15641576}
    15651577
     
    18711883        initFrom(widget);
    18721884    } else {
    1873         d->state->layoutDirection = QApplication::layoutDirection();
     1885        d->state->layoutDirection = Qt::LayoutDirectionAuto;
    18741886        // make sure we have a font compatible with the paintdevice
    18751887        d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
     
    23892401        return;
    23902402    }
     2403    if (d->state->composition_mode == mode)
     2404        return;
    23912405    if (d->extended) {
    23922406        d->state->composition_mode = mode;
     
    27042718
    27052719    if (d->extended) {
    2706         if (!hasClipping() && (op == Qt::IntersectClip || op == Qt::UniteClip))
     2720        if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
    27072721            op = Qt::ReplaceClip;
    27082722
     
    27622776    }
    27632777
    2764     if (!hasClipping() && (op == Qt::IntersectClip || op == Qt::UniteClip))
     2778    if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
    27652779        op = Qt::ReplaceClip;
    27662780
     
    28172831    }
    28182832
    2819     if (!hasClipping() && (op == Qt::IntersectClip || op == Qt::UniteClip))
     2833    if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
    28202834        op = Qt::ReplaceClip;
    28212835
     
    28782892
    28792893    For more information about the coordinate system, transformations
    2880     and window-viewport conversion, see \l {The Coordinate System}
    2881     documentation.
     2894    and window-viewport conversion, see \l {Coordinate System}.
    28822895
    28832896    \sa setWorldTransform(), QTransform
     
    28992912
    29002913    \sa {QPainter#Coordinate Transformations}{Coordinate Transformations},
    2901     {The Coordinate System}
     2914    {Coordinate System}
    29022915*/
    29032916
     
    30423055    false.
    30433056
    3044     \sa setWorldMatrixEnabled(), worldTransform(), {The Coordinate System}
     3057    \sa setWorldMatrixEnabled(), worldTransform(), {Coordinate System}
    30453058*/
    30463059
     
    32233236    }
    32243237
    3225     if (!hasClipping() && (op == Qt::IntersectClip || op == Qt::UniteClip))
     3238    if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
    32263239        op = Qt::ReplaceClip;
    32273240
     
    33843397    \endtable
    33853398
    3386     \sa drawLines(), drawPolyline(), {The Coordinate System}
     3399    \sa drawLines(), drawPolyline(), {Coordinate System}
    33873400*/
    33883401
     
    34313444    \endtable
    34323445
    3433     \sa drawRects(), drawPolygon(), {The Coordinate System}
     3446    \sa drawRects(), drawPolygon(), {Coordinate System}
    34343447*/
    34353448
     
    35953608    pen's color.
    35963609
    3597     \sa {The Coordinate System}
     3610    \sa {Coordinate System}
    35983611*/
    35993612
     
    36173630    the current pen's color.
    36183631
    3619     \sa {The Coordinate System}
     3632    \sa {Coordinate System}
    36203633*/
    36213634void QPainter::drawPoints(const QPointF *points, int pointCount)
     
    42234236    \endtable
    42244237
    4225     \sa drawPie(), {The Coordinate System}
     4238    \sa drawPie(), {Coordinate System}
    42264239*/
    42274240void QPainter::drawEllipse(const QRectF &r)
     
    42374250
    42384251    QRectF rect(r.normalized());
    4239     if (rect.isEmpty())
    4240         return;
    42414252
    42424253    if (d->extended) {
     
    42804291
    42814292    QRect rect(r.normalized());
    4282     if (rect.isEmpty())
    4283         return;
    42844293
    42854294    if (d->extended) {
     
    43534362    \endtable
    43544363
    4355     \sa drawPie(), drawChord(), {The Coordinate System}
     4364    \sa drawPie(), drawChord(), {Coordinate System}
    43564365*/
    43574366
     
    44174426    \endtable
    44184427
    4419     \sa drawEllipse(), drawChord(), {The Coordinate System}
     4428    \sa drawEllipse(), drawChord(), {Coordinate System}
    44204429*/
    44214430void QPainter::drawPie(const QRectF &r, int a, int alen)
     
    44864495    \endtable
    44874496
    4488     \sa drawArc(), drawPie(), {The Coordinate System}
     4497    \sa drawArc(), drawPie(), {Coordinate System}
    44894498*/
    44904499void QPainter::drawChord(const QRectF &r, int a, int alen)
     
    47774786    \endtable
    47784787
    4779     \sa drawLines(), drawPolygon(), {The Coordinate System}
     4788    \sa drawLines(), drawPolygon(), {Coordinate System}
    47804789*/
    47814790void QPainter::drawPolyline(const QPointF *points, int pointCount)
     
    49164925    rules.
    49174926
    4918     \sa  drawConvexPolygon(), drawPolyline(), {The Coordinate System}
     4927    \sa  drawConvexPolygon(), drawPolyline(), {Coordinate System}
    49194928*/
    49204929void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
     
    50675076    be faster than the drawPolygon() function.
    50685077
    5069     \sa drawPolygon(), drawPolyline(), {The Coordinate System}
     5078    \sa drawPolygon(), drawPolyline(), {Coordinate System}
    50705079*/
    50715080
     
    54125421        setBackgroundMode(Qt::TransparentMode);
    54135422        setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
    5414         QBrush brush(d->state->pen.color(), pm);
     5423        QBrush brush;
     5424
     5425        if (sw == pm.width() && sh == pm.height())
     5426            brush = QBrush(d->state->pen.color(), pm);
     5427        else
     5428            brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh));
     5429
    54155430        setBrush(brush);
    54165431        setPen(Qt::NoPen);
    5417         setBrushOrigin(QPointF(-sx, -sy));
    54185432
    54195433        drawRect(QRectF(0, 0, sw, sh));
     
    56985712}
    56995713
     5714
     5715void qt_draw_glyphs(QPainter *painter, const quint32 *glyphArray, const QPointF *positionArray,
     5716                    int glyphCount)
     5717{
     5718    QPainterPrivate *painter_d = QPainterPrivate::get(painter);
     5719    painter_d->drawGlyphs(glyphArray, positionArray, glyphCount);
     5720}
     5721
     5722void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *positionArray,
     5723                                 int glyphCount)
     5724{
     5725    updateState(state);
     5726
     5727    QFontEngine *fontEngine = state->font.d->engineForScript(QUnicodeTables::Common);
     5728
     5729    while (fontEngine->type() == QFontEngine::Multi) {
     5730        // Pick engine based on first glyph in array if we are using a multi engine.
     5731        // (all glyphs must be for same font)
     5732        int engineIdx = 0;
     5733        if (glyphCount > 0)
     5734            engineIdx = glyphArray[0] >> 24;
     5735
     5736        fontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx);
     5737    }
     5738
     5739    QVarLengthArray<QFixedPoint, 128> positions;
     5740    for (int i=0; i<glyphCount; ++i) {
     5741        QFixedPoint fp = QFixedPoint::fromPointF(positionArray[i]);
     5742        positions.append(fp);
     5743    }
     5744
     5745    if (extended != 0) {
     5746        QStaticTextItem staticTextItem;
     5747        staticTextItem.color = state->pen.color();
     5748        staticTextItem.font = state->font;
     5749        staticTextItem.setFontEngine(fontEngine);
     5750        staticTextItem.numGlyphs = glyphCount;
     5751        staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
     5752        staticTextItem.glyphPositions = positions.data();
     5753
     5754        extended->drawStaticTextItem(&staticTextItem);
     5755    } else {
     5756        QTextItemInt textItem;
     5757        textItem.f = &state->font;
     5758        textItem.fontEngine = fontEngine;
     5759
     5760        QVarLengthArray<QFixed, 128> advances(glyphCount);
     5761        QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
     5762        QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
     5763        qMemSet(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
     5764        qMemSet(advances.data(), 0, advances.size() * sizeof(QFixed));
     5765        qMemSet(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
     5766
     5767        textItem.glyphs.numGlyphs = glyphCount;
     5768        textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
     5769        textItem.glyphs.offsets = positions.data();
     5770        textItem.glyphs.advances_x = advances.data();
     5771        textItem.glyphs.advances_y = advances.data();
     5772        textItem.glyphs.justifications = glyphJustifications.data();
     5773        textItem.glyphs.attributes = glyphAttributes.data();
     5774
     5775        engine->drawTextItem(QPointF(0, 0), textItem);
     5776    }
     5777}
     5778
     5779/*!
     5780
     5781    \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText)
     5782    \since 4.7
     5783    \overload
     5784
     5785    Draws the \a staticText at the \a topLeftPosition.
     5786
     5787    \note The y-position is used as the top of the font.
     5788
     5789*/
     5790
     5791/*!
     5792    \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText)
     5793    \since 4.7
     5794    \overload
     5795
     5796    Draws the \a staticText at coordinates \a left and \a top.
     5797
     5798    \note The y-position is used as the top of the font.
     5799*/
     5800
    57005801/*!
    57015802    \fn void QPainter::drawText(const QPointF &position, const QString &text)
     
    57215822
    57225823/*!
     5824    \since 4.7
     5825
     5826    Draws the given \a staticText at the given \a topLeftPosition.
     5827
     5828    The text will be drawn using the font and the transformation set on the painter. If the
     5829    font and/or transformation set on the painter are different from the ones used to initialize
     5830    the layout of the QStaticText, then the layout will have to be recalculated. Use
     5831    QStaticText::prepare() to initialize \a staticText with the font and transformation with which
     5832    it will later be drawn.
     5833
     5834    If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was
     5835    last drawn, then there will be a slight overhead when translating the text to its new position.
     5836
     5837    \note If the painter's transformation is not affine, then \a staticText will be drawn using
     5838    regular calls to drawText(), losing any potential for performance improvement.
     5839
     5840    \note The y-position is used as the top of the font.
     5841
     5842    \sa QStaticText
     5843*/
     5844void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
     5845{
     5846    Q_D(QPainter);
     5847    if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen)
     5848        return;
     5849
     5850    QStaticTextPrivate *staticText_d =
     5851            const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
     5852
     5853    if (font() != staticText_d->font) {
     5854        staticText_d->font = font();
     5855        staticText_d->needsRelayout = true;
     5856    }
     5857
     5858    // If we don't have an extended paint engine, or if the painter is projected,
     5859    // we go through standard code path
     5860    if (d->extended == 0 || !d->state->matrix.isAffine()) {
     5861        staticText_d->paintText(topLeftPosition, this);
     5862        return;
     5863    }
     5864
     5865    bool paintEngineSupportsTransformations = d->extended->type() == QPaintEngine::OpenGL2
     5866                                           || d->extended->type() == QPaintEngine::OpenVG
     5867                                           || d->extended->type() == QPaintEngine::OpenGL;
     5868
     5869    if (paintEngineSupportsTransformations && !staticText_d->untransformedCoordinates) {
     5870        staticText_d->untransformedCoordinates = true;
     5871        staticText_d->needsRelayout = true;
     5872    } else if (!paintEngineSupportsTransformations && staticText_d->untransformedCoordinates) {
     5873        staticText_d->untransformedCoordinates = false;
     5874        staticText_d->needsRelayout = true;
     5875    }
     5876
     5877    // Don't recalculate entire layout because of translation, rather add the dx and dy
     5878    // into the position to move each text item the correct distance.
     5879    QPointF transformedPosition = topLeftPosition;
     5880    if (!staticText_d->untransformedCoordinates)
     5881        transformedPosition = transformedPosition * d->state->matrix;
     5882    QTransform oldMatrix;
     5883
     5884    // The translation has been applied to transformedPosition. Remove translation
     5885    // component from matrix.
     5886    if (d->state->matrix.isTranslating() && !staticText_d->untransformedCoordinates) {
     5887        qreal m11 = d->state->matrix.m11();
     5888        qreal m12 = d->state->matrix.m12();
     5889        qreal m13 = d->state->matrix.m13();
     5890        qreal m21 = d->state->matrix.m21();
     5891        qreal m22 = d->state->matrix.m22();
     5892        qreal m23 = d->state->matrix.m23();
     5893        qreal m33 = d->state->matrix.m33();
     5894
     5895        oldMatrix = d->state->matrix;
     5896        d->state->matrix.setMatrix(m11, m12, m13,
     5897                                   m21, m22, m23,
     5898                                   0.0, 0.0, m33);
     5899    }
     5900
     5901    // If the transform is not identical to the text transform,
     5902    // we have to relayout the text (for other transformations than plain translation)
     5903    bool staticTextNeedsReinit = staticText_d->needsRelayout;
     5904    if (!staticText_d->untransformedCoordinates && staticText_d->matrix != d->state->matrix) {
     5905        staticText_d->matrix = d->state->matrix;
     5906        staticTextNeedsReinit = true;
     5907    }
     5908
     5909    // Recreate the layout of the static text because the matrix or font has changed
     5910    if (staticTextNeedsReinit)
     5911        staticText_d->init();
     5912
     5913    if (transformedPosition != staticText_d->position) { // Translate to actual position
     5914        QFixed fx = QFixed::fromReal(transformedPosition.x());
     5915        QFixed fy = QFixed::fromReal(transformedPosition.y());
     5916        QFixed oldX = QFixed::fromReal(staticText_d->position.x());
     5917        QFixed oldY = QFixed::fromReal(staticText_d->position.y());
     5918        for (int item=0; item<staticText_d->itemCount;++item) {
     5919            QStaticTextItem *textItem = staticText_d->items + item;
     5920            for (int i=0; i<textItem->numGlyphs; ++i) {
     5921                textItem->glyphPositions[i].x += fx - oldX;
     5922                textItem->glyphPositions[i].y += fy - oldY;
     5923            }
     5924            textItem->userDataNeedsUpdate = true;
     5925        }
     5926
     5927        staticText_d->position = transformedPosition;
     5928    }
     5929
     5930    QPen oldPen = d->state->pen;
     5931    QColor currentColor = oldPen.color();
     5932    for (int i=0; i<staticText_d->itemCount; ++i) {
     5933        QStaticTextItem *item = staticText_d->items + i;
     5934        if (item->color.isValid() && currentColor != item->color) {
     5935            setPen(item->color);
     5936            currentColor = item->color;
     5937        }
     5938        d->extended->drawStaticTextItem(item);
     5939
     5940        drawDecorationForGlyphs(this, item->glyphs, item->glyphPositions,
     5941                                item->numGlyphs, item->fontEngine(), staticText_d->font,
     5942                                QTextCharFormat());
     5943    }
     5944    if (currentColor != oldPen.color())
     5945        setPen(oldPen);
     5946
     5947    if (!staticText_d->untransformedCoordinates && oldMatrix.isTranslating())
     5948        d->state->matrix = oldMatrix;
     5949}
     5950
     5951/*!
    57235952   \internal
    57245953*/
     
    57345963    if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen)
    57355964        return;
     5965
     5966    if (tf & Qt::TextBypassShaping) {
     5967        // Skip harfbuzz complex shaping, shape using glyph advances only
     5968        int len = str.length();
     5969        int numGlyphs = len;
     5970        QVarLengthGlyphLayoutArray glyphs(len);
     5971        QFontEngine *fontEngine = d->state->font.d->engineForScript(QUnicodeTables::Common);
     5972        if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
     5973            glyphs.resize(numGlyphs);
     5974            if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
     5975                Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
     5976        }
     5977
     5978        QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
     5979        drawTextItem(p, gf);
     5980        return;
     5981    }
    57365982
    57375983    QStackTextEngine engine(str, d->state->font);
     
    59406186    By default, QPainter draws text anti-aliased.
    59416187
    5942     \note The y-position is used as the baseline of the font.
     6188    \note The y-position is used as the top of the font.
    59436189
    59446190    \sa Qt::AlignmentFlag, Qt::TextFlag
     
    60156261    const qreal radiusBase = qMax(qreal(1), maxRadius);
    60166262
    6017     QString key = QLatin1String("WaveUnderline-");
    6018     key += pen.color().name();
    6019     key += QLatin1Char('-');
    6020     key += QString::number(radiusBase);
     6263    QString key = QLatin1Literal("WaveUnderline-")
     6264                  % pen.color().name()
     6265                  % HexString<qreal>(radiusBase);
    60216266
    60226267    QPixmap pixmap;
     
    60636308}
    60646309
    6065 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QTextItemInt &ti)
    6066 {
    6067     QTextCharFormat::UnderlineStyle underlineStyle = ti.underlineStyle;
     6310static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
     6311                                   QTextCharFormat::UnderlineStyle underlineStyle,
     6312                                   const QTextItem::RenderFlags flags, qreal width,
     6313                                   const QTextCharFormat &charFormat)
     6314{
    60686315    if (underlineStyle == QTextCharFormat::NoUnderline
    6069         && !(ti.flags & (QTextItem::StrikeOut | QTextItem::Overline)))
    6070         return;
    6071 
    6072     QFontEngine *fe = ti.fontEngine;
     6316        && !(flags & (QTextItem::StrikeOut | QTextItem::Overline)))
     6317        return;
    60736318
    60746319    const QPen oldPen = painter->pen();
     
    60806325    pen.setCapStyle(Qt::FlatCap);
    60816326
    6082     QLineF line(pos.x(), pos.y(), pos.x() + ti.width.toReal(), pos.y());
     6327    QLineF line(pos.x(), pos.y(), pos.x() + width, pos.y());
    60836328
    60846329    const qreal underlineOffset = fe->underlinePosition().toReal();
     
    60956340        painter->translate(0, pos.y() + 1);
    60966341
    6097         QColor uc = ti.charFormat.underlineColor();
     6342        QColor uc = charFormat.underlineColor();
    60986343        if (uc.isValid())
    60996344            pen.setColor(uc);
     
    61016346        // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms
    61026347        const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen);
    6103         const int descent = (int) ti.descent.toReal();
     6348        const int descent = (int) fe->descent().toReal();
    61046349
    61056350        painter->setBrushOrigin(painter->brushOrigin().x(), 0);
    6106         painter->fillRect(pos.x(), 0, qCeil(ti.width.toReal()), qMin(wave.height(), descent), wave);
     6351        painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
    61076352        painter->restore();
    61086353    } else if (underlineStyle != QTextCharFormat::NoUnderline) {
    61096354        QLineF underLine(line.x1(), underlinePos, line.x2(), underlinePos);
    61106355
    6111         QColor uc = ti.charFormat.underlineColor();
     6356        QColor uc = charFormat.underlineColor();
    61126357        if (uc.isValid())
    61136358            pen.setColor(uc);
     
    61216366    pen.setColor(oldPen.color());
    61226367
    6123     if (ti.flags & QTextItem::StrikeOut) {
     6368    if (flags & QTextItem::StrikeOut) {
    61246369        QLineF strikeOutLine = line;
    61256370        strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
     
    61286373    }
    61296374
    6130     if (ti.flags & QTextItem::Overline) {
     6375    if (flags & QTextItem::Overline) {
    61316376        QLineF overLine = line;
    61326377        overLine.translate(0., - fe->ascent().toReal());
     
    61376382    painter->setPen(oldPen);
    61386383    painter->setBrush(oldBrush);
     6384}
     6385
     6386static void drawDecorationForGlyphs(QPainter *painter, const glyph_t *glyphArray,
     6387                                    const QFixedPoint *positions, int glyphCount,
     6388                                    QFontEngine *fontEngine, const QFont &font,
     6389                                    const QTextCharFormat &charFormat)
     6390{
     6391    if (!(font.underline() || font.strikeOut() || font.overline()))
     6392        return;
     6393
     6394    QFixed leftMost;
     6395    QFixed rightMost;
     6396    QFixed baseLine;
     6397    for (int i=0; i<glyphCount; ++i) {
     6398        glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
     6399        if (i == 0 || leftMost > positions[i].x)
     6400            leftMost = positions[i].x;
     6401
     6402        // We don't support glyphs that do not share a common baseline. If this turns out to
     6403        // be a relevant use case, then we need to find clusters of glyphs that share a baseline
     6404        // and do a drawTextItemDecorations call per cluster.
     6405        if (i == 0 || baseLine < positions[i].y)
     6406            baseLine = positions[i].y;
     6407
     6408        // We use the advance rather than the actual bounds to match the algorithm in drawText()
     6409        if (i == 0 || rightMost < positions[i].x + gm.xoff)
     6410            rightMost = positions[i].x + gm.xoff;
     6411    }
     6412
     6413    QFixed width = rightMost - leftMost;
     6414    QTextItem::RenderFlags flags = 0;
     6415
     6416    if (font.underline())
     6417        flags |= QTextItem::Underline;
     6418    if (font.overline())
     6419        flags |= QTextItem::Overline;
     6420    if (font.strikeOut())
     6421        flags |= QTextItem::StrikeOut;
     6422
     6423    drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()),
     6424                           fontEngine,
     6425                           font.underline() ? QTextCharFormat::SingleUnderline
     6426                                            : QTextCharFormat::NoUnderline, flags,
     6427                           width.toReal(), charFormat);
    61396428}
    61406429
     
    62696558            d->engine->drawTextItem(p, ti);
    62706559    }
    6271     drawTextItemDecoration(this, p, ti);
     6560    drawTextItemDecoration(this, p, ti.fontEngine, ti.underlineStyle, ti.flags, ti.width.toReal(),
     6561                           ti.charFormat);
    62726562
    62736563    if (d->state->renderHints != oldRenderHints) {
     
    69097199    rectangle.
    69107200
    6911     \sa window(), viewTransformEnabled(), {The Coordinate
     7201    \sa window(), viewTransformEnabled(), {Coordinate
    69127202    System#Window-Viewport Conversion}{Window-Viewport Conversion}
    69137203*/
     
    69737263    rectangle.
    69747264
    6975     \sa viewport(), viewTransformEnabled() {The Coordinate
     7265    \sa viewport(), viewTransformEnabled() {Coordinate
    69767266    System#Window-Viewport Conversion}{Window-Viewport Conversion}
    69777267*/
     
    70577347    view transformations if \a enable is false.
    70587348
    7059     \sa viewTransformEnabled(), {The Coordinate System#Window-Viewport
     7349    \sa viewTransformEnabled(), {Coordinate System#Window-Viewport
    70607350    Conversion}{Window-Viewport Conversion}
    70617351*/
     
    78078097            QTextLine line = textLayout.lineAt(i);
    78088098
    7809             qreal advance = textLayout.engine()->lines[i].textAdvance.toReal();
     8099            qreal advance = line.horizontalAdvance();
    78108100            if (tf & Qt::AlignRight)
    78118101                xoff = r.width() - advance;
     
    78268116    to the specified \a direction.
    78278117
    7828     \sa layoutDirection(), drawText(), {QPainter#Settings}{Settings}
     8118    The default is Qt::LayoutDirectionAuto, which will implicitly determine the
     8119    direction from the text drawn.
     8120
     8121    \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings}
    78298122*/
    78308123void QPainter::setLayoutDirection(Qt::LayoutDirection direction)
     
    78388131    Returns the layout direction used by the painter when drawing text.
    78398132
    7840     \sa setLayoutDirection(), drawText(), {QPainter#Settings}{Settings}
     8133    \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings}
    78418134*/
    78428135Qt::LayoutDirection QPainter::layoutDirection() const
    78438136{
    78448137    Q_D(const QPainter);
    7845     return d->state ? d->state->layoutDirection : Qt::LeftToRight;
     8138    return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto;
    78468139}
    78478140
     
    85068799
    85078800/*!
    8508     Returns wether clipping is enabled or not in the current paint
     8801    Returns whether clipping is enabled or not in the current paint
    85098802    engine state.
    85108803
     
    87169009}
    87179010
     9011/*!
     9012    \since 4.7
     9013
     9014    This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap,
     9015    at multiple positions with different scale, rotation and opacity. \a
     9016    fragments is an array of \a fragmentCount elements specifying the
     9017    parameters used to draw each pixmap fragment. The \a hints
     9018    parameter can be used to pass in drawing hints.
     9019
     9020    This function is potentially faster than multiple calls to drawPixmap(),
     9021    since the backend can optimize state changes.
     9022
     9023    \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint
     9024*/
     9025
     9026void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
     9027                                   const QPixmap &pixmap, PixmapFragmentHints hints)
     9028{
     9029    Q_D(QPainter);
     9030
     9031    if (!d->engine || pixmap.isNull())
     9032        return;
     9033
     9034#ifndef QT_NO_DEBUG
     9035    for (int i = 0; i < fragmentCount; ++i) {
     9036        QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
     9037                          fragments[i].width, fragments[i].height);
     9038        if (!(QRectF(pixmap.rect()).contains(sourceRect)))
     9039            qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle");
     9040    }
     9041#endif
     9042
     9043    if (d->engine->isExtended()) {
     9044        d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
     9045    } else {
     9046        qreal oldOpacity = opacity();
     9047        QTransform oldTransform = transform();
     9048
     9049        for (int i = 0; i < fragmentCount; ++i) {
     9050            QTransform transform = oldTransform;
     9051            qreal xOffset = 0;
     9052            qreal yOffset = 0;
     9053            if (fragments[i].rotation == 0) {
     9054                xOffset = fragments[i].x;
     9055                yOffset = fragments[i].y;
     9056            } else {
     9057                transform.translate(fragments[i].x, fragments[i].y);
     9058                transform.rotate(fragments[i].rotation);
     9059            }
     9060            setOpacity(oldOpacity * fragments[i].opacity);
     9061            setTransform(transform);
     9062
     9063            qreal w = fragments[i].scaleX * fragments[i].width;
     9064            qreal h = fragments[i].scaleY * fragments[i].height;
     9065            QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
     9066                              fragments[i].width, fragments[i].height);
     9067            drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, sourceRect);
     9068        }
     9069
     9070        setOpacity(oldOpacity);
     9071        setTransform(oldTransform);
     9072    }
     9073}
     9074
     9075/*!
     9076    \since 4.7
     9077    \class QPainter::PixmapFragment
     9078
     9079    \brief This class is used in conjunction with the
     9080    QPainter::drawPixmapFragments() function to specify how a pixmap, or
     9081    sub-rect of a pixmap, is drawn.
     9082
     9083    The \a sourceLeft, \a sourceTop, \a width and \a height variables are used
     9084    as a source rectangle within the pixmap passed into the
     9085    QPainter::drawPixmapFragments() function. The variables \a x, \a y, \a
     9086    width and \a height are used to calculate the target rectangle that is
     9087    drawn. \a x and \a y denotes the center of the target rectangle. The \a
     9088    width and \a height in the target rectangle is scaled by the \a scaleX and
     9089    \a scaleY values. The resulting target rectangle is then rotated \a
     9090    rotation degrees around the \a x, \a y center point.
     9091
     9092    \sa QPainter::drawPixmapFragments()
     9093*/
     9094
     9095/*!
     9096    \since 4.7
     9097
     9098    This is a convenience function that returns a QPainter::PixmapFragment that is
     9099    initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a
     9100    rotation, \a opacity parameters.
     9101*/
     9102
     9103QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect,
     9104                                              qreal scaleX, qreal scaleY, qreal rotation,
     9105                                              qreal opacity)
     9106{
     9107    PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
     9108                               sourceRect.height(), scaleX, scaleY, rotation, opacity};
     9109    return fragment;
     9110}
     9111
     9112/*!
     9113    \variable QPainter::PixmapFragment::x
     9114    \brief the x coordinate of center point in the target rectangle.
     9115*/
     9116
     9117/*!
     9118    \variable QPainter::PixmapFragment::y
     9119    \brief the y coordinate of the center point in the target rectangle.
     9120*/
     9121
     9122/*!
     9123    \variable QPainter::PixmapFragment::sourceLeft
     9124    \brief the left coordinate of the source rectangle.
     9125*/
     9126
     9127/*!
     9128    \variable QPainter::PixmapFragment::sourceTop
     9129    \brief the top coordinate of the source rectangle.
     9130*/
     9131
     9132/*!
     9133    \variable QPainter::PixmapFragment::width
     9134
     9135    \brief the width of the source rectangle and is used to calculate the width
     9136    of the target rectangle.
     9137*/
     9138
     9139/*!
     9140    \variable QPainter::PixmapFragment::height
     9141
     9142    \brief the height of the source rectangle and is used to calculate the
     9143    height of the target rectangle.
     9144*/
     9145
     9146/*!
     9147    \variable QPainter::PixmapFragment::scaleX
     9148    \brief the horizontal scale of the target rectangle.
     9149*/
     9150
     9151/*!
     9152    \variable QPainter::PixmapFragment::scaleY
     9153    \brief the vertical scale of the target rectangle.
     9154*/
     9155
     9156/*!
     9157    \variable QPainter::PixmapFragment::rotation
     9158
     9159    \brief the rotation of the target rectangle in degrees. The target
     9160    rectangle is rotated after it has been scaled.
     9161*/
     9162
     9163/*!
     9164    \variable QPainter::PixmapFragment::opacity
     9165
     9166    \brief the opacity of the target rectangle, where 0.0 is fully transparent
     9167    and 1.0 is fully opaque.
     9168*/
     9169
     9170/*!
     9171    \since 4.7
     9172
     9173    \enum QPainter::PixmapFragmentHint
     9174
     9175    \value OpaqueHint Indicates that the pixmap fragments to be drawn are
     9176    opaque. Opaque fragments are potentially faster to draw.
     9177
     9178    \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment
     9179*/
     9180
    87189181void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
    87199182{
  • trunk/src/gui/painting/qpainter.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7979class QMatrix;
    8080class QTransform;
     81class QStaticText;
    8182
    8283class QPainterPrivateDeleter;
     
    9899
    99100    Q_DECLARE_FLAGS(RenderHints, RenderHint)
     101
     102    class PixmapFragment {
     103    public:
     104        qreal x;
     105        qreal y;
     106        qreal sourceLeft;
     107        qreal sourceTop;
     108        qreal width;
     109        qreal height;
     110        qreal scaleX;
     111        qreal scaleY;
     112        qreal rotation;
     113        qreal opacity;
     114        static PixmapFragment Q_GUI_EXPORT create(const QPointF &pos, const QRectF &sourceRect,
     115                                            qreal scaleX = 1, qreal scaleY = 1,
     116                                            qreal rotation = 0, qreal opacity = 1);
     117    };
     118
     119    enum PixmapFragmentHint {
     120        OpaqueHint = 0x01
     121    };
     122
     123    Q_DECLARE_FLAGS(PixmapFragmentHints, PixmapFragmentHint)
    100124
    101125    QPainter();
     
    351375    inline void drawPixmap(const QRect &r, const QPixmap &pm);
    352376    inline void drawPixmap(int x, int y, int w, int h, const QPixmap &pm);
     377
     378    void drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
     379                             const QPixmap &pixmap, PixmapFragmentHints hints = 0);
    353380
    354381    void drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
     
    369396    void setLayoutDirection(Qt::LayoutDirection direction);
    370397    Qt::LayoutDirection layoutDirection() const;
     398
     399    void drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText);
     400    inline void drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText);
     401    inline void drawStaticText(int left, int top, const QStaticText &staticText);
    371402
    372403    void drawText(const QPointF &p, const QString &s);
     
    897928}
    898929
     930inline void QPainter::drawStaticText(const QPoint &p, const QStaticText &staticText)
     931{
     932    drawStaticText(QPointF(p), staticText);
     933}
     934
     935inline void QPainter::drawStaticText(int x, int y, const QStaticText &staticText)
     936{
     937    drawStaticText(QPointF(x, y), staticText);
     938}
     939
    899940inline void QPainter::drawTextItem(const QPoint &p, const QTextItem &ti)
    900941{
  • trunk/src/gui/painting/qpainter_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    229229    void drawStretchedGradient(const QPainterPath &path, DrawOperation operation);
    230230    void drawOpaqueBackground(const QPainterPath &path, DrawOperation operation);
     231    void drawGlyphs(const quint32 *glyphArray, const QPointF *positionArray, int glyphCount);
    231232
    232233    void updateMatrix();
     
    238239
    239240    void checkEmulation();
     241
     242    static QPainterPrivate *get(QPainter *painter)
     243    {
     244        return painter->d_ptr.data();
     245    }
    240246
    241247    QTransform viewTransform() const;
     
    253259
    254260Q_GUI_EXPORT void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation);
     261Q_GUI_EXPORT void qt_draw_glyphs(QPainter *painter, const quint32 *glyphArray,
     262                                 const QPointF *positionArray, int glyphCount);
    255263
    256264QString qt_generate_brush_key(const QBrush &brush);
  • trunk/src/gui/painting/qpainterpath.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    11971197    d->elements += other.d_func()->elements;
    11981198
    1199     d->elements[first].type = LineToElement;
     1199    if (first != 0)
     1200        d->elements[first].type = LineToElement;
    12001201
    12011202    // avoid duplicate points
     
    12581259{
    12591260    ensureData();
     1261    if (d_func()->fillRule == fillRule)
     1262        return;
    12601263    detach();
    12611264
     
    19131916        case QPainterPath::MoveToElement:
    19141917            if (i > 0
    1915                 && qFuzzyCompare(last_pt.x(), last_start.y())
     1918                && qFuzzyCompare(last_pt.x(), last_start.x())
    19161919                && qFuzzyCompare(last_pt.y(), last_start.y())
    19171920                && qt_painterpath_isect_line_rect(last_pt.x(), last_pt.y(),
     
    23062309    returns a reference to the \a stream.
    23072310
    2308     \sa {Format of the QDataStream Operators}
     2311    \sa {Serializing Qt Data Types}
    23092312*/
    23102313QDataStream &operator<<(QDataStream &s, const QPainterPath &p)
     
    23332336    and returns a reference to the \a stream.
    23342337
    2335     \sa {Format of the QDataStream Operators}
     2338    \sa {Serializing Qt Data Types}
    23362339*/
    23372340QDataStream &operator>>(QDataStream &s, QPainterPath &p)
     
    31663169    Set operations on paths will treat the paths as areas. Non-closed
    31673170    paths will be treated as implicitly closed.
     3171    Bezier curves may be flattened to line segments due to numerical instability of
     3172    doing bezier curve intersections.
    31683173
    31693174    \sa intersected(), subtracted()
     
    31813186
    31823187    Returns a path which is the intersection of this path's fill area and \a p's fill area.
     3188    Bezier curves may be flattened to line segments due to numerical instability of
     3189    doing bezier curve intersections.
    31833190*/
    31843191QPainterPath QPainterPath::intersected(const QPainterPath &p) const
     
    31973204    Set operations on paths will treat the paths as areas. Non-closed
    31983205    paths will be treated as implicitly closed.
    3199 
     3206    Bezier curves may be flattened to line segments due to numerical instability of
     3207    doing bezier curve intersections.
    32003208*/
    32013209QPainterPath QPainterPath::subtracted(const QPainterPath &p) const
     
    32263234    and returning a path containing no intersecting edges. Consecutive parallel lines will also
    32273235    be merged. The simplified path will always use the default fill rule, Qt::OddEvenFill.
     3236    Bezier curves may be flattened to line segments due to numerical instability of
     3237    doing bezier curve intersections.
    32283238*/
    32293239QPainterPath QPainterPath::simplified() const
  • trunk/src/gui/painting/qpainterpath.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    289289
    290290private:
     291    Q_DISABLE_COPY(QPainterPathStroker)
     292
    291293    friend class QX11PaintEngine;
    292294
  • trunk/src/gui/painting/qpainterpath_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qpathclipper.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4444#include <private/qbezier_p.h>
    4545#include <private/qdatabuffer_p.h>
     46#include <private/qnumeric_p.h>
    4647#include <qmath.h>
    4748
     
    8687}
    8788
    88 static QPointF normalize(const QPointF &p)
    89 {
    90     return p / qSqrt(p.x() * p.x() + p.y() * p.y());
     89static void normalize(double &x, double &y)
     90{
     91    double reciprocal = 1 / qSqrt(x * x + y * y);
     92    x *= reciprocal;
     93    y *= reciprocal;
    9194}
    9295
     
    106109
    107110private:
    108     void intersectBeziers(const QBezier &one, const QBezier &two, QVector<QPair<qreal, qreal> > &t, QDataBuffer<QIntersection> &intersections);
    109     void intersectLines(const QLineF &a, const QLineF &b, QDataBuffer<QIntersection> &intersections);
    110 
    111     bool beziersIntersect(const QBezier &one, const QBezier &two) const;
    112111    bool linesIntersect(const QLineF &a, const QLineF &b) const;
    113112};
    114 
    115 bool QIntersectionFinder::beziersIntersect(const QBezier &one, const QBezier &two) const
    116 {
    117     return (comparePoints(one.pt1(), two.pt1()) && comparePoints(one.pt2(), two.pt2())
    118             && comparePoints(one.pt3(), two.pt3()) && comparePoints(one.pt4(), two.pt4()))
    119            || (comparePoints(one.pt1(), two.pt4()) && comparePoints(one.pt2(), two.pt3())
    120                && comparePoints(one.pt3(), two.pt2()) && comparePoints(one.pt4(), two.pt1()))
    121            || QBezier::findIntersections(one, two, 0);
    122 }
    123113
    124114bool QIntersectionFinder::linesIntersect(const QLineF &a, const QLineF &b) const
     
    175165    }
    176166
    177     // if the lines are not parallel and share a common end point, then they
    178     // don't intersect
    179     if (p1_equals_q1 || p1_equals_q2 || p2_equals_q1 || p2_equals_q2)
    180         return false;
    181 
    182167    const qreal invPar = 1 / par;
    183168
     
    194179}
    195180
    196 void QIntersectionFinder::intersectBeziers(const QBezier &one, const QBezier &two, QVector<QPair<qreal, qreal> > &t, QDataBuffer<QIntersection> &intersections)
    197 {
    198     if ((comparePoints(one.pt1(), two.pt1()) && comparePoints(one.pt2(), two.pt2())
    199          && comparePoints(one.pt3(), two.pt3()) && comparePoints(one.pt4(), two.pt4()))
    200         || (comparePoints(one.pt1(), two.pt4()) && comparePoints(one.pt2(), two.pt3())
    201             && comparePoints(one.pt3(), two.pt2()) && comparePoints(one.pt4(), two.pt1()))) {
    202 
    203         return;
    204     }
    205 
    206     t.clear();
    207 
    208     if (!QBezier::findIntersections(one, two, &t))
    209         return;
    210 
    211     int count = t.size();
    212 
    213     for (int i = 0; i < count; ++i) {
    214         qreal alpha_p = t.at(i).first;
    215         qreal alpha_q = t.at(i).second;
    216 
    217         QPointF pt;
    218         if (qFuzzyIsNull(alpha_p)) {
    219             pt = one.pt1();
    220         } else if (qFuzzyIsNull(alpha_p - 1)) {
    221             pt = one.pt4();
    222         } else if (qFuzzyIsNull(alpha_q)) {
    223             pt = two.pt1();
    224         } else if (qFuzzyIsNull(alpha_q - 1)) {
    225             pt = two.pt4();
     181bool QIntersectionFinder::hasIntersections(const QPathSegments &a, const QPathSegments &b) const
     182{
     183    if (a.segments() == 0 || b.segments() == 0)
     184        return false;
     185
     186    const QRectF &rb0 = b.elementBounds(0);
     187
     188    qreal minX = rb0.left();
     189    qreal minY = rb0.top();
     190    qreal maxX = rb0.right();
     191    qreal maxY = rb0.bottom();
     192
     193    for (int i = 1; i < b.segments(); ++i) {
     194        const QRectF &r = b.elementBounds(i);
     195        minX = qMin(minX, r.left());
     196        minY = qMin(minY, r.top());
     197        maxX = qMax(maxX, r.right());
     198        maxY = qMax(maxY, r.bottom());
     199    }
     200
     201    QRectF rb(minX, minY, maxX - minX, maxY - minY);
     202
     203    for (int i = 0; i < a.segments(); ++i) {
     204        const QRectF &r1 = a.elementBounds(i);
     205
     206        if (r1.left() > rb.right() || rb.left() > r1.right())
     207            continue;
     208        if (r1.top() > rb.bottom() || rb.top() > r1.bottom())
     209            continue;
     210
     211        for (int j = 0; j < b.segments(); ++j) {
     212            const QRectF &r2 = b.elementBounds(j);
     213
     214            if (r1.left() > r2.right() || r2.left() > r1.right())
     215                continue;
     216            if (r1.top() > r2.bottom() || r2.top() > r1.bottom())
     217                continue;
     218
     219            if (linesIntersect(a.lineAt(i), b.lineAt(j)))
     220                return true;
     221        }
     222    }
     223
     224    return false;
     225}
     226
     227namespace {
     228struct TreeNode
     229{
     230    qreal splitLeft;
     231    qreal splitRight;
     232    bool leaf;
     233
     234    int lowestLeftIndex;
     235    int lowestRightIndex;
     236
     237    union {
     238        struct {
     239            int first;
     240            int last;
     241        } interval;
     242        struct {
     243            int left;
     244            int right;
     245        } children;
     246    } index;
     247};
     248
     249struct RectF
     250{
     251    qreal x1;
     252    qreal y1;
     253    qreal x2;
     254    qreal y2;
     255};
     256
     257class SegmentTree
     258{
     259public:
     260    SegmentTree(QPathSegments &segments);
     261
     262    QRectF boundingRect() const;
     263
     264    void produceIntersections(int segment);
     265
     266private:
     267    TreeNode buildTree(int first, int last, int depth, const RectF &bounds);
     268
     269    void produceIntersectionsLeaf(const TreeNode &node, int segment);
     270    void produceIntersections(const TreeNode &node, int segment, const RectF &segmentBounds, const RectF &nodeBounds, int axis);
     271    void intersectLines(const QLineF &a, const QLineF &b, QDataBuffer<QIntersection> &intersections);
     272
     273    QPathSegments &m_segments;
     274    QVector<int> m_index;
     275
     276    RectF m_bounds;
     277
     278    QVector<TreeNode> m_tree;
     279    QDataBuffer<QIntersection> m_intersections;
     280};
     281
     282SegmentTree::SegmentTree(QPathSegments &segments)
     283    : m_segments(segments),
     284      m_intersections(0)
     285{
     286    m_bounds.x1 = qt_inf();
     287    m_bounds.y1 = qt_inf();
     288    m_bounds.x2 = -qt_inf();
     289    m_bounds.y2 = -qt_inf();
     290
     291    m_index.resize(m_segments.segments());
     292
     293    for (int i = 0; i < m_index.size(); ++i) {
     294        m_index[i] = i;
     295
     296        const QRectF &segmentBounds = m_segments.elementBounds(i);
     297
     298        if (segmentBounds.left() < m_bounds.x1)
     299            m_bounds.x1 = segmentBounds.left();
     300        if (segmentBounds.top() < m_bounds.y1)
     301            m_bounds.y1 = segmentBounds.top();
     302        if (segmentBounds.right() > m_bounds.x2)
     303            m_bounds.x2 = segmentBounds.right();
     304        if (segmentBounds.bottom() > m_bounds.y2)
     305            m_bounds.y2 = segmentBounds.bottom();
     306    }
     307
     308    m_tree.resize(1);
     309
     310    TreeNode root = buildTree(0, m_index.size(), 0, m_bounds);
     311    m_tree[0] = root;
     312}
     313
     314QRectF SegmentTree::boundingRect() const
     315{
     316    return QRectF(QPointF(m_bounds.x1, m_bounds.y1),
     317                  QPointF(m_bounds.x2, m_bounds.y2));
     318}
     319
     320static inline qreal coordinate(const QPointF &pos, int axis)
     321{
     322    return axis == 0 ? pos.x() : pos.y();
     323}
     324
     325TreeNode SegmentTree::buildTree(int first, int last, int depth, const RectF &bounds)
     326{
     327    if (depth >= 24 || (last - first) <= 10) {
     328        TreeNode node;
     329        node.leaf = true;
     330        node.index.interval.first = first;
     331        node.index.interval.last = last;
     332
     333        return node;
     334    }
     335
     336    int splitAxis = (depth & 1);
     337
     338    TreeNode node;
     339    node.leaf = false;
     340
     341    qreal split = 0.5f * ((&bounds.x1)[splitAxis] + (&bounds.x2)[splitAxis]);
     342
     343    node.splitLeft = (&bounds.x1)[splitAxis];
     344    node.splitRight = (&bounds.x2)[splitAxis];
     345
     346    node.lowestLeftIndex = INT_MAX;
     347    node.lowestRightIndex = INT_MAX;
     348
     349    const int treeSize = m_tree.size();
     350
     351    node.index.children.left = treeSize;
     352    node.index.children.right = treeSize + 1;
     353
     354    m_tree.resize(treeSize + 2);
     355
     356    int l = first;
     357    int r = last - 1;
     358
     359    // partition into left and right sets
     360    while (l <= r) {
     361        const int index = m_index.at(l);
     362        const QRectF &segmentBounds = m_segments.elementBounds(index);
     363
     364        qreal lowCoordinate = coordinate(segmentBounds.topLeft(), splitAxis);
     365
     366        if (coordinate(segmentBounds.center(), splitAxis) < split) {
     367            qreal highCoordinate = coordinate(segmentBounds.bottomRight(), splitAxis);
     368            if (highCoordinate > node.splitLeft)
     369                node.splitLeft = highCoordinate;
     370            if (index < node.lowestLeftIndex)
     371                node.lowestLeftIndex = index;
     372            ++l;
    226373        } else {
    227             pt = one.pointAt(alpha_p);
    228         }
    229 
    230         QIntersection intersection;
    231         intersection.alphaA = alpha_p;
    232         intersection.alphaB = alpha_q;
    233         intersection.pos = pt;
    234         intersections.add(intersection);
    235     }
    236 }
    237 
    238 void QIntersectionFinder::intersectLines(const QLineF &a, const QLineF &b, QDataBuffer<QIntersection> &intersections)
     374            if (lowCoordinate < node.splitRight)
     375                node.splitRight = lowCoordinate;
     376            if (index < node.lowestRightIndex)
     377                node.lowestRightIndex = index;
     378            qSwap(m_index[l], m_index[r]);
     379            --r;
     380        }
     381    }
     382
     383    RectF lbounds = bounds;
     384    (&lbounds.x2)[splitAxis] = node.splitLeft;
     385
     386    RectF rbounds = bounds;
     387    (&rbounds.x1)[splitAxis] = node.splitRight;
     388
     389    TreeNode left = buildTree(first, l, depth + 1, lbounds);
     390    m_tree[node.index.children.left] = left;
     391
     392    TreeNode right = buildTree(l, last, depth + 1, rbounds);
     393    m_tree[node.index.children.right] = right;
     394
     395    return node;
     396}
     397
     398void SegmentTree::intersectLines(const QLineF &a, const QLineF &b, QDataBuffer<QIntersection> &intersections)
    239399{
    240400    const QPointF p1 = a.p1();
     
    358518}
    359519
    360 static const QBezier bezierFromLine(const QLineF &line)
    361 {
    362     const QPointF p1 = line.p1();
    363     const QPointF p2 = line.p2();
    364     const QPointF delta = (p2 - p1) / 3;
    365     return QBezier::fromPoints(p1, p1 + delta, p1 + 2 * delta, p2);
    366 }
    367 
    368 bool QIntersectionFinder::hasIntersections(const QPathSegments &a, const QPathSegments &b) const
    369 {
    370     QBezier tempA;
    371     QBezier tempB;
    372 
    373     if (a.segments() == 0 || b.segments() == 0)
    374         return false;
    375 
    376     const QRectF &rb0 = b.elementBounds(0);
    377 
    378     qreal minX = rb0.left();
    379     qreal minY = rb0.top();
    380     qreal maxX = rb0.right();
    381     qreal maxY = rb0.bottom();
    382 
    383     for (int i = 1; i < b.segments(); ++i) {
    384         const QRectF &r = b.elementBounds(i);
    385         minX = qMin(minX, r.left());
    386         minY = qMin(minY, r.top());
    387         maxX = qMax(maxX, r.right());
    388         maxY = qMax(maxY, r.bottom());
    389     }
    390 
    391     QRectF rb(minX, minY, maxX - minX, maxY - minY);
    392 
    393     for (int i = 0; i < a.segments(); ++i) {
    394         const QBezier *bezierA = a.bezierAt(i);
    395         bool isBezierA = bezierA != 0;
    396 
    397         const QRectF &r1 = a.elementBounds(i);
    398 
    399         if (r1.left() > rb.right() || rb.left() > r1.right())
     520void SegmentTree::produceIntersections(int segment)
     521{
     522    const QRectF &segmentBounds = m_segments.elementBounds(segment);
     523
     524    RectF sbounds;
     525    sbounds.x1 = segmentBounds.left();
     526    sbounds.y1 = segmentBounds.top();
     527    sbounds.x2 = segmentBounds.right();
     528    sbounds.y2 = segmentBounds.bottom();
     529
     530    produceIntersections(m_tree.at(0), segment, sbounds, m_bounds, 0);
     531}
     532
     533void SegmentTree::produceIntersectionsLeaf(const TreeNode &node, int segment)
     534{
     535    const QRectF &r1 = m_segments.elementBounds(segment);
     536    const QLineF lineA = m_segments.lineAt(segment);
     537
     538    for (int i = node.index.interval.first; i < node.index.interval.last; ++i) {
     539        const int other = m_index.at(i);
     540        if (other >= segment)
    400541            continue;
    401         if (r1.top() > rb.bottom() || rb.top() > r1.bottom())
     542
     543        const QRectF &r2 = m_segments.elementBounds(other);
     544
     545        if (r1.left() > r2.right() || r2.left() > r1.right())
    402546            continue;
    403 
    404         for (int j = 0; j < b.segments(); ++j) {
    405             const QRectF &r2 = b.elementBounds(j);
    406 
    407             if (r1.left() > r2.right() || r2.left() > r1.right())
    408                 continue;
    409             if (r1.top() > r2.bottom() || r2.top() > r1.bottom())
    410                 continue;
    411 
    412             bool isBezierB = b.bezierAt(j) != 0;
    413 
    414             if (isBezierA || isBezierB) {
    415                 const QBezier *bezierB;
    416                 if (isBezierB) {
    417                     bezierB = b.bezierAt(j);
    418                 } else {
    419                     tempB = bezierFromLine(b.lineAt(j));
    420                     bezierB = &tempB;
    421                 }
    422 
    423                 if (!bezierA) {
    424                     tempA = bezierFromLine(a.lineAt(i));
    425                     bezierA = &tempA;
    426                 }
    427 
    428                 if (beziersIntersect(*bezierA, *bezierB))
    429                     return true;
    430             } else {
    431                 if (linesIntersect(a.lineAt(i), b.lineAt(j)))
    432                     return true;
    433             }
    434         }
    435     }
    436 
    437     return false;
     547        if (r1.top() > r2.bottom() || r2.top() > r1.bottom())
     548            continue;
     549
     550        m_intersections.reset();
     551
     552        const QLineF lineB = m_segments.lineAt(other);
     553
     554        intersectLines(lineA, lineB, m_intersections);
     555
     556        for (int k = 0; k < m_intersections.size(); ++k) {
     557            QPathSegments::Intersection i_isect, j_isect;
     558            i_isect.vertex = j_isect.vertex = m_segments.addPoint(m_intersections.at(k).pos);
     559
     560            i_isect.t = m_intersections.at(k).alphaA;
     561            j_isect.t = m_intersections.at(k).alphaB;
     562
     563            i_isect.next = 0;
     564            j_isect.next = 0;
     565
     566            m_segments.addIntersection(segment, i_isect);
     567            m_segments.addIntersection(other, j_isect);
     568        }
     569    }
     570}
     571
     572void SegmentTree::produceIntersections(const TreeNode &node, int segment, const RectF &segmentBounds, const RectF &nodeBounds, int axis)
     573{
     574    if (node.leaf) {
     575        produceIntersectionsLeaf(node, segment);
     576        return;
     577    }
     578
     579    RectF lbounds = nodeBounds;
     580    (&lbounds.x2)[axis] = node.splitLeft;
     581
     582    RectF rbounds = nodeBounds;
     583    (&rbounds.x1)[axis] = node.splitRight;
     584
     585    if (segment > node.lowestLeftIndex && (&segmentBounds.x1)[axis] <= node.splitLeft)
     586        produceIntersections(m_tree.at(node.index.children.left), segment, segmentBounds, lbounds, !axis);
     587
     588    if (segment > node.lowestRightIndex && (&segmentBounds.x2)[axis] >= node.splitRight)
     589        produceIntersections(m_tree.at(node.index.children.right), segment, segmentBounds, rbounds, !axis);
     590}
     591
    438592}
    439593
    440594void QIntersectionFinder::produceIntersections(QPathSegments &segments)
    441595{
    442     QBezier tempA;
    443     QBezier tempB;
    444 
    445     QVector<QPair<qreal, qreal> > t;
    446     QDataBuffer<QIntersection> intersections;
    447 
    448     for (int i = 0; i < segments.segments(); ++i) {
    449         const QBezier *bezierA = segments.bezierAt(i);
    450         bool isBezierA = bezierA != 0;
    451 
    452         const QRectF &r1 = segments.elementBounds(i);
    453 
    454         for (int j = 0; j < i; ++j) {
    455             const QRectF &r2 = segments.elementBounds(j);
    456 
    457             if (r1.left() > r2.right() || r2.left() > r1.right())
    458                 continue;
    459             if (r1.top() > r2.bottom() || r2.top() > r1.bottom())
    460                 continue;
    461 
    462             intersections.reset();
    463 
    464             bool isBezierB = segments.bezierAt(j) != 0;
    465 
    466             if (isBezierA || isBezierB) {
    467                 const QBezier *bezierB;
    468                 if (isBezierB) {
    469                     bezierB = segments.bezierAt(j);
    470                 } else {
    471                     tempB = bezierFromLine(segments.lineAt(j));
    472                     bezierB = &tempB;
    473                 }
    474 
    475                 if (!bezierA) {
    476                     tempA = bezierFromLine(segments.lineAt(i));
    477                     bezierA = &tempA;
    478                 }
    479 
    480                 intersectBeziers(*bezierA, *bezierB, t, intersections);
    481             } else {
    482                 const QLineF lineA = segments.lineAt(i);
    483                 const QLineF lineB = segments.lineAt(j);
    484 
    485                 intersectLines(lineA, lineB, intersections);
    486             }
    487 
    488             for (int k = 0; k < intersections.size(); ++k) {
    489                 QPathSegments::Intersection i_isect, j_isect;
    490                 i_isect.vertex = j_isect.vertex = segments.addPoint(intersections.at(k).pos);
    491 
    492                 i_isect.t = intersections.at(k).alphaA;
    493                 j_isect.t = intersections.at(k).alphaB;
    494 
    495                 i_isect.next = 0;
    496                 j_isect.next = 0;
    497 
    498                 segments.addIntersection(i, i_isect);
    499                 segments.addIntersection(j, j_isect);
    500             }
    501         }
    502     }
     596    SegmentTree tree(segments);
     597
     598    for (int i = 0; i < segments.segments(); ++i)
     599        tree.produceIntersections(i);
    503600}
    504601
     
    713810        addVertex(m_segments.pointAt(i));
    714811
    715     QDataBuffer<QPathSegments::Intersection> intersections;
     812    QDataBuffer<QPathSegments::Intersection> intersections(m_segments.segments());
    716813    for (int i = 0; i < m_segments.segments(); ++i) {
    717814        intersections.reset();
     
    732829        qSort(intersections.data(), intersections.data() + intersections.size());
    733830
    734         const QBezier *bezier = m_segments.bezierAt(i);
    735         if (bezier) {
    736             int first = m_segments.segmentAt(i).va;
    737             int second = m_segments.segmentAt(i).vb;
    738 
    739             qreal alpha = 0.0;
    740             int last = first;
    741             for (int j = 0; j < intersections.size(); ++j) {
    742                 const QPathSegments::Intersection &isect = intersections.at(j);
    743 
    744                 addBezierEdge(bezier, last, isect.vertex, alpha, isect.t, pathId);
    745 
    746                 alpha = isect.t;
    747                 last = isect.vertex;
    748             }
    749 
    750             addBezierEdge(bezier, last, second, alpha, 1.0, pathId);
    751         } else {
    752             int first = m_segments.segmentAt(i).va;
    753             int second = m_segments.segmentAt(i).vb;
    754 
    755             int last = first;
    756             for (int j = 0; j < intersections.size(); ++j) {
    757                 const QPathSegments::Intersection &isect = intersections.at(j);
    758 
    759                 QPathEdge *ep = edge(addEdge(last, isect.vertex));
    760 
    761                 if (ep) {
    762                     const int dir = m_segments.pointAt(last).y() < m_segments.pointAt(isect.vertex).y() ? 1 : -1;
    763                     if (pathId == 0)
    764                         ep->windingA += dir;
    765                     else
    766                         ep->windingB += dir;
    767                 }
    768 
    769                 last = isect.vertex;
    770             }
    771 
    772             QPathEdge *ep = edge(addEdge(last, second));
     831        int first = m_segments.segmentAt(i).va;
     832        int second = m_segments.segmentAt(i).vb;
     833
     834        int last = first;
     835        for (int j = 0; j < intersections.size(); ++j) {
     836            const QPathSegments::Intersection &isect = intersections.at(j);
     837
     838            QPathEdge *ep = edge(addEdge(last, isect.vertex));
    773839
    774840            if (ep) {
    775                 const int dir = m_segments.pointAt(last).y() < m_segments.pointAt(second).y() ? 1 : -1;
     841                const int dir = m_segments.pointAt(last).y() < m_segments.pointAt(isect.vertex).y() ? 1 : -1;
    776842                if (pathId == 0)
    777843                    ep->windingA += dir;
     
    779845                    ep->windingB += dir;
    780846            }
    781         }
    782     }
    783 }
    784 
    785 QWingedEdge::QWingedEdge()
    786 {
    787 }
    788 
    789 QWingedEdge::QWingedEdge(const QPainterPath &subject, const QPainterPath &clip)
     847
     848            last = isect.vertex;
     849        }
     850
     851        QPathEdge *ep = edge(addEdge(last, second));
     852
     853        if (ep) {
     854            const int dir = m_segments.pointAt(last).y() < m_segments.pointAt(second).y() ? 1 : -1;
     855            if (pathId == 0)
     856                ep->windingA += dir;
     857            else
     858                ep->windingB += dir;
     859        }
     860    }
     861}
     862
     863QWingedEdge::QWingedEdge() :
     864    m_edges(0),
     865    m_vertices(0),
     866    m_segments(0)
     867{
     868}
     869
     870QWingedEdge::QWingedEdge(const QPainterPath &subject, const QPainterPath &clip) :
     871    m_edges(subject.elementCount()),
     872    m_vertices(subject.elementCount()),
     873    m_segments(subject.elementCount())
    790874{
    791875    m_segments.setPath(subject);
     
    833917{
    834918    m_points.reset();
    835     m_beziers.reset();
    836919    m_intersections.reset();
    837920    m_segments.reset();
     
    880963                    m_segments << Segment(m_pathId, last, current);
    881964                } else {
    882                     m_segments << Segment(m_pathId, last, current, m_beziers.size());
    883                     m_beziers << bezier;
     965                    QRectF bounds = bezier.bounds();
     966
     967                    // threshold based on similar algorithm as in qtriangulatingstroker.cpp
     968                    int threshold = qMin<float>(64, qMax(bounds.width(), bounds.height()) * (2 * qreal(3.14) / 6));
     969
     970                    if (threshold < 3) threshold = 3;
     971                    qreal one_over_threshold_minus_1 = qreal(1) / (threshold - 1);
     972
     973                    for (int t = 1; t < threshold - 1; ++t) {
     974                        currentPoint = bezier.pointAt(t * one_over_threshold_minus_1);
     975
     976                        int index = m_points.size();
     977                        m_segments << Segment(m_pathId, last, index);
     978                        last = index;
     979
     980                        m_points << currentPoint;
     981                    }
     982
     983                    m_segments << Segment(m_pathId, last, current);
    884984                }
    885985            }
     
    897997
    898998    for (int i = firstSegment; i < m_segments.size(); ++i) {
    899         const QBezier *bezier = bezierAt(i);
    900         if (bezier) {
    901             m_segments.at(i).bounds = bezier->bounds();
    902         } else {
    903             const QLineF line = lineAt(i);
    904 
    905             qreal x1 = line.p1().x();
    906             qreal y1 = line.p1().y();
    907             qreal x2 = line.p2().x();
    908             qreal y2 = line.p2().y();
    909 
    910             if (x2 < x1)
    911                 qSwap(x1, x2);
    912             if (y2 < y1)
    913                 qSwap(y1, y2);
    914 
    915             m_segments.at(i).bounds = QRectF(x1, y1, x2 - x1, y2 - y1);
    916         }
     999        const QLineF line = lineAt(i);
     1000
     1001        qreal x1 = line.p1().x();
     1002        qreal y1 = line.p1().y();
     1003        qreal x2 = line.p2().x();
     1004        qreal y2 = line.p2().y();
     1005
     1006        if (x2 < x1)
     1007            qSwap(x1, x2);
     1008        if (y2 < y1)
     1009            qSwap(y1, y2);
     1010
     1011        m_segments.at(i).bounds = QRectF(x1, y1, x2 - x1, y2 - y1);
    9171012    }
    9181013
     
    9251020    const QPathEdge *bp = edge(b);
    9261021
    927     qreal a_angle = ap->angle;
    928     qreal b_angle = bp->angle;
     1022    double a_angle = ap->angle;
     1023    double b_angle = bp->angle;
    9291024
    9301025    if (vertex == ap->second)
     
    9341029        b_angle = bp->invAngle;
    9351030
    936     qreal result = b_angle - a_angle;
    937 
    938     if (qFuzzyIsNull(result) || qFuzzyCompare(result, 128))
    939         return 0;
    940 
    941     if (result < 0)
     1031    double result = b_angle - a_angle;
     1032
     1033    if (result >= 128.)
     1034        return result - 128.;
     1035    else if (result < 0)
    9421036        return result + 128.;
    9431037    else
     
    9451039}
    9461040
    947 static inline QPointF tangentAt(const QWingedEdge &list, int vi, int ei)
     1041static inline QPointF midPoint(const QWingedEdge &list, int ei)
    9481042{
    9491043    const QPathEdge *ep = list.edge(ei);
    9501044    Q_ASSERT(ep);
    9511045
    952     qreal t;
    953     qreal sign;
    954 
    955     if (ep->first == vi) {
    956         t = ep->t0;
    957         sign = 1;
    958     } else {
    959         t = ep->t1;
    960         sign = -1;
    961     }
    962 
    963     QPointF normal;
    964     if (ep->bezier) {
    965         normal = ep->bezier->derivedAt(t);
    966 
    967         if (qFuzzyIsNull(normal.x()) && qFuzzyIsNull(normal.y()))
    968             normal = ep->bezier->secondDerivedAt(t);
    969     } else {
    970         const QPointF a = *list.vertex(ep->first);
    971         const QPointF b = *list.vertex(ep->second);
    972         normal = b - a;
    973     }
    974 
    975     return normalize(sign * normal);
    976 }
    977 
    978 static inline QPointF midPoint(const QWingedEdge &list, int ei)
    979 {
    980     const QPathEdge *ep = list.edge(ei);
    981     Q_ASSERT(ep);
    982 
    983     if (ep->bezier) {
    984         return ep->bezier->pointAt(0.5 * (ep->t0 + ep->t1));
    985     } else {
    986         const QPointF a = *list.vertex(ep->first);
    987         const QPointF b = *list.vertex(ep->second);
    988         return a + 0.5 * (b - a);
    989     }
    990 }
    991 
    992 static QBezier transform(const QBezier &bezier, const QPointF &xAxis, const QPointF &yAxis, const QPointF &origin)
    993 {
    994     QPointF points[4] = {
    995         bezier.pt1(),
    996         bezier.pt2(),
    997         bezier.pt3(),
    998         bezier.pt4()
    999     };
    1000 
    1001     for (int i = 0; i < 4; ++i) {
    1002         const QPointF p = points[i] - origin;
    1003 
    1004         points[i].rx() = dot(xAxis, p);
    1005         points[i].ry() = dot(yAxis, p);
    1006     }
    1007 
    1008     return QBezier::fromPoints(points[0], points[1], points[2], points[3]);
    1009 }
    1010 
    1011 static bool isLeftOf(const QWingedEdge &list, int vi, int ai, int bi)
    1012 {
    1013     const QPathEdge *ap = list.edge(ai);
    1014     const QPathEdge *bp = list.edge(bi);
    1015 
    1016     Q_ASSERT(ap);
    1017     Q_ASSERT(bp);
    1018 
    1019     if (!(ap->bezier || bp->bezier))
    1020         return false;
    1021 
    1022     const QPointF tangent = tangentAt(list, vi, ai);
    1023     const QPointF normal(tangent.y(), -tangent.x());
    1024 
    1025     const QPointF origin = *list.vertex(vi);
    1026 
    1027     const QPointF dpA = midPoint(list, ai) - origin;
    1028     const QPointF dpB = midPoint(list, bi) - origin;
    1029 
    1030     qreal xA = dot(normal, dpA);
    1031     qreal xB = dot(normal, dpB);
    1032 
    1033     if (xA <= 0 && xB >= 0)
    1034         return true;
    1035 
    1036     if (xA >= 0 && xB <= 0)
    1037         return false;
    1038 
    1039     if (!ap->bezier)
    1040         return xB > 0;
    1041 
    1042     if (!bp->bezier)
    1043         return xA < 0;
    1044 
    1045     // both are beziers on the same side of the tangent
    1046 
    1047     // transform the beziers into the local coordinate system
    1048     // such that positive y is along the tangent, and positive x is along the normal
    1049 
    1050     QBezier bezierA = transform(*ap->bezier, normal, tangent, origin);
    1051     QBezier bezierB = transform(*bp->bezier, normal, tangent, origin);
    1052 
    1053     qreal y = qMin(bezierA.pointAt(0.5 * (ap->t0 + ap->t1)).y(),
    1054                    bezierB.pointAt(0.5 * (bp->t0 + bp->t1)).y());
    1055 
    1056     xA = bezierA.pointAt(bezierA.tForY(ap->t0, ap->t1, y)).x();
    1057     xB = bezierB.pointAt(bezierB.tForY(bp->t0, bp->t1, y)).x();
    1058 
    1059     return xA < xB;
     1046    const QPointF a = *list.vertex(ep->first);
     1047    const QPointF b = *list.vertex(ep->second);
     1048    return a + 0.5 * (b - a);
    10601049}
    10611050
     
    10861075
    10871076        Q_ASSERT(edge(status.edge)->vertex(status.direction) == vi);
    1088 
    10891077        qreal d2 = delta(vi, ei, status.edge);
    10901078
     
    10941082#endif
    10951083
    1096         if (!(qFuzzyIsNull(d2) && isLeftOf(*this, vi, status.edge, ei))
    1097             && (d2 < d || (qFuzzyCompare(d2, d) && isLeftOf(*this, vi, status.edge, position)))) {
     1084        if (d2 < d) {
    10981085            position = status.edge;
    10991086            d = d2;
     
    11871174}
    11881175
    1189 static qreal computeAngle(const QPointF &v)
     1176static double computeAngle(const QPointF &v)
    11901177{
    11911178#if 1
     
    11961183    }
    11971184
    1198     QPointF nv = normalize(v);
    1199     if (nv.y() < 0) {
    1200         if (nv.x() < 0) { // 0 - 32
    1201             return -32. * nv.x();
     1185    double vx = v.x();
     1186    double vy = v.y();
     1187    normalize(vx, vy);
     1188    if (vy < 0) {
     1189        if (vx < 0) { // 0 - 32
     1190            return -32. * vx;
    12021191        } else { // 96 - 128
    1203             return 128. - 32. * nv.x();
     1192            return 128. - 32. * vx;
    12041193        }
    12051194    } else { // 32 - 96
    1206         return 64. + 32 * nv.x();
     1195        return 64. + 32. * vx;
    12071196    }
    12081197#else
     
    12121201}
    12131202
    1214 int QWingedEdge::addEdge(const QPointF &a, const QPointF &b, const QBezier *bezier, qreal t0, qreal t1)
     1203int QWingedEdge::addEdge(const QPointF &a, const QPointF &b)
    12151204{
    12161205    int fi = insert(a);
    12171206    int si = insert(b);
    12181207
    1219     return addEdge(fi, si, bezier, t0, t1);
    1220 }
    1221 
    1222 int QWingedEdge::addEdge(int fi, int si, const QBezier *bezier, qreal t0, qreal t1)
     1208    return addEdge(fi, si);
     1209}
     1210
     1211int QWingedEdge::addEdge(int fi, int si)
    12231212{
    12241213    if (fi == si)
     
    12381227    QPathEdge *ep = edge(ei);
    12391228
    1240     ep->bezier = bezier;
    1241     ep->t0 = t0;
    1242     ep->t1 = t1;
    1243 
    1244     if (bezier) {
    1245         QPointF aTangent = bezier->derivedAt(t0);
    1246         QPointF bTangent = -bezier->derivedAt(t1);
    1247 
    1248         if (qFuzzyIsNull(aTangent.x()) && qFuzzyIsNull(aTangent.y()))
    1249             aTangent = bezier->secondDerivedAt(t0);
    1250 
    1251         if (qFuzzyIsNull(bTangent.x()) && qFuzzyIsNull(bTangent.y()))
    1252             bTangent = bezier->secondDerivedAt(t1);
    1253 
    1254         ep->angle = computeAngle(aTangent);
    1255         ep->invAngle = computeAngle(bTangent);
    1256     } else {
    1257         const QPointF tangent = QPointF(*sp) - QPointF(*fp);
    1258         ep->angle = computeAngle(tangent);
    1259         ep->invAngle = ep->angle + 64;
    1260         if (ep->invAngle >= 128)
    1261             ep->invAngle -= 128;
    1262     }
     1229    const QPointF tangent = QPointF(*sp) - QPointF(*fp);
     1230    ep->angle = computeAngle(tangent);
     1231    ep->invAngle = ep->angle + 64;
     1232    if (ep->invAngle >= 128)
     1233        ep->invAngle -= 128;
    12631234
    12641235    QPathVertex *vertices[2] = { fp, sp };
     
    13151286}
    13161287
    1317 void QWingedEdge::addBezierEdge(const QBezier *bezier, int vertexA, int vertexB, qreal alphaA, qreal alphaB, int path)
    1318 {
    1319     if (qFuzzyCompare(alphaA, alphaB))
    1320         return;
    1321 
    1322     qreal alphaMid = (alphaA + alphaB) * 0.5;
    1323 
    1324     qreal s0 = 0;
    1325     qreal s1 = 1;
    1326     int count = bezier->stationaryYPoints(s0, s1);
    1327 
    1328     m_splitPoints.clear();
    1329     m_splitPoints << alphaA;
    1330     m_splitPoints << alphaMid;
    1331     m_splitPoints << alphaB;
    1332 
    1333     if (count > 0 && !qFuzzyCompare(s0, alphaA) && !qFuzzyCompare(s0, alphaMid) && !qFuzzyCompare(s0, alphaB) && s0 > alphaA && s0 < alphaB)
    1334         m_splitPoints << s0;
    1335 
    1336     if (count > 1 && !qFuzzyCompare(s1, alphaA) && !qFuzzyCompare(s1, alphaMid) && !qFuzzyCompare(s1, alphaB) && s1 > alphaA && s1 < alphaB)
    1337         m_splitPoints << s1;
    1338 
    1339     if (count > 0)
    1340         qSort(m_splitPoints.begin(), m_splitPoints.end());
    1341 
    1342     int last = vertexA;
    1343     for (int i = 0; i < m_splitPoints.size() - 1; ++i) {
    1344         const qreal t0 = m_splitPoints[i];
    1345         const qreal t1 = m_splitPoints[i+1];
    1346 
    1347         int current;
    1348         if ((i + 1) == (m_splitPoints.size() - 1)) {
    1349             current = vertexB;
    1350         } else {
    1351             current = insert(bezier->pointAt(t1));
    1352         }
    1353 
    1354         QPathEdge *ep = edge(addEdge(last, current, bezier, t0, t1));
    1355 
    1356         if (ep) {
    1357             const int dir = m_vertices.at(last).y < m_vertices.at(current).y ? 1 : -1;
    1358             if (path == 0)
    1359                 ep->windingA += dir;
    1360             else
    1361                 ep->windingB += dir;
    1362         }
    1363 
    1364         last = current;
    1365     }
    1366 }
    1367 
    1368 void QWingedEdge::addBezierEdge(const QBezier *bezier, const QPointF &a, const QPointF &b, qreal alphaA, qreal alphaB, int path)
    1369 {
    1370     if (qFuzzyCompare(alphaA, alphaB))
    1371         return;
    1372 
    1373     if (comparePoints(a, b)) {
    1374         int v = insert(a);
    1375 
    1376         addBezierEdge(bezier, v, v, alphaA, alphaB, path);
    1377     } else {
    1378         int va = insert(a);
    1379         int vb = insert(b);
    1380 
    1381         addBezierEdge(bezier, va, vb, alphaA, alphaB, path);
    1382     }
    1383 }
    1384 
    13851288int QWingedEdge::insert(const QPathVertex &vertex)
    13861289{
     
    14311334    status.direction = QPathEdge::Forward;
    14321335
    1433     const QBezier *bezier = 0;
    1434     qreal t0 = 1;
    1435     qreal t1 = 0;
    1436     bool forward = true;
    1437 
    14381336    path.moveTo(*list.vertex(list.edge(edge)->first));
    14391337
     
    14411339        const QPathEdge *ep = list.edge(status.edge);
    14421340
    1443         if (ep->bezier != bezier || (bezier && t0 != ep->t1 && t1 != ep->t0)) {
    1444             if (bezier) {
    1445                 QBezier sub = bezier->bezierOnInterval(t0, t1);
    1446 
    1447                 if (forward)
    1448                     path.cubicTo(sub.pt2(), sub.pt3(), sub.pt4());
    1449                 else
    1450                     path.cubicTo(sub.pt3(), sub.pt2(), sub.pt1());
    1451             }
    1452 
    1453             bezier = ep->bezier;
    1454             t0 = 1;
    1455             t1 = 0;
    1456             forward = status.direction == QPathEdge::Forward;
    1457         }
    1458 
    1459         if (ep->bezier) {
    1460             t0 = qMin(t0, ep->t0);
    1461             t1 = qMax(t1, ep->t1);
    1462         } else
    1463             addLineTo(path, *list.vertex(ep->vertex(status.direction)));
     1341        addLineTo(path, *list.vertex(ep->vertex(status.direction)));
    14641342
    14651343        if (status.traversal == QPathEdge::LeftTraversal)
     
    14701348        status = list.next(status);
    14711349    } while (status.edge != edge);
    1472 
    1473     if (bezier) {
    1474         QBezier sub = bezier->bezierOnInterval(t0, t1);
    1475         if (forward)
    1476             path.cubicTo(sub.pt2(), sub.pt3(), sub.pt4());
    1477         else
    1478             path.cubicTo(sub.pt3(), sub.pt2(), sub.pt1());
    1479     }
    14801350}
    14811351
     
    15361406        return subjectPath.intersects(r2);
    15371407
    1538     QPathSegments a;
     1408    QPathSegments a(subjectPath.elementCount());
    15391409    a.setPath(subjectPath);
    1540     QPathSegments b;
     1410    QPathSegments b(clipPath.elementCount());
    15411411    b.setPath(clipPath);
    15421412
     
    15811451        return subjectPath.contains(r2);
    15821452
    1583     QPathSegments a;
     1453    QPathSegments a(subjectPath.elementCount());
    15841454    a.setPath(subjectPath);
    1585     QPathSegments b;
     1455    QPathSegments b(clipPath.elementCount());
    15861456    b.setPath(clipPath);
    15871457
     
    17051575        if (subjectPath == clipPath)
    17061576            return op == BoolSub ? QPainterPath() : subjectPath;
     1577
     1578        bool subjectIsRect = pathToRect(subjectPath, 0);
     1579        bool clipIsRect = pathToRect(clipPath, 0);
    17071580
    17081581        const QRectF clipBounds = clipPath.boundingRect();
     
    17331606
    17341607        if (clipBounds.contains(subjectBounds)) {
    1735             QRectF clipRect;
    1736             if (pathToRect(clipPath, &clipRect) && clipRect.contains(subjectBounds)) {
     1608            if (clipIsRect) {
    17371609                switch (op) {
    17381610                case BoolSub:
     
    17471619            }
    17481620        } else if (subjectBounds.contains(clipBounds)) {
    1749             QRectF subjectRect;
    1750             if (pathToRect(subjectPath, &subjectRect) && subjectRect.contains(clipBounds)) {
     1621            if (subjectIsRect) {
    17511622                switch (op) {
    17521623                case BoolSub:
    17531624                    if (clipPath.fillRule() == Qt::OddEvenFill) {
    17541625                        QPainterPath result = clipPath;
    1755                         result.addRect(subjectRect);
     1626                        result.addRect(subjectBounds);
    17561627                        return result;
    17571628                    } else {
    17581629                        QPainterPath result = clipPath.simplified();
    1759                         result.addRect(subjectRect);
     1630                        result.addRect(subjectBounds);
    17601631                        return result;
    17611632                    }
     
    17701641            }
    17711642        }
     1643
     1644        if (op == BoolAnd) {
     1645            if (subjectIsRect)
     1646                return intersect(clipPath, subjectBounds);
     1647            else if (clipIsRect)
     1648                return intersect(subjectPath, clipBounds);
     1649        }
    17721650    }
    17731651
     
    19311809
    19321810        if ((a.y() < y && b.y() > y) || (a.y() > y && b.y() < y)) {
    1933             if (ep->bezier) {
    1934                 qreal maxX = qMax(a.x(), qMax(b.x(), qMax(ep->bezier->x2, ep->bezier->x3)));
    1935                 qreal minX = qMin(a.x(), qMin(b.x(), qMin(ep->bezier->x2, ep->bezier->x3)));
    1936 
    1937                 if (minX > x) {
    1938                     winding += w;
    1939                 } else if (maxX > x) {
    1940                     const qreal t = ep->bezier->tForY(ep->t0, ep->t1, y);
    1941                     const qreal intersection = ep->bezier->pointAt(t).x();
    1942 
    1943                     if (intersection > x)
    1944                         winding += w;
    1945                 }
    1946             } else {
    1947                 qreal intersectionX = a.x() + (b.x() - a.x()) * (y - a.y()) / (b.y() - a.y());
    1948 
    1949                 if (intersectionX > x)
    1950                     winding += w;
    1951             }
     1811            qreal intersectionX = a.x() + (b.x() - a.x()) * (y - a.y()) / (b.y() - a.y());
     1812
     1813            if (intersectionX > x)
     1814                winding += w;
    19521815        }
    19531816    }
     
    19651828
    19661829        if ((a.y() < y && b.y() > y) || (a.y() > y && b.y() < y)) {
    1967             if (edge->bezier) {
    1968                 const qreal t = edge->bezier->tForY(edge->t0, edge->t1, y);
    1969                 const qreal intersection = edge->bezier->pointAt(t).x();
    1970 
    1971                 const QCrossingEdge edge = { i, intersection };
    1972                 crossings << edge;
    1973             } else {
    1974                 const qreal intersection = a.x() + (b.x() - a.x()) * (y - a.y()) / (b.y() - a.y());
    1975                 const QCrossingEdge edge = { i, intersection };
    1976                 crossings << edge;
    1977             }
     1830            const qreal intersection = a.x() + (b.x() - a.x()) * (y - a.y()) / (b.y() - a.y());
     1831            const QCrossingEdge edge = { i, intersection };
     1832            crossings << edge;
    19781833        }
    19791834    }
     
    20531908}
    20541909
     1910namespace {
     1911
     1912QList<QPainterPath> toSubpaths(const QPainterPath &path)
     1913{
     1914
     1915    QList<QPainterPath> subpaths;
     1916    if (path.isEmpty())
     1917        return subpaths;
     1918
     1919    QPainterPath current;
     1920    for (int i = 0; i < path.elementCount(); ++i) {
     1921        const QPainterPath::Element &e = path.elementAt(i);
     1922        switch (e.type) {
     1923        case QPainterPath::MoveToElement:
     1924            if (current.elementCount() > 1)
     1925                subpaths += current;
     1926            current = QPainterPath();
     1927            current.moveTo(e);
     1928            break;
     1929        case QPainterPath::LineToElement:
     1930            current.lineTo(e);
     1931            break;
     1932        case QPainterPath::CurveToElement: {
     1933            current.cubicTo(e, path.elementAt(i + 1), path.elementAt(i + 2));
     1934            i+=2;
     1935            break;
     1936        }
     1937        case QPainterPath::CurveToDataElement:
     1938            Q_ASSERT(!"toSubpaths(), bad element type");
     1939            break;
     1940        }
     1941    }
     1942
     1943    if (current.elementCount() > 1)
     1944        subpaths << current;
     1945
     1946    return subpaths;
     1947}
     1948
     1949enum Edge
     1950{
     1951    Left, Top, Right, Bottom
     1952};
     1953
     1954static bool isVertical(Edge edge)
     1955{
     1956    return edge == Left || edge == Right;
     1957}
     1958
     1959template <Edge edge>
     1960bool compare(const QPointF &p, qreal t)
     1961{
     1962    switch (edge)
     1963    {
     1964    case Left:
     1965        return p.x() < t;
     1966    case Right:
     1967        return p.x() > t;
     1968    case Top:
     1969        return p.y() < t;
     1970    default:
     1971        return p.y() > t;
     1972    }
     1973}
     1974
     1975template <Edge edge>
     1976QPointF intersectLine(const QPointF &a, const QPointF &b, qreal t)
     1977{
     1978    QLineF line(a, b);
     1979    switch (edge) {
     1980    case Left: // fall-through
     1981    case Right:
     1982        return line.pointAt((t - a.x()) / (b.x() - a.x()));
     1983    default:
     1984        return line.pointAt((t - a.y()) / (b.y() - a.y()));
     1985    }
     1986}
     1987
     1988void addLine(QPainterPath &path, const QLineF &line)
     1989{
     1990    if (path.elementCount() > 0)
     1991        path.lineTo(line.p1());
     1992    else
     1993        path.moveTo(line.p1());
     1994
     1995    path.lineTo(line.p2());
     1996}
     1997
     1998template <Edge edge>
     1999void clipLine(const QPointF &a, const QPointF &b, qreal t, QPainterPath &result)
     2000{
     2001    bool outA = compare<edge>(a, t);
     2002    bool outB = compare<edge>(b, t);
     2003    if (outA && outB)
     2004        return;
     2005
     2006    if (outA)
     2007        addLine(result, QLineF(intersectLine<edge>(a, b, t), b));
     2008    else if(outB)
     2009        addLine(result, QLineF(a, intersectLine<edge>(a, b, t)));
     2010    else
     2011        addLine(result, QLineF(a, b));
     2012}
     2013
     2014void addBezier(QPainterPath &path, const QBezier &bezier)
     2015{
     2016    if (path.elementCount() > 0)
     2017        path.lineTo(bezier.pt1());
     2018    else
     2019        path.moveTo(bezier.pt1());
     2020
     2021    path.cubicTo(bezier.pt2(), bezier.pt3(), bezier.pt4());
     2022}
     2023
     2024template <Edge edge>
     2025void clipBezier(const QPointF &a, const QPointF &b, const QPointF &c, const QPointF &d, qreal t, QPainterPath &result)
     2026{
     2027    QBezier bezier = QBezier::fromPoints(a, b, c, d);
     2028
     2029    bool outA = compare<edge>(a, t);
     2030    bool outB = compare<edge>(b, t);
     2031    bool outC = compare<edge>(c, t);
     2032    bool outD = compare<edge>(d, t);
     2033
     2034    int outCount = int(outA) + int(outB) + int(outC) + int(outD);
     2035
     2036    if (outCount == 4)
     2037        return;
     2038
     2039    if (outCount == 0) {
     2040        addBezier(result, bezier);
     2041        return;
     2042    }
     2043
     2044    QTransform flip = isVertical(edge) ? QTransform(0, 1, 1, 0, 0, 0) : QTransform();
     2045    QBezier unflipped = bezier;
     2046    QBezier flipped = bezier.mapBy(flip);
     2047
     2048    qreal t0 = 0, t1 = 1;
     2049    int stationary = flipped.stationaryYPoints(t0, t1);
     2050
     2051    qreal segments[4];
     2052    QPointF points[4];
     2053    points[0] = unflipped.pt1();
     2054    segments[0] = 0;
     2055
     2056    int segmentCount = 0;
     2057    if (stationary > 0) {
     2058        ++segmentCount;
     2059        segments[segmentCount] = t0;
     2060        points[segmentCount] = unflipped.pointAt(t0);
     2061    }
     2062    if (stationary > 1) {
     2063        ++segmentCount;
     2064        segments[segmentCount] = t1;
     2065        points[segmentCount] = unflipped.pointAt(t1);
     2066    }
     2067    ++segmentCount;
     2068    segments[segmentCount] = 1;
     2069    points[segmentCount] = unflipped.pt4();
     2070
     2071    qreal lastIntersection = 0;
     2072    for (int i = 0; i < segmentCount; ++i) {
     2073        outA = compare<edge>(points[i], t);
     2074        outB = compare<edge>(points[i+1], t);
     2075
     2076        if (outA != outB) {
     2077            qreal intersection = flipped.tForY(segments[i], segments[i+1], t);
     2078
     2079            if (outB)
     2080                addBezier(result, unflipped.getSubRange(lastIntersection, intersection));
     2081
     2082            lastIntersection = intersection;
     2083        }
     2084    }
     2085
     2086    if (!outB)
     2087        addBezier(result, unflipped.getSubRange(lastIntersection, 1));
     2088}
     2089
     2090// clips a single subpath against a single edge
     2091template <Edge edge>
     2092QPainterPath clip(const QPainterPath &path, qreal t)
     2093{
     2094    QPainterPath result;
     2095    for (int i = 1; i < path.elementCount(); ++i) {
     2096        const QPainterPath::Element &element = path.elementAt(i);
     2097        Q_ASSERT(!element.isMoveTo());
     2098        if (element.isLineTo()) {
     2099            clipLine<edge>(path.elementAt(i-1), path.elementAt(i), t, result);
     2100        } else {
     2101            clipBezier<edge>(path.elementAt(i-1), path.elementAt(i), path.elementAt(i+1), path.elementAt(i+2), t, result);
     2102            i += 2;
     2103        }
     2104    }
     2105
     2106    int last = path.elementCount() - 1;
     2107    if (QPointF(path.elementAt(last)) != QPointF(path.elementAt(0)))
     2108        clipLine<edge>(path.elementAt(last), path.elementAt(0), t, result);
     2109
     2110    return result;
     2111}
     2112
     2113QPainterPath intersectPath(const QPainterPath &path, const QRectF &rect)
     2114{
     2115    QList<QPainterPath> subpaths = toSubpaths(path);
     2116
     2117    QPainterPath result;
     2118    result.setFillRule(path.fillRule());
     2119    for (int i = 0; i < subpaths.size(); ++i) {
     2120        QPainterPath subPath = subpaths.at(i);
     2121        QRectF bounds = subPath.boundingRect();
     2122        if (bounds.intersects(rect)) {
     2123            if (bounds.left() < rect.left())
     2124                subPath = clip<Left>(subPath, rect.left());
     2125            if (bounds.right() > rect.right())
     2126                subPath = clip<Right>(subPath, rect.right());
     2127
     2128            bounds = subPath.boundingRect();
     2129
     2130            if (bounds.top() < rect.top())
     2131                subPath = clip<Top>(subPath, rect.top());
     2132            if (bounds.bottom() > rect.bottom())
     2133                subPath = clip<Bottom>(subPath, rect.bottom());
     2134
     2135            if (subPath.elementCount() > 1)
     2136                result.addPath(subPath);
     2137        }
     2138    }
     2139    return result;
     2140}
     2141
     2142}
     2143
     2144QPainterPath QPathClipper::intersect(const QPainterPath &path, const QRectF &rect)
     2145{
     2146    return intersectPath(path, rect);
     2147}
     2148
    20552149QT_END_NAMESPACE
  • trunk/src/gui/painting/qpathclipper_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8888
    8989    static bool pathToRect(const QPainterPath &path, QRectF *rect = 0);
     90    static QPainterPath intersect(const QPainterPath &path, const QRectF &rect);
    9091
    9192private:
     
    148149    int second;
    149150
    150     qreal angle;
    151     qreal invAngle;
    152 
    153     const QBezier *bezier;
    154     qreal t0;
    155     qreal t1;
     151    double angle;
     152    double invAngle;
    156153
    157154    int next(Traversal traversal, Direction direction) const;
     
    182179
    183180    struct Segment {
    184         Segment(int pathId, int vertexA, int vertexB, int bezierIndex = -1)
     181        Segment(int pathId, int vertexA, int vertexB)
    185182            : path(pathId)
    186             , bezier(bezierIndex)
    187183            , va(vertexA)
    188184            , vb(vertexB)
     
    192188
    193189        int path;
    194         int bezier;
    195190
    196191        // vertices
     
    205200
    206201
    207     QPathSegments();
     202    QPathSegments(int reserve);
    208203
    209204    void setPath(const QPainterPath &path);
     
    216211    const Segment &segmentAt(int index) const;
    217212    const QLineF lineAt(int index) const;
    218     const QBezier *bezierAt(int index) const;
    219213    const QRectF &elementBounds(int index) const;
    220214    int pathId(int index) const;
     
    231225    QDataBuffer<QPointF> m_points;
    232226    QDataBuffer<Segment> m_segments;
    233     QDataBuffer<QBezier> m_beziers;
    234227    QDataBuffer<Intersection> m_intersections;
    235228
     
    272265    TraversalStatus next(const TraversalStatus &status) const;
    273266
    274     int addEdge(const QPointF &a, const QPointF &b, const QBezier *bezier = 0, qreal t0 = 0, qreal t1 = 1);
    275     int addEdge(int vertexA, int vertexB, const QBezier *bezier = 0, qreal t0 = 0, qreal t1 = 1);
     267    int addEdge(const QPointF &a, const QPointF &b);
     268    int addEdge(int vertexA, int vertexB);
    276269
    277270    bool isInside(qreal x, qreal y) const;
     
    285278    void printNode(int i, FILE *handle);
    286279
    287     QBezier bezierFromIndex(int index) const;
    288 
    289280    void removeEdge(int ei);
    290     void addBezierEdge(const QBezier *bezier, const QPointF &a, const QPointF &b, qreal alphaA, qreal alphaB, int path);
    291     void addBezierEdge(const QBezier *bezier, int vertexA, int vertexB, qreal alphaA, qreal alphaB, int path);
    292281
    293282    int insert(const QPathVertex &vertex);
     
    312301    , angle(0)
    313302    , invAngle(0)
    314     , bezier(0)
    315     , t0(0)
    316     , t1(0)
    317303{
    318304    m_next[0][0] = -1;
     
    360346}
    361347
    362 inline QPathSegments::QPathSegments()
     348inline QPathSegments::QPathSegments(int reserve) :
     349    m_points(reserve),
     350    m_segments(reserve),
     351    m_intersections(reserve)
    363352{
    364353}
     
    394383    const Segment &segment = m_segments.at(index);
    395384    return QLineF(m_points.at(segment.va), m_points.at(segment.vb));
    396 }
    397 
    398 inline const QBezier *QPathSegments::bezierAt(int index) const
    399 {
    400     const Segment &segment = m_segments.at(index);
    401     if (segment.bezier >= 0)
    402         return &m_beziers.at(segment.bezier);
    403     else
    404         return 0;
    405385}
    406386
  • trunk/src/gui/painting/qpdf.cpp

    r781 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    917917
    918918
    919 QByteArray QPdf::stripSpecialCharacters(const QByteArray &string)
    920 {
    921     QByteArray s = string;
    922     s.replace(' ', "");
    923     s.replace('(', "");
    924     s.replace(')', "");
    925     s.replace('<', "");
    926     s.replace('>', "");
    927     s.replace('[', "");
    928     s.replace(']', "");
    929     s.replace('{', "");
    930     s.replace('}', "");
    931     s.replace('/', "");
    932     s.replace('%', "");
    933     return s;
    934 }
    935 
    936 
    937919// -------------------------- base engine, shared code between PS and PDF -----------------------
    938920
     
    14091391{
    14101392    Q_D(QPdfBaseEngine);
    1411     switch (key) {
     1393    switch (int(key)) {
    14121394    case PPK_CollateCopies:
    14131395        d->collate = value.toBool();
     
    14251407        d->fullPage = value.toBool();
    14261408        break;
     1409    case PPK_CopyCount: // fallthrough
    14271410    case PPK_NumberOfCopies:
    14281411        d->copies = value.toInt();
     
    14981481
    14991482    QVariant ret;
    1500     switch (key) {
     1483    switch (int(key)) {
    15011484    case PPK_CollateCopies:
    15021485        ret = d->collate;
     
    15131496    case PPK_FullPage:
    15141497        ret = d->fullPage;
     1498        break;
     1499    case PPK_CopyCount:
     1500        ret = d->copies;
     1501        break;
     1502    case PPK_SupportsMultipleCopies:
     1503#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
     1504        if (QCUPSSupport::isAvailable())
     1505            ret = true;
     1506        else
     1507#endif
     1508            ret = false;
    15151509        break;
    15161510    case PPK_NumberOfCopies:
  • trunk/src/gui/painting/qpdf_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    157157    const char *paperSizeToString(QPrinter::PaperSize paperSize);
    158158
    159 
    160     QByteArray stripSpecialCharacters(const QByteArray &string);
    161159}
    162160
     
    217215private:
    218216    void updateClipPath(const QPainterPath & path, Qt::ClipOperation op);
    219 
    220     friend int qt_printerRealNumCopies(QPaintEngine *);
    221217};
    222218
  • trunk/src/gui/painting/qpen.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    9393    brush, respectively. Pens may also be compared and streamed.
    9494
    95     For more information about painting in general, see \l{The Paint
     95    For more information about painting in general, see the \l{Paint
    9696    System} documentation.
    9797
     
    873873    the \a stream.
    874874
    875     \sa {Format of the QDataStream Operators}
     875    \sa {Serializing Qt Data Types}
    876876*/
    877877
     
    919919    returns a reference to the \a stream.
    920920
    921     \sa {Format of the QDataStream Operators}
     921    \sa {Serializing Qt Data Types}
    922922*/
    923923
  • trunk/src/gui/painting/qpen.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qpen_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qpolygon.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    720720    reference to the stream.
    721721
    722     \sa {Format of the QDataStream Operators}
     722    \sa {Serializing Qt Data Types}
    723723*/
    724724QDataStream &operator<<(QDataStream &s, const QPolygon &a)
     
    736736    polygon, and returns a reference to the stream.
    737737
    738     \sa {Format of the QDataStream Operators}
     738    \sa {Serializing Qt Data Types}
    739739*/
    740740QDataStream &operator>>(QDataStream &s, QPolygon &a)
     
    756756    reference to the stream.
    757757
    758     \sa {Format of the QDataStream Operators}
     758    \sa {Serializing Qt Data Types}
    759759*/
    760760
     
    777777    polygon, and returns a reference to the stream.
    778778
    779     \sa {Format of the QDataStream Operators}
     779    \sa {Serializing Qt Data Types}
    780780*/
    781781
  • trunk/src/gui/painting/qpolygon.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qpolygonclipper_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6363{
    6464public:
    65     QPolygonClipper()
     65    QPolygonClipper() :
     66        buffer1(0), buffer2(0)
    6667    {
    6768        x1 = y1 = x2 = y2 = 0;
  • trunk/src/gui/painting/qprintengine.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8787        PPK_CustomPaperSize,
    8888        PPK_PageMargins,
     89        PPK_CopyCount,
     90        PPK_SupportsMultipleCopies,
    8991        PPK_PaperSize = PPK_PageSize,
    9092
  • trunk/src/gui/painting/qprintengine_mac.mm

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    115115    if (d->state == QPrinter::Aborted)
    116116        return true;  // I was just here a function call ago :)
    117     if(d->paintEngine->type() == QPaintEngine::CoreGraphics)
     117    if(d->paintEngine->type() == QPaintEngine::CoreGraphics) {
     118        // We dont need the paint engine to call restoreGraphicsState()
     119        static_cast<QCoreGraphicsPaintEngine*>(d->paintEngine)->d_func()->stackCount = 0;
    118120        static_cast<QCoreGraphicsPaintEngine*>(d->paintEngine)->d_func()->hd = 0;
     121    }
    119122    d->paintEngine->end();
    120123    if (d->state != QPrinter::Idle)
     
    686689        d->fullPage = value.toBool();
    687690        break;
     691    case PPK_CopyCount: // fallthrough
    688692    case PPK_NumberOfCopies:
    689693        PMSetCopies(d->settings, value.toInt(), false);
     
    787791    case PPK_NumberOfCopies:
    788792        ret = 1;
     793        break;
     794    case PPK_CopyCount: {
     795        UInt32 copies = 1;
     796        PMGetCopies(d->settings, &copies);
     797        ret = (uint) copies;
     798        break;
     799    }
     800    case PPK_SupportsMultipleCopies:
     801        ret = true;
    789802        break;
    790803    case PPK_Orientation:
  • trunk/src/gui/painting/qprintengine_mac_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qprintengine_pdf.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    932932{
    933933    info = addXrefEntry(-1);
    934 
    935     // The 'text string' type in PDF is encoded either as PDFDocEncoding, or
    936     // Unicode UTF-16 with a Unicode byte order mark as the first character
    937     // (0xfeff), with the high-order byte first.
    938     QByteArray array("<<\n/Title (\xfe\xff");
    939     const ushort *utf16Title = title.utf16();
    940     for (int i=0; i < title.size(); ++i) {
    941         array.append((*(utf16Title + i)) >> 8);
    942         array.append((*(utf16Title + i)) & 0xff);
    943     }
    944     array.append(")\n/Creator (\xfe\xff");
    945     const ushort *utf16Creator = creator.utf16();
    946     for (int i=0; i < creator.size(); ++i) {
    947         array.append((*(utf16Creator + i)) >> 8);
    948         array.append((*(utf16Creator + i)) & 0xff);
    949     }
    950     array.append(")\n/Producer (Qt " QT_VERSION_STR " (C) 2010 Nokia Corporation and/or its subsidiary(-ies))\n");
    951     write(array);
    952 
     934    xprintf("<<\n/Title ");
     935    printString(title);
     936    xprintf("\n/Creator ");
     937    printString(creator);
     938    xprintf("\n/Producer ");
     939    printString(QString::fromLatin1("Qt " QT_VERSION_STR " (C) 2010 Nokia Corporation and/or its subsidiary(-ies)"));
    953940    QDateTime now = QDateTime::currentDateTime().toUTC();
    954941    QTime t = now.time();
    955942    QDate d = now.date();
    956     xprintf("/CreationDate (D:%d%02d%02d%02d%02d%02d)\n",
     943    xprintf("\n/CreationDate (D:%d%02d%02d%02d%02d%02d)\n",
    957944            d.year(),
    958945            d.month(),
     
    12311218}
    12321219
     1220void QPdfEnginePrivate::printString(const QString &string) {
     1221    // The 'text string' type in PDF is encoded either as PDFDocEncoding, or
     1222    // Unicode UTF-16 with a Unicode byte order mark as the first character
     1223    // (0xfeff), with the high-order byte first.
     1224    QByteArray array("(\xfe\xff");
     1225    const ushort *utf16 = string.utf16();
     1226   
     1227    for (int i=0; i < string.size(); ++i) {
     1228        char part[2] = {char((*(utf16 + i)) >> 8), char((*(utf16 + i)) & 0xff)};
     1229        for(int j=0; j < 2; ++j) {
     1230            if (part[j] == '(' || part[j] == ')' || part[j] == '\\')
     1231                array.append('\\');
     1232            array.append(part[j]);
     1233        }
     1234    }
     1235    array.append(")");
     1236    write(array);
     1237}
     1238
    12331239QT_END_NAMESPACE
    12341240
  • trunk/src/gui/painting/qprintengine_pdf_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    171171
    172172    int addXrefEntry(int object, bool printostr = true);
     173    void printString(const QString &string);
    173174    void xprintf(const char* fmt, ...);
    174175    inline void write(const QByteArray &data) {
  • trunk/src/gui/painting/qprintengine_ps.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6565#include "qregion.h"
    6666#include "qimagewriter.h"
    67 #include <private/qunicodetables_p.h>
    6867#include <private/qpainterpath_p.h>
    6968#include <qdebug.h>
     
    910909    if (d->clipEnabled && d->allClipped)
    911910        return;
    912     // ### Optimise implementation!
     911    // ### Optimize implementation!
    913912    qreal yPos = r.y();
    914913    qreal yOff = p.y();
  • trunk/src/gui/painting/qprintengine_ps_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qprintengine_qws.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    269269        ret = d->fullPage;
    270270        break;
     271    case PPK_CopyCount: // fallthrough
    271272    case PPK_NumberOfCopies:
    272273        ret = d->numCopies;
     274        break;
     275    case PPK_SupportsMultipleCopies:
     276        ret = false;
    273277        break;
    274278    case PPK_Orientation:
     
    330334        d->fullPage = value.toBool();
    331335        break;
     336    case PPK_CopyCount: // fallthrough
    332337    case PPK_NumberOfCopies:
    333338        d->numCopies = value.toInt();
  • trunk/src/gui/painting/qprintengine_qws_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qprintengine_win.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    369369
    370370    // We only want to convert the glyphs to text if the entire string is compatible with ASCII
    371     bool convertToText = true;
     371    // and if we actually have access to the chars.
     372    bool convertToText = ti.chars != 0;
    372373    for (int i=0;  i < ti.num_chars; ++i) {
    373374        if (ti.chars[i].unicode() >= 0x80) {
     
    851852    HPEN pen = ExtCreatePen(((penWidth == 0) ? PS_COSMETIC : PS_GEOMETRIC)
    852853                            | PS_SOLID | capStyle | joinStyle,
    853                             penWidth, &brush, 0, 0);
     854                            (penWidth == 0) ? 1 : penWidth, &brush, 0, 0);
    854855
    855856    HGDIOBJ old_pen = SelectObject(hdc, pen);
     
    12421243        break;
    12431244
     1245    case PPK_CopyCount: // fallthrough
    12441246    case PPK_NumberOfCopies:
    12451247        if (!d->devMode)
     
    14081410        break;
    14091411
     1412    case PPK_CopyCount:
     1413        value = d->num_copies;
     1414        break;
     1415
     1416    case PPK_SupportsMultipleCopies:
     1417        value = true;
     1418        break;
     1419
    14101420    case PPK_NumberOfCopies:
    14111421        value = 1;
  • trunk/src/gui/painting/qprintengine_win_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    109109    friend class QPrintDialog;
    110110    friend class QPageSetupDialog;
    111     friend int qt_printerRealNumCopies(QPaintEngine *);
    112111};
    113112
  • trunk/src/gui/painting/qprinter.cpp

    r782 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    159159}
    160160
    161 
    162 // returns the actual num copies set on a printer, not
    163 // the number that is documented in QPrinter::numCopies()
    164 int qt_printerRealNumCopies(QPaintEngine *engine)
    165 {
    166     int numCopies = 1;
    167     if (engine->type() == QPaintEngine::PostScript
    168         || engine->type() == QPaintEngine::Pdf)
    169     {
    170         QPdfBaseEngine *base = static_cast<QPdfBaseEngine *>(engine);
    171         numCopies = base->d_func()->copies;
    172     }
    173 #ifdef Q_WS_WIN
    174     else if (engine->type() == QPaintEngine::Windows) {
    175         QWin32PrintEngine *base = static_cast<QWin32PrintEngine *>(engine);
    176         numCopies = base->d_func()->num_copies;
    177     }
    178 #endif
    179     return numCopies;
    180 }
    181 
    182161void QPrinterPrivate::createDefaultEngines()
    183162{
     
    304283  \i setFullPage() tells QPrinter whether you want to deal with the
    305284  full page or just with the part the printer can draw on.
    306   \i setNumCopies() tells QPrinter how many copies of the document
     285  \i setCopyCount() tells QPrinter how many copies of the document
    307286  it should print.
    308287  \endlist
     
    405384    \value Selection Only the selection should be printed.
    406385    \value PageRange The specified page range should be printed.
     386    \value CurrentPage Only the current page should be printed.
    407387
    408388    \sa QAbstractPrintDialog::PrintRange
     
    594574  \value Selection Only the selection should be printed.
    595575  \value PageRange Print according to the from page and to page options.
     576  \value CurrentPage Only the current page should be printed.
    596577
    597578  \sa setPrintRange(), printRange()
     
    609590  \value PrintPageRange Describes if printing page ranges (from, to) should
    610591  be enabled
     592  \value PrintCurrentPage if Print Current Page option should be enabled
    611593
    612594  \sa setOptionEnabled(), isOptionEnabled()
     
    756738
    757739    QPrintEngine *oldPrintEngine = d->printEngine;
    758     QPaintEngine *oldPaintEngine = d->paintEngine; // same as the above - shouldn't be deleted
    759740    const bool def_engine = d->use_default_engine;
    760741    d->printEngine = 0;
     
    769750            // will return 1, disregarding the actual value that was set
    770751            if (key == QPrintEngine::PPK_NumberOfCopies)
    771                 prop = QVariant(qt_printerRealNumCopies(oldPaintEngine));
     752                prop = QVariant(copyCount());
    772753            else
    773754                prop = oldPrintEngine->property(key);
     
    12771258
    12781259/*!
     1260  \obsolete
    12791261  Returns the number of copies to be printed. The default value is 1.
    12801262
     
    12891271  explicit call to the print code for each copy.
    12901272
     1273  Use copyCount() in conjunction with supportsMultipleCopies() instead.
     1274
    12911275  \sa setNumCopies(), actualNumCopies()
    12921276*/
     
    13001284
    13011285/*!
     1286    \obsolete
    13021287    \since 4.6
    13031288
     
    13081293    dialog or using setNumCopies().
    13091294
     1295    Use copyCount() instead.
     1296
    13101297    \sa setNumCopies(), numCopies()
    13111298*/
    13121299int QPrinter::actualNumCopies() const
    13131300{
    1314     Q_D(const QPrinter);
    1315     return qt_printerRealNumCopies(d->paintEngine);
    1316 }
    1317 
    1318 
    1319 
    1320 /*!
     1301    return copyCount();
     1302}
     1303
     1304
     1305
     1306/*!
     1307  \obsolete
    13211308  Sets the number of copies to be printed to \a numCopies.
    13221309
    13231310  The printer driver reads this setting and prints the specified
    13241311  number of copies.
     1312
     1313  Use setCopyCount() instead.
    13251314
    13261315  \sa numCopies()
     
    13351324}
    13361325
     1326/*!
     1327    \since 4.7
     1328
     1329    Sets the number of copies to be printed to \a count.
     1330
     1331    The printer driver reads this setting and prints the specified number of
     1332    copies.
     1333
     1334    \sa copyCount(), supportsMultipleCopies()
     1335*/
     1336
     1337void QPrinter::setCopyCount(int count)
     1338{
     1339    Q_D(QPrinter);
     1340    ABORT_IF_ACTIVE("QPrinter::setCopyCount;");
     1341    d->printEngine->setProperty(QPrintEngine::PPK_CopyCount, count);
     1342    d->addToManualSetList(QPrintEngine::PPK_CopyCount);
     1343}
     1344
     1345/*!
     1346    \since 4.7
     1347
     1348    Returns the number of copies that will be printed. The default value is 1.
     1349
     1350    \sa setCopyCount(), supportsMultipleCopies()
     1351*/
     1352
     1353int QPrinter::copyCount() const
     1354{
     1355    Q_D(const QPrinter);
     1356    return d->printEngine->property(QPrintEngine::PPK_CopyCount).toInt();
     1357}
     1358
     1359/*!
     1360    \since 4.7
     1361
     1362    Returns true if the printer supports printing multiple copies of the same
     1363    document in one job; otherwise false is returned.
     1364
     1365    On most systems this function will return true. However, on X11 systems
     1366    that do not support CUPS, this function will return false. That means the
     1367    application has to handle the number of copies by printing the same
     1368    document the required number of times.
     1369
     1370    \sa setCopyCount(), copyCount()
     1371*/
     1372
     1373bool QPrinter::supportsMultipleCopies() const
     1374{
     1375    Q_D(const QPrinter);
     1376    return d->printEngine->property(QPrintEngine::PPK_SupportsMultipleCopies).toBool();
     1377}
    13371378
    13381379/*!
     
    22762317    full page or not.
    22772318
    2278     \value PPK_NumberOfCopies An integer specifying the number of
    2279     copies
     2319    \value PPK_NumberOfCopies Obsolete. An integer specifying the number of
     2320    copies. Use PPK_CopyCount instead.
    22802321
    22812322    \value PPK_Orientation Specifies a QPrinter::Orientation value.
     
    23232364    \value PPK_PageMargins A QList<QVariant> containing the left, top,
    23242365    right and bottom margin values.
     2366
     2367    \value PPK_CopyCount An integer specifying the number of copies to print.
     2368
     2369    \value PPK_SupportsMultipleCopies A boolean value indicating whether or not
     2370    the printer supports printing multiple copies in one job.
    23252371
    23262372    \value PPK_CustomBase Basis for extension.
  • trunk/src/gui/painting/qprinter.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    125125
    126126    // ### Qt 5: Merge with QAbstractPrintDialog::PrintRange
    127     enum PrintRange { AllPages, Selection, PageRange };
     127    enum PrintRange { AllPages, Selection, PageRange, CurrentPage };
    128128
    129129    enum Unit {
     
    199199
    200200    int actualNumCopies() const;
     201
     202    void setCopyCount(int);
     203    int copyCount() const;
     204    bool supportsMultipleCopies() const;
    201205
    202206    void setPaperSource(PaperSource);
  • trunk/src/gui/painting/qprinter_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qprinterinfo.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qprinterinfo.qdoc

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    77** This file is part of the documentation of the Qt Toolkit.
    88**
    9 ** $QT_BEGIN_LICENSE:LGPL$
     9** $QT_BEGIN_LICENSE:FDL$
    1010** Commercial Usage
    1111** Licensees holding valid Qt Commercial licenses may use this file in
    1212** accordance with the Qt Commercial License Agreement provided with the
    13 ** Software or, alternatively, in accordance with the terms contained in
    14 ** a written agreement between you and Nokia.
     13** Software or, alternatively, in accordance with the terms contained in a
     14** written agreement between you and Nokia.
    1515**
    16 ** GNU Lesser General Public License Usage
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
    18 ** General Public License version 2.1 as published by the Free Software
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
    20 ** packaging of this file.  Please review the following information to
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    23 **
    24 ** In addition, as a special exception, Nokia gives you certain additional
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    27 **
    28 ** GNU General Public License Usage
    29 ** Alternatively, this file may be used under the terms of the GNU
    30 ** General Public License version 3.0 as published by the Free Software
    31 ** Foundation and appearing in the file LICENSE.GPL included in the
    32 ** packaging of this file.  Please review the following information to
    33 ** ensure the GNU General Public License version 3.0 requirements will be
    34 ** met: http://www.gnu.org/copyleft/gpl.html.
     16** GNU Free Documentation License
     17** Alternatively, this file may be used under the terms of the GNU Free
     18** Documentation License version 1.3 as published by the Free Software
     19** Foundation and appearing in the file included in the packaging of this
     20** file.
    3521**
    3622** If you have questions regarding the use of this file, please contact
  • trunk/src/gui/painting/qprinterinfo_mac.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qprinterinfo_unix.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qprinterinfo_unix_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qprinterinfo_win.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qrasterdefs_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8282QT_FT_BEGIN_HEADER
    8383
    84 
    8584  /*************************************************************************/
    8685  /*                                                                       */
     
    102101  /*    pixel coordinates.                                                 */
    103102  /*                                                                       */
    104   typedef signed long  QT_FT_Pos;
     103  typedef signed int  QT_FT_Pos;
    105104
    106105
     
    838837  /*    independently to convert an outline into a bitmap or pixmap.       */
    839838  /*                                                                       */
    840   typedef struct QT_FT_RasterRec_*  QT_FT_Raster;
     839  typedef struct TRaster_ *QT_FT_Raster;
    841840
    842841
     
    10901089    void*                   user;
    10911090    QT_FT_BBox                 clip_box;
     1091    int                     skip_spans;
    10921092
    10931093  } QT_FT_Raster_Params;
     
    11191119  /*                                                                       */
    11201120  typedef int
    1121   (*QT_FT_Raster_NewFunc)( void*       memory,
    1122                         QT_FT_Raster*  raster );
     1121  (*QT_FT_Raster_NewFunc)( QT_FT_Raster*  raster );
    11231122
    11241123#define  QT_FT_Raster_New_Func    QT_FT_Raster_NewFunc
  • trunk/src/gui/painting/qrasterizer.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6666#define COORD_OFFSET 32 // 26.6, 32 is half a pixel
    6767
     68static inline QT_FT_Vector PointToVector(const QPointF &p)
     69{
     70    QT_FT_Vector result = { QT_FT_Pos(p.x() * 64), QT_FT_Pos(p.y() * 64) };
     71    return result;
     72}
     73
    6874class QSpanBuffer {
    6975public:
     
    199205
    200206QScanConverter::QScanConverter()
    201    : m_alloc(0)
     207   : m_lines(0)
     208   , m_alloc(0)
    202209   , m_size(0)
    203210   , m_intersections(0)
     211   , m_active(0)
    204212{
    205213}
     
    311319void qScanConvert(QScanConverter &d, T allVertical)
    312320{
     321    if (!d.m_lines.size()) {
     322        d.m_active.reset();
     323        return;
     324    }
    313325    qSort(d.m_lines.data(), d.m_lines.data() + d.m_lines.size(), QT_PREPEND_NAMESPACE(topOrder));
    314326    int line = 0;
     
    688700}
    689701
    690 static inline bool q16Dot16Compare(qreal p1, qreal p2)
    691 {
    692     return FloatToQ16Dot16(p2 - p1) == 0;
     702static inline bool q26Dot6Compare(qreal p1, qreal p2)
     703{
     704    return int((p2  - p1) * 64.) == 0;
    693705}
    694706
     
    703715}
    704716
     717static inline QPointF snapTo26Dot6Grid(const QPointF &p)
     718{
     719    return QPointF(qFloorF(p.x() * 64) * (1 / qreal(64)),
     720                   qFloorF(p.y() * 64) * (1 / qreal(64)));
     721}
     722
    705723void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, bool squareCap)
    706724{
     
    713731    QPointF pb = b;
    714732
    715     QPointF offs = QPointF(qAbs(b.y() - a.y()), qAbs(b.x() - a.x())) * width * 0.5;   
    716     if (squareCap)
    717         offs += QPointF(offs.y(), offs.x());
     733    if (squareCap) {
     734        QPointF delta = pb - pa;
     735        pa -= (0.5f * width) * delta;
     736        pb += (0.5f * width) * delta;
     737    }
     738
     739    QPointF offs = QPointF(qAbs(b.y() - a.y()), qAbs(b.x() - a.x())) * width * 0.5;
    718740    const QRectF clip(d->clipRect.topLeft() - offs, d->clipRect.bottomRight() + QPoint(1, 1) + offs);
    719741
    720     if (!clip.contains(a) || !clip.contains(b)) {
     742    if (!clip.contains(pa) || !clip.contains(pb)) {
    721743        qreal t1 = 0;
    722744        qreal t2 = 1;
    723745
    724         const qreal o[2] = { a.x(), a.y() };
    725         const qreal d[2] = { b.x() - a.x(), b.y() - a.y() };
     746        const qreal o[2] = { pa.x(), pa.y() };
     747        const qreal d[2] = { pb.x() - pa.x(), pb.y() - pa.y() };
    726748
    727749        const qreal low[2] = { clip.left(), clip.top() };
     
    746768                return;
    747769        }
    748         pa = a + (b - a) * t1;
    749         pb = a + (b - a) * t2;
     770
     771        QPointF npa = pa + (pb - pa) * t1;
     772        QPointF npb = pa + (pb - pa) * t2;
     773
     774        pa = npa;
     775        pb = npb;
    750776    }
    751777
     
    758784
    759785    {
    760         const qreal gridResolution = 64;
    761         const qreal reciprocal = 1 / gridResolution;
    762 
    763         // snap to grid to prevent large slopes
    764         pa.rx() = qFloorF(pa.rx() * gridResolution) * reciprocal;
    765         pa.ry() = qFloorF(pa.ry() * gridResolution) * reciprocal;
    766         pb.rx() = qFloorF(pb.rx() * gridResolution) * reciprocal;
    767         pb.ry() = qFloorF(pb.ry() * gridResolution) * reciprocal;
    768 
    769786        // old delta
    770787        const QPointF d0 = a - b;
     
    784801    QSpanBuffer buffer(d->blend, d->data, d->clipRect);
    785802
    786     if (q16Dot16Compare(pa.y(), pb.y())) {
     803    if (q26Dot6Compare(pa.y(), pb.y())) {
    787804        const qreal x = (pa.x() + pb.x()) * 0.5f;
    788805        const qreal dx = qAbs(pb.x() - pa.x()) * 0.5f;
     
    794811        pb = QPointF(x, y + dy);
    795812
    796         if (squareCap)
    797             width = 1 / width + 1.0f;
    798         else
    799             width = 1 / width;
    800 
    801         squareCap = false;
    802     }
    803 
    804     if (q16Dot16Compare(pa.x(), pb.x())) {
     813        width = 1 / width;
     814    }
     815
     816    if (q26Dot6Compare(pa.x(), pb.x())) {
    805817        if (pa.y() > pb.y())
    806818            qSwap(pa, pb);
     
    809821        const qreal halfWidth = 0.5f * width * dy;
    810822
    811         if (squareCap) {
    812             pa.ry() -= halfWidth;
    813             pb.ry() += halfWidth;
    814         }
    815 
    816823        qreal left = pa.x() - halfWidth;
    817824        qreal right = pa.x() + halfWidth;
     
    823830        pb.ry() = qBound(qreal(d->clipRect.top()), pb.y(), qreal(d->clipRect.bottom() + 1));
    824831
    825         if (q16Dot16Compare(left, right) || q16Dot16Compare(pa.y(), pb.y()))
     832        if (q26Dot6Compare(left, right) || q26Dot6Compare(pa.y(), pb.y()))
    826833            return;
    827834
     
    894901        const QPointF perp(delta.y(), -delta.x());
    895902
    896         if (squareCap) {
    897             pa -= delta;
    898             pb += delta;
    899         }
    900 
    901903        QPointF top;
    902904        QPointF left;
     
    916918        }
    917919
     920        top = snapTo26Dot6Grid(top);
     921        bottom = snapTo26Dot6Grid(bottom);
     922        left = snapTo26Dot6Grid(left);
     923        right = snapTo26Dot6Grid(right);
     924
    918925        const qreal topBound = qBound(qreal(d->clipRect.top()), top.y(), qreal(d->clipRect.bottom()));
    919926        const qreal bottomBound = qBound(qreal(d->clipRect.top()), bottom.y(), qreal(d->clipRect.bottom()));
    920927
    921         const qreal leftSlope = (left.x() - top.x()) / (left.y() - top.y());
    922         const qreal rightSlope = -1.0f / leftSlope;
    923 
    924         const Q16Dot16 leftSlopeFP = FloatToQ16Dot16(leftSlope);
    925         const Q16Dot16 rightSlopeFP = FloatToQ16Dot16(rightSlope);
     928        const QPointF topLeftEdge = left - top;
     929        const QPointF topRightEdge = right - top;
     930        const QPointF bottomLeftEdge = bottom - left;
     931        const QPointF bottomRightEdge = bottom - right;
     932
     933        const qreal topLeftSlope = topLeftEdge.x() / topLeftEdge.y();
     934        const qreal bottomLeftSlope = bottomLeftEdge.x() / bottomLeftEdge.y();
     935
     936        const qreal topRightSlope = topRightEdge.x() / topRightEdge.y();
     937        const qreal bottomRightSlope = bottomRightEdge.x() / bottomRightEdge.y();
     938
     939        const Q16Dot16 topLeftSlopeFP = FloatToQ16Dot16(topLeftSlope);
     940        const Q16Dot16 topRightSlopeFP = FloatToQ16Dot16(topRightSlope);
     941
     942        const Q16Dot16 bottomLeftSlopeFP = FloatToQ16Dot16(bottomLeftSlope);
     943        const Q16Dot16 bottomRightSlopeFP = FloatToQ16Dot16(bottomRightSlope);
     944
     945        const Q16Dot16 invTopLeftSlopeFP = FloatToQ16Dot16(1 / topLeftSlope);
     946        const Q16Dot16 invTopRightSlopeFP = FloatToQ16Dot16(1 / topRightSlope);
     947
     948        const Q16Dot16 invBottomLeftSlopeFP = FloatToQ16Dot16(1 / bottomLeftSlope);
     949        const Q16Dot16 invBottomRightSlopeFP = FloatToQ16Dot16(1 / bottomRightSlope);
    926950
    927951        if (d->antialiased) {
     
    931955            const Q16Dot16 iBottomFP = IntToQ16Dot16(int(bottomBound));
    932956
    933             Q16Dot16 leftIntersectAf = FloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * leftSlope);
    934             Q16Dot16 rightIntersectAf = FloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * rightSlope);
     957            Q16Dot16 leftIntersectAf = FloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topLeftSlope);
     958            Q16Dot16 rightIntersectAf = FloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topRightSlope);
    935959            Q16Dot16 leftIntersectBf = 0;
    936960            Q16Dot16 rightIntersectBf = 0;
    937961
    938962            if (iLeftFP < iTopFP)
    939                 leftIntersectBf = FloatToQ16Dot16(left.x() + (int(topBound) - left.y()) * rightSlope);
     963                leftIntersectBf = FloatToQ16Dot16(left.x() + (int(topBound) - left.y()) * bottomLeftSlope);
    940964
    941965            if (iRightFP < iTopFP)
    942                 rightIntersectBf = FloatToQ16Dot16(right.x() + (int(topBound) - right.y()) * leftSlope);
     966                rightIntersectBf = FloatToQ16Dot16(right.x() + (int(topBound) - right.y()) * bottomRightSlope);
    943967
    944968            Q16Dot16 rowTop, rowBottomLeft, rowBottomRight, rowTopLeft, rowTopRight, rowBottom;
     
    955979            rowTop = qMax(iTopFP, yTopFP);
    956980            topLeftIntersectAf = leftIntersectAf +
    957                                  Q16Dot16Multiply(leftSlopeFP, rowTop - iTopFP);
     981                                 Q16Dot16Multiply(topLeftSlopeFP, rowTop - iTopFP);
    958982            topRightIntersectAf = rightIntersectAf +
    959                                   Q16Dot16Multiply(rightSlopeFP, rowTop - iTopFP);
     983                                  Q16Dot16Multiply(topRightSlopeFP, rowTop - iTopFP);
    960984
    961985            Q16Dot16 yFP = iTopFP;
     
    969993                if (yFP == iLeftFP) {
    970994                    const int y = Q16Dot16ToInt(yFP);
    971                     leftIntersectBf = FloatToQ16Dot16(left.x() + (y - left.y()) * rightSlope);
    972                     topLeftIntersectBf = leftIntersectBf + Q16Dot16Multiply(rightSlopeFP, rowTopLeft - yFP);
    973                     bottomLeftIntersectAf = leftIntersectAf + Q16Dot16Multiply(leftSlopeFP, rowBottomLeft - yFP);
     995                    leftIntersectBf = FloatToQ16Dot16(left.x() + (y - left.y()) * bottomLeftSlope);
     996                    topLeftIntersectBf = leftIntersectBf + Q16Dot16Multiply(bottomLeftSlopeFP, rowTopLeft - yFP);
     997                    bottomLeftIntersectAf = leftIntersectAf + Q16Dot16Multiply(topLeftSlopeFP, rowBottomLeft - yFP);
    974998                } else {
    975999                    topLeftIntersectBf = leftIntersectBf;
    976                     bottomLeftIntersectAf = leftIntersectAf + leftSlopeFP;
     1000                    bottomLeftIntersectAf = leftIntersectAf + topLeftSlopeFP;
    9771001                }
    9781002
    9791003                if (yFP == iRightFP) {
    9801004                    const int y = Q16Dot16ToInt(yFP);
    981                     rightIntersectBf = FloatToQ16Dot16(right.x() + (y - right.y()) * leftSlope);
    982                     topRightIntersectBf = rightIntersectBf + Q16Dot16Multiply(leftSlopeFP, rowTopRight - yFP);
    983                     bottomRightIntersectAf = rightIntersectAf + Q16Dot16Multiply(rightSlopeFP, rowBottomRight - yFP);
     1005                    rightIntersectBf = FloatToQ16Dot16(right.x() + (y - right.y()) * bottomRightSlope);
     1006                    topRightIntersectBf = rightIntersectBf + Q16Dot16Multiply(bottomRightSlopeFP, rowTopRight - yFP);
     1007                    bottomRightIntersectAf = rightIntersectAf + Q16Dot16Multiply(topRightSlopeFP, rowBottomRight - yFP);
    9841008                } else {
    9851009                    topRightIntersectBf = rightIntersectBf;
    986                     bottomRightIntersectAf = rightIntersectAf + rightSlopeFP;
     1010                    bottomRightIntersectAf = rightIntersectAf + topRightSlopeFP;
    9871011                }
    9881012
    9891013                if (yFP == iBottomFP) {
    990                     bottomLeftIntersectBf = leftIntersectBf + Q16Dot16Multiply(rightSlopeFP, rowBottom - yFP);
    991                     bottomRightIntersectBf = rightIntersectBf + Q16Dot16Multiply(leftSlopeFP, rowBottom - yFP);
     1014                    bottomLeftIntersectBf = leftIntersectBf + Q16Dot16Multiply(bottomLeftSlopeFP, rowBottom - yFP);
     1015                    bottomRightIntersectBf = rightIntersectBf + Q16Dot16Multiply(bottomRightSlopeFP, rowBottom - yFP);
    9921016                } else {
    993                     bottomLeftIntersectBf = leftIntersectBf + rightSlopeFP;
    994                     bottomRightIntersectBf = rightIntersectBf + leftSlopeFP;
     1017                    bottomLeftIntersectBf = leftIntersectBf + bottomLeftSlopeFP;
     1018                    bottomRightIntersectBf = rightIntersectBf + bottomRightSlopeFP;
    9951019                }
    9961020
     
    10371061                        excluded += intersectPixelFP(x, rowTop, rowBottomLeft,
    10381062                                                     bottomLeftIntersectAf, topLeftIntersectAf,
    1039                                                      leftSlopeFP, -rightSlopeFP);
     1063                                                     topLeftSlopeFP, invTopLeftSlopeFP);
    10401064                    if (yFP >= iLeftFP)
    10411065                        excluded += intersectPixelFP(x, rowTopLeft, rowBottom,
    10421066                                                     topLeftIntersectBf, bottomLeftIntersectBf,
    1043                                                      rightSlopeFP, -leftSlopeFP);
     1067                                                     bottomLeftSlopeFP, invBottomLeftSlopeFP);
    10441068
    10451069                    if (x >= rightMin) {
     
    10471071                            excluded += (rowBottomRight - rowTop) - intersectPixelFP(x, rowTop, rowBottomRight,
    10481072                                                                                     topRightIntersectAf, bottomRightIntersectAf,
    1049                                                                                      rightSlopeFP, -leftSlopeFP);
     1073                                                                                     topRightSlopeFP, invTopRightSlopeFP);
    10501074                        if (yFP >= iRightFP)
    10511075                            excluded += (rowBottom - rowTopRight) - intersectPixelFP(x, rowTopRight, rowBottom,
    10521076                                                                                     bottomRightIntersectBf, topRightIntersectBf,
    1053                                                                                      leftSlopeFP, -rightSlopeFP);
     1077                                                                                     bottomRightSlopeFP, invBottomRightSlopeFP);
    10541078                    }
    10551079
     
    10691093                        excluded += (rowBottomRight - rowTop) - intersectPixelFP(x, rowTop, rowBottomRight,
    10701094                                                                                 topRightIntersectAf, bottomRightIntersectAf,
    1071                                                                                  rightSlopeFP, -leftSlopeFP);
     1095                                                                                 topRightSlopeFP, invTopRightSlopeFP);
    10721096                    if (yFP >= iRightFP)
    10731097                        excluded += (rowBottom - rowTopRight) - intersectPixelFP(x, rowTopRight, rowBottom,
    10741098                                                                                 bottomRightIntersectBf, topRightIntersectBf,
    1075                                                                                  leftSlopeFP, -rightSlopeFP);
     1099                                                                                 bottomRightSlopeFP, invBottomRightSlopeFP);
    10761100
    10771101                    Q16Dot16 coverage = rowHeight - excluded;
     
    10811105                }
    10821106
    1083                 leftIntersectAf += leftSlopeFP;
    1084                 leftIntersectBf += rightSlopeFP;
    1085                 rightIntersectAf += rightSlopeFP;
    1086                 rightIntersectBf += leftSlopeFP;
     1107                leftIntersectAf += topLeftSlopeFP;
     1108                leftIntersectBf += bottomLeftSlopeFP;
     1109                rightIntersectAf += topRightSlopeFP;
     1110                rightIntersectBf += bottomRightSlopeFP;
    10871111                topLeftIntersectAf = leftIntersectAf;
    10881112                topRightIntersectAf = rightIntersectAf;
     
    10981122            int iMiddle = qMin(iLeft, iRight);
    10991123
    1100             Q16Dot16 leftIntersectAf = FloatToQ16Dot16(top.x() + 0.5f + (iTop + 0.5f - top.y()) * leftSlope);
    1101             Q16Dot16 leftIntersectBf = FloatToQ16Dot16(left.x() + 0.5f + (iLeft + 1.5f - left.y()) * rightSlope);
    1102             Q16Dot16 rightIntersectAf = FloatToQ16Dot16(top.x() - 0.5f + (iTop + 0.5f - top.y()) * rightSlope);
    1103             Q16Dot16 rightIntersectBf = FloatToQ16Dot16(right.x() - 0.5f + (iRight + 1.5f - right.y()) * leftSlope);
     1124            Q16Dot16 leftIntersectAf = FloatToQ16Dot16(top.x() + 0.5f + (iTop + 0.5f - top.y()) * topLeftSlope);
     1125            Q16Dot16 leftIntersectBf = FloatToQ16Dot16(left.x() + 0.5f + (iLeft + 1.5f - left.y()) * bottomLeftSlope);
     1126            Q16Dot16 rightIntersectAf = FloatToQ16Dot16(top.x() - 0.5f + (iTop + 0.5f - top.y()) * topRightSlope);
     1127            Q16Dot16 rightIntersectBf = FloatToQ16Dot16(right.x() - 0.5f + (iRight + 1.5f - right.y()) * bottomRightSlope);
    11041128
    11051129            int ny;
     
    11231147             }
    11241148
    1125             DO_SEGMENT(iMiddle, leftIntersectAf, rightIntersectAf, leftSlopeFP, rightSlopeFP)
    1126             DO_SEGMENT(iRight, leftIntersectBf, rightIntersectAf, rightSlopeFP, rightSlopeFP)
    1127             DO_SEGMENT(iLeft, leftIntersectAf, rightIntersectBf, leftSlopeFP, leftSlopeFP)
    1128             DO_SEGMENT(iBottom, leftIntersectBf, rightIntersectBf, rightSlopeFP, leftSlopeFP)
     1149            DO_SEGMENT(iMiddle, leftIntersectAf, rightIntersectAf, topLeftSlopeFP, topRightSlopeFP)
     1150            DO_SEGMENT(iRight, leftIntersectBf, rightIntersectAf, bottomLeftSlopeFP, topRightSlopeFP)
     1151            DO_SEGMENT(iLeft, leftIntersectAf, rightIntersectBf, topLeftSlopeFP, bottomRightSlopeFP);
     1152            DO_SEGMENT(iBottom, leftIntersectBf, rightIntersectBf, bottomLeftSlopeFP, bottomRightSlopeFP);
    11291153#undef DO_SEGMENT
    11301154        }
     
    11761200
    11771201    d->scanConverter.end();
    1178 }
    1179 
    1180 static inline QT_FT_Vector PointToVector(const QPointF &p)
    1181 {
    1182     QT_FT_Vector result = { QT_FT_Pos(p.x() * 64), QT_FT_Pos(p.y() * 64) };
    1183     return result;
    11841202}
    11851203
  • trunk/src/gui/painting/qrasterizer_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qregion.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    712712
    713713/*!
     714    \fn bool QRegion::intersects(const QRect &rect) const
    714715    \since 4.2
    715716
     
    717718    returns false.
    718719*/
    719 bool QRegion::intersects(const QRect &rect) const
    720 {
    721     if (isEmpty() || rect.isNull())
    722         return false;
    723 
    724     const QRect r = rect.normalized();
    725     if (!rect_intersects(boundingRect(), r))
    726         return false;
    727     if (rectCount() == 1)
    728         return true;
    729 
    730     const QVector<QRect> myRects = rects();
    731     for (QVector<QRect>::const_iterator it = myRects.constBegin(); it < myRects.constEnd(); ++it)
    732         if (rect_intersects(r, *it))
    733             return true;
    734     return false;
    735 }
     720
    736721
    737722#if !defined (Q_OS_UNIX) && !defined (Q_WS_WIN) && !defined (Q_WS_PM)
     
    17261711QT_END_INCLUDE_NAMESPACE
    17271712
    1728 /*  1 if two BOXs overlap.
    1729  *  0 if two BOXs do not overlap.
     1713/*  1 if two BOXes overlap.
     1714 *  0 if two BOXes do not overlap.
    17301715 *  Remember, x2 and y2 are not in the region
    17311716 */
     
    43764361}
    43774362
     4363bool QRegion::intersects(const QRect &rect) const
     4364{
     4365    if (isEmptyHelper(d->qt_rgn) || rect.isNull())
     4366        return false;
     4367
     4368    const QRect r = rect.normalized();
     4369    if (!rect_intersects(d->qt_rgn->extents, r))
     4370        return false;
     4371    if (d->qt_rgn->numRects == 1)
     4372        return true;
     4373
     4374    const QVector<QRect> myRects = rects();
     4375    for (QVector<QRect>::const_iterator it = myRects.constBegin(); it < myRects.constEnd(); ++it)
     4376        if (rect_intersects(r, *it))
     4377            return true;
     4378    return false;
     4379}
     4380
     4381
    43784382#endif
    43794383QT_END_NAMESPACE
  • trunk/src/gui/painting/qregion.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    213213        void *xrectangles;
    214214#elif defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)
    215         mutable RgnHandle unused; // Here for binary compatability reasons. ### Qt 5 remove.
     215        mutable RgnHandle unused; // Here for binary compatibility reasons. ### Qt 5 remove.
    216216#endif
    217217#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) || defined(Q_WS_PM)
  • trunk/src/gui/painting/qregion_mac.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qregion_qws.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qregion_s60.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qregion_win.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qregion_x11.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qrgb.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6565
    6666Q_GUI_EXPORT_INLINE int qAlpha(QRgb rgb)                // get alpha part of RGBA
    67 { return ((rgb >> 24) & 0xff); }
     67{ return rgb >> 24; }
    6868
    6969Q_GUI_EXPORT_INLINE QRgb qRgb(int r, int g, int b)// set RGB value
  • trunk/src/gui/painting/qstroker.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    121121{
    122122public:
    123     QSubpathFlatIterator(const QDataBuffer<QStrokerOps::Element> *path)
    124         : m_path(path), m_pos(0), m_curve_index(-1) { }
     123    QSubpathFlatIterator(const QDataBuffer<QStrokerOps::Element> *path, qreal threshold)
     124        : m_path(path), m_pos(0), m_curve_index(-1), m_curve_threshold(threshold) { }
    125125
    126126    inline bool hasNext() const { return m_curve_index >= 0 || m_pos < m_path->size(); }
     
    153153                                                  qt_fixed_to_real(m_path->at(m_pos+1).y)),
    154154                                          QPointF(qt_fixed_to_real(m_path->at(m_pos+2).x),
    155                                                   qt_fixed_to_real(m_path->at(m_pos+2).y))).toPolygon();
     155                                                  qt_fixed_to_real(m_path->at(m_pos+2).y))).toPolygon(m_curve_threshold);
    156156            m_curve_index = 1;
    157157            e.type = QPainterPath::LineToElement;
     
    170170    QPolygonF m_curve;
    171171    int m_curve_index;
     172    qreal m_curve_threshold;
    172173};
    173174
     
    188189
    189190QStrokerOps::QStrokerOps()
    190     : m_customData(0), m_moveTo(0), m_lineTo(0), m_cubicTo(0)
     191    : m_elements(0)
     192    , m_curveThreshold(qt_real_to_fixed(0.25))
     193    , m_dashThreshold(qt_real_to_fixed(0.25))
     194    , m_customData(0)
     195    , m_moveTo(0)
     196    , m_lineTo(0)
     197    , m_cubicTo(0)
    191198{
    192199}
     
    195202{
    196203}
    197 
    198204
    199205/*!
     
    239245        return;
    240246
     247    setCurveThresholdFromTransform(QTransform());
    241248    begin(customData);
    242249    int count = path.elementCount();
     
    309316    if (!pointCount)
    310317        return;
     318
     319    setCurveThresholdFromTransform(QTransform());
    311320    begin(data);
    312321    if (matrix.isIdentity()) {
     
    349358    }
    350359
     360    setCurveThresholdFromTransform(QTransform());
    351361    begin(data);
    352362    moveTo(qt_real_to_fixed(start.x()), qt_real_to_fixed(start.y()));
     
    367377    m_strokeWidth = qt_real_to_fixed(1);
    368378    m_miterLimit = qt_real_to_fixed(2);
    369     m_curveThreshold = qt_real_to_fixed(0.25);
    370379}
    371380
    372381QStroker::~QStroker()
    373382{
    374 
    375383}
    376384
     
    603611            QLineF miterLine(QPointF(qt_fixed_to_real(focal_x),
    604612                                     qt_fixed_to_real(focal_y)), isect);
    605             if (miterLine.length() > qt_fixed_to_real(m_strokeWidth * m_miterLimit) / 2) {
     613            if (type == QLineF::NoIntersection || miterLine.length() > qt_fixed_to_real(m_strokeWidth * m_miterLimit) / 2) {
    606614                emitLineTo(qt_real_to_fixed(nextLine.x1()),
    607615                           qt_real_to_fixed(nextLine.y1()));
     
    10441052}
    10451053
     1054static inline bool lineRectIntersectsRect(qfixed2d p1, qfixed2d p2, const qfixed2d &tl, const qfixed2d &br)
     1055{
     1056    return ((p1.x > tl.x || p2.x > tl.x) && (p1.x < br.x || p2.x < br.x)
     1057        && (p1.y > tl.y || p2.y > tl.y) && (p1.y < br.y || p2.y < br.y));
     1058}
     1059
     1060// If the line intersects the rectangle, this function will return true.
     1061static bool lineIntersectsRect(qfixed2d p1, qfixed2d p2, const qfixed2d &tl, const qfixed2d &br)
     1062{
     1063    if (!lineRectIntersectsRect(p1, p2, tl, br))
     1064        return false;
     1065    if (p1.x == p2.x || p1.y == p2.y)
     1066        return true;
     1067
     1068    if (p1.y > p2.y)
     1069        qSwap(p1, p2); // make p1 above p2
     1070    qfixed2d u;
     1071    qfixed2d v;
     1072    qfixed2d w = {p2.x - p1.x, p2.y - p1.y};
     1073    if (p1.x < p2.x) {
     1074        // backslash
     1075        u.x = tl.x - p1.x; u.y = br.y - p1.y;
     1076        v.x = br.x - p1.x; v.y = tl.y - p1.y;
     1077    } else {
     1078        // slash
     1079        u.x = tl.x - p1.x; u.y = tl.y - p1.y;
     1080        v.x = br.x - p1.x; v.y = br.y - p1.y;
     1081    }
     1082#if defined(QFIXED_IS_26_6) || defined(QFIXED_IS_16_16)
     1083    qint64 val1 = qint64(u.x) * qint64(w.y) - qint64(u.y) * qint64(w.x);
     1084    qint64 val2 = qint64(v.x) * qint64(w.y) - qint64(v.y) * qint64(w.x);
     1085    return (val1 < 0 && val2 > 0) || (val1 > 0 && val2 < 0);
     1086#elif defined(QFIXED_IS_32_32)
     1087    // Cannot do proper test because it may overflow.
     1088    return true;
     1089#else
     1090    qreal val1 = u.x * w.y - u.y * w.x;
     1091    qreal val2 = v.x * w.y - v.y * w.x;
     1092    return (val1 < 0 && val2 > 0) || (val1 > 0 && val2 < 0);
     1093#endif
     1094}
    10461095
    10471096void QDashStroker::processCurrentSubpath()
     
    10681117        return;
    10691118
     1119    qreal invSumLength = qreal(1) / sumLength;
     1120
    10701121    Q_ASSERT(dashCount > 0);
    10711122
    1072     dashCount = (dashCount / 2) * 2; // Round down to even number
     1123    dashCount = dashCount & -2; // Round down to even number
    10731124
    10741125    int idash = 0; // Index to current dash
     
    10781129
    10791130    // make sure doffset is in range [0..sumLength)
    1080     doffset -= qFloor(doffset / sumLength) * sumLength;
     1131    doffset -= qFloor(doffset * invSumLength) * sumLength;
    10811132
    10821133    while (doffset >= dashes[idash]) {
    10831134        doffset -= dashes[idash];
    1084         idash = (idash + 1) % dashCount;
     1135        if (++idash >= dashCount)
     1136            idash = 0;
    10851137    }
    10861138
     
    10921144    QPainterPath dashPath;
    10931145
    1094     QSubpathFlatIterator it(&m_elements);
     1146    QSubpathFlatIterator it(&m_elements, m_dashThreshold);
    10951147    qfixed2d prev = it.next();
    10961148
     
    11201172
    11211173        bool done = pos >= estop;
     1174
     1175        if (clipping) {
     1176            // Check if the entire line can be clipped away.
     1177            if (!lineIntersectsRect(prev, e, clip_tl, clip_br)) {
     1178                // Cut away full dash sequences.
     1179                elen -= qFloor(elen * invSumLength) * sumLength;
     1180                // Update dash offset.
     1181                while (!done) {
     1182                    qreal dpos = pos + dashes[idash] - doffset - estart;
     1183
     1184                    Q_ASSERT(dpos >= 0);
     1185
     1186                    if (dpos > elen) { // dash extends this line
     1187                        doffset = dashes[idash] - (dpos - elen); // subtract the part already used
     1188                        pos = estop; // move pos to next path element
     1189                        done = true;
     1190                    } else { // Dash is on this line
     1191                        pos = dpos + estart;
     1192                        done = pos >= estop;
     1193                        if (++idash >= dashCount)
     1194                            idash = 0;
     1195                        doffset = 0; // full segment so no offset on next.
     1196                    }
     1197                }
     1198                hasMoveTo = false;
     1199                move_to_pos = e;
     1200            }
     1201        }
     1202
    11221203        // Dash away...
    11231204        while (!done) {
    11241205            QPointF p2;
    11251206
    1126             int idash_incr = 0;
    11271207            bool has_offset = doffset > 0;
     1208            bool evenDash = (idash & 1) == 0;
    11281209            qreal dpos = pos + dashes[idash] - doffset - estart;
    11291210
     
    11391220                pos = dpos + estart;
    11401221                done = pos >= estop;
    1141                 idash_incr = 1;
     1222                if (++idash >= dashCount)
     1223                    idash = 0;
    11421224                doffset = 0; // full segment so no offset on next.
    11431225            }
    11441226
    1145             if (idash % 2 == 0) {
     1227            if (evenDash) {
    11461228                line_to_pos.x = qt_real_to_fixed(p2.x());
    11471229                line_to_pos.y = qt_real_to_fixed(p2.y());
    11481230
    1149                 // If we have an offset, we're continuing a dash
    1150                 // from a previous element and should only
    1151                 // continue the current dash, without starting a
    1152                 // new subpath.
    1153                 if (!has_offset || !hasMoveTo) {
    1154                     emitMoveTo(move_to_pos.x, move_to_pos.y);
    1155                     hasMoveTo = true;
     1231                if (!clipping
     1232                    || lineRectIntersectsRect(move_to_pos, line_to_pos, clip_tl, clip_br))
     1233                {
     1234                    // If we have an offset, we're continuing a dash
     1235                    // from a previous element and should only
     1236                    // continue the current dash, without starting a
     1237                    // new subpath.
     1238                    if (!has_offset || !hasMoveTo) {
     1239                        emitMoveTo(move_to_pos.x, move_to_pos.y);
     1240                        hasMoveTo = true;
     1241                    }
     1242
     1243                    emitLineTo(line_to_pos.x, line_to_pos.y);
     1244                } else {
     1245                    hasMoveTo = false;
    11561246                }
    1157 
    1158                 if (!clipping
    1159                     // if move_to is inside...
    1160                     || (move_to_pos.x > clip_tl.x && move_to_pos.x < clip_br.x
    1161                      && move_to_pos.y > clip_tl.y && move_to_pos.y < clip_br.y)
    1162                     // Or if line_to is inside...
    1163                     || (line_to_pos.x > clip_tl.x && line_to_pos.x < clip_br.x
    1164                      && line_to_pos.y > clip_tl.y && line_to_pos.y < clip_br.y))
    1165                 {
    1166                     emitLineTo(line_to_pos.x, line_to_pos.y);
    1167                 }
     1247                move_to_pos = line_to_pos;
    11681248            } else {
    11691249                move_to_pos.x = qt_real_to_fixed(p2.x());
    11701250                move_to_pos.y = qt_real_to_fixed(p2.y());
    11711251            }
    1172 
    1173             idash = (idash + idash_incr) % dashCount;
    11741252        }
    11751253
  • trunk/src/gui/painting/qstroker_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    125125                                    void *data);
    126126
     127// qtransform.cpp
     128Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
     129
    127130class Q_GUI_EXPORT QStrokerOps
    128131{
     
    162165    void setClipRect(const QRectF &clip) { m_clip_rect = clip; }
    163166
     167    void setCurveThresholdFromTransform(const QTransform &transform)
     168    {
     169        qreal scale;
     170        qt_scaleForTransform(transform, &scale);
     171        m_dashThreshold = scale == 0 ? qreal(0.5) : (qreal(0.5) / scale);
     172    }
     173
     174    void setCurveThreshold(qfixed threshold) { m_curveThreshold = threshold; }
     175    qfixed curveThreshold() const { return m_curveThreshold; }
     176
    164177protected:
    165178    inline void emitMoveTo(qfixed x, qfixed y);
     
    171184
    172185    QRectF m_clip_rect;
     186    qfixed m_curveThreshold;
     187    qfixed m_dashThreshold;
    173188
    174189    void *m_customData;
     
    209224    qfixed miterLimit() const { return m_miterLimit; }
    210225
    211     void setCurveThreshold(qfixed threshold) { m_curveThreshold = threshold; }
    212     qfixed curveThreshold() const { return m_curveThreshold; }
    213 
    214226    void joinPoints(qfixed x, qfixed y, const QLineF &nextLine, LineJoinMode join);
    215227    inline void emitMoveTo(qfixed x, qfixed y);
     
    228240    qfixed m_strokeWidth;
    229241    qfixed m_miterLimit;
    230     qfixed m_curveThreshold;
    231242
    232243    LineJoinMode m_capStyle;
  • trunk/src/gui/painting/qstylepainter.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qstylepainter.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qtessellator.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qtessellator_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qtextureglyphcache.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4848#include "private/qfontengine_ft_p.h"
    4949
    50 #ifndef QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH
    51 #define QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH 256
    52 #endif
    53 
    5450QT_BEGIN_NAMESPACE
    5551
    5652// #define CACHE_DEBUG
    5753
    58 void QTextureGlyphCache::populate(const QTextItemInt &ti,
    59                                   const QVarLengthArray<glyph_t> &glyphs,
    60                                   const QVarLengthArray<QFixedPoint> &)
     54// returns the highest number closest to v, which is a power of 2
     55// NB! assumes 32 bit ints
     56static inline int qt_next_power_of_two(int v)
     57{
     58    v--;
     59    v |= v >> 1;
     60    v |= v >> 2;
     61    v |= v >> 4;
     62    v |= v >> 8;
     63    v |= v >> 16;
     64    ++v;
     65    return v;
     66}
     67
     68bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs,
     69                                  const QFixedPoint *)
    6170{
    6271#ifdef CACHE_DEBUG
    63     printf("Populating with '%s'\n", QString::fromRawData(ti.chars, ti.num_chars).toLatin1().data());
     72    printf("Populating with %d glyphs\n", numGlyphs);
    6473    qDebug() << " -> current transformation: " << m_transform;
    6574#endif
    6675
    67     m_current_textitem = &ti;
     76    m_current_fontengine = fontEngine;
    6877    const int margin = glyphMargin();
     78    const int paddingDoubled = glyphPadding() * 2;
    6979
    7080    QHash<glyph_t, Coord> listItemCoordinates;
     
    7282
    7383    // check each glyph for its metrics and get the required rowHeight.
    74     for (int i=0; i < glyphs.size(); ++i) {
     84    for (int i=0; i < numGlyphs; ++i) {
    7585        const glyph_t glyph = glyphs[i];
    7686        if (coords.contains(glyph))
     
    7888        if (listItemCoordinates.contains(glyph))
    7989            continue;
    80         glyph_metrics_t metrics = ti.fontEngine->boundingBox(glyph, m_transform);
     90        glyph_metrics_t metrics = fontEngine->boundingBox(glyph, m_transform);
    8191
    8292#ifdef CACHE_DEBUG
    83         printf("'%c' (%4x): w=%.2f, h=%.2f, xoff=%.2f, yoff=%.2f, x=%.2f, y=%.2f, ti.ascent=%.2f, ti.descent=%.2f\n",
    84                ti.chars[i].toLatin1(),
     93        printf("(%4x): w=%.2f, h=%.2f, xoff=%.2f, yoff=%.2f, x=%.2f, y=%.2f\n",
    8594               glyph,
    8695               metrics.width.toReal(),
     
    8998               metrics.yoff.toReal(),
    9099               metrics.x.toReal(),
    91                metrics.y.toReal(),
    92                ti.ascent.toReal(),
    93                ti.descent.toReal());
     100               metrics.y.toReal());
    94101#endif
    95102        int glyph_width = metrics.width.ceil().toInt();
     
    113120    }
    114121    if (listItemCoordinates.isEmpty())
    115         return;
    116 
    117     rowHeight += margin * 2;
     122        return true;
     123
     124    rowHeight += margin * 2 + paddingDoubled;
    118125    if (isNull())
    119         createCache(QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH, rowHeight);
     126        createCache(QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH, qt_next_power_of_two(rowHeight));
    120127
    121128    // now actually use the coords and paint the wanted glyps into cache.
     
    124131        Coord c = iter.value();
    125132
     133        m_currentRowHeight = qMax(m_currentRowHeight, c.h + margin * 2);
     134
    126135        if (m_cx + c.w > m_w) {
    127             // no room on the current line, start new glyph strip
    128             m_cx = 0;
    129             m_cy = m_h;
     136            int new_width = m_w*2;
     137            while (new_width < m_cx + c.w)
     138                new_width *= 2;
     139            if (new_width <= maxTextureWidth()) {
     140                resizeTextureData(new_width, m_h);
     141                m_w = new_width;
     142            } else {
     143                // no room on the current line, start new glyph strip
     144                m_cx = 0;
     145                m_cy += m_currentRowHeight + paddingDoubled;
     146                m_currentRowHeight = c.h + margin * 2; // New row
     147            }
    130148        }
    131149        if (m_cy + c.h > m_h) {
    132             int new_height;
    133             if (m_cx == 0) { // add a whole row
    134                 new_height = m_h + rowHeight;
    135                 m_cy = m_h;
    136             } else { // just extend row
    137                 new_height = m_cy + rowHeight;
    138             }
     150            int new_height = m_h*2;
     151            while (new_height < m_cy + c.h)
     152                new_height *= 2;
     153
     154            if (maxTextureHeight() > 0 && new_height > maxTextureHeight()) {
     155                // We can't make a new texture of the required size, so
     156                // bail out
     157                return false;
     158            }
     159
    139160            // if no room in the current texture - realloc a larger texture
    140161            resizeTextureData(m_w, new_height);
     
    148169        coords.insert(iter.key(), c);
    149170
    150         if (m_cx + c.w > m_w) {
    151             m_cx = 0;
    152             m_cy += rowHeight;
    153         } else {
    154             // for the Mono case, glyph_width is 8-bit aligned,
    155             // and therefore so will m_cx
    156             m_cx += c.w;
    157         }
     171        m_cx += c.w + paddingDoubled;
    158172        ++iter;
    159173    }
    160174
    161 
     175    return true;
    162176}
    163177
     
    183197        };
    184198
    185         QFontEngineFT *ft = static_cast<QFontEngineFT*> (m_current_textitem->fontEngine);
     199        QFontEngineFT *ft = static_cast<QFontEngineFT*> (m_current_fontengine);
    186200        QFontEngineFT::QGlyphSet *gset = ft->loadTransformedGlyphSet(m_transform);
    187201
    188202        if (gset && ft->loadGlyphs(gset, &g, 1, format)) {
    189             QFontEngineFT::Glyph *glyph = gset->glyph_data.value(g);
     203            QFontEngineFT::Glyph *glyph = gset->getGlyph(g);
    190204            const int bytesPerLine = (format == QFontEngineFT::Format_Mono ? ((glyph->width + 31) & ~31) >> 3
    191205                               : (glyph->width + 3) & ~3);
     
    195209#endif
    196210    if (m_type == QFontEngineGlyphCache::Raster_RGBMask)
    197         return m_current_textitem->fontEngine->alphaRGBMapForGlyph(g, glyphMargin(), m_transform);
     211        return m_current_fontengine->alphaRGBMapForGlyph(g, glyphMargin(), m_transform);
    198212    else
    199         return m_current_textitem->fontEngine->alphaMapForGlyph(g, m_transform);
     213        return m_current_fontengine->alphaMapForGlyph(g, m_transform);
    200214
    201215    return QImage();
     
    253267#endif
    254268
    255     if (m_type == QFontEngineGlyphCache::Raster_RGBMask) {
    256         QPainter p(&m_image);
     269    if (m_type == QFontEngineGlyphCache::Raster_RGBMask) {       
     270        QImage ref(m_image.bits() + (c.x * 4 + c.y * m_image.bytesPerLine()),
     271                   qMax(mask.width(), c.w), qMax(mask.height(), c.h), m_image.bytesPerLine(),
     272                   m_image.format());
     273        QPainter p(&ref);
    257274        p.setCompositionMode(QPainter::CompositionMode_Source);
    258         p.fillRect(c.x, c.y, c.w, c.h, QColor(0,0,0,0)); // TODO optimize this
    259         p.drawImage(c.x, c.y, mask);
     275        p.fillRect(0, 0, c.w, c.h, QColor(0,0,0,0)); // TODO optimize this
     276        p.drawImage(0, 0, mask);
    260277        p.end();
    261278    } else if (m_type == QFontEngineGlyphCache::Raster_Mono) {
     
    325342    if (m_image.rect().contains(base))
    326343        m_image.setPixel(base, 255);
    327     m_image.save(QString::fromLatin1("cache-%1-%2-%3.png")
    328                  .arg(m_current_textitem->font().family())
    329                  .arg(m_current_textitem->font().pointSize())
    330                  .arg(m_transform.type()));
     344    m_image.save(QString::fromLatin1("cache-%1.png").arg(int(this)));
    331345#endif
    332346}
  • trunk/src/gui/painting/qtextureglyphcache_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6565#endif
    6666
     67#ifndef QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH
     68#define QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH 256
     69#endif
     70
    6771struct glyph_metrics_t;
    6872typedef unsigned int glyph_t;
     
    7781public:
    7882    QTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix)
    79         : QFontEngineGlyphCache(matrix, type), m_w(0), m_h(0), m_cx(0), m_cy(0) { }
     83        : QFontEngineGlyphCache(matrix, type), m_current_fontengine(0),
     84                                               m_w(0), m_h(0), m_cx(0), m_cy(0), m_currentRowHeight(0)
     85        { }
    8086
    8187    virtual ~QTextureGlyphCache() { }
     
    9197    };
    9298
    93     void populate(const QTextItemInt &ti,
    94                   const QVarLengthArray<glyph_t> &glyphs,
    95                   const QVarLengthArray<QFixedPoint> &positions);
     99    bool populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs,
     100                  const QFixedPoint *positions);
    96101
    97102    virtual void createTextureData(int width, int height) = 0;
    98103    virtual void resizeTextureData(int width, int height) = 0;
    99104    virtual int glyphMargin() const { return 0; }
     105    virtual int glyphPadding() const { return 0; }
    100106
    101107    virtual void fillTexture(const Coord &coord, glyph_t glyph) = 0;
     
    112118
    113119    QImage textureMapForGlyph(glyph_t g) const;
     120    virtual int maxTextureWidth() const { return QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH; }
     121    virtual int maxTextureHeight() const { return -1; }
    114122
    115123protected:
    116     const QTextItemInt *m_current_textitem;
     124    QFontEngine *m_current_fontengine;
    117125
    118126    int m_w; // image width
     
    120128    int m_cx; // current x
    121129    int m_cy; // current y
     130    int m_currentRowHeight; // Height of last row
    122131};
    123132
    124133
    125 class QImageTextureGlyphCache : public QTextureGlyphCache
     134class Q_GUI_EXPORT QImageTextureGlyphCache : public QTextureGlyphCache
    126135{
    127136public:
  • trunk/src/gui/painting/qtransform.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4848#include "qvariant.h"
    4949#include <qmath.h>
     50#include <qnumeric.h>
    5051
    5152#include <private/qbezier_p.h>
     
    148149    QPaintDevice has its origin located at the top-left position. The
    149150    \e x values increase to the right; \e y values increase
    150     downward. For a complete description, see the \l {The Coordinate
    151     System}{coordinate system} documentation.
     151    downward. For a complete description, see the \l {Coordinate
     152    System} {coordinate system} documentation.
    152153
    153154    QPainter has functions to translate, scale, shear and rotate the
     
    223224    \endtable
    224225
    225     \sa QPainter, {The Coordinate System}, {demos/affine}{Affine
     226    \sa QPainter, {Coordinate System}, {demos/affine}{Affine
    226227    Transformations Demo}, {Transformations Example}
    227228*/
     
    411412    if (dx == 0 && dy == 0)
    412413        return *this;
     414#ifndef QT_NO_DEBUG
     415    if (qIsNaN(dx) | qIsNaN(dy)) {
     416        qWarning() << "QTransform::translate with NaN called";
     417        return *this;
     418    }
     419#endif
    413420
    414421    switch(inline_type()) {
     
    448455QTransform QTransform::fromTranslate(qreal dx, qreal dy)
    449456{
     457#ifndef QT_NO_DEBUG
     458    if (qIsNaN(dx) | qIsNaN(dy)) {
     459        qWarning() << "QTransform::fromTranslate with NaN called";
     460        return QTransform();
     461}
     462#endif
    450463    QTransform transform(1, 0, 0, 0, 1, 0, dx, dy, 1, true);
    451464    if (dx == 0 && dy == 0)
     
    467480    if (sx == 1 && sy == 1)
    468481        return *this;
     482#ifndef QT_NO_DEBUG
     483    if (qIsNaN(sx) | qIsNaN(sy)) {
     484        qWarning() << "QTransform::scale with NaN called";
     485        return *this;
     486    }
     487#endif
    469488
    470489    switch(inline_type()) {
     
    502521QTransform QTransform::fromScale(qreal sx, qreal sy)
    503522{
     523#ifndef QT_NO_DEBUG
     524    if (qIsNaN(sx) | qIsNaN(sy)) {
     525        qWarning() << "QTransform::fromScale with NaN called";
     526        return QTransform();
     527}
     528#endif
    504529    QTransform transform(sx, 0, 0, 0, sy, 0, 0, 0, 1, true);
    505530    if (sx == 1. && sy == 1.)
     
    521546    if (sh == 0 && sv == 0)
    522547        return *this;
     548#ifndef QT_NO_DEBUG
     549    if (qIsNaN(sh) | qIsNaN(sv)) {
     550        qWarning() << "QTransform::shear with NaN called";
     551        return *this;
     552    }
     553#endif
    523554
    524555    switch(inline_type()) {
     
    576607    if (a == 0)
    577608        return *this;
     609#ifndef QT_NO_DEBUG
     610    if (qIsNaN(a)) {
     611        qWarning() << "QTransform::rotate with NaN called";
     612        return *this;
     613    }
     614#endif
    578615
    579616    qreal sina = 0;
     
    661698QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis)
    662699{
     700#ifndef QT_NO_DEBUG
     701    if (qIsNaN(a)) {
     702        qWarning() << "QTransform::rotateRadians with NaN called";
     703        return *this;
     704    }
     705#endif
    663706    qreal sina = qSin(a);
    664707    qreal cosa = qCos(a);
     
    9861029    reference to the stream.
    9871030
    988     \sa {Format of the QDataStream Operators}
     1031    \sa {Serializing Qt Data Types}
    9891032*/
    9901033QDataStream & operator<<(QDataStream &s, const QTransform &m)
     
    10101053    reference to the stream.
    10111054
    1012     \sa {Format of the QDataStream Operators}
     1055    \sa {Serializing Qt Data Types}
    10131056*/
    10141057QDataStream & operator>>(QDataStream &s, QTransform &t)
     
    10381081QDebug operator<<(QDebug dbg, const QTransform &m)
    10391082{
    1040     dbg.nospace() << "QTransform("
    1041                   << "11="  << m.m11()
     1083    static const char *typeStr[] =
     1084    {
     1085        "TxNone",
     1086        "TxTranslate",
     1087        "TxScale",
     1088        "TxRotate",
     1089        "TxShear",
     1090        "TxProject"
     1091    };
     1092
     1093    dbg.nospace() << "QTransform(type=" << typeStr[m.type()] << ','
     1094                  << " 11=" << m.m11()
    10421095                  << " 12=" << m.m12()
    10431096                  << " 13=" << m.m13()
     
    10491102                  << " 33=" << m.m33()
    10501103                  << ')';
     1104
    10511105    return dbg.space();
    10521106}
     
    14921546    return true;
    14931547}
     1548Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
    14941549
    14951550static inline bool cubicTo_clipped(QPainterPath &path, const QTransform &transform, const QPointF &a, const QPointF &b, const QPointF &c, const QPointF &d, bool needsMoveTo)
     
    14971552    // Convert projective xformed curves to line
    14981553    // segments so they can be transformed more accurately
    1499     QPolygonF segment = QBezier::fromPoints(a, b, c, d).toPolygon();
     1554
     1555    qreal scale;
     1556    qt_scaleForTransform(transform, &scale);
     1557
     1558    qreal curveThreshold = scale == 0 ? qreal(0.25) : (qreal(0.25) / scale);
     1559
     1560    QPolygonF segment = QBezier::fromPoints(a, b, c, d).toPolygon(curveThreshold);
    15001561
    15011562    for (int i = 0; i < segment.size() - 1; ++i)
     
    15661627{
    15671628    TransformationType t = inline_type();
    1568     if (t == TxNone || path.isEmpty())
     1629    if (t == TxNone || path.elementCount() == 0)
    15691630        return path;
    15701631
  • trunk/src/gui/painting/qtransform.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6565class Q_GUI_EXPORT QTransform
    6666{
    67     Q_ENUMS(TransformationType)
    6867public:
    6968    enum TransformationType {
  • trunk/src/gui/painting/qvectorpath_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qwindowsurface.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4444#include <private/qwidget_p.h>
    4545#include <private/qbackingstore_p.h>
     46#include <private/qapplication_p.h>
    4647
    4748QT_BEGIN_NAMESPACE
     
    5051{
    5152public:
    52     QWindowSurfacePrivate(QWidget *w) : window(w), staticContentsSupport(false) {}
     53    QWindowSurfacePrivate(QWidget *w)
     54        : window(w)
     55        , staticContentsSupport(0)
     56        , partialUpdateSupport(1)
     57    {
     58    }
    5359
    5460    QWidget *window;
     
    5662    QRegion staticContents;
    5763    QList<QImage*> bufferImages;
    58     bool staticContentsSupport;
     64    uint staticContentsSupport : 1;
     65    uint partialUpdateSupport : 1;
    5966};
    6067
     
    111118    : d_ptr(new QWindowSurfacePrivate(window))
    112119{
    113     if (window)
    114         window->setWindowSurface(this);
     120    if (!QApplicationPrivate::runtime_graphics_system) {
     121        if(window)
     122            window->setWindowSurface(this);
     123    }
    115124}
    116125
     
    285294void QWindowSurface::setStaticContentsSupport(bool enable)
    286295{
     296    if (enable && !d_ptr->partialUpdateSupport) {
     297        qWarning("QWindowSurface::setStaticContentsSupport: static contents support requires partial update support");
     298        return;
     299    }
    287300    d_ptr->staticContentsSupport = enable;
    288301}
     
    301314{
    302315    return d_ptr->staticContentsSupport && !d_ptr->staticContents.isEmpty();
     316}
     317
     318bool QWindowSurface::hasPartialUpdateSupport() const
     319{
     320    return d_ptr->partialUpdateSupport;
     321}
     322
     323void QWindowSurface::setPartialUpdateSupport(bool enable)
     324{
     325    if (!enable && d_ptr->staticContentsSupport) {
     326        qWarning("QWindowSurface::setPartialUpdateSupport: static contents support requires partial update support");
     327        return;
     328    }
     329    d_ptr->partialUpdateSupport = enable;
    303330}
    304331
  • trunk/src/gui/painting/qwindowsurface_mac.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qwindowsurface_mac_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qwindowsurface_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7474
    7575    virtual QPaintDevice *paintDevice() = 0;
    76     virtual void flush(QWidget *widget, const QRegion &region,
    77                        const QPoint &offset) = 0;
     76
     77    // 'widget' can be a child widget, in which case 'region' is in child widget coordinates and
     78    // offset is the (child) widget's offset in relation to the window surface. On QWS, 'offset'
     79    // can be larger than just the offset from the top-level widget as there may also be window
     80    // decorations which are painted into the window surface.
     81    virtual void flush(QWidget *widget, const QRegion &region, const QPoint &offset) = 0;
    7882    virtual void setGeometry(const QRect &rect);
    7983    QRect geometry() const;
     
    9195
    9296    bool hasStaticContentsSupport() const;
     97    bool hasPartialUpdateSupport() const;
    9398
    9499    void setStaticContents(const QRegion &region);
     
    98103    bool hasStaticContents() const;
    99104    void setStaticContentsSupport(bool enable);
     105    void setPartialUpdateSupport(bool enable);
    100106
    101107private:
  • trunk/src/gui/painting/qwindowsurface_qws.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    883883        const QColor blank = Qt::transparent;
    884884        for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) {
    885             p.fillRect(*it, blank);
     885            QRect r = *it;
     886#ifdef Q_BACKINGSTORE_SUBSURFACES
     887            r.translate(painterOffset());
     888#endif
     889            p.fillRect(r, blank);
    886890        }
    887891    }
  • trunk/src/gui/painting/qwindowsurface_qws_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qwindowsurface_raster.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qwindowsurface_raster_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qwindowsurface_s60.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4444#include <QtGui/qpaintdevice.h>
    4545#include <private/qwidget_p.h>
    46 #include "qwindowsurface_s60_p.h"
    47 #include "qpixmap_s60_p.h"
    48 #include "qt_s60_p.h"
    49 #include "private/qdrawhelper_p.h"
     46#include <private/qwindowsurface_s60_p.h>
     47#include <private/qpixmap_s60_p.h>
     48#include <private/qt_s60_p.h>
     49#include <private/qapplication_p.h>
     50#include <private/qdrawhelper_p.h>
     51
     52#ifdef QT_GRAPHICSSYSTEM_RUNTIME
     53#include <private/qgraphicssystem_runtime_p.h>
     54#endif
    5055
    5156QT_BEGIN_NAMESPACE
     
    5762};
    5863
     64TDisplayMode displayMode(bool opaque)
     65{
     66
     67    TDisplayMode mode = S60->screenDevice()->DisplayMode();
     68    if (opaque) {
     69        mode = EColor16MU;
     70    } else  {
     71        if (QSysInfo::symbianVersion() >= QSysInfo::SV_SF_3)
     72            mode = Q_SYMBIAN_ECOLOR16MAP; // Symbian^3 WServ has support for ARGB32_PRE
     73        else
     74            mode = EColor16MA; // Symbian prior to Symbian^3 sw accelerates EColor16MA
     75    }
     76    return mode;
     77}
     78
    5979QS60WindowSurface::QS60WindowSurface(QWidget* widget)
    6080    : QWindowSurface(widget), d_ptr(new QS60WindowSurfacePrivate)
    6181{
    62 
    63     TDisplayMode mode = S60->screenDevice()->DisplayMode();
    64     bool isOpaque = qt_widget_private(widget)->isOpaque;
    65     if (mode == EColor16MA && isOpaque)
    66         mode = EColor16MU; // Faster since 16MU -> 16MA is typically accelerated
    67     else if (mode == EColor16MU && !isOpaque)
    68         mode = EColor16MA; // Try for transparency anyway
    69 
     82    TDisplayMode mode = displayMode(qt_widget_private(widget)->isOpaque);
    7083    // We create empty CFbsBitmap here -> it will be resized in setGeometry
    7184    CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap);   // CBase derived object needs check on new
     
    8093    setStaticContentsSupport(true);
    8194}
     95
    8296QS60WindowSurface::~QS60WindowSurface()
    8397{
     98#if defined(QT_GRAPHICSSYSTEM_RUNTIME) && defined(Q_SYMBIAN_SUPPORTS_SURFACES)
     99    if(QApplicationPrivate::runtime_graphics_system) {
     100        QRuntimeGraphicsSystem *runtimeGraphicsSystem =
     101                static_cast<QRuntimeGraphicsSystem*>(QApplicationPrivate::graphics_system);
     102        if(runtimeGraphicsSystem->graphicsSystemName() == QLatin1String("openvg")) {
     103
     104            // Graphics system has been switched from raster to openvg.
     105            // Issue empty redraw to clear the UI surface
     106
     107            QWidget *w = window();
     108            if (w->testAttribute(Qt::WA_WState_Created)) {
     109                RWindow *const window = static_cast<RWindow *>(w->winId()->DrawableWindow());
     110                window->BeginRedraw();
     111                window->EndRedraw();
     112            }
     113        }
     114    }
     115#endif
     116
    84117    delete d_ptr;
    85118}
     
    87120void QS60WindowSurface::beginPaint(const QRegion &rgn)
    88121{
     122#ifdef Q_SYMBIAN_SUPPORTS_SURFACES
     123    S60->wsSession().Finish();
     124#endif
     125
    89126    if (!qt_widget_private(window())->isOpaque) {
    90127        QS60PixmapData *pixmapData = static_cast<QS60PixmapData *>(d_ptr->device.data_ptr().data());
     128
     129        TDisplayMode mode = displayMode(false);
     130        if (pixmapData->cfbsBitmap->DisplayMode() != mode)
     131            pixmapData->convertToDisplayMode(mode);
     132
    91133        pixmapData->beginDataAccess();
    92134
  • trunk/src/gui/painting/qwindowsurface_s60_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qwindowsurface_x11.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qwindowsurface_x11_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/painting/qwmatrix.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
Note: See TracChangeset for help on using the changeset viewer.