Changeset 846 for trunk/src/gui/painting/qpainter.cpp
- Timestamp:
- May 5, 2011, 5:36:53 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/vendor/nokia/qt/4.7.2 (added) merged: 845 /branches/vendor/nokia/qt/current merged: 844 /branches/vendor/nokia/qt/4.6.3 removed
- Property svn:mergeinfo changed
-
trunk/src/gui/painting/qpainter.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 39 39 ** 40 40 ****************************************************************************/ 41 41 42 // QtCore 42 43 #include <qdebug.h> … … 70 71 #include <private/qpaintengine_raster_p.h> 71 72 #include <private/qmath_p.h> 73 #include <qstatictext.h> 74 #include <private/qstatictext_p.h> 75 #include <private/qstylehelper_p.h> 72 76 73 77 QT_BEGIN_NAMESPACE … … 87 91 int tabstops, int* tabarray, int tabarraylen, 88 92 QPainter *painter); 93 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, 94 QTextCharFormat::UnderlineStyle underlineStyle, 95 const QTextItem::RenderFlags flags, qreal width, 96 const QTextCharFormat &charFormat); 97 // Helper function to calculate left most position, width and flags for decoration drawing 98 static void drawDecorationForGlyphs(QPainter *painter, const glyph_t *glyphArray, 99 const QFixedPoint *positions, int glyphCount, 100 QFontEngine *fontEngine, const QFont &font, 101 const QTextCharFormat &charFormat); 89 102 90 103 static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush) … … 684 697 skip = false; 685 698 686 QBrush penBrush = s->pen.brush();687 Qt::BrushStyle brushStyle = s->brush.style();688 Qt::BrushStyle penBrushStyle = penBrush.style();699 QBrush penBrush = (qpen_style(s->pen) == Qt::NoPen) ? QBrush(Qt::NoBrush) : qpen_brush(s->pen); 700 Qt::BrushStyle brushStyle = qbrush_style(s->brush); 701 Qt::BrushStyle penBrushStyle = qbrush_style(penBrush); 689 702 alpha = (penBrushStyle != Qt::NoBrush 690 703 && (penBrushStyle < Qt::LinearGradientPattern && penBrush.color().alpha() != 255) … … 968 981 device on which the painter paints, and paintEngine() returns the 969 982 paint engine that the painter is currently operating on. For more 970 information, see \l {The Paint System} documentation.983 information, see the \l {Paint System}. 971 984 972 985 Sometimes it is desirable to make someone else paint on an unusual … … 1013 1026 \o viewport(), window(), worldTransform() make up the painter's coordinate 1014 1027 transformation system. For more information, see the \l 1015 {Coordinate Transformations} section and the \l { TheCoordinate1028 {Coordinate Transformations} section and the \l {Coordinate 1016 1029 System} documentation. 1017 1030 … … 1220 1233 worldTransform(). A matrix transforms a point in the plane to another 1221 1234 point. For more information about the transformation matrix, see 1222 the \l { TheCoordinate System} and QTransform documentation.1235 the \l {Coordinate System} and QTransform documentation. 1223 1236 1224 1237 The setWorldTransform() function can replace or add to the currently … … 1242 1255 transformation matrix. 1243 1256 1244 See also \l { The Coordinate System} documentation.1257 See also \l {Coordinate System} 1245 1258 1246 1259 \section1 Clipping … … 1561 1574 d->engine->setDirty(QPaintEngine::DirtyFont); 1562 1575 } 1563 d->state->layoutDirection = widget->layoutDirection();1564 1576 } 1565 1577 … … 1871 1883 initFrom(widget); 1872 1884 } else { 1873 d->state->layoutDirection = Q Application::layoutDirection();1885 d->state->layoutDirection = Qt::LayoutDirectionAuto; 1874 1886 // make sure we have a font compatible with the paintdevice 1875 1887 d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device()); … … 2389 2401 return; 2390 2402 } 2403 if (d->state->composition_mode == mode) 2404 return; 2391 2405 if (d->extended) { 2392 2406 d->state->composition_mode = mode; … … 2704 2718 2705 2719 if (d->extended) { 2706 if ( !hasClipping() && (op == Qt::IntersectClip ||op == Qt::UniteClip))2720 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip)) 2707 2721 op = Qt::ReplaceClip; 2708 2722 … … 2762 2776 } 2763 2777 2764 if ( !hasClipping() && (op == Qt::IntersectClip ||op == Qt::UniteClip))2778 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip)) 2765 2779 op = Qt::ReplaceClip; 2766 2780 … … 2817 2831 } 2818 2832 2819 if ( !hasClipping() && (op == Qt::IntersectClip ||op == Qt::UniteClip))2833 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip)) 2820 2834 op = Qt::ReplaceClip; 2821 2835 … … 2878 2892 2879 2893 For more information about the coordinate system, transformations 2880 and window-viewport conversion, see \l {The Coordinate System} 2881 documentation. 2894 and window-viewport conversion, see \l {Coordinate System}. 2882 2895 2883 2896 \sa setWorldTransform(), QTransform … … 2899 2912 2900 2913 \sa {QPainter#Coordinate Transformations}{Coordinate Transformations}, 2901 { TheCoordinate System}2914 {Coordinate System} 2902 2915 */ 2903 2916 … … 3042 3055 false. 3043 3056 3044 \sa setWorldMatrixEnabled(), worldTransform(), { TheCoordinate System}3057 \sa setWorldMatrixEnabled(), worldTransform(), {Coordinate System} 3045 3058 */ 3046 3059 … … 3223 3236 } 3224 3237 3225 if ( !hasClipping() && (op == Qt::IntersectClip ||op == Qt::UniteClip))3238 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip)) 3226 3239 op = Qt::ReplaceClip; 3227 3240 … … 3384 3397 \endtable 3385 3398 3386 \sa drawLines(), drawPolyline(), { TheCoordinate System}3399 \sa drawLines(), drawPolyline(), {Coordinate System} 3387 3400 */ 3388 3401 … … 3431 3444 \endtable 3432 3445 3433 \sa drawRects(), drawPolygon(), { TheCoordinate System}3446 \sa drawRects(), drawPolygon(), {Coordinate System} 3434 3447 */ 3435 3448 … … 3595 3608 pen's color. 3596 3609 3597 \sa { TheCoordinate System}3610 \sa {Coordinate System} 3598 3611 */ 3599 3612 … … 3617 3630 the current pen's color. 3618 3631 3619 \sa { TheCoordinate System}3632 \sa {Coordinate System} 3620 3633 */ 3621 3634 void QPainter::drawPoints(const QPointF *points, int pointCount) … … 4223 4236 \endtable 4224 4237 4225 \sa drawPie(), { TheCoordinate System}4238 \sa drawPie(), {Coordinate System} 4226 4239 */ 4227 4240 void QPainter::drawEllipse(const QRectF &r) … … 4237 4250 4238 4251 QRectF rect(r.normalized()); 4239 if (rect.isEmpty())4240 return;4241 4252 4242 4253 if (d->extended) { … … 4280 4291 4281 4292 QRect rect(r.normalized()); 4282 if (rect.isEmpty())4283 return;4284 4293 4285 4294 if (d->extended) { … … 4353 4362 \endtable 4354 4363 4355 \sa drawPie(), drawChord(), { TheCoordinate System}4364 \sa drawPie(), drawChord(), {Coordinate System} 4356 4365 */ 4357 4366 … … 4417 4426 \endtable 4418 4427 4419 \sa drawEllipse(), drawChord(), { TheCoordinate System}4428 \sa drawEllipse(), drawChord(), {Coordinate System} 4420 4429 */ 4421 4430 void QPainter::drawPie(const QRectF &r, int a, int alen) … … 4486 4495 \endtable 4487 4496 4488 \sa drawArc(), drawPie(), { TheCoordinate System}4497 \sa drawArc(), drawPie(), {Coordinate System} 4489 4498 */ 4490 4499 void QPainter::drawChord(const QRectF &r, int a, int alen) … … 4777 4786 \endtable 4778 4787 4779 \sa drawLines(), drawPolygon(), { TheCoordinate System}4788 \sa drawLines(), drawPolygon(), {Coordinate System} 4780 4789 */ 4781 4790 void QPainter::drawPolyline(const QPointF *points, int pointCount) … … 4916 4925 rules. 4917 4926 4918 \sa drawConvexPolygon(), drawPolyline(), { TheCoordinate System}4927 \sa drawConvexPolygon(), drawPolyline(), {Coordinate System} 4919 4928 */ 4920 4929 void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule) … … 5067 5076 be faster than the drawPolygon() function. 5068 5077 5069 \sa drawPolygon(), drawPolyline(), { TheCoordinate System}5078 \sa drawPolygon(), drawPolyline(), {Coordinate System} 5070 5079 */ 5071 5080 … … 5412 5421 setBackgroundMode(Qt::TransparentMode); 5413 5422 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform); 5414 QBrush brush(d->state->pen.color(), pm); 5423 QBrush brush; 5424 5425 if (sw == pm.width() && sh == pm.height()) 5426 brush = QBrush(d->state->pen.color(), pm); 5427 else 5428 brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh)); 5429 5415 5430 setBrush(brush); 5416 5431 setPen(Qt::NoPen); 5417 setBrushOrigin(QPointF(-sx, -sy));5418 5432 5419 5433 drawRect(QRectF(0, 0, sw, sh)); … … 5698 5712 } 5699 5713 5714 5715 void qt_draw_glyphs(QPainter *painter, const quint32 *glyphArray, const QPointF *positionArray, 5716 int glyphCount) 5717 { 5718 QPainterPrivate *painter_d = QPainterPrivate::get(painter); 5719 painter_d->drawGlyphs(glyphArray, positionArray, glyphCount); 5720 } 5721 5722 void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *positionArray, 5723 int glyphCount) 5724 { 5725 updateState(state); 5726 5727 QFontEngine *fontEngine = state->font.d->engineForScript(QUnicodeTables::Common); 5728 5729 while (fontEngine->type() == QFontEngine::Multi) { 5730 // Pick engine based on first glyph in array if we are using a multi engine. 5731 // (all glyphs must be for same font) 5732 int engineIdx = 0; 5733 if (glyphCount > 0) 5734 engineIdx = glyphArray[0] >> 24; 5735 5736 fontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx); 5737 } 5738 5739 QVarLengthArray<QFixedPoint, 128> positions; 5740 for (int i=0; i<glyphCount; ++i) { 5741 QFixedPoint fp = QFixedPoint::fromPointF(positionArray[i]); 5742 positions.append(fp); 5743 } 5744 5745 if (extended != 0) { 5746 QStaticTextItem staticTextItem; 5747 staticTextItem.color = state->pen.color(); 5748 staticTextItem.font = state->font; 5749 staticTextItem.setFontEngine(fontEngine); 5750 staticTextItem.numGlyphs = glyphCount; 5751 staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray)); 5752 staticTextItem.glyphPositions = positions.data(); 5753 5754 extended->drawStaticTextItem(&staticTextItem); 5755 } else { 5756 QTextItemInt textItem; 5757 textItem.f = &state->font; 5758 textItem.fontEngine = fontEngine; 5759 5760 QVarLengthArray<QFixed, 128> advances(glyphCount); 5761 QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount); 5762 QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount); 5763 qMemSet(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes)); 5764 qMemSet(advances.data(), 0, advances.size() * sizeof(QFixed)); 5765 qMemSet(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification)); 5766 5767 textItem.glyphs.numGlyphs = glyphCount; 5768 textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray)); 5769 textItem.glyphs.offsets = positions.data(); 5770 textItem.glyphs.advances_x = advances.data(); 5771 textItem.glyphs.advances_y = advances.data(); 5772 textItem.glyphs.justifications = glyphJustifications.data(); 5773 textItem.glyphs.attributes = glyphAttributes.data(); 5774 5775 engine->drawTextItem(QPointF(0, 0), textItem); 5776 } 5777 } 5778 5779 /*! 5780 5781 \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText) 5782 \since 4.7 5783 \overload 5784 5785 Draws the \a staticText at the \a topLeftPosition. 5786 5787 \note The y-position is used as the top of the font. 5788 5789 */ 5790 5791 /*! 5792 \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText) 5793 \since 4.7 5794 \overload 5795 5796 Draws the \a staticText at coordinates \a left and \a top. 5797 5798 \note The y-position is used as the top of the font. 5799 */ 5800 5700 5801 /*! 5701 5802 \fn void QPainter::drawText(const QPointF &position, const QString &text) … … 5721 5822 5722 5823 /*! 5824 \since 4.7 5825 5826 Draws the given \a staticText at the given \a topLeftPosition. 5827 5828 The text will be drawn using the font and the transformation set on the painter. If the 5829 font and/or transformation set on the painter are different from the ones used to initialize 5830 the layout of the QStaticText, then the layout will have to be recalculated. Use 5831 QStaticText::prepare() to initialize \a staticText with the font and transformation with which 5832 it will later be drawn. 5833 5834 If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was 5835 last drawn, then there will be a slight overhead when translating the text to its new position. 5836 5837 \note If the painter's transformation is not affine, then \a staticText will be drawn using 5838 regular calls to drawText(), losing any potential for performance improvement. 5839 5840 \note The y-position is used as the top of the font. 5841 5842 \sa QStaticText 5843 */ 5844 void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText) 5845 { 5846 Q_D(QPainter); 5847 if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen) 5848 return; 5849 5850 QStaticTextPrivate *staticText_d = 5851 const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText)); 5852 5853 if (font() != staticText_d->font) { 5854 staticText_d->font = font(); 5855 staticText_d->needsRelayout = true; 5856 } 5857 5858 // If we don't have an extended paint engine, or if the painter is projected, 5859 // we go through standard code path 5860 if (d->extended == 0 || !d->state->matrix.isAffine()) { 5861 staticText_d->paintText(topLeftPosition, this); 5862 return; 5863 } 5864 5865 bool paintEngineSupportsTransformations = d->extended->type() == QPaintEngine::OpenGL2 5866 || d->extended->type() == QPaintEngine::OpenVG 5867 || d->extended->type() == QPaintEngine::OpenGL; 5868 5869 if (paintEngineSupportsTransformations && !staticText_d->untransformedCoordinates) { 5870 staticText_d->untransformedCoordinates = true; 5871 staticText_d->needsRelayout = true; 5872 } else if (!paintEngineSupportsTransformations && staticText_d->untransformedCoordinates) { 5873 staticText_d->untransformedCoordinates = false; 5874 staticText_d->needsRelayout = true; 5875 } 5876 5877 // Don't recalculate entire layout because of translation, rather add the dx and dy 5878 // into the position to move each text item the correct distance. 5879 QPointF transformedPosition = topLeftPosition; 5880 if (!staticText_d->untransformedCoordinates) 5881 transformedPosition = transformedPosition * d->state->matrix; 5882 QTransform oldMatrix; 5883 5884 // The translation has been applied to transformedPosition. Remove translation 5885 // component from matrix. 5886 if (d->state->matrix.isTranslating() && !staticText_d->untransformedCoordinates) { 5887 qreal m11 = d->state->matrix.m11(); 5888 qreal m12 = d->state->matrix.m12(); 5889 qreal m13 = d->state->matrix.m13(); 5890 qreal m21 = d->state->matrix.m21(); 5891 qreal m22 = d->state->matrix.m22(); 5892 qreal m23 = d->state->matrix.m23(); 5893 qreal m33 = d->state->matrix.m33(); 5894 5895 oldMatrix = d->state->matrix; 5896 d->state->matrix.setMatrix(m11, m12, m13, 5897 m21, m22, m23, 5898 0.0, 0.0, m33); 5899 } 5900 5901 // If the transform is not identical to the text transform, 5902 // we have to relayout the text (for other transformations than plain translation) 5903 bool staticTextNeedsReinit = staticText_d->needsRelayout; 5904 if (!staticText_d->untransformedCoordinates && staticText_d->matrix != d->state->matrix) { 5905 staticText_d->matrix = d->state->matrix; 5906 staticTextNeedsReinit = true; 5907 } 5908 5909 // Recreate the layout of the static text because the matrix or font has changed 5910 if (staticTextNeedsReinit) 5911 staticText_d->init(); 5912 5913 if (transformedPosition != staticText_d->position) { // Translate to actual position 5914 QFixed fx = QFixed::fromReal(transformedPosition.x()); 5915 QFixed fy = QFixed::fromReal(transformedPosition.y()); 5916 QFixed oldX = QFixed::fromReal(staticText_d->position.x()); 5917 QFixed oldY = QFixed::fromReal(staticText_d->position.y()); 5918 for (int item=0; item<staticText_d->itemCount;++item) { 5919 QStaticTextItem *textItem = staticText_d->items + item; 5920 for (int i=0; i<textItem->numGlyphs; ++i) { 5921 textItem->glyphPositions[i].x += fx - oldX; 5922 textItem->glyphPositions[i].y += fy - oldY; 5923 } 5924 textItem->userDataNeedsUpdate = true; 5925 } 5926 5927 staticText_d->position = transformedPosition; 5928 } 5929 5930 QPen oldPen = d->state->pen; 5931 QColor currentColor = oldPen.color(); 5932 for (int i=0; i<staticText_d->itemCount; ++i) { 5933 QStaticTextItem *item = staticText_d->items + i; 5934 if (item->color.isValid() && currentColor != item->color) { 5935 setPen(item->color); 5936 currentColor = item->color; 5937 } 5938 d->extended->drawStaticTextItem(item); 5939 5940 drawDecorationForGlyphs(this, item->glyphs, item->glyphPositions, 5941 item->numGlyphs, item->fontEngine(), staticText_d->font, 5942 QTextCharFormat()); 5943 } 5944 if (currentColor != oldPen.color()) 5945 setPen(oldPen); 5946 5947 if (!staticText_d->untransformedCoordinates && oldMatrix.isTranslating()) 5948 d->state->matrix = oldMatrix; 5949 } 5950 5951 /*! 5723 5952 \internal 5724 5953 */ … … 5734 5963 if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen) 5735 5964 return; 5965 5966 if (tf & Qt::TextBypassShaping) { 5967 // Skip harfbuzz complex shaping, shape using glyph advances only 5968 int len = str.length(); 5969 int numGlyphs = len; 5970 QVarLengthGlyphLayoutArray glyphs(len); 5971 QFontEngine *fontEngine = d->state->font.d->engineForScript(QUnicodeTables::Common); 5972 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) { 5973 glyphs.resize(numGlyphs); 5974 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) 5975 Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice"); 5976 } 5977 5978 QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine); 5979 drawTextItem(p, gf); 5980 return; 5981 } 5736 5982 5737 5983 QStackTextEngine engine(str, d->state->font); … … 5940 6186 By default, QPainter draws text anti-aliased. 5941 6187 5942 \note The y-position is used as the baselineof the font.6188 \note The y-position is used as the top of the font. 5943 6189 5944 6190 \sa Qt::AlignmentFlag, Qt::TextFlag … … 6015 6261 const qreal radiusBase = qMax(qreal(1), maxRadius); 6016 6262 6017 QString key = QLatin1String("WaveUnderline-"); 6018 key += pen.color().name(); 6019 key += QLatin1Char('-'); 6020 key += QString::number(radiusBase); 6263 QString key = QLatin1Literal("WaveUnderline-") 6264 % pen.color().name() 6265 % HexString<qreal>(radiusBase); 6021 6266 6022 6267 QPixmap pixmap; … … 6063 6308 } 6064 6309 6065 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QTextItemInt &ti) 6066 { 6067 QTextCharFormat::UnderlineStyle underlineStyle = ti.underlineStyle; 6310 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, 6311 QTextCharFormat::UnderlineStyle underlineStyle, 6312 const QTextItem::RenderFlags flags, qreal width, 6313 const QTextCharFormat &charFormat) 6314 { 6068 6315 if (underlineStyle == QTextCharFormat::NoUnderline 6069 && !(ti.flags & (QTextItem::StrikeOut | QTextItem::Overline))) 6070 return; 6071 6072 QFontEngine *fe = ti.fontEngine; 6316 && !(flags & (QTextItem::StrikeOut | QTextItem::Overline))) 6317 return; 6073 6318 6074 6319 const QPen oldPen = painter->pen(); … … 6080 6325 pen.setCapStyle(Qt::FlatCap); 6081 6326 6082 QLineF line(pos.x(), pos.y(), pos.x() + ti.width.toReal(), pos.y());6327 QLineF line(pos.x(), pos.y(), pos.x() + width, pos.y()); 6083 6328 6084 6329 const qreal underlineOffset = fe->underlinePosition().toReal(); … … 6095 6340 painter->translate(0, pos.y() + 1); 6096 6341 6097 QColor uc = ti.charFormat.underlineColor();6342 QColor uc = charFormat.underlineColor(); 6098 6343 if (uc.isValid()) 6099 6344 pen.setColor(uc); … … 6101 6346 // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms 6102 6347 const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen); 6103 const int descent = (int) ti.descent.toReal();6348 const int descent = (int) fe->descent().toReal(); 6104 6349 6105 6350 painter->setBrushOrigin(painter->brushOrigin().x(), 0); 6106 painter->fillRect(pos.x(), 0, qCeil( ti.width.toReal()), qMin(wave.height(), descent), wave);6351 painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave); 6107 6352 painter->restore(); 6108 6353 } else if (underlineStyle != QTextCharFormat::NoUnderline) { 6109 6354 QLineF underLine(line.x1(), underlinePos, line.x2(), underlinePos); 6110 6355 6111 QColor uc = ti.charFormat.underlineColor();6356 QColor uc = charFormat.underlineColor(); 6112 6357 if (uc.isValid()) 6113 6358 pen.setColor(uc); … … 6121 6366 pen.setColor(oldPen.color()); 6122 6367 6123 if ( ti.flags & QTextItem::StrikeOut) {6368 if (flags & QTextItem::StrikeOut) { 6124 6369 QLineF strikeOutLine = line; 6125 6370 strikeOutLine.translate(0., - fe->ascent().toReal() / 3.); … … 6128 6373 } 6129 6374 6130 if ( ti.flags & QTextItem::Overline) {6375 if (flags & QTextItem::Overline) { 6131 6376 QLineF overLine = line; 6132 6377 overLine.translate(0., - fe->ascent().toReal()); … … 6137 6382 painter->setPen(oldPen); 6138 6383 painter->setBrush(oldBrush); 6384 } 6385 6386 static void drawDecorationForGlyphs(QPainter *painter, const glyph_t *glyphArray, 6387 const QFixedPoint *positions, int glyphCount, 6388 QFontEngine *fontEngine, const QFont &font, 6389 const QTextCharFormat &charFormat) 6390 { 6391 if (!(font.underline() || font.strikeOut() || font.overline())) 6392 return; 6393 6394 QFixed leftMost; 6395 QFixed rightMost; 6396 QFixed baseLine; 6397 for (int i=0; i<glyphCount; ++i) { 6398 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]); 6399 if (i == 0 || leftMost > positions[i].x) 6400 leftMost = positions[i].x; 6401 6402 // We don't support glyphs that do not share a common baseline. If this turns out to 6403 // be a relevant use case, then we need to find clusters of glyphs that share a baseline 6404 // and do a drawTextItemDecorations call per cluster. 6405 if (i == 0 || baseLine < positions[i].y) 6406 baseLine = positions[i].y; 6407 6408 // We use the advance rather than the actual bounds to match the algorithm in drawText() 6409 if (i == 0 || rightMost < positions[i].x + gm.xoff) 6410 rightMost = positions[i].x + gm.xoff; 6411 } 6412 6413 QFixed width = rightMost - leftMost; 6414 QTextItem::RenderFlags flags = 0; 6415 6416 if (font.underline()) 6417 flags |= QTextItem::Underline; 6418 if (font.overline()) 6419 flags |= QTextItem::Overline; 6420 if (font.strikeOut()) 6421 flags |= QTextItem::StrikeOut; 6422 6423 drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()), 6424 fontEngine, 6425 font.underline() ? QTextCharFormat::SingleUnderline 6426 : QTextCharFormat::NoUnderline, flags, 6427 width.toReal(), charFormat); 6139 6428 } 6140 6429 … … 6269 6558 d->engine->drawTextItem(p, ti); 6270 6559 } 6271 drawTextItemDecoration(this, p, ti); 6560 drawTextItemDecoration(this, p, ti.fontEngine, ti.underlineStyle, ti.flags, ti.width.toReal(), 6561 ti.charFormat); 6272 6562 6273 6563 if (d->state->renderHints != oldRenderHints) { … … 6909 7199 rectangle. 6910 7200 6911 \sa window(), viewTransformEnabled(), { TheCoordinate7201 \sa window(), viewTransformEnabled(), {Coordinate 6912 7202 System#Window-Viewport Conversion}{Window-Viewport Conversion} 6913 7203 */ … … 6973 7263 rectangle. 6974 7264 6975 \sa viewport(), viewTransformEnabled() { TheCoordinate7265 \sa viewport(), viewTransformEnabled() {Coordinate 6976 7266 System#Window-Viewport Conversion}{Window-Viewport Conversion} 6977 7267 */ … … 7057 7347 view transformations if \a enable is false. 7058 7348 7059 \sa viewTransformEnabled(), { TheCoordinate System#Window-Viewport7349 \sa viewTransformEnabled(), {Coordinate System#Window-Viewport 7060 7350 Conversion}{Window-Viewport Conversion} 7061 7351 */ … … 7807 8097 QTextLine line = textLayout.lineAt(i); 7808 8098 7809 qreal advance = textLayout.engine()->lines[i].textAdvance.toReal();8099 qreal advance = line.horizontalAdvance(); 7810 8100 if (tf & Qt::AlignRight) 7811 8101 xoff = r.width() - advance; … … 7826 8116 to the specified \a direction. 7827 8117 7828 \sa layoutDirection(), drawText(), {QPainter#Settings}{Settings} 8118 The default is Qt::LayoutDirectionAuto, which will implicitly determine the 8119 direction from the text drawn. 8120 8121 \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings} 7829 8122 */ 7830 8123 void QPainter::setLayoutDirection(Qt::LayoutDirection direction) … … 7838 8131 Returns the layout direction used by the painter when drawing text. 7839 8132 7840 \sa setLayoutDirection(), drawText(), {QPainter#Settings}{Settings}8133 \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings} 7841 8134 */ 7842 8135 Qt::LayoutDirection QPainter::layoutDirection() const 7843 8136 { 7844 8137 Q_D(const QPainter); 7845 return d->state ? d->state->layoutDirection : Qt::L eftToRight;8138 return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto; 7846 8139 } 7847 8140 … … 8506 8799 8507 8800 /*! 8508 Returns w ether clipping is enabled or not in the current paint8801 Returns whether clipping is enabled or not in the current paint 8509 8802 engine state. 8510 8803 … … 8716 9009 } 8717 9010 9011 /*! 9012 \since 4.7 9013 9014 This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap, 9015 at multiple positions with different scale, rotation and opacity. \a 9016 fragments is an array of \a fragmentCount elements specifying the 9017 parameters used to draw each pixmap fragment. The \a hints 9018 parameter can be used to pass in drawing hints. 9019 9020 This function is potentially faster than multiple calls to drawPixmap(), 9021 since the backend can optimize state changes. 9022 9023 \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint 9024 */ 9025 9026 void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount, 9027 const QPixmap &pixmap, PixmapFragmentHints hints) 9028 { 9029 Q_D(QPainter); 9030 9031 if (!d->engine || pixmap.isNull()) 9032 return; 9033 9034 #ifndef QT_NO_DEBUG 9035 for (int i = 0; i < fragmentCount; ++i) { 9036 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop, 9037 fragments[i].width, fragments[i].height); 9038 if (!(QRectF(pixmap.rect()).contains(sourceRect))) 9039 qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle"); 9040 } 9041 #endif 9042 9043 if (d->engine->isExtended()) { 9044 d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints); 9045 } else { 9046 qreal oldOpacity = opacity(); 9047 QTransform oldTransform = transform(); 9048 9049 for (int i = 0; i < fragmentCount; ++i) { 9050 QTransform transform = oldTransform; 9051 qreal xOffset = 0; 9052 qreal yOffset = 0; 9053 if (fragments[i].rotation == 0) { 9054 xOffset = fragments[i].x; 9055 yOffset = fragments[i].y; 9056 } else { 9057 transform.translate(fragments[i].x, fragments[i].y); 9058 transform.rotate(fragments[i].rotation); 9059 } 9060 setOpacity(oldOpacity * fragments[i].opacity); 9061 setTransform(transform); 9062 9063 qreal w = fragments[i].scaleX * fragments[i].width; 9064 qreal h = fragments[i].scaleY * fragments[i].height; 9065 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop, 9066 fragments[i].width, fragments[i].height); 9067 drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, sourceRect); 9068 } 9069 9070 setOpacity(oldOpacity); 9071 setTransform(oldTransform); 9072 } 9073 } 9074 9075 /*! 9076 \since 4.7 9077 \class QPainter::PixmapFragment 9078 9079 \brief This class is used in conjunction with the 9080 QPainter::drawPixmapFragments() function to specify how a pixmap, or 9081 sub-rect of a pixmap, is drawn. 9082 9083 The \a sourceLeft, \a sourceTop, \a width and \a height variables are used 9084 as a source rectangle within the pixmap passed into the 9085 QPainter::drawPixmapFragments() function. The variables \a x, \a y, \a 9086 width and \a height are used to calculate the target rectangle that is 9087 drawn. \a x and \a y denotes the center of the target rectangle. The \a 9088 width and \a height in the target rectangle is scaled by the \a scaleX and 9089 \a scaleY values. The resulting target rectangle is then rotated \a 9090 rotation degrees around the \a x, \a y center point. 9091 9092 \sa QPainter::drawPixmapFragments() 9093 */ 9094 9095 /*! 9096 \since 4.7 9097 9098 This is a convenience function that returns a QPainter::PixmapFragment that is 9099 initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a 9100 rotation, \a opacity parameters. 9101 */ 9102 9103 QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect, 9104 qreal scaleX, qreal scaleY, qreal rotation, 9105 qreal opacity) 9106 { 9107 PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(), 9108 sourceRect.height(), scaleX, scaleY, rotation, opacity}; 9109 return fragment; 9110 } 9111 9112 /*! 9113 \variable QPainter::PixmapFragment::x 9114 \brief the x coordinate of center point in the target rectangle. 9115 */ 9116 9117 /*! 9118 \variable QPainter::PixmapFragment::y 9119 \brief the y coordinate of the center point in the target rectangle. 9120 */ 9121 9122 /*! 9123 \variable QPainter::PixmapFragment::sourceLeft 9124 \brief the left coordinate of the source rectangle. 9125 */ 9126 9127 /*! 9128 \variable QPainter::PixmapFragment::sourceTop 9129 \brief the top coordinate of the source rectangle. 9130 */ 9131 9132 /*! 9133 \variable QPainter::PixmapFragment::width 9134 9135 \brief the width of the source rectangle and is used to calculate the width 9136 of the target rectangle. 9137 */ 9138 9139 /*! 9140 \variable QPainter::PixmapFragment::height 9141 9142 \brief the height of the source rectangle and is used to calculate the 9143 height of the target rectangle. 9144 */ 9145 9146 /*! 9147 \variable QPainter::PixmapFragment::scaleX 9148 \brief the horizontal scale of the target rectangle. 9149 */ 9150 9151 /*! 9152 \variable QPainter::PixmapFragment::scaleY 9153 \brief the vertical scale of the target rectangle. 9154 */ 9155 9156 /*! 9157 \variable QPainter::PixmapFragment::rotation 9158 9159 \brief the rotation of the target rectangle in degrees. The target 9160 rectangle is rotated after it has been scaled. 9161 */ 9162 9163 /*! 9164 \variable QPainter::PixmapFragment::opacity 9165 9166 \brief the opacity of the target rectangle, where 0.0 is fully transparent 9167 and 1.0 is fully opaque. 9168 */ 9169 9170 /*! 9171 \since 4.7 9172 9173 \enum QPainter::PixmapFragmentHint 9174 9175 \value OpaqueHint Indicates that the pixmap fragments to be drawn are 9176 opaque. Opaque fragments are potentially faster to draw. 9177 9178 \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment 9179 */ 9180 8718 9181 void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation) 8719 9182 {
Note:
See TracChangeset
for help on using the changeset viewer.