kdecore Library: ksvgiconpainter.cpp Source File (kdecore Library)

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

This file is part of the documentation for kdecore Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:18:12 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003