00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qvaluevector.h>
00022 #include <qstringlist.h>
00023 #include <qwmatrix.h>
00024 #include <qregexp.h>
00025 #include <qimage.h>
00026 #include <qdict.h>
00027 #include <qmap.h>
00028 #include <qdom.h>
00029
00030 #include <math.h>
00031
00032 #include <kdebug.h>
00033
00034 #include <libart_lgpl/art_svp.h>
00035 #include <libart_lgpl/art_rgb.h>
00036 #include <libart_lgpl/art_rgba.h>
00037 #include <libart_lgpl/art_vpath.h>
00038 #include <libart_lgpl/art_vpath_dash.h>
00039 #include <libart_lgpl/art_bpath.h>
00040 #include <libart_lgpl/art_affine.h>
00041 #include <libart_lgpl/art_svp_ops.h>
00042 #include <libart_lgpl/art_svp_vpath.h>
00043 #include <libart_lgpl/art_render_svp.h>
00044 #include <libart_lgpl/art_vpath_bpath.h>
00045 #include <libart_lgpl/art_svp_intersect.h>
00046 #include <libart_lgpl/art_svp_vpath_stroke.h>
00047
00048 #include "ksvgiconpainter.h"
00049
00050 #define ART_END2 10
00051
00052 const double deg2rad = 0.017453292519943295769;
00053
00054 class KSVGIconPainterHelper
00055 {
00056 public:
00057 KSVGIconPainterHelper(int width, int height, KSVGIconPainter *painter)
00058 {
00059 m_painter = painter;
00060
00061 m_clipSVP = 0;
00062
00063 m_fillColor = Qt::black;
00064
00065 m_useFill = true;
00066 m_useStroke = false;
00067
00068 m_useFillGradient = false;
00069 m_useStrokeGradient = false;
00070
00071 m_worldMatrix = new QWMatrix();
00072
00073
00074 m_image = new QImage(width, height, 32);
00075 m_image->setAlphaBuffer(true);
00076
00077 m_strokeWidth = 1.0;
00078 m_strokeMiterLimit = 4;
00079 m_dashOffset = 0;
00080 m_dashes = "";
00081
00082 m_opacity = 0xff;
00083 m_fillOpacity = 0xff;
00084 m_strokeOpacity = 0xff;
00085
00086 m_fillRule = "nonzero";
00087
00088 m_width = width;
00089 m_height = height;
00090
00091 m_rowstride = m_width * 4;
00092
00093
00094 m_buffer = art_new(art_u8, m_rowstride * m_height);
00095 memset(m_buffer, 0, m_rowstride * m_height);
00096
00097 m_tempBuffer = 0;
00098 }
00099
00100 ~KSVGIconPainterHelper()
00101 {
00102 if(m_clipSVP)
00103 art_svp_free(m_clipSVP);
00104
00105 art_free(m_buffer);
00106
00107 delete m_image;
00108 delete m_worldMatrix;
00109 }
00110
00111 ArtVpath *allocVPath(int number)
00112 {
00113 return art_new(ArtVpath, number);
00114 }
00115
00116 ArtBpath *allocBPath(int number)
00117 {
00118 return art_new(ArtBpath, number);
00119 }
00120
00121 void ensureSpace(QMemArray<ArtBpath> &vec, int index)
00122 {
00123 if(vec.size() == (unsigned int) index)
00124 vec.resize(index + 1);
00125 }
00126
00127 void createBuffer()
00128 {
00129 m_tempBuffer = art_new(art_u8, m_rowstride * m_height);
00130 memset(m_tempBuffer, 0, m_rowstride * m_height);
00131
00132
00133 art_u8 *temp = m_buffer;
00134 m_buffer = m_tempBuffer;
00135 m_tempBuffer = temp;
00136 }
00137
00138 void mixBuffer(int opacity)
00139 {
00140 art_u8 *srcPixel = m_buffer;
00141 art_u8 *dstPixel = m_tempBuffer;
00142
00143 for(int y = 0; y < m_height; y++)
00144 {
00145 for(int x = 0; x < m_width; x++)
00146 {
00147 art_u8 r, g, b, a;
00148
00149 a = srcPixel[4 * x + 3];
00150
00151 if(a)
00152 {
00153 r = srcPixel[4 * x];
00154 g = srcPixel[4 * x + 1];
00155 b = srcPixel[4 * x + 2];
00156
00157 int temp = a * opacity + 0x80;
00158 a = (temp + (temp >> 8)) >> 8;
00159 art_rgba_run_alpha(dstPixel + 4 * x, r, g, b, a, 1);
00160 }
00161 }
00162
00163 srcPixel += m_rowstride;
00164 dstPixel += m_rowstride;
00165 }
00166
00167
00168 art_u8 *temp = m_buffer;
00169 m_buffer = m_tempBuffer;
00170 m_tempBuffer = temp;
00171
00172 art_free(m_tempBuffer);
00173 m_tempBuffer = 0;
00174 }
00175
00176 Q_UINT32 toArtColor(QColor color)
00177 {
00178
00179 QString tempName = color.name();
00180 const char *str = tempName.latin1();
00181
00182 int result = 0;
00183
00184 for(int i = 1; str[i]; i++)
00185 {
00186 int hexval;
00187 if(str[i] >= '0' && str[i] <= '9')
00188 hexval = str[i] - '0';
00189 else if (str[i] >= 'A' && str[i] <= 'F')
00190 hexval = str[i] - 'A' + 10;
00191 else if (str[i] >= 'a' && str[i] <= 'f')
00192 hexval = str[i] - 'a' + 10;
00193 else
00194 break;
00195
00196 result = (result << 4) + hexval;
00197 }
00198
00199 return result;
00200 }
00201
00202 void drawSVP(ArtSVP *svp, Q_UINT32 rgb, int opacity)
00203 {
00204 if(!svp)
00205 return;
00206
00207 ArtRender *render = art_render_new(0, 0, m_width, m_height, m_buffer, m_rowstride, 3, 8, ART_ALPHA_SEPARATE, 0);
00208 art_render_svp(render, svp);
00209
00210 art_render_mask_solid(render, (opacity << 8) + opacity + (opacity >> 7));
00211
00212 ArtPixMaxDepth color[3];
00213 color[0] = ART_PIX_MAX_FROM_8(rgb >> 16);
00214 color[1] = ART_PIX_MAX_FROM_8((rgb >> 8) & 0xff);
00215 color[2] = ART_PIX_MAX_FROM_8(rgb & 0xff);
00216
00217 art_render_image_solid(render, color);
00218 art_render_invoke(render);
00219 }
00220
00221 void drawVPath(ArtVpath *vec)
00222 {
00223 ArtSVP *svp;
00224
00225 double affine[6];
00226 affine[0] = m_worldMatrix->m11();
00227 affine[1] = m_worldMatrix->m12();
00228 affine[2] = m_worldMatrix->m21();
00229 affine[3] = m_worldMatrix->m22();
00230 affine[4] = m_worldMatrix->dx();
00231 affine[5] = m_worldMatrix->dy();
00232
00233 ArtVpath *temp = art_vpath_affine_transform(vec, affine);
00234 art_free(vec);
00235 vec = temp;
00236
00237 ArtSVP *fillSVP = 0, *strokeSVP = 0;
00238
00239 Q_UINT32 fillColor = 0, strokeColor = 0;
00240
00241
00242 {
00243 int index = -1;
00244 QValueVector<int> toCorrect;
00245 while(vec[++index].code != ART_END)
00246 {
00247 if(vec[index].code == ART_END2)
00248 {
00249 vec[index].code = ART_LINETO;
00250 toCorrect.push_back(index);
00251 }
00252 }
00253
00254 fillColor = toArtColor(m_fillColor);
00255
00256 ArtSvpWriter *swr;
00257 ArtSVP *temp;
00258 temp = art_svp_from_vpath(vec);
00259
00260 if(m_fillRule == "evenodd")
00261 swr = art_svp_writer_rewind_new(ART_WIND_RULE_ODDEVEN);
00262 else
00263 swr = art_svp_writer_rewind_new(ART_WIND_RULE_NONZERO);
00264
00265 art_svp_intersector(temp, swr);
00266 svp = art_svp_writer_rewind_reap(swr);
00267
00268 fillSVP = svp;
00269
00270 art_svp_free(temp);
00271
00272 QValueVector<int>::iterator it;
00273 for(it = toCorrect.begin(); it != toCorrect.end(); ++it)
00274 vec[(*it)].code = (ArtPathcode)ART_END2;
00275 }
00276
00277
00278
00279 if(m_strokeWidth <= 0)
00280 m_useStroke = m_useStrokeGradient = false;
00281
00282
00283 if(m_useStroke || m_useStrokeGradient)
00284 {
00285 strokeColor = toArtColor(m_strokeColor);
00286
00287 double ratio = sqrt(pow(affine[0], 2) + pow(affine[3], 2)) / sqrt(2.0);
00288 double strokeWidth = m_strokeWidth * ratio;
00289
00290 ArtPathStrokeJoinType joinStyle = ART_PATH_STROKE_JOIN_MITER;
00291 ArtPathStrokeCapType capStyle = ART_PATH_STROKE_CAP_BUTT;
00292
00293 if(m_joinStyle == "miter")
00294 joinStyle = ART_PATH_STROKE_JOIN_MITER;
00295 else if(m_joinStyle == "round")
00296 joinStyle = ART_PATH_STROKE_JOIN_ROUND;
00297 else if(m_joinStyle == "bevel")
00298 joinStyle = ART_PATH_STROKE_JOIN_BEVEL;
00299
00300 if(m_capStyle == "butt")
00301 capStyle = ART_PATH_STROKE_CAP_BUTT;
00302 else if(m_capStyle == "round")
00303 capStyle = ART_PATH_STROKE_CAP_ROUND;
00304 else if(m_capStyle == "square")
00305 capStyle = ART_PATH_STROKE_CAP_SQUARE;
00306
00307 if(m_dashes.length() > 0)
00308 {
00309 QRegExp reg("[a-zA-Z,(; ]");
00310 QStringList dashList = QStringList::split(reg, m_dashes);
00311
00312 double *dashes = new double[dashList.count()];
00313 for(unsigned int i = 0; i < dashList.count(); i++)
00314 dashes[i] = dashList[i].toDouble();
00315
00316 ArtVpathDash dash;
00317 dash.offset = m_dashOffset;
00318 dash.n_dash = dashList.count();
00319
00320 dash.dash = dashes;
00321
00322 ArtVpath *vec2 = art_vpath_dash(vec, &dash);
00323 art_free(vec);
00324
00325 delete dashes;
00326
00327 vec = vec2;
00328 }
00329
00330 svp = art_svp_vpath_stroke(vec, joinStyle, capStyle, strokeWidth, m_strokeMiterLimit, 0.25);
00331
00332 strokeSVP = svp;
00333 }
00334
00335
00336 int fillOpacity = static_cast<int>(m_fillOpacity);
00337 int strokeOpacity = static_cast<int>(m_strokeOpacity);
00338 int opacity = static_cast<int>(m_opacity);
00339
00340
00341
00342 if(fillOpacity == strokeOpacity && fillOpacity == opacity && !m_useFillGradient && !m_useStrokeGradient)
00343 opacity = 255;
00344
00345 if(fillOpacity != 255)
00346 {
00347 int temp = fillOpacity * opacity + 0x80;
00348 fillOpacity = (temp + (temp >> 8)) >> 8;
00349 }
00350
00351 if(strokeOpacity != 255)
00352 {
00353 int temp = strokeOpacity * opacity + 0x80;
00354 strokeOpacity = (temp + (temp >> 8)) >> 8;
00355 }
00356
00357
00358 bool tempDone = false;
00359 if(m_opacity != 0xff)
00360 {
00361 tempDone = true;
00362 createBuffer();
00363 }
00364
00365
00366 if(m_useFillGradient)
00367 applyGradient(fillSVP, true);
00368 else if(m_useFill)
00369 drawSVP(fillSVP, fillColor, fillOpacity);
00370
00371 if(m_useStrokeGradient)
00372 applyGradient(strokeSVP, false);
00373 else if(m_useStroke)
00374 drawSVP(strokeSVP, strokeColor, strokeOpacity);
00375
00376
00377 if(tempDone)
00378 mixBuffer(opacity);
00379
00380 if(m_clipSVP)
00381 {
00382 art_svp_free(m_clipSVP);
00383 m_clipSVP = 0;
00384 }
00385
00386 if(fillSVP)
00387 art_svp_free(fillSVP);
00388
00389 if(strokeSVP)
00390 art_svp_free(strokeSVP);
00391
00392
00393 m_opacity = 255.0;
00394 m_fillOpacity = 255.0;
00395 m_strokeOpacity = 255.0;
00396
00397 art_free(vec);
00398 }
00399
00400 void applyLinearGradient(ArtSVP *svp, const QString &ref)
00401 {
00402 ArtGradientLinear *linear = m_linearGradientMap[ref];
00403 if(linear)
00404 {
00405 QDomElement element = m_linearGradientElementMap[linear];
00406
00407 double x1, y1, x2, y2;
00408 if(element.hasAttribute("x1"))
00409 x1 = m_painter->toPixel(element.attribute("x1"), true);
00410 else
00411 x1 = 0;
00412
00413 if(element.hasAttribute("y1"))
00414 y1 = m_painter->toPixel(element.attribute("y1"), false);
00415 else
00416 y1 = 0;
00417
00418 if(element.hasAttribute("x2"))
00419 x2 = m_painter->toPixel(element.attribute("x2"), true);
00420 else
00421 x2 = 100;
00422
00423 if(element.hasAttribute("y2"))
00424 y2 = m_painter->toPixel(element.attribute("y2"), false);
00425 else
00426 y2 = 0;
00427
00428
00429 QWMatrix m = m_painter->parseTransform(element.attribute("gradientTransform"));
00430 m.map(x1, y1, &x1, &y1);
00431 m.map(x2, y2, &x2, &y2);
00432
00433 double x1n = x1 * m_worldMatrix->m11() + y1 * m_worldMatrix->m21() + m_worldMatrix->dx();
00434 double y1n = x1 * m_worldMatrix->m12() + y1 * m_worldMatrix->m22() + m_worldMatrix->dy();
00435 double x2n = x2 * m_worldMatrix->m11() + y2 * m_worldMatrix->m21() + m_worldMatrix->dx();
00436 double y2n = x2 * m_worldMatrix->m12() + y2 * m_worldMatrix->m22() + m_worldMatrix->dy();
00437
00438 double dx = x2n - x1n;
00439 double dy = y2n - y1n;
00440 double scale = 1.0 / (dx * dx + dy * dy);
00441
00442 linear->a = dx * scale;
00443 linear->b = dy * scale;
00444 linear->c = -(x1n * linear->a + y1n * linear->b);
00445
00446 ArtRender *render = art_render_new(0, 0, m_width, m_height, m_buffer, m_rowstride, 3, 8, ART_ALPHA_SEPARATE, 0);
00447 art_render_svp(render, svp);
00448
00449 art_render_gradient_linear(render, linear, ART_FILTER_HYPER);
00450 art_render_invoke(render);
00451 }
00452 }
00453
00454 void applyRadialGradient(ArtSVP *svp, const QString &ref)
00455 {
00456 ArtGradientRadial *radial = m_radialGradientMap[ref];
00457 if(radial)
00458 {
00459 QDomElement element = m_radialGradientElementMap[radial];
00460
00461 double cx, cy, r, fx, fy;
00462 if(element.hasAttribute("cx"))
00463 cx = m_painter->toPixel(element.attribute("cx"), true);
00464 else
00465 cx = 50;
00466
00467 if(element.hasAttribute("cy"))
00468 cy = m_painter->toPixel(element.attribute("cy"), false);
00469 else
00470 cy = 50;
00471
00472 if(element.hasAttribute("r"))
00473 r = m_painter->toPixel(element.attribute("r"), true);
00474 else
00475 r = 50;
00476
00477 if(element.hasAttribute("fx"))
00478 fx = m_painter->toPixel(element.attribute("fx"), false);
00479 else
00480 fx = cx;
00481
00482 if(element.hasAttribute("fy"))
00483 fy = m_painter->toPixel(element.attribute("fy"), false);
00484 else
00485 fy = cy;
00486
00487 radial->affine[0] = m_worldMatrix->m11();
00488 radial->affine[1] = m_worldMatrix->m12();
00489 radial->affine[2] = m_worldMatrix->m21();
00490 radial->affine[3] = m_worldMatrix->m22();
00491 radial->affine[4] = m_worldMatrix->dx();
00492 radial->affine[5] = m_worldMatrix->dy();
00493
00494 radial->fx = (fx - cx) / r;
00495 radial->fy = (fy - cy) / r;
00496
00497 double aff1[6], aff2[6], gradTransform[6];
00498
00499
00500 QWMatrix m = m_painter->parseTransform(element.attribute("gradientTransform"));
00501
00502 gradTransform[0] = m.m11();
00503 gradTransform[1] = m.m12();
00504 gradTransform[2] = m.m21();
00505 gradTransform[3] = m.m22();
00506 gradTransform[4] = m.dx();
00507 gradTransform[5] = m.dy();
00508
00509 art_affine_scale(aff1, r, r);
00510 art_affine_translate(aff2, cx, cy);
00511
00512 art_affine_multiply(aff1, aff1, aff2);
00513 art_affine_multiply(aff1, aff1, gradTransform);
00514 art_affine_multiply(aff1, aff1, radial->affine);
00515 art_affine_invert(radial->affine, aff1);
00516
00517 ArtRender *render = art_render_new(0, 0, m_width, m_height, m_buffer, m_rowstride, 3, 8, ART_ALPHA_SEPARATE, 0);
00518 art_render_svp(render, svp);
00519
00520 art_render_gradient_radial(render, radial, ART_FILTER_HYPER);
00521 art_render_invoke(render);
00522 }
00523 }
00524
00525 void applyGradient(ArtSVP *svp, const QString &ref)
00526 {
00527 ArtGradientLinear *linear = m_linearGradientMap[ref];
00528 if(linear)
00529 {
00530 QDomElement element = m_linearGradientElementMap[linear];
00531
00532 if(!element.hasAttribute("xlink:href"))
00533 {
00534 applyLinearGradient(svp, ref);
00535 return;
00536 }
00537 else
00538 {
00539 ArtGradientLinear *linear = m_linearGradientMap[element.attribute("xlink:href").mid(1)];
00540 QDomElement newElement = m_linearGradientElementMap[linear];
00541
00542
00543 QDict<QString> refattrs;
00544 refattrs.setAutoDelete(true);
00545
00546 for(unsigned int i = 0; i < newElement.attributes().length(); ++i)
00547 refattrs.insert(newElement.attributes().item(i).nodeName(), new QString(newElement.attributes().item(i).nodeValue()));
00548
00549
00550 if(!newElement.isNull())
00551 {
00552 QDomNamedNodeMap attr = element.attributes();
00553
00554 for(unsigned int i = 0; i < attr.length(); i++)
00555 {
00556 QString name = attr.item(i).nodeName();
00557 if(name != "xlink:href" && name != "id")
00558 newElement.setAttribute(name, attr.item(i).nodeValue());
00559 }
00560 }
00561
00562 applyGradient(svp, element.attribute("xlink:href").mid(1));
00563
00564
00565 QDictIterator<QString> itr(refattrs);
00566 for(; itr.current(); ++itr)
00567 newElement.setAttribute(itr.currentKey(), *(itr.current()));
00568
00569 return;
00570 }
00571 }
00572
00573 ArtGradientRadial *radial = m_radialGradientMap[ref];
00574 if(radial)
00575 {
00576 QDomElement element = m_radialGradientElementMap[radial];
00577
00578 if(!element.hasAttribute("xlink:href"))
00579 {
00580 applyRadialGradient(svp, ref);
00581 return;
00582 }
00583 else
00584 {
00585 ArtGradientRadial *radial = m_radialGradientMap[element.attribute("xlink:href").mid(1)];
00586 QDomElement newElement = m_radialGradientElementMap[radial];
00587
00588
00589 QDict<QString> refattrs;
00590 refattrs.setAutoDelete(true);
00591
00592 for(unsigned int i = 0; i < newElement.attributes().length(); ++i)
00593 refattrs.insert(newElement.attributes().item(i).nodeName(), new QString(newElement.attributes().item(i).nodeValue()));
00594
00595
00596 if(!newElement.isNull())
00597 {
00598 QDomNamedNodeMap attr = element.attributes();
00599
00600 for(unsigned int i = 0; i < attr.length(); i++)
00601 {
00602 QString name = attr.item(i).nodeName();
00603 if(name != "xlink:href" && name != "id")
00604 newElement.setAttribute(name, attr.item(i).nodeValue());
00605 }
00606 }
00607
00608 applyGradient(svp, element.attribute("xlink:href").mid(1));
00609
00610
00611 QDictIterator<QString> itr(refattrs);
00612 for(; itr.current(); ++itr)
00613 newElement.setAttribute(itr.currentKey(), *(itr.current()));
00614
00615 return;
00616 }
00617 }
00618 }
00619
00620 void applyGradient(ArtSVP *svp, bool fill)
00621 {
00622 QString ref;
00623
00624 if(fill)
00625 {
00626 m_useFillGradient = false;
00627 ref = m_fillGradientReference;
00628 }
00629 else
00630 {
00631 m_useStrokeGradient = false;
00632 ref = m_strokeGradientReference;
00633 }
00634
00635 applyGradient(svp, ref);
00636 }
00637
00638 void blit()
00639 {
00640 unsigned char *line = m_buffer;
00641
00642 for(int y = 0; y < m_height; y++)
00643 {
00644 QRgb *sl = reinterpret_cast<QRgb *>(m_image->scanLine(y));
00645 for(int x = 0; x < m_width; x++)
00646 sl[x] = qRgba(line[x * 4], line[x * 4 + 1], line[x * 4 + 2], line[x * 4 + 3]);
00647
00648 line += m_rowstride;
00649 }
00650 }
00651
00652 void calculateArc(bool relative, QMemArray<ArtBpath> &vec, int &index, double &curx, double &cury, double angle, double x, double y, double r1, double r2, bool largeArcFlag, bool sweepFlag)
00653 {
00654 double sin_th, cos_th;
00655 double a00, a01, a10, a11;
00656 double x0, y0, x1, y1, xc, yc;
00657 double d, sfactor, sfactor_sq;
00658 double th0, th1, th_arc;
00659 int i, n_segs;
00660
00661 sin_th = sin(angle * (M_PI / 180.0));
00662 cos_th = cos(angle * (M_PI / 180.0));
00663
00664 double dx;
00665
00666 if(!relative)
00667 dx = (curx - x) / 2.0;
00668 else
00669 dx = -x / 2.0;
00670
00671 double dy;
00672
00673 if(!relative)
00674 dy = (cury - y) / 2.0;
00675 else
00676 dy = -y / 2.0;
00677
00678 double _x1 = cos_th * dx + sin_th * dy;
00679 double _y1 = -sin_th * dx + cos_th * dy;
00680 double Pr1 = r1 * r1;
00681 double Pr2 = r2 * r2;
00682 double Px = _x1 * _x1;
00683 double Py = _y1 * _y1;
00684
00685
00686 double check = Px / Pr1 + Py / Pr2;
00687 if(check > 1)
00688 {
00689 r1 = r1 * sqrt(check);
00690 r2 = r2 * sqrt(check);
00691 }
00692
00693 a00 = cos_th / r1;
00694 a01 = sin_th / r1;
00695 a10 = -sin_th / r2;
00696 a11 = cos_th / r2;
00697
00698 x0 = a00 * curx + a01 * cury;
00699 y0 = a10 * curx + a11 * cury;
00700
00701 if(!relative)
00702 x1 = a00 * x + a01 * y;
00703 else
00704 x1 = a00 * (curx + x) + a01 * (cury + y);
00705
00706 if(!relative)
00707 y1 = a10 * x + a11 * y;
00708 else
00709 y1 = a10 * (curx + x) + a11 * (cury + y);
00710
00711
00712
00713
00714
00715
00716
00717 d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
00718
00719 sfactor_sq = 1.0 / d - 0.25;
00720
00721 if(sfactor_sq < 0)
00722 sfactor_sq = 0;
00723
00724 sfactor = sqrt(sfactor_sq);
00725
00726 if(sweepFlag == largeArcFlag)
00727 sfactor = -sfactor;
00728
00729 xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
00730 yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
00731
00732
00733 th0 = atan2(y0 - yc, x0 - xc);
00734 th1 = atan2(y1 - yc, x1 - xc);
00735
00736 th_arc = th1 - th0;
00737 if(th_arc < 0 && sweepFlag)
00738 th_arc += 2 * M_PI;
00739 else if(th_arc > 0 && !sweepFlag)
00740 th_arc -= 2 * M_PI;
00741
00742 n_segs = (int) (int) ceil(fabs(th_arc / (M_PI * 0.5 + 0.001)));
00743
00744 for(i = 0; i < n_segs; i++)
00745 {
00746 index++;
00747
00748 ensureSpace(vec, index);
00749
00750 {
00751 double sin_th, cos_th;
00752 double a00, a01, a10, a11;
00753 double x1, y1, x2, y2, x3, y3;
00754 double t;
00755 double th_half;
00756
00757 double _th0 = th0 + i * th_arc / n_segs;
00758 double _th1 = th0 + (i + 1) * th_arc / n_segs;
00759
00760 sin_th = sin(angle * (M_PI / 180.0));
00761 cos_th = cos(angle * (M_PI / 180.0));
00762
00763
00764 a00 = cos_th * r1;
00765 a01 = -sin_th * r2;
00766 a10 = sin_th * r1;
00767 a11 = cos_th * r2;
00768
00769 th_half = 0.5 * (_th1 - _th0);
00770 t = (8.0 / 3.0) * sin(th_half * 0.5) * sin(th_half * 0.5) / sin(th_half);
00771 x1 = xc + cos(_th0) - t * sin(_th0);
00772 y1 = yc + sin(_th0) + t * cos(_th0);
00773 x3 = xc + cos(_th1);
00774 y3 = yc + sin(_th1);
00775 x2 = x3 + t * sin(_th1);
00776 y2 = y3 - t * cos(_th1);
00777
00778 ensureSpace(vec, index);
00779
00780 vec[index].code = ART_CURVETO;
00781 vec[index].x1 = a00 * x1 + a01 * y1;
00782 vec[index].y1 = a10 * x1 + a11 * y1;
00783 vec[index].x2 = a00 * x2 + a01 * y2;
00784 vec[index].y2 = a10 * x2 + a11 * y2;
00785 vec[index].x3 = a00 * x3 + a01 * y3;
00786 vec[index].y3 = a10 * x3 + a11 * y3;
00787 }
00788 }
00789
00790 if(!relative)
00791 curx = x;
00792 else
00793 curx += x;
00794
00795 if(!relative)
00796 cury = y;
00797 else
00798 cury += y;
00799 }
00800
00801
00802 static void art_vpath_render_bez(ArtVpath **p_vpath, int *pn, int *pn_max,
00803 double x0, double y0,
00804 double x1, double y1,
00805 double x2, double y2,
00806 double x3, double y3,
00807 double flatness)
00808 {
00809 double x3_0, y3_0, z3_0_dot, z1_dot, z2_dot;
00810 double z1_perp, z2_perp, max_perp_sq;
00811
00812 double x_m, y_m, xa1, ya1, xa2, ya2, xb1, yb1, xb2, yb2;
00813
00814 x3_0 = x3 - x0;
00815 y3_0 = y3 - y0;
00816
00817 z3_0_dot = x3_0 * x3_0 + y3_0 * y3_0;
00818
00819 if (z3_0_dot < 0.001)
00820 goto nosubdivide;
00821
00822 max_perp_sq = flatness * flatness * z3_0_dot;
00823
00824 z1_perp = (y1 - y0) * x3_0 - (x1 - x0) * y3_0;
00825 if (z1_perp * z1_perp > max_perp_sq)
00826 goto subdivide;
00827
00828 z2_perp = (y3 - y2) * x3_0 - (x3 - x2) * y3_0;
00829 if (z2_perp * z2_perp > max_perp_sq)
00830 goto subdivide;
00831
00832 z1_dot = (x1 - x0) * x3_0 + (y1 - y0) * y3_0;
00833 if (z1_dot < 0 && z1_dot * z1_dot > max_perp_sq)
00834 goto subdivide;
00835
00836 z2_dot = (x3 - x2) * x3_0 + (y3 - y2) * y3_0;
00837 if (z2_dot < 0 && z2_dot * z2_dot > max_perp_sq)
00838 goto subdivide;
00839
00840 if (z1_dot + z1_dot > z3_0_dot)
00841 goto subdivide;
00842
00843 if (z2_dot + z2_dot > z3_0_dot)
00844 goto subdivide;
00845
00846 nosubdivide:
00847 art_vpath_add_point (p_vpath, pn, pn_max, ART_LINETO, x3, y3);
00848 return;
00849
00850 subdivide:
00851 xa1 = (x0 + x1) * 0.5;
00852 ya1 = (y0 + y1) * 0.5;
00853 xa2 = (x0 + 2 * x1 + x2) * 0.25;
00854 ya2 = (y0 + 2 * y1 + y2) * 0.25;
00855 xb1 = (x1 + 2 * x2 + x3) * 0.25;
00856 yb1 = (y1 + 2 * y2 + y3) * 0.25;
00857 xb2 = (x2 + x3) * 0.5;
00858 yb2 = (y2 + y3) * 0.5;
00859 x_m = (xa2 + xb1) * 0.5;
00860 y_m = (ya2 + yb1) * 0.5;
00861 art_vpath_render_bez (p_vpath, pn, pn_max, x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, flatness);
00862 art_vpath_render_bez (p_vpath, pn, pn_max, x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, flatness);
00863 }
00864
00865 ArtVpath *art_bez_path_to_vec(const ArtBpath *bez, double flatness)
00866 {
00867 ArtVpath *vec;
00868 int vec_n, vec_n_max;
00869 int bez_index;
00870 double x, y;
00871
00872 vec_n = 0;
00873 vec_n_max = (1 << 4);
00874 vec = art_new (ArtVpath, vec_n_max);
00875
00876 x = 0;
00877 y = 0;
00878
00879 bez_index = 0;
00880 do
00881 {
00882 if(vec_n >= vec_n_max)
00883 art_expand (vec, ArtVpath, vec_n_max);
00884
00885 switch (bez[bez_index].code)
00886 {
00887 case ART_MOVETO_OPEN:
00888 case ART_MOVETO:
00889 case ART_LINETO:
00890 x = bez[bez_index].x3;
00891 y = bez[bez_index].y3;
00892 vec[vec_n].code = bez[bez_index].code;
00893 vec[vec_n].x = x;
00894 vec[vec_n].y = y;
00895 vec_n++;
00896 break;
00897 case ART_END:
00898 vec[vec_n].code = ART_END;
00899 vec[vec_n].x = 0;
00900 vec[vec_n].y = 0;
00901 vec_n++;
00902 break;
00903 case ART_END2:
00904 vec[vec_n].code = (ArtPathcode)ART_END2;
00905 vec[vec_n].x = bez[bez_index].x3;
00906 vec[vec_n].y = bez[bez_index].y3;
00907 vec_n++;
00908 break;
00909 case ART_CURVETO:
00910 art_vpath_render_bez (&vec, &vec_n, &vec_n_max,
00911 x, y,
00912 bez[bez_index].x1, bez[bez_index].y1,
00913 bez[bez_index].x2, bez[bez_index].y2,
00914 bez[bez_index].x3, bez[bez_index].y3,
00915 flatness);
00916 x = bez[bez_index].x3;
00917 y = bez[bez_index].y3;
00918 break;
00919 }
00920 }
00921
00922 while (bez[bez_index++].code != ART_END);
00923 return vec;
00924 }
00925
00926 static void art_rgb_affine_run(int *p_x0, int *p_x1, int y,
00927 int src_width, int src_height,
00928 const double affine[6])
00929 {
00930 int x0, x1;
00931 double z;
00932 double x_intercept;
00933 int xi;
00934
00935 x0 = *p_x0;
00936 x1 = *p_x1;
00937
00938 if (affine[0] > 1e-6)
00939 {
00940 z = affine[2] * (y + 0.5) + affine[4];
00941 x_intercept = -z / affine[0];
00942 xi = (int) (int) ceil (x_intercept + 1e-6 - 0.5);
00943 if (xi > x0)
00944 x0 = xi;
00945 x_intercept = (-z + src_width) / affine[0];
00946 xi = (int) ceil (x_intercept - 1e-6 - 0.5);
00947 if (xi < x1)
00948 x1 = xi;
00949 }
00950 else if (affine[0] < -1e-6)
00951 {
00952 z = affine[2] * (y + 0.5) + affine[4];
00953 x_intercept = (-z + src_width) / affine[0];
00954 xi = (int) ceil (x_intercept + 1e-6 - 0.5);
00955 if (xi > x0)
00956 x0 = xi;
00957 x_intercept = -z / affine[0];
00958 xi = (int) ceil (x_intercept - 1e-6 - 0.5);
00959 if (xi < x1)
00960 x1 = xi;
00961 }
00962 else
00963 {
00964 z = affine[2] * (y + 0.5) + affine[4];
00965 if (z < 0 || z >= src_width)
00966 {
00967 *p_x1 = *p_x0;
00968 return;
00969 }
00970 }
00971 if (affine[1] > 1e-6)
00972 {
00973 z = affine[3] * (y + 0.5) + affine[5];
00974 x_intercept = -z / affine[1];
00975 xi = (int) ceil (x_intercept + 1e-6 - 0.5);
00976 if (xi > x0)
00977 x0 = xi;
00978 x_intercept = (-z + src_height) / affine[1];
00979 xi = (int) ceil (x_intercept - 1e-6 - 0.5);
00980 if (xi < x1)
00981 x1 = xi;
00982 }
00983 else if (affine[1] < -1e-6)
00984 {
00985 z = affine[3] * (y + 0.5) + affine[5];
00986 x_intercept = (-z + src_height) / affine[1];
00987 xi = (int) ceil (x_intercept + 1e-6 - 0.5);
00988 if (xi > x0)
00989 x0 = xi;
00990 x_intercept = -z / affine[1];
00991 xi = (int) ceil (x_intercept - 1e-6 - 0.5);
00992 if (xi < x1)
00993 x1 = xi;
00994 }
00995 else
00996 {
00997 z = affine[3] * (y + 0.5) + affine[5];
00998 if (z < 0 || z >= src_height)
00999 {
01000 *p_x1 = *p_x0;
01001 return;
01002 }
01003 }
01004
01005 *p_x0 = x0;
01006 *p_x1 = x1;
01007 }
01008
01009
01010 static void art_rgba_rgba_affine(art_u8 *dst,
01011 int x0, int y0, int x1, int y1, int dst_rowstride,
01012 const art_u8 *src,
01013 int src_width, int src_height, int src_rowstride,
01014 const double affine[6])
01015 {
01016 int x, y;
01017 double inv[6];
01018 art_u8 *dst_p, *dst_linestart;
01019 const art_u8 *src_p;
01020 ArtPoint pt, src_pt;
01021 int src_x, src_y;
01022 int alpha;
01023 art_u8 bg_r, bg_g, bg_b, bg_a, cr, cg, cb;
01024 art_u8 fg_r, fg_g, fg_b;
01025 int tmp;
01026 int run_x0, run_x1;
01027
01028 dst_linestart = dst;
01029 art_affine_invert (inv, affine);
01030 for (y = y0; y < y1; y++)
01031 {
01032 pt.y = y + 0.5;
01033 run_x0 = x0;
01034 run_x1 = x1;
01035 art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
01036 inv);
01037 dst_p = dst_linestart + (run_x0 - x0) * 4;
01038 for (x = run_x0; x < run_x1; x++)
01039 {
01040 pt.x = x + 0.5;
01041 art_affine_point (&src_pt, &pt, inv);
01042 src_x = (int) floor (src_pt.x);
01043 src_y = (int) floor (src_pt.y);
01044 src_p = src + (src_y * src_rowstride) + src_x * 4;
01045 if (src_x >= 0 && src_x < src_width &&
01046 src_y >= 0 && src_y < src_height)
01047 {
01048
01049 alpha = src_p[3];
01050 if (alpha)
01051 {
01052 if (alpha == 255)
01053 {
01054 dst_p[0] = src_p[0];
01055 dst_p[1] = src_p[1];
01056 dst_p[2] = src_p[2];
01057 dst_p[3] = 255;
01058 }
01059 else
01060 {
01061 bg_r = dst_p[0];
01062 bg_g = dst_p[1];
01063 bg_b = dst_p[2];
01064 bg_a = dst_p[3];
01065
01066 cr = (bg_r * bg_a + 0x80) >> 8;
01067 cg = (bg_g * bg_g + 0x80) >> 8;
01068 cb = (bg_b * bg_b + 0x80) >> 8;
01069
01070 tmp = (src_p[0] - bg_r) * alpha;
01071 fg_r = bg_r + ((tmp + (tmp >> 8) + 0x80) >> 8);
01072 tmp = (src_p[1] - bg_g) * alpha;
01073 fg_g = bg_g + ((tmp + (tmp >> 8) + 0x80) >> 8);
01074 tmp = (src_p[2] - bg_b) * alpha;
01075 fg_b = bg_b + ((tmp + (tmp >> 8) + 0x80) >> 8);
01076
01077 dst_p[0] = fg_r;
01078 dst_p[1] = fg_g;
01079 dst_p[2] = fg_b;
01080 dst_p[3] = bg_a + (((255 - bg_a) * alpha + 0x80) >> 8);
01081 }
01082 }
01083 } else { dst_p[0] = 255; dst_p[1] = 0; dst_p[2] = 0; dst_p[3] = 255;}
01084 dst_p += 4;
01085 }
01086 dst_linestart += dst_rowstride;
01087 }
01088 }
01089
01090 private:
01091 friend class KSVGIconPainter;
01092 ArtSVP *m_clipSVP;
01093
01094 QImage *m_image;
01095 QWMatrix *m_worldMatrix;
01096
01097 QString m_fillRule;
01098 QString m_joinStyle;
01099 QString m_capStyle;
01100
01101 int m_strokeMiterLimit;
01102
01103 QString m_dashes;
01104 unsigned short m_dashOffset;
01105
01106 QColor m_fillColor;
01107 QColor m_strokeColor;
01108
01109 art_u8 *m_buffer;
01110 art_u8 *m_tempBuffer;
01111
01112 int m_width;
01113 int m_height;
01114
01115 int m_rowstride;
01116
01117 double m_opacity;
01118 double m_fillOpacity;
01119 double m_strokeOpacity;
01120
01121 bool m_useFill;
01122 bool m_useStroke;
01123
01124 bool m_useFillGradient;
01125 bool m_useStrokeGradient;
01126
01127 QString m_fillGradientReference;
01128 QString m_strokeGradientReference;
01129
01130 QMap<QString, ArtGradientLinear *> m_linearGradientMap;
01131 QMap<ArtGradientLinear *, QDomElement> m_linearGradientElementMap;
01132
01133 QMap<QString, ArtGradientRadial *> m_radialGradientMap;
01134 QMap<ArtGradientRadial *, QDomElement> m_radialGradientElementMap;
01135
01136 KSVGIconPainter *m_painter;
01137
01138 double m_strokeWidth;
01139 };
01140
01141 struct KSVGIconPainter::Private
01142 {
01143 KSVGIconPainterHelper *helper;
01144
01145 int drawWidth;
01146 int drawHeight;
01147 };
01148
01149 KSVGIconPainter::KSVGIconPainter(int width, int height, int dwidth, int dheight) : d(new Private())
01150 {
01151 d->helper = new KSVGIconPainterHelper(width, height, this);
01152
01153 d->drawWidth = dwidth;
01154 d->drawHeight = dheight;
01155 }
01156
01157 KSVGIconPainter::~KSVGIconPainter()
01158 {
01159 delete d->helper;
01160 delete d;
01161 }
01162
01163 void KSVGIconPainter::finish()
01164 {
01165 d->helper->blit();
01166 }
01167
01168 QImage *KSVGIconPainter::image()
01169 {
01170 return new QImage(*d->helper->m_image);
01171 }
01172
01173 QWMatrix *KSVGIconPainter::worldMatrix()
01174 {
01175 return d->helper->m_worldMatrix;
01176 }
01177
01178 void KSVGIconPainter::setWorldMatrix(QWMatrix *matrix)
01179 {
01180 if(d->helper->m_worldMatrix)
01181 delete d->helper->m_worldMatrix;
01182
01183 d->helper->m_worldMatrix = matrix;
01184 }
01185
01186 void KSVGIconPainter::setStrokeWidth(double width)
01187 {
01188 d->helper->m_strokeWidth = width;
01189 }
01190
01191 void KSVGIconPainter::setStrokeMiterLimit(const QString &miter)
01192 {
01193 d->helper->m_strokeMiterLimit = miter.toInt();
01194 }
01195
01196 void KSVGIconPainter::setStrokeDashOffset(const QString &dashOffset)
01197 {
01198 d->helper->m_dashOffset = dashOffset.toUInt();
01199 }
01200
01201 void KSVGIconPainter::setStrokeDashArray(const QString &dashes)
01202 {
01203 d->helper->m_dashes = dashes;
01204 }
01205
01206 void KSVGIconPainter::setCapStyle(const QString &cap)
01207 {
01208 d->helper->m_capStyle = cap;
01209 }
01210
01211 void KSVGIconPainter::setJoinStyle(const QString &join)
01212 {
01213 d->helper->m_joinStyle = join;
01214 }
01215
01216 void KSVGIconPainter::setStrokeColor(const QString &stroke)
01217 {
01218 if(stroke.startsWith("url"))
01219 {
01220 d->helper->m_useStroke = false;
01221 d->helper->m_useStrokeGradient = true;
01222
01223 QString url = stroke;
01224
01225 unsigned int start = url.find("#") + 1;
01226 unsigned int end = url.findRev(")");
01227
01228 d->helper->m_strokeGradientReference = url.mid(start, end - start);
01229 }
01230 else
01231 {
01232 d->helper->m_strokeColor = parseColor(stroke);
01233
01234 d->helper->m_useStrokeGradient = false;
01235 d->helper->m_strokeGradientReference = QString::null;
01236
01237 if(stroke.stripWhiteSpace().lower() != "none")
01238 setUseStroke(true);
01239 else
01240 setUseStroke(false);
01241 }
01242 }
01243
01244 void KSVGIconPainter::setFillColor(const QString &fill)
01245 {
01246 if(fill.startsWith("url"))
01247 {
01248 d->helper->m_useFill = false;
01249 d->helper->m_useFillGradient = true;
01250
01251 QString url = fill;
01252
01253 unsigned int start = url.find("#") + 1;
01254 unsigned int end = url.findRev(")");
01255
01256 d->helper->m_fillGradientReference = url.mid(start, end - start);
01257 }
01258 else
01259 {
01260 d->helper->m_fillColor = parseColor(fill);
01261
01262 d->helper->m_useFillGradient = false;
01263 d->helper->m_fillGradientReference = QString::null;
01264
01265 if(fill.stripWhiteSpace().lower() != "none")
01266 setUseFill(true);
01267 else
01268 setUseFill(false);
01269 }
01270 }
01271
01272 void KSVGIconPainter::setFillRule(const QString &fillRule)
01273 {
01274 d->helper->m_fillRule = fillRule;
01275 }
01276
01277 Q_UINT32 KSVGIconPainter::parseOpacity(QString data)
01278 {
01279 int opacity = 255;
01280
01281 if(!data.isEmpty())
01282 {
01283 double temp;
01284
01285 if(data.contains("%"))
01286 {
01287 QString tempString = data.left(data.length() - 1);
01288 temp = double(255 * tempString.toDouble()) / 100.0;
01289 }
01290 else
01291 temp = data.toDouble();
01292
01293 opacity = (int) floor(temp * 255 + 0.5);
01294 }
01295
01296 return opacity;
01297 }
01298
01299 void KSVGIconPainter::setFillOpacity(const QString &fillOpacity)
01300 {
01301 d->helper->m_fillOpacity = parseOpacity(fillOpacity);
01302 }
01303
01304 void KSVGIconPainter::setStrokeOpacity(const QString &strokeOpacity)
01305 {
01306 d->helper->m_strokeOpacity = parseOpacity(strokeOpacity);
01307 }
01308
01309 void KSVGIconPainter::setOpacity(const QString &opacity)
01310 {
01311 d->helper->m_opacity = parseOpacity(opacity);
01312 }
01313
01314 void KSVGIconPainter::setUseFill(bool fill)
01315 {
01316 d->helper->m_useFill = fill;
01317 }
01318
01319 void KSVGIconPainter::setUseStroke(bool stroke)
01320 {
01321 d->helper->m_useStroke = stroke;
01322 }
01323
01324 void KSVGIconPainter::setClippingRect(int x, int y, int w, int h)
01325 {
01326 ArtVpath *vec = d->helper->allocVPath(6);
01327
01328 vec[0].code = ART_MOVETO;
01329 vec[0].x = x;
01330 vec[0].y = y;
01331
01332 vec[1].code = ART_LINETO;
01333 vec[1].x = x;
01334 vec[1].y = y + h;
01335
01336 vec[2].code = ART_LINETO;
01337 vec[2].x = x + w;
01338 vec[2].y = y + h;
01339
01340 vec[3].code = ART_LINETO;
01341 vec[3].x = x + w;
01342 vec[3].y = y;
01343
01344 vec[4].code = ART_LINETO;
01345 vec[4].x = x;
01346 vec[4].y = y;
01347
01348 vec[5].code = ART_END;
01349
01350 if(d->helper->m_clipSVP)
01351 art_svp_free(d->helper->m_clipSVP);
01352
01353 d->helper->m_clipSVP = art_svp_from_vpath(vec);
01354
01355 art_free(vec);
01356 }
01357
01358 void KSVGIconPainter::drawRectangle(double x, double y, double w, double h, double rx, double ry)
01359 {
01360 if((int) rx != 0 && (int) ry != 0)
01361 {
01362 ArtVpath *res;
01363 ArtBpath *vec = d->helper->allocBPath(10);
01364
01365 int i = 0;
01366
01367 if(rx > w / 2)
01368 rx = w / 2;
01369
01370 if(ry > h / 2)
01371 ry = h / 2;
01372
01373 vec[i].code = ART_MOVETO_OPEN;
01374 vec[i].x3 = x + rx;
01375 vec[i].y3 = y;
01376
01377 i++;
01378
01379 vec[i].code = ART_CURVETO;
01380 vec[i].x1 = x + rx * (1 - 0.552);
01381 vec[i].y1 = y;
01382 vec[i].x2 = x;
01383 vec[i].y2 = y + ry * (1 - 0.552);
01384 vec[i].x3 = x;
01385 vec[i].y3 = y + ry;
01386
01387 i++;
01388
01389 if(ry < h / 2)
01390 {
01391 vec[i].code = ART_LINETO;
01392 vec[i].x3 = x;
01393 vec[i].y3 = y + h - ry;
01394
01395 i++;
01396 }
01397
01398 vec[i].code = ART_CURVETO;
01399 vec[i].x1 = x;
01400 vec[i].y1 = y + h - ry * (1 - 0.552);
01401 vec[i].x2 = x + rx * (1 - 0.552);
01402 vec[i].y2 = y + h;
01403 vec[i].x3 = x + rx;
01404 vec[i].y3 = y + h;
01405
01406 i++;
01407
01408 if(rx < w / 2)
01409 {
01410 vec[i].code = ART_LINETO;
01411 vec[i].x3 = x + w - rx;
01412 vec[i].y3 = y + h;
01413
01414 i++;
01415 }
01416
01417 vec[i].code = ART_CURVETO;
01418 vec[i].x1 = x + w - rx * (1 - 0.552);
01419 vec[i].y1 = y + h;
01420 vec[i].x2 = x + w;
01421 vec[i].y2 = y + h - ry * (1 - 0.552);
01422 vec[i].x3 = x + w;
01423
01424 vec[i].y3 = y + h - ry;
01425
01426 i++;
01427
01428 if(ry < h / 2)
01429 {
01430 vec[i].code = ART_LINETO;
01431 vec[i].x3 = x + w;
01432 vec[i].y3 = y + ry;
01433
01434 i++;
01435 }
01436
01437 vec[i].code = ART_CURVETO;
01438 vec[i].x1 = x + w;
01439 vec[i].y1 = y + ry * (1 - 0.552);
01440 vec[i].x2 = x + w - rx * (1 - 0.552);
01441 vec[i].y2 = y;
01442 vec[i].x3 = x + w - rx;
01443 vec[i].y3 = y;
01444
01445 i++;
01446
01447 if(rx < w / 2)
01448 {
01449 vec[i].code = ART_LINETO;
01450 vec[i].x3 = x + rx;
01451 vec[i].y3 = y;
01452
01453 i++;
01454 }
01455
01456 vec[i].code = ART_END;
01457
01458 res = d->helper->art_bez_path_to_vec(vec, 0.25);
01459 art_free(vec);
01460 d->helper->drawVPath(res);
01461 }
01462 else
01463 {
01464 ArtVpath *vec = d->helper->allocVPath(6);
01465
01466 vec[0].code = ART_MOVETO;
01467 vec[0].x = x;
01468 vec[0].y = y;
01469
01470 vec[1].code = ART_LINETO;
01471 vec[1].x = x;
01472 vec[1].y = y + h;
01473
01474 vec[2].code = ART_LINETO;
01475 vec[2].x = x + w;
01476 vec[2].y = y + h;
01477
01478 vec[3].code = ART_LINETO;
01479 vec[3].x = x + w;
01480 vec[3].y = y;
01481
01482 vec[4].code = ART_LINETO;
01483 vec[4].x = x;
01484 vec[4].y = y;
01485
01486 vec[5].code = ART_END;
01487
01488 d->helper->drawVPath(vec);
01489 }
01490 }
01491
01492 void KSVGIconPainter::drawEllipse(double cx, double cy, double rx, double ry)
01493 {
01494 ArtVpath *vec, *vec2;
01495 ArtBpath *temp, *abp;
01496
01497 temp = d->helper->allocBPath(6);
01498
01499 double x0, y0, x1, y1, x2, y2, x3, y3, len, s, e;
01500 double affine[6];
01501 int i = 0;
01502
01503
01504 art_affine_scale(affine, rx * 10.0, ry * 10.0);
01505
01506 temp[i].code = ART_MOVETO;
01507 temp[i].x3 = cos(0.0);
01508 temp[i].y3 = sin(0.0);
01509
01510 i++;
01511
01512 for(s = 0; s < 2 * M_PI; s += M_PI_2)
01513 {
01514 e = s + M_PI_2;
01515 if(e > 2 * M_PI)
01516 e = 2 * M_PI;
01517
01518 len = 0.552 * (e - s) / M_PI_2;
01519 x0 = cos (s);
01520 y0 = sin (s);
01521 x1 = x0 + len * cos (s + M_PI_2);
01522 y1 = y0 + len * sin (s + M_PI_2);
01523 x3 = cos (e);
01524 y3 = sin (e);
01525 x2 = x3 + len * cos (e - M_PI_2);
01526 y2 = y3 + len * sin (e - M_PI_2);
01527
01528 temp[i].code = ART_CURVETO;
01529 temp[i].x1 = x1;
01530 temp[i].y1 = y1;
01531 temp[i].x2 = x2;
01532 temp[i].y2 = y2;
01533 temp[i].x3 = x3;
01534 temp[i].y3 = y3;
01535
01536 i++;
01537 }
01538
01539 temp[i].code = ART_END;
01540
01541 abp = art_bpath_affine_transform(temp, affine);
01542 vec = d->helper->art_bez_path_to_vec(abp, 0.25);
01543 art_free(abp);
01544
01545 art_affine_scale(affine, 0.1, 0.1);
01546 affine[4] = cx;
01547 affine[5] = cy;
01548 vec2 = art_vpath_affine_transform(vec, affine);
01549
01550 art_free(vec);
01551
01552 d->helper->drawVPath(vec2);
01553 }
01554
01555 void KSVGIconPainter::drawLine(double x1, double y1, double x2, double y2)
01556 {
01557 ArtVpath *vec;
01558
01559 vec = d->helper->allocVPath(3);
01560
01561 vec[0].code = ART_MOVETO_OPEN;
01562 vec[0].x = x1;
01563 vec[0].y = y1;
01564
01565 vec[1].code = ART_LINETO;
01566 vec[1].x = x2;
01567 vec[1].y = y2;
01568
01569 vec[2].code = ART_END;
01570
01571 d->helper->drawVPath(vec);
01572 }
01573
01574 void KSVGIconPainter::drawPolyline(QPointArray polyArray, int points)
01575 {
01576 if(polyArray.point(0).x() == -1 || polyArray.point(0).y() == -1)
01577 return;
01578
01579 ArtVpath *polyline;
01580
01581 if(points == -1)
01582 points = polyArray.count();
01583
01584 polyline = d->helper->allocVPath(3 + points);
01585 polyline[0].code = ART_MOVETO;
01586 polyline[0].x = polyArray.point(0).x();
01587 polyline[0].y = polyArray.point(0).y();
01588
01589 int index;
01590 for(index = 1; index < points; index++)
01591 {
01592 QPoint point = polyArray.point(index);
01593 polyline[index].code = ART_LINETO;
01594 polyline[index].x = point.x();
01595 polyline[index].y = point.y();
01596 }
01597
01598 if(d->helper->m_useFill)
01599 {
01600 polyline[index].code = (ArtPathcode)ART_END2;
01601 polyline[index].x = polyArray.point(0).x();
01602 polyline[index++].y = polyArray.point(0).y();
01603 }
01604
01605 polyline[index].code = ART_END;
01606
01607 d->helper->drawVPath(polyline);
01608 }
01609
01610 void KSVGIconPainter::drawPolygon(QPointArray polyArray)
01611 {
01612 ArtVpath *polygon;
01613
01614 polygon = d->helper->allocVPath(3 + polyArray.count());
01615 polygon[0].code = ART_MOVETO;
01616 polygon[0].x = polyArray.point(0).x();
01617 polygon[0].y = polyArray.point(0).y();
01618
01619 unsigned int index;
01620 for(index = 1; index < polyArray.count(); index++)
01621 {
01622 QPoint point = polyArray.point(index);
01623 polygon[index].code = ART_LINETO;
01624 polygon[index].x = point.x();
01625 polygon[index].y = point.y();
01626 }
01627
01628 polygon[index].code = ART_LINETO;
01629 polygon[index].x = polyArray.point(0).x();
01630 polygon[index].y = polyArray.point(0).y();
01631
01632 index++;
01633 polygon[index].code = ART_END;
01634
01635 d->helper->drawVPath(polygon);
01636 }
01637
01638
01639
01640 const char *getCoord(const char *ptr, double &number)
01641 {
01642 int integer, exponent;
01643 double decimal, frac;
01644 int sign, expsign;
01645
01646 exponent = 0;
01647 integer = 0;
01648 frac = 1.0;
01649 decimal = 0;
01650 sign = 1;
01651 expsign = 1;
01652
01653
01654 if(*ptr == '+')
01655 ptr++;
01656 else if(*ptr == '-')
01657 {
01658 ptr++;
01659 sign = -1;
01660 }
01661
01662 while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
01663 integer = (integer * 10) + *(ptr++) - '0';
01664
01665 if(*ptr == '.')
01666 {
01667 ptr++;
01668 while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
01669 decimal += (*(ptr++) - '0') * (frac *= 0.1);
01670 }
01671
01672 if(*ptr == 'e' || *ptr == 'E')
01673 {
01674 ptr++;
01675
01676
01677 if(*ptr == '+')
01678 ptr++;
01679 else if(*ptr == '-')
01680 {
01681 ptr++;
01682 expsign = -1;
01683 }
01684
01685 exponent = 0;
01686 while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
01687 {
01688 exponent *= 10;
01689 exponent += *ptr - '0';
01690 ptr++;
01691 }
01692 }
01693
01694 number = integer + decimal;
01695 number *= sign * pow(10.0, expsign * exponent);
01696
01697
01698 if(*ptr == ' ')
01699 ptr++;
01700
01701 return ptr;
01702 }
01703
01704 void KSVGIconPainter::drawPath(const QString &data, bool filled)
01705 {
01706 QString value = data;
01707
01708 QMemArray<ArtBpath> vec;
01709 int index = -1;
01710
01711 double curx = 0.0, cury = 0.0, contrlx = 0.0, contrly = 0.0, xc, yc;
01712 unsigned int lastCommand = 0;
01713
01714 QString _d = value.replace(QRegExp(","), " ");
01715 _d = _d.simplifyWhiteSpace();
01716 const char *ptr = _d.latin1();
01717 const char *end = _d.latin1() + _d.length() + 1;
01718
01719 double tox, toy, x1, y1, x2, y2, rx, ry, angle;
01720 bool largeArc, sweep;
01721 char command = *(ptr++);
01722
01723 while(ptr < end)
01724 {
01725 if(*ptr == ' ')
01726 ptr++;
01727
01728 switch(command)
01729 {
01730 case 'm':
01731 ptr = getCoord(ptr, tox);
01732 ptr = getCoord(ptr, toy);
01733
01734 if(index != -1 && lastCommand != 'z')
01735 {
01736
01737 int find = -1;
01738 for(int i = index; i >= 0; i--)
01739 {
01740 if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO)
01741 {
01742 find = i;
01743 break;
01744 }
01745 }
01746
01747 index++;
01748
01749 if(vec.size() == (unsigned int) index)
01750 vec.resize(index + 1);
01751
01752 vec[index].code = (ArtPathcode)ART_END2;
01753 vec[index].x3 = vec[find].x3;
01754 vec[index].y3 = vec[find].y3;
01755 }
01756
01757 curx += tox;
01758 cury += toy;
01759
01760 index++;
01761
01762 d->helper->ensureSpace(vec, index);
01763
01764 vec[index].code = (index == 0) ? ART_MOVETO : ART_MOVETO_OPEN;
01765 vec[index].x3 = curx;
01766 vec[index].y3 = cury;
01767
01768 lastCommand = 'm';
01769 break;
01770 case 'M':
01771 ptr = getCoord(ptr, tox);
01772 ptr = getCoord(ptr, toy);
01773 if(index != -1 && lastCommand != 'z')
01774 {
01775
01776 int find = -1;
01777 for(int i = index; i >= 0; i--)
01778 {
01779 if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO)
01780 {
01781 find = i;
01782 break;
01783 }
01784 }
01785
01786 index++;
01787
01788 if(vec.size() == (unsigned int) index)
01789 vec.resize(index + 1);
01790
01791 vec[index].code = (ArtPathcode)ART_END2;
01792 vec[index].x3 = vec[find].x3;
01793 vec[index].y3 = vec[find].y3;
01794 }
01795
01796 curx = tox;
01797 cury = toy;
01798
01799 index++;
01800
01801 d->helper->ensureSpace(vec, index);
01802
01803 vec[index].code = (index == 0) ? ART_MOVETO : ART_MOVETO_OPEN;
01804 vec[index].x3 = curx;
01805 vec[index].y3 = cury;
01806
01807 lastCommand = 'M';
01808 break;
01809 case 'l':
01810 ptr = getCoord(ptr, tox);
01811 ptr = getCoord(ptr, toy);
01812
01813 index++;
01814
01815 d->helper->ensureSpace(vec, index);
01816
01817 vec[index].code = ART_LINETO;
01818 vec[index].x3 = curx + tox;
01819 vec[index].y3 = cury + toy;
01820
01821 curx += tox;
01822 cury += toy;
01823
01824 lastCommand = 'l';
01825 break;
01826 case 'L':
01827 ptr = getCoord(ptr, tox);
01828 ptr = getCoord(ptr, toy);
01829
01830 index++;
01831
01832 d->helper->ensureSpace(vec, index);
01833
01834 vec[index].code = ART_LINETO;
01835 vec[index].x3 = tox;
01836 vec[index].y3 = toy;
01837
01838 curx = tox;
01839 cury = toy;
01840
01841 lastCommand = 'L';
01842 break;
01843 case 'h':
01844 ptr = getCoord(ptr, tox);
01845
01846 index++;
01847
01848 curx += tox;
01849
01850 d->helper->ensureSpace(vec, index);
01851
01852 vec[index].code = ART_LINETO;
01853 vec[index].x3 = curx;
01854 vec[index].y3 = cury;
01855
01856 lastCommand = 'h';
01857 break;
01858 case 'H':
01859 ptr = getCoord(ptr, tox);
01860
01861 index++;
01862
01863 curx = tox;
01864
01865 d->helper->ensureSpace(vec, index);
01866
01867 vec[index].code = ART_LINETO;
01868 vec[index].x3 = curx;
01869 vec[index].y3 = cury;
01870
01871 lastCommand = 'H';
01872 break;
01873 case 'v':
01874 ptr = getCoord(ptr, toy);
01875
01876 index++;
01877
01878 cury += toy;
01879
01880 d->helper->ensureSpace(vec, index);
01881
01882 vec[index].code = ART_LINETO;
01883 vec[index].x3 = curx;
01884 vec[index].y3 = cury;
01885
01886 lastCommand = 'v';
01887 break;
01888 case 'V':
01889 ptr = getCoord(ptr, toy);
01890
01891 index++;
01892
01893 cury = toy;
01894
01895 d->helper->ensureSpace(vec, index);
01896
01897 vec[index].code = ART_LINETO;
01898 vec[index].x3 = curx;
01899 vec[index].y3 = cury;
01900
01901 lastCommand = 'V';
01902 break;
01903 case 'c':
01904 ptr = getCoord(ptr, x1);
01905 ptr = getCoord(ptr, y1);
01906 ptr = getCoord(ptr, x2);
01907 ptr = getCoord(ptr, y2);
01908 ptr = getCoord(ptr, tox);
01909 ptr = getCoord(ptr, toy);
01910
01911 index++;
01912
01913 d->helper->ensureSpace(vec, index);
01914
01915 vec[index].code = ART_CURVETO;
01916 vec[index].x1 = curx + x1;
01917 vec[index].y1 = cury + y1;
01918 vec[index].x2 = curx + x2;
01919 vec[index].y2 = cury + y2;
01920 vec[index].x3 = curx + tox;
01921 vec[index].y3 = cury + toy;
01922
01923 curx += tox;
01924 cury += toy;
01925
01926 contrlx = vec[index].x2;
01927 contrly = vec[index].y2;
01928
01929 lastCommand = 'c';
01930 break;
01931 case 'C':
01932 ptr = getCoord(ptr, x1);
01933 ptr = getCoord(ptr, y1);
01934 ptr = getCoord(ptr, x2);
01935 ptr = getCoord(ptr, y2);
01936 ptr = getCoord(ptr, tox);
01937 ptr = getCoord(ptr, toy);
01938
01939 index++;
01940
01941 d->helper->ensureSpace(vec, index);
01942
01943 vec[index].code = ART_CURVETO;
01944 vec[index].x1 = x1;
01945 vec[index].y1 = y1;
01946 vec[index].x2 = x2;
01947 vec[index].y2 = y2;
01948 vec[index].x3 = tox;
01949 vec[index].y3 = toy;
01950
01951 curx = vec[index].x3;
01952 cury = vec[index].y3;
01953 contrlx = vec[index].x2;
01954 contrly = vec[index].y2;
01955
01956 lastCommand = 'C';
01957 break;
01958 case 's':
01959 ptr = getCoord(ptr, x2);
01960 ptr = getCoord(ptr, y2);
01961 ptr = getCoord(ptr, tox);
01962 ptr = getCoord(ptr, toy);
01963
01964 index++;
01965
01966 d->helper->ensureSpace(vec, index);
01967
01968 vec[index].code = ART_CURVETO;
01969 vec[index].x1 = 2 * curx - contrlx;
01970 vec[index].y1 = 2 * cury - contrly;
01971 vec[index].x2 = curx + x2;
01972 vec[index].y2 = cury + y2;
01973 vec[index].x3 = curx + tox;
01974 vec[index].y3 = cury + toy;
01975
01976 curx += tox;
01977 cury += toy;
01978
01979 contrlx = vec[index].x2;
01980 contrly = vec[index].y2;
01981
01982 lastCommand = 's';
01983 break;
01984 case 'S':
01985 ptr = getCoord(ptr, x2);
01986 ptr = getCoord(ptr, y2);
01987 ptr = getCoord(ptr, tox);
01988 ptr = getCoord(ptr, toy);
01989
01990 index++;
01991
01992 d->helper->ensureSpace(vec, index);
01993
01994 vec[index].code = ART_CURVETO;
01995 vec[index].x1 = 2 * curx - contrlx;
01996 vec[index].y1 = 2 * cury - contrly;
01997 vec[index].x2 = x2;
01998 vec[index].y2 = y2;
01999 vec[index].x3 = tox;
02000 vec[index].y3 = toy;
02001
02002 curx = vec[index].x3;
02003 cury = vec[index].y3;
02004 contrlx = vec[index].x2;
02005 contrly = vec[index].y2;
02006
02007 lastCommand = 'S';
02008 break;
02009 case 'q':
02010 ptr = getCoord(ptr, x1);
02011 ptr = getCoord(ptr, y1);
02012 ptr = getCoord(ptr, tox);
02013 ptr = getCoord(ptr, toy);
02014
02015 index++;
02016
02017 d->helper->ensureSpace(vec, index);
02018
02019 vec[index].code = ART_CURVETO;
02020 vec[index].x1 = (curx + 2 * (x1 + curx)) * (1.0 / 3.0);
02021 vec[index].y1 = (cury + 2 * (y1 + cury)) * (1.0 / 3.0);
02022 vec[index].x2 = ((curx + tox) + 2 * (x1 + curx)) * (1.0 / 3.0);
02023 vec[index].y2 = ((cury + toy) + 2 * (y1 + cury)) * (1.0 / 3.0);
02024 vec[index].x3 = curx + tox;
02025 vec[index].y3 = cury + toy;
02026
02027 contrlx = curx + x1;
02028 contrly = cury + y1;
02029 curx += tox;
02030 cury += toy;
02031
02032 lastCommand = 'q';
02033 break;
02034 case 'Q':
02035 ptr = getCoord(ptr, x1);
02036 ptr = getCoord(ptr, y1);
02037 ptr = getCoord(ptr, tox);
02038 ptr = getCoord(ptr, toy);
02039
02040 index++;
02041
02042 d->helper->ensureSpace(vec, index);
02043
02044
02045 vec[index].code = ART_CURVETO;
02046 vec[index].x1 = (curx + 2 * x1) * (1.0 / 3.0);
02047 vec[index].y1 = (cury + 2 * y1) * (1.0 / 3.0);
02048 vec[index].x2 = (tox + 2 * x1) * (1.0 / 3.0);
02049 vec[index].y2 = (toy + 2 * y1) * (1.0 / 3.0);
02050 vec[index].x3 = tox;
02051 vec[index].y3 = toy;
02052
02053 curx = vec[index].x3;
02054 cury = vec[index].y3;
02055 contrlx = vec[index].x2;
02056 contrly = vec[index].y2;
02057
02058 lastCommand = 'Q';
02059 break;
02060 case 't':
02061 ptr = getCoord(ptr, tox);
02062 ptr = getCoord(ptr, toy);
02063
02064 xc = 2 * curx - contrlx;
02065 yc = 2 * cury - contrly;
02066
02067 index++;
02068
02069 d->helper->ensureSpace(vec, index);
02070
02071 vec[index].code = ART_CURVETO;
02072 vec[index].x1 = (curx + 2 * xc) * (1.0 / 3.0);
02073 vec[index].y1 = (cury + 2 * yc) * (1.0 / 3.0);
02074 vec[index].x2 = ((curx + tox) + 2 * xc) * (1.0 / 3.0);
02075 vec[index].y2 = ((cury + toy) + 2 * yc) * (1.0 / 3.0);
02076
02077 vec[index].x3 = curx + tox;
02078 vec[index].y3 = cury + toy;
02079
02080 curx += tox;
02081 cury += toy;
02082 contrlx = xc;
02083 contrly = yc;
02084
02085 lastCommand = 't';
02086 break;
02087 case 'T':
02088 ptr = getCoord(ptr, tox);
02089 ptr = getCoord(ptr, toy);
02090
02091 xc = 2 * curx - contrlx;
02092 yc = 2 * cury - contrly;
02093
02094 index++;
02095
02096 d->helper->ensureSpace(vec, index);
02097
02098 vec[index].code = ART_CURVETO;
02099 vec[index].x1 = (curx + 2 * xc) * (1.0 / 3.0);
02100 vec[index].y1 = (cury + 2 * yc) * (1.0 / 3.0);
02101 vec[index].x2 = (tox + 2 * xc) * (1.0 / 3.0);
02102 vec[index].y2 = (toy + 2 * yc) * (1.0 / 3.0);
02103 vec[index].x3 = tox;
02104 vec[index].y3 = toy;
02105
02106 curx = tox;
02107 cury = toy;
02108 contrlx = xc;
02109 contrly = yc;
02110
02111 lastCommand = 'T';
02112 break;
02113 case 'z':
02114 case 'Z':
02115 int find;
02116 find = -1;
02117 for(int i = index; i >= 0; i--)
02118 {
02119 if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO)
02120 {
02121 find = i;
02122 break;
02123 }
02124 }
02125
02126 if(find != -1)
02127 {
02128 if(vec[find].x3 != curx || vec[find].y3 != cury)
02129 {
02130 index++;
02131
02132 d->helper->ensureSpace(vec, index);
02133
02134 vec[index].code = ART_LINETO;
02135 vec[index].x3 = vec[find].x3;
02136 vec[index].y3 = vec[find].y3;
02137 }
02138 }
02139
02140
02141 curx = vec[find].x3;
02142 cury = vec[find].y3;
02143
02144 lastCommand = 'z';
02145 break;
02146 case 'a':
02147 ptr = getCoord(ptr, rx);
02148 ptr = getCoord(ptr, ry);
02149 ptr = getCoord(ptr, angle);
02150 ptr = getCoord(ptr, tox);
02151 largeArc = tox == 1;
02152 ptr = getCoord(ptr, tox);
02153 sweep = tox == 1;
02154 ptr = getCoord(ptr, tox);
02155 ptr = getCoord(ptr, toy);
02156
02157 d->helper->calculateArc(true, vec, index, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep);
02158
02159 lastCommand = 'a';
02160 break;
02161 case 'A':
02162 ptr = getCoord(ptr, rx);
02163 ptr = getCoord(ptr, ry);
02164 ptr = getCoord(ptr, angle);
02165 ptr = getCoord(ptr, tox);
02166 largeArc = tox == 1;
02167 ptr = getCoord(ptr, tox);
02168 sweep = tox == 1;
02169 ptr = getCoord(ptr, tox);
02170 ptr = getCoord(ptr, toy);
02171
02172 d->helper->calculateArc(false, vec, index, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep);
02173
02174 lastCommand = 'A';
02175 break;
02176 }
02177
02178 if(*ptr == '+' || *ptr == '-' || (*ptr >= '0' && *ptr <= '9'))
02179 {
02180
02181 if(command == 'M')
02182 command = 'L';
02183 else if(command == 'm')
02184 command = 'l';
02185 }
02186 else
02187 command = *(ptr++);
02188
02189
02190 if(lastCommand != 'C' && lastCommand != 'c'
02191 && lastCommand != 'S' && lastCommand != 's'
02192 && lastCommand != 'Q' && lastCommand != 'q'
02193 && lastCommand != 'T' && lastCommand != 't')
02194 {
02195 contrlx = curx;
02196 contrly = cury;
02197 }
02198 }
02199
02200
02201 int find = -1;
02202 for(int i = index; i >= 0; i--)
02203 {
02204 if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO)
02205 {
02206 find = i;
02207 break;
02208 }
02209 }
02210
02211
02212 if(curx != vec[find].x3 && cury != vec[find].y3)
02213 {
02214 if((int) curx == (int) vec[find].x3 && (int) cury == (int) vec[find].y3)
02215 {
02216 index++;
02217
02218 if(vec.size() == (unsigned int) index)
02219 vec.resize(index + 1);
02220
02221 vec[index].code = ART_LINETO;
02222 vec[index].x3 = vec[find].x3;
02223 vec[index].y3 = vec[find].y3;
02224
02225 curx = vec[find].x3;
02226 cury = vec[find].y3;
02227 }
02228 }
02229
02230
02231 if(filled)
02232 {
02233 if((int) curx != (int) vec[find].x3 || (int) cury != (int) vec[find].y3)
02234 {
02235 index++;
02236
02237 if(vec.size() == (unsigned int) index)
02238 vec.resize(index + 1);
02239
02240 vec[index].code = (ArtPathcode)ART_END2;
02241 vec[index].x3 = vec[find].x3;
02242 vec[index].y3 = vec[find].y3;
02243
02244 curx = vec[find].x3;
02245 cury = vec[find].y3;
02246 }
02247 }
02248
02249
02250 index++;
02251
02252 if(vec.size() == (unsigned int) index)
02253 vec.resize(index + 1);
02254
02255 vec[index].code = ART_END;
02256
02257
02258
02259 bool render = false;
02260 for(int i = index; i >= 0; i--)
02261 {
02262 if(vec[i].code != ART_MOVETO_OPEN && vec[i].code != ART_MOVETO && !(vec[i].code >= ART_END))
02263 {
02264 render = true;
02265 break;
02266 }
02267 }
02268
02269 if(render)
02270 d->helper->drawVPath(d->helper->art_bez_path_to_vec(vec.data(), 0.25));
02271 }
02272
02273 void KSVGIconPainter::drawImage(double x, double y, QImage &image)
02274 {
02275 if(image.depth() != 32)
02276 image = image.convertDepth(32);
02277
02278 double affine[6];
02279 affine[0] = d->helper->m_worldMatrix->m11();
02280 affine[1] = d->helper->m_worldMatrix->m12();
02281 affine[2] = d->helper->m_worldMatrix->m21();
02282 affine[3] = d->helper->m_worldMatrix->m22();
02283 affine[4] = x;
02284 affine[5] = y;
02285
02286 d->helper->art_rgba_rgba_affine(d->helper->m_buffer, 0, 0, d->helper->m_width, d->helper->m_height,
02287 d->helper->m_rowstride, image.bits(), image.width(), image.height(),
02288 image.width() * 4, affine);
02289 }
02290
02291 QColor KSVGIconPainter::parseColor(const QString ¶m)
02292 {
02293 if(param.stripWhiteSpace().startsWith("#"))
02294 {
02295 QColor color;
02296 color.setNamedColor(param.stripWhiteSpace());
02297 return color;
02298 }
02299 else if(param.stripWhiteSpace().startsWith("rgb("))
02300 {
02301 QString parse = param.stripWhiteSpace();
02302 QStringList colors = QStringList::split(',', parse);
02303 QString r = colors[0].right((colors[0].length() - 4));
02304 QString g = colors[1];
02305 QString b = colors[2].left((colors[2].length() - 1));
02306
02307 if(r.contains("%"))
02308 {
02309 r = r.left(r.length() - 1);
02310 r = QString::number(int((double(255 * r.toDouble()) / 100.0)));
02311 }
02312
02313 if(g.contains("%"))
02314 {
02315 g = g.left(g.length() - 1);
02316 g = QString::number(int((double(255 * g.toDouble()) / 100.0)));
02317 }
02318
02319 if(b.contains("%"))
02320 {
02321 b = b.left(b.length() - 1);
02322 b = QString::number(int((double(255 * b.toDouble()) / 100.0)));
02323 }
02324
02325 return QColor(r.toInt(), g.toInt(), b.toInt());
02326 }
02327 else
02328 {
02329 QString rgbColor = param.stripWhiteSpace();
02330
02331 if(rgbColor == "aliceblue")
02332 return QColor(240, 248, 255);
02333 else if(rgbColor == "antiquewhite")
02334 return QColor(250, 235, 215);
02335 else if(rgbColor == "aqua")
02336 return QColor(0, 255, 255);
02337 else if(rgbColor == "aquamarine")
02338 return QColor(127, 255, 212);
02339 else if(rgbColor == "azure")
02340 return QColor(240, 255, 255);
02341 else if(rgbColor == "beige")
02342 return QColor(245, 245, 220);
02343 else if(rgbColor == "bisque")
02344 return QColor(255, 228, 196);
02345 else if(rgbColor == "black")
02346 return QColor(0, 0, 0);
02347 else if(rgbColor == "blanchedalmond")
02348 return QColor(255, 235, 205);
02349 else if(rgbColor == "blue")
02350 return QColor(0, 0, 255);
02351 else if(rgbColor == "blueviolet")
02352 return QColor(138, 43, 226);
02353 else if(rgbColor == "brown")
02354 return QColor(165, 42, 42);
02355 else if(rgbColor == "burlywood")
02356 return QColor(222, 184, 135);
02357 else if(rgbColor == "cadetblue")
02358 return QColor(95, 158, 160);
02359 else if(rgbColor == "chartreuse")
02360 return QColor(127, 255, 0);
02361 else if(rgbColor == "chocolate")
02362 return QColor(210, 105, 30);
02363 else if(rgbColor == "coral")
02364 return QColor(255, 127, 80);
02365 else if(rgbColor == "cornflowerblue")
02366 return QColor(100, 149, 237);
02367 else if(rgbColor == "cornsilk")
02368 return QColor(255, 248, 220);
02369 else if(rgbColor == "crimson")
02370 return QColor(220, 20, 60);
02371 else if(rgbColor == "cyan")
02372 return QColor(0, 255, 255);
02373 else if(rgbColor == "darkblue")
02374 return QColor(0, 0, 139);
02375 else if(rgbColor == "darkcyan")
02376 return QColor(0, 139, 139);
02377 else if(rgbColor == "darkgoldenrod")
02378 return QColor(184, 134, 11);
02379 else if(rgbColor == "darkgray")
02380 return QColor(169, 169, 169);
02381 else if(rgbColor == "darkgrey")
02382 return QColor(169, 169, 169);
02383 else if(rgbColor == "darkgreen")
02384 return QColor(0, 100, 0);
02385 else if(rgbColor == "darkkhaki")
02386 return QColor(189, 183, 107);
02387 else if(rgbColor == "darkmagenta")
02388 return QColor(139, 0, 139);
02389 else if(rgbColor == "darkolivegreen")
02390 return QColor(85, 107, 47);
02391 else if(rgbColor == "darkorange")
02392 return QColor(255, 140, 0);
02393 else if(rgbColor == "darkorchid")
02394 return QColor(153, 50, 204);
02395 else if(rgbColor == "darkred")
02396 return QColor(139, 0, 0);
02397 else if(rgbColor == "darksalmon")
02398 return QColor(233, 150, 122);
02399 else if(rgbColor == "darkseagreen")
02400 return QColor(143, 188, 143);
02401 else if(rgbColor == "darkslateblue")
02402 return QColor(72, 61, 139);
02403 else if(rgbColor == "darkslategray")
02404 return QColor(47, 79, 79);
02405 else if(rgbColor == "darkslategrey")
02406 return QColor(47, 79, 79);
02407 else if(rgbColor == "darkturquoise")
02408 return QColor(0, 206, 209);
02409 else if(rgbColor == "darkviolet")
02410 return QColor(148, 0, 211);
02411 else if(rgbColor == "deeppink")
02412 return QColor(255, 20, 147);
02413 else if(rgbColor == "deepskyblue")
02414 return QColor(0, 191, 255);
02415 else if(rgbColor == "dimgray")
02416 return QColor(105, 105, 105);
02417 else if(rgbColor == "dimgrey")
02418 return QColor(105, 105, 105);
02419 else if(rgbColor == "dodgerblue")
02420 return QColor(30, 144, 255);
02421 else if(rgbColor == "firebrick")
02422 return QColor(178, 34, 34);
02423 else if(rgbColor == "floralwhite")
02424 return QColor(255, 250, 240);
02425 else if(rgbColor == "forestgreen")
02426 return QColor(34, 139, 34);
02427 else if(rgbColor == "fuchsia")
02428 return QColor(255, 0, 255);
02429 else if(rgbColor == "gainsboro")
02430 return QColor(220, 220, 220);
02431 else if(rgbColor == "ghostwhite")
02432 return QColor(248, 248, 255);
02433 else if(rgbColor == "gold")
02434 return QColor(255, 215, 0);
02435 else if(rgbColor == "goldenrod")
02436 return QColor(218, 165, 32);
02437 else if(rgbColor == "gray")
02438 return QColor(128, 128, 128);
02439 else if(rgbColor == "grey")
02440 return QColor(128, 128, 128);
02441 else if(rgbColor == "green")
02442 return QColor(0, 128, 0);
02443 else if(rgbColor == "greenyellow")
02444 return QColor(173, 255, 47);
02445 else if(rgbColor == "honeydew")
02446 return QColor(240, 255, 240);
02447 else if(rgbColor == "hotpink")
02448 return QColor(255, 105, 180);
02449 else if(rgbColor == "indianred")
02450 return QColor(205, 92, 92);
02451 else if(rgbColor == "indigo")
02452 return QColor(75, 0, 130);
02453 else if(rgbColor == "ivory")
02454 return QColor(255, 255, 240);
02455 else if(rgbColor == "khaki")
02456 return QColor(240, 230, 140);
02457 else if(rgbColor == "lavender")
02458 return QColor(230, 230, 250);
02459 else if(rgbColor == "lavenderblush")
02460 return QColor(255, 240, 245);
02461 else if(rgbColor == "lawngreen")
02462 return QColor(124, 252, 0);
02463 else if(rgbColor == "lemonchiffon")
02464 return QColor(255, 250, 205);
02465 else if(rgbColor == "lightblue")
02466 return QColor(173, 216, 230);
02467 else if(rgbColor == "lightcoral")
02468 return QColor(240, 128, 128);
02469 else if(rgbColor == "lightcyan")
02470 return QColor(224, 255, 255);
02471 else if(rgbColor == "lightgoldenrodyellow")
02472 return QColor(250, 250, 210);
02473 else if(rgbColor == "lightgray")
02474 return QColor(211, 211, 211);
02475 else if(rgbColor == "lightgrey")
02476 return QColor(211, 211, 211);
02477 else if(rgbColor == "lightgreen")
02478 return QColor(144, 238, 144);
02479 else if(rgbColor == "lightpink")
02480 return QColor(255, 182, 193);
02481 else if(rgbColor == "lightsalmon")
02482 return QColor(255, 160, 122);
02483 else if(rgbColor == "lightseagreen")
02484 return QColor(32, 178, 170);
02485 else if(rgbColor == "lightskyblue")
02486 return QColor(135, 206, 250);
02487 else if(rgbColor == "lightslategray")
02488 return QColor(119, 136, 153);
02489 else if(rgbColor == "lightslategrey")
02490 return QColor(119, 136, 153);
02491 else if(rgbColor == "lightsteelblue")
02492 return QColor(176, 196, 222);
02493 else if(rgbColor == "lightyellow")
02494 return QColor(255, 255, 224);
02495 else if(rgbColor == "lime")
02496 return QColor(0, 255, 0);
02497 else if(rgbColor == "limegreen")
02498 return QColor(50, 205, 50);
02499 else if(rgbColor == "linen")
02500 return QColor(250, 240, 230);
02501 else if(rgbColor == "magenta")
02502 return QColor(255, 0, 255);
02503 else if(rgbColor == "maroon")
02504 return QColor(128, 0, 0);
02505 else if(rgbColor == "mediumaquamarine")
02506 return QColor(102, 205, 170);
02507 else if(rgbColor == "mediumblue")
02508 return QColor(0, 0, 205);
02509 else if(rgbColor == "mediumorchid")
02510 return QColor(186, 85, 211);
02511 else if(rgbColor == "mediumpurple")
02512 return QColor(147, 112, 219);
02513 else if(rgbColor == "mediumseagreen")
02514 return QColor(60, 179, 113);
02515 else if(rgbColor == "mediumslateblue")
02516 return QColor(123, 104, 238);
02517 else if(rgbColor == "mediumspringgreen")
02518 return QColor(0, 250, 154);
02519 else if(rgbColor == "mediumturquoise")
02520 return QColor(72, 209, 204);
02521 else if(rgbColor == "mediumvioletred")
02522 return QColor(199, 21, 133);
02523 else if(rgbColor == "midnightblue")
02524 return QColor(25, 25, 112);
02525 else if(rgbColor == "mintcream")
02526 return QColor(245, 255, 250);
02527 else if(rgbColor == "mistyrose")
02528 return QColor(255, 228, 225);
02529 else if(rgbColor == "moccasin")
02530 return QColor(255, 228, 181);
02531 else if(rgbColor == "navajowhite")
02532 return QColor(255, 222, 173);
02533 else if(rgbColor == "navy")
02534 return QColor(0, 0, 128);
02535 else if(rgbColor == "oldlace")
02536 return QColor(253, 245, 230);
02537 else if(rgbColor == "olive")
02538 return QColor(128, 128, 0);
02539 else if(rgbColor == "olivedrab")
02540 return QColor(107, 142, 35);
02541 else if(rgbColor == "orange")
02542 return QColor(255, 165, 0);
02543 else if(rgbColor == "orangered")
02544 return QColor(255, 69, 0);
02545 else if(rgbColor == "orchid")
02546 return QColor(218, 112, 214);
02547 else if(rgbColor == "palegoldenrod")
02548 return QColor(238, 232, 170);
02549 else if(rgbColor == "palegreen")
02550 return QColor(152, 251, 152);
02551 else if(rgbColor == "paleturquoise")
02552 return QColor(175, 238, 238);
02553 else if(rgbColor == "palevioletred")
02554 return QColor(219, 112, 147);
02555 else if(rgbColor == "papayawhip")
02556 return QColor(255, 239, 213);
02557 else if(rgbColor == "peachpuff")
02558 return QColor(255, 218, 185);
02559 else if(rgbColor == "peru")
02560 return QColor(205, 133, 63);
02561 else if(rgbColor == "pink")
02562 return QColor(255, 192, 203);
02563 else if(rgbColor == "plum")
02564 return QColor(221, 160, 221);
02565 else if(rgbColor == "powderblue")
02566 return QColor(176, 224, 230);
02567 else if(rgbColor == "purple")
02568 return QColor(128, 0, 128);
02569 else if(rgbColor == "red")
02570 return QColor(255, 0, 0);
02571 else if(rgbColor == "rosybrown")
02572 return QColor(188, 143, 143);
02573 else if(rgbColor == "royalblue")
02574 return QColor(65, 105, 225);
02575 else if(rgbColor == "saddlebrown")
02576 return QColor(139, 69, 19);
02577 else if(rgbColor == "salmon")
02578 return QColor(250, 128, 114);
02579 else if(rgbColor == "sandybrown")
02580 return QColor(244, 164, 96);
02581 else if(rgbColor == "seagreen")
02582 return QColor(46, 139, 87);
02583 else if(rgbColor == "seashell")
02584 return QColor(255, 245, 238);
02585 else if(rgbColor == "sienna")
02586 return QColor(160, 82, 45);
02587 else if(rgbColor == "silver")
02588 return QColor(192, 192, 192);
02589 else if(rgbColor == "skyblue")
02590 return QColor(135, 206, 235);
02591 else if(rgbColor == "slateblue")
02592 return QColor(106, 90, 205);
02593 else if(rgbColor == "slategray")
02594 return QColor(112, 128, 144);
02595 else if(rgbColor == "slategrey")
02596 return QColor(112, 128, 144);
02597 else if(rgbColor == "snow")
02598 return QColor(255, 250, 250);
02599 else if(rgbColor == "springgreen")
02600 return QColor(0, 255, 127);
02601 else if(rgbColor == "steelblue")
02602 return QColor(70, 130, 180);
02603 else if(rgbColor == "tan")
02604 return QColor(210, 180, 140);
02605 else if(rgbColor == "teal")
02606 return QColor(0, 128, 128);
02607 else if(rgbColor == "thistle")
02608 return QColor(216, 191, 216);
02609 else if(rgbColor == "tomato")
02610 return QColor(255, 99, 71);
02611 else if(rgbColor == "turquoise")
02612 return QColor(64, 224, 208);
02613 else if(rgbColor == "violet")
02614 return QColor(238, 130, 238);
02615 else if(rgbColor == "wheat")
02616 return QColor(245, 222, 179);
02617 else if(rgbColor == "white")
02618 return QColor(255, 255, 255);
02619 else if(rgbColor == "whitesmoke")
02620 return QColor(245, 245, 245);
02621 else if(rgbColor == "yellow")
02622 return QColor(255, 255, 0);
02623 else if(rgbColor == "yellowgreen")
02624 return QColor(154, 205, 50);
02625 }
02626
02627 return QColor();
02628 }
02629
02630 double KSVGIconPainter::dpi()
02631 {
02632 return 90.0;
02633 }
02634
02635 double KSVGIconPainter::toPixel(const QString &s, bool hmode)
02636 {
02637 if(s.isEmpty())
02638 return 0.0;
02639
02640 QString check = s;
02641
02642 double ret = 0.0;
02643
02644 bool ok = false;
02645
02646 double value = check.toDouble(&ok);
02647
02648 if(!ok)
02649 {
02650 QRegExp reg("[0-9 .-]");
02651 check.replace(reg, "");
02652
02653 if(check.compare("px") == 0)
02654 ret = value;
02655 else if(check.compare("cm") == 0)
02656 ret = (value / 2.54) * dpi();
02657 else if(check.compare("pc") == 0)
02658 ret = (value / 6.0) * dpi();
02659 else if(check.compare("mm") == 0)
02660 ret = (value / 25.4) * dpi();
02661 else if(check.compare("in") == 0)
02662 ret = value * dpi();
02663 else if(check.compare("pt") == 0)
02664 ret = (value / 72.0) * dpi();
02665 else if(check.compare("%") == 0)
02666 {
02667 ret = value / 100.0;
02668
02669 if(hmode)
02670 ret *= d->drawWidth;
02671 else
02672 ret *= d->drawHeight;
02673 }
02674 }
02675 else
02676 ret = value;
02677
02678 return ret;
02679 }
02680
02681 ArtGradientLinear *KSVGIconPainter::linearGradient(const QString &id)
02682 {
02683 return d->helper->m_linearGradientMap[id];
02684 }
02685
02686 void KSVGIconPainter::addLinearGradient(const QString &id, ArtGradientLinear *gradient)
02687 {
02688 d->helper->m_linearGradientMap.insert(id, gradient);
02689 }
02690
02691 QDomElement KSVGIconPainter::linearGradientElement(ArtGradientLinear *linear)
02692 {
02693 return d->helper->m_linearGradientElementMap[linear];
02694 }
02695
02696 void KSVGIconPainter::addLinearGradientElement(ArtGradientLinear *gradient, QDomElement element)
02697 {
02698 d->helper->m_linearGradientElementMap.insert(gradient, element);
02699 }
02700
02701 ArtGradientRadial *KSVGIconPainter::radialGradient(const QString &id)
02702 {
02703 return d->helper->m_radialGradientMap[id];
02704 }
02705
02706 void KSVGIconPainter::addRadialGradient(const QString &id, ArtGradientRadial *gradient)
02707 {
02708 d->helper->m_radialGradientMap.insert(id, gradient);
02709 }
02710
02711 QDomElement KSVGIconPainter::radialGradientElement(ArtGradientRadial *radial)
02712 {
02713 return d->helper->m_radialGradientElementMap[radial];
02714 }
02715
02716 void KSVGIconPainter::addRadialGradientElement(ArtGradientRadial *gradient, QDomElement element)
02717 {
02718 d->helper->m_radialGradientElementMap.insert(gradient, element);
02719 }
02720
02721 Q_UINT32 KSVGIconPainter::toArtColor(QColor color)
02722 {
02723 return d->helper->toArtColor(color);
02724 }
02725
02726 QWMatrix KSVGIconPainter::parseTransform(const QString &transform)
02727 {
02728 QWMatrix result;
02729
02730
02731 QStringList subtransforms = QStringList::split(')', transform);
02732 QStringList::ConstIterator it = subtransforms.begin();
02733 QStringList::ConstIterator end = subtransforms.end();
02734 for(; it != end; ++it)
02735 {
02736 QStringList subtransform = QStringList::split('(', (*it));
02737
02738 subtransform[0] = subtransform[0].stripWhiteSpace().lower();
02739 subtransform[1] = subtransform[1].simplifyWhiteSpace();
02740 QRegExp reg("[a-zA-Z,( ]");
02741 QStringList params = QStringList::split(reg, subtransform[1]);
02742
02743 if(subtransform[0].startsWith(";") || subtransform[0].startsWith(","))
02744 subtransform[0] = subtransform[0].right(subtransform[0].length() - 1);
02745
02746 if(subtransform[0] == "rotate")
02747 {
02748 if(params.count() == 3)
02749 {
02750 float x = params[1].toFloat();
02751 float y = params[2].toFloat();
02752
02753 result.translate(x, y);
02754 result.rotate(params[0].toFloat());
02755 result.translate(-x, -y);
02756 }
02757 else
02758 result.rotate(params[0].toFloat());
02759 }
02760 else if(subtransform[0] == "translate")
02761 {
02762 if(params.count() == 2)
02763 result.translate(params[0].toFloat(), params[1].toFloat());
02764 else
02765 result.translate(params[0].toFloat() , 0);
02766 }
02767 else if(subtransform[0] == "scale")
02768 {
02769 if(params.count() == 2)
02770 result.scale(params[0].toFloat(), params[1].toFloat());
02771 else
02772 result.scale(params[0].toFloat(), params[0].toFloat());
02773 }
02774 else if(subtransform[0] == "skewx")
02775 result.shear(tan(params[0].toFloat() * deg2rad), 0.0F);
02776 else if(subtransform[0] == "skewy")
02777 result.shear(tan(params[0].toFloat() * deg2rad), 0.0F);
02778 else if(subtransform[0] == "skewy")
02779 result.shear(0.0F, tan(params[0].toFloat() * deg2rad));
02780 else if(subtransform[0] == "matrix")
02781 {
02782 if(params.count() >= 6)
02783 result.setMatrix(params[0].toFloat(), params[1].toFloat(), params[2].toFloat(), params[3].toFloat(), params[4].toFloat(), params[5].toFloat());
02784 }
02785 }
02786
02787 return result;
02788 }