qoutlinemapper.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/painting/qoutlinemapper.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 "qoutlinemapper_p.h"-
41-
42#include<private/qpainterpath_p "qbezier_p.h>h"-
43#include "qmath.h"-
44#include<private/qbezier_p "qpainterpath_p.h>h"-
45-
46#include <stdlib.h>-
47-
48QT_BEGIN_NAMESPACE-
49-
50#define qreal_to_fixed_26_6(f) (qRound(f * 64))-
51-
52-
53-
54-
55static const QRectF boundingRect(const QPointF *points, int pointCount)-
56{-
57 const QPointF *e = points;-
58 const QPointF *last = points + pointCount;-
59 qreal minx, maxx, miny, maxy;-
60 minx = maxx = e->x();-
61 miny = maxy = e->y();-
62 while (++e < last) {-
63 if (e->x() < minx)-
64 minx = e->x();-
65 else if (e->x() > maxx)-
66 maxx = e->x();-
67 if (e->y() < miny)-
68 miny = e->y();-
69 else if (e->y() > maxy)-
70 maxy = e->y();-
71 }-
72 return QRectF(QPointF(minx, miny), QPointF(maxx, maxy));-
73}-
74-
75void QOutlineMapper::curveTo(const QPointF &cp1, const QPointF &cp2, const QPointF &ep) {-
76#ifdef QT_DEBUG_CONVERT-
77 printf("QOutlineMapper::curveTo() (%f, %f)\n", ep.x(), ep.y());-
78#endif-
79-
80 QBezier bezier = QBezier::fromPoints(m_elements.last(), cp1, cp2, ep);-
81-
82 bool outsideClip = false;-
83 // Test one point first before doing a full intersection test.-
84
!QRectF(m_clip...sform.map(ep))Description
TRUEnever evaluated
FALSEnever evaluated
if (!QRectF(m_clip_rect).contains(m_transform.map(ep))) {
!QRectF(m_clip...sform.map(ep))Description
TRUEnever evaluated
FALSEnever evaluated
0
85 QRectF potentialCurveArea = m_transform.mapRect(bezier.bounds());-
86 outsideClip = !potentialCurveArea.intersects(m_clip_rect);-
87 }
never executed: end of block
0
88 if (outsideClip) {
outsideClipDescription
TRUEnever evaluated
FALSEnever evaluated
0
89 // The curve is entirely outside the clip rect, so just-
90 // approximate it with a line that closes the path.-
91 lineTo(ep);-
92 } else {
never executed: end of block
0
93 bezier.addToPolygon(m_elements, m_curve_threshold);-
94 m_element_types.reserve(m_elements.size());-
95 for (int i = m_elements.size() - m_element_types.size(); i; --i)
iDescription
TRUEnever evaluated
FALSEnever evaluated
0
96 m_element_types << QPainterPath::LineToElement;
never executed: m_element_types << QPainterPath::LineToElement;
0
97 }
never executed: end of block
0
98 Q_ASSERT(m_elements.size() == m_element_types.size());-
99}
never executed: end of block
0
100-
101-
102QT_FT_Outline *QOutlineMapper::convertPath(const QPainterPath &path)-
103{-
104 Q_ASSERT(!path.isEmpty());-
105 int elmCount = path.elementCount();-
106#ifdef QT_DEBUG_CONVERT-
107 printf("QOutlineMapper::convertPath(), size=%d\n", elmCount);-
108#endif-
109 beginOutline(path.fillRule());-
110-
111 for (int index=0; index<elmCount; ++index) {-
112 const QPainterPath::Element &elm = path.elementAt(index);-
113-
114 switch (elm.type) {-
115-
116 case QPainterPath::MoveToElement:-
117 if (index == elmCount - 1)-
118 continue;-
119 moveTo(elm);-
120 break;-
121-
122 case QPainterPath::LineToElement:-
123 lineTo(elm);-
124 break;-
125-
126 case QPainterPath::CurveToElement:-
127 curveTo(elm, path.elementAt(index + 1), path.elementAt(index + 2));-
128 index += 2;-
129 break;-
130-
131 default:-
132 break; // This will never hit..-
133 }-
134 }-
135-
136 endOutline();-
137 return outline();-
138}-
139-
140QT_FT_Outline *QOutlineMapper::convertPath(const QVectorPath &path)-
141{-
142 int count = path.elementCount();-
143-
144#ifdef QT_DEBUG_CONVERT-
145 printf("QOutlineMapper::convertPath(VP), size=%d\n", count);-
146#endif-
147 beginOutline(path.hasWindingFill() ? Qt::WindingFill : Qt::OddEvenFill);-
148-
149 if (path.elements()) {-
150 // TODO: if we do closing of subpaths in convertElements instead we-
151 // could avoid this loop-
152 const QPainterPath::ElementType *elements = path.elements();-
153 const QPointF *points = reinterpret_cast<const QPointF *>(path.points());-
154-
155 for (int index = 0; index < count; ++index) {-
156 switch (elements[index]) {-
157 case QPainterPath::MoveToElement:-
158 if (index == count - 1)-
159 continue;-
160 moveTo(points[index]);-
161 break;-
162-
163 case QPainterPath::LineToElement:-
164 lineTo(points[index]);-
165 break;-
166-
167 case QPainterPath::CurveToElement:-
168 curveTo(points[index], points[index+1], points[index+2]);-
169 index += 2;-
170 break;-
171-
172 default:-
173 break; // This will never hit..-
174 }-
175 }-
176-
177 } else {-
178 // ### We can kill this copying and just use the buffer straight...-
179-
180 m_elements.resize(count);-
181 if (count)-
182 memcpy(m_elements.data(), path.points(), count* sizeof(QPointF));-
183-
184 m_element_types.resize(0);-
185 }-
186-
187 endOutline();-
188 return outline();-
189}-
190-
191-
192void QOutlineMapper::endOutline()-
193{-
194 closeSubpath();-
195-
196 if (m_elements.isEmpty()) {
m_elements.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
197 memset(&m_outline, 0, sizeof(m_outline));-
198 return;
never executed: return;
0
199 }-
200-
201 QPointF *elements = m_elements.data();-
202-
203 // Transform the outline-
204 if (m_txop == QTransform::TxNone)m_transform.isIdentity()) {
m_transform.isIdentity()Description
TRUEnever evaluated
FALSEnever evaluated
0
205 // Nothing to do-
206 } else if (m_txop == QTransform::TxTranslate) {
never executed: end of block
m_transform.ty...orm::TxProjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
for (int i = 0; i < m_elements.size(); ++i) {
never executed: end of block
m_transform.ty...orm::TxProjectDescription
TRUEnever evaluated
FALSEnever evaluated
QPointF &e = elements[i];
never executed: end of block
m_transform.ty...orm::TxProjectDescription
TRUEnever evaluated
FALSEnever evaluated
e = QPointF
never executed: end of block
m_transform.ty...orm::TxProjectDescription
TRUEnever evaluated
FALSEnever evaluated
(e.x() + m_dx, em_transform.ytype() + m_dy);
never executed: end of block
m_transform.ty...orm::TxProjectDescription
TRUEnever evaluated
FALSEnever evaluated
}
never executed: end of block
m_transform.ty...orm::TxProjectDescription
TRUEnever evaluated
FALSEnever evaluated
} else if (m_txop ==
never executed: end of block
m_transform.ty...orm::TxProjectDescription
TRUEnever evaluated
FALSEnever evaluated
< QTransform::TxScaleTxProject) {
never executed: end of block
m_transform.ty...orm::TxProjectDescription
TRUEnever evaluated
FALSEnever evaluated
207 for (int i = 0; i < m_elements.size(); ++i)
i < m_elements.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
208 {
never executed: elements[i] = m_transform.map(elements[i]);
0
QPointF &e =
never executed: elements[i] = m_transform.map(elements[i]);
elements[i];
never executed: elements[i] = m_transform.map(elements[i]);
e
never executed: elements[i] = m_transform.map(elements[i]);
] = QPointF(m_m11 * e.x() + m_dx, m_m22 * em_transform.y() + m_dy);
never executed: elements[i] = m_transform.map(elements[i]);
}
never executed: elements[i] = m_transform.map(elements[i]);
} else if (m_txop < QTransform::TxProject) {
never executed: elements[i] = m_transform.map(elements[i]);
for
never executed: elements[i] = m_transform.map(elements[i]);
map(int i = 0; i < m_elements.size(); ++i) {
never executed: elements[i] = m_transform.map(elements[i]);
QPointF &e =
never executed: elements[i] = m_transform.map(elements[i]);
elements[i];
never executed: elements[i] = m_transform.map(elements[i]);
e = QPointF(m_m11 * e.x() + m_m21 * e.y() + m_dx,
never executed: elements[i] = m_transform.map(elements[i]);
m_m22 * e.y() + m_m12 * e.x() + m_dy);
never executed: elements[i] = m_transform.map(elements[i]);
}
never executed: elements[i] = m_transform.map(elements[i]);
]);
never executed: elements[i] = m_transform.map(elements[i]);
209 } else {
never executed: end of block
0
210 const QVectorPath vp((qreal *)elements, m_elements.size(),-
211 m_element_types.size() ? m_element_types.data() : 0);-
212 QPainterPath path = vp.convertToPainterPath();-
213 path = QTransform(m_m11, m_m12, m_m13, m_m21, m_m22, m_m23, m_dx, m_dy, m_m33).m_transform.map(path);-
214 if (!(m_outline.flags & QT_FT_OUTLINE_EVEN_ODD_FILL))
!(m_outline.flags & 0x2)Description
TRUEnever evaluated
FALSEnever evaluated
0
215 path.setFillRule(Qt::WindingFill);
never executed: path.setFillRule(Qt::WindingFill);
0
216 uint old_txop = m_txop;
path.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
m_txop = QTransform::TxNone;
path.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
if (path.isEmpty()) {
path.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
217 m_valid = false;-
218 } else {
never executed: end of block
0
219 QTransform oldTransform = m_transform;-
220 m_transform.reset();-
221 convertPath(path);-
222 m_txopm_transform = old_txopoldTransform;-
223 }
never executed: end of block
0
224 return;
never executed: return;
0
225 }-
226-
227 controlPointRect = boundingRect(elements, m_elements.size());-
228-
229#ifdef QT_DEBUG_CONVERT-
230 printf(" - control point rect (%.2f, %.2f) %.2f x %.2f, clip=(%d,%d, %dx%d)\n",-
231 controlPointRect.x(), controlPointRect.y(),-
232 controlPointRect.width(), controlPointRect.height(),-
233 m_clip_rect.x(), m_clip_rect.y(), m_clip_rect.width(), m_clip_rect.height());-
234#endif-
235-
236-
237 // Check for out of dev bounds...-
238 const bool do_clip = !m_in_clip_elements && ((controlPointRect.left() < -QT_RASTER_COORD_LIMIT
!m_in_clip_elementsDescription
TRUEnever evaluated
FALSEnever evaluated
controlPointRe...ER_COORD_LIMITDescription
TRUEnever evaluated
FALSEnever evaluated
0
239 || controlPointRect.right() > QT_RASTER_COORD_LIMIT
controlPointRe...ER_COORD_LIMITDescription
TRUEnever evaluated
FALSEnever evaluated
0
240 || controlPointRect.top() < -QT_RASTER_COORD_LIMIT
controlPointRe...ER_COORD_LIMITDescription
TRUEnever evaluated
FALSEnever evaluated
0
241 || controlPointRect.bottom() > QT_RASTER_COORD_LIMIT
controlPointRe...ER_COORD_LIMITDescription
TRUEnever evaluated
FALSEnever evaluated
0
242 || controlPointRect.width() > QT_RASTER_COORD_LIMIT
controlPointRe...ER_COORD_LIMITDescription
TRUEnever evaluated
FALSEnever evaluated
0
243 || controlPointRect.height() > QT_RASTER_COORD_LIMIT));
controlPointRe...ER_COORD_LIMITDescription
TRUEnever evaluated
FALSEnever evaluated
0
244-
245 if (do_clip) {
do_clipDescription
TRUEnever evaluated
FALSEnever evaluated
0
246 clipElements(elements, elementTypes(), m_elements.size());-
247 } else {
never executed: end of block
0
248 convertElements(elements, elementTypes(), m_elements.size());-
249 }
never executed: end of block
0
250}-
251-
252void QOutlineMapper::convertElements(const QPointF *elements,-
253 const QPainterPath::ElementType *types,-
254 int element_count)-
255{-
256-
257 if (types) {-
258 // Translate into FT coords-
259 const QPointF *e = elements;-
260 for (int i=0; i<element_count; ++i) {-
261 switch (*types) {-
262 case QPainterPath::MoveToElement:-
263 {-
264 QT_FT_Vector pt_fixed = { qreal_to_fixed_26_6(e->x()),-
265 qreal_to_fixed_26_6(e->y()) };-
266 if (i != 0)-
267 m_contours << m_points.size() - 1;-
268 m_points << pt_fixed;-
269 m_tags << QT_FT_CURVE_TAG_ON;-
270 }-
271 break;-
272-
273 case QPainterPath::LineToElement:-
274 {-
275 QT_FT_Vector pt_fixed = { qreal_to_fixed_26_6(e->x()),-
276 qreal_to_fixed_26_6(e->y()) };-
277 m_points << pt_fixed;-
278 m_tags << QT_FT_CURVE_TAG_ON;-
279 }-
280 break;-
281-
282 case QPainterPath::CurveToElement:-
283 {-
284 QT_FT_Vector cp1_fixed = { qreal_to_fixed_26_6(e->x()),-
285 qreal_to_fixed_26_6(e->y()) };-
286 ++e;-
287 QT_FT_Vector cp2_fixed = { qreal_to_fixed_26_6((e)->x()),-
288 qreal_to_fixed_26_6((e)->y()) };-
289 ++e;-
290 QT_FT_Vector ep_fixed = { qreal_to_fixed_26_6((e)->x()),-
291 qreal_to_fixed_26_6((e)->y()) };-
292-
293 m_points << cp1_fixed << cp2_fixed << ep_fixed;-
294 m_tags << QT_FT_CURVE_TAG_CUBIC-
295 << QT_FT_CURVE_TAG_CUBIC-
296 << QT_FT_CURVE_TAG_ON;-
297-
298 types += 2;-
299 i += 2;-
300 }-
301 break;-
302 default:-
303 break;-
304 }-
305 ++types;-
306 ++e;-
307 }-
308 } else {-
309 // Plain polygon...-
310 const QPointF *last = elements + element_count;-
311 const QPointF *e = elements;-
312 while (e < last) {-
313 QT_FT_Vector pt_fixed = { qreal_to_fixed_26_6(e->x()),-
314 qreal_to_fixed_26_6(e->y()) };-
315 m_points << pt_fixed;-
316 m_tags << QT_FT_CURVE_TAG_ON;-
317 ++e;-
318 }-
319 }-
320-
321 // close the very last subpath-
322 m_contours << m_points.size() - 1;-
323-
324 m_outline.n_contours = m_contours.size();-
325 m_outline.n_points = m_points.size();-
326-
327 m_outline.points = m_points.data();-
328 m_outline.tags = m_tags.data();-
329 m_outline.contours = m_contours.data();-
330-
331#ifdef QT_DEBUG_CONVERT-
332 printf("QOutlineMapper::endOutline\n");-
333-
334 printf(" - contours: %d\n", m_outline.n_contours);-
335 for (int i=0; i<m_outline.n_contours; ++i) {-
336 printf(" - %d\n", m_outline.contours[i]);-
337 }-
338-
339 printf(" - points: %d\n", m_outline.n_points);-
340 for (int i=0; i<m_outline.n_points; ++i) {-
341 printf(" - %d -- %.2f, %.2f, (%d, %d)\n", i,-
342 (double) (m_outline.points[i].x / 64.0),-
343 (double) (m_outline.points[i].y / 64.0),-
344 (int) m_outline.points[i].x, (int) m_outline.points[i].y);-
345 }-
346#endif-
347}-
348-
349void QOutlineMapper::clipElements(const QPointF *elements,-
350 const QPainterPath::ElementType *types,-
351 int element_count)-
352{-
353 // We could save a bit of time by actually implementing them fully-
354 // instead of going through convenience functionallity, but since-
355 // this part of code hardly every used, it shouldn't matter.-
356-
357 m_in_clip_elements = true;-
358-
359 QPainterPath path;-
360-
361 if (!(m_outline.flags & QT_FT_OUTLINE_EVEN_ODD_FILL))
!(m_outline.flags & 0x2)Description
TRUEnever evaluated
FALSEnever evaluated
0
362 path.setFillRule(Qt::WindingFill);
never executed: path.setFillRule(Qt::WindingFill);
0
363-
364 if (types) {
typesDescription
TRUEnever evaluated
FALSEnever evaluated
0
365 for (int i=0; i<element_count; ++i) {
i<element_countDescription
TRUEnever evaluated
FALSEnever evaluated
0
366 switch (types[i]) {-
367 case QPainterPath::MoveToElement:
never executed: case QPainterPath::MoveToElement:
0
368 path.moveTo(elements[i]);-
369 break;
never executed: break;
0
370-
371 case QPainterPath::LineToElement:
never executed: case QPainterPath::LineToElement:
0
372 path.lineTo(elements[i]);-
373 break;
never executed: break;
0
374-
375 case QPainterPath::CurveToElement:
never executed: case QPainterPath::CurveToElement:
0
376 path.cubicTo(elements[i], elements[i+1], elements[i+2]);-
377 i += 2;-
378 break;
never executed: break;
0
379 default:
never executed: default:
0
380 break;
never executed: break;
0
381 }-
382 }-
383 } else {
never executed: end of block
0
384 path.moveTo(elements[0]);-
385 for (int i=1; i<element_count; ++i)
i<element_countDescription
TRUEnever evaluated
FALSEnever evaluated
0
386 path.lineTo(elements[i]);
never executed: path.lineTo(elements[i]);
0
387 }
never executed: end of block
0
388-
389 QPainterPath clipPath;-
390 clipPath.addRect(m_clip_rect);-
391 QPainterPath clippedPath = path.intersected(clipPath);-
392 uint old_txop = m_txop;
clippedPath.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
m_txop = QTransform::TxNone;
clippedPath.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
if (clippedPath.isEmpty()) {
clippedPath.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
393 m_valid = false;-
394 } else {
never executed: end of block
0
395 QTransform oldTransform = m_transform;-
396 m_transform.reset();-
397 convertPath(clippedPath);-
398 m_txopm_transform = old_txopoldTransform;-
399 }
never executed: end of block
0
400-
401 m_in_clip_elements = false;-
402}
never executed: end of block
0
403-
404QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

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