summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>2009-10-29 16:32:57 (GMT)
committerEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>2009-10-29 16:32:57 (GMT)
commit4204fdcc04e20eabd19704f2235ba06afa84605e (patch)
treec078d5bbd9ae783dc6e1c120dbb6dcdb17fd3f5e /src/gui
parent263c81d923a1ed90335a3fb05c87330630456073 (diff)
downloadQt-4204fdcc04e20eabd19704f2235ba06afa84605e.zip
Qt-4204fdcc04e20eabd19704f2235ba06afa84605e.tar.gz
Qt-4204fdcc04e20eabd19704f2235ba06afa84605e.tar.bz2
Avoid infinite loop when laying out text with unconvertible chars
When the stringToCMap() fails, it can be because it did not have enough space in the layout, or it can because of other errors. In order to implement "try-again" processing in a simple way, we had an infinite loop which assumed that stringToCMap() would always succeed in the second run (which would be the case if the only possible error was "not enough space".) Since there are other possible failures not related to the number of glyphs, you could easily get into an infinite loop here, e.g. when laying out text that contains the Byte Order Mark. The fix changes the implementation to explictly try stringToCMap() twice at max, and is also how it's implemented in the default qtextengine.cpp. Task-number: QTBUG-4680 Reviewed-by: Trond Conflicts: src/gui/text/qtextengine_mac.cpp tests/auto/qtextlayout/tst_qtextlayout.cpp
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/text/qtextengine_mac.cpp77
1 files changed, 37 insertions, 40 deletions
diff --git a/src/gui/text/qtextengine_mac.cpp b/src/gui/text/qtextengine_mac.cpp
index 4f20094..e35f9e0 100644
--- a/src/gui/text/qtextengine_mac.cpp
+++ b/src/gui/text/qtextengine_mac.cpp
@@ -595,53 +595,50 @@ void QTextEngine::shapeTextMac(int item) const
str = reinterpret_cast<const QChar *>(uc);
}
- while (true) {
- ensureSpace(num_glyphs);
- num_glyphs = layoutData->glyphLayout.numGlyphs - layoutData->used;
-
- QGlyphLayout g = availableGlyphs(&si);
- g.numGlyphs = num_glyphs;
- unsigned short *log_clusters = logClusters(&si);
-
- if (fe->stringToCMap(str,
- len,
- &g,
- &num_glyphs,
- flags,
- log_clusters,
- attributes())) {
-
- heuristicSetGlyphAttributes(str, len, &g, log_clusters, num_glyphs);
- break;
- }
+ ensureSpace(num_glyphs);
+ num_glyphs = layoutData->glyphLayout.numGlyphs - layoutData->used;
+
+ QGlyphLayout g = availableGlyphs(&si);
+ g.numGlyphs = num_glyphs;
+ unsigned short *log_clusters = logClusters(&si);
+
+ bool stringToCMapFailed = false;
+ if (!fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters, attributes())) {
+ ensureSpace(num_glyphs);
+ stringToCMapFailed = fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters,
+ attributes());
}
- si.num_glyphs = num_glyphs;
+ if (!stringToCMapFailed) {
+ heuristicSetGlyphAttributes(str, len, &g, log_clusters, num_glyphs);
- layoutData->used += si.num_glyphs;
+ si.num_glyphs = num_glyphs;
- QGlyphLayout g = shapedGlyphs(&si);
+ layoutData->used += si.num_glyphs;
- if (si.analysis.script == QUnicodeTables::Arabic) {
- QVarLengthArray<QArabicProperties> props(len + 2);
- QArabicProperties *properties = props.data();
- int f = si.position;
- int l = len;
- if (f > 0) {
- --f;
- ++l;
- ++properties;
- }
- if (f + l < layoutData->string.length()) {
- ++l;
- }
- qt_getArabicProperties((const unsigned short *)(layoutData->string.unicode()+f), l, props.data());
+ QGlyphLayout g = shapedGlyphs(&si);
- unsigned short *log_clusters = logClusters(&si);
+ if (si.analysis.script == QUnicodeTables::Arabic) {
+ QVarLengthArray<QArabicProperties> props(len + 2);
+ QArabicProperties *properties = props.data();
+ int f = si.position;
+ int l = len;
+ if (f > 0) {
+ --f;
+ ++l;
+ ++properties;
+ }
+ if (f + l < layoutData->string.length()) {
+ ++l;
+ }
+ qt_getArabicProperties((const unsigned short *)(layoutData->string.unicode()+f), l, props.data());
- for (int i = 0; i < len; ++i) {
- int gpos = log_clusters[i];
- g.attributes[gpos].justification = properties[i].justification;
+ unsigned short *log_clusters = logClusters(&si);
+
+ for (int i = 0; i < len; ++i) {
+ int gpos = log_clusters[i];
+ g.attributes[gpos].justification = properties[i].justification;
+ }
}
}