qtextengine.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/text/qtextengine.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2015 The Qt Company Ltd.-
4** Contact: http://www.qt.io/licensing/-
5**-
6** This file is part of the QtGui module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL21$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see http://www.qt.io/terms-conditions. For further-
15** information use the contact form at http://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 2.1 or version 3 as published by the Free-
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and-
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the-
22** following information to ensure the GNU Lesser General Public License-
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and-
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.-
25**-
26** As a special exception, The Qt Company gives you certain additional-
27** rights. These rights are described in The Qt Company LGPL Exception-
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.-
29**-
30** $QT_END_LICENSE$-
31**-
32****************************************************************************/-
33-
34#include "qdebug.h"-
35#include "qtextformat.h"-
36#include "qtextformat_p.h"-
37#include "qtextengine_p.h"-
38#include "qabstracttextdocumentlayout.h"-
39#include "qtextlayout.h"-
40#include "qtextboundaryfinder.h"-
41#include "qvarlengtharray.h"-
42#include "qfont.h"-
43#include "qfont_p.h"-
44#include "qfontengine_p.h"-
45#include "qstring.h"-
46#include "qtextdocument_p.h"-
47#include "qrawfont.h"-
48#include "qrawfont_p.h"-
49#include <qguiapplication.h>-
50#include <qinputmethod.h>-
51#include <algorithm>-
52#include <stdlib.h>-
53-
54QT_BEGIN_NAMESPACE-
55-
56static const float smallCapsFraction = 0.7f;-
57-
58namespace {-
59// Helper class used in QTextEngine::itemize-
60// keep it out here to allow us to keep supporting various compilers.-
61class Itemizer {-
62public:-
63 Itemizer(const QString &string, const QScriptAnalysis *analysis, QScriptItemArray &items)-
64 : m_string(string),-
65 m_analysis(analysis),-
66 m_items(items),-
67 m_splitter(0)-
68 {-
69 }
never executed: end of block
0
70 ~Itemizer()-
71 {-
72 delete m_splitter;-
73 }
never executed: end of block
0
74-
75 /// generate the script items-
76 /// The caps parameter is used to choose the algoritm of splitting text and assiging roles to the textitems-
77 void generate(int start, int length, QFont::Capitalization caps)-
78 {-
79 if (caps == QFont::SmallCaps)
caps == QFont::SmallCapsDescription
TRUEnever evaluated
FALSEnever evaluated
0
80 generateScriptItemsSmallCaps(reinterpret_cast<const ushort *>(m_string.unicode()), start, length);
never executed: generateScriptItemsSmallCaps(reinterpret_cast<const ushort *>(m_string.unicode()), start, length);
0
81 else if(caps == QFont::Capitalize)
caps == QFont::CapitalizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
82 generateScriptItemsCapitalize(start, length);
never executed: generateScriptItemsCapitalize(start, length);
0
83 else if(caps != QFont::MixedCase) {
caps != QFont::MixedCaseDescription
TRUEnever evaluated
FALSEnever evaluated
0
84 generateScriptItemsAndChangeCase(start, length,-
85 caps == QFont::AllLowercase ? QScriptAnalysis::Lowercase : QScriptAnalysis::Uppercase);-
86 }
never executed: end of block
0
87 else-
88 generateScriptItems(start, length);
never executed: generateScriptItems(start, length);
0
89 }-
90-
91private:-
92 enum { MaxItemLength = 4096 };-
93-
94 void generateScriptItemsAndChangeCase(int start, int length, QScriptAnalysis::Flags flags)-
95 {-
96 generateScriptItems(start, length);-
97 if (m_items.isEmpty()) // the next loop won't work in that case
m_items.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
98 return;
never executed: return;
0
99 QScriptItemArray::Iterator iter = m_items.end();-
100 do {-
101 iter--;-
102 if (iter->analysis.flags < QScriptAnalysis::LineOrParagraphSeparator)
iter->analysis...graphSeparatorDescription
TRUEnever evaluated
FALSEnever evaluated
0
103 iter->analysis.flags = flags;
never executed: iter->analysis.flags = flags;
0
104 } while (iter->position > start);
never executed: end of block
iter->position > startDescription
TRUEnever evaluated
FALSEnever evaluated
0
105 }
never executed: end of block
0
106-
107 void generateScriptItems(int start, int length)-
108 {-
109 if (!length)
!lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
110 return;
never executed: return;
0
111 const int end = start + length;-
112 for (int i = start + 1; i < end; ++i) {
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
113 if (m_analysis[i].bidiLevel == m_analysis[start].bidiLevel
m_analysis[i]....art].bidiLevelDescription
TRUEnever evaluated
FALSEnever evaluated
0
114 && m_analysis[i].flags == m_analysis[start].flags
m_analysis[i]....s[start].flagsDescription
TRUEnever evaluated
FALSEnever evaluated
0
115 && (m_analysis[i].script == m_analysis[start].script || m_string[i] == QLatin1Char('.'))
m_analysis[i]....[start].scriptDescription
TRUEnever evaluated
FALSEnever evaluated
m_string[i] ==...atin1Char('.')Description
TRUEnever evaluated
FALSEnever evaluated
0
116 && m_analysis[i].flags < QScriptAnalysis::SpaceTabOrObject
m_analysis[i]....aceTabOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
117 && i - start < MaxItemLength)
i - start < MaxItemLengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
118 continue;
never executed: continue;
0
119 m_items.append(QScriptItem(start, m_analysis[start]));-
120 start = i;-
121 }
never executed: end of block
0
122 m_items.append(QScriptItem(start, m_analysis[start]));-
123 }
never executed: end of block
0
124-
125 void generateScriptItemsCapitalize(int start, int length)-
126 {-
127 if (!length)
!lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
128 return;
never executed: return;
0
129-
130 if (!m_splitter)
!m_splitterDescription
TRUEnever evaluated
FALSEnever evaluated
0
131 m_splitter = new QTextBoundaryFinder(QTextBoundaryFinder::Word,
never executed: m_splitter = new QTextBoundaryFinder(QTextBoundaryFinder::Word, m_string.constData(), m_string.length(), 0, 0);
0
132 m_string.constData(), m_string.length(),
never executed: m_splitter = new QTextBoundaryFinder(QTextBoundaryFinder::Word, m_string.constData(), m_string.length(), 0, 0);
0
133 /*buffer*/0, /*buffer size*/0);
never executed: m_splitter = new QTextBoundaryFinder(QTextBoundaryFinder::Word, m_string.constData(), m_string.length(), 0, 0);
0
134-
135 m_splitter->setPosition(start);-
136 QScriptAnalysis itemAnalysis = m_analysis[start];-
137-
138 if (m_splitter->boundaryReasons() & QTextBoundaryFinder::StartOfItem)
m_splitter->bo...r::StartOfItemDescription
TRUEnever evaluated
FALSEnever evaluated
0
139 itemAnalysis.flags = QScriptAnalysis::Uppercase;
never executed: itemAnalysis.flags = QScriptAnalysis::Uppercase;
0
140-
141 m_splitter->toNextBoundary();-
142-
143 const int end = start + length;-
144 for (int i = start + 1; i < end; ++i) {
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
145 bool atWordStart = false;-
146-
147 if (i == m_splitter->position()) {
i == m_splitter->position()Description
TRUEnever evaluated
FALSEnever evaluated
0
148 if (m_splitter->boundaryReasons() & QTextBoundaryFinder::StartOfItem) {
m_splitter->bo...r::StartOfItemDescription
TRUEnever evaluated
FALSEnever evaluated
0
149 Q_ASSERT(m_analysis[i].flags < QScriptAnalysis::TabOrObject);-
150 atWordStart = true;-
151 }
never executed: end of block
0
152-
153 m_splitter->toNextBoundary();-
154 }
never executed: end of block
0
155-
156 if (m_analysis[i] == itemAnalysis
m_analysis[i] == itemAnalysisDescription
TRUEnever evaluated
FALSEnever evaluated
0
157 && m_analysis[i].flags < QScriptAnalysis::TabOrObject
m_analysis[i]....s::TabOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
158 && !atWordStart
!atWordStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
159 && i - start < MaxItemLength)
i - start < MaxItemLengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
160 continue;
never executed: continue;
0
161-
162 m_items.append(QScriptItem(start, itemAnalysis));-
163 start = i;-
164 itemAnalysis = m_analysis[start];-
165-
166 if (atWordStart)
atWordStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
167 itemAnalysis.flags = QScriptAnalysis::Uppercase;
never executed: itemAnalysis.flags = QScriptAnalysis::Uppercase;
0
168 }
never executed: end of block
0
169 m_items.append(QScriptItem(start, itemAnalysis));-
170 }
never executed: end of block
0
171-
172 void generateScriptItemsSmallCaps(const ushort *uc, int start, int length)-
173 {-
174 if (!length)
!lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
175 return;
never executed: return;
0
176 bool lower = (QChar::category(uc[start]) == QChar::Letter_Lowercase);-
177 const int end = start + length;-
178 // split text into parts that are already uppercase and parts that are lowercase, and mark the latter to be uppercased later.-
179 for (int i = start + 1; i < end; ++i) {
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
180 bool l = (QChar::category(uc[i]) == QChar::Letter_Lowercase);-
181 if ((m_analysis[i] == m_analysis[start])
(m_analysis[i]...alysis[start])Description
TRUEnever evaluated
FALSEnever evaluated
0
182 && m_analysis[i].flags < QScriptAnalysis::TabOrObject
m_analysis[i]....s::TabOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
183 && l == lower
l == lowerDescription
TRUEnever evaluated
FALSEnever evaluated
0
184 && i - start < MaxItemLength)
i - start < MaxItemLengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
185 continue;
never executed: continue;
0
186 m_items.append(QScriptItem(start, m_analysis[start]));-
187 if (lower)
lowerDescription
TRUEnever evaluated
FALSEnever evaluated
0
188 m_items.last().analysis.flags = QScriptAnalysis::SmallCaps;
never executed: m_items.last().analysis.flags = QScriptAnalysis::SmallCaps;
0
189-
190 start = i;-
191 lower = l;-
192 }
never executed: end of block
0
193 m_items.append(QScriptItem(start, m_analysis[start]));-
194 if (lower)
lowerDescription
TRUEnever evaluated
FALSEnever evaluated
0
195 m_items.last().analysis.flags = QScriptAnalysis::SmallCaps;
never executed: m_items.last().analysis.flags = QScriptAnalysis::SmallCaps;
0
196 }
never executed: end of block
0
197-
198 const QString &m_string;-
199 const QScriptAnalysis * const m_analysis;-
200 QScriptItemArray &m_items;-
201 QTextBoundaryFinder *m_splitter;-
202};-
203}-
204-
205-
206// -----------------------------------------------------------------------------
207//-
208// The BiDi algorithm-
209//-
210// -----------------------------------------------------------------------------
211-
212#define BIDI_DEBUG 0-
213#if (BIDI_DEBUG >= 1)-
214QT_BEGIN_INCLUDE_NAMESPACE-
215#include <iostream>-
216QT_END_INCLUDE_NAMESPACE-
217using namespace std;-
218-
219static const char *directions[] = {-
220 "DirL", "DirR", "DirEN", "DirES", "DirET", "DirAN", "DirCS", "DirB", "DirS", "DirWS", "DirON",-
221 "DirLRE", "DirLRO", "DirAL", "DirRLE", "DirRLO", "DirPDF", "DirNSM", "DirBN",-
222 "DirLRI", "DirRLI", "DirFSI", "DirPDI"-
223};-
224-
225#endif-
226-
227struct QBidiStatus {-
228 QBidiStatus() {-
229 eor = QChar::DirON;-
230 lastStrong = QChar::DirON;-
231 last = QChar:: DirON;-
232 dir = QChar::DirON;-
233 }
never executed: end of block
0
234 QChar::Direction eor;-
235 QChar::Direction lastStrong;-
236 QChar::Direction last;-
237 QChar::Direction dir;-
238};-
239-
240enum { MaxBidiLevel = 61 };-
241-
242struct QBidiControl {-
243 inline QBidiControl(bool rtl)-
244 : cCtx(0), base(rtl ? 1 : 0), level(rtl ? 1 : 0), override(false) {}
never executed: end of block
0
245-
246 inline void embed(bool rtl, bool o = false) {-
247 unsigned int toAdd = 1;-
248 if((level%2 != 0) == rtl ) {
(level%2 != 0) == rtlDescription
TRUEnever evaluated
FALSEnever evaluated
0
249 ++toAdd;-
250 }
never executed: end of block
0
251 if (level + toAdd <= MaxBidiLevel) {
level + toAdd <= MaxBidiLevelDescription
TRUEnever evaluated
FALSEnever evaluated
0
252 ctx[cCtx].level = level;-
253 ctx[cCtx].override = override;-
254 cCtx++;-
255 override = o;-
256 level += toAdd;-
257 }
never executed: end of block
0
258 }
never executed: end of block
0
259 inline bool canPop() const { return cCtx != 0; }
never executed: return cCtx != 0;
0
260 inline void pdf() {-
261 Q_ASSERT(cCtx);-
262 --cCtx;-
263 level = ctx[cCtx].level;-
264 override = ctx[cCtx].override;-
265 }
never executed: end of block
0
266-
267 inline QChar::Direction basicDirection() const {-
268 return (base ? QChar::DirR : QChar:: DirL);
never executed: return (base ? QChar::DirR : QChar:: DirL);
baseDescription
TRUEnever evaluated
FALSEnever evaluated
0
269 }-
270 inline unsigned int baseLevel() const {-
271 return base;
never executed: return base;
0
272 }-
273 inline QChar::Direction direction() const {-
274 return ((level%2) ? QChar::DirR : QChar:: DirL);
never executed: return ((level%2) ? QChar::DirR : QChar:: DirL);
(level%2)Description
TRUEnever evaluated
FALSEnever evaluated
0
275 }-
276-
277 struct {-
278 unsigned int level;-
279 bool override;-
280 } ctx[MaxBidiLevel];-
281 unsigned int cCtx;-
282 const unsigned int base;-
283 unsigned int level;-
284 bool override;-
285};-
286-
287-
288static void appendItems(QScriptAnalysis *analysis, int &start, int &stop, const QBidiControl &control, QChar::Direction dir)-
289{-
290 if (start > stop)
start > stopDescription
TRUEnever evaluated
FALSEnever evaluated
0
291 return;
never executed: return;
0
292-
293 int level = control.level;-
294-
295 if(dir != QChar::DirON && !control.override) {
dir != QChar::DirONDescription
TRUEnever evaluated
FALSEnever evaluated
!control.overrideDescription
TRUEnever evaluated
FALSEnever evaluated
0
296 // add level of run (cases I1 & I2)-
297 if(level % 2) {
level % 2Description
TRUEnever evaluated
FALSEnever evaluated
0
298 if(dir == QChar::DirL || dir == QChar::DirAN || dir == QChar::DirEN)
dir == QChar::DirLDescription
TRUEnever evaluated
FALSEnever evaluated
dir == QChar::DirANDescription
TRUEnever evaluated
FALSEnever evaluated
dir == QChar::DirENDescription
TRUEnever evaluated
FALSEnever evaluated
0
299 level++;
never executed: level++;
0
300 } else {
never executed: end of block
0
301 if(dir == QChar::DirR)
dir == QChar::DirRDescription
TRUEnever evaluated
FALSEnever evaluated
0
302 level++;
never executed: level++;
0
303 else if(dir == QChar::DirAN || dir == QChar::DirEN)
dir == QChar::DirANDescription
TRUEnever evaluated
FALSEnever evaluated
dir == QChar::DirENDescription
TRUEnever evaluated
FALSEnever evaluated
0
304 level += 2;
never executed: level += 2;
0
305 }
never executed: end of block
0
306 }-
307-
308#if (BIDI_DEBUG >= 1)-
309 qDebug("new run: dir=%s from %d, to %d level = %d override=%d", directions[dir], start, stop, level, control.override);-
310#endif-
311 QScriptAnalysis *s = analysis + start;-
312 const QScriptAnalysis *e = analysis + stop;-
313 while (s <= e) {
s <= eDescription
TRUEnever evaluated
FALSEnever evaluated
0
314 s->bidiLevel = level;-
315 ++s;-
316 }
never executed: end of block
0
317 ++stop;-
318 start = stop;-
319}
never executed: end of block
0
320-
321static QChar::Direction skipBoundryNeutrals(QScriptAnalysis *analysis,-
322 const ushort *unicode, int length,-
323 int &sor, int &eor, QBidiControl &control)-
324{-
325 QChar::Direction dir = control.basicDirection();-
326 int level = sor > 0 ? analysis[sor - 1].bidiLevel : control.level;
sor > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
327 while (sor < length) {
sor < lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
328 dir = QChar::direction(unicode[sor]);-
329 // Keep skipping DirBN as if it doesn't exist-
330 if (dir != QChar::DirBN)
dir != QChar::DirBNDescription
TRUEnever evaluated
FALSEnever evaluated
0
331 break;
never executed: break;
0
332 analysis[sor++].bidiLevel = level;-
333 }
never executed: end of block
0
334-
335 eor = sor;-
336 if (eor == length)
eor == lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
337 dir = control.basicDirection();
never executed: dir = control.basicDirection();
0
338-
339 return dir;
never executed: return dir;
0
340}-
341-
342// creates the next QScript items.-
343static bool bidiItemize(QTextEngine *engine, QScriptAnalysis *analysis, QBidiControl &control)-
344{-
345 bool rightToLeft = (control.basicDirection() == 1);-
346 bool hasBidi = rightToLeft;-
347#if BIDI_DEBUG >= 2-
348 qDebug() << "bidiItemize: rightToLeft=" << rightToLeft << engine->layoutData->string;-
349#endif-
350-
351 int sor = 0;-
352 int eor = -1;-
353-
354-
355 int length = engine->layoutData->string.length();-
356-
357 const ushort *unicode = (const ushort *)engine->layoutData->string.unicode();-
358 int current = 0;-
359-
360 QChar::Direction dir = rightToLeft ? QChar::DirR : QChar::DirL;
rightToLeftDescription
TRUEnever evaluated
FALSEnever evaluated
0
361 QBidiStatus status;-
362-
363 QChar::Direction sdir = QChar::direction(*unicode);-
364 if (sdir != QChar::DirL && sdir != QChar::DirR && sdir != QChar::DirEN && sdir != QChar::DirAN)
sdir != QChar::DirLDescription
TRUEnever evaluated
FALSEnever evaluated
sdir != QChar::DirRDescription
TRUEnever evaluated
FALSEnever evaluated
sdir != QChar::DirENDescription
TRUEnever evaluated
FALSEnever evaluated
sdir != QChar::DirANDescription
TRUEnever evaluated
FALSEnever evaluated
0
365 sdir = QChar::DirON;
never executed: sdir = QChar::DirON;
0
366 else-
367 dir = QChar::DirON;
never executed: dir = QChar::DirON;
0
368 status.eor = sdir;-
369 status.lastStrong = rightToLeft ? QChar::DirR : QChar::DirL;
rightToLeftDescription
TRUEnever evaluated
FALSEnever evaluated
0
370 status.last = status.lastStrong;-
371 status.dir = sdir;-
372-
373-
374 while (current <= length) {
current <= lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
375-
376 QChar::Direction dirCurrent;-
377 if (current == (int)length)
current == (int)lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
378 dirCurrent = control.basicDirection();
never executed: dirCurrent = control.basicDirection();
0
379 else-
380 dirCurrent = QChar::direction(unicode[current]);
never executed: dirCurrent = QChar::direction(unicode[current]);
0
381-
382#if (BIDI_DEBUG >= 2)-
383// qDebug() << "pos=" << current << " dir=" << directions[dir]-
384// << " current=" << directions[dirCurrent] << " last=" << directions[status.last]-
385// << " eor=" << eor << '/' << directions[status.eor]-
386// << " sor=" << sor << " lastStrong="-
387// << directions[status.lastStrong]-
388// << " level=" << (int)control.level << " override=" << (bool)control.override;-
389#endif-
390-
391 switch(dirCurrent) {-
392-
393 // embedding and overrides (X1-X9 in the BiDi specs)-
394 case QChar::DirRLE:
never executed: case QChar::DirRLE:
0
395 case QChar::DirRLO:
never executed: case QChar::DirRLO:
0
396 case QChar::DirLRE:
never executed: case QChar::DirLRE:
0
397 case QChar::DirLRO:
never executed: case QChar::DirLRO:
0
398 {-
399 bool rtl = (dirCurrent == QChar::DirRLE || dirCurrent == QChar::DirRLO);
dirCurrent == QChar::DirRLEDescription
TRUEnever evaluated
FALSEnever evaluated
dirCurrent == QChar::DirRLODescription
TRUEnever evaluated
FALSEnever evaluated
0
400 hasBidi |= rtl;-
401 bool override = (dirCurrent == QChar::DirLRO || dirCurrent == QChar::DirRLO);
dirCurrent == QChar::DirLRODescription
TRUEnever evaluated
FALSEnever evaluated
dirCurrent == QChar::DirRLODescription
TRUEnever evaluated
FALSEnever evaluated
0
402-
403 unsigned int level = control.level+1;-
404 if ((level%2 != 0) == rtl) ++level;
never executed: ++level;
(level%2 != 0) == rtlDescription
TRUEnever evaluated
FALSEnever evaluated
0
405 if(level < MaxBidiLevel) {
level < MaxBidiLevelDescription
TRUEnever evaluated
FALSEnever evaluated
0
406 eor = current-1;-
407 appendItems(analysis, sor, eor, control, dir);-
408 eor = current;-
409 control.embed(rtl, override);-
410 QChar::Direction edir = (rtl ? QChar::DirR : QChar::DirL);
rtlDescription
TRUEnever evaluated
FALSEnever evaluated
0
411 dir = status.eor = edir;-
412 status.lastStrong = edir;-
413 }
never executed: end of block
0
414 break;
never executed: break;
0
415 }-
416 case QChar::DirPDF:
never executed: case QChar::DirPDF:
0
417 {-
418 if (control.canPop()) {
control.canPop()Description
TRUEnever evaluated
FALSEnever evaluated
0
419 if (dir != control.direction()) {
dir != control.direction()Description
TRUEnever evaluated
FALSEnever evaluated
0
420 eor = current-1;-
421 appendItems(analysis, sor, eor, control, dir);-
422 dir = control.direction();-
423 }
never executed: end of block
0
424 eor = current;-
425 appendItems(analysis, sor, eor, control, dir);-
426 control.pdf();-
427 dir = QChar::DirON; status.eor = QChar::DirON;-
428 status.last = control.direction();-
429 if (control.override)
control.overrideDescription
TRUEnever evaluated
FALSEnever evaluated
0
430 dir = control.direction();
never executed: dir = control.direction();
0
431 else-
432 dir = QChar::DirON;
never executed: dir = QChar::DirON;
0
433 status.lastStrong = control.direction();-
434 }
never executed: end of block
0
435 break;
never executed: break;
0
436 }-
437-
438 // strong types-
439 case QChar::DirL:
never executed: case QChar::DirL:
0
440 if(dir == QChar::DirON)
dir == QChar::DirONDescription
TRUEnever evaluated
FALSEnever evaluated
0
441 dir = QChar::DirL;
never executed: dir = QChar::DirL;
0
442 switch(status.last)-
443 {-
444 case QChar::DirL:
never executed: case QChar::DirL:
0
445 eor = current; status.eor = QChar::DirL; break;
never executed: break;
0
446 case QChar::DirR:
never executed: case QChar::DirR:
0
447 case QChar::DirAL:
never executed: case QChar::DirAL:
0
448 case QChar::DirEN:
never executed: case QChar::DirEN:
0
449 case QChar::DirAN:
never executed: case QChar::DirAN:
0
450 if (eor >= 0) {
eor >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
451 appendItems(analysis, sor, eor, control, dir);-
452 status.eor = dir = skipBoundryNeutrals(analysis, unicode, length, sor, eor, control);-
453 } else {
never executed: end of block
0
454 eor = current; status.eor = dir;-
455 }
never executed: end of block
0
456 break;
never executed: break;
0
457 case QChar::DirES:
never executed: case QChar::DirES:
0
458 case QChar::DirET:
never executed: case QChar::DirET:
0
459 case QChar::DirCS:
never executed: case QChar::DirCS:
0
460 case QChar::DirBN:
never executed: case QChar::DirBN:
0
461 case QChar::DirB:
never executed: case QChar::DirB:
0
462 case QChar::DirS:
never executed: case QChar::DirS:
0
463 case QChar::DirWS:
never executed: case QChar::DirWS:
0
464 case QChar::DirON:
never executed: case QChar::DirON:
0
465 if(dir != QChar::DirL) {
dir != QChar::DirLDescription
TRUEnever evaluated
FALSEnever evaluated
0
466 //last stuff takes embedding dir-
467 if(control.direction() == QChar::DirR) {
control.direct...== QChar::DirRDescription
TRUEnever evaluated
FALSEnever evaluated
0
468 if(status.eor != QChar::DirR) {
status.eor != QChar::DirRDescription
TRUEnever evaluated
FALSEnever evaluated
0
469 // AN or EN-
470 appendItems(analysis, sor, eor, control, dir);-
471 status.eor = QChar::DirON;-
472 dir = QChar::DirR;-
473 }
never executed: end of block
0
474 eor = current - 1;-
475 appendItems(analysis, sor, eor, control, dir);-
476 status.eor = dir = skipBoundryNeutrals(analysis, unicode, length, sor, eor, control);-
477 } else {
never executed: end of block
0
478 if(status.eor != QChar::DirL) {
status.eor != QChar::DirLDescription
TRUEnever evaluated
FALSEnever evaluated
0
479 appendItems(analysis, sor, eor, control, dir);-
480 status.eor = QChar::DirON;-
481 dir = QChar::DirL;-
482 } else {
never executed: end of block
0
483 eor = current; status.eor = QChar::DirL; break;
never executed: break;
0
484 }-
485 }-
486 } else {-
487 eor = current; status.eor = QChar::DirL;-
488 }
never executed: end of block
0
489 default:
code before this statement never executed: default:
never executed: default:
0
490 break;
never executed: break;
0
491 }-
492 status.lastStrong = QChar::DirL;-
493 break;
never executed: break;
0
494 case QChar::DirAL:
never executed: case QChar::DirAL:
0
495 case QChar::DirR:
never executed: case QChar::DirR:
0
496 hasBidi = true;-
497 if(dir == QChar::DirON) dir = QChar::DirR;
never executed: dir = QChar::DirR;
dir == QChar::DirONDescription
TRUEnever evaluated
FALSEnever evaluated
0
498 switch(status.last)-
499 {-
500 case QChar::DirL:
never executed: case QChar::DirL:
0
501 case QChar::DirEN:
never executed: case QChar::DirEN:
0
502 case QChar::DirAN:
never executed: case QChar::DirAN:
0
503 if (eor >= 0)
eor >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
504 appendItems(analysis, sor, eor, control, dir);
never executed: appendItems(analysis, sor, eor, control, dir);
0
505 // fall through-
506 case QChar::DirR:
code before this statement never executed: case QChar::DirR:
never executed: case QChar::DirR:
0
507 case QChar::DirAL:
never executed: case QChar::DirAL:
0
508 dir = QChar::DirR; eor = current; status.eor = QChar::DirR; break;
never executed: break;
0
509 case QChar::DirES:
never executed: case QChar::DirES:
0
510 case QChar::DirET:
never executed: case QChar::DirET:
0
511 case QChar::DirCS:
never executed: case QChar::DirCS:
0
512 case QChar::DirBN:
never executed: case QChar::DirBN:
0
513 case QChar::DirB:
never executed: case QChar::DirB:
0
514 case QChar::DirS:
never executed: case QChar::DirS:
0
515 case QChar::DirWS:
never executed: case QChar::DirWS:
0
516 case QChar::DirON:
never executed: case QChar::DirON:
0
517 if(status.eor != QChar::DirR && status.eor != QChar::DirAL) {
status.eor != QChar::DirRDescription
TRUEnever evaluated
FALSEnever evaluated
status.eor != QChar::DirALDescription
TRUEnever evaluated
FALSEnever evaluated
0
518 //last stuff takes embedding dir-
519 if(control.direction() == QChar::DirR
control.direct...== QChar::DirRDescription
TRUEnever evaluated
FALSEnever evaluated
0
520 || status.lastStrong == QChar::DirR || status.lastStrong == QChar::DirAL) {
status.lastStr...== QChar::DirRDescription
TRUEnever evaluated
FALSEnever evaluated
status.lastStr...= QChar::DirALDescription
TRUEnever evaluated
FALSEnever evaluated
0
521 appendItems(analysis, sor, eor, control, dir);-
522 dir = QChar::DirR; status.eor = QChar::DirON;-
523 eor = current;-
524 } else {
never executed: end of block
0
525 eor = current - 1;-
526 appendItems(analysis, sor, eor, control, dir);-
527 dir = QChar::DirR; status.eor = QChar::DirON;-
528 }
never executed: end of block
0
529 } else {-
530 eor = current; status.eor = QChar::DirR;-
531 }
never executed: end of block
0
532 default:
code before this statement never executed: default:
never executed: default:
0
533 break;
never executed: break;
0
534 }-
535 status.lastStrong = dirCurrent;-
536 break;
never executed: break;
0
537-
538 // weak types:-
539-
540 case QChar::DirNSM:
never executed: case QChar::DirNSM:
0
541 if (eor == current-1)
eor == current-1Description
TRUEnever evaluated
FALSEnever evaluated
0
542 eor = current;
never executed: eor = current;
0
543 break;
never executed: break;
0
544 case QChar::DirEN:
never executed: case QChar::DirEN:
0
545 // if last strong was AL change EN to AN-
546 if(status.lastStrong != QChar::DirAL) {
status.lastStr...= QChar::DirALDescription
TRUEnever evaluated
FALSEnever evaluated
0
547 if(dir == QChar::DirON) {
dir == QChar::DirONDescription
TRUEnever evaluated
FALSEnever evaluated
0
548 if(status.lastStrong == QChar::DirL)
status.lastStr...== QChar::DirLDescription
TRUEnever evaluated
FALSEnever evaluated
0
549 dir = QChar::DirL;
never executed: dir = QChar::DirL;
0
550 else-
551 dir = QChar::DirEN;
never executed: dir = QChar::DirEN;
0
552 }-
553 switch(status.last)-
554 {-
555 case QChar::DirET:
never executed: case QChar::DirET:
0
556 if (status.lastStrong == QChar::DirR || status.lastStrong == QChar::DirAL) {
status.lastStr...== QChar::DirRDescription
TRUEnever evaluated
FALSEnever evaluated
status.lastStr...= QChar::DirALDescription
TRUEnever evaluated
FALSEnever evaluated
0
557 appendItems(analysis, sor, eor, control, dir);-
558 status.eor = QChar::DirON;-
559 dir = QChar::DirAN;-
560 }
never executed: end of block
0
561 // fall through-
562 case QChar::DirEN:
code before this statement never executed: case QChar::DirEN:
never executed: case QChar::DirEN:
0
563 case QChar::DirL:
never executed: case QChar::DirL:
0
564 eor = current;-
565 status.eor = dirCurrent;-
566 break;
never executed: break;
0
567 case QChar::DirR:
never executed: case QChar::DirR:
0
568 case QChar::DirAL:
never executed: case QChar::DirAL:
0
569 case QChar::DirAN:
never executed: case QChar::DirAN:
0
570 if (eor >= 0)
eor >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
571 appendItems(analysis, sor, eor, control, dir);
never executed: appendItems(analysis, sor, eor, control, dir);
0
572 else-
573 eor = current;
never executed: eor = current;
0
574 status.eor = QChar::DirEN;-
575 dir = QChar::DirAN; break;
never executed: break;
0
576 case QChar::DirES:
never executed: case QChar::DirES:
0
577 case QChar::DirCS:
never executed: case QChar::DirCS:
0
578 if(status.eor == QChar::DirEN || dir == QChar::DirAN) {
status.eor == QChar::DirENDescription
TRUEnever evaluated
FALSEnever evaluated
dir == QChar::DirANDescription
TRUEnever evaluated
FALSEnever evaluated
0
579 eor = current; break;
never executed: break;
0
580 }-
581 case QChar::DirBN:
code before this statement never executed: case QChar::DirBN:
never executed: case QChar::DirBN:
0
582 case QChar::DirB:
never executed: case QChar::DirB:
0
583 case QChar::DirS:
never executed: case QChar::DirS:
0
584 case QChar::DirWS:
never executed: case QChar::DirWS:
0
585 case QChar::DirON:
never executed: case QChar::DirON:
0
586 if(status.eor == QChar::DirR) {
status.eor == QChar::DirRDescription
TRUEnever evaluated
FALSEnever evaluated
0
587 // neutrals go to R-
588 eor = current - 1;-
589 appendItems(analysis, sor, eor, control, dir);-
590 dir = QChar::DirON; status.eor = QChar::DirEN;-
591 dir = QChar::DirAN;-
592 }
never executed: end of block
0
593 else if(status.eor == QChar::DirL ||
status.eor == QChar::DirLDescription
TRUEnever evaluated
FALSEnever evaluated
0
594 (status.eor == QChar::DirEN && status.lastStrong == QChar::DirL)) {
status.eor == QChar::DirENDescription
TRUEnever evaluated
FALSEnever evaluated
status.lastStr...== QChar::DirLDescription
TRUEnever evaluated
FALSEnever evaluated
0
595 eor = current; status.eor = dirCurrent;-
596 } else {
never executed: end of block
0
597 // numbers on both sides, neutrals get right to left direction-
598 if(dir != QChar::DirL) {
dir != QChar::DirLDescription
TRUEnever evaluated
FALSEnever evaluated
0
599 appendItems(analysis, sor, eor, control, dir);-
600 dir = QChar::DirON; status.eor = QChar::DirON;-
601 eor = current - 1;-
602 dir = QChar::DirR;-
603 appendItems(analysis, sor, eor, control, dir);-
604 dir = QChar::DirON; status.eor = QChar::DirON;-
605 dir = QChar::DirAN;-
606 } else {
never executed: end of block
0
607 eor = current; status.eor = dirCurrent;-
608 }
never executed: end of block
0
609 }-
610 default:
code before this statement never executed: default:
never executed: default:
0
611 break;
never executed: break;
0
612 }-
613 break;
never executed: break;
0
614 }-
615 case QChar::DirAN:
code before this statement never executed: case QChar::DirAN:
never executed: case QChar::DirAN:
0
616 hasBidi = true;-
617 dirCurrent = QChar::DirAN;-
618 if(dir == QChar::DirON) dir = QChar::DirAN;
never executed: dir = QChar::DirAN;
dir == QChar::DirONDescription
TRUEnever evaluated
FALSEnever evaluated
0
619 switch(status.last)-
620 {-
621 case QChar::DirL:
never executed: case QChar::DirL:
0
622 case QChar::DirAN:
never executed: case QChar::DirAN:
0
623 eor = current; status.eor = QChar::DirAN; break;
never executed: break;
0
624 case QChar::DirR:
never executed: case QChar::DirR:
0
625 case QChar::DirAL:
never executed: case QChar::DirAL:
0
626 case QChar::DirEN:
never executed: case QChar::DirEN:
0
627 if (eor >= 0){
eor >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
628 appendItems(analysis, sor, eor, control, dir);-
629 } else {
never executed: end of block
0
630 eor = current;-
631 }
never executed: end of block
0
632 dir = QChar::DirAN; status.eor = QChar::DirAN;-
633 break;
never executed: break;
0
634 case QChar::DirCS:
never executed: case QChar::DirCS:
0
635 if(status.eor == QChar::DirAN) {
status.eor == QChar::DirANDescription
TRUEnever evaluated
FALSEnever evaluated
0
636 eor = current; break;
never executed: break;
0
637 }-
638 case QChar::DirES:
code before this statement never executed: case QChar::DirES:
never executed: case QChar::DirES:
0
639 case QChar::DirET:
never executed: case QChar::DirET:
0
640 case QChar::DirBN:
never executed: case QChar::DirBN:
0
641 case QChar::DirB:
never executed: case QChar::DirB:
0
642 case QChar::DirS:
never executed: case QChar::DirS:
0
643 case QChar::DirWS:
never executed: case QChar::DirWS:
0
644 case QChar::DirON:
never executed: case QChar::DirON:
0
645 if(status.eor == QChar::DirR) {
status.eor == QChar::DirRDescription
TRUEnever evaluated
FALSEnever evaluated
0
646 // neutrals go to R-
647 eor = current - 1;-
648 appendItems(analysis, sor, eor, control, dir);-
649 status.eor = QChar::DirAN;-
650 dir = QChar::DirAN;-
651 } else if(status.eor == QChar::DirL ||
never executed: end of block
status.eor == QChar::DirLDescription
TRUEnever evaluated
FALSEnever evaluated
0
652 (status.eor == QChar::DirEN && status.lastStrong == QChar::DirL)) {
status.eor == QChar::DirENDescription
TRUEnever evaluated
FALSEnever evaluated
status.lastStr...== QChar::DirLDescription
TRUEnever evaluated
FALSEnever evaluated
0
653 eor = current; status.eor = dirCurrent;-
654 } else {
never executed: end of block
0
655 // numbers on both sides, neutrals get right to left direction-
656 if(dir != QChar::DirL) {
dir != QChar::DirLDescription
TRUEnever evaluated
FALSEnever evaluated
0
657 appendItems(analysis, sor, eor, control, dir);-
658 status.eor = QChar::DirON;-
659 eor = current - 1;-
660 dir = QChar::DirR;-
661 appendItems(analysis, sor, eor, control, dir);-
662 status.eor = QChar::DirAN;-
663 dir = QChar::DirAN;-
664 } else {
never executed: end of block
0
665 eor = current; status.eor = dirCurrent;-
666 }
never executed: end of block
0
667 }-
668 default:
code before this statement never executed: default:
never executed: default:
0
669 break;
never executed: break;
0
670 }-
671 break;
never executed: break;
0
672 case QChar::DirES:
never executed: case QChar::DirES:
0
673 case QChar::DirCS:
never executed: case QChar::DirCS:
0
674 break;
never executed: break;
0
675 case QChar::DirET:
never executed: case QChar::DirET:
0
676 if(status.last == QChar::DirEN) {
status.last == QChar::DirENDescription
TRUEnever evaluated
FALSEnever evaluated
0
677 dirCurrent = QChar::DirEN;-
678 eor = current; status.eor = dirCurrent;-
679 }
never executed: end of block
0
680 break;
never executed: break;
0
681-
682 // boundary neutrals should be ignored-
683 case QChar::DirBN:
never executed: case QChar::DirBN:
0
684 break;
never executed: break;
0
685 // neutrals-
686 case QChar::DirB:
never executed: case QChar::DirB:
0
687 // ### what do we do with newline and paragraph separators that come to here?-
688 break;
never executed: break;
0
689 case QChar::DirS:
never executed: case QChar::DirS:
0
690 // ### implement rule L1-
691 break;
never executed: break;
0
692 case QChar::DirWS:
never executed: case QChar::DirWS:
0
693 case QChar::DirON:
never executed: case QChar::DirON:
0
694 break;
never executed: break;
0
695 default:
never executed: default:
0
696 break;
never executed: break;
0
697 }-
698-
699 //qDebug() << " after: dir=" << // dir << " current=" << dirCurrent << " last=" << status.last << " eor=" << status.eor << " lastStrong=" << status.lastStrong << " embedding=" << control.direction();-
700-
701 if(current >= (int)length) break;
never executed: break;
current >= (int)lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
702-
703 // set status.last as needed.-
704 switch(dirCurrent) {-
705 case QChar::DirET:
never executed: case QChar::DirET:
0
706 case QChar::DirES:
never executed: case QChar::DirES:
0
707 case QChar::DirCS:
never executed: case QChar::DirCS:
0
708 case QChar::DirS:
never executed: case QChar::DirS:
0
709 case QChar::DirWS:
never executed: case QChar::DirWS:
0
710 case QChar::DirON:
never executed: case QChar::DirON:
0
711 switch(status.last)-
712 {-
713 case QChar::DirL:
never executed: case QChar::DirL:
0
714 case QChar::DirR:
never executed: case QChar::DirR:
0
715 case QChar::DirAL:
never executed: case QChar::DirAL:
0
716 case QChar::DirEN:
never executed: case QChar::DirEN:
0
717 case QChar::DirAN:
never executed: case QChar::DirAN:
0
718 status.last = dirCurrent;-
719 break;
never executed: break;
0
720 default:
never executed: default:
0
721 status.last = QChar::DirON;-
722 }
never executed: end of block
0
723 break;
never executed: break;
0
724 case QChar::DirNSM:
never executed: case QChar::DirNSM:
0
725 case QChar::DirBN:
never executed: case QChar::DirBN:
0
726 // ignore these-
727 break;
never executed: break;
0
728 case QChar::DirLRO:
never executed: case QChar::DirLRO:
0
729 case QChar::DirLRE:
never executed: case QChar::DirLRE:
0
730 status.last = QChar::DirL;-
731 break;
never executed: break;
0
732 case QChar::DirRLO:
never executed: case QChar::DirRLO:
0
733 case QChar::DirRLE:
never executed: case QChar::DirRLE:
0
734 status.last = QChar::DirR;-
735 break;
never executed: break;
0
736 case QChar::DirEN:
never executed: case QChar::DirEN:
0
737 if (status.last == QChar::DirL) {
status.last == QChar::DirLDescription
TRUEnever evaluated
FALSEnever evaluated
0
738 status.last = QChar::DirL;-
739 break;
never executed: break;
0
740 }-
741 // fall through-
742 default:
code before this statement never executed: default:
never executed: default:
0
743 status.last = dirCurrent;-
744 }
never executed: end of block
0
745-
746 ++current;-
747 }
never executed: end of block
0
748-
749#if (BIDI_DEBUG >= 1)-
750 qDebug() << "reached end of line current=" << current << ", eor=" << eor;-
751#endif-
752 eor = current - 1; // remove dummy char-
753-
754 if (sor <= eor)
sor <= eorDescription
TRUEnever evaluated
FALSEnever evaluated
0
755 appendItems(analysis, sor, eor, control, dir);
never executed: appendItems(analysis, sor, eor, control, dir);
0
756-
757 return hasBidi;
never executed: return hasBidi;
0
758}-
759-
760void QTextEngine::bidiReorder(int numItems, const quint8 *levels, int *visualOrder)-
761{-
762-
763 // first find highest and lowest levels-
764 quint8 levelLow = 128;-
765 quint8 levelHigh = 0;-
766 int i = 0;-
767 while (i < numItems) {
i < numItemsDescription
TRUEnever evaluated
FALSEnever evaluated
0
768 //printf("level = %d\n", r->level);-
769 if (levels[i] > levelHigh)
levels[i] > levelHighDescription
TRUEnever evaluated
FALSEnever evaluated
0
770 levelHigh = levels[i];
never executed: levelHigh = levels[i];
0
771 if (levels[i] < levelLow)
levels[i] < levelLowDescription
TRUEnever evaluated
FALSEnever evaluated
0
772 levelLow = levels[i];
never executed: levelLow = levels[i];
0
773 i++;-
774 }
never executed: end of block
0
775-
776 // implements reordering of the line (L2 according to BiDi spec):-
777 // L2. From the highest level found in the text to the lowest odd level on each line,-
778 // reverse any contiguous sequence of characters that are at that level or higher.-
779-
780 // reversing is only done up to the lowest odd level-
781 if(!(levelLow%2)) levelLow++;
never executed: levelLow++;
!(levelLow%2)Description
TRUEnever evaluated
FALSEnever evaluated
0
782-
783#if (BIDI_DEBUG >= 1)-
784// qDebug() << "reorderLine: lineLow = " << (uint)levelLow << ", lineHigh = " << (uint)levelHigh;-
785#endif-
786-
787 int count = numItems - 1;-
788 for (i = 0; i < numItems; i++)
i < numItemsDescription
TRUEnever evaluated
FALSEnever evaluated
0
789 visualOrder[i] = i;
never executed: visualOrder[i] = i;
0
790-
791 while(levelHigh >= levelLow) {
levelHigh >= levelLowDescription
TRUEnever evaluated
FALSEnever evaluated
0
792 int i = 0;-
793 while (i < count) {
i < countDescription
TRUEnever evaluated
FALSEnever evaluated
0
794 while(i < count && levels[i] < levelHigh) i++;
never executed: i++;
i < countDescription
TRUEnever evaluated
FALSEnever evaluated
levels[i] < levelHighDescription
TRUEnever evaluated
FALSEnever evaluated
0
795 int start = i;-
796 while(i <= count && levels[i] >= levelHigh) i++;
never executed: i++;
i <= countDescription
TRUEnever evaluated
FALSEnever evaluated
levels[i] >= levelHighDescription
TRUEnever evaluated
FALSEnever evaluated
0
797 int end = i-1;-
798-
799 if(start != end) {
start != endDescription
TRUEnever evaluated
FALSEnever evaluated
0
800 //qDebug() << "reversing from " << start << " to " << end;-
801 for(int j = 0; j < (end-start+1)/2; j++) {
j < (end-start+1)/2Description
TRUEnever evaluated
FALSEnever evaluated
0
802 int tmp = visualOrder[start+j];-
803 visualOrder[start+j] = visualOrder[end-j];-
804 visualOrder[end-j] = tmp;-
805 }
never executed: end of block
0
806 }
never executed: end of block
0
807 i++;-
808 }
never executed: end of block
0
809 levelHigh--;-
810 }
never executed: end of block
0
811-
812#if (BIDI_DEBUG >= 1)-
813// qDebug() << "visual order is:";-
814// for (i = 0; i < numItems; i++)-
815// qDebug() << visualOrder[i];-
816#endif-
817}
never executed: end of block
0
818-
819-
820enum JustificationClass {-
821 Justification_Prohibited = 0, // Justification can not be applied after this glyph-
822 Justification_Arabic_Space = 1, // This glyph represents a space inside arabic text-
823 Justification_Character = 2, // Inter-character justification point follows this glyph-
824 Justification_Space = 4, // This glyph represents a blank outside an Arabic run-
825 Justification_Arabic_Normal = 7, // Normal Middle-Of-Word glyph that connects to the right (begin)-
826 Justification_Arabic_Waw = 8, // Next character is final form of Waw/Ain/Qaf/Feh-
827 Justification_Arabic_BaRa = 9, // Next two characters are Ba + Ra/Ya/AlefMaksura-
828 Justification_Arabic_Alef = 10, // Next character is final form of Alef/Tah/Lam/Kaf/Gaf-
829 Justification_Arabic_HahDal = 11, // Next character is final form of Hah/Dal/Teh Marbuta-
830 Justification_Arabic_Seen = 12, // Initial or medial form of Seen/Sad-
831 Justification_Arabic_Kashida = 13 // User-inserted Kashida(U+0640)-
832};-
833-
834#ifdef QT_ENABLE_HARFBUZZ_NG-
835-
836/*-
837 Adds an inter character justification opportunity after the number or letter-
838 character and a space justification opportunity after the space character.-
839*/-
840static inline void qt_getDefaultJustificationOpportunities(const ushort *string, int length, QGlyphLayout g, ushort *log_clusters, int spaceAs)-
841{-
842 int str_pos = 0;-
843 while (str_pos < length) {
str_pos < lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
844 int glyph_pos = log_clusters[str_pos];-
845-
846 Q_ASSERT(glyph_pos < g.numGlyphs && g.attributes[glyph_pos].clusterStart);-
847-
848 uint ucs4 = string[str_pos];-
849 if (QChar::isHighSurrogate(ucs4) && str_pos + 1 < length) {
QChar::isHighSurrogate(ucs4)Description
TRUEnever evaluated
FALSEnever evaluated
str_pos + 1 < lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
850 ushort low = string[str_pos + 1];-
851 if (QChar::isLowSurrogate(low)) {
QChar::isLowSurrogate(low)Description
TRUEnever evaluated
FALSEnever evaluated
0
852 ++str_pos;-
853 ucs4 = QChar::surrogateToUcs4(ucs4, low);-
854 }
never executed: end of block
0
855 }
never executed: end of block
0
856-
857 // skip whole cluster-
858 do {-
859 ++str_pos;-
860 } while (str_pos < length && log_clusters[str_pos] == glyph_pos);
never executed: end of block
str_pos < lengthDescription
TRUEnever evaluated
FALSEnever evaluated
log_clusters[s...] == glyph_posDescription
TRUEnever evaluated
FALSEnever evaluated
0
861 do {-
862 ++glyph_pos;-
863 } while (glyph_pos < g.numGlyphs && !g.attributes[glyph_pos].clusterStart);
never executed: end of block
glyph_pos < g.numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
!g.attributes[...].clusterStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
864 --glyph_pos;-
865-
866 // justification opportunity at the end of cluster-
867 if (Q_LIKELY(QChar::isLetterOrNumber(ucs4)))
__builtin_expe...(ucs4)), true)Description
TRUEnever evaluated
FALSEnever evaluated
0
868 g.attributes[glyph_pos].justification = Justification_Character;
never executed: g.attributes[glyph_pos].justification = Justification_Character;
0
869 else if (Q_LIKELY(QChar::isSpace(ucs4)))
__builtin_expe...(ucs4)), true)Description
TRUEnever evaluated
FALSEnever evaluated
0
870 g.attributes[glyph_pos].justification = spaceAs;
never executed: g.attributes[glyph_pos].justification = spaceAs;
0
871 }
never executed: end of block
0
872}
never executed: end of block
0
873-
874static inline void qt_getJustificationOpportunities(const ushort *string, int length, const QScriptItem &si, QGlyphLayout g, ushort *log_clusters)-
875{-
876 Q_ASSERT(length > 0 && g.numGlyphs > 0);-
877-
878 for (int glyph_pos = 0; glyph_pos < g.numGlyphs; ++glyph_pos)
glyph_pos < g.numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
879 g.attributes[glyph_pos].justification = Justification_Prohibited;
never executed: g.attributes[glyph_pos].justification = Justification_Prohibited;
0
880-
881 int spaceAs;-
882-
883 switch (si.analysis.script) {-
884 case QChar::Script_Arabic:
never executed: case QChar::Script_Arabic:
0
885 case QChar::Script_Syriac:
never executed: case QChar::Script_Syriac:
0
886 case QChar::Script_Nko:
never executed: case QChar::Script_Nko:
0
887 case QChar::Script_Mandaic:
never executed: case QChar::Script_Mandaic:
0
888 case QChar::Script_Mongolian:
never executed: case QChar::Script_Mongolian:
0
889 case QChar::Script_PhagsPa:
never executed: case QChar::Script_PhagsPa:
0
890 case QChar::Script_Manichaean:
never executed: case QChar::Script_Manichaean:
0
891 case QChar::Script_PsalterPahlavi:
never executed: case QChar::Script_PsalterPahlavi:
0
892 // same as default but inter character justification takes precedence-
893 spaceAs = Justification_Arabic_Space;-
894 break;
never executed: break;
0
895-
896 case QChar::Script_Tibetan:
never executed: case QChar::Script_Tibetan:
0
897 case QChar::Script_Hiragana:
never executed: case QChar::Script_Hiragana:
0
898 case QChar::Script_Katakana:
never executed: case QChar::Script_Katakana:
0
899 case QChar::Script_Bopomofo:
never executed: case QChar::Script_Bopomofo:
0
900 case QChar::Script_Han:
never executed: case QChar::Script_Han:
0
901 // same as default but inter character justification is the only option-
902 spaceAs = Justification_Character;-
903 break;
never executed: break;
0
904-
905 default:
never executed: default:
0
906 spaceAs = Justification_Space;-
907 break;
never executed: break;
0
908 }-
909-
910 qt_getDefaultJustificationOpportunities(string, length, g, log_clusters, spaceAs);-
911}
never executed: end of block
0
912-
913#endif // QT_ENABLE_HARFBUZZ_NG-
914-
915-
916// shape all the items that intersect with the line, taking tab widths into account to find out what text actually fits in the line.-
917void QTextEngine::shapeLine(const QScriptLine &line)-
918{-
919 QFixed x;-
920 bool first = true;-
921 int item = findItem(line.from);-
922 if (item == -1)
item == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
923 return;
never executed: return;
0
924-
925 const int end = findItem(line.from + line.length + line.trailingSpaces - 1, item);-
926 for ( ; item <= end; ++item) {
item <= endDescription
TRUEnever evaluated
FALSEnever evaluated
0
927 QScriptItem &si = layoutData->items[item];-
928 if (si.analysis.flags == QScriptAnalysis::Tab) {
si.analysis.fl...tAnalysis::TabDescription
TRUEnever evaluated
FALSEnever evaluated
0
929 ensureSpace(1);-
930 si.width = calculateTabWidth(item, x);-
931 } else {
never executed: end of block
0
932 shape(item);-
933 }
never executed: end of block
0
934 if (first && si.position != line.from) { // that means our x position has to be offset
firstDescription
TRUEnever evaluated
FALSEnever evaluated
si.position != line.fromDescription
TRUEnever evaluated
FALSEnever evaluated
0
935 QGlyphLayout glyphs = shapedGlyphs(&si);-
936 Q_ASSERT(line.from > si.position);-
937 for (int i = line.from - si.position - 1; i >= 0; i--) {
i >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
938 x -= glyphs.effectiveAdvance(i);-
939 }
never executed: end of block
0
940 }
never executed: end of block
0
941 first = false;-
942-
943 x += si.width;-
944 }
never executed: end of block
0
945}
never executed: end of block
0
946-
947#ifdef QT_ENABLE_HARFBUZZ_NG-
948extern bool qt_useHarfbuzzNG(); // defined in qfontengine.cpp-
949#endif-
950-
951void QTextEngine::shapeText(int item) const-
952{-
953 Q_ASSERT(item < layoutData->items.size());-
954 QScriptItem &si = layoutData->items[item];-
955-
956 if (si.num_glyphs)
si.num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
957 return;
never executed: return;
0
958-
959 si.width = 0;-
960 si.glyph_data_offset = layoutData->used;-
961-
962 const ushort *string = reinterpret_cast<const ushort *>(layoutData->string.constData()) + si.position;-
963 const int itemLength = length(item);-
964-
965 QString casedString;-
966 if (si.analysis.flags && si.analysis.flags <= QScriptAnalysis::SmallCaps) {
si.analysis.flagsDescription
TRUEnever evaluated
FALSEnever evaluated
si.analysis.fl...sis::SmallCapsDescription
TRUEnever evaluated
FALSEnever evaluated
0
967 casedString.resize(itemLength);-
968 ushort *uc = reinterpret_cast<ushort *>(casedString.data());-
969 for (int i = 0; i < itemLength; ++i) {
i < itemLengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
970 uint ucs4 = string[i];-
971 if (QChar::isHighSurrogate(ucs4) && i + 1 < itemLength) {
QChar::isHighSurrogate(ucs4)Description
TRUEnever evaluated
FALSEnever evaluated
i + 1 < itemLengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
972 uint low = string[i + 1];-
973 if (QChar::isLowSurrogate(low)) {
QChar::isLowSurrogate(low)Description
TRUEnever evaluated
FALSEnever evaluated
0
974 ++i;-
975 ucs4 = QChar::surrogateToUcs4(ucs4, low);-
976 ucs4 = si.analysis.flags == QScriptAnalysis::Lowercase ? QChar::toLower(ucs4)
si.analysis.fl...sis::LowercaseDescription
TRUEnever evaluated
FALSEnever evaluated
0
977 : QChar::toUpper(ucs4);-
978 // high part never changes in simple casing-
979 uc[i] = QChar::lowSurrogate(ucs4);-
980 }
never executed: end of block
0
981 } else {
never executed: end of block
0
982 uc[i] = si.analysis.flags == QScriptAnalysis::Lowercase ? QChar::toLower(ucs4)
si.analysis.fl...sis::LowercaseDescription
TRUEnever evaluated
FALSEnever evaluated
0
983 : QChar::toUpper(ucs4);-
984 }
never executed: end of block
0
985 }-
986 string = reinterpret_cast<const ushort *>(casedString.constData());-
987 }
never executed: end of block
0
988-
989 if (Q_UNLIKELY(!ensureSpace(itemLength))) {
__builtin_expe...ngth)), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
990 Q_UNREACHABLE(); // ### report OOM error somehow-
991 return;
never executed: return;
0
992 }-
993-
994 QFontEngine *fontEngine = this->fontEngine(si, &si.ascent, &si.descent, &si.leading);-
995-
996 // split up the item into parts that come from different font engines-
997 // k * 3 entries, array[k] == index in string, array[k + 1] == index in glyphs, array[k + 2] == engine index-
998 QVector<uint> itemBoundaries;-
999 itemBoundaries.reserve(24);-
1000 if (fontEngine->type() == QFontEngine::Multi) {
fontEngine->ty...tEngine::MultiDescription
TRUEnever evaluated
FALSEnever evaluated
0
1001 // ask the font engine to find out which glyphs (as an index in the specific font)-
1002 // to use for the text in one item.-
1003 QGlyphLayout initialGlyphs = availableGlyphs(&si);-
1004-
1005 int nGlyphs = initialGlyphs.numGlyphs;-
1006 QFontEngine::ShaperFlags shaperFlags(QFontEngine::GlyphIndicesOnly);-
1007 if (!fontEngine->stringToCMap(reinterpret_cast<const QChar *>(string), itemLength, &initialGlyphs, &nGlyphs, shaperFlags))
!fontEngine->s..., shaperFlags)Description
TRUEnever evaluated
FALSEnever evaluated
0
1008 Q_UNREACHABLE();
never executed: end of block
0
1009-
1010 uint lastEngine = ~0u;-
1011 for (int i = 0, glyph_pos = 0; i < itemLength; ++i, ++glyph_pos) {
i < itemLengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1012 const uint engineIdx = initialGlyphs.glyphs[glyph_pos] >> 24;-
1013 if (lastEngine != engineIdx) {
lastEngine != engineIdxDescription
TRUEnever evaluated
FALSEnever evaluated
0
1014 itemBoundaries.append(i);-
1015 itemBoundaries.append(glyph_pos);-
1016 itemBoundaries.append(engineIdx);-
1017-
1018 if (engineIdx != 0) {
engineIdx != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1019 QFontEngine *actualFontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx);-
1020 si.ascent = qMax(actualFontEngine->ascent(), si.ascent);-
1021 si.descent = qMax(actualFontEngine->descent(), si.descent);-
1022 si.leading = qMax(actualFontEngine->leading(), si.leading);-
1023 }
never executed: end of block
0
1024-
1025 lastEngine = engineIdx;-
1026 }
never executed: end of block
0
1027-
1028 if (QChar::isHighSurrogate(string[i]) && i + 1 < itemLength && QChar::isLowSurrogate(string[i + 1]))
QChar::isHighS...ate(string[i])Description
TRUEnever evaluated
FALSEnever evaluated
i + 1 < itemLengthDescription
TRUEnever evaluated
FALSEnever evaluated
QChar::isLowSu...string[i + 1])Description
TRUEnever evaluated
FALSEnever evaluated
0
1029 ++i;
never executed: ++i;
0
1030 }
never executed: end of block
0
1031 } else {
never executed: end of block
0
1032 itemBoundaries.append(0);-
1033 itemBoundaries.append(0);-
1034 itemBoundaries.append(0);-
1035 }
never executed: end of block
0
1036-
1037 bool kerningEnabled;-
1038 bool letterSpacingIsAbsolute;-
1039 QFixed letterSpacing, wordSpacing;-
1040#ifndef QT_NO_RAWFONT-
1041 if (useRawFont) {
useRawFontDescription
TRUEnever evaluated
FALSEnever evaluated
0
1042 QTextCharFormat f = format(&si);-
1043 kerningEnabled = f.fontKerning();-
1044 wordSpacing = QFixed::fromReal(f.fontWordSpacing());-
1045 letterSpacing = QFixed::fromReal(f.fontLetterSpacing());-
1046 letterSpacingIsAbsolute = true;-
1047 } else
never executed: end of block
0
1048#endif-
1049 {-
1050 QFont font = this->font(si);-
1051 kerningEnabled = font.d->kerning;-
1052 letterSpacingIsAbsolute = font.d->letterSpacingIsAbsolute;-
1053 letterSpacing = font.d->letterSpacing;-
1054 wordSpacing = font.d->wordSpacing;-
1055-
1056 if (letterSpacingIsAbsolute && letterSpacing.value())
letterSpacingIsAbsoluteDescription
TRUEnever evaluated
FALSEnever evaluated
letterSpacing.value()Description
TRUEnever evaluated
FALSEnever evaluated
0
1057 letterSpacing *= font.d->dpi / qt_defaultDpiY();
never executed: letterSpacing *= font.d->dpi / qt_defaultDpiY();
0
1058 }
never executed: end of block
0
1059-
1060#ifdef QT_ENABLE_HARFBUZZ_NG-
1061 if (Q_LIKELY(qt_useHarfbuzzNG()))
__builtin_expe...zzNG()), true)Description
TRUEnever evaluated
FALSEnever evaluated
0
1062 si.num_glyphs = shapeTextWithHarfbuzzNG(si, string, itemLength, fontEngine, itemBoundaries, kerningEnabled, letterSpacing != 0);
never executed: si.num_glyphs = shapeTextWithHarfbuzzNG(si, string, itemLength, fontEngine, itemBoundaries, kerningEnabled, letterSpacing != 0);
0
1063 else-
1064#endif-
1065 si.num_glyphs = shapeTextWithHarfbuzz(si, string, itemLength, fontEngine, itemBoundaries, kerningEnabled);
never executed: si.num_glyphs = shapeTextWithHarfbuzz(si, string, itemLength, fontEngine, itemBoundaries, kerningEnabled);
0
1066 if (Q_UNLIKELY(si.num_glyphs == 0)) {
__builtin_expe... == 0), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
1067 Q_UNREACHABLE(); // ### report shaping errors somehow-
1068 return;
never executed: return;
0
1069 }-
1070-
1071-
1072 layoutData->used += si.num_glyphs;-
1073-
1074 QGlyphLayout glyphs = shapedGlyphs(&si);-
1075-
1076#ifdef QT_ENABLE_HARFBUZZ_NG-
1077 if (Q_LIKELY(qt_useHarfbuzzNG()))
__builtin_expe...zzNG()), true)Description
TRUEnever evaluated
FALSEnever evaluated
0
1078 qt_getJustificationOpportunities(string, itemLength, si, glyphs, logClusters(&si));
never executed: qt_getJustificationOpportunities(string, itemLength, si, glyphs, logClusters(&si));
0
1079#endif-
1080-
1081 if (letterSpacing != 0) {
letterSpacing != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1082 for (int i = 1; i < si.num_glyphs; ++i) {
i < si.num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1083 if (glyphs.attributes[i].clusterStart) {
glyphs.attribu...].clusterStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
1084 if (letterSpacingIsAbsolute)
letterSpacingIsAbsoluteDescription
TRUEnever evaluated
FALSEnever evaluated
0
1085 glyphs.advances[i - 1] += letterSpacing;
never executed: glyphs.advances[i - 1] += letterSpacing;
0
1086 else {-
1087 QFixed &advance = glyphs.advances[i - 1];-
1088 advance += (letterSpacing - 100) * advance / 100;-
1089 }
never executed: end of block
0
1090 }-
1091 }
never executed: end of block
0
1092 if (letterSpacingIsAbsolute)
letterSpacingIsAbsoluteDescription
TRUEnever evaluated
FALSEnever evaluated
0
1093 glyphs.advances[si.num_glyphs - 1] += letterSpacing;
never executed: glyphs.advances[si.num_glyphs - 1] += letterSpacing;
0
1094 else {-
1095 QFixed &advance = glyphs.advances[si.num_glyphs - 1];-
1096 advance += (letterSpacing - 100) * advance / 100;-
1097 }
never executed: end of block
0
1098 }-
1099 if (wordSpacing != 0) {
wordSpacing != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1100 for (int i = 0; i < si.num_glyphs; ++i) {
i < si.num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1101 if (glyphs.attributes[i].justification == Justification_Space
glyphs.attribu...fication_SpaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
1102 || glyphs.attributes[i].justification == Justification_Arabic_Space) {
glyphs.attribu...n_Arabic_SpaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
1103 // word spacing only gets added once to a consecutive run of spaces (see CSS spec)-
1104 if (i + 1 == si.num_glyphs
i + 1 == si.num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1105 ||(glyphs.attributes[i+1].justification != Justification_Space
glyphs.attribu...fication_SpaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
1106 && glyphs.attributes[i+1].justification != Justification_Arabic_Space))
glyphs.attribu...n_Arabic_SpaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
1107 glyphs.advances[i] += wordSpacing;
never executed: glyphs.advances[i] += wordSpacing;
0
1108 }
never executed: end of block
0
1109 }
never executed: end of block
0
1110 }
never executed: end of block
0
1111-
1112 for (int i = 0; i < si.num_glyphs; ++i)
i < si.num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1113 si.width += glyphs.advances[i] * !glyphs.attributes[i].dontPrint;
never executed: si.width += glyphs.advances[i] * !glyphs.attributes[i].dontPrint;
0
1114}
never executed: end of block
0
1115-
1116#ifdef QT_ENABLE_HARFBUZZ_NG-
1117-
1118QT_BEGIN_INCLUDE_NAMESPACE-
1119-
1120#include "qharfbuzzng_p.h"-
1121-
1122QT_END_INCLUDE_NAMESPACE-
1123-
1124int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,-
1125 const ushort *string,-
1126 int itemLength,-
1127 QFontEngine *fontEngine,-
1128 const QVector<uint> &itemBoundaries,-
1129 bool kerningEnabled,-
1130 bool hasLetterSpacing) const-
1131{-
1132 uint glyphs_shaped = 0;-
1133-
1134 hb_buffer_t *buffer = hb_buffer_create();-
1135 hb_buffer_set_unicode_funcs(buffer, hb_qt_get_unicode_funcs());-
1136 hb_buffer_pre_allocate(buffer, itemLength);-
1137 if (Q_UNLIKELY(!hb_buffer_allocation_successful(buffer))) {
__builtin_expe...ffer)), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
1138 hb_buffer_destroy(buffer);-
1139 return 0;
never executed: return 0;
0
1140 }-
1141-
1142 hb_segment_properties_t props = HB_SEGMENT_PROPERTIES_DEFAULT;-
1143 props.direction = si.analysis.bidiLevel % 2 ? HB_DIRECTION_RTL : HB_DIRECTION_LTR;
si.analysis.bidiLevel % 2Description
TRUEnever evaluated
FALSEnever evaluated
0
1144 QChar::Script script = QChar::Script(si.analysis.script);-
1145 props.script = hb_qt_script_to_script(script);-
1146 // ### props.language = hb_language_get_default_for_script(props.script);-
1147-
1148 for (int k = 0; k < itemBoundaries.size(); k += 3) {
k < itemBoundaries.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1149 const uint item_pos = itemBoundaries[k];-
1150 const uint item_length = (k + 4 < itemBoundaries.size() ? itemBoundaries[k + 3] : itemLength) - item_pos;
k + 4 < itemBoundaries.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1151 const uint engineIdx = itemBoundaries[k + 2];-
1152-
1153 QFontEngine *actualFontEngine = fontEngine->type() != QFontEngine::Multi ? fontEngine
fontEngine->ty...tEngine::MultiDescription
TRUEnever evaluated
FALSEnever evaluated
0
1154 : static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx);-
1155-
1156-
1157 // prepare buffer-
1158 hb_buffer_clear_contents(buffer);-
1159 hb_buffer_add_utf16(buffer, reinterpret_cast<const uint16_t *>(string) + item_pos, item_length, 0, item_length);-
1160-
1161 hb_buffer_set_segment_properties(buffer, &props);-
1162 hb_buffer_guess_segment_properties(buffer);-
1163-
1164 uint buffer_flags = HB_BUFFER_FLAG_DEFAULT;-
1165 // Symbol encoding used to encode various crap in the 32..255 character code range,-
1166 // and thus might override U+00AD [SHY]; avoid hiding default ignorables-
1167 if (Q_UNLIKELY(actualFontEngine->symbol))
__builtin_expe...ymbol), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
1168 buffer_flags |= HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES;
never executed: buffer_flags |= HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES;
0
1169 hb_buffer_set_flags(buffer, hb_buffer_flags_t(buffer_flags));-
1170-
1171-
1172 // shape-
1173 {-
1174 hb_font_t *hb_font = hb_qt_font_get_for_engine(actualFontEngine);-
1175 Q_ASSERT(hb_font);-
1176 hb_qt_font_set_use_design_metrics(hb_font, option.useDesignMetrics() ? uint(QFontEngine::DesignMetrics) : 0); // ###-
1177-
1178 // Ligatures are incompatible with custom letter spacing, so when a letter spacing is set,-
1179 // we disable them for writing systems where they are purely cosmetic.-
1180 bool scriptRequiresOpenType = ((script >= QChar::Script_Syriac && script <= QChar::Script_Sinhala)
script >= QChar::Script_SyriacDescription
TRUEnever evaluated
FALSEnever evaluated
script <= QCha...Script_SinhalaDescription
TRUEnever evaluated
FALSEnever evaluated
0
1181 || script == QChar::Script_Khmer || script == QChar::Script_Nko);
script == QChar::Script_KhmerDescription
TRUEnever evaluated
FALSEnever evaluated
script == QChar::Script_NkoDescription
TRUEnever evaluated
FALSEnever evaluated
0
1182-
1183 bool dontLigate = hasLetterSpacing && !scriptRequiresOpenType;
hasLetterSpacingDescription
TRUEnever evaluated
FALSEnever evaluated
!scriptRequiresOpenTypeDescription
TRUEnever evaluated
FALSEnever evaluated
0
1184 const hb_feature_t features[5] = {-
1185 { HB_TAG('k','e','r','n'), !!kerningEnabled, 0, uint(-1) },-
1186 { HB_TAG('l','i','g','a'), !dontLigate, 0, uint(-1) },-
1187 { HB_TAG('c','l','i','g'), !dontLigate, 0, uint(-1) },-
1188 { HB_TAG('d','l','i','g'), !dontLigate, 0, uint(-1) },-
1189 { HB_TAG('h','l','i','g'), !dontLigate, 0, uint(-1) } };-
1190 const int num_features = dontLigate ? 5 : 1;
dontLigateDescription
TRUEnever evaluated
FALSEnever evaluated
0
1191-
1192 const char *const *shaper_list = Q_NULLPTR;-
1193#if defined(Q_OS_DARWIN)-
1194 // What's behind QFontEngine::FaceData::user_data isn't compatible between different font engines-
1195 // - specifically functions in hb-coretext.cc would run into undefined behavior with data-
1196 // from non-CoreText engine. The other shapers works with that engine just fine.-
1197 if (actualFontEngine->type() != QFontEngine::Mac) {-
1198 static const char *s_shaper_list_without_coretext[] = {-
1199 "graphite2",-
1200 "ot",-
1201 "fallback",-
1202 Q_NULLPTR-
1203 };-
1204 shaper_list = s_shaper_list_without_coretext;-
1205 }-
1206#endif-
1207-
1208 bool shapedOk = hb_shape_full(hb_font, buffer, features, num_features, shaper_list);-
1209 if (Q_UNLIKELY(!shapedOk)) {
__builtin_expe...pedOk), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
1210 hb_buffer_destroy(buffer);-
1211 return 0;
never executed: return 0;
0
1212 }-
1213-
1214 if (Q_UNLIKELY(HB_DIRECTION_IS_BACKWARD(props.direction)))
__builtin_expe...== 5)), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
1215 hb_buffer_reverse(buffer);
never executed: hb_buffer_reverse(buffer);
0
1216 }-
1217-
1218 const uint num_glyphs = hb_buffer_get_length(buffer);-
1219 // ensure we have enough space for shaped glyphs and metrics-
1220 if (Q_UNLIKELY(num_glyphs == 0 || !ensureSpace(glyphs_shaped + num_glyphs))) {
__builtin_expe...yphs)), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
1221 hb_buffer_destroy(buffer);-
1222 return 0;
never executed: return 0;
0
1223 }-
1224-
1225 // fetch the shaped glyphs and metrics-
1226 QGlyphLayout g = availableGlyphs(&si).mid(glyphs_shaped, num_glyphs);-
1227 ushort *log_clusters = logClusters(&si) + item_pos;-
1228-
1229 hb_glyph_info_t *infos = hb_buffer_get_glyph_infos(buffer, 0);-
1230 hb_glyph_position_t *positions = hb_buffer_get_glyph_positions(buffer, 0);-
1231 uint str_pos = 0;-
1232 uint last_cluster = ~0u;-
1233 uint last_glyph_pos = glyphs_shaped;-
1234 for (uint i = 0; i < num_glyphs; ++i, ++infos, ++positions) {
i < num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1235 g.glyphs[i] = infos->codepoint;-
1236-
1237 g.advances[i] = QFixed::fromFixed(positions->x_advance);-
1238 g.offsets[i].x = QFixed::fromFixed(positions->x_offset);-
1239 g.offsets[i].y = QFixed::fromFixed(positions->y_offset);-
1240-
1241 uint cluster = infos->cluster;-
1242 if (Q_LIKELY(last_cluster != cluster)) {
__builtin_expe...luster), true)Description
TRUEnever evaluated
FALSEnever evaluated
0
1243 g.attributes[i].clusterStart = true;-
1244-
1245 // fix up clusters so that the cluster indices will be monotonic-
1246 // and thus we never return out-of-order indices-
1247 while (last_cluster++ < cluster && str_pos < item_length)
last_cluster++ < clusterDescription
TRUEnever evaluated
FALSEnever evaluated
str_pos < item_lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1248 log_clusters[str_pos++] = last_glyph_pos;
never executed: log_clusters[str_pos++] = last_glyph_pos;
0
1249 last_glyph_pos = i + glyphs_shaped;-
1250 last_cluster = cluster;-
1251-
1252 // hide characters that should normally be invisible-
1253 switch (string[item_pos + str_pos]) {-
1254 case QChar::LineFeed:
never executed: case QChar::LineFeed:
0
1255 case 0x000c: // FormFeed
never executed: case 0x000c:
0
1256 case QChar::CarriageReturn:
never executed: case QChar::CarriageReturn:
0
1257 case QChar::LineSeparator:
never executed: case QChar::LineSeparator:
0
1258 case QChar::ParagraphSeparator:
never executed: case QChar::ParagraphSeparator:
0
1259 g.attributes[i].dontPrint = true;-
1260 break;
never executed: break;
0
1261 case QChar::SoftHyphen:
never executed: case QChar::SoftHyphen:
0
1262 if (!actualFontEngine->symbol) {
!actualFontEngine->symbolDescription
TRUEnever evaluated
FALSEnever evaluated
0
1263 // U+00AD [SOFT HYPHEN] is a default ignorable codepoint,-
1264 // so we replace its glyph and metrics with ones for-
1265 // U+002D [HYPHEN-MINUS] and make it visible if it appears at line-break-
1266 g.glyphs[i] = actualFontEngine->glyphIndex('-');-
1267 if (Q_LIKELY(g.glyphs[i] != 0)) {
__builtin_expe...] != 0), true)Description
TRUEnever evaluated
FALSEnever evaluated
0
1268 QGlyphLayout tmp = g.mid(i, 1);-
1269 actualFontEngine->recalcAdvances(&tmp, 0);-
1270 }
never executed: end of block
0
1271 g.attributes[i].dontPrint = true;-
1272 }
never executed: end of block
0
1273 break;
never executed: break;
0
1274 default:
never executed: default:
0
1275 break;
never executed: break;
0
1276 }-
1277 }-
1278 }
never executed: end of block
0
1279 while (str_pos < item_length)
str_pos < item_lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1280 log_clusters[str_pos++] = last_glyph_pos;
never executed: log_clusters[str_pos++] = last_glyph_pos;
0
1281-
1282 if (Q_UNLIKELY(engineIdx != 0)) {
__builtin_expe... != 0), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
1283 for (quint32 i = 0; i < num_glyphs; ++i)
i < num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1284 g.glyphs[i] |= (engineIdx << 24);
never executed: g.glyphs[i] |= (engineIdx << 24);
0
1285 }
never executed: end of block
0
1286-
1287#ifdef Q_OS_DARWIN-
1288 if (actualFontEngine->type() == QFontEngine::Mac) {-
1289 // CTRunGetPosition has a bug which applies matrix on 10.6, so we disable-
1290 // scaling the advances for this particular version-
1291 if (QSysInfo::MacintoshVersion != QSysInfo::MV_10_6 && actualFontEngine->fontDef.stretch != 100) {-
1292 QFixed stretch = QFixed(int(actualFontEngine->fontDef.stretch)) / QFixed(100);-
1293 for (uint i = 0; i < num_glyphs; ++i)-
1294 g.advances[i] *= stretch;-
1295 }-
1296 }-
1297#endif-
1298-
1299 if (!actualFontEngine->supportsSubPixelPositions() || (actualFontEngine->fontDef.styleStrategy & QFont::ForceIntegerMetrics)) {
!actualFontEng...xelPositions()Description
TRUEnever evaluated
FALSEnever evaluated
(actualFontEng...ntegerMetrics)Description
TRUEnever evaluated
FALSEnever evaluated
0
1300 for (uint i = 0; i < num_glyphs; ++i)
i < num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1301 g.advances[i] = g.advances[i].round();
never executed: g.advances[i] = g.advances[i].round();
0
1302 }
never executed: end of block
0
1303-
1304 glyphs_shaped += num_glyphs;-
1305 }
never executed: end of block
0
1306-
1307 hb_buffer_destroy(buffer);-
1308-
1309 return glyphs_shaped;
never executed: return glyphs_shaped;
0
1310}-
1311-
1312#endif // QT_ENABLE_HARFBUZZ_NG-
1313-
1314-
1315QT_BEGIN_INCLUDE_NAMESPACE-
1316-
1317#include <private/qharfbuzz_p.h>-
1318-
1319QT_END_INCLUDE_NAMESPACE-
1320-
1321Q_STATIC_ASSERT(sizeof(HB_Glyph) == sizeof(glyph_t));-
1322Q_STATIC_ASSERT(sizeof(HB_Fixed) == sizeof(QFixed));-
1323Q_STATIC_ASSERT(sizeof(HB_FixedPoint) == sizeof(QFixedPoint));-
1324-
1325static inline void moveGlyphData(const QGlyphLayout &destination, const QGlyphLayout &source, int num)-
1326{-
1327 if (num > 0 && destination.glyphs != source.glyphs)
num > 0Description
TRUEnever evaluated
FALSEnever evaluated
destination.gl... source.glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1328 memmove(destination.glyphs, source.glyphs, num * sizeof(glyph_t));
never executed: memmove(destination.glyphs, source.glyphs, num * sizeof(glyph_t));
0
1329}
never executed: end of block
0
1330-
1331int QTextEngine::shapeTextWithHarfbuzz(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector<uint> &itemBoundaries, bool kerningEnabled) const-
1332{-
1333 HB_ShaperItem entire_shaper_item;-
1334 memset(&entire_shaper_item, 0, sizeof(entire_shaper_item));-
1335 entire_shaper_item.string = reinterpret_cast<const HB_UChar16 *>(string);-
1336 entire_shaper_item.stringLength = itemLength;-
1337 entire_shaper_item.item.script = script_to_hbscript(si.analysis.script);-
1338 entire_shaper_item.item.pos = 0;-
1339 entire_shaper_item.item.length = itemLength;-
1340 entire_shaper_item.item.bidiLevel = si.analysis.bidiLevel;-
1341-
1342 entire_shaper_item.shaperFlags = 0;-
1343 if (!kerningEnabled)
!kerningEnabledDescription
TRUEnever evaluated
FALSEnever evaluated
0
1344 entire_shaper_item.shaperFlags |= HB_ShaperFlag_NoKerning;
never executed: entire_shaper_item.shaperFlags |= HB_ShaperFlag_NoKerning;
0
1345 if (option.useDesignMetrics())
option.useDesignMetrics()Description
TRUEnever evaluated
FALSEnever evaluated
0
1346 entire_shaper_item.shaperFlags |= HB_ShaperFlag_UseDesignMetrics;
never executed: entire_shaper_item.shaperFlags |= HB_ShaperFlag_UseDesignMetrics;
0
1347-
1348 // ensure we are not asserting in HB_HeuristicSetGlyphAttributes()-
1349 entire_shaper_item.num_glyphs = 0;-
1350 for (int i = 0; i < itemLength; ++i, ++entire_shaper_item.num_glyphs) {
i < itemLengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1351 if (QChar::isHighSurrogate(string[i]) && i + 1 < itemLength && QChar::isLowSurrogate(string[i + 1]))
QChar::isHighS...ate(string[i])Description
TRUEnever evaluated
FALSEnever evaluated
i + 1 < itemLengthDescription
TRUEnever evaluated
FALSEnever evaluated
QChar::isLowSu...string[i + 1])Description
TRUEnever evaluated
FALSEnever evaluated
0
1352 ++i;
never executed: ++i;
0
1353 }
never executed: end of block
0
1354-
1355-
1356 int remaining_glyphs = entire_shaper_item.num_glyphs;-
1357 int glyph_pos = 0;-
1358 // for each item shape using harfbuzz and store the results in our layoutData's glyphs array.-
1359 for (int k = 0; k < itemBoundaries.size(); k += 3) {
k < itemBoundaries.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1360 HB_ShaperItem shaper_item = entire_shaper_item;-
1361 shaper_item.item.pos = itemBoundaries[k];-
1362 if (k + 4 < itemBoundaries.size()) {
k + 4 < itemBoundaries.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1363 shaper_item.item.length = itemBoundaries[k + 3] - shaper_item.item.pos;-
1364 shaper_item.num_glyphs = itemBoundaries[k + 4] - itemBoundaries[k + 1];-
1365 } else { // last combo in the list, avoid out of bounds access.
never executed: end of block
0
1366 shaper_item.item.length -= shaper_item.item.pos - entire_shaper_item.item.pos;-
1367 shaper_item.num_glyphs -= itemBoundaries[k + 1];-
1368 }
never executed: end of block
0
1369 shaper_item.initialGlyphCount = shaper_item.num_glyphs;-
1370 if (shaper_item.num_glyphs < shaper_item.item.length)
shaper_item.nu...em.item.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1371 shaper_item.num_glyphs = shaper_item.item.length;
never executed: shaper_item.num_glyphs = shaper_item.item.length;
0
1372-
1373 uint engineIdx = itemBoundaries[k + 2];-
1374 QFontEngine *actualFontEngine = fontEngine;-
1375 if (fontEngine->type() == QFontEngine::Multi) {
fontEngine->ty...tEngine::MultiDescription
TRUEnever evaluated
FALSEnever evaluated
0
1376 actualFontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx);-
1377-
1378 if ((si.analysis.bidiLevel % 2) == 0)
(si.analysis.b...evel % 2) == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1379 shaper_item.glyphIndicesPresent = true;
never executed: shaper_item.glyphIndicesPresent = true;
0
1380 }
never executed: end of block
0
1381-
1382 shaper_item.font = (HB_Font)actualFontEngine->harfbuzzFont();-
1383 shaper_item.face = (HB_Face)actualFontEngine->harfbuzzFace();-
1384-
1385 remaining_glyphs -= shaper_item.initialGlyphCount;-
1386-
1387 QVarLengthArray<HB_GlyphAttributes, 128> hbGlyphAttributes;-
1388 do {-
1389 if (!ensureSpace(glyph_pos + shaper_item.num_glyphs + remaining_glyphs))
!ensureSpace(g...aining_glyphs)Description
TRUEnever evaluated
FALSEnever evaluated
0
1390 return 0;
never executed: return 0;
0
1391 if (hbGlyphAttributes.size() < int(shaper_item.num_glyphs)) {
hbGlyphAttribu...em.num_glyphs)Description
TRUEnever evaluated
FALSEnever evaluated
0
1392 hbGlyphAttributes.resize(shaper_item.num_glyphs);-
1393 memset(hbGlyphAttributes.data(), 0, hbGlyphAttributes.size() * sizeof(HB_GlyphAttributes));-
1394 }
never executed: end of block
0
1395-
1396 const QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos);-
1397 if (fontEngine->type() == QFontEngine::Multi && shaper_item.num_glyphs > shaper_item.item.length)
fontEngine->ty...tEngine::MultiDescription
TRUEnever evaluated
FALSEnever evaluated
shaper_item.nu...em.item.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1398 moveGlyphData(g.mid(shaper_item.num_glyphs), g.mid(shaper_item.initialGlyphCount), remaining_glyphs);
never executed: moveGlyphData(g.mid(shaper_item.num_glyphs), g.mid(shaper_item.initialGlyphCount), remaining_glyphs);
0
1399-
1400 shaper_item.glyphs = reinterpret_cast<HB_Glyph *>(g.glyphs);-
1401 shaper_item.advances = reinterpret_cast<HB_Fixed *>(g.advances);-
1402 shaper_item.offsets = reinterpret_cast<HB_FixedPoint *>(g.offsets);-
1403 shaper_item.attributes = hbGlyphAttributes.data();-
1404-
1405 if (engineIdx != 0 && shaper_item.glyphIndicesPresent) {
engineIdx != 0Description
TRUEnever evaluated
FALSEnever evaluated
shaper_item.gl...IndicesPresentDescription
TRUEnever evaluated
FALSEnever evaluated
0
1406 for (quint32 i = 0; i < shaper_item.initialGlyphCount; ++i)
i < shaper_ite...tialGlyphCountDescription
TRUEnever evaluated
FALSEnever evaluated
0
1407 shaper_item.glyphs[i] &= 0x00ffffff;
never executed: shaper_item.glyphs[i] &= 0x00ffffff;
0
1408 }
never executed: end of block
0
1409-
1410 shaper_item.log_clusters = logClusters(&si) + shaper_item.item.pos - entire_shaper_item.item.pos;-
1411 } while (!qShapeItem(&shaper_item)); // this does the actual shaping via harfbuzz.
never executed: end of block
!qShapeItem(&shaper_item)Description
TRUEnever evaluated
FALSEnever evaluated
0
1412-
1413 QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos, shaper_item.num_glyphs);-
1414 if (fontEngine->type() == QFontEngine::Multi)
fontEngine->ty...tEngine::MultiDescription
TRUEnever evaluated
FALSEnever evaluated
0
1415 moveGlyphData(g.mid(shaper_item.num_glyphs), g.mid(shaper_item.initialGlyphCount), remaining_glyphs);
never executed: moveGlyphData(g.mid(shaper_item.num_glyphs), g.mid(shaper_item.initialGlyphCount), remaining_glyphs);
0
1416-
1417 for (quint32 i = 0; i < shaper_item.num_glyphs; ++i) {
i < shaper_item.num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1418 HB_GlyphAttributes hbAttrs = hbGlyphAttributes.at(i);-
1419 QGlyphAttributes &attrs = g.attributes[i];-
1420 attrs.clusterStart = hbAttrs.clusterStart;-
1421 attrs.dontPrint = hbAttrs.dontPrint;-
1422 attrs.justification = hbAttrs.justification;-
1423 }
never executed: end of block
0
1424-
1425 for (quint32 i = 0; i < shaper_item.item.length; ++i) {
i < shaper_item.item.lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1426 // Workaround wrong log_clusters for surrogates (i.e. QTBUG-39875)-
1427 if (shaper_item.log_clusters[i] >= shaper_item.num_glyphs)
shaper_item.lo...tem.num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1428 shaper_item.log_clusters[i] = shaper_item.num_glyphs - 1;
never executed: shaper_item.log_clusters[i] = shaper_item.num_glyphs - 1;
0
1429 shaper_item.log_clusters[i] += glyph_pos;-
1430 }
never executed: end of block
0
1431-
1432 if (kerningEnabled && !shaper_item.kerning_applied)
kerningEnabledDescription
TRUEnever evaluated
FALSEnever evaluated
!shaper_item.kerning_appliedDescription
TRUEnever evaluated
FALSEnever evaluated
0
1433 actualFontEngine->doKerning(&g, option.useDesignMetrics() ? QFontEngine::DesignMetrics : QFontEngine::ShaperFlags(0));
never executed: actualFontEngine->doKerning(&g, option.useDesignMetrics() ? QFontEngine::DesignMetrics : QFontEngine::ShaperFlags(0));
0
1434-
1435 if (engineIdx != 0) {
engineIdx != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1436 for (quint32 i = 0; i < shaper_item.num_glyphs; ++i)
i < shaper_item.num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1437 g.glyphs[i] |= (engineIdx << 24);
never executed: g.glyphs[i] |= (engineIdx << 24);
0
1438 }
never executed: end of block
0
1439-
1440 glyph_pos += shaper_item.num_glyphs;-
1441 }
never executed: end of block
0
1442-
1443 return glyph_pos;
never executed: return glyph_pos;
0
1444}-
1445-
1446void QTextEngine::init(QTextEngine *e)-
1447{-
1448 e->ignoreBidi = false;-
1449 e->cacheGlyphs = false;-
1450 e->forceJustification = false;-
1451 e->visualMovement = false;-
1452 e->delayDecorations = false;-
1453-
1454 e->layoutData = 0;-
1455-
1456 e->minWidth = 0;-
1457 e->maxWidth = 0;-
1458-
1459 e->specialData = 0;-
1460 e->stackEngine = false;-
1461#ifndef QT_NO_RAWFONT-
1462 e->useRawFont = false;-
1463#endif-
1464}
never executed: end of block
0
1465-
1466QTextEngine::QTextEngine()-
1467{-
1468 init(this);-
1469}
never executed: end of block
0
1470-
1471QTextEngine::QTextEngine(const QString &str, const QFont &f)-
1472 : text(str),-
1473 fnt(f)-
1474{-
1475 init(this);-
1476}
never executed: end of block
0
1477-
1478QTextEngine::~QTextEngine()-
1479{-
1480 if (!stackEngine)
!stackEngineDescription
TRUEnever evaluated
FALSEnever evaluated
0
1481 delete layoutData;
never executed: delete layoutData;
0
1482 delete specialData;-
1483 resetFontEngineCache();-
1484}
never executed: end of block
0
1485-
1486const QCharAttributes *QTextEngine::attributes() const-
1487{-
1488 if (layoutData && layoutData->haveCharAttributes)
layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
layoutData->haveCharAttributesDescription
TRUEnever evaluated
FALSEnever evaluated
0
1489 return (QCharAttributes *) layoutData->memory;
never executed: return (QCharAttributes *) layoutData->memory;
0
1490-
1491 itemize();-
1492 if (! ensureSpace(layoutData->string.length()))
! ensureSpace(...ring.length())Description
TRUEnever evaluated
FALSEnever evaluated
0
1493 return NULL;
never executed: return __null;
0
1494-
1495 QVarLengthArray<QUnicodeTools::ScriptItem> scriptItems(layoutData->items.size());-
1496 for (int i = 0; i < layoutData->items.size(); ++i) {
i < layoutData->items.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1497 const QScriptItem &si = layoutData->items[i];-
1498 scriptItems[i].position = si.position;-
1499 scriptItems[i].script = si.analysis.script;-
1500 }
never executed: end of block
0
1501-
1502 QUnicodeTools::initCharAttributes(reinterpret_cast<const ushort *>(layoutData->string.constData()),-
1503 layoutData->string.length(),-
1504 scriptItems.data(), scriptItems.size(),-
1505 (QCharAttributes *)layoutData->memory);-
1506-
1507-
1508 layoutData->haveCharAttributes = true;-
1509 return (QCharAttributes *) layoutData->memory;
never executed: return (QCharAttributes *) layoutData->memory;
0
1510}-
1511-
1512void QTextEngine::shape(int item) const-
1513{-
1514 if (layoutData->items[item].analysis.flags == QScriptAnalysis::Object) {
layoutData->it...alysis::ObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
1515 ensureSpace(1);-
1516 if (block.docHandle()) {
block.docHandle()Description
TRUEnever evaluated
FALSEnever evaluated
0
1517 docLayout()->resizeInlineObject(QTextInlineObject(item, const_cast<QTextEngine *>(this)),-
1518 layoutData->items[item].position + block.position(),-
1519 format(&layoutData->items[item]));-
1520 }
never executed: end of block
0
1521 } else if (layoutData->items[item].analysis.flags == QScriptAnalysis::Tab) {
never executed: end of block
layoutData->it...tAnalysis::TabDescription
TRUEnever evaluated
FALSEnever evaluated
0
1522 // set up at least the ascent/descent/leading of the script item for the tab-
1523 fontEngine(layoutData->items[item],-
1524 &layoutData->items[item].ascent,-
1525 &layoutData->items[item].descent,-
1526 &layoutData->items[item].leading);-
1527 } else {
never executed: end of block
0
1528 shapeText(item);-
1529 }
never executed: end of block
0
1530}-
1531-
1532static inline void releaseCachedFontEngine(QFontEngine *fontEngine)-
1533{-
1534 if (fontEngine && !fontEngine->ref.deref())
fontEngineDescription
TRUEnever evaluated
FALSEnever evaluated
!fontEngine->ref.deref()Description
TRUEnever evaluated
FALSEnever evaluated
0
1535 delete fontEngine;
never executed: delete fontEngine;
0
1536}
never executed: end of block
0
1537-
1538void QTextEngine::resetFontEngineCache()-
1539{-
1540 releaseCachedFontEngine(feCache.prevFontEngine);-
1541 releaseCachedFontEngine(feCache.prevScaledFontEngine);-
1542 feCache.reset();-
1543}
never executed: end of block
0
1544-
1545void QTextEngine::invalidate()-
1546{-
1547 freeMemory();-
1548 minWidth = 0;-
1549 maxWidth = 0;-
1550-
1551 resetFontEngineCache();-
1552}
never executed: end of block
0
1553-
1554void QTextEngine::clearLineData()-
1555{-
1556 lines.clear();-
1557}
never executed: end of block
0
1558-
1559void QTextEngine::validate() const-
1560{-
1561 if (layoutData)
layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
0
1562 return;
never executed: return;
0
1563 layoutData = new LayoutData();-
1564 if (block.docHandle()) {
block.docHandle()Description
TRUEnever evaluated
FALSEnever evaluated
0
1565 layoutData->string = block.text();-
1566 if (option.flags() & QTextOption::ShowLineAndParagraphSeparators)
option.flags()...raphSeparatorsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1567 layoutData->string += QLatin1Char(block.next().isValid() ? 0xb6 : 0x20);
never executed: layoutData->string += QLatin1Char(block.next().isValid() ? 0xb6 : 0x20);
0
1568 } else {
never executed: end of block
0
1569 layoutData->string = text;-
1570 }
never executed: end of block
0
1571 if (specialData && specialData->preeditPosition != -1)
specialDataDescription
TRUEnever evaluated
FALSEnever evaluated
specialData->p...Position != -1Description
TRUEnever evaluated
FALSEnever evaluated
0
1572 layoutData->string.insert(specialData->preeditPosition, specialData->preeditText);
never executed: layoutData->string.insert(specialData->preeditPosition, specialData->preeditText);
0
1573}
never executed: end of block
0
1574-
1575void QTextEngine::itemize() const-
1576{-
1577 validate();-
1578 if (layoutData->items.size())
layoutData->items.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1579 return;
never executed: return;
0
1580-
1581 int length = layoutData->string.length();-
1582 if (!length)
!lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1583 return;
never executed: return;
0
1584-
1585 const ushort *string = reinterpret_cast<const ushort *>(layoutData->string.unicode());-
1586-
1587 bool ignore = ignoreBidi;-
1588-
1589 bool rtl = isRightToLeft();-
1590-
1591 if (!ignore && !rtl) {
!ignoreDescription
TRUEnever evaluated
FALSEnever evaluated
!rtlDescription
TRUEnever evaluated
FALSEnever evaluated
0
1592 ignore = true;-
1593 const QChar *start = layoutData->string.unicode();-
1594 const QChar * const end = start + length;-
1595 while (start < end) {
start < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1596 if (start->unicode() >= 0x590) {
start->unicode() >= 0x590Description
TRUEnever evaluated
FALSEnever evaluated
0
1597 ignore = false;-
1598 break;
never executed: break;
0
1599 }-
1600 ++start;-
1601 }
never executed: end of block
0
1602 }
never executed: end of block
0
1603-
1604 QVarLengthArray<QScriptAnalysis, 4096> scriptAnalysis(length);-
1605 QScriptAnalysis *analysis = scriptAnalysis.data();-
1606-
1607 QBidiControl control(rtl);-
1608-
1609 if (ignore) {
ignoreDescription
TRUEnever evaluated
FALSEnever evaluated
0
1610 memset(analysis, 0, length*sizeof(QScriptAnalysis));-
1611 if (option.textDirection() == Qt::RightToLeft) {
option.textDir...t::RightToLeftDescription
TRUEnever evaluated
FALSEnever evaluated
0
1612 for (int i = 0; i < length; ++i)
i < lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1613 analysis[i].bidiLevel = 1;
never executed: analysis[i].bidiLevel = 1;
0
1614 layoutData->hasBidi = true;-
1615 }
never executed: end of block
0
1616 } else {
never executed: end of block
0
1617 layoutData->hasBidi = bidiItemize(const_cast<QTextEngine *>(this), analysis, control);-
1618 }
never executed: end of block
0
1619-
1620 {-
1621 QVarLengthArray<uchar> scripts(length);-
1622 QUnicodeTools::initScripts(string, length, scripts.data());-
1623 for (int i = 0; i < length; ++i)
i < lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1624 analysis[i].script = scripts.at(i);
never executed: analysis[i].script = scripts.at(i);
0
1625 }-
1626-
1627 const ushort *uc = string;-
1628 const ushort *e = uc + length;-
1629 while (uc < e) {
uc < eDescription
TRUEnever evaluated
FALSEnever evaluated
0
1630 switch (*uc) {-
1631 case QChar::ObjectReplacementCharacter:
never executed: case QChar::ObjectReplacementCharacter:
0
1632 analysis->flags = QScriptAnalysis::Object;-
1633 break;
never executed: break;
0
1634 case QChar::LineSeparator:
never executed: case QChar::LineSeparator:
0
1635 if (analysis->bidiLevel % 2)
analysis->bidiLevel % 2Description
TRUEnever evaluated
FALSEnever evaluated
0
1636 --analysis->bidiLevel;
never executed: --analysis->bidiLevel;
0
1637 analysis->flags = QScriptAnalysis::LineOrParagraphSeparator;-
1638 if (option.flags() & QTextOption::ShowLineAndParagraphSeparators) {
option.flags()...raphSeparatorsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1639 const int offset = uc - string;-
1640 layoutData->string.detach();-
1641 string = reinterpret_cast<const ushort *>(layoutData->string.unicode());-
1642 uc = string + offset;-
1643 e = uc + length;-
1644 *const_cast<ushort*>(uc) = 0x21B5; // visual line separator-
1645 }
never executed: end of block
0
1646 break;
never executed: break;
0
1647 case QChar::Tabulation:
never executed: case QChar::Tabulation:
0
1648 analysis->flags = QScriptAnalysis::Tab;-
1649 analysis->bidiLevel = control.baseLevel();-
1650 break;
never executed: break;
0
1651 case QChar::Space:
never executed: case QChar::Space:
0
1652 case QChar::Nbsp:
never executed: case QChar::Nbsp:
0
1653 if (option.flags() & QTextOption::ShowTabsAndSpaces) {
option.flags()...wTabsAndSpacesDescription
TRUEnever evaluated
FALSEnever evaluated
0
1654 analysis->flags = QScriptAnalysis::Space;-
1655 analysis->bidiLevel = control.baseLevel();-
1656 break;
never executed: break;
0
1657 }-
1658 // fall through-
1659 default:
code before this statement never executed: default:
never executed: default:
0
1660 analysis->flags = QScriptAnalysis::None;-
1661 break;
never executed: break;
0
1662 }-
1663#ifndef QT_ENABLE_HARFBUZZ_NG-
1664 analysis->script = hbscript_to_script(script_to_hbscript(analysis->script));-
1665#endif-
1666 ++uc;-
1667 ++analysis;-
1668 }
never executed: end of block
0
1669 if (option.flags() & QTextOption::ShowLineAndParagraphSeparators) {
option.flags()...raphSeparatorsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1670 (analysis-1)->flags = QScriptAnalysis::LineOrParagraphSeparator; // to exclude it from width-
1671 }
never executed: end of block
0
1672#ifdef QT_ENABLE_HARFBUZZ_NG-
1673 analysis = scriptAnalysis.data();-
1674 if (qt_useHarfbuzzNG()) {
qt_useHarfbuzzNG()Description
TRUEnever evaluated
FALSEnever evaluated
0
1675 // ### pretend HB-old behavior for now-
1676 for (int i = 0; i < length; ++i) {
i < lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1677 switch (analysis[i].script) {-
1678 case QChar::Script_Latin:
never executed: case QChar::Script_Latin:
0
1679 case QChar::Script_Hiragana:
never executed: case QChar::Script_Hiragana:
0
1680 case QChar::Script_Katakana:
never executed: case QChar::Script_Katakana:
0
1681 case QChar::Script_Bopomofo:
never executed: case QChar::Script_Bopomofo:
0
1682 case QChar::Script_Han:
never executed: case QChar::Script_Han:
0
1683 analysis[i].script = QChar::Script_Common;-
1684 break;
never executed: break;
0
1685 default:
never executed: default:
0
1686 break;
never executed: break;
0
1687 }-
1688 }-
1689 } else {
never executed: end of block
0
1690 for (int i = 0; i < length; ++i)
i < lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1691 analysis[i].script = hbscript_to_script(script_to_hbscript(analysis[i].script));
never executed: analysis[i].script = hbscript_to_script(script_to_hbscript(analysis[i].script));
0
1692 }
never executed: end of block
0
1693#endif-
1694-
1695 Itemizer itemizer(layoutData->string, scriptAnalysis.data(), layoutData->items);-
1696-
1697 const QTextDocumentPrivate *p = block.docHandle();-
1698 if (p) {
pDescription
TRUEnever evaluated
FALSEnever evaluated
0
1699 SpecialData *s = specialData;-
1700-
1701 QTextDocumentPrivate::FragmentIterator it = p->find(block.position());-
1702 QTextDocumentPrivate::FragmentIterator end = p->find(block.position() + block.length() - 1); // -1 to omit the block separator char-
1703 int format = it.value()->format;-
1704-
1705 int prevPosition = 0;-
1706 int position = prevPosition;-
1707 while (1) {-
1708 const QTextFragmentData * const frag = it.value();-
1709 if (it == end || format != frag->format) {
it == endDescription
TRUEnever evaluated
FALSEnever evaluated
format != frag->formatDescription
TRUEnever evaluated
FALSEnever evaluated
0
1710 if (s && position >= s->preeditPosition) {
sDescription
TRUEnever evaluated
FALSEnever evaluated
position >= s->preeditPositionDescription
TRUEnever evaluated
FALSEnever evaluated
0
1711 position += s->preeditText.length();-
1712 s = 0;-
1713 }
never executed: end of block
0
1714 Q_ASSERT(position <= length);-
1715 QFont::Capitalization capitalization =-
1716 formatCollection()->charFormat(format).hasProperty(QTextFormat::FontCapitalization)
formatCollecti...apitalization)Description
TRUEnever evaluated
FALSEnever evaluated
0
1717 ? formatCollection()->charFormat(format).fontCapitalization()-
1718 : formatCollection()->defaultFont().capitalization();-
1719 itemizer.generate(prevPosition, position - prevPosition, capitalization);-
1720 if (it == end) {
it == endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1721 if (position < length)
position < lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1722 itemizer.generate(position, length - position, capitalization);
never executed: itemizer.generate(position, length - position, capitalization);
0
1723 break;
never executed: break;
0
1724 }-
1725 format = frag->format;-
1726 prevPosition = position;-
1727 }
never executed: end of block
0
1728 position += frag->size_array[0];-
1729 ++it;-
1730 }
never executed: end of block
0
1731 } else {
never executed: end of block
0
1732#ifndef QT_NO_RAWFONT-
1733 if (useRawFont && specialData) {
useRawFontDescription
TRUEnever evaluated
FALSEnever evaluated
specialDataDescription
TRUEnever evaluated
FALSEnever evaluated
0
1734 int lastIndex = 0;-
1735 for (int i = 0; i < specialData->formats.size(); ++i) {
i < specialDat...formats.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1736 const QTextLayout::FormatRange &range = specialData->formats.at(i);-
1737 const QTextCharFormat &format = range.format;-
1738 if (format.hasProperty(QTextFormat::FontCapitalization)) {
format.hasProp...apitalization)Description
TRUEnever evaluated
FALSEnever evaluated
0
1739 itemizer.generate(lastIndex, range.start - lastIndex, QFont::MixedCase);-
1740 itemizer.generate(range.start, range.length, format.fontCapitalization());-
1741 lastIndex = range.start + range.length;-
1742 }
never executed: end of block
0
1743 }
never executed: end of block
0
1744 itemizer.generate(lastIndex, length - lastIndex, QFont::MixedCase);-
1745 } else
never executed: end of block
0
1746#endif-
1747 itemizer.generate(0, length, static_cast<QFont::Capitalization> (fnt.d->capital));
never executed: itemizer.generate(0, length, static_cast<QFont::Capitalization> (fnt.d->capital));
0
1748 }-
1749-
1750 addRequiredBoundaries();-
1751 resolveFormats();-
1752}
never executed: end of block
0
1753-
1754bool QTextEngine::isRightToLeft() const-
1755{-
1756 switch (option.textDirection()) {-
1757 case Qt::LeftToRight:
never executed: case Qt::LeftToRight:
0
1758 return false;
never executed: return false;
0
1759 case Qt::RightToLeft:
never executed: case Qt::RightToLeft:
0
1760 return true;
never executed: return true;
0
1761 default:
never executed: default:
0
1762 break;
never executed: break;
0
1763 }-
1764 if (!layoutData)
!layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
0
1765 itemize();
never executed: itemize();
0
1766 // this places the cursor in the right position depending on the keyboard layout-
1767 if (layoutData->string.isEmpty())
layoutData->string.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1768 return QGuiApplication::inputMethod()->inputDirection() == Qt::RightToLeft;
never executed: return QGuiApplication::inputMethod()->inputDirection() == Qt::RightToLeft;
0
1769 return layoutData->string.isRightToLeft();
never executed: return layoutData->string.isRightToLeft();
0
1770}-
1771-
1772-
1773int QTextEngine::findItem(int strPos, int firstItem) const-
1774{-
1775 itemize();-
1776 if (strPos < 0 || strPos >= layoutData->string.size() || firstItem < 0)
strPos < 0Description
TRUEnever evaluated
FALSEnever evaluated
strPos >= layo...>string.size()Description
TRUEnever evaluated
FALSEnever evaluated
firstItem < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1777 return -1;
never executed: return -1;
0
1778-
1779 int left = firstItem + 1;-
1780 int right = layoutData->items.size()-1;-
1781 while(left <= right) {
left <= rightDescription
TRUEnever evaluated
FALSEnever evaluated
0
1782 int middle = ((right-left)/2)+left;-
1783 if (strPos > layoutData->items[middle].position)
strPos > layou...ddle].positionDescription
TRUEnever evaluated
FALSEnever evaluated
0
1784 left = middle+1;
never executed: left = middle+1;
0
1785 else if(strPos < layoutData->items[middle].position)
strPos < layou...ddle].positionDescription
TRUEnever evaluated
FALSEnever evaluated
0
1786 right = middle-1;
never executed: right = middle-1;
0
1787 else {-
1788 return middle;
never executed: return middle;
0
1789 }-
1790 }-
1791 return right;
never executed: return right;
0
1792}-
1793-
1794QFixed QTextEngine::width(int from, int len) const-
1795{-
1796 itemize();-
1797-
1798 QFixed w = 0;-
1799-
1800// qDebug("QTextEngine::width(from = %d, len = %d), numItems=%d, strleng=%d", from, len, items.size(), string.length());-
1801 for (int i = 0; i < layoutData->items.size(); i++) {
i < layoutData->items.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1802 const QScriptItem *si = layoutData->items.constData() + i;-
1803 int pos = si->position;-
1804 int ilen = length(i);-
1805// qDebug("item %d: from %d len %d", i, pos, ilen);-
1806 if (pos >= from + len)
pos >= from + lenDescription
TRUEnever evaluated
FALSEnever evaluated
0
1807 break;
never executed: break;
0
1808 if (pos + ilen > from) {
pos + ilen > fromDescription
TRUEnever evaluated
FALSEnever evaluated
0
1809 if (!si->num_glyphs)
!si->num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1810 shape(i);
never executed: shape(i);
0
1811-
1812 if (si->analysis.flags == QScriptAnalysis::Object) {
si->analysis.f...alysis::ObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
1813 w += si->width;-
1814 continue;
never executed: continue;
0
1815 } else if (si->analysis.flags == QScriptAnalysis::Tab) {
si->analysis.f...tAnalysis::TabDescription
TRUEnever evaluated
FALSEnever evaluated
0
1816 w += calculateTabWidth(i, w);-
1817 continue;
never executed: continue;
0
1818 }-
1819-
1820-
1821 QGlyphLayout glyphs = shapedGlyphs(si);-
1822 unsigned short *logClusters = this->logClusters(si);-
1823-
1824// fprintf(stderr, " logclusters:");-
1825// for (int k = 0; k < ilen; k++)-
1826// fprintf(stderr, " %d", logClusters[k]);-
1827// fprintf(stderr, "\n");-
1828 // do the simple thing for now and give the first glyph in a cluster the full width, all other ones 0.-
1829 int charFrom = from - pos;-
1830 if (charFrom < 0)
charFrom < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1831 charFrom = 0;
never executed: charFrom = 0;
0
1832 int glyphStart = logClusters[charFrom];-
1833 if (charFrom > 0 && logClusters[charFrom-1] == glyphStart)
charFrom > 0Description
TRUEnever evaluated
FALSEnever evaluated
logClusters[ch... == glyphStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
1834 while (charFrom < ilen && logClusters[charFrom] == glyphStart)
charFrom < ilenDescription
TRUEnever evaluated
FALSEnever evaluated
logClusters[ch... == glyphStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
1835 charFrom++;
never executed: charFrom++;
0
1836 if (charFrom < ilen) {
charFrom < ilenDescription
TRUEnever evaluated
FALSEnever evaluated
0
1837 glyphStart = logClusters[charFrom];-
1838 int charEnd = from + len - 1 - pos;-
1839 if (charEnd >= ilen)
charEnd >= ilenDescription
TRUEnever evaluated
FALSEnever evaluated
0
1840 charEnd = ilen-1;
never executed: charEnd = ilen-1;
0
1841 int glyphEnd = logClusters[charEnd];-
1842 while (charEnd < ilen && logClusters[charEnd] == glyphEnd)
charEnd < ilenDescription
TRUEnever evaluated
FALSEnever evaluated
logClusters[ch...d] == glyphEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
1843 charEnd++;
never executed: charEnd++;
0
1844 glyphEnd = (charEnd == ilen) ? si->num_glyphs : logClusters[charEnd];
(charEnd == ilen)Description
TRUEnever evaluated
FALSEnever evaluated
0
1845-
1846// qDebug("char: start=%d end=%d / glyph: start = %d, end = %d", charFrom, charEnd, glyphStart, glyphEnd);-
1847 for (int i = glyphStart; i < glyphEnd; i++)
i < glyphEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
1848 w += glyphs.advances[i] * !glyphs.attributes[i].dontPrint;
never executed: w += glyphs.advances[i] * !glyphs.attributes[i].dontPrint;
0
1849 }
never executed: end of block
0
1850 }
never executed: end of block
0
1851 }
never executed: end of block
0
1852// qDebug(" --> w= %d ", w);-
1853 return w;
never executed: return w;
0
1854}-
1855-
1856glyph_metrics_t QTextEngine::boundingBox(int from, int len) const-
1857{-
1858 itemize();-
1859-
1860 glyph_metrics_t gm;-
1861-
1862 for (int i = 0; i < layoutData->items.size(); i++) {
i < layoutData->items.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1863 const QScriptItem *si = layoutData->items.constData() + i;-
1864-
1865 int pos = si->position;-
1866 int ilen = length(i);-
1867 if (pos > from + len)
pos > from + lenDescription
TRUEnever evaluated
FALSEnever evaluated
0
1868 break;
never executed: break;
0
1869 if (pos + ilen > from) {
pos + ilen > fromDescription
TRUEnever evaluated
FALSEnever evaluated
0
1870 if (!si->num_glyphs)
!si->num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1871 shape(i);
never executed: shape(i);
0
1872-
1873 if (si->analysis.flags == QScriptAnalysis::Object) {
si->analysis.f...alysis::ObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
1874 gm.width += si->width;-
1875 continue;
never executed: continue;
0
1876 } else if (si->analysis.flags == QScriptAnalysis::Tab) {
si->analysis.f...tAnalysis::TabDescription
TRUEnever evaluated
FALSEnever evaluated
0
1877 gm.width += calculateTabWidth(i, gm.width);-
1878 continue;
never executed: continue;
0
1879 }-
1880-
1881 unsigned short *logClusters = this->logClusters(si);-
1882 QGlyphLayout glyphs = shapedGlyphs(si);-
1883-
1884 // do the simple thing for now and give the first glyph in a cluster the full width, all other ones 0.-
1885 int charFrom = from - pos;-
1886 if (charFrom < 0)
charFrom < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1887 charFrom = 0;
never executed: charFrom = 0;
0
1888 int glyphStart = logClusters[charFrom];-
1889 if (charFrom > 0 && logClusters[charFrom-1] == glyphStart)
charFrom > 0Description
TRUEnever evaluated
FALSEnever evaluated
logClusters[ch... == glyphStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
1890 while (charFrom < ilen && logClusters[charFrom] == glyphStart)
charFrom < ilenDescription
TRUEnever evaluated
FALSEnever evaluated
logClusters[ch... == glyphStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
1891 charFrom++;
never executed: charFrom++;
0
1892 if (charFrom < ilen) {
charFrom < ilenDescription
TRUEnever evaluated
FALSEnever evaluated
0
1893 QFontEngine *fe = fontEngine(*si);-
1894 glyphStart = logClusters[charFrom];-
1895 int charEnd = from + len - 1 - pos;-
1896 if (charEnd >= ilen)
charEnd >= ilenDescription
TRUEnever evaluated
FALSEnever evaluated
0
1897 charEnd = ilen-1;
never executed: charEnd = ilen-1;
0
1898 int glyphEnd = logClusters[charEnd];-
1899 while (charEnd < ilen && logClusters[charEnd] == glyphEnd)
charEnd < ilenDescription
TRUEnever evaluated
FALSEnever evaluated
logClusters[ch...d] == glyphEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
1900 charEnd++;
never executed: charEnd++;
0
1901 glyphEnd = (charEnd == ilen) ? si->num_glyphs : logClusters[charEnd];
(charEnd == ilen)Description
TRUEnever evaluated
FALSEnever evaluated
0
1902 if (glyphStart <= glyphEnd ) {
glyphStart <= glyphEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
1903 glyph_metrics_t m = fe->boundingBox(glyphs.mid(glyphStart, glyphEnd - glyphStart));-
1904 gm.x = qMin(gm.x, m.x + gm.xoff);-
1905 gm.y = qMin(gm.y, m.y + gm.yoff);-
1906 gm.width = qMax(gm.width, m.width+gm.xoff);-
1907 gm.height = qMax(gm.height, m.height+gm.yoff);-
1908 gm.xoff += m.xoff;-
1909 gm.yoff += m.yoff;-
1910 }
never executed: end of block
0
1911 }
never executed: end of block
0
1912 }
never executed: end of block
0
1913 }
never executed: end of block
0
1914 return gm;
never executed: return gm;
0
1915}-
1916-
1917glyph_metrics_t QTextEngine::tightBoundingBox(int from, int len) const-
1918{-
1919 itemize();-
1920-
1921 glyph_metrics_t gm;-
1922-
1923 for (int i = 0; i < layoutData->items.size(); i++) {
i < layoutData->items.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1924 const QScriptItem *si = layoutData->items.constData() + i;-
1925 int pos = si->position;-
1926 int ilen = length(i);-
1927 if (pos > from + len)
pos > from + lenDescription
TRUEnever evaluated
FALSEnever evaluated
0
1928 break;
never executed: break;
0
1929 if (pos + len > from) {
pos + len > fromDescription
TRUEnever evaluated
FALSEnever evaluated
0
1930 if (!si->num_glyphs)
!si->num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1931 shape(i);
never executed: shape(i);
0
1932 unsigned short *logClusters = this->logClusters(si);-
1933 QGlyphLayout glyphs = shapedGlyphs(si);-
1934-
1935 // do the simple thing for now and give the first glyph in a cluster the full width, all other ones 0.-
1936 int charFrom = from - pos;-
1937 if (charFrom < 0)
charFrom < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1938 charFrom = 0;
never executed: charFrom = 0;
0
1939 int glyphStart = logClusters[charFrom];-
1940 if (charFrom > 0 && logClusters[charFrom-1] == glyphStart)
charFrom > 0Description
TRUEnever evaluated
FALSEnever evaluated
logClusters[ch... == glyphStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
1941 while (charFrom < ilen && logClusters[charFrom] == glyphStart)
charFrom < ilenDescription
TRUEnever evaluated
FALSEnever evaluated
logClusters[ch... == glyphStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
1942 charFrom++;
never executed: charFrom++;
0
1943 if (charFrom < ilen) {
charFrom < ilenDescription
TRUEnever evaluated
FALSEnever evaluated
0
1944 glyphStart = logClusters[charFrom];-
1945 int charEnd = from + len - 1 - pos;-
1946 if (charEnd >= ilen)
charEnd >= ilenDescription
TRUEnever evaluated
FALSEnever evaluated
0
1947 charEnd = ilen-1;
never executed: charEnd = ilen-1;
0
1948 int glyphEnd = logClusters[charEnd];-
1949 while (charEnd < ilen && logClusters[charEnd] == glyphEnd)
charEnd < ilenDescription
TRUEnever evaluated
FALSEnever evaluated
logClusters[ch...d] == glyphEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
1950 charEnd++;
never executed: charEnd++;
0
1951 glyphEnd = (charEnd == ilen) ? si->num_glyphs : logClusters[charEnd];
(charEnd == ilen)Description
TRUEnever evaluated
FALSEnever evaluated
0
1952 if (glyphStart <= glyphEnd ) {
glyphStart <= glyphEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
1953 QFontEngine *fe = fontEngine(*si);-
1954 glyph_metrics_t m = fe->tightBoundingBox(glyphs.mid(glyphStart, glyphEnd - glyphStart));-
1955 gm.x = qMin(gm.x, m.x + gm.xoff);-
1956 gm.y = qMin(gm.y, m.y + gm.yoff);-
1957 gm.width = qMax(gm.width, m.width+gm.xoff);-
1958 gm.height = qMax(gm.height, m.height+gm.yoff);-
1959 gm.xoff += m.xoff;-
1960 gm.yoff += m.yoff;-
1961 }
never executed: end of block
0
1962 }
never executed: end of block
0
1963 }
never executed: end of block
0
1964 }
never executed: end of block
0
1965 return gm;
never executed: return gm;
0
1966}-
1967-
1968QFont QTextEngine::font(const QScriptItem &si) const-
1969{-
1970 QFont font = fnt;-
1971 if (hasFormats()) {
hasFormats()Description
TRUEnever evaluated
FALSEnever evaluated
0
1972 QTextCharFormat f = format(&si);-
1973 font = f.font();-
1974-
1975 if (block.docHandle() && block.docHandle()->layout()) {
block.docHandle()Description
TRUEnever evaluated
FALSEnever evaluated
block.docHandle()->layout()Description
TRUEnever evaluated
FALSEnever evaluated
0
1976 // Make sure we get the right dpi on printers-
1977 QPaintDevice *pdev = block.docHandle()->layout()->paintDevice();-
1978 if (pdev)
pdevDescription
TRUEnever evaluated
FALSEnever evaluated
0
1979 font = QFont(font, pdev);
never executed: font = QFont(font, pdev);
0
1980 } else {
never executed: end of block
0
1981 font = font.resolve(fnt);-
1982 }
never executed: end of block
0
1983 QTextCharFormat::VerticalAlignment valign = f.verticalAlignment();-
1984 if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) {
valign == QTex...ignSuperScriptDescription
TRUEnever evaluated
FALSEnever evaluated
valign == QTex...AlignSubScriptDescription
TRUEnever evaluated
FALSEnever evaluated
0
1985 if (font.pointSize() != -1)
font.pointSize() != -1Description
TRUEnever evaluated
FALSEnever evaluated
0
1986 font.setPointSize((font.pointSize() * 2) / 3);
never executed: font.setPointSize((font.pointSize() * 2) / 3);
0
1987 else-
1988 font.setPixelSize((font.pixelSize() * 2) / 3);
never executed: font.setPixelSize((font.pixelSize() * 2) / 3);
0
1989 }-
1990 }
never executed: end of block
0
1991-
1992 if (si.analysis.flags == QScriptAnalysis::SmallCaps)
si.analysis.fl...sis::SmallCapsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1993 font = font.d->smallCapsFont();
never executed: font = font.d->smallCapsFont();
0
1994-
1995 return font;
never executed: return font;
0
1996}-
1997-
1998QTextEngine::FontEngineCache::FontEngineCache()-
1999{-
2000 reset();-
2001}
never executed: end of block
0
2002-
2003//we cache the previous results of this function, as calling it numerous times with the same effective-
2004//input is common (and hard to cache at a higher level)-
2005QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFixed *descent, QFixed *leading) const-
2006{-
2007 QFontEngine *engine = 0;-
2008 QFontEngine *scaledEngine = 0;-
2009 int script = si.analysis.script;-
2010-
2011 QFont font = fnt;-
2012#ifndef QT_NO_RAWFONT-
2013 if (useRawFont && rawFont.isValid()) {
useRawFontDescription
TRUEnever evaluated
FALSEnever evaluated
rawFont.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
2014 if (feCache.prevFontEngine && feCache.prevFontEngine->type() == QFontEngine::Multi && feCache.prevScript == script) {
feCache.prevFontEngineDescription
TRUEnever evaluated
FALSEnever evaluated
feCache.prevFo...tEngine::MultiDescription
TRUEnever evaluated
FALSEnever evaluated
feCache.prevScript == scriptDescription
TRUEnever evaluated
FALSEnever evaluated
0
2015 engine = feCache.prevFontEngine;-
2016 } else {
never executed: end of block
0
2017 engine = QFontEngineMulti::createMultiFontEngine(rawFont.d->fontEngine, script);-
2018 feCache.prevFontEngine = engine;-
2019 feCache.prevScript = script;-
2020 engine->ref.ref();-
2021 if (feCache.prevScaledFontEngine) {
feCache.prevScaledFontEngineDescription
TRUEnever evaluated
FALSEnever evaluated
0
2022 releaseCachedFontEngine(feCache.prevScaledFontEngine);-
2023 feCache.prevScaledFontEngine = 0;-
2024 }
never executed: end of block
0
2025 }
never executed: end of block
0
2026 if (si.analysis.flags == QScriptAnalysis::SmallCaps) {
si.analysis.fl...sis::SmallCapsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2027 if (feCache.prevScaledFontEngine) {
feCache.prevScaledFontEngineDescription
TRUEnever evaluated
FALSEnever evaluated
0
2028 scaledEngine = feCache.prevScaledFontEngine;-
2029 } else {
never executed: end of block
0
2030 QFontEngine *scEngine = rawFont.d->fontEngine->cloneWithSize(smallCapsFraction * rawFont.pixelSize());-
2031 scEngine->ref.ref();-
2032 scaledEngine = QFontEngineMulti::createMultiFontEngine(scEngine, script);-
2033 scaledEngine->ref.ref();-
2034 feCache.prevScaledFontEngine = scaledEngine;-
2035 // If scEngine is not ref'ed by scaledEngine, make sure it is deallocated and not leaked.-
2036 if (!scEngine->ref.deref())
!scEngine->ref.deref()Description
TRUEnever evaluated
FALSEnever evaluated
0
2037 delete scEngine;
never executed: delete scEngine;
0
2038-
2039 }
never executed: end of block
0
2040 }-
2041 } else
never executed: end of block
0
2042#endif-
2043 {-
2044 if (hasFormats()) {
hasFormats()Description
TRUEnever evaluated
FALSEnever evaluated
0
2045 if (feCache.prevFontEngine && feCache.prevPosition == si.position && feCache.prevLength == length(&si) && feCache.prevScript == script) {
feCache.prevFontEngineDescription
TRUEnever evaluated
FALSEnever evaluated
feCache.prevPo...== si.positionDescription
TRUEnever evaluated
FALSEnever evaluated
feCache.prevLe...== length(&si)Description
TRUEnever evaluated
FALSEnever evaluated
feCache.prevScript == scriptDescription
TRUEnever evaluated
FALSEnever evaluated
0
2046 engine = feCache.prevFontEngine;-
2047 scaledEngine = feCache.prevScaledFontEngine;-
2048 } else {
never executed: end of block
0
2049 QTextCharFormat f = format(&si);-
2050 font = f.font();-
2051-
2052 if (block.docHandle() && block.docHandle()->layout()) {
block.docHandle()Description
TRUEnever evaluated
FALSEnever evaluated
block.docHandle()->layout()Description
TRUEnever evaluated
FALSEnever evaluated
0
2053 // Make sure we get the right dpi on printers-
2054 QPaintDevice *pdev = block.docHandle()->layout()->paintDevice();-
2055 if (pdev)
pdevDescription
TRUEnever evaluated
FALSEnever evaluated
0
2056 font = QFont(font, pdev);
never executed: font = QFont(font, pdev);
0
2057 } else {
never executed: end of block
0
2058 font = font.resolve(fnt);-
2059 }
never executed: end of block
0
2060 engine = font.d->engineForScript(script);-
2061 if (engine)
engineDescription
TRUEnever evaluated
FALSEnever evaluated
0
2062 engine->ref.ref();
never executed: engine->ref.ref();
0
2063-
2064 QTextCharFormat::VerticalAlignment valign = f.verticalAlignment();-
2065 if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) {
valign == QTex...ignSuperScriptDescription
TRUEnever evaluated
FALSEnever evaluated
valign == QTex...AlignSubScriptDescription
TRUEnever evaluated
FALSEnever evaluated
0
2066 if (font.pointSize() != -1)
font.pointSize() != -1Description
TRUEnever evaluated
FALSEnever evaluated
0
2067 font.setPointSize((font.pointSize() * 2) / 3);
never executed: font.setPointSize((font.pointSize() * 2) / 3);
0
2068 else-
2069 font.setPixelSize((font.pixelSize() * 2) / 3);
never executed: font.setPixelSize((font.pixelSize() * 2) / 3);
0
2070 scaledEngine = font.d->engineForScript(script);-
2071 if (scaledEngine)
scaledEngineDescription
TRUEnever evaluated
FALSEnever evaluated
0
2072 scaledEngine->ref.ref();
never executed: scaledEngine->ref.ref();
0
2073 }
never executed: end of block
0
2074-
2075 if (feCache.prevFontEngine)
feCache.prevFontEngineDescription
TRUEnever evaluated
FALSEnever evaluated
0
2076 releaseCachedFontEngine(feCache.prevFontEngine);
never executed: releaseCachedFontEngine(feCache.prevFontEngine);
0
2077 feCache.prevFontEngine = engine;-
2078-
2079 if (feCache.prevScaledFontEngine)
feCache.prevScaledFontEngineDescription
TRUEnever evaluated
FALSEnever evaluated
0
2080 releaseCachedFontEngine(feCache.prevScaledFontEngine);
never executed: releaseCachedFontEngine(feCache.prevScaledFontEngine);
0
2081 feCache.prevScaledFontEngine = scaledEngine;-
2082-
2083 feCache.prevScript = script;-
2084 feCache.prevPosition = si.position;-
2085 feCache.prevLength = length(&si);-
2086 }
never executed: end of block
0
2087 } else {-
2088 if (feCache.prevFontEngine && feCache.prevScript == script && feCache.prevPosition == -1)
feCache.prevFontEngineDescription
TRUEnever evaluated
FALSEnever evaluated
feCache.prevScript == scriptDescription
TRUEnever evaluated
FALSEnever evaluated
feCache.prevPosition == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
2089 engine = feCache.prevFontEngine;
never executed: engine = feCache.prevFontEngine;
0
2090 else {-
2091 engine = font.d->engineForScript(script);-
2092-
2093 if (engine)
engineDescription
TRUEnever evaluated
FALSEnever evaluated
0
2094 engine->ref.ref();
never executed: engine->ref.ref();
0
2095 if (feCache.prevFontEngine)
feCache.prevFontEngineDescription
TRUEnever evaluated
FALSEnever evaluated
0
2096 releaseCachedFontEngine(feCache.prevFontEngine);
never executed: releaseCachedFontEngine(feCache.prevFontEngine);
0
2097 feCache.prevFontEngine = engine;-
2098-
2099 feCache.prevScript = script;-
2100 feCache.prevPosition = -1;-
2101 feCache.prevLength = -1;-
2102 feCache.prevScaledFontEngine = 0;-
2103 }
never executed: end of block
0
2104 }-
2105-
2106 if (si.analysis.flags == QScriptAnalysis::SmallCaps) {
si.analysis.fl...sis::SmallCapsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2107 QFontPrivate *p = font.d->smallCapsFontPrivate();-
2108 scaledEngine = p->engineForScript(script);-
2109 }
never executed: end of block
0
2110 }
never executed: end of block
0
2111-
2112 if (ascent) {
ascentDescription
TRUEnever evaluated
FALSEnever evaluated
0
2113 *ascent = engine->ascent();-
2114 *descent = engine->descent();-
2115 *leading = engine->leading();-
2116 }
never executed: end of block
0
2117-
2118 if (scaledEngine)
scaledEngineDescription
TRUEnever evaluated
FALSEnever evaluated
0
2119 return scaledEngine;
never executed: return scaledEngine;
0
2120 return engine;
never executed: return engine;
0
2121}-
2122-
2123struct QJustificationPoint {-
2124 int type;-
2125 QFixed kashidaWidth;-
2126 QGlyphLayout glyph;-
2127};-
2128-
2129Q_DECLARE_TYPEINFO(QJustificationPoint, Q_PRIMITIVE_TYPE);-
2130-
2131static void set(QJustificationPoint *point, int type, const QGlyphLayout &glyph, QFontEngine *fe)-
2132{-
2133 point->type = type;-
2134 point->glyph = glyph;-
2135-
2136 if (type >= Justification_Arabic_Normal) {
type >= Justif..._Arabic_NormalDescription
TRUEnever evaluated
FALSEnever evaluated
0
2137 QChar ch(0x640); // Kashida character-
2138-
2139 glyph_t kashidaGlyph = fe->glyphIndex(ch.unicode());-
2140 if (kashidaGlyph != 0) {
kashidaGlyph != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2141 QGlyphLayout g;-
2142 g.numGlyphs = 1;-
2143 g.glyphs = &kashidaGlyph;-
2144 g.advances = &point->kashidaWidth;-
2145 fe->recalcAdvances(&g, 0);-
2146-
2147 if (point->kashidaWidth == 0)
point->kashidaWidth == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2148 point->type = Justification_Prohibited;
never executed: point->type = Justification_Prohibited;
0
2149 } else {
never executed: end of block
0
2150 point->type = Justification_Prohibited;-
2151 point->kashidaWidth = 0;-
2152 }
never executed: end of block
0
2153 }-
2154}
never executed: end of block
0
2155-
2156-
2157void QTextEngine::justify(const QScriptLine &line)-
2158{-
2159// qDebug("justify: line.gridfitted = %d, line.justified=%d", line.gridfitted, line.justified);-
2160 if (line.gridfitted && line.justified)
line.gridfittedDescription
TRUEnever evaluated
FALSEnever evaluated
line.justifiedDescription
TRUEnever evaluated
FALSEnever evaluated
0
2161 return;
never executed: return;
0
2162-
2163 if (!line.gridfitted) {
!line.gridfittedDescription
TRUEnever evaluated
FALSEnever evaluated
0
2164 // redo layout in device metrics, then adjust-
2165 const_cast<QScriptLine &>(line).gridfitted = true;-
2166 }
never executed: end of block
0
2167-
2168 if ((option.alignment() & Qt::AlignHorizontal_Mask) != Qt::AlignJustify)
(option.alignm...::AlignJustifyDescription
TRUEnever evaluated
FALSEnever evaluated
0
2169 return;
never executed: return;
0
2170-
2171 itemize();-
2172-
2173 if (!forceJustification) {
!forceJustificationDescription
TRUEnever evaluated
FALSEnever evaluated
0
2174 int end = line.from + (int)line.length + line.trailingSpaces;-
2175 if (end == layoutData->string.length())
end == layoutD...tring.length()Description
TRUEnever evaluated
FALSEnever evaluated
0
2176 return; // no justification at end of paragraph
never executed: return;
0
2177 if (end && layoutData->items[findItem(end-1)].analysis.flags == QScriptAnalysis::LineOrParagraphSeparator)
endDescription
TRUEnever evaluated
FALSEnever evaluated
layoutData->it...graphSeparatorDescription
TRUEnever evaluated
FALSEnever evaluated
0
2178 return; // no justification at the end of an explicitly separated line
never executed: return;
0
2179 }
never executed: end of block
0
2180-
2181 // justify line-
2182 int maxJustify = 0;-
2183-
2184 // don't include trailing white spaces when doing justification-
2185 int line_length = line.length;-
2186 const QCharAttributes *a = attributes();-
2187 if (! a)
! aDescription
TRUEnever evaluated
FALSEnever evaluated
0
2188 return;
never executed: return;
0
2189 a += line.from;-
2190 while (line_length && a[line_length-1].whiteSpace)
line_lengthDescription
TRUEnever evaluated
FALSEnever evaluated
a[line_length-1].whiteSpaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
2191 --line_length;
never executed: --line_length;
0
2192 // subtract one char more, as we can't justfy after the last character-
2193 --line_length;-
2194-
2195 if (line_length <= 0)
line_length <= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2196 return;
never executed: return;
0
2197-
2198 int firstItem = findItem(line.from);-
2199 int lastItem = findItem(line.from + line_length - 1, firstItem);-
2200 int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0;
firstItem >= 0Description
TRUEnever evaluated
FALSEnever evaluated
lastItem >= firstItemDescription
TRUEnever evaluated
FALSEnever evaluated
0
2201-
2202 QVarLengthArray<QJustificationPoint> justificationPoints;-
2203 int nPoints = 0;-
2204// qDebug("justifying from %d len %d, firstItem=%d, nItems=%d (%s)", line.from, line_length, firstItem, nItems, layoutData->string.mid(line.from, line_length).toUtf8().constData());-
2205 QFixed minKashida = 0x100000;-
2206-
2207 // we need to do all shaping before we go into the next loop, as we there-
2208 // store pointers to the glyph data that could get reallocated by the shaping-
2209 // process.-
2210 for (int i = 0; i < nItems; ++i) {
i < nItemsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2211 QScriptItem &si = layoutData->items[firstItem + i];-
2212 if (!si.num_glyphs)
!si.num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2213 shape(firstItem + i);
never executed: shape(firstItem + i);
0
2214 }
never executed: end of block
0
2215-
2216 for (int i = 0; i < nItems; ++i) {
i < nItemsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2217 QScriptItem &si = layoutData->items[firstItem + i];-
2218-
2219 int kashida_type = Justification_Arabic_Normal;-
2220 int kashida_pos = -1;-
2221-
2222 int start = qMax(line.from - si.position, 0);-
2223 int end = qMin(line.from + line_length - (int)si.position, length(firstItem+i));-
2224-
2225 unsigned short *log_clusters = logClusters(&si);-
2226-
2227 int gs = log_clusters[start];-
2228 int ge = (end == length(firstItem+i) ? si.num_glyphs : log_clusters[end]);
end == length(firstItem+i)Description
TRUEnever evaluated
FALSEnever evaluated
0
2229-
2230 Q_ASSERT(ge <= si.num_glyphs);-
2231-
2232 const QGlyphLayout g = shapedGlyphs(&si);-
2233-
2234 for (int i = gs; i < ge; ++i) {
i < geDescription
TRUEnever evaluated
FALSEnever evaluated
0
2235 g.justifications[i].type = QGlyphJustification::JustifyNone;-
2236 g.justifications[i].nKashidas = 0;-
2237 g.justifications[i].space_18d6 = 0;-
2238-
2239 justificationPoints.resize(nPoints+3);-
2240 int justification = g.attributes[i].justification;-
2241-
2242 switch(justification) {-
2243 case Justification_Prohibited:
never executed: case Justification_Prohibited:
0
2244 break;
never executed: break;
0
2245 case Justification_Space:
never executed: case Justification_Space:
0
2246 // fall through-
2247 case Justification_Arabic_Space:
never executed: case Justification_Arabic_Space:
0
2248 if (kashida_pos >= 0) {
kashida_pos >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2249// qDebug("kashida position at %d in word", kashida_pos);-
2250 set(&justificationPoints[nPoints], kashida_type, g.mid(kashida_pos), fontEngine(si));-
2251 if (justificationPoints[nPoints].kashidaWidth > 0) {
justificationP...shidaWidth > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2252 minKashida = qMin(minKashida, justificationPoints[nPoints].kashidaWidth);-
2253 maxJustify = qMax(maxJustify, justificationPoints[nPoints].type);-
2254 ++nPoints;-
2255 }
never executed: end of block
0
2256 }
never executed: end of block
0
2257 kashida_pos = -1;-
2258 kashida_type = Justification_Arabic_Normal;-
2259 // fall through-
2260 case Justification_Character:
code before this statement never executed: case Justification_Character:
never executed: case Justification_Character:
0
2261 set(&justificationPoints[nPoints++], justification, g.mid(i), fontEngine(si));-
2262 maxJustify = qMax(maxJustify, justification);-
2263 break;
never executed: break;
0
2264 case Justification_Arabic_Normal:
never executed: case Justification_Arabic_Normal:
0
2265 case Justification_Arabic_Waw:
never executed: case Justification_Arabic_Waw:
0
2266 case Justification_Arabic_BaRa:
never executed: case Justification_Arabic_BaRa:
0
2267 case Justification_Arabic_Alef:
never executed: case Justification_Arabic_Alef:
0
2268 case Justification_Arabic_HahDal:
never executed: case Justification_Arabic_HahDal:
0
2269 case Justification_Arabic_Seen:
never executed: case Justification_Arabic_Seen:
0
2270 case Justification_Arabic_Kashida:
never executed: case Justification_Arabic_Kashida:
0
2271 if (justification >= kashida_type) {
justification >= kashida_typeDescription
TRUEnever evaluated
FALSEnever evaluated
0
2272 kashida_pos = i;-
2273 kashida_type = justification;-
2274 }
never executed: end of block
0
2275 }
never executed: end of block
0
2276 }
never executed: end of block
0
2277 if (kashida_pos >= 0) {
kashida_pos >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2278 set(&justificationPoints[nPoints], kashida_type, g.mid(kashida_pos), fontEngine(si));-
2279 if (justificationPoints[nPoints].kashidaWidth > 0) {
justificationP...shidaWidth > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2280 minKashida = qMin(minKashida, justificationPoints[nPoints].kashidaWidth);-
2281 maxJustify = qMax(maxJustify, justificationPoints[nPoints].type);-
2282 ++nPoints;-
2283 }
never executed: end of block
0
2284 }
never executed: end of block
0
2285 }
never executed: end of block
0
2286-
2287 QFixed leading = leadingSpaceWidth(line);-
2288 QFixed need = line.width - line.textWidth - leading;-
2289 if (need < 0) {
need < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2290 // line overflows already!-
2291 const_cast<QScriptLine &>(line).justified = true;-
2292 return;
never executed: return;
0
2293 }-
2294-
2295// qDebug("doing justification: textWidth=%x, requested=%x, maxJustify=%d", line.textWidth.value(), line.width.value(), maxJustify);-
2296// qDebug(" minKashida=%f, need=%f", minKashida.toReal(), need.toReal());-
2297-
2298 // distribute in priority order-
2299 if (maxJustify >= Justification_Arabic_Normal) {
maxJustify >= ..._Arabic_NormalDescription
TRUEnever evaluated
FALSEnever evaluated
0
2300 while (need >= minKashida) {
need >= minKashidaDescription
TRUEnever evaluated
FALSEnever evaluated
0
2301 for (int type = maxJustify; need >= minKashida && type >= Justification_Arabic_Normal; --type) {
need >= minKashidaDescription
TRUEnever evaluated
FALSEnever evaluated
type >= Justif..._Arabic_NormalDescription
TRUEnever evaluated
FALSEnever evaluated
0
2302 for (int i = 0; need >= minKashida && i < nPoints; ++i) {
need >= minKashidaDescription
TRUEnever evaluated
FALSEnever evaluated
i < nPointsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2303 if (justificationPoints[i].type == type && justificationPoints[i].kashidaWidth <= need) {
justificationP...].type == typeDescription
TRUEnever evaluated
FALSEnever evaluated
justificationP...aWidth <= needDescription
TRUEnever evaluated
FALSEnever evaluated
0
2304 justificationPoints[i].glyph.justifications->nKashidas++;-
2305 // ############-
2306 justificationPoints[i].glyph.justifications->space_18d6 += justificationPoints[i].kashidaWidth.value();-
2307 need -= justificationPoints[i].kashidaWidth;-
2308// qDebug("adding kashida type %d with width %x, neednow %x", type, justificationPoints[i].kashidaWidth, need.value());-
2309 }
never executed: end of block
0
2310 }
never executed: end of block
0
2311 }
never executed: end of block
0
2312 }
never executed: end of block
0
2313 }
never executed: end of block
0
2314 Q_ASSERT(need >= 0);-
2315 if (!need)
!needDescription
TRUEnever evaluated
FALSEnever evaluated
0
2316 goto end;
never executed: goto end;
0
2317-
2318 maxJustify = qMin(maxJustify, int(Justification_Space));-
2319 for (int type = maxJustify; need != 0 && type > 0; --type) {
need != 0Description
TRUEnever evaluated
FALSEnever evaluated
type > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2320 int n = 0;-
2321 for (int i = 0; i < nPoints; ++i) {
i < nPointsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2322 if (justificationPoints[i].type == type)
justificationP...].type == typeDescription
TRUEnever evaluated
FALSEnever evaluated
0
2323 ++n;
never executed: ++n;
0
2324 }
never executed: end of block
0
2325// qDebug("number of points for justification type %d: %d", type, n);-
2326-
2327-
2328 if (!n)
!nDescription
TRUEnever evaluated
FALSEnever evaluated
0
2329 continue;
never executed: continue;
0
2330-
2331 for (int i = 0; i < nPoints; ++i) {
i < nPointsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2332 if (justificationPoints[i].type == type) {
justificationP...].type == typeDescription
TRUEnever evaluated
FALSEnever evaluated
0
2333 QFixed add = need/n;-
2334// qDebug("adding %x to glyph %x", add.value(), justificationPoints[i].glyph->glyph);-
2335 justificationPoints[i].glyph.justifications[0].space_18d6 = add.value();-
2336 need -= add;-
2337 --n;-
2338 }
never executed: end of block
0
2339 }
never executed: end of block
0
2340-
2341 Q_ASSERT(!need);-
2342 }
never executed: end of block
0
2343 end:
code before this statement never executed: end:
0
2344 const_cast<QScriptLine &>(line).justified = true;-
2345}
never executed: end of block
0
2346-
2347void QScriptLine::setDefaultHeight(QTextEngine *eng)-
2348{-
2349 QFont f;-
2350 QFontEngine *e;-
2351-
2352 if (eng->block.docHandle() && eng->block.docHandle()->layout()) {
eng->block.docHandle()Description
TRUEnever evaluated
FALSEnever evaluated
eng->block.doc...le()->layout()Description
TRUEnever evaluated
FALSEnever evaluated
0
2353 f = eng->block.charFormat().font();-
2354 // Make sure we get the right dpi on printers-
2355 QPaintDevice *pdev = eng->block.docHandle()->layout()->paintDevice();-
2356 if (pdev)
pdevDescription
TRUEnever evaluated
FALSEnever evaluated
0
2357 f = QFont(f, pdev);
never executed: f = QFont(f, pdev);
0
2358 e = f.d->engineForScript(QChar::Script_Common);-
2359 } else {
never executed: end of block
0
2360 e = eng->fnt.d->engineForScript(QChar::Script_Common);-
2361 }
never executed: end of block
0
2362-
2363 QFixed other_ascent = e->ascent();-
2364 QFixed other_descent = e->descent();-
2365 QFixed other_leading = e->leading();-
2366 leading = qMax(leading + ascent, other_leading + other_ascent) - qMax(ascent, other_ascent);-
2367 ascent = qMax(ascent, other_ascent);-
2368 descent = qMax(descent, other_descent);-
2369}
never executed: end of block
0
2370-
2371QTextEngine::LayoutData::LayoutData()-
2372{-
2373 memory = 0;-
2374 allocated = 0;-
2375 memory_on_stack = false;-
2376 used = 0;-
2377 hasBidi = false;-
2378 layoutState = LayoutEmpty;-
2379 haveCharAttributes = false;-
2380 logClustersPtr = 0;-
2381 available_glyphs = 0;-
2382}
never executed: end of block
0
2383-
2384QTextEngine::LayoutData::LayoutData(const QString &str, void **stack_memory, int _allocated)-
2385 : string(str)-
2386{-
2387 allocated = _allocated;-
2388-
2389 int space_charAttributes = sizeof(QCharAttributes)*string.length()/sizeof(void*) + 1;-
2390 int space_logClusters = sizeof(unsigned short)*string.length()/sizeof(void*) + 1;-
2391 available_glyphs = ((int)allocated - space_charAttributes - space_logClusters)*(int)sizeof(void*)/(int)QGlyphLayout::SpaceNeeded;-
2392-
2393 if (available_glyphs < str.length()) {
available_glyp...< str.length()Description
TRUEnever evaluated
FALSEnever evaluated
0
2394 // need to allocate on the heap-
2395 allocated = 0;-
2396-
2397 memory_on_stack = false;-
2398 memory = 0;-
2399 logClustersPtr = 0;-
2400 } else {
never executed: end of block
0
2401 memory_on_stack = true;-
2402 memory = stack_memory;-
2403 logClustersPtr = (unsigned short *)(memory + space_charAttributes);-
2404-
2405 void *m = memory + space_charAttributes + space_logClusters;-
2406 glyphLayout = QGlyphLayout(reinterpret_cast<char *>(m), str.length());-
2407 glyphLayout.clear();-
2408 memset(memory, 0, space_charAttributes*sizeof(void *));-
2409 }
never executed: end of block
0
2410 used = 0;-
2411 hasBidi = false;-
2412 layoutState = LayoutEmpty;-
2413 haveCharAttributes = false;-
2414}
never executed: end of block
0
2415-
2416QTextEngine::LayoutData::~LayoutData()-
2417{-
2418 if (!memory_on_stack)
!memory_on_stackDescription
TRUEnever evaluated
FALSEnever evaluated
0
2419 free(memory);
never executed: free(memory);
0
2420 memory = 0;-
2421}
never executed: end of block
0
2422-
2423bool QTextEngine::LayoutData::reallocate(int totalGlyphs)-
2424{-
2425 Q_ASSERT(totalGlyphs >= glyphLayout.numGlyphs);-
2426 if (memory_on_stack && available_glyphs >= totalGlyphs) {
memory_on_stackDescription
TRUEnever evaluated
FALSEnever evaluated
available_glyp...>= totalGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2427 glyphLayout.grow(glyphLayout.data(), totalGlyphs);-
2428 return true;
never executed: return true;
0
2429 }-
2430-
2431 int space_charAttributes = sizeof(QCharAttributes)*string.length()/sizeof(void*) + 1;-
2432 int space_logClusters = sizeof(unsigned short)*string.length()/sizeof(void*) + 1;-
2433 int space_glyphs = (totalGlyphs * QGlyphLayout::SpaceNeeded) / sizeof(void *) + 2;-
2434-
2435 int newAllocated = space_charAttributes + space_glyphs + space_logClusters;-
2436 // These values can be negative if the length of string/glyphs causes overflow,-
2437 // we can't layout such a long string all at once, so return false here to-
2438 // indicate there is a failure-
2439 if (space_charAttributes < 0 || space_logClusters < 0 || space_glyphs < 0 || newAllocated < allocated) {
space_charAttributes < 0Description
TRUEnever evaluated
FALSEnever evaluated
space_logClusters < 0Description
TRUEnever evaluated
FALSEnever evaluated
space_glyphs < 0Description
TRUEnever evaluated
FALSEnever evaluated
newAllocated < allocatedDescription
TRUEnever evaluated
FALSEnever evaluated
0
2440 layoutState = LayoutFailed;-
2441 return false;
never executed: return false;
0
2442 }-
2443-
2444 void **newMem = (void **)::realloc(memory_on_stack ? 0 : memory, newAllocated*sizeof(void *));-
2445 if (!newMem) {
!newMemDescription
TRUEnever evaluated
FALSEnever evaluated
0
2446 layoutState = LayoutFailed;-
2447 return false;
never executed: return false;
0
2448 }-
2449 if (memory_on_stack)
memory_on_stackDescription
TRUEnever evaluated
FALSEnever evaluated
0
2450 memcpy(newMem, memory, allocated*sizeof(void *));
never executed: memcpy(newMem, memory, allocated*sizeof(void *));
0
2451 memory = newMem;-
2452 memory_on_stack = false;-
2453-
2454 void **m = memory;-
2455 m += space_charAttributes;-
2456 logClustersPtr = (unsigned short *) m;-
2457 m += space_logClusters;-
2458-
2459 const int space_preGlyphLayout = space_charAttributes + space_logClusters;-
2460 if (allocated < space_preGlyphLayout)
allocated < sp...preGlyphLayoutDescription
TRUEnever evaluated
FALSEnever evaluated
0
2461 memset(memory + allocated, 0, (space_preGlyphLayout - allocated)*sizeof(void *));
never executed: memset(memory + allocated, 0, (space_preGlyphLayout - allocated)*sizeof(void *));
0
2462-
2463 glyphLayout.grow(reinterpret_cast<char *>(m), totalGlyphs);-
2464-
2465 allocated = newAllocated;-
2466 return true;
never executed: return true;
0
2467}-
2468-
2469// grow to the new size, copying the existing data to the new layout-
2470void QGlyphLayout::grow(char *address, int totalGlyphs)-
2471{-
2472 QGlyphLayout oldLayout(address, numGlyphs);-
2473 QGlyphLayout newLayout(address, totalGlyphs);-
2474-
2475 if (numGlyphs) {
numGlyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2476 // move the existing data-
2477 memmove(newLayout.attributes, oldLayout.attributes, numGlyphs * sizeof(QGlyphAttributes));-
2478 memmove(newLayout.justifications, oldLayout.justifications, numGlyphs * sizeof(QGlyphJustification));-
2479 memmove(newLayout.advances, oldLayout.advances, numGlyphs * sizeof(QFixed));-
2480 memmove(newLayout.glyphs, oldLayout.glyphs, numGlyphs * sizeof(glyph_t));-
2481 }
never executed: end of block
0
2482-
2483 // clear the new data-
2484 newLayout.clear(numGlyphs);-
2485-
2486 *this = newLayout;-
2487}
never executed: end of block
0
2488-
2489void QTextEngine::freeMemory()-
2490{-
2491 if (!stackEngine) {
!stackEngineDescription
TRUEnever evaluated
FALSEnever evaluated
0
2492 delete layoutData;-
2493 layoutData = 0;-
2494 } else {
never executed: end of block
0
2495 layoutData->used = 0;-
2496 layoutData->hasBidi = false;-
2497 layoutData->layoutState = LayoutEmpty;-
2498 layoutData->haveCharAttributes = false;-
2499 layoutData->items.clear();-
2500 }
never executed: end of block
0
2501 if (specialData)
specialDataDescription
TRUEnever evaluated
FALSEnever evaluated
0
2502 specialData->resolvedFormats.clear();
never executed: specialData->resolvedFormats.clear();
0
2503 for (int i = 0; i < lines.size(); ++i) {
i < lines.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
2504 lines[i].justified = 0;-
2505 lines[i].gridfitted = 0;-
2506 }
never executed: end of block
0
2507}
never executed: end of block
0
2508-
2509int QTextEngine::formatIndex(const QScriptItem *si) const-
2510{-
2511 if (specialData && !specialData->resolvedFormats.isEmpty()) {
specialDataDescription
TRUEnever evaluated
FALSEnever evaluated
!specialData->...mats.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
2512 QTextFormatCollection *collection = formatCollection();-
2513 Q_ASSERT(collection);-
2514 return collection->indexForFormat(specialData->resolvedFormats.at(si - &layoutData->items[0]));
never executed: return collection->indexForFormat(specialData->resolvedFormats.at(si - &layoutData->items[0]));
0
2515 }-
2516-
2517 QTextDocumentPrivate *p = block.docHandle();-
2518 if (!p)
!pDescription
TRUEnever evaluated
FALSEnever evaluated
0
2519 return -1;
never executed: return -1;
0
2520 int pos = si->position;-
2521 if (specialData && si->position >= specialData->preeditPosition) {
specialDataDescription
TRUEnever evaluated
FALSEnever evaluated
si->position >...reeditPositionDescription
TRUEnever evaluated
FALSEnever evaluated
0
2522 if (si->position < specialData->preeditPosition + specialData->preeditText.length())
si->position <...tText.length()Description
TRUEnever evaluated
FALSEnever evaluated
0
2523 pos = qMax(qMin(block.length(), specialData->preeditPosition) - 1, 0);
never executed: pos = qMax(qMin(block.length(), specialData->preeditPosition) - 1, 0);
0
2524 else-
2525 pos -= specialData->preeditText.length();
never executed: pos -= specialData->preeditText.length();
0
2526 }-
2527 QTextDocumentPrivate::FragmentIterator it = p->find(block.position() + pos);-
2528 return it.value()->format;
never executed: return it.value()->format;
0
2529}-
2530-
2531-
2532QTextCharFormat QTextEngine::format(const QScriptItem *si) const-
2533{-
2534 if (const QTextFormatCollection *collection = formatCollection())
const QTextFor...atCollection()Description
TRUEnever evaluated
FALSEnever evaluated
0
2535 return collection->charFormat(formatIndex(si));
never executed: return collection->charFormat(formatIndex(si));
0
2536 return QTextCharFormat();
never executed: return QTextCharFormat();
0
2537}-
2538-
2539void QTextEngine::addRequiredBoundaries() const-
2540{-
2541 if (specialData) {
specialDataDescription
TRUEnever evaluated
FALSEnever evaluated
0
2542 for (int i = 0; i < specialData->formats.size(); ++i) {
i < specialDat...formats.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
2543 const QTextLayout::FormatRange &r = specialData->formats.at(i);-
2544 setBoundary(r.start);-
2545 setBoundary(r.start + r.length);-
2546 //qDebug("adding boundaries %d %d", r.start, r.start+r.length);-
2547 }
never executed: end of block
0
2548 }
never executed: end of block
0
2549}
never executed: end of block
0
2550-
2551bool QTextEngine::atWordSeparator(int position) const-
2552{-
2553 const QChar c = layoutData->string.at(position);-
2554 switch (c.unicode()) {-
2555 case '.':
never executed: case '.':
0
2556 case ',':
never executed: case ',':
0
2557 case '?':
never executed: case '?':
0
2558 case '!':
never executed: case '!':
0
2559 case '@':
never executed: case '@':
0
2560 case '#':
never executed: case '#':
0
2561 case '$':
never executed: case '$':
0
2562 case ':':
never executed: case ':':
0
2563 case ';':
never executed: case ';':
0
2564 case '-':
never executed: case '-':
0
2565 case '<':
never executed: case '<':
0
2566 case '>':
never executed: case '>':
0
2567 case '[':
never executed: case '[':
0
2568 case ']':
never executed: case ']':
0
2569 case '(':
never executed: case '(':
0
2570 case ')':
never executed: case ')':
0
2571 case '{':
never executed: case '{':
0
2572 case '}':
never executed: case '}':
0
2573 case '=':
never executed: case '=':
0
2574 case '/':
never executed: case '/':
0
2575 case '+':
never executed: case '+':
0
2576 case '%':
never executed: case '%':
0
2577 case '&':
never executed: case '&':
0
2578 case '^':
never executed: case '^':
0
2579 case '*':
never executed: case '*':
0
2580 case '\'':
never executed: case '\'':
0
2581 case '"':
never executed: case '"':
0
2582 case '`':
never executed: case '`':
0
2583 case '~':
never executed: case '~':
0
2584 case '|':
never executed: case '|':
0
2585 case '\\':
never executed: case '\\':
0
2586 return true;
never executed: return true;
0
2587 default:
never executed: default:
0
2588 break;
never executed: break;
0
2589 }-
2590 return false;
never executed: return false;
0
2591}-
2592-
2593void QTextEngine::setPreeditArea(int position, const QString &preeditText)-
2594{-
2595 if (preeditText.isEmpty()) {
preeditText.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
2596 if (!specialData)
!specialDataDescription
TRUEnever evaluated
FALSEnever evaluated
0
2597 return;
never executed: return;
0
2598 if (specialData->formats.isEmpty()) {
specialData->formats.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
2599 delete specialData;-
2600 specialData = 0;-
2601 } else {
never executed: end of block
0
2602 specialData->preeditText = QString();-
2603 specialData->preeditPosition = -1;-
2604 }
never executed: end of block
0
2605 } else {-
2606 if (!specialData)
!specialDataDescription
TRUEnever evaluated
FALSEnever evaluated
0
2607 specialData = new SpecialData;
never executed: specialData = new SpecialData;
0
2608 specialData->preeditPosition = position;-
2609 specialData->preeditText = preeditText;-
2610 }
never executed: end of block
0
2611 invalidate();-
2612 clearLineData();-
2613}
never executed: end of block
0
2614-
2615void QTextEngine::setFormats(const QVector<QTextLayout::FormatRange> &formats)-
2616{-
2617 if (formats.isEmpty()) {
formats.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
2618 if (!specialData)
!specialDataDescription
TRUEnever evaluated
FALSEnever evaluated
0
2619 return;
never executed: return;
0
2620 if (specialData->preeditText.isEmpty()) {
specialData->p...Text.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
2621 delete specialData;-
2622 specialData = 0;-
2623 } else {
never executed: end of block
0
2624 specialData->formats.clear();-
2625 }
never executed: end of block
0
2626 } else {-
2627 if (!specialData) {
!specialDataDescription
TRUEnever evaluated
FALSEnever evaluated
0
2628 specialData = new SpecialData;-
2629 specialData->preeditPosition = -1;-
2630 }
never executed: end of block
0
2631 specialData->formats = formats;-
2632 indexFormats();-
2633 }
never executed: end of block
0
2634 invalidate();-
2635 clearLineData();-
2636}
never executed: end of block
0
2637-
2638void QTextEngine::indexFormats()-
2639{-
2640 QTextFormatCollection *collection = formatCollection();-
2641 if (!collection) {
!collectionDescription
TRUEnever evaluated
FALSEnever evaluated
0
2642 Q_ASSERT(!block.docHandle());-
2643 specialData->formatCollection.reset(new QTextFormatCollection);-
2644 collection = specialData->formatCollection.data();-
2645 }
never executed: end of block
0
2646-
2647 // replace with shared copies-
2648 for (int i = 0; i < specialData->formats.size(); ++i) {
i < specialDat...formats.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
2649 QTextCharFormat &format = specialData->formats[i].format;-
2650 format = collection->charFormat(collection->indexForFormat(format));-
2651 }
never executed: end of block
0
2652}
never executed: end of block
0
2653-
2654/* These two helper functions are used to determine whether we need to insert a ZWJ character-
2655 between the text that gets truncated and the ellipsis. This is important to get-
2656 correctly shaped results for arabic text.-
2657*/-
2658static inline bool nextCharJoins(const QString &string, int pos)-
2659{-
2660 while (pos < string.length() && string.at(pos).category() == QChar::Mark_NonSpacing)
pos < string.length()Description
TRUEnever evaluated
FALSEnever evaluated
string.at(pos)...ark_NonSpacingDescription
TRUEnever evaluated
FALSEnever evaluated
0
2661 ++pos;
never executed: ++pos;
0
2662 if (pos == string.length())
pos == string.length()Description
TRUEnever evaluated
FALSEnever evaluated
0
2663 return false;
never executed: return false;
0
2664 QChar::JoiningType joining = string.at(pos).joiningType();-
2665 return joining != QChar::Joining_None && joining != QChar::Joining_Transparent;
never executed: return joining != QChar::Joining_None && joining != QChar::Joining_Transparent;
joining != QChar::Joining_NoneDescription
TRUEnever evaluated
FALSEnever evaluated
joining != QCh...ng_TransparentDescription
TRUEnever evaluated
FALSEnever evaluated
0
2666}-
2667-
2668static inline bool prevCharJoins(const QString &string, int pos)-
2669{-
2670 while (pos > 0 && string.at(pos - 1).category() == QChar::Mark_NonSpacing)
pos > 0Description
TRUEnever evaluated
FALSEnever evaluated
string.at(pos ...ark_NonSpacingDescription
TRUEnever evaluated
FALSEnever evaluated
0
2671 --pos;
never executed: --pos;
0
2672 if (pos == 0)
pos == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2673 return false;
never executed: return false;
0
2674 QChar::JoiningType joining = string.at(pos - 1).joiningType();-
2675 return joining == QChar::Joining_Dual || joining == QChar::Joining_Causing;
never executed: return joining == QChar::Joining_Dual || joining == QChar::Joining_Causing;
joining == QChar::Joining_DualDescription
TRUEnever evaluated
FALSEnever evaluated
joining == QCh...oining_CausingDescription
TRUEnever evaluated
FALSEnever evaluated
0
2676}-
2677-
2678static inline bool isRetainableControlCode(QChar c)-
2679{-
2680 return (c.unicode() >= 0x202a && c.unicode() <= 0x202e) // LRE, RLE, PDF, LRO, RLO
never executed: return (c.unicode() >= 0x202a && c.unicode() <= 0x202e) || (c.unicode() >= 0x200e && c.unicode() <= 0x200f) || (c.unicode() >= 0x2066 && c.unicode() <= 0x2069);
c.unicode() >= 0x202aDescription
TRUEnever evaluated
FALSEnever evaluated
c.unicode() <= 0x202eDescription
TRUEnever evaluated
FALSEnever evaluated
0
2681 || (c.unicode() >= 0x200e && c.unicode() <= 0x200f) // LRM, RLM
never executed: return (c.unicode() >= 0x202a && c.unicode() <= 0x202e) || (c.unicode() >= 0x200e && c.unicode() <= 0x200f) || (c.unicode() >= 0x2066 && c.unicode() <= 0x2069);
c.unicode() >= 0x200eDescription
TRUEnever evaluated
FALSEnever evaluated
c.unicode() <= 0x200fDescription
TRUEnever evaluated
FALSEnever evaluated
0
2682 || (c.unicode() >= 0x2066 && c.unicode() <= 0x2069); // LRM, RLM
never executed: return (c.unicode() >= 0x202a && c.unicode() <= 0x202e) || (c.unicode() >= 0x200e && c.unicode() <= 0x200f) || (c.unicode() >= 0x2066 && c.unicode() <= 0x2069);
c.unicode() >= 0x2066Description
TRUEnever evaluated
FALSEnever evaluated
c.unicode() <= 0x2069Description
TRUEnever evaluated
FALSEnever evaluated
0
2683}-
2684-
2685static QString stringMidRetainingBidiCC(const QString &string,-
2686 const QString &ellidePrefix,-
2687 const QString &ellideSuffix,-
2688 int subStringFrom,-
2689 int subStringTo,-
2690 int midStart,-
2691 int midLength)-
2692{-
2693 QString prefix;-
2694 for (int i=subStringFrom; i<midStart; ++i) {
i<midStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
2695 QChar c = string.at(i);-
2696 if (isRetainableControlCode(c))
isRetainableControlCode(c)Description
TRUEnever evaluated
FALSEnever evaluated
0
2697 prefix += c;
never executed: prefix += c;
0
2698 }
never executed: end of block
0
2699-
2700 QString suffix;-
2701 for (int i=midStart + midLength; i<subStringTo; ++i) {
i<subStringToDescription
TRUEnever evaluated
FALSEnever evaluated
0
2702 QChar c = string.at(i);-
2703 if (isRetainableControlCode(c))
isRetainableControlCode(c)Description
TRUEnever evaluated
FALSEnever evaluated
0
2704 suffix += c;
never executed: suffix += c;
0
2705 }
never executed: end of block
0
2706-
2707 return prefix + ellidePrefix + string.mid(midStart, midLength) + ellideSuffix + suffix;
never executed: return prefix + ellidePrefix + string.mid(midStart, midLength) + ellideSuffix + suffix;
0
2708}-
2709-
2710QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int flags, int from, int count) const-
2711{-
2712// qDebug() << "elidedText; available width" << width.toReal() << "text width:" << this->width(0, layoutData->string.length()).toReal();-
2713-
2714 if (flags & Qt::TextShowMnemonic) {
flags & Qt::TextShowMnemonicDescription
TRUEnever evaluated
FALSEnever evaluated
0
2715 itemize();-
2716 QCharAttributes *attributes = const_cast<QCharAttributes *>(this->attributes());-
2717 if (!attributes)
!attributesDescription
TRUEnever evaluated
FALSEnever evaluated
0
2718 return QString();
never executed: return QString();
0
2719 for (int i = 0; i < layoutData->items.size(); ++i) {
i < layoutData->items.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
2720 QScriptItem &si = layoutData->items[i];-
2721 if (!si.num_glyphs)
!si.num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
2722 shape(i);
never executed: shape(i);
0
2723-
2724 unsigned short *logClusters = this->logClusters(&si);-
2725 QGlyphLayout glyphs = shapedGlyphs(&si);-
2726-
2727 const int end = si.position + length(&si);-
2728 for (int i = si.position; i < end - 1; ++i) {
i < end - 1Description
TRUEnever evaluated
FALSEnever evaluated
0
2729 if (layoutData->string.at(i) == QLatin1Char('&')
layoutData->st...atin1Char('&')Description
TRUEnever evaluated
FALSEnever evaluated
0
2730 && !attributes[i + 1].whiteSpace && attributes[i + 1].graphemeBoundary) {
!attributes[i + 1].whiteSpaceDescription
TRUEnever evaluated
FALSEnever evaluated
attributes[i +...aphemeBoundaryDescription
TRUEnever evaluated
FALSEnever evaluated
0
2731 const int gp = logClusters[i - si.position];-
2732 glyphs.attributes[gp].dontPrint = true;-
2733 // emulate grapheme cluster-
2734 attributes[i] = attributes[i + 1];-
2735 memset(attributes + i + 1, 0, sizeof(QCharAttributes));-
2736 if (layoutData->string.at(i + 1) == QLatin1Char('&'))
layoutData->st...atin1Char('&')Description
TRUEnever evaluated
FALSEnever evaluated
0
2737 ++i;
never executed: ++i;
0
2738 }
never executed: end of block
0
2739 }
never executed: end of block
0
2740 }
never executed: end of block
0
2741 }
never executed: end of block
0
2742-
2743 validate();-
2744-
2745 const int to = count >= 0 && count <= layoutData->string.length() - from
count >= 0Description
TRUEnever evaluated
FALSEnever evaluated
count <= layou...ength() - fromDescription
TRUEnever evaluated
FALSEnever evaluated
0
2746 ? from + count-
2747 : layoutData->string.length();-
2748-
2749 if (mode == Qt::ElideNone
mode == Qt::ElideNoneDescription
TRUEnever evaluated
FALSEnever evaluated
0
2750 || this->width(from, layoutData->string.length()) <= width
this->width(fr...th()) <= widthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2751 || to - from <= 1)
to - from <= 1Description
TRUEnever evaluated
FALSEnever evaluated
0
2752 return layoutData->string.mid(from, from - to);
never executed: return layoutData->string.mid(from, from - to);
0
2753-
2754 QFixed ellipsisWidth;-
2755 QString ellipsisText;-
2756 {-
2757 QFontEngine *engine = fnt.d->engineForScript(QChar::Script_Common);-
2758-
2759 QChar ellipsisChar(0x2026);-
2760-
2761 glyph_t glyph = engine->glyphIndex(ellipsisChar.unicode());-
2762-
2763 QGlyphLayout glyphs;-
2764 glyphs.numGlyphs = 1;-
2765 glyphs.glyphs = &glyph;-
2766 glyphs.advances = &ellipsisWidth;-
2767-
2768 if (glyph != 0) {
glyph != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2769 engine->recalcAdvances(&glyphs, 0);-
2770-
2771 ellipsisText = ellipsisChar;-
2772 } else {
never executed: end of block
0
2773 glyph = engine->glyphIndex('.');-
2774 if (glyph != 0) {
glyph != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2775 engine->recalcAdvances(&glyphs, 0);-
2776-
2777 ellipsisWidth *= 3;-
2778 ellipsisText = QStringLiteral("...");
never executed: return qstring_literal_temp;
0
2779 }
never executed: end of block
0
2780 }
never executed: end of block
0
2781 }-
2782-
2783 const QFixed availableWidth = width - ellipsisWidth;-
2784 if (availableWidth < 0)
availableWidth < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2785 return QString();
never executed: return QString();
0
2786-
2787 const QCharAttributes *attributes = this->attributes();-
2788 if (!attributes)
!attributesDescription
TRUEnever evaluated
FALSEnever evaluated
0
2789 return QString();
never executed: return QString();
0
2790-
2791 if (mode == Qt::ElideRight) {
mode == Qt::ElideRightDescription
TRUEnever evaluated
FALSEnever evaluated
0
2792 QFixed currentWidth;-
2793 int pos;-
2794 int nextBreak = from;-
2795-
2796 do {-
2797 pos = nextBreak;-
2798-
2799 ++nextBreak;-
2800 while (nextBreak < layoutData->string.length() && !attributes[nextBreak].graphemeBoundary)
nextBreak < la...tring.length()Description
TRUEnever evaluated
FALSEnever evaluated
!attributes[ne...aphemeBoundaryDescription
TRUEnever evaluated
FALSEnever evaluated
0
2801 ++nextBreak;
never executed: ++nextBreak;
0
2802-
2803 currentWidth += this->width(pos, nextBreak - pos);-
2804 } while (nextBreak < to
never executed: end of block
nextBreak < toDescription
TRUEnever evaluated
FALSEnever evaluated
0
2805 && currentWidth < availableWidth);
currentWidth < availableWidthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2806-
2807 if (nextCharJoins(layoutData->string, pos))
nextCharJoins(...->string, pos)Description
TRUEnever evaluated
FALSEnever evaluated
0
2808 ellipsisText.prepend(QChar(0x200d) /* ZWJ */);
never executed: ellipsisText.prepend(QChar(0x200d) );
0
2809-
2810 return stringMidRetainingBidiCC(layoutData->string,
never executed: return stringMidRetainingBidiCC(layoutData->string, QString(), ellipsisText, from, to, from, pos - from);
0
2811 QString(), ellipsisText,
never executed: return stringMidRetainingBidiCC(layoutData->string, QString(), ellipsisText, from, to, from, pos - from);
0
2812 from, to,
never executed: return stringMidRetainingBidiCC(layoutData->string, QString(), ellipsisText, from, to, from, pos - from);
0
2813 from, pos - from);
never executed: return stringMidRetainingBidiCC(layoutData->string, QString(), ellipsisText, from, to, from, pos - from);
0
2814 } else if (mode == Qt::ElideLeft) {
mode == Qt::ElideLeftDescription
TRUEnever evaluated
FALSEnever evaluated
0
2815 QFixed currentWidth;-
2816 int pos;-
2817 int nextBreak = to;-
2818-
2819 do {-
2820 pos = nextBreak;-
2821-
2822 --nextBreak;-
2823 while (nextBreak > 0 && !attributes[nextBreak].graphemeBoundary)
nextBreak > 0Description
TRUEnever evaluated
FALSEnever evaluated
!attributes[ne...aphemeBoundaryDescription
TRUEnever evaluated
FALSEnever evaluated
0
2824 --nextBreak;
never executed: --nextBreak;
0
2825-
2826 currentWidth += this->width(nextBreak, pos - nextBreak);-
2827 } while (nextBreak > from
never executed: end of block
nextBreak > fromDescription
TRUEnever evaluated
FALSEnever evaluated
0
2828 && currentWidth < availableWidth);
currentWidth < availableWidthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2829-
2830 if (prevCharJoins(layoutData->string, pos))
prevCharJoins(...->string, pos)Description
TRUEnever evaluated
FALSEnever evaluated
0
2831 ellipsisText.append(QChar(0x200d) /* ZWJ */);
never executed: ellipsisText.append(QChar(0x200d) );
0
2832-
2833 return stringMidRetainingBidiCC(layoutData->string,
never executed: return stringMidRetainingBidiCC(layoutData->string, ellipsisText, QString(), from, to, pos, to - pos);
0
2834 ellipsisText, QString(),
never executed: return stringMidRetainingBidiCC(layoutData->string, ellipsisText, QString(), from, to, pos, to - pos);
0
2835 from, to,
never executed: return stringMidRetainingBidiCC(layoutData->string, ellipsisText, QString(), from, to, pos, to - pos);
0
2836 pos, to - pos);
never executed: return stringMidRetainingBidiCC(layoutData->string, ellipsisText, QString(), from, to, pos, to - pos);
0
2837 } else if (mode == Qt::ElideMiddle) {
mode == Qt::ElideMiddleDescription
TRUEnever evaluated
FALSEnever evaluated
0
2838 QFixed leftWidth;-
2839 QFixed rightWidth;-
2840-
2841 int leftPos = from;-
2842 int nextLeftBreak = from;-
2843-
2844 int rightPos = to;-
2845 int nextRightBreak = to;-
2846-
2847 do {-
2848 leftPos = nextLeftBreak;-
2849 rightPos = nextRightBreak;-
2850-
2851 ++nextLeftBreak;-
2852 while (nextLeftBreak < layoutData->string.length() && !attributes[nextLeftBreak].graphemeBoundary)
nextLeftBreak ...tring.length()Description
TRUEnever evaluated
FALSEnever evaluated
!attributes[ne...aphemeBoundaryDescription
TRUEnever evaluated
FALSEnever evaluated
0
2853 ++nextLeftBreak;
never executed: ++nextLeftBreak;
0
2854-
2855 --nextRightBreak;-
2856 while (nextRightBreak > from && !attributes[nextRightBreak].graphemeBoundary)
nextRightBreak > fromDescription
TRUEnever evaluated
FALSEnever evaluated
!attributes[ne...aphemeBoundaryDescription
TRUEnever evaluated
FALSEnever evaluated
0
2857 --nextRightBreak;
never executed: --nextRightBreak;
0
2858-
2859 leftWidth += this->width(leftPos, nextLeftBreak - leftPos);-
2860 rightWidth += this->width(nextRightBreak, rightPos - nextRightBreak);-
2861 } while (nextLeftBreak < to
never executed: end of block
nextLeftBreak < toDescription
TRUEnever evaluated
FALSEnever evaluated
0
2862 && nextRightBreak > from
nextRightBreak > fromDescription
TRUEnever evaluated
FALSEnever evaluated
0
2863 && leftWidth + rightWidth < availableWidth);
leftWidth + ri...availableWidthDescription
TRUEnever evaluated
FALSEnever evaluated
0
2864-
2865 if (nextCharJoins(layoutData->string, leftPos))
nextCharJoins(...ring, leftPos)Description
TRUEnever evaluated
FALSEnever evaluated
0
2866 ellipsisText.prepend(QChar(0x200d) /* ZWJ */);
never executed: ellipsisText.prepend(QChar(0x200d) );
0
2867 if (prevCharJoins(layoutData->string, rightPos))
prevCharJoins(...ing, rightPos)Description
TRUEnever evaluated
FALSEnever evaluated
0
2868 ellipsisText.append(QChar(0x200d) /* ZWJ */);
never executed: ellipsisText.append(QChar(0x200d) );
0
2869-
2870 return layoutData->string.mid(from, leftPos - from) + ellipsisText + layoutData->string.mid(rightPos, to - rightPos);
never executed: return layoutData->string.mid(from, leftPos - from) + ellipsisText + layoutData->string.mid(rightPos, to - rightPos);
0
2871 }-
2872-
2873 return layoutData->string.mid(from, to - from);
never executed: return layoutData->string.mid(from, to - from);
0
2874}-
2875-
2876void QTextEngine::setBoundary(int strPos) const-
2877{-
2878 const int item = findItem(strPos);-
2879 if (item < 0)
item < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2880 return;
never executed: return;
0
2881-
2882 QScriptItem newItem = layoutData->items.at(item);-
2883 if (newItem.position != strPos) {
newItem.position != strPosDescription
TRUEnever evaluated
FALSEnever evaluated
0
2884 newItem.position = strPos;-
2885 layoutData->items.insert(item + 1, newItem);-
2886 }
never executed: end of block
0
2887}
never executed: end of block
0
2888-
2889QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const-
2890{-
2891 const QScriptItem &si = layoutData->items[item];-
2892-
2893 QFixed dpiScale = 1;-
2894 if (block.docHandle() && block.docHandle()->layout()) {
block.docHandle()Description
TRUEnever evaluated
FALSEnever evaluated
block.docHandle()->layout()Description
TRUEnever evaluated
FALSEnever evaluated
0
2895 QPaintDevice *pdev = block.docHandle()->layout()->paintDevice();-
2896 if (pdev)
pdevDescription
TRUEnever evaluated
FALSEnever evaluated
0
2897 dpiScale = QFixed::fromReal(pdev->logicalDpiY() / qreal(qt_defaultDpiY()));
never executed: dpiScale = QFixed::fromReal(pdev->logicalDpiY() / qreal(qt_defaultDpiY()));
0
2898 } else {
never executed: end of block
0
2899 dpiScale = QFixed::fromReal(fnt.d->dpi / qreal(qt_defaultDpiY()));-
2900 }
never executed: end of block
0
2901-
2902 QList<QTextOption::Tab> tabArray = option.tabs();-
2903 if (!tabArray.isEmpty()) {
!tabArray.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
2904 if (isRightToLeft()) { // rebase the tabArray positions.
isRightToLeft()Description
TRUEnever evaluated
FALSEnever evaluated
0
2905 QList<QTextOption::Tab> newTabs;-
2906 newTabs.reserve(tabArray.count());-
2907 QList<QTextOption::Tab>::Iterator iter = tabArray.begin();-
2908 while(iter != tabArray.end()) {
iter != tabArray.end()Description
TRUEnever evaluated
FALSEnever evaluated
0
2909 QTextOption::Tab tab = *iter;-
2910 if (tab.type == QTextOption::LeftTab)
tab.type == QT...ption::LeftTabDescription
TRUEnever evaluated
FALSEnever evaluated
0
2911 tab.type = QTextOption::RightTab;
never executed: tab.type = QTextOption::RightTab;
0
2912 else if (tab.type == QTextOption::RightTab)
tab.type == QT...tion::RightTabDescription
TRUEnever evaluated
FALSEnever evaluated
0
2913 tab.type = QTextOption::LeftTab;
never executed: tab.type = QTextOption::LeftTab;
0
2914 newTabs << tab;-
2915 ++iter;-
2916 }
never executed: end of block
0
2917 tabArray = newTabs;-
2918 }
never executed: end of block
0
2919 for (int i = 0; i < tabArray.size(); ++i) {
i < tabArray.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
2920 QFixed tab = QFixed::fromReal(tabArray[i].position) * dpiScale;-
2921 if (tab > x) { // this is the tab we need.
tab > xDescription
TRUEnever evaluated
FALSEnever evaluated
0
2922 QTextOption::Tab tabSpec = tabArray[i];-
2923 int tabSectionEnd = layoutData->string.count();-
2924 if (tabSpec.type == QTextOption::RightTab || tabSpec.type == QTextOption::CenterTab) {
tabSpec.type =...tion::RightTabDescription
TRUEnever evaluated
FALSEnever evaluated
tabSpec.type =...ion::CenterTabDescription
TRUEnever evaluated
FALSEnever evaluated
0
2925 // find next tab to calculate the width required.-
2926 tab = QFixed::fromReal(tabSpec.position);-
2927 for (int i=item + 1; i < layoutData->items.count(); i++) {
i < layoutData->items.count()Description
TRUEnever evaluated
FALSEnever evaluated
0
2928 const QScriptItem &item = layoutData->items[i];-
2929 if (item.analysis.flags == QScriptAnalysis::TabOrObject) { // found it.
item.analysis....s::TabOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
2930 tabSectionEnd = item.position;-
2931 break;
never executed: break;
0
2932 }-
2933 }
never executed: end of block
0
2934 }
never executed: end of block
0
2935 else if (tabSpec.type == QTextOption::DelimiterTab)
tabSpec.type =...::DelimiterTabDescription
TRUEnever evaluated
FALSEnever evaluated
0
2936 // find delimitor character to calculate the width required-
2937 tabSectionEnd = qMax(si.position, layoutData->string.indexOf(tabSpec.delimiter, si.position) + 1);
never executed: tabSectionEnd = qMax(si.position, layoutData->string.indexOf(tabSpec.delimiter, si.position) + 1);
0
2938-
2939 if (tabSectionEnd > si.position) {
tabSectionEnd > si.positionDescription
TRUEnever evaluated
FALSEnever evaluated
0
2940 QFixed length;-
2941 // Calculate the length of text between this tab and the tabSectionEnd-
2942 for (int i=item; i < layoutData->items.count(); i++) {
i < layoutData->items.count()Description
TRUEnever evaluated
FALSEnever evaluated
0
2943 QScriptItem &item = layoutData->items[i];-
2944 if (item.position > tabSectionEnd || item.position <= si.position)
item.position > tabSectionEndDescription
TRUEnever evaluated
FALSEnever evaluated
item.position <= si.positionDescription
TRUEnever evaluated
FALSEnever evaluated
0
2945 continue;
never executed: continue;
0
2946 shape(i); // first, lets make sure relevant text is already shaped-
2947 if (item.analysis.flags == QScriptAnalysis::Object) {
item.analysis....alysis::ObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
2948 length += item.width;-
2949 continue;
never executed: continue;
0
2950 }-
2951 QGlyphLayout glyphs = this->shapedGlyphs(&item);-
2952 const int end = qMin(item.position + item.num_glyphs, tabSectionEnd) - item.position;-
2953 for (int i=0; i < end; i++)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
2954 length += glyphs.advances[i] * !glyphs.attributes[i].dontPrint;
never executed: length += glyphs.advances[i] * !glyphs.attributes[i].dontPrint;
0
2955 if (end + item.position == tabSectionEnd && tabSpec.type == QTextOption::DelimiterTab) // remove half of matching char
end + item.pos... tabSectionEndDescription
TRUEnever evaluated
FALSEnever evaluated
tabSpec.type =...::DelimiterTabDescription
TRUEnever evaluated
FALSEnever evaluated
0
2956 length -= glyphs.advances[end] / 2 * !glyphs.attributes[end].dontPrint;
never executed: length -= glyphs.advances[end] / 2 * !glyphs.attributes[end].dontPrint;
0
2957 }
never executed: end of block
0
2958-
2959 switch (tabSpec.type) {-
2960 case QTextOption::CenterTab:
never executed: case QTextOption::CenterTab:
0
2961 length /= 2;-
2962 // fall through-
2963 case QTextOption::DelimiterTab:
code before this statement never executed: case QTextOption::DelimiterTab:
never executed: case QTextOption::DelimiterTab:
0
2964 // fall through-
2965 case QTextOption::RightTab:
never executed: case QTextOption::RightTab:
0
2966 tab = QFixed::fromReal(tabSpec.position) * dpiScale - length;-
2967 if (tab < x) // default to tab taking no space
tab < xDescription
TRUEnever evaluated
FALSEnever evaluated
0
2968 return QFixed();
never executed: return QFixed();
0
2969 break;
never executed: break;
0
2970 case QTextOption::LeftTab:
never executed: case QTextOption::LeftTab:
0
2971 break;
never executed: break;
0
2972 }-
2973 }
never executed: end of block
0
2974 return tab - x;
never executed: return tab - x;
0
2975 }-
2976 }
never executed: end of block
0
2977 }
never executed: end of block
0
2978 QFixed tab = QFixed::fromReal(option.tabStop());-
2979 if (tab <= 0)
tab <= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
2980 tab = 80; // default
never executed: tab = 80;
0
2981 tab *= dpiScale;-
2982 QFixed nextTabPos = ((x / tab).truncate() + 1) * tab;-
2983 QFixed tabWidth = nextTabPos - x;-
2984-
2985 return tabWidth;
never executed: return tabWidth;
0
2986}-
2987-
2988namespace {-
2989class FormatRangeComparatorByStart {-
2990 const QVector<QTextLayout::FormatRange> &list;-
2991public:-
2992 FormatRangeComparatorByStart(const QVector<QTextLayout::FormatRange> &list) : list(list) { }
never executed: end of block
0
2993 bool operator()(int a, int b) {-
2994 return list.at(a).start < list.at(b).start;
never executed: return list.at(a).start < list.at(b).start;
0
2995 }-
2996};-
2997class FormatRangeComparatorByEnd {-
2998 const QVector<QTextLayout::FormatRange> &list;-
2999public:-
3000 FormatRangeComparatorByEnd(const QVector<QTextLayout::FormatRange> &list) : list(list) { }
never executed: end of block
0
3001 bool operator()(int a, int b) {-
3002 return list.at(a).start + list.at(a).length < list.at(b).start + list.at(b).length;
never executed: return list.at(a).start + list.at(a).length < list.at(b).start + list.at(b).length;
0
3003 }-
3004};-
3005}-
3006-
3007void QTextEngine::resolveFormats() const-
3008{-
3009 if (!specialData || specialData->formats.isEmpty())
!specialDataDescription
TRUEnever evaluated
FALSEnever evaluated
specialData->formats.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
3010 return;
never executed: return;
0
3011 Q_ASSERT(specialData->resolvedFormats.isEmpty());-
3012-
3013 QTextFormatCollection *collection = formatCollection();-
3014-
3015 QVector<QTextCharFormat> resolvedFormats(layoutData->items.count());-
3016-
3017 QVarLengthArray<int, 64> formatsSortedByStart;-
3018 formatsSortedByStart.reserve(specialData->formats.size());-
3019 for (int i = 0; i < specialData->formats.size(); ++i) {
i < specialDat...formats.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
3020 if (specialData->formats.at(i).length >= 0)
specialData->f...i).length >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
3021 formatsSortedByStart.append(i);
never executed: formatsSortedByStart.append(i);
0
3022 }
never executed: end of block
0
3023 QVarLengthArray<int, 64> formatsSortedByEnd = formatsSortedByStart;-
3024 std::sort(formatsSortedByStart.begin(), formatsSortedByStart.end(),-
3025 FormatRangeComparatorByStart(specialData->formats));-
3026 std::sort(formatsSortedByEnd.begin(), formatsSortedByEnd.end(),-
3027 FormatRangeComparatorByEnd(specialData->formats));-
3028-
3029 QVarLengthArray<int, 16> currentFormats;-
3030 const int *startIt = formatsSortedByStart.constBegin();-
3031 const int *endIt = formatsSortedByEnd.constBegin();-
3032-
3033 for (int i = 0; i < layoutData->items.count(); ++i) {
i < layoutData->items.count()Description
TRUEnever evaluated
FALSEnever evaluated
0
3034 const QScriptItem *si = &layoutData->items.at(i);-
3035 int end = si->position + length(si);-
3036-
3037 while (startIt != formatsSortedByStart.constEnd() &&
startIt != for...art.constEnd()Description
TRUEnever evaluated
FALSEnever evaluated
0
3038 specialData->formats.at(*startIt).start <= si->position) {
specialData->f...= si->positionDescription
TRUEnever evaluated
FALSEnever evaluated
0
3039 currentFormats.insert(std::upper_bound(currentFormats.begin(), currentFormats.end(), *startIt),-
3040 *startIt);-
3041 ++startIt;-
3042 }
never executed: end of block
0
3043 while (endIt != formatsSortedByEnd.constEnd() &&
endIt != forma...End.constEnd()Description
TRUEnever evaluated
FALSEnever evaluated
0
3044 specialData->formats.at(*endIt).start + specialData->formats.at(*endIt).length < end) {
specialData->f...).length < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
3045 int *currentFormatIterator = std::lower_bound(currentFormats.begin(), currentFormats.end(), *endIt);-
3046 if (*endIt < *currentFormatIterator)
*endIt < *curr...FormatIteratorDescription
TRUEnever evaluated
FALSEnever evaluated
0
3047 currentFormatIterator = currentFormats.end();
never executed: currentFormatIterator = currentFormats.end();
0
3048 currentFormats.remove(currentFormatIterator - currentFormats.begin());-
3049 ++endIt;-
3050 }
never executed: end of block
0
3051-
3052 QTextCharFormat &format = resolvedFormats[i];-
3053 if (block.docHandle()) {
block.docHandle()Description
TRUEnever evaluated
FALSEnever evaluated
0
3054 // when we have a docHandle, formatIndex might still return a valid index based-
3055 // on the preeditPosition. for all other cases, we cleared the resolved format indices-
3056 format = collection->charFormat(formatIndex(si));-
3057 }
never executed: end of block
0
3058 if (!currentFormats.isEmpty()) {
!currentFormats.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
3059 foreach (int cur, currentFormats) {-
3060 const QTextLayout::FormatRange &range = specialData->formats.at(cur);-
3061 Q_ASSERT(range.start <= si->position && range.start + range.length >= end);-
3062 format.merge(range.format);-
3063 }
never executed: end of block
0
3064 format = collection->charFormat(collection->indexForFormat(format)); // get shared copy-
3065 }
never executed: end of block
0
3066 }
never executed: end of block
0
3067-
3068 specialData->resolvedFormats = resolvedFormats;-
3069}
never executed: end of block
0
3070-
3071QFixed QTextEngine::leadingSpaceWidth(const QScriptLine &line)-
3072{-
3073 if (!line.hasTrailingSpaces
!line.hasTrailingSpacesDescription
TRUEnever evaluated
FALSEnever evaluated
0
3074 || (option.flags() & QTextOption::IncludeTrailingSpaces)
(option.flags(...railingSpaces)Description
TRUEnever evaluated
FALSEnever evaluated
0
3075 || !isRightToLeft())
!isRightToLeft()Description
TRUEnever evaluated
FALSEnever evaluated
0
3076 return QFixed();
never executed: return QFixed();
0
3077-
3078 return width(line.from + line.length, line.trailingSpaces);
never executed: return width(line.from + line.length, line.trailingSpaces);
0
3079}-
3080-
3081QFixed QTextEngine::alignLine(const QScriptLine &line)-
3082{-
3083 QFixed x = 0;-
3084 justify(line);-
3085 // if width is QFIXED_MAX that means we used setNumColumns() and that implicitly makes this line left aligned.-
3086 if (!line.justified && line.width != QFIXED_MAX) {
!line.justifiedDescription
TRUEnever evaluated
FALSEnever evaluated
line.width != (2147483647/256)Description
TRUEnever evaluated
FALSEnever evaluated
0
3087 int align = option.alignment();-
3088 if (align & Qt::AlignJustify && isRightToLeft())
align & Qt::AlignJustifyDescription
TRUEnever evaluated
FALSEnever evaluated
isRightToLeft()Description
TRUEnever evaluated
FALSEnever evaluated
0
3089 align = Qt::AlignRight;
never executed: align = Qt::AlignRight;
0
3090 if (align & Qt::AlignRight)
align & Qt::AlignRightDescription
TRUEnever evaluated
FALSEnever evaluated
0
3091 x = line.width - (line.textAdvance);
never executed: x = line.width - (line.textAdvance);
0
3092 else if (align & Qt::AlignHCenter)
align & Qt::AlignHCenterDescription
TRUEnever evaluated
FALSEnever evaluated
0
3093 x = (line.width - line.textAdvance)/2;
never executed: x = (line.width - line.textAdvance)/2;
0
3094 }
never executed: end of block
0
3095 return x;
never executed: return x;
0
3096}-
3097-
3098QFixed QTextEngine::offsetInLigature(const QScriptItem *si, int pos, int max, int glyph_pos)-
3099{-
3100 unsigned short *logClusters = this->logClusters(si);-
3101 const QGlyphLayout &glyphs = shapedGlyphs(si);-
3102-
3103 int offsetInCluster = 0;-
3104 for (int i = pos - 1; i >= 0; i--) {
i >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
3105 if (logClusters[i] == glyph_pos)
logClusters[i] == glyph_posDescription
TRUEnever evaluated
FALSEnever evaluated
0
3106 offsetInCluster++;
never executed: offsetInCluster++;
0
3107 else-
3108 break;
never executed: break;
0
3109 }-
3110-
3111 // in the case that the offset is inside a (multi-character) glyph,-
3112 // interpolate the position.-
3113 if (offsetInCluster > 0) {
offsetInCluster > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
3114 int clusterLength = 0;-
3115 for (int i = pos - offsetInCluster; i < max; i++) {
i < maxDescription
TRUEnever evaluated
FALSEnever evaluated
0
3116 if (logClusters[i] == glyph_pos)
logClusters[i] == glyph_posDescription
TRUEnever evaluated
FALSEnever evaluated
0
3117 clusterLength++;
never executed: clusterLength++;
0
3118 else-
3119 break;
never executed: break;
0
3120 }-
3121 if (clusterLength)
clusterLengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
3122 return glyphs.advances[glyph_pos] * offsetInCluster / clusterLength;
never executed: return glyphs.advances[glyph_pos] * offsetInCluster / clusterLength;
0
3123 }
never executed: end of block
0
3124-
3125 return 0;
never executed: return 0;
0
3126}-
3127-
3128// Scan in logClusters[from..to-1] for glyph_pos-
3129int QTextEngine::getClusterLength(unsigned short *logClusters,-
3130 const QCharAttributes *attributes,-
3131 int from, int to, int glyph_pos, int *start)-
3132{-
3133 int clusterLength = 0;-
3134 for (int i = from; i < to; i++) {
i < toDescription
TRUEnever evaluated
FALSEnever evaluated
0
3135 if (logClusters[i] == glyph_pos && attributes[i].graphemeBoundary) {
logClusters[i] == glyph_posDescription
TRUEnever evaluated
FALSEnever evaluated
attributes[i].graphemeBoundaryDescription
TRUEnever evaluated
FALSEnever evaluated
0
3136 if (*start < 0)
*start < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
3137 *start = i;
never executed: *start = i;
0
3138 clusterLength++;-
3139 }
never executed: end of block
0
3140 else if (clusterLength)
clusterLengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
3141 break;
never executed: break;
0
3142 }
never executed: end of block
0
3143 return clusterLength;
never executed: return clusterLength;
0
3144}-
3145-
3146int QTextEngine::positionInLigature(const QScriptItem *si, int end,-
3147 QFixed x, QFixed edge, int glyph_pos,-
3148 bool cursorOnCharacter)-
3149{-
3150 unsigned short *logClusters = this->logClusters(si);-
3151 int clusterStart = -1;-
3152 int clusterLength = 0;-
3153-
3154 if (si->analysis.script != QChar::Script_Common &&
si->analysis.s...:Script_CommonDescription
TRUEnever evaluated
FALSEnever evaluated
0
3155 si->analysis.script != QChar::Script_Greek) {
si->analysis.s...::Script_GreekDescription
TRUEnever evaluated
FALSEnever evaluated
0
3156 if (glyph_pos == -1)
glyph_pos == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
3157 return si->position + end;
never executed: return si->position + end;
0
3158 else {-
3159 int i;-
3160 for (i = 0; i < end; i++)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
3161 if (logClusters[i] == glyph_pos)
logClusters[i] == glyph_posDescription
TRUEnever evaluated
FALSEnever evaluated
0
3162 break;
never executed: break;
0
3163 return si->position + i;
never executed: return si->position + i;
0
3164 }-
3165 }-
3166-
3167 if (glyph_pos == -1 && end > 0)
glyph_pos == -1Description
TRUEnever evaluated
FALSEnever evaluated
end > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
3168 glyph_pos = logClusters[end - 1];
never executed: glyph_pos = logClusters[end - 1];
0
3169 else {-
3170 if (x <= edge)
x <= edgeDescription
TRUEnever evaluated
FALSEnever evaluated
0
3171 glyph_pos--;
never executed: glyph_pos--;
0
3172 }
never executed: end of block
0
3173-
3174 const QCharAttributes *attrs = attributes() + si->position;-
3175 logClusters = this->logClusters(si);-
3176 clusterLength = getClusterLength(logClusters, attrs, 0, end, glyph_pos, &clusterStart);-
3177-
3178 if (clusterLength) {
clusterLengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
3179 const QGlyphLayout &glyphs = shapedGlyphs(si);-
3180 QFixed glyphWidth = glyphs.effectiveAdvance(glyph_pos);-
3181 // the approximate width of each individual element of the ligature-
3182 QFixed perItemWidth = glyphWidth / clusterLength;-
3183 if (perItemWidth <= 0)
perItemWidth <= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
3184 return si->position + clusterStart;
never executed: return si->position + clusterStart;
0
3185 QFixed left = x > edge ? edge : edge - glyphWidth;
x > edgeDescription
TRUEnever evaluated
FALSEnever evaluated
0
3186 int n = ((x - left) / perItemWidth).floor().toInt();-
3187 QFixed dist = x - left - n * perItemWidth;-
3188 int closestItem = dist > (perItemWidth / 2) ? n + 1 : n;
dist > (perItemWidth / 2)Description
TRUEnever evaluated
FALSEnever evaluated
0
3189 if (cursorOnCharacter && closestItem > 0)
cursorOnCharacterDescription
TRUEnever evaluated
FALSEnever evaluated
closestItem > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
3190 closestItem--;
never executed: closestItem--;
0
3191 int pos = clusterStart + closestItem;-
3192 // Jump to the next grapheme boundary-
3193 while (pos < end && !attrs[pos].graphemeBoundary)
pos < endDescription
TRUEnever evaluated
FALSEnever evaluated
!attrs[pos].graphemeBoundaryDescription
TRUEnever evaluated
FALSEnever evaluated
0
3194 pos++;
never executed: pos++;
0
3195 return si->position + pos;
never executed: return si->position + pos;
0
3196 }-
3197 return si->position + end;
never executed: return si->position + end;
0
3198}-
3199-
3200int QTextEngine::previousLogicalPosition(int oldPos) const-
3201{-
3202 const QCharAttributes *attrs = attributes();-
3203 int len = block.isValid() ? block.length() - 1
block.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
3204 : layoutData->string.length();-
3205 Q_ASSERT(len <= layoutData->string.length());-
3206 if (!attrs || oldPos <= 0 || oldPos > len)
!attrsDescription
TRUEnever evaluated
FALSEnever evaluated
oldPos <= 0Description
TRUEnever evaluated
FALSEnever evaluated
oldPos > lenDescription
TRUEnever evaluated
FALSEnever evaluated
0
3207 return oldPos;
never executed: return oldPos;
0
3208-
3209 oldPos--;-
3210 while (oldPos && !attrs[oldPos].graphemeBoundary)
oldPosDescription
TRUEnever evaluated
FALSEnever evaluated
!attrs[oldPos]...aphemeBoundaryDescription
TRUEnever evaluated
FALSEnever evaluated
0
3211 oldPos--;
never executed: oldPos--;
0
3212 return oldPos;
never executed: return oldPos;
0
3213}-
3214-
3215int QTextEngine::nextLogicalPosition(int oldPos) const-
3216{-
3217 const QCharAttributes *attrs = attributes();-
3218 int len = block.isValid() ? block.length() - 1
block.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
3219 : layoutData->string.length();-
3220 Q_ASSERT(len <= layoutData->string.length());-
3221 if (!attrs || oldPos < 0 || oldPos >= len)
!attrsDescription
TRUEnever evaluated
FALSEnever evaluated
oldPos < 0Description
TRUEnever evaluated
FALSEnever evaluated
oldPos >= lenDescription
TRUEnever evaluated
FALSEnever evaluated
0
3222 return oldPos;
never executed: return oldPos;
0
3223-
3224 oldPos++;-
3225 while (oldPos < len && !attrs[oldPos].graphemeBoundary)
oldPos < lenDescription
TRUEnever evaluated
FALSEnever evaluated
!attrs[oldPos]...aphemeBoundaryDescription
TRUEnever evaluated
FALSEnever evaluated
0
3226 oldPos++;
never executed: oldPos++;
0
3227 return oldPos;
never executed: return oldPos;
0
3228}-
3229-
3230int QTextEngine::lineNumberForTextPosition(int pos)-
3231{-
3232 if (!layoutData)
!layoutDataDescription
TRUEnever evaluated
FALSEnever evaluated
0
3233 itemize();
never executed: itemize();
0
3234 if (pos == layoutData->string.length() && lines.size())
pos == layoutD...tring.length()Description
TRUEnever evaluated
FALSEnever evaluated
lines.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
3235 return lines.size() - 1;
never executed: return lines.size() - 1;
0
3236 for (int i = 0; i < lines.size(); ++i) {
i < lines.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
3237 const QScriptLine& line = lines[i];-
3238 if (line.from + line.length + line.trailingSpaces > pos)
line.from + li...ngSpaces > posDescription
TRUEnever evaluated
FALSEnever evaluated
0
3239 return i;
never executed: return i;
0
3240 }
never executed: end of block
0
3241 return -1;
never executed: return -1;
0
3242}-
3243-
3244void QTextEngine::insertionPointsForLine(int lineNum, QVector<int> &insertionPoints)-
3245{-
3246 QTextLineItemIterator iterator(this, lineNum);-
3247-
3248 insertionPoints.reserve(iterator.line.length);-
3249-
3250 bool lastLine = lineNum >= lines.size() - 1;-
3251-
3252 while (!iterator.atEnd()) {
!iterator.atEnd()Description
TRUEnever evaluated
FALSEnever evaluated
0
3253 const QScriptItem &si = iterator.next();-
3254-
3255 int end = iterator.itemEnd;-
3256 if (lastLine && iterator.item == iterator.lastItem)
lastLineDescription
TRUEnever evaluated
FALSEnever evaluated
iterator.item ...rator.lastItemDescription
TRUEnever evaluated
FALSEnever evaluated
0
3257 ++end; // the last item in the last line -> insert eol position
never executed: ++end;
0
3258 if (si.analysis.bidiLevel % 2) {
si.analysis.bidiLevel % 2Description
TRUEnever evaluated
FALSEnever evaluated
0
3259 for (int i = end - 1; i >= iterator.itemStart; --i)
i >= iterator.itemStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
3260 insertionPoints.push_back(i);
never executed: insertionPoints.push_back(i);
0
3261 } else {
never executed: end of block
0
3262 for (int i = iterator.itemStart; i < end; ++i)
i < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
3263 insertionPoints.push_back(i);
never executed: insertionPoints.push_back(i);
0
3264 }
never executed: end of block
0
3265 }-
3266}
never executed: end of block
0
3267-
3268int QTextEngine::endOfLine(int lineNum)-
3269{-
3270 QVector<int> insertionPoints;-
3271 insertionPointsForLine(lineNum, insertionPoints);-
3272-
3273 if (insertionPoints.size() > 0)
insertionPoints.size() > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
3274 return insertionPoints.last();
never executed: return insertionPoints.last();
0
3275 return 0;
never executed: return 0;
0
3276}-
3277-
3278int QTextEngine::beginningOfLine(int lineNum)-
3279{-
3280 QVector<int> insertionPoints;-
3281 insertionPointsForLine(lineNum, insertionPoints);-
3282-
3283 if (insertionPoints.size() > 0)
insertionPoints.size() > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
3284 return insertionPoints.first();
never executed: return insertionPoints.first();
0
3285 return 0;
never executed: return 0;
0
3286}-
3287-
3288int QTextEngine::positionAfterVisualMovement(int pos, QTextCursor::MoveOperation op)-
3289{-
3290 itemize();-
3291-
3292 bool moveRight = (op == QTextCursor::Right);-
3293 bool alignRight = isRightToLeft();-
3294 if (!layoutData->hasBidi)
!layoutData->hasBidiDescription
TRUEnever evaluated
FALSEnever evaluated
0
3295 return moveRight ^ alignRight ? nextLogicalPosition(pos) : previousLogicalPosition(pos);
never executed: return moveRight ^ alignRight ? nextLogicalPosition(pos) : previousLogicalPosition(pos);
moveRight ^ alignRightDescription
TRUEnever evaluated
FALSEnever evaluated
0
3296-
3297 int lineNum = lineNumberForTextPosition(pos);-
3298 if (lineNum < 0)
lineNum < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
3299 return pos;
never executed: return pos;
0
3300-
3301 QVector<int> insertionPoints;-
3302 insertionPointsForLine(lineNum, insertionPoints);-
3303 int i, max = insertionPoints.size();-
3304 for (i = 0; i < max; i++)
i < maxDescription
TRUEnever evaluated
FALSEnever evaluated
0
3305 if (pos == insertionPoints[i]) {
pos == insertionPoints[i]Description
TRUEnever evaluated
FALSEnever evaluated
0
3306 if (moveRight) {
moveRightDescription
TRUEnever evaluated
FALSEnever evaluated
0
3307 if (i + 1 < max)
i + 1 < maxDescription
TRUEnever evaluated
FALSEnever evaluated
0
3308 return insertionPoints[i + 1];
never executed: return insertionPoints[i + 1];
0
3309 } else {
never executed: end of block
0
3310 if (i > 0)
i > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
3311 return insertionPoints[i - 1];
never executed: return insertionPoints[i - 1];
0
3312 }
never executed: end of block
0
3313-
3314 if (moveRight ^ alignRight) {
moveRight ^ alignRightDescription
TRUEnever evaluated
FALSEnever evaluated
0
3315 if (lineNum + 1 < lines.size())
lineNum + 1 < lines.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
3316 return alignRight ? endOfLine(lineNum + 1) : beginningOfLine(lineNum + 1);
never executed: return alignRight ? endOfLine(lineNum + 1) : beginningOfLine(lineNum + 1);
alignRightDescription
TRUEnever evaluated
FALSEnever evaluated
0
3317 }
never executed: end of block
0
3318 else {-
3319 if (lineNum > 0)
lineNum > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
3320 return alignRight ? beginningOfLine(lineNum - 1) : endOfLine(lineNum - 1);
never executed: return alignRight ? beginningOfLine(lineNum - 1) : endOfLine(lineNum - 1);
alignRightDescription
TRUEnever evaluated
FALSEnever evaluated
0
3321 }
never executed: end of block
0
3322-
3323 break;
never executed: break;
0
3324 }-
3325-
3326 return pos;
never executed: return pos;
0
3327}-
3328-
3329void QTextEngine::addItemDecoration(QPainter *painter, const QLineF &line, ItemDecorationList *decorationList)-
3330{-
3331 if (delayDecorations) {
delayDecorationsDescription
TRUEnever evaluated
FALSEnever evaluated
0
3332 decorationList->append(ItemDecoration(line.x1(), line.x2(), line.y1(), painter->pen()));-
3333 } else {
never executed: end of block
0
3334 painter->drawLine(line);-
3335 }
never executed: end of block
0
3336}-
3337-
3338void QTextEngine::addUnderline(QPainter *painter, const QLineF &line)-
3339{-
3340 // qDebug() << "Adding underline:" << line;-
3341 addItemDecoration(painter, line, &underlineList);-
3342}
never executed: end of block
0
3343-
3344void QTextEngine::addStrikeOut(QPainter *painter, const QLineF &line)-
3345{-
3346 addItemDecoration(painter, line, &strikeOutList);-
3347}
never executed: end of block
0
3348-
3349void QTextEngine::addOverline(QPainter *painter, const QLineF &line)-
3350{-
3351 addItemDecoration(painter, line, &overlineList);-
3352}
never executed: end of block
0
3353-
3354void QTextEngine::drawItemDecorationList(QPainter *painter, const ItemDecorationList &decorationList)-
3355{-
3356 // qDebug() << "Drawing" << decorationList.size() << "decorations";-
3357 if (decorationList.isEmpty())
decorationList.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
3358 return;
never executed: return;
0
3359-
3360 foreach (const ItemDecoration &decoration, decorationList) {-
3361 painter->setPen(decoration.pen);-
3362 painter->drawLine(QLineF(decoration.x1, decoration.y, decoration.x2, decoration.y));-
3363 }
never executed: end of block
0
3364}
never executed: end of block
0
3365-
3366void QTextEngine::drawDecorations(QPainter *painter)-
3367{-
3368 QPen oldPen = painter->pen();-
3369-
3370 bool wasCompatiblePainting = painter->renderHints()-
3371 & QPainter::Qt4CompatiblePainting;-
3372-
3373 if (wasCompatiblePainting)
wasCompatiblePaintingDescription
TRUEnever evaluated
FALSEnever evaluated
0
3374 painter->setRenderHint(QPainter::Qt4CompatiblePainting, false);
never executed: painter->setRenderHint(QPainter::Qt4CompatiblePainting, false);
0
3375-
3376 adjustUnderlines();-
3377 drawItemDecorationList(painter, underlineList);-
3378 drawItemDecorationList(painter, strikeOutList);-
3379 drawItemDecorationList(painter, overlineList);-
3380-
3381 clearDecorations();-
3382-
3383 if (wasCompatiblePainting)
wasCompatiblePaintingDescription
TRUEnever evaluated
FALSEnever evaluated
0
3384 painter->setRenderHint(QPainter::Qt4CompatiblePainting);
never executed: painter->setRenderHint(QPainter::Qt4CompatiblePainting);
0
3385-
3386 painter->setPen(oldPen);-
3387}
never executed: end of block
0
3388-
3389void QTextEngine::clearDecorations()-
3390{-
3391 underlineList.clear();-
3392 strikeOutList.clear();-
3393 overlineList.clear();-
3394}
never executed: end of block
0
3395-
3396void QTextEngine::adjustUnderlines()-
3397{-
3398 // qDebug() << __PRETTY_FUNCTION__ << underlineList.count() << "underlines";-
3399 if (underlineList.isEmpty())
underlineList.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
3400 return;
never executed: return;
0
3401-
3402 ItemDecorationList::iterator start = underlineList.begin();-
3403 ItemDecorationList::iterator end = underlineList.end();-
3404 ItemDecorationList::iterator it = start;-
3405 qreal underlinePos = start->y;-
3406 qreal penWidth = start->pen.widthF();-
3407 qreal lastLineEnd = start->x1;-
3408-
3409 while (it != end) {
it != endDescription
TRUEnever evaluated
FALSEnever evaluated
0
3410 if (qFuzzyCompare(lastLineEnd, it->x1)) { // no gap between underlines
qFuzzyCompare(...neEnd, it->x1)Description
TRUEnever evaluated
FALSEnever evaluated
0
3411 underlinePos = qMax(underlinePos, it->y);-
3412 penWidth = qMax(penWidth, it->pen.widthF());-
3413 } else { // gap between this and the last underline
never executed: end of block
0
3414 adjustUnderlines(start, it, underlinePos, penWidth);-
3415 start = it;-
3416 underlinePos = start->y;-
3417 penWidth = start->pen.widthF();-
3418 }
never executed: end of block
0
3419 lastLineEnd = it->x2;-
3420 ++it;-
3421 }
never executed: end of block
0
3422-
3423 adjustUnderlines(start, end, underlinePos, penWidth);-
3424}
never executed: end of block
0
3425-
3426void QTextEngine::adjustUnderlines(ItemDecorationList::iterator start,-
3427 ItemDecorationList::iterator end,-
3428 qreal underlinePos, qreal penWidth)-
3429{-
3430 for (ItemDecorationList::iterator it = start; it != end; ++it) {
it != endDescription
TRUEnever evaluated
FALSEnever evaluated
0
3431 it->y = underlinePos;-
3432 it->pen.setWidthF(penWidth);-
3433 }
never executed: end of block
0
3434}
never executed: end of block
0
3435-
3436QStackTextEngine::QStackTextEngine(const QString &string, const QFont &f)-
3437 : QTextEngine(string, f),-
3438 _layoutData(string, _memory, MemSize)-
3439{-
3440 stackEngine = true;-
3441 layoutData = &_layoutData;-
3442}
never executed: end of block
0
3443-
3444QTextItemInt::QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFormat &format)-
3445 : justified(false), underlineStyle(QTextCharFormat::NoUnderline), charFormat(format),-
3446 num_chars(0), chars(0), logClusters(0), f(0), fontEngine(0)-
3447{-
3448 f = font;-
3449 fontEngine = f->d->engineForScript(si.analysis.script);-
3450 Q_ASSERT(fontEngine);-
3451-
3452 initWithScriptItem(si);-
3453}
never executed: end of block
0
3454-
3455QTextItemInt::QTextItemInt(const QGlyphLayout &g, QFont *font, const QChar *chars_, int numChars, QFontEngine *fe, const QTextCharFormat &format)-
3456 : flags(0), justified(false), underlineStyle(QTextCharFormat::NoUnderline), charFormat(format),-
3457 num_chars(numChars), chars(chars_), logClusters(0), f(font), glyphs(g), fontEngine(fe)-
3458{-
3459}
never executed: end of block
0
3460-
3461// Fix up flags and underlineStyle with given info-
3462void QTextItemInt::initWithScriptItem(const QScriptItem &si)-
3463{-
3464 // explicitly initialize flags so that initFontAttributes can be called-
3465 // multiple times on the same TextItem-
3466 flags = 0;-
3467 if (si.analysis.bidiLevel %2)
si.analysis.bidiLevel %2Description
TRUEnever evaluated
FALSEnever evaluated
0
3468 flags |= QTextItem::RightToLeft;
never executed: flags |= QTextItem::RightToLeft;
0
3469 ascent = si.ascent;-
3470 descent = si.descent;-
3471-
3472 if (charFormat.hasProperty(QTextFormat::TextUnderlineStyle)) {
charFormat.has...nderlineStyle)Description
TRUEnever evaluated
FALSEnever evaluated
0
3473 underlineStyle = charFormat.underlineStyle();-
3474 } else if (charFormat.boolProperty(QTextFormat::FontUnderline)
never executed: end of block
charFormat.boo...FontUnderline)Description
TRUEnever evaluated
FALSEnever evaluated
0
3475 || f->d->underline) {
f->d->underlineDescription
TRUEnever evaluated
FALSEnever evaluated
0
3476 underlineStyle = QTextCharFormat::SingleUnderline;-
3477 }
never executed: end of block
0
3478-
3479 // compat-
3480 if (underlineStyle == QTextCharFormat::SingleUnderline)
underlineStyle...ingleUnderlineDescription
TRUEnever evaluated
FALSEnever evaluated
0
3481 flags |= QTextItem::Underline;
never executed: flags |= QTextItem::Underline;
0
3482-
3483 if (f->d->overline || charFormat.fontOverline())
f->d->overlineDescription
TRUEnever evaluated
FALSEnever evaluated
charFormat.fontOverline()Description
TRUEnever evaluated
FALSEnever evaluated
0
3484 flags |= QTextItem::Overline;
never executed: flags |= QTextItem::Overline;
0
3485 if (f->d->strikeOut || charFormat.fontStrikeOut())
f->d->strikeOutDescription
TRUEnever evaluated
FALSEnever evaluated
charFormat.fontStrikeOut()Description
TRUEnever evaluated
FALSEnever evaluated
0
3486 flags |= QTextItem::StrikeOut;
never executed: flags |= QTextItem::StrikeOut;
0
3487}
never executed: end of block
0
3488-
3489QTextItemInt QTextItemInt::midItem(QFontEngine *fontEngine, int firstGlyphIndex, int numGlyphs) const-
3490{-
3491 QTextItemInt ti = *this;-
3492 const int end = firstGlyphIndex + numGlyphs;-
3493 ti.glyphs = glyphs.mid(firstGlyphIndex, numGlyphs);-
3494 ti.fontEngine = fontEngine;-
3495-
3496 if (logClusters && chars) {
logClustersDescription
TRUEnever evaluated
FALSEnever evaluated
charsDescription
TRUEnever evaluated
FALSEnever evaluated
0
3497 const int logClusterOffset = logClusters[0];-
3498 while (logClusters[ti.chars - chars] - logClusterOffset < firstGlyphIndex)
logClusters[ti...irstGlyphIndexDescription
TRUEnever evaluated
FALSEnever evaluated
0
3499 ++ti.chars;
never executed: ++ti.chars;
0
3500-
3501 ti.logClusters += (ti.chars - chars);-
3502-
3503 ti.num_chars = 0;-
3504 int char_start = ti.chars - chars;-
3505 while (char_start + ti.num_chars < num_chars && ti.logClusters[ti.num_chars] - logClusterOffset < end)
char_start + t...rs < num_charsDescription
TRUEnever evaluated
FALSEnever evaluated
ti.logClusters...erOffset < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
3506 ++ti.num_chars;
never executed: ++ti.num_chars;
0
3507 }
never executed: end of block
0
3508 return ti;
never executed: return ti;
0
3509}-
3510-
3511-
3512QTransform qt_true_matrix(qreal w, qreal h, QTransform x)-
3513{-
3514 QRectF rect = x.mapRect(QRectF(0, 0, w, h));-
3515 return x * QTransform::fromTranslate(-rect.x(), -rect.y());
never executed: return x * QTransform::fromTranslate(-rect.x(), -rect.y());
0
3516}-
3517-
3518-
3519glyph_metrics_t glyph_metrics_t::transformed(const QTransform &matrix) const-
3520{-
3521 if (matrix.type() < QTransform::TxTranslate)
matrix.type() ...m::TxTranslateDescription
TRUEnever evaluated
FALSEnever evaluated
0
3522 return *this;
never executed: return *this;
0
3523-
3524 glyph_metrics_t m = *this;-
3525-
3526 qreal w = width.toReal();-
3527 qreal h = height.toReal();-
3528 QTransform xform = qt_true_matrix(w, h, matrix);-
3529-
3530 QRectF rect(0, 0, w, h);-
3531 rect = xform.mapRect(rect);-
3532 m.width = QFixed::fromReal(rect.width());-
3533 m.height = QFixed::fromReal(rect.height());-
3534-
3535 QLineF l = xform.map(QLineF(x.toReal(), y.toReal(), xoff.toReal(), yoff.toReal()));-
3536-
3537 m.x = QFixed::fromReal(l.x1());-
3538 m.y = QFixed::fromReal(l.y1());-
3539-
3540 // The offset is relative to the baseline which is why we use dx/dy of the line-
3541 m.xoff = QFixed::fromReal(l.dx());-
3542 m.yoff = QFixed::fromReal(l.dy());-
3543-
3544 return m;
never executed: return m;
0
3545}-
3546-
3547QTextLineItemIterator::QTextLineItemIterator(QTextEngine *_eng, int _lineNum, const QPointF &pos,-
3548 const QTextLayout::FormatRange *_selection)-
3549 : eng(_eng),-
3550 line(eng->lines[_lineNum]),-
3551 si(0),-
3552 lineNum(_lineNum),-
3553 lineEnd(line.from + line.length),-
3554 firstItem(eng->findItem(line.from)),-
3555 lastItem(eng->findItem(lineEnd - 1, firstItem)),-
3556 nItems((firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0),-
3557 logicalItem(-1),-
3558 item(-1),-
3559 visualOrder(nItems),-
3560 selection(_selection)-
3561{-
3562 x = QFixed::fromReal(pos.x());-
3563-
3564 x += line.x;-
3565-
3566 x += eng->alignLine(line);-
3567-
3568 QVarLengthArray<uchar> levels(nItems);-
3569 for (int i = 0; i < nItems; ++i)
i < nItemsDescription
TRUEnever evaluated
FALSEnever evaluated
0
3570 levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;
never executed: levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;
0
3571 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());-
3572-
3573 eng->shapeLine(line);-
3574}
never executed: end of block
0
3575-
3576QScriptItem &QTextLineItemIterator::next()-
3577{-
3578 x += itemWidth;-
3579-
3580 ++logicalItem;-
3581 item = visualOrder[logicalItem] + firstItem;-
3582 itemLength = eng->length(item);-
3583 si = &eng->layoutData->items[item];-
3584 if (!si->num_glyphs)
!si->num_glyphsDescription
TRUEnever evaluated
FALSEnever evaluated
0
3585 eng->shape(item);
never executed: eng->shape(item);
0
3586-
3587 itemStart = qMax(line.from, si->position);-
3588 itemEnd = qMin(lineEnd, si->position + itemLength);-
3589-
3590 if (si->analysis.flags >= QScriptAnalysis::TabOrObject) {
si->analysis.f...s::TabOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
3591 glyphsStart = 0;-
3592 glyphsEnd = 1;-
3593 itemWidth = si->width;-
3594 return *si;
never executed: return *si;
0
3595 }-
3596-
3597 unsigned short *logClusters = eng->logClusters(si);-
3598 QGlyphLayout glyphs = eng->shapedGlyphs(si);-
3599-
3600 glyphsStart = logClusters[itemStart - si->position];-
3601 glyphsEnd = (itemEnd == si->position + itemLength) ? si->num_glyphs : logClusters[itemEnd - si->position];
(itemEnd == si... + itemLength)Description
TRUEnever evaluated
FALSEnever evaluated
0
3602-
3603 // show soft-hyphen at line-break-
3604 if (si->position + itemLength >= lineEnd
si->position +...gth >= lineEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
3605 && eng->layoutData->string.at(lineEnd - 1).unicode() == QChar::SoftHyphen)
eng->layoutDat...ar::SoftHyphenDescription
TRUEnever evaluated
FALSEnever evaluated
0
3606 glyphs.attributes[glyphsEnd - 1].dontPrint = false;
never executed: glyphs.attributes[glyphsEnd - 1].dontPrint = false;
0
3607-
3608 itemWidth = 0;-
3609 for (int g = glyphsStart; g < glyphsEnd; ++g)
g < glyphsEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
3610 itemWidth += glyphs.effectiveAdvance(g);
never executed: itemWidth += glyphs.effectiveAdvance(g);
0
3611-
3612 return *si;
never executed: return *si;
0
3613}-
3614-
3615bool QTextLineItemIterator::getSelectionBounds(QFixed *selectionX, QFixed *selectionWidth) const-
3616{-
3617 *selectionX = *selectionWidth = 0;-
3618-
3619 if (!selection)
!selectionDescription
TRUEnever evaluated
FALSEnever evaluated
0
3620 return false;
never executed: return false;
0
3621-
3622 if (si->analysis.flags >= QScriptAnalysis::TabOrObject) {
si->analysis.f...s::TabOrObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
3623 if (si->position >= selection->start + selection->length
si->position >...ection->lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
3624 || si->position + itemLength <= selection->start)
si->position +...lection->startDescription
TRUEnever evaluated
FALSEnever evaluated
0
3625 return false;
never executed: return false;
0
3626-
3627 *selectionX = x;-
3628 *selectionWidth = itemWidth;-
3629 } else {
never executed: end of block
0
3630 unsigned short *logClusters = eng->logClusters(si);-
3631 QGlyphLayout glyphs = eng->shapedGlyphs(si);-
3632-
3633 int from = qMax(itemStart, selection->start) - si->position;-
3634 int to = qMin(itemEnd, selection->start + selection->length) - si->position;-
3635 if (from >= to)
from >= toDescription
TRUEnever evaluated
FALSEnever evaluated
0
3636 return false;
never executed: return false;
0
3637-
3638 int start_glyph = logClusters[from];-
3639 int end_glyph = (to == itemLength) ? si->num_glyphs : logClusters[to];
(to == itemLength)Description
TRUEnever evaluated
FALSEnever evaluated
0
3640 QFixed soff;-
3641 QFixed swidth;-
3642 if (si->analysis.bidiLevel %2) {
si->analysis.bidiLevel %2Description
TRUEnever evaluated
FALSEnever evaluated
0
3643 for (int g = glyphsEnd - 1; g >= end_glyph; --g)
g >= end_glyphDescription
TRUEnever evaluated
FALSEnever evaluated
0
3644 soff += glyphs.effectiveAdvance(g);
never executed: soff += glyphs.effectiveAdvance(g);
0
3645 for (int g = end_glyph - 1; g >= start_glyph; --g)
g >= start_glyphDescription
TRUEnever evaluated
FALSEnever evaluated
0
3646 swidth += glyphs.effectiveAdvance(g);
never executed: swidth += glyphs.effectiveAdvance(g);
0
3647 } else {
never executed: end of block
0
3648 for (int g = glyphsStart; g < start_glyph; ++g)
g < start_glyphDescription
TRUEnever evaluated
FALSEnever evaluated
0
3649 soff += glyphs.effectiveAdvance(g);
never executed: soff += glyphs.effectiveAdvance(g);
0
3650 for (int g = start_glyph; g < end_glyph; ++g)
g < end_glyphDescription
TRUEnever evaluated
FALSEnever evaluated
0
3651 swidth += glyphs.effectiveAdvance(g);
never executed: swidth += glyphs.effectiveAdvance(g);
0
3652 }
never executed: end of block
0
3653-
3654 // If the starting character is in the middle of a ligature,-
3655 // selection should only contain the right part of that ligature-
3656 // glyph, so we need to get the width of the left part here and-
3657 // add it to *selectionX-
3658 QFixed leftOffsetInLigature = eng->offsetInLigature(si, from, to, start_glyph);-
3659 *selectionX = x + soff + leftOffsetInLigature;-
3660 *selectionWidth = swidth - leftOffsetInLigature;-
3661 // If the ending character is also part of a ligature, swidth does-
3662 // not contain that part yet, we also need to find out the width of-
3663 // that left part-
3664 *selectionWidth += eng->offsetInLigature(si, to, itemLength, end_glyph);-
3665 }
never executed: end of block
0
3666 return true;
never executed: return true;
0
3667}-
3668-
3669QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9