diff options
Diffstat (limited to 'src/gui')
59 files changed, 621 insertions, 6124 deletions
diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp index d786f3e..073c25b 100644 --- a/src/gui/dialogs/qfiledialog.cpp +++ b/src/gui/dialogs/qfiledialog.cpp @@ -1538,52 +1538,51 @@ extern QString qt_win_get_existing_directory(const QFileDialogArgs &args); #endif /*! - This is a convenience static function that returns an existing file - selected by the user. If the user presses Cancel, it returns a null - string. + This is a convenience static function that returns an existing file + selected by the user. If the user presses Cancel, it returns a null string. - \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 8 + \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 8 - The function creates a modal file dialog with the given \a parent widget. - If the parent is not 0, the dialog will be shown centered over the - parent widget. + The function creates a modal file dialog with the given \a parent widget. + If \a parent is not 0, the dialog will be shown centered over the parent + widget. - The file dialog's working directory will be set to \a dir. If \a - dir includes a file name, the file will be selected. Only files - that match the given \a filter are shown. The filter selected is - set to \a selectedFilter. The parameters \a dir, \a - selectedFilter, and \a filter may be empty strings. If you want - multiple filters, separate them with ';;', for example: + The file dialog's working directory will be set to \a dir. If \a dir + includes a file name, the file will be selected. Only files that match the + given \a filter are shown. The filter selected is set to \a selectedFilter. + The parameters \a dir, \a selectedFilter, and \a filter may be empty + strings. If you want multiple filters, separate them with ';;', for + example: - \code + \code "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)" - \endcode + \endcode - The \a options argument holds various - options about how to run the dialog, see the QFileDialog::Option enum for - more information on the flags you can pass. + The \a options argument holds various options about how to run the dialog, + see the QFileDialog::Option enum for more information on the flags you can + pass. - The dialog's caption is set to \a caption. If \a caption is not - specified then a default caption will be used. + The dialog's caption is set to \a caption. If \a caption is not specified + then a default caption will be used. - Under Windows and Mac OS X, this static function will use the native - file dialog and not a QFileDialog. + On Windows and Mac OS X, this static function will use the native file + dialog and not a QFileDialog. - Note that on Windows the dialog will spin a blocking modal event loop - that will not dispatch any QTimers, and if parent is not 0 then it will - position the dialog just under the parent's title bar. + On Windows the dialog will spin a blocking modal event loop that will not + dispatch any QTimers, and if \a parent is not 0 then it will position the + dialog just below the parent's title bar. - Under Unix/X11, the normal behavior of the file dialog is to resolve - and follow symlinks. For example, if \c{/usr/tmp} is a symlink to - \c{/var/tmp}, the file dialog will change to \c{/var/tmp} after - entering \c{/usr/tmp}. If \a options includes DontResolveSymlinks, - the file dialog will treat symlinks as regular directories. + On Unix/X11, the normal behavior of the file dialog is to resolve and + follow symlinks. For example, if \c{/usr/tmp} is a symlink to \c{/var/tmp}, + the file dialog will change to \c{/var/tmp} after entering \c{/usr/tmp}. If + \a options includes DontResolveSymlinks, the file dialog will treat + symlinks as regular directories. - \warning Do not delete \a parent during the execution of the dialog. - If you want to do this, you should create the dialog - yourself using one of the QFileDialog constructors. + \warning Do not delete \a parent during the execution of the dialog. If you + want to do this, you should create the dialog yourself using one of the + QFileDialog constructors. - \sa getOpenFileNames(), getSaveFileName(), getExistingDirectory() + \sa getOpenFileNames(), getSaveFileName(), getExistingDirectory() */ QString QFileDialog::getOpenFileName(QWidget *parent, const QString &caption, @@ -1626,54 +1625,53 @@ QString QFileDialog::getOpenFileName(QWidget *parent, } /*! - This is a convenience static function that will return one or more - existing files selected by the user. + This is a convenience static function that will return one or more existing + files selected by the user. - \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 9 + \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 9 - This function creates a modal file dialog with the given \a parent - widget. If the parent is not 0, the dialog will be shown centered - over the parent widget. + This function creates a modal file dialog with the given \a parent widget. + If \a parent is not 0, the dialog will be shown centered over the parent + widget. - The file dialog's working directory will be set to \a dir. If \a - dir includes a file name, the file will be selected. The filter - is set to \a filter so that only those files which match the filter - are shown. The filter selected is set to \a selectedFilter. The parameters - \a dir, \a selectedFilter and \a filter may be empty strings. If you - need multiple filters, separate them with ';;', for instance: + The file dialog's working directory will be set to \a dir. If \a dir + includes a file name, the file will be selected. The filter is set to + \a filter so that only those files which match the filter are shown. The + filter selected is set to \a selectedFilter. The parameters \a dir, + \a selectedFilter and \a filter may be empty strings. If you need multiple + filters, separate them with ';;', for instance: - \code + \code "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)" - \endcode + \endcode - The dialog's caption is set to \a caption. If \a caption is not - specified then a default caption will be used. + The dialog's caption is set to \a caption. If \a caption is not specified + then a default caption will be used. - Under Windows and Mac OS X, this static function will use the native - file dialog and not a QFileDialog. On Mac OS X, the \a dir argument - is ignored, the native dialog always displays the last visited directory. + On Windows and Mac OS X, this static function will use the native file + dialog and not a QFileDialog. - Note that on Windows the dialog will spin a blocking modal event loop - that will not dispatch any QTimers, and if parent is not 0 then it will - position the dialog just under the parent's title bar. + On Windows the dialog will spin a blocking modal event loop that will not + dispatch any QTimers, and if \a parent is not 0 then it will position the + dialog just below the parent's title bar. - Under Unix/X11, the normal behavior of the file dialog is to resolve - and follow symlinks. For example, if \c{/usr/tmp} is a symlink to - \c{/var/tmp}, the file dialog will change to \c{/var/tmp} after - entering \c{/usr/tmp}. The \a options argument holds various - options about how to run the dialog, see the QFileDialog::Option enum for - more information on the flags you can pass. + On Unix/X11, the normal behavior of the file dialog is to resolve and + follow symlinks. For example, if \c{/usr/tmp} is a symlink to \c{/var/tmp}, + the file dialog will change to \c{/var/tmp} after entering \c{/usr/tmp}. + The \a options argument holds various options about how to run the dialog, + see the QFileDialog::Option enum for more information on the flags you can + pass. - Note that if you want to iterate over the list of files, you should - iterate over a copy. For example: + \note If you want to iterate over the list of files, you should iterate + over a copy. For example: \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 10 - \warning Do not delete \a parent during the execution of the dialog. - If you want to do this, you should create the dialog - yourself using one of the QFileDialog constructors. + \warning Do not delete \a parent during the execution of the dialog. If you + want to do this, you should create the dialog yourself using one of the + QFileDialog constructors. - \sa getOpenFileName(), getSaveFileName(), getExistingDirectory() + \sa getOpenFileName(), getSaveFileName(), getExistingDirectory() */ QStringList QFileDialog::getOpenFileNames(QWidget *parent, const QString &caption, @@ -1717,54 +1715,54 @@ QStringList QFileDialog::getOpenFileNames(QWidget *parent, } /*! - This is a convenience static function that will return a file name - selected by the user. The file does not have to exist. + This is a convenience static function that will return a file name selected + by the user. The file does not have to exist. - It creates a modal file dialog with the given \a parent widget. If the - parent is not 0, the dialog will be shown centered over the parent - widget. + It creates a modal file dialog with the given \a parent widget. If + \a parent is not 0, the dialog will be shown centered over the parent + widget. - \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 11 + \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 11 - The file dialog's working directory will be set to \a dir. If \a - dir includes a file name, the file will be selected. Only files that - match the \a filter are shown. The filter selected is set to - \a selectedFilter. The parameters \a dir, \a selectedFilter, and - \a filter may be empty strings. Multiple filters are separated with ';;'. - For instance: + The file dialog's working directory will be set to \a dir. If \a dir + includes a file name, the file will be selected. Only files that match the + \a filter are shown. The filter selected is set to \a selectedFilter. The + parameters \a dir, \a selectedFilter, and \a filter may be empty strings. + Multiple filters are separated with ';;'. For instance: - \code + \code "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)" - \endcode + \endcode - The \a options argument holds various - options about how to run the dialog, see the QFileDialog::Option enum for - more information on the flags you can pass. + The \a options argument holds various options about how to run the dialog, + see the QFileDialog::Option enum for more information on the flags you can + pass. - The default filter can be chosen by setting \a selectedFilter to the desired value. + The default filter can be chosen by setting \a selectedFilter to the + desired value. - The dialog's caption is set to \a caption. If \a caption is not - specified then a default caption will be used. + The dialog's caption is set to \a caption. If \a caption is not specified, + a default caption will be used. - Under Windows and Mac OS X, this static function will use the native - file dialog and not a QFileDialog. + On Windows and Mac OS X, this static function will use the native file + dialog and not a QFileDialog. - Note that on Windows the dialog will spin a blocking modal event loop - that will not dispatch any QTimers, and if parent is not 0 then it will - position the dialog just under the parent's title bar. - On Mac OS X, the filter argument is ignored. + On Windows the dialog will spin a blocking modal event loop that will not + dispatch any QTimers, and if \a parent is not 0 then it will position the + dialog just below the parent's title bar. On Mac OS X, with its native file + dialog, the filter argument is ignored. - Under Unix/X11, the normal behavior of the file dialog is to resolve - and follow symlinks. For example, if \c{/usr/tmp} is a symlink to - \c{/var/tmp}, the file dialog will change to \c{/var/tmp} after - entering \c{/usr/tmp}. If \a options includes DontResolveSymlinks, - the file dialog will treat symlinks as regular directories. + On Unix/X11, the normal behavior of the file dialog is to resolve and + follow symlinks. For example, if \c{/usr/tmp} is a symlink to \c{/var/tmp}, + the file dialog will change to \c{/var/tmp} after entering \c{/usr/tmp}. If + \a options includes DontResolveSymlinks the file dialog will treat symlinks + as regular directories. - \warning Do not delete \a parent during the execution of the dialog. - If you want to do this, you should create the dialog - yourself using one of the QFileDialog constructors. + \warning Do not delete \a parent during the execution of the dialog. If you + want to do this, you should create the dialog yourself using one of the + QFileDialog constructors. - \sa getOpenFileName(), getOpenFileNames(), getExistingDirectory() + \sa getOpenFileName(), getOpenFileNames(), getExistingDirectory() */ QString QFileDialog::getSaveFileName(QWidget *parent, const QString &caption, @@ -1810,46 +1808,43 @@ QString QFileDialog::getSaveFileName(QWidget *parent, } /*! - This is a convenience static function that will return an existing - directory selected by the user. + This is a convenience static function that will return an existing + directory selected by the user. - \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 12 + \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 12 - This function creates a modal file dialog with the given \a parent - widget. If the parent is not 0, the dialog will be shown centered over - the parent widget. + This function creates a modal file dialog with the given \a parent widget. + If \a parent is not 0, the dialog will be shown centered over the parent + widget. - The dialog's working directory is set to \a dir, and the caption is - set to \a caption. Either of these may be an empty string in which case - the current directory and a default caption will be used - respectively. + The dialog's working directory is set to \a dir, and the caption is set to + \a caption. Either of these may be an empty string in which case the + current directory and a default caption will be used respectively. - The \a options argument holds various - options about how to run the dialog, see the QFileDialog::Option enum for - more information on the flags you can pass. Note that \l{QFileDialog::}{ShowDirsOnly} - must be set to ensure a native file dialog. + The \a options argument holds various options about how to run the dialog, + see the QFileDialog::Option enum for more information on the flags you can + pass. To ensure a native file dialog, \l{QFileDialog::}{ShowDirsOnly} must + be set. - Under Windows and Mac OS X, this static function will use the native - file dialog and not a QFileDialog. On Mac OS X, the \a dir argument - is ignored, the native dialog always displays the last visited directory. - On Windows CE, if the device has no native file dialog, a QFileDialog - will be used. + On Windows and Mac OS X, this static function will use the native file + dialog and not a QFileDialog. On Windows CE, if the device has no native + file dialog, a QFileDialog will be used. - Under Unix/X11, the normal behavior of the file dialog is to resolve - and follow symlinks. For example, if \c{/usr/tmp} is a symlink to - \c{/var/tmp}, the file dialog will change to \c{/var/tmp} after - entering \c{/usr/tmp}. If \a options includes DontResolveSymlinks, - the file dialog will treat symlinks as regular directories. + On Unix/X11, the normal behavior of the file dialog is to resolve and + follow symlinks. For example, if \c{/usr/tmp} is a symlink to \c{/var/tmp}, + the file dialog will change to \c{/var/tmp} after entering \c{/usr/tmp}. If + \a options includes DontResolveSymlinks, the file dialog will treat + symlinks as regular directories. - Note that on Windows the dialog will spin a blocking modal event loop - that will not dispatch any QTimers, and if parent is not 0 then it will - position the dialog just under the parent's title bar. + On Windows the dialog will spin a blocking modal event loop that will not + dispatch any QTimers, and if \a parent is not 0 then it will position the + dialog just below the parent's title bar. - \warning Do not delete \a parent during the execution of the dialog. - If you want to do this, you should create the dialog - yourself using one of the QFileDialog constructors. + \warning Do not delete \a parent during the execution of the dialog. If you + want to do this, you should create the dialog yourself using one of the + QFileDialog constructors. - \sa getOpenFileName(), getOpenFileNames(), getSaveFileName() + \sa getOpenFileName(), getOpenFileNames(), getSaveFileName() */ QString QFileDialog::getExistingDirectory(QWidget *parent, const QString &caption, diff --git a/src/gui/dialogs/qfilesystemmodel_p.h b/src/gui/dialogs/qfilesystemmodel_p.h index 0a1265a..61e8b4c 100644 --- a/src/gui/dialogs/qfilesystemmodel_p.h +++ b/src/gui/dialogs/qfilesystemmodel_p.h @@ -164,9 +164,12 @@ public: QHash<QString, QFileSystemNode *>::const_iterator iterator; for(iterator = children.constBegin() ; iterator != children.constEnd() ; ++iterator) { //On windows the root (My computer) has no path so we don't want to add a / for nothing (e.g. /C:/) - if (!path.isEmpty()) - iterator.value()->updateIcon(iconProvider, path + QLatin1Char('/') + iterator.value()->fileName); - else + if (!path.isEmpty()) { + if (path.endsWith(QLatin1Char('/'))) + iterator.value()->updateIcon(iconProvider, path + iterator.value()->fileName); + else + iterator.value()->updateIcon(iconProvider, path + QLatin1Char('/') + iterator.value()->fileName); + } else iterator.value()->updateIcon(iconProvider, iterator.value()->fileName); } } @@ -177,9 +180,12 @@ public: QHash<QString, QFileSystemNode *>::const_iterator iterator; for(iterator = children.constBegin() ; iterator != children.constEnd() ; ++iterator) { //On windows the root (My computer) has no path so we don't want to add a / for nothing (e.g. /C:/) - if (!path.isEmpty()) - iterator.value()->retranslateStrings(iconProvider, path + QLatin1Char('/') + iterator.value()->fileName); - else + if (!path.isEmpty()) { + if (path.endsWith(QLatin1Char('/'))) + iterator.value()->retranslateStrings(iconProvider, path + iterator.value()->fileName); + else + iterator.value()->retranslateStrings(iconProvider, path + QLatin1Char('/') + iterator.value()->fileName); + } else iterator.value()->retranslateStrings(iconProvider, iterator.value()->fileName); } } diff --git a/src/gui/dialogs/qfontdialog_mac.mm b/src/gui/dialogs/qfontdialog_mac.mm index 42be3be..50917a1 100644 --- a/src/gui/dialogs/qfontdialog_mac.mm +++ b/src/gui/dialogs/qfontdialog_mac.mm @@ -87,7 +87,6 @@ const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWin NSButton *mOkButton; NSButton *mCancelButton; QFontDialogPrivate *mPriv; - NSFont *mCocoaFont; QFont *mQtFont; BOOL mPanelHackedWithButtons; CGFloat mDialogExtraWidth; @@ -119,6 +118,29 @@ const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWin - (void)cleanUpAfterMyself; @end +static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont) +{ + QFont newFont; + if (cocoaFont) { + int pSize = qRound([cocoaFont pointSize]); + QString family(QCFString::toQString(reinterpret_cast<CFStringRef>([cocoaFont familyName]))); + QString typeface(QCFString::toQString(reinterpret_cast<CFStringRef>([cocoaFont fontName]))); +// qDebug() << "original family" << family << "typeface" << typeface << "psize" << pSize; + int hyphenPos = typeface.indexOf(QLatin1Char('-')); + if (hyphenPos != -1) { + typeface.remove(0, hyphenPos + 1); + } else { + typeface = QLatin1String("Normal"); + } +// qDebug() << " massaged family" << family << "typeface" << typeface << "psize" << pSize; + newFont = QFontDatabase().font(family, typeface, pSize); + newFont.setUnderline(resolveFont.underline()); + newFont.setStrikeOut(resolveFont.strikeOut()); + + } + return newFont; +} + @implementation QCocoaFontPanelDelegate - (id)initWithFontPanel:(NSFontPanel *)panel stolenContentView:(NSView *)stolenContentView @@ -134,7 +156,6 @@ const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWin mOkButton = okButton; mCancelButton = cancelButton; mPriv = priv; - mCocoaFont = 0; mPanelHackedWithButtons = (okButton != 0); mDialogExtraWidth = extraWidth; mDialogExtraHeight = extraHeight; @@ -155,42 +176,14 @@ const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWin - (void)dealloc { - if (mCocoaFont) - [mCocoaFont release]; delete mQtFont; [super dealloc]; } - (void)changeFont:(id)sender { - Q_UNUSED(sender); - - QFont newFont; - - if (mCocoaFont) - [mCocoaFont autorelease]; NSFont *dummyFont = [NSFont userFontOfSize:12.0]; - mCocoaFont = [sender convertFont:dummyFont]; - if (mCocoaFont) { - [mCocoaFont retain]; - - int pSize = qRound([mCocoaFont pointSize]); - QString family(QCFString::toQString(reinterpret_cast<CFStringRef>([mCocoaFont familyName]))); - QString typeface(QCFString::toQString(reinterpret_cast<CFStringRef>([mCocoaFont fontName]))); -// qDebug() << "original family" << family << "typeface" << typeface << "psize" << pSize; - int hyphenPos = typeface.indexOf(QLatin1Char('-')); - if (hyphenPos != -1) { - typeface.remove(0, hyphenPos + 1); - } else { - typeface = QLatin1String("Normal"); - } -// qDebug() << " massaged family" << family << "typeface" << typeface << "psize" << pSize; - newFont = QFontDatabase().font(family, typeface, pSize); - newFont.setUnderline(mQtFont->underline()); - newFont.setStrikeOut(mQtFont->strikeOut()); - } - - [self setQtFont:newFont]; + [self setQtFont:qfontForCocoaFont([sender convertFont:dummyFont], *mQtFont)]; if (mPriv) mPriv->updateSampleFont(*mQtFont); } @@ -317,6 +310,9 @@ const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWin - (void)onOkClicked { Q_ASSERT(mPanelHackedWithButtons); + NSFontManager *fontManager = [NSFontManager sharedFontManager]; + [self setQtFont:qfontForCocoaFont([fontManager convertFont:[fontManager selectedFont]], + *mQtFont)]; [[mStolenContentView window] close]; [self finishOffWithCode:NSOKButton]; } @@ -374,16 +370,7 @@ const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWin mModalSession = 0; } - // temporary hack to work around bug in deleteLater() in Qt/Mac Cocoa -#if 1 - bool deleteDialog = mPriv->fontDialog()->testAttribute(Qt::WA_DeleteOnClose); - mPriv->fontDialog()->setAttribute(Qt::WA_DeleteOnClose, false); -#endif mPriv->done((code == NSOKButton) ? QDialog::Accepted : QDialog::Rejected); -#if 1 - if (deleteDialog) - delete mPriv->fontDialog(); -#endif } else { [NSApp stopModalWithCode:code]; } diff --git a/src/gui/dialogs/qsidebar.cpp b/src/gui/dialogs/qsidebar.cpp index bfdb37e..26108d7 100644 --- a/src/gui/dialogs/qsidebar.cpp +++ b/src/gui/dialogs/qsidebar.cpp @@ -248,7 +248,11 @@ void QUrlModel::addUrls(const QList<QUrl> &list, int row, bool move) if (!url.isValid() || url.scheme() != QLatin1String("file")) continue; for (int j = 0; move && j < rowCount(); ++j) { +#if defined(Q_OS_WIN) + if (index(j, 0).data(UrlRole).toUrl().toLocalFile().toLower() == url.toLocalFile().toLower()) { +#else if (index(j, 0).data(UrlRole) == url) { +#endif removeRow(j); if (j <= row) row--; diff --git a/src/gui/embedded/qscreentransformed_qws.cpp b/src/gui/embedded/qscreentransformed_qws.cpp index f988789..46ac1d1 100644 --- a/src/gui/embedded/qscreentransformed_qws.cpp +++ b/src/gui/embedded/qscreentransformed_qws.cpp @@ -410,7 +410,9 @@ void QTransformedScreen::blit(const QImage &image, const QPoint &topLeft, #endif #ifdef QT_QWS_DEPTH_8 case 8: - if (image.depth() == 16) + if (image.format() == QImage::Format_RGB444) + SET_BLIT_FUNC(quint8, qrgb444, trans, func); + else if (image.depth() == 16) SET_BLIT_FUNC(quint8, quint16, trans, func); else SET_BLIT_FUNC(quint8, quint32, trans, func); diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 7971711..92be62f 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -885,6 +885,38 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de /*! \internal + Returns the bounding rect of this item's children (excluding itself). +*/ +void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rect) +{ + for (int i = 0; i < children.size(); ++i) { + QGraphicsItem *child = children.at(i); + QGraphicsItemPrivate *childd = child->d_ptr; + bool hasX = childd->hasTransform; + bool hasPos = !childd->pos.isNull(); + if (hasPos || hasX) { + QTransform matrix; + if (hasX) + matrix = child->transform(); + if (hasPos) { + const QPointF &p = childd->pos; + matrix *= QTransform::fromTranslate(p.x(), p.y()); + } + matrix *= *x; + *rect |= matrix.mapRect(child->boundingRect()); + if (!childd->children.isEmpty()) + childd->childrenBoundingRectHelper(&matrix, rect); + } else { + *rect |= x->mapRect(child->boundingRect()); + if (!childd->children.isEmpty()) + childd->childrenBoundingRectHelper(x, rect); + } + } +} + +/*! + \internal + Empty all cached pixmaps from the pixmap cache. */ void QGraphicsItemCache::purge() @@ -3255,13 +3287,8 @@ void QGraphicsItem::setZValue(qreal z) QRectF QGraphicsItem::childrenBoundingRect() const { QRectF childRect; - foreach (QGraphicsItem *child, children()) { - QPointF childPos = child->pos(); - QTransform matrix = child->transform(); - if (!childPos.isNull()) - matrix *= QTransform::fromTranslate(childPos.x(), childPos.y()); - childRect |= matrix.mapRect(child->boundingRect() | child->childrenBoundingRect()); - } + QTransform x; + d_ptr->childrenBoundingRectHelper(&x, &childRect); return childRect; } diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index fb0bd2d..bcbd737 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -187,6 +187,7 @@ public: void addChild(QGraphicsItem *child); void removeChild(QGraphicsItem *child); void setParentItemHelper(QGraphicsItem *parent, bool deleting); + void childrenBoundingRectHelper(QTransform *x, QRectF *rect); virtual void resolveFont(uint inheritedMask) { diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index a9d585c..7720a10 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -2809,9 +2809,7 @@ void QGraphicsView::setupViewport(QWidget *widget) const bool isGLWidget = widget->inherits("QGLWidget"); - d->accelerateScrolling = !(isGLWidget - || widget->testAttribute(Qt::WA_MSWindowsUseDirect3D) - || qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault)); + d->accelerateScrolling = !(isGLWidget); widget->setFocusPolicy(Qt::StrongFocus); diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 3b82da8..f495b31 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -1359,14 +1359,6 @@ bool QPixmap::isDetached() const void QPixmap::deref() { if (data && !data->ref.deref()) { // Destroy image if last ref -#if !defined(QT_NO_DIRECT3D) && defined(Q_WS_WIN) - if (data->classId() == QPixmapData::RasterClass) { - QRasterPixmapData *rData = static_cast<QRasterPixmapData*>(data); - if (rData->texture) - rData->texture->Release(); - rData->texture = 0; - } -#endif if (data->is_cached && qt_pixmap_cleanup_hook_64) qt_pixmap_cleanup_hook_64(cacheKey()); delete data; @@ -1938,12 +1930,6 @@ void QPixmap::detach() if (id == QPixmapData::RasterClass) { QRasterPixmapData *rasterData = static_cast<QRasterPixmapData*>(data); rasterData->image.detach(); -#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECT3D) - if (rasterData->texture) { - rasterData->texture->Release(); - rasterData->texture = 0; - } -#endif } if (data->is_cached && qt_pixmap_cleanup_hook_64 && data->ref == 1) diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h index cd3b465..a5609e4 100644 --- a/src/gui/image/qpixmap.h +++ b/src/gui/image/qpixmap.h @@ -254,8 +254,6 @@ private: friend class QWidgetPrivate; friend class QRasterPaintEngine; friend class QRasterBuffer; - friend class QDirect3DPaintEngine; - friend class QDirect3DPaintEnginePrivate; friend class QDetachedPixmap; #if !defined(QT_NO_DATASTREAM) friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QPixmap &); diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index 145b02a..b5556cd 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -50,12 +50,6 @@ #include <private/qwidget_p.h> #include <private/qdrawhelper_p.h> -#if !defined(QT_NO_DIRECT3D) && defined(Q_WS_WIN) -#include <private/qpaintengine_d3d_p.h> -#include <d3d9.h> -extern QDirect3DPaintEngine *qt_d3dEngine(); -#endif - QT_BEGIN_NAMESPACE const uchar qt_pixmap_bit_mask[] = { 0x01, 0x02, 0x04, 0x08, @@ -63,9 +57,6 @@ const uchar qt_pixmap_bit_mask[] = { 0x01, 0x02, 0x04, 0x08, QRasterPixmapData::QRasterPixmapData(PixelType type) : QPixmapData(type, RasterClass) -#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECT3D) - , texture(0) -#endif { } diff --git a/src/gui/image/qpixmap_raster_p.h b/src/gui/image/qpixmap_raster_p.h index 48d5cf8..9d3bf72 100644 --- a/src/gui/image/qpixmap_raster_p.h +++ b/src/gui/image/qpixmap_raster_p.h @@ -58,9 +58,6 @@ #ifdef Q_WS_WIN # include "qt_windows.h" -# ifndef QT_NO_DIRECT3D -# include <d3d9.h> -# endif #endif QT_BEGIN_NAMESPACE @@ -88,10 +85,6 @@ protected: int metric(QPaintDevice::PaintDeviceMetric metric) const; private: -#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECT3D) - friend class QDirect3DPaintEnginePrivate; - IDirect3DTexture9 *texture; -#endif friend class QPixmap; friend class QBitmap; friend class QDetachedPixmap; diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp index eedb6a3..458d6b9 100644 --- a/src/gui/image/qpixmapcache.cpp +++ b/src/gui/image/qpixmapcache.cpp @@ -187,6 +187,11 @@ bool QPMCache::insert(const QString& key, const QPixmap &pixmap, int cost) cacheKeys.insert(key, cacheKey); return true; } + qint64 oldCacheKey = cacheKeys.value(key, -1); + //If for the same key we add already a pixmap we should delete it + if (oldCacheKey != -1) + QCache<qint64, QDetachedPixmap>::remove(oldCacheKey); + bool success = QCache<qint64, QDetachedPixmap>::insert(cacheKey, new QDetachedPixmap(pixmap), cost); if (success) { cacheKeys.insert(key, cacheKey); diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp index 91431c4..fee19c9 100644 --- a/src/gui/itemviews/qsortfilterproxymodel.cpp +++ b/src/gui/itemviews/qsortfilterproxymodel.cpp @@ -56,6 +56,15 @@ QT_BEGIN_NAMESPACE typedef QList<QPair<QModelIndex, QPersistentModelIndex> > QModelIndexPairList; +static inline QSet<int> qVectorToSet(const QVector<int> &vector) +{ + QSet<int> set; + set.reserve(vector.size()); + for(int i=0; i < vector.size(); ++i) + set << vector.at(i); + return set; +} + class QSortFilterProxyModelLessThan { public: @@ -223,8 +232,8 @@ public: QModelIndexPairList store_persistent_indexes(); void update_persistent_indexes(const QModelIndexPairList &source_indexes); - void filter_changed(); - void handle_filter_changed( + void filter_changed(const QModelIndex &source_parent = QModelIndex()); + QSet<int> handle_filter_changed( QVector<int> &source_to_proxy, QVector<int> &proxy_to_source, const QModelIndex &source_parent, Qt::Orientation orient); @@ -928,27 +937,39 @@ void QSortFilterProxyModelPrivate::update_persistent_indexes( q->changePersistentIndexList(from, to); } + /*! \internal Updates the proxy model (adds/removes rows) based on the new filter. */ -void QSortFilterProxyModelPrivate::filter_changed() +void QSortFilterProxyModelPrivate::filter_changed(const QModelIndex &source_parent) { - QMap<QModelIndex, Mapping *>::const_iterator it; - for (it = source_index_mapping.constBegin(); it != source_index_mapping.constEnd(); ++it) { - QModelIndex source_parent = it.key(); - Mapping *m = it.value(); - handle_filter_changed(m->proxy_rows, m->source_rows, source_parent, Qt::Vertical); - handle_filter_changed(m->proxy_columns, m->source_columns, source_parent, Qt::Horizontal); + IndexMap::const_iterator it = source_index_mapping.constFind(source_parent); + if (it == source_index_mapping.constEnd()) + return; + Mapping *m = it.value(); + QSet<int> rows_removed = handle_filter_changed(m->proxy_rows, m->source_rows, source_parent, Qt::Vertical); + QSet<int> columns_removed = handle_filter_changed(m->proxy_columns, m->source_columns, source_parent, Qt::Horizontal); + QVector<QModelIndex>::iterator it2 = m->mapped_children.end(); + while (it2 != m->mapped_children.begin()) { + --it2; + const QModelIndex source_child_index = *it2; + if (rows_removed.contains(source_child_index.row()) || columns_removed.contains(source_child_index.column())) { + it2 = m->mapped_children.erase(it2); + remove_from_mapping(source_child_index); + } else { + filter_changed(source_child_index); + } } } /*! \internal + returns the removed items indexes */ -void QSortFilterProxyModelPrivate::handle_filter_changed( +QSet<int> QSortFilterProxyModelPrivate::handle_filter_changed( QVector<int> &source_to_proxy, QVector<int> &proxy_to_source, const QModelIndex &source_parent, Qt::Orientation orient) { @@ -985,6 +1006,7 @@ void QSortFilterProxyModelPrivate::handle_filter_changed( insert_source_items(source_to_proxy, proxy_to_source, source_items_insert, source_parent, orient); } + return qVectorToSet(source_items_remove); } void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &source_top_left, @@ -1035,15 +1057,14 @@ void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &sourc if (!source_rows_remove.isEmpty()) { remove_source_items(m->proxy_rows, m->source_rows, source_rows_remove, source_parent, Qt::Vertical); - QSet<int> source_rows_remove_set = source_rows_remove.toList().toSet(); - QVector<QModelIndex>::iterator it = m->mapped_children.begin(); - while (it != m->mapped_children.end()) { + QSet<int> source_rows_remove_set = qVectorToSet(source_rows_remove); + QVector<QModelIndex>::iterator it = m->mapped_children.end(); + while (it != m->mapped_children.begin()) { + --it; const QModelIndex source_child_index = *it; if (source_rows_remove_set.contains(source_child_index.row())) { it = m->mapped_children.erase(it); remove_from_mapping(source_child_index); - } else { - ++it; } } } diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index cb2b014..a1b982a 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -193,7 +193,7 @@ embedded { MENU_NIB.path = Resources MENU_NIB.version = Versions QMAKE_BUNDLE_DATA += MENU_NIB - RESOURCES += mac/maccursors.qrc + RESOURCES += mac/macresources.qrc LIBS += -framework AppKit } diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp index 921be22..c6addc1 100644 --- a/src/gui/kernel/qaction.cpp +++ b/src/gui/kernel/qaction.cpp @@ -136,27 +136,25 @@ void QActionPrivate::redoGrab(QShortcutMap &map) void QActionPrivate::redoGrabAlternate(QShortcutMap &map) { Q_Q(QAction); - for (int i = 0; i < alternateShortcutIds.size(); ++i) - if (int id = alternateShortcutIds.at(i)) + foreach (int id, alternateShortcutIds) + if (id) map.removeShortcut(id, q); alternateShortcutIds.clear(); if (alternateShortcuts.isEmpty()) return; - for (int i = 0; i < alternateShortcuts.size(); ++i) { - const QKeySequence &alternate = alternateShortcuts.at(i); + foreach (const QKeySequence& alternate, alternateShortcuts) { if (!alternate.isEmpty()) alternateShortcutIds.append(map.addShortcut(q, alternate, shortcutContext)); else alternateShortcutIds.append(0); } - if (!enabled) { - for (int i = 0; i < alternateShortcutIds.size(); ++i) - map.setShortcutEnabled(false, alternateShortcutIds.at(i), q); + foreach (int id, alternateShortcutIds) + map.setShortcutEnabled(false, id, q); } if (!autorepeat) { - for (int i = 0; i < alternateShortcutIds.size(); ++i) - map.setShortcutAutoRepeat(false, alternateShortcutIds.at(i), q); + foreach (int id, alternateShortcutIds) + map.setShortcutAutoRepeat(false, id, q); } } @@ -165,26 +163,10 @@ void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map) Q_Q(QAction); if (shortcutId) map.setShortcutEnabled(enable, shortcutId, q); - for (int i = 0; i < alternateShortcutIds.size(); ++i) - if (int id = alternateShortcutIds.at(i)) + foreach (int id, alternateShortcutIds) + if (id) map.setShortcutEnabled(enable, id, q); } - -void QActionPrivate::removeAll(QShortcutMap &map) -{ - Q_Q(QAction); - if (shortcutId) { - map.removeShortcut(shortcutId, q); - shortcutId = 0; - } - - for (int i = 0; i < alternateShortcutIds.size(); ++i) - if (int id = alternateShortcutIds.at(i)) - map.removeShortcut(id, q); - - alternateShortcutIds.clear(); -} - #endif // QT_NO_SHORTCUT @@ -633,8 +615,8 @@ QAction::~QAction() #ifndef QT_NO_SHORTCUT if (d->shortcutId && qApp) { qApp->d_func()->shortcutMap.removeShortcut(d->shortcutId, this); - for (int i = 0; i < d->alternateShortcutIds.size(); ++i) - qApp->d_func()->shortcutMap.removeShortcut(d->alternateShortcutIds.at(i), this); + foreach (int id, d->alternateShortcutIds) + qApp->d_func()->shortcutMap.removeShortcut(id, this); } #endif } @@ -1067,12 +1049,7 @@ void QAction::setVisible(bool b) d->visible = b; d->enabled = b && !d->forceDisabled && (!d->group || d->group->isEnabled()) ; #ifndef QT_NO_SHORTCUT - if (b) { - d->redoGrab(qApp->d_func()->shortcutMap); - d->redoGrabAlternate(qApp->d_func()->shortcutMap); - } else { - d->removeAll(qApp->d_func()->shortcutMap); - } + d->setShortcutEnabled(d->enabled, qApp->d_func()->shortcutMap); #endif d->sendDataChanged(); } diff --git a/src/gui/kernel/qaction_p.h b/src/gui/kernel/qaction_p.h index a5b3731..0617ef5 100644 --- a/src/gui/kernel/qaction_p.h +++ b/src/gui/kernel/qaction_p.h @@ -111,7 +111,6 @@ public: void redoGrab(QShortcutMap &map); void redoGrabAlternate(QShortcutMap &map); void setShortcutEnabled(bool enable, QShortcutMap &map); - void removeAll(QShortcutMap &map); static QShortcutMap *globalMap; #endif // QT_NO_SHORTCUT diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index fd189c7..34c135c 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -107,9 +107,6 @@ static void initResources() Q_INIT_RESOURCE(qstyle); #endif -#if !defined(QT_NO_DIRECT3D) && defined(Q_WS_WIN) - Q_INIT_RESOURCE(qpaintengine_d3d); -#endif Q_INIT_RESOURCE(qmessagebox); #if !defined(QT_NO_PRINTDIALOG) Q_INIT_RESOURCE(qprintdialog); @@ -620,13 +617,6 @@ void QApplicationPrivate::process_cmdline() and QPixmaps. Available options are \c{raster} and \c{opengl}. \endlist - The Windows version of Qt supports an additional command line option, if - Direct3D support has been compiled into Qt: - \list - \o -direct3d will make the Direct3D paint engine the default widget - paint engine in Qt. \bold {This functionality is experimental.} - \endlist - The X11 version of Qt supports some traditional X11 command line options: \list \o -display \e display, sets the X display (default is $DISPLAY). @@ -832,12 +822,13 @@ QApplication::QApplication(Display *dpy, int &argc, char **argv, #endif // Q_WS_X11 +extern void qInitDrawhelperAsm(); /*! + \fn void QApplicationPrivate::initialize() + Initializes the QApplication object, called from the constructors. */ -extern void qInitDrawhelperAsm(); - void QApplicationPrivate::initialize() { QWidgetPrivate::mapper = new QWidgetMapper; @@ -2106,8 +2097,8 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason) if (that) QApplication::sendEvent(that->style(), &in); } + emit qApp->focusChanged(prev, focus_widget); } - emit qApp->focusChanged(prev, focus_widget); } } @@ -3504,7 +3495,7 @@ void QApplication::changeOverrideCursor(const QCursor &cursor) It is necessary to call this function to start event handling. The main event loop receives events from the window system and dispatches these to the application widgets. - + Generally, no user interaction can take place before calling exec(). As a special case, modal widgets like QMessageBox can be used before calling exec(), because modal widgets call exec() to start a local event loop. diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 2f2fc2c..c1cb7e2 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -745,9 +745,6 @@ void qt_init(QApplicationPrivate *priv, int) appNoGrab = !appNoGrab; else #endif // QT_DEBUG - if (qstrcmp(argv[i], "-direct3d") == 0) - QApplication::setAttribute(Qt::AA_MSWindowsUseDirect3DByDefault); - else argv[j++] = argv[i]; } if(j < priv->argc) { diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 366e576..d7ca2f4 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -402,7 +402,7 @@ extern bool qt_xdnd_dragging; // gui or non-gui from qapplication.cpp extern bool qt_is_gui_used; -/*! +/*! \internal Try to resolve a \a symbol from \a library with the version specified by \a vernum. @@ -840,7 +840,7 @@ bool QApplicationPrivate::x11_apply_settings() } int kdeSessionVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt(); - + if (!appFont) { QFont font(QApplication::font()); QString fontDescription; @@ -1583,6 +1583,7 @@ static PtrWacomConfigOpenDevice ptrWacomConfigOpenDevice = 0; static PtrWacomConfigGetRawParam ptrWacomConfigGetRawParam = 0; static PtrWacomConfigCloseDevice ptrWacomConfigCloseDevice = 0; static PtrWacomConfigTerm ptrWacomConfigTerm = 0; +Q_GLOBAL_STATIC(QByteArray, wacomDeviceName) #endif #endif @@ -1952,11 +1953,17 @@ void qt_init(QApplicationPrivate *priv, int, { QString displayName = QLatin1String(XDisplayName(NULL)); - // apparently MITSHM only works for local displays, so do a quick check here - // to determine whether the display is local or not (not 100 % accurate) + // MITSHM only works for local displays, so do a quick check here + // to determine whether the display is local or not (not 100 % accurate). + // BGR server layouts are not supported either, since it requires the raster + // engine to work on a QImage with BGR layout. bool local = displayName.isEmpty() || displayName.lastIndexOf(QLatin1Char(':')) == 0; - if (local && (qgetenv("QT_X11_NO_MITSHM").toInt() == 0)) - X11->use_mitshm = mitshm_pixmaps; + if (local && (qgetenv("QT_X11_NO_MITSHM").toInt() == 0)) { + Visual *defaultVisual = DefaultVisual(X11->display, DefaultScreen(X11->display)); + X11->use_mitshm = mitshm_pixmaps && (defaultVisual->red_mask == 0xff0000 + && defaultVisual->green_mask == 0xff00 + && defaultVisual->blue_mask == 0xff); + } } #endif // QT_NO_MITSHM @@ -2377,6 +2384,8 @@ void qt_init(QApplicationPrivate *priv, int, #else if (devs->type == ATOM(XWacomStylus)) { deviceType = QTabletEvent::Stylus; + if (wacomDeviceName()->isEmpty()) + wacomDeviceName()->append(devs->name); gotStylus = true; } else if (devs->type == ATOM(XWacomEraser)) { deviceType = QTabletEvent::XFreeEraser; @@ -4511,8 +4520,7 @@ void fetchWacomToolId(int &deviceType, qint64 &serialId) WACOMCONFIG *config = ptrWacomConfigInit(X11->display, 0); if (config == 0) return; - const char *name = "stylus"; // TODO get this from the X config instead (users may have called it differently) - WACOMDEVICE *device = ptrWacomConfigOpenDevice (config, name); + WACOMDEVICE *device = ptrWacomConfigOpenDevice (config, wacomDeviceName()->constData()); if (device == 0) return; unsigned keys[1]; diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index dcb3564..cf66605 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -293,9 +293,18 @@ extern "C" { QPoint posDrag(localPoint.x, localPoint.y); NSDragOperation nsActions = [sender draggingSourceOperationMask]; Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations(nsActions); + QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastOperation) = nsActions; + Qt::KeyboardModifiers modifiers = Qt::NoModifier; + if ([sender draggingSource] != nil) { + // modifier flags might have changed, update it here since we don't send any input events. + QApplicationPrivate::modifier_buttons = qt_cocoaModifiers2QtModifiers([[NSApp currentEvent] modifierFlags]); + modifiers = QApplication::keyboardModifiers(); + } else { + // when the source is from another application the above technique will not work. + modifiers = qt_cocoaDragOperation2QtModifiers(nsActions); + } // send the drag enter event to the widget. - QDragEnterEvent qDEEvent(posDrag, qtAllowed, mimeData, - QApplication::mouseButtons(), QApplication::keyboardModifiers()); + QDragEnterEvent qDEEvent(posDrag, qtAllowed, mimeData, QApplication::mouseButtons(), modifiers); QApplication::sendEvent(qwidget, &qDEEvent); if (!qDEEvent.isAccepted()) { // widget is not interested in this drag, so ignore this drop data. @@ -303,24 +312,23 @@ extern "C" { return NSDragOperationNone; } else { // send a drag move event immediately after a drag enter event (as per documentation). - QDragMoveEvent qDMEvent(posDrag, qtAllowed, mimeData, - QApplication::mouseButtons(), QApplication::keyboardModifiers()); + QDragMoveEvent qDMEvent(posDrag, qtAllowed, mimeData, QApplication::mouseButtons(), modifiers); qDMEvent.setDropAction(qDEEvent.dropAction()); qDMEvent.accept(); // accept by default, since enter event was accepted. QApplication::sendEvent(qwidget, &qDMEvent); if (!qDMEvent.isAccepted() || qDMEvent.dropAction() == Qt::IgnoreAction) { // since we accepted the drag enter event, the widget expects // future drage move events. - // ### check if we need to treat this like the drag enter event. + // ### check if we need to treat this like the drag enter event. nsActions = QT_PREPEND_NAMESPACE(qt_mac_mapDropAction)(qDEEvent.dropAction()); } else { nsActions = QT_PREPEND_NAMESPACE(qt_mac_mapDropAction)(qDMEvent.dropAction()); - } + } QT_PREPEND_NAMESPACE(qt_mac_copy_answer_rect)(qDMEvent); - return nsActions; + return nsActions; } } - + - (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender { // drag enter event was rejected, so ignore the move event. @@ -338,11 +346,19 @@ extern "C" { // send drag move event to the widget QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastOperation) = nsActions; Qt::DropActions qtAllowed = QT_PREPEND_NAMESPACE(qt_mac_mapNSDragOperations)(nsActions); + Qt::KeyboardModifiers modifiers = Qt::NoModifier; + if ([sender draggingSource] != nil) { + // modifier flags might have changed, update it here since we don't send any input events. + QApplicationPrivate::modifier_buttons = qt_cocoaModifiers2QtModifiers([[NSApp currentEvent] modifierFlags]); + modifiers = QApplication::keyboardModifiers(); + } else { + // when the source is from another application the above technique will not work. + modifiers = qt_cocoaDragOperation2QtModifiers(nsActions); + } QMimeData *mimeData = dropData; if (QDragManager::self()->source()) mimeData = QDragManager::self()->dragPrivate()->data; - QDragMoveEvent qDMEvent(posDrag, qtAllowed, mimeData, - QApplication::mouseButtons(), QApplication::keyboardModifiers()); + QDragMoveEvent qDMEvent(posDrag, qtAllowed, mimeData, QApplication::mouseButtons(), modifiers); qDMEvent.setDropAction(QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec).lastAction); qDMEvent.accept(); QApplication::sendEvent(qwidget, &qDMEvent); @@ -371,12 +387,12 @@ extern "C" { - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender { [self addDropData:sender]; - + NSPoint windowPoint = [sender draggingLocation]; NSPoint globalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:windowPoint]; NSPoint localPoint = [self convertPoint:windowPoint fromView:nil]; QPoint posDrop(localPoint.x, localPoint.y); - + NSDragOperation nsActions = [sender draggingSourceOperationMask]; Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations(nsActions); QMimeData *mimeData = dropData; @@ -388,6 +404,8 @@ extern "C" { if (QDragManager::self()->object) QDragManager::self()->dragPrivate()->target = qwidget; QApplication::sendEvent(qwidget, &de); + if (QDragManager::self()->object) + QDragManager::self()->dragPrivate()->executed_action = de.dropAction(); if (!de.isAccepted()) return NO; else @@ -419,10 +437,9 @@ extern "C" { - (void) setFrameSize:(NSSize)newSize { [super setFrameSize:newSize]; - + // A change in size has required the view to be invalidated. - if ([self inLiveResize]) - { + if ([self inLiveResize]) { NSRect rects[4]; NSInteger count; [self getRectsExposedDuringLiveResize:rects count:&count]; @@ -430,9 +447,7 @@ extern "C" { { [self setNeedsDisplayInRect:rects[count]]; } - } - else - { + } else { [self setNeedsDisplay:YES]; } } @@ -567,7 +582,7 @@ extern "C" { if (!qAppInstance()->activeModalWidget() || QApplicationPrivate::tryModalHelper(qwidget, 0)) { QApplication::sendEvent(qwidget, &enterEvent); qt_mouseover = qwidget; - + // Update cursor and dispatch hover events. qt_mac_update_cursor_at_global_pos(flipPoint(globalPoint).toPoint()); if (qwidget->testAttribute(Qt::WA_Hover) && @@ -622,7 +637,7 @@ extern "C" { [viewsToLookAt addObject:qt_mac_nativeview_for(parentWidget)]; parentWidget = parentWidget->parentWidget(); } - + // Now walk through the subviews of each view and determine which subview should // get the event. We look through all the subviews at a given level with // the assumption that the last item to be found the candidate has a higher z-order. @@ -758,7 +773,7 @@ extern "C" { if (currentIManager && [currentIManager wantsToHandleMouseEvents]) { [currentIManager handleMouseEvent:theEvent]; } - + NSPoint windowPoint = [theEvent locationInWindow]; NSPoint globalPoint = [[theEvent window] convertBaseToScreen:windowPoint]; NSPoint localPoint = [self convertPoint:windowPoint fromView:nil]; @@ -767,7 +782,7 @@ extern "C" { Qt::MouseButton buttons = cocoaButton2QtButton([theEvent buttonNumber]); bool wheelOK = false; Qt::KeyboardModifiers keyMods = qt_cocoaModifiers2QtModifiers([theEvent modifierFlags]); - + // Mouse wheel deltas seem to tick in at increments of 0.1. Qt widgets // expect the delta to be a multiple of 120. const int ScrollFactor = 10 * 120; @@ -789,7 +804,7 @@ extern "C" { wheelOK = qwe2.isAccepted(); } } - + if (deltaY) { QWheelEvent qwe(qlocal, qglobal, deltaY, buttons, keyMods, Qt::Vertical); qt_sendSpontaneousEvent(qwidget, &qwe); @@ -802,7 +817,7 @@ extern "C" { wheelOK = qwe2.isAccepted(); } } - + if (deltaZ) { // Qt doesn't explicitly support wheels with a Z component. In a misguided attempt to // try to be ahead of the pack, I'm adding this extra value. @@ -891,6 +906,11 @@ extern "C" { Q_UNUSED(anImage); Q_UNUSED(aPoint); qMacDnDParams()->performedAction = operation; + if (QDragManager::self()->object + && QDragManager::self()->dragPrivate()->executed_action != Qt::ActionMask) { + qMacDnDParams()->performedAction = + qt_mac_mapDropAction(QDragManager::self()->dragPrivate()->executed_action); + } } - (QWidget *)qt_qwidget @@ -1214,13 +1234,13 @@ Qt::DropAction QDragManager::drag(QDrag *o) so we just bail early to prevent it */ if(!(GetCurrentEventButtonState() & kEventMouseButtonPrimary)) return Qt::IgnoreAction; - + if(object) { dragPrivate()->source->removeEventFilter(this); cancel(); beingCancelled = false; } - + object = o; dragPrivate()->target = 0; @@ -1232,7 +1252,7 @@ Qt::DropAction QDragManager::drag(QDrag *o) QMacPasteboard dragBoard((CFStringRef) NSDragPboard, QMacPasteboardMime::MIME_DND); dragPrivate()->data->setData(QLatin1String("application/x-qt-mime-type-name"), QByteArray()); dragBoard.setMimeData(dragPrivate()->data); - + // create the image QPoint hotspot; QPixmap pix = dragPrivate()->pixmap; @@ -1278,6 +1298,7 @@ Qt::DropAction QDragManager::drag(QDrag *o) NSSize mouseOffset = {0.0, 0.0}; NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; NSPoint windowPoint = [dndParams->theEvent locationInWindow]; + dragPrivate()->executed_action = Qt::ActionMask; // do the drag [dndParams->view retain]; [dndParams->view dragImage:image @@ -1289,6 +1310,7 @@ Qt::DropAction QDragManager::drag(QDrag *o) slideBack:YES]; [dndParams->view release]; [image release]; + dragPrivate()->executed_action = Qt::IgnoreAction; object = 0; Qt::DropAction performedAction(qt_mac_mapNSDragOperation(dndParams->performedAction)); // do post drag processing, if required. diff --git a/src/gui/kernel/qshortcut.cpp b/src/gui/kernel/qshortcut.cpp index f3c93c6..50b6e59 100644 --- a/src/gui/kernel/qshortcut.cpp +++ b/src/gui/kernel/qshortcut.cpp @@ -385,21 +385,19 @@ bool QShortcut::event(QEvent *e) { Q_D(QShortcut); bool handled = false; - if (e->type() == QEvent::Shortcut) { + if (d->sc_enabled && e->type() == QEvent::Shortcut) { QShortcutEvent *se = static_cast<QShortcutEvent *>(e); if (se->shortcutId() == d->sc_id && se->key() == d->sc_sequence){ - if (d->sc_enabled) { #ifndef QT_NO_WHATSTHIS - if (QWhatsThis::inWhatsThisMode()) { - QWhatsThis::showText(QCursor::pos(), d->sc_whatsthis); - handled = true; - } else + if (QWhatsThis::inWhatsThisMode()) { + QWhatsThis::showText(QCursor::pos(), d->sc_whatsthis); + handled = true; + } else #endif - if (se->isAmbiguous()) - emit activatedAmbiguously(); - else - emit activated(); - } + if (se->isAmbiguous()) + emit activatedAmbiguously(); + else + emit activated(); handled = true; } } diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp index 9766a69..ed9654b 100644 --- a/src/gui/kernel/qshortcutmap.cpp +++ b/src/gui/kernel/qshortcutmap.cpp @@ -370,8 +370,9 @@ bool QShortcutMap::tryShortcutEvent(QObject *o, QKeyEvent *e) default: break; } - - return true; + // If nextState is QKeySequence::ExactMatch && identicals.count == 0 + // we've only found disabled shortcuts + return identicalMatches > 0 || result == QKeySequence::PartialMatch; } /*! \internal @@ -493,7 +494,9 @@ QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e) // We don't need partials, if we have identicals if (d->identicals.size()) break; - partialFound = true; + // We only care about enabled partials, so we don't consume + // key events when all partials are disabled! + partialFound |= (*it).enabled; } } ++it; diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 52e76d8..f000292 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -515,6 +515,18 @@ Qt::KeyboardModifiers qt_cocoaModifiers2QtModifiers(ulong modifierFlags) return qtMods; } +Qt::KeyboardModifiers qt_cocoaDragOperation2QtModifiers(uint dragOperations) +{ + Qt::KeyboardModifiers qtMods =Qt::NoModifier; + if (dragOperations & NSDragOperationLink) + qtMods |= Qt::MetaModifier; + if (dragOperations & NSDragOperationGeneric) + qtMods |= Qt::ControlModifier; + if (dragOperations & NSDragOperationCopy) + qtMods |= Qt::AltModifier; + return qtMods; +} + static inline QEvent::Type cocoaEvent2QtEvent(NSUInteger eventType) { // Handle the trivial cases that can be determined from the type. diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h index ef55aa4..63a301c 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -141,6 +141,7 @@ inline QApplication *qAppInstance() { return static_cast<QApplication *>(QCoreAp struct ::TabletProximityRec; void qt_dispatchTabletProximityEvent(const ::TabletProximityRec &proxRec); Qt::KeyboardModifiers qt_cocoaModifiers2QtModifiers(ulong modifierFlags); +Qt::KeyboardModifiers qt_cocoaDragOperation2QtModifiers(uint dragOperations); inline int flipYCoordinate(int y) { return QApplication::desktop()->screenGeometry(0).height() - y; diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 9f5f18d..9f0d2a4 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -183,6 +183,7 @@ QWidgetPrivate::QWidgetPrivate(int version) : ,inDirtyList(0) ,isScrolled(0) ,isMoved(0) + ,usesDoubleBufferedGLContext(0) #ifdef Q_WS_WIN ,noPaintOnScreen(0) #endif @@ -2132,6 +2133,10 @@ QWidget *QWidget::find(WId id) If a widget is non-native (alien) and winId() is invoked on it, that widget will be provided a native handle. + On Mac OS X, the type returned depends on which framework Qt was linked + against. If Qt is using Carbon, the {WId} is actually an HIViewRef. If Qt + is using Cocoa, {WId} is a pointer to an NSView. + \note We recommend that you do not store this value as it is likely to change at run-time. @@ -4714,10 +4719,13 @@ void QWidget::render(QPaintDevice *target, const QPoint &targetOffset, if (redirected) { target = redirected; offset -= redirectionOffset; - if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp). - const QRegion redirectedSystemClip = redirected->paintEngine()->systemClip(); - if (!redirectedSystemClip.isEmpty()) - paintRegion &= redirectedSystemClip.translated(-offset); + } + + if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp). + if (QPaintEngine *targetEngine = target->paintEngine()) { + const QRegion targetSystemClip = targetEngine->systemClip(); + if (!targetSystemClip.isEmpty()) + paintRegion &= targetSystemClip.translated(-offset); } } @@ -9792,27 +9800,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) QEvent e(QEvent::MouseTrackingChange); QApplication::sendEvent(this, &e); break; } -#if !defined(QT_NO_DIRECT3D) && defined(Q_WS_WIN) - case Qt::WA_MSWindowsUseDirect3D: - if (!qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault)) { - if (on) { - if (!d->extra) - d->createExtra(); - d->extra->had_auto_fill_bg = d->extra->autoFillBackground; - d->extra->had_no_system_bg = testAttribute(Qt::WA_NoSystemBackground); - d->extra->had_paint_on_screen = testAttribute(Qt::WA_PaintOnScreen); - // enforce the opaque widget state D3D needs - d->extra->autoFillBackground = true; - setAttribute(Qt::WA_PaintOnScreen); - setAttribute(Qt::WA_NoSystemBackground); - } else if (d->extra) { - d->extra->autoFillBackground = d->extra->had_auto_fill_bg; - setAttribute(Qt::WA_PaintOnScreen, d->extra->had_paint_on_screen); - setAttribute(Qt::WA_NoSystemBackground, d->extra->had_no_system_bg); - } - } - break; -#endif case Qt::WA_NativeWindow: { QInputContext *ic = 0; if (on && !internalWinId() && testAttribute(Qt::WA_InputMethodEnabled) && hasFocus()) { diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 013fc1e..0f74c32 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -3995,6 +3995,33 @@ void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect) } } +void QWidgetPrivate::applyMaxAndMinSizeConstraints(int &w, int &h) +{ + if (QWExtra *extra = extraData()) { + w = qMin(w, extra->maxw); + h = qMin(h, extra->maxh); + w = qMax(w, extra->minw); + h = qMax(h, extra->minh); + + // Deal with size increment + if (QTLWExtra *top = topData()) { + if(top->incw) { + w = w/top->incw; + w *= top->incw; + } + if(top->inch) { + h = h/top->inch; + h *= top->inch; + } + } + } + + if (isRealWindow()) { + w = qMax(0, w); + h = qMax(0, h); + } +} + void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) { Q_Q(QWidget); @@ -4005,7 +4032,9 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) QMacCocoaAutoReleasePool pool; bool realWindow = isRealWindow(); + if (realWindow && !(w == 0 && h == 0) && !q->testAttribute(Qt::WA_DontShowOnScreen)) { + applyMaxAndMinSizeConstraints(w, h); topData()->isSetGeometry = 1; topData()->isMove = isMove; #ifndef QT_MAC_USE_COCOA @@ -4031,10 +4060,26 @@ void QWidgetPrivate::setGeometry_sys_helper(int x, int y, int w, int h, bool isM { Q_Q(QWidget); bool realWindow = isRealWindow(); - if(QWExtra *extra = extraData()) { // any size restrictions? - if(realWindow) { + + QPoint oldp = q->pos(); + QSize olds = q->size(); + const bool isResize = (olds != QSize(w, h)); + + if (!realWindow && !isResize && QPoint(x, y) == oldp) + return; + + if (isResize) + data.window_state = data.window_state & ~Qt::WindowMaximized; + + const bool visible = q->isVisible(); + data.crect = QRect(x, y, w, h); + + if (realWindow) { + if (QWExtra *extra = extraData()) { + applyMaxAndMinSizeConstraints(w, h); qt_mac_update_sizer(q); - if(q->windowFlags() & Qt::WindowMaximizeButtonHint) { + + if (q->windowFlags() & Qt::WindowMaximizeButtonHint) { #ifndef QT_MAC_USE_COCOA OSWindowRef window = qt_mac_window_for(q); if(extra->maxw && extra->maxh && extra->maxw == extra->minw @@ -4045,43 +4090,8 @@ void QWidgetPrivate::setGeometry_sys_helper(int x, int y, int w, int h, bool isM } #endif } - } - - w = qMin(w,extra->maxw); - h = qMin(h,extra->maxh); - w = qMax(w,extra->minw); - h = qMax(h,extra->minh); - - // Deal with size increment - if(QTLWExtra *top = topData()) { - if(top->incw) { - w = w/top->incw; - w *= top->incw; - } - if(top->inch) { - h = h/top->inch; - h *= top->inch; - } - } - } - - if (realWindow) { - w = qMax(0, w); - h = qMax(0, h); - } - - QPoint oldp = q->pos(); - QSize olds = q->size(); - const bool isResize = (olds != QSize(w, h)); - if(!realWindow && !isResize && QPoint(x, y) == oldp) - return; - if(isResize && q->isMaximized()) - data.window_state = data.window_state & ~Qt::WindowMaximized; - const bool visible = q->isVisible(); - data.crect = QRect(x, y, w, h); - if(realWindow) { - if(QWExtra *extra = extraData()) { //set constraints + // Update max and min constraints: const float max_f(20000); #ifndef QT_MAC_USE_COCOA #define SF(x) ((x > max_f) ? max_f : x) diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 9e93f66..8731551 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -177,11 +177,6 @@ struct QWExtra { //bit flags at the end to improve packing #if defined(Q_WS_WIN) uint shown_mode : 8; // widget show mode -#ifndef QT_NO_DIRECT3D - uint had_paint_on_screen : 1; - uint had_no_system_bg : 1; - uint had_auto_fill_bg : 1; -#endif #endif #if defined(Q_WS_X11) uint compress_events : 1; @@ -257,6 +252,7 @@ public: void macUpdateIsOpaque(); void setEnabled_helper_sys(bool enable); bool isRealWindow() const; + void applyMaxAndMinSizeConstraints(int &w, int &h); #endif void raise_sys(); @@ -535,6 +531,7 @@ public: uint inDirtyList : 1; uint isScrolled : 1; uint isMoved : 1; + uint usesDoubleBufferedGLContext : 1; #ifdef Q_WS_WIN uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine() diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index ffbb341..7374994 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -56,12 +56,6 @@ #include "private/qbackingstore_p.h" #include "private/qwindowsurface_raster_p.h" -#ifndef QT_NO_DIRECT3D -#include "private/qpaintengine_d3d_p.h" -#include "private/qwindowsurface_d3d_p.h" -#endif - - #include <qdebug.h> #include <private/qapplication_p.h> @@ -1716,11 +1710,6 @@ void QWidgetPrivate::createSysExtra() #ifndef QT_NO_DRAGANDDROP extra->dropTarget = 0; #endif -#ifndef QT_NO_DIRECT3D - extra->had_auto_fill_bg = 0; - extra->had_paint_on_screen = 0; - extra->had_no_system_bg = 0; -#endif } void QWidgetPrivate::deleteSysExtra() @@ -1931,22 +1920,6 @@ void QWidgetPrivate::setWindowOpacity_sys(qreal level) // }; // Q_GLOBAL_STATIC(QGlobalRasterPaintEngine, globalRasterPaintEngine) -#ifndef QT_NO_DIRECT3D -static void cleanup_d3d_engine(); -Q_GLOBAL_STATIC_WITH_INITIALIZER(QDirect3DPaintEngine, _qt_d3dEngine, - { - qAddPostRoutine(cleanup_d3d_engine); - }) -static void cleanup_d3d_engine() -{ - _qt_d3dEngine()->cleanup(); -} -QDirect3DPaintEngine* qt_d3dEngine() -{ - return _qt_d3dEngine(); -} -#endif - #ifndef QT_NO_DIRECTDRAW static uchar *qt_primary_surface_bits; @@ -2059,19 +2032,6 @@ void qt_win_initialize_directdraw() { } QPaintEngine *QWidget::paintEngine() const { -#ifndef QT_NO_DIRECT3D - if ((qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault) - || testAttribute(Qt::WA_MSWindowsUseDirect3D)) - && qt_d3dEngine()->hasDirect3DSupport()) - { - QDirect3DPaintEngine *engine = qt_d3dEngine(); - if (qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault)) - engine->setFlushOnEnd(false); - else - engine->setFlushOnEnd(true); - return engine; - } -#endif #ifndef QT_NO_DIRECTDRAW QOnScreenRasterPaintEngine *pe = onScreenPaintEngine(); pe->widget = this; @@ -2100,13 +2060,6 @@ QPaintEngine *QWidget::paintEngine() const QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys() { Q_Q(QWidget); -#ifndef QT_NO_DIRECT3D - extern QDirect3DPaintEngine *qt_d3dEngine(); - if (qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault) && (q->windowOpacity() == 1.0f) - && qt_d3dEngine()->hasDirect3DSupport()) { - return new QD3DWindowSurface(q); - } -#endif return new QRasterWindowSurface(q); } diff --git a/src/gui/mac/images/leopard-unified-toolbar-on.png b/src/gui/mac/images/leopard-unified-toolbar-on.png Binary files differnew file mode 100644 index 0000000..6716597 --- /dev/null +++ b/src/gui/mac/images/leopard-unified-toolbar-on.png diff --git a/src/gui/mac/maccursors.qrc b/src/gui/mac/macresources.qrc index d80a63b..9696002 100644 --- a/src/gui/mac/maccursors.qrc +++ b/src/gui/mac/macresources.qrc @@ -6,4 +6,7 @@ <file>images/waitcursor.png</file> <file>images/pluscursor.png</file> </qresource> +<qresource prefix="/trolltech/mac/style"> +<file>images/leopard-unified-toolbar-on.png</file> +</qresource> </RCC> diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 528559c..34d1779 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -103,12 +103,6 @@ win32 { painting/qprinterinfo_win.cpp \ painting/qregion_win.cpp !win32-borland:!wince*:LIBS += -lmsimg32 - contains(QT_CONFIG, direct3d) { - HEADERS += painting/qpaintengine_d3d_p.h - SOURCES += painting/qpaintengine_d3d.cpp - RESOURCES += painting/qpaintengine_d3d.qrc - LIBS += -ldxguid - } } embedded { @@ -362,8 +356,4 @@ embedded { SOURCES += painting/qwindowsurface_qws.cpp } -win32:contains(QT_CONFIG, direct3d) { - HEADERS += painting/qwindowsurface_d3d_p.h - SOURCES += painting/qwindowsurface_d3d.cpp -} diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index fbac811a..34df6c9 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -1517,13 +1517,20 @@ void QWidgetPrivate::repaint_sys(const QRegion &rgn) extra->staticContentsSize = data.crect.size(); } + QPaintEngine *engine = q->paintEngine(); + // QGLWidget does not support partial updates if: + // 1) The context is double buffered + // 2) The context is single buffered and auto-fill background is enabled. + const bool noPartialUpdateSupport = (engine && engine->type() == QPaintEngine::OpenGL) + && (usesDoubleBufferedGLContext || q->autoFillBackground()); + QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn); + #ifdef Q_WS_MAC // No difference between update() and repaint() on the Mac. - update_sys(rgn); + update_sys(toBePainted); return; #endif - QRegion toBePainted(rgn); toBePainted &= clipRect(); clipToEffectiveMask(toBePainted); if (toBePainted.isEmpty()) diff --git a/src/gui/painting/qmemrotate.cpp b/src/gui/painting/qmemrotate.cpp index 7ad0e42..4058143 100644 --- a/src/gui/painting/qmemrotate.cpp +++ b/src/gui/painting/qmemrotate.cpp @@ -537,6 +537,7 @@ QT_IMPL_MEMROTATE(quint32, quint24) QT_IMPL_MEMROTATE(quint32, quint18) QT_IMPL_MEMROTATE(quint32, quint8) QT_IMPL_MEMROTATE(quint16, quint8) +QT_IMPL_MEMROTATE(qrgb444, quint8) QT_IMPL_MEMROTATE(quint8, quint8) #ifdef QT_QWS_DEPTH_GENERIC QT_IMPL_MEMROTATE(quint32, qrgb_generic16) diff --git a/src/gui/painting/qmemrotate_p.h b/src/gui/painting/qmemrotate_p.h index bd6006b..c1eb93e 100644 --- a/src/gui/painting/qmemrotate_p.h +++ b/src/gui/painting/qmemrotate_p.h @@ -90,6 +90,7 @@ QT_DECL_MEMROTATE(quint32, quint24); QT_DECL_MEMROTATE(quint32, quint18); QT_DECL_MEMROTATE(quint32, quint8); QT_DECL_MEMROTATE(quint16, quint8); +QT_DECL_MEMROTATE(qrgb444, quint8); QT_DECL_MEMROTATE(quint8, quint8); #ifdef QT_QWS_DEPTH_GENERIC QT_DECL_MEMROTATE(quint32, qrgb_generic16); diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp index ad09060..7de1ec4 100644 --- a/src/gui/painting/qpaintengine.cpp +++ b/src/gui/painting/qpaintengine.cpp @@ -949,8 +949,8 @@ void QPaintEngine::setSystemClip(const QRegion ®ion) Q_D(QPaintEngine); d->systemClip = region; // Be backward compatible and only call d->systemStateChanged() - // if we currently have a system transform set. - if (d->hasSystemTransform) { + // if we currently have a system transform/viewport set. + if (d->hasSystemTransform || d->hasSystemViewport) { d->transformSystemClip(); d->systemStateChanged(); } diff --git a/src/gui/painting/qpaintengine_d3d.cpp b/src/gui/painting/qpaintengine_d3d.cpp deleted file mode 100644 index 9a7638b..0000000 --- a/src/gui/painting/qpaintengine_d3d.cpp +++ /dev/null @@ -1,4576 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <qdebug.h> -#include "qpaintengine_d3d_p.h" - -#include "private/qdrawhelper_p.h" -#include "private/qfont_p.h" -#include "private/qfontengine_p.h" -#include "private/qpaintengine_p.h" -#include "private/qtessellator_p.h" -#include <private/qbezier_p.h> -#include <private/qpainter_p.h> -#include <private/qpixmap_raster_p.h> -#include <private/qpolygonclipper_p.h> -#include <qbuffer.h> -#include <qcache.h> -#include <qdir.h> -#include <qfileinfo.h> -#include <qlibrary.h> -#include <qlibraryinfo.h> -#include <qmath.h> -#include <qpaintdevice.h> -#include <qpixmapcache.h> - -#include <qwidget.h> -#include <d3d9.h> -#include <d3dx9.h> - -#include <mmintrin.h> -#include <xmmintrin.h> - -QT_BEGIN_NAMESPACE - -#ifndef M_PI - #define M_PI 3.14159265358979323846 -#endif - -#define QD3D_MASK_MARGIN 1 -#define QD3D_BATCH_SIZE 256 - -// for the ClearType detection stuff.. -#ifndef SPI_GETFONTSMOOTHINGTYPE -#define SPI_GETFONTSMOOTHINGTYPE 0x200A -#endif - -#ifndef FE_FONTSMOOTHINGCLEARTYPE -#define FE_FONTSMOOTHINGCLEARTYPE 0x0002 -#endif - -//#include <performance.h> -#define PM_INIT -#define PM_MEASURE(A) -#define PM_DISPLAY - -//debugging -//#define QT_DEBUG_VERTEXBUFFER_ACCESS -//#define QT_DEBUG_D3D -//#define QT_DEBUG_D3D_CALLS - -#define QD3D_SET_MARK(output) \ - D3DPERF_SetMarker(0, QString(output).utf16()); - -#define QT_VERTEX_RESET_LIMIT 24576 -#define QT_VERTEX_BUF_SIZE 32768 -#define QD3DFVF_CSVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX2 | D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEXCOORDSIZE4(1)) - -// this is a different usage of the effect framework than intended, -// but it's convenient for us to use (See effect file) -#define PASS_STENCIL_ODDEVEN 0 -#define PASS_STENCIL_WINDING 1 -#define PASS_STENCIL_DRAW 2 -#define PASS_STENCIL_DRAW_DIRECT 3 -#define PASS_STENCIL_CLIP 4 -#define PASS_STENCIL_NOSTENCILCHECK 5 -#define PASS_STENCIL_NOSTENCILCHECK_DIRECT 6 -#define PASS_TEXT 7 -#define PASS_CLEARTYPE_TEXT 8 -#define PASS_ALIASED_LINES 9 -#define PASS_ALIASED_LINES_DIRECT 10 - -#define PASS_AA_CREATEMASK 0 -#define PASS_AA_DRAW 1 -#define PASS_AA_DRAW_DIRECT 2 - -#define D3D_STAGE_COUNT 2 -#define D3D_RENDER_STATES 210 -#define D3D_TEXTURE_STATES 33 -#define D3D_SAMPLE_STATES 14 - - -typedef HRESULT (APIENTRY *PFND3DXCREATEBUFFER)(DWORD, LPD3DXBUFFER *); -typedef HRESULT (APIENTRY *PFND3DXCREATEEFFECT)(LPDIRECT3DDEVICE9, LPCVOID, UINT, CONST D3DXMACRO *, - LPD3DXINCLUDE, DWORD, LPD3DXEFFECTPOOL, - LPD3DXEFFECT *, LPD3DXBUFFER *); -typedef D3DXMATRIX *(APIENTRY *PFND3DXMATRIXORTHOOFFCENTERLH)(D3DMATRIX *, FLOAT, FLOAT, - FLOAT, FLOAT, FLOAT, FLOAT); -typedef IDirect3D9 *(APIENTRY *PFNDIRECT3DCREATE9)(uint); - -static PFNDIRECT3DCREATE9 pDirect3DCreate9 = 0; -static PFND3DXCREATEBUFFER pD3DXCreateBuffer = 0; -static PFND3DXCREATEEFFECT pD3DXCreateEffect = 0; -static PFND3DXMATRIXORTHOOFFCENTERLH pD3DXMatrixOrthoOffCenterLH = 0; - - -class QD3DSurfaceManager : public QObject { - Q_OBJECT - -public: - enum QD3DSurfaceManagerStatus { - NoStatus = 0, - NeedsResetting = 0x01, - MaxSizeChanged = 0x02 - }; - - QD3DSurfaceManager(); - ~QD3DSurfaceManager(); - - void init(LPDIRECT3D9 object); - - void setPaintDevice(QPaintDevice *pd); - - int status() const; - void reset(); - - LPDIRECT3DSURFACE9 renderTarget(); - - LPDIRECT3DSURFACE9 surface(QPaintDevice *pd); - LPDIRECT3DSWAPCHAIN9 swapChain(QPaintDevice *pd); - void releasePaintDevice(QPaintDevice *pd); - - LPDIRECT3DDEVICE9 device(); - void cleanup(); - - QSize maxSize() const; - -private: - struct D3DSwapChain { - QSize size; - LPDIRECT3DSWAPCHAIN9 swapchain; - LPDIRECT3DSURFACE9 surface; - }; - - void updateMaxSize(); - void initPresentParameters(D3DPRESENT_PARAMETERS *params); - D3DSwapChain *createSwapChain(QWidget *w); - - QSize m_max_size; - int m_status; - QMap<QPaintDevice *, D3DSwapChain *> m_swapchains; - - LPDIRECT3DDEVICE9 m_device; - QPaintDevice *m_pd; - HWND m_dummy; - D3DSwapChain *m_current; - -private Q_SLOTS: - void cleanupPaintDevice(QObject *); -}; - -struct vertex { - D3DVECTOR pos; - DWORD color; - FLOAT s0, t0, r0, q0; - FLOAT s1, t1, r1, q1; -}; - -struct QD3DMaskPosition { - int x, y, channel; -}; - - -struct QD3DBatchItem { - enum QD3DBatchInfo { - BI_WINDING = 0x0001, - BI_AA = 0x0002, - BI_BRECT = 0x0004, - BI_MASKFULL = 0x0008, - BI_TEXT = 0x0010, - BI_MASK = 0x0020, - BI_CLIP = 0x0040, - BI_SCISSOR = 0x0080, - - BI_PIXMAP = 0x0100, - BI_IMAGE = 0x0200, - BI_COMPLEXBRUSH = 0x0400, - - BI_CLEARCLIP = 0x0800, // clip nothing (filling the clip mask with 0) - BI_TRANSFORM = 0x1000, - BI_MASKSCISSOR = 0x2000, - BI_FASTLINE = 0x4000, - BI_COSMETICPEN = 0x8000 - }; - - int m_info; - - int m_count; - int m_offset; - - QD3DMaskPosition m_maskpos; - qreal m_xoffset; - qreal m_yoffset; - qreal m_opacity; - - QPixmap m_pixmap; - QRectF m_brect; - QBrush m_brush; - - IDirect3DTexture9 *m_texture; - - qreal m_width; - qreal m_distance; - - QTransform m_matrix; - QPainter::CompositionMode m_cmode; - - QVector<int> m_pointstops; -}; - -struct QD3DBatch { - int m_item_index; - QD3DBatchItem items[QD3D_BATCH_SIZE]; -}; - -class QD3DStateManager; -class QD3DFontCache; -class QD3DDrawHelper; -class QD3DGradientCache; - -class QDirect3DPaintEnginePrivate : public QPaintEnginePrivate -{ - Q_DECLARE_PUBLIC(QDirect3DPaintEngine) - -public: - enum RenderTechnique { - RT_NoTechnique, - RT_Antialiased, - RT_Aliased, - }; - - QDirect3DPaintEnginePrivate() - : m_d3d_object(0) - , m_d3d_device(0) - , m_txop(QTransform::TxNone) - , m_effect(0) - , m_flush_on_end(0) - { init(); } - - ~QDirect3DPaintEnginePrivate(); - - bool init(); - void initDevice(); - - inline QD3DBatchItem *nextBatchItem(); - - QPolygonF brushCoordinates(const QRectF &r, bool stroke, qreal *fp) const; - void fillAliasedPath(QPainterPath path, const QRectF &brect, const QTransform &txform); - void fillAntialiasedPath(const QPainterPath &path, const QRectF &brect, - const QTransform &txform, bool stroke); - void fillPath(const QPainterPath &path, QRectF brect); - - void strokePath(const QPainterPath &path, QRectF brect, bool simple = false); - QPainterPath strokePathFastPen(const QPainterPath &path); - void strokeAliasedPath(QPainterPath path, const QRectF &brect, const QTransform &txform); - - void flushBatch(); - int flushAntialiased(int offset); - void flushAliased(QD3DBatchItem *item, int offset); - void flushText(QD3DBatchItem *item, int offset); - void flushLines(QD3DBatchItem *item, int offset); - - void updateTransform(const QTransform &matrix); - void updatePen(const QPen &pen); - void updateBrush(const QBrush &pen); - void updateClipRegion(const QRegion &clipregion, Qt::ClipOperation op = Qt::ReplaceClip); - void updateClipPath(const QPainterPath &clipregion, Qt::ClipOperation op = Qt::ReplaceClip); - void updateFont(const QFont &font); - - void setRenderTechnique(RenderTechnique technique); - - QPointF transformPoint(const QPointF &p, qreal *w) const; - - bool prepareBatch(QD3DBatchItem *item, int offset); - void prepareItem(QD3DBatchItem *item); - void cleanupItem(QD3DBatchItem *item); - void setCompositionMode(QPainter::CompositionMode mode); - - void verifyTexture(const QPixmap &pixmap); - - bool isFastRect(const QRectF &rect); - - void releaseDC(); - - void cleanup(); - bool testCaps(); - - QPixmap getPattern(Qt::BrushStyle style) const; - - // clipping - QPainterPath m_sysclip_path; - QPainterPath m_clip_path; - QRegion m_sysclip_region; - QRegion m_clip_region; - - qreal m_opacity; - D3DCOLOR m_opacity_color; - - int m_current_state; - - ID3DXEffect* m_effect; - - RenderTechnique m_current_technique; - - QTransform m_matrix; - qreal m_inv_scale; - - QPen m_pen; - Qt::BrushStyle m_pen_brush_style; - QTransform m_inv_pen_matrix; - D3DCOLOR m_pen_color; - qreal m_pen_width; - - QBrush m_brush; - Qt::BrushStyle m_brush_style; - QTransform m_inv_brush_matrix; - D3DCOLOR m_brush_color; - QTransform m_brush_origin; - - uint m_clipping_enabled : 1; - uint m_has_complex_clipping : 1; - uint m_cleartype_text: 1; - uint m_has_pen : 1; - uint m_has_cosmetic_pen : 1; - uint m_has_brush : 1; - uint m_has_fast_pen : 1; - uint m_has_aa_fast_pen : 1; - uint m_flush_on_end : 1; - uint m_supports_d3d : 1; - - QTransform::TransformationType m_txop; - - QPainter::CompositionMode m_cmode; - - QD3DSurfaceManager m_surface_manager; - QSize m_surface_size; - - LPDIRECT3D9 m_d3d_object; - LPDIRECT3DDEVICE9 m_d3d_device; - IDirect3DSurface9 *m_current_surface; - bool m_in_scene; - - QD3DGradientCache *m_gradient_cache; - QD3DDrawHelper *m_draw_helper; - QD3DBatch m_batch; - QD3DStateManager *m_statemanager; - - HDC m_dc; - IDirect3DSurface9 *m_dcsurface; - - QMap<Qt::BrushStyle, QPixmap> m_patterns; -}; - - -class QD3DStateManager : public ID3DXEffectStateManager { -public: - QD3DStateManager(LPDIRECT3DDEVICE9 pDevice, ID3DXEffect *effect); - void reset(); - - inline void startStateBlock(); - inline void endStateBlock(); - - inline void setCosmeticPen(bool enabled); - inline void setBrushMode(int mode); - inline void setTexture(LPDIRECT3DBASETEXTURE9 pTexture); - inline void setTexture(LPDIRECT3DBASETEXTURE9 pTexture, QGradient::Spread spread); - inline void setTransformation(const QTransform *matrix = 0); - inline void setProjection(const D3DXMATRIX *pMatrix); - inline void setMaskChannel(int channel); - inline void setMaskOffset(qreal x, qreal y); - inline void setFocalDistance(const qreal &fd); - - inline void beginPass(int pass); - inline void endPass(); - - STDMETHOD(QueryInterface)(REFIID iid, LPVOID *ppv); - STDMETHOD_(ULONG, AddRef)(); - STDMETHOD_(ULONG, Release)(); - - STDMETHOD(SetTransform)(D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX *pMatrix); - STDMETHOD(SetMaterial)(CONST D3DMATERIAL9 *pMaterial); - STDMETHOD(SetLight)(DWORD Index, CONST D3DLIGHT9 *pLight); - STDMETHOD(LightEnable)(DWORD Index, BOOL Enable); - STDMETHOD(SetRenderState)(D3DRENDERSTATETYPE State, DWORD Value); - STDMETHOD(SetTexture)(DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture); - STDMETHOD(SetTextureStageState)(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value); - STDMETHOD(SetSamplerState)(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value); - STDMETHOD(SetNPatchMode)(FLOAT NumSegments); - STDMETHOD(SetFVF)(DWORD FVF); - STDMETHOD(SetVertexShader)(LPDIRECT3DVERTEXSHADER9 pShader); - STDMETHOD(SetVertexShaderConstantF)(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount); - STDMETHOD(SetVertexShaderConstantI)(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount); - STDMETHOD(SetVertexShaderConstantB)(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount); - STDMETHOD(SetPixelShader)(LPDIRECT3DPIXELSHADER9 pShader); - STDMETHOD(SetPixelShaderConstantF)(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount); - STDMETHOD(SetPixelShaderConstantI)(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount); - STDMETHOD(SetPixelShaderConstantB)(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount); -private: - LPDIRECT3DVERTEXSHADER9 m_vertexshader; - LPDIRECT3DPIXELSHADER9 m_pixelshader; - - LPDIRECT3DBASETEXTURE9 m_textures[D3D_STAGE_COUNT]; - DWORD m_texturestates[D3D_STAGE_COUNT][D3D_TEXTURE_STATES]; - DWORD m_samplerstates[D3D_STAGE_COUNT][D3D_SAMPLE_STATES]; - DWORD m_renderstate[D3D_RENDER_STATES]; - - qreal m_radgradfd; - - bool m_cosmetic_pen; - int m_pass; - int m_maskchannel; - int m_brushmode; - LPDIRECT3DBASETEXTURE9 m_texture; - D3DXMATRIX m_projection; - - D3DXMATRIX m_d3dIdentityMatrix; - bool m_isIdentity; - QTransform m_transformation; - - LPDIRECT3DDEVICE9 m_pDevice; - ID3DXEffect *m_effect; - - LONG m_refs; - bool m_changed; - qreal m_xoffset, m_yoffset; - static int m_mask_channels[4][4]; -}; - -// -// font cache stuff -// - -struct QD3DGlyphCoord { - // stores the offset and size of a glyph texture - qreal x; - qreal y; - qreal width; - qreal height; - qreal log_width; - qreal log_height; - QFixed x_offset; - QFixed y_offset; -}; - -struct QD3DFontTexture { - int x_offset; // current glyph offset within the texture - int y_offset; - int width; - int height; - IDirect3DTexture9 *texture; -}; - -typedef QHash<glyph_t, QD3DGlyphCoord*> QD3DGlyphHash; -typedef QHash<QFontEngine*, QD3DGlyphHash*> QD3DFontGlyphHash; -typedef QHash<quint64, QD3DFontTexture*> QD3DFontTexHash; - -class QD3DGlyphCache : public QObject -{ - Q_OBJECT -public: - QD3DGlyphCache() - : QObject(0) - , current_cache(0) {} - ~QD3DGlyphCache(); - QD3DGlyphCoord *lookup(QFontEngine *, glyph_t); - void cacheGlyphs(QDirect3DPaintEngine *, const QTextItemInt &, const QVarLengthArray<glyph_t> &, - bool); - void cleanCache(); - inline QD3DFontTexture *fontTexture(QFontEngine *engine) { - return font_textures.constFind(reinterpret_cast<quint64>(engine)).value(); - } - -public slots: - void fontEngineDestroyed(QObject *); - -private: - QImage clearTypeGlyph(QFontEngine *, glyph_t glyph); - QD3DGlyphHash *current_cache; - QD3DFontTexHash font_textures; - QD3DFontGlyphHash font_cache; -}; - -QD3DGlyphCache::~QD3DGlyphCache() -{ -} - -QD3DGlyphCoord *QD3DGlyphCache::lookup(QFontEngine *, glyph_t g) -{ - Q_ASSERT(current_cache != 0); - QD3DGlyphHash::const_iterator it = current_cache->constFind(g); - if (it == current_cache->constEnd()) - return 0; - return it.value(); -} - -void QD3DGlyphCache::cleanCache() -{ - QList<quint64> keys = font_textures.keys(); - for (int i=0; i<keys.size(); ++i) - font_textures.value(keys.at(i))->texture->Release(); - - qDeleteAll(font_textures); - qDeleteAll(font_cache); - font_textures.clear(); - font_cache.clear(); - current_cache = 0; -} - -void QD3DGlyphCache::fontEngineDestroyed(QObject *object) -{ -// qDebug() << "=> font engine destroyed: " << object; - QFontEngine *engine = static_cast<QFontEngine *>(object); - - QD3DFontGlyphHash::iterator cache_it = font_cache.find(engine); - if (cache_it != font_cache.end()) { - QD3DGlyphHash *cache = font_cache.take(engine); - delete cache; - } - - quint64 font_key = reinterpret_cast<quint64>(engine); - QD3DFontTexture *tex = font_textures.take(font_key); - if (tex) { - tex->texture->Release(); - delete tex; - } -} - -QImage QD3DGlyphCache::clearTypeGlyph(QFontEngine *engine, glyph_t glyph) -{ - glyph_metrics_t gm = engine->boundingBox(glyph); - int glyph_x = qFloor(gm.x.toReal()); - int glyph_y = qFloor(gm.y.toReal()); - int glyph_width = qCeil((gm.x + gm.width).toReal()) - glyph_x + 2; - int glyph_height = qCeil((gm.y + gm.height).toReal()) - glyph_y + 2; - - if (glyph_width + glyph_x <= 0 || glyph_height <= 0) - return QImage(); - QImage im(glyph_width + glyph_x, glyph_height, QImage::Format_ARGB32_Premultiplied); - im.fill(0xff000000); // solid black - QPainter p(&im); - - p.setPen(Qt::white); - p.setBrush(Qt::NoBrush); - - QTextItemInt ti; - ti.ascent = engine->ascent(); - ti.descent = engine->descent(); - ti.width = glyph_width; - ti.fontEngine = engine; - - QGlyphLayoutArray<1> glyphLayout; - ti.glyphs = glyphLayout; - ti.glyphs.glyphs[0] = glyph; - ti.glyphs.advances_x[0] = glyph_width; - p.drawTextItem(QPointF(-glyph_x, -glyph_y), ti); - p.end(); - return im; -} - -#if 0 -static void dump_font_texture(QD3DFontTexture *tex) -{ - QColor color(Qt::red); - D3DLOCKED_RECT rect; - if (FAILED(tex->texture->LockRect(0, &rect, 0, 0))) { - qDebug() << "debug: unable to lock texture rect."; - return; - } - -// cleartype version -// uint *tex_data = (uint *) rect.pBits; -// QImage im(tex->width, tex->height, QImage::Format_ARGB32); -// for (int y=0; y<tex->height; ++y) { -// for (int x=0; x<tex->width; ++x) { -// im.setPixel(x, y, ((*(tex_data+x+y*tex->width)))); -// } -// } - uchar *tex_data = (uchar *) rect.pBits; - QImage im(rect.Pitch, tex->height, QImage::Format_ARGB32); - for (int y=0; y<tex->height; ++y) { - for (int x=0; x<rect.Pitch; ++x) { - uchar val = ((*(tex_data+x+y*rect.Pitch))); - im.setPixel(x, y, 0xff000000 | (val << 16) | (val << 8) | val); - } - } - tex->texture->UnlockRect(0); - static int i= 0; - im.save(QString("tx%1.png").arg(i++)); -} -#endif - -void QD3DGlyphCache::cacheGlyphs(QDirect3DPaintEngine *engine, const QTextItemInt &ti, - const QVarLengthArray<glyph_t> &glyphs, bool clearType) -{ - IDirect3DDevice9 *device = engine->d_func()->m_d3d_device; - QD3DFontGlyphHash::const_iterator cache_it = font_cache.constFind(ti.fontEngine); - QD3DGlyphHash *cache = 0; - if (cache_it == font_cache.constEnd()) { - cache = new QD3DGlyphHash; - font_cache.insert(ti.fontEngine, cache); - connect(ti.fontEngine, SIGNAL(destroyed(QObject *)), SLOT(fontEngineDestroyed(QObject *))); - } else { - cache = cache_it.value(); - } - - current_cache = cache; - - D3DFORMAT tex_format = clearType ? D3DFMT_A8R8G8B8 : D3DFMT_A8; - quint64 font_key = reinterpret_cast<quint64>(ti.fontEngine); - QD3DFontTexHash::const_iterator it = font_textures.constFind(font_key); - QD3DFontTexture *font_tex = 0; - if (it == font_textures.constEnd()) { - // alloc a new texture, put it into the cache - int tex_height = qCeil(ti.ascent.toReal() + ti.descent.toReal()) + 5; - int tex_width = tex_height * 30; // ### - IDirect3DTexture9 *tex; - if (FAILED(device->CreateTexture(tex_width, tex_height, 1, 0, - tex_format, D3DPOOL_MANAGED, &tex, NULL))) - { - qWarning("QD3DGlyphCache::cacheGlyphs(): can't allocate font texture (%dx%d).", - tex_width, tex_height); - return; - } else { -// qDebug() << "=> new font texture: " << QSize(tex_width,tex_height); - font_tex = new QD3DFontTexture; - font_tex->texture = tex; - font_tex->x_offset = 0; - font_tex->y_offset = 0; - font_tex->width = tex_width; - font_tex->height = tex_height; - font_textures.insert(font_key, font_tex); - } - } else { - font_tex = it.value(); - // make it current render target.. - } - - // cache each glyph - for (int i=0; i<glyphs.size(); ++i) { - QD3DGlyphHash::const_iterator it = cache->constFind(glyphs[i]); - if (it == cache->constEnd()) { - glyph_metrics_t metrics = ti.fontEngine->boundingBox(glyphs[i]); - int glyph_width = qCeil(metrics.width.toReal()) + 5; - int glyph_height = qCeil(ti.ascent.toReal() + ti.descent.toReal()) + 5; - if (font_tex->x_offset + glyph_width > font_tex->width) { - // no room on the current line, start new glyph strip - int strip_height = glyph_height; - font_tex->x_offset = 0; - font_tex->y_offset += strip_height; - if (font_tex->y_offset >= font_tex->height) { - // if no room in the current texture - realloc a larger texture - int old_tex_height = font_tex->height; - font_tex->height += strip_height; - - IDirect3DTexture9 *new_tex; - if (FAILED(device->CreateTexture(font_tex->width, font_tex->height, 1, 0, - tex_format, D3DPOOL_MANAGED, &new_tex, NULL))) - { - qWarning("QD3DGlyphCache(): can't re-allocate font texture."); - return; - } else { -// qDebug() << " -> new glyph strip added:" << QSize(font_tex->width,font_tex->height); - - D3DLOCKED_RECT new_rect, old_rect; - if (FAILED(font_tex->texture->LockRect(0, &old_rect, 0, D3DLOCK_READONLY))) { - qDebug() << "QD3DGlyphCache: unable to lock texture rect."; - return; - } - if (FAILED(new_tex->LockRect(0, &new_rect, 0, 0))) { - qDebug() << "QD3DGlyphCache: unable to lock texture rect."; - return; - } - memcpy(new_rect.pBits, old_rect.pBits, new_rect.Pitch * old_tex_height); - font_tex->texture->UnlockRect(0); - new_tex->UnlockRect(0); - engine->d_func()->flushBatch(); - font_tex->texture->Release(); - font_tex->texture = new_tex; - } - - // update the texture coords and the y offset for the existing glyphs in - // the cache, because of the texture size change - QD3DGlyphHash::iterator it = cache->begin(); - while (it != cache->end()) { - it.value()->height = (it.value()->height * old_tex_height) / font_tex->height; - it.value()->y = (it.value()->y * old_tex_height) / font_tex->height; - ++it; - } - } - } - QD3DGlyphCoord *d3d_glyph = new QD3DGlyphCoord; - d3d_glyph->x = qreal(font_tex->x_offset) / font_tex->width; - d3d_glyph->y = qreal(font_tex->y_offset) / font_tex->height; - d3d_glyph->width = qreal(glyph_width) / font_tex->width; - d3d_glyph->height = qreal(glyph_height) / font_tex->height; - d3d_glyph->log_width = d3d_glyph->width * font_tex->width; - d3d_glyph->log_height = d3d_glyph->height * font_tex->height; - d3d_glyph->x_offset = -metrics.x; - d3d_glyph->y_offset = metrics.y; - - QImage glyph_im; - if (clearType) - glyph_im = clearTypeGlyph(ti.fontEngine, glyphs[i]); - else - glyph_im = ti.fontEngine->alphaMapForGlyph(glyphs[i]).convertToFormat(QImage::Format_Indexed8); - - // write glyph to texture - D3DLOCKED_RECT rect; - RECT glyph_rect = { font_tex->x_offset, font_tex->y_offset, - font_tex->x_offset + glyph_im.width(), - font_tex->y_offset + glyph_im.height() }; - -// qDebug() << " > new glyph char added:" << QSize(glyph_im.width(), glyph_im.height()); - if (FAILED(font_tex->texture->LockRect(0, &rect, &glyph_rect, 0))) { - qDebug() << "QD3DGlyphCache: unable to lock texture rect."; - return; - } - - // ### unify these loops - if (clearType) { - int ppl = rect.Pitch / 4; - uint *tex_data = (uint *) rect.pBits; - for (int y=0; y<glyph_im.height(); ++y) { - uint *s = (uint *) glyph_im.scanLine(y); - for (int x=0; x<glyph_im.width(); ++x) { - tex_data[ppl*y + x] = *s; - ++s; - } - } - } else { - int ppl = rect.Pitch; - uchar *tex_data = (uchar *) rect.pBits; - for (int y=0; y<glyph_im.height(); ++y) { - uchar *s = (uchar *) glyph_im.scanLine(y); - for (int x=0; x<glyph_im.width(); ++x) { - tex_data[ppl*y + x] = *s; - ++s; - } - } - } - font_tex->texture->UnlockRect(0); - - // debug -// dump_font_texture(font_tex); - - if (font_tex->x_offset + glyph_width > font_tex->width) { - font_tex->x_offset = 0; - font_tex->y_offset += glyph_height; - } else { - font_tex->x_offset += glyph_width; - } - - cache->insert(glyphs[i], d3d_glyph); - } - } -} - -Q_GLOBAL_STATIC(QD3DGlyphCache, qd3d_glyph_cache) - -// -// end font caching stuff -// - - -// -// D3D image cache stuff -// - -// ### keep the GL stuff in mind.. -typedef void (*_qt_image_cleanup_hook_64)(qint64); -extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64; - -static void qd3d_image_cleanup(qint64 key); - -class QD3DImage -{ -public: - QD3DImage(IDirect3DDevice9 *device, const QImage &image); - ~QD3DImage(); - - IDirect3DTexture9 *texture; -}; - -static QList<IDirect3DTexture9 *> qd3d_release_list; - -QD3DImage::QD3DImage(IDirect3DDevice9 *device, const QImage &image) -{ - texture = 0; - Q_ASSERT(device); - QImage im = image.convertToFormat(QImage::Format_ARGB32); - if (FAILED(device->CreateTexture(im.width(), im.height(), 1, 0, - D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, 0))) { - qWarning("QD3DImage(): unable to create Direct3D texture."); - return; - } -// qDebug(" -> created image texture: %p - 0x%08x%08x",texture,uint (image.cacheKey() >> 32),uint (image.cacheKey() & 0xffffffff)); - D3DLOCKED_RECT rect; - if (FAILED(texture->LockRect(0, &rect, 0, 0))) { - qDebug() << "QD3DImage: unable to lock texture rect."; - return; - } - DWORD *dst = (DWORD *) rect.pBits; - DWORD *src = (DWORD *) im.scanLine(0); - - Q_ASSERT((rect.Pitch/4) == (im.bytesPerLine()/4)); - memcpy(dst, src, rect.Pitch*im.height()); - texture->UnlockRect(0); -} - -QD3DImage::~QD3DImage() -{ - if (texture) - qd3d_release_list.append(texture); -} - -static int qd3d_cache_limit = 64*1024; // cache ~64 MB worth of textures -typedef QCache<quint64, QD3DImage> QD3DImageCache; - -class QD3DImageManager -{ -public: - QD3DImageManager() { - // ### GL does the same! - qt_image_cleanup_hook_64 = qd3d_image_cleanup; - cache.setMaxCost(qd3d_cache_limit); - } - ~QD3DImageManager() { -// qDebug() << "unhooking d3d image cache"; - qt_image_cleanup_hook_64 = 0; - cache.clear(); - } - - IDirect3DTexture9 *lookup(IDirect3DDevice9 *device, const QImage &image); - void remove(quint64 key); - -private: - QD3DImageCache cache; -}; - -IDirect3DTexture9 *QD3DImageManager::lookup(IDirect3DDevice9 *device, const QImage &image) -{ - QD3DImage *tex_image = 0; - - tex_image = cache.object(image.cacheKey()); - if (!tex_image) { - // to avoid cache thrashing we remove images from the cache - // that have the same serial no as the cached image, since - // that image is most likely destoyed already, and we got a - // stale cache entry - uint serial = (uint) (image.cacheKey() >> 32); - QList<quint64> keys = cache.keys(); - for (int i=0; i<keys.size(); ++i) { - if ((uint)(keys.at(i) >> 32) == serial) { - cache.remove(keys.at(i)); - break; - } - } -// qDebug(" => cached: %d, adding cache image: 0x%08x%08x",cache.size(), uint (image.cacheKey() >> 32),uint (image.cacheKey() & 0xffffffff)); - // add cache entry - int cost = image.width()*image.height()*4/1024; - if (cache.totalCost() + cost > cache.maxCost()) { - // no room for new entries? kick out half the cached images - int old_max_cost = cache.maxCost(); - cache.setMaxCost(old_max_cost/2); - cache.setMaxCost(old_max_cost); - } - tex_image = new QD3DImage(device, image); - cache.insert(image.cacheKey(), tex_image, cost); -// qDebug() << "==> total cache cost: " << cache.totalCost() << cost; - } - - return tex_image->texture; -} - -void QD3DImageManager::remove(quint64 key) -{ -// QList<quint64> keys = cache.keys(); -// if (keys.contains(key)) -// qDebug() << "entery removed from cache"; - cache.remove(key); -} - -Q_GLOBAL_STATIC(QD3DImageManager, qd3d_image_cache) - -static void qd3d_image_cleanup(qint64 key) -{ -// qDebug() << "qd3d_image_cleanup:"; -// qDebug(" => key: 0x%08x%08x", (uint) (key >> 32), (uint)(key & 0xffffffff)); - qd3d_image_cache()->remove(key); -} - -// -// end D3D image cache stuff -// - -class QD3DDrawHelper : public QTessellator -{ -public: - QD3DDrawHelper(QDirect3DPaintEnginePrivate *pe); - ~QD3DDrawHelper(); - - bool needsFlushing() const; - QD3DMaskPosition allocateMaskPosition(const QRectF &brect, bool *breakbatch); - - void setClipPath(const QPainterPath &path, QD3DBatchItem **item); - - void queueAntialiasedMask(const QPolygonF &poly, QD3DBatchItem **item, const QRectF &brect); - QRectF queueAliasedMask(const QPainterPath &path, QD3DBatchItem **item, D3DCOLOR color); - - void queueRect(const QRectF &rect, QD3DBatchItem *item, D3DCOLOR color, const QPolygonF &trect); - void queueRect(const QRectF &rect, QD3DBatchItem *item, D3DCOLOR color); - - void queueTextGlyph(const QRectF &rect, const qreal *tex_coords, QD3DBatchItem *item, - D3DCOLOR color); - - void queueAntialiasedLines(const QPainterPath &path, QD3DBatchItem **item, const QRectF &brect); - void queueAliasedLines(const QLineF *lines, int lineCount, QD3DBatchItem **item); - - int drawAntialiasedMask(int offset, int maxoffset); - void drawAliasedMask(int offset); - void drawAntialiasedBoundingRect(QD3DBatchItem *item); - void drawAliasedBoundingRect(QD3DBatchItem *item); - void drawTextItem(QD3DBatchItem *item); - void drawAliasedLines(QD3DBatchItem *item); - - void setMaskSize(QSize size); - - void beforeReset(); - void afterReset(); - - IDirect3DSurface9 *freeMaskSurface(); - - inline void lockVertexBuffer(); - inline void unlockVertexBuffer(); - - inline int index() { return m_index; } - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - enum VertexBufferAccess { - CLEAR = 0x00, - READ = 0x01, - WRITE = 0x02 - }; - int accesscontrol[QT_VERTEX_BUF_SIZE]; -#endif - -private: - void addTrap(const Trapezoid &trap); - void tessellate(const QPolygonF &poly); - inline void lineToStencil(qreal x, qreal y); - inline void curveToStencil(const QPointF &cp1, const QPointF &cp2, const QPointF &ep); - QRectF pathToVertexArrays(const QPainterPath &path); - void resetMask(); - - QDirect3DPaintEnginePrivate *m_pe; - - qreal m_xoffset, m_yoffset; - int m_startindex; - int m_index; - int m_height, m_width; - LPDIRECT3DVERTEXBUFFER9 m_d3dvbuff; - vertex *m_vbuff; - QD3DBatchItem *m_item; - QRectF m_boundingRect; - - qreal max_x; - qreal max_y; - qreal min_x; - qreal min_y; - qreal firstx; - qreal firsty; - - QPointF tess_lastpoint; - int tess_index; - - bool m_locked; - IDirect3DTexture9 *m_mask; - IDirect3DSurface9 *m_maskSurface; - IDirect3DSurface9 *m_depthStencilSurface; - - D3DCOLOR m_color; - bool m_clearmask; - bool m_isLine; - bool m_firstPoint; - - QD3DMaskPosition m_mask_position; - int m_mask_offsetX2; - int m_mask_offsetY2; -}; - -QD3DStateManager::QD3DStateManager(LPDIRECT3DDEVICE9 pDevice, ID3DXEffect *effect) - : m_pDevice(pDevice), m_effect(effect), m_refs(0) -{ - if (FAILED(D3DXMatrixIdentity(&m_d3dIdentityMatrix))) { - qWarning("QDirect3DPaintEngine: D3DXMatrixIdentity failed"); - } - reset(); -} - -void QD3DStateManager::reset() -{ - m_radgradfd = -1; - - m_cosmetic_pen = false; - m_pass = -1; - m_maskchannel = -1; - m_brushmode = -1; - m_texture = 0; - m_xoffset = INT_MAX; - m_yoffset = INT_MAX; - - m_vertexshader = 0; - m_pixelshader = 0; - - m_isIdentity = true; - m_transformation = QTransform(); - m_effect->SetMatrix("g_mTransformation", &m_d3dIdentityMatrix); - - ZeroMemory(&m_projection, sizeof(D3DMATRIX)); - ZeroMemory(m_textures, sizeof(LPDIRECT3DBASETEXTURE9) * D3D_STAGE_COUNT); - FillMemory(m_samplerstates, sizeof(DWORD) * D3D_SAMPLE_STATES * D3D_STAGE_COUNT, 0xFFFFFFFE); - FillMemory(m_texturestates, sizeof(DWORD) * D3D_TEXTURE_STATES * D3D_STAGE_COUNT, 0xFFFFFFFE); - FillMemory(m_renderstate, sizeof(DWORD) * D3D_RENDER_STATES, 0xFFFFFFFE); -} - -inline void QD3DStateManager::beginPass(int pass) -{ - if (pass != m_pass) { - if (m_pass != -1) - m_effect->EndPass(); - m_effect->BeginPass(pass); - m_pass = pass; - } -} - -inline void QD3DStateManager::endPass() -{ - if (m_pass != -1) { - m_pass = -1; - m_effect->EndPass(); - } -} - -inline void QD3DStateManager::startStateBlock() { - m_changed = false; -} - -inline void QD3DStateManager::setCosmeticPen(bool enabled) -{ - if (enabled != m_cosmetic_pen) { - m_effect->SetBool("g_mCosmeticPen", enabled); - m_cosmetic_pen = enabled; - m_changed = true; - } -} - -inline void QD3DStateManager::setBrushMode(int mode) -{ - if (mode != m_brushmode) { - m_effect->SetInt("g_mBrushMode", mode); - m_brushmode = mode; - m_changed = true; - } -} - -inline void QD3DStateManager::setTexture(LPDIRECT3DBASETEXTURE9 pTexture) -{ - SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER); - SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER); - - if (pTexture != m_texture) { - m_texture = pTexture; - m_effect->SetTexture("g_mTexture", pTexture); - m_changed = true; - } -} - -inline void QD3DStateManager::setTexture(LPDIRECT3DBASETEXTURE9 pTexture, QGradient::Spread spread) -{ - switch(spread) { - case QGradient::RepeatSpread: - SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); - SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); - break; - case QGradient::ReflectSpread: - SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR); - SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR); - break; - default: - SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - break; - }; - - if (pTexture != m_texture) { - m_texture = pTexture; - m_effect->SetTexture("g_mTexture", pTexture); - m_changed = true; - } -} - -inline void QD3DStateManager::setTransformation(const QTransform *matrix) -{ - if (matrix) { - if (*matrix != m_transformation) { - D3DXMATRIX dxmatrix(matrix->m11(), matrix->m12(), 0, matrix->m13(), - matrix->m21(), matrix->m22(), 0, matrix->m23(), - 0, 0, 1, 0, - matrix->dx(), matrix->dy(), 0, 1); - m_effect->SetMatrix("g_mTransformation", &dxmatrix); - m_transformation = *matrix; - m_changed = true; - m_isIdentity = false; - } - } else if (!m_isIdentity) { - m_effect->SetMatrix("g_mTransformation", &m_d3dIdentityMatrix); - m_transformation = QTransform(); - m_changed = true; - m_isIdentity = true; - } -} - -inline void QD3DStateManager::setProjection(const D3DXMATRIX *pMatrix) -{ - if (*pMatrix != m_projection) { - m_effect->SetMatrix("g_mViewProjection", pMatrix); - m_projection = *pMatrix; - m_changed = true; - } -} - -inline void QD3DStateManager::setFocalDistance(const qreal &fd) -{ - if (fd != m_radgradfd) { - m_effect->SetFloat("g_mFocalDist", fd); - m_changed = true; - m_radgradfd = fd; - } -} - -inline void QD3DStateManager::setMaskOffset(qreal x, qreal y) -{ - if (x != m_xoffset || y != m_yoffset) { - float offset[2] = {x, y}; - m_effect->SetFloatArray("g_mMaskOffset", offset, 2); - m_xoffset = x; - m_yoffset = y; - m_changed = true; - } -} - -inline void QD3DStateManager::setMaskChannel(int channel) -{ - if (m_maskchannel != channel) { - m_effect->SetIntArray("g_mChannel", m_mask_channels[channel], 4); - m_maskchannel = channel; - m_changed = true; - } -} - -inline void QD3DStateManager::endStateBlock() -{ - if (m_changed) { - m_effect->CommitChanges(); - m_changed = false; - } -} - -STDMETHODIMP QD3DStateManager::QueryInterface(REFIID iid, LPVOID *ppv) -{ - if(iid == IID_IUnknown || iid == IID_ID3DXEffectStateManager) - { - *ppv = this; - ++m_refs; - return NOERROR; - } - *ppv = NULL; - return ResultFromScode(E_NOINTERFACE); -} - -STDMETHODIMP_(ULONG) QD3DStateManager::AddRef(void) -{ - return (ULONG)InterlockedIncrement( &m_refs ); -} - - -STDMETHODIMP_(ULONG) QD3DStateManager::Release(void) -{ - if( 0L == InterlockedDecrement( &m_refs ) ) { - delete this; - return 0L; - } - - return m_refs; -} -STDMETHODIMP QD3DStateManager::SetTransform(D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX *pMatrix) -{ - return m_pDevice->SetTransform(State, pMatrix); -} - -STDMETHODIMP QD3DStateManager::SetMaterial(CONST D3DMATERIAL9 *pMaterial) -{ - return m_pDevice->SetMaterial(pMaterial); -} - -STDMETHODIMP QD3DStateManager::SetLight(DWORD Index, CONST D3DLIGHT9 *pLight) -{ - return m_pDevice->SetLight(Index, pLight); -} - -STDMETHODIMP QD3DStateManager::LightEnable(DWORD Index, BOOL Enable) -{ - return m_pDevice->LightEnable(Index, Enable); -} - -STDMETHODIMP QD3DStateManager::SetRenderState(D3DRENDERSTATETYPE State, DWORD Value) -{ - if (State < D3D_RENDER_STATES) { - if (m_renderstate[State] == Value) - return S_OK; - m_renderstate[State] = Value; - } - return m_pDevice->SetRenderState(State, Value); -} - -STDMETHODIMP QD3DStateManager::SetTexture(DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture) -{ - if (Stage < D3D_STAGE_COUNT) { - if (m_textures[Stage] == pTexture) - return S_OK; - m_textures[Stage] = pTexture; - } - return m_pDevice->SetTexture(Stage, pTexture); -} - -STDMETHODIMP QD3DStateManager::SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) -{ - if (Stage < D3D_STAGE_COUNT && Type < D3D_TEXTURE_STATES) { - if (m_texturestates[Stage][Type] == Value) - return S_OK; - m_texturestates[Stage][Type] = Value; - } - return m_pDevice->SetTextureStageState(Stage, Type, Value); -} - -STDMETHODIMP QD3DStateManager::SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) -{ - if (Sampler < D3D_STAGE_COUNT && Type < D3D_SAMPLE_STATES) { - if (m_samplerstates[Sampler][Type] == Value) - return S_OK; - m_samplerstates[Sampler][Type] = Value; - } - return m_pDevice->SetSamplerState(Sampler, Type, Value); -} - -STDMETHODIMP QD3DStateManager::SetNPatchMode(FLOAT NumSegments) -{ - return m_pDevice->SetNPatchMode(NumSegments); -} - -STDMETHODIMP QD3DStateManager::SetFVF(DWORD FVF) -{ - return m_pDevice->SetFVF(FVF); -} - -STDMETHODIMP QD3DStateManager::SetVertexShader(LPDIRECT3DVERTEXSHADER9 pShader) -{ - if (m_vertexshader == pShader) - return S_OK; - m_vertexshader = pShader; - return m_pDevice->SetVertexShader(pShader); -} - -STDMETHODIMP QD3DStateManager::SetVertexShaderConstantF(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount) -{ - return m_pDevice->SetVertexShaderConstantF(RegisterIndex, pConstantData, RegisterCount); -} - -STDMETHODIMP QD3DStateManager::SetVertexShaderConstantI(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount) -{ - return m_pDevice->SetVertexShaderConstantI(RegisterIndex, pConstantData, RegisterCount); -} - -STDMETHODIMP QD3DStateManager::SetVertexShaderConstantB(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount) -{ - return m_pDevice->SetVertexShaderConstantB(RegisterIndex, pConstantData, RegisterCount); -} - -STDMETHODIMP QD3DStateManager::SetPixelShader(LPDIRECT3DPIXELSHADER9 pShader) -{ - if (m_pixelshader == pShader) - return S_OK; - m_pixelshader = pShader; - return m_pDevice->SetPixelShader(pShader); -} - -STDMETHODIMP QD3DStateManager::SetPixelShaderConstantF(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount) -{ - return m_pDevice->SetPixelShaderConstantF(RegisterIndex, pConstantData, RegisterCount); -} - -STDMETHODIMP QD3DStateManager::SetPixelShaderConstantI(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount) -{ - return m_pDevice->SetPixelShaderConstantI(RegisterIndex, pConstantData, RegisterCount); -} - -STDMETHODIMP QD3DStateManager::SetPixelShaderConstantB(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount) -{ - return m_pDevice->SetPixelShaderConstantB(RegisterIndex, pConstantData, RegisterCount); -} - -#define QD3D_GRADIENT_CACHE_SIZE 60 -#define QD3D_GRADIENT_PALETTE_SIZE 1024 - -class QD3DGradientCache -{ - struct CacheInfo - { - inline CacheInfo(QGradientStops s, qreal op) : - stops(s), opacity(op) {} - - IDirect3DTexture9 *texture; - QGradientStops stops; - qreal opacity; - }; - - typedef QMultiHash<quint64, CacheInfo> QD3DGradientColorTableHash; - -public: - QD3DGradientCache(LPDIRECT3DDEVICE9 device); - ~QD3DGradientCache(); - - inline IDirect3DTexture9 *getBuffer(const QGradientStops &stops, qreal opacity); - -protected: - inline void generateGradientColorTable(const QGradientStops& s, - uint *colorTable, - int size, qreal opacity) const; - IDirect3DTexture9 *addCacheElement(quint64 hash_val, const QGradientStops &stops, qreal opacity); - void cleanCache(); - - QD3DGradientColorTableHash cache; - LPDIRECT3DDEVICE9 m_device; -}; - -QD3DGradientCache::QD3DGradientCache(LPDIRECT3DDEVICE9 device) - : m_device(device) -{ - -} - -QD3DGradientCache::~QD3DGradientCache() -{ - cleanCache(); -} - -inline IDirect3DTexture9 *QD3DGradientCache::getBuffer(const QGradientStops &stops, qreal opacity) -{ - quint64 hash_val = 0; - - for (int i = 0; i < stops.size() && i <= 2; i++) - hash_val += stops[i].second.rgba(); - - QD3DGradientColorTableHash::const_iterator it = cache.constFind(hash_val); - - if (it == cache.constEnd()) - return addCacheElement(hash_val, stops, opacity); - else { - do { - const CacheInfo &cache_info = it.value(); - if (cache_info.stops == stops && cache_info.opacity == opacity) { - return cache_info.texture; - } - ++it; - } while (it != cache.constEnd() && it.key() == hash_val); - // an exact match for these stops and opacity was not found, create new cache - return addCacheElement(hash_val, stops, opacity); - } -} - -void QD3DGradientCache::generateGradientColorTable(const QGradientStops& s, uint *colorTable, int size, qreal opacity) const -{ - int pos = 0; - qreal fpos = 0.0; - qreal incr = 1.0 / qreal(size); - QVector<uint> colors(s.size()); - - for (int i = 0; i < s.size(); ++i) - colors[i] = s[i].second.rgba(); - - uint alpha = qRound(opacity * 255); - while (fpos < s.first().first) { - colorTable[pos] = ARGB_COMBINE_ALPHA(colors[0], alpha); - pos++; - fpos += incr; - } - - for (int i = 0; i < s.size() - 1; ++i) { - qreal delta = 1/(s[i+1].first - s[i].first); - while (fpos < s[i+1].first && pos < size) { - int dist = int(256 * ((fpos - s[i].first) * delta)); - int idist = 256 - dist; - uint current_color = ARGB_COMBINE_ALPHA(colors[i], alpha); - uint next_color = ARGB_COMBINE_ALPHA(colors[i+1], alpha); -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - colorTable[pos] = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist); -#else - uint c = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist); - colorTable[pos] = ( (c << 24) & 0xff000000) - | ((c >> 24) & 0x000000ff) - | ((c << 8) & 0x00ff0000) - | ((c >> 8) & 0x0000ff00); -#endif // Q_BYTE_ORDER - ++pos; - fpos += incr; - } - } - for (;pos < size; ++pos) - colorTable[pos] = colors[s.size() - 1]; -} - -IDirect3DTexture9 *QD3DGradientCache::addCacheElement(quint64 hash_val, const QGradientStops &stops, qreal opacity) -{ - if (cache.size() == QD3D_GRADIENT_CACHE_SIZE) { - int elem_to_remove = qrand() % QD3D_GRADIENT_CACHE_SIZE; - uint key = cache.keys()[elem_to_remove]; - - // need to call release on each removed cache entry: - QD3DGradientColorTableHash::const_iterator it = cache.constFind(key); - do { - it.value().texture->Release(); - } while (++it != cache.constEnd() && it.key() == key); - - cache.remove(key); // may remove more than 1, but OK - } - - CacheInfo cache_entry(stops, opacity); - uint buffer[QD3D_GRADIENT_PALETTE_SIZE]; - generateGradientColorTable(stops, buffer, QD3D_GRADIENT_PALETTE_SIZE, opacity); - - if (FAILED(m_device->CreateTexture(QD3D_GRADIENT_PALETTE_SIZE, 1, 1, 0, - D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &cache_entry.texture, 0))) { - qWarning("QD3DGradientCache::addCacheElement(): unable to create Direct3D texture."); - return 0; - } - - D3DLOCKED_RECT rect; - if (FAILED(cache_entry.texture->LockRect(0, &rect, 0, 0))) { - qDebug() << "QD3DGradientCache::addCacheElement(): unable to lock texture rect."; - return 0; - } - memcpy(rect.pBits, buffer, rect.Pitch); - cache_entry.texture->UnlockRect(0); - - return cache.insert(hash_val, cache_entry).value().texture; -} - -void QD3DGradientCache::cleanCache() -{ - QD3DGradientColorTableHash::const_iterator it = cache.constBegin(); - for (; it != cache.constEnd(); ++it) { - const CacheInfo &cache_info = it.value(); - cache_info.texture->Release(); - } - cache.clear(); -} - -QD3DSurfaceManager::QD3DSurfaceManager() : - m_status(NoStatus), m_dummy(0), m_device(0), m_pd(0), m_current(0) -{ - -} - -QD3DSurfaceManager::~QD3DSurfaceManager() -{ -} - -void QD3DSurfaceManager::setPaintDevice(QPaintDevice *pd) -{ - m_status = NoStatus; - m_pd = pd; - m_current = 0; - - if (m_device->TestCooperativeLevel() != D3D_OK) { - m_status = NeedsResetting; - return; - } - - m_current = m_swapchains.value(pd, 0); - QWidget *w = static_cast<QWidget*>(pd); - - if (m_current) { - if (m_current->size != w->size()) { - m_swapchains.remove(pd); - m_current->surface->Release(); - m_current->swapchain->Release(); - delete m_current; - m_current = 0; - } - } - - if (!m_current) { - m_current = createSwapChain(w); - updateMaxSize(); - } -} - -int QD3DSurfaceManager::status() const -{ - return m_status; -} - -void QD3DSurfaceManager::reset() -{ - QList<QPaintDevice *> pds = m_swapchains.keys(); - - QMap<QPaintDevice *, D3DSwapChain *>::const_iterator i = m_swapchains.constBegin(); - while (i != m_swapchains.constEnd()) { - i.value()->surface->Release(); - i.value()->swapchain->Release(); - ++i; - } - qDeleteAll(m_swapchains.values()); - m_swapchains.clear(); - - D3DPRESENT_PARAMETERS params; - initPresentParameters(¶ms); - params.hDeviceWindow = m_dummy; - - HRESULT res = m_device->Reset(¶ms); - if (FAILED(res)) { - switch (res) { - case D3DERR_DEVICELOST: - qWarning("QDirect3DPaintEngine: Reset failed (D3DERR_DEVICELOST)"); - break; - case D3DERR_DRIVERINTERNALERROR: - qWarning("QDirect3DPaintEngine: Reset failed (D3DERR_DRIVERINTERNALERROR)"); - break; - case D3DERR_OUTOFVIDEOMEMORY: - qWarning("QDirect3DPaintEngine: Reset failed (D3DERR_OUTOFVIDEOMEMORY)"); - break; - default: - qWarning("QDirect3DPaintEngine: Reset failed"); - }; - } - - for (int i=0; i<pds.count(); ++i) { - QWidget *w = static_cast<QWidget*>(pds.at(i)); - createSwapChain(w); - } - - // reset the mask as well - m_status = MaxSizeChanged; - - setPaintDevice(m_pd); - updateMaxSize(); -} - -LPDIRECT3DSURFACE9 QD3DSurfaceManager::renderTarget() -{ - return m_current ? m_current->surface : 0; -} - -LPDIRECT3DSURFACE9 QD3DSurfaceManager::surface(QPaintDevice *pd) -{ - D3DSwapChain *swapchain = m_swapchains.value(pd, 0); - return swapchain ? swapchain->surface : 0; -} - -LPDIRECT3DSWAPCHAIN9 QD3DSurfaceManager::swapChain(QPaintDevice *pd) -{ - D3DSwapChain *swapchain = m_swapchains.value(pd, 0); - return swapchain ? swapchain->swapchain : 0; -} - -void QD3DSurfaceManager::releasePaintDevice(QPaintDevice *pd) -{ - D3DSwapChain *swapchain = m_swapchains.take(pd); - - if (swapchain) { - swapchain->surface->Release(); - swapchain->swapchain->Release(); - delete swapchain; - if (swapchain == m_current) - m_current = 0; - } -} - -LPDIRECT3DDEVICE9 QD3DSurfaceManager::device() -{ - return m_device; -} - -void QD3DSurfaceManager::cleanup() -{ - QPixmapCache::clear(); - qd3d_glyph_cache()->cleanCache(); - - // release doomed textures - for (int k=0; k<qd3d_release_list.size(); ++k) - qd3d_release_list.at(k)->Release(); - qd3d_release_list.clear(); - - QMap<QPaintDevice *, D3DSwapChain *>::const_iterator i = m_swapchains.constBegin(); - while (i != m_swapchains.constEnd()) { - i.value()->surface->Release(); - i.value()->swapchain->Release(); - ++i; - } - qDeleteAll(m_swapchains.values()); - - if (m_device) - m_device->Release(); - - DestroyWindow(m_dummy); - QString cname(QLatin1String("qt_d3d_dummy")); - QT_WA({ - UnregisterClass((TCHAR*)cname.utf16(), (HINSTANCE)qWinAppInst()); - } , { - UnregisterClassA(cname.toLatin1(), (HINSTANCE)qWinAppInst()); - }); -} - -QSize QD3DSurfaceManager::maxSize() const -{ - return m_max_size; -} - -extern "C" { - LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); -}; - -void QD3DSurfaceManager::init(LPDIRECT3D9 object) -{ - QString cname(QLatin1String("qt_d3d_dummy")); - uint style = CS_DBLCLKS | CS_SAVEBITS; - ATOM atom; - QT_WA({ - WNDCLASS wc; - wc.style = style; - wc.lpfnWndProc = (WNDPROC)QtWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = (HINSTANCE)qWinAppInst(); - wc.hIcon = 0; - wc.hCursor = 0; - wc.hbrBackground = 0; - wc.lpszMenuName = 0; - wc.lpszClassName = (TCHAR*)cname.utf16(); - atom = RegisterClass(&wc); - } , { - WNDCLASSA wc; - wc.style = style; - wc.lpfnWndProc = (WNDPROC)QtWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = (HINSTANCE)qWinAppInst(); - wc.hIcon = 0; - wc.hCursor = 0; - wc.hbrBackground = 0; - wc.lpszMenuName = 0; - QByteArray tempArray = cname.toLatin1(); - wc.lpszClassName = tempArray; - atom = RegisterClassA(&wc); - }); - - QT_WA({ - const TCHAR *className = (TCHAR*)cname.utf16(); - m_dummy = CreateWindow(className, className, 0, - 0, 0, 1, 1, - 0, 0, qWinAppInst(), 0); - } , { - m_dummy = CreateWindowA(cname.toLatin1(), cname.toLatin1(), 0, - 0, 0, 1, 1, - 0, 0, qWinAppInst(), 0); - }); - - D3DPRESENT_PARAMETERS params; - initPresentParameters(¶ms); - params.hDeviceWindow = m_dummy; - - HRESULT res = object->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, 0, - D3DCREATE_PUREDEVICE|D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_NOWINDOWCHANGES|D3DCREATE_FPU_PRESERVE, - ¶ms, &m_device); - - if (FAILED(res) || m_device == 0) - qWarning("QDirect3DPaintEngine: failed to create Direct3D device (error=0x%x).", res); -} - -void QD3DSurfaceManager::updateMaxSize() -{ - int w = 0, h = 0; - QMap<QPaintDevice *, D3DSwapChain *>::const_iterator i = m_swapchains.constBegin(); - while (i != m_swapchains.constEnd()) { - - int nw = i.key()->width(); - if (nw > w) - w = nw; - - int nh = i.key()->height(); - if (nh > h) - h = nh; - - ++i; - } - - QSize newsize = QSize(w, h); - if (newsize != m_max_size) { - m_status |= MaxSizeChanged; - m_max_size = newsize; - } -} - -void QD3DSurfaceManager::initPresentParameters(D3DPRESENT_PARAMETERS *params) -{ - ZeroMemory(params, sizeof(D3DPRESENT_PARAMETERS)); - params->Windowed = true; - params->SwapEffect = D3DSWAPEFFECT_COPY; - params->BackBufferFormat = D3DFMT_UNKNOWN; - params->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; - params->Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; -} - -QD3DSurfaceManager::D3DSwapChain *QD3DSurfaceManager::createSwapChain(QWidget *w) -{ - D3DPRESENT_PARAMETERS params; - initPresentParameters(¶ms); - params.hDeviceWindow = w->winId(); - D3DSwapChain *swapchain = new D3DSwapChain(); - swapchain->size = w->size(); - if (FAILED(m_device->CreateAdditionalSwapChain(¶ms, &swapchain->swapchain))) - qWarning("QDirect3DPaintEngine: CreateAdditionalSwapChain failed"); - if (FAILED(swapchain->swapchain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &swapchain->surface))) - qWarning("QDirect3DPaintEngine: GetBackBuffer failed"); - m_swapchains.insert(w, swapchain); - connect(w, SIGNAL(destroyed(QObject *)), SLOT(cleanupPaintDevice(QObject *))); - - // init with background color - QColor bg = w->palette().color(QPalette::Background); - m_device->ColorFill(swapchain->surface, 0, D3DCOLOR_ARGB(bg.alpha(), bg.red(),bg.green(),bg.blue())); - - return swapchain; -} - -void QD3DSurfaceManager::cleanupPaintDevice(QObject *object) -{ - QWidget *w = static_cast<QWidget *>(object); - releasePaintDevice(w); -} - -int QD3DStateManager::m_mask_channels[4][4] = - {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}}; - -QD3DDrawHelper::QD3DDrawHelper(QDirect3DPaintEnginePrivate *pe) - : m_pe(pe), m_d3dvbuff(0), m_maskSurface(0), m_depthStencilSurface(0), - m_locked(false), m_mask(0), m_startindex(0), m_index(0), m_vbuff(0), m_clearmask(true), - m_isLine(false), m_firstPoint(true) -{ - resetMask(); -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - memset(accesscontrol, 0, QT_VERTEX_BUF_SIZE * sizeof(VertexBufferAccess)); -#endif - - // create vertex buffer - afterReset(); -} - -QD3DDrawHelper::~QD3DDrawHelper() -{ - if (m_maskSurface) - m_maskSurface->Release(); - - if (m_mask) - m_mask->Release(); - - if (m_depthStencilSurface) - m_depthStencilSurface->Release(); - - if (m_d3dvbuff) - m_d3dvbuff->Release(); -} - -inline void QD3DDrawHelper::lockVertexBuffer() -{ - if (!m_locked) { - DWORD lockflags = D3DLOCK_NOOVERWRITE; - if (m_startindex >= QT_VERTEX_RESET_LIMIT) { - m_startindex = 0; - m_index = 0; - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - for (int i=0; i<QT_VERTEX_BUF_SIZE; ++i) { - if (accesscontrol[i] != (WRITE|READ) && accesscontrol[i] != CLEAR) - qDebug() << "Vertex Buffer: Access Error"; - } - memset(accesscontrol, 0, QT_VERTEX_BUF_SIZE * sizeof(VertexBufferAccess)); -#endif - - lockflags = D3DLOCK_DISCARD; - } - - if (FAILED(m_d3dvbuff->Lock(0, 0, (void**)&m_vbuff, lockflags))) { - qWarning() << "QDirect3DPaintEngine: unable to lock vertex buffer."; - } - m_locked = true; - } -} - -inline void QD3DDrawHelper::unlockVertexBuffer() -{ - if (m_locked) { - if (FAILED(m_d3dvbuff->Unlock())) { - qWarning() << "QDirect3DPaintEngine: unable to unlock vertex buffer."; - } - m_locked = false; - } -} - -void QD3DDrawHelper::setClipPath(const QPainterPath &path, QD3DBatchItem **item) -{ - lockVertexBuffer(); - - m_item = *item; - m_item->m_maskpos.x = m_item->m_maskpos.y = 0; - m_item->m_maskpos.channel = 3; - m_item->m_info |= QD3DBatchItem::BI_CLIP; - - bool winding = (path.fillRule() == Qt::WindingFill); - if (winding) - m_item->m_info |= QD3DBatchItem::BI_WINDING; - - if (!path.isEmpty()) { - m_item->m_info |= QD3DBatchItem::BI_MASK; - m_item->m_info &= ~QD3DBatchItem::BI_AA; - m_color = 0; - QRectF brect = pathToVertexArrays(path); - queueRect(brect, m_item, 0); - } - - *item = m_item; -} - - - -void QD3DDrawHelper::queueAntialiasedMask(const QPolygonF &poly, QD3DBatchItem **item, const QRectF &brect) -{ - lockVertexBuffer(); - - m_item = *item; - m_item->m_info |= QD3DBatchItem::BI_MASK; - setWinding(m_item->m_info & QD3DBatchItem::BI_WINDING); - - int xoffset = m_item->m_maskpos.x; - int yoffset = m_item->m_maskpos.y; - - int x = brect.left(); - int y = brect.top(); - - m_item->m_xoffset = (xoffset - x) + 1; - m_item->m_yoffset = (yoffset - y) + 1; - - m_boundingRect = brect; - tessellate(poly); - - *item = m_item; -} - -QRectF QD3DDrawHelper::queueAliasedMask(const QPainterPath &path, QD3DBatchItem **item, D3DCOLOR color) -{ - lockVertexBuffer(); - - m_color = color; - m_item = *item; - m_item->m_info |= QD3DBatchItem::BI_MASK; - - bool winding = (path.fillRule() == Qt::WindingFill); - if (winding) - m_item->m_info |= QD3DBatchItem::BI_WINDING; - - QRectF result = pathToVertexArrays(path); - *item = m_item; - return result; -} - -// used for drawing aliased transformed rects directly -// don't use for antialiased or masked drawing -void QD3DDrawHelper::queueRect(const QRectF &rect, QD3DBatchItem *item, D3DCOLOR color, const QPolygonF &trect) -{ - lockVertexBuffer(); - - qreal zval = (item->m_info & QD3DBatchItem::BI_CLIP) ? 0.0f : 0.5f; - item->m_info |= QD3DBatchItem::BI_BRECT; - - // if the item does not have a mask, the offset is different - if (!(item->m_info & QD3DBatchItem::BI_MASK)) { - item->m_offset = m_index; - item->m_count = (item->m_info & QD3DBatchItem::BI_AA) ? 0 : -2; - } - - qreal x1 = rect.left(); - qreal y1 = rect.top(); - qreal x2 = rect.right(); - qreal y2 = rect.bottom(); - - QPointF tc = trect.at(0); - vertex v1 = { {x1, y1, zval} , color, - tc.x(), tc.y(), 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f }; - - tc = trect.at(1); - vertex v2 = { {x2, y1, zval} , color, - tc.x(), tc.y(), 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f}; - - tc = trect.at(2); - vertex v3 = { {x2, y2, zval} , color, - tc.x(), tc.y(), 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f};; - - tc = trect.at(3); - vertex v4 = { {x1, y2, zval} , color, - tc.x(), tc.y(), 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f}; - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - for (int i=m_index; i<(m_index + 4); ++i) { - if ((m_index + 4) > QT_VERTEX_BUF_SIZE) - qDebug() << "Vertex Buffer: Buffer overflow"; - if (accesscontrol[i] != CLEAR) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[i] |= WRITE; - } -#endif - - m_vbuff[m_index++] = v1; - m_vbuff[m_index++] = v2; - m_vbuff[m_index++] = v3; - m_vbuff[m_index++] = v4; - - m_startindex = m_index; -} - - -QD3DMaskPosition QD3DDrawHelper::allocateMaskPosition(const QRectF &brect, bool *breakbatch) -{ - int w = brect.width(); - int h = brect.height(); - - w += 3; - h += 3; - - if (w > m_width) - w = m_width; - if (h > m_height) - h = m_height; - - *breakbatch = false; - - if ((m_height - m_mask_offsetY2) >= h && (m_width - m_mask_position.x) >= w) { - m_mask_position.y = m_mask_offsetY2; - } else if ((m_width - m_mask_offsetX2) >= w) { - m_mask_position.y = QD3D_MASK_MARGIN; - m_mask_position.x = m_mask_offsetX2; - } else if (m_mask_position.channel < 3) { - ++m_mask_position.channel; - m_mask_position.x = m_mask_position.y = QD3D_MASK_MARGIN; - m_mask_offsetX2 = m_mask_offsetY2 = QD3D_MASK_MARGIN; - } else { - resetMask(); - *breakbatch = true; - } - - int newoffset = m_mask_position.x + w; - if (m_mask_offsetX2 < newoffset) - m_mask_offsetX2 = newoffset; - m_mask_offsetY2 = (m_mask_position.y + h); - - return m_mask_position; - -} - -void QD3DDrawHelper::queueRect(const QRectF &rect, QD3DBatchItem *item, D3DCOLOR color) -{ - lockVertexBuffer(); - - QRectF brect; - item->m_info |= QD3DBatchItem::BI_BRECT; - qreal zval = (item->m_info & QD3DBatchItem::BI_CLIP) ? 0.0f : 0.5f; - - if (item->m_info & QD3DBatchItem::BI_AA) { - int xoffset = item->m_maskpos.x; - int yoffset = item->m_maskpos.y; - - int x = rect.left(); - int y = rect.top(); - - brect = QRectF(x, y, rect.width() + 1, rect.height() + 1); - - item->m_xoffset = (xoffset - x) + 1; - item->m_yoffset = (yoffset - y) + 1; - - // if the item does not have a mask, the offset is different - if (!(item->m_info & QD3DBatchItem::BI_MASK)) { - item->m_offset = m_index; - item->m_count = 0; - } - } else { - brect = rect; - - if (!(item->m_info & QD3DBatchItem::BI_MASK)) { - item->m_offset = m_index; - item->m_count = -2; - } - } - - qreal left = brect.left(); - qreal right = brect.right(); - qreal top = brect.top(); - qreal bottom = brect.bottom(); - - vertex v1 = { {left, bottom, zval}, color, - 0.f, 0.f, 0.f, 0.f, - 0.f, 0.f, 0.f, 0.f}; - vertex v2 = { {left, top, zval}, color, - 0.f, 0.f, 0.f, 0.f, - 0.f, 0.f, 0.f, 0.f}; - vertex v3 = { {right, top, zval}, color, - 0.f, 0.f, 0.f, 0.f, - 0.f, 0.f, 0.f, 0.f}; - vertex v4 = { {right, bottom, zval}, color, - 0.f, 0.f, 0.f, 0.f, - 0.f, 0.f, 0.f, 0.f}; - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - for (int i=m_index; i<(m_index + 4); ++i) { - if ((m_index + 4) > QT_VERTEX_BUF_SIZE) - qDebug() << "Vertex Buffer: Buffer overflow"; - if (accesscontrol[i] != CLEAR) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[i] |= WRITE; - } -#endif - - m_vbuff[m_index++] = v1; - m_vbuff[m_index++] = v2; - m_vbuff[m_index++] = v3; - m_vbuff[m_index++] = v4; - - m_startindex = m_index; -} - -void QD3DDrawHelper::queueAntialiasedLines(const QPainterPath &path, QD3DBatchItem **item, const QRectF &brect) -{ - lockVertexBuffer(); - - m_item = *item; - m_item->m_info |= QD3DBatchItem::BI_MASK; - setWinding(m_item->m_info & QD3DBatchItem::BI_WINDING); - - int xoffset = m_item->m_maskpos.x; - int yoffset = m_item->m_maskpos.y; - int x = brect.left(); - int y = brect.top(); - - m_item->m_xoffset = (xoffset - x) + 1; - m_item->m_yoffset = (yoffset - y) + 1; - - m_boundingRect = brect; - - m_xoffset = (x - xoffset) + 0.5f; - m_yoffset = (y - yoffset) + 0.5f; - - QPointF last; - for (int i = 0; i < path.elementCount(); ++i) { - QPainterPath::Element element = path.elementAt(i); - - //Q_ASSERT(!element.isCurveTo()); - - if (element.isLineTo()) - QTessellator::tessellateRect(last, element, m_item->m_width); - - last = element; - } - - m_item->m_offset = m_startindex; - m_item->m_count = ( m_index - m_startindex ) / 3; - m_startindex = m_index; - - *item = m_item; -} - -void QD3DDrawHelper::queueAliasedLines(const QLineF *lines, int lineCount, QD3DBatchItem **item) -{ - lockVertexBuffer(); - - m_item = *item; - m_item->m_info |= QD3DBatchItem::BI_FASTLINE; - - for (int i=0; i<lineCount; ++i) { - const QLineF line = lines[i]; - qreal p1x = line.p1().x(); - qreal p1y = line.p1().y(); - qreal p2x = line.p2().x(); - qreal p2y = line.p2().y(); - - vertex v1 = { {p1x, p1y, m_pe->m_pen_width} , m_pe->m_pen_color, - -1.f, -1.f, p2x, p2y, - 0.f, 0.f, 0.f, 0.f }; - vertex v2 = { {p1x, p1y, m_pe->m_pen_width} , m_pe->m_pen_color, - 1.f, -1.f, p2x, p2y, - 0.f, 0.f, 0.f, 0.f }; - vertex v3 = { {p1x, p1y, m_pe->m_pen_width} , m_pe->m_pen_color, - 1.f, 1.f, p2x, p2y, - 0.f, 0.f, 0.f, 0.f }; - vertex v4 = { {p1x, p1y, m_pe->m_pen_width} , m_pe->m_pen_color, - -1.f, 1.f, p2x, p2y, - 0.f, 0.f, 0.f, 0.f }; - - m_vbuff[m_index++] = v1; - m_vbuff[m_index++] = v2; - m_vbuff[m_index++] = v4; - m_vbuff[m_index++] = v4; - m_vbuff[m_index++] = v2; - m_vbuff[m_index++] = v3; - - if (m_index >= (QT_VERTEX_BUF_SIZE - 16)) { - m_item->m_offset = m_startindex; - m_item->m_count = ( m_index - m_startindex ) / 2; - m_startindex = m_index; - - QD3DBatchItem itemcopy = *m_item; - m_item = m_pe->nextBatchItem(); - *m_item = itemcopy; - - lockVertexBuffer(); - } - } - - m_item->m_offset = m_startindex; - m_item->m_count = ( m_index - m_startindex ) - 2; - m_startindex = m_index; - - *item = m_item; -} - -void QD3DDrawHelper::queueTextGlyph(const QRectF &rect, const qreal *tex_coords, - QD3DBatchItem *item, D3DCOLOR color) -{ - lockVertexBuffer(); - - qreal x1 = rect.left(); - qreal y1 = rect.top(); - qreal x2 = rect.right(); - qreal y2 = rect.bottom(); - - vertex v1 = { {x1, y1, 0.5f}, color, - tex_coords[0], tex_coords[1], 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f}; - vertex v2 = { {x2, y1, 0.5f}, color, - tex_coords[2], tex_coords[1], 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f}; - vertex v3 = { {x2, y2, 0.5f}, color, - tex_coords[2], tex_coords[3], 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f}; - vertex v4 = { {x1, y1, 0.5f}, color, - tex_coords[0], tex_coords[1], 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f}; - vertex v5 = { {x2, y2, 0.5f}, color, - tex_coords[2], tex_coords[3], 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f}; - vertex v6 = { {x1, y2, 0.5f}, color, - tex_coords[0], tex_coords[3], 0.f, 0.f, - 0.f , 0.f , 0.f, 0.f}; - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - for (int i=m_index; i<(m_index + 6); ++i) { - if ((m_index + 6) > QT_VERTEX_BUF_SIZE) - qDebug() << "Vertex Buffer: Buffer overflow"; - if (accesscontrol[i] != CLEAR) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[i] |= WRITE; - } -#endif - - m_vbuff[m_index++] = v1; - m_vbuff[m_index++] = v2; - m_vbuff[m_index++] = v3; - m_vbuff[m_index++] = v4; - m_vbuff[m_index++] = v5; - m_vbuff[m_index++] = v6; - - m_startindex = m_index; - ++item->m_count; -} - -bool QD3DDrawHelper::needsFlushing() const -{ - return (m_pe->m_batch.m_item_index >= QD3D_BATCH_SIZE || m_startindex >= QT_VERTEX_RESET_LIMIT); -} - -void QD3DDrawHelper::setMaskSize(QSize size) -{ - m_width = size.width(); - m_height = size.height(); - - if (m_maskSurface) - m_maskSurface->Release(); - - if (m_mask) - m_mask->Release(); - - if (FAILED(m_pe->m_d3d_device->CreateTexture(m_width, m_height, 1, D3DUSAGE_RENDERTARGET, - D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_mask, NULL))) { - qWarning() << "QDirect3DPaintEngine: CreateTexture() failed."; - } - - if (m_depthStencilSurface) - m_depthStencilSurface->Release(); - - if (FAILED(m_pe->m_d3d_device->CreateDepthStencilSurface(m_width, m_height, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, - TRUE, &m_depthStencilSurface, NULL))) { - qWarning() << "QDirect3DPaintEngine: CreateDepthStencilSurface() failed."; - } - - m_pe->m_d3d_device->SetDepthStencilSurface(m_depthStencilSurface); - m_pe->m_d3d_device->Clear(0, 0, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0, 0.0f, 0); - - if (FAILED(m_mask->GetSurfaceLevel(0, &m_maskSurface))) { - qWarning() << "QDirect3DPaintEngine: GetSurfaceLevel() failed."; - } - - m_pe->m_d3d_device->ColorFill(m_maskSurface, 0, D3DCOLOR_ARGB(0,0,0,0)); - D3DXMATRIX projMatrix; - pD3DXMatrixOrthoOffCenterLH(&projMatrix, 0, m_width, m_height, 0, 0, 1); - m_pe->m_effect->SetMatrix("g_mMaskProjection", &projMatrix); - m_pe->m_effect->SetTexture("g_mAAMask", m_mask); -} - -void QD3DDrawHelper::beforeReset() -{ - resetMask(); - m_clearmask = true; - - if (m_maskSurface) { - m_maskSurface->Release(); - m_maskSurface = 0; - } - - if (m_mask) { - m_mask->Release(); - m_mask = 0; - } - - if (m_depthStencilSurface) { - m_depthStencilSurface->Release(); - m_depthStencilSurface = 0; - } - - if (m_d3dvbuff) - m_d3dvbuff->Release(); -} - -void QD3DDrawHelper::afterReset() -{ - if (FAILED(m_pe->m_d3d_device->CreateVertexBuffer(QT_VERTEX_BUF_SIZE*sizeof(vertex), D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, - QD3DFVF_CSVERTEX, - D3DPOOL_DEFAULT, &m_d3dvbuff, NULL))) { - qWarning() << "QDirect3DPaintEngine: failed to create vertex buffer."; - } - - m_pe->m_d3d_device->SetStreamSource(0, m_d3dvbuff, 0, sizeof(vertex)); - m_pe->m_d3d_device->SetFVF(QD3DFVF_CSVERTEX); - - m_startindex = 0; - m_index = 0; -} - -IDirect3DSurface9 *QD3DDrawHelper::freeMaskSurface() -{ - // we need to make sure the mask is cleared when it's used for something else - resetMask(); - m_clearmask = true; - - return m_maskSurface; -} - -int QD3DDrawHelper::drawAntialiasedMask(int offset, int maxoffset) -{ - int newoffset = offset; - QD3DBatchItem *item = &(m_pe->m_batch.items[offset]); - - // set mask as render target - if (FAILED(m_pe->m_d3d_device->SetRenderTarget(0, m_maskSurface))) - qWarning() << "QDirect3DPaintEngine: SetRenderTarget failed!"; - - if (m_clearmask) { - m_pe->m_d3d_device->Clear(0, 0, D3DCLEAR_TARGET,D3DCOLOR_ARGB(0,0,0,0), 0, 0); - m_clearmask = false; - } - - // fill the mask - m_pe->m_statemanager->beginPass(PASS_AA_CREATEMASK); - for (; newoffset<maxoffset; ++newoffset) { - item = &(m_pe->m_batch.items[newoffset]); - if (!(item->m_info & QD3DBatchItem::BI_AA) || !(item->m_info & QD3DBatchItem::BI_MASK)) { - break; - } else if (item->m_info & QD3DBatchItem::BI_MASKFULL) { - item->m_info &= ~QD3DBatchItem::BI_MASKFULL; - m_clearmask = true; - break; - } - - m_pe->m_statemanager->startStateBlock(); - if (item->m_info & QD3DBatchItem::BI_MASKSCISSOR) { - RECT rect; - QRectF srect = item->m_brect.adjusted(item->m_xoffset, item->m_yoffset, - item->m_xoffset, item->m_yoffset); - rect.left = qMax(qRound(srect.left()), 0); - rect.top = qMax(qRound(srect.top()), 0); - rect.bottom = qMin(m_height, qRound(srect.bottom())); - rect.right = qMin(m_width, qRound(srect.right())); - m_pe->m_d3d_device->SetScissorRect(&rect); - m_pe->m_statemanager->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); - } - m_pe->m_statemanager->setMaskChannel(item->m_maskpos.channel); - m_pe->m_statemanager->endStateBlock(); - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - int vbstart = item->m_offset; - for (int i=vbstart; i<(vbstart + (item->m_count * 3)); ++i) { - if (accesscontrol[i] != WRITE) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[i] |= READ; - } -#endif - - m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLELIST, item->m_offset, item->m_count); - - if (item->m_info & QD3DBatchItem::BI_MASKSCISSOR) { - m_pe->m_statemanager->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); - } - } - m_pe->m_statemanager->endPass(); - - return newoffset; -} - -void QD3DDrawHelper::drawAliasedMask(int offset) -{ - QD3DBatchItem *item = &(m_pe->m_batch.items[offset]); - if (item->m_info & QD3DBatchItem::BI_MASK) { - m_pe->m_statemanager->beginPass( (item->m_info & QD3DBatchItem::BI_WINDING) ? PASS_STENCIL_WINDING : PASS_STENCIL_ODDEVEN ); - int prev_stop = 0; - for (int i=0; i<item->m_pointstops.count(); ++i) { - int stop = item->m_pointstops.at(i); - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - int vbstart = (item->m_offset + prev_stop); - for (int j=vbstart; j<(vbstart+(stop - prev_stop)); ++j) { - if (accesscontrol[j] != WRITE) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[j] |= READ; - } -#endif - m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLEFAN, item->m_offset + prev_stop, (stop - prev_stop) - 2); - prev_stop = stop; - } - m_pe->m_statemanager->endPass(); - } -} - -void QD3DDrawHelper::drawTextItem(QD3DBatchItem *item) -{ -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - int vbstart = item->m_offset; - for (int j=vbstart; j<(vbstart + ((item->m_count * 2) * 3)); ++j) { - if (accesscontrol[j] != WRITE) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[j] |= READ; - } -#endif - m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLELIST, item->m_offset, item->m_count*2); -} - -void QD3DDrawHelper::drawAliasedLines(QD3DBatchItem *item) -{ - m_pe->m_statemanager->setCosmeticPen(item->m_info & QD3DBatchItem::BI_COSMETICPEN); - if (item->m_info & QD3DBatchItem::BI_TRANSFORM) { - m_pe->m_statemanager->setTransformation(&item->m_matrix); - } else { - m_pe->m_statemanager->setTransformation(); - } - int pass = (item->m_info & QD3DBatchItem::BI_MASK) - ? PASS_ALIASED_LINES - : PASS_ALIASED_LINES_DIRECT; - m_pe->m_statemanager->beginPass(pass); - m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLELIST, item->m_offset, (item->m_count + 2) / 3); - m_pe->m_statemanager->endPass(); -} - -void QD3DDrawHelper::drawAntialiasedBoundingRect(QD3DBatchItem *item) -{ - if (item->m_info & QD3DBatchItem::BI_SCISSOR) { - RECT rect; - rect.left = qMax(qRound(item->m_brect.left()), 0); - rect.top = qMax(qRound(item->m_brect.top()), 0); - rect.bottom = qMin(m_height, qRound(item->m_brect.bottom())); - rect.right = qMin(m_width, qRound(item->m_brect.right())); - m_pe->m_d3d_device->SetScissorRect(&rect); - m_pe->m_statemanager->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); - } - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - int vbstart = item->m_offset + (item->m_count * 3); - for (int j=vbstart; j<(vbstart + 4); ++j) { - if (accesscontrol[j] != WRITE) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[j] |= READ; - } -#endif - - m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLEFAN, item->m_offset + (item->m_count * 3), 2); - - if (item->m_info & QD3DBatchItem::BI_SCISSOR) { - m_pe->m_statemanager->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); - } -} - -void QD3DDrawHelper::drawAliasedBoundingRect(QD3DBatchItem *item) -{ -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - int vbstart = (item->m_offset + item->m_count + 2); - for (int j=vbstart; j<(vbstart + 4); ++j) { - if (accesscontrol[j] != WRITE) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[j] |= READ; - } -#endif - - m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLEFAN, item->m_offset + item->m_count + 2, 2); -} - -void QD3DDrawHelper::addTrap(const Trapezoid &trap) -{ - qreal topLeftY = Q27Dot5ToDouble(trap.topLeft->y) - m_yoffset; - qreal topLeftX = Q27Dot5ToDouble(trap.topLeft->x) - m_xoffset; - qreal topRightY = Q27Dot5ToDouble(trap.topRight->y) - m_yoffset; - qreal topRightX = Q27Dot5ToDouble(trap.topRight->x) - m_xoffset; - qreal top = Q27Dot5ToDouble(trap.top) - m_yoffset; - qreal bottom = Q27Dot5ToDouble(trap.bottom) - m_yoffset; - - Q27Dot5 _h = trap.topLeft->y - trap.bottomLeft->y; - Q27Dot5 _w = trap.topLeft->x - trap.bottomLeft->x; - qreal _leftA = (qreal)_w/_h; - qreal _leftB = topLeftX - _leftA * topLeftY; - - _h = trap.topRight->y - trap.bottomRight->y; - _w = trap.topRight->x - trap.bottomRight->x; - qreal _rightA = (qreal)_w/_h; - qreal _rightB = topRightX - _rightA * topRightY; - - qreal invLeftA = qFuzzyIsNull(_leftA) ? 0.0 : 1.0 / _leftA; - qreal invRightA = qFuzzyIsNull(_rightA) ? 0.0 : 1.0 / _rightA; - - vertex v1 = { {1.f, top - 1.f, 0.5f}, 0.f, - top, bottom, invLeftA, -invRightA, - _leftA, _leftB, _rightA, _rightB}; - vertex v2 = { {0.f, top - 1.f, 0.5f}, 0.f, - top, bottom, invLeftA, -invRightA, - _leftA, _leftB, _rightA, _rightB}; - vertex v3 = { {0.f, bottom + 1.f, 0.5f}, 0.f, - top, bottom, invLeftA, -invRightA, - _leftA, _leftB, _rightA, _rightB}; - - vertex v4 = { {1.f, top - 1.f, 0.5f}, 0.f, - top, bottom, invLeftA, -invRightA, - _leftA, _leftB, _rightA, _rightB}; - vertex v5 = { {0.f, bottom + 1.f, 0.5f}, 0.f, - top, bottom, invLeftA, -invRightA, - _leftA, _leftB, _rightA, _rightB}; - vertex v6 = { {1.f, bottom + 1.f, 0.5f}, 0.f, - top, bottom, invLeftA, -invRightA, - _leftA, _leftB, _rightA, _rightB}; - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - for (int i=m_index; i<(m_index + 6); ++i) { - if ((m_index + 6) > QT_VERTEX_BUF_SIZE) - qDebug() << "Vertex Buffer: Buffer overflow"; - if (accesscontrol[i] != CLEAR) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[i] |= WRITE; - } -#endif - - m_vbuff[m_index++] = v1; - m_vbuff[m_index++] = v2; - m_vbuff[m_index++] = v3; - m_vbuff[m_index++] = v4; - m_vbuff[m_index++] = v5; - m_vbuff[m_index++] = v6; - - // check if buffer is full - if (m_index >= (QT_VERTEX_BUF_SIZE - 16)) { - m_item->m_offset = m_startindex; - m_item->m_count = ( m_index - m_startindex ) / 3; - m_startindex = m_index; - - QD3DBatchItem itemcopy = *m_item; - m_item = m_pe->nextBatchItem(); - *m_item = itemcopy; - m_item->m_info &= ~QD3DBatchItem::BI_MASKFULL; - - lockVertexBuffer(); - } -} - -void QD3DDrawHelper::tessellate(const QPolygonF &poly) { - int xoffset = m_item->m_maskpos.x; - int yoffset = m_item->m_maskpos.y; - - int x = m_boundingRect.left(); - int y = m_boundingRect.top(); - m_xoffset = (x - xoffset) + 0.5f; - m_yoffset = (y - yoffset) + 0.5f; - - QTessellator::tessellate(poly.data(), poly.count()); - - m_item->m_offset = m_startindex; - m_item->m_count = ( m_index - m_startindex ) / 3; - m_startindex = m_index; -} - -inline void QD3DDrawHelper::lineToStencil(qreal x, qreal y) -{ - QPointF lastPt = tess_lastpoint; - tess_lastpoint = QPointF(x, y); - - if (m_isLine && m_firstPoint) - return; - - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - if (m_index > QT_VERTEX_BUF_SIZE) - qDebug() << "Vertex Buffer: Buffer overflow"; - if (accesscontrol[m_index] != CLEAR) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[m_index] |= WRITE; -#endif - - vertex v; - if (m_isLine) { - vertex v1 = { {lastPt.x(), lastPt.y(), m_pe->m_pen_width }, m_color, - -1.f, -1.f, x, y, - 0.f, 0.f, 0.f, 0.f}; - vertex v2 = { {lastPt.x(), lastPt.y(), m_pe->m_pen_width }, m_color, - 1.f, -1.f, x, y, - 0.f, 0.f, 0.f, 0.f}; - vertex v3 = { {lastPt.x(), lastPt.y(), m_pe->m_pen_width }, m_color, - 1.f, 1.f, x, y, - 0.f, 0.f, 0.f, 0.f}; - vertex v4 = { {lastPt.x(), lastPt.y(), m_pe->m_pen_width }, m_color, - -1.f, 1.f, x, y, - 0.f, 0.f, 0.f, 0.f}; - m_vbuff[m_index++] = v1; - m_vbuff[m_index++] = v2; - m_vbuff[m_index++] = v4; - m_vbuff[m_index++] = v4; - m_vbuff[m_index++] = v2; - m_vbuff[m_index++] = v3; - } else { - vertex v1 = { {x, y, 0.5f}, m_color, - 0.f, 0.f, 0.f, 0.f, - 0.f, 0.f, 0.f, 0.f}; - m_vbuff[m_index++] = v1; - v = v1; - } - ++tess_index; - - // check if buffer is full - if (m_index >= (QT_VERTEX_BUF_SIZE - 16)) { - int firstindex = m_startindex; - if (!m_item->m_pointstops.isEmpty()) - firstindex = m_item->m_pointstops.last(); - - vertex first = m_vbuff[firstindex]; - - // finish current polygon - m_item->m_pointstops.append(tess_index); - m_item->m_offset = m_startindex; - m_startindex = m_index; - - // copy item - QD3DBatchItem itemcopy = *m_item; - m_item = m_pe->nextBatchItem(); - *m_item = itemcopy; - - // start new polygon - lockVertexBuffer(); - m_item->m_pointstops.clear(); - if (!m_isLine) { - tess_index = 2; - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - if (accesscontrol[m_index] != CLEAR) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[m_index] |= WRITE; -#endif - - m_vbuff[m_index++] = first; - -#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS - if (accesscontrol[m_index] != CLEAR) - qDebug() << "Vertex Buffer: Access Error"; - accesscontrol[m_index] |= WRITE; -#endif - - m_vbuff[m_index++] = v; - } else { - tess_index = 0; - } - } - - if (x > max_x) - max_x = x; - else if (x < min_x) - min_x = x; - if (y > max_y) - max_y = y; - else if (y < min_y) - min_y = y; -} - -inline void QD3DDrawHelper::curveToStencil(const QPointF &cp1, const QPointF &cp2, - const QPointF &ep) -{ - qreal inverseScale = 0.5f; - qreal inverseScaleHalf = inverseScale / 2; - - QBezier beziers[32]; - beziers[0] = QBezier::fromPoints(tess_lastpoint, cp1, cp2, ep); - QBezier *b = beziers; - while (b >= beziers) { - // check if we can pop the top bezier curve from the stack - qreal l = qAbs(b->x4 - b->x1) + qAbs(b->y4 - b->y1); - qreal d; - if (l > inverseScale) { - d = qAbs( (b->x4 - b->x1)*(b->y1 - b->y2) - (b->y4 - b->y1)*(b->x1 - b->x2) ) - + qAbs( (b->x4 - b->x1)*(b->y1 - b->y3) - (b->y4 - b->y1)*(b->x1 - b->x3) ); - d /= l; - } else { - d = qAbs(b->x1 - b->x2) + qAbs(b->y1 - b->y2) + - qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3); - } - if (d < inverseScaleHalf || b == beziers + 31) { - // good enough, we pop it off and add the endpoint - lineToStencil(b->x4, b->y4); - --b; - } else { - // split, second half of the polygon goes lower into the stack - b->split(b+1, b); - ++b; - } - } -} - -QRectF QD3DDrawHelper::pathToVertexArrays(const QPainterPath &path) -{ - m_isLine = (m_item->m_info & QD3DBatchItem::BI_FASTLINE); - const QPainterPath::Element &first = path.elementAt(0); - firstx = first.x; - firsty = first.y; - min_x = max_x = firstx; - min_y = max_y = firsty; - - m_firstPoint = true; - tess_index = 0; - m_item->m_pointstops.clear(); - lineToStencil(firstx, firsty); - m_firstPoint = false; - - for (int i=1; i<path.elementCount(); ++i) { - const QPainterPath::Element &e = path.elementAt(i); - switch (e.type) { - case QPainterPath::MoveToElement: - m_item->m_pointstops.append(tess_index); - m_firstPoint = true; - lineToStencil(e.x, e.y); - m_firstPoint = false; - break; - case QPainterPath::LineToElement: - lineToStencil(e.x, e.y); - break; - case QPainterPath::CurveToElement: - curveToStencil(e, path.elementAt(i+1), path.elementAt(i+2)); - i+=2; - break; - default: - break; - } - } - - if (!m_isLine) - lineToStencil(firstx, firsty); - - m_item->m_pointstops.append(tess_index); - - m_item->m_offset = m_startindex; - m_item->m_count = ( m_index - m_startindex ) - 2; - m_startindex = m_index; - - QRectF result; - result.setLeft(min_x); - result.setRight(max_x); - result.setTop(min_y); - result.setBottom(max_y); - - if (m_isLine) - result.adjust(0,0,1,1); - - return result; -} - -void QD3DDrawHelper::resetMask() -{ - m_mask_position.x = m_mask_position.y = QD3D_MASK_MARGIN; - m_mask_position.channel = 0; - m_mask_offsetX2 = m_mask_offsetY2 = QD3D_MASK_MARGIN; -} - - -static inline QPainterPath strokeForPath(const QPainterPath &path, const QPen &cpen) { - QPainterPathStroker stroker; - if (cpen.style() == Qt::CustomDashLine) - stroker.setDashPattern(cpen.dashPattern()); - else - stroker.setDashPattern(cpen.style()); - - stroker.setCapStyle(cpen.capStyle()); - stroker.setJoinStyle(cpen.joinStyle()); - stroker.setMiterLimit(cpen.miterLimit()); - stroker.setWidth(cpen.widthF()); - - QPainterPath stroke = stroker.createStroke(path); - stroke.setFillRule(Qt::WindingFill); - return stroke; -} - - -QDirect3DPaintEnginePrivate::~QDirect3DPaintEnginePrivate() -{ - -} - -void QDirect3DPaintEnginePrivate::updateClipPath(const QPainterPath &path, Qt::ClipOperation op) -{ - //#### remove me - QRegion r(path.toFillPolygon().toPolygon(), path.fillRule()); - updateClipRegion(r, op); - -/* if (m_draw_helper->needsFlushing()) - flushBatch(); - - if (op == Qt::IntersectClip && !has_clipping) - op = Qt::ReplaceClip; - - // switch to paths - if (!m_has_complex_clipping) { - m_clip_path = QPainterPath(); - m_clip_path.addRegion(m_clip_region); - m_clip_region = QRegion(); - m_sysclip_path = QPainterPath(); - m_sysclip_path.addRegion(m_sysclip_region); - m_sysclip_region = QRegion(); - m_has_complex_clipping = true; - } - - QPainterPath cpath = m_matrix.map(path); - - QD3DBatchItem *item = &m_batch.items[m_batch.m_item_index++]; - item->m_info = QD3DBatchItem::BI_COMPLEXCLIP; - - switch (op) { - case Qt::UniteClip: - has_clipping = true; - m_clip_path = m_clip_path.united(cpath); - break; - case Qt::ReplaceClip: - has_clipping = true; - m_clip_path = cpath; - break; - case Qt::NoClip: - m_has_complex_clipping = false; - has_clipping = false; - item->m_info |= QD3DBatchItem::BI_CLEARCLIP; - break; - default: // intersect clip - has_clipping = true; - m_clip_path = m_clip_path.intersected(cpath); - break; - } - - if (!m_sysclip_path.isEmpty()) { - item->m_info &= ~QD3DBatchItem::BI_CLEARCLIP; - if (has_clipping) - m_clip_path = m_clip_path.intersected(m_sysclip_path); - else - m_clip_path = m_sysclip_path; - } - - // update the aliased clipping mask - m_draw_helper->setClipPath(m_clip_path, item); - - // update the antialiased clipping mask - if (m_draw_helper->needsFlushing()) - flushBatch(); - - QD3DBatchItem *aaitem = &m_batch.items[m_batch.m_item_index++]; - aaitem->m_info = item->m_info|QD3DBatchItem::BI_AA; - m_draw_helper->setClipPath(m_clip_path, aaitem); */ -} - -extern QPainterPath qt_regionToPath(const QRegion ®ion); - -void QDirect3DPaintEnginePrivate::updateClipRegion(const QRegion &clipregion, Qt::ClipOperation op) -{ - if (m_draw_helper->needsFlushing()) - flushBatch(); - if (m_has_complex_clipping) { - QPainterPath path = qt_regionToPath(clipregion); - updateClipPath(path, op); - return; - } - - if (op == Qt::IntersectClip && m_clip_region.isEmpty()) - op = Qt::ReplaceClip; - - QRegion cregion = m_matrix.map(clipregion); - - QD3DBatchItem *item = nextBatchItem(); - item->m_info &= ~QD3DBatchItem::BI_AA; - - switch (op) { - case Qt::UniteClip: - m_clip_region = m_clip_region.united(cregion); - break; - case Qt::ReplaceClip: - m_clip_region = cregion; - break; - case Qt::NoClip: - m_clip_region = QRegion(); - item->m_info |= QD3DBatchItem::BI_CLEARCLIP; - break; - default: // intersect clip - m_clip_region = m_clip_region.intersected(cregion); - break; - } - - QRegion crgn = m_clip_region; - if (!m_sysclip_region.isEmpty()) { - item->m_info &= ~QD3DBatchItem::BI_CLEARCLIP; - if (!crgn.isEmpty()) - crgn = crgn.intersected(m_sysclip_region); - else - crgn = m_sysclip_region; - } - - QPainterPath path = qt_regionToPath(crgn); - m_draw_helper->setClipPath(path, &item); -} - -void QDirect3DPaintEnginePrivate::updateFont(const QFont &) -{ -} - -void QDirect3DPaintEnginePrivate::setRenderTechnique(RenderTechnique technique) -{ - if (m_current_technique != technique) { - if (m_current_technique != RT_NoTechnique) - m_effect->End(); - - if (technique == RT_Aliased) { - m_effect->SetTechnique("Aliased"); - m_effect->Begin(0,D3DXFX_DONOTSAVESTATE); - } else if (technique == RT_Antialiased) { - m_effect->SetTechnique("Antialiased"); - m_effect->Begin(0,D3DXFX_DONOTSAVESTATE); - } - } - - m_current_technique = technique; -} - -/*QPolygonF QDirect3DPaintEnginePrivate::transformedRect(const QRectF &brect) const -{ - QPolygonF poly(brect); - return m_matrix.map(poly); -} - -QPolygonF QDirect3DPaintEnginePrivate::calcTextureCoords(const QPolygonF &trect) const -{ - QPolygonF result(4); - QRectF brect = trect.boundingRect(); - qreal angle = atan(trect.at(0).x() - -} - -QPolygonF QDirect3DPaintEnginePrivate::offsetTextureCoords(const QRectF &brect, const QPolygonF &trect) const -{ - -}*/ - -inline QD3DBatchItem *QDirect3DPaintEnginePrivate::nextBatchItem() -{ - if (m_draw_helper->needsFlushing()) - flushBatch(); - - QD3DBatchItem *item = &m_batch.items[m_batch.m_item_index++]; - item->m_info = m_current_state; - item->m_cmode = m_cmode; - return item; -} - -qreal calculateAngle(qreal dx, qreal dy) -{ - qreal angle; - - if (qFuzzyIsNull(dx)) { - angle = (dy < 0) ? -M_PI/2 : M_PI/2; - } else { - angle = atanf(dy/dx); - if (dx < 0) - angle += M_PI; - } - - return angle; -} - -QPolygonF QDirect3DPaintEnginePrivate::brushCoordinates(const QRectF &r, bool stroke, qreal *fd) const -{ - QBrush brush; - QTransform matrix; - Qt::BrushStyle style; - - if (stroke) { - brush = m_pen.brush(); - matrix = m_inv_pen_matrix; - style = m_pen_brush_style; - } else { - brush = m_brush; - matrix = m_inv_brush_matrix; - style = m_brush_style; - } - - QPolygonF bpoly; - switch(style) { - case Qt::TexturePattern: { - QTransform totxcoords; - QRectF adj_brect = r.adjusted(-0.5f, -0.5f, -0.5f, -0.5f); - totxcoords.scale(1.0f/brush.texture().width(), - 1.0f/brush.texture().height()); - bpoly = matrix.map(QPolygonF(adj_brect)); - bpoly = totxcoords.map(bpoly); - break; } - case Qt::LinearGradientPattern: { - const QLinearGradient *g = static_cast<const QLinearGradient *>(brush.gradient()); - QPointF start = g->start(); - QPointF stop = g->finalStop(); - qreal dx = stop.x() - start.x(); - qreal dy = stop.y() - start.y(); - qreal length = sqrt(dx * dx + dy * dy); - qreal angle = calculateAngle(dx, dy); - QTransform totxcoords; - QRectF adj_brect = r.adjusted(-0.5f, -0.5f, -0.5f, -0.5f); - totxcoords.scale(1.0f/length, 1.0f/length); - totxcoords.rotateRadians(-angle); - totxcoords.translate(-start.x(), -start.y()); - bpoly = matrix.map(QPolygonF(adj_brect)); - bpoly = totxcoords.map(bpoly); - break; } - case Qt::ConicalGradientPattern: { - const QConicalGradient *g = static_cast<const QConicalGradient *>(brush.gradient()); - QPointF center = g->center(); - qreal angle = g->angle(); - QTransform totxcoords; - totxcoords.rotate(angle); - totxcoords.translate(-center.x(), -center.y()); - bpoly = matrix.map(QPolygonF(r)); - bpoly = totxcoords.map(bpoly); - break; } - case Qt::RadialGradientPattern: { - const QRadialGradient *g = static_cast<const QRadialGradient *>(brush.gradient()); - QPointF center = g->center(); - QPointF focalpoint = g->focalPoint(); - qreal dx = focalpoint.x() - center.x(); - qreal dy = focalpoint.y() - center.y(); - qreal radius = g->radius(); - *fd = sqrt(dx * dx + dy * dy) / radius; - qreal angle = calculateAngle(dx, dy); - QTransform totxcoords; - totxcoords.scale(1.0f/radius, 1.0f/radius); - totxcoords.rotateRadians(-angle); - totxcoords.translate(-center.x(), -center.y()); - bpoly = matrix.map(QPolygonF(r)); - bpoly = totxcoords.map(bpoly); - break; } - default: { - QTransform totxcoords; - QRectF adj_brect = r.adjusted(-0.5f, -0.5f, -0.5f, -0.5f); - QPixmap pat = getPattern(style); - totxcoords.scale(1.0f/pat.width(), - 1.0f/pat.height()); - bpoly = matrix.map(QPolygonF(adj_brect)); - bpoly = totxcoords.map(bpoly); } - }; - - return bpoly; -} - -void QDirect3DPaintEnginePrivate::strokeAliasedPath(QPainterPath path, const QRectF &brect, const QTransform &txform) -{ - D3DCOLOR solid_color; - QD3DBatchItem *item = nextBatchItem(); - - if (!txform.isIdentity()) - path = txform.map(path); - - QRectF trect; - QPolygonF txcoord; - - solid_color = m_pen_color; - bool has_complex_brush = false; - if (m_pen_brush_style != Qt::SolidPattern) { - has_complex_brush = true; - item->m_brush = m_pen.brush(); - item->m_info |= QD3DBatchItem::BI_COMPLEXBRUSH; - item->m_opacity = m_opacity; - } - - if (m_has_fast_pen) { - item->m_info |= QD3DBatchItem::BI_FASTLINE; - if (m_pen_brush_style == Qt::SolidPattern) { - m_draw_helper->queueAliasedMask(path, &item, solid_color); - item->m_info &= ~QD3DBatchItem::BI_MASK; // bypass stencil buffer - return; - } - } - - QRectF txrect = m_draw_helper->queueAliasedMask(path, &item, 0); - - if (has_complex_brush) { - trect = brect; - txcoord = brushCoordinates(brect, true, &item->m_distance); - item->m_info |= QD3DBatchItem::BI_TRANSFORM; - item->m_matrix = m_matrix; - } else { - trect = txrect; - static const QPolygonF empty_poly(4); - txcoord = empty_poly; - } - - m_draw_helper->queueRect(trect, item, solid_color, txcoord); -} - -void QDirect3DPaintEnginePrivate::fillAliasedPath(QPainterPath path, const QRectF &brect, const QTransform &txform) -{ - D3DCOLOR solid_color; - QD3DBatchItem *item = nextBatchItem(); - - if (!txform.isIdentity()) - path = txform.map(path); - - QRectF trect; - QPolygonF txcoord; - - solid_color = m_brush_color; - bool has_complex_brush = false; - if (m_brush_style != Qt::SolidPattern) { - has_complex_brush = true; - item->m_brush = m_brush; - item->m_info |= QD3DBatchItem::BI_COMPLEXBRUSH; - item->m_opacity = m_opacity; - } - - QRectF txrect = m_draw_helper->queueAliasedMask(path, &item, 0); - - if (has_complex_brush) { - trect = brect; - txcoord = brushCoordinates(brect, false, &item->m_distance); - item->m_info |= QD3DBatchItem::BI_TRANSFORM; - item->m_matrix = m_matrix; - } else { - trect = txrect; - static const QPolygonF empty_poly(4); - txcoord = empty_poly; - } - - m_draw_helper->queueRect(trect, item, solid_color, txcoord); -} - -void QDirect3DPaintEnginePrivate::fillAntialiasedPath(const QPainterPath &path, const QRectF &brect, - const QTransform &txform, bool stroke) -{ - D3DCOLOR solid_color; - bool winding = (path.fillRule() == Qt::WindingFill); - QPolygonF poly; - QRectF txrect; - QPainterPath tpath; - - if (m_has_aa_fast_pen && stroke) { - tpath = txform.map(path); - txrect = tpath.controlPointRect(); - txrect.adjust(-(m_pen_width/2),-(m_pen_width/2), m_pen_width, m_pen_width); - } else { - poly = path.toFillPolygon(txform); - txrect = poly.boundingRect(); - } - - // brect = approx. bounding rect before transformation - // txrect = exact bounding rect after transformation - // trect = the rectangle to be drawn - // txcoord = the texture coordinates - // adj_txrect = adjusted rect to include aliased outline - - bool use_scissor = false; - if (txrect.left() < 0) { - txrect.adjust(-txrect.left(),0,0,0); - use_scissor = true; - } - if (txrect.top() < 0) { - txrect.adjust(0,-txrect.top(),0,0); - use_scissor = true; - } - - if (!txrect.isValid()) - return; - - QD3DBatchItem *item = nextBatchItem(); - - QRectF adj_txrect = txrect.adjusted(-1,-1,1,1); - QRectF trect; - QPolygonF txcoord; - - bool has_complex_brush = false; - if (stroke) { - solid_color = m_pen_color; - if (m_pen_brush_style != Qt::SolidPattern) { - has_complex_brush = true; - item->m_brush = m_pen.brush(); - } - item->m_width = m_pen_width; - } else { - solid_color = m_brush_color; - if (m_brush_style != Qt::SolidPattern) { - has_complex_brush = true; - item->m_brush = m_brush; - } - } - - qreal focaldist = 0; - if (has_complex_brush) { - trect = brect; - txcoord = brushCoordinates(brect, stroke, &focaldist); - } else { - trect = adj_txrect; - static const QPolygonF empty_poly(4); - txcoord = empty_poly; - } - - bool maskfull; - item->m_maskpos = m_draw_helper->allocateMaskPosition(txrect, &maskfull); - if (maskfull) - item->m_info |= QD3DBatchItem::BI_MASKFULL; - item->m_distance = focaldist; - - if (winding) - item->m_info |= QD3DBatchItem::BI_WINDING; - - if (has_complex_brush) { - item->m_info |= QD3DBatchItem::BI_SCISSOR|QD3DBatchItem::BI_COMPLEXBRUSH| - QD3DBatchItem::BI_TRANSFORM; - item->m_brect = adj_txrect; - item->m_matrix = m_matrix; - item->m_opacity = m_opacity; - } - if (use_scissor) { - item->m_info |= QD3DBatchItem::BI_MASKSCISSOR; - item->m_brect = adj_txrect; - } - - if (m_has_aa_fast_pen && stroke) { - m_draw_helper->queueAntialiasedLines(tpath, &item, txrect); - } else { - m_draw_helper->queueAntialiasedMask(poly, &item, txrect); - } - - m_draw_helper->queueRect(trect, item, solid_color, txcoord); -} - -QPainterPath QDirect3DPaintEnginePrivate::strokePathFastPen(const QPainterPath &path) -{ - QPainterPath result; - QBezier beziers[32]; - for (int i=0; i<path.elementCount(); ++i) { - const QPainterPath::Element &e = path.elementAt(i); - switch (e.type) { - case QPainterPath::MoveToElement: - result.moveTo(e.x, e.y); - break; - case QPainterPath::LineToElement: - result.lineTo(e.x, e.y); - break; - - case QPainterPath::CurveToElement: - { - QPointF sp = path.elementAt(i-1); - QPointF cp2 = path.elementAt(i+1); - QPointF ep = path.elementAt(i+2); - i+=2; - - qreal inverseScaleHalf = m_inv_scale / 2; - beziers[0] = QBezier::fromPoints(sp, e, cp2, ep); - QBezier *b = beziers; - while (b >= beziers) { - // check if we can pop the top bezier curve from the stack - qreal l = qAbs(b->x4 - b->x1) + qAbs(b->y4 - b->y1); - qreal d; - if (l > m_inv_scale) { - d = qAbs( (b->x4 - b->x1)*(b->y1 - b->y2) - - (b->y4 - b->y1)*(b->x1 - b->x2) ) - + qAbs( (b->x4 - b->x1)*(b->y1 - b->y3) - - (b->y4 - b->y1)*(b->x1 - b->x3) ); - d /= l; - } else { - d = qAbs(b->x1 - b->x2) + qAbs(b->y1 - b->y2) + - qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3); - } - if (d < inverseScaleHalf || b == beziers + 31) { - // good enough, we pop it off and add the endpoint - result.lineTo(b->x4, b->y4); - --b; - } else { - // split, second half of the polygon goes lower into the stack - b->split(b+1, b); - ++b; - } - } - } // case CurveToElement - default: - break; - } // end of switch - } - return result; -} - -void QDirect3DPaintEnginePrivate::strokePath(const QPainterPath &path, QRectF brect, bool simple) -{ - QTransform txform; - QPainterPath tpath; - - if (m_has_fast_pen || m_has_aa_fast_pen) { - if (!simple) - tpath = strokePathFastPen(path); - else - tpath = path; //already only lines - } else { - tpath = strokeForPath(path, m_pen); - } - - if (tpath.isEmpty()) - return; - - //brect is null if the path is not transformed - if (brect.isNull()) - txform = m_matrix; - - if (!brect.isNull()) { - // brect is set when the path is transformed already, - // this is the case when we have a cosmetic pen. - brect.adjust(-(m_pen_width/2),-(m_pen_width/2), m_pen_width, m_pen_width); - } - - if (brect.isNull()) - brect = tpath.controlPointRect(); - brect.adjust(-m_inv_scale,-m_inv_scale,m_inv_scale,m_inv_scale); //adjust for antialiasing - - if (m_current_state & QD3DBatchItem::BI_AA) { - fillAntialiasedPath(tpath, brect, txform, true); - } else { - strokeAliasedPath(tpath, brect, txform); - } -} - -void QDirect3DPaintEnginePrivate::fillPath(const QPainterPath &path, QRectF brect) -{ - QTransform txform; - - //brect is null if the path is not transformed - if (brect.isNull()) - txform = m_matrix; - - if (brect.isNull()) - brect = path.controlPointRect(); - brect.adjust(-m_inv_scale,-m_inv_scale,m_inv_scale,m_inv_scale); //adjust for antialiasing - - if (m_current_state & QD3DBatchItem::BI_AA) { - fillAntialiasedPath(path, brect, txform, false); - } else { - fillAliasedPath(path, brect, txform); - } -} - - -bool QDirect3DPaintEnginePrivate::init() -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEnginePrivate::init()"; -#endif - - m_draw_helper = 0; - m_gradient_cache = 0; - m_dc = 0; - m_dcsurface = 0; - - m_supports_d3d = false; - m_current_state = 0; - m_in_scene = false; - m_has_fast_pen = false; - m_has_aa_fast_pen = false; - m_has_pen = false; - m_has_brush = false; - m_pen_color = 0; - m_brush_color = 0; - m_current_surface = 0; - m_batch.m_item_index = 0; - m_current_technique = RT_NoTechnique; - - if (!pDirect3DCreate9) { - QLibrary d3d_lib(QLatin1String("d3d9.dll")); - pDirect3DCreate9 = (PFNDIRECT3DCREATE9) d3d_lib.resolve("Direct3DCreate9"); - if (!pDirect3DCreate9) { - qWarning("QDirect3DPaintEngine: failed to resolve symbols from d3d9.dll.\n" - "Make sure you have the DirectX run-time installed."); - return false; - } - } - - if (!pD3DXCreateBuffer || !pD3DXCreateEffect || !pD3DXMatrixOrthoOffCenterLH) { - QLibrary d3dx_lib(QLatin1String("d3dx9_32.dll")); - pD3DXCreateBuffer = (PFND3DXCREATEBUFFER) d3dx_lib.resolve("D3DXCreateBuffer"); - pD3DXCreateEffect = (PFND3DXCREATEEFFECT) d3dx_lib.resolve("D3DXCreateEffect"); - pD3DXMatrixOrthoOffCenterLH = (PFND3DXMATRIXORTHOOFFCENTERLH) - d3dx_lib.resolve("D3DXMatrixOrthoOffCenterLH"); - if (!(pD3DXCreateBuffer && pD3DXCreateEffect && pD3DXMatrixOrthoOffCenterLH)) { - qWarning("QDirect3DPaintEngine: failed to resolve symbols from d3dx9_32.dll.\n" - "Make sure you have the DirectX run-time installed."); - return false; - } - } - - if (!m_d3d_object) { - m_d3d_object = pDirect3DCreate9(D3D_SDK_VERSION); - if (!m_d3d_object) { - qWarning("QDirect3DPaintEngine: failed to create Direct3D object.\n" - "Direct3D support in Qt will be disabled."); - return false; - } - } - - m_supports_d3d = testCaps(); - if (!m_supports_d3d) - return false; - - m_surface_manager.init(m_d3d_object); - m_d3d_device = m_surface_manager.device(); - - if (!m_d3d_device) - return false; - - /* load shaders */ - QFile file(QLatin1String(":/qpaintengine_d3d.fx")); - QByteArray fxFile; - if (file.open(QFile::ReadOnly)) - fxFile = file.readAll(); - - if (fxFile.size() > 0) { - LPD3DXBUFFER compout; - pD3DXCreateBuffer(4096, &compout); - DWORD dwShaderFlags = D3DXFX_NOT_CLONEABLE|D3DXFX_DONOTSAVESTATE|D3DXSHADER_OPTIMIZATION_LEVEL3; - if(FAILED(pD3DXCreateEffect(m_d3d_device, fxFile.constData(), fxFile.size(), - NULL, NULL, dwShaderFlags, NULL, &m_effect, &compout))) { - qWarning("QDirect3DPaintEngine: failed to compile effect file"); - if (compout) - qWarning((char *)compout->GetBufferPointer()); - m_supports_d3d = false; - return false; - } - if (m_effect) { - m_statemanager = new QD3DStateManager(m_d3d_device, m_effect); - m_effect->SetStateManager(m_statemanager); - m_draw_helper = new QD3DDrawHelper(this); - initDevice(); - m_gradient_cache = new QD3DGradientCache(m_d3d_device); - } - } else { - return false; - } - - return true; -} - -QPixmap QDirect3DPaintEnginePrivate::getPattern(Qt::BrushStyle style) const -{ - if (!m_patterns.contains(style)) { - QImage img(16,16,QImage::Format_ARGB32); - img.fill(0); - QPainter p(&img); - p.setBrush(QBrush(Qt::white, style)); - p.setPen(Qt::NoPen); - p.drawRect(0,0,16,16); - p.end(); - QPixmap pattern(QPixmap::fromImage(img)); - QDirect3DPaintEnginePrivate *ct = const_cast<QDirect3DPaintEnginePrivate *>(this); - ct->verifyTexture(pattern); - ct->m_patterns.insert(style, pattern); - } - - return m_patterns.value(style); -} - -bool QDirect3DPaintEnginePrivate::testCaps() -{ - D3DCAPS9 caps; - if (FAILED(m_d3d_object->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps))) - return false; - - if ((caps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) - && (caps.DevCaps & D3DDEVCAPS_PUREDEVICE) - && (caps.RasterCaps & D3DPRASTERCAPS_SCISSORTEST) - && (caps.StencilCaps & D3DSTENCILCAPS_TWOSIDED)) - return true; -#if 0 - qDebug() << "Direct3D caps:"; - qDebug() << "D3DPRESENT_INTERVAL_IMMEDIATE:" << ((caps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) != 0); - qDebug() << "D3DDEVCAPS_PUREDEVICE:" << ((caps.DevCaps & D3DDEVCAPS_PUREDEVICE) != 0); - qDebug() << "D3DPRASTERCAPS_SCISSORTEST:" << ((caps.RasterCaps & D3DPRASTERCAPS_SCISSORTEST) != 0); - qDebug() << "D3DSTENCILCAPS_TWOSIDED:" << ((caps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) != 0); -#endif - return false; -} - -void QDirect3DPaintEnginePrivate::initDevice() -{ - m_statemanager->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - m_statemanager->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); - m_statemanager->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); - m_statemanager->SetRenderState(D3DRS_LIGHTING, FALSE); - m_statemanager->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - m_statemanager->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - m_statemanager->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTALPHA); -} - -void QDirect3DPaintEnginePrivate::updatePen(const QPen &pen) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::updatePen"; -#endif - m_pen = pen; - m_has_cosmetic_pen = false; - m_has_pen = (m_pen.style() != Qt::NoPen); - if (m_has_pen) { - m_pen_brush_style = m_pen.brush().style(); - - if (m_pen_brush_style >= Qt::SolidPattern && m_pen_brush_style <= Qt::DiagCrossPattern) { - int a, r, g, b; - m_pen.color().getRgb(&r, &g, &b, &a); - m_pen_color = D3DCOLOR_ARGB((int)(a * m_opacity),r,g,b); - } else { - m_pen_color = m_opacity_color; - } - - m_has_cosmetic_pen = m_pen.isCosmetic(); - - if (m_pen_brush_style != Qt::NoBrush && - m_pen_brush_style != Qt::SolidPattern) { - bool ok; - m_inv_pen_matrix = m_pen.brush().transform().inverted(&ok); - if (!ok) - qWarning() << "QDirect3DPaintEngine: No inverse matix for pen brush matrix."; - } - - m_pen_width = m_pen.widthF(); - if (m_pen_width == 0.0f) - m_pen_width = 1.0f; - } -} - -void QDirect3DPaintEnginePrivate::updateBrush(const QBrush &brush) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::updateBrush"; -#endif - m_brush = brush; - m_brush_style = m_brush.style(); - m_has_brush = (m_brush_style != Qt::NoBrush); - if (m_has_brush) { - if (m_brush_style >= Qt::SolidPattern && m_brush_style <= Qt::DiagCrossPattern) { - int a, r, g, b; - m_brush.color().getRgb(&r, &g, &b, &a); - m_brush_color = D3DCOLOR_ARGB((int)(a * m_opacity),r,g,b); - } else { - m_brush_color = m_opacity_color; - } - - if (m_brush_style != Qt::SolidPattern) { - bool ok; - m_inv_brush_matrix = (m_brush.transform() * m_brush_origin).inverted(&ok); - if (!ok) - qWarning() << "QDirect3DPaintEngine: No inverse matix for brush matrix."; - - // make sure the texture is loaded as a texture - if (m_brush_style == Qt::TexturePattern) - verifyTexture(m_brush.texture()); - - - } - } -} - -void QDirect3DPaintEnginePrivate::updateTransform(const QTransform &matrix) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::updateTransform"; -#endif - m_matrix = matrix; - m_inv_scale = qMax(1 / qMax( qMax(qAbs(m_matrix.m11()), qAbs(m_matrix.m22())), - qMax(qAbs(m_matrix.m12()), qAbs(m_matrix.m21())) ), 0.0001); - m_txop = matrix.type(); -} - -int QDirect3DPaintEnginePrivate::flushAntialiased(int offset) -{ - // fills the mask (returns number of items added to the mask) - int newoffset = m_draw_helper->drawAntialiasedMask(offset, m_batch.m_item_index); - - // set the render target to the current output surface - if (FAILED(m_d3d_device->SetRenderTarget(0, m_current_surface))) - qWarning() << "QDirect3DPaintEngine: SetRenderTarget failed!"; - - // draw the bounding boxes (using the mask generated by drawAntialiasedMask) - for (int i=offset; i<newoffset; ++i) { - QD3DBatchItem *item = &(m_batch.items[i]); - int pass = (item->m_info & QD3DBatchItem::BI_COMPLEXBRUSH) ? PASS_AA_DRAW : PASS_AA_DRAW_DIRECT; - m_statemanager->beginPass(pass); - prepareItem(item); - if (item->m_info & QD3DBatchItem::BI_BRECT) - m_draw_helper->drawAntialiasedBoundingRect(item); - cleanupItem(item); - } - - m_statemanager->endPass(); - - return newoffset; -} - -bool QDirect3DPaintEnginePrivate::prepareBatch(QD3DBatchItem *item, int offset) -{ - if (item->m_info & QD3DBatchItem::BI_CLIP) { - setRenderTechnique(RT_Aliased); - if (item->m_info & QD3DBatchItem::BI_CLEARCLIP) { - m_d3d_device->Clear(0, 0, D3DCLEAR_ZBUFFER, 0, 0.0f, 0); - return true; - } - - m_draw_helper->drawAliasedMask(offset); - m_d3d_device->Clear(0, 0, D3DCLEAR_ZBUFFER, 0, 1.0f, 0); - if (item->m_info & QD3DBatchItem::BI_BRECT) { - m_statemanager->beginPass(PASS_STENCIL_CLIP); - m_draw_helper->drawAliasedBoundingRect(item); - m_statemanager->endPass(); - } - - return true; - } - - if (item->m_info & QD3DBatchItem::BI_AA) { - setRenderTechnique(RT_Antialiased); - } else { - setRenderTechnique(RT_Aliased); - } - - return false; -} - -void QDirect3DPaintEnginePrivate::prepareItem(QD3DBatchItem *item) { - // pixmap - int brushmode = 0; - m_statemanager->startStateBlock(); - if ((item->m_info & QD3DBatchItem::BI_PIXMAP) || (item->m_info & QD3DBatchItem::BI_IMAGE)) { - QRasterPixmapData *data = static_cast<QRasterPixmapData*>(item->m_pixmap.data); - IDirect3DTexture9 *tex = (item->m_info & QD3DBatchItem::BI_PIXMAP) ? - data->texture : item->m_texture; - m_statemanager->setTexture(tex); - brushmode = 5; - } - - if (item->m_info & QD3DBatchItem::BI_AA) { - m_statemanager->setMaskChannel(item->m_maskpos.channel); - m_statemanager->setMaskOffset(item->m_xoffset, item->m_yoffset); - } - - if (item->m_info & QD3DBatchItem::BI_COMPLEXBRUSH) { - const QBrush brush = item->m_brush; - switch (brush.style()) { - case Qt::TexturePattern: { - QRasterPixmapData *data = static_cast<QRasterPixmapData*>(brush.texture().data); - m_statemanager->setTexture(data->texture, QGradient::RepeatSpread); - brushmode = 1; - break; - } - case Qt::LinearGradientPattern: - m_statemanager->setTexture(m_gradient_cache-> - getBuffer(brush.gradient()->stops(), item->m_opacity), - brush.gradient()->spread()); - brushmode = 2; - break; - case Qt::ConicalGradientPattern: - m_statemanager->setTexture(m_gradient_cache-> - getBuffer(brush.gradient()->stops(), item->m_opacity), - brush.gradient()->spread()); - brushmode = 3; - break; - case Qt::RadialGradientPattern: - m_statemanager->setTexture(m_gradient_cache-> - getBuffer(brush.gradient()->stops(), item->m_opacity), - brush.gradient()->spread()); - m_statemanager->setFocalDistance(item->m_distance); - brushmode = 4; - break; - default: { - QRasterPixmapData *data = static_cast<QRasterPixmapData*>(getPattern(brush.style()).data); - m_statemanager->setTexture(data->texture, QGradient::RepeatSpread); - brushmode = 5; - } - }; - } - - if (item->m_info & QD3DBatchItem::BI_TRANSFORM) { - m_statemanager->setTransformation(&item->m_matrix); - } else { - m_statemanager->setTransformation(); - } - - m_statemanager->setBrushMode(brushmode); - setCompositionMode(item->m_cmode); - m_statemanager->endStateBlock(); -} - - -void QDirect3DPaintEnginePrivate::releaseDC() -{ - if (m_dc) { - m_dcsurface->ReleaseDC(m_dc); - m_dcsurface = 0; - m_dc = 0; - } -} - - -void QDirect3DPaintEnginePrivate::cleanupItem(QD3DBatchItem *item) -{ - if (item->m_info & QD3DBatchItem::BI_PIXMAP) - item->m_pixmap = QPixmap(); - item->m_brush = QBrush(); -} - -void QDirect3DPaintEnginePrivate::verifyTexture(const QPixmap &pm) -{ - QRasterPixmapData *pmData = static_cast<QRasterPixmapData*>(pm.data); - if (!pmData->texture) { - QImage im = pmData->image; - // bitmaps are drawn with the current pen color - if (im.depth() == 1) { - QVector<QRgb> colors(2); - colors[0] = 0; - colors[1] = m_pen.color().rgba(); - im.setColorTable(colors); - } - im = im.convertToFormat(QImage::Format_ARGB32); - if (FAILED(m_d3d_device->CreateTexture(im.width(), im.height(), 1, 0, - D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pmData->texture, 0))) - { - qWarning("QDirect3DPaintEngine: unable to create Direct3D texture from pixmap."); - return; - } - D3DLOCKED_RECT rect; - if (FAILED(pmData->texture->LockRect(0, &rect, 0, 0))) { - qDebug() << "QDirect3DPaintEngine: unable to lock texture rect."; - return; - } - DWORD *dst = (DWORD *) rect.pBits; - DWORD *src = (DWORD *) im.scanLine(0); - - Q_ASSERT((rect.Pitch/4) == (im.bytesPerLine()/4)); - memcpy(dst, src, rect.Pitch*im.height()); - pmData->texture->UnlockRect(0); - } -} - -bool QDirect3DPaintEnginePrivate::isFastRect(const QRectF &rect) -{ - if (m_matrix.type() < QTransform::TxRotate) { - QRectF r = m_matrix.mapRect(rect); - return r.topLeft().toPoint() == r.topLeft() - && r.bottomRight().toPoint() == r.bottomRight(); - } - - return false; -} - -void QDirect3DPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode mode) -{ - switch(mode) { - case QPainter::CompositionMode_SourceOver: - default: - m_statemanager->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - m_statemanager->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); - }; -} - -void QDirect3DPaintEnginePrivate::cleanup() -{ - // clean batch - for(int i=0; i<QD3D_BATCH_SIZE; ++i) { - m_batch.items[i].m_brush = QBrush(); - m_batch.items[i].m_pixmap = QPixmap(); - } - - m_surface_manager.cleanup(); - m_patterns.clear(); - - delete m_gradient_cache; - delete m_draw_helper; - - if (m_effect) - m_effect->Release(); - - if (m_d3d_object) - m_d3d_object->Release(); - - m_effect = 0; - m_d3d_object = 0; - m_gradient_cache = 0; - m_draw_helper = 0; -} - -void QDirect3DPaintEnginePrivate::flushAliased(QD3DBatchItem *item, int offset) -{ - m_draw_helper->drawAliasedMask(offset); - - if (item->m_info & QD3DBatchItem::BI_BRECT) { - int pass = (item->m_info & QD3DBatchItem::BI_MASK) ? PASS_STENCIL_DRAW_DIRECT : PASS_STENCIL_NOSTENCILCHECK_DIRECT; - if (item->m_info & (QD3DBatchItem::BI_COMPLEXBRUSH|QD3DBatchItem::BI_IMAGE|QD3DBatchItem::BI_PIXMAP) ) - pass = (item->m_info & QD3DBatchItem::BI_MASK) ? PASS_STENCIL_DRAW : PASS_STENCIL_NOSTENCILCHECK; - m_statemanager->beginPass(pass); - prepareItem(item); - m_draw_helper->drawAliasedBoundingRect(item); - cleanupItem(item); - m_statemanager->endPass(); - } -} - -void QDirect3DPaintEnginePrivate::flushText(QD3DBatchItem *item, int) -{ - prepareItem(item); - m_statemanager->setTexture(item->m_texture); - m_statemanager->setBrushMode(1); -// m_statemanager->SetRenderState(D3DRS_BLENDFACTOR, item->m_brush.color().rgba()); - m_statemanager->beginPass(m_cleartype_text ? PASS_CLEARTYPE_TEXT : PASS_TEXT); - m_draw_helper->drawTextItem(item); - m_statemanager->endPass(); - cleanupItem(item); -} - -void QDirect3DPaintEnginePrivate::flushLines(QD3DBatchItem *item, int) -{ - m_draw_helper->drawAliasedLines(item); - - if (item->m_info & QD3DBatchItem::BI_BRECT) { - int pass = (item->m_info & QD3DBatchItem::BI_COMPLEXBRUSH) ? PASS_STENCIL_DRAW : PASS_STENCIL_DRAW_DIRECT; - m_statemanager->beginPass(pass); - prepareItem(item); - m_draw_helper->drawAliasedBoundingRect(item); - cleanupItem(item); - m_statemanager->endPass(); - } -} - -void QDirect3DPaintEnginePrivate::flushBatch() -{ -// static int dbgcounter = 0; -// ++dbgcounter; -// qDebug() << " -> flush" << dbgcounter; - - int offset = 0; - m_draw_helper->unlockVertexBuffer(); - releaseDC(); - - // iterate over all items in the batch - while (offset != m_batch.m_item_index) { - QD3DBatchItem *item = &(m_batch.items[offset]); - - if (prepareBatch(item, offset)) { - ++offset; - continue; - } - - if (item->m_info & QD3DBatchItem::BI_FASTLINE) { - flushLines(item, offset++); - } else if (item->m_info & QD3DBatchItem::BI_AA) { - offset = flushAntialiased(offset); - } else if (item->m_info & QD3DBatchItem::BI_TEXT) { - flushText(item, offset++); - } else { - flushAliased(item, offset++); - } - } - - // reset batch - m_batch.m_item_index = 0; - - // release doomed textures - for (int i=0; i<qd3d_release_list.size(); ++i) - qd3d_release_list.at(i)->Release(); - qd3d_release_list.clear(); -} - -QDirect3DPaintEngine::QDirect3DPaintEngine() - : QPaintEngine(*(new QDirect3DPaintEnginePrivate), - PaintEngineFeatures(AllFeatures & ~ObjectBoundingModeGradients)) -{ } - -QDirect3DPaintEngine::~QDirect3DPaintEngine() -{ -} - -bool QDirect3DPaintEngine::begin(QPaintDevice *device) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::begin"; -#endif - Q_D(QDirect3DPaintEngine); - setActive(true); - - QSize old_size = d->m_surface_size; - d->m_surface_size = QRect(0, 0, device->width(), device->height()).size(); - - d->m_current_state = 0; - d->m_inv_scale = 1; - d->m_opacity = 1.0f; - d->m_opacity_color = D3DCOLOR_ARGB(255,255,255,255); - d->m_matrix = QTransform(); - d->m_brush_origin = QTransform(); - d->m_txop = QTransform::TxNone; - d->m_cmode = QPainter::CompositionMode_SourceOver; - - Q_ASSERT(device && device->devType() == QInternal::Widget); - if (d->m_d3d_device == 0) { - qWarning() << "QDirect3DPaintEngine: No Device!"; - return false; - } - - d->m_cleartype_text = false; -// QT_WA({ -// UINT result; -// BOOL ok; -// ok = SystemParametersInfoW(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0); -// if (ok) -// d->m_cleartype_text = (result == FE_FONTSMOOTHINGCLEARTYPE); -// }, { -// UINT result; -// BOOL ok; -// ok = SystemParametersInfoA(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0); -// if (ok) -// d->m_cleartype_text = (result == FE_FONTSMOOTHINGCLEARTYPE); -// }); - - d->m_surface_manager.setPaintDevice(device); - int status = d->m_surface_manager.status(); - if (status & QD3DSurfaceManager::NeedsResetting) { - d->m_effect->OnLostDevice(); - d->m_draw_helper->beforeReset(); - d->m_statemanager->reset(); - d->m_surface_manager.reset(); - d->m_draw_helper->afterReset(); - d->m_effect->OnResetDevice(); - d->initDevice(); - } - - LPDIRECT3DSURFACE9 newsurface = d->m_surface_manager.renderTarget(); - if (d->m_current_surface != newsurface) { - d->m_current_surface = newsurface; - if (FAILED(d->m_d3d_device->SetRenderTarget(0, newsurface))) - qWarning() << "QDirect3DPaintEngine: SetRenderTarget failed!"; - } - - status = d->m_surface_manager.status(); - if (status & QD3DSurfaceManager::MaxSizeChanged) { - QSize maxsize = d->m_surface_manager.maxSize(); - d->m_draw_helper->setMaskSize(maxsize); - int masksize[2] = {maxsize.width(), maxsize.height()}; - d->m_effect->SetIntArray("g_mMaskSize", masksize, 2); - } - - if (old_size != d->m_surface_size) { - D3DXMATRIX projMatrix; - pD3DXMatrixOrthoOffCenterLH(&projMatrix, 0, d->m_surface_size.width(), d->m_surface_size.height(), 0, 0.0f, 1.0f); - d->m_statemanager->setProjection(&projMatrix); - } - - if (!d->m_in_scene) { - if (FAILED(d->m_d3d_device->BeginScene())) { - qWarning() << "QDirect3DPaintEngine: BeginScene() failed."; - return false; - } - QWidget *widget = static_cast<QWidget *>(device); - if (widget->autoFillBackground() == true) { - QColor color = widget->palette().brush(widget->backgroundRole()).color(); - RECT rect = {0, 0, widget->width(), widget->height()}; - d->m_d3d_device->ColorFill(d->m_current_surface, &rect, - D3DCOLOR_ARGB(color.alpha(), color.red(), color.green(), color.blue())); - } - d->m_in_scene = true; - } - - // set system clip - d->m_clipping_enabled = false; - d->m_has_complex_clipping = false; - - d->m_sysclip_region = systemClip(); - QVector<QRect> rects = d->m_sysclip_region.rects(); - if (rects.count() == 1 && rects.at(0).size() == d->m_surface_size) - d->m_sysclip_region = QRegion(); - - d->updateClipRegion(QRegion(), Qt::NoClip); - - return true; -} - -void QDirect3DPaintEngine::drawEllipse(const QRectF &rect) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawEllipse (float)"; -#endif - QPaintEngine::drawEllipse(rect); -} - -void QDirect3DPaintEngine::drawEllipse(const QRect &rect) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawEllipse"; -#endif - QPaintEngine::drawEllipse(rect); -} - -void QDirect3DPaintEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr, - Qt::ImageConversionFlags) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawImage"; -#endif - - Q_D(QDirect3DPaintEngine); - int width = image.width(); - int height = image.height(); - - // transform rectangle - QPolygonF txrect(QRectF(sr.left() / width, sr.top() / height, - sr.width() / width, sr.height() / height)); - - QD3DBatchItem *item = d->nextBatchItem(); - item->m_info = QD3DBatchItem::BI_IMAGE | QD3DBatchItem::BI_TRANSFORM; - item->m_texture = qd3d_image_cache()->lookup(d->m_d3d_device, image); - item->m_matrix = d->m_matrix; - d->m_draw_helper->queueRect(r.adjusted(-0.5f,-0.5f,-0.5f,-0.5f), item, d->m_opacity_color, txrect); -} - -void QDirect3DPaintEngine::drawLines(const QLineF *lines, int lineCount) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawLines (float)"; -#endif - Q_D(QDirect3DPaintEngine); - - if (!d->m_has_pen) - return; - - if (d->m_has_fast_pen && (d->m_pen_brush_style == Qt::SolidPattern)) { - QD3DBatchItem *item = d->nextBatchItem(); - if (d->m_pen.isCosmetic()) - item->m_info |= QD3DBatchItem::BI_COSMETICPEN; - item->m_info |= QD3DBatchItem::BI_TRANSFORM; - item->m_matrix = d->m_matrix; - d->m_draw_helper->queueAliasedLines(lines, lineCount, &item); - } else { - QRectF brect; - QPainterPath path; - - // creates a path with the lines - path.moveTo(lines[0].x1(), lines[0].y1()); - qreal lastx = lines[0].x2(); - qreal lasty = lines[0].y2(); - path.lineTo(lastx, lasty); - - for (int i=1; i<lineCount; ++i) { - qreal x = lines[i].x1(); - qreal y = lines[i].y1(); - if (lastx != x || lasty != y) { - path.moveTo(x, y); - } - path.lineTo(lines[i].x2(), lines[i].y2()); - } - - if (d->m_has_cosmetic_pen) { - brect = path.controlPointRect(); - path = d->m_matrix.map(path); - } - - d->strokePath(path, brect, true); - } -} - -void QDirect3DPaintEngine::drawLines(const QLine *lines, int lineCount) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawLines"; -#endif - QPaintEngine::drawLines(lines, lineCount); -} - -void QDirect3DPaintEngine::drawPath(const QPainterPath &path) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawPath"; -#endif - Q_D(QDirect3DPaintEngine); - - if (path.isEmpty()) - return; - - QRectF brect; - QPainterPath tpath; - - if (d->m_has_cosmetic_pen) { - brect = path.controlPointRect(); - tpath = d->m_matrix.map(path); - } else { - tpath = path; - } - - if (d->m_has_brush) - d->fillPath(tpath, brect); - - if (d->m_has_pen) - d->strokePath(tpath, brect); -} - - -QPointF QDirect3DPaintEnginePrivate::transformPoint(const QPointF &p, qreal *w) const -{ - (*w) = 1.0f; - qreal fx = p.x(); - qreal fy = p.y(); - qreal nx = m_matrix.m11()*fx + m_matrix.m21()*fy + m_matrix.m31(); - qreal ny = m_matrix.m12()*fx + m_matrix.m22()*fy + m_matrix.m32(); - if (!m_matrix.isAffine()) { - *w = m_matrix.m13()*fx + m_matrix.m23()*fy + m_matrix.m33(); - //*w = 1/(*w); - nx = nx/(*w); - ny = ny/(*w); - } - return QPointF(nx, ny); -} - -void QDirect3DPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawPixmap"; -#endif - Q_D(QDirect3DPaintEngine); - - if (d->m_draw_helper->needsFlushing()) - d->flushBatch(); - - int width = pm.width(); - int height = pm.height(); - - // transform rectangle - QPolygonF txrect(QRectF(sr.left() / width, sr.top() / height, - sr.width() / width, sr.height() / height)); - - QD3DBatchItem *item = d->nextBatchItem(); - item->m_info = QD3DBatchItem::BI_PIXMAP|QD3DBatchItem::BI_TRANSFORM; - - item->m_pixmap = pm; - d->verifyTexture(item->m_pixmap); - - item->m_matrix = d->m_matrix; - d->m_draw_helper->queueRect(r.adjusted(-0.5f,-0.5f,-0.5f,-0.5f), item, d->m_opacity_color, txrect); -} - -void QDirect3DPaintEngine::drawPoints(const QPointF *points, int pointCount) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawPoints (float)"; -#endif - QPaintEngine::drawPoints(points, pointCount); -} - -void QDirect3DPaintEngine::drawPoints(const QPoint *points, int pointCount) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawPoints"; -#endif - QPaintEngine::drawPoints(points, pointCount); -} - -void QDirect3DPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawPolygon"; -#endif - Q_D(QDirect3DPaintEngine); - - if (d->m_has_brush && mode != PolylineMode) { - QPainterPath path; - path.setFillRule(mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill); - path.moveTo(points[0]); - for (int i=1; i<pointCount; ++i) - path.lineTo(points[i]); - if (path.isEmpty()) - return; - d->fillPath(path, QRectF()); - } - - if (d->m_has_pen) { - QPainterPath path(points[0]); - for (int i = 1; i < pointCount; ++i) - path.lineTo(points[i]); - if (mode != PolylineMode) - path.lineTo(points[0]); - - if (path.isEmpty()) - return; - QRectF brect; - if (d->m_has_cosmetic_pen) { - brect = path.controlPointRect(); - path = d->m_matrix.map(path); - } - - d->strokePath(path, brect); - } -} - -void QDirect3DPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawPolygon"; -#endif - QPaintEngine::drawPolygon(points, pointCount, mode); -} - -void QDirect3DPaintEngine::drawRects(const QRectF *rects, int rectCount) -{ - Q_D(QDirect3DPaintEngine); -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawRects (float)"; -#endif - for (int i=0; i<rectCount; ++i) { - if ((d->m_brush_style == Qt::SolidPattern) && - (!(d->m_current_state & QD3DBatchItem::BI_AA) || d->isFastRect(rects[i]))) { - QD3DBatchItem *item = d->nextBatchItem(); - item->m_info |= QD3DBatchItem::BI_TRANSFORM; - item->m_info &= ~QD3DBatchItem::BI_AA; - item->m_matrix = d->m_matrix; - const QRectF rect = rects[i]; - d->m_draw_helper->queueRect(rect, item, d->m_brush_color); - - if (d->m_has_pen) { - if (d->m_has_fast_pen && (d->m_pen_brush_style == Qt::SolidPattern)) { - QLineF lines[4]; - qreal x1 = rect.x(); - qreal y1 = rect.y(); - qreal x2 = rect.width() + x1; - qreal y2 = rect.height() + y1; - lines[0] = QLineF(x1, y1, x2, y1); - lines[1] = QLineF(x2, y1, x2, y2); - lines[2] = QLineF(x2, y2, x1, y2); - lines[3] = QLineF(x1, y2, x1, y1); - QD3DBatchItem *item = d->nextBatchItem(); - if (d->m_pen.isCosmetic()) - item->m_info |= QD3DBatchItem::BI_COSMETICPEN; - item->m_info |= QD3DBatchItem::BI_TRANSFORM; - item->m_matrix = d->m_matrix; - d->m_draw_helper->queueAliasedLines(lines, 4, &item); - } else { - QPainterPath path; - QRectF brect; - - path.addRect(rects[i]); - if (d->m_has_cosmetic_pen) { - brect = path.controlPointRect(); - path = d->m_matrix.map(path); - } - - d->strokePath(path, brect, true); - } - } - } else { - QPainterPath path; - QRectF brect; - - path.addRect(rects[i]); - if (d->m_has_cosmetic_pen) { - brect = path.controlPointRect(); - path = d->m_matrix.map(path); - } - - if (d->m_has_brush) - d->fillPath(path, brect); - - if (d->m_has_pen) - d->strokePath(path, brect, true); - } - } -} - -void QDirect3DPaintEngine::drawRects(const QRect *rects, int rectCount) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawRects"; -#endif - QPaintEngine::drawRects(rects, rectCount); -} - - -void QDirect3DPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) -{ - Q_D(QDirect3DPaintEngine); - -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawTextItem"; -#endif -// if (d->m_matrix.isScaling() || (d->m_pen_brush_style >= Qt::LinearGradientPattern -// && d->m_pen_brush_style <= Qt::ConicalGradientPattern)) { -// QPaintEngine::drawTextItem(p, textItem); -// return; -// } - - const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); - QVarLengthArray<QFixedPoint> positions; - QVarLengthArray<glyph_t> glyphs; - QTransform matrix; - matrix.translate(p.x(), p.y()); - ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); - - qd3d_glyph_cache()->cacheGlyphs(this, ti, glyphs, d->m_cleartype_text); - QD3DFontTexture *font_tex = qd3d_glyph_cache()->fontTexture(ti.fontEngine); - - QD3DBatchItem *item = d->nextBatchItem(); - d->m_draw_helper->lockVertexBuffer(); - - item->m_info = QD3DBatchItem::BI_TEXT - | (d->m_current_state & ~QD3DBatchItem::BI_AA) | QD3DBatchItem::BI_TRANSFORM; - item->m_texture = font_tex->texture; - item->m_offset = d->m_draw_helper->index(); - item->m_matrix = d->m_matrix; - item->m_count = 0; - item->m_brush = d->m_pen.brush(); - - for (int i=0; i< glyphs.size(); ++i) { - QD3DGlyphCoord *g = qd3d_glyph_cache()->lookup(ti.fontEngine, glyphs[i]); - - // we don't cache glyphs with no width/height - if (!g) - continue; - - // texture coords - qreal tex_coords[] = { g->x, g->y, g->x + g->width, g->y + g->height }; - QPointF logical_pos(qRound((positions[i].x - g->x_offset).toReal()) - 0.5f, - qRound((positions[i].y + g->y_offset).toReal()) - 0.5f); - - QRectF glyph_rect(logical_pos, QSizeF(g->log_width, g->log_height)); - d->m_draw_helper->queueTextGlyph(glyph_rect, tex_coords, item, d->m_pen_color); - } -} - -void QDirect3DPaintEngine::drawTiledPixmap(const QRectF &rect, const QPixmap &pixmap, const QPointF &p) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::drawTiledPixmap"; -#endif - QPaintEngine::drawTiledPixmap(rect, pixmap, p); -} - -bool QDirect3DPaintEngine::end() -{ - Q_D(QDirect3DPaintEngine); - - d->flushBatch(); - - if (d->m_flush_on_end) { - QPaintDevice *pdev = paintDevice(); - LPDIRECT3DSWAPCHAIN9 swapchain = swapChain(pdev); - - - QWidget *w = 0; - if (pdev->devType() == QInternal::Widget) { - w = static_cast<QWidget *>(pdev); - } - - if (w && swapchain) { - QRect br = w->rect(); - QRect wbr = br;//.translated(-w->pos()); - - RECT destrect; - destrect.left = wbr.x(); - destrect.top = wbr.y(); - destrect.right = destrect.left + wbr.width(); - destrect.bottom = destrect.top + wbr.height(); - - RECT srcrect; - srcrect.left = br.x();// + w->x(); - srcrect.top = br.y();// + w->y(); - srcrect.right = wbr.width() + srcrect.left; - srcrect.bottom = wbr.height() + srcrect.top; - int devwidth = w->width(); - int devheight = w->height(); - - if (devwidth <= srcrect.right) { - int diff = srcrect.right - devwidth; - srcrect.right -= diff; - destrect.right -= diff; - if (srcrect.right <= srcrect.left) - return false; - } - if (devheight <= srcrect.bottom) { - int diff = srcrect.bottom - devheight; - srcrect.bottom -= diff; - destrect.bottom -= diff; - if (srcrect.bottom <= srcrect.top) - return false; - } - - if (FAILED(swapchain->Present(&srcrect, &destrect, w->winId(), 0, 0))) - qWarning("QDirect3DPaintEngine: failed to present back buffer."); - } - } - - - return true; -} - -void QDirect3DPaintEngine::updateState(const QPaintEngineState &state) -{ -#ifdef QT_DEBUG_D3D_CALLS - qDebug() << "QDirect3DPaintEngine::updateState"; -#endif - Q_D(QDirect3DPaintEngine); - - bool update_fast_pen = false; - DirtyFlags flags = state.state(); - - if (flags & DirtyOpacity) { - d->m_opacity = state.opacity(); - if (d->m_opacity > 1.0f) - d->m_opacity = 1.0f; - if (d->m_opacity < 0.f) - d->m_opacity = 0.f; - uint c = (d->m_opacity * 255); - d->m_opacity_color = D3DCOLOR_ARGB(c,c,c,c); - flags |= (DirtyPen | DirtyBrush); - } - - if (flags & DirtyCompositionMode) { - d->m_cmode = state.compositionMode(); - } - - if (flags & DirtyTransform) { - d->updateTransform(state.transform()); - update_fast_pen = true; - } - - if (flags & DirtyHints) { - if (state.renderHints() & QPainter::Antialiasing) - d->m_current_state |= QD3DBatchItem::BI_AA; - else - d->m_current_state &= ~QD3DBatchItem::BI_AA; - update_fast_pen = true; - } - - if (flags & DirtyFont) { - d->updateFont(state.font()); - } - - if (state.state() & DirtyClipEnabled) { - if (state.isClipEnabled() && !d->m_clipping_enabled) { - d->m_clipping_enabled = true; - if (d->m_has_complex_clipping) - d->updateClipPath(painter()->clipPath(), Qt::ReplaceClip); - else - d->updateClipRegion(painter()->clipRegion(), Qt::ReplaceClip); - } else if (!state.isClipEnabled() && d->m_clipping_enabled) { - d->m_clipping_enabled = false; - if (d->m_has_complex_clipping) - d->updateClipPath(QPainterPath(), Qt::NoClip); - else - d->updateClipRegion(QRegion(), Qt::NoClip); - } - } - - if (flags & DirtyClipRegion) { - d->updateClipRegion(state.clipRegion(), state.clipOperation()); - } - - if (flags & DirtyClipPath) { - d->updateClipPath(state.clipPath(), state.clipOperation()); - } - - if (flags & DirtyBrushOrigin) { - d->m_brush_origin = QTransform(); - d->m_brush_origin.translate(-state.brushOrigin().x(), - -state.brushOrigin().y()); - flags |= DirtyBrush; - } - - if (flags & DirtyPen) { - d->updatePen(state.pen()); - update_fast_pen = true; - } - - if (flags & DirtyBrush) - d->updateBrush(state.brush()); - - if (update_fast_pen && d->m_has_pen) { - if (d->m_current_state & QD3DBatchItem::BI_AA) { - d->m_has_fast_pen = false; - d->m_has_aa_fast_pen = ((d->m_txop <= QTransform::TxTranslate) || d->m_has_cosmetic_pen) - && (d->m_pen_width <= 1.0f) - && (d->m_pen.style() == Qt::SolidLine); - } else { - d->m_has_aa_fast_pen = false; - d->m_has_fast_pen = ((d->m_txop <= QTransform::TxTranslate) || d->m_has_cosmetic_pen) - && (d->m_pen.style() == Qt::SolidLine) - && (d->m_pen.capStyle() == Qt::SquareCap); - } - } -} - -void QDirect3DPaintEngine::cleanup() -{ - Q_D(QDirect3DPaintEngine); - d->cleanup(); -} - -void QDirect3DPaintEngine::scroll(QPaintDevice *pd, const RECT &srcrect, const RECT &destrect) -{ - Q_D(QDirect3DPaintEngine); - LPDIRECT3DSURFACE9 srcsurf = d->m_surface_manager.surface(pd); - LPDIRECT3DSURFACE9 masksurf = d->m_draw_helper->freeMaskSurface(); - if (FAILED(d->m_d3d_device->StretchRect(srcsurf, &srcrect, masksurf, &srcrect, D3DTEXF_NONE))) - qWarning("QDirect3DPaintEngine: StretchRect failed."); - if (FAILED(d->m_d3d_device->StretchRect(masksurf, &srcrect, srcsurf, &destrect, D3DTEXF_NONE))) - qWarning("QDirect3DPaintEngine: StretchRect failed."); -} - -LPDIRECT3DSWAPCHAIN9 QDirect3DPaintEngine::swapChain(QPaintDevice *pd) -{ - Q_D(QDirect3DPaintEngine); - - if (d->m_in_scene) { - if (d->m_d3d_device == 0) { - qWarning("QDirect3DPaintEngine: No device!"); - return false; - } - - d->setRenderTechnique(QDirect3DPaintEnginePrivate::RT_NoTechnique); - if (FAILED(d->m_d3d_device->EndScene())) - qWarning("QDirect3DPaintEngine: failed to end scene."); - - d->m_in_scene = false; - } - - return d->m_surface_manager.swapChain(pd); -} - -void QDirect3DPaintEngine::releaseSwapChain(QPaintDevice *pd) -{ - Q_D(QDirect3DPaintEngine); - d->m_surface_manager.releasePaintDevice(pd); -} - -HDC QDirect3DPaintEngine::getDC() const -{ - QDirect3DPaintEnginePrivate *d = const_cast<QDirect3DPaintEnginePrivate *>(d_func()); - - if (!d->m_dc && d->m_current_surface) { - d->m_dcsurface = d->m_current_surface; - if (FAILED(d->m_current_surface->GetDC(&d->m_dc))) - qWarning() << "QDirect3DPaintEngine::getDC() failed!"; - } - - return d->m_dc; -} - -void QDirect3DPaintEngine::setFlushOnEnd(bool flushOnEnd) -{ - Q_D(QDirect3DPaintEngine); - - d->m_flush_on_end = flushOnEnd; -} - -bool QDirect3DPaintEngine::hasDirect3DSupport() -{ - Q_D(QDirect3DPaintEngine); - return d->m_supports_d3d; -} - -QT_END_NAMESPACE - -#include "qpaintengine_d3d.moc" diff --git a/src/gui/painting/qpaintengine_d3d.fx b/src/gui/painting/qpaintengine_d3d.fx deleted file mode 100644 index 1148b2a..0000000 --- a/src/gui/painting/qpaintengine_d3d.fx +++ /dev/null @@ -1,608 +0,0 @@ -bool g_mCosmeticPen; -int4 g_mChannel; -float2 g_mMaskOffset; -int2 g_mMaskSize; -float4x4 g_mMaskProjection; -float4x4 g_mViewProjection; -float4x4 g_mTransformation; -texture g_mAAMask; -texture g_mTexture; -int g_mBrushMode; -float g_mFocalDist; - -#define M_PI 3.14159265358979323846 - -sampler PixmapSampler = sampler_state -{ - texture = <g_mTexture>; - MIPFILTER = NONE; - MINFILTER = LINEAR; - MAGFILTER = LINEAR; -}; - -sampler TextSampler = sampler_state -{ - texture = <g_mTexture>; - MIPFILTER = NONE; - MINFILTER = POINT; - MAGFILTER = POINT; -}; - -sampler AAMaskSampler = sampler_state -{ - texture = <g_mAAMask>; - AddressU = WRAP; - AddressV = WRAP; - AddressW = WRAP; - MIPFILTER = NONE; - MINFILTER = POINT; - MAGFILTER = POINT; -}; - -struct VS_FULL -{ - float4 Position : POSITION; - float4 Diffuse : COLOR0; - float4 TexCoords0 : TEXCOORD0; - float4 TexCoords1 : TEXCOORD1; -}; - -VS_FULL TrapezoidVS( float4 Position : POSITION, - float4 Diffuse : COLOR0, - float4 TexCoords0 : TEXCOORD0, - float4 TexCoords1 : TEXCOORD1) -{ - VS_FULL Output; - - float a = (TexCoords1.x * Position.x) + (TexCoords1.z * (1.0 - Position.x) ); // left or right a - float b = (TexCoords1.y * Position.x) + (TexCoords1.w * (1.0 - Position.x) ); // left or right b - float d = 1.0 - (Position.x * 2); - - Position.x = (a * Position.y + b) + ( sqrt( abs(a * a) ) * d ); - //Position.x += step(abs(a), 0) * d; - Position.x += (0.5 * d); - - Output.Position = mul(Position, g_mMaskProjection); - Output.Diffuse = Diffuse; - Output.TexCoords0 = TexCoords0; - Output.TexCoords1 = TexCoords1; - - return Output; -} - -struct PS_OUTPUT -{ - float4 Color : COLOR0; -}; - -PS_OUTPUT TrapezoidPS(VS_FULL In, float2 pixelPos : VPOS) -{ - PS_OUTPUT Out; - - float top = max(pixelPos.y - 0.5, In.TexCoords0.x); - float bottom = min(pixelPos.y + 0.5, In.TexCoords0.y); - - float area = bottom - top; - - float left = pixelPos.x - 0.5; - float right = pixelPos.x + 0.5; - - // use line equations to compute intersections of left/right edges with top/bottom of truncated pixel - // vecX: x = (left, top), y = (left, bottom), z = (right, top), w = (right, bottom) - float4 vecX = In.TexCoords1.xxzz * float2(top, bottom).xyxy + In.TexCoords1.yyww; - - float2 invA = In.TexCoords0.zw; - - // transform right line to left to be able to use same calculations for both - vecX.zw = 2 * pixelPos.x - vecX.zw; - - float2 topX = float2(vecX.x, vecX.z); - float2 bottomX = float2(vecX.y, vecX.w); - - // transform lines such that top intersection is to the right of bottom intersection - float2 topXTemp = max(topX, bottomX); - float2 bottomXTemp = min(topX, bottomX); - - // make sure line slope reflects mirrored lines - invA = lerp(invA, -invA, step(topX, bottomX)); - - float2 vecLeftRight = float2(left, right); - - // compute the intersections of the lines with the left and right edges of the pixel - // intersectY: x = (left_line, left), y = (left_line, right), z = (right_line, left), w = (right_line, right) - float4 intersectY = top + (vecLeftRight.xyxy - topXTemp.xxyy) * invA.xxyy; - - float2 temp = lerp(area - 0.5 * (right - bottomXTemp) * (bottom - intersectY.yw), // left < bottom < right < top - (0.5 * (topXTemp + bottomXTemp) - left) * area, // left < bottom < top < right - step(topXTemp, right)); - - float2 excluded = 0.5 * (intersectY.xz - top) * (topXTemp - left); // bottom < left < top < right - - excluded = lerp(0.5 * (intersectY.yw + intersectY.xz) - top, // bottom < left < right < top - excluded, step(topXTemp, right)); - - excluded = lerp(temp, // left < bottom < right (see calculation of temp) - excluded, step(bottomXTemp, left)); - - excluded = lerp(float2(area, area), // right < bottom < top - excluded, step(bottomXTemp, right)); - - excluded *= step(left, topXTemp); - - float result = (area - excluded.x - excluded.y) * step(top, bottom); - Out.Color.r = result * g_mChannel[0]; - Out.Color.g = result * g_mChannel[1]; - Out.Color.b = result * g_mChannel[2]; - Out.Color.a = result * g_mChannel[3]; - - return Out; -} - -VS_FULL ViewProjectionVS( float4 Position : POSITION, - float4 Diffuse : COLOR0, - float4 TexCoords0 : TEXCOORD0, - float4 TexCoords1 : TEXCOORD1) -{ - VS_FULL Output; - - Output.Position = mul(Position, g_mTransformation); - Output.Position = mul(Output.Position, g_mViewProjection); - Output.Diffuse = Diffuse; - Output.TexCoords0 = TexCoords0; - Output.TexCoords1 = TexCoords1; - - return Output; -} - -PS_OUTPUT DirectMaskPS(VS_FULL In, float2 pixelPos : VPOS) -{ - PS_OUTPUT Out; - Out.Color = In.Diffuse; - - float2 maskcoords = ( (pixelPos + g_mMaskOffset) - 0.5 ) / g_mMaskSize; - float2 clipcoords = (pixelPos - 0.5) / g_mMaskSize; - - float4 c = tex2D(AAMaskSampler, maskcoords.xy) * Out.Color.a; - Out.Color.a = c.r * g_mChannel[0]; - Out.Color.a += c.g * g_mChannel[1]; - Out.Color.a += c.b * g_mChannel[2]; - Out.Color.a += c.a * g_mChannel[3]; - - return Out; -} - -PS_OUTPUT MaskPS(VS_FULL In, float2 pixelPos : VPOS) -{ - PS_OUTPUT Out; - - if (g_mBrushMode == 1) { - float x = In.TexCoords0.x; - float y = In.TexCoords0.y; - x = x - int(x); - y = y - int(y); - Out.Color = tex2D(PixmapSampler, float2(x, y)); - Out.Color.a = Out.Color.a * In.Diffuse.a; - } else if (g_mBrushMode == 2) { - Out.Color = tex1D(PixmapSampler, In.TexCoords0.x); - } else if (g_mBrushMode == 3) { - float t = atan2(In.TexCoords0.y, -In.TexCoords0.x) / (2 * M_PI); - Out.Color = tex1D(PixmapSampler, t + 0.5); - } else if (g_mBrushMode == 4) { - float2 tc = float2(In.TexCoords0.x, abs(In.TexCoords0.y)); - float a = (tc.x - g_mFocalDist) / tc.y; - float b = g_mFocalDist; - - float A = 1 + (a * a); - float B = 2.0 * a * b; - float C = (b * b) - 1; - - float y = (-B + sqrt(B*B - 4.0*A*C)) / (2.0*A); - Out.Color = tex1D(PixmapSampler, (tc.y / y) ); - } else if (g_mBrushMode == 5) { - Out.Color = tex2D(PixmapSampler, In.TexCoords0.xy); - Out.Color = Out.Color * In.Diffuse; - } else { - Out.Color = In.Diffuse; - } - - float2 maskcoords = ( (pixelPos + g_mMaskOffset) - 0.5 ) / g_mMaskSize; - - float4 c = tex2D(AAMaskSampler, maskcoords.xy) * Out.Color.a; - Out.Color.a = c.r * g_mChannel[0]; - Out.Color.a += c.g * g_mChannel[1]; - Out.Color.a += c.b * g_mChannel[2]; - Out.Color.a += c.a * g_mChannel[3]; - - return Out; -} - -struct VS_NORMAL -{ - float4 Position : POSITION; - float4 Diffuse : COLOR0; - float4 TexCoords : TEXCOORD0; -}; - -VS_NORMAL MaskProjectionVS(VS_NORMAL In) -{ - VS_NORMAL Output; - - Output.Position = mul(In.Position, g_mMaskProjection); - Output.Diffuse = In.Diffuse; - Output.TexCoords = In.TexCoords; - - return Output; -} - -float4 DirectSimplePS(float4 Color : COLOR0) : COLOR0 -{ - return Color; -} - -float4 SimplePS(float4 Color : COLOR0, float4 TexCoords : TEXCOORD0) : COLOR0 -{ - if (g_mBrushMode == 1) { - float opacity = Color.a; - float x = TexCoords.x; - float y = TexCoords.y; - x = x - int(x); - y = y - int(y); - Color = tex2D(PixmapSampler, float2(x, y)); - Color.a = Color.a * opacity; - } else if (g_mBrushMode == 2) { - Color = tex1D(PixmapSampler, TexCoords.x); - } else if (g_mBrushMode == 3) { - float t = atan2(TexCoords.y, -TexCoords.x) / (2 * M_PI); - Color = tex1D(PixmapSampler, t + 0.5); - } else if (g_mBrushMode == 4) { - float2 tc = float2(TexCoords.x, abs(TexCoords.y)); - float a = (tc.x - g_mFocalDist) / tc.y; - float b = g_mFocalDist; - - float A = 1 + (a * a); - float B = 2.0 * a * b; - float C = (b * b) - 1; - - float y = (-B + sqrt(B*B - 4.0*A*C)) / (2.0*A); - Color = tex1D(PixmapSampler, (tc.y / y) ); - } else if (g_mBrushMode == 5) { - Color = tex2D(PixmapSampler, TexCoords.xy) * Color; - } - - return Color; -} - -float4 TextPS(float4 Color : COLOR0, float4 TexCoords : TEXCOORD0) : COLOR0 -{ - Color.a *= tex2D(TextSampler, TexCoords.xy).a; - return Color; -} - -float4 ClearTypePS(float4 Color : COLOR0, float4 TexCoords : TEXCOORD0) : COLOR0 -{ -// if (g_mUsePixmap) { -// float4 MaskColor = tex2D(PixmapSampler, TexCoords.xy); -// Color = float4(1.0, 0.0, 0.0, 1.0); -// Color.a = (1 - MaskColor.a) + MaskColor.a * Color.a; -// Color.r = (1.0 - MaskColor.r) + (MaskColor.r * Color.r); -// Color.g = (1.0 - MaskColor.g) + (MaskColor.g * Color.g); -// Color.b = (1.0 - MaskColor.b) + (MaskColor.b * Color.b); -// Color = MaskColor; - return tex2D(PixmapSampler, TexCoords.xy); -} - -VS_NORMAL NoTxAliasedVS(VS_NORMAL In) -{ - VS_NORMAL Output; - - Output.Position = mul(In.Position, g_mViewProjection); - Output.Diffuse = In.Diffuse; - Output.TexCoords = In.TexCoords; - - return Output; -} - -VS_NORMAL AliasedVS(VS_NORMAL In) -{ - VS_NORMAL Output; - - Output.Position = mul(In.Position, g_mTransformation); - Output.Position = mul(Output.Position, g_mViewProjection); - Output.Diffuse = In.Diffuse; - Output.TexCoords = In.TexCoords; - - return Output; -} - -VS_NORMAL AliasedLinesVS(VS_NORMAL In) -{ - VS_NORMAL Output; - - float4 start = float4(In.Position.x, In.Position.y, 0.5, In.Position.w); - float4 end = float4(In.TexCoords.z, In.TexCoords.w, 0.5, In.Position.w); - if (g_mCosmeticPen) { - start = mul(start, g_mTransformation); - end = mul(end, g_mTransformation); - } - - float2 line_vec = end - start; - float2 vec = normalize(line_vec); - float2 norm = float2(-vec.y, vec.x); - - float pen_width = In.Position.z; - norm = norm * pen_width * 0.5; - vec = vec * pen_width * 0.5; - - Output.Position.w = In.Position.w; - Output.Position.x = start.x + (vec.x * In.TexCoords.x); - Output.Position.x = Output.Position.x + (norm.x * In.TexCoords.y); - Output.Position.x = Output.Position.x + (line_vec.x * step(0, In.TexCoords.x)); - Output.Position.y = start.y + (vec.y * In.TexCoords.x); - Output.Position.y = Output.Position.y + (norm.y * In.TexCoords.y); - Output.Position.y = Output.Position.y + (line_vec.y * step(0, In.TexCoords.x)); - Output.Position.z = 0.5; - - if (!g_mCosmeticPen) { - Output.Position = mul(Output.Position, g_mTransformation); - } - Output.Position = mul(Output.Position, g_mViewProjection); - - Output.Diffuse = In.Diffuse; - Output.TexCoords = In.TexCoords; - - return Output; -} - - -technique Antialiased -{ - pass PASS_AA_CREATEMASK - { - StencilEnable = False; - ZWriteEnable = False; - ColorWriteEnable = 0x0f; - ZEnable = False; - - SrcBlend = One; - DestBlend = One; - - VertexShader = compile vs_3_0 TrapezoidVS(); - PixelShader = compile ps_3_0 TrapezoidPS(); - } - - pass PASS_AA_DRAW - { - StencilEnable = False; - ZFunc = Greater; - ZWriteEnable = False; - ZEnable = True; - ColorWriteEnable = 0x0f; - - VertexShader = compile vs_3_0 ViewProjectionVS(); - PixelShader = compile ps_3_0 MaskPS(); - } - - pass PASS_AA_DRAW_DIRECT - { - StencilEnable = False; - ZFunc = Greater; - ZEnable = True; - ZWriteEnable = False; - ColorWriteEnable = 0x0f; - - VertexShader = compile vs_3_0 ViewProjectionVS(); - PixelShader = compile ps_3_0 DirectMaskPS(); - } -} - -technique Aliased -{ - pass PASS_STENCIL_ODDEVEN - { - TwoSidedStencilMode = False; - StencilEnable = True; - StencilPass = Invert; - StencilFunc = Always; - ColorWriteEnable = 0; - - ZEnable = False; - ZWriteEnable = False; - - VertexShader = compile vs_1_1 NoTxAliasedVS(); - PixelShader = compile ps_2_0 DirectSimplePS(); - } - - pass PASS_STENCIL_WINDING - { - TwoSidedStencilMode = True; - StencilEnable = True; - StencilRef = 0; - StencilMask = 0xFFFFFFFF; - - CCW_StencilPass = Incr; - CCW_StencilFunc = Always; - - StencilPass = Decr; - StencilFunc = Always; - - ColorWriteEnable = 0; - - ZEnable = False; - ZWriteEnable = False; - - VertexShader = compile vs_1_1 NoTxAliasedVS(); - PixelShader = compile ps_2_0 DirectSimplePS(); - } - - pass PASS_STENCIL_DRAW - { - TwoSidedStencilMode = False; - StencilEnable = True; - StencilFunc = NotEqual; - StencilMask = 0xFFFFFFFF; - StencilRef = 0; - StencilPass = Zero; - StencilFail = Zero; - StencilZFail = Zero; - - ColorWriteEnable = 0x0f; - ZEnable = True; - ZWriteEnable = False; - ZFunc = Greater; - - VertexShader = compile vs_1_1 AliasedVS(); - PixelShader = compile ps_2_0 SimplePS(); - } - - pass PASS_STENCIL_DRAW_DIRECT - { - TwoSidedStencilMode = False; - StencilEnable = True; - StencilFunc = NotEqual; - StencilMask = 0xFFFFFFFF; - StencilRef = 0; - StencilPass = Zero; - StencilFail = Zero; - StencilZFail = Zero; - - ColorWriteEnable = 0x0f; - ZEnable = True; - ZWriteEnable = False; - ZFunc = Greater; - - VertexShader = compile vs_1_1 AliasedVS(); - PixelShader = compile ps_2_0 DirectSimplePS(); - } - - pass PASS_STENCIL_CLIP - { - TwoSidedStencilMode = False; - StencilEnable = True; - StencilFunc = NotEqual; - StencilMask = 0xFFFFFFFF; - StencilRef = 0; - StencilPass = Zero; - StencilFail = Zero; - StencilZFail = Zero; - - ColorWriteEnable = 0; - ZEnable = True; - ZWriteEnable = True; - ZFunc = Always; - - VertexShader = compile vs_1_1 NoTxAliasedVS(); - PixelShader = compile ps_2_0 DirectSimplePS(); - } - - pass PASS_STENCIL_NOSTENCILCHECK - { - StencilEnable = False; - - ZEnable = True; - ZWriteEnable = False; - ZFunc = Greater; - - ColorWriteEnable = 0x0f; - - SrcBlend = SrcAlpha; - DestBlend = InvSrcAlpha; - - VertexShader = compile vs_1_1 AliasedVS(); - PixelShader = compile ps_2_0 SimplePS(); - } - - pass PASS_STENCIL_NOSTENCILCHECK_DIRECT - { - StencilEnable = False; - - ZEnable = True; - ZWriteEnable = False; - ZFunc = Greater; - - ColorWriteEnable = 0x0f; - - SrcBlend = SrcAlpha; - DestBlend = InvSrcAlpha; - - VertexShader = compile vs_1_1 AliasedVS(); - PixelShader = compile ps_2_0 DirectSimplePS(); - } - - pass PASS_TEXT - { - StencilEnable = False; - - ZEnable = True; - ZWriteEnable = False; - ZFunc = Greater; - - ColorWriteEnable = 0x0f; - - SrcBlend = SrcAlpha; - DestBlend = InvSrcAlpha; - - VertexShader = compile vs_1_1 AliasedVS(); - PixelShader = compile ps_2_0 TextPS(); - } - - pass PASS_CLEARTYPE_TEXT - { - StencilEnable = False; - - ZEnable = True; - ZWriteEnable = False; - ZFunc = Greater; - - ColorWriteEnable = 0x0f; - -// SrcBlend = SrcAlpha; -// DestBlend = InvSrcAlpha; - -// SrcBlend = DestColor; -// DestBlend = Zero; - SrcBlend = BlendFactor; - DestBlend = InvSrcColor; - -// SrcBlend = Zero; -// DestBlend = SrcColor; - -// SrcBlend = One; -// DestBlend = Zero; - - VertexShader = compile vs_3_0 AliasedVS(); - PixelShader = compile ps_3_0 ClearTypePS(); - } - - pass PASS_ALIASED_LINES - { - TwoSidedStencilMode = False; - StencilEnable = True; - StencilPass = Invert; - StencilFunc = Always; - ColorWriteEnable = 0; - - ZEnable = False; - ZWriteEnable = False; - - VertexShader = compile vs_1_1 AliasedLinesVS(); - PixelShader = compile ps_2_0 DirectSimplePS(); - } - - pass PASS_ALIASED_LINES_DIRECT - { - StencilEnable = False; - - ZEnable = True; - ZWriteEnable = False; - ZFunc = Greater; - - ColorWriteEnable = 0x0f; - - SrcBlend = SrcAlpha; - DestBlend = InvSrcAlpha; - - VertexShader = compile vs_1_1 AliasedLinesVS(); - PixelShader = compile ps_2_0 DirectSimplePS(); - } -} - diff --git a/src/gui/painting/qpaintengine_d3d.qrc b/src/gui/painting/qpaintengine_d3d.qrc deleted file mode 100644 index c106f2b..0000000 --- a/src/gui/painting/qpaintengine_d3d.qrc +++ /dev/null @@ -1,5 +0,0 @@ -<!DOCTYPE RCC><RCC version="1.0"> -<qresource> - <file>qpaintengine_d3d.fx</file> -</qresource> -</RCC> diff --git a/src/gui/painting/qpaintengine_d3d_p.h b/src/gui/painting/qpaintengine_d3d_p.h deleted file mode 100644 index 8fa5cf6..0000000 --- a/src/gui/painting/qpaintengine_d3d_p.h +++ /dev/null @@ -1,120 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPAINTENGINE_D3D_P_H -#define QPAINTENGINE_D3D_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "QtGui/qpaintengine.h" -#include <d3d9.h> - -QT_BEGIN_NAMESPACE - -class QDirect3DPaintEnginePrivate; -class QDirect3DPaintEngine : public QPaintEngine -{ - Q_DECLARE_PRIVATE(QDirect3DPaintEngine) -public: - QDirect3DPaintEngine(); - ~QDirect3DPaintEngine(); - bool begin(QPaintDevice *device); - - void drawEllipse(const QRectF &rect); - void drawEllipse(const QRect &rect); - - void drawImage(const QRectF &rectangle, const QImage &image, const QRectF &sr, - Qt::ImageConversionFlags flags = Qt::AutoColor); - - void drawLines(const QLineF *lines, int lineCount); - void drawLines(const QLine *lines, int lineCount); - - void drawPath(const QPainterPath &path); - - void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); - - void drawPoints(const QPointF *points, int pointCount); - void drawPoints(const QPoint *points, int pointCount); - - void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); - void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode); - - void drawRects(const QRectF *rects, int rectCount); - void drawRects(const QRect * rects, int rectCount); - - void drawTextItem(const QPointF &p, const QTextItem &textItem); - - void drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr); - - bool end(); - - Type type() const { return Direct3D; } - void updateState(const QPaintEngineState &state); - - void cleanup(); - - HDC getDC() const; - void setFlushOnEnd(bool flushOnEnd); - bool hasDirect3DSupport(); - -public: - void scroll(QPaintDevice *pd, const RECT &srcrect, const RECT &destrect); - LPDIRECT3DSWAPCHAIN9 swapChain(QPaintDevice *pd); - void releaseSwapChain(QPaintDevice *pd); - -private: - Q_DISABLE_COPY(QDirect3DPaintEngine) - friend class QPixmap; - friend class QD3DGlyphCache; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/gui/painting/qpaintengine_p.h b/src/gui/painting/qpaintengine_p.h index eeba7ec..0b5e175 100644 --- a/src/gui/painting/qpaintengine_p.h +++ b/src/gui/painting/qpaintengine_p.h @@ -83,10 +83,12 @@ public: if (systemClip.isEmpty()) return; - if (systemTransform.type() <= QTransform::TxTranslate) - systemClip.translate(qRound(systemTransform.dx()), qRound(systemTransform.dy())); - else - systemClip = systemTransform.map(systemClip); + if (hasSystemTransform) { + if (systemTransform.type() <= QTransform::TxTranslate) + systemClip.translate(qRound(systemTransform.dx()), qRound(systemTransform.dy())); + else + systemClip = systemTransform.map(systemClip); + } // Make sure we're inside the viewport. if (hasSystemViewport) { @@ -101,7 +103,7 @@ public: inline void setSystemTransform(const QTransform &xform) { systemTransform = xform; - if ((hasSystemTransform = !xform.isIdentity())) + if ((hasSystemTransform = !xform.isIdentity()) || hasSystemViewport) transformSystemClip(); systemStateChanged(); } diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index d2b1ed7..295abc5 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -4409,6 +4409,9 @@ void QClipData::fixup() */ void QClipData::setClipRect(const QRect &rect) { + if (rect == clipRect) + return; + // qDebug() << "setClipRect" << clipSpanHeight << count << allocated << rect; hasRectClip = true; clipRect = rect; @@ -4418,6 +4421,11 @@ void QClipData::setClipRect(const QRect &rect) ymin = qMin(rect.y(), clipSpanHeight); ymax = qMin(rect.y() + rect.height(), clipSpanHeight); + if (m_spans) { + delete m_spans; + m_spans = 0; + } + // qDebug() << xmin << xmax << ymin << ymax; } @@ -4441,6 +4449,12 @@ void QClipData::setClipRegion(const QRegion ®ion) ymin = rect.y(); ymax = rect.y() + rect.height(); } + + if (m_spans) { + delete m_spans; + m_spans = 0; + } + } /*! diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index caed293..d9c7937 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -5167,6 +5167,9 @@ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm) Q_D(QPainter); + if (!d->engine) + return; + #ifndef QT_NO_DEBUG qt_painter_thread_test(d->device->devType(), "drawPixmap()"); #endif @@ -5176,9 +5179,6 @@ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm) return; } - if (!d->engine) - return; - qreal x = p.x(); qreal y = p.y(); diff --git a/src/gui/painting/qprintengine_win.cpp b/src/gui/painting/qprintengine_win.cpp index c8674b7..7601beb 100644 --- a/src/gui/painting/qprintengine_win.cpp +++ b/src/gui/painting/qprintengine_win.cpp @@ -1532,7 +1532,7 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const value = rect; } else { value = QTransform(1/d->stretch_x, 0, 0, 1/d->stretch_y, 0, 0) - .mapRect(d->fullPage ? d->devPaperRect : d->devPageRect); + .mapRect(d->fullPage ? d->devPhysicalPageRect : d->devPageRect); } break; diff --git a/src/gui/painting/qprinter.cpp b/src/gui/painting/qprinter.cpp index 4f3e71c..5161e32 100644 --- a/src/gui/painting/qprinter.cpp +++ b/src/gui/painting/qprinter.cpp @@ -834,11 +834,15 @@ void QPrinter::setPrinterName(const QString &name) #endif QList<QPrinterInfo> prnList = QPrinterInfo::availablePrinters(); - d->validPrinter = false; - for (int i = 0; i < prnList.size(); ++i) { - if (prnList[i].printerName() == name) { - d->validPrinter = true; - break; + if (name.isEmpty()) { + d->validPrinter = d->outputFormat == QPrinter::PdfFormat || d->outputFormat == QPrinter::PostScriptFormat; + } else { + d->validPrinter = false; + for (int i = 0; i < prnList.size(); ++i) { + if (prnList[i].printerName() == name) { + d->validPrinter = true; + break; + } } } diff --git a/src/gui/painting/qwindowsurface_d3d.cpp b/src/gui/painting/qwindowsurface_d3d.cpp deleted file mode 100644 index 2b7f633..0000000 --- a/src/gui/painting/qwindowsurface_d3d.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -//#define D3D_DEBUG_BACKBUFFER - -#include <QtGui/QPaintDevice> -#include <QtGui/QWidget> -#include "qdebug.h" - -#include "qpaintengine_d3d_p.h" -#include "qwindowsurface_d3d_p.h" -#include "private/qwidget_p.h" -#include "private/qbackingstore_p.h" - -#include <d3d9.h> - -QT_BEGIN_NAMESPACE - -extern QDirect3DPaintEngine *qt_d3dEngine(); - -struct QD3DWindowSurfacePrivate -{ - QSize m_lastSize; - QWidget *m_widget; -}; - -QD3DWindowSurface::QD3DWindowSurface(QWidget *window) - : QWindowSurface(window), d_ptr(new QD3DWindowSurfacePrivate) -{ - Q_ASSERT(window->isTopLevel()); - d_ptr->m_widget = window; -} - - -QD3DWindowSurface::~QD3DWindowSurface() -{ - delete d_ptr; -} - -QPaintDevice *QD3DWindowSurface::paintDevice() -{ - return d_ptr->m_widget; -} - - -void QD3DWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset) -{ - QPoint wOffset = qt_qwidget_data(widget)->wrect.topLeft(); - - QDirect3DPaintEngine *engine = qt_d3dEngine(); - LPDIRECT3DSWAPCHAIN9 swapchain = engine->swapChain(d_ptr->m_widget); - - if (swapchain) { - QRect br = rgn.boundingRect(); - QRect wbr = br.translated(-wOffset); - - RECT destrect; - destrect.left = wbr.x(); - destrect.top = wbr.y(); - destrect.right = destrect.left + wbr.width(); - destrect.bottom = destrect.top + wbr.height(); - - RECT srcrect; - srcrect.left = br.x() + offset.x(); - srcrect.top = br.y() + offset.y(); - srcrect.right = wbr.width() + srcrect.left; - srcrect.bottom = wbr.height() + srcrect.top; - int devwidth = d_ptr->m_lastSize.width(); - int devheight = d_ptr->m_lastSize.height(); - - if (devwidth <= srcrect.right) { - int diff = srcrect.right - devwidth; - srcrect.right -= diff; - destrect.right -= diff; - if (srcrect.right <= srcrect.left) - return; - } - if (devheight <= srcrect.bottom) { - int diff = srcrect.bottom - devheight; - srcrect.bottom -= diff; - destrect.bottom -= diff; - if (srcrect.bottom <= srcrect.top) - return; - } - - if (FAILED(swapchain->Present(&srcrect, &destrect, widget->winId(), 0, 0))) - qWarning("QDirect3DPaintEngine: failed to present back buffer."); - -#ifdef D3D_DEBUG_BACKBUFFER - qDebug() << widget << srcrect.left << srcrect.top << wbr.width() << wbr.height() << "Dest: " << destrect.left << destrect.top; - IDirect3DSurface9 *surface; - swapchain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &surface); - QString filename("C:\\test.bmp"); - D3DXSaveSurfaceToFile(filename.utf16(), D3DXIFF_BMP, surface, 0, 0); - surface->Release(); -#endif - } -} - -void QD3DWindowSurface::setGeometry(const QRect &rect) -{ - if (rect.isEmpty()) - qt_d3dEngine()->releaseSwapChain(d_ptr->m_widget); - - d_ptr->m_lastSize = rect.size(); - QWindowSurface::setGeometry(rect); -} - - -bool QD3DWindowSurface::scroll(const QRegion &area, int dx, int dy) -{ - QDirect3DPaintEngine *engine = qt_d3dEngine(); - QRect rect = area.boundingRect(); - - RECT destrect; - destrect.left = rect.x()+dx; - destrect.top = rect.y()+dy; - destrect.right = rect.width() + destrect.left; - destrect.bottom = rect.height() + destrect.top; - - RECT srcrect; - srcrect.left = rect.x(); - srcrect.top = rect.y(); - srcrect.right = rect.width() + srcrect.left; - srcrect.bottom = rect.height() + srcrect.top; - - engine->scroll(d_ptr->m_widget, srcrect, destrect); - return true; -} - -QT_END_NAMESPACE diff --git a/src/gui/painting/qwindowsurface_d3d_p.h b/src/gui/painting/qwindowsurface_d3d_p.h deleted file mode 100644 index 9cdfe29..0000000 --- a/src/gui/painting/qwindowsurface_d3d_p.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWINDOWSURFACE_D3D_P_H -#define QWINDOWSURFACE_D3D_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of the QLibrary class. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// - -#include <qglobal.h> -#include "private/qwindowsurface_p.h" - -QT_BEGIN_NAMESPACE - -class QPaintDevice; -class QPoint; -class QRegion; -class QWidget; -struct QD3DWindowSurfacePrivate; - -class QD3DWindowSurface : public QWindowSurface -{ -public: - QD3DWindowSurface(QWidget *widget); - ~QD3DWindowSurface(); - - QPaintDevice *paintDevice(); - void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); - void setGeometry(const QRect &rect); - bool scroll(const QRegion &area, int dx, int dy); - -private: - QD3DWindowSurfacePrivate *d_ptr; -}; - -QT_END_NAMESPACE - -#endif // QWINDOWSURFACE_D3D_P_H diff --git a/src/gui/styles/gtksymbols.cpp b/src/gui/styles/gtksymbols.cpp index acb8437..0842ec7 100644 --- a/src/gui/styles/gtksymbols.cpp +++ b/src/gui/styles/gtksymbols.cpp @@ -746,9 +746,9 @@ static void setupGtkFileChooser(GtkWidget* gtkFileChooser, QWidget *parent, foreach (const QString &rawfilter, filters) { GtkFileFilter *gtkFilter = QGtk::gtk_file_filter_new (); QString name = rawfilter.left(rawfilter.indexOf(QLatin1Char('('))); - QGtk::gtk_file_filter_set_name(gtkFilter, qPrintable(name)); - QStringList extensions = extract_filter(rawfilter); + QGtk::gtk_file_filter_set_name(gtkFilter, qPrintable(name.isEmpty() ? extensions.join(QLS(", ")) : name)); + foreach (const QString &fileExtension, extensions) { QGtk::gtk_file_filter_add_pattern (gtkFilter, qPrintable(fileExtension)); } diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp index be80d37..f8ae1a6 100644 --- a/src/gui/styles/qcommonstyle.cpp +++ b/src/gui/styles/qcommonstyle.cpp @@ -2019,7 +2019,9 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, : QIcon::Disabled); QPixmap tabIcon = tabV2.icon.pixmap(iconSize, (tabV2.state & State_Enabled) ? QIcon::Normal - : QIcon::Disabled); + : QIcon::Disabled, + (tabV2.state & State_Selected) ? QIcon::On + : QIcon::Off); int offset = 6; int left = opt->rect.left(); diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp index b7fa575..ca71da2 100644 --- a/src/gui/styles/qgtkstyle.cpp +++ b/src/gui/styles/qgtkstyle.cpp @@ -951,14 +951,15 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, "interior-focus", &interior_focus, "focus-line-width", &focus_line_width, NULL); + // See https://bugzilla.mozilla.org/show_bug.cgi?id=405421 for info about this hack + g_object_set_data(G_OBJECT(gtkEntry), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); + if (!interior_focus && option->state & State_HasFocus) rect.adjust(focus_line_width, focus_line_width, -focus_line_width, -focus_line_width); - gtkPainter.paintShadow(gtkEntry, "entry", rect, option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE, GTK_SHADOW_IN, gtkEntry->style, option->state & State_HasFocus ? QLS("focus") : QString()); - if (!interior_focus && option->state & State_HasFocus) gtkPainter.paintShadow(gtkEntry, "entry", option->rect, option->state & State_Enabled ? GTK_STATE_ACTIVE : GTK_STATE_INSENSITIVE, diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm index 5d08c58..e32c5e2 100644 --- a/src/gui/styles/qmacstyle_mac.mm +++ b/src/gui/styles/qmacstyle_mac.mm @@ -2649,6 +2649,9 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW case PM_MenuHMargin: ret = 0; break; + case PM_ToolBarFrameWidth: + ret = 0; + break; default: ret = QWindowsStyle::pixelMetric(metric, opt, widget); break; @@ -3679,8 +3682,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter if (tb->toolButtonStyle != Qt::ToolButtonIconOnly) { needText = true; if (tb->toolButtonStyle == Qt::ToolButtonTextUnderIcon) { - pr.setHeight(pixmap.size().height() + 6); - cr.adjust(0, pr.bottom(), 0, -3); + pr.setHeight(pixmap.size().height()); + cr.adjust(0, pr.bottom() + 1, 0, 1); alignment |= Qt::AlignCenter; } else { pr.setWidth(pixmap.width() + 8); @@ -3688,7 +3691,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter alignment |= Qt::AlignLeft | Qt::AlignVCenter; } } - if (down) { + if (opt->state & State_Sunken) { pr.translate(shiftX, shiftY); pixmap = darkenPixmap(pixmap); } @@ -3718,7 +3721,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } drawItemText(p, cr, alignment, pal, tb->state & State_Enabled, tb->text, role); - if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_5 && down) { + if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_5 && + (tb->state & State_Sunken)) { // Draw a "drop shadow" in earlier versions. drawItemText(p, cr.adjusted(0, 1, 0, 1), alignment, tb->palette, tb->state & State_Enabled, tb->text); @@ -4544,9 +4548,10 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter case CE_ToolBar: { // For unified tool bars, draw nothing. if (w) { - if (QMainWindow * mainWindow = qobject_cast<QMainWindow *>(w->window())) + if (QMainWindow * mainWindow = qobject_cast<QMainWindow *>(w->window())) { if (mainWindow->unifiedTitleAndToolBarOnMac()) break; + } } // draw background gradient @@ -5270,6 +5275,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex if (const QStyleOptionToolButton *tb = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) { if (widget && qobject_cast<QToolBar *>(widget->parentWidget())) { +// p->fillRect(tb->rect, QColor(155, 0, 155, 155)); if (tb->subControls & SC_ToolButtonMenu) { QStyleOption arrowOpt(0); arrowOpt.rect = subControlRect(cc, tb, SC_ToolButtonMenu, widget); @@ -5282,16 +5288,22 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex drawToolbarButtonArrow(tb->rect, tds, cg); } if (tb->state & State_On) { - QPen oldPen = p->pen(); - p->setPen(QColor(0, 0, 0, 0x3a)); - p->fillRect(tb->rect.adjusted(1, 1, -1, -1), QColor(0, 0, 0, 0x12)); - p->drawLine(tb->rect.left() + 1, tb->rect.top(), - tb->rect.right() - 1, tb->rect.top()); - p->drawLine(tb->rect.left() + 1, tb->rect.bottom(), - tb->rect.right() - 1, tb->rect.bottom()); - p->drawLine(tb->rect.topLeft(), tb->rect.bottomLeft()); - p->drawLine(tb->rect.topRight(), tb->rect.bottomRight()); - p->setPen(oldPen); + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { + static QPixmap pm(QLatin1String(":/trolltech/mac/style/images/leopard-unified-toolbar-on.png")); + p->setRenderHint(QPainter::SmoothPixmapTransform); + QStyleHelper::drawBorderPixmap(pm, p, tb->rect, 2, 2, 2, 2); + } else { + QPen oldPen = p->pen(); + p->setPen(QColor(0, 0, 0, 0x3a)); + p->fillRect(tb->rect.adjusted(1, 1, -1, -1), QColor(0, 0, 0, 0x12)); + p->drawLine(tb->rect.left() + 1, tb->rect.top(), + tb->rect.right() - 1, tb->rect.top()); + p->drawLine(tb->rect.left() + 1, tb->rect.bottom(), + tb->rect.right() - 1, tb->rect.bottom()); + p->drawLine(tb->rect.topLeft(), tb->rect.bottomLeft()); + p->drawLine(tb->rect.topRight(), tb->rect.bottomRight()); + p->setPen(oldPen); + } } drawControl(CE_ToolButtonLabel, opt, p, widget); } else { @@ -6009,6 +6021,14 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, } break; case CT_ToolButton: + if (widget && qobject_cast<const QToolBar *>(widget->parentWidget())) { + sz.rwidth() += 4; + if (sz.height() <= 32) { + // Workaround strange HIToolBar bug when getting constraints. + sz.rheight() += 1; + } + return sz; + } sz.rwidth() += 10; sz.rheight() += 10; return sz; diff --git a/src/gui/styles/qstylehelper.cpp b/src/gui/styles/qstylehelper.cpp index 3320970..69f8cd2 100644 --- a/src/gui/styles/qstylehelper.cpp +++ b/src/gui/styles/qstylehelper.cpp @@ -50,9 +50,10 @@ QT_BEGIN_NAMESPACE -const bool QStyleHelper::UsePixmapCache = true; +namespace QStyleHelper { +const bool UsePixmapCache = true; -QString QStyleHelper::uniqueName(const QString &key, const QStyleOption *option, const QSize &size) +QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size) { QString tmp; const QStyleOptionComplex *complexOption = qstyleoption_cast<const QStyleOptionComplex *>(option); @@ -74,7 +75,7 @@ QString QStyleHelper::uniqueName(const QString &key, const QStyleOption *option, #ifndef QT_NO_DIAL -int QStyleHelper::calcBigLineSize(int radius) +int calcBigLineSize(int radius) { int bigLineSize = radius / 6; if (bigLineSize < 4) @@ -107,7 +108,7 @@ static QPointF calcRadialPos(const QStyleOptionSlider *dial, qreal offset) return pos; } -qreal QStyleHelper::angle(const QPointF &p1, const QPointF &p2) +qreal angle(const QPointF &p1, const QPointF &p2) { static const qreal rad_factor = 180 / Q_PI; qreal _angle = 0; @@ -139,7 +140,7 @@ qreal QStyleHelper::angle(const QPointF &p1, const QPointF &p2) return _angle; } -QPolygonF QStyleHelper::calcLines(const QStyleOptionSlider *dial) +QPolygonF calcLines(const QStyleOptionSlider *dial) { QPolygonF poly; int width = dial->rect.width(); @@ -182,7 +183,7 @@ QPolygonF QStyleHelper::calcLines(const QStyleOptionSlider *dial) // This will draw a nice and shiny QDial for us. We don't want // all the shinyness in QWindowsStyle, hence we place it here -void QStyleHelper::drawDial(const QStyleOptionSlider *option, QPainter *painter) +void drawDial(const QStyleOptionSlider *option, QPainter *painter) { QPalette pal = option->palette; QColor buttonColor = pal.button().color(); @@ -292,4 +293,61 @@ void QStyleHelper::drawDial(const QStyleOptionSlider *option, QPainter *painter) } #endif //QT_NO_DIAL +void drawBorderPixmap(const QPixmap &pixmap, QPainter *painter, const QRect &rect, + int left, int top, int right, + int bottom) +{ + QSize size = pixmap.size(); + //painter->setRenderHint(QPainter::SmoothPixmapTransform); + + //top + if (top > 0) { + painter->drawPixmap(QRect(rect.left() + left, rect.top(), rect.width() -right - left, top), pixmap, + QRect(left, 0, size.width() -right - left, top)); + + //top-left + if(left > 0) + painter->drawPixmap(QRect(rect.left(), rect.top(), left, top), pixmap, + QRect(0, 0, left, top)); + + //top-right + if (right > 0) + painter->drawPixmap(QRect(rect.left() + rect.width() - right, rect.top(), right, top), pixmap, + QRect(size.width() - right, 0, right, top)); + } + + //left + if (left > 0) + painter->drawPixmap(QRect(rect.left(), rect.top()+top, left, rect.height() - top - bottom), pixmap, + QRect(0, top, left, size.height() - bottom - top)); + + //center + painter->drawPixmap(QRect(rect.left() + left, rect.top()+top, rect.width() -right - left, + rect.height() - bottom - top), pixmap, + QRect(left, top, size.width() -right -left, + size.height() - bottom - top)); + //right + if (right > 0) + painter->drawPixmap(QRect(rect.left() +rect.width() - right, rect.top()+top, right, rect.height() - top - bottom), pixmap, + QRect(size.width() - right, top, right, size.height() - bottom - top)); + + //bottom + if (bottom > 0) { + painter->drawPixmap(QRect(rect.left() +left, rect.top() + rect.height() - bottom, + rect.width() - right - left, bottom), pixmap, + QRect(left, size.height() - bottom, + size.width() - right - left, bottom)); + //bottom-left + if (left > 0) + painter->drawPixmap(QRect(rect.left(), rect.top() + rect.height() - bottom, left, bottom), pixmap, + QRect(0, size.height() - bottom, left, bottom)); + + //bottom-right + if (right > 0) + painter->drawPixmap(QRect(rect.left() + rect.width() - right, rect.top() + rect.height() - bottom, right, bottom), pixmap, + QRect(size.width() - right, size.height() - bottom, right, bottom)); + + } +} +} QT_END_NAMESPACE diff --git a/src/gui/styles/qstylehelper_p.h b/src/gui/styles/qstylehelper_p.h index d9b2e28..711bd2d 100644 --- a/src/gui/styles/qstylehelper_p.h +++ b/src/gui/styles/qstylehelper_p.h @@ -19,6 +19,7 @@ QT_BEGIN_NAMESPACE class QPainter; +class QPixmap; class QStyleOptionSlider; class QStyleOption; @@ -32,6 +33,9 @@ namespace QStyleHelper int calcBigLineSize(int radius); void drawDial(const QStyleOptionSlider *dial, QPainter *painter); #endif //QT_NO_DIAL + void drawBorderPixmap(const QPixmap &pixmap, QPainter *painter, const QRect &rect, + int left = 0, int top = 0, int right = 0, + int bottom = 0); } QT_END_NAMESPACE diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index 49ac57a..f480008 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -2876,12 +2876,6 @@ void QStyleSheetStyle::polish(QWidget *w) QRenderRule rule = renderRule(w, PseudoElement_None, PseudoClass_Any); if (rule.hasDrawable() || rule.hasBox()) { if (w->metaObject() == &QWidget::staticMetaObject -#ifndef QT_NO_MENUBAR - || qobject_cast<QMenuBar *>(w) -#endif -#ifndef QT_NO_MENU - || qobject_cast<QMenu *>(w) -#endif #ifndef QT_NO_ITEMVIEWS || qobject_cast<QHeaderView *>(w) #endif @@ -4164,9 +4158,8 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q rule.configurePalette(&frmOpt.palette, QPalette::Text, QPalette::Base); frmOpt.rect = rule.borderRect(frmOpt.rect); baseStyle()->drawControl(ce, &frmOpt, p, w); - } else { - rule.drawBorder(p, rule.borderRect(opt->rect)); } + // else, borders are already drawn in PE_Widget } return; @@ -4220,12 +4213,6 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op QRect rect = opt->rect; switch (pe) { - case PE_PanelStatusBar: - if (rule.hasDrawable()) { - rule.drawRule(p, opt->rect); - return; - } - break; case PE_FrameStatusBar: { QRenderRule subRule = renderRule(w->parentWidget(), opt, PseudoElement_Item); @@ -4337,36 +4324,34 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op return; case PE_Widget: - if (!rule.hasBackground()) { + if (!rule.hasDrawable()) { QWidget *container = containerWidget(w); if (autoFillDisabledWidgets->contains(container) - && (container == w || !renderRule(container, opt).hasBackground())) { + && (container == w || !renderRule(container, opt).hasDrawable())) { //we do not have a background, but we disabled the autofillbackground anyway. so fill the background now. // (this may happen if we have rules like :focus) p->fillRect(opt->rect, opt->palette.brush(w->backgroundRole())); } break; } - #ifndef QT_NO_SCROLLAREA if (const QAbstractScrollArea *sa = qobject_cast<const QAbstractScrollArea *>(w)) { const QAbstractScrollAreaPrivate *sap = sa->d_func(); rule.drawBackground(p, opt->rect, sap->contentsOffset()); - } else -#endif - { - rule.drawBackground(p, opt->rect); + if (rule.hasBorder()) + rule.drawBorder(p, rule.borderRect(opt->rect)); + break; } - - return; - - case PE_FrameMenu: +#endif + //fall tghought + case PE_PanelMenu: case PE_PanelMenuBar: - if (!rule.hasNativeBorder()) { - rule.drawBorder(p, rule.borderRect(opt->rect)); + case PE_PanelStatusBar: + if(rule.hasDrawable()) { + rule.drawRule(p, opt->rect); return; } - break; + break; case PE_IndicatorToolBarSeparator: case PE_IndicatorToolBarHandle: { @@ -5887,13 +5872,11 @@ void QStyleSheetStyle::clearWidgetFont(QWidget* w) const w->setProperty("_q_styleSheetWidgetFont", QVariant(QVariant::Invalid)); } -// Returns the palette that should be used when the particular widget is focused. -// This needs to be called by some widgets that do drawing themselves instead -// of through the style. -// ### This should be removed ideally by Qt 4.5, and at least by Qt 5, and fixed -// for good by letting the style draw everything. +// Polish palette that should be used for a particular widget, with particular states +// (eg. :focus, :hover, ...) +// this is called by widgets that paint themself in their paint event // Returns true if there is a new palette in pal. -bool QStyleSheetStyle::focusPalette(const QWidget* w, const QStyleOption* opt, QPalette* pal) +bool QStyleSheetStyle::styleSheetPalette(const QWidget* w, const QStyleOption* opt, QPalette* pal) { if (!w || !opt || !pal) return false; diff --git a/src/gui/styles/qstylesheetstyle_p.h b/src/gui/styles/qstylesheetstyle_p.h index 1f61445..e057274 100644 --- a/src/gui/styles/qstylesheetstyle_p.h +++ b/src/gui/styles/qstylesheetstyle_p.h @@ -131,7 +131,7 @@ public: void saveWidgetFont(QWidget* w, const QFont& font) const; void clearWidgetFont(QWidget* w) const; - bool focusPalette(const QWidget* w, const QStyleOption* opt, QPalette* pal); + bool styleSheetPalette(const QWidget* w, const QStyleOption* opt, QPalette* pal); protected Q_SLOTS: QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt = 0, diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp index 63c1315..016b7c1 100644 --- a/src/gui/widgets/qlabel.cpp +++ b/src/gui/widgets/qlabel.cpp @@ -971,6 +971,13 @@ void QLabel::paintEvent(QPaintEvent *) #endif if (d->isTextLabel) { QRectF lr = d->layoutRect(); + QStyleOption opt; + opt.initFrom(this); +#ifndef QT_NO_STYLE_STYLESHEET + if (QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(style)) { + cssStyle->styleSheetPalette(this, &opt, &opt.palette); + } +#endif if (d->control) { #ifndef QT_NO_SHORTCUT const bool underline = (bool)style->styleHint(QStyle::SH_UnderlineShortcut, 0, this, 0); @@ -984,11 +991,9 @@ void QLabel::paintEvent(QPaintEvent *) d->ensureTextLayouted(); QAbstractTextDocumentLayout::PaintContext context; - QStyleOption opt(0); - opt.init(this); if (!isEnabled() && style->styleHint(QStyle::SH_EtchDisabledText, &opt, this)) { - context.palette = palette(); + context.palette = opt.palette; context.palette.setColor(QPalette::Text, context.palette.light().color()); painter.save(); painter.translate(lr.x() + 1, lr.y() + 1); @@ -999,12 +1004,7 @@ void QLabel::paintEvent(QPaintEvent *) } // Adjust the palette - context.palette = palette(); -#ifndef QT_NO_STYLE_STYLESHEET - if (QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(style)) { - cssStyle->focusPalette(this, &opt, &context.palette); - } -#endif + context.palette = opt.palette; if (foregroundRole() != QPalette::Text && isEnabled()) context.palette.setColor(QPalette::Text, context.palette.color(foregroundRole())); @@ -1019,12 +1019,10 @@ void QLabel::paintEvent(QPaintEvent *) int flags = align; if (d->hasShortcut) { flags |= Qt::TextShowMnemonic; - QStyleOption opt; - opt.initFrom(this); if (!style->styleHint(QStyle::SH_UnderlineShortcut, &opt, this)) flags |= Qt::TextHideMnemonic; } - style->drawItemText(&painter, lr.toRect(), flags, palette(), isEnabled(), d->text, foregroundRole()); + style->drawItemText(&painter, lr.toRect(), flags, opt.palette, isEnabled(), d->text, foregroundRole()); } } else #ifndef QT_NO_PICTURE diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index e243ad0..d16ed10 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -2518,7 +2518,7 @@ void QLineEdit::paintEvent(QPaintEvent *) // draw text, selections and cursors #ifndef QT_NO_STYLE_STYLESHEET if (QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(style())) { - cssStyle->focusPalette(this, &panel, &pal); + cssStyle->styleSheetPalette(this, &panel, &pal); } #endif p.setPen(pal.text().color()); diff --git a/src/gui/widgets/qmainwindowlayout_mac.mm b/src/gui/widgets/qmainwindowlayout_mac.mm index c807afb..53e1ad5 100644 --- a/src/gui/widgets/qmainwindowlayout_mac.mm +++ b/src/gui/widgets/qmainwindowlayout_mac.mm @@ -502,11 +502,11 @@ void QMainWindowLayout::fixSizeInUnifiedToolbar(QToolBar *tb) const QMacCocoaAutoReleasePool pool; QWidgetItem layoutItem(tb); QSize size = layoutItem.maximumSize(); - NSSize nssize = NSMakeSize(size.width(), size.height()); + NSSize nssize = NSMakeSize(size.width(), size.height() - 2); [item setMaxSize:nssize]; size = layoutItem.minimumSize(); nssize.width = size.width(); - nssize.height = size.height(); + nssize.height = size.height() - 2; [item setMinSize:nssize]; } } diff --git a/src/gui/widgets/qtabbar.cpp b/src/gui/widgets/qtabbar.cpp index b562b1f..49de8c1 100644 --- a/src/gui/widgets/qtabbar.cpp +++ b/src/gui/widgets/qtabbar.cpp @@ -1941,8 +1941,10 @@ void QTabBar::changeEvent(QEvent *event) if (event->type() == QEvent::StyleChange) { d->elideMode = Qt::TextElideMode(style()->styleHint(QStyle::SH_TabBar_ElideMode, 0, this)); d->useScrollButtons = !style()->styleHint(QStyle::SH_TabBar_PreferNoArrows, 0, this); + d->refresh(); + } else if (event->type() == QEvent::FontChange) { + d->refresh(); } - d->refresh(); QWidget::changeEvent(event); } |