ksvgiconengine.cpp Source File (kdecore Library)

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

# ksvgiconengine.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     along with this library; see the file COPYING.LIB.  If not, write to
    00017     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00018     Boston, MA 02111-1307, USA.
    00019 */
    00020
    00021 #include <qdom.h>
    00022 #include <qfile.h>
    00023 #include <qcolor.h>
    00024 #include <qimage.h>
    00025 #include <qregexp.h>
    00026 #include <qwmatrix.h>
    00027
    00028 #include <kdebug.h>
    00029 #include <kmdcodec.h>
    00030
    00031 #include <zlib.h>
    00032 #include <math.h>
    00033
    00034 #include "ksvgiconpainter.h"
    00035 #include "ksvgiconengine.h"
    00036
    00037 class KSVGIconEngineHelper
    00038 {
    00039 public:
    00040         KSVGIconEngineHelper(KSVGIconEngine *engine)
    00041         {
    00042                 m_engine = engine;
    00043         }
    00044
    00045         ~KSVGIconEngineHelper()
    00046         {
    00047         }
    00048
    00049         double dpi()
    00050         {
    00051             return 90.0; // TODO: make modal?
    00052         }
    00053
    00054         double toPixel(const QString &s, bool hmode)
    00055         {
    00056                 if(s.isEmpty())
    00057                         return 0.0;
    00058
    00059                 QString check = s;
    00060
    00061                 double ret = 0.0;
    00062
    00063                 bool ok = false;
    00064
    00065                 double value = check.toDouble(&ok);
    00066
    00067                 if(!ok)
    00068                 {
    00069                         QRegExp reg("[0-9 .-]");
    00070                         check.replace(reg, "");
    00071
    00072                         if(check.compare("px") == 0)
    00073                                 ret = value;
    00074                         else if(check.compare("cm") == 0)
    00075                                 ret = (value / 2.54) * dpi();
    00076                         else if(check.compare("pc") == 0)
    00077                                 ret = (value / 6.0) * dpi();
    00078                         else if(check.compare("mm") == 0)
    00079                                 ret = (value / 25.4) * dpi();
    00080                         else if(check.compare("in") == 0)
    00081                                 ret = value * dpi();
    00082                         else if(check.compare("pt") == 0)
    00083                                 ret = (value / 72.0) * dpi();
    00084                         else if(check.compare("%") == 0)
    00085                         {
    00086                                 ret = value / 100.0;
    00087
    00088                                 if(hmode)
    00089                                         ret *= m_engine->width();
    00090                                 else
    00091                                         ret *= m_engine->height();
    00092                         }
    00093                         else if(check.compare("em") == 0)
    00094                         {
    00095                                 ret = (value / 72.0) * dpi() * 12.0; // TODO make this depend on actual font size
    00096                         }
    00097                 }
    00098                 else
    00099                         ret = value;
    00100
    00101                 return ret;
    00102         }
    00103
    00104         ArtGradientStop *parseGradientStops(QDomElement element, int &offsets)
    00105         {
    00106                 QMemArray<ArtGradientStop> *stopArray = new QMemArray<ArtGradientStop>();
    00107
    00108                 float oldOffset = -1, newOffset = -1;
    00109                 for(QDomNode node = element.firstChild(); !node.isNull(); node = node.nextSibling())
    00110                 {
    00111                         QDomElement element = node.toElement();
    00112
    00113                         oldOffset = newOffset;
    00114                         QString temp = element.attribute("offset");
    00115
    00116                         if(temp.contains("%"))
    00117                         {
    00118                                 temp = temp.left(temp.length() - 1);
    00119                                 newOffset = temp.toFloat() / 100.0;
    00120                         }
    00121                         else
    00122                                 newOffset = temp.toFloat();
    00123
    00124                         // Spec  skip double offset specifications
    00125                         if(oldOffset == newOffset)
    00126                                 continue;
    00127
    00128                         offsets++;
    00129                         stopArray->resize(offsets + 1);
    00130
    00131                         (*stopArray)[offsets].offset = newOffset;
    00132
    00133                         QString parseOpacity;
    00134                         QString parseColor;
    00135
    00136                         if(element.hasAttribute("stop-opacity"))
    00137                                 parseOpacity = element.attribute("stop-opacity");
    00138
    00139                         if(element.hasAttribute("stop-color"))
    00140                                 parseColor = element.attribute("stop-color");
    00141
    00142                         if(parseOpacity.isEmpty() || parseColor.isEmpty())
    00143                         {
    00144                                 QString style = element.attribute("style");
    00145
    00146                                 QStringList substyles = QStringList::split(';', style);
    00147                                 for(QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it)
    00148                                 {
    00149                                         QStringList substyle = QStringList::split(':', (*it));
    00150                                         QString command = substyle[0];
    00151                                         QString params = substyle[1];
    00152                                         command = command.stripWhiteSpace();
    00153                                         params = params.stripWhiteSpace();
    00154
    00155                                         if(command == "stop-color")
    00156                                         {
    00157                                                 parseColor = params;
    00158
    00159                                                 if(!parseOpacity.isEmpty())
    00160                                                         break;
    00161                                         }
    00162                                         else if(command == "stop-opacity")
    00163                                         {
    00164                                                 parseOpacity = params;
    00165
    00166                                                 if(!parseColor.isEmpty())
    00167                                                         break;
    00168                                         }
    00169                                 }
    00170                         }
    00171
    00172                         // Parse color using KSVGIconPainter (which uses Qt)
    00173                         // Supports all svg-needed color formats
    00174                         QColor qStopColor = m_engine->painter()->parseColor(parseColor);
    00175
    00176                         // Convert in a libart suitable form
    00177                         Q_UINT32 stopColor = m_engine->painter()->toArtColor(qStopColor);
    00178
    00179                         int opacity = m_engine->painter()->parseOpacity(parseOpacity);
    00180
    00181                         Q_UINT32 rgba = (stopColor << 8) | opacity;
    00182                         Q_UINT32 r, g, b, a;
    00183
    00184                         // Convert from separated to premultiplied alpha
    00185                         a = rgba & 0xff;
    00186                         r = (rgba >> 24) * a + 0x80;
    00187                         r = (r + (r >> 8)) >> 8;
    00188                         g = ((rgba >> 16) & 0xff) * a + 0x80;
    00189                         g = (g + (g >> 8)) >> 8;
    00190                         b = ((rgba >> 8) & 0xff) * a + 0x80;
    00191                         b = (b + (b >> 8)) >> 8;
    00192
    00193                         (*stopArray)[offsets].color[0] = ART_PIX_MAX_FROM_8(r);
    00194                         (*stopArray)[offsets].color[1] = ART_PIX_MAX_FROM_8(g);
    00195                         (*stopArray)[offsets].color[2] = ART_PIX_MAX_FROM_8(b);
    00196                         (*stopArray)[offsets].color[3] = ART_PIX_MAX_FROM_8(a);
    00197                 }
    00198
    00199                 return stopArray->data();
    00200         }
    00201
    00202         QPointArray parsePoints(QString points)
    00203         {
    00204                 if(points.isEmpty())
    00205                         return QPointArray();
    00206
    00207                 points = points.simplifyWhiteSpace();
    00208
    00209                 if(points.contains(",,") || points.contains(", ,"))
    00210                         return QPointArray();
    00211
    00212                 points.replace(QRegExp(","), " ");
    00213                 points.replace(QRegExp("\r"), "");
    00214                 points.replace(QRegExp("\n"), "");
    00215
    00216                 points = points.simplifyWhiteSpace();
    00217
    00218                 QStringList pointList = QStringList::split(' ', points);
    00219
    00220                 QPointArray array(pointList.count() / 2);
    00221                 int i = 0;
    00222
    00223                 for(QStringList::Iterator it = pointList.begin(); it != pointList.end(); it++)
    00224                 {
    00225                         float x = (*(it++)).toFloat();
    00226                         float y = (*(it)).toFloat();
    00227
    00228                         array.setPoint(i, static_cast<int>(x), static_cast<int>(y));
    00229                 i++;
    00230                 }
    00231
    00232                 return array;
    00233         }
    00234
    00235         void parseTransform(const QString &transform)
    00236         {
    00237                 // Combine new and old matrix
    00238                 QWMatrix matrix = m_engine->painter()->parseTransform(transform);
    00239
    00240                 QWMatrix *current = m_engine->painter()->worldMatrix();
    00241                 *current *= matrix;
    00242         }
    00243
    00244         void parseCommonAttributes(QDomNode &node)
    00245         {
    00246                 // Set important default attributes
    00247                 m_engine->painter()->setFillColor("black");
    00248                 m_engine->painter()->setStrokeColor("none");
    00249                 m_engine->painter()->setStrokeDashArray("");
    00250                 m_engine->painter()->setStrokeWidth(1);
    00251                 m_engine->painter()->setJoinStyle("");
    00252                 m_engine->painter()->setCapStyle("");
    00253         //      m_engine->painter()->setFillOpacity(255, true);
    00254         //      m_engine->painter()->setStrokeOpacity(255, true);
    00255
    00256                 // Collect parent node's attributes
    00257                 QPtrList<QDomNamedNodeMap> applyList;
    00258                 applyList.setAutoDelete(true);
    00259
    00260                 QDomNode shape = node.parentNode();
    00261                 for(; !shape.isNull() ; shape = shape.parentNode())
    00262                         applyList.prepend(new QDomNamedNodeMap(shape.attributes()));
    00263
    00264                 // Apply parent attributes
    00265                 for(QDomNamedNodeMap *map = applyList.first(); map != 0; map = applyList.next())
    00266                 {
    00267                         QDomNamedNodeMap attr = *map;
    00268
    00269                         for(unsigned int i = 0; i < attr.count(); i++)
    00270                         {
    00271                                 QString name, value;
    00272
    00273                                 name = attr.item(i).nodeName().lower();
    00274                                 value = attr.item(i).nodeValue();
    00275
    00276                                 if(name == "transform")
    00277                                         parseTransform(value);
    00278                                 else if(name == "style")
    00279                                         parseStyle(value);
    00280                                 else
    00281                                         parsePA(name, value);
    00282                         }
    00283                 }
    00284
    00285                 // Apply local attributes
    00286                 QDomNamedNodeMap attr = node.attributes();
    00287
    00288                 for(unsigned int i = 0; i < attr.count(); i++)
    00289                 {
    00290                         QDomNode current = attr.item(i);
    00291
    00292                         if(current.nodeName().lower() == "transform")
    00293                                 parseTransform(current.nodeValue());
    00294                         else if(current.nodeName().lower() == "style")
    00295                                 parseStyle(current.nodeValue());
    00296                         else
    00297                                 parsePA(current.nodeName().lower(), current.nodeValue());
    00298                 }
    00299         }
    00300
    00301         void handleTags(QDomElement element, bool paint)
    00302         {
    00303                 if(element.tagName() == "linearGradient")
    00304                 {
    00305                         ArtGradientLinear *gradient = new ArtGradientLinear();
    00306
    00307                         int offsets = -1;
    00308                         gradient->stops = parseGradientStops(element, offsets);
    00309                         gradient->n_stops = offsets + 1;
    00310
    00311                         QString spread = element.attribute("spreadMethod");
    00312                         if(spread == "repeat")
    00313                                 gradient->spread = ART_GRADIENT_REPEAT;
    00314                         else if(spread == "reflect")
    00315                                 gradient->spread = ART_GRADIENT_REFLECT;
    00316                         else
    00317                                 gradient->spread = ART_GRADIENT_PAD;
    00318
    00319                         m_engine->painter()->addLinearGradient(element.attribute("id"), gradient);
    00320                         m_engine->painter()->addLinearGradientElement(gradient, element);
    00321                         return;
    00322                 }
    00323                 else if(element.tagName() == "radialGradient")
    00324                 {
    00325                         ArtGradientRadial *gradient = new ArtGradientRadial();
    00326
    00327                         int offsets = -1;
    00328                         gradient->stops = parseGradientStops(element, offsets);
    00329                         gradient->n_stops = offsets + 1;
    00330
    00331                         m_engine->painter()->addRadialGradient(element.attribute("id"), gradient);
    00332                         m_engine->painter()->addRadialGradientElement(gradient, element);
    00333                         return;
    00334                 }
    00335
    00336                 if(!paint)
    00337                         return;
    00338
    00339                 // TODO: Default attribute values
    00340                 if(element.tagName() == "rect")
    00341                 {
    00342                         double x = toPixel(element.attribute("x"), true);
    00343                         double y = toPixel(element.attribute("y"), false);
    00344                         double w = toPixel(element.attribute("width"), true);
    00345                         double h = toPixel(element.attribute("height"), false);
    00346
    00347                         double rx = 0.0;
    00348                         double ry = 0.0;
    00349
    00350                         if(element.hasAttribute("rx"))
    00351                                 rx = toPixel(element.attribute("rx"), true);
    00352
    00353                         if(element.hasAttribute("ry"))
    00354                                 ry = toPixel(element.attribute("ry"), false);
    00355
    00356                         m_engine->painter()->drawRectangle(x, y, w, h, rx, ry);
    00357                 }
    00358                 else if(element.tagName() == "g" || element.tagName() == "defs")
    00359                 {
    00360                         QDomNode iterate = element.firstChild();
    00361
    00362                         while(!iterate.isNull())
    00363                         {
    00364                                 // Reset matrix
    00365                                 m_engine->painter()->setWorldMatrix(new QWMatrix(m_initialMatrix));
    00366
    00367                                 // Parse common attributes, style / transform
    00368                                 parseCommonAttributes(iterate);
    00369
    00370                                 handleTags(iterate.toElement(), (element.tagName() == "defs") ? false : true);
    00371                                 iterate = iterate.nextSibling();
    00372                         }
    00373                 }
    00374                 else if(element.tagName() == "line")
    00375                 {
    00376                         double x1 = toPixel(element.attribute("x1"), true);
    00377                         double y1 = toPixel(element.attribute("y1"), false);
    00378                         double x2 = toPixel(element.attribute("x2"), true);
    00379                         double y2 = toPixel(element.attribute("y2"), false);
    00380
    00381                         m_engine->painter()->drawLine(x1, y1, x2, y2);
    00382                 }
    00383                 else if(element.tagName() == "circle")
    00384                 {
    00385                         double cx = toPixel(element.attribute("cx"), true);
    00386                         double cy = toPixel(element.attribute("cy"), false);
    00387
    00388                         double r = toPixel(element.attribute("r"), true); // TODO: horiz correct?
    00389
    00390                         m_engine->painter()->drawEllipse(cx, cy, r, r);
    00391                 }
    00392                 else if(element.tagName() == "ellipse")
    00393                 {
    00394                         double cx = toPixel(element.attribute("cx"), true);
    00395                         double cy = toPixel(element.attribute("cy"), false);
    00396
    00397                         double rx = toPixel(element.attribute("rx"), true);
    00398                         double ry = toPixel(element.attribute("ry"), false);
    00399
    00400                         m_engine->painter()->drawEllipse(cx, cy, rx, ry);
    00401                 }
    00402                 else if(element.tagName() == "polyline")
    00403                 {
    00404                         QPointArray polyline = parsePoints(element.attribute("points"));
    00405                         m_engine->painter()->drawPolyline(polyline);
    00406                 }
    00407                 else if(element.tagName() == "polygon")
    00408                 {
    00409                         QPointArray polygon = parsePoints(element.attribute("points"));
    00410                         m_engine->painter()->drawPolygon(polygon);
    00411                 }
    00412                 else if(element.tagName() == "path")
    00413                 {
    00414                         bool filled = true;
    00415
    00416                         if(element.hasAttribute("fill") && element.attribute("fill").contains("none"))
    00417                                 filled = false;
    00418
    00419                         if(element.attribute("style").contains("fill") && element.attribute("style").stripWhiteSpace().contains("fill:none"))
    00420                                 filled = false;
    00421
    00422                         m_engine->painter()->drawPath(element.attribute("d"), filled);
    00423                 }
    00424                 else if(element.tagName() == "image")
    00425                 {
    00426                         double x = toPixel(element.attribute("x"), true);
    00427                         double y = toPixel(element.attribute("y"), false);
    00428                         double w = toPixel(element.attribute("width"), true);
    00429                         double h = toPixel(element.attribute("height"), false);
    00430
    00431                         QString href = element.attribute("xlink:href");
    00432
    00433                         if(href.startsWith("data:"))
    00434                         {
    00435                                 // Get input
    00436                                 QCString input = href.mid(13).utf8();
    00437
    00438                                 // Decode into 'output'
    00439                                 QByteArray output;
    00440                                 KCodecs::base64Decode(input, output);
    00441
    00442                                 // Display
    00443                                 QImage *image = new QImage(output);
    00444
    00445                                 // Scale, if needed
    00446                                 if(image->width() != (int) w || image->height() != (int) h)
    00447                                 {
    00448                                         QImage show = image->smoothScale((int) w, (int) h, QImage::ScaleMin);
    00449                                         m_engine->painter()->drawImage(x, y, show);
    00450                                 }
    00451
    00452                                 m_engine->painter()->drawImage(x, y, *image);
    00453                         }
    00454                 }
    00455         }
    00456
    00457         void parseStyle(const QString &style)
    00458         {
    00459                 QStringList substyles = QStringList::split(';', style);
    00460                 for(QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it)
    00461                 {
    00462                         QStringList substyle = QStringList::split(':', (*it));
    00463                         QString command = substyle[0];
    00464                         QString params = substyle[1];
    00465                         command = command.stripWhiteSpace();
    00466                         params = params.stripWhiteSpace();
    00467
    00468                         parsePA(command, params);
    00469                 }
    00470         }
    00471
    00472         void parsePA(const QString &command, const QString &value)
    00473         {
    00474                 if(command == "stroke-width") // TODO: horiz:false correct?
    00475                         m_engine->painter()->setStrokeWidth(toPixel(value, false));
    00476                 else if(command == "stroke-miterlimit")
    00477                         m_engine->painter()->setStrokeMiterLimit(value);
    00478                 else if(command == "stroke-linecap")
    00479                         m_engine->painter()->setCapStyle(value);
    00480                 else if(command == "stroke-linejoin")
    00481                         m_engine->painter()->setJoinStyle(value);
    00482                 else if(command == "stroke-dashoffset")
    00483                         m_engine->painter()->setStrokeDashOffset(value);
    00484                 else if(command == "stroke-dasharray")
    00485                         m_engine->painter()->setStrokeDashArray(value);
    00486                         else if(command == "stroke")
    00487                         m_engine->painter()->setStrokeColor(value);
    00488                 else if(command == "fill")
    00489                         m_engine->painter()->setFillColor(value);
    00490                 else if(command == "fill-rule")
    00491                         m_engine->painter()->setFillRule(value);
    00492                 else if(command == "fill-opacity" || command == "stroke-opacity" || command == "opacity")
    00493                 {
    00494                         if(command == "fill-opacity")
    00495                                 m_engine->painter()->setFillOpacity(value);
    00496                         else if(command == "stroke-value")
    00497                                 m_engine->painter()->setStrokeOpacity(value);
    00498                         else
    00499                         {
    00500                                 m_engine->painter()->setOpacity(value);
    00501                                 m_engine->painter()->setFillOpacity(value);
    00502                                 m_engine->painter()->setStrokeOpacity(value);
    00503                         }
    00504                 }
    00505         }
    00506
    00507 private:
    00508         friend class KSVGIconEngine;
    00509
    00510         KSVGIconEngine *m_engine;
    00511         QWMatrix m_initialMatrix;
    00512 };
    00513
    00514 struct KSVGIconEngine::Private
    00515 {
    00516         KSVGIconPainter *painter;
    00517         KSVGIconEngineHelper *helper;
    00518
    00519         double width;
    00520         double height;
    00521 };
    00522
    00523 KSVGIconEngine::KSVGIconEngine() : d(new Private())
    00524 {
    00525         d->painter = 0;
    00526         d->helper = new KSVGIconEngineHelper(this);
    00527
    00528         d->width = 0.0;
    00529         d->height = 0.0;
    00530 }
    00531
    00532 KSVGIconEngine::~KSVGIconEngine()
    00533 {
    00534         if(d->painter)
    00535                 delete d->painter;
    00536
    00537         delete d->helper;
    00538
    00539         delete d;
    00540 }
    00541
    00542 bool KSVGIconEngine::load(int width, int height, const QString &path)
    00543 {
    00544         QDomDocument svgDocument("svg");
    00545         QFile file(path);
    00546
    00547         if(path.right(3).upper() == "SVG")
    00548         {
    00549                 // Open SVG Icon
    00550                 if(!file.open(IO_ReadOnly))
    00551                         return false;
    00552
    00553                 svgDocument.setContent(&file);
    00554         }
    00555         else // SVGZ
    00556         {
    00557                 gzFile svgz = gzopen(path.latin1(), "ro");
    00558                 if(!svgz)
    00559                         return false;
    00560
    00561                 QString data;
    00562                 bool done = false;
    00563
    00564                 char *buffer = new char[1024];
    00565
    00566                 while(!done)
    00567                 {
    00568                         memset(buffer, 0, 1024);
    00569
    00570                         int ret = gzread(svgz, buffer, 1024);
    00571                         if(ret == 0)
    00572                                 done = true;
    00573                         else if(ret == -1)
    00574                                 return false;
    00575
    00576                         data += QString::fromUtf8(buffer);
    00577                 }
    00578
    00579                 gzclose(svgz);
    00580
    00581                 svgDocument.setContent(data);
    00582         }
    00583
    00584         if(svgDocument.isNull())
    00585                 return false;
    00586
    00587         // Check for root element
    00588         QDomNode rootNode = svgDocument.namedItem("svg");
    00589         if(rootNode.isNull() || !rootNode.isElement())
    00590                 return false;
    00591
    00592         // Detect width and height
    00593         QDomElement rootElement = rootNode.toElement();
    00594
    00595         d->width = width;
    00596
    00597         if(rootElement.hasAttribute("width"))
    00598                 d->width = d->helper->toPixel(rootElement.attribute("width"), true);
    00599         else
    00600                 d->width = d->helper->toPixel("100%", true);
    00601
    00602         d->height = height;
    00603
    00604         if(rootElement.hasAttribute("height"))
    00605                 d->height = d->helper->toPixel(rootElement.attribute("height"), false);
    00606         else
    00607                 d->height = d->helper->toPixel("100%", false);
    00608
    00609         // Create icon painter
    00610         d->painter = new KSVGIconPainter(width, height, static_cast<int>(d->width), static_cast<int>(d->height));
    00611
    00612         // Set viewport clipping rect
    00613         d->painter->setClippingRect(0, 0, width, height);
    00614
    00615         // Apply viewbox
    00616         if(rootElement.hasAttribute("viewBox"))
    00617         {
    00618                 QStringList points = QStringList::split(' ', rootElement.attribute("viewBox").simplifyWhiteSpace());
    00619
    00620                 float w = points[2].toFloat();
    00621                 float h = points[3].toFloat();
    00622
    00623                 double vratiow = width / w;
    00624                 double vratioh = height / h;
    00625
    00626                 d->width = w;
    00627                 d->height = h;
    00628
    00629                 d->painter->worldMatrix()->scale(vratiow, vratioh);
    00630         }
    00631         else
    00632         {
    00633                 // Fit into 'width' and 'height'
    00634                 // FIXME: Use an aspect ratio
    00635                 double ratiow = width / d->width;
    00636                 double ratioh = height / d->height;
    00637
    00638                 d->painter->worldMatrix()->scale(ratiow, ratioh);
    00639         }
    00640
    00641         QWMatrix initialMatrix = *d->painter->worldMatrix();
    00642         d->helper->m_initialMatrix = initialMatrix;
    00643
    00644         // Apply transform
    00645         if(rootElement.hasAttribute("transform"))
    00646                 d->helper->parseTransform(rootElement.attribute("transform"));
    00647
    00648         // Go through all elements
    00649         QDomNode svgNode = rootElement.firstChild();
    00650         while(!svgNode.isNull())
    00651         {
    00652                 QDomElement svgChild = svgNode.toElement();
    00653                 if(!svgChild.isNull())
    00654                 {
    00655                         d->helper->parseCommonAttributes(svgNode);
    00656                         d->helper->handleTags(svgChild, true);
    00657                 }
    00658
    00659                 svgNode = svgNode.nextSibling();
    00660
    00661                 // Reset matrix
    00662                 d->painter->setWorldMatrix(new QWMatrix(initialMatrix));
    00663         }
    00664
    00665         d->painter->finish();
    00666
    00667         return true;
    00668 }
    00669
    00670 KSVGIconPainter *KSVGIconEngine::painter()
    00671 {
    00672         return d->painter;
    00673 }
    00674
    00675 double KSVGIconEngine::width()
    00676 {
    00677         return d->width;
    00678 }
    00679
    00680 double KSVGIconEngine::height()
    00681 {
    00682         return d->height;
    00683 }
    00684
    00685 // vim:ts=4:noet

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