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 "qbezier_p.h"-
43#include "qmath.h"-
44#include "qpainterpath_p.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) {
++e < lastDescription
TRUEnever evaluated
FALSEnever evaluated
0
63 if (e->x() < minx)
e->x() < minxDescription
TRUEnever evaluated
FALSEnever evaluated
0
64 minx = e->x();
never executed: minx = e->x();
0
65 else if (e->x() > maxx)
e->x() > maxxDescription
TRUEnever evaluated
FALSEnever evaluated
0
66 maxx = e->x();
never executed: maxx = e->x();
0
67 if (e->y() < miny)
e->y() < minyDescription
TRUEnever evaluated
FALSEnever evaluated
0
68 miny = e->y();
never executed: miny = e->y();
0
69 else if (e->y() > maxy)
e->y() > maxyDescription
TRUEnever evaluated
FALSEnever evaluated
0
70 maxy = e->y();
never executed: maxy = e->y();
0
71 }
never executed: end of block
0
72 return QRectF(QPointF(minx, miny), QPointF(maxx, maxy));
never executed: return QRectF(QPointF(minx, miny), QPointF(maxx, maxy));
0
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 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) {
index<elmCountDescription
TRUEnever evaluated
FALSEnever evaluated
0
112 const QPainterPath::Element &elm = path.elementAt(index);-
113-
114 switch (elm.type) {-
115-
116 case QPainterPath::MoveToElement:
never executed: case QPainterPath::MoveToElement:
0
117 if (index == elmCount - 1)
index == elmCount - 1Description
TRUEnever evaluated
FALSEnever evaluated
0
118 continue;
never executed: continue;
0
119 moveTo(elm);-
120 break;
never executed: break;
0
121-
122 case QPainterPath::LineToElement:
never executed: case QPainterPath::LineToElement:
0
123 lineTo(elm);-
124 break;
never executed: break;
0
125-
126 case QPainterPath::CurveToElement:
never executed: case QPainterPath::CurveToElement:
0
127 curveTo(elm, path.elementAt(index + 1), path.elementAt(index + 2));-
128 index += 2;-
129 break;
never executed: break;
0
130-
131 default:
never executed: default:
0
132 break; // This will never hit..
never executed: break;
0
133 }-
134 }-
135-
136 endOutline();-
137 return outline();
never executed: return outline();
0
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()) {
path.elements()Description
TRUEnever evaluated
FALSEnever evaluated
0
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) {
index < countDescription
TRUEnever evaluated
FALSEnever evaluated
0
156 switch (elements[index]) {-
157 case QPainterPath::MoveToElement:
never executed: case QPainterPath::MoveToElement:
0
158 if (index == count - 1)
index == count - 1Description
TRUEnever evaluated
FALSEnever evaluated
0
159 continue;
never executed: continue;
0
160 moveTo(points[index]);-
161 break;
never executed: break;
0
162-
163 case QPainterPath::LineToElement:
never executed: case QPainterPath::LineToElement:
0
164 lineTo(points[index]);-
165 break;
never executed: break;
0
166-
167 case QPainterPath::CurveToElement:
never executed: case QPainterPath::CurveToElement:
0
168 curveTo(points[index], points[index+1], points[index+2]);-
169 index += 2;-
170 break;
never executed: break;
0
171-
172 default:
never executed: default:
0
173 break; // This will never hit..
never executed: break;
0
174 }-
175 }-
176-
177 } else {
never executed: end of block
0
178 // ### We can kill this copying and just use the buffer straight...-
179-
180 m_elements.resize(count);-
181 if (count)
countDescription
TRUEnever evaluated
FALSEnever evaluated
0
182 memcpy(m_elements.data(), path.points(), count* sizeof(QPointF));
never executed: memcpy(m_elements.data(), path.points(), count* sizeof(QPointF));
0
183-
184 m_element_types.resize(0);-
185 }
never executed: end of block
0
186-
187 endOutline();-
188 return outline();
never executed: return outline();
0
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_transform.isIdentity()) {
m_transform.isIdentity()Description
TRUEnever evaluated
FALSEnever evaluated
0
205 // Nothing to do-
206 } else if (m_transform.type() < QTransform::TxProject) {
never executed: end of block
m_transform.ty...orm::TxProjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
207 for (int i = 0; i < m_elements.size(); ++i)
i < m_elements.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
208 elements[i] = m_transform.map(elements[i]);
never executed: elements[i] = m_transform.map(elements[i]);
0
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 = 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 if (path.isEmpty()) {
path.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
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_transform = oldTransform;-
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) {
typesDescription
TRUEnever evaluated
FALSEnever evaluated
0
258 // Translate into FT coords-
259 const QPointF *e = elements;-
260 for (int i=0; i<element_count; ++i) {
i<element_countDescription
TRUEnever evaluated
FALSEnever evaluated
0
261 switch (*types) {-
262 case QPainterPath::MoveToElement:
never executed: case QPainterPath::MoveToElement:
0
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)
i != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
267 m_contours << m_points.size() - 1;
never executed: m_contours << m_points.size() - 1;
0
268 m_points << pt_fixed;-
269 m_tags << QT_FT_CURVE_TAG_ON;-
270 }-
271 break;
never executed: break;
0
272-
273 case QPainterPath::LineToElement:
never executed: case QPainterPath::LineToElement:
0
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;
never executed: break;
0
281-
282 case QPainterPath::CurveToElement:
never executed: case QPainterPath::CurveToElement:
0
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;
never executed: break;
0
302 default:
never executed: default:
0
303 break;
never executed: break;
0
304 }-
305 ++types;-
306 ++e;-
307 }
never executed: end of block
0
308 } else {
never executed: end of block
0
309 // Plain polygon...-
310 const QPointF *last = elements + element_count;-
311 const QPointF *e = elements;-
312 while (e < last) {
e < lastDescription
TRUEnever evaluated
FALSEnever evaluated
0
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 }
never executed: end of block
0
319 }
never executed: end of block
0
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}
never executed: end of block
0
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 if (clippedPath.isEmpty()) {
clippedPath.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
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_transform = oldTransform;-
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