54 #include <private/qunicodetables_p.h> 84 generateScriptItemsSmallCaps(reinterpret_cast<const ushort *>(m_string.unicode()), start, length);
86 generateScriptItemsCapitalize(start, length);
88 generateScriptItemsAndChangeCase(start, length,
92 generateScriptItems(start, length);
96 enum { MaxItemLength = 4096 };
100 generateScriptItems(start, length);
101 if (m_items.isEmpty())
111 void generateScriptItems(
int start,
int length)
115 const int end = start + length;
116 for (
int i = start + 1; i <
end; ++i) {
128 if (m_analysis[i].bidiLevel == m_analysis[start].bidiLevel
129 && m_analysis[i].flags == m_analysis[start].flags
132 && i - start < MaxItemLength)
134 m_items.append(
QScriptItem(start, m_analysis[start]));
137 m_items.append(
QScriptItem(start, m_analysis[start]));
140 void generateScriptItemsCapitalize(
int start,
int length)
147 m_string.constData(), m_string.length(),
155 m_splitter->toNextBoundary();
158 const int end = start + length;
159 for (
int i = start + 1; i <
end; ++i) {
161 bool atWordBoundary =
false;
163 if (i == m_splitter->position()) {
166 atWordBoundary =
true;
168 m_splitter->toNextBoundary();
171 if (m_analysis[i] == itemAnalysis
174 && i - start < MaxItemLength)
179 itemAnalysis = m_analysis[start];
187 void generateScriptItemsSmallCaps(
const ushort *uc,
int start,
int length)
192 const int end = start + length;
194 for (
int i = start + 1; i <
end; ++i) {
196 if ((m_analysis[i] == m_analysis[start])
199 && i - start < MaxItemLength)
201 m_items.append(
QScriptItem(start, m_analysis[start]));
208 m_items.append(
QScriptItem(start, m_analysis[start]));
228 #if (BIDI_DEBUG >= 1) 234 static const char *directions[] = {
235 "DirL",
"DirR",
"DirEN",
"DirES",
"DirET",
"DirAN",
"DirCS",
"DirB",
"DirS",
"DirWS",
"DirON",
236 "DirLRE",
"DirLRO",
"DirAL",
"DirRLE",
"DirRLO",
"DirPDF",
"DirNSM",
"DirBN" 258 : cCtx(0),
base(rtl ? 1 : 0), level(rtl ? 1 : 0), override(false) {}
260 inline void embed(
bool rtl,
bool o =
false) {
261 unsigned int toAdd = 1;
262 if((level%2 != 0) == rtl ) {
266 ctx[cCtx].level = level;
267 ctx[cCtx].override =
override;
273 inline bool canPop()
const {
return cCtx != 0; }
277 level =
ctx[cCtx].level;
278 override =
ctx[cCtx].override;
307 int level = control.
level;
322 #if (BIDI_DEBUG >= 1) 323 qDebug(
"new run: dir=%s from %d, to %d level = %d override=%d", directions[dir], start, stop, level, control.
override);
336 const ushort *unicode,
int length,
340 int level = sor > 0 ? analysis[sor - 1].
bidiLevel : control.
level;
341 while (sor < length) {
360 bool hasBidi = rightToLeft;
388 while (current <= length) {
391 if (current == (
int)length)
396 #if (BIDI_DEBUG >= 2) 417 unsigned int level = control.
level+1;
418 if ((level%2 != 0) == rtl) ++level;
423 control.
embed(rtl,
override);
425 dir = status.
eor = edir;
468 eor = current; status.
eor = dir;
555 if (eor == current-1)
579 status.
eor = dirCurrent;
593 eor = current;
break;
609 eor = current; status.
eor = dirCurrent;
621 eor = current; status.
eor = dirCurrent;
650 eor = current;
break;
667 eor = current; status.
eor = dirCurrent;
679 eor = current; status.
eor = dirCurrent;
692 eor = current; status.
eor = dirCurrent;
715 if(current >= (
int)length)
break;
732 status.
last = dirCurrent;
757 status.
last = dirCurrent;
763 #if (BIDI_DEBUG >= 1) 764 qDebug() <<
"reached end of line current=" << current <<
", eor=" << eor;
781 while (i < numItems) {
783 if (levels[i] > levelHigh)
784 levelHigh = levels[i];
785 if (levels[i] < levelLow)
786 levelLow = levels[i];
795 if(!(levelLow%2)) levelLow++;
797 #if (BIDI_DEBUG >= 1) 801 int count = numItems - 1;
802 for (i = 0; i < numItems; i++)
805 while(levelHigh >= levelLow) {
808 while(i < count && levels[i] < levelHigh) i++;
810 while(i <= count && levels[i] >= levelHigh) i++;
815 for(
int j = 0; j < (end-start+1)/2; j++) {
816 int tmp = visualOrder[start+j];
817 visualOrder[start+j] = visualOrder[end-j];
818 visualOrder[end-j] = tmp;
826 #if (BIDI_DEBUG >= 1) 835 #if defined(Q_WS_X11) || defined (Q_WS_QWS) 837 #elif defined(Q_WS_MAC) 841 #include <private/qharfbuzz_p.h> 843 QT_END_INCLUDE_NAMESPACE
848 int nGlyphs = item->num_glyphs;
851 if (item->item.bidiLevel % 2)
854 bool result = fontEngine->
stringToCMap(reinterpret_cast<const QChar *>(item->string + item->item.pos), item->item.length, glyphs, &nGlyphs, shaperFlags);
855 item->num_glyphs = nGlyphs;
865 const int end = findItem(line.
from + line.
length - 1);
866 int item = findItem(line.
from);
869 for (item = findItem(line.
from); item <= end; ++item) {
873 si.
width = calculateTabWidth(item, x);
880 for (
int i = line.
from - si.
position - 1; i >= 0; i--) {
890 #if !defined(QT_ENABLE_HARFBUZZ_FOR_MAC) && defined(Q_WS_MAC) 893 static enum { Yes, No, Unknown }
status = Unknown;
895 if (status == Unknown) {
897 bool value = !v.
isEmpty() && v !=
"0" && v !=
"false";
898 if (value) status = Yes;
901 return status == Yes;
907 Q_ASSERT(item < layoutData->items.size());
913 #if defined(Q_WS_MAC) 914 #if !defined(QT_ENABLE_HARFBUZZ_FOR_MAC) 917 QFontEngine *actualFontEngine = fontEngine(si, &si.ascent, &si.descent, &si.leading);
919 actualFontEngine = static_cast<QFontEngineMulti *>(actualFontEngine)->engine(0);
922 HB_Script
script = (HB_Script) si.analysis.script;
923 if (face->supported_scripts[script])
924 shapeTextWithHarfbuzz(item);
927 #if !defined(QT_ENABLE_HARFBUZZ_FOR_MAC) 932 #elif defined(Q_WS_WINCE) 933 shapeTextWithCE(item);
935 shapeTextWithHarfbuzz(item);
944 QFont font = this->font(si);
949 if (letterSpacingIsAbsolute && letterSpacing.
value())
952 if (letterSpacing != 0) {
953 for (
int i = 1; i < si.num_glyphs; ++i) {
955 if (letterSpacingIsAbsolute)
959 advance += (letterSpacing - 100) * advance / 100;
963 if (letterSpacingIsAbsolute)
964 glyphs.
advances_x[si.num_glyphs-1] += letterSpacing;
967 advance += (letterSpacing - 100) * advance / 100;
970 if (wordSpacing != 0) {
971 for (
int i = 0; i < si.num_glyphs; ++i) {
972 if (glyphs.
attributes[i].justification == HB_Space
973 || glyphs.
attributes[i].justification == HB_Arabic_Space) {
975 if (i + 1 == si.num_glyphs
976 ||(glyphs.
attributes[i+1].justification != HB_Space
977 && glyphs.
attributes[i+1].justification != HB_Arabic_Space))
983 for (
int i = 0; i < si.num_glyphs; ++i)
994 #if defined(Q_WS_WINCE) //TODO 1008 for (
int i = 0; i < length; i++) {
1009 if (uc[i].isHighSurrogate() && i < length-1 && uc[i+1].isLowSurrogate()) {
1010 logClusters[i] = glyph_pos;
1011 logClusters[++i] = glyph_pos;
1013 logClusters[i] = glyph_pos;
1021 const bool symbolFont =
false;
1028 for (
int i = 1; i < length; ++i) {
1029 if (logClusters[i] == pos)
1033 while (pos < logClusters[i]) {
1038 if ((!symbolFont && uc[i].unicode() == 0x00ad) ||
qIsControlChar(uc[i].unicode()))
1046 cStart = logClusters[i];
1052 if ((uc[pos].unicode() & 0xff00) == 0x0e00) {
1054 unsigned char col = uc[pos].
cell();
1065 }
else if (col == 0xb1 ||
1074 }
else if (col == 0xbc) {
1081 glyphs->
attributes[pos].clusterStart =
false;
1082 glyphs->
attributes[pos].combiningClass = cmb;
1083 logClusters[i] = cStart;
1092 glyphs->
attributes[pos-1].justification = HB_Space;
1094 glyphs->
attributes[pos-1].justification = HB_Character;
1096 glyphs->
attributes[pos-1].justification = HB_NoJustification;
1100 pos = logClusters[length-1];
1102 glyphs->
attributes[pos].justification = HB_Space;
1104 glyphs->
attributes[pos].justification = HB_Character;
1114 QTextEngine::ShaperFlags flags;
1117 if (option.useDesignMetrics())
1118 flags |= DesignMetrics;
1124 const int len = length(item);
1125 int num_glyphs = length(item);
1132 for (
int i = 0; i < len; ++i) {
1138 str =
reinterpret_cast<const QChar *
>(uc);
1142 if (! ensureSpace(num_glyphs)) {
1145 const ushort *uc =
reinterpret_cast<const ushort *
>(str);
1150 num_glyphs = layoutData->glyphLayout.numGlyphs - layoutData->used;
1153 unsigned short *log_clusters = logClusters(&si);
1169 const ushort *uc =
reinterpret_cast<const ushort *
>(str);
1178 memmove(destination.
glyphs, source.
glyphs, num *
sizeof(HB_Glyph));
1181 memmove(destination.
offsets, source.
offsets, num *
sizeof(HB_FixedPoint));
1197 bool kerningEnabled = this->font(si).d->kerning;
1199 HB_ShaperItem entire_shaper_item;
1200 qMemSet(&entire_shaper_item, 0,
sizeof(entire_shaper_item));
1201 entire_shaper_item.string =
reinterpret_cast<const HB_UChar16 *
>(layoutData->string.constData());
1202 entire_shaper_item.stringLength = layoutData->string.length();
1204 entire_shaper_item.item.pos = si.
position;
1205 entire_shaper_item.item.length = length(item);
1208 HB_UChar16 upperCased[256];
1210 HB_UChar16 *uc = upperCased;
1211 if (entire_shaper_item.item.length > 256)
1212 uc =
new HB_UChar16[entire_shaper_item.item.length];
1213 for (
uint i = 0; i < entire_shaper_item.item.length; ++i) {
1219 entire_shaper_item.item.pos = 0;
1220 entire_shaper_item.string = uc;
1221 entire_shaper_item.stringLength = entire_shaper_item.item.length;
1224 entire_shaper_item.shaperFlags = 0;
1225 if (!kerningEnabled)
1226 entire_shaper_item.shaperFlags |= HB_ShaperFlag_NoKerning;
1227 if (option.useDesignMetrics())
1228 entire_shaper_item.shaperFlags |= HB_ShaperFlag_UseDesignMetrics;
1230 entire_shaper_item.num_glyphs =
qMax(layoutData->glyphLayout.numGlyphs - layoutData->used,
int(entire_shaper_item.item.length));
1231 if (! ensureSpace(entire_shaper_item.num_glyphs)) {
1233 delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string);
1236 QGlyphLayout initialGlyphs = availableGlyphs(&si).
mid(0, entire_shaper_item.num_glyphs);
1238 if (!
stringToGlyphs(&entire_shaper_item, &initialGlyphs, font)) {
1239 if (! ensureSpace(entire_shaper_item.num_glyphs)) {
1241 delete []
const_cast<HB_UChar16 *
>(entire_shaper_item.string);
1244 initialGlyphs = availableGlyphs(&si).
mid(0, entire_shaper_item.num_glyphs);
1246 if (!
stringToGlyphs(&entire_shaper_item, &initialGlyphs, font)) {
1248 if (
hasCaseChange(si) && entire_shaper_item.string != upperCased)
1249 delete []
const_cast<HB_UChar16 *
>(entire_shaper_item.string);
1257 itemBoundaries[0] = entire_shaper_item.item.pos;
1258 itemBoundaries[1] = 0;
1261 uint lastEngine = 0;
1262 int charIdx = entire_shaper_item.item.pos;
1263 const int stringEnd = charIdx + entire_shaper_item.item.length;
1264 for (
quint32 i = 0; i < entire_shaper_item.num_glyphs; ++i, ++charIdx) {
1265 uint engineIdx = initialGlyphs.
glyphs[i] >> 24;
1266 if (engineIdx != lastEngine && i > 0) {
1267 itemBoundaries.
append(charIdx);
1268 itemBoundaries.
append(i);
1270 lastEngine = engineIdx;
1271 if (HB_IsHighSurrogate(entire_shaper_item.string[charIdx])
1272 && charIdx < stringEnd - 1
1273 && HB_IsLowSurrogate(entire_shaper_item.string[charIdx + 1]))
1280 int remaining_glyphs = entire_shaper_item.num_glyphs;
1283 for (
int k = 0; k < itemBoundaries.
size(); k += 2) {
1285 HB_ShaperItem shaper_item = entire_shaper_item;
1287 shaper_item.item.pos = itemBoundaries[k];
1288 if (k < itemBoundaries.
size() - 3) {
1289 shaper_item.item.length = itemBoundaries[k + 2] - shaper_item.item.pos;
1290 shaper_item.num_glyphs = itemBoundaries[k + 3] - itemBoundaries[k + 1];
1292 shaper_item.item.length -= shaper_item.item.pos - entire_shaper_item.item.pos;
1293 shaper_item.num_glyphs -= itemBoundaries[k + 1];
1295 shaper_item.initialGlyphCount = shaper_item.num_glyphs;
1296 if (shaper_item.num_glyphs < shaper_item.item.length)
1297 shaper_item.num_glyphs = shaper_item.item.length;
1302 engineIdx =
uint(availableGlyphs(&si).glyphs[glyph_pos] >> 24);
1304 actualFontEngine =
static_cast<QFontEngineMulti *
>(font)->engine(engineIdx);
1314 shaper_item.glyphIndicesPresent =
true;
1316 remaining_glyphs -= shaper_item.initialGlyphCount;
1319 if (! ensureSpace(glyph_pos + shaper_item.num_glyphs + remaining_glyphs)) {
1321 delete []
const_cast<HB_UChar16 *
>(entire_shaper_item.string);
1326 if (shaper_item.num_glyphs > shaper_item.item.length)
1327 moveGlyphData(g.
mid(shaper_item.num_glyphs), g.
mid(shaper_item.initialGlyphCount), remaining_glyphs);
1329 shaper_item.glyphs = g.
glyphs;
1331 shaper_item.advances =
reinterpret_cast<HB_Fixed *
>(g.
advances_x);
1332 shaper_item.offsets =
reinterpret_cast<HB_FixedPoint *
>(g.
offsets);
1334 if (shaper_item.glyphIndicesPresent) {
1335 for (hb_uint32 i = 0; i < shaper_item.initialGlyphCount; ++i)
1336 shaper_item.glyphs[i] &= 0x00ffffff;
1339 shaper_item.log_clusters = logClusters(&si) + shaper_item.item.pos - entire_shaper_item.item.pos;
1344 QGlyphLayout g = availableGlyphs(&si).
mid(glyph_pos, shaper_item.num_glyphs);
1345 moveGlyphData(g.
mid(shaper_item.num_glyphs), g.
mid(shaper_item.initialGlyphCount), remaining_glyphs);
1347 for (hb_uint32 i = 0; i < shaper_item.num_glyphs; ++i)
1350 for (hb_uint32 i = 0; i < shaper_item.item.length; ++i)
1351 shaper_item.log_clusters[i] += glyph_pos;
1353 if (kerningEnabled && !shaper_item.kerning_applied)
1356 glyph_pos += shaper_item.num_glyphs;
1364 if (
hasCaseChange(si) && entire_shaper_item.string != upperCased)
1365 delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string);
1418 hbScriptItems[i].pos = si.
position;
1419 hbScriptItems[i].length =
length(i);
1426 hbScriptItems.data(), hbScriptItems.size(),
1511 #if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) 1520 if (!ignore && !rtl) {
1524 while (start < end) {
1525 if (start->
unicode() >= 0x590) {
1541 for (
int i = 0; i <
length; ++i)
1542 analysis[i].bidiLevel = 1;
1564 *const_cast<ushort*>(uc) = 0x21B5;
1586 lastScript = analysis->
script;
1602 int format = it.value()->format;
1604 int prevPosition = 0;
1608 if (it == end || format != frag->
format) {
1614 itemizer.generate(prevPosition, position - prevPosition,
1615 formats()->charFormat(format).fontCapitalization());
1617 if (position < length)
1618 itemizer.generate(position, length - position,
1619 formats()->charFormat(format).fontCapitalization());
1629 itemizer.generate(0, length, static_cast<QFont::Capitalization> (
fnt.
d->
capital));
1661 while (left <= right) {
1662 int middle = ((right-
left)/2)+
left;
1665 else if (strPos < layoutData->items[middle].
position)
1686 if (pos >= from + len)
1688 if (pos + ilen > from) {
1709 int charFrom = from - pos;
1712 int glyphStart = logClusters[charFrom];
1713 if (charFrom > 0 && logClusters[charFrom-1] == glyphStart)
1714 while (charFrom < ilen && logClusters[charFrom] == glyphStart)
1716 if (charFrom < ilen) {
1717 glyphStart = logClusters[charFrom];
1718 int charEnd = from + len - 1 - pos;
1719 if (charEnd >= ilen)
1721 int glyphEnd = logClusters[charEnd];
1722 while (charEnd < ilen && logClusters[charEnd] == glyphEnd)
1724 glyphEnd = (charEnd == ilen) ? si->
num_glyphs : logClusters[charEnd];
1727 for (
int i = glyphStart; i < glyphEnd; i++)
1747 if (pos > from + len)
1749 if (pos + ilen > from) {
1765 int charFrom = from - pos;
1768 int glyphStart = logClusters[charFrom];
1769 if (charFrom > 0 && logClusters[charFrom-1] == glyphStart)
1770 while (charFrom < ilen && logClusters[charFrom] == glyphStart)
1772 if (charFrom < ilen) {
1774 glyphStart = logClusters[charFrom];
1775 int charEnd = from + len - 1 - pos;
1776 if (charEnd >= ilen)
1778 int glyphEnd = logClusters[charEnd];
1779 while (charEnd < ilen && logClusters[charEnd] == glyphEnd)
1781 glyphEnd = (charEnd == ilen) ? si->
num_glyphs : logClusters[charEnd];
1782 if (glyphStart <= glyphEnd ) {
1807 if (pos > from + len)
1809 if (pos + len > from) {
1816 int charFrom = from - pos;
1819 int glyphStart = logClusters[charFrom];
1820 if (charFrom > 0 && logClusters[charFrom-1] == glyphStart)
1821 while (charFrom < ilen && logClusters[charFrom] == glyphStart)
1823 if (charFrom < ilen) {
1824 glyphStart = logClusters[charFrom];
1825 int charEnd = from + len - 1 - pos;
1826 if (charEnd >= ilen)
1828 int glyphEnd = logClusters[charEnd];
1829 while (charEnd < ilen && logClusters[charEnd] == glyphEnd)
1831 glyphEnd = (charEnd == ilen) ? si->
num_glyphs : logClusters[charEnd];
1832 if (glyphStart <= glyphEnd ) {
1859 font =
QFont(font, pdev);
1904 font =
QFont(font, pdev);
1955 *ascent = engine->
ascent();
1961 return scaledEngine;
1977 point->glyph = glyph;
1978 point->fontEngine = fe;
1980 if (type >= HB_Arabic_Normal) {
1984 fe->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
1988 point->type = HB_NoJustification;
1989 point->kashidaWidth = 0;
2003 const_cast<QScriptLine &
>(line).gridfitted =
true;
2023 int line_length = line.
length;
2028 while (line_length && a[line_length-1].whiteSpace)
2037 int nItems =
findItem(line.
from + line_length - 1) - firstItem + 1;
2042 QFixed minKashida = 0x100000;
2047 for (
int i = 0; i < nItems; ++i) {
2050 shape(firstItem + i);
2053 for (
int i = 0; i < nItems; ++i) {
2056 int kashida_type = HB_Arabic_Normal;
2057 int kashida_pos = -1;
2060 int end =
qMin(line.
from + line_length - (
int)si.
position, length(firstItem+i));
2064 int gs = log_clusters[start];
2069 for (
int i = gs; i < ge; ++i) {
2074 justificationPoints.
resize(nPoints+3);
2075 int justification = g.
attributes[i].justification;
2077 switch(justification) {
2078 case HB_NoJustification:
2082 case HB_Arabic_Space :
2083 if (kashida_pos >= 0) {
2085 set(&justificationPoints[nPoints], kashida_type, g.
mid(kashida_pos),
fontEngine(si));
2086 if (justificationPoints[nPoints].kashidaWidth > 0) {
2087 minKashida =
qMin(minKashida, justificationPoints[nPoints].kashidaWidth);
2088 maxJustify =
qMax(maxJustify, justificationPoints[nPoints].type);
2093 kashida_type = HB_Arabic_Normal;
2096 set(&justificationPoints[nPoints++], justification, g.
mid(i),
fontEngine(si));
2097 maxJustify =
qMax(maxJustify, justification);
2099 case HB_Arabic_Normal :
2100 case HB_Arabic_Waw :
2101 case HB_Arabic_BaRa :
2102 case HB_Arabic_Alef :
2103 case HB_Arabic_HaaDal :
2104 case HB_Arabic_Seen :
2105 case HB_Arabic_Kashida :
2106 if (justification >= kashida_type) {
2108 kashida_type = justification;
2112 if (kashida_pos >= 0) {
2113 set(&justificationPoints[nPoints], kashida_type, g.
mid(kashida_pos),
fontEngine(si));
2114 if (justificationPoints[nPoints].kashidaWidth > 0) {
2115 minKashida =
qMin(minKashida, justificationPoints[nPoints].kashidaWidth);
2116 maxJustify =
qMax(maxJustify, justificationPoints[nPoints].type);
2134 if (maxJustify >= HB_Arabic_Normal) {
2135 while (need >= minKashida) {
2136 for (
int type = maxJustify; need >= minKashida && type >= HB_Arabic_Normal; --
type) {
2137 for (
int i = 0; need >= minKashida && i < nPoints; ++i) {
2138 if (justificationPoints[i].type == type && justificationPoints[i].kashidaWidth <= need) {
2139 justificationPoints[i].glyph.justifications->nKashidas++;
2141 justificationPoints[i].glyph.justifications->space_18d6 += justificationPoints[i].kashidaWidth.
value();
2142 need -= justificationPoints[i].kashidaWidth;
2153 maxJustify =
qMin(maxJustify, (
int)HB_Space);
2154 for (
int type = maxJustify; need != 0 && type > 0; --
type) {
2156 for (
int i = 0; i < nPoints; ++i) {
2157 if (justificationPoints[i].type == type)
2166 for (
int i = 0; i < nPoints; ++i) {
2167 if (justificationPoints[i].type == type) {
2170 justificationPoints[i].glyph.justifications[0].space_18d6 = add.
value();
2201 leading =
qMax(leading + ascent, other_leading + other_ascent) -
qMax(ascent, other_ascent);
2202 ascent =
qMax(ascent, other_ascent);
2203 descent =
qMax(descent, other_descent);
2210 memory_on_stack =
false;
2214 haveCharAttributes =
false;
2216 available_glyphs = 0;
2224 int space_charAttributes =
sizeof(HB_CharAttributes)*
string.
length()/
sizeof(
void*) + 1;
2225 int space_logClusters =
sizeof(
unsigned short)*
string.
length()/
sizeof(
void*) + 1;
2240 void *m =
memory + space_charAttributes + space_logClusters;
2243 memset(
memory, 0, space_charAttributes*
sizeof(
void *));
2266 int space_charAttributes =
sizeof(HB_CharAttributes)*
string.
length()/
sizeof(
void*) + 1;
2267 int space_logClusters =
sizeof(
unsigned short)*
string.
length()/
sizeof(
void*) + 1;
2270 int newAllocated = space_charAttributes + space_glyphs + space_logClusters;
2274 if (space_charAttributes < 0 || space_logClusters < 0 || space_glyphs < 0 || newAllocated <
allocated) {
2286 memcpy(newMem, memory,
allocated*
sizeof(
void *));
2291 m += space_charAttributes;
2293 m += space_logClusters;
2295 const int space_preGlyphLayout = space_charAttributes + space_logClusters;
2317 memmove(newLayout.
glyphs, oldLayout.
glyphs, numGlyphs *
sizeof(HB_Glyph));
2321 newLayout.
clear(numGlyphs);
2337 for (
int i = 0; i <
lines.
size(); ++i) {
2338 lines[i].justified = 0;
2339 lines[i].gridfitted = 0;
2358 return it.value()->format;
2471 if (pos ==
string.
length())
2504 for (
int i = si.
position; i < end - 1; ++i) {
2506 const int gp = logClusters[i - si.
position];
2508 attributes[i + 1].charStop =
false;
2509 attributes[i + 1].whiteSpace =
false;
2510 attributes[i + 1].lineBreakType = HB_NoBreak;
2528 QChar ellipsisChar(0x2026);
2535 ? static_cast<QFontEngineMulti *>(fe)->engine(0)
2543 && feForEllipsis->
canRender(&ellipsisChar, 1)) {
2545 feForEllipsis->
stringToCMap(&ellipsisChar, 1, &ellipsisGlyph, &nGlyphs, 0);
2549 if (ellipsisGlyph.
glyphs[0]) {
2551 ellipsisText = ellipsisChar;
2560 for (
int i = 0; i < nGlyphs; ++i)
2562 ellipsisText = dotDotDot;
2566 const QFixed availableWidth =
width - ellipsisWidth;
2567 if (availableWidth < 0)
2583 while (nextBreak < layoutData->
string.
length() && !attributes[nextBreak].charStop)
2586 currentWidth += this->
width(pos, nextBreak - pos);
2587 }
while (nextBreak < layoutData->
string.
length()
2588 && currentWidth < availableWidth);
2591 ellipsisText.prepend(
QChar(0x200d) );
2603 while (nextBreak > 0 && !attributes[nextBreak].charStop)
2606 currentWidth += this->
width(nextBreak, pos - nextBreak);
2607 }
while (nextBreak > 0
2608 && currentWidth < availableWidth);
2611 ellipsisText.append(
QChar(0x200d) );
2619 int nextLeftBreak = 0;
2625 leftPos = nextLeftBreak;
2626 rightPos = nextRightBreak;
2629 while (nextLeftBreak < layoutData->
string.
length() && !attributes[nextLeftBreak].charStop)
2633 while (nextRightBreak > 0 && !attributes[nextRightBreak].charStop)
2636 leftWidth += this->
width(leftPos, nextLeftBreak - leftPos);
2637 rightWidth += this->
width(nextRightBreak, rightPos - nextRightBreak);
2638 }
while (nextLeftBreak < layoutData->
string.
length()
2639 && nextRightBreak > 0
2640 && leftWidth + rightWidth < availableWidth);
2643 ellipsisText.prepend(
QChar(0x200d) );
2645 ellipsisText.append(
QChar(0x200d) );
2654 struct QScriptItemComparator {
2667 strPos, QScriptItemComparator());
2670 if (it->position == strPos) {
2700 for(
int j = 0; j < breakGlyph; ++j)
2728 while(iter != tabArray.
end()) {
2739 for (
int i = 0; i < tabArray.
size(); ++i) {
2769 for (
int i=0; i <
end; i++)
2775 switch (tabSpec.
type) {
2798 QFixed nextTabPos = ((x / tab).truncate() + 1) * tab;
2799 QFixed tabWidth = nextTabPos - x;
2854 int offsetInCluster = 0;
2855 for (
int i = pos - 1; i >= 0; i--) {
2856 if (logClusters[i] == glyph_pos)
2864 if (offsetInCluster > 0) {
2865 int clusterLength = 0;
2866 for (
int i = pos - offsetInCluster; i < max; i++) {
2867 if (logClusters[i] == glyph_pos)
2873 return glyphs.
advances_x[glyph_pos] * offsetInCluster / clusterLength;
2882 int from,
int to,
int glyph_pos,
int *start)
2884 int clusterLength = 0;
2885 for (
int i = from; i < to; i++) {
2886 if (logClusters[i] == glyph_pos && attributes[i].charStop) {
2891 else if (clusterLength)
2894 return clusterLength;
2899 bool cursorOnCharacter)
2902 int clusterStart = -1;
2903 int clusterLength = 0;
2907 if (glyph_pos == -1)
2911 for (i = 0; i <
end; i++)
2912 if (logClusters[i] == glyph_pos)
2918 if (glyph_pos == -1 && end > 0)
2919 glyph_pos = logClusters[end - 1];
2925 const HB_CharAttributes *attrs =
attributes();
2927 clusterLength =
getClusterLength(logClusters, attrs, 0, end, glyph_pos, &clusterStart);
2929 if (clusterLength) {
2933 QFixed perItemWidth = glyphWidth / clusterLength;
2934 if (perItemWidth <= 0)
2935 return si->
position + clusterStart;
2936 QFixed left = x > edge ? edge : edge - glyphWidth;
2938 QFixed dist = x - left - n * perItemWidth;
2939 int closestItem = dist > (perItemWidth / 2) ? n + 1 : n;
2940 if (cursorOnCharacter && closestItem > 0)
2942 int pos = si->
position + clusterStart + closestItem;
2944 while (pos < end && !attrs[pos].charStop)
2953 const HB_CharAttributes *attrs =
attributes();
2954 if (!attrs || oldPos < 0)
2960 while (oldPos && !attrs[oldPos].charStop)
2967 const HB_CharAttributes *attrs =
attributes();
2971 if (!attrs || oldPos < 0 || oldPos >= len)
2975 while (oldPos < len && !attrs[oldPos].charStop)
2986 for (
int i = 0; i <
lines.
size(); ++i) {
2998 bool lastLine = lineNum >=
lines.
size() - 1;
3000 while (!iterator.
atEnd()) {
3007 for (; i >= min; i--)
3013 for (; i < max; i++)
3024 if (insertionPoints.
size() > 0)
3025 return insertionPoints.
last();
3034 if (insertionPoints.
size() > 0)
3035 return insertionPoints.
first();
3054 int i, max = insertionPoints.
size();
3055 for (i = 0; i < max; i++)
3056 if (pos == insertionPoints[i]) {
3059 return insertionPoints[i + 1];
3062 return insertionPoints[i - 1];
3065 if (moveRight ^ alignRight) {
3080 _layoutData(string, _memory, MemSize)
3087 : justified(false), underlineStyle(
QTextCharFormat::NoUnderline), charFormat(format),
3134 const int end = firstGlyphIndex + numGlyphs;
3169 qreal h = height.toReal();
3177 QLineF l = xform.
map(
QLineF(x.toReal(), y.toReal(), xoff.toReal(), yoff.toReal()));
3192 line(eng->lines[_lineNum]),
3195 lineEnd(line.from + line.length),
3196 firstItem(eng->findItem(line.from)),
3197 lastItem(eng->findItem(lineEnd - 1)),
3198 nItems((firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0),
3201 visualOrder(nItems),
3203 selection(_selection)
3211 for (
int i = 0; i <
nItems; ++i)
3260 *selectionX = *selectionWidth = 0;
3267 ||
si->
position + itemLength <= selection->start)
3281 int start_glyph = logClusters[from];
3286 for (
int g =
glyphsEnd - 1; g >= end_glyph; --g)
3288 for (
int g = end_glyph - 1; g >= start_glyph; --g)
3293 for (
int g = start_glyph; g < end_glyph; ++g)
3302 *selectionX =
x + soff + leftOffsetInLigature;
3303 *selectionWidth = swidth - leftOffsetInLigature;
glyph_metrics_t tightBoundingBox(const QGlyphLayout &glyphs)
QTextCharFormat format(const QScriptItem *si) const
void setPointSize(int)
Sets the point size to pointSize.
QChar::Direction direction() const
QTextCharFormat charFormat(int index) const
QFont font() const
Returns the font for this character format.
QVarLengthArray< uchar > levels
The QTextLayout::FormatRange structure is used to apply extra formatting information for a specified ...
qreal y() const
Returns the y-coordinate of the rectangle's top edge.
bool isRightToLeft() const
Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
Joining
This enum type defines the Unicode joining attributes.
unsigned short trailingSpaces
QGlyphJustification * justifications
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
QString text() const
Returns the block's contents as plain text.
The QTextCharFormat class provides formatting information for characters in a QTextDocument.
static bool prevCharJoins(const QString &string, int pos)
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
QString elidedText(Qt::TextElideMode mode, const QFixed &width, int flags=0) const
#define QT_END_NAMESPACE
This macro expands to.
bool atWordSeparator(int position) const
int getClusterLength(unsigned short *logClusters, const HB_CharAttributes *attributes, int from, int to, int glyph_pos, int *start)
void clear(int first=0, int last=-1)
bool letterSpacingIsAbsolute
const QChar at(int i) const
Returns the character at the given index position in the string.
bool qIsControlChar(ushort uc)
int lineNumberForTextPosition(int pos)
bool fontStrikeOut() const
Returns true if the text format's font is struck out (has a horizontal line drawn through it); otherw...
ushort unicode() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
#define it(className, varName)
The QFlag class is a helper data type for QFlags.
int count(const T &t) const
Returns the number of occurrences of value in the vector.
Q_GUI_EXPORT int qt_defaultDpiY()
virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const
QFixed calculateTabWidth(int index, QFixed x) const
returns the width of tab at index (in the tabs array) with the tab-start at position x ...
static bool hasCaseChange(const QScriptItem &si)
virtual void resizeInlineObject(QTextInlineObject item, int posInDocument, const QTextFormat &format)
Sets the size of the inline object item corresponding to the text format.
SpecialData * specialData
T & first()
Returns a reference to the first item in the vector.
int pixelSize() const
Returns the pixel size of the font if it was set with setPixelSize().
#define at(className, varName)
The QByteArray class provides an array of bytes.
Q_CORE_EXPORT QTextStream & reset(QTextStream &s)
int length() const
Returns the number of characters in this string.
The QPointF class defines a point in the plane using floating point precision.
int findItem(int strPos) const
static qreal position(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine)
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the vector...
iterator begin()
Returns an STL-style iterator pointing to the first item in the list.
void insertionPointsForLine(int lineNum, QVector< int > &insertionPoints)
Flags flags() const
Returns the flags associated with the option.
static bool ignore(const char *test, const char *const *table)
int endOfLine(int lineNum)
QFontEngine * fontEngine(const QScriptItem &si, QFixed *ascent=0, QFixed *descent=0, QFixed *leading=0) const
bool ensureSpace(int nGlyphs) const
static LibLoadStatus status
#define QT_END_INCLUDE_NAMESPACE
This macro is equivalent to QT_BEGIN_NAMESPACE.
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
const unsigned short * logClusters
long ASN1_INTEGER_get ASN1_INTEGER * a
int count(const T &t) const
Returns the number of occurrences of value in the list.
QAbstractTextDocumentLayout * layout() const
bool ref()
Atomically increments the value of this QAtomicInt.
QFixed offsetInLigature(const QScriptItem *si, int pos, int max, int glyph_pos)
int start
Specifies the beginning of the format range within the text layout's text.
unsigned short * logClusters(const QScriptItem *si) const
QChar::Direction lastStrong
The QString class provides a Unicode character string.
QTextFormat format(int idx) const
QGlyphLayout mid(int position, int n=-1) const
static QFixed fromReal(qreal r)
static bool stringToGlyphs(HB_ShaperItem *item, QGlyphLayout *glyphs, QFontEngine *fontEngine)
QVarLengthArray< int > visualOrder
Capitalization
Rendering option for text this font applies to.
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const =0
QFontPrivate * smallCapsFontPrivate() const
const HB_CharAttributes * attributes() const
void addRequiredBoundaries() const
virtual Type type() const =0
The QChar class provides a 16-bit Unicode character.
Q_CORE_EXPORT QTextStream & right(QTextStream &s)
QList< QTextLayout::FormatRange > addFormats
qreal tabStop() const
Returns the distance in device units between tab stops.
TabType type
Determine which type is used.
FragmentMap::ConstIterator FragmentIterator
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Category category() const
Returns the character's category.
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
qreal x() const
Returns the x-coordinate of this point.
void resize(int size)
Sets the size of the vector to size.
QTextBlock next() const
Returns the text block in the document after this block, or an empty text block if this is the last o...
The QLineF class provides a two-dimensional vector using floating point precision.
int position() const
Returns the index of the block's first character within the document.
qreal position
Distance from the start of the paragraph.
Q_CORE_EXPORT void qDebug(const char *,...)
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the vector.
bool hasProperty(int propertyId) const
Returns true if the text format has a property with the given propertyId; otherwise returns false...
QFont resolve(const QFont &) const
Returns a new QFont that has attributes copied from other that have not been previously set on this f...
VerticalAlignment
This enum describes the ways that adjacent characters can be vertically aligned.
void shapeLine(const QScriptLine &line)
QFontEngine * prevFontEngine
#define QT_BEGIN_NAMESPACE
This macro expands to.
glyph_metrics_t transformed(const QTransform &xform) const
FragmentIterator find(int pos) const
The QRectF class defines a rectangle in the plane using floating point precision. ...
UnderlineStyle underlineStyle() const
Returns the style of underlining the text.
bool fontOverline() const
Returns true if the text format's font is overlined; otherwise returns false.
QChar delimiter
If type is DelimitorTab; tab until this char is found in the text.
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
void clear()
Removes all the elements from the vector and releases the memory used by the vector.
const QChar * unicode() const
Returns a '\0'-terminated Unicode representation of the string.
The QTextFormat class provides formatting information for a QTextDocument.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
virtual bool canRender(const QChar *string, int len)=0
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the list...
qreal height() const
Returns the height of the rectangle.
bool isRightToLeft() const
Returns true if the string is read right to left.
QGlyphLayout shapedGlyphs(const QScriptItem *si) const
const T & at(int i) const
Returns the item at index position i in the list.
bool deref()
Atomically decrements the value of this QAtomicInt.
virtual QFixed ascent() const =0
void setBoundary(int strPos) const
virtual QFixed descent() const =0
static void appendItems(QScriptAnalysis *analysis, int &start, int &stop, const QBidiControl &control, QChar::Direction dir)
static void bidiReorder(int numRuns, const quint8 *levels, int *visualOrder)
void resetFontEngineCache()
void setPosition(int position)
Sets the current position of the QTextBoundaryFinder to position.
qreal ascent() const
Corresponds to the ascent of the piece of text that is drawn.
glyph_metrics_t boundingBox(int from, int len) const
int indexOf(QChar c, int from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
unsigned short num_glyphs
qreal width() const
Returns the width of the rectangle.
QChar toUpper() const
Returns the uppercase equivalent if the character is lowercase or titlecase; otherwise returns the ch...
int positionInLigature(const QScriptItem *si, int end, QFixed x, QFixed edge, int glyph_pos, bool cursorOnCharacter)
const QTextLayout::FormatRange * selection
virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs)=0
int length() const
Returns the length of the block in characters.
QTransform qt_true_matrix(qreal w, qreal h, QTransform x)
qreal descent() const
Corresponds to the descent of the piece of text that is drawn.
static bool nextCharJoins(const QString &string, int pos)
static int spaceNeededForGlyphLayout(int totalGlyphs)
void indexAdditionalFormats()
void shapeTextWithHarfbuzz(int item) const
take the item from layoutData->items and
QTextCharFormat charFormat() const
Returns the QTextCharFormat that describes the block's character format.
Q_CORE_EXPORT int QT_FASTCALL script(uint ucs4)
static bool enableHarfBuzz()
QList< Tab > tabs() const
Returns a list of tab positions defined for the text layout.
const T & at(int i) const
Returns the item at index position i in the vector.
static void init(QTextEngine *e)
QFontEngine * engineForScript(int script) const
qreal width() const
Specifies the total width of the text to be drawn.
HB_Font harfbuzzFont() const
void shapeTextWithCE(int item) const
unsigned short * logClustersPtr
static void heuristicSetGlyphAttributes(const QChar *uc, int length, QGlyphLayout *glyphs, unsigned short *logClusters, int num_glyphs)
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
void insert(int i, const T &t)
Inserts value at index position i in the vector.
VerticalAlignment verticalAlignment() const
Returns the vertical alignment used for characters with this format.
QStackTextEngine(const QString &string, const QFont &f)
void setDefaultHeight(QTextEngine *eng)
static bool bidiItemize(QTextEngine *engine, QScriptAnalysis *analysis, QBidiControl &control)
void * qMemSet(void *dest, int c, size_t n)
void shape(int item) const
QTextCharFormat::UnderlineStyle underlineStyle
Direction
This enum type defines the Unicode direction attributes.
void justify(const QScriptLine &si)
void merge(const QTextFormat &other)
Merges the other format with this format; where there are conflicts the other format takes precedence...
The QTextInlineObject class represents an inline object in a QTextLayout.
The QFont class specifies a font used for drawing text.
qreal x() const
Returns the x-coordinate of the rectangle's left edge.
Qt::LayoutDirection textDirection() const
Returns the direction of the text layout defined by the option.
QVector< int > addFormatIndices
static QChar::Direction skipBoundryNeutrals(QScriptAnalysis *analysis, const ushort *unicode, int length, int &sor, int &eor, QBidiControl &control)
QExplicitlySharedDataPointer< QFontPrivate > d
T & last()
Returns a reference to the last item in the vector.
QTextItemInt midItem(QFontEngine *fontEngine, int firstGlyphIndex, int numGlyphs) const
QVector< int > resolvedFormatIndices
int size() const
Returns the number of items in the list.
bool getSelectionBounds(QFixed *selectionX, QFixed *selectionWidth) const
int length(int item) const
QPaintDevice * paintDevice() const
Returns the paint device used to render the document's layout.
int previousLogicalPosition(int oldPos) const
bool boolProperty(int propertyId) const
Returns the value of the property specified by propertyId.
QFixed alignLine(const QScriptLine &line)
if(void) toggleToolbarShown
uchar cell() const
Returns the cell (least significant byte) of the Unicode character.
QChar::Direction basicDirection() const
void push_back(const T &t)
This function is provided for STL compatibility.
char toLatin1() const
Returns the Latin-1 character equivalent to the QChar, or 0.
int formatIndex(const QScriptItem *si) const
#define QT_BEGIN_INCLUDE_NAMESPACE
This macro is equivalent to QT_END_NAMESPACE.
void grow(char *address, int totalGlyphs)
QFixed effectiveAdvance(int item) const
bool isValid() const
Returns true if this text block is valid; otherwise returns false.
Qt::Alignment alignment() const
Returns the text alignment defined by the option.
int length
Specifies the numer of characters the format range spans.
HB_GlyphAttributes * attributes
bool atSpace(int position) const
QTextCharFormat format
Specifies the format to apply.
int pointSize() const
Returns the point size of the font.
glyph_metrics_t tightBoundingBox(int from, int len) const
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
bool isEmpty() const
Returns true if the vector has size 0; otherwise returns false.
unsigned int baseLevel() const
const T * constData() const
Returns a const pointer to the data stored in the vector.
QTextDocumentPrivate * docHandle() const
QFont smallCapsFont() const
Direction direction() const
Returns the character's direction.
bool reallocate(int totalGlyphs)
void setPixelSize(int)
Sets the font size to pixelSize pixels.
static Qt::LayoutDirection keyboardInputDirection()
Returns the current keyboard input direction.
QFontEngine * prevScaledFontEngine
HB_Bool qShapeItem(HB_ShaperItem *item)
const QTextCharFormat charFormat
void initWithScriptItem(const QScriptItem &si)
static const KeyPair *const end
void splitItem(int item, int pos) const
int positionAfterVisualMovement(int oldPos, QTextCursor::MoveOperation op)
void embed(bool rtl, bool o=false)
void qGetCharAttributes(const HB_UChar16 *string, hb_uint32 stringLength, const HB_ScriptItem *items, hb_uint32 numItems, HB_CharAttributes *attributes)
Q_CORE_EXPORT QTextStream & left(QTextStream &s)
QString & insert(int i, QChar c)
QTextFormatCollection * formats() const
int indexForFormat(const QTextFormat &f)
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
The QTextBoundaryFinder class provides a way of finding Unicode text boundaries in a string...
QChar toLower() const
Returns the lowercase equivalent if the character is uppercase or titlecase; otherwise returns the ch...
int size() const
Returns the number of items in the vector.
QFont font() const
Returns the font that should be used to draw the text.
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
QAbstractTextDocumentLayout * docLayout() const
const QChar * constData() const
Returns a pointer to the data stored in the QString.
int beginningOfLine(int lineNum)
QTextLineItemIterator(QTextEngine *eng, int lineNum, const QPointF &pos=QPointF(), const QTextLayout::FormatRange *_selection=0)
void shapeText(int item) const
Q_DECLARE_TYPEINFO(QJustificationPoint, Q_PRIMITIVE_TYPE)
static void moveGlyphData(const QGlyphLayout &destination, const QGlyphLayout &source, int num)
QFixed leadingSpaceWidth(const QScriptLine &line)
Q_CORE_EXPORT const Properties *QT_FASTCALL properties(uint ucs4)
virtual QFixed leading() const =0
static void releaseCachedFontEngine(QFontEngine *fontEngine)
void resolveAdditionalFormats() const
Each tab definition is represented by this struct.
HB_Face harfbuzzFace() const
int nextLogicalPosition(int oldPos) const
QFixed width(int charFrom, int numChars) const