GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
octave-qsvghandler.h
Go to the documentation of this file.
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 Qt SVG 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// --------------------------------------------------------------------------
41// Build a QPainterPath from the "d" attribute of a path element
42// These functions were originally extracted from Qt-5.12 sources
43// (qsvghandler.cpp)
44// Modifications:
45// * use static_cast<qreal> to avoid old style cast warning.
46// Some portions are extracted from Qt6.5:
47// https://github.com/qt/qtsvg/blob/6.5.0/src/svg/qsvghandler.cpp
48// --------------------------------------------------------------------------
49
50#include <cmath>
51
52#include <QPainterPath>
53
54static inline bool isDigit(ushort ch)
55{
56 static quint16 magic = 0x3ff;
57 return ((ch >> 4) == 3) && (magic >> (ch & 15));
58}
59
60static qreal toDouble(const QChar *&str)
61{
62 const int maxLen = 255;//technically doubles can go til 308+ but whatever
63 char temp[maxLen+1];
64 int pos = 0;
65
66 if (*str == QLatin1Char('-')) {
67 temp[pos++] = '-';
68 ++str;
69 } else if (*str == QLatin1Char('+')) {
70 ++str;
71 }
72 while (isDigit(str->unicode()) && pos < maxLen) {
73 temp[pos++] = str->toLatin1();
74 ++str;
75 }
76 if (*str == QLatin1Char('.') && pos < maxLen) {
77 temp[pos++] = '.';
78 ++str;
79 }
80 while (isDigit(str->unicode()) && pos < maxLen) {
81 temp[pos++] = str->toLatin1();
82 ++str;
83 }
84 bool exponent = false;
85 if ((*str == QLatin1Char('e') || *str == QLatin1Char('E')) && pos < maxLen) {
86 exponent = true;
87 temp[pos++] = 'e';
88 ++str;
89 if ((*str == QLatin1Char('-') || *str == QLatin1Char('+')) && pos < maxLen) {
90 temp[pos++] = str->toLatin1();
91 ++str;
92 }
93 while (isDigit(str->unicode()) && pos < maxLen) {
94 temp[pos++] = str->toLatin1();
95 ++str;
96 }
97 }
98
99 temp[pos] = '\0';
100
101 qreal val;
102 if (!exponent && pos < 10) {
103 int ival = 0;
104 const char *t = temp;
105 bool neg = false;
106 if(*t == '-') {
107 neg = true;
108 ++t;
109 }
110 while(*t && *t != '.') {
111 ival *= 10;
112 ival += (*t) - '0';
113 ++t;
114 }
115 if(*t == '.') {
116 ++t;
117 int div = 1;
118 while(*t) {
119 ival *= 10;
120 ival += (*t) - '0';
121 div *= 10;
122 ++t;
123 }
124 val = static_cast<qreal> (ival)/static_cast<qreal> (div);
125 } else {
126 val = ival;
127 }
128 if (neg)
129 val = -val;
130 } else {
131 val = QByteArray::fromRawData(temp, pos).toDouble();
132 // Do not tolerate values too wild to be represented normally by floats
133 if (std::fpclassify (static_cast<float> (val)) != FP_NORMAL)
134 val = 0;
135 }
136 return val;
137
138}
139
140static inline void parseNumbersArray(const QChar *&str, QVarLengthArray<qreal, 8> &points,
141 const char *pattern = nullptr)
142{
143 const size_t patternLen = qstrlen(pattern);
144 while (str->isSpace())
145 ++str;
146 while (isDigit(str->unicode()) ||
147 *str == QLatin1Char('-') || *str == QLatin1Char('+') ||
148 *str == QLatin1Char('.')) {
149
150 if (patternLen && pattern[points.size() % patternLen] == 'f') {
151 // flag expected, may only be 0 or 1
152 if (*str != QLatin1Char('0') && *str != QLatin1Char('1'))
153 return;
154 points.append(*str == QLatin1Char('0') ? 0.0 : 1.0);
155 ++str;
156 } else {
157 points.append(toDouble(str));
158 }
159
160 while (str->isSpace())
161 ++str;
162 if (*str == QLatin1Char(','))
163 ++str;
164
165 //eat the rest of space
166 while (str->isSpace())
167 ++str;
168 }
169}
170
171static void pathArcSegment(QPainterPath &path,
172 qreal xc, qreal yc,
173 qreal th0, qreal th1,
174 qreal rx, qreal ry, qreal xAxisRotation)
175{
176 qreal sinTh, cosTh;
177 qreal a00, a01, a10, a11;
178 qreal x1, y1, x2, y2, x3, y3;
179 qreal t;
180 qreal thHalf;
181
182 sinTh = qSin(xAxisRotation * (3.141592653589793 / 180.0));
183 cosTh = qCos(xAxisRotation * (3.141592653589793 / 180.0));
184
185 a00 = cosTh * rx;
186 a01 = -sinTh * ry;
187 a10 = sinTh * rx;
188 a11 = cosTh * ry;
189
190 thHalf = 0.5 * (th1 - th0);
191 t = (8.0 / 3.0) * qSin(thHalf * 0.5) * qSin(thHalf * 0.5) / qSin(thHalf);
192 x1 = xc + qCos(th0) - t * qSin(th0);
193 y1 = yc + qSin(th0) + t * qCos(th0);
194 x3 = xc + qCos(th1);
195 y3 = yc + qSin(th1);
196 x2 = x3 + t * qSin(th1);
197 y2 = y3 - t * qCos(th1);
198
199 path.cubicTo(a00 * x1 + a01 * y1, a10 * x1 + a11 * y1,
200 a00 * x2 + a01 * y2, a10 * x2 + a11 * y2,
201 a00 * x3 + a01 * y3, a10 * x3 + a11 * y3);
202}
203
204// the arc handling code underneath is from XSVG (BSD license)
205/*
206 * Copyright 2002 USC/Information Sciences Institute
207 *
208 * Permission to use, copy, modify, distribute, and sell this software
209 * and its documentation for any purpose is hereby granted without
210 * fee, provided that the above copyright notice appear in all copies
211 * and that both that copyright notice and this permission notice
212 * appear in supporting documentation, and that the name of
213 * Information Sciences Institute not be used in advertising or
214 * publicity pertaining to distribution of the software without
215 * specific, written prior permission. Information Sciences Institute
216 * makes no representations about the suitability of this software for
217 * any purpose. It is provided "as is" without express or implied
218 * warranty.
219 *
220 * INFORMATION SCIENCES INSTITUTE DISCLAIMS ALL WARRANTIES WITH REGARD
221 * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
222 * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL INFORMATION SCIENCES
223 * INSTITUTE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
224 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
225 * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
226 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
227 * PERFORMANCE OF THIS SOFTWARE.
228 *
229 */
230static void pathArc(QPainterPath &path,
231 qreal rx,
232 qreal ry,
233 qreal x_axis_rotation,
234 int large_arc_flag,
235 int sweep_flag,
236 qreal x,
237 qreal y,
238 qreal curx, qreal cury)
239{
240 const qreal Pr1 = rx * rx;
241 const qreal Pr2 = ry * ry;
242
243 if (!Pr1 || !Pr2)
244 return;
245
246 qreal sin_th, cos_th;
247 qreal a00, a01, a10, a11;
248 qreal x0, y0, x1, y1, xc, yc;
249 qreal d, sfactor, sfactor_sq;
250 qreal th0, th1, th_arc;
251 int i, n_segs;
252 qreal dx, dy, dx1, dy1, Px, Py, check;
253
254 rx = qAbs(rx);
255 ry = qAbs(ry);
256
257 sin_th = qSin(x_axis_rotation * (3.141592653589793 / 180.0));
258 cos_th = qCos(x_axis_rotation * (3.141592653589793 / 180.0));
259
260 dx = (curx - x) / 2.0;
261 dy = (cury - y) / 2.0;
262 dx1 = cos_th * dx + sin_th * dy;
263 dy1 = -sin_th * dx + cos_th * dy;
264 Px = dx1 * dx1;
265 Py = dy1 * dy1;
266 /* Spec : check if radii are large enough */
267 check = Px / Pr1 + Py / Pr2;
268 if (check > 1) {
269 rx = rx * qSqrt(check);
270 ry = ry * qSqrt(check);
271 }
272
273 a00 = cos_th / rx;
274 a01 = sin_th / rx;
275 a10 = -sin_th / ry;
276 a11 = cos_th / ry;
277 x0 = a00 * curx + a01 * cury;
278 y0 = a10 * curx + a11 * cury;
279 x1 = a00 * x + a01 * y;
280 y1 = a10 * x + a11 * y;
281 /* (x0, y0) is current point in transformed coordinate space.
282 (x1, y1) is new point in transformed coordinate space.
283
284 The arc fits a unit-radius circle in this space.
285 */
286 d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
287 if (!d)
288 return;
289 sfactor_sq = 1.0 / d - 0.25;
290 if (sfactor_sq < 0) sfactor_sq = 0;
291 sfactor = qSqrt(sfactor_sq);
292 if (sweep_flag == large_arc_flag) sfactor = -sfactor;
293 xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
294 yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
295 /* (xc, yc) is center of the circle. */
296
297 th0 = qAtan2(y0 - yc, x0 - xc);
298 th1 = qAtan2(y1 - yc, x1 - xc);
299
300 th_arc = th1 - th0;
301 if (th_arc < 0 && sweep_flag)
302 th_arc += 2 * 3.141592653589793;
303 else if (th_arc > 0 && !sweep_flag)
304 th_arc -= 2 * 3.141592653589793;
305
306 n_segs = qCeil(qAbs(th_arc / (3.141592653589793 * 0.5 + 0.001)));
307
308 for (i = 0; i < n_segs; i++) {
309 pathArcSegment(path, xc, yc,
310 th0 + i * th_arc / n_segs,
311 th0 + (i + 1) * th_arc / n_segs,
312 rx, ry, x_axis_rotation);
313 }
314}
315
316#if HAVE_QSTRINGVIEW
317static QTransform parseTransformationMatrix(QStringView value)
318#else
319static QTransform parseTransformationMatrix(const QStringRef &value)
320#endif
321{
322 if (value.isEmpty())
323 return QTransform();
324
325 QTransform matrix;
326#if HAVE_QSTRINGVIEW
327 const QChar *str = value.data();
328 const QChar *end = str + value.size();
329#else
330 const QChar *str = value.constData();
331 const QChar *end = str + value.length();
332#endif
333
334 while (str < end) {
335 if (str->isSpace() || *str == QLatin1Char(',')) {
336 ++str;
337 continue;
338 }
339 enum State {
340 Matrix,
341 Translate,
342 Rotate,
343 Scale,
344 SkewX,
345 SkewY
346 };
347 State state = Matrix;
348 if (*str == QLatin1Char('m')) { //matrix
349 const char *ident = "atrix";
350 for (int i = 0; i < 5; ++i)
351 if (*(++str) != QLatin1Char(ident[i]))
352 goto error;
353 ++str;
354 state = Matrix;
355 } else if (*str == QLatin1Char('t')) { //translate
356 const char *ident = "ranslate";
357 for (int i = 0; i < 8; ++i)
358 if (*(++str) != QLatin1Char(ident[i]))
359 goto error;
360 ++str;
361 state = Translate;
362 } else if (*str == QLatin1Char('r')) { //rotate
363 const char *ident = "otate";
364 for (int i = 0; i < 5; ++i)
365 if (*(++str) != QLatin1Char(ident[i]))
366 goto error;
367 ++str;
368 state = Rotate;
369 } else if (*str == QLatin1Char('s')) { //scale, skewX, skewY
370 ++str;
371 if (*str == QLatin1Char('c')) {
372 const char *ident = "ale";
373 for (int i = 0; i < 3; ++i)
374 if (*(++str) != QLatin1Char(ident[i]))
375 goto error;
376 ++str;
377 state = Scale;
378 } else if (*str == QLatin1Char('k')) {
379 if (*(++str) != QLatin1Char('e'))
380 goto error;
381 if (*(++str) != QLatin1Char('w'))
382 goto error;
383 ++str;
384 if (*str == QLatin1Char('X'))
385 state = SkewX;
386 else if (*str == QLatin1Char('Y'))
387 state = SkewY;
388 else
389 goto error;
390 ++str;
391 } else {
392 goto error;
393 }
394 } else {
395 goto error;
396 }
397
398
399 while (str < end && str->isSpace())
400 ++str;
401 if (*str != QLatin1Char('('))
402 goto error;
403 ++str;
404 QVarLengthArray<qreal, 8> points;
405 parseNumbersArray(str, points);
406 if (*str != QLatin1Char(')'))
407 goto error;
408 ++str;
409
410 if(state == Matrix) {
411 if(points.count() != 6)
412 goto error;
413 matrix = QTransform(points[0], points[1],
414 points[2], points[3],
415 points[4], points[5]) * matrix;
416 } else if (state == Translate) {
417 if (points.count() == 1)
418 matrix.translate(points[0], 0);
419 else if (points.count() == 2)
420 matrix.translate(points[0], points[1]);
421 else
422 goto error;
423 } else if (state == Rotate) {
424 if(points.count() == 1) {
425 matrix.rotate(points[0]);
426 } else if (points.count() == 3) {
427 matrix.translate(points[1], points[2]);
428 matrix.rotate(points[0]);
429 matrix.translate(-points[1], -points[2]);
430 } else {
431 goto error;
432 }
433 } else if (state == Scale) {
434 if (points.count() < 1 || points.count() > 2)
435 goto error;
436 qreal sx = points[0];
437 qreal sy = sx;
438 if(points.count() == 2)
439 sy = points[1];
440 matrix.scale(sx, sy);
441 } else if (state == SkewX) {
442 if (points.count() != 1)
443 goto error;
444 const qreal deg2rad = qreal(0.017453292519943295769);
445 matrix.shear(qTan(points[0]*deg2rad), 0);
446 } else if (state == SkewY) {
447 if (points.count() != 1)
448 goto error;
449 const qreal deg2rad = qreal(0.017453292519943295769);
450 matrix.shear(0, qTan(points[0]*deg2rad));
451 }
452 }
453 error:
454 return matrix;
455}
456
457#if HAVE_QSTRINGVIEW
458static bool parsePathDataFast(QStringView dataStr, QPainterPath &path)
459#else
460static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
461#endif
462{
463 const int maxElementCount = 0x7fff; // Assume file corruption if more path elements than this
464 qreal x0 = 0, y0 = 0; // starting point
465 qreal x = 0, y = 0; // current point
466 char lastMode = 0;
467 QPointF ctrlPt;
468#if HAVE_QSTRINGVIEW
469 const QChar *str = dataStr.data();
470#else
471 const QChar *str = dataStr.constData();
472#endif
473 const QChar *end = str + dataStr.size();
474
475 bool ok = true;
476 while (ok && str != end) {
477 while (str->isSpace() && (str + 1) != end)
478 ++str;
479 QChar pathElem = *str;
480 ++str;
481 QChar endc = *end;
482 *const_cast<QChar *>(end) = u'\0'; // parseNumbersArray requires 0-termination that QStringView cannot guarantee
483 const char *pattern = nullptr;
484 if (pathElem == QLatin1Char('a') || pathElem == QLatin1Char('A'))
485 pattern = "rrrffrr";
486 QVarLengthArray<qreal, 8> arg;
487 parseNumbersArray(str, arg, pattern);
488 *const_cast<QChar *>(end) = endc;
489 if (pathElem == QLatin1Char('z') || pathElem == QLatin1Char('Z'))
490 arg.append(0);//dummy
491 const qreal *num = arg.constData();
492 int count = arg.count();
493 while (ok && count > 0) {
494 qreal offsetX = x; // correction offsets
495 qreal offsetY = y; // for relative commands
496 switch (pathElem.unicode()) {
497 case 'm': {
498 if (count < 2) {
499 ok = false;
500 break;
501 }
502 x = x0 = num[0] + offsetX;
503 y = y0 = num[1] + offsetY;
504 num += 2;
505 count -= 2;
506 path.moveTo(x0, y0);
507
508 // As per 1.2 spec 8.3.2 The "moveto" commands
509 // If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
510 // the subsequent pairs shall be treated as implicit 'lineto' commands.
511 pathElem = QLatin1Char('l');
512 }
513 break;
514 case 'M': {
515 if (count < 2) {
516 ok = false;
517 break;
518 }
519 x = x0 = num[0];
520 y = y0 = num[1];
521 num += 2;
522 count -= 2;
523 path.moveTo(x0, y0);
524
525 // As per 1.2 spec 8.3.2 The "moveto" commands
526 // If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
527 // the subsequent pairs shall be treated as implicit 'lineto' commands.
528 pathElem = QLatin1Char('L');
529 }
530 break;
531 case 'z':
532 case 'Z': {
533 x = x0;
534 y = y0;
535 count--; // skip dummy
536 num++;
537 path.closeSubpath();
538 }
539 break;
540 case 'l': {
541 if (count < 2) {
542 ok = false;
543 break;
544 }
545 x = num[0] + offsetX;
546 y = num[1] + offsetY;
547 num += 2;
548 count -= 2;
549 path.lineTo(x, y);
550
551 }
552 break;
553 case 'L': {
554 if (count < 2) {
555 ok = false;
556 break;
557 }
558 x = num[0];
559 y = num[1];
560 num += 2;
561 count -= 2;
562 path.lineTo(x, y);
563 }
564 break;
565 case 'h': {
566 x = num[0] + offsetX;
567 num++;
568 count--;
569 path.lineTo(x, y);
570 }
571 break;
572 case 'H': {
573 x = num[0];
574 num++;
575 count--;
576 path.lineTo(x, y);
577 }
578 break;
579 case 'v': {
580 y = num[0] + offsetY;
581 num++;
582 count--;
583 path.lineTo(x, y);
584 }
585 break;
586 case 'V': {
587 y = num[0];
588 num++;
589 count--;
590 path.lineTo(x, y);
591 }
592 break;
593 case 'c': {
594 if (count < 6) {
595 ok = false;
596 break;
597 }
598 QPointF c1(num[0] + offsetX, num[1] + offsetY);
599 QPointF c2(num[2] + offsetX, num[3] + offsetY);
600 QPointF e(num[4] + offsetX, num[5] + offsetY);
601 num += 6;
602 count -= 6;
603 path.cubicTo(c1, c2, e);
604 ctrlPt = c2;
605 x = e.x();
606 y = e.y();
607 break;
608 }
609 case 'C': {
610 if (count < 6) {
611 ok = false;
612 break;
613 }
614 QPointF c1(num[0], num[1]);
615 QPointF c2(num[2], num[3]);
616 QPointF e(num[4], num[5]);
617 num += 6;
618 count -= 6;
619 path.cubicTo(c1, c2, e);
620 ctrlPt = c2;
621 x = e.x();
622 y = e.y();
623 break;
624 }
625 case 's': {
626 if (count < 4) {
627 ok = false;
628 break;
629 }
630 QPointF c1;
631 if (lastMode == 'c' || lastMode == 'C' ||
632 lastMode == 's' || lastMode == 'S')
633 c1 = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
634 else
635 c1 = QPointF(x, y);
636 QPointF c2(num[0] + offsetX, num[1] + offsetY);
637 QPointF e(num[2] + offsetX, num[3] + offsetY);
638 num += 4;
639 count -= 4;
640 path.cubicTo(c1, c2, e);
641 ctrlPt = c2;
642 x = e.x();
643 y = e.y();
644 break;
645 }
646 case 'S': {
647 if (count < 4) {
648 ok = false;
649 break;
650 }
651 QPointF c1;
652 if (lastMode == 'c' || lastMode == 'C' ||
653 lastMode == 's' || lastMode == 'S')
654 c1 = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
655 else
656 c1 = QPointF(x, y);
657 QPointF c2(num[0], num[1]);
658 QPointF e(num[2], num[3]);
659 num += 4;
660 count -= 4;
661 path.cubicTo(c1, c2, e);
662 ctrlPt = c2;
663 x = e.x();
664 y = e.y();
665 break;
666 }
667 case 'q': {
668 if (count < 4) {
669 ok = false;
670 break;
671 }
672 QPointF c(num[0] + offsetX, num[1] + offsetY);
673 QPointF e(num[2] + offsetX, num[3] + offsetY);
674 num += 4;
675 count -= 4;
676 path.quadTo(c, e);
677 ctrlPt = c;
678 x = e.x();
679 y = e.y();
680 break;
681 }
682 case 'Q': {
683 if (count < 4) {
684 ok = false;
685 break;
686 }
687 QPointF c(num[0], num[1]);
688 QPointF e(num[2], num[3]);
689 num += 4;
690 count -= 4;
691 path.quadTo(c, e);
692 ctrlPt = c;
693 x = e.x();
694 y = e.y();
695 break;
696 }
697 case 't': {
698 if (count < 2) {
699 ok = false;
700 break;
701 }
702 QPointF e(num[0] + offsetX, num[1] + offsetY);
703 num += 2;
704 count -= 2;
705 QPointF c;
706 if (lastMode == 'q' || lastMode == 'Q' ||
707 lastMode == 't' || lastMode == 'T')
708 c = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
709 else
710 c = QPointF(x, y);
711 path.quadTo(c, e);
712 ctrlPt = c;
713 x = e.x();
714 y = e.y();
715 break;
716 }
717 case 'T': {
718 if (count < 2) {
719 ok = false;
720 break;
721 }
722 QPointF e(num[0], num[1]);
723 num += 2;
724 count -= 2;
725 QPointF c;
726 if (lastMode == 'q' || lastMode == 'Q' ||
727 lastMode == 't' || lastMode == 'T')
728 c = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
729 else
730 c = QPointF(x, y);
731 path.quadTo(c, e);
732 ctrlPt = c;
733 x = e.x();
734 y = e.y();
735 break;
736 }
737 case 'a': {
738 if (count < 7) {
739 ok = false;
740 break;
741 }
742 qreal rx = (*num++);
743 qreal ry = (*num++);
744 qreal xAxisRotation = (*num++);
745 qreal largeArcFlag = (*num++);
746 qreal sweepFlag = (*num++);
747 qreal ex = (*num++) + offsetX;
748 qreal ey = (*num++) + offsetY;
749 count -= 7;
750 qreal curx = x;
751 qreal cury = y;
752 pathArc(path, rx, ry, xAxisRotation, int(largeArcFlag),
753 int(sweepFlag), ex, ey, curx, cury);
754
755 x = ex;
756 y = ey;
757 }
758 break;
759 case 'A': {
760 if (count < 7) {
761 ok = false;
762 break;
763 }
764 qreal rx = (*num++);
765 qreal ry = (*num++);
766 qreal xAxisRotation = (*num++);
767 qreal largeArcFlag = (*num++);
768 qreal sweepFlag = (*num++);
769 qreal ex = (*num++);
770 qreal ey = (*num++);
771 count -= 7;
772 qreal curx = x;
773 qreal cury = y;
774 pathArc(path, rx, ry, xAxisRotation, int(largeArcFlag),
775 int(sweepFlag), ex, ey, curx, cury);
776
777 x = ex;
778 y = ey;
779 }
780 break;
781 default:
782 ok = false;
783 break;
784 }
785 lastMode = pathElem.toLatin1();
786 if (path.elementCount() > maxElementCount)
787 ok = false;
788 }
789 }
790 return ok;
791}
void error(const char *fmt,...)
Definition error.cc:1003
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
F77_RET_T const F77_DBLE * x