• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kdecore
 

kdecore

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

kdecore

Skip menu "kdecore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdecore

Skip menu "kdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kdecore by doxygen 1.7.6.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |