Qt 4.8
qoutlinemapper.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qoutlinemapper_p.h"
43 #include <private/qpainterpath_p.h>
44 #include "qmath.h"
45 
46 #include <stdlib.h>
47 
49 
50 static const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
51 
52 #define qreal_to_fixed_26_6(f) (int(f * 64))
53 
54 
55 
56 
57 static const QRectF boundingRect(const QPointF *points, int pointCount)
58 {
59  const QPointF *e = points;
60  const QPointF *last = points + pointCount;
61  qreal minx, maxx, miny, maxy;
62  minx = maxx = e->x();
63  miny = maxy = e->y();
64  while (++e < last) {
65  if (e->x() < minx)
66  minx = e->x();
67  else if (e->x() > maxx)
68  maxx = e->x();
69  if (e->y() < miny)
70  miny = e->y();
71  else if (e->y() > maxy)
72  maxy = e->y();
73  }
74  return QRectF(QPointF(minx, miny), QPointF(maxx, maxy));
75 }
76 
77 
79 {
80  Q_ASSERT(!path.isEmpty());
81  int elmCount = path.elementCount();
82 #ifdef QT_DEBUG_CONVERT
83  printf("QOutlineMapper::convertPath(), size=%d\n", elmCount);
84 #endif
85  beginOutline(path.fillRule());
86 
87  for (int index=0; index<elmCount; ++index) {
88  const QPainterPath::Element &elm = path.elementAt(index);
89 
90  switch (elm.type) {
91 
93  if (index == elmCount - 1)
94  continue;
95  moveTo(elm);
96  break;
97 
99  lineTo(elm);
100  break;
101 
103  curveTo(elm, path.elementAt(index + 1), path.elementAt(index + 2));
104  index += 2;
105  break;
106 
107  default:
108  break; // This will never hit..
109  }
110  }
111 
112  endOutline();
113  return outline();
114 }
115 
117 {
118  int count = path.elementCount();
119 
120 #ifdef QT_DEBUG_CONVERT
121  printf("QOutlineMapper::convertPath(VP), size=%d\n", count);
122 #endif
124 
125  if (path.elements()) {
126  // TODO: if we do closing of subpaths in convertElements instead we
127  // could avoid this loop
129  const QPointF *points = reinterpret_cast<const QPointF *>(path.points());
130 
131  for (int index = 0; index < count; ++index) {
132  switch (elements[index]) {
134  if (index == count - 1)
135  continue;
136  moveTo(points[index]);
137  break;
138 
140  lineTo(points[index]);
141  break;
142 
144  curveTo(points[index], points[index+1], points[index+2]);
145  index += 2;
146  break;
147 
148  default:
149  break; // This will never hit..
150  }
151  }
152 
153  } else {
154  // ### We can kill this copying and just use the buffer straight...
155 
156  m_elements.resize(count);
157  if (count)
158  memcpy(m_elements.data(), path.points(), count* sizeof(QPointF));
159 
161  }
162 
163  endOutline();
164  return outline();
165 }
166 
167 
169 {
170  closeSubpath();
171 
172  int element_count = m_elements.size();
173 
174  if (element_count == 0) {
175  memset(&m_outline, 0, sizeof(m_outline));
176  return;
177  }
178 
179  QPointF *elements;
180 
181  // Transform the outline
182  if (m_txop == QTransform::TxNone) {
183  elements = m_elements.data();
184  } else {
186  for (int i=0; i<m_elements.size(); ++i) {
187  const QPointF &e = m_elements.at(i);
188  m_elements_dev << QPointF(e.x() + m_dx, e.y() + m_dy);
189  }
190  } else if (m_txop == QTransform::TxScale) {
191  for (int i=0; i<m_elements.size(); ++i) {
192  const QPointF &e = m_elements.at(i);
193  m_elements_dev << QPointF(m_m11 * e.x() + m_dx, m_m22 * e.y() + m_dy);
194  }
195  } else if (m_txop < QTransform::TxProject) {
196  for (int i=0; i<m_elements.size(); ++i) {
197  const QPointF &e = m_elements.at(i);
198  m_elements_dev << QPointF(m_m11 * e.x() + m_m21 * e.y() + m_dx,
199  m_m22 * e.y() + m_m12 * e.x() + m_dy);
200  }
201  } else {
203  QPainterPath path = vp.convertToPainterPath();
204  path = QTransform(m_m11, m_m12, m_m13, m_m21, m_m22, m_m23, m_dx, m_dy, m_m33).map(path);
206  path.setFillRule(Qt::WindingFill);
207  uint old_txop = m_txop;
209  if (path.isEmpty())
210  m_valid = false;
211  else
212  convertPath(path);
213  m_txop = old_txop;
214  return;
215  }
216  elements = m_elements_dev.data();
217  }
218 
219  controlPointRect = boundingRect(elements, element_count);
220 
221 #ifdef QT_DEBUG_CONVERT
222  printf(" - control point rect (%.2f, %.2f) %.2f x %.2f, clip=(%d,%d, %dx%d)\n",
226 #endif
227 
228 
229  // Check for out of dev bounds...
230  const bool do_clip = !m_in_clip_elements && ((controlPointRect.left() < -QT_RASTER_COORD_LIMIT
236 
237  if (do_clip) {
238  clipElements(elements, elementTypes(), element_count);
239  } else {
240  convertElements(elements, elementTypes(), element_count);
241  }
242 }
243 
246  int element_count)
247 {
248 
249  if (types) {
250  // Translate into FT coords
251  const QPointF *e = elements;
252  for (int i=0; i<element_count; ++i) {
253  switch (*types) {
255  {
256  QT_FT_Vector pt_fixed = { qreal_to_fixed_26_6(e->x()),
257  qreal_to_fixed_26_6(e->y()) };
258  if (i != 0)
259  m_contours << m_points.size() - 1;
260  m_points << pt_fixed;
262  }
263  break;
264 
266  {
267  QT_FT_Vector pt_fixed = { qreal_to_fixed_26_6(e->x()),
268  qreal_to_fixed_26_6(e->y()) };
269  m_points << pt_fixed;
271  }
272  break;
273 
275  {
276  QT_FT_Vector cp1_fixed = { qreal_to_fixed_26_6(e->x()),
277  qreal_to_fixed_26_6(e->y()) };
278  ++e;
279  QT_FT_Vector cp2_fixed = { qreal_to_fixed_26_6((e)->x()),
280  qreal_to_fixed_26_6((e)->y()) };
281  ++e;
282  QT_FT_Vector ep_fixed = { qreal_to_fixed_26_6((e)->x()),
283  qreal_to_fixed_26_6((e)->y()) };
284 
285  m_points << cp1_fixed << cp2_fixed << ep_fixed;
289 
290  types += 2;
291  i += 2;
292  }
293  break;
294  default:
295  break;
296  }
297  ++types;
298  ++e;
299  }
300  } else {
301  // Plain polygon...
302  const QPointF *last = elements + element_count;
303  const QPointF *e = elements;
304  while (e < last) {
305  QT_FT_Vector pt_fixed = { qreal_to_fixed_26_6(e->x()),
306  qreal_to_fixed_26_6(e->y()) };
307  m_points << pt_fixed;
309  ++e;
310  }
311  }
312 
313  // close the very last subpath
314  m_contours << m_points.size() - 1;
315 
317  m_outline.n_points = m_points.size();
318 
319  m_outline.points = m_points.data();
322 
323 #ifdef QT_DEBUG_CONVERT
324  printf("QOutlineMapper::endOutline\n");
325 
326  printf(" - contours: %d\n", m_outline.n_contours);
327  for (int i=0; i<m_outline.n_contours; ++i) {
328  printf(" - %d\n", m_outline.contours[i]);
329  }
330 
331  printf(" - points: %d\n", m_outline.n_points);
332  for (int i=0; i<m_outline.n_points; ++i) {
333  printf(" - %d -- %.2f, %.2f, (%d, %d)\n", i,
334  (double) (m_outline.points[i].x / 64.0),
335  (double) (m_outline.points[i].y / 64.0),
336  (int) m_outline.points[i].x, (int) m_outline.points[i].y);
337  }
338 #endif
339 }
340 
343  int element_count)
344 {
345  // We could save a bit of time by actually implementing them fully
346  // instead of going through convenience functionallity, but since
347  // this part of code hardly every used, it shouldn't matter.
348 
349  m_in_clip_elements = true;
350 
351  QPainterPath path;
352 
355 
356  if (types) {
357  for (int i=0; i<element_count; ++i) {
358  switch (types[i]) {
360  path.moveTo(elements[i]);
361  break;
362 
364  path.lineTo(elements[i]);
365  break;
366 
368  path.cubicTo(elements[i], elements[i+1], elements[i+2]);
369  i += 2;
370  break;
371  default:
372  break;
373  }
374  }
375  } else {
376  path.moveTo(elements[0]);
377  for (int i=1; i<element_count; ++i)
378  path.lineTo(elements[i]);
379  }
380 
381  QPainterPath clipPath;
382  clipPath.addRect(m_clip_rect);
383  QPainterPath clippedPath = path.intersected(clipPath);
384  uint old_txop = m_txop;
386  if (clippedPath.isEmpty())
387  m_valid = false;
388  else
389  convertPath(clippedPath);
390  m_txop = old_txop;
391 
392  m_in_clip_elements = false;
393 }
394 
ElementType type
the type of element
Definition: qpainterpath.h:81
The QPainterPath::Element class specifies the position and type of a subpath.
Definition: qpainterpath.h:77
bool isEmpty() const
Returns true if either there are no elements in this path, or if the only element is a MoveToElement;...
Definition: qpainterpath.h:392
ElementType
This enum describes the types of elements used to connect vertices in subpaths.
Definition: qpainterpath.h:70
void curveTo(const QPointF &cp1, const QPointF &cp2, const QPointF &ep)
#define QT_FT_OUTLINE_EVEN_ODD_FILL
qreal y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:667
QT_FT_Outline m_outline
void lineTo(const QPointF &pt)
qreal right() const
Returns the x-coordinate of the rectangle&#39;s right edge.
Definition: qrect.h:527
#define QT_FT_CURVE_TAG_CUBIC
double qreal
Definition: qglobal.h:1193
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
#define QT_FT_CURVE_TAG_ON
int elementCount() const
#define qreal_to_fixed_26_6(f)
Type * data() const
Definition: qdatabuffer_p.h:84
The QPainterPath class provides a container for painting operations, enabling graphical shapes to be ...
Definition: qpainterpath.h:67
void moveTo(const QPointF &pt)
void resize(int size)
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
qreal left() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:525
QPainterPath intersected(const QPainterPath &r) const
Returns a path which is the intersection of this path&#39;s fill area and p&#39;s fill area.
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
static const qreal aliasedCoordinateDelta
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
QDataBuffer< QPointF > m_elements_dev
QDataBuffer< QT_FT_Vector > m_points
const QPainterPath::ElementType * elements() const
void moveTo(const QPointF &p)
Moves the current point to the given point, implicitly starting a new subpath and closing the previou...
const QPainterPath::Element & elementAt(int i) const
Returns the element at the given index in the painter path.
Definition: qpainterpath.h:402
QDataBuffer< char > m_tags
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
QT_FT_Outline * outline()
static const QRectF boundingRect(const QPointF *points, int pointCount)
void lineTo(const QPointF &p)
Adds a straight line from the current position to the given endPoint.
QPainterPath::ElementType * elementTypes() const
void setFillRule(Qt::FillRule fillRule)
Sets the fill rule of the painter path to the given fillRule.
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
The QRectF class defines a rectangle in the plane using floating point precision. ...
Definition: qrect.h:511
const int QT_RASTER_COORD_LIMIT
void convertElements(const QPointF *points, const QPainterPath::ElementType *types, int count)
qreal height() const
Returns the height of the rectangle.
Definition: qrect.h:710
QT_FT_Vector * points
QPoint map(const QPoint &p) const
Creates and returns a QPoint object that is a copy of the given point, mapped into the coordinate sys...
Type & at(int i)
Definition: qdatabuffer_p.h:86
unsigned int uint
Definition: qglobal.h:996
void addRect(const QRectF &rect)
Adds the given rectangle to this path as a closed subpath.
QDataBuffer< QPointF > m_elements
qreal width() const
Returns the width of the rectangle.
Definition: qrect.h:707
Qt::FillRule fillRule() const
Returns the painter path&#39;s currently set fill rule.
bool hasWindingFill() const
static const struct @32 types[]
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
qreal x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:664
void beginOutline(Qt::FillRule fillRule)
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
const qreal * points() const
QDataBuffer< QPainterPath::ElementType > m_element_types
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287
quint16 index
void cubicTo(const QPointF &ctrlPt1, const QPointF &ctrlPt2, const QPointF &endPt)
Adds a cubic Bezier curve between the current position and the given endPoint using the control point...
static const QTextHtmlElement elements[Html_NumElements]
qreal top() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:526
int elementCount() const
Returns the number of path elements in the painter path.
Definition: qpainterpath.h:397
qreal bottom() const
Returns the y-coordinate of the rectangle&#39;s bottom edge.
Definition: qrect.h:528
void clipElements(const QPointF *points, const QPainterPath::ElementType *types, int count)
QT_FT_Outline * convertPath(const QPainterPath &path)
QDataBuffer< int > m_contours
The QTransform class specifies 2D transformations of a coordinate system.
Definition: qtransform.h:65
int size() const
Definition: qdatabuffer_p.h:83