qdistancefield.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/text/qdistancefield.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 QtDeclarative 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 "qdistancefield_p.h"-
41#include <qmath.h>-
42#include <private/qdatabuffer_p.h>-
43#include <private/qimage_p.h>-
44#include <private/qpathsimplifier_p.h>-
45-
46QT_BEGIN_NAMESPACE-
47-
48namespace-
49{-
50 enum FillHDir-
51 {-
52 LeftToRight,-
53 RightToLeft-
54 };-
55-
56 enum FillVDir-
57 {-
58 TopDown,-
59 BottomUp-
60 };-
61-
62 enum FillClip-
63 {-
64 NoClip,-
65 Clip-
66 };-
67}-
68-
69template <FillClip clip, FillHDir dir>-
70inline void fillLine(qint32 *, int, int, int, qint32, qint32)-
71{-
72}-
73-
74template <>-
75inline void fillLine<Clip, LeftToRight>(qint32 *line, int width, int lx, int rx, qint32 d, qint32 dd)-
76{-
77 int fromX = qMax(0, lx >> 8);-
78 int toX = qMin(width, rx >> 8);-
79 int x = toX - fromX;-
80 if (x <= 0)-
81 return;-
82 qint32 val = d + (((fromX << 8) + 0xff - lx) * dd >> 8);-
83 line += fromX;-
84 do {-
85 *line = abs(val) < abs(*line) ? val : *line;-
86 val += dd;-
87 ++line;-
88 } while (--x);-
89}-
90-
91template <>-
92inline void fillLine<Clip, RightToLeft>(qint32 *line, int width, int lx, int rx, qint32 d, qint32 dd)-
93{-
94 int fromX = qMax(0, lx >> 8);-
95 int toX = qMin(width, rx >> 8);-
96 int x = toX - fromX;-
97 if (x <= 0)-
98 return;-
99 qint32 val = d + (((toX << 8) + 0xff - rx) * dd >> 8);-
100 line += toX;-
101 do {-
102 val -= dd;-
103 --line;-
104 *line = abs(val) < abs(*line) ? val : *line;-
105 } while (--x);-
106}-
107-
108template <>-
109inline void fillLine<NoClip, LeftToRight>(qint32 *line, int, int lx, int rx, qint32 d, qint32 dd)-
110{-
111 int fromX = lx >> 8;-
112 int toX = rx >> 8;-
113 int x = toX - fromX;-
114 if (x <= 0)-
115 return;-
116 qint32 val = d + ((~lx & 0xff) * dd >> 8);-
117 line += fromX;-
118 do {-
119 *line = abs(val) < abs(*line) ? val : *line;-
120 val += dd;-
121 ++line;-
122 } while (--x);-
123}-
124-
125template <>-
126inline void fillLine<NoClip, RightToLeft>(qint32 *line, int, int lx, int rx, qint32 d, qint32 dd)-
127{-
128 int fromX = lx >> 8;-
129 int toX = rx >> 8;-
130 int x = toX - fromX;-
131 if (x <= 0)-
132 return;-
133 qint32 val = d + ((~rx & 0xff) * dd >> 8);-
134 line += toX;-
135 do {-
136 val -= dd;-
137 --line;-
138 *line = abs(val) < abs(*line) ? val : *line;-
139 } while (--x);-
140}-
141-
142template <FillClip clip, FillVDir vDir, FillHDir hDir>-
143inline void fillLines(qint32 *bits, int width, int height, int upperY, int lowerY,-
144 int &lx, int ldx, int &rx, int rdx, qint32 &d, qint32 ddy, qint32 ddx)-
145{-
146 Q_UNUSED(height);-
147 Q_ASSERT(upperY < lowerY);-
148 int y = lowerY - upperY;-
149 if (vDir == TopDown) {-
150 qint32 *line = bits + upperY * width;-
151 do {-
152 fillLine<clip, hDir>(line, width, lx, rx, d, ddx);-
153 lx += ldx;-
154 d += ddy;-
155 rx += rdx;-
156 line += width;-
157 } while (--y);-
158 } else {-
159 qint32 *line = bits + lowerY * width;-
160 do {-
161 lx -= ldx;-
162 d -= ddy;-
163 rx -= rdx;-
164 line -= width;-
165 fillLine<clip, hDir>(line, width, lx, rx, d, ddx);-
166 } while (--y);-
167 }-
168}-
169-
170template <FillClip clip>-
171void drawTriangle(qint32 *bits, int width, int height, const QPoint *center,-
172 const QPoint *v1, const QPoint *v2, qint32 value)-
173{-
174 const int y1 = clip == Clip ? qBound(0, v1->y() >> 8, height) : v1->y() >> 8;-
175 const int y2 = clip == Clip ? qBound(0, v2->y() >> 8, height) : v2->y() >> 8;-
176 const int yC = clip == Clip ? qBound(0, center->y() >> 8, height) : center->y() >> 8;-
177-
178 const int v1Frac = clip == Clip ? (y1 << 8) + 0xff - v1->y() : ~v2->y() & 0xff;-
179 const int v2Frac = clip == Clip ? (y2 << 8) + 0xff - v2->y() : ~v1->y() & 0xff;-
180 const int centerFrac = clip == Clip ? (yC << 8) + 0xff - center->y() : ~center->y() & 0xff;-
181-
182 int dx1 = 0, x1 = 0, dx2 = 0, x2 = 0;-
183 qint32 dd1, d1, dd2, d2;-
184 if (v1->y() != center->y()) {-
185 dx1 = ((v1->x() - center->x()) << 8) / (v1->y() - center->y());-
186 x1 = center->x() + centerFrac * (v1->x() - center->x()) / (v1->y() - center->y());-
187 }-
188 if (v2->y() != center->y()) {-
189 dx2 = ((v2->x() - center->x()) << 8) / (v2->y() - center->y());-
190 x2 = center->x() + centerFrac * (v2->x() - center->x()) / (v2->y() - center->y());-
191 }-
192-
193 const qint32 div = (v2->x() - center->x()) * (v1->y() - center->y())-
194 - (v2->y() - center->y()) * (v1->x() - center->x());-
195 const qint32 dd = div ? qint32((qint64(value * (v1->y() - v2->y())) << 8) / div) : 0;-
196-
197 if (y2 < yC) {-
198 if (y1 < yC) {-
199 // Center at the bottom.-
200 if (y2 < y1) {-
201 // y2 < y1 < yC-
202 // Long right edge.-
203 d1 = centerFrac * value / (v1->y() - center->y());-
204 dd1 = ((value << 8) / (v1->y() - center->y()));-
205 fillLines<clip, BottomUp, LeftToRight>(bits, width, height, y1, yC, x1, dx1,-
206 x2, dx2, d1, dd1, dd);-
207 dx1 = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());-
208 x1 = v1->x() + v1Frac * (v1->x() - v2->x()) / (v1->y() - v2->y());-
209 fillLines<clip, BottomUp, LeftToRight>(bits, width, height, y2, y1, x1, dx1,-
210 x2, dx2, value, 0, dd);-
211 } else {-
212 // y1 <= y2 < yC-
213 // Long left edge.-
214 d2 = centerFrac * value / (v2->y() - center->y());-
215 dd2 = ((value << 8) / (v2->y() - center->y()));-
216 fillLines<clip, BottomUp, RightToLeft>(bits, width, height, y2, yC, x1, dx1,-
217 x2, dx2, d2, dd2, dd);-
218 if (y1 != y2) {-
219 dx2 = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());-
220 x2 = v2->x() + v2Frac * (v1->x() - v2->x()) / (v1->y() - v2->y());-
221 fillLines<clip, BottomUp, RightToLeft>(bits, width, height, y1, y2, x1, dx1,-
222 x2, dx2, value, 0, dd);-
223 }-
224 }-
225 } else {-
226 // y2 < yC <= y1-
227 // Center to the right.-
228 int dx = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());-
229 int xUp, xDn;-
230 xUp = xDn = v2->x() + (clip == Clip ? (yC << 8) + 0xff - v2->y()-
231 : (center->y() | 0xff) - v2->y())-
232 * (v1->x() - v2->x()) / (v1->y() - v2->y());-
233 fillLines<clip, BottomUp, LeftToRight>(bits, width, height, y2, yC, xUp, dx,-
234 x2, dx2, value, 0, dd);-
235 if (yC != y1)-
236 fillLines<clip, TopDown, LeftToRight>(bits, width, height, yC, y1, xDn, dx,-
237 x1, dx1, value, 0, dd);-
238 }-
239 } else {-
240 if (y1 < yC) {-
241 // y1 < yC <= y2-
242 // Center to the left.-
243 int dx = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());-
244 int xUp, xDn;-
245 xUp = xDn = v1->x() + (clip == Clip ? (yC << 8) + 0xff - v1->y()-
246 : (center->y() | 0xff) - v1->y())-
247 * (v1->x() - v2->x()) / (v1->y() - v2->y());-
248 fillLines<clip, BottomUp, RightToLeft>(bits, width, height, y1, yC, x1, dx1,-
249 xUp, dx, value, 0, dd);-
250 if (yC != y2)-
251 fillLines<clip, TopDown, RightToLeft>(bits, width, height, yC, y2, x2, dx2,-
252 xDn, dx, value, 0, dd);-
253 } else {-
254 // Center at the top.-
255 if (y2 < y1) {-
256 // yC <= y2 < y1-
257 // Long right edge.-
258 if (yC != y2) {-
259 d2 = centerFrac * value / (v2->y() - center->y());-
260 dd2 = ((value << 8) / (v2->y() - center->y()));-
261 fillLines<clip, TopDown, LeftToRight>(bits, width, height, yC, y2, x2, dx2,-
262 x1, dx1, d2, dd2, dd);-
263 }-
264 dx2 = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());-
265 x2 = v2->x() + v2Frac * (v1->x() - v2->x()) / (v1->y() - v2->y());-
266 fillLines<clip, TopDown, LeftToRight>(bits, width, height, y2, y1, x2, dx2,-
267 x1, dx1, value, 0, dd);-
268 } else {-
269 // Long left edge.-
270 // yC <= y1 <= y2-
271 if (yC != y1) {-
272 d1 = centerFrac * value / (v1->y() - center->y());-
273 dd1 = ((value << 8) / (v1->y() - center->y()));-
274 fillLines<clip, TopDown, RightToLeft>(bits, width, height, yC, y1, x2, dx2,-
275 x1, dx1, d1, dd1, dd);-
276 }-
277 if (y1 != y2) {-
278 dx1 = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());-
279 x1 = v1->x() + v1Frac * (v1->x() - v2->x()) / (v1->y() - v2->y());-
280 fillLines<clip, TopDown, RightToLeft>(bits, width, height, y1, y2, x2, dx2,-
281 x1, dx1, value, 0, dd);-
282 }-
283 }-
284 }-
285 }-
286}-
287-
288template <FillClip clip>-
289void drawRectangle(qint32 *bits, int width, int height,-
290 const QPoint *int1, const QPoint *center1, const QPoint *ext1,-
291 const QPoint *int2, const QPoint *center2, const QPoint *ext2,-
292 qint32 extValue)-
293{-
294 if (center1->y() > center2->y()) {-
295 qSwap(center1, center2);-
296 qSwap(int1, ext2);-
297 qSwap(ext1, int2);-
298 extValue = -extValue;-
299 }-
300-
301 Q_ASSERT(ext1->x() - center1->x() == center1->x() - int1->x());-
302 Q_ASSERT(ext1->y() - center1->y() == center1->y() - int1->y());-
303 Q_ASSERT(ext2->x() - center2->x() == center2->x() - int2->x());-
304 Q_ASSERT(ext2->y() - center2->y() == center2->y() - int2->y());-
305-
306 const int yc1 = clip == Clip ? qBound(0, center1->y() >> 8, height) : center1->y() >> 8;-
307 const int yc2 = clip == Clip ? qBound(0, center2->y() >> 8, height) : center2->y() >> 8;-
308 const int yi1 = clip == Clip ? qBound(0, int1->y() >> 8, height) : int1->y() >> 8;-
309 const int yi2 = clip == Clip ? qBound(0, int2->y() >> 8, height) : int2->y() >> 8;-
310 const int ye1 = clip == Clip ? qBound(0, ext1->y() >> 8, height) : ext1->y() >> 8;-
311 const int ye2 = clip == Clip ? qBound(0, ext2->y() >> 8, height) : ext2->y() >> 8;-
312-
313 const int center1Frac = clip == Clip ? (yc1 << 8) + 0xff - center1->y() : ~center1->y() & 0xff;-
314 const int center2Frac = clip == Clip ? (yc2 << 8) + 0xff - center2->y() : ~center2->y() & 0xff;-
315 const int int1Frac = clip == Clip ? (yi1 << 8) + 0xff - int1->y() : ~int1->y() & 0xff;-
316 const int ext1Frac = clip == Clip ? (ye1 << 8) + 0xff - ext1->y() : ~ext1->y() & 0xff;-
317-
318 int dxC = 0, dxE = 0; // cap slope, edge slope-
319 qint32 ddC = 0;-
320 if (ext1->y() != int1->y()) {-
321 dxC = ((ext1->x() - int1->x()) << 8) / (ext1->y() - int1->y());-
322 ddC = (extValue << 9) / (ext1->y() - int1->y());-
323 }-
324 if (ext1->y() != ext2->y())-
325 dxE = ((ext1->x() - ext2->x()) << 8) / (ext1->y() - ext2->y());-
326-
327 const qint32 div = (ext1->x() - int1->x()) * (ext2->y() - int1->y())-
328 - (ext1->y() - int1->y()) * (ext2->x() - int1->x());-
329 const qint32 dd = div ? qint32((qint64(extValue * (ext2->y() - ext1->y())) << 9) / div) : 0;-
330-
331 int xe1, xe2, xc1, xc2;-
332 qint32 d;-
333-
334 qint32 intValue = -extValue;-
335-
336 if (center2->x() < center1->x()) {-
337 // Leaning to the right. '/'-
338 if (int1->y() < ext2->y()) {-
339 // Mostly vertical.-
340 Q_ASSERT(ext1->y() != ext2->y());-
341 xe1 = ext1->x() + ext1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());-
342 xe2 = int1->x() + int1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());-
343 if (ye1 != yi1) {-
344 xc2 = center1->x() + center1Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());-
345 xc2 += (ye1 - yc1) * dxC;-
346 fillLines<clip, TopDown, LeftToRight>(bits, width, height, ye1, yi1, xe1, dxE,-
347 xc2, dxC, extValue, 0, dd);-
348 }-
349 if (yi1 != ye2)-
350 fillLines<clip, TopDown, LeftToRight>(bits, width, height, yi1, ye2, xe1, dxE,-
351 xe2, dxE, extValue, 0, dd);-
352 if (ye2 != yi2) {-
353 xc1 = center2->x() + center2Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());-
354 xc1 += (ye2 - yc2) * dxC;-
355 fillLines<clip, TopDown, RightToLeft>(bits, width, height, ye2, yi2, xc1, dxC,-
356 xe2, dxE, intValue, 0, dd);-
357 }-
358 } else {-
359 // Mostly horizontal.-
360 Q_ASSERT(ext1->y() != int1->y());-
361 xc1 = center2->x() + center2Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());-
362 xc2 = center1->x() + center1Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());-
363 xc1 += (ye2 - yc2) * dxC;-
364 xc2 += (ye1 - yc1) * dxC;-
365 if (ye1 != ye2) {-
366 xe1 = ext1->x() + ext1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());-
367 fillLines<clip, TopDown, LeftToRight>(bits, width, height, ye1, ye2, xe1, dxE,-
368 xc2, dxC, extValue, 0, dd);-
369 }-
370 if (ye2 != yi1) {-
371 d = (clip == Clip ? (ye2 << 8) + 0xff - center2->y()-
372 : (ext2->y() | 0xff) - center2->y())-
373 * 2 * extValue / (ext1->y() - int1->y());-
374 fillLines<clip, TopDown, LeftToRight>(bits, width, height, ye2, yi1, xc1, dxC,-
375 xc2, dxC, d, ddC, dd);-
376 }-
377 if (yi1 != yi2) {-
378 xe2 = int1->x() + int1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());-
379 fillLines<clip, TopDown, RightToLeft>(bits, width, height, yi1, yi2, xc1, dxC,-
380 xe2, dxE, intValue, 0, dd);-
381 }-
382 }-
383 } else {-
384 // Leaning to the left. '\'-
385 if (ext1->y() < int2->y()) {-
386 // Mostly vertical.-
387 Q_ASSERT(ext1->y() != ext2->y());-
388 xe1 = ext1->x() + ext1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());-
389 xe2 = int1->x() + int1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());-
390 if (yi1 != ye1) {-
391 xc1 = center1->x() + center1Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());-
392 xc1 += (yi1 - yc1) * dxC;-
393 fillLines<clip, TopDown, RightToLeft>(bits, width, height, yi1, ye1, xc1, dxC,-
394 xe2, dxE, intValue, 0, dd);-
395 }-
396 if (ye1 != yi2)-
397 fillLines<clip, TopDown, RightToLeft>(bits, width, height, ye1, yi2, xe1, dxE,-
398 xe2, dxE, intValue, 0, dd);-
399 if (yi2 != ye2) {-
400 xc2 = center2->x() + center2Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());-
401 xc2 += (yi2 - yc2) * dxC;-
402 fillLines<clip, TopDown, LeftToRight>(bits, width, height, yi2, ye2, xe1, dxE,-
403 xc2, dxC, extValue, 0, dd);-
404 }-
405 } else {-
406 // Mostly horizontal.-
407 Q_ASSERT(ext1->y() != int1->y());-
408 xc1 = center1->x() + center1Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());-
409 xc2 = center2->x() + center2Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());-
410 xc1 += (yi1 - yc1) * dxC;-
411 xc2 += (yi2 - yc2) * dxC;-
412 if (yi1 != yi2) {-
413 xe2 = int1->x() + int1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());-
414 fillLines<clip, TopDown, RightToLeft>(bits, width, height, yi1, yi2, xc1, dxC,-
415 xe2, dxE, intValue, 0, dd);-
416 }-
417 if (yi2 != ye1) {-
418 d = (clip == Clip ? (yi2 << 8) + 0xff - center2->y()-
419 : (int2->y() | 0xff) - center2->y())-
420 * 2 * extValue / (ext1->y() - int1->y());-
421 fillLines<clip, TopDown, RightToLeft>(bits, width, height, yi2, ye1, xc1, dxC,-
422 xc2, dxC, d, ddC, dd);-
423 }-
424 if (ye1 != ye2) {-
425 xe1 = ext1->x() + ext1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());-
426 fillLines<clip, TopDown, LeftToRight>(bits, width, height, ye1, ye2, xe1, dxE,-
427 xc2, dxC, extValue, 0, dd);-
428 }-
429 }-
430 }-
431}-
432-
433static void drawPolygons(qint32 *bits, int width, int height, const QPoint *vertices,-
434 const quint32 *indices, int indexCount, qint32 value)-
435{-
436 Q_ASSERT(indexCount != 0);-
437 typedefQ_ASSERT(height <= 128);-
438 QVarLengthArray<quint8, 16> ScanLine;-
QVarLengthArray<ScanLine, 128> scans(height);[128];
439 int first = 0;-
440 for (int i = 1; i < indexCount; ++i) {
i < indexCountDescription
TRUEnever evaluated
FALSEnever evaluated
0
441 quint32 idx1 = indices[i - 1];-
442 quint32 idx2 = indices[i];-
443 Q_ASSERT(idx1 != quint32(-1));-
444 if (idx2 == quint32(-1)) {
idx2 == quint32(-1)Description
TRUEnever evaluated
FALSEnever evaluated
0
445 idx2 = indices[first];-
446 Q_ASSERT(idx2 != quint32(-1));-
447 first = ++i;-
448 }
never executed: end of block
0
449 const QPoint *v1 = &vertices[idx1];-
450 const QPoint *v2 = &vertices[idx2];-
451 if (v2->y() < v1->y())
v2->y() < v1->y()Description
TRUEnever evaluated
FALSEnever evaluated
0
452 qSwap(v1, v2);
never executed: qSwap(v1, v2);
0
453 int fromY = qMax(0, v1->y() >> 8);-
454 int toY = qMin(height, v2->y() >> 8);-
455 if (fromY >= toY)
fromY >= toYDescription
TRUEnever evaluated
FALSEnever evaluated
0
456 continue;
never executed: continue;
0
457 int dx = ((v2->x() - v1->x()) << 8) / (v2->y() - v1->y());-
458 int x = v1->x() + ((fromY << 8) + 0xff - v1->y()) * (v2->x() - v1->x()) / (v2->y() - v1->y());-
459 for (int y = fromY; y < toY; ++y) {
y < toYDescription
TRUEnever evaluated
FALSEnever evaluated
0
460 quint32 c = quint32(x >> 8);-
461 if (c < quint32(width))
c < quint32(width)Description
TRUEnever evaluated
FALSEnever evaluated
0
462 scans[y].append(quint8(c));
never executed: scans[y].append(quint8(c));
0
463 x += dx;-
464 }
never executed: end of block
0
465 }
never executed: end of block
0
466 for (int i = 0; i < height; ++i) {
i < heightDescription
TRUEnever evaluated
FALSEnever evaluated
0
467 quint8 *scanline = scans[i].data();-
468 int size = scans[i].size();-
469 for (int j = 1; j < size; ++j) {
j < sizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
470 int k = j;-
471 quint8 value = scanline[k];-
472 for (; k != 0 && value < scanline[k - 1]; --k)
k != 0Description
TRUEnever evaluated
FALSEnever evaluated
value < scanline[k - 1]Description
TRUEnever evaluated
FALSEnever evaluated
0
473 scanline[k] = scanline[k - 1];
never executed: scanline[k] = scanline[k - 1];
0
474 scanline[k] = value;-
475 }
never executed: end of block
0
476 qint32 *line = bits + i * width;-
477 int j = 0;-
478 for (; j + 1 < size; j += 2) {
j + 1 < sizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
479 for (quint8 x = scanline[j]; x < scanline[j + 1]; ++x)
x < scanline[j + 1]Description
TRUEnever evaluated
FALSEnever evaluated
0
480 line[x] = value;
never executed: line[x] = value;
0
481 }
never executed: end of block
0
482 if (j < size) {
j < sizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
483 for (int x = scanline[j]; x < width; ++x)
x < widthDescription
TRUEnever evaluated
FALSEnever evaluated
0
484 line[x] = value;
never executed: line[x] = value;
0
485 }
never executed: end of block
0
486 }
never executed: end of block
0
487}
never executed: end of block
0
488-
489static void makeDistanceField(QDistanceFieldData *data, const QPainterPath &path, int dfScale, int offs)-
490{-
491 if (!data || !data->data)-
492 return;-
493-
494 if (path.isEmpty()) {-
495 memset(data->data, 0, data->nbytes);-
496 return;-
497 }-
498-
499 int imgWidth = data->width;-
500 int imgHeight = data->height;-
501-
502 QTransform transform;-
503 transform.translate(offs, offs);-
504 transform.scale(qreal(1) / dfScale, qreal(1) / dfScale);-
505-
506 QDataBuffer<quint32> pathIndices(0);-
507 QDataBuffer<QPoint> pathVertices(0);-
508 qSimplifyPath(path, pathVertices, pathIndices, transform);-
509-
510 const qint32 interiorColor = -0x7f80; // 8:8 signed format, -127.5-
511 const qint32 exteriorColor = 0x7f80; // 8:8 signed format, 127.5-
512-
513 QScopedArrayPointer<qint32> bits(new qint32[imgWidth * imgHeight]);-
514 for (int i = 0; i < imgWidth * imgHeight; ++i)-
515 bits[i] = exteriorColor;-
516-
517 const qreal angleStep = qreal(15 * 3.141592653589793238 / 180);-
518 const QPoint rotation(qRound(qCos(angleStep) * 0x4000),-
519 qRound(qSin(angleStep) * 0x4000)); // 2:14 signed-
520-
521 const quint32 *indices = pathIndices.data();-
522 QVarLengthArray<QPoint> normals;-
523 QVarLengthArray<QPoint> vertices;-
524 QVarLengthArray<bool> isConvex;-
525 QVarLengthArray<bool> needsClipping;-
526-
527 drawPolygons(bits.data(), imgWidth, imgHeight, pathVertices.data(),-
528 indices, pathIndices.size(), interiorColor);-
529-
530 int index = 0;-
531-
532 while (index < pathIndices.size()) {-
533 normals.clear();-
534 vertices.clear();-
535 needsClipping.clear();-
536-
537 // Find end of polygon.-
538 int end = index;-
539 while (indices[end] != quint32(-1))-
540 ++end;-
541-
542 // Calculate vertex normals.-
543 for (int next = index, prev = end - 1; next < end; prev = next++) {-
544 quint32 fromVertexIndex = indices[prev];-
545 quint32 toVertexIndex = indices[next];-
546-
547 const QPoint &from = pathVertices.at(fromVertexIndex);-
548 const QPoint &to = pathVertices.at(toVertexIndex);-
549-
550 QPoint n(to.y() - from.y(), from.x() - to.x());-
551 if (n.x() == 0 && n.y() == 0)-
552 continue;-
553 int scale = qRound((offs << 16) / qSqrt(qreal(n.x()) * n.x() + qreal(n.y()) * n.y())); // 8:16-
554 Q_ASSERT(scale != 0);-
555-
556 n.rx() = n.x() * scale >> 8;-
557 n.ry() = n.y() * scale >> 8;-
558 normals.append(n);-
559 QPoint v(to.x() + 0x7f, to.y() + 0x7f);-
560 vertices.append(v);-
561 needsClipping.append((to.x() < offs << 8) || (to.x() >= (imgWidth - offs) << 8)-
562 || (to.y() < offs << 8) || (to.y() >= (imgHeight - offs) << 8));-
563 }-
564-
565 isConvex.resize(normals.count());-
566 for (int next = 0, prev = normals.count() - 1; next < normals.count(); prev = next++) {-
567 isConvex[prev] = normals.at(prev).x() * normals.at(next).y()-
568 - normals.at(prev).y() * normals.at(next).x() < 0;-
569 }-
570-
571 // Draw quads.-
572 for (int next = 0, prev = normals.count() - 1; next < normals.count(); prev = next++) {-
573 QPoint n = normals.at(next);-
574 QPoint intPrev = vertices.at(prev);-
575 QPoint extPrev = vertices.at(prev);-
576 QPoint intNext = vertices.at(next);-
577 QPoint extNext = vertices.at(next);-
578-
579 extPrev.rx() -= n.x();-
580 extPrev.ry() -= n.y();-
581 intPrev.rx() += n.x();-
582 intPrev.ry() += n.y();-
583 extNext.rx() -= n.x();-
584 extNext.ry() -= n.y();-
585 intNext.rx() += n.x();-
586 intNext.ry() += n.y();-
587-
588 if (needsClipping[prev] || needsClipping[next]) {-
589 drawRectangle<Clip>(bits.data(), imgWidth, imgHeight,-
590 &intPrev, &vertices.at(prev), &extPrev,-
591 &intNext, &vertices.at(next), &extNext,-
592 exteriorColor);-
593 } else {-
594 drawRectangle<NoClip>(bits.data(), imgWidth, imgHeight,-
595 &intPrev, &vertices.at(prev), &extPrev,-
596 &intNext, &vertices.at(next), &extNext,-
597 exteriorColor);-
598 }-
599-
600 if (isConvex.at(prev)) {-
601 QPoint p = extPrev;-
602 if (needsClipping[prev]) {-
603 for (;;) {-
604 QPoint rn((n.x() * rotation.x() - n.y() * rotation.y()) >> 14,-
605 (n.y() * rotation.x() + n.x() * rotation.y()) >> 14);-
606 n = rn;-
607 if (n.x() * normals.at(prev).y() - n.y() * normals.at(prev).x() <= 0) {-
608 p.rx() = vertices.at(prev).x() - normals.at(prev).x();-
609 p.ry() = vertices.at(prev).y() - normals.at(prev).y();-
610 drawTriangle<Clip>(bits.data(), imgWidth, imgHeight, &vertices.at(prev),-
611 &extPrev, &p, exteriorColor);-
612 break;-
613 }-
614-
615 p.rx() = vertices.at(prev).x() - n.x();-
616 p.ry() = vertices.at(prev).y() - n.y();-
617 drawTriangle<Clip>(bits.data(), imgWidth, imgHeight, &vertices.at(prev),-
618 &extPrev, &p, exteriorColor);-
619 extPrev = p;-
620 }-
621 } else {-
622 for (;;) {-
623 QPoint rn((n.x() * rotation.x() - n.y() * rotation.y()) >> 14,-
624 (n.y() * rotation.x() + n.x() * rotation.y()) >> 14);-
625 n = rn;-
626 if (n.x() * normals.at(prev).y() - n.y() * normals.at(prev).x() <= 0) {-
627 p.rx() = vertices.at(prev).x() - normals.at(prev).x();-
628 p.ry() = vertices.at(prev).y() - normals.at(prev).y();-
629 drawTriangle<NoClip>(bits.data(), imgWidth, imgHeight, &vertices.at(prev),-
630 &extPrev, &p, exteriorColor);-
631 break;-
632 }-
633-
634 p.rx() = vertices.at(prev).x() - n.x();-
635 p.ry() = vertices.at(prev).y() - n.y();-
636 drawTriangle<NoClip>(bits.data(), imgWidth, imgHeight, &vertices.at(prev),-
637 &extPrev, &p, exteriorColor);-
638 extPrev = p;-
639 }-
640 }-
641 } else {-
642 QPoint p = intPrev;-
643 if (needsClipping[prev]) {-
644 for (;;) {-
645 QPoint rn((n.x() * rotation.x() + n.y() * rotation.y()) >> 14,-
646 (n.y() * rotation.x() - n.x() * rotation.y()) >> 14);-
647 n = rn;-
648 if (n.x() * normals.at(prev).y() - n.y() * normals.at(prev).x() >= 0) {-
649 p.rx() = vertices.at(prev).x() + normals.at(prev).x();-
650 p.ry() = vertices.at(prev).y() + normals.at(prev).y();-
651 drawTriangle<Clip>(bits.data(), imgWidth, imgHeight, &vertices.at(prev),-
652 &p, &intPrev, interiorColor);-
653 break;-
654 }-
655-
656 p.rx() = vertices.at(prev).x() + n.x();-
657 p.ry() = vertices.at(prev).y() + n.y();-
658 drawTriangle<Clip>(bits.data(), imgWidth, imgHeight, &vertices.at(prev),-
659 &p, &intPrev, interiorColor);-
660 intPrev = p;-
661 }-
662 } else {-
663 for (;;) {-
664 QPoint rn((n.x() * rotation.x() + n.y() * rotation.y()) >> 14,-
665 (n.y() * rotation.x() - n.x() * rotation.y()) >> 14);-
666 n = rn;-
667 if (n.x() * normals.at(prev).y() - n.y() * normals.at(prev).x() >= 0) {-
668 p.rx() = vertices.at(prev).x() + normals.at(prev).x();-
669 p.ry() = vertices.at(prev).y() + normals.at(prev).y();-
670 drawTriangle<NoClip>(bits.data(), imgWidth, imgHeight, &vertices.at(prev),-
671 &p, &intPrev, interiorColor);-
672 break;-
673 }-
674-
675 p.rx() = vertices.at(prev).x() + n.x();-
676 p.ry() = vertices.at(prev).y() + n.y();-
677 drawTriangle<NoClip>(bits.data(), imgWidth, imgHeight, &vertices.at(prev),-
678 &p, &intPrev, interiorColor);-
679 intPrev = p;-
680 }-
681 }-
682 }-
683 }-
684-
685 index = end + 1;-
686 }-
687-
688 const qint32 *inLine = bits.data();-
689 uchar *outLine = data->data;-
690 for (int y = 0; y < imgHeight; ++y) {-
691 for (int x = 0; x < imgWidth; ++x, ++inLine, ++outLine)-
692 *outLine = uchar((0x7f80 - *inLine) >> 8);-
693 }-
694}-
695-
696static bool imageHasNarrowOutlines(const QImage &im)-
697{-
698 if (im.isNull() || im.width() < 1 || im.height() < 1)-
699 return false;-
700 else if (im.width() == 1 || im.height() == 1)-
701 return true;-
702-
703 int minHThick = 999;-
704 int minVThick = 999;-
705-
706 int thick = 0;-
707 bool in = false;-
708 int y = (im.height() + 1) / 2;-
709 for (int x = 0; x < im.width(); ++x) {-
710 int a = qAlpha(im.pixel(x, y));-
711 if (a > 127) {-
712 in = true;-
713 ++thick;-
714 } else if (in) {-
715 in = false;-
716 minHThick = qMin(minHThick, thick);-
717 thick = 0;-
718 }-
719 }-
720-
721 thick = 0;-
722 in = false;-
723 int x = (im.width() + 1) / 2;-
724 for (int y = 0; y < im.height(); ++y) {-
725 int a = qAlpha(im.pixel(x, y));-
726 if (a > 127) {-
727 in = true;-
728 ++thick;-
729 } else if (in) {-
730 in = false;-
731 minVThick = qMin(minVThick, thick);-
732 thick = 0;-
733 }-
734 }-
735-
736 return minHThick == 1 || minVThick == 1;-
737}-
738-
739bool qt_fontHasNarrowOutlines(QFontEngine *fontEngine)-
740{-
741 QFontEngine *fe = fontEngine->cloneWithSize(QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE);-
742 if (!fe)-
743 return false;-
744-
745 QImage im;-
746-
747 const glyph_t glyph = fe->glyphIndex('O');-
748 if (glyph != 0)-
749 im = fe->alphaMapForGlyph(glyph, QFixed(), QTransform());-
750-
751 Q_ASSERT(fe->ref.load() == 0);-
752 delete fe;-
753-
754 return imageHasNarrowOutlines(im);-
755}-
756-
757bool qt_fontHasNarrowOutlines(const QRawFont &f)-
758{-
759 QRawFont font = f;-
760 font.setPixelSize(QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE);-
761 if (!font.isValid())-
762 return false;-
763-
764 QVector<quint32> glyphIndices = font.glyphIndexesForString(QLatin1String("O"));-
765 if (glyphIndices.isEmpty() || glyphIndices[0] == 0)-
766 return false;-
767-
768 return imageHasNarrowOutlines(font.alphaMapForGlyph(glyphIndices.at(0),-
769 QRawFont::PixelAntialiasing));-
770}-
771-
772-
773QDistanceFieldData::QDistanceFieldData(const QDistanceFieldData &other)-
774 : QSharedData(other)-
775 , glyph(other.glyph)-
776 , width(other.width)-
777 , height(other.height)-
778 , nbytes(other.nbytes)-
779{-
780 if (nbytes && other.data)-
781 data = (uchar *)memcpy(malloc(nbytes), other.data, nbytes);-
782 else-
783 data = 0;-
784}-
785-
786QDistanceFieldData::~QDistanceFieldData()-
787{-
788 free(data);-
789}-
790-
791QDistanceFieldData *QDistanceFieldData::create(const QSize &size)-
792{-
793 QDistanceFieldData *data = new QDistanceFieldData;-
794-
795 if (size.isValid()) {-
796 data->width = size.width();-
797 data->height = size.height();-
798 // pixel data stored as a 1-byte alpha value-
799 data->nbytes = data->width * data->height; // tightly packed-
800 data->data = (uchar *)malloc(data->nbytes);-
801 }-
802-
803 return data;-
804}-
805-
806QDistanceFieldData *QDistanceFieldData::create(const QPainterPath &path, bool doubleResolution)-
807{-
808 int dfMargin = QT_DISTANCEFIELD_RADIUS(doubleResolution) / QT_DISTANCEFIELD_SCALE(doubleResolution);-
809 int glyphWidth = qCeil(path.boundingRect().width() / QT_DISTANCEFIELD_SCALE(doubleResolution)) + dfMargin * 2;-
810 int glyphHeight = qCeil(path.boundingRect().height() / QT_DISTANCEFIELD_SCALE(doubleResolution)) + dfMargin * 2;-
811-
812 QDistanceFieldData *data = create(QSize(glyphWidth, glyphHeight));-
813-
814 makeDistanceField(data,-
815 path,-
816 QT_DISTANCEFIELD_SCALE(doubleResolution),-
817 QT_DISTANCEFIELD_RADIUS(doubleResolution) / QT_DISTANCEFIELD_SCALE(doubleResolution));-
818 return data;-
819}-
820-
821-
822QDistanceField::QDistanceField()-
823 : d(new QDistanceFieldData)-
824{-
825}-
826-
827QDistanceField::QDistanceField(int width, int height)-
828 : d(QDistanceFieldData::create(QSize(width, height)))-
829{-
830}-
831-
832QDistanceField::QDistanceField(const QDistanceField &other)-
833{-
834 d = other.d;-
835}-
836-
837QDistanceField::QDistanceField(const QRawFont &font, glyph_t glyph, bool doubleResolution)-
838{-
839 setGlyph(font, glyph, doubleResolution);-
840}-
841-
842QDistanceField::QDistanceField(QFontEngine *fontEngine, glyph_t glyph, bool doubleResolution)-
843{-
844 setGlyph(fontEngine, glyph, doubleResolution);-
845}-
846-
847QDistanceField::QDistanceField(const QPainterPath &path, glyph_t glyph, bool doubleResolution)-
848{-
849 QPainterPath dfPath = path;-
850 dfPath.translate(-dfPath.boundingRect().topLeft());-
851 dfPath.setFillRule(Qt::WindingFill);-
852-
853 d = QDistanceFieldData::create(dfPath, doubleResolution);-
854 d->glyph = glyph;-
855}-
856-
857-
858QDistanceField::QDistanceField(QDistanceFieldData *data)-
859 : d(data)-
860{-
861}-
862-
863bool QDistanceField::isNull() const-
864{-
865 return !d->data;-
866}-
867-
868glyph_t QDistanceField::glyph() const-
869{-
870 return d->glyph;-
871}-
872-
873void QDistanceField::setGlyph(const QRawFont &font, glyph_t glyph, bool doubleResolution)-
874{-
875 QRawFont renderFont = font;-
876 renderFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(doubleResolution) * QT_DISTANCEFIELD_SCALE(doubleResolution));-
877-
878 QPainterPath path = renderFont.pathForGlyph(glyph);-
879 path.translate(-path.boundingRect().topLeft());-
880 path.setFillRule(Qt::WindingFill);-
881-
882 d = QDistanceFieldData::create(path, doubleResolution);-
883 d->glyph = glyph;-
884}-
885-
886void QDistanceField::setGlyph(QFontEngine *fontEngine, glyph_t glyph, bool doubleResolution)-
887{-
888 QFixedPoint position;-
889 QPainterPath path;-
890 fontEngine->addGlyphsToPath(&glyph, &position, 1, &path, 0);-
891 path.translate(-path.boundingRect().topLeft());-
892 path.setFillRule(Qt::WindingFill);-
893-
894 d = QDistanceFieldData::create(path, doubleResolution);-
895 d->glyph = glyph;-
896}-
897-
898int QDistanceField::width() const-
899{-
900 return d->width;-
901}-
902-
903int QDistanceField::height() const-
904{-
905 return d->height;-
906}-
907-
908QDistanceField QDistanceField::copy(const QRect &r) const-
909{-
910 if (isNull())-
911 return QDistanceField();-
912-
913 if (r.isNull())-
914 return QDistanceField(new QDistanceFieldData(*d));-
915-
916 int x = r.x();-
917 int y = r.y();-
918 int w = r.width();-
919 int h = r.height();-
920-
921 int dx = 0;-
922 int dy = 0;-
923 if (w <= 0 || h <= 0)-
924 return QDistanceField();-
925-
926 QDistanceField df(w, h);-
927 if (df.isNull())-
928 return df;-
929-
930 if (x < 0 || y < 0 || x + w > d->width || y + h > d->height) {-
931 memset(df.d->data, 0, df.d->nbytes);-
932 if (x < 0) {-
933 dx = -x;-
934 x = 0;-
935 }-
936 if (y < 0) {-
937 dy = -y;-
938 y = 0;-
939 }-
940 }-
941-
942 int pixels_to_copy = qMax(w - dx, 0);-
943 if (x > d->width)-
944 pixels_to_copy = 0;-
945 else if (pixels_to_copy > d->width - x)-
946 pixels_to_copy = d->width - x;-
947 int lines_to_copy = qMax(h - dy, 0);-
948 if (y > d->height)-
949 lines_to_copy = 0;-
950 else if (lines_to_copy > d->height - y)-
951 lines_to_copy = d->height - y;-
952-
953 const uchar *src = d->data + x + y * d->width;-
954 uchar *dest = df.d->data + dx + dy * df.d->width;-
955 for (int i = 0; i < lines_to_copy; ++i) {-
956 memcpy(dest, src, pixels_to_copy);-
957 src += d->width;-
958 dest += df.d->width;-
959 }-
960-
961 df.d->glyph = d->glyph;-
962-
963 return df;-
964}-
965-
966uchar *QDistanceField::bits()-
967{-
968 return d->data;-
969}-
970-
971const uchar *QDistanceField::bits() const-
972{-
973 return d->data;-
974}-
975-
976const uchar *QDistanceField::constBits() const-
977{-
978 return d->data;-
979}-
980-
981uchar *QDistanceField::scanLine(int i)-
982{-
983 if (isNull())-
984 return 0;-
985-
986 Q_ASSERT(i >= 0 && i < d->height);-
987 return d->data + i * d->width;-
988}-
989-
990const uchar *QDistanceField::scanLine(int i) const-
991{-
992 if (isNull())-
993 return 0;-
994-
995 Q_ASSERT(i >= 0 && i < d->height);-
996 return d->data + i * d->width;-
997}-
998-
999const uchar *QDistanceField::constScanLine(int i) const-
1000{-
1001 if (isNull())-
1002 return 0;-
1003-
1004 Q_ASSERT(i >= 0 && i < d->height);-
1005 return d->data + i * d->width;-
1006}-
1007-
1008QImage QDistanceField::toImage(QImage::Format format) const-
1009{-
1010 if (isNull())-
1011 return QImage();-
1012-
1013 QImage image(d->width, d->height, qt_depthForFormat(format) == 8 ?-
1014 format : QImage::Format_ARGB32_Premultiplied);-
1015 if (image.isNull())-
1016 return image;-
1017-
1018 if (image.depth() == 8) {-
1019 for (int y = 0; y < d->height; ++y)-
1020 memcpy(image.scanLine(y), scanLine(y), d->width);-
1021 } else {-
1022 for (int y = 0; y < d->height; ++y) {-
1023 for (int x = 0; x < d->width; ++x) {-
1024 uint alpha = *(d->data + x + y * d->width);-
1025 image.setPixel(x, y, alpha << 24);-
1026 }-
1027 }-
1028-
1029 if (image.format() != format)-
1030 image = image.convertToFormat(format);-
1031 }-
1032-
1033 return image;-
1034}-
1035-
1036QT_END_NAMESPACE-
1037-
Source codeSwitch to Preprocessed file

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