kdecore Library API Documentation

ksvgiconpainter.cpp

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