From cad70d64d0bbada72a072ac7fdf461839db9d72a Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 3 May 2010 09:55:44 +0200 Subject: New class: QGlyphs Introduce an API to access glyph indexes in a font directly. A bug was discovered during this work, where different hinting flags in loadGlyph() and loadGlyphMetrics() would make the metrics in the two functions different, thus causing drawCachedGlyphs() (which uses loadGlyphMetrics() indirectly) to use different metrics than the standard drawTextItem() code path (which uses loadGlyph()). The bug was visible in the tst_QGlyphs::drawExistingGlyphs() test. Reviewed-by: Simon Hausmann --- src/gui/painting/qpainter.cpp | 52 +++-- src/gui/painting/qpainter.h | 3 + src/gui/painting/qpainter_p.h | 3 +- src/gui/text/qfont.h | 1 + src/gui/text/qfontengine.cpp | 18 ++ src/gui/text/qfontengine_ft.cpp | 9 + src/gui/text/qfontengine_mac.mm | 27 +++ src/gui/text/qfontengine_p.h | 9 +- src/gui/text/qglyphs.cpp | 199 +++++++++++++++++ src/gui/text/qglyphs.h | 96 +++++++++ src/gui/text/qglyphs_p.h | 84 ++++++++ src/gui/text/qtextlayout.cpp | 136 ++++++++++++ src/gui/text/qtextlayout.h | 5 + src/gui/text/text.pri | 7 +- tests/auto/qglyphs/qglyphs.pro | 5 + tests/auto/qglyphs/test.ttf | Bin 0 -> 3712 bytes tests/auto/qglyphs/tst_qglyphs.cpp | 431 +++++++++++++++++++++++++++++++++++++ 17 files changed, 1069 insertions(+), 16 deletions(-) create mode 100644 src/gui/text/qglyphs.cpp create mode 100644 src/gui/text/qglyphs.h create mode 100644 src/gui/text/qglyphs_p.h create mode 100644 tests/auto/qglyphs/qglyphs.pro create mode 100644 tests/auto/qglyphs/test.ttf create mode 100644 tests/auto/qglyphs/tst_qglyphs.cpp diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index dd3584a..cb56ac8 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -61,6 +61,8 @@ #include "qstyle.h" #include "qthread.h" #include "qvarlengtharray.h" +#include "qstatictext.h" +#include "qglyphs.h" #include #include @@ -70,8 +72,8 @@ #include #include #include -#include #include +#include QT_BEGIN_NAMESPACE @@ -5704,16 +5706,47 @@ void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QR d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags); } +/*! + Draws the glyphs represented by \a glyphs at \a position. The \a position gives the + edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font + selected on \a glyphs and at offsets given by the positions in \a glyphs. + + \since 4.8 + + \sa QGlyphs::setFont(), QGlyphs::setPositions(), QGlyphs::setGlyphIndexes() +*/ +void QPainter::drawGlyphs(const QPointF &position, const QGlyphs &glyphs) +{ + Q_D(QPainter); + + QFont oldFont = d->state->font; + d->state->font = glyphs.font(); + + QVector glyphIndexes = glyphs.glyphIndexes(); + QVector glyphPositions = glyphs.positions(); + + int count = qMin(glyphIndexes.size(), glyphPositions.size()); + QVarLengthArray fixedPointPositions(count); + for (int i=0; idrawGlyphs(glyphIndexes.data(), fixedPointPositions.data(), count); + + d->state->font = oldFont; +} void qt_draw_glyphs(QPainter *painter, const quint32 *glyphArray, const QPointF *positionArray, int glyphCount) -{ +{ + QVarLengthArray positions(glyphCount); + for (int i=0; idrawGlyphs(glyphArray, positionArray, glyphCount); + painter_d->drawGlyphs(const_cast(glyphArray), positions.data(), glyphCount); } -void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *positionArray, - int glyphCount) +void QPainterPrivate::drawGlyphs(quint32 *glyphArray, QFixedPoint *positions, int glyphCount) { updateState(state); @@ -5729,11 +5762,6 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit fontEngine = static_cast(fontEngine)->engine(engineIdx); } - QVarLengthArray positions; - for (int i=0; i(const_cast(glyphArray)); - staticTextItem.glyphPositions = positions.data(); + staticTextItem.glyphPositions = positions; extended->drawStaticTextItem(&staticTextItem); } else { @@ -5759,7 +5787,7 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit textItem.glyphs.numGlyphs = glyphCount; textItem.glyphs.glyphs = reinterpret_cast(const_cast(glyphArray)); - textItem.glyphs.offsets = positions.data(); + textItem.glyphs.offsets = positions; textItem.glyphs.advances_x = advances.data(); textItem.glyphs.advances_y = advances.data(); textItem.glyphs.justifications = glyphJustifications.data(); diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index edfb67e..85751a9 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -79,6 +79,7 @@ class QTextItem; class QMatrix; class QTransform; class QStaticText; +class QGlyphs; class QPainterPrivateDeleter; @@ -396,6 +397,8 @@ public: void setLayoutDirection(Qt::LayoutDirection direction); Qt::LayoutDirection layoutDirection() const; + void drawGlyphs(const QPointF &position, const QGlyphs &glyphs); + void drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText); inline void drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText); inline void drawStaticText(int left, int top, const QStaticText &staticText); diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h index 9362dbe..a61f5ca 100644 --- a/src/gui/painting/qpainter_p.h +++ b/src/gui/painting/qpainter_p.h @@ -70,6 +70,7 @@ QT_BEGIN_NAMESPACE class QPaintEngine; class QEmulationPaintEngine; class QPaintEngineEx; +struct QFixedPoint; struct QTLWExtra; @@ -228,7 +229,7 @@ public: void draw_helper(const QPainterPath &path, DrawOperation operation = StrokeAndFillDraw); void drawStretchedGradient(const QPainterPath &path, DrawOperation operation); void drawOpaqueBackground(const QPainterPath &path, DrawOperation operation); - void drawGlyphs(const quint32 *glyphArray, const QPointF *positionArray, int glyphCount); + void drawGlyphs(quint32 *glyphArray, QFixedPoint *positionArray, int glyphCount); void updateMatrix(); void updateInvMatrix(); diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h index 6f62424..b0e405e 100644 --- a/src/gui/text/qfont.h +++ b/src/gui/text/qfont.h @@ -312,6 +312,7 @@ private: friend class QPainterReplayer; friend class QPaintBufferEngine; friend class QCommandLinkButtonPrivate; + friend class QFontEngine; #ifndef QT_NO_DATASTREAM friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QFont &); diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 194c5f3..2d95bae 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -242,6 +242,24 @@ glyph_metrics_t QFontEngine::boundingBox(glyph_t glyph, const QTransform &matrix return metrics; } +QFont QFontEngine::createExplicitFont() const +{ + return createExplicitFontWithName(fontDef.family); +} + +QFont QFontEngine::createExplicitFontWithName(const QString &familyName) const +{ + QFont font(familyName); + font.setStyleStrategy(QFont::NoFontMerging); + font.setWeight(fontDef.weight); + font.setItalic(fontDef.style == QFont::StyleItalic); + if (fontDef.pointSize < 0) + font.setPixelSize(fontDef.pixelSize); + else + font.setPointSizeF(fontDef.pointSize); + return font; +} + QFixed QFontEngine::xHeight() const { QGlyphLayoutArray<8> glyphs; diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 9056012..7376893 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -756,9 +756,18 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph return g; int load_flags = FT_LOAD_DEFAULT | default_load_flags; + int load_target = default_hint_style == HintLight + ? FT_LOAD_TARGET_LIGHT + : FT_LOAD_TARGET_NORMAL; + if (set->outline_drawing) load_flags = FT_LOAD_NO_BITMAP; + if (default_hint_style == HintNone) + load_flags |= FT_LOAD_NO_HINTING; + else + load_flags |= load_target; + // apply our matrix to this, but note that the metrics will not be affected by this. FT_Face face = lockFace(); FT_Matrix matrix = this->matrix; diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm index 3be6d28..c9b5655 100644 --- a/src/gui/text/qfontengine_mac.mm +++ b/src/gui/text/qfontengine_mac.mm @@ -607,6 +607,12 @@ void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *position } } +QFont QCoreTextFontEngine::createExplicitFont() const +{ + QString familyName = QCFString::toQString(CTFontCopyFamilyName(ctfont)); + return createExplicitFontWithName(familyName); +} + QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, int margin, bool aa) { const glyph_metrics_t br = boundingBox(glyph); @@ -1542,6 +1548,27 @@ static void addGlyphsToPathHelper(ATSUStyle style, glyph_t *glyphs, QFixedPoint DisposeATSCubicClosePathUPP(closePath); } +QFont QFontEngineMac::createExplicitFont() const +{ + FMFont fmFont = FMGetFontFromATSFontRef(fontID); + + FMFontFamily fmFamily; + FMFontStyle fmStyle; + QString familyName; + if (!FMGetFontFamilyInstanceFromFont(fmFont, &fmFamily, &fmStyle)) { + ATSFontFamilyRef familyRef = FMGetATSFontFamilyRefFromFontFamily(fmFamily); + QCFString cfFamilyName;; + ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &cfFamilyName); + familyName = cfFamilyName; + } else { + QCFString cfFontName; + ATSFontGetName(fontID, kATSOptionFlagsDefault, &cfFontName); + familyName = cfFontName; + } + + return createExplicitFontWithName(familyName); +} + void QFontEngineMac::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags) { diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 922acfb..d29ef45 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -173,6 +173,10 @@ public: #endif virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, QPainterPath *path, QTextItem::RenderFlags flags); + + /* Creates a QFont object to represent this particular QFontEngine */ + virtual QFont createExplicitFont() const; + void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags, QVarLengthArray &glyphs_out, QVarLengthArray &positions); @@ -252,6 +256,7 @@ public: int glyphFormat; protected: + QFont createExplicitFontWithName(const QString &familyName) const; static const QVector &grayPalette(); private: @@ -454,7 +459,7 @@ public: virtual QImage alphaRGBMapForGlyph(glyph_t, int margin, const QTransform &t); virtual qreal minRightBearing() const; virtual qreal minLeftBearing() const; - + virtual QFont createExplicitFont() const; private: QImage imageForGlyph(glyph_t glyph, int margin, bool colorful); @@ -520,6 +525,8 @@ public: virtual qreal maxCharWidth() const; virtual QFixed averageCharWidth() const; + virtual QFont createExplicitFont() const; + virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags); diff --git a/src/gui/text/qglyphs.cpp b/src/gui/text/qglyphs.cpp new file mode 100644 index 0000000..847646e --- /dev/null +++ b/src/gui/text/qglyphs.cpp @@ -0,0 +1,199 @@ +#include "qglyphs.h" +#include "qglyphs_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QGlyphs + \brief the QGlyphs class provides direct access to the internal glyphs in a font + \since 4.8 + + \ingroup text + \mainclass + + When Qt displays a string of text encoded in Unicode, it will first convert the Unicode points + into a list of glyph indexes and a list of positions based on one or more fonts. The Unicode + representation of the text and the QFont object will in this case serve as a convenient + abstraction that hides the details of what actually takes place when displaying the text + on-screen. For instance, by the time the text actually reaches the screen, it may be represented + by a set of fonts in addition to the one specified by the user, e.g. in case the originally + selected font did not support all the writing systems contained in the text. + + Under certain circumstances, it can be useful as an application developer to have more low-level + control over which glyphs in a specific font are drawn to the screen. This could for instance + be the case in applications that use an external font engine and text shaper together with Qt. + QGlyphs provides an interface to the raw data needed to get text on the screen. It + contains a list of glyph indexes, a position for each glyph and a font. + + It is the user's responsibility to ensure that the selected font actually contains the + provided glyph indexes. + + QTextLayout::glyphs() can be used to convert unicode encoded text into a list of QGlyphs + objects, and QPainter::drawGlyphs() can be used to draw the glyphs. +*/ + + +/*! + Constructs an empty QGlyphs object. +*/ +QGlyphs::QGlyphs() : d(new QGlyphsPrivate) +{ +} + +/*! + Constructs a QGlyphs object which is a copy of \a other. +*/ +QGlyphs::QGlyphs(const QGlyphs &other) +{ + d = other.d; +} + +/*! + Destroys the QGlyphs. +*/ +QGlyphs::~QGlyphs() +{ + // Required for QExplicitlySharedDataPointer +} + +/*! + \internal +*/ +void QGlyphs::detach() +{ + if (d->ref != 1) + d.detach(); +} + +/*! + Assigns \a other to this QGlyphs object. +*/ +QGlyphs &QGlyphs::operator=(const QGlyphs &other) +{ + d = other.d; + return *this; +} + +/*! + Compares \a other to this QGlyphs object. Returns true if the list of glyph indexes, + the list of positions and the font are all equal, otherwise returns false. +*/ +bool QGlyphs::operator==(const QGlyphs &other) const +{ + return ((d == other.d) + || (d->glyphIndexes == other.d->glyphIndexes + && d->glyphPositions == other.d->glyphPositions + && d->font == other.d->font)); +} + +/*! + Compares \a other to this QGlyphs object. Returns true if any of the list of glyph + indexes, the list of positions or the font are different, otherwise returns false. +*/ +bool QGlyphs::operator!=(const QGlyphs &other) const +{ + return !(*this == other); +} + +/*! + \internal + + Adds together the lists of glyph indexes and positions in \a other and this QGlyphs + object and returns the result. The font in the returned QGlyphs will be the same as in + this QGlyphs object. +*/ +QGlyphs QGlyphs::operator+(const QGlyphs &other) const +{ + QGlyphs ret(*this); + ret += other; + return ret; +} + +/*! + \internal + + Appends the glyph indexes and positions in \a other to this QGlyphs object and returns + a reference to the current object. +*/ +QGlyphs &QGlyphs::operator+=(const QGlyphs &other) +{ + detach(); + + d->glyphIndexes += other.d->glyphIndexes; + d->glyphPositions += other.d->glyphPositions; + + return *this; +} + +/*! + Returns the font selected for this QGlyphs object. + + \sa setFont() +*/ +QFont QGlyphs::font() const +{ + return d->font; +} + +/*! + Sets the font in which to look up the glyph indexes to \a font. This must be an explicitly + resolvable font which defines glyphs for the specified glyph indexes. + + \sa font(), setGlyphIndexes() +*/ +void QGlyphs::setFont(const QFont &font) +{ + detach(); + d->font = font; +} + +/*! + Returns the glyph indexes for this QGlyphs object. + + \sa setGlyphIndexes(), setPositions() +*/ +QVector QGlyphs::glyphIndexes() const +{ + return d->glyphIndexes; +} + +/*! + Set the glyph indexes for this QGlyphs object to \a glyphIndexes. The glyph indexes must + be valid for the selected font. +*/ +void QGlyphs::setGlyphIndexes(const QVector &glyphIndexes) +{ + detach(); + d->glyphIndexes = glyphIndexes; +} + +/*! + Returns the position of the edge of the baseline for each glyph in this set of glyph indexes. +*/ +QVector QGlyphs::positions() const +{ + return d->glyphPositions; +} + +/*! + Sets the positions of the edge of the baseline for each glyph in this set of glyph indexes to + \a positions. +*/ +void QGlyphs::setPositions(const QVector &positions) +{ + detach(); + d->glyphPositions = positions; +} + +/*! + Clears all data in the QGlyphs object. +*/ +void QGlyphs::clear() +{ + detach(); + d->glyphPositions = QVector(); + d->glyphIndexes = QVector(); + d->font = QFont(); +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qglyphs.h b/src/gui/text/qglyphs.h new file mode 100644 index 0000000..282ecb4 --- /dev/null +++ b/src/gui/text/qglyphs.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGLYPHS_H +#define QGLYPHS_H + +#include +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QGlyphsPrivate; +class Q_GUI_EXPORT QGlyphs +{ +public: + QGlyphs(); + QGlyphs(const QGlyphs &other); + ~QGlyphs(); + + QFont font() const; + void setFont(const QFont &font); + + QVector glyphIndexes() const; + void setGlyphIndexes(const QVector &glyphIndexes); + + QVector positions() const; + void setPositions(const QVector &positions); + + void clear(); + + QGlyphs &operator=(const QGlyphs &other); + bool operator==(const QGlyphs &other) const; + bool operator!=(const QGlyphs &other) const; + +private: + friend class QGlyphsPrivate; + friend class QTextLine; + + QGlyphs operator+(const QGlyphs &other) const; + QGlyphs &operator+=(const QGlyphs &other); + + void detach(); + QExplicitlySharedDataPointer d; + +}; + +QT_END_NAMESPACE + +QT_END_HEADER + + +#endif // QGLYPHS_H diff --git a/src/gui/text/qglyphs_p.h b/src/gui/text/qglyphs_p.h new file mode 100644 index 0000000..c39f5d0 --- /dev/null +++ b/src/gui/text/qglyphs_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGLYPHS_P_H +#define QGLYPHS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of internal files. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// + +#include +#include "qglyphs.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGlyphsPrivate: public QSharedData +{ +public: + QGlyphsPrivate() + { + } + + QGlyphsPrivate(const QGlyphsPrivate &other) + : QSharedData(other), glyphIndexes(other.glyphIndexes), glyphPositions(other.glyphPositions), font(other.font) + { + } + + QVector glyphIndexes; + QVector glyphPositions; + QFont font; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGLYPHS_P_H diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 412c909..b581969 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -52,6 +52,8 @@ #include "qtextformat_p.h" #include "qstyleoption.h" #include "qpainterpath.h" +#include "qglyphs.h" +#include "qglyphs_p.h" #include #include @@ -894,6 +896,7 @@ qreal QTextLayout::maximumWidth() const return d->maxWidth.toReal(); } + /*! \internal */ @@ -1106,6 +1109,24 @@ static inline QRectF clipIfValid(const QRectF &rect, const QRectF &clip) return clip.isValid() ? (rect & clip) : rect; } + +/*! + Returns the glyph indexes and positions for all glyphs in this QTextLayout. This is an + expensive function, and should not be called in a time sensitive context. + + \since 4.8 + + \sa draw(), QPainter::drawGlyphs() +*/ +QList QTextLayout::glyphs() const +{ + QList glyphs; + for (int i=0; ilines.size(); ++i) + glyphs += QTextLine(i, d).glyphs(); + + return glyphs; +} + /*! Draws the whole layout on the painter \a p at the position specified by \a pos. @@ -2135,6 +2156,121 @@ static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const Q } +namespace { + struct GlyphInfo + { + GlyphInfo(const QGlyphLayout &layout, const QPointF &position) + : glyphLayout(layout), itemPosition(position) + { + } + + QGlyphLayout glyphLayout; + QPointF itemPosition; + }; +} + +/*! + \internal + + Returns the glyph indexes and positions for all glyphs in this QTextLine. + + \since 4.8 + + \sa QTextLayout::glyphs() +*/ +QList QTextLine::glyphs() const +{ + const QScriptLine &line = eng->lines[i]; + + if (line.length == 0) + return QList(); + + QHash glyphLayoutHash; + + QTextLineItemIterator iterator(eng, i); + qreal y = line.y.toReal() + line.base().toReal(); + while (!iterator.atEnd()) { + QScriptItem &si = iterator.next(); + QPointF pos(iterator.x.toReal(), y); + + QFont font = eng->font(si); + QGlyphLayout glyphLayout = eng->shapedGlyphs(&si).mid(iterator.glyphsStart, + iterator.glyphsEnd - iterator.glyphsStart); + + if (glyphLayout.numGlyphs > 0) { + QFontEngine *mainFontEngine = font.d->engineForScript(si.analysis.script); + if (mainFontEngine->type() == QFontEngine::Multi) { + QFontEngineMulti *multiFontEngine = static_cast(mainFontEngine); + int start = 0; + int end; + int which = glyphLayout.glyphs[0] >> 24; + for (end = 0; end < glyphLayout.numGlyphs; ++end) { + const int e = glyphLayout.glyphs[end] >> 24; + if (e == which) + continue; + + QGlyphLayout subLayout = glyphLayout.mid(start, end - start); + glyphLayoutHash.insertMulti(multiFontEngine->engine(which), + GlyphInfo(subLayout, pos)); + + start = end; + which = e; + } + + QGlyphLayout subLayout = glyphLayout.mid(start, end - start); + glyphLayoutHash.insertMulti(multiFontEngine->engine(which), + GlyphInfo(subLayout, pos)); + + } else { + glyphLayoutHash.insertMulti(mainFontEngine, + GlyphInfo(glyphLayout, pos)); + } + } + } + + QHash glyphsHash; + + QList keys = glyphLayoutHash.uniqueKeys(); + for (int i=0; icreateExplicitFont(); + + QList glyphLayouts = glyphLayoutHash.values(fontEngine); + for (int j=0; j glyphsArray; + QVarLengthArray positionsArray; + + fontEngine->getGlyphPositions(glyphLayout, QTransform(), 0, glyphsArray, positionsArray); + Q_ASSERT(glyphsArray.size() == positionsArray.size()); + + QVector glyphs; + QVector positions; + for (int i=0; i #include #include +#include QT_BEGIN_HEADER @@ -166,6 +167,8 @@ public: qreal minimumWidth() const; qreal maximumWidth() const; + QList glyphs() const; + QTextEngine *engine() const { return d; } void setFlags(int flags); private: @@ -236,6 +239,8 @@ public: private: QTextLine(int line, QTextEngine *e) : i(line), eng(e) {} void layout_helper(int numGlyphs); + QList glyphs() const; + friend class QTextLayout; int i; QTextEngine *eng; diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri index 9ec3142..4e1e9fa 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -39,7 +39,9 @@ HEADERS += \ text/qzipwriter_p.h \ text/qtextodfwriter_p.h \ text/qstatictext_p.h \ - text/qstatictext.h + text/qstatictext.h \ + text/qglyphs.h \ + text/qglyphs_p.h SOURCES += \ text/qfont.cpp \ @@ -69,7 +71,8 @@ SOURCES += \ text/qcssparser.cpp \ text/qzip.cpp \ text/qtextodfwriter.cpp \ - text/qstatictext.cpp + text/qstatictext.cpp \ + text/qglyphs.cpp win32 { SOURCES += \ diff --git a/tests/auto/qglyphs/qglyphs.pro b/tests/auto/qglyphs/qglyphs.pro new file mode 100644 index 0000000..70920f0 --- /dev/null +++ b/tests/auto/qglyphs/qglyphs.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +QT = core gui + +SOURCES += \ + tst_qglyphs.cpp diff --git a/tests/auto/qglyphs/test.ttf b/tests/auto/qglyphs/test.ttf new file mode 100644 index 0000000..9043a57 Binary files /dev/null and b/tests/auto/qglyphs/test.ttf differ diff --git a/tests/auto/qglyphs/tst_qglyphs.cpp b/tests/auto/qglyphs/tst_qglyphs.cpp new file mode 100644 index 0000000..c906f10 --- /dev/null +++ b/tests/auto/qglyphs/tst_qglyphs.cpp @@ -0,0 +1,431 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include +#include +#include +#include + +//#define DEBUG_SAVE_IMAGE + +class tst_QGlyphs: public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + void cleanupTestCase(); + + void constructionAndDestruction(); + void copyConstructor(); + void assignment(); + void equalsOperator_data(); + void equalsOperator(); + void textLayoutGlyphIndexes(); + void drawExistingGlyphs(); + void drawNonExistentGlyphs(); + void drawMultiScriptText1(); + void drawMultiScriptText2(); + void detach(); + +private: + int m_testFontId; + QFont m_testFont; +}; + +Q_DECLARE_METATYPE(QGlyphs); + +void tst_QGlyphs::initTestCase() +{ + m_testFontId = QFontDatabase::addApplicationFont("test.ttf"); + QVERIFY(m_testFontId >= 0); + + m_testFont = QFont("QtsSpecialTestFont"); + + QCOMPARE(QFontInfo(m_testFont).family(), QString::fromLatin1("QtsSpecialTestFont")); +} + +void tst_QGlyphs::cleanupTestCase() +{ + QFontDatabase::removeApplicationFont(m_testFontId); +} + +void tst_QGlyphs::constructionAndDestruction() +{ + QGlyphs glyphIndexes; +} + +static QGlyphs make_dummy_indexes() +{ + QGlyphs glyphs; + + QVector glyphIndexes; + QVector positions; + QFont font; + font.setPointSize(18); + + glyphIndexes.append(1); + glyphIndexes.append(2); + glyphIndexes.append(3); + + positions.append(QPointF(1, 2)); + positions.append(QPointF(3, 4)); + positions.append(QPointF(5, 6)); + + glyphs.setFont(font); + glyphs.setGlyphIndexes(glyphIndexes); + glyphs.setPositions(positions); + + return glyphs; +} + +static QGlyphs make_dummy_indexes2() +{ + QGlyphs glyphs; + + QVector glyphIndexes; + QVector positions; + QFont font; + font.setPointSize(26); + + glyphIndexes.append(4); + glyphIndexes.append(5); + glyphIndexes.append(6); + + positions.append(QPointF(7, 8)); + positions.append(QPointF(9, 10)); + positions.append(QPointF(11, 12)); + + glyphs.setFont(font); + glyphs.setGlyphIndexes(glyphIndexes); + glyphs.setPositions(positions); + + return glyphs; +} + + +void tst_QGlyphs::copyConstructor() +{ + QGlyphs glyphs; + + { + QVector glyphIndexes; + QVector positions; + QFont font; + font.setPointSize(18); + + glyphIndexes.append(1); + glyphIndexes.append(2); + glyphIndexes.append(3); + + positions.append(QPointF(1, 2)); + positions.append(QPointF(3, 4)); + positions.append(QPointF(5, 6)); + + glyphs.setFont(font); + glyphs.setGlyphIndexes(glyphIndexes); + glyphs.setPositions(positions); + } + + QGlyphs otherGlyphs(glyphs); + QCOMPARE(otherGlyphs.font(), glyphs.font()); + QCOMPARE(glyphs.glyphIndexes(), otherGlyphs.glyphIndexes()); + QCOMPARE(glyphs.positions(), otherGlyphs.positions()); +} + +void tst_QGlyphs::assignment() +{ + QGlyphs glyphs(make_dummy_indexes()); + + QGlyphs otherGlyphs = glyphs; + QCOMPARE(otherGlyphs.font(), glyphs.font()); + QCOMPARE(glyphs.glyphIndexes(), otherGlyphs.glyphIndexes()); + QCOMPARE(glyphs.positions(), otherGlyphs.positions()); +} + +void tst_QGlyphs::equalsOperator_data() +{ + QTest::addColumn("one"); + QTest::addColumn("two"); + QTest::addColumn("equals"); + + QGlyphs one(make_dummy_indexes()); + QGlyphs two(make_dummy_indexes()); + + QTest::newRow("Identical") << one << two << true; + + { + QGlyphs busted(two); + + QVector positions = busted.positions(); + positions[2] += QPointF(1, 1); + busted.setPositions(positions); + + QTest::newRow("Different positions") << one << busted << false; + } + + { + QGlyphs busted(two); + QFont font = busted.font(); + font.setPointSize(font.pointSize() * 2); + busted.setFont(font); + + QTest::newRow("Different fonts") << one << busted << false; + } + + { + QGlyphs busted(two); + + QVector glyphIndexes = busted.glyphIndexes(); + glyphIndexes[2] += 1; + busted.setGlyphIndexes(glyphIndexes); + + QTest::newRow("Different glyph indexes") << one << busted << false; + } + +} + +void tst_QGlyphs::equalsOperator() +{ + QFETCH(QGlyphs, one); + QFETCH(QGlyphs, two); + QFETCH(bool, equals); + + QCOMPARE(one == two, equals); + QCOMPARE(one != two, !equals); +} + + +void tst_QGlyphs::textLayoutGlyphIndexes() +{ + QString s; + s.append(QLatin1Char('A')); + s.append(QChar(0xe000)); + + QTextLayout layout(s); + layout.setFont(m_testFont); + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + + QList listOfGlyphs = layout.glyphs(); + QCOMPARE(listOfGlyphs.size(), 1); + + QGlyphs glyphs = listOfGlyphs.at(0); + + QCOMPARE(glyphs.glyphIndexes().size(), 2); + QCOMPARE(glyphs.glyphIndexes().at(0), quint32(2)); + QCOMPARE(glyphs.glyphIndexes().at(1), quint32(1)); +} + +void tst_QGlyphs::drawExistingGlyphs() +{ + QImage textLayoutDraw(1000, 1000, QImage::Format_ARGB32); + QImage drawGlyphs(1000, 1000, QImage::Format_ARGB32); + + textLayoutDraw.fill(0xffffffff); + drawGlyphs.fill(0xffffffff); + + QString s; + s.append(QLatin1Char('A')); + s.append(QChar(0xe000)); + + QTextLayout layout(s); + layout.setFont(m_testFont); + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + + { + QPainter p(&textLayoutDraw); + layout.draw(&p, QPointF(50, 50)); + } + + QGlyphs glyphs = layout.glyphs().size() > 0 + ? layout.glyphs().at(0) + : QGlyphs(); + + { + QPainter p(&drawGlyphs); + p.drawGlyphs(QPointF(50, 50), glyphs); + } + +#if defined(DEBUG_SAVE_IMAGE) + textLayoutDraw.save("drawExistingGlyphs_textLayoutDraw.png"); + drawGlyphs.save("drawExistingGlyphs_drawGlyphIndexes.png"); +#endif + + QCOMPARE(textLayoutDraw, drawGlyphs); +} + +void tst_QGlyphs::drawNonExistentGlyphs() +{ + QVector glyphIndexes; + glyphIndexes.append(3); + + QVector glyphPositions; + glyphPositions.append(QPointF(0, 0)); + + QGlyphs glyphs; + glyphs.setGlyphIndexes(glyphIndexes); + glyphs.setPositions(glyphPositions); + glyphs.setFont(m_testFont); + + QImage image(1000, 1000, QImage::Format_ARGB32); + image.fill(0); + + QImage imageBefore = image; + { + QPainter p(&image); + p.drawGlyphs(QPointF(50, 50), glyphs); + } + +#if defined(DEBUG_SAVE_IMAGE) + image.save("drawNonExistentGlyphs.png"); +#endif + + QCOMPARE(image, imageBefore); // Should be unchanged +} + +void tst_QGlyphs::drawMultiScriptText1() +{ + QString text; + text += QChar(0x3131); // Hangul, Kiyeok + + QTextLayout textLayout(text); + textLayout.beginLayout(); + textLayout.createLine(); + textLayout.endLayout(); + + QImage textLayoutDraw(1000, 1000, QImage::Format_ARGB32); + textLayoutDraw.fill(0xffffffff); + + QImage drawGlyphs(1000, 1000, QImage::Format_ARGB32); + drawGlyphs.fill(0xffffffff); + + QList glyphsList = textLayout.glyphs(); + QCOMPARE(glyphsList.size(), 1); + + { + QPainter p(&textLayoutDraw); + textLayout.draw(&p, QPointF(50, 50)); + } + + { + QPainter p(&drawGlyphs); + foreach (QGlyphs glyphs, glyphsList) + p.drawGlyphs(QPointF(50, 50), glyphs); + } + +#if defined(DEBUG_SAVE_IMAGE) + textLayoutDraw.save("drawMultiScriptText1_textLayoutDraw.png"); + drawGlyphs.save("drawMultiScriptText1_drawGlyphIndexes.png"); +#endif + + QCOMPARE(drawGlyphs, textLayoutDraw); +} + + +void tst_QGlyphs::drawMultiScriptText2() +{ +#if defined(Q_WS_MAC) + QSKIP("Unstable because of QTBUG-11145", SkipAll); +#endif + + QString text; + text += QChar(0x0621); // Arabic, Hamza + text += QChar(0x3131); // Hangul, Kiyeok + + QTextLayout textLayout(text); + textLayout.beginLayout(); + textLayout.createLine(); + textLayout.endLayout(); + + QImage textLayoutDraw(1000, 1000, QImage::Format_ARGB32); + textLayoutDraw.fill(0xffffffff); + + QImage drawGlyphs(1000, 1000, QImage::Format_ARGB32); + drawGlyphs.fill(0xffffffff); + + QList glyphsList = textLayout.glyphs(); + QCOMPARE(glyphsList.size(), 2); + + { + QPainter p(&textLayoutDraw); + textLayout.draw(&p, QPointF(50, 50)); + } + + { + QPainter p(&drawGlyphs); + foreach (QGlyphs glyphs, glyphsList) + p.drawGlyphs(QPointF(50, 50), glyphs); + } + +#if defined(DEBUG_SAVE_IMAGE) + textLayoutDraw.save("drawMultiScriptText2_textLayoutDraw.png"); + drawGlyphs.save("drawMultiScriptText2_drawGlyphIndexes.png"); +#endif + + QCOMPARE(drawGlyphs, textLayoutDraw); +} + +void tst_QGlyphs::detach() +{ + QGlyphs glyphs; + + glyphs.setGlyphIndexes(QVector() << 1 << 2 << 3); + + QGlyphs otherGlyphs; + otherGlyphs = glyphs; + + QCOMPARE(otherGlyphs.glyphIndexes(), glyphs.glyphIndexes()); + + otherGlyphs.setGlyphIndexes(QVector() << 4 << 5 << 6); + + QCOMPARE(otherGlyphs.glyphIndexes(), QVector() << 4 << 5 << 6); + QCOMPARE(glyphs.glyphIndexes(), QVector() << 1 << 2 << 3); +} + +QTEST_MAIN(tst_QGlyphs) +#include "tst_qglyphs.moc" + -- cgit v0.12 From 3a3a3964c001112738890dde897a2f024baf8825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Arve=20S=C3=A6ther?= Date: Fri, 4 Jun 2010 10:36:03 +0200 Subject: Don't add the qmediaplayer.pro to the destination path of the sources. Casper observed that installing the demo created a folder called qmediaplayer.pro in the same folder as qmediaplayer.pro was located. Reviewed-by: Casper van Donderen --- demos/qmediaplayer/qmediaplayer.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/qmediaplayer/qmediaplayer.pro b/demos/qmediaplayer/qmediaplayer.pro index cfe3905..9407a81 100644 --- a/demos/qmediaplayer/qmediaplayer.pro +++ b/demos/qmediaplayer/qmediaplayer.pro @@ -17,7 +17,7 @@ HEADERS += mediaplayer.h target.path = $$[QT_INSTALL_DEMOS]/qmediaplayer sources.files = $$SOURCES $$HEADERS $$FORMS $$RESOURCES *.pro *.html *.doc images -sources.path = $$[QT_INSTALL_DEMOS]/qmediaplayer qmediaplayer.pro +sources.path = $$[QT_INSTALL_DEMOS]/qmediaplayer INSTALLS += target sources wince*{ -- cgit v0.12 From 397295f1a91c782f905374213b85ef1108c357e3 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 4 Jun 2010 11:10:47 +0200 Subject: Qt now really unloads plugins and libraries when exiting an app It also means that when creating a QPluginLoader or a QLibrary for a dynamic lib already loaded, isLoaded will return true immediately after the creation of the instance of QPluginLoader or QLibrary. Reviewed-By: Jan-Arve Saether --- src/corelib/plugin/qlibrary.cpp | 31 +++++++++++++--- src/corelib/plugin/qlibrary_p.h | 2 ++ src/corelib/plugin/qpluginloader.cpp | 8 ++--- src/gui/kernel/qapplication_win.cpp | 14 +++----- src/gui/kernel/qapplication_x11.cpp | 28 +++++++-------- src/gui/kernel/qdesktopwidget_win.cpp | 14 +++----- src/gui/kernel/qguifunctions_wince.cpp | 2 -- src/gui/widgets/qmenu_wince.cpp | 2 -- tests/auto/qlibrary/tst_qlibrary.cpp | 66 ++++++++++++++++++++++------------ 9 files changed, 97 insertions(+), 70 deletions(-) diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index ccde2b0..f6ae038 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -426,10 +426,14 @@ struct LibraryData { LibraryData() : settings(0) { } ~LibraryData() { delete settings; + foreach(QLibraryPrivate *lib, loadedLibs) { + lib->unload(); + } } QSettings *settings; LibraryMap libraryMap; + QSet loadedLibs; }; Q_GLOBAL_STATIC(LibraryData, libraryData) @@ -481,7 +485,18 @@ bool QLibraryPrivate::load() return true; if (fileName.isEmpty()) return false; - return load_sys(); + + bool ret = load_sys(); + if (ret) { + //when loading a library we add a reference to it so that the QLibraryPrivate won't get deleted + //this allows to unload the library at a later time + if (LibraryData *lib = libraryData()) { + lib->loadedLibs += this; + libraryRefCount.ref(); + } + } + + return ret; } bool QLibraryPrivate::unload() @@ -489,10 +504,16 @@ bool QLibraryPrivate::unload() if (!pHnd) return false; if (!libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to - if (instance) - delete instance(); + delete inst.data(); if (unload_sys()) { - instance = 0; + if (qt_debug_component()) + qWarning() << "QLibraryPrivate::unload succeeded on" << fileName; + //when the library is unloaded, we release the reference on it so that 'this' + //can get deleted + if (LibraryData *lib = libraryData()) { + if (lib->loadedLibs.remove(this)) + libraryRefCount.deref(); + } pHnd = 0; } } @@ -1126,7 +1147,7 @@ void QLibrary::setFileNameAndVersion(const QString &fileName, const QString &ver */ void *QLibrary::resolve(const char *symbol) { - if (!load()) + if (!isLoaded() && !load()) return 0; return d->resolve(symbol); } diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h index 02dc523..b73fce5 100644 --- a/src/corelib/plugin/qlibrary_p.h +++ b/src/corelib/plugin/qlibrary_p.h @@ -60,6 +60,7 @@ #include "QtCore/qpointer.h" #include "QtCore/qstringlist.h" #include "QtCore/qplugin.h" +#include "QtCore/qsharedpointer.h" #ifndef QT_NO_LIBRARY @@ -90,6 +91,7 @@ public: static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString()); + QWeakPointer inst; QtPluginInstanceFunction instance; uint qt_version; QString lastModified; diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp index b1d1ecc..9f322df 100644 --- a/src/corelib/plugin/qpluginloader.cpp +++ b/src/corelib/plugin/qpluginloader.cpp @@ -198,11 +198,11 @@ QPluginLoader::~QPluginLoader() */ QObject *QPluginLoader::instance() { - if (!load()) + if (!isLoaded() && !load()) return 0; - if (d->instance) - return d->instance(); - return 0; + if (!d->inst && d->instance) + d->inst = d->instance(); + return d->inst.data(); } /*! diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 60fc5e1..d2ce5ff 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -206,8 +206,6 @@ static void resolveAygLibs() if (!aygResolved) { aygResolved = true; QLibrary ayglib(QLatin1String("aygshell")); - if (!ayglib.load()) - return; ptrRecognizeGesture = (AygRecognizeGesture) ayglib.resolve("SHRecognizeGesture"); } } @@ -3642,13 +3640,11 @@ static void initWinTabFunctions() return; QLibrary library(QLatin1String("wintab32")); - if (library.load()) { - ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); - ptrWTGet = (PtrWTGet)library.resolve("WTGetW"); - ptrWTEnable = (PtrWTEnable)library.resolve("WTEnable"); - ptrWTOverlap = (PtrWTEnable)library.resolve("WTOverlap"); - ptrWTPacketsGet = (PtrWTPacketsGet)library.resolve("WTPacketsGet"); - } + ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); + ptrWTGet = (PtrWTGet)library.resolve("WTGetW"); + ptrWTEnable = (PtrWTEnable)library.resolve("WTEnable"); + ptrWTOverlap = (PtrWTEnable)library.resolve("WTOverlap"); + ptrWTPacketsGet = (PtrWTPacketsGet)library.resolve("WTPacketsGet"); #endif // Q_OS_WINCE } #endif // QT_NO_TABLETEVENT diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 78fc704..b2dc638 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -456,11 +456,9 @@ static void* qt_load_library_runtime(const char *library, int vernum, Q_FOREACH(int version, versions) { QLatin1String libName(library); QLibrary xfixesLib(libName, version); - if (xfixesLib.load()) { - void *ptr = xfixesLib.resolve(symbol); - if (ptr) - return ptr; - } + void *ptr = xfixesLib.resolve(symbol); + if (ptr) + return ptr; } return 0; } @@ -2557,22 +2555,20 @@ void qt_init(QApplicationPrivate *priv, int, #if !defined (Q_OS_IRIX) && !defined (QT_NO_TABLET) QLibrary wacom(QString::fromLatin1("wacomcfg"), 0); // version 0 is the latest release at time of writing this. - if (wacom.load()) { - // NOTE: C casts instead of reinterpret_cast for GCC 3.3.x - ptrWacomConfigInit = (PtrWacomConfigInit)wacom.resolve("WacomConfigInit"); - ptrWacomConfigOpenDevice = (PtrWacomConfigOpenDevice)wacom.resolve("WacomConfigOpenDevice"); - ptrWacomConfigGetRawParam = (PtrWacomConfigGetRawParam)wacom.resolve("WacomConfigGetRawParam"); - ptrWacomConfigCloseDevice = (PtrWacomConfigCloseDevice)wacom.resolve("WacomConfigCloseDevice"); - ptrWacomConfigTerm = (PtrWacomConfigTerm)wacom.resolve("WacomConfigTerm"); - - if (ptrWacomConfigInit == 0 || ptrWacomConfigOpenDevice == 0 || ptrWacomConfigGetRawParam == 0 - || ptrWacomConfigCloseDevice == 0 || ptrWacomConfigTerm == 0) { // either we have all, or we have none. + // NOTE: C casts instead of reinterpret_cast for GCC 3.3.x + ptrWacomConfigInit = (PtrWacomConfigInit)wacom.resolve("WacomConfigInit"); + ptrWacomConfigOpenDevice = (PtrWacomConfigOpenDevice)wacom.resolve("WacomConfigOpenDevice"); + ptrWacomConfigGetRawParam = (PtrWacomConfigGetRawParam)wacom.resolve("WacomConfigGetRawParam"); + ptrWacomConfigCloseDevice = (PtrWacomConfigCloseDevice)wacom.resolve("WacomConfigCloseDevice"); + ptrWacomConfigTerm = (PtrWacomConfigTerm)wacom.resolve("WacomConfigTerm"); + + if (ptrWacomConfigInit == 0 || ptrWacomConfigOpenDevice == 0 || ptrWacomConfigGetRawParam == 0 + || ptrWacomConfigCloseDevice == 0 || ptrWacomConfigTerm == 0) { // either we have all, or we have none. ptrWacomConfigInit = 0; ptrWacomConfigOpenDevice = 0; ptrWacomConfigGetRawParam = 0; ptrWacomConfigCloseDevice = 0; ptrWacomConfigTerm = 0; - } } #endif } diff --git a/src/gui/kernel/qdesktopwidget_win.cpp b/src/gui/kernel/qdesktopwidget_win.cpp index 07dbc24..5aa206c 100644 --- a/src/gui/kernel/qdesktopwidget_win.cpp +++ b/src/gui/kernel/qdesktopwidget_win.cpp @@ -156,10 +156,8 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that) #ifndef Q_OS_WINCE QLibrary user32Lib(QLatin1String("user32")); - if (user32Lib.load()) { - enumDisplayMonitors = (EnumFunc)user32Lib.resolve("EnumDisplayMonitors"); - getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW"); - } + enumDisplayMonitors = (EnumFunc)user32Lib.resolve("EnumDisplayMonitors"); + getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW"); if (!enumDisplayMonitors || !getMonitorInfo) { screenCount = GetSystemMetrics(80); // SM_CMONITORS @@ -174,11 +172,9 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that) getMonitorInfo = 0; #else QLibrary coreLib(QLatin1String("coredll")); - if (coreLib.load()) { - // CE >= 4.0 case - enumDisplayMonitors = (EnumFunc)coreLib.resolve("EnumDisplayMonitors"); - getMonitorInfo = (InfoFunc)coreLib.resolve("GetMonitorInfo"); - } + // CE >= 4.0 case + enumDisplayMonitors = (EnumFunc)coreLib.resolve("EnumDisplayMonitors"); + getMonitorInfo = (InfoFunc)coreLib.resolve("GetMonitorInfo"); if ((!enumDisplayMonitors || !getMonitorInfo)) { screenCount = GetSystemMetrics(SM_CMONITORS); diff --git a/src/gui/kernel/qguifunctions_wince.cpp b/src/gui/kernel/qguifunctions_wince.cpp index f5004b0..cc98d43 100644 --- a/src/gui/kernel/qguifunctions_wince.cpp +++ b/src/gui/kernel/qguifunctions_wince.cpp @@ -123,8 +123,6 @@ static void resolveAygLibs() if (!aygResolved) { aygResolved = true; QLibrary ayglib(QLatin1String("aygshell")); - if (!ayglib.load()) - return; ptrAygInitDialog = (AygInitDialog) ayglib.resolve("SHInitDialog"); ptrAygFullScreen = (AygFullScreen) ayglib.resolve("SHFullScreen"); ptrAygSHSipInfo = (AygSHSipInfo) ayglib.resolve("SHSipInfo"); diff --git a/src/gui/widgets/qmenu_wince.cpp b/src/gui/widgets/qmenu_wince.cpp index e088db6..15d0116 100644 --- a/src/gui/widgets/qmenu_wince.cpp +++ b/src/gui/widgets/qmenu_wince.cpp @@ -113,8 +113,6 @@ static void resolveAygLibs() if (!aygResolved) { aygResolved = true; QLibrary aygLib(QLatin1String("aygshell")); - if (!aygLib.load()) - return; ptrCreateMenuBar = (AygCreateMenuBar) aygLib.resolve("SHCreateMenuBar"); ptrEnableSoftKey = (AygEnableSoftKey) aygLib.resolve("SHEnableSoftkey"); } diff --git a/tests/auto/qlibrary/tst_qlibrary.cpp b/tests/auto/qlibrary/tst_qlibrary.cpp index 3d26e0b..99e6de3 100644 --- a/tests/auto/qlibrary/tst_qlibrary.cpp +++ b/tests/auto/qlibrary/tst_qlibrary.cpp @@ -203,6 +203,7 @@ void tst_QLibrary::version() VersionFunction fnVersion = (VersionFunction)library.resolve("mylibversion"); QVERIFY(fnVersion); QCOMPARE(fnVersion(), resultversion); + QVERIFY(library.unload()); #else Q_UNUSED(lib); Q_UNUSED(loadversion); @@ -249,6 +250,7 @@ void tst_QLibrary::load() bool ok = library.load(); if ( result ) { QVERIFY( ok ); + QVERIFY(library.unload()); } else { QVERIFY( !ok ); } @@ -338,6 +340,7 @@ void tst_QLibrary::resolve() } else { QVERIFY( func == 0 ); } + library.unload(); } void tst_QLibrary::library_data() @@ -469,7 +472,9 @@ void tst_QLibrary::errorString() break; } QRegExp re(errorString); - QVERIFY2(re.exactMatch(lib.errorString()), qPrintable(lib.errorString())); + QString libErrorString = lib.errorString(); + QVERIFY(!lib.isLoaded() || lib.unload()); + QVERIFY2(re.exactMatch(libErrorString), qPrintable(libErrorString)); QCOMPARE(ok, success); } @@ -525,6 +530,7 @@ void tst_QLibrary::loadHints() bool ok = library.load(); if ( result ) { QVERIFY( ok ); + QVERIFY(library.unload()); } else { QVERIFY( !ok ); } @@ -565,6 +571,7 @@ void tst_QLibrary::fileName() #else QCOMPARE(lib.fileName(), expectedFilename); #endif + QVERIFY(lib.unload()); } @@ -576,29 +583,42 @@ void tst_QLibrary::multipleInstancesForOneLibrary() QString lib = QDir::currentPath() + "/mylib"; #endif - QLibrary lib1(lib); - QLibrary lib2(lib); - QCOMPARE(lib1.isLoaded(), false); - QCOMPARE(lib2.isLoaded(), false); - lib1.load(); - QCOMPARE(lib1.isLoaded(), true); - QCOMPARE(lib2.isLoaded(), true); - QCOMPARE(lib1.unload(), true); - QCOMPARE(lib1.isLoaded(), false); - QCOMPARE(lib2.isLoaded(), false); - lib1.load(); - lib2.load(); - QCOMPARE(lib1.isLoaded(), true); - QCOMPARE(lib2.isLoaded(), true); - QCOMPARE(lib1.unload(), false); - QCOMPARE(lib1.isLoaded(), true); - QCOMPARE(lib2.isLoaded(), true); - QCOMPARE(lib2.unload(), true); - QCOMPARE(lib1.isLoaded(), false); - QCOMPARE(lib2.isLoaded(), false); + { + QLibrary lib1(lib); + QLibrary lib2(lib); + QCOMPARE(lib1.isLoaded(), false); + QCOMPARE(lib2.isLoaded(), false); + lib1.load(); + QCOMPARE(lib1.isLoaded(), true); + QCOMPARE(lib2.isLoaded(), true); + QCOMPARE(lib1.unload(), true); + QCOMPARE(lib1.isLoaded(), false); + QCOMPARE(lib2.isLoaded(), false); + lib1.load(); + lib2.load(); + QCOMPARE(lib1.isLoaded(), true); + QCOMPARE(lib2.isLoaded(), true); + QCOMPARE(lib1.unload(), false); + QCOMPARE(lib1.isLoaded(), true); + QCOMPARE(lib2.isLoaded(), true); + QCOMPARE(lib2.unload(), true); + QCOMPARE(lib1.isLoaded(), false); + QCOMPARE(lib2.isLoaded(), false); + + // Finally; unload on that is already unloaded + QCOMPARE(lib1.unload(), false); + } - // Finally; unload on that is already unloaded - QCOMPARE(lib1.unload(), false); + //now let's try with a 3rd one that will go out of scope + { + QLibrary lib1(lib); + QCOMPARE(lib1.isLoaded(), false); + lib1.load(); + QCOMPARE(lib1.isLoaded(), true); + } + QLibrary lib2(lib); + //lib2 should be loaded because lib1 was loaded and never unloaded + QCOMPARE(lib2.isLoaded(), true); /* lib1.setLoadHints(QLibrary::ResolveAllSymbolsHint); -- cgit v0.12 From a865aa2a022478aabea26b0f363a55db2c43fec7 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 4 Jun 2010 15:34:30 +0200 Subject: Reimplement more of QAbstractItemModel in QAbstractProxyModel The non-structural parts of the API are implemented to forward calls to the source model. Merge-request: 656 Reviewed-by: Olivier Goffart --- src/gui/itemviews/qabstractproxymodel.cpp | 96 +++++++++++++++++++++++++++++++ src/gui/itemviews/qabstractproxymodel.h | 12 ++++ 2 files changed, 108 insertions(+) diff --git a/src/gui/itemviews/qabstractproxymodel.cpp b/src/gui/itemviews/qabstractproxymodel.cpp index 43a1327..4d4b3d8 100644 --- a/src/gui/itemviews/qabstractproxymodel.cpp +++ b/src/gui/itemviews/qabstractproxymodel.cpp @@ -45,6 +45,9 @@ #include "qitemselectionmodel.h" #include +#include +#include + QT_BEGIN_NAMESPACE @@ -262,6 +265,15 @@ bool QAbstractProxyModel::setData(const QModelIndex &index, const QVariant &valu /*! \reimp */ +bool QAbstractProxyModel::setItemData(const QModelIndex &index, const QMap< int, QVariant >& roles) +{ + Q_D(QAbstractProxyModel); + return d->model->setItemData(mapToSource(index), roles); +} + +/*! + \reimp + */ bool QAbstractProxyModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) { Q_D(QAbstractProxyModel); @@ -276,6 +288,90 @@ bool QAbstractProxyModel::setHeaderData(int section, Qt::Orientation orientation return d->model->setHeaderData(sourceSection, orientation, value, role); } +/*! + \reimp + */ +QModelIndex QAbstractProxyModel::buddy(const QModelIndex &index) const +{ + Q_D(const QAbstractProxyModel); + return mapFromSource(d->model->buddy(mapToSource(index))); +} + +/*! + \reimp + */ +bool QAbstractProxyModel::canFetchMore(const QModelIndex &parent) const +{ + Q_D(const QAbstractProxyModel); + return d->model->canFetchMore(mapToSource(parent)); +} + +/*! + \reimp + */ +void QAbstractProxyModel::fetchMore(const QModelIndex &parent) +{ + Q_D(QAbstractProxyModel); + d->model->fetchMore(mapToSource(parent)); +} + +/*! + \reimp + */ +void QAbstractProxyModel::sort(int column, Qt::SortOrder order) +{ + Q_D(QAbstractProxyModel); + d->model->sort(column, order); +} + +/*! + \reimp + */ +QSize QAbstractProxyModel::span(const QModelIndex &index) const +{ + Q_D(const QAbstractProxyModel); + return d->model->span(mapToSource(index)); +} + +/*! + \reimp + */ +bool QAbstractProxyModel::hasChildren(const QModelIndex &parent) const +{ + Q_D(const QAbstractProxyModel); + return d->model->hasChildren(mapToSource(parent)); +} + +/*! + \reimp + */ +QMimeData* QAbstractProxyModel::mimeData(const QModelIndexList &indexes) const +{ + Q_D(const QAbstractProxyModel); + QModelIndexList list; + foreach(const QModelIndex &index, indexes) + list << mapToSource(index); + return d->model->mimeData(indexes); +} + +/*! + \reimp + */ +QStringList QAbstractProxyModel::mimeTypes() const +{ + Q_D(const QAbstractProxyModel); + return d->model->mimeTypes(); +} + +/*! + \reimp + */ +Qt::DropActions QAbstractProxyModel::supportedDropActions() const +{ + Q_D(const QAbstractProxyModel); + return d->model->supportedDropActions(); +} + QT_END_NAMESPACE #include "moc_qabstractproxymodel.cpp" diff --git a/src/gui/itemviews/qabstractproxymodel.h b/src/gui/itemviews/qabstractproxymodel.h index c6bb985..a5a1168 100644 --- a/src/gui/itemviews/qabstractproxymodel.h +++ b/src/gui/itemviews/qabstractproxymodel.h @@ -81,8 +81,20 @@ public: Qt::ItemFlags flags(const QModelIndex &index) const; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + bool setItemData(const QModelIndex& index, const QMap &roles); bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole); + QModelIndex buddy(const QModelIndex &index) const; + bool canFetchMore(const QModelIndex &parent) const; + void fetchMore(const QModelIndex &parent); + void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); + QSize span(const QModelIndex &index) const; + bool hasChildren(const QModelIndex &parent = QModelIndex()) const; + + QMimeData* mimeData(const QModelIndexList &indexes) const; + QStringList mimeTypes() const; + Qt::DropActions supportedDropActions() const; + protected: QAbstractProxyModel(QAbstractProxyModelPrivate &, QObject *parent); -- cgit v0.12 From 114bd0ca8e3e892cd3118ac2dd4cfe87e12b0310 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 4 Jun 2010 17:17:25 +0200 Subject: make the plugin loader autotests pass --- tests/auto/qpluginloader/tst_qpluginloader.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/auto/qpluginloader/tst_qpluginloader.cpp b/tests/auto/qpluginloader/tst_qpluginloader.cpp index 705e600..61d59a1 100644 --- a/tests/auto/qpluginloader/tst_qpluginloader.cpp +++ b/tests/auto/qpluginloader/tst_qpluginloader.cpp @@ -287,12 +287,14 @@ void tst_QPluginLoader::deleteinstanceOnUnload() QSignalSpy spy1(loader1.instance(), SIGNAL(destroyed())); QSignalSpy spy2(loader2.instance(), SIGNAL(destroyed())); - QCOMPARE(loader1.unload(), false); // refcount not reached 0, not really unloaded - QCOMPARE(spy1.count(), 0); - QCOMPARE(spy2.count(), 0); + if (pass == 0) { + QCOMPARE(loader2.unload(), false); // refcount not reached 0, not really unloaded + QCOMPARE(spy1.count(), 0); + QCOMPARE(spy2.count(), 0); + } QCOMPARE(instance1->pluginName(), QLatin1String("Plugin ok")); QCOMPARE(instance2->pluginName(), QLatin1String("Plugin ok")); - QCOMPARE(loader2.unload(), true); // refcount reached 0, did really unload + QVERIFY(loader1.unload()); // refcount reached 0, did really unload QCOMPARE(spy1.count(), 1); QCOMPARE(spy2.count(), 1); } -- cgit v0.12 From 3ef17db7085f0b77661ced78522c8cfcb0e52144 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 4 Jun 2010 18:37:29 +0200 Subject: add missing header --- src/gui/text/qglyphs.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/gui/text/qglyphs.cpp b/src/gui/text/qglyphs.cpp index 847646e..2447752 100644 --- a/src/gui/text/qglyphs.cpp +++ b/src/gui/text/qglyphs.cpp @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #include "qglyphs.h" #include "qglyphs_p.h" -- cgit v0.12 From 9e712c65899681ca08534476145dda05e5edb0bc Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 7 Jun 2010 12:14:10 +0200 Subject: Fix maketestselftest by adding the qglyphs test Also make the test find the font in shadow build Reviewed-by: eskil --- tests/auto/gui.pro | 1 + tests/auto/qglyphs/qglyphs.pro | 6 ++++++ tests/auto/qglyphs/tst_qglyphs.cpp | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/auto/gui.pro b/tests/auto/gui.pro index a8fd2b4..d2669c6 100644 --- a/tests/auto/gui.pro +++ b/tests/auto/gui.pro @@ -57,6 +57,7 @@ SUBDIRS=\ qfontdialog \ qfontmetrics \ qformlayout \ + qglyphs \ qgraphicsanchorlayout \ qgraphicsanchorlayout1 \ qgraphicseffect \ diff --git a/tests/auto/qglyphs/qglyphs.pro b/tests/auto/qglyphs/qglyphs.pro index 70920f0..5084cf9 100644 --- a/tests/auto/qglyphs/qglyphs.pro +++ b/tests/auto/qglyphs/qglyphs.pro @@ -3,3 +3,9 @@ QT = core gui SOURCES += \ tst_qglyphs.cpp + +wince*|symbian*: { + DEFINES += SRCDIR=\\\"\\\" +} else { + DEFINES += SRCDIR=\\\"$$PWD/\\\" +} \ No newline at end of file diff --git a/tests/auto/qglyphs/tst_qglyphs.cpp b/tests/auto/qglyphs/tst_qglyphs.cpp index c906f10..2a0e670 100644 --- a/tests/auto/qglyphs/tst_qglyphs.cpp +++ b/tests/auto/qglyphs/tst_qglyphs.cpp @@ -77,7 +77,7 @@ Q_DECLARE_METATYPE(QGlyphs); void tst_QGlyphs::initTestCase() { - m_testFontId = QFontDatabase::addApplicationFont("test.ttf"); + m_testFontId = QFontDatabase::addApplicationFont(SRCDIR "test.ttf"); QVERIFY(m_testFontId >= 0); m_testFont = QFont("QtsSpecialTestFont"); -- cgit v0.12 From e55b6a34ea06646e81b559a0605aabc150119565 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 26 Apr 2010 12:10:36 +0200 Subject: qdrawhelper: remove code duplication Reviewed-by: Samuel --- src/gui/painting/qdrawhelper.cpp | 154 ++++++++------------------------------- 1 file changed, 30 insertions(+), 124 deletions(-) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index bfa1136..e18ab75 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -656,6 +656,28 @@ const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const return buffer; } +template +static inline void fetchTransformedBilinear_pixelBounds(int max, int l1, int l2, int &v1, int &v2) +{ + if (blendType == BlendTransformedBilinearTiled) { + v1 %= max; + if (v1 < 0) v1 += max; + v2 = v1 + 1; + v2 %= max; + } else { + if (v1 < l1) { + v2 = v1 = l1; + } else if (v1 >= l2 - 1) { + v2 = v1 = l2 - 1; + } else { + v2 = v1 + 1; + } + } + + Q_ASSERT(v1 >= 0 && v1 < max); + Q_ASSERT(v2 >= 0 && v2 < max); +} + template /* blendType = BlendTransformedBilinear or BlendTransformedBilinearTiled */ Q_STATIC_TEMPLATE_FUNCTION const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *, const QSpanData *data, @@ -702,37 +724,8 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * int y1 = (fy >> 16); int y2; - if (blendType == BlendTransformedBilinearTiled) { - x1 %= image_width; - if (x1 < 0) x1 += image_width; - x2 = x1 + 1; - x2 %= image_width; - - y1 %= image_height; - if (y1 < 0) y1 += image_height; - y2 = y1 + 1; - y2 %= image_height; - } else { - if (x1 < image_x1) { - x2 = x1 = image_x1; - } else if (x1 >= image_x2 - 1) { - x2 = x1 = image_x2 - 1; - } else { - x2 = x1 + 1; - } - if (y1 < image_y1) { - y2 = y1 = image_y1; - } else if (y1 >= image_y2 - 1) { - y2 = y1 = image_y2 - 1; - } else { - y2 = y1 + 1; - } - } - - Q_ASSERT(x1 >= 0 && x1 < image_width); - Q_ASSERT(x2 >= 0 && x2 < image_width); - Q_ASSERT(y1 >= 0 && y1 < image_height); - Q_ASSERT(y2 >= 0 && y2 < image_height); + fetchTransformedBilinear_pixelBounds(image_width, image_x1, image_x2, x1, x2); + fetchTransformedBilinear_pixelBounds(image_height, image_y1, image_y2, y1, y2); const uchar *s1 = data->texture.scanLine(y1); const uchar *s2 = data->texture.scanLine(y2); @@ -779,37 +772,8 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * int idistx = 256 - distx; int idisty = 256 - disty; - if (blendType == BlendTransformedBilinearTiled) { - x1 %= image_width; - if (x1 < 0) x1 += image_width; - x2 = x1 + 1; - x2 %= image_width; - - y1 %= image_height; - if (y1 < 0) y1 += image_height; - y2 = y1 + 1; - y2 %= image_height; - } else { - if (x1 < 0) { - x2 = x1 = 0; - } else if (x1 >= image_width - 1) { - x2 = x1 = image_width - 1; - } else { - x2 = x1 + 1; - } - if (y1 < 0) { - y2 = y1 = 0; - } else if (y1 >= image_height - 1) { - y2 = y1 = image_height - 1; - } else { - y2 = y1 + 1; - } - } - - Q_ASSERT(x1 >= 0 && x1 < image_width); - Q_ASSERT(x2 >= 0 && x2 < image_width); - Q_ASSERT(y1 >= 0 && y1 < image_height); - Q_ASSERT(y2 >= 0 && y2 < image_height); + fetchTransformedBilinear_pixelBounds(image_width, image_x1, image_x2, x1, x2); + fetchTransformedBilinear_pixelBounds(image_height, image_y1, image_y2, y1, y2); const uchar *s1 = data->texture.scanLine(y1); const uchar *s2 = data->texture.scanLine(y2); @@ -5220,37 +5184,8 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_argb(int count, const int y1 = (y >> 16); int y2; - if (blendType == BlendTransformedBilinearTiled) { - x1 %= image_width; - if (x1 < 0) x1 += image_width; - x2 = x1 + 1; - x2 %= image_width; - - y1 %= image_height; - if (y1 < 0) y1 += image_height; - y2 = y1 + 1; - y2 %= image_height; - - Q_ASSERT(x1 >= 0 && x1 < image_width); - Q_ASSERT(x2 >= 0 && x2 < image_width); - Q_ASSERT(y1 >= 0 && y1 < image_height); - Q_ASSERT(y2 >= 0 && y2 < image_height); - } else { - if (x1 < image_x1) { - x2 = x1 = image_x1; - } else if (x1 >= image_x2 - 1) { - x2 = x1 = image_x2 - 1; - } else { - x2 = x1 + 1; - } - if (y1 < image_y1) { - y2 = y1 = image_y1; - } else if (y1 >= image_y2 - 1) { - y2 = y1 = image_y2 - 1; - } else { - y2 = y1 + 1; - } - } + fetchTransformedBilinear_pixelBounds(image_width, image_x1, image_x2, x1, x2); + fetchTransformedBilinear_pixelBounds(image_height, image_y1, image_y2, y1, y2); int y1_offset = y1 * scanline_offset; int y2_offset = y2 * scanline_offset; @@ -5330,37 +5265,8 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_argb(int count, const int idistx = 256 - distx; int idisty = 256 - disty; - if (blendType == BlendTransformedBilinearTiled) { - x1 %= image_width; - if (x1 < 0) x1 += image_width; - x2 = x1 + 1; - x2 %= image_width; - - y1 %= image_height; - if (y1 < 0) y1 += image_height; - y2 = y1 + 1; - y2 %= image_height; - - Q_ASSERT(x1 >= 0 && x1 < image_width); - Q_ASSERT(x2 >= 0 && x2 < image_width); - Q_ASSERT(y1 >= 0 && y1 < image_height); - Q_ASSERT(y2 >= 0 && y2 < image_height); - } else { - if (x1 < image_x1) { - x2 = x1 = image_x1; - } else if (x1 >= image_x2 - 1) { - x2 = x1 = image_x2 - 1; - } else { - x2 = x1 + 1; - } - if (y1 < image_y1) { - y2 = y1 = image_y1; - } else if (y1 >= image_y2 - 1) { - y2 = y1 = image_y2 - 1; - } else { - y2 = y1 + 1; - } - } + fetchTransformedBilinear_pixelBounds(image_width, image_x1, image_x2, x1, x2); + fetchTransformedBilinear_pixelBounds(image_height, image_y1, image_y2, y1, y2); int y1_offset = y1 * scanline_offset; int y2_offset = y2 * scanline_offset; -- cgit v0.12 From 0d7e6839172f5feae2c81c5c552f685520504afc Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 26 Apr 2010 13:40:09 +0200 Subject: qdrawhelper: optimize fetchTransformedBilinear When scaling down, there is no need to keep 8 bit accurancy on the position 4 bit is enough and should not be noticable for the human eye. Also optimize the pure scaling if there is no rotation: when scaling up, do the average between the top and the bottom row then use this pre-computation later. Reviewed-by: Samuel --- src/gui/painting/qdrawhelper.cpp | 195 +++++++++++++++++++++++++++++++++++---- tests/auto/qimage/tst_qimage.cpp | 6 +- 2 files changed, 178 insertions(+), 23 deletions(-) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index e18ab75..bd961a4 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -656,6 +656,24 @@ const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const return buffer; } +/** \internal + interpolate 4 argb pixels with the distx and disty factor. + distx and disty bust be between 0 and 16 + */ +static inline uint interpolate_4_pixels_16(uint tl, uint tr, uint bl, uint br, int distx, int disty, int idistx, int idisty) +{ + uint tlrb = ((tl & 0x00ff00ff) * idistx * idisty); + uint tlag = (((tl & 0xff00ff00) >> 8) * idistx * idisty); + uint trrb = ((tr & 0x00ff00ff) * distx * idisty); + uint trag = (((tr & 0xff00ff00) >> 8) * distx * idisty); + uint blrb = ((bl & 0x00ff00ff) * idistx * disty); + uint blag = (((bl & 0xff00ff00) >> 8) * idistx * disty); + uint brrb = ((br & 0x00ff00ff) * distx * disty); + uint brag = (((br & 0xff00ff00) >> 8) * distx * disty); + return (((tlrb + trrb + blrb + brrb) >> 8) & 0x00ff00ff) | ((tlag + trag + blag + brag) & 0xff00ff00); +} + + template static inline void fetchTransformedBilinear_pixelBounds(int max, int l1, int l2, int &v1, int &v2) { @@ -718,35 +736,172 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * fx -= half_point; fy -= half_point; - while (b < end) { - int x1 = (fx >> 16); - int x2; + + if (fdy == 0) { //simple scale, no rotation int y1 = (fy >> 16); int y2; - - fetchTransformedBilinear_pixelBounds(image_width, image_x1, image_x2, x1, x2); fetchTransformedBilinear_pixelBounds(image_height, image_y1, image_y2, y1, y2); - const uchar *s1 = data->texture.scanLine(y1); const uchar *s2 = data->texture.scanLine(y2); - uint tl = fetch(s1, x1, data->texture.colorTable); - uint tr = fetch(s1, x2, data->texture.colorTable); - uint bl = fetch(s2, x1, data->texture.colorTable); - uint br = fetch(s2, x2, data->texture.colorTable); + if (fdx <= fixed_scale && fdx > 0) { // scale up on X + int disty = (fy & 0x0000ffff) >> 8; + int idisty = 256 - disty; + int count = length * data->m11 + 2; + int x_ = fx >> 16; + + quint32 intermediate_buffer[buffer_size + 2][2]; + Q_ASSERT(length * data->m11 <= buffer_size); + if (blendType == BlendTransformedBilinearTiled) { + x_ %= image_width; + if (x_ < 0) x_ += image_width; + } + for (int f = 0; f < count; f++) { + int x; + if (blendType == BlendTransformedBilinearTiled) { + if (x_ >= image_width) x_ -= image_width; + x = x_; + } else { + x = qBound(image_x1, x_, image_x2 - 1); + } - int distx = (fx & 0x0000ffff) >> 8; - int disty = (fy & 0x0000ffff) >> 8; - int idistx = 256 - distx; - int idisty = 256 - disty; + uint t = fetch(s1, x, data->texture.colorTable); + uint b = fetch(s2, x, data->texture.colorTable); - uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); - uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); - *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); + intermediate_buffer[f][0] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff; + intermediate_buffer[f][1] = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff; + x_++; + } + fx &= fixed_scale - 1; + Q_ASSERT((fx >> 16) == 0); + while (b < end) { + register int x1 = (fx >> 16); + register int x2 = x1 + 1; + Q_ASSERT(x1 >= 0); + Q_ASSERT(x2 < count); + + register int distx = (fx & 0x0000ffff) >> 8; + register int idistx = 256 - distx; + int rb = ((intermediate_buffer[x1][0] * idistx + intermediate_buffer[x2][0] * distx) >> 8) & 0xff00ff; + int ag = (intermediate_buffer[x1][1] * idistx + intermediate_buffer[x2][1] * distx) & 0xff00ff00; + *b = rb | ag; + b++; + fx += fdx; + } + } else if ((fdx < 0 && fdx > -(fixed_scale / 8)) || fabs(data->m22) < (1./8.)) { // scale up more than 8x + int y1 = (fy >> 16); + int y2; + fetchTransformedBilinear_pixelBounds(image_height, image_y1, image_y2, y1, y2); + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); + int disty = (fy & 0x0000ffff) >> 8; + int idisty = 256 - disty; + while (b < end) { + int x1 = (fx >> 16); + int x2; + fetchTransformedBilinear_pixelBounds(image_height, image_x1, image_x2, x1, x2); + uint tl = fetch(s1, x1, data->texture.colorTable); + uint tr = fetch(s1, x2, data->texture.colorTable); + uint bl = fetch(s2, x1, data->texture.colorTable); + uint br = fetch(s2, x2, data->texture.colorTable); - fx += fdx; - fy += fdy; - ++b; + int distx = (fx & 0x0000ffff) >> 8; + int idistx = 256 - distx; + + uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); + uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); + *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); + + fx += fdx; + ++b; + } + } else { //scale down + int y1 = (fy >> 16); + int y2; + fetchTransformedBilinear_pixelBounds(image_height, image_y1, image_y2, y1, y2); + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); + int disty = (fy & 0x0000ffff) >> 12; + int idisty = 16 - disty; + while (b < end) { + int x1 = (fx >> 16); + int x2; + fetchTransformedBilinear_pixelBounds(image_height, image_x1, image_x2, x1, x2); + uint tl = fetch(s1, x1, data->texture.colorTable); + uint tr = fetch(s1, x2, data->texture.colorTable); + uint bl = fetch(s2, x1, data->texture.colorTable); + uint br = fetch(s2, x2, data->texture.colorTable); + int distx = (fx & 0x0000ffff) >> 12; + int idistx = 16 - distx; + *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty, idistx, idisty); + fx += fdx; + ++b; + } + } + } else { //rotation + if (fabs(data->m11) > 8 || fabs(data->m22) > 8) { + //if we are zooming more than 8 times, we use 8bit precision for the position. + while (b < end) { + int x1 = (fx >> 16); + int x2; + int y1 = (fy >> 16); + int y2; + + fetchTransformedBilinear_pixelBounds(image_width, image_x1, image_x2, x1, x2); + fetchTransformedBilinear_pixelBounds(image_height, image_y1, image_y2, y1, y2); + + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); + + uint tl = fetch(s1, x1, data->texture.colorTable); + uint tr = fetch(s1, x2, data->texture.colorTable); + uint bl = fetch(s2, x1, data->texture.colorTable); + uint br = fetch(s2, x2, data->texture.colorTable); + + int distx = (fx & 0x0000ffff) >> 8; + int disty = (fy & 0x0000ffff) >> 8; + int idistx = 256 - distx; + int idisty = 256 - disty; + + uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); + uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); + *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); + + fx += fdx; + fy += fdy; + ++b; + } + } else { + //we are zooming less than 8x, use 4bit precision + while (b < end) { + int x1 = (fx >> 16); + int x2; + int y1 = (fy >> 16); + int y2; + + fetchTransformedBilinear_pixelBounds(image_width, image_x1, image_x2, x1, x2); + fetchTransformedBilinear_pixelBounds(image_height, image_y1, image_y2, y1, y2); + + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); + + uint tl = fetch(s1, x1, data->texture.colorTable); + uint tr = fetch(s1, x2, data->texture.colorTable); + uint bl = fetch(s2, x1, data->texture.colorTable); + uint br = fetch(s2, x2, data->texture.colorTable); + + int distx = (fx & 0x0000ffff) >> 12; + int disty = (fy & 0x0000ffff) >> 12; + int idistx = 16 - distx; + int idisty = 16 - disty; + + *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty, idistx, idisty); + + fx += fdx; + fy += fdy; + ++b; + } + } } } else { const qreal fdx = data->m11; diff --git a/tests/auto/qimage/tst_qimage.cpp b/tests/auto/qimage/tst_qimage.cpp index 16deb03..10514d9 100644 --- a/tests/auto/qimage/tst_qimage.cpp +++ b/tests/auto/qimage/tst_qimage.cpp @@ -1465,9 +1465,9 @@ void tst_QImage::smoothScale3() QRgb cb = b.pixel(x, y); // tolerate a little bit of rounding errors - QVERIFY(compare(qRed(ca), qRed(cb), 3)); - QVERIFY(compare(qGreen(ca), qGreen(cb), 3)); - QVERIFY(compare(qBlue(ca), qBlue(cb), 3)); + QVERIFY(compare(qRed(ca), qRed(cb), 16)); + QVERIFY(compare(qGreen(ca), qGreen(cb), 16)); + QVERIFY(compare(qBlue(ca), qBlue(cb), 16)); } } } -- cgit v0.12 From bc846277c47cb9980f3b6003ec702b7739568d15 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 7 Jun 2010 12:40:15 +0200 Subject: Remove unused function in tst_QGlyphs Static function which was never called, caused a warning with gcc --- tests/auto/qglyphs/tst_qglyphs.cpp | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/tests/auto/qglyphs/tst_qglyphs.cpp b/tests/auto/qglyphs/tst_qglyphs.cpp index 2a0e670..177b981 100644 --- a/tests/auto/qglyphs/tst_qglyphs.cpp +++ b/tests/auto/qglyphs/tst_qglyphs.cpp @@ -119,31 +119,6 @@ static QGlyphs make_dummy_indexes() return glyphs; } -static QGlyphs make_dummy_indexes2() -{ - QGlyphs glyphs; - - QVector glyphIndexes; - QVector positions; - QFont font; - font.setPointSize(26); - - glyphIndexes.append(4); - glyphIndexes.append(5); - glyphIndexes.append(6); - - positions.append(QPointF(7, 8)); - positions.append(QPointF(9, 10)); - positions.append(QPointF(11, 12)); - - glyphs.setFont(font); - glyphs.setGlyphIndexes(glyphIndexes); - glyphs.setPositions(positions); - - return glyphs; -} - - void tst_QGlyphs::copyConstructor() { QGlyphs glyphs; -- cgit v0.12 From 422648966d634b27cfcf8cad8a895724322637cb Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 7 Jun 2010 13:24:56 +0200 Subject: Test native graphics engine in tst_QGlyphs Drawing to QImage will always go through the raster engine, so some bugs might not be caught. This also fixes a test failure on X11, since the raster engine on X11 is inconsistent with regards to how it handles subpixel antialiasing into images. See task QTBUG-11268. Reviewed-by: Olivier --- tests/auto/qglyphs/tst_qglyphs.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/auto/qglyphs/tst_qglyphs.cpp b/tests/auto/qglyphs/tst_qglyphs.cpp index 177b981..90309ea 100644 --- a/tests/auto/qglyphs/tst_qglyphs.cpp +++ b/tests/auto/qglyphs/tst_qglyphs.cpp @@ -235,11 +235,11 @@ void tst_QGlyphs::textLayoutGlyphIndexes() void tst_QGlyphs::drawExistingGlyphs() { - QImage textLayoutDraw(1000, 1000, QImage::Format_ARGB32); - QImage drawGlyphs(1000, 1000, QImage::Format_ARGB32); + QPixmap textLayoutDraw(1000, 1000); + QPixmap drawGlyphs(1000, 1000); - textLayoutDraw.fill(0xffffffff); - drawGlyphs.fill(0xffffffff); + textLayoutDraw.fill(Qt::white); + drawGlyphs.fill(Qt::white); QString s; s.append(QLatin1Char('A')); @@ -286,10 +286,10 @@ void tst_QGlyphs::drawNonExistentGlyphs() glyphs.setPositions(glyphPositions); glyphs.setFont(m_testFont); - QImage image(1000, 1000, QImage::Format_ARGB32); - image.fill(0); + QPixmap image(1000, 1000); + image.fill(Qt::white); - QImage imageBefore = image; + QPixmap imageBefore = image; { QPainter p(&image); p.drawGlyphs(QPointF(50, 50), glyphs); @@ -312,11 +312,11 @@ void tst_QGlyphs::drawMultiScriptText1() textLayout.createLine(); textLayout.endLayout(); - QImage textLayoutDraw(1000, 1000, QImage::Format_ARGB32); - textLayoutDraw.fill(0xffffffff); + QPixmap textLayoutDraw(1000, 1000); + textLayoutDraw.fill(Qt::white); - QImage drawGlyphs(1000, 1000, QImage::Format_ARGB32); - drawGlyphs.fill(0xffffffff); + QPixmap drawGlyphs(1000, 1000); + drawGlyphs.fill(Qt::white); QList glyphsList = textLayout.glyphs(); QCOMPARE(glyphsList.size(), 1); @@ -356,11 +356,11 @@ void tst_QGlyphs::drawMultiScriptText2() textLayout.createLine(); textLayout.endLayout(); - QImage textLayoutDraw(1000, 1000, QImage::Format_ARGB32); - textLayoutDraw.fill(0xffffffff); + QPixmap textLayoutDraw(1000, 1000); + textLayoutDraw.fill(Qt::white); - QImage drawGlyphs(1000, 1000, QImage::Format_ARGB32); - drawGlyphs.fill(0xffffffff); + QPixmap drawGlyphs(1000, 1000); + drawGlyphs.fill(Qt::white); QList glyphsList = textLayout.glyphs(); QCOMPARE(glyphsList.size(), 2); -- cgit v0.12 From 29ef46edfd4f01da7d79338c031b237af415be3a Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 7 Jun 2010 16:43:04 +0200 Subject: Fix compilation with RVCT RVCT does not like static template functions --- src/gui/painting/qdrawhelper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index bd961a4..a765102 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -675,7 +675,7 @@ static inline uint interpolate_4_pixels_16(uint tl, uint tr, uint bl, uint br, i template -static inline void fetchTransformedBilinear_pixelBounds(int max, int l1, int l2, int &v1, int &v2) +Q_STATIC_TEMPLATE_FUNCTION inline void fetchTransformedBilinear_pixelBounds(int max, int l1, int l2, int &v1, int &v2) { if (blendType == BlendTransformedBilinearTiled) { v1 %= max; -- cgit v0.12 From 23306a399c0703eea7420231903c850566bfe2f0 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 7 Jun 2010 21:01:36 +0200 Subject: Make tst_image a little bit more tollerent to rounding errors --- tests/auto/qimage/tst_qimage.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/auto/qimage/tst_qimage.cpp b/tests/auto/qimage/tst_qimage.cpp index 10514d9..2164b05 100644 --- a/tests/auto/qimage/tst_qimage.cpp +++ b/tests/auto/qimage/tst_qimage.cpp @@ -1426,11 +1426,6 @@ static inline int rand8() return int(256. * (qrand() / (RAND_MAX + 1.0))); } -static inline bool compare(int a, int b, int tolerance) -{ - return qAbs(a - b) <= tolerance; -} - // compares img.scale against the bilinear filtering used by QPainter void tst_QImage::smoothScale3() { @@ -1458,6 +1453,7 @@ void tst_QImage::smoothScale3() p.scale(scales[i], scales[i]); p.drawImage(0, 0, img); p.end(); + int err = 0; for (int y = 0; y < a.height(); ++y) { for (int x = 0; x < a.width(); ++x) { @@ -1465,11 +1461,15 @@ void tst_QImage::smoothScale3() QRgb cb = b.pixel(x, y); // tolerate a little bit of rounding errors - QVERIFY(compare(qRed(ca), qRed(cb), 16)); - QVERIFY(compare(qGreen(ca), qGreen(cb), 16)); - QVERIFY(compare(qBlue(ca), qBlue(cb), 16)); + bool r = true; + r &= qAbs(qRed(ca) - qRed(cb)) <= 18; + r &= qAbs(qGreen(ca) - qGreen(cb)) <= 18; + r &= qAbs(qBlue(ca) - qBlue(cb)) <= 18; + if (!r) + err++; } } + QCOMPARE(err, 0); } } -- cgit v0.12 From 572d13eeaaa7aea7aa09d6c5de420338f742ea4b Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 9 Jun 2010 16:55:59 +0200 Subject: Fix warning with gcc in -pedantic Empty marcro arguments throws warning on some compilers. (Correction of 89dfa8d7a46c992b066e5335d64089bf796e2f83) Reviewed-by: Thiago Task-number: QTBUG-11334 --- src/corelib/global/qglobal.h | 6 +++--- src/corelib/tools/qsharedpointer_impl.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 28ac377..6bcc95b 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -2041,8 +2041,7 @@ enum { /* TYPEINFO flags */ Q_DUMMY_TYPE = 0x4 }; -#define Q_DECLARE_TYPEINFO_TEMPLATE(TYPE, FLAGS, TEMPLATE_ARG) \ -template \ +#define Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) \ class QTypeInfo \ { \ public: \ @@ -2057,7 +2056,8 @@ public: \ } #define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \ -Q_DECLARE_TYPEINFO_TEMPLATE(TYPE, FLAGS, ) +template<> \ +Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) template diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 9e40bd5..2329470 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -844,8 +844,8 @@ qobject_cast(const QWeakPointer &src) #endif -Q_DECLARE_TYPEINFO_TEMPLATE(QWeakPointer, Q_MOVABLE_TYPE, typename T); -Q_DECLARE_TYPEINFO_TEMPLATE(QSharedPointer, Q_MOVABLE_TYPE, typename T); +template Q_DECLARE_TYPEINFO_BODY(QWeakPointer, Q_MOVABLE_TYPE); +template Q_DECLARE_TYPEINFO_BODY(QSharedPointer, Q_MOVABLE_TYPE); QT_END_NAMESPACE -- cgit v0.12 From f189881fbe6d06051c4c6d86419533ddd9966d2a Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Mon, 14 Jun 2010 10:14:05 +0200 Subject: Finally, remove some trailing whitespace. Reviewed-by: Alexis Menard --- src/gui/graphicsview/qgraphicsgridlayout.h | 2 +- src/gui/graphicsview/qgraphicsitem.cpp | 4 ++-- src/gui/graphicsview/qgraphicsitemanimation.cpp | 22 +++++++++++----------- src/gui/graphicsview/qgraphicslayout.cpp | 10 +++++----- src/gui/graphicsview/qgraphicslayout_p.cpp | 12 ++++++------ src/gui/graphicsview/qgraphicslayout_p.h | 8 ++++---- src/gui/graphicsview/qgraphicslayoutitem.cpp | 2 +- src/gui/graphicsview/qgraphicslayoutitem.h | 2 +- src/gui/graphicsview/qgraphicsview.cpp | 2 +- src/gui/graphicsview/qgraphicswidget_p.cpp | 2 +- 10 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsgridlayout.h b/src/gui/graphicsview/qgraphicsgridlayout.h index 6580a02..ddfb447 100644 --- a/src/gui/graphicsview/qgraphicsgridlayout.h +++ b/src/gui/graphicsview/qgraphicsgridlayout.h @@ -109,7 +109,7 @@ public: int columnCount() const; QGraphicsLayoutItem *itemAt(int row, int column) const; - + // inherited from QGraphicsLayout int count() const; QGraphicsLayoutItem *itemAt(int index) const; diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index b867345..d1f6eb3 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -7618,9 +7618,9 @@ int QGraphicsItemPrivate::children_count(QDeclarativeListProperty *list, int index) { QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(static_cast(list->object)); - if (index >= 0 && index < d->children.count()) + if (index >= 0 && index < d->children.count()) return d->children.at(index)->toGraphicsObject(); - else + else return 0; } diff --git a/src/gui/graphicsview/qgraphicsitemanimation.cpp b/src/gui/graphicsview/qgraphicsitemanimation.cpp index 9cb9a8d..9689616 100644 --- a/src/gui/graphicsview/qgraphicsitemanimation.cpp +++ b/src/gui/graphicsview/qgraphicsitemanimation.cpp @@ -49,20 +49,20 @@ The QGraphicsItemAnimation class animates a QGraphicsItem. You can schedule changes to the item's transformation matrix at - specified steps. The QGraphicsItemAnimation class has a - current step value. When this value changes the transformations - scheduled at that step are performed. The current step of the + specified steps. The QGraphicsItemAnimation class has a + current step value. When this value changes the transformations + scheduled at that step are performed. The current step of the animation is set with the \c setStep() function. QGraphicsItemAnimation will do a simple linear interpolation - between the nearest adjacent scheduled changes to calculate the + between the nearest adjacent scheduled changes to calculate the matrix. For instance, if you set the position of an item at values 0.0 and 1.0, the animation will show the item moving in a straight - line between these positions. The same is true for scaling and + line between these positions. The same is true for scaling and rotation. It is usual to use the class with a QTimeLine. The timeline's - \l{QTimeLine::}{valueChanged()} signal is then connected to the + \l{QTimeLine::}{valueChanged()} signal is then connected to the \c setStep() slot. For example, you can set up an item for rotation by calling \c setRotationAt() for different step values. The animations timeline is set with the setTimeLine() function. @@ -286,7 +286,7 @@ QList > QGraphicsItemAnimation::posList() const QList > list; for (int i = 0; i < d->xPosition.size(); ++i) list << QPair(d->xPosition.at(i).step, QPointF(d->xPosition.at(i).value, d->yPosition.at(i).value)); - + return list; } @@ -343,7 +343,7 @@ QList > QGraphicsItemAnimation::rotationList() const QList > list; for (int i = 0; i < d->rotation.size(); ++i) list << QPair(d->rotation.at(i).step, d->rotation.at(i).value); - + return list; } @@ -395,7 +395,7 @@ QList > QGraphicsItemAnimation::translationList() const QList > list; for (int i = 0; i < d->xTranslation.size(); ++i) list << QPair(d->xTranslation.at(i).step, QPointF(d->xTranslation.at(i).value, d->yTranslation.at(i).value)); - + return list; } @@ -447,7 +447,7 @@ QList > QGraphicsItemAnimation::scaleList() const QList > list; for (int i = 0; i < d->horizontalScale.size(); ++i) list << QPair(d->horizontalScale.at(i).step, QPointF(d->horizontalScale.at(i).value, d->verticalScale.at(i).value)); - + return list; } @@ -499,7 +499,7 @@ QList > QGraphicsItemAnimation::shearList() const QList > list; for (int i = 0; i < d->horizontalShear.size(); ++i) list << QPair(d->horizontalShear.at(i).step, QPointF(d->horizontalShear.at(i).value, d->verticalShear.at(i).value)); - + return list; } diff --git a/src/gui/graphicsview/qgraphicslayout.cpp b/src/gui/graphicsview/qgraphicslayout.cpp index 86b4589..91f386f 100644 --- a/src/gui/graphicsview/qgraphicslayout.cpp +++ b/src/gui/graphicsview/qgraphicslayout.cpp @@ -145,7 +145,7 @@ QT_BEGIN_NAMESPACE /*! Contructs a QGraphicsLayout object. - + \a parent is passed to QGraphicsLayoutItem's constructor and the QGraphicsLayoutItem's isLayout argument is set to \e true. @@ -259,7 +259,7 @@ void QGraphicsLayout::activate() return; d->activateRecursive(this); - + // we don't call activate on a sublayout, but somebody might. // Therefore, we walk to the parentitem of the toplevel layout. QGraphicsLayoutItem *parentItem = this; @@ -270,7 +270,7 @@ void QGraphicsLayout::activate() Q_ASSERT(!parentItem->isLayout()); setGeometry(parentItem->contentsRect()); // relayout children - + // ### bug, should be parentItem ? parentLayoutItem()->updateGeometry(); // bubble up; will set activated to false // ### too many resizes? maybe we should walk up the chain to the @@ -307,7 +307,7 @@ void QGraphicsLayout::invalidate() // does not call the base implementation? In addition, updateGeometry() // does more than we need. layoutItem->d_func()->sizeHintCacheDirty = true; - layoutItem = layoutItem->parentLayoutItem(); + layoutItem = layoutItem->parentLayoutItem(); } if (layoutItem) layoutItem->d_func()->sizeHintCacheDirty = true; @@ -347,7 +347,7 @@ void QGraphicsLayout::updateGeometry() widget. QGraphicsLayout uses this event handler to listen for layout related events such as geometry changes, layout changes or layout direction changes. - + \a e is a pointer to the event. You can reimplement this event handler to track similar events for your diff --git a/src/gui/graphicsview/qgraphicslayout_p.cpp b/src/gui/graphicsview/qgraphicslayout_p.cpp index 88652ec..163fc65 100644 --- a/src/gui/graphicsview/qgraphicslayout_p.cpp +++ b/src/gui/graphicsview/qgraphicslayout_p.cpp @@ -136,13 +136,13 @@ static bool removeLayoutItemFromLayout(QGraphicsLayout *lay, QGraphicsLayoutItem /*! \internal - This function is called from subclasses to add a layout item \a layoutItem + This function is called from subclasses to add a layout item \a layoutItem to a layout. It takes care of automatically reparenting graphics items, if needed. If \a layoutItem is a is already in a layout, it will remove it from that layout. - + */ void QGraphicsLayoutPrivate::addChildLayoutItem(QGraphicsLayoutItem *layoutItem) { @@ -150,14 +150,14 @@ void QGraphicsLayoutPrivate::addChildLayoutItem(QGraphicsLayoutItem *layoutItem) if (QGraphicsLayoutItem *maybeLayout = layoutItem->parentLayoutItem()) { if (maybeLayout->isLayout()) removeLayoutItemFromLayout(static_cast(maybeLayout), layoutItem); - } + } layoutItem->setParentLayoutItem(q); if (layoutItem->isLayout()) { if (QGraphicsItem *parItem = parentItem()) { static_cast(layoutItem)->d_func()->reparentChildItems(parItem); } } else { - if (QGraphicsItem *item = layoutItem->graphicsItem()) { + if (QGraphicsItem *item = layoutItem->graphicsItem()) { QGraphicsItem *newParent = parentItem(); QGraphicsItem *oldParent = item->parentItem(); if (oldParent == newParent || !newParent) @@ -182,7 +182,7 @@ void QGraphicsLayoutPrivate::activateRecursive(QGraphicsLayoutItem *item) QGraphicsLayout *layout = static_cast(item); if (layout->d_func()->activated) layout->invalidate(); - + for (int i = layout->count() - 1; i >= 0; --i) { QGraphicsLayoutItem *childItem = layout->itemAt(i); if (childItem) @@ -194,5 +194,5 @@ void QGraphicsLayoutPrivate::activateRecursive(QGraphicsLayoutItem *item) QT_END_NAMESPACE - + #endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicslayout_p.h b/src/gui/graphicsview/qgraphicslayout_p.h index 3083555..5c8e706 100644 --- a/src/gui/graphicsview/qgraphicslayout_p.h +++ b/src/gui/graphicsview/qgraphicslayout_p.h @@ -84,7 +84,7 @@ class QLayoutStyleInfo public: inline QLayoutStyleInfo() { invalidate(); } inline QLayoutStyleInfo(QStyle *style, QWidget *widget) - : m_valid(true), m_style(style), m_widget(widget) + : m_valid(true), m_style(style), m_widget(widget) { Q_ASSERT(style); if (widget) //### @@ -112,7 +112,7 @@ public: return m_defaultSpacing[o - 1]; } - inline qreal perItemSpacing(QSizePolicy::ControlType control1, + inline qreal perItemSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, Qt::Orientation orientation) const { @@ -132,7 +132,7 @@ class Q_AUTOTEST_EXPORT QGraphicsLayoutPrivate : public QGraphicsLayoutItemPriva Q_DECLARE_PUBLIC(QGraphicsLayout) public: - QGraphicsLayoutPrivate() : QGraphicsLayoutItemPrivate(0, true), left(-1.0), top(-1.0), right(-1.0), bottom(-1.0), + QGraphicsLayoutPrivate() : QGraphicsLayoutItemPrivate(0, true), left(-1.0), top(-1.0), right(-1.0), bottom(-1.0), activated(true) { } void reparentChildItems(QGraphicsItem *newParent); @@ -148,7 +148,7 @@ public: QT_END_NAMESPACE - + #endif //QT_NO_GRAPHICSVIEW #endif diff --git a/src/gui/graphicsview/qgraphicslayoutitem.cpp b/src/gui/graphicsview/qgraphicslayoutitem.cpp index 5a7f1af..f4d77f0 100644 --- a/src/gui/graphicsview/qgraphicslayoutitem.cpp +++ b/src/gui/graphicsview/qgraphicslayoutitem.cpp @@ -648,7 +648,7 @@ void QGraphicsLayoutItem::setMaximumHeight(qreal height) is equivalent to the item's position in parent coordinates). You must reimplement this function in a subclass of QGraphicsLayoutItem to - receive geometry updates. The layout will call this function when it does a + receive geometry updates. The layout will call this function when it does a rearrangement. If \a rect is outside of the bounds of minimumSize and maximumSize, it diff --git a/src/gui/graphicsview/qgraphicslayoutitem.h b/src/gui/graphicsview/qgraphicslayoutitem.h index f707c62..cb894a4 100644 --- a/src/gui/graphicsview/qgraphicslayoutitem.h +++ b/src/gui/graphicsview/qgraphicslayoutitem.h @@ -118,7 +118,7 @@ protected: private: QSizeF *effectiveSizeHints(const QSizeF &constraint) const; Q_DECLARE_PRIVATE(QGraphicsLayoutItem) - + friend class QGraphicsLayout; }; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index a83b528..8076a21 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3703,7 +3703,7 @@ void QGraphicsView::drawForeground(QPainter *painter, const QRectF &rect) } /*! - \obsolete + \obsolete Draws the items \a items in the scene using \a painter, after the background and before the foreground are drawn. \a numItems is the number diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp index 28070da..d503cff 100644 --- a/src/gui/graphicsview/qgraphicswidget_p.cpp +++ b/src/gui/graphicsview/qgraphicswidget_p.cpp @@ -761,7 +761,7 @@ void QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget *new QGraphicsWidget *firstOld = 0; bool wasPreviousNew = true; - + while (w != q) { bool isCurrentNew = q->isAncestorOf(w); if (isCurrentNew) { -- cgit v0.12 From 171ad741fda84384a64ce56c847de7667051914c Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 15 Jun 2010 02:49:18 +0200 Subject: Fix tst_QGlyphs to pass on Windows XP Hangul not supported on XP by default, so change the script in the tests to greek instead. --- tests/auto/qglyphs/tst_qglyphs.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/auto/qglyphs/tst_qglyphs.cpp b/tests/auto/qglyphs/tst_qglyphs.cpp index 90309ea..5df5889 100644 --- a/tests/auto/qglyphs/tst_qglyphs.cpp +++ b/tests/auto/qglyphs/tst_qglyphs.cpp @@ -46,7 +46,7 @@ #include #include -//#define DEBUG_SAVE_IMAGE +#define DEBUG_SAVE_IMAGE class tst_QGlyphs: public QObject { @@ -305,7 +305,7 @@ void tst_QGlyphs::drawNonExistentGlyphs() void tst_QGlyphs::drawMultiScriptText1() { QString text; - text += QChar(0x3131); // Hangul, Kiyeok + text += QChar(0x03D0); // Greek, beta QTextLayout textLayout(text); textLayout.beginLayout(); @@ -349,7 +349,7 @@ void tst_QGlyphs::drawMultiScriptText2() QString text; text += QChar(0x0621); // Arabic, Hamza - text += QChar(0x3131); // Hangul, Kiyeok + text += QChar(0x03D0); // Greek, beta QTextLayout textLayout(text); textLayout.beginLayout(); -- cgit v0.12 From 7b7f3869b15cee6f6815e10d49dcb8209a415edd Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 15 Jun 2010 09:29:57 +0200 Subject: Remove debug info from tst_QGlyphs Mistakenly added in 171ad741fda84384a64ce56c847de7667051914c. --- tests/auto/qglyphs/tst_qglyphs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qglyphs/tst_qglyphs.cpp b/tests/auto/qglyphs/tst_qglyphs.cpp index 5df5889..54a69dc 100644 --- a/tests/auto/qglyphs/tst_qglyphs.cpp +++ b/tests/auto/qglyphs/tst_qglyphs.cpp @@ -46,7 +46,7 @@ #include #include -#define DEBUG_SAVE_IMAGE +// #define DEBUG_SAVE_IMAGE class tst_QGlyphs: public QObject { -- cgit v0.12 From 4be622995ad6a46b10788f5d62ed2368cffcb3dd Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 16 Jun 2010 11:00:15 +0200 Subject: QListView: speedup QListView::setRowHidden() Basically the same optimisation that had been made long ago in the tree view: Use the right data structure for QListViewPrivate::hiddenRows (QSet instead of QVector) Task-number: QTBUG-11438 Reviewed-by: Gabriel --- src/gui/itemviews/qlistview.cpp | 13 ++++++++----- src/gui/itemviews/qlistview_p.h | 7 +++++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index 846d911..c20e0b1 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -756,10 +756,13 @@ void QListView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e // if the parent is above d->root in the tree, nothing will happen QAbstractItemView::rowsAboutToBeRemoved(parent, start, end); if (parent == d->root) { - for (int i = d->hiddenRows.count() - 1; i >= 0; --i) { - int hiddenRow = d->hiddenRows.at(i).row(); + QSet::iterator it = d->hiddenRows.begin(); + while (it != d->hiddenRows.end()) { + int hiddenRow = it->row(); if (hiddenRow >= start && hiddenRow <= end) { - d->hiddenRows.remove(i); + it = d->hiddenRows.erase(it); + } else { + ++it; } } } @@ -1849,12 +1852,12 @@ bool QListViewPrivate::dropOn(QDropEvent *event, int *dropRow, int *dropCol, QMo void QCommonListViewBase::appendHiddenRow(int row) { - dd->hiddenRows.append(dd->model->index(row, 0, qq->rootIndex())); + dd->hiddenRows.insert(dd->model->index(row, 0, qq->rootIndex())); } void QCommonListViewBase::removeHiddenRow(int row) { - dd->hiddenRows.remove(dd->hiddenRows.indexOf(dd->model->index(row, 0, qq->rootIndex()))); + dd->hiddenRows.remove(dd->model->index(row, 0, qq->rootIndex())); } void QCommonListViewBase::updateHorizontalScrollBar(const QSize &step) diff --git a/src/gui/itemviews/qlistview_p.h b/src/gui/itemviews/qlistview_p.h index 9ae1f50..1b71131 100644 --- a/src/gui/itemviews/qlistview_p.h +++ b/src/gui/itemviews/qlistview_p.h @@ -378,7 +378,10 @@ public: inline bool isSelectionRectVisible() const { return showElasticBand; } inline QModelIndex modelIndex(int row) const { return model->index(row, column, root); } - inline bool isHidden(int row) const { return hiddenRows.contains(model->index(row, 0, root)); } + inline bool isHidden(int row) const { + QModelIndex idx = model->index(row, 0, root); + return isPersistent(idx) && hiddenRows.contains(idx); + } inline bool isHiddenOrDisabled(int row) const { return isHidden(row) || !isIndexEnabled(modelIndex(row)); } inline void removeCurrentAndDisabled(QVector *indexes, const QModelIndex ¤t) const { @@ -432,7 +435,7 @@ public: QBasicTimer batchLayoutTimer; // used for hidden items - QVector hiddenRows; + QSet hiddenRows; int column; bool uniformItemSizes; -- cgit v0.12 From 660145873a05b159b2f96dab8f0eaa75499146ff Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 7 Jun 2010 16:26:52 +0200 Subject: qdrawhelper: Use SSE2 in fetchTransformedBilinear (when scalling up) It is possible to use SSE2 to speedup the smooth scaling of a pixmap Benchmark results: Drawing the home screen of Qt Creator: Qt 4.7: 45fps After last set of patches: 75fps After this patch: 95fps Reviewed-by: Samuel --- src/gui/painting/qdrawhelper.cpp | 85 +++++++++++++++++++++++++++++++++------- 1 file changed, 71 insertions(+), 14 deletions(-) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index a765102..51d841e 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -748,30 +748,87 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * int disty = (fy & 0x0000ffff) >> 8; int idisty = 256 - disty; int count = length * data->m11 + 2; - int x_ = fx >> 16; + int x = fx >> 16; - quint32 intermediate_buffer[buffer_size + 2][2]; + // The idea is first to do the interpolation between the row s1 and the row s2 + // into an intermediate buffer, then we interpolate between two pixel of this buffer. + + // intermediate_buffer[0] is a buffer of red-blue component of the pixel, in the form 0x00RR00BB + // intermediate_buffer[1] is the alpha-green component of the pixel, in the form 0x00AA00GG + quint32 intermediate_buffer[2][buffer_size + 2]; Q_ASSERT(length * data->m11 <= buffer_size); + int f = 0; + int lim = count; if (blendType == BlendTransformedBilinearTiled) { - x_ %= image_width; - if (x_ < 0) x_ += image_width; + x %= image_width; + if (x < 0) x += image_width; + } else { + lim = qMin(count, image_x2-x); + if (x < image_x1) { + Q_ASSERT(x < image_x2); + uint t = fetch(s1, image_x1, data->texture.colorTable); + uint b = fetch(s2, image_x1, data->texture.colorTable); + quint32 rb = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff; + quint32 ag = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff; + do { + intermediate_buffer[0][f] = rb; + intermediate_buffer[1][f] = ag; + f++; + x++; + } while (x < image_x1 && f < lim); + } } - for (int f = 0; f < count; f++) { - int x; + +#if defined(QT_ALWAYS_HAVE_SSE2) + if (blendType != BlendTransformedBilinearTiled && + (format == QImage::Format_ARGB32_Premultiplied || format == QImage::Format_RGB32)) { + + const __m128i disty_ = _mm_set1_epi16(disty); + const __m128i idisty_ = _mm_set1_epi16(idisty); + const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); + + lim -= 3; + for (; f < lim; x += 4, f += 4) { + // Load 4 pixels from s1, and split the alpha-green and red-blue component + __m128i top = _mm_loadu_si128((__m128i*)((const uint *)(s1)+x)); + __m128i topAG = _mm_srli_epi16(top, 8); + __m128i topRB = _mm_and_si128(top, colorMask); + // Multiplies each colour component by idisty + topAG = _mm_mullo_epi16 (topAG, idisty_); + topRB = _mm_mullo_epi16 (topRB, idisty_); + + // Same for the s2 vector + __m128i bottom = _mm_loadu_si128((__m128i*)((const uint *)(s2)+x)); + __m128i bottomAG = _mm_srli_epi16(bottom, 8); + __m128i bottomRB = _mm_and_si128(bottom, colorMask); + bottomAG = _mm_mullo_epi16 (bottomAG, disty_); + bottomRB = _mm_mullo_epi16 (bottomRB, disty_); + + // Add the values, and shift to only keep 8 significant bits per colors + __m128i rAG =_mm_add_epi16(topAG, bottomAG); + rAG = _mm_srli_epi16(rAG, 8); + _mm_storeu_si128((__m128i*)(&intermediate_buffer[1][f]), rAG); + __m128i rRB =_mm_add_epi16(topRB, bottomRB); + rRB = _mm_srli_epi16(rRB, 8); + _mm_storeu_si128((__m128i*)(&intermediate_buffer[0][f]), rRB); + } + } +#endif + for (; f < count; f++) { // Same as above but without sse2 if (blendType == BlendTransformedBilinearTiled) { - if (x_ >= image_width) x_ -= image_width; - x = x_; + if (x >= image_width) x -= image_width; } else { - x = qBound(image_x1, x_, image_x2 - 1); + x = qMin(x, image_x2 - 1); } uint t = fetch(s1, x, data->texture.colorTable); uint b = fetch(s2, x, data->texture.colorTable); - intermediate_buffer[f][0] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff; - intermediate_buffer[f][1] = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff; - x_++; + intermediate_buffer[0][f] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff; + intermediate_buffer[1][f] = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff; + x++; } + // Now interpolate the values from the intermediate_buffer to get the final result. fx &= fixed_scale - 1; Q_ASSERT((fx >> 16) == 0); while (b < end) { @@ -782,8 +839,8 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * register int distx = (fx & 0x0000ffff) >> 8; register int idistx = 256 - distx; - int rb = ((intermediate_buffer[x1][0] * idistx + intermediate_buffer[x2][0] * distx) >> 8) & 0xff00ff; - int ag = (intermediate_buffer[x1][1] * idistx + intermediate_buffer[x2][1] * distx) & 0xff00ff00; + int rb = ((intermediate_buffer[0][x1] * idistx + intermediate_buffer[0][x2] * distx) >> 8) & 0xff00ff; + int ag = (intermediate_buffer[1][x1] * idistx + intermediate_buffer[1][x2] * distx) & 0xff00ff00; *b = rb | ag; b++; fx += fdx; -- cgit v0.12 From fb23b6893d5228d3716ed0899ef089aeeafec3bf Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 18 Jun 2010 14:30:37 +0200 Subject: Fix compiler warning --- src/corelib/tools/qscopedpointer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qscopedpointer.h b/src/corelib/tools/qscopedpointer.h index e972d71..40d3851 100644 --- a/src/corelib/tools/qscopedpointer.h +++ b/src/corelib/tools/qscopedpointer.h @@ -213,7 +213,7 @@ public: } private: - explicit inline QScopedArrayPointer(void *p) { + explicit inline QScopedArrayPointer(void *) { // Enforce the same type. // If you get a compile error here, make sure you declare -- cgit v0.12