diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2010-09-23 11:43:10 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2010-09-23 11:43:10 (GMT) |
commit | 82d28ac2065f348e7eacb20c455894ab349b666e (patch) | |
tree | 46e2fe80ff972e5df7a482d6b25bce7f4564ba79 /src | |
parent | b92df717c0a07ad77b5662fea6f78e8a6a5ea693 (diff) | |
parent | d1817df87461fc071527eb77d3c1259e713b94a4 (diff) | |
download | Qt-82d28ac2065f348e7eacb20c455894ab349b666e.zip Qt-82d28ac2065f348e7eacb20c455894ab349b666e.tar.gz Qt-82d28ac2065f348e7eacb20c455894ab349b666e.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-2 into 4.7-integration
* '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-2:
Compile on Symbian - rework the X11 mask patch a bit.
Fix text direction setting in QTextBlock layout
Fix text direction handling in QLabel
Fixed QPixmap::resize() for X11 pixmap with masks.
QPainter not restored correctly in Graphics View.
Setting QGraphicsItem::ItemClipsChildrenToShape forces ItemClipsToShape
Fix compilation
Fixed drawing of QPixmaps with masks in the GL 2 and X11 engines.
Fix warning on MSVC
QThread: make sure start works even if called after exit
Revert "Fixed painter path drawing on FBO without stencil buffer."
Fix a crash with D&d on mingw
Revert "Keep other text format with QTextOption::SuppressColors tag on"
Fixed stencil buffer on FBOs with OpenGL ES.
Keep other text format with QTextOption::SuppressColors tag on
QTreeView: do not scroll to top if last item is removed
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/thread/qthread_unix.cpp | 2 | ||||
-rw-r--r-- | src/corelib/thread/qthread_win.cpp | 2 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsscene.cpp | 126 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsview.cpp | 3 | ||||
-rw-r--r-- | src/gui/image/qpixmap.cpp | 43 | ||||
-rw-r--r-- | src/gui/image/qpixmap_x11.cpp | 3 | ||||
-rw-r--r-- | src/gui/itemviews/qtreeview.cpp | 4 | ||||
-rw-r--r-- | src/gui/kernel/qdnd_win.cpp | 12 | ||||
-rw-r--r-- | src/gui/styles/qstylehelper_p.h | 2 | ||||
-rw-r--r-- | src/gui/text/qtextcontrol.cpp | 6 | ||||
-rw-r--r-- | src/gui/widgets/qlabel.cpp | 27 | ||||
-rw-r--r-- | src/gui/widgets/qlabel_p.h | 1 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 30 | ||||
-rw-r--r-- | src/opengl/qgl_x11.cpp | 4 | ||||
-rw-r--r-- | src/opengl/qglframebufferobject.cpp | 105 | ||||
-rw-r--r-- | src/opengl/qglframebufferobject_p.h | 5 |
16 files changed, 232 insertions, 143 deletions
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 2824e15..a7601b6 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -514,6 +514,8 @@ void QThread::start(Priority priority) d->running = true; d->finished = false; d->terminated = false; + d->returnCode = 0; + d->exited = false; pthread_attr_t attr; pthread_attr_init(&attr); diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index 37d5b87..f0cbe8d 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -405,6 +405,8 @@ void QThread::start(Priority priority) d->running = true; d->finished = false; d->terminated = false; + d->exited = false; + d->returnCode = 0; /* NOTE: we create the thread in the suspended state, set the diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 54fdf3f..8dc15bf 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4814,6 +4814,27 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } } +static inline void setClip(QPainter *painter, QGraphicsItem *item) +{ + painter->save(); + QRectF clipRect; + const QPainterPath clipPath(item->shape()); + if (QPathClipper::pathToRect(clipPath, &clipRect)) + painter->setClipRect(clipRect, Qt::IntersectClip); + else + painter->setClipPath(clipPath, Qt::IntersectClip); +} + +static inline void setWorldTransform(QPainter *painter, const QTransform *const transformPtr, + const QTransform *effectTransform) +{ + Q_ASSERT(transformPtr); + if (effectTransform) + painter->setWorldTransform(*transformPtr * *effectTransform); + else + painter->setWorldTransform(*transformPtr); +} + void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform, const QTransform *const transformPtr, QRegion *exposedRegion, QWidget *widget, qreal opacity, const QTransform *effectTransform, @@ -4822,36 +4843,37 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity); const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); const bool itemHasChildren = !item->d_ptr->children.isEmpty(); + bool setChildClip = itemClipsChildrenToShape; + bool itemHasChildrenStackedBehind = false; int i = 0; if (itemHasChildren) { + if (itemClipsChildrenToShape) + setWorldTransform(painter, transformPtr, effectTransform); + item->d_ptr->ensureSortedChildren(); + // Items with the 'ItemStacksBehindParent' flag are put in front of the list + // so all we have to do is to check the first item. + itemHasChildrenStackedBehind = (item->d_ptr->children.at(0)->d_ptr->flags + & QGraphicsItem::ItemStacksBehindParent); - if (itemClipsChildrenToShape) { - painter->save(); - Q_ASSERT(transformPtr); - if (effectTransform) - painter->setWorldTransform(*transformPtr * *effectTransform); - else - painter->setWorldTransform(*transformPtr); - QRectF clipRect; - const QPainterPath clipPath(item->shape()); - if (QPathClipper::pathToRect(clipPath, &clipRect)) - painter->setClipRect(clipRect, Qt::IntersectClip); - else - painter->setClipPath(clipPath, Qt::IntersectClip); - } + if (itemHasChildrenStackedBehind) { + if (itemClipsChildrenToShape) { + setClip(painter, item); + setChildClip = false; + } - // Draw children behind - for (i = 0; i < item->d_ptr->children.size(); ++i) { - QGraphicsItem *child = item->d_ptr->children.at(i); - if (wasDirtyParentSceneTransform) - child->d_ptr->dirtySceneTransform = 1; - if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) - break; - if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) - continue; - drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform); + // Draw children behind + for (i = 0; i < item->d_ptr->children.size(); ++i) { + QGraphicsItem *child = item->d_ptr->children.at(i); + if (wasDirtyParentSceneTransform) + child->d_ptr->dirtySceneTransform = 1; + if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) + break; + if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) + continue; + drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform); + } } } @@ -4864,38 +4886,50 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q ? *exposedRegion : QRegion(), exposedRegion == 0); const bool itemClipsToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsToShape; - const bool savePainter = itemClipsToShape || painterStateProtection; - if (savePainter) - painter->save(); + bool restorePainterClip = false; if (!itemHasChildren || !itemClipsChildrenToShape) { - if (effectTransform) - painter->setWorldTransform(*transformPtr * *effectTransform); - else - painter->setWorldTransform(*transformPtr); + // Item does not have children or clip children to shape. + setWorldTransform(painter, transformPtr, effectTransform); + if ((restorePainterClip = itemClipsToShape)) + setClip(painter, item); + } else if (itemHasChildrenStackedBehind){ + // Item clips children to shape and has children stacked behind, which means + // the painter is already clipped to the item's shape. + if (itemClipsToShape) { + // The clip is already correct. Ensure correct world transform. + setWorldTransform(painter, transformPtr, effectTransform); + } else { + // Remove clip (this also ensures correct world transform). + painter->restore(); + setChildClip = true; + } + } else if (itemClipsToShape) { + // Item clips children and itself to shape. It does not have hildren stacked + // behind, which means the clip has not yet been set. We set it now and re-use it + // for the children. + setClip(painter, item); + setChildClip = false; } - if (itemClipsToShape) { - QRectF clipRect; - const QPainterPath clipPath(item->shape()); - if (QPathClipper::pathToRect(clipPath, &clipRect)) - painter->setClipRect(clipRect, Qt::IntersectClip); - else - painter->setClipPath(clipPath, Qt::IntersectClip); - } - painter->setOpacity(opacity); + if (painterStateProtection && !restorePainterClip) + painter->save(); + painter->setOpacity(opacity); if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget) item->paint(painter, &styleOptionTmp, widget); else drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection); - if (savePainter) + if (painterStateProtection || restorePainterClip) painter->restore(); } // Draw children in front if (itemHasChildren) { + if (setChildClip) + setClip(painter, item); + for (; i < item->d_ptr->children.size(); ++i) { QGraphicsItem *child = item->d_ptr->children.at(i); if (wasDirtyParentSceneTransform) @@ -4904,11 +4938,11 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q continue; drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform); } - } - // Restore child clip - if (itemHasChildren && itemClipsChildrenToShape) - painter->restore(); + // Restore child clip + if (itemClipsChildrenToShape) + painter->restore(); + } } void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren, @@ -5271,6 +5305,7 @@ void QGraphicsScene::drawItems(QPainter *painter, if (!d->unpolishedItems.isEmpty()) d->_q_polishItems(); + const qreal opacity = painter->opacity(); QTransform viewTransform = painter->worldTransform(); Q_UNUSED(options); @@ -5304,6 +5339,7 @@ void QGraphicsScene::drawItems(QPainter *painter, topLevelItems.at(i)->d_ptr->itemDiscovered = 0; painter->setWorldTransform(viewTransform); + painter->setOpacity(opacity); } /*! diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index c8aca80..a566c8e 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3475,7 +3475,8 @@ void QGraphicsView::paintEvent(QPaintEvent *event) // IndirectPainting (the else branch), because in that case we always save() // and restore() in QGraphicsScene::drawItems(). if (!d->scene->d_func()->painterStateProtection) - painter.setWorldTransform(viewTransform); + painter.setOpacity(1.0); + painter.setWorldTransform(viewTransform); } else { // Make sure we don't have unpolished items before we draw if (!d->scene->d_func()->unpolishedItems.isEmpty()) diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 1e502bd..64d8ed2 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -664,14 +664,19 @@ void QPixmap::resize_helper(const QSize &s) #if defined(Q_WS_X11) if (x11Data && x11Data->x11_mask) { - QX11PixmapData *pmData = static_cast<QX11PixmapData*>(pd); - pmData->x11_mask = (Qt::HANDLE)XCreatePixmap(X11->display, - RootWindow(x11Data->xinfo.display(), - x11Data->xinfo.screen()), - w, h, 1); - GC gc = XCreateGC(X11->display, pmData->x11_mask, 0, 0); - XCopyArea(X11->display, x11Data->x11_mask, pmData->x11_mask, gc, 0, 0, qMin(width(), w), qMin(height(), h), 0, 0); - XFreeGC(X11->display, gc); + QPixmapData *newPd = pm.pixmapData(); + QX11PixmapData *pmData = (newPd && newPd->classId() == QPixmapData::X11Class) + ? static_cast<QX11PixmapData*>(newPd) : 0; + if (pmData) { + pmData->x11_mask = (Qt::HANDLE)XCreatePixmap(X11->display, + RootWindow(x11Data->xinfo.display(), + x11Data->xinfo.screen()), + w, h, 1); + GC gc = XCreateGC(X11->display, pmData->x11_mask, 0, 0); + XCopyArea(X11->display, x11Data->x11_mask, pmData->x11_mask, gc, 0, 0, + qMin(width(), w), qMin(height(), h), 0, 0); + XFreeGC(X11->display, gc); + } } #endif *this = pm; @@ -836,7 +841,7 @@ bool QPixmap::load(const QString &fileName, const char *format, Qt::ImageConvers % HexString<quint64>(info.size()) % HexString<uint>(data ? data->pixelType() : QPixmapData::PixmapType); - // Note: If no extension is provided, we try to match the + // Note: If no extension is provided, we try to match the // file against known plugin extensions if (!info.completeSuffix().isEmpty() && !info.exists()) return false; @@ -1793,13 +1798,27 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode) Returns true if this pixmap has an alpha channel, \e or has a mask, otherwise returns false. - \warning This is potentially an expensive operation. - \sa hasAlphaChannel(), mask() */ bool QPixmap::hasAlpha() const { - return data && (data->hasAlphaChannel() || !data->mask().isNull()); +#if defined(Q_WS_X11) + if (data && data->hasAlphaChannel()) + return true; + QPixmapData *pd = pixmapData(); + if (pd && pd->classId() == QPixmapData::X11Class) { + QX11PixmapData *x11Data = static_cast<QX11PixmapData*>(pd); +#ifndef QT_NO_XRENDER + if (x11Data->picture && x11Data->d == 32) + return true; +#endif + if (x11Data->d == 1 || x11Data->x11_mask) + return true; + } + return false; +#else + return data && data->hasAlphaChannel(); +#endif } /*! diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp index 3d9c363..01f2c11 100644 --- a/src/gui/image/qpixmap_x11.cpp +++ b/src/gui/image/qpixmap_x11.cpp @@ -1321,7 +1321,6 @@ QBitmap QX11PixmapData::mask() const return mask; } - /*! Sets a mask bitmap. @@ -1549,7 +1548,7 @@ QImage QX11PixmapData::toImage(const QRect &rect) const if (!xiWrapper.xi) return QImage(); - if (canTakeQImageFromXImage(xiWrapper)) + if (!x11_mask && canTakeQImageFromXImage(xiWrapper)) return takeQImageFromXImage(xiWrapper); QImage image = toImage(xiWrapper, rect); diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index b797776..40b51fe 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -3435,6 +3435,10 @@ void QTreeViewPrivate::updateScrollBars() if (!viewportSize.isValid()) viewportSize = QSize(0, 0); + if (viewItems.isEmpty()) { + q->doItemsLayout(); + } + int itemsInViewport = 0; if (uniformRowHeights) { if (defaultItemHeight <= 0) diff --git a/src/gui/kernel/qdnd_win.cpp b/src/gui/kernel/qdnd_win.cpp index a164c2a..7083886 100644 --- a/src/gui/kernel/qdnd_win.cpp +++ b/src/gui/kernel/qdnd_win.cpp @@ -515,7 +515,7 @@ static inline Qt::MouseButtons keystate_to_mousebutton(DWORD grfKeyState) //--------------------------------------------------------------------- // IDropSource Methods //--------------------------------------------------------------------- -STDMETHODIMP +QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP QOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) { #ifdef QDND_DEBUG @@ -545,7 +545,7 @@ QOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) } } -STDMETHODIMP +QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP QOleDropSource::GiveFeedback(DWORD dwEffect) { Qt::DropAction action = translateToQDragDropAction(dwEffect); @@ -626,7 +626,7 @@ QOleDropTarget::Release(void) // IDropTarget Methods //--------------------------------------------------------------------- -STDMETHODIMP +QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP QOleDropTarget::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) { #ifdef QDND_DEBUG @@ -688,7 +688,7 @@ void QOleDropTarget::sendDragEnterEvent(QWidget *dragEnterWidget, DWORD grfKeySt } -STDMETHODIMP +QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP QOleDropTarget::DragOver(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) { #ifdef QDND_DEBUG @@ -758,7 +758,7 @@ QOleDropTarget::DragOver(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) return NOERROR; } -STDMETHODIMP +QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP QOleDropTarget::DragLeave() { #ifdef QDND_DEBUG @@ -785,7 +785,7 @@ QOleDropTarget::DragLeave() #define KEY_STATE_BUTTON_MASK (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON) -STDMETHODIMP +QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP QOleDropTarget::Drop(LPDATAOBJECT /*pDataObj*/, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) { #ifdef QDND_DEBUG diff --git a/src/gui/styles/qstylehelper_p.h b/src/gui/styles/qstylehelper_p.h index 71fce55..3759929 100644 --- a/src/gui/styles/qstylehelper_p.h +++ b/src/gui/styles/qstylehelper_p.h @@ -108,7 +108,7 @@ template <typename T> { typedef HexString<T> type; enum { ExactSize = true }; - static int size(const HexString<T> &str) { return sizeof(str.val) * 2; } + static int size(const HexString<T> &) { return sizeof(T) * 2; } static inline void appendTo(const HexString<T> &str, QChar *&out) { str.write(out); } }; diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index 5fe0c0c..7f2c4e9 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -404,12 +404,6 @@ void QTextControlPrivate::init(Qt::TextFormat format, const QString &text, QText Q_Q(QTextControl); setContent(format, text, document); - QWidget *parentWidget = qobject_cast<QWidget*>(parent); - if (parentWidget) { - QTextOption opt = doc->defaultTextOption(); - opt.setTextDirection(parentWidget->layoutDirection()); - doc->setDefaultTextOption(opt); - } doc->setUndoRedoEnabled(interactionFlags & Qt::TextEditable); q->setCursorWidth(-1); } diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp index bdbd0b0..42be03b 100644 --- a/src/gui/widgets/qlabel.cpp +++ b/src/gui/widgets/qlabel.cpp @@ -635,7 +635,7 @@ QSize QLabelPrivate::sizeForWidth(int w) const br = movie->currentPixmap().rect(); #endif else if (isTextLabel) { - int align = QStyle::visualAlignment(q->layoutDirection(), QFlag(this->align)); + int align = QStyle::visualAlignment(textDirection(), QFlag(this->align)); // Add indentation int m = indent; @@ -1059,7 +1059,8 @@ void QLabel::paintEvent(QPaintEvent *) drawFrame(&painter); QRect cr = contentsRect(); cr.adjust(d->margin, d->margin, -d->margin, -d->margin); - int align = QStyle::visualAlignment(layoutDirection(), QFlag(d->align)); + int align = QStyle::visualAlignment(d->isTextLabel ? d->textDirection() + : layoutDirection(), QFlag(d->align)); #ifndef QT_NO_MOVIE if (d->movie) { @@ -1119,7 +1120,8 @@ void QLabel::paintEvent(QPaintEvent *) d->control->drawContents(&painter, QRectF(), this); painter.restore(); } else { - int flags = align; + int flags = align | (d->textDirection() == Qt::LeftToRight ? Qt::TextForceLeftToRight + : Qt::TextForceRightToLeft); if (d->hasShortcut) { flags |= Qt::TextShowMnemonic; if (!style->styleHint(QStyle::SH_UnderlineShortcut, &opt, this)) @@ -1447,10 +1449,6 @@ void QLabel::changeEvent(QEvent *ev) d->control->setPalette(palette()); } else if (ev->type() == QEvent::ContentsRectChange) { d->updateLabel(); - } else if (ev->type() == QEvent::LayoutDirectionChange) { - if (d->isTextLabel && d->control) { - d->sendControlEvent(ev); - } } QFrame::changeEvent(ev); } @@ -1486,6 +1484,15 @@ void QLabel::setScaledContents(bool enable) update(contentsRect()); } +Qt::LayoutDirection QLabelPrivate::textDirection() const +{ + if (control) { + QTextOption opt = control->document()->defaultTextOption(); + return opt.textDirection(); + } + + return text.isRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight; +} /*! \fn void QLabel::setAlignment(Qt::AlignmentFlag flag) @@ -1503,7 +1510,8 @@ QRect QLabelPrivate::documentRect() const Q_ASSERT_X(isTextLabel, "documentRect", "document rect called for label that is not a text label!"); QRect cr = q->contentsRect(); cr.adjust(margin, margin, -margin, -margin); - const int align = QStyle::visualAlignment(q->layoutDirection(), QFlag(this->align)); + const int align = QStyle::visualAlignment(isTextLabel ? textDirection() + : q->layoutDirection(), QFlag(this->align)); int m = indent; if (m < 0 && q->frameWidth()) // no indent, but we do have a frame m = q->fontMetrics().width(QLatin1Char('x')) / 2 - margin; @@ -1564,7 +1572,6 @@ void QLabelPrivate::ensureTextLayouted() const if (!textLayoutDirty) return; ensureTextPopulated(); - Q_Q(const QLabel); if (control) { QTextDocument *doc = control->document(); QTextOption opt = doc->defaultTextOption(); @@ -1576,8 +1583,6 @@ void QLabelPrivate::ensureTextLayouted() const else opt.setWrapMode(QTextOption::ManualWrap); - opt.setTextDirection(q->layoutDirection()); - doc->setDefaultTextOption(opt); QTextFrameFormat fmt = doc->rootFrame()->frameFormat(); diff --git a/src/gui/widgets/qlabel_p.h b/src/gui/widgets/qlabel_p.h index fba7224..83624c7 100644 --- a/src/gui/widgets/qlabel_p.h +++ b/src/gui/widgets/qlabel_p.h @@ -132,6 +132,7 @@ public: QRectF layoutRect() const; QRect documentRect() const; QPoint layoutPoint(const QPoint& p) const; + Qt::LayoutDirection textDirection() const; #ifndef QT_NO_CONTEXTMENU QMenu *createStandardContextMenu(const QPoint &pos); #endif diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 2347e66..ee59830 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -866,32 +866,6 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) if (do_vectorpath_cache) path.makeCacheable(); - if (!device->format().stencil()) { - // If there is no stencil buffer, triangulate the path instead. - - QRectF bbox = path.controlPointRect(); - // If the path doesn't fit within these limits, it is possible that the triangulation will fail. - bool withinLimits = (bbox.left() > -0x8000 * inverseScale) - && (bbox.right() < 0x8000 * inverseScale) - && (bbox.top() > -0x8000 * inverseScale) - && (bbox.bottom() < 0x8000 * inverseScale); - if (withinLimits) { - QTriangleSet polys = qTriangulate(path, QTransform().scale(1 / inverseScale, 1 / inverseScale)); - - QVarLengthArray<float> vertices(polys.vertices.size()); - for (int i = 0; i < polys.vertices.size(); ++i) - vertices[i] = float(inverseScale * polys.vertices.at(i)); - - prepareForDraw(currentBrush.isOpaque()); - setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, vertices.constData()); - glDrawElements(GL_TRIANGLES, polys.indices.size(), GL_UNSIGNED_INT, polys.indices.constData()); - } else { - // We can't handle big, concave painter paths with OpenGL without stencil buffer. - qWarning("Painter path exceeds +/-32767 pixels."); - } - return; - } - // The path is too complicated & needs the stencil technique vertexCoordinateArray.clear(); vertexCoordinateArray.addPath(path, inverseScale, false); @@ -1340,7 +1314,7 @@ void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, c QGLRect srcRect(src.left(), top, src.right(), bottom); bool isBitmap = pixmap.isQBitmap(); - bool isOpaque = !isBitmap && !pixmap.hasAlphaChannel(); + bool isOpaque = !isBitmap && !pixmap.hasAlpha(); d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, state()->renderHints & QPainter::SmoothPixmapTransform, texture->id); @@ -1791,7 +1765,7 @@ void QGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFragmen transferMode(ImageArrayDrawingMode); bool isBitmap = pixmap.isQBitmap(); - bool isOpaque = !isBitmap && (!pixmap.hasAlphaChannel() || (hints & QPainter::OpaqueHint)) && allOpaque; + bool isOpaque = !isBitmap && (!pixmap.hasAlpha() || (hints & QPainter::OpaqueHint)) && allOpaque; updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, q->state()->renderHints & QPainter::SmoothPixmapTransform, texture->id); diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp index f3a4c95..7f4c670 100644 --- a/src/opengl/qgl_x11.cpp +++ b/src/opengl/qgl_x11.cpp @@ -1776,6 +1776,10 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pixmap, cons QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pixmap->data_ptr().data()); Q_ASSERT(pixmapData->classId() == QPixmapData::X11Class); + // We can't use TFP if the pixmap has a separate X11 mask + if (pixmapData->x11_mask) + return 0; + if (!qt_resolveTextureFromPixmap(paintDevice)) return 0; diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index adbba85..6c9b288 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -324,10 +324,6 @@ void QGLFBOGLPaintDevice::setFBO(QGLFramebufferObject* f, fboFormat.setStencil(true); } else if (attachment == QGLFramebufferObject::Depth) { fboFormat.setDepth(true); - fboFormat.setStencil(false); - } else { - fboFormat.setDepth(false); - fboFormat.setStencil(false); } GLenum format = f->format().internalTextureFormat(); @@ -472,13 +468,17 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_SAMPLES_EXT, &samples); } + // In practice, a combined depth-stencil buffer is supported by all desktop platforms, while a + // separate stencil buffer is not. On embedded devices however, a combined depth-stencil buffer + // might not be supported while separate buffers are, according to QTBUG-12861. + if (attachment == QGLFramebufferObject::CombinedDepthStencil && (QGLExtensions::glExtensions() & QGLExtensions::PackedDepthStencil)) { // depth and stencil buffer needs another extension - glGenRenderbuffers(1, &depth_stencil_buffer); - Q_ASSERT(!glIsRenderbuffer(depth_stencil_buffer)); - glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_stencil_buffer); - Q_ASSERT(glIsRenderbuffer(depth_stencil_buffer)); + glGenRenderbuffers(1, &depth_buffer); + Q_ASSERT(!glIsRenderbuffer(depth_buffer)); + glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_buffer); + Q_ASSERT(glIsRenderbuffer(depth_buffer)); if (samples != 0 && glRenderbufferStorageMultisampleEXT) glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_DEPTH24_STENCIL8_EXT, size.width(), size.height()); @@ -486,24 +486,26 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, size.width(), size.height()); - GLint i = 0; - glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i); + stencil_buffer = depth_buffer; glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, depth_stencil_buffer); + GL_RENDERBUFFER_EXT, depth_buffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, depth_stencil_buffer); - fbo_attachment = QGLFramebufferObject::CombinedDepthStencil; + GL_RENDERBUFFER_EXT, stencil_buffer); valid = checkFramebufferStatus(); - if (!valid) - glDeleteRenderbuffers(1, &depth_stencil_buffer); - } else if (attachment == QGLFramebufferObject::Depth - || attachment == QGLFramebufferObject::CombinedDepthStencil) + if (!valid) { + glDeleteRenderbuffers(1, &depth_buffer); + stencil_buffer = depth_buffer = 0; + } + } + + if (depth_buffer == 0 && (attachment == QGLFramebufferObject::CombinedDepthStencil + || (attachment == QGLFramebufferObject::Depth))) { - glGenRenderbuffers(1, &depth_stencil_buffer); - Q_ASSERT(!glIsRenderbuffer(depth_stencil_buffer)); - glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_stencil_buffer); - Q_ASSERT(glIsRenderbuffer(depth_stencil_buffer)); + glGenRenderbuffers(1, &depth_buffer); + Q_ASSERT(!glIsRenderbuffer(depth_buffer)); + glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_buffer); + Q_ASSERT(glIsRenderbuffer(depth_buffer)); if (samples != 0 && glRenderbufferStorageMultisampleEXT) { #ifdef QT_OPENGL_ES #define GL_DEPTH_COMPONENT16 0x81A5 @@ -521,14 +523,53 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size.width(), size.height()); #endif } - GLint i = 0; - glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i); glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, depth_stencil_buffer); - fbo_attachment = QGLFramebufferObject::Depth; + GL_RENDERBUFFER_EXT, depth_buffer); valid = checkFramebufferStatus(); - if (!valid) - glDeleteRenderbuffers(1, &depth_stencil_buffer); + if (!valid) { + glDeleteRenderbuffers(1, &depth_buffer); + depth_buffer = 0; + } + } + + if (stencil_buffer == 0 && (attachment == QGLFramebufferObject::CombinedDepthStencil)) { + glGenRenderbuffers(1, &stencil_buffer); + Q_ASSERT(!glIsRenderbuffer(stencil_buffer)); + glBindRenderbuffer(GL_RENDERBUFFER_EXT, stencil_buffer); + Q_ASSERT(glIsRenderbuffer(stencil_buffer)); + if (samples != 0 && glRenderbufferStorageMultisampleEXT) { +#ifdef QT_OPENGL_ES + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, + GL_STENCIL_INDEX8_EXT, size.width(), size.height()); +#else + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, + GL_STENCIL_INDEX, size.width(), size.height()); +#endif + } else { +#ifdef QT_OPENGL_ES + glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8_EXT, + size.width(), size.height()); +#else + glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX, + size.width(), size.height()); +#endif + } + glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, stencil_buffer); + valid = checkFramebufferStatus(); + if (!valid) { + glDeleteRenderbuffers(1, &stencil_buffer); + stencil_buffer = 0; + } + } + + // The FBO might have become valid after removing the depth or stencil buffer. + valid = checkFramebufferStatus(); + + if (depth_buffer && stencil_buffer) { + fbo_attachment = QGLFramebufferObject::CombinedDepthStencil; + } else if (depth_buffer) { + fbo_attachment = QGLFramebufferObject::Depth; } else { fbo_attachment = QGLFramebufferObject::NoAttachment; } @@ -539,6 +580,10 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, glDeleteRenderbuffers(1, &color_buffer); else glDeleteTextures(1, &texture); + if (depth_buffer) + glDeleteRenderbuffers(1, &depth_buffer); + if (stencil_buffer && depth_buffer != stencil_buffer) + glDeleteRenderbuffers(1, &stencil_buffer); glDeleteFramebuffers(1, &fbo); fbo_guard.setId(0); } @@ -821,8 +866,10 @@ QGLFramebufferObject::~QGLFramebufferObject() glDeleteTextures(1, &d->texture); if (d->color_buffer) glDeleteRenderbuffers(1, &d->color_buffer); - if (d->depth_stencil_buffer) - glDeleteRenderbuffers(1, &d->depth_stencil_buffer); + if (d->depth_buffer) + glDeleteRenderbuffers(1, &d->depth_buffer); + if (d->stencil_buffer && d->stencil_buffer != d->depth_buffer) + glDeleteRenderbuffers(1, &d->stencil_buffer); GLuint fbo = d->fbo(); glDeleteFramebuffers(1, &fbo); } diff --git a/src/opengl/qglframebufferobject_p.h b/src/opengl/qglframebufferobject_p.h index d8ff012..58b4e9e 100644 --- a/src/opengl/qglframebufferobject_p.h +++ b/src/opengl/qglframebufferobject_p.h @@ -126,7 +126,7 @@ private: class QGLFramebufferObjectPrivate { public: - QGLFramebufferObjectPrivate() : fbo_guard(0), texture(0), depth_stencil_buffer(0) + QGLFramebufferObjectPrivate() : fbo_guard(0), texture(0), depth_buffer(0), stencil_buffer(0) , color_buffer(0), valid(false), engine(0) {} ~QGLFramebufferObjectPrivate() {} @@ -136,7 +136,8 @@ public: bool checkFramebufferStatus() const; QGLSharedResourceGuard fbo_guard; GLuint texture; - GLuint depth_stencil_buffer; + GLuint depth_buffer; + GLuint stencil_buffer; GLuint color_buffer; GLenum target; QSize size; |