diff options
Diffstat (limited to 'src/gui/painting/qpainter.cpp')
-rw-r--r-- | src/gui/painting/qpainter.cpp | 77 |
1 files changed, 54 insertions, 23 deletions
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 3f387d575b..3af8fdea2e 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -229,16 +229,11 @@ QTransform QPainterPrivate::viewTransform() const int QPainterPrivate::effectiveDevicePixelRatio() const { - // Limited feature introduction for Qt 5.0.0, remove ifdef in a later release. -#ifdef Q_OS_MAC // Special cases for devices that does not support PdmDevicePixelRatio go here: if (device->devType() == QInternal::Printer) return 1; return qMax(1, device->metric(QPaintDevice::PdmDevicePixelRatio)); -#else - return 1; -#endif } QTransform QPainterPrivate::hidpiScaleTransform() const @@ -1111,6 +1106,11 @@ void QPainterPrivate::updateState(QPainterState *newState) \li \inlineimage qpainter-pathstroking.png \endtable + Text drawing is done using drawText(). When you need + fine-grained positioning, boundingRect() tells you where a given + drawText() command will draw. + + \section1 Drawing Pixmaps and Images There are functions to draw pixmaps/images, namely drawPixmap(), drawImage() and drawTiledPixmap(). Both drawPixmap() and drawImage() @@ -1118,15 +1118,25 @@ void QPainterPrivate::updateState(QPainterState *newState) on-screen while drawImage() may be faster on a QPrinter or other devices. - Text drawing is done using drawText(). When you need - fine-grained positioning, boundingRect() tells you where a given - drawText() command will draw. - There is a drawPicture() function that draws the contents of an entire QPicture. The drawPicture() function is the only function that disregards all the painter's settings as QPicture has its own settings. + \section2 Drawing High Resolution Versions of Pixmaps and Images + + High resolution versions of pixmaps have a \e{device pixel ratio} value larger + than 1 (see QImageReader, QPixmap::devicePixelRatio()). Should it match the value + of the underlying QPaintDevice, it is drawn directly onto the device with no + additional transformation applied. + + This is for example the case when drawing a QPixmap of 64x64 pixels size with + a device pixel ratio of 2 onto a high DPI screen which also has + a device pixel ratio of 2. Note that the pixmap is then effectively 32x32 + pixels in \e{user space}. Code paths in Qt that calculate layout geometry + based on the pixmap size will use this size. The net effect of this is that + the pixmap is displayed as high DPI pixmap rather than a large pixmap. + \section1 Rendering Quality To get the optimal rendering result using QPainter, you should use @@ -5029,6 +5039,8 @@ static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransfor into the given \a target in the paint device. \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree. + \note See \l{Drawing High Resolution Versions of Pixmaps and Images} on how this is affected + by QPixmap::devicePixelRatio(). \table 100% \row @@ -5043,7 +5055,7 @@ static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransfor transparent. Drawing bitmaps with gradient or texture colors is not supported. - \sa drawImage() + \sa drawImage(), QPixmap::devicePixelRatio() */ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm) { @@ -5607,6 +5619,8 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positio staticTextItem.numGlyphs = glyphCount; staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray)); staticTextItem.glyphPositions = positions; + // The font property is meaningless, the fontengine must be used directly: + staticTextItem.usesRawFont = true; extended->drawStaticTextItem(&staticTextItem); } else { @@ -6422,6 +6436,7 @@ void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QText continue; + multi->ensureEngineAt(which); QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start); ti2.width = 0; // set the high byte to zero and calc the width @@ -6449,6 +6464,7 @@ void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QText which = e; } + multi->ensureEngineAt(which); QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start); ti2.width = 0; // set the high byte to zero and calc the width @@ -7404,8 +7420,6 @@ void qt_format_text(const QFont &fnt, const QRectF &_r, tf |= Qt::TextDontPrint; uint maxUnderlines = 0; - int numUnderlines = 0; - QVarLengthArray<int, 32> underlinePositions(1); QFontMetricsF fm(fnt); QString text = str; @@ -7436,11 +7450,15 @@ start_lengthVariant: } } + // no need to do extra work for underlines if we don't paint + if (tf & Qt::TextDontPrint) + maxUnderlines = 0; + + QList<QTextLayout::FormatRange> underlineFormats; int length = offset - old_offset; if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) { - underlinePositions.resize(maxUnderlines + 1); - QChar *cout = text.data() + old_offset; + QChar *cout0 = cout; QChar *cin = cout; int l = length; while (l) { @@ -7450,8 +7468,24 @@ start_lengthVariant: --l; if (!l) break; - if (*cin != QLatin1Char('&') && !hidemnmemonic) - underlinePositions[numUnderlines++] = cout - text.data() - old_offset; + if (*cin != QLatin1Char('&') && !hidemnmemonic) { + QTextLayout::FormatRange range; + range.start = cout - cout0; + range.length = 1; + range.format.setFontUnderline(true); + underlineFormats.append(range); + } + } else if (hidemnmemonic && *cin == QLatin1Char('(') && l >= 4 && + cin[1] == QLatin1Char('&') && cin[2] != QLatin1Char('&') && + cin[3] == QLatin1Char(')')) { + int n = 0; + while ((cout - n) > cout0 && (cout - n - 1)->isSpace()) + ++n; + cout -= n; + cin += 4; + length -= n + 4; + l -= 4; + continue; } *cout = *cin; ++cout; @@ -7460,11 +7494,6 @@ start_lengthVariant: } } - // no need to do extra work for underlines if we don't paint - if (tf & Qt::TextDontPrint) - numUnderlines = 0; - - underlinePositions[numUnderlines] = -1; qreal height = 0; qreal width = 0; @@ -7497,7 +7526,7 @@ start_lengthVariant: engine.forceJustification = true; QTextLayout textLayout(&engine); textLayout.setCacheEnabled(true); - textLayout.engine()->underlinePositions = underlinePositions.data(); + textLayout.setAdditionalFormats(underlineFormats); if (finalText.isEmpty()) { height = fm.height(); @@ -7685,6 +7714,8 @@ void QPainterState::init(QPainter *p) { into the \a target rectangle in the paint device. \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree. + \note See \l{Drawing High Resolution Versions of Pixmaps and Images} on how this is affected + by QImage::devicePixelRatio(). If the image needs to be modified to fit in a lower-resolution result (e.g. converting from 32-bit to 8-bit), use the \a flags to @@ -7696,7 +7727,7 @@ void QPainterState::init(QPainter *p) { \snippet code/src_gui_painting_qpainter.cpp 20 \endtable - \sa drawPixmap() + \sa drawPixmap(), QImage::devicePixelRatio() */ /*! |