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/text/qtextengine.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)
     
    886886    QFixed wordSpacing = font.d->wordSpacing;
    887887
    888     if (letterSpacingIsAbsolute)
     888    if (letterSpacingIsAbsolute && letterSpacing.value())
    889889        letterSpacing *= font.d->dpi / qt_defaultDpiY();
    890890
     
    895895                    glyphs.advances_x[i-1] += letterSpacing;
    896896                else {
    897                     const QFixed advance = glyphs.advances_x[i-1];
    898                     glyphs.advances_x[i-1] += (letterSpacing - 100) * advance / 100;
     897                    QFixed &advance = glyphs.advances_x[i-1];
     898                    advance += (letterSpacing - 100) * advance / 100;
    899899                }
    900900            }
     
    903903            glyphs.advances_x[si.num_glyphs-1] += letterSpacing;
    904904        else {
    905             const QFixed advance = glyphs.advances_x[si.num_glyphs-1];
    906             glyphs.advances_x[si.num_glyphs-1] += (letterSpacing - 100) * advance / 100;
     905            QFixed &advance = glyphs.advances_x[si.num_glyphs-1];
     906            advance += (letterSpacing - 100) * advance / 100;
    907907        }
    908908    }
     
    922922    for (int i = 0; i < si.num_glyphs; ++i)
    923923        si.width += glyphs.advances_x[i];
     924}
     925
     926static inline bool hasCaseChange(const QScriptItem &si)
     927{
     928    return si.analysis.flags == QScriptAnalysis::SmallCaps ||
     929           si.analysis.flags == QScriptAnalysis::Uppercase ||
     930           si.analysis.flags == QScriptAnalysis::Lowercase;
    924931}
    925932
     
    10511058        flags |= DesignMetrics;
    10521059
    1053     attributes(); // pre-initialize char attributes
     1060    // pre-initialize char attributes
     1061    if (! attributes())
     1062        return;
    10541063
    10551064    const int len = length(item);
     
    10571066    const QChar *str = layoutData->string.unicode() + si.position;
    10581067    ushort upperCased[256];
    1059     if (si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase
    1060             || si.analysis.flags == QScriptAnalysis::Lowercase) {
     1068    if (hasCaseChange(si)) {
    10611069        ushort *uc = upperCased;
    10621070        if (len > 256)
     
    10721080
    10731081    while (true) {
    1074         ensureSpace(num_glyphs);
     1082        if (! ensureSpace(num_glyphs)) {
     1083            // If str is converted to uppercase/lowercase form with a new buffer,
     1084            // we need to delete that buffer before return for error
     1085            const ushort *uc = reinterpret_cast<const ushort *>(str);
     1086            if (hasCaseChange(si) && uc != upperCased)
     1087                delete [] uc;
     1088            return;
     1089        }
    10751090        num_glyphs = layoutData->glyphLayout.numGlyphs - layoutData->used;
    10761091
     
    10931108
    10941109    const ushort *uc = reinterpret_cast<const ushort *>(str);
    1095     if ((si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase
    1096          || si.analysis.flags == QScriptAnalysis::Lowercase)
    1097         && uc != upperCased)
     1110    if (hasCaseChange(si) && uc != upperCased)
    10981111        delete [] uc;
    10991112}
     
    11251138
    11261139    HB_ShaperItem entire_shaper_item;
    1127     entire_shaper_item.kerning_applied = false;
     1140    qMemSet(&entire_shaper_item, 0, sizeof(entire_shaper_item));
    11281141    entire_shaper_item.string = reinterpret_cast<const HB_UChar16 *>(layoutData->string.constData());
    11291142    entire_shaper_item.stringLength = layoutData->string.length();
     
    11321145    entire_shaper_item.item.length = length(item);
    11331146    entire_shaper_item.item.bidiLevel = si.analysis.bidiLevel;
    1134     entire_shaper_item.glyphIndicesPresent = false;
    11351147
    11361148    HB_UChar16 upperCased[256]; // XXX what about making this 4096, so we don't have to extend it ever.
    1137     if (si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase
    1138             || si.analysis.flags == QScriptAnalysis::Lowercase) {
     1149    if (hasCaseChange(si)) {
    11391150        HB_UChar16 *uc = upperCased;
    11401151        if (entire_shaper_item.item.length > 256)
     
    11581169
    11591170    entire_shaper_item.num_glyphs = qMax(layoutData->glyphLayout.numGlyphs - layoutData->used, int(entire_shaper_item.item.length));
    1160     ensureSpace(entire_shaper_item.num_glyphs);
     1171    if (! ensureSpace(entire_shaper_item.num_glyphs)) {
     1172        if (hasCaseChange(si))
     1173            delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string);
     1174        return;
     1175    }
    11611176    QGlyphLayout initialGlyphs = availableGlyphs(&si).mid(0, entire_shaper_item.num_glyphs);
    11621177
    11631178    if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, font)) {
    1164         ensureSpace(entire_shaper_item.num_glyphs);
     1179        if (! ensureSpace(entire_shaper_item.num_glyphs)) {
     1180            if (hasCaseChange(si))
     1181                delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string);
     1182            return;
     1183        }
    11651184        initialGlyphs = availableGlyphs(&si).mid(0, entire_shaper_item.num_glyphs);
    11661185
    11671186        if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, font)) {
    11681187            // ############ if this happens there's a bug in the fontengine
    1169             if ((si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase
    1170                     || si.analysis.flags == QScriptAnalysis::Lowercase) && entire_shaper_item.string != upperCased)
     1188            if (hasCaseChange(si) && entire_shaper_item.string != upperCased)
    11711189                delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string);
    11721190            return;
     
    12331251
    12341252        do {
    1235             ensureSpace(glyph_pos + shaper_item.num_glyphs + remaining_glyphs);
     1253            if (! ensureSpace(glyph_pos + shaper_item.num_glyphs + remaining_glyphs)) {
     1254                if (hasCaseChange(si))
     1255                    delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string);
     1256                return;
     1257            }
    12361258
    12371259            const QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos);
     
    12731295    layoutData->used += si.num_glyphs;
    12741296
    1275     if ((si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase)
    1276         && entire_shaper_item.string != upperCased)
     1297    if (hasCaseChange(si) && entire_shaper_item.string != upperCased)
    12771298        delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string);
    12781299}
     
    13001321
    13011322QTextEngine::QTextEngine(const QString &str, const QFont &f)
    1302     : fnt(f)
     1323    : text(str),
     1324      fnt(f)
    13031325{
    13041326    init(this);
    1305     text = str;
    13061327}
    13071328
     
    13191340
    13201341    itemize();
    1321     ensureSpace(layoutData->string.length());
     1342    if (! ensureSpace(layoutData->string.length()))
     1343        return NULL;
    13221344
    13231345    QVarLengthArray<HB_ScriptItem> hbScriptItems(layoutData->items.size());
     
    14061428    bool ignore = ignoreBidi;
    14071429#endif
    1408     if (!ignore && option.textDirection() == Qt::LeftToRight) {
     1430
     1431    bool rtl = isRightToLeft();
     1432
     1433    if (!ignore && !rtl) {
    14091434        ignore = true;
    14101435        const QChar *start = layoutData->string.unicode();
     
    14221447    QScriptAnalysis *analysis = scriptAnalysis.data();
    14231448
    1424     QBidiControl control(option.textDirection() == Qt::RightToLeft);
     1449    QBidiControl control(rtl);
    14251450
    14261451    if (ignore) {
     
    15171542}
    15181543
     1544bool QTextEngine::isRightToLeft() const
     1545{
     1546    switch (option.textDirection()) {
     1547    case Qt::LeftToRight:
     1548        return false;
     1549    case Qt::RightToLeft:
     1550        return true;
     1551    default:
     1552        break;
     1553    }
     1554    // this places the cursor in the right position depending on the keyboard layout
     1555    if (layoutData->string.isEmpty())
     1556        return QApplication::keyboardInputDirection() == Qt::RightToLeft;
     1557    return layoutData->string.isRightToLeft();
     1558}
     1559
     1560
    15191561int QTextEngine::findItem(int strPos) const
    15201562{
    15211563    itemize();
    1522 
    1523     // ##### use binary search
    1524     int item;
    1525     for (item = layoutData->items.size()-1; item > 0; --item) {
    1526         if (layoutData->items[item].position <= strPos)
    1527             break;
    1528     }
    1529     return item;
     1564    int left = 0;
     1565    int right = layoutData->items.size()-1;
     1566    while(left <= right) {
     1567        int middle = ((right-left)/2)+left;
     1568        if (strPos > layoutData->items[middle].position)
     1569            left = middle+1;
     1570        else if(strPos < layoutData->items[middle].position)
     1571            right = middle-1;
     1572        else {
     1573            return middle;
     1574        }
     1575    }
     1576    return right;
    15301577}
    15311578
     
    16001647    for (int i = 0; i < layoutData->items.size(); i++) {
    16011648        const QScriptItem *si = layoutData->items.constData() + i;
    1602         QFontEngine *fe = fontEngine(*si);
    16031649
    16041650        int pos = si->position;
     
    16301676                    charFrom++;
    16311677            if (charFrom < ilen) {
     1678                QFontEngine *fe = fontEngine(*si);
    16321679                glyphStart = logClusters[charFrom];
    16331680                int charEnd = from + len - 1 - pos;
     
    16481695                }
    16491696            }
    1650 
    1651             glyph_t glyph = glyphs.glyphs[logClusters[ilen - 1]];
    1652             glyph_metrics_t gi = fe->boundingBox(glyph);
    1653             if (gi.isValid())
    1654                 gm.width -= qRound(gi.xoff - gi.x - gi.width);
    16551697        }
    16561698    }
     
    18381880            return; // no justification at end of paragraph
    18391881        if (end && layoutData->items[findItem(end-1)].analysis.flags == QScriptAnalysis::LineOrParagraphSeparator)
    1840             return; // no justification at the end of an explicitely separated line
     1882            return; // no justification at the end of an explicitly separated line
    18411883    }
    18421884
     
    18461888    // don't include trailing white spaces when doing justification
    18471889    int line_length = line.length;
    1848     const HB_CharAttributes *a = attributes()+line.from;
     1890    const HB_CharAttributes *a = attributes();
     1891    if (! a)
     1892        return;
     1893    a += line.from;
    18491894    while (line_length && a[line_length-1].whiteSpace)
    18501895        --line_length;
     
    19051950//                     qDebug("kashida position at %d in word", kashida_pos);
    19061951                    set(&justificationPoints[nPoints], kashida_type, g.mid(kashida_pos), fontEngine(si));
    1907                     minKashida = qMin(minKashida, justificationPoints[nPoints].kashidaWidth);
    1908                     maxJustify = qMax(maxJustify, justificationPoints[nPoints].type);
    1909                     ++nPoints;
     1952                    if (justificationPoints[nPoints].kashidaWidth > 0) {
     1953                        minKashida = qMin(minKashida, justificationPoints[nPoints].kashidaWidth);
     1954                        maxJustify = qMax(maxJustify, justificationPoints[nPoints].type);
     1955                        ++nPoints;
     1956                    }
    19101957                }
    19111958                kashida_pos = -1;
     
    19311978        if (kashida_pos >= 0) {
    19321979            set(&justificationPoints[nPoints], kashida_type, g.mid(kashida_pos), fontEngine(si));
    1933             minKashida = qMin(minKashida, justificationPoints[nPoints].kashidaWidth);
    1934             maxJustify = qMax(maxJustify, justificationPoints[nPoints].type);
    1935             ++nPoints;
     1980            if (justificationPoints[nPoints].kashidaWidth > 0) {
     1981                minKashida = qMin(minKashida, justificationPoints[nPoints].kashidaWidth);
     1982                maxJustify = qMax(maxJustify, justificationPoints[nPoints].type);
     1983                ++nPoints;
     1984            }
    19361985        }
    19371986    }
     
    20272076    used = 0;
    20282077    hasBidi = false;
    2029     inLayout = false;
     2078    layoutState = LayoutEmpty;
    20302079    haveCharAttributes = false;
    20312080    logClustersPtr = 0;
     
    20612110    used = 0;
    20622111    hasBidi = false;
    2063     inLayout = false;
     2112    layoutState = LayoutEmpty;
    20642113    haveCharAttributes = false;
    20652114}
     
    20722121}
    20732122
    2074 void QTextEngine::LayoutData::reallocate(int totalGlyphs)
     2123bool QTextEngine::LayoutData::reallocate(int totalGlyphs)
    20752124{
    20762125    Q_ASSERT(totalGlyphs >= glyphLayout.numGlyphs);
    20772126    if (memory_on_stack && available_glyphs >= totalGlyphs) {
    20782127        glyphLayout.grow(glyphLayout.data(), totalGlyphs);
    2079         return;
     2128        return true;
    20802129    }
    20812130
     
    20852134
    20862135    int newAllocated = space_charAttributes + space_glyphs + space_logClusters;
    2087     Q_ASSERT(newAllocated >= allocated);
     2136    // These values can be negative if the length of string/glyphs causes overflow,
     2137    // we can't layout such a long string all at once, so return false here to
     2138    // indicate there is a failure
     2139    if (space_charAttributes < 0 || space_logClusters < 0 || space_glyphs < 0 || newAllocated < allocated) {
     2140        layoutState = LayoutFailed;
     2141        return false;
     2142    }
     2143
    20882144    void **newMem = memory;
    20892145    newMem = (void **)::realloc(memory_on_stack ? 0 : memory, newAllocated*sizeof(void *));
    2090     Q_CHECK_PTR(newMem);
    2091     if (memory_on_stack && newMem)
     2146    if (!newMem) {
     2147        layoutState = LayoutFailed;
     2148        return false;
     2149    }
     2150    if (memory_on_stack)
    20922151        memcpy(newMem, memory, allocated*sizeof(void *));
    20932152    memory = newMem;
     
    21062165
    21072166    allocated = newAllocated;
     2167    return true;
    21082168}
    21092169
     
    21372197        layoutData->used = 0;
    21382198        layoutData->hasBidi = false;
    2139         layoutData->inLayout = false;
     2199        layoutData->layoutState = LayoutEmpty;
    21402200        layoutData->haveCharAttributes = false;
    21412201    }
     
    22082268    case '?':
    22092269    case '!':
     2270    case '@':
     2271    case '#':
     2272    case '$':
    22102273    case ':':
    22112274    case ';':
     
    22282291    case '\'':
    22292292    case '"':
     2293    case '`':
    22302294    case '~':
    22312295    case '|':
     
    22962360
    22972361            HB_CharAttributes *attributes = const_cast<HB_CharAttributes *>(this->attributes());
     2362            if (!attributes)
     2363                return QString();
     2364
    22982365            unsigned short *logClusters = this->logClusters(&si);
    22992366            QGlyphLayout glyphs = shapedGlyphs(&si);
     
    23672434
    23682435    const HB_CharAttributes *attributes = this->attributes();
     2436    if (!attributes)
     2437        return QString();
    23692438
    23702439    if (mode == Qt::ElideRight) {
     
    24532522
    24542523    int itemToSplit = 0;
    2455     while (itemToSplit < layoutData->items.size() && layoutData->items[itemToSplit].position <= strPos)
     2524    while (itemToSplit < layoutData->items.size() && layoutData->items.at(itemToSplit).position <= strPos)
    24562525        itemToSplit++;
    24572526    itemToSplit--;
    2458     if (layoutData->items[itemToSplit].position == strPos) {
     2527    if (layoutData->items.at(itemToSplit).position == strPos) {
    24592528        // already a split at the requested position
    24602529        return;
    24612530    }
    2462     splitItem(itemToSplit, strPos - layoutData->items[itemToSplit].position);
     2531    splitItem(itemToSplit, strPos - layoutData->items.at(itemToSplit).position);
    24632532}
    24642533
     
    24682537        return;
    24692538
    2470     layoutData->items.insert(item + 1, QScriptItem(layoutData->items[item]));
     2539    layoutData->items.insert(item + 1, layoutData->items[item]);
    24712540    QScriptItem &oldItem = layoutData->items[item];
    24722541    QScriptItem &newItem = layoutData->items[item+1];
     
    25132582    QList<QTextOption::Tab> tabArray = option.tabs();
    25142583    if (!tabArray.isEmpty()) {
    2515         if (option.textDirection() == Qt::RightToLeft) { // rebase the tabArray positions.
     2584        if (isRightToLeft()) { // rebase the tabArray positions.
    25162585            QList<QTextOption::Tab> newTabs;
    25172586            QList<QTextOption::Tab>::Iterator iter = tabArray.begin();
     
    26112680
    26122681QStackTextEngine::QStackTextEngine(const QString &string, const QFont &f)
    2613     : _layoutData(string, _memory, MemSize)
    2614 {
    2615     fnt = f;
    2616     text = string;
     2682    : QTextEngine(string, f),
     2683      _layoutData(string, _memory, MemSize)
     2684{
    26172685    stackEngine = true;
    26182686    layoutData = &_layoutData;
     
    26512719}
    26522720
     2721QTextItemInt::QTextItemInt(const QGlyphLayout &g, QFont *font, const QChar *chars_, int numChars, QFontEngine *fe)
     2722    : flags(0), justified(false), underlineStyle(QTextCharFormat::NoUnderline),
     2723      num_chars(numChars), chars(chars_), logClusters(0), f(font),  glyphs(g), fontEngine(fe)
     2724{
     2725}
     2726
    26532727QTextItemInt QTextItemInt::midItem(QFontEngine *fontEngine, int firstGlyphIndex, int numGlyphs) const
    26542728{
Note: See TracChangeset for help on using the changeset viewer.