| # kdecore Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# ksvgiconpainter.cpp

    00001 /*
    00002     Copyright (C) 2002 Nikolas Zimmermann <wildfox@kde.org>
    00003     This file is part of the KDE project
    00004
    00005     This library is free software; you can redistribute it and/or
    00006     modify it under the terms of the GNU Library General Public
    00007     License as published by the Free Software Foundation; either
    00008     version 2 of the License, or (at your option) any later version.
    00009
    00010     This library is distributed in the hope that it will be useful,
    00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00013     Library General Public License for more details.
    00014
    00015     You should have received a copy of the GNU Library General Public License
    00016     aint with this library; see the file COPYING.LIB.  If not, write to
    00017     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00018     Boston, MA 02111-1307, USA.
    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; // pi/180
    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                 // Create new image with alpha support
    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                 // Make internal libart rendering buffer transparent
    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                 // Swap buffers, so we work with the new one internally...
    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                 // Re-swap again...
    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                 // Convert in a libart suitable form
    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                 // Filling
    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                 // There seems to be a problem when stroke width is zero, this is a quick
    00278                 // fix (Rob).
    00279                 if(m_strokeWidth <= 0)
    00280                         m_useStroke = m_useStrokeGradient = false;
    00281
    00282                 // Stroking
    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                 // Apply opacity
    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                 // Needed hack, to support both transparent
    00341                 // paths and transparent gradients
    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                 // Create temporary buffer if necessary
    00358                 bool tempDone = false;
    00359                 if(m_opacity != 0xff)
    00360                 {
    00361                         tempDone = true;
    00362                         createBuffer();
    00363                 }
    00364
    00365                 // Apply Gradients on fill/stroke
    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                 // Mix in temporary buffer, if possible
    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                 // Reset opacity values
    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                         // Adjust to gradientTransform
    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                         // Respect gradientTransform
    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                                 // Saved 'old' attributes
    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                                 // Copy attributes
    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                                 // Restore attributes
    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                                 // Saved 'old' attributes
    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                                 // Copy attributes
    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                                 // Restore attributes
    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                 // Spec : check if radii are large enough
    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                 /* (x0, y0) is current point in transformed coordinate space.
    00712                    (x1, y1) is new point in transformed coordinate space.
    00713
    00714                    The arc fits a unit-radius circle in this space.
    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                 /* (xc, yc) is center of the circle. */
    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                                 /* inverse transform compared with rsvg_path_arc */
    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         // For any docs, see the libart library
    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         // Slightly modified version to support RGBA buffers, copied from gnome-print
    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         // Use a blowup factor of 10 to make ellipses with small radii look good
    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         // undo blowup
    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) // if the polyline must be filled, inform libart that it should not be closed.
    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 // Path parsing tool
    01639 // parses the coord into number and forwards to the next token
    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         // read the sign
    01654         if(*ptr == '+')
    01655                 ptr++;
    01656         else if(*ptr == '-')
    01657         {
    01658                 ptr++;
    01659                 sign = -1;
    01660         }
    01661         // read the integer part
    01662         while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
    01663                 integer = (integer * 10) + *(ptr++) - '0';
    01664
    01665         if(*ptr == '.') // read the decimals
    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') // read the exponent part
    01673         {
    01674                 ptr++;
    01675
    01676                 // read the sign of the exponent
    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         // skip the following space
    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                                         // Find last subpath
    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                                         // Find last subpath
    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                                 // TODO : if this fails make it more like QuadraticRel
    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                                 // reset for next (sub)path
    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                         // there are still coords in this command
    02181                         if(command == 'M')
    02182                                 command = 'L';
    02183                         else if(command == 'm')
    02184                                 command = 'l';
    02185                 }
    02186                 else
    02187                         command = *(ptr++);
    02188
    02189                 // Detect reflection points
    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         // Find last subpath
    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         // Fix a problem where the .svg file used doubles as values... (sofico.svg)
    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         // Handle filled paths that are not closed explicitly
    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         // Close
    02250         index++;
    02251
    02252         if(vec.size() == (unsigned int) index)
    02253                 vec.resize(index + 1);
    02254
    02255         vec[index].code = ART_END;
    02256
    02257         // There are pure-moveto paths which reference paint servers *bah*
    02258         // Do NOT render them
    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 &param)
    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; // TODO: make modal?
    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         // Split string for handling 1 transform statement at a time
    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    // Spec : if only one param given, assume 2nd param to be 0
    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    // Spec : if only one param given, assume uniform scaling
    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 }

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 12:46:58 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001