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

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