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/qtextengine.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    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 have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    364364//         qDebug() << "pos=" << current << " dir=" << directions[dir]
    365365//                  << " current=" << directions[dirCurrent] << " last=" << directions[status.last]
    366 //                  << " eor=" << eor << "/" << directions[status.eor]
     366//                  << " eor=" << eor << '/' << directions[status.eor]
    367367//                  << " sor=" << sor << " lastStrong="
    368368//                  << directions[status.lastStrong]
     
    869869#if defined(Q_WS_MAC)
    870870    shapeTextMac(item);
    871 #elif defined(Q_OS_WINCE)
     871#elif defined(Q_WS_WINCE)
    872872    shapeTextWithCE(item);
    873873#else
     
    924924}
    925925
    926 #if defined(Q_OS_WINCE) //TODO
     926#if defined(Q_WS_WINCE) //TODO
    927927// set the glyph attributes heuristically. Assumes a 1 to 1 relationship between chars and glyphs
    928928// and no reordering.
     
    10431043    si.glyph_data_offset = layoutData->used;
    10441044
    1045     QFontEngine *fe = fontEngine(si, &si.ascent, &si.descent);
     1045    QFontEngine *fe = fontEngine(si, &si.ascent, &si.descent, &si.leading);
    10461046
    10471047    QTextEngine::ShaperFlags flags;
     
    11001100#endif
    11011101
     1102static inline void moveGlyphData(const QGlyphLayout &destination, const QGlyphLayout &source, int num)
     1103{
     1104    if (num > 0 && destination.glyphs != source.glyphs) {
     1105        memmove(destination.glyphs, source.glyphs, num * sizeof(HB_Glyph));
     1106        memmove(destination.attributes, source.attributes, num * sizeof(HB_GlyphAttributes));
     1107        memmove(destination.advances_x, source.advances_x, num * sizeof(HB_Fixed));
     1108        memmove(destination.offsets, source.offsets, num * sizeof(HB_FixedPoint));
     1109    }
     1110}
     1111
    11021112/// take the item from layoutData->items and
    11031113void QTextEngine::shapeTextWithHarfbuzz(int item) const
     
    11101120    si.glyph_data_offset = layoutData->used;
    11111121
    1112     QFontEngine *font = fontEngine(si, &si.ascent, &si.descent);
     1122    QFontEngine *font = fontEngine(si, &si.ascent, &si.descent, &si.leading);
    11131123
    11141124    bool kerningEnabled = this->font(si).d->kerning;
     
    11901200
    11911201
    1192     int initial_glyph_pos = 0;
     1202    int remaining_glyphs = entire_shaper_item.num_glyphs;
    11931203    int glyph_pos = 0;
    11941204    // for each item shape using harfbuzz and store the results in our layoutData's glyphs array.
     
    12101220        uint engineIdx = 0;
    12111221        if (font->type() == QFontEngine::Multi) {
    1212             engineIdx = uint(initialGlyphs.glyphs[itemBoundaries[k + 1]] >> 24);
     1222            engineIdx = uint(availableGlyphs(&si).glyphs[glyph_pos] >> 24);
    12131223
    12141224            actualFontEngine = static_cast<QFontEngineMulti *>(font)->engine(engineIdx);
     
    12201230        shaper_item.glyphIndicesPresent = true;
    12211231
     1232        remaining_glyphs -= shaper_item.initialGlyphCount;
     1233
    12221234        do {
    1223             ensureSpace(glyph_pos + shaper_item.num_glyphs);
    1224             initialGlyphs = availableGlyphs(&si).mid(0, entire_shaper_item.num_glyphs);
    1225             shaper_item.num_glyphs = layoutData->glyphLayout.numGlyphs - layoutData->used - glyph_pos;
    1226 
    1227             const QGlyphLayout g = availableGlyphs(&si);
    1228             shaper_item.glyphs = g.glyphs + glyph_pos;
    1229             shaper_item.attributes = g.attributes + glyph_pos;
    1230             shaper_item.advances = reinterpret_cast<HB_Fixed *>(g.advances_x + glyph_pos);
    1231             shaper_item.offsets = reinterpret_cast<HB_FixedPoint *>(g.offsets + glyph_pos);
     1235            ensureSpace(glyph_pos + shaper_item.num_glyphs + remaining_glyphs);
     1236
     1237            const QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos);
     1238            moveGlyphData(g.mid(shaper_item.num_glyphs), g.mid(shaper_item.initialGlyphCount), remaining_glyphs);
     1239
     1240            shaper_item.glyphs = g.glyphs;
     1241            shaper_item.attributes = g.attributes;
     1242            shaper_item.advances = reinterpret_cast<HB_Fixed *>(g.advances_x);
     1243            shaper_item.offsets = reinterpret_cast<HB_FixedPoint *>(g.offsets);
    12321244
    12331245            if (shaper_item.glyphIndicesPresent) {
     
    12421254
    12431255        QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos, shaper_item.num_glyphs);
    1244 
    1245         for (hb_uint32 i = 0; i < shaper_item.item.length; ++i) {
     1256        moveGlyphData(g.mid(shaper_item.num_glyphs), g.mid(shaper_item.initialGlyphCount), remaining_glyphs);
     1257
     1258        for (hb_uint32 i = 0; i < shaper_item.num_glyphs; ++i)
    12461259            g.glyphs[i] = g.glyphs[i] | (engineIdx << 24);
     1260
     1261        for (hb_uint32 i = 0; i < shaper_item.item.length; ++i)
    12471262            shaper_item.log_clusters[i] += glyph_pos;
    1248         }
    12491263
    12501264        if (kerningEnabled && !shaper_item.kerning_applied)
     
    12521266
    12531267        glyph_pos += shaper_item.num_glyphs;
    1254 
    1255         initial_glyph_pos += shaper_item.initialGlyphCount;
    12561268    }
    12571269
     
    13391351        }
    13401352    } else if (layoutData->items[item].analysis.flags == QScriptAnalysis::Tab) {
    1341         // set up at least the ascent/descent of the script item for the tab
    1342         fontEngine(layoutData->items[item], &layoutData->items[item].ascent, &layoutData->items[item].descent);
     1353        // set up at least the ascent/descent/leading of the script item for the tab
     1354        fontEngine(layoutData->items[item],
     1355                   &layoutData->items[item].ascent,
     1356                   &layoutData->items[item].descent,
     1357                   &layoutData->items[item].leading);
    13431358    } else {
    13441359        shapeText(item);
     
    13851400    if (!length)
    13861401        return;
    1387 
     1402#if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)
     1403    // ATSUI requires RTL flags to correctly identify the character stops.
     1404    bool ignore = false;
     1405#else
    13881406    bool ignore = ignoreBidi;
     1407#endif
    13891408    if (!ignore && option.textDirection() == Qt::LeftToRight) {
    13901409        ignore = true;
     
    15831602    for (int i = 0; i < layoutData->items.size(); i++) {
    15841603        const QScriptItem *si = layoutData->items.constData() + i;
     1604        QFontEngine *fe = fontEngine(*si);
     1605
    15851606        int pos = si->position;
    15861607        int ilen = length(i);
    15871608        if (pos > from + len)
    15881609            break;
    1589         if (pos + len > from) {
     1610        if (pos + ilen > from) {
    15901611            if (!si->num_glyphs)
    15911612                shape(i);
     
    16201641                glyphEnd = (charEnd == ilen) ? si->num_glyphs : logClusters[charEnd];
    16211642                if (glyphStart <= glyphEnd ) {
    1622                     QFontEngine *fe = fontEngine(*si);
    16231643                    glyph_metrics_t m = fe->boundingBox(glyphs.mid(glyphStart, glyphEnd - glyphStart));
    16241644                    gm.x = qMin(gm.x, m.x + gm.xoff);
     
    16301650                }
    16311651            }
     1652
     1653            glyph_t glyph = glyphs.glyphs[logClusters[pos + ilen - 1]];
     1654            glyph_metrics_t gi = fe->boundingBox(glyph);
     1655            if (gi.isValid())
     1656                gm.width -= qRound(gi.xoff - gi.x - gi.width);
    16321657        }
    16331658    }
     
    17161741}
    17171742
    1718 QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFixed *descent) const
     1743QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFixed *descent, QFixed *leading) const
    17191744{
    17201745    QFontEngine *engine = 0;
     
    17561781        *ascent = engine->ascent();
    17571782        *descent = engine->descent();
     1783        *leading = engine->leading();
    17581784    }
    17591785
     
    19882014    }
    19892015
    1990     ascent = qMax(ascent, e->ascent());
    1991     descent = qMax(descent, e->descent());
     2016    QFixed other_ascent = e->ascent();
     2017    QFixed other_descent = e->descent();
     2018    QFixed other_leading = e->leading();
     2019    leading = qMax(leading + ascent, other_leading + other_ascent) - qMax(ascent, other_ascent);
     2020    ascent = qMax(ascent, other_ascent);
     2021    descent = qMax(descent, other_descent);
    19922022}
    19932023
     
    20582088    int newAllocated = space_charAttributes + space_glyphs + space_logClusters;
    20592089    Q_ASSERT(newAllocated >= allocated);
    2060     void **old_mem = memory;
    2061     memory = (void **)::realloc(memory_on_stack ? 0 : old_mem, newAllocated*sizeof(void *));
    2062     if (memory_on_stack && memory)
    2063         memcpy(memory, old_mem, allocated*sizeof(void *));
     2090    void **newMem = memory;
     2091    newMem = (void **)::realloc(memory_on_stack ? 0 : memory, newAllocated*sizeof(void *));
     2092    Q_CHECK_PTR(newMem);
     2093    if (memory_on_stack && newMem)
     2094        memcpy(newMem, memory, allocated*sizeof(void *));
     2095    memory = newMem;
    20642096    memory_on_stack = false;
    20652097
     
    21992231    case '"':
    22002232    case '~':
     2233    case '|':
    22012234        return true;
    22022235    default:
     
    22292262        specialData->addFormats[i].format = QTextCharFormat();
    22302263    }
     2264}
     2265
     2266/* These two helper functions are used to determine whether we need to insert a ZWJ character
     2267   between the text that gets truncated and the ellipsis. This is important to get
     2268   correctly shaped results for arabic text.
     2269*/
     2270static bool nextCharJoins(const QString &string, int pos)
     2271{
     2272    while (pos < string.length() && string.at(pos).category() == QChar::Mark_NonSpacing)
     2273        ++pos;
     2274    if (pos == string.length())
     2275        return false;
     2276    return string.at(pos).joining() != QChar::OtherJoining;
     2277}
     2278
     2279static bool prevCharJoins(const QString &string, int pos)
     2280{
     2281    while (pos > 0 && string.at(pos - 1).category() == QChar::Mark_NonSpacing)
     2282        --pos;
     2283    if (pos == 0)
     2284        return false;
     2285    return (string.at(pos - 1).joining() == QChar::Dual || string.at(pos - 1).joining() == QChar::Center);
    22312286}
    22322287
     
    23312386                 && currentWidth < availableWidth);
    23322387
     2388        if (nextCharJoins(layoutData->string, pos))
     2389            ellipsisText.prepend(QChar(0x200d) /* ZWJ */);
     2390
    23332391        return layoutData->string.left(pos) + ellipsisText;
    23342392    } else if (mode == Qt::ElideLeft) {
     
    23482406                 && currentWidth < availableWidth);
    23492407
     2408        if (prevCharJoins(layoutData->string, pos))
     2409            ellipsisText.append(QChar(0x200d) /* ZWJ */);
     2410
    23502411        return ellipsisText + layoutData->string.mid(pos);
    23512412    } else if (mode == Qt::ElideMiddle) {
     
    23762437                 && nextRightBreak > 0
    23772438                 && leftWidth + rightWidth < availableWidth);
     2439
     2440        if (nextCharJoins(layoutData->string, leftPos))
     2441            ellipsisText.prepend(QChar(0x200d) /* ZWJ */);
     2442        if (prevCharJoins(layoutData->string, rightPos))
     2443            ellipsisText.append(QChar(0x200d) /* ZWJ */);
    23782444
    23792445        return layoutData->string.left(leftPos) + ellipsisText + layoutData->string.mid(rightPos);
Note: See TracChangeset for help on using the changeset viewer.