Ignore:
Timestamp:
Feb 11, 2010, 11:19:06 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.1 sources.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/gui/text/qtextlayout.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information ([email protected])
     4** All rights reserved.
     5** Contact: Nokia Corporation ([email protected])
    56**
    67** This file is part of the QtGui module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you
     37** @nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6262
    6363#define ObjectSelectionBrush (QTextFormat::ForegroundBrush + 1)
     64
     65
    6466
    6567static inline QFixed leadingSpaceWidth(QTextEngine *eng, const QScriptLine &line)
     
    127129    a QTextLayout.
    128130
    129     \ingroup text
     131    \ingroup
    130132
    131133    This class is only used if the text layout is used to lay out
     
    284286    paragraph of text.
    285287
    286     \ingroup text
     288    \ingroup
    287289
    288290    It offers most features expected from a modern text layout
     
    366368    if (paintdevice)
    367369        f = QFont(font, paintdevice);
    368     d = new QTextEngine((text.isNull() ? (const QString&)QString::fromLatin1("") : text), f.d);
     370    d = new QTextEngine((text.isNull() ? (const QString&)QString::fromLatin1("") : text), f.d);
    369371}
    370372
     
    859861        xmax = qMax(xmax, si.x+qMax(si.width, si.textWidth));
    860862        // ### shouldn't the ascent be used in ymin???
    861         ymax = qMax(ymax, si.y+si.ascent+si.descent+1);
     863        ymax = qMax(ymax, si.y+si.);
    862864    }
    863865    return QRectF(xmin.toReal(), ymin.toReal(), (xmax-xmin).toReal(), (ymax-ymin).toReal());
     
    10701072    QTextLineItemIterator iterator(eng, lineNumber, pos, selection);
    10711073
    1072     const QFixed y = QFixed::fromReal(pos.y()) + line.y + line.ascent;
    1073 
     1074
     1075
     1076    const qreal selectionY = pos.y() + line.y.toReal();
    10741077    const qreal lineHeight = line.height().toReal();
    1075     const qreal selectionY = (y - line.ascent).toReal();
    10761078
    10771079    QFixed lastSelectionX = iterator.x;
     
    11441146
    11451147    QPainterPath excludedRegion;
     1148
    11461149    for (int i = 0; i < selections.size(); ++i) {
    11471150        FormatRange selection = selections.at(i);
     
    12031206
    12041207
     1208
     1209
     1210
     1211
     1212
     1213
     1214
     1215
     1216
     1217
     1218
     1219
     1220
     1221
     1222
     1223
     1224
    12051225        p->save();
    12061226        p->setClipPath(region, Qt::IntersectClip);
    1207 
    1208         selection.format.setProperty(ObjectSelectionBrush, selection.format.property(QTextFormat::BackgroundBrush));
    1209         // don't just clear the property, set an empty brush that overrides a potential
    1210         // background brush specified in the text
    1211         selection.format.setProperty(QTextFormat::BackgroundBrush, QBrush());
    1212         selection.format.clearProperty(QTextFormat::OutlinePen);
    12131227
    12141228        for (int line = firstLine; line < lastLine; ++line) {
     
    12181232        p->restore();
    12191233
    1220         if (selection.format.foreground().style() != Qt::NoBrush) // i.e. we have drawn text
    1221             excludedRegion += region;
     1234        if (hasText) {
     1235            textDoneRegion += region;
     1236        } else {
     1237            if (hasBackground)
     1238                textDoneRegion -= region;
     1239        }
     1240
     1241        excludedRegion += region;
     1242    }
     1243
     1244    QPainterPath needsTextButNoBackground = excludedRegion - textDoneRegion;
     1245    if (!needsTextButNoBackground.isEmpty()){
     1246        p->save();
     1247        p->setClipPath(needsTextButNoBackground, Qt::IntersectClip);
     1248        FormatRange selection;
     1249        selection.start = 0;
     1250        selection.length = INT_MAX;
     1251        selection.format.setProperty(SuppressBackground, true);
     1252        for (int line = firstLine; line < lastLine; ++line) {
     1253            QTextLine l(line, d);
     1254            l.draw(p, position, &selection);
     1255        }
     1256        p->restore();
    12221257    }
    12231258
     
    13001335
    13011336    int itm = d->findItem(cursorPosition - 1);
    1302     QFixed ascent = sl.ascent;
     1337    QFixed ;
    13031338    QFixed descent = sl.descent;
    13041339    bool rightToLeft = (d->option.textDirection() == Qt::RightToLeft);
     
    13061341        const QScriptItem &si = d->layoutData->items.at(itm);
    13071342        if (si.ascent > 0)
    1308             ascent = si.ascent;
     1343            = si.ascent;
    13091344        if (si.descent > 0)
    13101345            descent = si.descent;
    13111346        rightToLeft = si.analysis.bidiLevel % 2;
    13121347    }
    1313     qreal y = position.y() + (sl.y + sl.ascent - ascent).toReal();
     1348    qreal y = position.y() + (sl.y + sl.).toReal();
    13141349    bool toggleAntialiasing = !(p->renderHints() & QPainter::Antialiasing)
    13151350                              && (p->transform().type() > QTransform::TxTranslate);
    13161351    if (toggleAntialiasing)
    13171352        p->setRenderHint(QPainter::Antialiasing);
    1318     p->fillRect(QRectF(x, y, qreal(width), (ascent + descent).toReal()), p->pen().brush());
     1353    p->fillRect(QRectF(x, y, qreal(width), ().toReal()), p->pen().brush());
    13191354    if (toggleAntialiasing)
    13201355        p->setRenderHint(QPainter::Antialiasing, false);
     
    13341369    \brief The QTextLine class represents a line of text inside a QTextLayout.
    13351370
    1336     \ingroup text
     1371    \ingroup
    13371372
    13381373    A text line is usually created by QTextLayout::createLine().
     
    14661501
    14671502/*!
    1468     Returns the line's height. This is equal to ascent() + descent() + 1.
    1469 
    1470     \sa ascent() descent()
     1503    Returns the line's height. This is equal to ascent() + descent() + 1
     1504    if leading is not included. If leading is included, this equals to
     1505    ascent() + descent() + leading() + 1.
     1506
     1507    \sa ascent() descent() leading() setLeadingIncluded()
    14711508*/
    14721509qreal QTextLine::height() const
     
    14741511    return eng->lines[i].height().toReal();
    14751512}
     1513
     1514
     1515
     1516
     1517
     1518
     1519
     1520
     1521
     1522
     1523
     1524
     1525
     1526
     1527
     1528
     1529
     1530
     1531
     1532
     1533
     1534
     1535
     1536
     1537
     1538
     1539
     1540
     1541
     1542
     1543
     1544
     1545
     1546
     1547
     1548
     1549
     1550
     1551
     1552
     1553
     1554
     1555
     1556
     1557
    14761558
    14771559/*!
     
    15551637#endif
    15561638
    1557 static inline bool checkFullOtherwiseExtend(QScriptLine &line, QScriptLine &tmpData, QScriptLine &spaceData,
    1558                                             int glyphCount, int maxGlyphs, QFixed &minw, bool manualWrap,
    1559                                             QFixed softHyphenWidth = QFixed())
    1560 {
     1639namespace {
     1640
     1641    struct LineBreakHelper
     1642    {
     1643        LineBreakHelper() : glyphCount(0), maxGlyphs(0), manualWrap(false) {}
     1644
     1645        QScriptLine tmpData;
     1646        QScriptLine spaceData;
     1647
     1648        int glyphCount;
     1649        int maxGlyphs;
     1650
     1651        QFixed minw;
     1652        QFixed softHyphenWidth;
     1653        QFixed rightBearing;
     1654
     1655        bool manualWrap;
     1656
     1657        bool checkFullOtherwiseExtend(QScriptLine &line);
     1658    };
     1659
     1660inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line)
     1661{       
    15611662    LB_DEBUG("possible break width %f, spacew=%f", tmpData.textWidth.toReal(), spaceData.textWidth.toReal());
    1562     if (line.length && !manualWrap &&
    1563         (line.textWidth + tmpData.textWidth + spaceData.textWidth + softHyphenWidth > line.width || glyphCount > maxGlyphs))
     1663
     1664    QFixed newWidth = line.textWidth + tmpData.textWidth + spaceData.textWidth + softHyphenWidth + rightBearing;
     1665    if (line.length && !manualWrap && (newWidth > line.width || glyphCount > maxGlyphs))
    15641666        return true;
     1667
    15651668    minw = qMax(minw, tmpData.textWidth);
    15661669    line += tmpData;
    15671670    line.textWidth += spaceData.textWidth;
     1671
    15681672    line.length += spaceData.length;
    15691673    tmpData.textWidth = 0;
     
    15711675    spaceData.textWidth = 0;
    15721676    spaceData.length = 0;
     1677
    15731678    return false;
    15741679}
    15751680
     1681
     1682
     1683
    15761684static inline void addNextCluster(int &pos, int end, QScriptLine &line, int &glyphCount,
    1577                                   const QScriptItem &current, const unsigned short *logClusters, const QGlyphLayout &glyphs)
     1685                                  const QScriptItem &current, const unsigned short *logClusters,
     1686                                  const QGlyphLayout &glyphs)
    15781687{
    15791688    int glyphPosition = logClusters[pos];
     
    16081717    Q_ASSERT(line.from < eng->layoutData->string.length());
    16091718
     1719
     1720
     1721
     1722
    16101723    QTextOption::WrapMode wrapMode = eng->option.wrapMode();
    16111724    bool breakany = (wrapMode == QTextOption::WrapAnywhere);
    1612     bool manualWrap = (wrapMode == QTextOption::ManualWrap || wrapMode == QTextOption::NoWrap);
     1725    manualWrap = (wrapMode == QTextOption::ManualWrap || wrapMode == QTextOption::NoWrap);
    16131726
    16141727    // #### binary search!
     
    16201733    }
    16211734
    1622     QFixed minw = 0;
    1623     int glyphCount = 0;
    1624 
    16251735    LB_DEBUG("from: %d: item=%d, total %d, width available %f", line.from, newItem, eng->layoutData->items.size(), line.width.toReal());
    1626     QScriptLine tmpData;
    1627     QScriptLine spaceData;
    16281736
    16291737    Qt::Alignment alignment = eng->option.alignment();
     
    16341742    QGlyphLayout glyphs;
    16351743    const unsigned short *logClusters = eng->layoutData->logClustersPtr;
     1744
    16361745    while (newItem < eng->layoutData->items.size()) {
     1746
     1747
    16371748        if (newItem != item) {
    16381749            item = newItem;
     
    16491760        const QScriptItem &current = eng->layoutData->items[item];
    16501761
    1651         tmpData.ascent = qMax(tmpData.ascent, current.ascent);
    1652         tmpData.descent = qMax(tmpData.descent, current.descent);
     1762        lbh.tmpData.leading = qMax(lbh.tmpData.leading + lbh.tmpData.ascent,
     1763                                   current.leading + current.ascent) - qMax(lbh.tmpData.ascent,
     1764                                                                            current.ascent);
     1765        lbh.tmpData.ascent = qMax(lbh.tmpData.ascent, current.ascent);
     1766        lbh.tmpData.descent = qMax(lbh.tmpData.descent, current.descent);
    16531767
    16541768        if (current.analysis.flags == QScriptAnalysis::Tab && (alignment & (Qt::AlignLeft | Qt::AlignRight | Qt::AlignCenter | Qt::AlignJustify))) {
    1655             if (checkFullOtherwiseExtend(line, tmpData, spaceData, glyphCount, maxGlyphs, minw, manualWrap))
     1769            if ())
    16561770                goto found;
    16571771
    1658             QFixed x = line.x + line.textWidth + tmpData.textWidth + spaceData.textWidth;
    1659             spaceData.textWidth += eng->calculateTabWidth(item, x);
    1660             spaceData.length++;
     1772            QFixed x = line.x + line.textWidth + lbh.tmpData.textWidth + lbh.spaceData.textWidth;
     1773            QFixed tabWidth = eng->calculateTabWidth(item, x);
     1774
     1775            lbh.spaceData.textWidth += tabWidth;
     1776            lbh.spaceData.length++;
    16611777            newItem = item + 1;
    1662             ++glyphCount;
    1663             if (checkFullOtherwiseExtend(line, tmpData, spaceData, glyphCount, maxGlyphs, minw, manualWrap))
     1778
     1779            QFixed averageCharWidth = eng->fontEngine(current)->averageCharWidth();
     1780            lbh.glyphCount += qRound(tabWidth / averageCharWidth);
     1781
     1782            if (lbh.checkFullOtherwiseExtend(line))
    16641783                goto found;
    16651784        } else if (current.analysis.flags == QScriptAnalysis::LineOrParagraphSeparator) {
    16661785            // if the line consists only of the line separator make sure
    16671786            // we have a sane height
    1668             if (!line.length && !tmpData.length)
     1787            if (!line.length && !tmpData.length)
    16691788                line.setDefaultHeight(eng);
    16701789            if (eng->option.flags() & QTextOption::ShowLineAndParagraphSeparators) {
    1671                 addNextCluster(pos, end, tmpData, glyphCount, current, logClusters, glyphs);
     1790                addNextCluster(pos, end, lbh.tmpData, lbh.glyphCount,
     1791                               current, logClusters, glyphs);
    16721792            } else {
    1673                 tmpData.length++;
     1793                tmpData.length++;
    16741794            }
    1675             line += tmpData;
     1795            line += tmpData;
    16761796            goto found;
    16771797        } else if (current.analysis.flags == QScriptAnalysis::Object) {
    1678             tmpData.length++;
     1798            tmpData.length++;
    16791799
    16801800            QTextFormat format = eng->formats()->format(eng->formatIndex(&eng->layoutData->items[item]));
     
    16821802                eng->docLayout()->positionInlineObject(QTextInlineObject(item, eng), eng->block.position() + current.position, format);
    16831803
    1684             tmpData.textWidth += current.width;
     1804            tmpData.textWidth += current.width;
    16851805
    16861806            newItem = item + 1;
    1687             ++glyphCount;
    1688             if (checkFullOtherwiseExtend(line, tmpData, spaceData, glyphCount, maxGlyphs, minw, manualWrap))
     1807            ++glyphCount;
     1808            if ())
    16891809                goto found;
    16901810        } else if (attributes[pos].whiteSpace) {
    16911811            while (pos < end && attributes[pos].whiteSpace)
    1692                 addNextCluster(pos, end, spaceData, glyphCount, current, logClusters, glyphs);
    1693 
    1694             if (!manualWrap && spaceData.textWidth > line.width) {
    1695                 spaceData.textWidth = line.width; // ignore spaces that fall out of the line.
     1812                addNextCluster(pos, end, lbh.spaceData, lbh.glyphCount,
     1813                               current, logClusters, glyphs);
     1814
     1815            if (!lbh.manualWrap && lbh.spaceData.textWidth > line.width) {
     1816                lbh.spaceData.textWidth = line.width; // ignore spaces that fall out of the line.
    16961817                goto found;
    16971818            }
     
    16991820            bool sb_or_ws = false;
    17001821            do {
    1701                 addNextCluster(pos, end, tmpData, glyphCount, current, logClusters, glyphs);
     1822                addNextCluster(pos, end, lbh.tmpData, lbh.glyphCount,
     1823                               current, logClusters, glyphs);
    17021824
    17031825                if (attributes[pos].whiteSpace || attributes[pos-1].lineBreakType != HB_NoBreak) {
     
    17081830                }
    17091831            } while (pos < end);
    1710             minw = qMax(tmpData.textWidth, minw);
    1711 
    1712             QFixed softHyphenWidth;
     1832            lbh.minw = qMax(lbh.tmpData.textWidth, lbh.minw);
     1833
    17131834            if (pos && attributes[pos - 1].lineBreakType == HB_SoftHyphen) {
    17141835                // if we are splitting up a word because of
     
    17291850                //
    17301851                if (line.length)
    1731                     softHyphenWidth = glyphs.advances_x[logClusters[pos - 1]];
     1852                    softHyphenWidth = glyphs.advances_x[logClusters[pos - 1]];
    17321853                else if (breakany)
    1733                     tmpData.textWidth += glyphs.advances_x[logClusters[pos - 1]];
     1854                    tmpData.textWidth += glyphs.advances_x[logClusters[pos - 1]];
    17341855            }
    17351856
    1736             if ((sb_or_ws|breakany)
    1737                 && checkFullOtherwiseExtend(line, tmpData, spaceData, glyphCount, maxGlyphs, minw, manualWrap, softHyphenWidth)) {
     1857            // The actual width of the text needs to take the right bearing into account. The
     1858            // right bearing is left-ward, which means that if the rightmost pixel is to the right
     1859            // of the advance of the glyph, the bearing will be negative. We flip the sign
     1860            // for the code to be more readable. Logic borrowed from qfontmetrics.cpp.
     1861            if (pos) {
     1862                QFontEngine *fontEngine = eng->fontEngine(current);
     1863                glyph_t glyph = glyphs.glyphs[logClusters[pos - 1]];
     1864                glyph_metrics_t gi = fontEngine->boundingBox(glyph);
     1865                if (gi.isValid())
     1866                    lbh.rightBearing = qMax(QFixed(), -(gi.xoff - gi.x - gi.width));
     1867            }
     1868
     1869            if ((sb_or_ws|breakany) && lbh.checkFullOtherwiseExtend(line)) {
    17381870                if (!breakany) {
    1739                     line.textWidth += softHyphenWidth;
     1871                    line.textWidth += softHyphenWidth;
    17401872                }
     1873
     1874
     1875
    17411876                goto found;
    17421877            }
     
    17461881    }
    17471882    LB_DEBUG("reached end of line");
    1748     checkFullOtherwiseExtend(line, tmpData, spaceData, glyphCount, maxGlyphs, minw, manualWrap);
    1749 found:
     1883    lbh.checkFullOtherwiseExtend(line);
     1884    line.textWidth += lbh.rightBearing;
     1885
     1886found:       
    17501887    if (line.length == 0) {
    17511888        LB_DEBUG("no break available in line, adding temp: length %d, width %f, space: length %d, width %f",
    1752                tmpData.length, tmpData.textWidth.toReal(), spaceData.length, spaceData.textWidth.toReal());
    1753         line += tmpData;
     1889               lbh.tmpData.length, lbh.tmpData.textWidth.toReal(),
     1890               lbh.spaceData.length, lbh.spaceData.textWidth.toReal());
     1891        line += lbh.tmpData;
    17541892    }
    17551893
    17561894    LB_DEBUG("line length = %d, ascent=%f, descent=%f, textWidth=%f (spacew=%f)", line.length, line.ascent.toReal(),
    1757            line.descent.toReal(), line.textWidth.toReal(), spaceData.width.toReal());
     1895           line.descent.toReal(), line.textWidth.toReal(), spaceData.width.toReal());
    17581896    LB_DEBUG("        : '%s'", eng->layoutData->string.mid(line.from, line.length).toUtf8().data());
    17591897
    1760     if (manualWrap) {
     1898    if (manualWrap) {
    17611899        eng->minWidth = qMax(eng->minWidth, line.textWidth);
    17621900        eng->maxWidth = qMax(eng->maxWidth, line.textWidth);
    17631901    } else {
    1764         eng->minWidth = qMax(eng->minWidth, minw);
     1902        eng->minWidth = qMax(eng->minWidth, minw);
    17651903        eng->maxWidth += line.textWidth;
    17661904    }
    17671905
    17681906    if (line.textWidth > 0 && item < eng->layoutData->items.size())
    1769         eng->maxWidth += spaceData.textWidth;
     1907        eng->maxWidth += spaceData.textWidth;
    17701908    if (eng->option.flags() & QTextOption::IncludeTrailingSpaces)
    1771         line.textWidth += spaceData.textWidth;
    1772     line.length += spaceData.length;
    1773     if (spaceData.length)
     1909        line.textWidth += spaceData.textWidth;
     1910    line.length += spaceData.length;
     1911    if (spaceData.length)
    17741912        line.hasTrailingSpaces = true;
    17751913
     
    17781916
    17791917    if (eng->option.wrapMode() == QTextOption::WrapAtWordBoundaryOrAnywhere) {
    1780         if ((maxGlyphs != INT_MAX && glyphCount > maxGlyphs)
    1781             || (maxGlyphs == INT_MAX && line.textWidth > line.width)) {
     1918        if ((maxGlyphs)
     1919            || (maxGlyphs == INT_MAX && line.textWidth > line.width)) {
    17821920
    17831921            eng->option.setWrapMode(QTextOption::WrapAnywhere);
    17841922            line.length = 0;
    17851923            line.textWidth = 0;
    1786             layout_helper(maxGlyphs);
     1924            layout_helper(maxGlyphs);
    17871925            eng->option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
    17881926        }
     
    19132051{
    19142052    QBrush c = chf.foreground();
    1915     if (c.style() == Qt::NoBrush)
     2053    if (c.style() == Qt::NoBrush)
    19162054        p->setPen(defaultPen);
     2055
    19172056
    19182057    QBrush bg = chf.background();
    1919     if (bg.style() != Qt::NoBrush)
     2058    if (bg.style() != Qt::NoBrush)
    19202059        p->fillRect(r, bg);
    1921     if (c.style() != Qt::NoBrush)
     2060    if (c.style() != Qt::NoBrush)
    19222061        p->setPen(QPen(c, 0));
     2062
     2063
    19232064}
    19242065
     
    19342075    QPen pen = p->pen();
    19352076
    1936     bool noText = (selection && selection->format.foreground().style() == Qt::NoBrush);
     2077    bool noText = (selection && selection->format.);
    19372078
    19382079    if (!line.length) {
     
    19522093
    19532094    QTextLineItemIterator iterator(eng, i, pos, selection);
    1954     const QFixed y = QFixed::fromReal(pos.y()) + line.y + line.ascent;
     2095    QFixed lineBase = line.base();
     2096
     2097    const QFixed y = QFixed::fromReal(pos.y()) + line.y + lineBase;
    19552098
    19562099    bool suppressColors = (eng->option.flags() & QTextOption::SuppressColors);
     
    19752118                format.merge(selection->format);
    19762119
    1977             setPenAndDrawBackground(p, pen, format, QRectF(iterator.x.toReal(), (y - line.ascent).toReal(),
     2120            setPenAndDrawBackground(p, pen, format, QRectF(iterator.x.toReal(), (y - line).toReal(),
    19782121                                                           iterator.itemWidth.toReal(), line.height().toReal()));
    19792122
     
    19962139                    QFixed itemY = y - si.ascent;
    19972140                    if (format.verticalAlignment() == QTextCharFormat::AlignTop) {
    1998                         itemY = y - line.ascent;
     2141                        itemY = y - line;
    19992142                    }
    20002143
Note: See TracChangeset for help on using the changeset viewer.