Changeset 561 for trunk/src/gui/text/qtextengine.cpp
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/gui/text/qtextengine.cpp
r2 r561 2 2 ** 3 3 ** 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) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 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. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** 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. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 364 364 // qDebug() << "pos=" << current << " dir=" << directions[dir] 365 365 // << " current=" << directions[dirCurrent] << " last=" << directions[status.last] 366 // << " eor=" << eor << "/"<< directions[status.eor]366 // << " eor=" << eor << '/' << directions[status.eor] 367 367 // << " sor=" << sor << " lastStrong=" 368 368 // << directions[status.lastStrong] … … 869 869 #if defined(Q_WS_MAC) 870 870 shapeTextMac(item); 871 #elif defined(Q_ OS_WINCE)871 #elif defined(Q_WS_WINCE) 872 872 shapeTextWithCE(item); 873 873 #else … … 924 924 } 925 925 926 #if defined(Q_ OS_WINCE) //TODO926 #if defined(Q_WS_WINCE) //TODO 927 927 // set the glyph attributes heuristically. Assumes a 1 to 1 relationship between chars and glyphs 928 928 // and no reordering. … … 1043 1043 si.glyph_data_offset = layoutData->used; 1044 1044 1045 QFontEngine *fe = fontEngine(si, &si.ascent, &si.descent );1045 QFontEngine *fe = fontEngine(si, &si.ascent, &si.descent, &si.leading); 1046 1046 1047 1047 QTextEngine::ShaperFlags flags; … … 1100 1100 #endif 1101 1101 1102 static 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 1102 1112 /// take the item from layoutData->items and 1103 1113 void QTextEngine::shapeTextWithHarfbuzz(int item) const … … 1110 1120 si.glyph_data_offset = layoutData->used; 1111 1121 1112 QFontEngine *font = fontEngine(si, &si.ascent, &si.descent );1122 QFontEngine *font = fontEngine(si, &si.ascent, &si.descent, &si.leading); 1113 1123 1114 1124 bool kerningEnabled = this->font(si).d->kerning; … … 1190 1200 1191 1201 1192 int initial_glyph_pos = 0;1202 int remaining_glyphs = entire_shaper_item.num_glyphs; 1193 1203 int glyph_pos = 0; 1194 1204 // for each item shape using harfbuzz and store the results in our layoutData's glyphs array. … … 1210 1220 uint engineIdx = 0; 1211 1221 if (font->type() == QFontEngine::Multi) { 1212 engineIdx = uint( initialGlyphs.glyphs[itemBoundaries[k + 1]] >> 24);1222 engineIdx = uint(availableGlyphs(&si).glyphs[glyph_pos] >> 24); 1213 1223 1214 1224 actualFontEngine = static_cast<QFontEngineMulti *>(font)->engine(engineIdx); … … 1220 1230 shaper_item.glyphIndicesPresent = true; 1221 1231 1232 remaining_glyphs -= shaper_item.initialGlyphCount; 1233 1222 1234 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); 1232 1244 1233 1245 if (shaper_item.glyphIndicesPresent) { … … 1242 1254 1243 1255 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) 1246 1259 g.glyphs[i] = g.glyphs[i] | (engineIdx << 24); 1260 1261 for (hb_uint32 i = 0; i < shaper_item.item.length; ++i) 1247 1262 shaper_item.log_clusters[i] += glyph_pos; 1248 }1249 1263 1250 1264 if (kerningEnabled && !shaper_item.kerning_applied) … … 1252 1266 1253 1267 glyph_pos += shaper_item.num_glyphs; 1254 1255 initial_glyph_pos += shaper_item.initialGlyphCount;1256 1268 } 1257 1269 … … 1339 1351 } 1340 1352 } 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); 1343 1358 } else { 1344 1359 shapeText(item); … … 1385 1400 if (!length) 1386 1401 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 1388 1406 bool ignore = ignoreBidi; 1407 #endif 1389 1408 if (!ignore && option.textDirection() == Qt::LeftToRight) { 1390 1409 ignore = true; … … 1583 1602 for (int i = 0; i < layoutData->items.size(); i++) { 1584 1603 const QScriptItem *si = layoutData->items.constData() + i; 1604 QFontEngine *fe = fontEngine(*si); 1605 1585 1606 int pos = si->position; 1586 1607 int ilen = length(i); 1587 1608 if (pos > from + len) 1588 1609 break; 1589 if (pos + len > from) {1610 if (pos + ilen > from) { 1590 1611 if (!si->num_glyphs) 1591 1612 shape(i); … … 1620 1641 glyphEnd = (charEnd == ilen) ? si->num_glyphs : logClusters[charEnd]; 1621 1642 if (glyphStart <= glyphEnd ) { 1622 QFontEngine *fe = fontEngine(*si);1623 1643 glyph_metrics_t m = fe->boundingBox(glyphs.mid(glyphStart, glyphEnd - glyphStart)); 1624 1644 gm.x = qMin(gm.x, m.x + gm.xoff); … … 1630 1650 } 1631 1651 } 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); 1632 1657 } 1633 1658 } … … 1716 1741 } 1717 1742 1718 QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFixed *descent ) const1743 QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFixed *descent, QFixed *leading) const 1719 1744 { 1720 1745 QFontEngine *engine = 0; … … 1756 1781 *ascent = engine->ascent(); 1757 1782 *descent = engine->descent(); 1783 *leading = engine->leading(); 1758 1784 } 1759 1785 … … 1988 2014 } 1989 2015 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); 1992 2022 } 1993 2023 … … 2058 2088 int newAllocated = space_charAttributes + space_glyphs + space_logClusters; 2059 2089 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; 2064 2096 memory_on_stack = false; 2065 2097 … … 2199 2231 case '"': 2200 2232 case '~': 2233 case '|': 2201 2234 return true; 2202 2235 default: … … 2229 2262 specialData->addFormats[i].format = QTextCharFormat(); 2230 2263 } 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 */ 2270 static 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 2279 static 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); 2231 2286 } 2232 2287 … … 2331 2386 && currentWidth < availableWidth); 2332 2387 2388 if (nextCharJoins(layoutData->string, pos)) 2389 ellipsisText.prepend(QChar(0x200d) /* ZWJ */); 2390 2333 2391 return layoutData->string.left(pos) + ellipsisText; 2334 2392 } else if (mode == Qt::ElideLeft) { … … 2348 2406 && currentWidth < availableWidth); 2349 2407 2408 if (prevCharJoins(layoutData->string, pos)) 2409 ellipsisText.append(QChar(0x200d) /* ZWJ */); 2410 2350 2411 return ellipsisText + layoutData->string.mid(pos); 2351 2412 } else if (mode == Qt::ElideMiddle) { … … 2376 2437 && nextRightBreak > 0 2377 2438 && 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 */); 2378 2444 2379 2445 return layoutData->string.left(leftPos) + ellipsisText + layoutData->string.mid(rightPos);
Note:
See TracChangeset
for help on using the changeset viewer.