Ignore:
Timestamp:
May 5, 2011, 5:36:53 AM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/gui/painting/qpainter.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    3939**
    4040****************************************************************************/
     41
    4142// QtCore
    4243#include <qdebug.h>
     
    7071#include <private/qpaintengine_raster_p.h>
    7172#include <private/qmath_p.h>
     73#include <qstatictext.h>
     74#include <private/qstatictext_p.h>
     75#include <private/qstylehelper_p.h>
    7276
    7377QT_BEGIN_NAMESPACE
     
    8791                    int tabstops, int* tabarray, int tabarraylen,
    8892                    QPainter *painter);
     93static 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
     98static void drawDecorationForGlyphs(QPainter *painter, const glyph_t *glyphArray,
     99                                    const QFixedPoint *positions, int glyphCount,
     100                                    QFontEngine *fontEngine, const QFont &font,
     101                                    const QTextCharFormat &charFormat);
    89102
    90103static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush)
     
    684697        skip = false;
    685698
    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);
    689702        alpha = (penBrushStyle != Qt::NoBrush
    690703                 && (penBrushStyle < Qt::LinearGradientPattern && penBrush.color().alpha() != 255)
     
    968981    device on which the painter paints, and paintEngine() returns the
    969982    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}.
    971984
    972985    Sometimes it is desirable to make someone else paint on an unusual
     
    10131026    \o viewport(), window(), worldTransform() make up the painter's coordinate
    10141027        transformation system. For more information, see the \l
    1015         {Coordinate Transformations} section and the \l {The Coordinate
     1028        {Coordinate Transformations} section and the \l {Coordinate
    10161029        System} documentation.
    10171030
     
    12201233    worldTransform(). A matrix transforms a point in the plane to another
    12211234    point. For more information about the transformation matrix, see
    1222     the \l {The Coordinate System} and QTransform documentation.
     1235    the \l {Coordinate System} and QTransform documentation.
    12231236
    12241237    The setWorldTransform() function can replace or add to the currently
     
    12421255    transformation matrix.
    12431256
    1244     See also \l {The Coordinate System} documentation.
     1257    See also \l {Coordinate System}
    12451258
    12461259    \section1 Clipping
     
    15611574        d->engine->setDirty(QPaintEngine::DirtyFont);
    15621575    }
    1563     d->state->layoutDirection = widget->layoutDirection();
    15641576}
    15651577
     
    18711883        initFrom(widget);
    18721884    } else {
    1873         d->state->layoutDirection = QApplication::layoutDirection();
     1885        d->state->layoutDirection = Qt::LayoutDirectionAuto;
    18741886        // make sure we have a font compatible with the paintdevice
    18751887        d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
     
    23892401        return;
    23902402    }
     2403    if (d->state->composition_mode == mode)
     2404        return;
    23912405    if (d->extended) {
    23922406        d->state->composition_mode = mode;
     
    27042718
    27052719    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))
    27072721            op = Qt::ReplaceClip;
    27082722
     
    27622776    }
    27632777
    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))
    27652779        op = Qt::ReplaceClip;
    27662780
     
    28172831    }
    28182832
    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))
    28202834        op = Qt::ReplaceClip;
    28212835
     
    28782892
    28792893    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}.
    28822895
    28832896    \sa setWorldTransform(), QTransform
     
    28992912
    29002913    \sa {QPainter#Coordinate Transformations}{Coordinate Transformations},
    2901     {The Coordinate System}
     2914    {Coordinate System}
    29022915*/
    29032916
     
    30423055    false.
    30433056
    3044     \sa setWorldMatrixEnabled(), worldTransform(), {The Coordinate System}
     3057    \sa setWorldMatrixEnabled(), worldTransform(), {Coordinate System}
    30453058*/
    30463059
     
    32233236    }
    32243237
    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))
    32263239        op = Qt::ReplaceClip;
    32273240
     
    33843397    \endtable
    33853398
    3386     \sa drawLines(), drawPolyline(), {The Coordinate System}
     3399    \sa drawLines(), drawPolyline(), {Coordinate System}
    33873400*/
    33883401
     
    34313444    \endtable
    34323445
    3433     \sa drawRects(), drawPolygon(), {The Coordinate System}
     3446    \sa drawRects(), drawPolygon(), {Coordinate System}
    34343447*/
    34353448
     
    35953608    pen's color.
    35963609
    3597     \sa {The Coordinate System}
     3610    \sa {Coordinate System}
    35983611*/
    35993612
     
    36173630    the current pen's color.
    36183631
    3619     \sa {The Coordinate System}
     3632    \sa {Coordinate System}
    36203633*/
    36213634void QPainter::drawPoints(const QPointF *points, int pointCount)
     
    42234236    \endtable
    42244237
    4225     \sa drawPie(), {The Coordinate System}
     4238    \sa drawPie(), {Coordinate System}
    42264239*/
    42274240void QPainter::drawEllipse(const QRectF &r)
     
    42374250
    42384251    QRectF rect(r.normalized());
    4239     if (rect.isEmpty())
    4240         return;
    42414252
    42424253    if (d->extended) {
     
    42804291
    42814292    QRect rect(r.normalized());
    4282     if (rect.isEmpty())
    4283         return;
    42844293
    42854294    if (d->extended) {
     
    43534362    \endtable
    43544363
    4355     \sa drawPie(), drawChord(), {The Coordinate System}
     4364    \sa drawPie(), drawChord(), {Coordinate System}
    43564365*/
    43574366
     
    44174426    \endtable
    44184427
    4419     \sa drawEllipse(), drawChord(), {The Coordinate System}
     4428    \sa drawEllipse(), drawChord(), {Coordinate System}
    44204429*/
    44214430void QPainter::drawPie(const QRectF &r, int a, int alen)
     
    44864495    \endtable
    44874496
    4488     \sa drawArc(), drawPie(), {The Coordinate System}
     4497    \sa drawArc(), drawPie(), {Coordinate System}
    44894498*/
    44904499void QPainter::drawChord(const QRectF &r, int a, int alen)
     
    47774786    \endtable
    47784787
    4779     \sa drawLines(), drawPolygon(), {The Coordinate System}
     4788    \sa drawLines(), drawPolygon(), {Coordinate System}
    47804789*/
    47814790void QPainter::drawPolyline(const QPointF *points, int pointCount)
     
    49164925    rules.
    49174926
    4918     \sa  drawConvexPolygon(), drawPolyline(), {The Coordinate System}
     4927    \sa  drawConvexPolygon(), drawPolyline(), {Coordinate System}
    49194928*/
    49204929void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
     
    50675076    be faster than the drawPolygon() function.
    50685077
    5069     \sa drawPolygon(), drawPolyline(), {The Coordinate System}
     5078    \sa drawPolygon(), drawPolyline(), {Coordinate System}
    50705079*/
    50715080
     
    54125421        setBackgroundMode(Qt::TransparentMode);
    54135422        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
    54155430        setBrush(brush);
    54165431        setPen(Qt::NoPen);
    5417         setBrushOrigin(QPointF(-sx, -sy));
    54185432
    54195433        drawRect(QRectF(0, 0, sw, sh));
     
    56985712}
    56995713
     5714
     5715void 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
     5722void 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
    57005801/*!
    57015802    \fn void QPainter::drawText(const QPointF &position, const QString &text)
     
    57215822
    57225823/*!
     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*/
     5844void 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/*!
    57235952   \internal
    57245953*/
     
    57345963    if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen)
    57355964        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    }
    57365982
    57375983    QStackTextEngine engine(str, d->state->font);
     
    59406186    By default, QPainter draws text anti-aliased.
    59416187
    5942     \note The y-position is used as the baseline of the font.
     6188    \note The y-position is used as the top of the font.
    59436189
    59446190    \sa Qt::AlignmentFlag, Qt::TextFlag
     
    60156261    const qreal radiusBase = qMax(qreal(1), maxRadius);
    60166262
    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);
    60216266
    60226267    QPixmap pixmap;
     
    60636308}
    60646309
    6065 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QTextItemInt &ti)
    6066 {
    6067     QTextCharFormat::UnderlineStyle underlineStyle = ti.underlineStyle;
     6310static 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{
    60686315    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;
    60736318
    60746319    const QPen oldPen = painter->pen();
     
    60806325    pen.setCapStyle(Qt::FlatCap);
    60816326
    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());
    60836328
    60846329    const qreal underlineOffset = fe->underlinePosition().toReal();
     
    60956340        painter->translate(0, pos.y() + 1);
    60966341
    6097         QColor uc = ti.charFormat.underlineColor();
     6342        QColor uc = charFormat.underlineColor();
    60986343        if (uc.isValid())
    60996344            pen.setColor(uc);
     
    61016346        // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms
    61026347        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();
    61046349
    61056350        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);
    61076352        painter->restore();
    61086353    } else if (underlineStyle != QTextCharFormat::NoUnderline) {
    61096354        QLineF underLine(line.x1(), underlinePos, line.x2(), underlinePos);
    61106355
    6111         QColor uc = ti.charFormat.underlineColor();
     6356        QColor uc = charFormat.underlineColor();
    61126357        if (uc.isValid())
    61136358            pen.setColor(uc);
     
    61216366    pen.setColor(oldPen.color());
    61226367
    6123     if (ti.flags & QTextItem::StrikeOut) {
     6368    if (flags & QTextItem::StrikeOut) {
    61246369        QLineF strikeOutLine = line;
    61256370        strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
     
    61286373    }
    61296374
    6130     if (ti.flags & QTextItem::Overline) {
     6375    if (flags & QTextItem::Overline) {
    61316376        QLineF overLine = line;
    61326377        overLine.translate(0., - fe->ascent().toReal());
     
    61376382    painter->setPen(oldPen);
    61386383    painter->setBrush(oldBrush);
     6384}
     6385
     6386static 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);
    61396428}
    61406429
     
    62696558            d->engine->drawTextItem(p, ti);
    62706559    }
    6271     drawTextItemDecoration(this, p, ti);
     6560    drawTextItemDecoration(this, p, ti.fontEngine, ti.underlineStyle, ti.flags, ti.width.toReal(),
     6561                           ti.charFormat);
    62726562
    62736563    if (d->state->renderHints != oldRenderHints) {
     
    69097199    rectangle.
    69107200
    6911     \sa window(), viewTransformEnabled(), {The Coordinate
     7201    \sa window(), viewTransformEnabled(), {Coordinate
    69127202    System#Window-Viewport Conversion}{Window-Viewport Conversion}
    69137203*/
     
    69737263    rectangle.
    69747264
    6975     \sa viewport(), viewTransformEnabled() {The Coordinate
     7265    \sa viewport(), viewTransformEnabled() {Coordinate
    69767266    System#Window-Viewport Conversion}{Window-Viewport Conversion}
    69777267*/
     
    70577347    view transformations if \a enable is false.
    70587348
    7059     \sa viewTransformEnabled(), {The Coordinate System#Window-Viewport
     7349    \sa viewTransformEnabled(), {Coordinate System#Window-Viewport
    70607350    Conversion}{Window-Viewport Conversion}
    70617351*/
     
    78078097            QTextLine line = textLayout.lineAt(i);
    78088098
    7809             qreal advance = textLayout.engine()->lines[i].textAdvance.toReal();
     8099            qreal advance = line.horizontalAdvance();
    78108100            if (tf & Qt::AlignRight)
    78118101                xoff = r.width() - advance;
     
    78268116    to the specified \a direction.
    78278117
    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}
    78298122*/
    78308123void QPainter::setLayoutDirection(Qt::LayoutDirection direction)
     
    78388131    Returns the layout direction used by the painter when drawing text.
    78398132
    7840     \sa setLayoutDirection(), drawText(), {QPainter#Settings}{Settings}
     8133    \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings}
    78418134*/
    78428135Qt::LayoutDirection QPainter::layoutDirection() const
    78438136{
    78448137    Q_D(const QPainter);
    7845     return d->state ? d->state->layoutDirection : Qt::LeftToRight;
     8138    return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto;
    78468139}
    78478140
     
    85068799
    85078800/*!
    8508     Returns wether clipping is enabled or not in the current paint
     8801    Returns whether clipping is enabled or not in the current paint
    85098802    engine state.
    85108803
     
    87169009}
    87179010
     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
     9026void 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
     9103QPainter::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
    87189181void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
    87199182{
Note: See TracChangeset for help on using the changeset viewer.