Warning, file /office/calligra/libs/flake/KoPathShapeLoader.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net>
0003  *
0004  * This library is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU Library General Public
0006  * License as published by the Free Software Foundation; either
0007  * version 2 of the License, or (at your option) any later version.
0008  *
0009  * This library is distributed in the hope that it will be useful,
0010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012  * Library General Public License for more details.
0013  *
0014  * You should have received a copy of the GNU Library General Public License
0015  * along with this library; see the file COPYING.LIB.  If not, write to
0016  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017  * Boston, MA 02110-1301, USA.
0018  */
0019 
0020 #include "KoPathShapeLoader.h"
0021 #include "KoPathShape.h"
0022 #include <math.h>
0023 #include <FlakeDebug.h>
0024 
0025 class KoPathShapeLoaderPrivate
0026 {
0027 public:
0028     KoPathShapeLoaderPrivate(KoPathShape * p) : path(p) {
0029         Q_ASSERT(path);
0030         path->clear();
0031     }
0032 
0033     void parseSvg(const QString &svgInputData, bool process = false);
0034 
0035     void svgMoveTo(qreal x1, qreal y1, bool abs = true);
0036     void svgLineTo(qreal x1, qreal y1, bool abs = true);
0037     void svgLineToHorizontal(qreal x, bool abs = true);
0038     void svgLineToVertical(qreal y, bool abs = true);
0039     void svgCurveToCubic(qreal x1, qreal y1, qreal x2, qreal y2, qreal x, qreal y, bool abs = true);
0040     void svgCurveToCubicSmooth(qreal x, qreal y, qreal x2, qreal y2, bool abs = true);
0041     void svgCurveToQuadratic(qreal x, qreal y, qreal x1, qreal y1, bool abs = true);
0042     void svgCurveToQuadraticSmooth(qreal x, qreal y, bool abs = true);
0043     void svgArcTo(qreal x, qreal y, qreal r1, qreal r2, qreal angle, bool largeArcFlag, bool sweepFlag, bool abs = true);
0044     void svgClosePath();
0045 
0046     const char *getCoord(const char *, qreal &);
0047     void calculateArc(bool relative, qreal &curx, qreal &cury, qreal angle, qreal x, qreal y, qreal r1, qreal r2, bool largeArcFlag, bool sweepFlag);
0048 
0049     KoPathShape * path; ///< the path shape to work on
0050     QPointF lastPoint;
0051 };
0052 
0053 void KoPathShapeLoaderPrivate::parseSvg(const QString &s, bool process)
0054 {
0055     if (!s.isEmpty()) {
0056         QString d = s;
0057         d.replace(',', ' ');
0058         d = d.simplified();
0059 
0060         const QByteArray buffer = d.toLatin1();
0061         const char *ptr = buffer.constData();
0062         const char *end = buffer.constData() + buffer.length() + 1;
0063 
0064         qreal curx = 0.0;
0065         qreal cury = 0.0;
0066         qreal contrlx, contrly, subpathx, subpathy, tox, toy, x1, y1, x2, y2, xc, yc;
0067         qreal px1, py1, px2, py2, px3, py3;
0068         bool relative;
0069         char command = *(ptr++), lastCommand = ' ';
0070 
0071         subpathx = subpathy = curx = cury = contrlx = contrly = 0.0;
0072         while (ptr < end) {
0073             if (*ptr == ' ')
0074                 ++ptr;
0075 
0076             relative = false;
0077 
0078             switch (command) {
0079             case 'm':
0080                 relative = true;
0081             case 'M': {
0082                 ptr = getCoord(ptr, tox);
0083                 ptr = getCoord(ptr, toy);
0084 
0085                 if (process) {
0086                     subpathx = curx = relative ? curx + tox : tox;
0087                     subpathy = cury = relative ? cury + toy : toy;
0088 
0089                     svgMoveTo(curx, cury);
0090                 } else
0091                     svgMoveTo(tox, toy, !relative);
0092                 break;
0093             }
0094             case 'l':
0095                 relative = true;
0096             case 'L': {
0097                 ptr = getCoord(ptr, tox);
0098                 ptr = getCoord(ptr, toy);
0099 
0100                 if (process) {
0101                     curx = relative ? curx + tox : tox;
0102                     cury = relative ? cury + toy : toy;
0103 
0104                     svgLineTo(curx, cury);
0105                 } else
0106                     svgLineTo(tox, toy, !relative);
0107                 break;
0108             }
0109             case 'h': {
0110                 ptr = getCoord(ptr, tox);
0111                 if (process) {
0112                     curx = curx + tox;
0113                     svgLineTo(curx, cury);
0114                 } else
0115                     svgLineToHorizontal(tox, false);
0116                 break;
0117             }
0118             case 'H': {
0119                 ptr = getCoord(ptr, tox);
0120                 if (process) {
0121                     curx = tox;
0122                     svgLineTo(curx, cury);
0123                 } else
0124                     svgLineToHorizontal(tox);
0125                 break;
0126             }
0127             case 'v': {
0128                 ptr = getCoord(ptr, toy);
0129                 if (process) {
0130                     cury = cury + toy;
0131                     svgLineTo(curx, cury);
0132                 } else
0133                     svgLineToVertical(toy, false);
0134                 break;
0135             }
0136             case 'V': {
0137                 ptr = getCoord(ptr, toy);
0138                 if (process) {
0139                     cury = toy;
0140                     svgLineTo(curx, cury);
0141                 } else
0142                     svgLineToVertical(toy);
0143                 break;
0144             }
0145             case 'z':
0146             case 'Z': {
0147                 // reset curx, cury for next path
0148                 if (process) {
0149                     curx = subpathx;
0150                     cury = subpathy;
0151                 }
0152                 svgClosePath();
0153                 break;
0154             }
0155             case 'c':
0156                 relative = true;
0157             case 'C': {
0158                 ptr = getCoord(ptr, x1);
0159                 ptr = getCoord(ptr, y1);
0160                 ptr = getCoord(ptr, x2);
0161                 ptr = getCoord(ptr, y2);
0162                 ptr = getCoord(ptr, tox);
0163                 ptr = getCoord(ptr, toy);
0164 
0165                 if (process) {
0166                     px1 = relative ? curx + x1 : x1;
0167                     py1 = relative ? cury + y1 : y1;
0168                     px2 = relative ? curx + x2 : x2;
0169                     py2 = relative ? cury + y2 : y2;
0170                     px3 = relative ? curx + tox : tox;
0171                     py3 = relative ? cury + toy : toy;
0172 
0173                     svgCurveToCubic(px1, py1, px2, py2, px3, py3);
0174 
0175                     contrlx = relative ? curx + x2 : x2;
0176                     contrly = relative ? cury + y2 : y2;
0177                     curx = relative ? curx + tox : tox;
0178                     cury = relative ? cury + toy : toy;
0179                 } else
0180                     svgCurveToCubic(x1, y1, x2, y2, tox, toy, !relative);
0181 
0182                 break;
0183             }
0184             case 's':
0185                 relative = true;
0186             case 'S': {
0187                 ptr = getCoord(ptr, x2);
0188                 ptr = getCoord(ptr, y2);
0189                 ptr = getCoord(ptr, tox);
0190                 ptr = getCoord(ptr, toy);
0191                 if (!(lastCommand == 'c' || lastCommand == 'C' ||
0192                         lastCommand == 's' || lastCommand == 'S')) {
0193                     contrlx = curx;
0194                     contrly = cury;
0195                 }
0196 
0197                 if (process) {
0198                     px1 = 2 * curx - contrlx;
0199                     py1 = 2 * cury - contrly;
0200                     px2 = relative ? curx + x2 : x2;
0201                     py2 = relative ? cury + y2 : y2;
0202                     px3 = relative ? curx + tox : tox;
0203                     py3 = relative ? cury + toy : toy;
0204 
0205                     svgCurveToCubic(px1, py1, px2, py2, px3, py3);
0206 
0207                     contrlx = relative ? curx + x2 : x2;
0208                     contrly = relative ? cury + y2 : y2;
0209                     curx = relative ? curx + tox : tox;
0210                     cury = relative ? cury + toy : toy;
0211                 } else
0212                     svgCurveToCubicSmooth(x2, y2, tox, toy, !relative);
0213                 break;
0214             }
0215             case 'q':
0216                 relative = true;
0217             case 'Q': {
0218                 ptr = getCoord(ptr, x1);
0219                 ptr = getCoord(ptr, y1);
0220                 ptr = getCoord(ptr, tox);
0221                 ptr = getCoord(ptr, toy);
0222 
0223                 if (process) {
0224                     px1 = relative ? (curx + 2 * (x1 + curx)) * (1.0 / 3.0) : (curx + 2 * x1) * (1.0 / 3.0);
0225                     py1 = relative ? (cury + 2 * (y1 + cury)) * (1.0 / 3.0) : (cury + 2 * y1) * (1.0 / 3.0);
0226                     px2 = relative ? ((curx + tox) + 2 * (x1 + curx)) * (1.0 / 3.0) : (tox + 2 * x1) * (1.0 / 3.0);
0227                     py2 = relative ? ((cury + toy) + 2 * (y1 + cury)) * (1.0 / 3.0) : (toy + 2 * y1) * (1.0 / 3.0);
0228                     px3 = relative ? curx + tox : tox;
0229                     py3 = relative ? cury + toy : toy;
0230 
0231                     svgCurveToCubic(px1, py1, px2, py2, px3, py3);
0232 
0233                     contrlx = relative ? curx + x1 : x1;
0234                     contrly = relative ? cury + y1 : y1;
0235                     curx = relative ? curx + tox : tox;
0236                     cury = relative ? cury + toy : toy;
0237                 } else
0238                     svgCurveToQuadratic(x1, y1, tox, toy, !relative);
0239                 break;
0240             }
0241             case 't':
0242                 relative = true;
0243             case 'T': {
0244                 ptr = getCoord(ptr, tox);
0245                 ptr = getCoord(ptr, toy);
0246                 if (!(lastCommand == 'q' || lastCommand == 'Q' ||
0247                         lastCommand == 't' || lastCommand == 'T')) {
0248                     contrlx = curx;
0249                     contrly = cury;
0250                 }
0251 
0252                 if (process) {
0253                     xc = 2 * curx - contrlx;
0254                     yc = 2 * cury - contrly;
0255 
0256                     px1 = (curx + 2 * xc) * (1.0 / 3.0);
0257                     py1 = (cury + 2 * yc) * (1.0 / 3.0);
0258                     px2 = relative ? ((curx + tox) + 2 * xc) * (1.0 / 3.0) : (tox + 2 * xc) * (1.0 / 3.0);
0259                     py2 = relative ? ((cury + toy) + 2 * yc) * (1.0 / 3.0) : (toy + 2 * yc) * (1.0 / 3.0);
0260                     px3 = relative ? curx + tox : tox;
0261                     py3 = relative ? cury + toy : toy;
0262 
0263                     svgCurveToCubic(px1, py1, px2, py2, px3, py3);
0264 
0265                     contrlx = xc;
0266                     contrly = yc;
0267                     curx = relative ? curx + tox : tox;
0268                     cury = relative ? cury + toy : toy;
0269                 } else
0270                     svgCurveToQuadraticSmooth(tox, toy, !relative);
0271                 break;
0272             }
0273             case 'a':
0274                 relative = true;
0275             case 'A': {
0276                 bool largeArc, sweep;
0277                 qreal angle, rx, ry;
0278                 ptr = getCoord(ptr, rx);
0279                 ptr = getCoord(ptr, ry);
0280                 ptr = getCoord(ptr, angle);
0281                 ptr = getCoord(ptr, tox);
0282                 largeArc = tox == 1;
0283                 ptr = getCoord(ptr, tox);
0284                 sweep = tox == 1;
0285                 ptr = getCoord(ptr, tox);
0286                 ptr = getCoord(ptr, toy);
0287 
0288                 // Spec: radii are nonnegative numbers
0289                 rx = fabs(rx);
0290                 ry = fabs(ry);
0291 
0292                 if (process)
0293                     calculateArc(relative, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep);
0294                 else
0295                     svgArcTo(tox, toy, rx, ry, angle, largeArc, sweep, !relative);
0296                 break;
0297             }
0298             default: {
0299                 // when svg parser is used for a parsing an odf path an unknown command
0300                 // can be encountered, so we stop parsing here
0301                 debugFlake << "KoSvgPathParser::parseSVG(): unknown command \"" << command << "\"";
0302                 return;
0303             }
0304             }
0305 
0306             lastCommand = command;
0307 
0308             if (*ptr == '+' || *ptr == '-' || (*ptr >= '0' && *ptr <= '9')) {
0309                 // there are still coords in this command
0310                 if (command == 'M')
0311                     command = 'L';
0312                 else if (command == 'm')
0313                     command = 'l';
0314             } else
0315                 command = *(ptr++);
0316 
0317             if (lastCommand != 'C' && lastCommand != 'c' &&
0318                     lastCommand != 'S' && lastCommand != 's' &&
0319                     lastCommand != 'Q' && lastCommand != 'q' &&
0320                     lastCommand != 'T' && lastCommand != 't') {
0321                 contrlx = curx;
0322                 contrly = cury;
0323             }
0324         }
0325     }
0326 }
0327 
0328 // parses the coord into number and forwards to the next token
0329 const char * KoPathShapeLoaderPrivate::getCoord(const char *ptr, qreal &number)
0330 {
0331     int integer, exponent;
0332     qreal decimal, frac;
0333     int sign, expsign;
0334 
0335     exponent = 0;
0336     integer = 0;
0337     frac = 1.0;
0338     decimal = 0;
0339     sign = 1;
0340     expsign = 1;
0341 
0342     // read the sign
0343     if (*ptr == '+')
0344         ++ptr;
0345     else if (*ptr == '-') {
0346         ++ptr;
0347         sign = -1;
0348     }
0349 
0350     // read the integer part
0351     while (*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
0352         integer = (integer * 10) + *(ptr++) - '0';
0353     if (*ptr == '.') { // read the decimals
0354         ++ptr;
0355         while (*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
0356             decimal += (*(ptr++) - '0') * (frac *= 0.1);
0357     }
0358 
0359     if (*ptr == 'e' || *ptr == 'E') { // read the exponent part
0360         ++ptr;
0361 
0362         // read the sign of the exponent
0363         if (*ptr == '+')
0364             ++ptr;
0365         else if (*ptr == '-') {
0366             ++ptr;
0367             expsign = -1;
0368         }
0369 
0370         exponent = 0;
0371         while (*ptr != '\0' && *ptr >= '0' && *ptr <= '9') {
0372             exponent *= 10;
0373             exponent += *ptr - '0';
0374             ++ptr;
0375         }
0376     }
0377     number = integer + decimal;
0378     number *= sign * pow((qreal)10, qreal(expsign * exponent));
0379 
0380     // skip the following space
0381     if (*ptr == ' ')
0382         ++ptr;
0383 
0384     return ptr;
0385 }
0386 
0387 // This works by converting the SVG arc to "simple" beziers.
0388 // For each bezier found a svgToCurve call is done.
0389 // Adapted from Niko's code in kdelibs/kdecore/svgicons.
0390 // Maybe this can serve in some shared lib? (Rob)
0391 void KoPathShapeLoaderPrivate::calculateArc(bool relative, qreal &curx, qreal &cury, qreal angle, qreal x, qreal y, qreal r1, qreal r2, bool largeArcFlag, bool sweepFlag)
0392 {
0393     qreal sin_th, cos_th;
0394     qreal a00, a01, a10, a11;
0395     qreal x0, y0, x1, y1, xc, yc;
0396     qreal d, sfactor, sfactor_sq;
0397     qreal th0, th1, th_arc;
0398     int i, n_segs;
0399 
0400     sin_th = sin(angle * (M_PI / 180.0));
0401     cos_th = cos(angle * (M_PI / 180.0));
0402 
0403     qreal dx;
0404 
0405     if (!relative)
0406         dx = (curx - x) / 2.0;
0407     else
0408         dx = -x / 2.0;
0409 
0410     qreal dy;
0411 
0412     if (!relative)
0413         dy = (cury - y) / 2.0;
0414     else
0415         dy = -y / 2.0;
0416 
0417     qreal _x1 =  cos_th * dx + sin_th * dy;
0418     qreal _y1 = -sin_th * dx + cos_th * dy;
0419     qreal Pr1 = r1 * r1;
0420     qreal Pr2 = r2 * r2;
0421     qreal Px = _x1 * _x1;
0422     qreal Py = _y1 * _y1;
0423 
0424     // Spec : check if radii are large enough
0425     qreal check = Px / Pr1 + Py / Pr2;
0426     if (check > 1) {
0427         r1 = r1 * sqrt(check);
0428         r2 = r2 * sqrt(check);
0429     }
0430 
0431     a00 = cos_th / r1;
0432     a01 = sin_th / r1;
0433     a10 = -sin_th / r2;
0434     a11 = cos_th / r2;
0435 
0436     x0 = a00 * curx + a01 * cury;
0437     y0 = a10 * curx + a11 * cury;
0438 
0439     if (!relative)
0440         x1 = a00 * x + a01 * y;
0441     else
0442         x1 = a00 * (curx + x) + a01 * (cury + y);
0443 
0444     if (!relative)
0445         y1 = a10 * x + a11 * y;
0446     else
0447         y1 = a10 * (curx + x) + a11 * (cury + y);
0448 
0449     /* (x0, y0) is current point in transformed coordinate space.
0450         (x1, y1) is new point in transformed coordinate space.
0451 
0452         The arc fits a unit-radius circle in this space.
0453     */
0454 
0455     d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
0456 
0457     sfactor_sq = 1.0 / d - 0.25;
0458 
0459     if (sfactor_sq < 0)
0460         sfactor_sq = 0;
0461 
0462     sfactor = sqrt(sfactor_sq);
0463 
0464     if (sweepFlag == largeArcFlag)
0465         sfactor = -sfactor;
0466 
0467     xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
0468     yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
0469 
0470     /* (xc, yc) is center of the circle. */
0471     th0 = atan2(y0 - yc, x0 - xc);
0472     th1 = atan2(y1 - yc, x1 - xc);
0473 
0474     th_arc = th1 - th0;
0475     if (th_arc < 0 && sweepFlag)
0476         th_arc += 2 * M_PI;
0477     else if (th_arc > 0 && !sweepFlag)
0478         th_arc -= 2 * M_PI;
0479 
0480     n_segs = (int)(int) ceil(fabs(th_arc / (M_PI * 0.5 + 0.001)));
0481 
0482     for (i = 0; i < n_segs; ++i) {
0483         {
0484             qreal sin_th, cos_th;
0485             qreal a00, a01, a10, a11;
0486             qreal x1, y1, x2, y2, x3, y3;
0487             qreal t;
0488             qreal th_half;
0489 
0490             qreal _th0 = th0 + i * th_arc / n_segs;
0491             qreal _th1 = th0 + (i + 1) * th_arc / n_segs;
0492 
0493             sin_th = sin(angle * (M_PI / 180.0));
0494             cos_th = cos(angle * (M_PI / 180.0));
0495 
0496             /* inverse transform compared with rsvg_path_arc */
0497             a00 = cos_th * r1;
0498             a01 = -sin_th * r2;
0499             a10 = sin_th * r1;
0500             a11 = cos_th * r2;
0501 
0502             th_half = 0.5 * (_th1 - _th0);
0503             t = (8.0 / 3.0) * sin(th_half * 0.5) * sin(th_half * 0.5) / sin(th_half);
0504             x1 = xc + cos(_th0) - t * sin(_th0);
0505             y1 = yc + sin(_th0) + t * cos(_th0);
0506             x3 = xc + cos(_th1);
0507             y3 = yc + sin(_th1);
0508             x2 = x3 + t * sin(_th1);
0509             y2 = y3 - t * cos(_th1);
0510 
0511             svgCurveToCubic(a00 * x1 + a01 * y1, a10 * x1 + a11 * y1, a00 * x2 + a01 * y2, a10 * x2 + a11 * y2, a00 * x3 + a01 * y3, a10 * x3 + a11 * y3);
0512         }
0513     }
0514 
0515     if (!relative)
0516         curx = x;
0517     else
0518         curx += x;
0519 
0520     if (!relative)
0521         cury = y;
0522     else
0523         cury += y;
0524 }
0525 
0526 void KoPathShapeLoaderPrivate::svgMoveTo(qreal x1, qreal y1, bool abs)
0527 {
0528     if (abs)
0529         lastPoint = QPointF(x1, y1);
0530     else
0531         lastPoint += QPointF(x1, y1);
0532     path->moveTo(lastPoint);
0533 }
0534 
0535 void KoPathShapeLoaderPrivate::svgLineTo(qreal x1, qreal y1, bool abs)
0536 {
0537     if (abs)
0538         lastPoint = QPointF(x1, y1);
0539     else
0540         lastPoint += QPointF(x1, y1);
0541 
0542     path->lineTo(lastPoint);
0543 }
0544 
0545 void KoPathShapeLoaderPrivate::svgLineToHorizontal(qreal x, bool abs)
0546 {
0547     if (abs)
0548         lastPoint.setX(x);
0549     else
0550         lastPoint.rx() += x;
0551 
0552     path->lineTo(lastPoint);
0553 }
0554 
0555 void KoPathShapeLoaderPrivate::svgLineToVertical(qreal y, bool abs)
0556 {
0557     if (abs)
0558         lastPoint.setY(y);
0559     else
0560         lastPoint.ry() += y;
0561 
0562     path->lineTo(lastPoint);
0563 }
0564 
0565 void KoPathShapeLoaderPrivate::svgCurveToCubic(qreal x1, qreal y1, qreal x2, qreal y2, qreal x, qreal y, bool abs)
0566 {
0567     QPointF p1, p2;
0568     if (abs) {
0569         p1 = QPointF(x1, y1);
0570         p2 = QPointF(x2, y2);
0571         lastPoint = QPointF(x, y);
0572     } else {
0573         p1 = lastPoint + QPointF(x1, y1);
0574         p2 = lastPoint + QPointF(x2, y2);
0575         lastPoint += QPointF(x, y);
0576     }
0577 
0578     path->curveTo(p1, p2, lastPoint);
0579 }
0580 
0581 void KoPathShapeLoaderPrivate::svgCurveToCubicSmooth(qreal x, qreal y, qreal x2, qreal y2, bool abs)
0582 {
0583     Q_UNUSED(x);
0584     Q_UNUSED(y);
0585     Q_UNUSED(x2);
0586     Q_UNUSED(y2);
0587     Q_UNUSED(abs);
0588     // TODO implement
0589 }
0590 
0591 void KoPathShapeLoaderPrivate::svgCurveToQuadratic(qreal x, qreal y, qreal x1, qreal y1, bool abs)
0592 {
0593     Q_UNUSED(x);
0594     Q_UNUSED(y);
0595     Q_UNUSED(x1);
0596     Q_UNUSED(y1);
0597     Q_UNUSED(abs);
0598     // TODO implement
0599 }
0600 
0601 void KoPathShapeLoaderPrivate::svgCurveToQuadraticSmooth(qreal x, qreal y, bool abs)
0602 {
0603     Q_UNUSED(x);
0604     Q_UNUSED(y);
0605     Q_UNUSED(abs);
0606     // TODO implement
0607 }
0608 
0609 void KoPathShapeLoaderPrivate::svgArcTo(qreal x, qreal y, qreal r1, qreal r2, qreal angle, bool largeArcFlag, bool sweepFlag, bool abs)
0610 {
0611     Q_UNUSED(x);
0612     Q_UNUSED(y);
0613     Q_UNUSED(r1);
0614     Q_UNUSED(r2);
0615     Q_UNUSED(angle);
0616     Q_UNUSED(largeArcFlag);
0617     Q_UNUSED(sweepFlag);
0618     Q_UNUSED(abs);
0619     // TODO implement
0620 }
0621 
0622 void KoPathShapeLoaderPrivate::svgClosePath()
0623 {
0624     path->closeMerge();
0625 }
0626 
0627 KoPathShapeLoader::KoPathShapeLoader(KoPathShape *path)
0628     : d(new KoPathShapeLoaderPrivate(path))
0629 {
0630 }
0631 
0632 KoPathShapeLoader::~KoPathShapeLoader()
0633 {
0634     delete d;
0635 }
0636 
0637 void KoPathShapeLoader::parseSvg(const QString &s, bool process)
0638 {
0639     d->parseSvg(s, process);
0640 }