20static const QRectF boundingRect(
const QPointF *points,
int pointCount)
22 const QPointF *e = points;
23 const QPointF *last = points + pointCount;
24 qreal minx, maxx, miny, maxy;
30 else if (e->x() > maxx)
34 else if (e->y() > maxy)
37 return QRectF(QPointF(minx, miny), QPointF(maxx, maxy));
42 auto limitCoords = [](QRect r) {
51 if (clipRect != m_clip_rect) {
52 m_clip_rect = limitCoords(clipRect);
53 const int mw = 1 << 10;
54 m_clip_trigger_rect = QRectF(limitCoords(m_clip_rect.adjusted(-mw, -mw, mw, mw)));
59#ifdef QT_DEBUG_CONVERT
60 printf(
"QOutlineMapper::curveTo() (%f, %f)\n", ep.x(), ep.y());
63 if (!m_elements.size())
65 QBezier bezier = QBezier::fromPoints(m_elements.last(), cp1, cp2, ep);
67 bool outsideClip =
false;
69 if (!QRectF(m_clip_rect).contains(m_transform.map(ep))) {
70 QRectF potentialCurveArea = m_transform.mapRect(bezier.bounds());
71 outsideClip = !potentialCurveArea.intersects(m_clip_rect);
78 bezier.addToPolygon(m_elements, m_curve_threshold);
79 m_element_types.reserve(m_elements.size());
80 for (
int i = m_elements.size() - m_element_types.size(); i; --i)
81 m_element_types << QPainterPath::LineToElement;
83 Q_ASSERT(m_elements.size() == m_element_types.size());
89 Q_ASSERT(!path.isEmpty());
90 int elmCount = path.elementCount();
91#ifdef QT_DEBUG_CONVERT
92 printf(
"QOutlineMapper::convertPath(), size=%d\n", elmCount);
94 beginOutline(path.fillRule());
96 for (
int index=0; index<elmCount; ++index) {
97 const QPainterPath::Element &elm = path.elementAt(index);
101 case QPainterPath::MoveToElement:
102 if (index == elmCount - 1)
107 case QPainterPath::LineToElement:
111 case QPainterPath::CurveToElement:
112 curveTo(elm, path.elementAt(index + 1), path.elementAt(index + 2));
127 int count = path.elementCount();
129#ifdef QT_DEBUG_CONVERT
130 printf(
"QOutlineMapper::convertPath(VP), size=%d\n", count);
132 beginOutline(path.hasWindingFill() ? Qt::WindingFill : Qt::OddEvenFill);
134 if (path.elements()) {
137 const QPainterPath::ElementType *elements = path.elements();
138 const QPointF *points =
reinterpret_cast<
const QPointF *>(path.points());
140 for (
int index = 0; index < count; ++index) {
141 switch (elements[index]) {
142 case QPainterPath::MoveToElement:
143 if (index == count - 1)
145 moveTo(points[index]);
148 case QPainterPath::LineToElement:
149 lineTo(points[index]);
152 case QPainterPath::CurveToElement:
153 curveTo(points[index], points[index+1], points[index+2]);
165 m_elements.resize(count);
167 memcpy(
static_cast<
void *>(m_elements.data()),
static_cast<
const void *>(path.points()), count*
sizeof(QPointF));
169 m_element_types.resize(0);
181 if (m_elements.isEmpty()) {
182 memset(&m_outline, 0,
sizeof(m_outline));
186 QPointF *elements = m_elements.data();
189 if (m_transform.isIdentity()) {
191 }
else if (m_transform.type() < QTransform::TxProject) {
192 for (
int i = 0; i < m_elements.size(); ++i)
193 elements[i] = m_transform.map(elements[i]);
195 const QVectorPath vp((qreal *)elements, m_elements.size(),
196 m_element_types.size() ? m_element_types.data() :
nullptr);
197 QPainterPath path = vp.convertToPainterPath();
198 path = m_transform.map(path);
199 if (!(m_outline.flags & QT_FT_OUTLINE_EVEN_ODD_FILL))
200 path.setFillRule(Qt::WindingFill);
201 if (path.isEmpty()) {
204 QTransform oldTransform = m_transform;
207 m_transform = oldTransform;
212 controlPointRect = boundingRect(elements, m_elements.size());
214#ifdef QT_DEBUG_CONVERT
215 printf(
" - control point rect (%.2f, %.2f) %.2f x %.2f, clip=(%d,%d, %dx%d)\n",
216 controlPointRect.x(), controlPointRect.y(),
217 controlPointRect.width(), controlPointRect.height(),
218 m_clip_rect.x(), m_clip_rect.y(), m_clip_rect.width(), m_clip_rect.height());
222 if (!m_in_clip_elements && !m_clip_trigger_rect.contains(controlPointRect)) {
223 clipElements(elements, elementTypes(), m_elements.size());
225 convertElements(elements, elementTypes(), m_elements.size());
230 const QPainterPath::ElementType *types,
236 const QPointF *e = elements;
237 for (
int i=0; i<element_count; ++i) {
239 case QPainterPath::MoveToElement:
244 m_contours << m_points.size() - 1;
245 m_points << pt_fixed;
246 m_tags << QT_FT_CURVE_TAG_ON;
250 case QPainterPath::LineToElement:
254 m_points << pt_fixed;
255 m_tags << QT_FT_CURVE_TAG_ON;
259 case QPainterPath::CurveToElement:
270 m_points << cp1_fixed << cp2_fixed << ep_fixed;
271 m_tags << QT_FT_CURVE_TAG_CUBIC
272 << QT_FT_CURVE_TAG_CUBIC
273 << QT_FT_CURVE_TAG_ON;
287 const QPointF *last = elements + element_count;
288 const QPointF *e = elements;
292 m_points << pt_fixed;
293 m_tags << QT_FT_CURVE_TAG_ON;
299 m_contours << m_points.size() - 1;
301 m_outline.n_contours = m_contours.size();
302 m_outline.n_points = m_points.size();
304 m_outline.points = m_points.data();
305 m_outline.tags = m_tags.data();
306 m_outline.contours = m_contours.data();
308#ifdef QT_DEBUG_CONVERT
309 printf(
"QOutlineMapper::endOutline\n");
311 printf(
" - contours: %d\n", m_outline.n_contours);
312 for (
int i=0; i<m_outline.n_contours; ++i) {
313 printf(
" - %d\n", m_outline.contours[i]);
316 printf(
" - points: %d\n", m_outline.n_points);
317 for (
int i=0; i<m_outline.n_points; ++i) {
318 printf(
" - %d -- %.2f, %.2f, (%d, %d)\n", i,
319 (
double) (m_outline.points[i].x / 64.0),
320 (
double) (m_outline.points[i].y / 64.0),
321 (
int) m_outline.points[i].x, (
int) m_outline.points[i].y);
327 const QPainterPath::ElementType *types,
334 QScopedValueRollback<
bool> in_clip_elements(m_in_clip_elements,
true);
338 if (!(m_outline.flags & QT_FT_OUTLINE_EVEN_ODD_FILL))
339 path.setFillRule(Qt::WindingFill);
342 for (
int i=0; i<element_count; ++i) {
344 case QPainterPath::MoveToElement:
345 path.moveTo(elements[i]);
348 case QPainterPath::LineToElement:
349 path.lineTo(elements[i]);
352 case QPainterPath::CurveToElement:
353 path.cubicTo(elements[i], elements[i+1], elements[i+2]);
361 path.moveTo(elements[0]);
362 for (
int i=1; i<element_count; ++i)
363 path.lineTo(elements[i]);
366 QPainterPath clipPath;
367 clipPath.addRect(m_clip_rect);
368 QPainterPath clippedPath = path.intersected(clipPath);
369 if (clippedPath.isEmpty()) {
372 QTransform oldTransform = m_transform;
374 convertPath(clippedPath);
375 m_transform = oldTransform;