Changeset 846 for trunk/src/gui/text/qtextengine.cpp
- Timestamp:
- May 5, 2011, 5:36:53 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/vendor/nokia/qt/4.7.2 (added) merged: 845 /branches/vendor/nokia/qt/current merged: 844 /branches/vendor/nokia/qt/4.6.3 removed
- Property svn:mergeinfo changed
-
trunk/src/gui/text/qtextengine.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 886 886 QFixed wordSpacing = font.d->wordSpacing; 887 887 888 if (letterSpacingIsAbsolute )888 if (letterSpacingIsAbsolute && letterSpacing.value()) 889 889 letterSpacing *= font.d->dpi / qt_defaultDpiY(); 890 890 … … 895 895 glyphs.advances_x[i-1] += letterSpacing; 896 896 else { 897 const QFixedadvance = 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; 899 899 } 900 900 } … … 903 903 glyphs.advances_x[si.num_glyphs-1] += letterSpacing; 904 904 else { 905 const QFixedadvance = 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; 907 907 } 908 908 } … … 922 922 for (int i = 0; i < si.num_glyphs; ++i) 923 923 si.width += glyphs.advances_x[i]; 924 } 925 926 static 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; 924 931 } 925 932 … … 1051 1058 flags |= DesignMetrics; 1052 1059 1053 attributes(); // pre-initialize char attributes 1060 // pre-initialize char attributes 1061 if (! attributes()) 1062 return; 1054 1063 1055 1064 const int len = length(item); … … 1057 1066 const QChar *str = layoutData->string.unicode() + si.position; 1058 1067 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)) { 1061 1069 ushort *uc = upperCased; 1062 1070 if (len > 256) … … 1072 1080 1073 1081 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 } 1075 1090 num_glyphs = layoutData->glyphLayout.numGlyphs - layoutData->used; 1076 1091 … … 1093 1108 1094 1109 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) 1098 1111 delete [] uc; 1099 1112 } … … 1125 1138 1126 1139 HB_ShaperItem entire_shaper_item; 1127 entire_shaper_item.kerning_applied = false;1140 qMemSet(&entire_shaper_item, 0, sizeof(entire_shaper_item)); 1128 1141 entire_shaper_item.string = reinterpret_cast<const HB_UChar16 *>(layoutData->string.constData()); 1129 1142 entire_shaper_item.stringLength = layoutData->string.length(); … … 1132 1145 entire_shaper_item.item.length = length(item); 1133 1146 entire_shaper_item.item.bidiLevel = si.analysis.bidiLevel; 1134 entire_shaper_item.glyphIndicesPresent = false;1135 1147 1136 1148 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)) { 1139 1150 HB_UChar16 *uc = upperCased; 1140 1151 if (entire_shaper_item.item.length > 256) … … 1158 1169 1159 1170 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 } 1161 1176 QGlyphLayout initialGlyphs = availableGlyphs(&si).mid(0, entire_shaper_item.num_glyphs); 1162 1177 1163 1178 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 } 1165 1184 initialGlyphs = availableGlyphs(&si).mid(0, entire_shaper_item.num_glyphs); 1166 1185 1167 1186 if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, font)) { 1168 1187 // ############ 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) 1171 1189 delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string); 1172 1190 return; … … 1233 1251 1234 1252 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 } 1236 1258 1237 1259 const QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos); … … 1273 1295 layoutData->used += si.num_glyphs; 1274 1296 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) 1277 1298 delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string); 1278 1299 } … … 1300 1321 1301 1322 QTextEngine::QTextEngine(const QString &str, const QFont &f) 1302 : fnt(f) 1323 : text(str), 1324 fnt(f) 1303 1325 { 1304 1326 init(this); 1305 text = str;1306 1327 } 1307 1328 … … 1319 1340 1320 1341 itemize(); 1321 ensureSpace(layoutData->string.length()); 1342 if (! ensureSpace(layoutData->string.length())) 1343 return NULL; 1322 1344 1323 1345 QVarLengthArray<HB_ScriptItem> hbScriptItems(layoutData->items.size()); … … 1406 1428 bool ignore = ignoreBidi; 1407 1429 #endif 1408 if (!ignore && option.textDirection() == Qt::LeftToRight) { 1430 1431 bool rtl = isRightToLeft(); 1432 1433 if (!ignore && !rtl) { 1409 1434 ignore = true; 1410 1435 const QChar *start = layoutData->string.unicode(); … … 1422 1447 QScriptAnalysis *analysis = scriptAnalysis.data(); 1423 1448 1424 QBidiControl control( option.textDirection() == Qt::RightToLeft);1449 QBidiControl control(rtl); 1425 1450 1426 1451 if (ignore) { … … 1517 1542 } 1518 1543 1544 bool 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 1519 1561 int QTextEngine::findItem(int strPos) const 1520 1562 { 1521 1563 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; 1530 1577 } 1531 1578 … … 1600 1647 for (int i = 0; i < layoutData->items.size(); i++) { 1601 1648 const QScriptItem *si = layoutData->items.constData() + i; 1602 QFontEngine *fe = fontEngine(*si);1603 1649 1604 1650 int pos = si->position; … … 1630 1676 charFrom++; 1631 1677 if (charFrom < ilen) { 1678 QFontEngine *fe = fontEngine(*si); 1632 1679 glyphStart = logClusters[charFrom]; 1633 1680 int charEnd = from + len - 1 - pos; … … 1648 1695 } 1649 1696 } 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);1655 1697 } 1656 1698 } … … 1838 1880 return; // no justification at end of paragraph 1839 1881 if (end && layoutData->items[findItem(end-1)].analysis.flags == QScriptAnalysis::LineOrParagraphSeparator) 1840 return; // no justification at the end of an explicit ely separated line1882 return; // no justification at the end of an explicitly separated line 1841 1883 } 1842 1884 … … 1846 1888 // don't include trailing white spaces when doing justification 1847 1889 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; 1849 1894 while (line_length && a[line_length-1].whiteSpace) 1850 1895 --line_length; … … 1905 1950 // qDebug("kashida position at %d in word", kashida_pos); 1906 1951 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 } 1910 1957 } 1911 1958 kashida_pos = -1; … … 1931 1978 if (kashida_pos >= 0) { 1932 1979 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 } 1936 1985 } 1937 1986 } … … 2027 2076 used = 0; 2028 2077 hasBidi = false; 2029 inLayout = false;2078 layoutState = LayoutEmpty; 2030 2079 haveCharAttributes = false; 2031 2080 logClustersPtr = 0; … … 2061 2110 used = 0; 2062 2111 hasBidi = false; 2063 inLayout = false;2112 layoutState = LayoutEmpty; 2064 2113 haveCharAttributes = false; 2065 2114 } … … 2072 2121 } 2073 2122 2074 voidQTextEngine::LayoutData::reallocate(int totalGlyphs)2123 bool QTextEngine::LayoutData::reallocate(int totalGlyphs) 2075 2124 { 2076 2125 Q_ASSERT(totalGlyphs >= glyphLayout.numGlyphs); 2077 2126 if (memory_on_stack && available_glyphs >= totalGlyphs) { 2078 2127 glyphLayout.grow(glyphLayout.data(), totalGlyphs); 2079 return ;2128 return true; 2080 2129 } 2081 2130 … … 2085 2134 2086 2135 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 2088 2144 void **newMem = memory; 2089 2145 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) 2092 2151 memcpy(newMem, memory, allocated*sizeof(void *)); 2093 2152 memory = newMem; … … 2106 2165 2107 2166 allocated = newAllocated; 2167 return true; 2108 2168 } 2109 2169 … … 2137 2197 layoutData->used = 0; 2138 2198 layoutData->hasBidi = false; 2139 layoutData-> inLayout = false;2199 layoutData->layoutState = LayoutEmpty; 2140 2200 layoutData->haveCharAttributes = false; 2141 2201 } … … 2208 2268 case '?': 2209 2269 case '!': 2270 case '@': 2271 case '#': 2272 case '$': 2210 2273 case ':': 2211 2274 case ';': … … 2228 2291 case '\'': 2229 2292 case '"': 2293 case '`': 2230 2294 case '~': 2231 2295 case '|': … … 2296 2360 2297 2361 HB_CharAttributes *attributes = const_cast<HB_CharAttributes *>(this->attributes()); 2362 if (!attributes) 2363 return QString(); 2364 2298 2365 unsigned short *logClusters = this->logClusters(&si); 2299 2366 QGlyphLayout glyphs = shapedGlyphs(&si); … … 2367 2434 2368 2435 const HB_CharAttributes *attributes = this->attributes(); 2436 if (!attributes) 2437 return QString(); 2369 2438 2370 2439 if (mode == Qt::ElideRight) { … … 2453 2522 2454 2523 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) 2456 2525 itemToSplit++; 2457 2526 itemToSplit--; 2458 if (layoutData->items [itemToSplit].position == strPos) {2527 if (layoutData->items.at(itemToSplit).position == strPos) { 2459 2528 // already a split at the requested position 2460 2529 return; 2461 2530 } 2462 splitItem(itemToSplit, strPos - layoutData->items [itemToSplit].position);2531 splitItem(itemToSplit, strPos - layoutData->items.at(itemToSplit).position); 2463 2532 } 2464 2533 … … 2468 2537 return; 2469 2538 2470 layoutData->items.insert(item + 1, QScriptItem(layoutData->items[item]));2539 layoutData->items.insert(item + 1, layoutData->items[item]); 2471 2540 QScriptItem &oldItem = layoutData->items[item]; 2472 2541 QScriptItem &newItem = layoutData->items[item+1]; … … 2513 2582 QList<QTextOption::Tab> tabArray = option.tabs(); 2514 2583 if (!tabArray.isEmpty()) { 2515 if ( option.textDirection() == Qt::RightToLeft) { // rebase the tabArray positions.2584 if (isRightToLeft()) { // rebase the tabArray positions. 2516 2585 QList<QTextOption::Tab> newTabs; 2517 2586 QList<QTextOption::Tab>::Iterator iter = tabArray.begin(); … … 2611 2680 2612 2681 QStackTextEngine::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 { 2617 2685 stackEngine = true; 2618 2686 layoutData = &_layoutData; … … 2651 2719 } 2652 2720 2721 QTextItemInt::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 2653 2727 QTextItemInt QTextItemInt::midItem(QFontEngine *fontEngine, int firstGlyphIndex, int numGlyphs) const 2654 2728 {
Note:
See TracChangeset
for help on using the changeset viewer.