From 3a5f473a16b3bc64e6793a9a5002d961a2a0762a Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 17 Mar 2010 11:14:15 +0100 Subject: Fix a crash in animation groups when deleting uncontrolled animations The problem was that we were not removing their references from the private object hash and at some point we could access it. Task-number: QTBUG-8910 Reviewed-by: gabi --- src/corelib/animation/qanimationgroup.cpp | 4 ++-- src/corelib/animation/qanimationgroup_p.h | 15 +++++++++++++-- src/corelib/animation/qparallelanimationgroup.cpp | 15 +++++++++------ src/corelib/animation/qparallelanimationgroup_p.h | 2 ++ src/corelib/animation/qsequentialanimationgroup.cpp | 13 ++++++++----- src/corelib/animation/qsequentialanimationgroup_p.h | 2 +- .../tst_qparallelanimationgroup.cpp | 17 ++++++++++++++++- 7 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/corelib/animation/qanimationgroup.cpp b/src/corelib/animation/qanimationgroup.cpp index a89f949..2decda3 100644 --- a/src/corelib/animation/qanimationgroup.cpp +++ b/src/corelib/animation/qanimationgroup.cpp @@ -244,7 +244,7 @@ QAbstractAnimation *QAnimationGroup::takeAnimation(int index) // in ChildRemoved event d->animations.removeAt(index); animation->setParent(0); - d->animationRemovedAt(index); + d->animationRemoved(index, animation); return animation; } @@ -285,7 +285,7 @@ bool QAnimationGroup::event(QEvent *event) } -void QAnimationGroupPrivate::animationRemovedAt(int index) +void QAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *) { Q_Q(QAnimationGroup); Q_UNUSED(index); diff --git a/src/corelib/animation/qanimationgroup_p.h b/src/corelib/animation/qanimationgroup_p.h index 394773b..45603b3 100644 --- a/src/corelib/animation/qanimationgroup_p.h +++ b/src/corelib/animation/qanimationgroup_p.h @@ -72,8 +72,19 @@ public: isGroup = true; } - virtual void animationInsertedAt(int index) { Q_UNUSED(index) }; - virtual void animationRemovedAt(int index); + virtual void animationInsertedAt(int) { } + virtual void animationRemoved(int, QAbstractAnimation *); + + void disconnectUncontrolledAnimation(QAbstractAnimation *anim) + { + //0 for the signal here because we might be called from the animation destructor + QObject::disconnect(anim, 0, q_func(), SLOT(_q_uncontrolledAnimationFinished())); + } + + void connectUncontrolledAnimation(QAbstractAnimation *anim) + { + QObject::connect(anim, SIGNAL(finished()), q_func(), SLOT(_q_uncontrolledAnimationFinished())); + } QList animations; }; diff --git a/src/corelib/animation/qparallelanimationgroup.cpp b/src/corelib/animation/qparallelanimationgroup.cpp index eaa0364..280afed 100644 --- a/src/corelib/animation/qparallelanimationgroup.cpp +++ b/src/corelib/animation/qparallelanimationgroup.cpp @@ -246,11 +246,9 @@ void QParallelAnimationGroupPrivate::_q_uncontrolledAnimationFinished() void QParallelAnimationGroupPrivate::disconnectUncontrolledAnimations() { - Q_Q(QParallelAnimationGroup); - QHash::iterator it = uncontrolledFinishTime.begin(); while (it != uncontrolledFinishTime.end()) { - QObject::disconnect(it.key(), SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished())); + disconnectUncontrolledAnimation(it.key()); ++it; } @@ -259,13 +257,11 @@ void QParallelAnimationGroupPrivate::disconnectUncontrolledAnimations() void QParallelAnimationGroupPrivate::connectUncontrolledAnimations() { - Q_Q(QParallelAnimationGroup); - for (int i = 0; i < animations.size(); ++i) { QAbstractAnimation *animation = animations.at(i); if (animation->duration() == -1 || animation->loopCount() < 0) { uncontrolledFinishTime[animation] = -1; - QObject::connect(animation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished())); + connectUncontrolledAnimation(animation); } } } @@ -305,6 +301,13 @@ bool QParallelAnimationGroupPrivate::isUncontrolledAnimationFinished(QAbstractAn return uncontrolledFinishTime.value(anim, -1) >= 0; } +void QParallelAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *anim) +{ + QAnimationGroupPrivate::animationRemoved(index, anim); + disconnectUncontrolledAnimation(anim); + uncontrolledFinishTime.remove(anim); +} + /*! \reimp */ diff --git a/src/corelib/animation/qparallelanimationgroup_p.h b/src/corelib/animation/qparallelanimationgroup_p.h index a74d496..cab4fa9 100644 --- a/src/corelib/animation/qparallelanimationgroup_p.h +++ b/src/corelib/animation/qparallelanimationgroup_p.h @@ -80,6 +80,8 @@ public: void connectUncontrolledAnimations(); void disconnectUncontrolledAnimations(); + void animationRemoved(int index, QAbstractAnimation *); + // private slot void _q_uncontrolledAnimationFinished(); }; diff --git a/src/corelib/animation/qsequentialanimationgroup.cpp b/src/corelib/animation/qsequentialanimationgroup.cpp index 8ab084a..7617c1f 100644 --- a/src/corelib/animation/qsequentialanimationgroup.cpp +++ b/src/corelib/animation/qsequentialanimationgroup.cpp @@ -479,7 +479,7 @@ void QSequentialAnimationGroupPrivate::activateCurrentAnimation(bool intermediat // connects to the finish signal of uncontrolled animations if (currentAnimation->totalDuration() == -1) - QObject::connect(currentAnimation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished())); + connectUncontrolledAnimation(currentAnimation); currentAnimation->start(); if (!intermediate && state == QSequentialAnimationGroup::Paused) @@ -496,7 +496,7 @@ void QSequentialAnimationGroupPrivate::_q_uncontrolledAnimationFinished() actualDuration.append(-1); actualDuration[currentAnimationIndex] = currentAnimation->currentTime(); - QObject::disconnect(currentAnimation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished())); + disconnectUncontrolledAnimation(currentAnimation); if ((direction == QAbstractAnimation::Forward && currentAnimation == animations.last()) || (direction == QAbstractAnimation::Backward && currentAnimationIndex == 0)) { @@ -543,10 +543,10 @@ void QSequentialAnimationGroupPrivate::animationInsertedAt(int index) the group at index \a index. The animation is no more listed when this method is called. */ -void QSequentialAnimationGroupPrivate::animationRemovedAt(int index) +void QSequentialAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *anim) { Q_Q(QSequentialAnimationGroup); - QAnimationGroupPrivate::animationRemovedAt(index); + QAnimationGroupPrivate::animationRemoved(index, anim); Q_ASSERT(currentAnimation); // currentAnimation should always be set @@ -555,7 +555,10 @@ void QSequentialAnimationGroupPrivate::animationRemovedAt(int index) const int currentIndex = animations.indexOf(currentAnimation); if (currentIndex == -1) { - //we're removing the current animation, let's update it to another one + //we're removing the current animation + + disconnectUncontrolledAnimation(currentAnimation); + if (index < animations.count()) setCurrentAnimation(index); //let's try to take the next one else if (index > 0) diff --git a/src/corelib/animation/qsequentialanimationgroup_p.h b/src/corelib/animation/qsequentialanimationgroup_p.h index a55e136..de69916 100644 --- a/src/corelib/animation/qsequentialanimationgroup_p.h +++ b/src/corelib/animation/qsequentialanimationgroup_p.h @@ -85,7 +85,7 @@ public: void activateCurrentAnimation(bool intermediate = false); void animationInsertedAt(int index); - void animationRemovedAt(int index); + void animationRemoved(int index, QAbstractAnimation *anim); bool atEnd() const; diff --git a/tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp b/tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp index fb0f3e0..d2d86fb 100644 --- a/tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp +++ b/tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp @@ -75,6 +75,8 @@ private slots: void loopCount(); void autoAdd(); void pauseResume(); + + void QTBUG8910_crashWhenRemovingUncontrolledAnimation(); }; tst_QParallelAnimationGroup::tst_QParallelAnimationGroup() @@ -999,9 +1001,22 @@ void tst_QParallelAnimationGroup::pauseResume() QCOMPARE(spy.count(), 2); //this shouldn't have changed group.resume(); QCOMPARE(spy.count(), 2); //this shouldn't have changed +} - +void tst_QParallelAnimationGroup::QTBUG8910_crashWhenRemovingUncontrolledAnimation() +{ + QParallelAnimationGroup group; + TestAnimation *anim = new TestAnimation; + anim->setLoopCount(-1); + TestAnimation *anim2 = new TestAnimation; + anim2->setLoopCount(-1); + group.addAnimation(anim); + group.addAnimation(anim2); + group.start(); + delete anim; + // it would crash here because the internals of the group would still have a reference to anim + delete anim2; } -- cgit v0.12 From e1915815bc5ef86b3844608bba46769da5173363 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 17 Mar 2010 10:53:34 +0100 Subject: Optimize speed of QTextLayout and QPainter::drawText QFontEngine::boundingBox() is potentially an expensive function, because the font engines have to consult the underlying font system for the values and usually do not cache the results. To account for negative right bearing in the case of text layouts, we would call the boundingBox() function at every potential break point in the text, causing a great performance hit on text drawing. To minimize the impact of this, we only calculate the right bearing when we have to: 1. If subtracting the minimum right bearing from the width would cause the line to expand beyond its maximum line width, then we have to get the actual metrics of the last glyph to check if we need to break. 2. The line's final textWidth should include the negative right bearing, so unless it has already been calculated, we calculate it when the correct line width has been found. This gives us a potentially huge speed-up, since boundingBox() will in the common case only be called once for the last glyph in each text line. Task-number: QTBUG-9074 Reviewed-by: Simon Hausmann --- src/gui/text/qtextlayout.cpp | 122 +++++++++++++++++++++++++++++-------------- 1 file changed, 82 insertions(+), 40 deletions(-) diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index af91603..204effa 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1644,28 +1644,67 @@ namespace { struct LineBreakHelper { - LineBreakHelper() : glyphCount(0), maxGlyphs(0), manualWrap(false) {} + LineBreakHelper() + : glyphCount(0), maxGlyphs(0), currentPosition(0), fontEngine(0), logClusters(0), + manualWrap(false) + { + } + QScriptLine tmpData; QScriptLine spaceData; + QGlyphLayout glyphs; + int glyphCount; int maxGlyphs; + int currentPosition; QFixed minw; QFixed softHyphenWidth; QFixed rightBearing; + QFixed minimumRightBearing; + + QFontEngine *fontEngine; + const unsigned short *logClusters; bool manualWrap; bool checkFullOtherwiseExtend(QScriptLine &line); + + QFixed calculateNewWidth(const QScriptLine &line) const { + return line.textWidth + tmpData.textWidth + spaceData.textWidth + softHyphenWidth + - qMin(rightBearing, QFixed()); + } + + inline glyph_t currentGlyph() const + { + Q_ASSERT(currentPosition > 0); + return glyphs.glyphs[logClusters[currentPosition - 1]]; + } + + inline void adjustRightBearing() + { + if (currentPosition <= 0) + return; + + glyph_metrics_t gi = fontEngine->boundingBox(currentGlyph()); + if (gi.isValid()) + rightBearing = qMin(QFixed(), gi.xoff - gi.x - gi.width); + } + + inline void resetRightBearing() + { + rightBearing = QFixed(1); // Any positive number is defined as invalid since only + // negative right bearings are interesting to us. + } }; inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line) { LB_DEBUG("possible break width %f, spacew=%f", tmpData.textWidth.toReal(), spaceData.textWidth.toReal()); - QFixed newWidth = line.textWidth + tmpData.textWidth + spaceData.textWidth + softHyphenWidth + rightBearing; + QFixed newWidth = calculateNewWidth(line); if (line.length && !manualWrap && (newWidth > line.width || glyphCount > maxGlyphs)) return true; @@ -1741,13 +1780,12 @@ void QTextLine::layout_helper(int maxGlyphs) Qt::Alignment alignment = eng->option.alignment(); const HB_CharAttributes *attributes = eng->attributes(); - int pos = line.from; + lbh.currentPosition = line.from; int end = 0; - QGlyphLayout glyphs; - const unsigned short *logClusters = eng->layoutData->logClustersPtr; + lbh.logClusters = eng->layoutData->logClustersPtr; while (newItem < eng->layoutData->items.size()) { - lbh.rightBearing = 0; + lbh.resetRightBearing(); lbh.softHyphenWidth = 0; if (newItem != item) { item = newItem; @@ -1755,13 +1793,19 @@ void QTextLine::layout_helper(int maxGlyphs) if (!current.num_glyphs) { eng->shape(item); attributes = eng->attributes(); - logClusters = eng->layoutData->logClustersPtr; + lbh.logClusters = eng->layoutData->logClustersPtr; } - pos = qMax(line.from, current.position); + lbh.currentPosition = qMax(line.from, current.position); end = current.position + eng->length(item); - glyphs = eng->shapedGlyphs(¤t); + lbh.glyphs = eng->shapedGlyphs(¤t); } const QScriptItem ¤t = eng->layoutData->items[item]; + QFontEngine *fontEngine = eng->fontEngine(current); + if (lbh.fontEngine != fontEngine) { + lbh.fontEngine = fontEngine; + lbh.minimumRightBearing = qMin(QFixed(), + QFixed::fromReal(fontEngine->minRightBearing())); + } lbh.tmpData.leading = qMax(lbh.tmpData.leading + lbh.tmpData.ascent, current.leading + current.ascent) - qMax(lbh.tmpData.ascent, @@ -1791,8 +1835,8 @@ void QTextLine::layout_helper(int maxGlyphs) if (!line.length && !lbh.tmpData.length) line.setDefaultHeight(eng); if (eng->option.flags() & QTextOption::ShowLineAndParagraphSeparators) { - addNextCluster(pos, end, lbh.tmpData, lbh.glyphCount, - current, logClusters, glyphs); + addNextCluster(lbh.currentPosition, end, lbh.tmpData, lbh.glyphCount, + current, lbh.logClusters, lbh.glyphs); } else { lbh.tmpData.length++; } @@ -1811,10 +1855,10 @@ void QTextLine::layout_helper(int maxGlyphs) ++lbh.glyphCount; if (lbh.checkFullOtherwiseExtend(line)) goto found; - } else if (attributes[pos].whiteSpace) { - while (pos < end && attributes[pos].whiteSpace) - addNextCluster(pos, end, lbh.spaceData, lbh.glyphCount, - current, logClusters, glyphs); + } else if (attributes[lbh.currentPosition].whiteSpace) { + while (lbh.currentPosition < end && attributes[lbh.currentPosition].whiteSpace) + addNextCluster(lbh.currentPosition, end, lbh.spaceData, lbh.glyphCount, + current, lbh.logClusters, lbh.glyphs); if (!lbh.manualWrap && lbh.spaceData.textWidth > line.width) { lbh.spaceData.textWidth = line.width; // ignore spaces that fall out of the line. @@ -1823,19 +1867,19 @@ void QTextLine::layout_helper(int maxGlyphs) } else { bool sb_or_ws = false; do { - addNextCluster(pos, end, lbh.tmpData, lbh.glyphCount, - current, logClusters, glyphs); + addNextCluster(lbh.currentPosition, end, lbh.tmpData, lbh.glyphCount, + current, lbh.logClusters, lbh.glyphs); - if (attributes[pos].whiteSpace || attributes[pos-1].lineBreakType != HB_NoBreak) { + if (attributes[lbh.currentPosition].whiteSpace || attributes[lbh.currentPosition-1].lineBreakType != HB_NoBreak) { sb_or_ws = true; break; - } else if (breakany && attributes[pos].charStop) { + } else if (breakany && attributes[lbh.currentPosition].charStop) { break; } - } while (pos < end); + } while (lbh.currentPosition < end); lbh.minw = qMax(lbh.tmpData.textWidth, lbh.minw); - if (pos && attributes[pos - 1].lineBreakType == HB_SoftHyphen) { + if (lbh.currentPosition && attributes[lbh.currentPosition - 1].lineBreakType == HB_SoftHyphen) { // if we are splitting up a word because of // a soft hyphen then we ... // @@ -1853,41 +1897,39 @@ void QTextLine::layout_helper(int maxGlyphs) // and thus become invisible again. // if (line.length) - lbh.softHyphenWidth = glyphs.advances_x[logClusters[pos - 1]]; + lbh.softHyphenWidth = lbh.glyphs.advances_x[lbh.logClusters[lbh.currentPosition - 1]]; else if (breakany) - lbh.tmpData.textWidth += glyphs.advances_x[logClusters[pos - 1]]; + lbh.tmpData.textWidth += lbh.glyphs.advances_x[lbh.logClusters[lbh.currentPosition - 1]]; } // The actual width of the text needs to take the right bearing into account. The // right bearing is left-ward, which means that if the rightmost pixel is to the right // of the advance of the glyph, the bearing will be negative. We flip the sign // for the code to be more readable. Logic borrowed from qfontmetrics.cpp. - if (pos) { - QFontEngine *fontEngine = eng->fontEngine(current); - glyph_t glyph = glyphs.glyphs[logClusters[pos - 1]]; - glyph_metrics_t gi = fontEngine->boundingBox(glyph); - if (gi.isValid()) - lbh.rightBearing = qMax(QFixed(), -(gi.xoff - gi.x - gi.width)); - } + // We ignore the right bearing if the minimum negative bearing is too little to + // expand the text beyond the edge. + if (sb_or_ws|breakany) { + if (lbh.calculateNewWidth(line) + lbh.minimumRightBearing > line.width) + lbh.adjustRightBearing(); + if (lbh.checkFullOtherwiseExtend(line)) { + if (!breakany) { + line.textWidth += lbh.softHyphenWidth; + } - if ((sb_or_ws|breakany) && lbh.checkFullOtherwiseExtend(line)) { - if (!breakany) { - line.textWidth += lbh.softHyphenWidth; + goto found; } - - line.textWidth += lbh.rightBearing; - - goto found; } } - if (pos == end) + if (lbh.currentPosition == end) newItem = item + 1; } LB_DEBUG("reached end of line"); lbh.checkFullOtherwiseExtend(line); - line.textWidth += lbh.rightBearing; - found: + if (lbh.rightBearing > 0) // If right bearing has not yet been adjusted + lbh.adjustRightBearing(); + line.textWidth -= qMin(QFixed(), lbh.rightBearing); + if (line.length == 0) { LB_DEBUG("no break available in line, adding temp: length %d, width %f, space: length %d, width %f", lbh.tmpData.length, lbh.tmpData.textWidth.toReal(), -- cgit v0.12 From 6aba7215a0ac2092a7f00015df0d7a80681ef6bc Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Wed, 17 Mar 2010 14:28:50 +0100 Subject: Fixes blending problem when paiting non-opaque items with cache enabled. In most cases when partially updating an item, the old content of the cache needs to be replaced with the new content (CompositionMode_Source). But in a specific case when using DeviceCoordinateCache and when the item is transformed, the new content needs to be blended (CompositionMode_SourceAtop) with the old one to avoid incorrect fully transparent background. Autotest included. Task-number: QTBUG-7863 Reviewed-by: bnilsen --- src/gui/graphicsview/qgraphicsscene.cpp | 6 ++ tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 132 ++++++++++++++++++++++- 2 files changed, 136 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 4ee2301..6934abc 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4285,6 +4285,12 @@ static void _q_paintIntoCache(QPixmap *pix, QGraphicsItem *item, const QRegion & if (!subPix.isNull()) { // Blit the subpixmap into the main pixmap. pixmapPainter.begin(pix); + if (item->cacheMode() == QGraphicsItem::DeviceCoordinateCache + && itemToPixmap.type() > QTransform::TxTranslate) { + pixmapPainter.setCompositionMode(QPainter::CompositionMode_SourceAtop); + } else { + pixmapPainter.setCompositionMode(QPainter::CompositionMode_Source); + } pixmapPainter.setClipRegion(pixmapExposed); pixmapPainter.drawPixmap(br.topLeft(), subPix); pixmapPainter.end(); diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index 9d437d6..9cd86a6 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -283,6 +283,7 @@ private slots: void task250680_childClip(); void taskQTBUG_5904_crashWithDeviceCoordinateCache(); void taskQT657_paintIntoCacheWithTransparentParts(); + void taskQTBUG_7863_paintIntoCacheWithTransparentParts(); }; void tst_QGraphicsScene::initTestCase() @@ -4348,8 +4349,9 @@ void tst_QGraphicsScene::taskQTBUG_5904_crashWithDeviceCoordinateCache() void tst_QGraphicsScene::taskQT657_paintIntoCacheWithTransparentParts() { + // Test using DeviceCoordinateCache and opaque item QWidget *w = new QWidget(); - w->setPalette(Qt::blue); + w->setPalette(QColor(0, 0, 255)); w->setGeometry(0, 0, 50, 50); QGraphicsScene *scene = new QGraphicsScene(); @@ -4361,7 +4363,7 @@ void tst_QGraphicsScene::taskQT657_paintIntoCacheWithTransparentParts() view->show(); QTest::qWaitForWindowShown(view); - w->update(10,10,10,10); + w->update(10, 10, 10, 10); QTest::qWait(50); QPixmap pix; @@ -4382,6 +4384,132 @@ void tst_QGraphicsScene::taskQT657_paintIntoCacheWithTransparentParts() for(int j = 0; j < im.height(); j++) QCOMPARE(qAlpha(im.pixel(i, j)), 255); } + + delete w; +} + +void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts() +{ + // Test using DeviceCoordinateCache and semi-transparent item + { + QGraphicsRectItem *backItem = new QGraphicsRectItem(0, 0, 100, 100); + backItem->setBrush(QColor(255, 255, 0)); + QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 50, 50); + rectItem->setBrush(QColor(0, 0, 255, 125)); + rectItem->setParentItem(backItem); + + QGraphicsScene *scene = new QGraphicsScene(); + QGraphicsView *view = new QGraphicsView(scene); + + scene->addItem(backItem); + rectItem->setCacheMode(QGraphicsItem::DeviceCoordinateCache); + backItem->rotate(15); + + view->show(); + QTest::qWaitForWindowShown(view); + rectItem->update(10, 10, 10, 10); + QTest::qWait(50); + + QPixmap pix; + QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem); + QPixmapCache::Key key = itemp->extraItemCache()->deviceData.value(view->viewport()).key; + QVERIFY(QPixmapCache::find(key, &pix)); + + QTransform t = rectItem->sceneTransform(); + // Map from scene coordinates to pixmap coordinates. + // X origin in the pixmap is the most-left point + // of the item's boundingRect in the scene. + qreal adjust = t.mapRect(rectItem->boundingRect().toRect()).left(); + QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1); + QPixmap subpix = pix.copy(rect); + + QImage im = subpix.toImage(); + for(int i = 0; i < im.width(); i++) { + for(int j = 0; j < im.height(); j++) { + QCOMPARE(qAlpha(im.pixel(i, j)), 125); + } + } + + delete view; + } + + // Test using ItemCoordinateCache and opaque item + { + QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 50, 50); + rectItem->setBrush(QColor(0, 0, 255)); + + QGraphicsScene *scene = new QGraphicsScene(); + QGraphicsView *view = new QGraphicsView(scene); + + scene->addItem(rectItem); + rectItem->setCacheMode(QGraphicsItem::ItemCoordinateCache); + rectItem->rotate(15); + + view->show(); + QTest::qWaitForWindowShown(view); + rectItem->update(10, 10, 10, 10); + QTest::qWait(50); + + QPixmap pix; + QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem); + QPixmapCache::Key key = itemp->extraItemCache()->key; + QVERIFY(QPixmapCache::find(key, &pix)); + + QTransform t = rectItem->sceneTransform(); + // Map from scene coordinates to pixmap coordinates. + // X origin in the pixmap is the most-left point + // of the item's boundingRect in the scene. + qreal adjust = t.mapRect(rectItem->boundingRect().toRect()).left(); + QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1); + QPixmap subpix = pix.copy(rect); + + QImage im = subpix.toImage(); + for(int i = 0; i < im.width(); i++) { + for(int j = 0; j < im.height(); j++) + QCOMPARE(qAlpha(im.pixel(i, j)), 255); + } + + delete view; + } + + // Test using ItemCoordinateCache and semi-transparent item + { + QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 50, 50); + rectItem->setBrush(QColor(0, 0, 255, 125)); + + QGraphicsScene *scene = new QGraphicsScene(); + QGraphicsView *view = new QGraphicsView(scene); + + scene->addItem(rectItem); + rectItem->setCacheMode(QGraphicsItem::ItemCoordinateCache); + rectItem->rotate(15); + + view->show(); + QTest::qWaitForWindowShown(view); + rectItem->update(10, 10, 10, 10); + QTest::qWait(50); + + QPixmap pix; + QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem); + QPixmapCache::Key key = itemp->extraItemCache()->key; + QVERIFY(QPixmapCache::find(key, &pix)); + + QTransform t = rectItem->sceneTransform(); + // Map from scene coordinates to pixmap coordinates. + // X origin in the pixmap is the most-left point + // of the item's boundingRect in the scene. + qreal adjust = t.mapRect(rectItem->boundingRect().toRect()).left(); + QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1); + QPixmap subpix = pix.copy(rect); + + QImage im = subpix.toImage(); + for(int i = 0; i < im.width(); i++) { + for(int j = 0; j < im.height(); j++) + QCOMPARE(qAlpha(im.pixel(i, j)), 125); + } + + delete view; + } } QTEST_MAIN(tst_QGraphicsScene) -- cgit v0.12 From 1ebeb971d3382aec0fff927ce2d6ea7b0452584f Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 17 Mar 2010 14:40:24 +0100 Subject: Optimize getting bearings of a glyph on Windows for true type fonts Usually, the bearing of a glyph is calculated based on the bounding box of the glyph. However, retrieving these bounds is a costly operation on Windows. For true type fonts, we can retrieve the bearings directly by getting the ABC widths, so as an optimization we implement a new virtual function in QFontEngine which retrieves the bearings of the glyph. The default implementation uses boundingBox, but on Windows we try to take the shortcut. Reviewed-by: Simon Hausmann --- src/gui/text/qfontengine.cpp | 14 ++++++++++++++ src/gui/text/qfontengine_p.h | 3 +++ src/gui/text/qfontengine_win.cpp | 24 ++++++++++++++++++++++++ src/gui/text/qfontengine_win_p.h | 2 ++ src/gui/text/qfontmetrics.cpp | 21 +++++++++++++-------- src/gui/text/qtextlayout.cpp | 6 +++--- 6 files changed, 59 insertions(+), 11 deletions(-) diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index c000457..3ec389f 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -379,6 +379,14 @@ void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform Q_ASSERT(positions.size() == glyphs_out.size()); } +void QFontEngine::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing) +{ + glyph_metrics_t gi = boundingBox(glyph); + if (leftBearing != 0) + *leftBearing = gi.x.toReal(); + if (rightBearing != 0) + *rightBearing = (gi.xoff - gi.x - gi.width).toReal(); +} glyph_metrics_t QFontEngine::tightBoundingBox(const QGlyphLayout &glyphs) { @@ -1385,6 +1393,12 @@ glyph_metrics_t QFontEngineMulti::boundingBox(const QGlyphLayout &glyphs) return overall; } +void QFontEngineMulti::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing) +{ + int which = highByte(glyph); + engine(which)->getGlyphBearings(stripped(glyph), leftBearing, rightBearing); +} + void QFontEngineMulti::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) { diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 71ab5a5..e645caf 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -206,6 +206,8 @@ public: virtual qreal minLeftBearing() const { return qreal(); } virtual qreal minRightBearing() const { return qreal(); } + virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0); + virtual const char *name() const = 0; virtual bool canRender(const QChar *string, int len) = 0; @@ -374,6 +376,7 @@ public: virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const; virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const; virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags); + virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0); virtual QFixed ascent() const; virtual QFixed descent() const; diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp index 1a815d3..a133b48 100644 --- a/src/gui/text/qfontengine_win.cpp +++ b/src/gui/text/qfontengine_win.cpp @@ -649,6 +649,30 @@ static const ushort char_table[] = { static const int char_table_entries = sizeof(char_table)/sizeof(ushort); +void QFontEngineWin::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing) +{ + HDC hdc = shared_dc(); + SelectObject(hdc, hfont); + +#ifndef Q_WS_WINCE + if (ttf) +#endif + + { + ABC abcWidths; + GetCharABCWidthsI(hdc, glyph, 1, 0, &abcWidths); + if (leftBearing) + *leftBearing = abcWidths.abcA; + if (rightBearing) + *rightBearing = abcWidths.abcC; + } + +#ifndef Q_WS_WINCE + else { + QFontEngine::getGlyphBearings(glyph, leftBearing, rightBearing); + } +#endif +} qreal QFontEngineWin::minLeftBearing() const { diff --git a/src/gui/text/qfontengine_win_p.h b/src/gui/text/qfontengine_win_p.h index f9d8f8b..f19e48e 100644 --- a/src/gui/text/qfontengine_win_p.h +++ b/src/gui/text/qfontengine_win_p.h @@ -106,6 +106,8 @@ public: virtual QImage alphaMapForGlyph(glyph_t, const QTransform &xform); virtual QImage alphaRGBMapForGlyph(glyph_t t, int margin, const QTransform &xform); + virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0); + int getGlyphIndexes(const QChar *ch, int numChars, QGlyphLayout *glyphs, bool mirrored) const; void getCMap(); diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp index 41d0af1..44a18de 100644 --- a/src/gui/text/qfontmetrics.cpp +++ b/src/gui/text/qfontmetrics.cpp @@ -472,8 +472,9 @@ int QFontMetrics::leftBearing(QChar ch) const int nglyphs = 9; engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0); // ### can nglyphs != 1 happen at all? Not currently I think - glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]); - return qRound(gi.x); + qreal lb; + engine->getGlyphBearings(glyphs.glyphs[0], &lb); + return qRound(lb); } /*! @@ -506,8 +507,9 @@ int QFontMetrics::rightBearing(QChar ch) const int nglyphs = 9; engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0); // ### can nglyphs != 1 happen at all? Not currently I think - glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]); - return qRound(gi.xoff - gi.x - gi.width); + qreal rb; + engine->getGlyphBearings(glyphs.glyphs[0], 0, &rb); + return qRound(rb); } /*! @@ -1317,8 +1319,9 @@ qreal QFontMetricsF::leftBearing(QChar ch) const int nglyphs = 9; engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0); // ### can nglyphs != 1 happen at all? Not currently I think - glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]); - return gi.x.toReal(); + qreal lb; + engine->getGlyphBearings(glyphs.glyphs[0], &lb); + return lb; } /*! @@ -1351,8 +1354,10 @@ qreal QFontMetricsF::rightBearing(QChar ch) const int nglyphs = 9; engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0); // ### can nglyphs != 1 happen at all? Not currently I think - glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]); - return (gi.xoff - gi.x - gi.width).toReal(); + qreal rb; + engine->getGlyphBearings(glyphs.glyphs[0], 0, &rb); + return rb; + } /*! diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 204effa..3c0e85e 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1688,9 +1688,9 @@ namespace { if (currentPosition <= 0) return; - glyph_metrics_t gi = fontEngine->boundingBox(currentGlyph()); - if (gi.isValid()) - rightBearing = qMin(QFixed(), gi.xoff - gi.x - gi.width); + qreal rb; + fontEngine->getGlyphBearings(currentGlyph(), 0, &rb); + rightBearing = qMin(QFixed(), QFixed::fromReal(rb)); } inline void resetRightBearing() -- cgit v0.12 From 7a9d7a7ad225589d8815f91e07228a0beb74465b Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Thu, 18 Mar 2010 11:57:58 +0100 Subject: Stabilize taskQTBUG_7863_paintIntoCacheWithTransparentParts auto-test. --- tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 34 +++++++++++++++--------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index 9cd86a6..43ce46d 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -4355,7 +4355,8 @@ void tst_QGraphicsScene::taskQT657_paintIntoCacheWithTransparentParts() w->setGeometry(0, 0, 50, 50); QGraphicsScene *scene = new QGraphicsScene(); - QGraphicsView *view = new QGraphicsView(scene); + CustomView *view = new CustomView; + view->setScene(scene); QGraphicsProxyWidget *proxy = scene->addWidget(w); proxy->setCacheMode(QGraphicsItem::DeviceCoordinateCache); @@ -4363,13 +4364,14 @@ void tst_QGraphicsScene::taskQT657_paintIntoCacheWithTransparentParts() view->show(); QTest::qWaitForWindowShown(view); - w->update(10, 10, 10, 10); + view->repaints = 0; + proxy->update(10, 10, 10, 10); QTest::qWait(50); + QTRY_VERIFY(view->repaints > 0); QPixmap pix; QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(proxy); - QPixmapCache::Key key = itemp->extraItemCache()->deviceData.value(view->viewport()).key; - QVERIFY(QPixmapCache::find(key, &pix)); + QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->deviceData.value(view->viewport()).key, &pix)); QTransform t = proxy->sceneTransform(); // Map from scene coordinates to pixmap coordinates. @@ -4399,7 +4401,8 @@ void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts() rectItem->setParentItem(backItem); QGraphicsScene *scene = new QGraphicsScene(); - QGraphicsView *view = new QGraphicsView(scene); + CustomView *view = new CustomView; + view->setScene(scene); scene->addItem(backItem); rectItem->setCacheMode(QGraphicsItem::DeviceCoordinateCache); @@ -4407,13 +4410,14 @@ void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts() view->show(); QTest::qWaitForWindowShown(view); + view->repaints = 0; rectItem->update(10, 10, 10, 10); QTest::qWait(50); + QTRY_VERIFY(view->repaints > 0); QPixmap pix; QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem); - QPixmapCache::Key key = itemp->extraItemCache()->deviceData.value(view->viewport()).key; - QVERIFY(QPixmapCache::find(key, &pix)); + QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->deviceData.value(view->viewport()).key, &pix)); QTransform t = rectItem->sceneTransform(); // Map from scene coordinates to pixmap coordinates. @@ -4439,7 +4443,8 @@ void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts() rectItem->setBrush(QColor(0, 0, 255)); QGraphicsScene *scene = new QGraphicsScene(); - QGraphicsView *view = new QGraphicsView(scene); + CustomView *view = new CustomView; + view->setScene(scene); scene->addItem(rectItem); rectItem->setCacheMode(QGraphicsItem::ItemCoordinateCache); @@ -4447,13 +4452,14 @@ void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts() view->show(); QTest::qWaitForWindowShown(view); + view->repaints = 0; rectItem->update(10, 10, 10, 10); QTest::qWait(50); + QTRY_VERIFY(view->repaints > 0); QPixmap pix; QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem); - QPixmapCache::Key key = itemp->extraItemCache()->key; - QVERIFY(QPixmapCache::find(key, &pix)); + QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->key, &pix)); QTransform t = rectItem->sceneTransform(); // Map from scene coordinates to pixmap coordinates. @@ -4478,7 +4484,8 @@ void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts() rectItem->setBrush(QColor(0, 0, 255, 125)); QGraphicsScene *scene = new QGraphicsScene(); - QGraphicsView *view = new QGraphicsView(scene); + CustomView *view = new CustomView; + view->setScene(scene); scene->addItem(rectItem); rectItem->setCacheMode(QGraphicsItem::ItemCoordinateCache); @@ -4486,13 +4493,14 @@ void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts() view->show(); QTest::qWaitForWindowShown(view); + view->repaints = 0; rectItem->update(10, 10, 10, 10); QTest::qWait(50); + QTRY_VERIFY(view->repaints > 0); QPixmap pix; QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem); - QPixmapCache::Key key = itemp->extraItemCache()->key; - QVERIFY(QPixmapCache::find(key, &pix)); + QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->key, &pix)); QTransform t = rectItem->sceneTransform(); // Map from scene coordinates to pixmap coordinates. -- cgit v0.12 From dc57f977ed8334530ef0da7e585eec7daef304eb Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 18 Mar 2010 17:44:27 +0100 Subject: fix PM_TabBarScrollButtonWidth pixel metric in Windows mobile style Task-number: QTBUG-8757 Reviewed-by: thartman --- src/gui/styles/qwindowsmobilestyle.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/gui/styles/qwindowsmobilestyle.cpp b/src/gui/styles/qwindowsmobilestyle.cpp index 6e77409..a5da038 100644 --- a/src/gui/styles/qwindowsmobilestyle.cpp +++ b/src/gui/styles/qwindowsmobilestyle.cpp @@ -6949,10 +6949,11 @@ int QWindowsMobileStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, co case PM_SliderThickness: ret = d->doubleControls ? windowsMobileSliderThickness * 2: windowsMobileSliderThickness; break; - case PM_TabBarScrollButtonWidth: - ret = d->doubleControls ? 14 * 2 : 18; - case PM_CheckBoxLabelSpacing: - case PM_RadioButtonLabelSpacing: + case PM_TabBarScrollButtonWidth: + ret = d->doubleControls ? 14 * 2 : 18; + break; + case PM_CheckBoxLabelSpacing: + case PM_RadioButtonLabelSpacing: ret = d->doubleControls ? 6 * 2 : 6; break; // Returns the number of pixels to use for the business part of the -- cgit v0.12 From 78e1a866ba5d594233db80f7aab88331db237d3a Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Wed, 17 Mar 2010 01:29:17 +0100 Subject: Implement Q_PRIVATE_PROPERTY that allows you to declare properties where the read/write are in the d pointer. Works like Q_PRIVATE_SLOT. Reviewed-by:olivier Reviewed-by:akennedy Reviewed-by:warwick allison --- src/corelib/kernel/qobjectdefs.h | 2 ++ src/tools/moc/generator.cpp | 43 ++++++++++++++++++--------- src/tools/moc/keywords.cpp | 30 ++++++++++++++----- src/tools/moc/moc.cpp | 44 +++++++++++++++++++++++---- src/tools/moc/moc.h | 4 ++- src/tools/moc/token.cpp | 1 + src/tools/moc/token.h | 1 + src/tools/moc/util/generate_keywords.cpp | 2 +- tests/auto/moc/tst_moc.cpp | 51 ++++++++++++++++++++++++++++++++ 9 files changed, 150 insertions(+), 28 deletions(-) diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 8ed7f3f..f496354 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -78,6 +78,7 @@ class QString; #define Q_CLASSINFO(name, value) #define Q_INTERFACES(x) #define Q_PROPERTY(text) +#define Q_PRIVATE_PROPERTY(d, text) #define Q_OVERRIDE(text) #define Q_ENUMS(x) #define Q_FLAGS(x) @@ -178,6 +179,7 @@ private: #define Q_CLASSINFO(name, value) Q_CLASSINFO(name, value) #define Q_INTERFACES(x) Q_INTERFACES(x) #define Q_PROPERTY(text) Q_PROPERTY(text) +#define Q_PRIVATE_PROPERTY(d, text) Q_PRIVATE_PROPERTY(d, text) #define Q_OVERRIDE(text) Q_OVERRIDE(text) #define Q_ENUMS(x) Q_ENUMS(x) #define Q_FLAGS(x) Q_FLAGS(x) diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 982d95f5..ff8029b 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -738,18 +738,23 @@ void Generator::generateMetacall() const PropertyDef &p = cdef->propertyList.at(propindex); if (p.read.isEmpty()) continue; + QByteArray prefix; + if (p.inPrivateClass.size()) { + prefix = p.inPrivateClass; + prefix.append("->"); + } if (p.gspec == PropertyDef::PointerSpec) - fprintf(out, " case %d: _a[0] = const_cast(reinterpret_cast(%s())); break;\n", - propindex, p.read.constData()); + fprintf(out, " case %d: _a[0] = const_cast(reinterpret_cast(%s%s())); break;\n", + propindex, prefix.constData(), p.read.constData()); else if (p.gspec == PropertyDef::ReferenceSpec) - fprintf(out, " case %d: _a[0] = const_cast(reinterpret_cast(&%s())); break;\n", - propindex, p.read.constData()); + fprintf(out, " case %d: _a[0] = const_cast(reinterpret_cast(&%s%s())); break;\n", + propindex, prefix.constData(), p.read.constData()); else if (cdef->enumDeclarations.value(p.type, false)) - fprintf(out, " case %d: *reinterpret_cast(_v) = QFlag(%s()); break;\n", - propindex, p.read.constData()); + fprintf(out, " case %d: *reinterpret_cast(_v) = QFlag(%s%s()); break;\n", + propindex, prefix.constData(), p.read.constData()); else - fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s(); break;\n", - propindex, p.type.constData(), p.read.constData()); + fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s(); break;\n", + propindex, p.type.constData(), prefix.constData(), p.read.constData()); } fprintf(out, " }\n"); } @@ -768,12 +773,17 @@ void Generator::generateMetacall() const PropertyDef &p = cdef->propertyList.at(propindex); if (p.write.isEmpty()) continue; + QByteArray prefix; + if (p.inPrivateClass.size()) { + prefix = p.inPrivateClass; + prefix.append("->"); + } if (cdef->enumDeclarations.value(p.type, false)) { - fprintf(out, " case %d: %s(QFlag(*reinterpret_cast(_v))); break;\n", - propindex, p.write.constData()); + fprintf(out, " case %d: %s%s(QFlag(*reinterpret_cast(_v))); break;\n", + propindex, prefix.constData(), p.write.constData()); } else { - fprintf(out, " case %d: %s(*reinterpret_cast< %s*>(_v)); break;\n", - propindex, p.write.constData(), p.type.constData()); + fprintf(out, " case %d: %s%s(*reinterpret_cast< %s*>(_v)); break;\n", + propindex, prefix.constData(), p.write.constData(), p.type.constData()); } } fprintf(out, " }\n"); @@ -791,8 +801,13 @@ void Generator::generateMetacall() const PropertyDef &p = cdef->propertyList.at(propindex); if (!p.reset.endsWith(')')) continue; - fprintf(out, " case %d: %s; break;\n", - propindex, p.reset.constData()); + QByteArray prefix; + if (p.inPrivateClass.size()) { + prefix = p.inPrivateClass; + prefix.append("->"); + } + fprintf(out, " case %d: %s%s; break;\n", + propindex, prefix.constData(), p.reset.constData()); } fprintf(out, " }\n"); } diff --git a/src/tools/moc/keywords.cpp b/src/tools/moc/keywords.cpp index abc6be0..df1ba0d 100644 --- a/src/tools/moc/keywords.cpp +++ b/src/tools/moc/keywords.cpp @@ -43,12 +43,12 @@ // DO NOT EDIT. static const short keyword_trans[][128] = { - {0,0,0,0,0,0,0,0,0,525,522,0,0,0,0,0, + {0,0,0,0,0,0,0,0,0,533,530,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 525,252,523,526,0,38,239,524,25,26,236,234,30,235,27,237, + 533,252,531,534,0,38,239,532,25,26,236,234,30,235,27,237, 22,22,22,22,22,22,22,22,22,22,34,41,23,39,24,43, 0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,21,8,8,8,8,8,8,8,8,8,31,527,32,238,8, + 8,21,8,8,8,8,8,8,8,8,8,31,535,32,238,8, 0,1,2,3,4,5,6,7,8,9,8,8,10,11,12,13, 14,8,15,16,17,18,19,20,8,8,8,36,245,37,248,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -190,7 +190,7 @@ static const short keyword_trans[][128] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,42,0,0,0,28,0, - 530,530,530,530,530,530,530,530,530,530,0,0,0,0,0,0, + 538,538,538,538,538,538,538,538,538,538,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -349,7 +349,7 @@ static const short keyword_trans[][128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,529,0,0,0,0,528, + 0,0,0,0,0,0,0,0,0,0,537,0,0,0,0,536, 0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -430,6 +430,14 @@ static const short keyword_trans[][128] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 522,0,0,481,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,497,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,486, @@ -925,12 +933,12 @@ static const struct {CHARACTER, 0, 84, 478, CHARACTER}, {CHARACTER, 0, 69, 479, CHARACTER}, {CHARACTER, 0, 95, 480, CHARACTER}, - {CHARACTER, 0, 83, 481, CHARACTER}, + {CHARACTER, 48, 0, 0, CHARACTER}, {CHARACTER, 0, 76, 482, CHARACTER}, {CHARACTER, 0, 79, 483, CHARACTER}, {CHARACTER, 0, 84, 484, CHARACTER}, {Q_PRIVATE_SLOT_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 48, 0, 0, CHARACTER}, + {CHARACTER, 49, 0, 0, CHARACTER}, {CHARACTER, 0, 77, 487, CHARACTER}, {CHARACTER, 0, 79, 488, CHARACTER}, {CHARACTER, 0, 67, 489, CHARACTER}, @@ -967,6 +975,14 @@ static const struct {CHARACTER, 0, 76, 520, CHARACTER}, {CHARACTER, 0, 69, 521, CHARACTER}, {Q_SCRIPTABLE_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 82, 523, CHARACTER}, + {CHARACTER, 0, 79, 524, CHARACTER}, + {CHARACTER, 0, 80, 525, CHARACTER}, + {CHARACTER, 0, 69, 526, CHARACTER}, + {CHARACTER, 0, 82, 527, CHARACTER}, + {CHARACTER, 0, 84, 528, CHARACTER}, + {CHARACTER, 0, 89, 529, CHARACTER}, + {Q_PRIVATE_PROPERTY_TOKEN, 0, 0, 0, CHARACTER}, {NEWLINE, 0, 0, 0, NOTOKEN}, {QUOTE, 0, 0, 0, NOTOKEN}, {SINGLEQUOTE, 0, 0, 0, NOTOKEN}, diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 94ad56f..680b8a5 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -658,6 +658,9 @@ void Moc::parse() case Q_PRIVATE_SLOT_TOKEN: parseSlotInPrivate(&def, access); break; + case Q_PRIVATE_PROPERTY_TOKEN: + parsePrivateProperty(&def); + break; case ENUM: { EnumDef enumDef; if (parseEnum(&enumDef)) @@ -872,11 +875,8 @@ void Moc::parseSignals(ClassDef *def) } } - -void Moc::parseProperty(ClassDef *def) +void Moc::createPropertyDef(PropertyDef &propDef) { - next(LPAREN); - PropertyDef propDef; QByteArray type = parseType().name; if (type.isEmpty()) error(); @@ -964,7 +964,6 @@ void Moc::parseProperty(ClassDef *def) error(2); } } - next(RPAREN); if (propDef.read.isNull()) { QByteArray msg; msg += "Property declaration "; @@ -988,6 +987,41 @@ void Moc::parseProperty(ClassDef *def) propDef.constant = false; warning(msg.constData()); } +} + +void Moc::parseProperty(ClassDef *def) +{ + next(LPAREN); + PropertyDef propDef; + createPropertyDef(propDef); + next(RPAREN); + + + if(!propDef.notify.isEmpty()) + def->notifyableProperties++; + def->propertyList += propDef; +} + +void Moc::parsePrivateProperty(ClassDef *def) +{ + next(LPAREN); + PropertyDef propDef; + next(IDENTIFIER); + propDef.inPrivateClass = lexem(); + while (test(SCOPE)) { + propDef.inPrivateClass += lexem(); + next(IDENTIFIER); + propDef.inPrivateClass += lexem(); + } + // also allow void functions + if (test(LPAREN)) { + next(RPAREN); + propDef.inPrivateClass += "()"; + } + + next(COMMA); + + createPropertyDef(propDef); if(!propDef.notify.isEmpty()) def->notifyableProperties++; diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index 10abfc6..d365ed5 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -116,7 +116,7 @@ struct FunctionDef struct PropertyDef { PropertyDef():notifyId(-1), constant(false), final(false), gspec(ValueSpec){} - QByteArray name, type, read, write, reset, designable, scriptable, editable, stored, user, notify; + QByteArray name, type, read, write, reset, designable, scriptable, editable, stored, user, notify, inPrivateClass; int notifyId; bool constant; bool final; @@ -217,6 +217,7 @@ public: void parseSlots(ClassDef *def, FunctionDef::Access access); void parseSignals(ClassDef *def); void parseProperty(ClassDef *def); + void createPropertyDef(PropertyDef &def); void parseEnumOrFlag(ClassDef *def, bool isFlag); void parseFlag(ClassDef *def); void parseClassInfo(ClassDef *def); @@ -224,6 +225,7 @@ public: void parseDeclareInterface(); void parseDeclareMetatype(); void parseSlotInPrivate(ClassDef *def, FunctionDef::Access access); + void parsePrivateProperty(ClassDef *def); void parseFunctionArguments(FunctionDef *def); diff --git a/src/tools/moc/token.cpp b/src/tools/moc/token.cpp index 98307a1..3da9446 100644 --- a/src/tools/moc/token.cpp +++ b/src/tools/moc/token.cpp @@ -179,6 +179,7 @@ const char *tokenTypeName(Token t) case Q_SIGNAL_TOKEN: return "Q_SIGNAL_TOKEN"; case Q_SLOT_TOKEN: return "Q_SLOT_TOKEN"; case Q_PRIVATE_SLOT_TOKEN: return "Q_PRIVATE_SLOT_TOKEN"; + case Q_PRIVATE_PROPERTY_TOKEN: return "Q_PRIVATE_PROPERTY_TOKEN"; case SPECIAL_TREATMENT_MARK: return "SPECIAL_TREATMENT_MARK"; case MOC_INCLUDE_BEGIN: return "MOC_INCLUDE_BEGIN"; case MOC_INCLUDE_END: return "MOC_INCLUDE_END"; diff --git a/src/tools/moc/token.h b/src/tools/moc/token.h index 6b1ad7d..6ca3d84 100644 --- a/src/tools/moc/token.h +++ b/src/tools/moc/token.h @@ -185,6 +185,7 @@ enum Token { Q_QT3_SUPPORT_TOKEN, Q_INVOKABLE_TOKEN, Q_SCRIPTABLE_TOKEN, + Q_PRIVATE_PROPERTY_TOKEN, Q_META_TOKEN_END, SPECIAL_TREATMENT_MARK = Q_META_TOKEN_END, MOC_INCLUDE_BEGIN, diff --git a/src/tools/moc/util/generate_keywords.cpp b/src/tools/moc/util/generate_keywords.cpp index 0641b40..88f187d 100644 --- a/src/tools/moc/util/generate_keywords.cpp +++ b/src/tools/moc/util/generate_keywords.cpp @@ -248,7 +248,7 @@ static const Keyword keywords[] = { { "Q_SIGNAL", "Q_SIGNAL_TOKEN" }, { "Q_SLOT", "Q_SLOT_TOKEN" }, { "Q_SCRIPTABLE", "Q_SCRIPTABLE_TOKEN" }, - + { "Q_PRIVATE_PROPERTY", "Q_PRIVATE_PROPERTY_TOKEN" }, { "\n", "NEWLINE" }, { "\"", "QUOTE" }, { "\'", "SINGLEQUOTE" }, diff --git a/tests/auto/moc/tst_moc.cpp b/tests/auto/moc/tst_moc.cpp index fad4845..30c2721 100644 --- a/tests/auto/moc/tst_moc.cpp +++ b/tests/auto/moc/tst_moc.cpp @@ -484,6 +484,7 @@ private slots: void singleFunctionKeywordSignalAndSlot(); void templateGtGt(); void qprivateslots(); + void qprivateproperties(); void inlineSlotsWithThrowDeclaration(); void warnOnPropertyWithoutREAD(); void constructors(); @@ -1071,6 +1072,56 @@ void tst_Moc::qprivateslots() QVERIFY(mobj->indexOfMethod("method1()") != -1); //tast204730 } +class PrivatePropertyTest : public QObject +{ + Q_OBJECT + Q_PROPERTY(int foo READ foo WRITE setFoo); + Q_PRIVATE_PROPERTY(d, int bar READ bar WRITE setBar); + Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, int plop READ plop WRITE setPlop); + Q_PRIVATE_PROPERTY(PrivatePropertyTest::d_func(), int baz READ baz WRITE setBaz); + class MyDPointer { + public: + MyDPointer() : mBar(0), mPlop(0) {} + int bar() { return mBar ; } + void setBar(int value) { mBar = value; } + int plop() { return mPlop ; } + void setPlop(int value) { mPlop = value; } + int baz() { return mBaz ; } + void setBaz(int value) { mBaz = value; } + private: + int mBar; + int mPlop; + int mBaz; + }; +public: + PrivatePropertyTest() : mFoo(0), d (new MyDPointer) {} + int foo() { return mFoo ; } + void setFoo(int value) { mFoo = value; } + MyDPointer *d_func() {return d;} +private: + int mFoo; + MyDPointer *d; +}; + + +void tst_Moc::qprivateproperties() +{ + PrivatePropertyTest test; + + test.setProperty("foo", 1); + QCOMPARE(test.property("foo"), qVariantFromValue(1)); + + test.setProperty("bar", 2); + QCOMPARE(test.property("bar"), qVariantFromValue(2)); + + test.setProperty("plop", 3); + QCOMPARE(test.property("plop"), qVariantFromValue(3)); + + test.setProperty("baz", 4); + QCOMPARE(test.property("baz"), qVariantFromValue(4)); + +} + #include "task189996.h" void InlineSlotsWithThrowDeclaration::c() throw() {} -- cgit v0.12 From 79a02c86c445e50630bcae62a4505f212281ec8b Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Thu, 18 Mar 2010 03:10:34 +0100 Subject: Add NOTIFY to size property so QML bindings are working fine. Just add the notify + the signal. Task-number:QTBUG-8277 Reviewed-by:yoann --- src/gui/graphicsview/qgraphicswidget.cpp | 1 + src/gui/graphicsview/qgraphicswidget.h | 5 ++++- tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp | 4 +++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index 5e01785..b0a0ef0 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -391,6 +391,7 @@ void QGraphicsWidget::setGeometry(const QRectF &rect) QGraphicsSceneResizeEvent re; re.setOldSize(oldSize); re.setNewSize(newGeom.size()); + emit sizeChanged(); QApplication::sendEvent(this, &re); } } diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h index f1d382b..56b5f88 100644 --- a/src/gui/graphicsview/qgraphicswidget.h +++ b/src/gui/graphicsview/qgraphicswidget.h @@ -73,7 +73,7 @@ class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLay Q_PROPERTY(QPalette palette READ palette WRITE setPalette) Q_PROPERTY(QFont font READ font WRITE setFont) Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection RESET unsetLayoutDirection) - Q_PROPERTY(QSizeF size READ size WRITE resize) + Q_PROPERTY(QSizeF size READ size WRITE resize NOTIFY sizeChanged) Q_PROPERTY(QSizeF minimumSize READ minimumSize WRITE setMinimumSize) Q_PROPERTY(QSizeF preferredSize READ preferredSize WRITE setPreferredSize) Q_PROPERTY(QSizeF maximumSize READ maximumSize WRITE setMaximumSize) @@ -175,6 +175,9 @@ public: using QObject::children; #endif +Q_SIGNALS: + void sizeChanged(); + public Q_SLOTS: bool close(); diff --git a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp index 4a874be..91fcf50 100644 --- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp +++ b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp @@ -765,11 +765,13 @@ void tst_QGraphicsWidget::geometry() { SubQGraphicsWidget widget; QCOMPARE(widget.geometry(), QRectF(widget.pos(), widget.size())); - + QSignalSpy spy(&widget, SIGNAL(sizeChanged())); QFETCH(QPointF, pos); QFETCH(QSizeF, size); widget.setPos(pos); widget.resize(size); + if (!size.isNull()) + QCOMPARE(spy.count(), 1); QCOMPARE(widget.geometry(), QRectF(pos, size)); } -- cgit v0.12 From 13bccd4ade76dd8a9c1cc067cc2b8da69c11def2 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Fri, 19 Mar 2010 06:25:35 +0100 Subject: Better handling for NOTIFY in QGraphicsWidget regarding geometry changes We bundle the size and the geometry into the same NOTIFY signal. Reviewed-by:akennedy --- src/gui/graphicsview/qgraphicswidget.cpp | 3 +-- src/gui/graphicsview/qgraphicswidget.h | 7 +++---- tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index b0a0ef0..f42fe4f 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -384,14 +384,13 @@ void QGraphicsWidget::setGeometry(const QRectF &rect) } QSizeF oldSize = size(); QGraphicsLayoutItem::setGeometry(newGeom); - + emit geometryChanged(); // Send resize event bool resized = newGeom.size() != oldSize; if (resized) { QGraphicsSceneResizeEvent re; re.setOldSize(oldSize); re.setNewSize(newGeom.size()); - emit sizeChanged(); QApplication::sendEvent(this, &re); } } diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h index 56b5f88..468a134 100644 --- a/src/gui/graphicsview/qgraphicswidget.h +++ b/src/gui/graphicsview/qgraphicswidget.h @@ -73,7 +73,7 @@ class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLay Q_PROPERTY(QPalette palette READ palette WRITE setPalette) Q_PROPERTY(QFont font READ font WRITE setFont) Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection RESET unsetLayoutDirection) - Q_PROPERTY(QSizeF size READ size WRITE resize NOTIFY sizeChanged) + Q_PROPERTY(QSizeF size READ size WRITE resize NOTIFY geometryChanged) Q_PROPERTY(QSizeF minimumSize READ minimumSize WRITE setMinimumSize) Q_PROPERTY(QSizeF preferredSize READ preferredSize WRITE setPreferredSize) Q_PROPERTY(QSizeF maximumSize READ maximumSize WRITE setMaximumSize) @@ -81,11 +81,10 @@ class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLay Q_PROPERTY(Qt::FocusPolicy focusPolicy READ focusPolicy WRITE setFocusPolicy) Q_PROPERTY(Qt::WindowFlags windowFlags READ windowFlags WRITE setWindowFlags) Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle) - Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry) + Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry NOTIFY geometryChanged) public: QGraphicsWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0); ~QGraphicsWidget(); - QGraphicsLayout *layout() const; void setLayout(QGraphicsLayout *layout); void adjustSize(); @@ -176,7 +175,7 @@ public: #endif Q_SIGNALS: - void sizeChanged(); + void geometryChanged(); public Q_SLOTS: bool close(); diff --git a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp index 91fcf50..0d1ad9e 100644 --- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp +++ b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp @@ -765,7 +765,7 @@ void tst_QGraphicsWidget::geometry() { SubQGraphicsWidget widget; QCOMPARE(widget.geometry(), QRectF(widget.pos(), widget.size())); - QSignalSpy spy(&widget, SIGNAL(sizeChanged())); + QSignalSpy spy(&widget, SIGNAL(geometryChanged())); QFETCH(QPointF, pos); QFETCH(QSizeF, size); widget.setPos(pos); -- cgit v0.12 From 3b45cff46eefcbe341f2e1adc3e864229c217226 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 19 Mar 2010 11:01:23 +0100 Subject: stabilize tst_QAccessibility::comboBoxTest --- tests/auto/qaccessibility/tst_qaccessibility.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/auto/qaccessibility/tst_qaccessibility.cpp b/tests/auto/qaccessibility/tst_qaccessibility.cpp index 133cb33..e5a332a 100644 --- a/tests/auto/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/qaccessibility/tst_qaccessibility.cpp @@ -3923,9 +3923,8 @@ void tst_QAccessibility::comboBoxTest() acc = QAccessible::queryAccessibleInterface(cb); - QRect accRect = acc->rect(0); for (int i = 1; i < acc->childCount(); ++i) { - QVERIFY(accRect.contains(acc->rect(i))); + QTRY_VERIFY(acc->rect(0).contains(acc->rect(i))); } QCOMPARE(acc->doAction(QAccessible::Press, 2), true); QTest::qWait(400); -- cgit v0.12 From 725c2c29c192349016b1332824a7716bbb992f31 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 19 Mar 2010 11:24:56 +0100 Subject: Revert "Optimize getting bearings of a glyph on Windows for true type fonts" This reverts commit 1ebeb971d3382aec0fff927ce2d6ea7b0452584f. This broke tst_qlistview::wordWrap in QWS --- src/gui/text/qfontengine.cpp | 14 -------------- src/gui/text/qfontengine_p.h | 3 --- src/gui/text/qfontengine_win.cpp | 24 ------------------------ src/gui/text/qfontengine_win_p.h | 2 -- src/gui/text/qfontmetrics.cpp | 21 ++++++++------------- src/gui/text/qtextlayout.cpp | 6 +++--- 6 files changed, 11 insertions(+), 59 deletions(-) diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 3ec389f..c000457 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -379,14 +379,6 @@ void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform Q_ASSERT(positions.size() == glyphs_out.size()); } -void QFontEngine::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing) -{ - glyph_metrics_t gi = boundingBox(glyph); - if (leftBearing != 0) - *leftBearing = gi.x.toReal(); - if (rightBearing != 0) - *rightBearing = (gi.xoff - gi.x - gi.width).toReal(); -} glyph_metrics_t QFontEngine::tightBoundingBox(const QGlyphLayout &glyphs) { @@ -1393,12 +1385,6 @@ glyph_metrics_t QFontEngineMulti::boundingBox(const QGlyphLayout &glyphs) return overall; } -void QFontEngineMulti::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing) -{ - int which = highByte(glyph); - engine(which)->getGlyphBearings(stripped(glyph), leftBearing, rightBearing); -} - void QFontEngineMulti::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) { diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index e645caf..71ab5a5 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -206,8 +206,6 @@ public: virtual qreal minLeftBearing() const { return qreal(); } virtual qreal minRightBearing() const { return qreal(); } - virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0); - virtual const char *name() const = 0; virtual bool canRender(const QChar *string, int len) = 0; @@ -376,7 +374,6 @@ public: virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const; virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const; virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags); - virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0); virtual QFixed ascent() const; virtual QFixed descent() const; diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp index a133b48..1a815d3 100644 --- a/src/gui/text/qfontengine_win.cpp +++ b/src/gui/text/qfontengine_win.cpp @@ -649,30 +649,6 @@ static const ushort char_table[] = { static const int char_table_entries = sizeof(char_table)/sizeof(ushort); -void QFontEngineWin::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing) -{ - HDC hdc = shared_dc(); - SelectObject(hdc, hfont); - -#ifndef Q_WS_WINCE - if (ttf) -#endif - - { - ABC abcWidths; - GetCharABCWidthsI(hdc, glyph, 1, 0, &abcWidths); - if (leftBearing) - *leftBearing = abcWidths.abcA; - if (rightBearing) - *rightBearing = abcWidths.abcC; - } - -#ifndef Q_WS_WINCE - else { - QFontEngine::getGlyphBearings(glyph, leftBearing, rightBearing); - } -#endif -} qreal QFontEngineWin::minLeftBearing() const { diff --git a/src/gui/text/qfontengine_win_p.h b/src/gui/text/qfontengine_win_p.h index f19e48e..f9d8f8b 100644 --- a/src/gui/text/qfontengine_win_p.h +++ b/src/gui/text/qfontengine_win_p.h @@ -106,8 +106,6 @@ public: virtual QImage alphaMapForGlyph(glyph_t, const QTransform &xform); virtual QImage alphaRGBMapForGlyph(glyph_t t, int margin, const QTransform &xform); - virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0); - int getGlyphIndexes(const QChar *ch, int numChars, QGlyphLayout *glyphs, bool mirrored) const; void getCMap(); diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp index 44a18de..41d0af1 100644 --- a/src/gui/text/qfontmetrics.cpp +++ b/src/gui/text/qfontmetrics.cpp @@ -472,9 +472,8 @@ int QFontMetrics::leftBearing(QChar ch) const int nglyphs = 9; engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0); // ### can nglyphs != 1 happen at all? Not currently I think - qreal lb; - engine->getGlyphBearings(glyphs.glyphs[0], &lb); - return qRound(lb); + glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]); + return qRound(gi.x); } /*! @@ -507,9 +506,8 @@ int QFontMetrics::rightBearing(QChar ch) const int nglyphs = 9; engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0); // ### can nglyphs != 1 happen at all? Not currently I think - qreal rb; - engine->getGlyphBearings(glyphs.glyphs[0], 0, &rb); - return qRound(rb); + glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]); + return qRound(gi.xoff - gi.x - gi.width); } /*! @@ -1319,9 +1317,8 @@ qreal QFontMetricsF::leftBearing(QChar ch) const int nglyphs = 9; engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0); // ### can nglyphs != 1 happen at all? Not currently I think - qreal lb; - engine->getGlyphBearings(glyphs.glyphs[0], &lb); - return lb; + glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]); + return gi.x.toReal(); } /*! @@ -1354,10 +1351,8 @@ qreal QFontMetricsF::rightBearing(QChar ch) const int nglyphs = 9; engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0); // ### can nglyphs != 1 happen at all? Not currently I think - qreal rb; - engine->getGlyphBearings(glyphs.glyphs[0], 0, &rb); - return rb; - + glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]); + return (gi.xoff - gi.x - gi.width).toReal(); } /*! diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 3c0e85e..204effa 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1688,9 +1688,9 @@ namespace { if (currentPosition <= 0) return; - qreal rb; - fontEngine->getGlyphBearings(currentGlyph(), 0, &rb); - rightBearing = qMin(QFixed(), QFixed::fromReal(rb)); + glyph_metrics_t gi = fontEngine->boundingBox(currentGlyph()); + if (gi.isValid()) + rightBearing = qMin(QFixed(), gi.xoff - gi.x - gi.width); } inline void resetRightBearing() -- cgit v0.12 From 5ec83155359553d3e5df230a4aca22eaa1066fc7 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Fri, 19 Mar 2010 13:13:09 +0100 Subject: fix QTabBar scroll button arrow position in Windows mobile style Task-number: QTBUG-8757 Reviewed-by: thartman --- src/gui/styles/qwindowsmobilestyle.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/gui/styles/qwindowsmobilestyle.cpp b/src/gui/styles/qwindowsmobilestyle.cpp index a5da038..5f939d0 100644 --- a/src/gui/styles/qwindowsmobilestyle.cpp +++ b/src/gui/styles/qwindowsmobilestyle.cpp @@ -5076,6 +5076,10 @@ void QWindowsMobileStyle::drawPrimitive(PrimitiveElement element, const QStyleOp color = option->palette.buttonText().color(); QImage image; int xoffset, yoffset; + bool isTabBarArrow = widget && widget->parent() + && widget->inherits("QToolButton") + && widget->parent()->inherits("QTabBar"); + switch (element) { case PE_IndicatorArrowUp: image = d->imageArrowUp; @@ -5090,12 +5094,12 @@ void QWindowsMobileStyle::drawPrimitive(PrimitiveElement element, const QStyleOp case PE_IndicatorArrowLeft: image = d->imageArrowLeft; xoffset = 8; - yoffset = 2; + yoffset = isTabBarArrow ? 12 : 2; break; case PE_IndicatorArrowRight: image = d->imageArrowRight; xoffset = 8; - yoffset = 2; + yoffset = isTabBarArrow ? 12 : 2; break; case PE_IndicatorArrowUpBig: image = d->imageArrowUpBig; -- cgit v0.12