src/gui/text/qtextengine.cpp
changeset 37 758a864f9613
parent 33 3e2da88830cd
equal deleted inserted replaced
36:ef0373b55136 37:758a864f9613
   921 
   921 
   922     for (int i = 0; i < si.num_glyphs; ++i)
   922     for (int i = 0; i < si.num_glyphs; ++i)
   923         si.width += glyphs.advances_x[i];
   923         si.width += glyphs.advances_x[i];
   924 }
   924 }
   925 
   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;
       
   931 }
       
   932 
   926 #if defined(Q_WS_WINCE) //TODO
   933 #if defined(Q_WS_WINCE) //TODO
   927 // set the glyph attributes heuristically. Assumes a 1 to 1 relationship between chars and glyphs
   934 // set the glyph attributes heuristically. Assumes a 1 to 1 relationship between chars and glyphs
   928 // and no reordering.
   935 // and no reordering.
   929 // also computes logClusters heuristically
   936 // also computes logClusters heuristically
   930 static void heuristicSetGlyphAttributes(const QChar *uc, int length, QGlyphLayout *glyphs, unsigned short *logClusters, int num_glyphs)
   937 static void heuristicSetGlyphAttributes(const QChar *uc, int length, QGlyphLayout *glyphs, unsigned short *logClusters, int num_glyphs)
  1048     if (si.analysis.bidiLevel % 2)
  1055     if (si.analysis.bidiLevel % 2)
  1049         flags |= RightToLeft;
  1056         flags |= RightToLeft;
  1050     if (option.useDesignMetrics())
  1057     if (option.useDesignMetrics())
  1051 	flags |= DesignMetrics;
  1058 	flags |= DesignMetrics;
  1052 
  1059 
  1053     attributes(); // pre-initialize char attributes
  1060     // pre-initialize char attributes
       
  1061     if (! attributes())
       
  1062         return;
  1054 
  1063 
  1055     const int len = length(item);
  1064     const int len = length(item);
  1056     int num_glyphs = length(item);
  1065     int num_glyphs = length(item);
  1057     const QChar *str = layoutData->string.unicode() + si.position;
  1066     const QChar *str = layoutData->string.unicode() + si.position;
  1058     ushort upperCased[256];
  1067     ushort upperCased[256];
  1059     if (si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase
  1068     if (hasCaseChange(si)) {
  1060             || si.analysis.flags == QScriptAnalysis::Lowercase) {
       
  1061         ushort *uc = upperCased;
  1069         ushort *uc = upperCased;
  1062         if (len > 256)
  1070         if (len > 256)
  1063             uc = new ushort[len];
  1071             uc = new ushort[len];
  1064         for (int i = 0; i < len; ++i) {
  1072         for (int i = 0; i < len; ++i) {
  1065             if(si.analysis.flags == QScriptAnalysis::Lowercase)
  1073             if(si.analysis.flags == QScriptAnalysis::Lowercase)
  1069         }
  1077         }
  1070         str = reinterpret_cast<const QChar *>(uc);
  1078         str = reinterpret_cast<const QChar *>(uc);
  1071     }
  1079     }
  1072 
  1080 
  1073     while (true) {
  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         num_glyphs = layoutData->glyphLayout.numGlyphs - layoutData->used;
  1090         num_glyphs = layoutData->glyphLayout.numGlyphs - layoutData->used;
  1076 
  1091 
  1077         QGlyphLayout g = availableGlyphs(&si);
  1092         QGlyphLayout g = availableGlyphs(&si);
  1078         unsigned short *log_clusters = logClusters(&si);
  1093         unsigned short *log_clusters = logClusters(&si);
  1079 
  1094 
  1090     si.num_glyphs = num_glyphs;
  1105     si.num_glyphs = num_glyphs;
  1091 
  1106 
  1092     layoutData->used += si.num_glyphs;
  1107     layoutData->used += si.num_glyphs;
  1093 
  1108 
  1094     const ushort *uc = reinterpret_cast<const ushort *>(str);
  1109     const ushort *uc = reinterpret_cast<const ushort *>(str);
  1095     if ((si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase
  1110     if (hasCaseChange(si) && uc != upperCased)
  1096          || si.analysis.flags == QScriptAnalysis::Lowercase)
       
  1097         && uc != upperCased)
       
  1098         delete [] uc;
  1111         delete [] uc;
  1099 }
  1112 }
  1100 #endif
  1113 #endif
  1101 
  1114 
  1102 static inline void moveGlyphData(const QGlyphLayout &destination, const QGlyphLayout &source, int num)
  1115 static inline void moveGlyphData(const QGlyphLayout &destination, const QGlyphLayout &source, int num)
  1131     entire_shaper_item.item.pos = si.position;
  1144     entire_shaper_item.item.pos = si.position;
  1132     entire_shaper_item.item.length = length(item);
  1145     entire_shaper_item.item.length = length(item);
  1133     entire_shaper_item.item.bidiLevel = si.analysis.bidiLevel;
  1146     entire_shaper_item.item.bidiLevel = si.analysis.bidiLevel;
  1134 
  1147 
  1135     HB_UChar16 upperCased[256]; // XXX what about making this 4096, so we don't have to extend it ever.
  1148     HB_UChar16 upperCased[256]; // XXX what about making this 4096, so we don't have to extend it ever.
  1136     if (si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase
  1149     if (hasCaseChange(si)) {
  1137             || si.analysis.flags == QScriptAnalysis::Lowercase) {
       
  1138         HB_UChar16 *uc = upperCased;
  1150         HB_UChar16 *uc = upperCased;
  1139         if (entire_shaper_item.item.length > 256)
  1151         if (entire_shaper_item.item.length > 256)
  1140             uc = new HB_UChar16[entire_shaper_item.item.length];
  1152             uc = new HB_UChar16[entire_shaper_item.item.length];
  1141         for (uint i = 0; i < entire_shaper_item.item.length; ++i) {
  1153         for (uint i = 0; i < entire_shaper_item.item.length; ++i) {
  1142             if(si.analysis.flags == QScriptAnalysis::Lowercase)
  1154             if(si.analysis.flags == QScriptAnalysis::Lowercase)
  1154         entire_shaper_item.shaperFlags |= HB_ShaperFlag_NoKerning;
  1166         entire_shaper_item.shaperFlags |= HB_ShaperFlag_NoKerning;
  1155     if (option.useDesignMetrics())
  1167     if (option.useDesignMetrics())
  1156         entire_shaper_item.shaperFlags |= HB_ShaperFlag_UseDesignMetrics;
  1168         entire_shaper_item.shaperFlags |= HB_ShaperFlag_UseDesignMetrics;
  1157 
  1169 
  1158     entire_shaper_item.num_glyphs = qMax(layoutData->glyphLayout.numGlyphs - layoutData->used, int(entire_shaper_item.item.length));
  1170     entire_shaper_item.num_glyphs = qMax(layoutData->glyphLayout.numGlyphs - layoutData->used, int(entire_shaper_item.item.length));
  1159     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     }
  1160     QGlyphLayout initialGlyphs = availableGlyphs(&si).mid(0, entire_shaper_item.num_glyphs);
  1176     QGlyphLayout initialGlyphs = availableGlyphs(&si).mid(0, entire_shaper_item.num_glyphs);
  1161 
  1177 
  1162     if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, font)) {
  1178     if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, font)) {
  1163         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         }
  1164         initialGlyphs = availableGlyphs(&si).mid(0, entire_shaper_item.num_glyphs);
  1184         initialGlyphs = availableGlyphs(&si).mid(0, entire_shaper_item.num_glyphs);
  1165 
  1185 
  1166         if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, font)) {
  1186         if (!stringToGlyphs(&entire_shaper_item, &initialGlyphs, font)) {
  1167             // ############ if this happens there's a bug in the fontengine
  1187             // ############ if this happens there's a bug in the fontengine
  1168             if ((si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase
  1188             if (hasCaseChange(si) && entire_shaper_item.string != upperCased)
  1169                     || si.analysis.flags == QScriptAnalysis::Lowercase) && entire_shaper_item.string != upperCased)
       
  1170                 delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string);
  1189                 delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string);
  1171             return;
  1190             return;
  1172         }
  1191         }
  1173     }
  1192     }
  1174 
  1193 
  1229         shaper_item.glyphIndicesPresent = true;
  1248         shaper_item.glyphIndicesPresent = true;
  1230 
  1249 
  1231         remaining_glyphs -= shaper_item.initialGlyphCount;
  1250         remaining_glyphs -= shaper_item.initialGlyphCount;
  1232 
  1251 
  1233         do {
  1252         do {
  1234             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             }
  1235 
  1258 
  1236             const QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos);
  1259             const QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos);
  1237             moveGlyphData(g.mid(shaper_item.num_glyphs), g.mid(shaper_item.initialGlyphCount), remaining_glyphs);
  1260             moveGlyphData(g.mid(shaper_item.num_glyphs), g.mid(shaper_item.initialGlyphCount), remaining_glyphs);
  1238 
  1261 
  1239             shaper_item.glyphs = g.glyphs;
  1262             shaper_item.glyphs = g.glyphs;
  1269 //     qDebug("    -> item: script=%d num_glyphs=%d", shaper_item.script, shaper_item.num_glyphs);
  1292 //     qDebug("    -> item: script=%d num_glyphs=%d", shaper_item.script, shaper_item.num_glyphs);
  1270     si.num_glyphs = glyph_pos;
  1293     si.num_glyphs = glyph_pos;
  1271 
  1294 
  1272     layoutData->used += si.num_glyphs;
  1295     layoutData->used += si.num_glyphs;
  1273 
  1296 
  1274     if ((si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase)
  1297     if (hasCaseChange(si) && entire_shaper_item.string != upperCased)
  1275         && entire_shaper_item.string != upperCased)
       
  1276         delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string);
  1298         delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string);
  1277 }
  1299 }
  1278 
  1300 
  1279 static void init(QTextEngine *e)
  1301 static void init(QTextEngine *e)
  1280 {
  1302 {
  1315 {
  1337 {
  1316     if (layoutData && layoutData->haveCharAttributes)
  1338     if (layoutData && layoutData->haveCharAttributes)
  1317         return (HB_CharAttributes *) layoutData->memory;
  1339         return (HB_CharAttributes *) layoutData->memory;
  1318 
  1340 
  1319     itemize();
  1341     itemize();
  1320     ensureSpace(layoutData->string.length());
  1342     if (! ensureSpace(layoutData->string.length()))
       
  1343         return NULL;
  1321 
  1344 
  1322     QVarLengthArray<HB_ScriptItem> hbScriptItems(layoutData->items.size());
  1345     QVarLengthArray<HB_ScriptItem> hbScriptItems(layoutData->items.size());
  1323 
  1346 
  1324     for (int i = 0; i < layoutData->items.size(); ++i) {
  1347     for (int i = 0; i < layoutData->items.size(); ++i) {
  1325         const QScriptItem &si = layoutData->items[i];
  1348         const QScriptItem &si = layoutData->items[i];
  1536 
  1559 
  1537 
  1560 
  1538 int QTextEngine::findItem(int strPos) const
  1561 int QTextEngine::findItem(int strPos) const
  1539 {
  1562 {
  1540     itemize();
  1563     itemize();
  1541 
  1564     int left = 0;
  1542     // ##### use binary search
  1565     int right = layoutData->items.size()-1;
  1543     int item;
  1566     while(left <= right) {
  1544     for (item = layoutData->items.size()-1; item > 0; --item) {
  1567         int middle = ((right-left)/2)+left;
  1545         if (layoutData->items[item].position <= strPos)
  1568         if (strPos > layoutData->items[middle].position)
  1546             break;
  1569             left = middle+1;
  1547     }
  1570         else if(strPos < layoutData->items[middle].position)
  1548     return item;
  1571             right = middle-1;
       
  1572         else {
       
  1573             return middle;
       
  1574         }
       
  1575     }
       
  1576     return right;
  1549 }
  1577 }
  1550 
  1578 
  1551 QFixed QTextEngine::width(int from, int len) const
  1579 QFixed QTextEngine::width(int from, int len) const
  1552 {
  1580 {
  1553     itemize();
  1581     itemize();
  1616 
  1644 
  1617     glyph_metrics_t gm;
  1645     glyph_metrics_t gm;
  1618 
  1646 
  1619     for (int i = 0; i < layoutData->items.size(); i++) {
  1647     for (int i = 0; i < layoutData->items.size(); i++) {
  1620         const QScriptItem *si = layoutData->items.constData() + i;
  1648         const QScriptItem *si = layoutData->items.constData() + i;
  1621         QFontEngine *fe = fontEngine(*si);
       
  1622 
  1649 
  1623         int pos = si->position;
  1650         int pos = si->position;
  1624         int ilen = length(i);
  1651         int ilen = length(i);
  1625         if (pos > from + len)
  1652         if (pos > from + len)
  1626             break;
  1653             break;
  1646             int glyphStart = logClusters[charFrom];
  1673             int glyphStart = logClusters[charFrom];
  1647             if (charFrom > 0 && logClusters[charFrom-1] == glyphStart)
  1674             if (charFrom > 0 && logClusters[charFrom-1] == glyphStart)
  1648                 while (charFrom < ilen && logClusters[charFrom] == glyphStart)
  1675                 while (charFrom < ilen && logClusters[charFrom] == glyphStart)
  1649                     charFrom++;
  1676                     charFrom++;
  1650             if (charFrom < ilen) {
  1677             if (charFrom < ilen) {
       
  1678                 QFontEngine *fe = fontEngine(*si);
  1651                 glyphStart = logClusters[charFrom];
  1679                 glyphStart = logClusters[charFrom];
  1652                 int charEnd = from + len - 1 - pos;
  1680                 int charEnd = from + len - 1 - pos;
  1653                 if (charEnd >= ilen)
  1681                 if (charEnd >= ilen)
  1654                     charEnd = ilen-1;
  1682                     charEnd = ilen-1;
  1655                 int glyphEnd = logClusters[charEnd];
  1683                 int glyphEnd = logClusters[charEnd];
  1664                     gm.height = qMax(gm.height, m.height+gm.yoff);
  1692                     gm.height = qMax(gm.height, m.height+gm.yoff);
  1665                     gm.xoff += m.xoff;
  1693                     gm.xoff += m.xoff;
  1666                     gm.yoff += m.yoff;
  1694                     gm.yoff += m.yoff;
  1667                 }
  1695                 }
  1668             }
  1696             }
  1669 
       
  1670             glyph_t glyph = glyphs.glyphs[logClusters[ilen - 1]];
       
  1671             glyph_metrics_t gi = fe->boundingBox(glyph);
       
  1672             if (gi.isValid())
       
  1673                 gm.width -= qRound(gi.xoff - gi.x - gi.width);
       
  1674         }
  1697         }
  1675     }
  1698     }
  1676     return gm;
  1699     return gm;
  1677 }
  1700 }
  1678 
  1701 
  1862     // justify line
  1885     // justify line
  1863     int maxJustify = 0;
  1886     int maxJustify = 0;
  1864 
  1887 
  1865     // don't include trailing white spaces when doing justification
  1888     // don't include trailing white spaces when doing justification
  1866     int line_length = line.length;
  1889     int line_length = line.length;
  1867     const HB_CharAttributes *a = attributes()+line.from;
  1890     const HB_CharAttributes *a = attributes();
       
  1891     if (! a)
       
  1892         return;
       
  1893     a += line.from;
  1868     while (line_length && a[line_length-1].whiteSpace)
  1894     while (line_length && a[line_length-1].whiteSpace)
  1869         --line_length;
  1895         --line_length;
  1870     // subtract one char more, as we can't justfy after the last character
  1896     // subtract one char more, as we can't justfy after the last character
  1871     --line_length;
  1897     --line_length;
  1872 
  1898 
  2043     memory = 0;
  2069     memory = 0;
  2044     allocated = 0;
  2070     allocated = 0;
  2045     memory_on_stack = false;
  2071     memory_on_stack = false;
  2046     used = 0;
  2072     used = 0;
  2047     hasBidi = false;
  2073     hasBidi = false;
  2048     inLayout = false;
  2074     layoutState = LayoutEmpty;
  2049     haveCharAttributes = false;
  2075     haveCharAttributes = false;
  2050     logClustersPtr = 0;
  2076     logClustersPtr = 0;
  2051     available_glyphs = 0;
  2077     available_glyphs = 0;
  2052 }
  2078 }
  2053 
  2079 
  2077         glyphLayout.clear();
  2103         glyphLayout.clear();
  2078         memset(memory, 0, space_charAttributes*sizeof(void *));
  2104         memset(memory, 0, space_charAttributes*sizeof(void *));
  2079     }
  2105     }
  2080     used = 0;
  2106     used = 0;
  2081     hasBidi = false;
  2107     hasBidi = false;
  2082     inLayout = false;
  2108     layoutState = LayoutEmpty;
  2083     haveCharAttributes = false;
  2109     haveCharAttributes = false;
  2084 }
  2110 }
  2085 
  2111 
  2086 QTextEngine::LayoutData::~LayoutData()
  2112 QTextEngine::LayoutData::~LayoutData()
  2087 {
  2113 {
  2088     if (!memory_on_stack)
  2114     if (!memory_on_stack)
  2089         free(memory);
  2115         free(memory);
  2090     memory = 0;
  2116     memory = 0;
  2091 }
  2117 }
  2092 
  2118 
  2093 void QTextEngine::LayoutData::reallocate(int totalGlyphs)
  2119 bool QTextEngine::LayoutData::reallocate(int totalGlyphs)
  2094 {
  2120 {
  2095     Q_ASSERT(totalGlyphs >= glyphLayout.numGlyphs);
  2121     Q_ASSERT(totalGlyphs >= glyphLayout.numGlyphs);
  2096     if (memory_on_stack && available_glyphs >= totalGlyphs) {
  2122     if (memory_on_stack && available_glyphs >= totalGlyphs) {
  2097         glyphLayout.grow(glyphLayout.data(), totalGlyphs);
  2123         glyphLayout.grow(glyphLayout.data(), totalGlyphs);
  2098         return;
  2124         return true;
  2099     }
  2125     }
  2100 
  2126 
  2101     int space_charAttributes = sizeof(HB_CharAttributes)*string.length()/sizeof(void*) + 1;
  2127     int space_charAttributes = sizeof(HB_CharAttributes)*string.length()/sizeof(void*) + 1;
  2102     int space_logClusters = sizeof(unsigned short)*string.length()/sizeof(void*) + 1;
  2128     int space_logClusters = sizeof(unsigned short)*string.length()/sizeof(void*) + 1;
  2103     int space_glyphs = QGlyphLayout::spaceNeededForGlyphLayout(totalGlyphs)/sizeof(void*) + 2;
  2129     int space_glyphs = QGlyphLayout::spaceNeededForGlyphLayout(totalGlyphs)/sizeof(void*) + 2;
  2104 
  2130 
  2105     int newAllocated = space_charAttributes + space_glyphs + space_logClusters;
  2131     int newAllocated = space_charAttributes + space_glyphs + space_logClusters;
  2106     Q_ASSERT(newAllocated >= allocated);
  2132     // These values can be negative if the length of string/glyphs causes overflow,
       
  2133     // we can't layout such a long string all at once, so return false here to
       
  2134     // indicate there is a failure
       
  2135     if (space_charAttributes < 0 || space_logClusters < 0 || space_glyphs < 0 || newAllocated < allocated) {
       
  2136         layoutState = LayoutFailed;
       
  2137         return false;
       
  2138     }
       
  2139 
  2107     void **newMem = memory;
  2140     void **newMem = memory;
  2108     newMem = (void **)::realloc(memory_on_stack ? 0 : memory, newAllocated*sizeof(void *));
  2141     newMem = (void **)::realloc(memory_on_stack ? 0 : memory, newAllocated*sizeof(void *));
  2109     Q_CHECK_PTR(newMem);
  2142     if (!newMem) {
  2110     if (memory_on_stack && newMem)
  2143         layoutState = LayoutFailed;
       
  2144         return false;
       
  2145     }
       
  2146     if (memory_on_stack)
  2111         memcpy(newMem, memory, allocated*sizeof(void *));
  2147         memcpy(newMem, memory, allocated*sizeof(void *));
  2112     memory = newMem;
  2148     memory = newMem;
  2113     memory_on_stack = false;
  2149     memory_on_stack = false;
  2114 
  2150 
  2115     void **m = memory;
  2151     void **m = memory;
  2122         memset(memory + allocated, 0, (space_preGlyphLayout - allocated)*sizeof(void *));
  2158         memset(memory + allocated, 0, (space_preGlyphLayout - allocated)*sizeof(void *));
  2123 
  2159 
  2124     glyphLayout.grow(reinterpret_cast<char *>(m), totalGlyphs);
  2160     glyphLayout.grow(reinterpret_cast<char *>(m), totalGlyphs);
  2125 
  2161 
  2126     allocated = newAllocated;
  2162     allocated = newAllocated;
       
  2163     return true;
  2127 }
  2164 }
  2128 
  2165 
  2129 // grow to the new size, copying the existing data to the new layout
  2166 // grow to the new size, copying the existing data to the new layout
  2130 void QGlyphLayout::grow(char *address, int totalGlyphs)
  2167 void QGlyphLayout::grow(char *address, int totalGlyphs)
  2131 {
  2168 {
  2153         delete layoutData;
  2190         delete layoutData;
  2154         layoutData = 0;
  2191         layoutData = 0;
  2155     } else {
  2192     } else {
  2156         layoutData->used = 0;
  2193         layoutData->used = 0;
  2157         layoutData->hasBidi = false;
  2194         layoutData->hasBidi = false;
  2158         layoutData->inLayout = false;
  2195         layoutData->layoutState = LayoutEmpty;
  2159         layoutData->haveCharAttributes = false;
  2196         layoutData->haveCharAttributes = false;
  2160     }
  2197     }
  2161     for (int i = 0; i < lines.size(); ++i) {
  2198     for (int i = 0; i < lines.size(); ++i) {
  2162         lines[i].justified = 0;
  2199         lines[i].justified = 0;
  2163         lines[i].gridfitted = 0;
  2200         lines[i].gridfitted = 0;
  2224     switch (c.toLatin1()) {
  2261     switch (c.toLatin1()) {
  2225     case '.':
  2262     case '.':
  2226     case ',':
  2263     case ',':
  2227     case '?':
  2264     case '?':
  2228     case '!':
  2265     case '!':
       
  2266     case '@':
       
  2267     case '#':
       
  2268     case '$':
  2229     case ':':
  2269     case ':':
  2230     case ';':
  2270     case ';':
  2231     case '-':
  2271     case '-':
  2232     case '<':
  2272     case '<':
  2233     case '>':
  2273     case '>':
  2244     case '&':
  2284     case '&':
  2245     case '^':
  2285     case '^':
  2246     case '*':
  2286     case '*':
  2247     case '\'':
  2287     case '\'':
  2248     case '"':
  2288     case '"':
       
  2289     case '`':
  2249     case '~':
  2290     case '~':
  2250     case '|':
  2291     case '|':
  2251         return true;
  2292         return true;
  2252     default:
  2293     default:
  2253         return false;
  2294         return false;
  2312             QScriptItem &si = layoutData->items[i];
  2353             QScriptItem &si = layoutData->items[i];
  2313             if (!si.num_glyphs)
  2354             if (!si.num_glyphs)
  2314                 shape(i);
  2355                 shape(i);
  2315 
  2356 
  2316             HB_CharAttributes *attributes = const_cast<HB_CharAttributes *>(this->attributes());
  2357             HB_CharAttributes *attributes = const_cast<HB_CharAttributes *>(this->attributes());
       
  2358             if (!attributes)
       
  2359                 return QString();
       
  2360 
  2317             unsigned short *logClusters = this->logClusters(&si);
  2361             unsigned short *logClusters = this->logClusters(&si);
  2318             QGlyphLayout glyphs = shapedGlyphs(&si);
  2362             QGlyphLayout glyphs = shapedGlyphs(&si);
  2319 
  2363 
  2320             const int end = si.position + length(&si);
  2364             const int end = si.position + length(&si);
  2321             for (int i = si.position; i < end - 1; ++i)
  2365             for (int i = si.position; i < end - 1; ++i)
  2383     const QFixed availableWidth = width - ellipsisWidth;
  2427     const QFixed availableWidth = width - ellipsisWidth;
  2384     if (availableWidth < 0)
  2428     if (availableWidth < 0)
  2385         return QString();
  2429         return QString();
  2386 
  2430 
  2387     const HB_CharAttributes *attributes = this->attributes();
  2431     const HB_CharAttributes *attributes = this->attributes();
       
  2432     if (!attributes)
       
  2433         return QString();
  2388 
  2434 
  2389     if (mode == Qt::ElideRight) {
  2435     if (mode == Qt::ElideRight) {
  2390         QFixed currentWidth;
  2436         QFixed currentWidth;
  2391         int pos = 0;
  2437         int pos = 0;
  2392         int nextBreak = 0;
  2438         int nextBreak = 0;