diff options
Diffstat (limited to 'kdecore/svgicons')
-rw-r--r-- | kdecore/svgicons/CMakeLists.txt | 38 | ||||
-rw-r--r-- | kdecore/svgicons/Makefile.am | 6 | ||||
-rw-r--r-- | kdecore/svgicons/TODO | 5 | ||||
-rw-r--r-- | kdecore/svgicons/ksvgiconengine.cpp | 692 | ||||
-rw-r--r-- | kdecore/svgicons/ksvgiconengine.h | 49 | ||||
-rw-r--r-- | kdecore/svgicons/ksvgiconpainter.cpp | 2837 | ||||
-rw-r--r-- | kdecore/svgicons/ksvgiconpainter.h | 101 |
7 files changed, 0 insertions, 3728 deletions
diff --git a/kdecore/svgicons/CMakeLists.txt b/kdecore/svgicons/CMakeLists.txt deleted file mode 100644 index 4f2345510..000000000 --- a/kdecore/svgicons/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -################################################# -# -# (C) 2010 Serghei Amelian -# serghei (DOT) amelian (AT) gmail.com -# -# Improvements and feedback are welcome -# -# This file is released under GPL >= 2 -# -################################################# - -include_directories( - ${TQT_INCLUDE_DIRS} - ${CMAKE_BINARY_DIR}/tdecore - ${CMAKE_SOURCE_DIR}/tdecore - ${LIBART_INCLUDE_DIRS} -) - - -##### headers ################################### - -install( FILES - ksvgiconengine.h - DESTINATION ${INCLUDE_INSTALL_DIR} ) - - -##### kdesvgicons ############################### - -set( target kdesvgicons ) - -set( ${target}_SRCS - ksvgiconengine.cpp ksvgiconpainter.cpp -) - -tde_add_library( ${target} STATIC_PIC - SOURCES ${${target}_SRCS} - LINK ${LIBART_LIBRARIES} -) diff --git a/kdecore/svgicons/Makefile.am b/kdecore/svgicons/Makefile.am deleted file mode 100644 index ca398a5bd..000000000 --- a/kdecore/svgicons/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -INCLUDES = -I$(srcdir)/.. $(LIBART_CFLAGS) $(all_includes) - -noinst_LTLIBRARIES = libkdesvgicons.la - -include_HEADERS = ksvgiconengine.h -libkdesvgicons_la_SOURCES = ksvgiconengine.cpp ksvgiconpainter.cpp diff --git a/kdecore/svgicons/TODO b/kdecore/svgicons/TODO deleted file mode 100644 index 6ecafb8bf..000000000 --- a/kdecore/svgicons/TODO +++ /dev/null @@ -1,5 +0,0 @@ -* Units.svg is wrong -* faster implementations of parseStyle, parseTransform, if needed -* smaller art_render_new areas, if needed -* make gradients work for boundingbox as well -* patterns diff --git a/kdecore/svgicons/ksvgiconengine.cpp b/kdecore/svgicons/ksvgiconengine.cpp deleted file mode 100644 index 85830126b..000000000 --- a/kdecore/svgicons/ksvgiconengine.cpp +++ /dev/null @@ -1,692 +0,0 @@ -/* - Copyright (C) 2002 Nikolas Zimmermann <wildfox@kde.org> - This file is part of the KDE project - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include <tqdom.h> -#include <tqfile.h> -#include <tqcolor.h> -#include <tqimage.h> -#include <tqwmatrix.h> -#include <tqregexp.h> - -#include <kmdcodec.h> - -#include <zlib.h> - -#include "ksvgiconpainter.h" -#include "ksvgiconengine.h" - -class KSVGIconEngineHelper -{ -public: - KSVGIconEngineHelper(KSVGIconEngine *engine) - { - m_engine = engine; - } - - ~KSVGIconEngineHelper() - { - } - - double toPixel(const TQString &s, bool hmode) - { - return m_engine->painter()->toPixel(s, hmode); - } - - ArtGradientStop *parseGradientStops(TQDomElement element, int &offsets) - { - if (!element.hasChildNodes()) - return 0; - - TQValueList<ArtGradientStop> stopList; - - float oldOffset = -1, newOffset = -1; - for(TQDomNode node = element.firstChild(); !node.isNull(); node = node.nextSibling()) - { - TQDomElement element = node.toElement(); - - oldOffset = newOffset; - TQString temp = element.attribute("offset"); - - if(temp.contains("%")) - { - temp = temp.left(temp.length() - 1); - newOffset = temp.toFloat() / 100.0; - } - else - newOffset = temp.toFloat(); - - // Spec skip double offset specifications - if(oldOffset == newOffset) - continue; - - offsets++; - stopList.append(ArtGradientStop()); - - ArtGradientStop &stop = stopList.last(); - - stop.offset = newOffset; - - TQString parseOpacity; - TQString parseColor; - - if(element.hasAttribute("stop-opacity")) - parseOpacity = element.attribute("stop-opacity"); - - if(element.hasAttribute("stop-color")) - parseColor = element.attribute("stop-color"); - - if(parseOpacity.isEmpty() || parseColor.isEmpty()) - { - TQString style = element.attribute("style"); - - TQStringList substyles = TQStringList::split(';', style); - for(TQStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it) - { - TQStringList substyle = TQStringList::split(':', (*it)); - TQString command = substyle[0]; - TQString params = substyle[1]; - command = command.stripWhiteSpace(); - params = params.stripWhiteSpace(); - - if(command == "stop-color") - { - parseColor = params; - - if(!parseOpacity.isEmpty()) - break; - } - else if(command == "stop-opacity") - { - parseOpacity = params; - - if(!parseColor.isEmpty()) - break; - } - } - } - - // Parse color using KSVGIconPainter (which uses Qt) - // Supports all svg-needed color formats - TQColor qStopColor = m_engine->painter()->parseColor(parseColor); - - // Convert in a libart suitable form - TQ_UINT32 stopColor = m_engine->painter()->toArtColor(qStopColor); - - int opacity = m_engine->painter()->parseOpacity(parseOpacity); - - TQ_UINT32 rgba = (stopColor << 8) | opacity; - TQ_UINT32 r, g, b, a; - - // Convert from separated to premultiplied alpha - a = rgba & 0xff; - r = (rgba >> 24) * a + 0x80; - r = (r + (r >> 8)) >> 8; - g = ((rgba >> 16) & 0xff) * a + 0x80; - g = (g + (g >> 8)) >> 8; - b = ((rgba >> 8) & 0xff) * a + 0x80; - b = (b + (b >> 8)) >> 8; - - stop.color[0] = ART_PIX_MAX_FROM_8(r); - stop.color[1] = ART_PIX_MAX_FROM_8(g); - stop.color[2] = ART_PIX_MAX_FROM_8(b); - stop.color[3] = ART_PIX_MAX_FROM_8(a); - } - - if (stopList.isEmpty()) - return 0; - - ArtGradientStop *stops = new ArtGradientStop[stopList.count()]; - - TQValueList<ArtGradientStop>::iterator it = stopList.begin(); - TQValueList<ArtGradientStop>::iterator end = stopList.end(); - - for (int i = 0; it != end; ++i, ++it) - stops[i] = *it; - - return stops; - } - - TQPointArray parsePoints(TQString points) - { - if(points.isEmpty()) - return TQPointArray(); - - points = points.simplifyWhiteSpace(); - - if(points.contains(",,") || points.contains(", ,")) - return TQPointArray(); - - points.replace(',', ' '); - points.replace('\r', TQString()); - points.replace('\n', TQString()); - - points = points.simplifyWhiteSpace(); - - TQStringList pointList = TQStringList::split(' ', points); - - TQPointArray array(pointList.count() / 2); - int i = 0; - - for(TQStringList::Iterator it = pointList.begin(); it != pointList.end(); it++) - { - float x = (*(it++)).toFloat(); - float y = (*(it)).toFloat(); - - array.setPoint(i, static_cast<int>(x), static_cast<int>(y)); - i++; - } - - return array; - } - - void parseTransform(const TQString &transform) - { - // Combine new and old matrix - TQWMatrix matrix = m_engine->painter()->parseTransform(transform); - - TQWMatrix *current = m_engine->painter()->tqworldMatrix(); -#ifdef USE_QT4 -printf("[FIXME] *current = matrix * *current locks up under Qt4; bypassing for now\n\r"); -#else // USE_QT4 - *current = matrix * *current; -#endif // USE_QT4 - } - - void parseCommonAttributes(TQDomNode &node) - { - // Set important default attributes - m_engine->painter()->setFillColor("black"); - m_engine->painter()->setStrokeColor("none"); - m_engine->painter()->setStrokeDashArray(""); - m_engine->painter()->setStrokeWidth(1); - m_engine->painter()->setJoinStyle(""); - m_engine->painter()->setCapStyle(""); - // m_engine->painter()->setFillOpacity(255, true); - // m_engine->painter()->setStrokeOpacity(255, true); - - // Collect parent node's attributes - TQPtrList<TQDomNamedNodeMap> applyList; - applyList.setAutoDelete(true); - - TQDomNode tqshape = node.parentNode(); - for(; !tqshape.isNull() ; tqshape = tqshape.parentNode()) - applyList.prepend(new TQDomNamedNodeMap(tqshape.attributes())); - - // Apply parent attributes - for(TQDomNamedNodeMap *map = applyList.first(); map != 0; map = applyList.next()) - { - TQDomNamedNodeMap attr = *map; - - for(unsigned int i = 0; i < attr.count(); i++) - { - TQString name, value; - - name = attr.item(i).nodeName().lower(); - value = attr.item(i).nodeValue(); - - if(name == "transform") - parseTransform(value); - else if(name == "style") - parseStyle(value); - else - parsePA(name, value); - } - } - - // Apply local attributes - TQDomNamedNodeMap attr = node.attributes(); - - for(unsigned int i = 0; i < attr.count(); i++) - { - TQDomNode current = attr.item(i); - - if(current.nodeName().lower() == "transform") - parseTransform(current.nodeValue()); - else if(current.nodeName().lower() == "style") - parseStyle(current.nodeValue()); - else - parsePA(current.nodeName().lower(), current.nodeValue()); - } - } - - bool handleTags(TQDomElement element, bool paint) - { - if(element.attribute("display") == "none") - return false; - if(element.tagName() == "linearGradient") - { - ArtGradientLinear *gradient = new ArtGradientLinear(); - - int offsets = -1; - gradient->stops = parseGradientStops(element, offsets); - gradient->n_stops = offsets + 1; - - TQString spread = element.attribute("spreadMethod"); - if(spread == "repeat") - gradient->spread = ART_GRADIENT_REPEAT; - else if(spread == "reflect") - gradient->spread = ART_GRADIENT_REFLECT; - else - gradient->spread = ART_GRADIENT_PAD; - - m_engine->painter()->addLinearGradient(element.attribute("id"), gradient); - m_engine->painter()->addLinearGradientElement(gradient, element); - return true; - } - else if(element.tagName() == "radialGradient") - { - ArtGradientRadial *gradient = new ArtGradientRadial(); - - int offsets = -1; - gradient->stops = parseGradientStops(element, offsets); - gradient->n_stops = offsets + 1; - - m_engine->painter()->addRadialGradient(element.attribute("id"), gradient); - m_engine->painter()->addRadialGradientElement(gradient, element); - return true; - } - - if(!paint) - return true; - - // TODO: Default attribute values - if(element.tagName() == "rect") - { - double x = toPixel(element.attribute("x"), true); - double y = toPixel(element.attribute("y"), false); - double w = toPixel(element.attribute("width"), true); - double h = toPixel(element.attribute("height"), false); - - double rx = 0.0; - double ry = 0.0; - - if(element.hasAttribute("rx")) - rx = toPixel(element.attribute("rx"), true); - - if(element.hasAttribute("ry")) - ry = toPixel(element.attribute("ry"), false); - - m_engine->painter()->drawRectangle(x, y, w, h, rx, ry); - } - else if(element.tagName() == "switch") - { - TQDomNode iterate = element.firstChild(); - - while(!iterate.isNull()) - { - // Reset matrix - m_engine->painter()->setWorldMatrix(new TQWMatrix(m_initialMatrix)); - - // Parse common attributes, style / transform - parseCommonAttributes(iterate); - - if(handleTags(iterate.toElement(), true)) - return true; - iterate = iterate.nextSibling(); - } - return true; - } - else if(element.tagName() == "g" || element.tagName() == "defs") - { - TQDomNode iterate = element.firstChild(); - - while(!iterate.isNull()) - { - // Reset matrix - m_engine->painter()->setWorldMatrix(new TQWMatrix(m_initialMatrix)); - - // Parse common attributes, style / transform - parseCommonAttributes(iterate); - - handleTags(iterate.toElement(), (element.tagName() == "defs") ? false : true); - iterate = iterate.nextSibling(); - } - return true; - } - else if(element.tagName() == "line") - { - double x1 = toPixel(element.attribute("x1"), true); - double y1 = toPixel(element.attribute("y1"), false); - double x2 = toPixel(element.attribute("x2"), true); - double y2 = toPixel(element.attribute("y2"), false); - - m_engine->painter()->drawLine(x1, y1, x2, y2); - return true; - } - else if(element.tagName() == "circle") - { - double cx = toPixel(element.attribute("cx"), true); - double cy = toPixel(element.attribute("cy"), false); - - double r = toPixel(element.attribute("r"), true); // TODO: horiz correct? - - m_engine->painter()->drawEllipse(cx, cy, r, r); - return true; - } - else if(element.tagName() == "ellipse") - { - double cx = toPixel(element.attribute("cx"), true); - double cy = toPixel(element.attribute("cy"), false); - - double rx = toPixel(element.attribute("rx"), true); - double ry = toPixel(element.attribute("ry"), false); - - m_engine->painter()->drawEllipse(cx, cy, rx, ry); - return true; - } - else if(element.tagName() == "polyline") - { - TQPointArray polyline = parsePoints(element.attribute("points")); - m_engine->painter()->drawPolyline(polyline); - return true; - } - else if(element.tagName() == "polygon") - { - TQPointArray polygon = parsePoints(element.attribute("points")); - m_engine->painter()->drawPolygon(polygon); - return true; - } - else if(element.tagName() == "path") - { - bool filled = true; - - if(element.hasAttribute("fill") && element.attribute("fill").contains("none")) - filled = false; - - if(element.attribute("style").contains("fill") && element.attribute("style").stripWhiteSpace().contains("fill:none")) - filled = false; - - m_engine->painter()->drawPath(element.attribute("d"), filled); - return true; - } - else if(element.tagName() == "image") - { - double x = toPixel(element.attribute("x"), true); - double y = toPixel(element.attribute("y"), false); - double w = toPixel(element.attribute("width"), true); - double h = toPixel(element.attribute("height"), false); - - TQString href = element.attribute("xlink:href"); - - TQImage image; - if(href.startsWith("data:")) - { - // Get input - TQCString input = TQString(href.remove(TQRegExp("^data:image/.*;base64,"))).utf8(); - - // Decode into 'output' - TQByteArray output; - KCodecs::base64Decode(input, output); - - // Display - image.loadFromData(output); - } - else - image.load(href); - - if (!image.isNull()) - { - // Scale, if needed - if(image.width() != (int) w || image.height() != (int) h) - image = image.smoothScale((int) w, (int) h, TQ_ScaleFree); - - m_engine->painter()->drawImage(x, y, image); - } - - return true; - } - return false; - } - - void parseStyle(const TQString &style) - { - TQStringList substyles = TQStringList::split(';', style); - for(TQStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it) - { - TQStringList substyle = TQStringList::split(':', (*it)); - TQString command = substyle[0]; - TQString params = substyle[1]; - command = command.stripWhiteSpace(); - params = params.stripWhiteSpace(); - - parsePA(command, params); - } - } - - void parsePA(const TQString &command, const TQString &value) - { - if(command == "stroke-width") // TODO: horiz:false correct? - m_engine->painter()->setStrokeWidth(toPixel(value, false)); - else if(command == "stroke-miterlimit") - m_engine->painter()->setStrokeMiterLimit(value); - else if(command == "stroke-linecap") - m_engine->painter()->setCapStyle(value); - else if(command == "stroke-linejoin") - m_engine->painter()->setJoinStyle(value); - else if(command == "stroke-dashoffset") - m_engine->painter()->setStrokeDashOffset(value); - else if(command == "stroke-dasharray" && value != "none") - m_engine->painter()->setStrokeDashArray(value); - else if(command == "stroke") - m_engine->painter()->setStrokeColor(value); - else if(command == "fill") - m_engine->painter()->setFillColor(value); - else if(command == "fill-rule") - m_engine->painter()->setFillRule(value); - else if(command == "fill-opacity" || command == "stroke-opacity" || command == "opacity") - { - if(command == "fill-opacity") - m_engine->painter()->setFillOpacity(value); - else if(command == "stroke-value") - m_engine->painter()->setStrokeOpacity(value); - else - { - m_engine->painter()->setOpacity(value); - m_engine->painter()->setFillOpacity(value); - m_engine->painter()->setStrokeOpacity(value); - } - } - } - -private: - friend class KSVGIconEngine; - - KSVGIconEngine *m_engine; - TQWMatrix m_initialMatrix; -}; - -struct KSVGIconEngine::Private -{ - KSVGIconPainter *painter; - KSVGIconEngineHelper *helper; - - double width; - double height; -}; - -KSVGIconEngine::KSVGIconEngine() : d(new Private()) -{ - d->painter = 0; - d->helper = new KSVGIconEngineHelper(this); - - d->width = 0.0; - d->height = 0.0; -} - -KSVGIconEngine::~KSVGIconEngine() -{ - if(d->painter) - delete d->painter; - - delete d->helper; - - delete d; -} - -bool KSVGIconEngine::load(int width, int height, const TQString &path) -{ - if(path.isNull()) return false; - - TQDomDocument svgDocument("svg"); - TQFile file(path); - - if(path.right(3).upper() == "SVG") - { - // Open SVG Icon - if(!file.open(IO_ReadOnly)) - return false; - - svgDocument.setContent(&file); - } - else // SVGZ - { - gzFile svgz = gzopen(path.latin1(), "ro"); - if(!svgz) - return false; - - TQString data; - bool done = false; - - TQCString buffer(1024); - int length = 0; - - while(!done) - { - int ret = gzread(svgz, buffer.data() + length, 1024); - if(ret == 0) - done = true; - else if(ret == -1) - return false; - else { - buffer.resize(buffer.size()+1024); - length += ret; - } - } - - gzclose(svgz); - - svgDocument.setContent(buffer); - } - - if(svgDocument.isNull()) - return false; - - // Check for root element - TQDomNode rootNode = svgDocument.namedItem("svg"); - if(rootNode.isNull() || !rootNode.isElement()) - return false; - - // Detect width and height - TQDomElement rootElement = rootNode.toElement(); - - // Create icon painter - d->painter = new KSVGIconPainter(width, height); - - d->width = width; // this sets default for no width -> 100% case - if(rootElement.hasAttribute("width")) - d->width = d->helper->toPixel(rootElement.attribute("width"), true); - - d->height = height; // this sets default for no height -> 100% case - if(rootElement.hasAttribute("height")) - d->height = d->helper->toPixel(rootElement.attribute("height"), false); - - // Create icon painter - d->painter->setDrawWidth(static_cast<int>(d->width)); - d->painter->setDrawHeight(static_cast<int>(d->height)); - - // Set viewport clipping rect - d->painter->setClippingRect(0, 0, width, height); - - // Apply viewbox - if(rootElement.hasAttribute("viewBox")) - { - TQStringList points = TQStringList::split(' ', rootElement.attribute("viewBox").simplifyWhiteSpace()); - - float w = points[2].toFloat(); - float h = points[3].toFloat(); - - double vratiow = width / w; - double vratioh = height / h; - - d->width = w; - d->height = h; - - d->painter->tqworldMatrix()->scale(vratiow, vratioh); - } - else - { - // Fit into 'width' and 'height' - // FIXME: Use an aspect ratio - double ratiow = width / d->width; - double ratioh = height / d->height; - - d->painter->tqworldMatrix()->scale(ratiow, ratioh); - } - - TQWMatrix initialMatrix = *d->painter->tqworldMatrix(); - d->helper->m_initialMatrix = initialMatrix; - - // Apply transform - if(rootElement.hasAttribute("transform")) - d->helper->parseTransform(rootElement.attribute("transform")); - - // Go through all elements - TQDomNode svgNode = rootElement.firstChild(); - while(!svgNode.isNull()) - { - TQDomElement svgChild = svgNode.toElement(); - if(!svgChild.isNull()) - { - d->helper->parseCommonAttributes(svgNode); - d->helper->handleTags(svgChild, true); - } - - svgNode = svgNode.nextSibling(); - - // Reset matrix - d->painter->setWorldMatrix(new TQWMatrix(initialMatrix)); - } - - d->painter->finish(); - - return true; -} - -KSVGIconPainter *KSVGIconEngine::painter() -{ - return d->painter; -} - -TQImage *KSVGIconEngine::image() -{ - return d->painter->image(); -} - -double KSVGIconEngine::width() -{ - return d->width; -} - -double KSVGIconEngine::height() -{ - return d->height; -} - -// vim:ts=4:noet diff --git a/kdecore/svgicons/ksvgiconengine.h b/kdecore/svgicons/ksvgiconengine.h deleted file mode 100644 index 3ef2063e9..000000000 --- a/kdecore/svgicons/ksvgiconengine.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (C) 2002 Nikolas Zimmermann <wildfox@kde.org> - This file is part of the KDE project - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#ifndef KSVGIconEngine_H -#define KSVGIconEngine_H - -#include <kdelibs_export.h> - -/** \internal DO NOT USE! */ - -class KSVGIconPainter; - -class KDECORE_EXPORT KSVGIconEngine -{ -public: - KSVGIconEngine(); - ~KSVGIconEngine(); - - bool load(int width, int height, const TQString &path); - - KSVGIconPainter *painter(); - TQImage *image(); - - double width(); - double height(); - -private: - struct Private; - Private *d; -}; - -#endif diff --git a/kdecore/svgicons/ksvgiconpainter.cpp b/kdecore/svgicons/ksvgiconpainter.cpp deleted file mode 100644 index 2f988ce78..000000000 --- a/kdecore/svgicons/ksvgiconpainter.cpp +++ /dev/null @@ -1,2837 +0,0 @@ -/* - Copyright (C) 2002 Nikolas Zimmermann <wildfox@kde.org> - This file is part of the KDE project - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - aint with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include <tqvaluevector.h> -#include <tqstringlist.h> -#include <tqwmatrix.h> -#include <tqregexp.h> -#include <tqimage.h> -#include <tqdict.h> -#include <tqmap.h> -#include <tqdom.h> - -#include <math.h> - -#include <kdebug.h> - -#include <libart_lgpl/art_rgba.h> -#include <libart_lgpl/art_bpath.h> -#include <libart_lgpl/art_vpath.h> -#include <libart_lgpl/art_vpath_dash.h> -#include <libart_lgpl/art_affine.h> -#include <libart_lgpl/art_render_svp.h> -#include <libart_lgpl/art_svp.h> -#include <libart_lgpl/art_svp_vpath.h> -#include <libart_lgpl/art_svp_intersect.h> -#include <libart_lgpl/art_svp_vpath_stroke.h> - -#include "ksvgiconpainter.h" - -#define ART_END2 10 - -const double deg2rad = 0.017453292519943295769; // pi/180 - -class KSVGIconPainterHelper -{ -public: - KSVGIconPainterHelper(int width, int height, KSVGIconPainter *painter) - { - m_painter = painter; - - m_clipSVP = 0; - - m_fillColor = Qt::black; - - m_useFill = true; - m_useStroke = false; - - m_useFillGradient = false; - m_useStrokeGradient = false; - - m_tqworldMatrix = new TQWMatrix(); - - // Create new image with alpha support - m_image = new TQImage(width, height, 32); - m_image->setAlphaBuffer(true); - - m_strokeWidth = 1.0; - m_strokeMiterLimit = 4; - m_dashOffset = 0; - m_dashes = ""; - - m_opacity = 0xff; - m_fillOpacity = 0xff; - m_strokeOpacity = 0xff; - - m_fillRule = "nonzero"; - - m_width = width; - m_height = height; - - m_rowstride = m_width * 4; - - // Make internal libart rendering buffer transparent - m_buffer = art_new(art_u8, m_rowstride * m_height); - memset(m_buffer, 0, m_rowstride * m_height); - - m_tempBuffer = 0; - } - - ~KSVGIconPainterHelper() - { - if(m_clipSVP) - art_svp_free(m_clipSVP); - - art_free(m_buffer); - - delete m_image; - delete m_tqworldMatrix; - - for(TQMap<TQString, ArtGradientLinear *>::Iterator it = m_linearGradientMap.begin(); it != m_linearGradientMap.end(); ++it) - { - if (!it.data()) - continue; - delete [] it.data()->stops; - delete it.data(); - } - for(TQMap<TQString, ArtGradientRadial *>::Iterator it = m_radialGradientMap.begin(); it != m_radialGradientMap.end(); ++it) - { - if (!it.data()) - continue; - delete [] it.data()->stops; - delete it.data(); - } - } - - ArtVpath *allocVPath(int number) - { - return art_new(ArtVpath, number); - } - - ArtBpath *allocBPath(int number) - { - return art_new(ArtBpath, number); - } - - void ensureSpace(TQMemArray<ArtBpath> &vec, int index) - { - if(vec.size() == (unsigned int) index) - vec.resize(index + 1); - } - - void createBuffer() - { - m_tempBuffer = art_new(art_u8, m_rowstride * m_height); - memset(m_tempBuffer, 0, m_rowstride * m_height); - - // Swap buffers, so we work with the new one internally... - art_u8 *temp = m_buffer; - m_buffer = m_tempBuffer; - m_tempBuffer = temp; - } - - void mixBuffer(int opacity) - { - art_u8 *srcPixel = m_buffer; - art_u8 *dstPixel = m_tempBuffer; - - for(int y = 0; y < m_height; y++) - { - for(int x = 0; x < m_width; x++) - { - art_u8 r, g, b, a; - - a = srcPixel[4 * x + 3]; - - if(a) - { - r = srcPixel[4 * x]; - g = srcPixel[4 * x + 1]; - b = srcPixel[4 * x + 2]; - - int temp = a * opacity + 0x80; - a = (temp + (temp >> 8)) >> 8; - art_rgba_run_alpha(dstPixel + 4 * x, r, g, b, a, 1); - } - } - - srcPixel += m_rowstride; - dstPixel += m_rowstride; - } - - // Re-swap again... - art_u8 *temp = m_buffer; - m_buffer = m_tempBuffer; - m_tempBuffer = temp; - - art_free(m_tempBuffer); - m_tempBuffer = 0; - } - - TQ_UINT32 toArtColor(const TQColor &color) - { - // Convert in a libart suitable form - TQString tempName = color.name(); - const char *str = tempName.latin1(); - - int result = 0; - - for(int i = 1; str[i]; i++) - { - int hexval; - if(str[i] >= '0' && str[i] <= '9') - hexval = str[i] - '0'; - else if (str[i] >= 'A' && str[i] <= 'F') - hexval = str[i] - 'A' + 10; - else if (str[i] >= 'a' && str[i] <= 'f') - hexval = str[i] - 'a' + 10; - else - break; - - result = (result << 4) + hexval; - } - - return result; - } - - void drawSVP(ArtSVP *svp, TQ_UINT32 rgb, int opacity) - { - if(!svp) - return; - - ArtRender *render = art_render_new(0, 0, m_width, m_height, m_buffer, m_rowstride, 3, 8, ART_ALPHA_SEPARATE, 0); - art_render_svp(render, svp); - - art_render_mask_solid(render, (opacity << 8) + opacity + (opacity >> 7)); - - ArtPixMaxDepth color[3]; - color[0] = ART_PIX_MAX_FROM_8(rgb >> 16); - color[1] = ART_PIX_MAX_FROM_8((rgb >> 8) & 0xff); - color[2] = ART_PIX_MAX_FROM_8(rgb & 0xff); - - art_render_image_solid(render, color); - art_render_invoke(render); - } - - void drawBPath(ArtBpath *bpath) - { - double affine[6]; - affine[0] = m_tqworldMatrix->m11(); - affine[1] = m_tqworldMatrix->m12(); - affine[2] = m_tqworldMatrix->m21(); - affine[3] = m_tqworldMatrix->m22(); - affine[4] = m_tqworldMatrix->dx(); - affine[5] = m_tqworldMatrix->dy(); - - ArtBpath *temp = art_bpath_affine_transform(bpath, affine); - ArtVpath *vec = art_bez_path_to_vec(temp, 0.25); - art_free(temp); - drawPathInternal(vec, affine); - } - - void drawVPath(ArtVpath *vec) - { - double affine[6]; - affine[0] = m_tqworldMatrix->m11(); - affine[1] = m_tqworldMatrix->m12(); - affine[2] = m_tqworldMatrix->m21(); - affine[3] = m_tqworldMatrix->m22(); - affine[4] = m_tqworldMatrix->dx(); - affine[5] = m_tqworldMatrix->dy(); - - ArtVpath *temp = art_vpath_affine_transform(vec, affine); - art_free(vec); - vec = temp; - drawPathInternal(vec, affine); - } - - void drawPathInternal(ArtVpath *vec, double *affine) - { - ArtSVP *svp; - ArtSVP *fillSVP = 0, *strokeSVP = 0; - - TQ_UINT32 fillColor = 0, strokeColor = 0; - - // Filling - { - int index = -1; - TQValueVector<int> toCorrect; - while(vec[++index].code != ART_END) - { - if(vec[index].code == ART_END2) - { - vec[index].code = ART_LINETO; - toCorrect.push_back(index); - } - } - - fillColor = toArtColor(m_fillColor); - - ArtSvpWriter *swr; - ArtSVP *temp; - temp = art_svp_from_vpath(vec); - - if(m_fillRule == "evenodd") - swr = art_svp_writer_rewind_new(ART_WIND_RULE_ODDEVEN); - else - swr = art_svp_writer_rewind_new(ART_WIND_RULE_NONZERO); - - art_svp_intersector(temp, swr); - svp = art_svp_writer_rewind_reap(swr); - - fillSVP = svp; - - art_svp_free(temp); - - TQValueVector<int>::iterator it; - for(it = toCorrect.begin(); it != toCorrect.end(); ++it) - vec[(*it)].code = (ArtPathcode)ART_END2; - } - - // There seems to be a problem when stroke width is zero, this is a quick - // fix (Rob). - if(m_strokeWidth <= 0) - m_useStroke = m_useStrokeGradient = false; - - // Stroking - if(m_useStroke || m_useStrokeGradient) - { - strokeColor = toArtColor(m_strokeColor); - - double ratio = art_affine_expansion(affine); - double strokeWidth = m_strokeWidth * ratio; - - ArtPathStrokeJoinType joinStyle = ART_PATH_STROKE_JOIN_MITER; - ArtPathStrokeCapType capStyle = ART_PATH_STROKE_CAP_BUTT; - - if(m_joinStyle == "miter") - joinStyle = ART_PATH_STROKE_JOIN_MITER; - else if(m_joinStyle == "round") - joinStyle = ART_PATH_STROKE_JOIN_ROUND; - else if(m_joinStyle == "bevel") - joinStyle = ART_PATH_STROKE_JOIN_BEVEL; - - if(m_capStyle == "butt") - capStyle = ART_PATH_STROKE_CAP_BUTT; - else if(m_capStyle == "round") - capStyle = ART_PATH_STROKE_CAP_ROUND; - else if(m_capStyle == "square") - capStyle = ART_PATH_STROKE_CAP_SQUARE; - - if(m_dashes.length() > 0) - { - TQRegExp reg("[, ]"); - TQStringList dashList = TQStringList::split(reg, m_dashes); - - double *dashes = new double[dashList.count()]; - for(unsigned int i = 0; i < dashList.count(); i++) - dashes[i] = m_painter->toPixel(dashList[i], true); - - ArtVpathDash dash; - dash.offset = m_dashOffset; - dash.n_dash = dashList.count(); - - dash.dash = dashes; - - ArtVpath *vec2 = art_vpath_dash(vec, &dash); - art_free(vec); - - delete[] dashes; - - vec = vec2; - } - - svp = art_svp_vpath_stroke(vec, joinStyle, capStyle, strokeWidth, m_strokeMiterLimit, 0.25); - - strokeSVP = svp; - } - - // Apply opacity - int fillOpacity = static_cast<int>(m_fillOpacity); - int strokeOpacity = static_cast<int>(m_strokeOpacity); - int opacity = static_cast<int>(m_opacity); - - // Needed hack, to support both transparent - // paths and transparent gradients - if(fillOpacity == strokeOpacity && fillOpacity == opacity && !m_useFillGradient && !m_useStrokeGradient) - opacity = 255; - - if(fillOpacity != 255) - { - int temp = fillOpacity * opacity + 0x80; - fillOpacity = (temp + (temp >> 8)) >> 8; - } - - if(strokeOpacity != 255) - { - int temp = strokeOpacity * opacity + 0x80; - strokeOpacity = (temp + (temp >> 8)) >> 8; - } - - // Create temporary buffer if necessary - bool tempDone = false; - if(m_opacity != 0xff) - { - tempDone = true; - createBuffer(); - } - - // Apply Gradients on fill/stroke - if(m_useFillGradient) - applyGradient(fillSVP, true); - else if(m_useFill) - drawSVP(fillSVP, fillColor, fillOpacity); - - if(m_useStrokeGradient) - applyGradient(strokeSVP, false); - else if(m_useStroke) - drawSVP(strokeSVP, strokeColor, strokeOpacity); - - // Mix in temporary buffer, if possible - if(tempDone) - mixBuffer(opacity); - - if(m_clipSVP) - { - art_svp_free(m_clipSVP); - m_clipSVP = 0; - } - - if(fillSVP) - art_svp_free(fillSVP); - - if(strokeSVP) - art_svp_free(strokeSVP); - - // Reset opacity values - m_opacity = 255.0; - m_fillOpacity = 255.0; - m_strokeOpacity = 255.0; - - art_free(vec); - } - - void applyLinearGradient(ArtSVP *svp, const TQString &ref) - { - ArtGradientLinear *linear = m_linearGradientMap[ref]; - if(linear) - { - TQDomElement element = m_linearGradientElementMap[linear]; - - double x1, y1, x2, y2; - if(element.hasAttribute("x1")) - x1 = m_painter->toPixel(element.attribute("x1"), true); - else - x1 = 0; - - if(element.hasAttribute("y1")) - y1 = m_painter->toPixel(element.attribute("y1"), false); - else - y1 = 0; - - if(element.hasAttribute("x2")) - x2 = m_painter->toPixel(element.attribute("x2"), true); - else - x2 = 100; - - if(element.hasAttribute("y2")) - y2 = m_painter->toPixel(element.attribute("y2"), false); - else - y2 = 0; - - // Adjust to gradientTransform - TQWMatrix m = m_painter->parseTransform(element.attribute("gradientTransform")); - m.map(x1, y1, &x1, &y1); - m.map(x2, y2, &x2, &y2); - - double x1n = x1 * m_tqworldMatrix->m11() + y1 * m_tqworldMatrix->m21() + m_tqworldMatrix->dx(); - double y1n = x1 * m_tqworldMatrix->m12() + y1 * m_tqworldMatrix->m22() + m_tqworldMatrix->dy(); - double x2n = x2 * m_tqworldMatrix->m11() + y2 * m_tqworldMatrix->m21() + m_tqworldMatrix->dx(); - double y2n = x2 * m_tqworldMatrix->m12() + y2 * m_tqworldMatrix->m22() + m_tqworldMatrix->dy(); - - double dx = x2n - x1n; - double dy = y2n - y1n; - double scale = 1.0 / (dx * dx + dy * dy); - - linear->a = dx * scale; - linear->b = dy * scale; - linear->c = -(x1n * linear->a + y1n * linear->b); - - ArtRender *render = art_render_new(0, 0, m_width, m_height, m_buffer, m_rowstride, 3, 8, ART_ALPHA_SEPARATE, 0); - art_render_svp(render, svp); - - art_render_gradient_linear(render, linear, ART_FILTER_HYPER); - art_render_invoke(render); - } - } - - void applyRadialGradient(ArtSVP *svp, const TQString &ref) - { - ArtGradientRadial *radial = m_radialGradientMap[ref]; - if(radial) - { - TQDomElement element = m_radialGradientElementMap[radial]; - - double cx, cy, r, fx, fy; - if(element.hasAttribute("cx")) - cx = m_painter->toPixel(element.attribute("cx"), true); - else - cx = 50; - - if(element.hasAttribute("cy")) - cy = m_painter->toPixel(element.attribute("cy"), false); - else - cy = 50; - - if(element.hasAttribute("r")) - r = m_painter->toPixel(element.attribute("r"), true); - else - r = 50; - - if(element.hasAttribute("fx")) - fx = m_painter->toPixel(element.attribute("fx"), false); - else - fx = cx; - - if(element.hasAttribute("fy")) - fy = m_painter->toPixel(element.attribute("fy"), false); - else - fy = cy; - - radial->affine[0] = m_tqworldMatrix->m11(); - radial->affine[1] = m_tqworldMatrix->m12(); - radial->affine[2] = m_tqworldMatrix->m21(); - radial->affine[3] = m_tqworldMatrix->m22(); - radial->affine[4] = m_tqworldMatrix->dx(); - radial->affine[5] = m_tqworldMatrix->dy(); - - radial->fx = (fx - cx) / r; - radial->fy = (fy - cy) / r; - - double aff1[6], aff2[6], gradTransform[6]; - - // Respect gradientTransform - TQWMatrix m = m_painter->parseTransform(element.attribute("gradientTransform")); - - gradTransform[0] = m.m11(); - gradTransform[1] = m.m12(); - gradTransform[2] = m.m21(); - gradTransform[3] = m.m22(); - gradTransform[4] = m.dx(); - gradTransform[5] = m.dy(); - - art_affine_scale(aff1, r, r); - art_affine_translate(aff2, cx, cy); - - art_affine_multiply(aff1, aff1, aff2); - art_affine_multiply(aff1, aff1, gradTransform); - art_affine_multiply(aff1, aff1, radial->affine); - art_affine_invert(radial->affine, aff1); - - ArtRender *render = art_render_new(0, 0, m_width, m_height, m_buffer, m_rowstride, 3, 8, ART_ALPHA_SEPARATE, 0); - art_render_svp(render, svp); - - art_render_gradient_radial(render, radial, ART_FILTER_HYPER); - art_render_invoke(render); - } - } - - void applyGradient(ArtSVP *svp, const TQString &ref) - { - ArtGradientLinear *linear = m_linearGradientMap[ref]; - if(linear) - { - TQDomElement element = m_linearGradientElementMap[linear]; - - if(!element.hasAttribute("xlink:href")) - { - applyLinearGradient(svp, ref); - return; - } - else - { - ArtGradientLinear *linear = m_linearGradientMap[element.attribute("xlink:href").mid(1)]; - TQDomElement newElement = m_linearGradientElementMap[linear]; - - // Saved 'old' attributes - TQDict<TQString> refattrs; - refattrs.setAutoDelete(true); - - for(unsigned int i = 0; i < newElement.attributes().length(); ++i) - refattrs.insert(newElement.attributes().item(i).nodeName(), new TQString(newElement.attributes().item(i).nodeValue())); - - // Copy attributes - if(!newElement.isNull()) - { - TQDomNamedNodeMap attr = element.attributes(); - - for(unsigned int i = 0; i < attr.length(); i++) - { - TQString name = attr.item(i).nodeName(); - if(name != "xlink:href" && name != "id") - newElement.setAttribute(name, attr.item(i).nodeValue()); - } - } - - applyGradient(svp, element.attribute("xlink:href").mid(1)); - - // Restore attributes - TQDictIterator<TQString> itr(refattrs); - for(; itr.current(); ++itr) - newElement.setAttribute(itr.currentKey(), *(itr.current())); - - return; - } - } - - ArtGradientRadial *radial = m_radialGradientMap[ref]; - if(radial) - { - TQDomElement element = m_radialGradientElementMap[radial]; - - if(!element.hasAttribute("xlink:href")) - { - applyRadialGradient(svp, ref); - return; - } - else - { - ArtGradientRadial *radial = m_radialGradientMap[element.attribute("xlink:href").mid(1)]; - TQDomElement newElement = m_radialGradientElementMap[radial]; - - // Saved 'old' attributes - TQDict<TQString> refattrs; - refattrs.setAutoDelete(true); - - for(unsigned int i = 0; i < newElement.attributes().length(); ++i) - refattrs.insert(newElement.attributes().item(i).nodeName(), new TQString(newElement.attributes().item(i).nodeValue())); - - // Copy attributes - if(!newElement.isNull()) - { - TQDomNamedNodeMap attr = element.attributes(); - - for(unsigned int i = 0; i < attr.length(); i++) - { - TQString name = attr.item(i).nodeName(); - if(name != "xlink:href" && name != "id") - newElement.setAttribute(name, attr.item(i).nodeValue()); - } - } - - applyGradient(svp, element.attribute("xlink:href").mid(1)); - - // Restore attributes - TQDictIterator<TQString> itr(refattrs); - for(; itr.current(); ++itr) - newElement.setAttribute(itr.currentKey(), *(itr.current())); - - return; - } - } - } - - void applyGradient(ArtSVP *svp, bool fill) - { - TQString ref; - - if(fill) - { - m_useFillGradient = false; - ref = m_fillGradientReference; - } - else - { - m_useStrokeGradient = false; - ref = m_strokeGradientReference; - } - - applyGradient(svp, ref); - } - - void blit() - { - unsigned char *line = m_buffer; - - for(int y = 0; y < m_height; y++) - { - QRgb *sl = reinterpret_cast<QRgb *>(m_image->scanLine(y)); - for(int x = 0; x < m_width; x++) - sl[x] = tqRgba(line[x * 4], line[x * 4 + 1], line[x * 4 + 2], line[x * 4 + 3]); - - line += m_rowstride; - } - } - - 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) - { - double sin_th, cos_th; - double a00, a01, a10, a11; - double x0, y0, x1, y1, xc, yc; - double d, sfactor, sfactor_sq; - double th0, th1, th_arc; - int i, n_segs; - - sin_th = sin(angle * (M_PI / 180.0)); - cos_th = cos(angle * (M_PI / 180.0)); - - double dx; - - if(!relative) - dx = (curx - x) / 2.0; - else - dx = -x / 2.0; - - double dy; - - if(!relative) - dy = (cury - y) / 2.0; - else - dy = -y / 2.0; - - double _x1 = cos_th * dx + sin_th * dy; - double _y1 = -sin_th * dx + cos_th * dy; - double Pr1 = r1 * r1; - double Pr2 = r2 * r2; - double Px = _x1 * _x1; - double Py = _y1 * _y1; - - // Spec : check if radii are large enough - double check = Px / Pr1 + Py / Pr2; - if(check > 1) - { - r1 = r1 * sqrt(check); - r2 = r2 * sqrt(check); - } - - a00 = cos_th / r1; - a01 = sin_th / r1; - a10 = -sin_th / r2; - a11 = cos_th / r2; - - x0 = a00 * curx + a01 * cury; - y0 = a10 * curx + a11 * cury; - - if(!relative) - x1 = a00 * x + a01 * y; - else - x1 = a00 * (curx + x) + a01 * (cury + y); - - if(!relative) - y1 = a10 * x + a11 * y; - else - y1 = a10 * (curx + x) + a11 * (cury + y); - - /* (x0, y0) is current point in transformed coordinate space. - (x1, y1) is new point in transformed coordinate space. - - The arc fits a unit-radius circle in this space. - */ - - d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0); - - sfactor_sq = 1.0 / d - 0.25; - - if(sfactor_sq < 0) - sfactor_sq = 0; - - sfactor = sqrt(sfactor_sq); - - if(sweepFlag == largeArcFlag) - sfactor = -sfactor; - - xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0); - yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0); - - /* (xc, yc) is center of the circle. */ - th0 = atan2(y0 - yc, x0 - xc); - th1 = atan2(y1 - yc, x1 - xc); - - th_arc = th1 - th0; - if(th_arc < 0 && sweepFlag) - th_arc += 2 * M_PI; - else if(th_arc > 0 && !sweepFlag) - th_arc -= 2 * M_PI; - - n_segs = (int) (int) ceil(fabs(th_arc / (M_PI * 0.5 + 0.001))); - - for(i = 0; i < n_segs; i++) - { - index++; - - ensureSpace(vec, index); - - { - double sin_th, cos_th; - double a00, a01, a10, a11; - double x1, y1, x2, y2, x3, y3; - double t; - double th_half; - - double _th0 = th0 + i * th_arc / n_segs; - double _th1 = th0 + (i + 1) * th_arc / n_segs; - - sin_th = sin(angle * (M_PI / 180.0)); - cos_th = cos(angle * (M_PI / 180.0)); - - /* inverse transform compared with rsvg_path_arc */ - a00 = cos_th * r1; - a01 = -sin_th * r2; - a10 = sin_th * r1; - a11 = cos_th * r2; - - th_half = 0.5 * (_th1 - _th0); - t = (8.0 / 3.0) * sin(th_half * 0.5) * sin(th_half * 0.5) / sin(th_half); - x1 = xc + cos(_th0) - t * sin(_th0); - y1 = yc + sin(_th0) + t * cos(_th0); - x3 = xc + cos(_th1); - y3 = yc + sin(_th1); - x2 = x3 + t * sin(_th1); - y2 = y3 - t * cos(_th1); - - ensureSpace(vec, index); - - vec[index].code = ART_CURVETO; - vec[index].x1 = a00 * x1 + a01 * y1; - vec[index].y1 = a10 * x1 + a11 * y1; - vec[index].x2 = a00 * x2 + a01 * y2; - vec[index].y2 = a10 * x2 + a11 * y2; - vec[index].x3 = a00 * x3 + a01 * y3; - vec[index].y3 = a10 * x3 + a11 * y3; - } - } - - if(!relative) - curx = x; - else - curx += x; - - if(!relative) - cury = y; - else - cury += y; - } - - // For any docs, see the libart library - static void art_vpath_render_bez(ArtVpath **p_vpath, int *pn, int *pn_max, - double x0, double y0, - double x1, double y1, - double x2, double y2, - double x3, double y3, - double flatness) - { - double x3_0, y3_0, z3_0_dot, z1_dot, z2_dot; - double z1_perp, z2_perp, max_perp_sq; - - double x_m, y_m, xa1, ya1, xa2, ya2, xb1, yb1, xb2, yb2; - - x3_0 = x3 - x0; - y3_0 = y3 - y0; - - z3_0_dot = x3_0 * x3_0 + y3_0 * y3_0; - - if (z3_0_dot < 0.001) - goto nosubdivide; - - max_perp_sq = flatness * flatness * z3_0_dot; - - z1_perp = (y1 - y0) * x3_0 - (x1 - x0) * y3_0; - if (z1_perp * z1_perp > max_perp_sq) - goto subdivide; - - z2_perp = (y3 - y2) * x3_0 - (x3 - x2) * y3_0; - if (z2_perp * z2_perp > max_perp_sq) - goto subdivide; - - z1_dot = (x1 - x0) * x3_0 + (y1 - y0) * y3_0; - if (z1_dot < 0 && z1_dot * z1_dot > max_perp_sq) - goto subdivide; - - z2_dot = (x3 - x2) * x3_0 + (y3 - y2) * y3_0; - if (z2_dot < 0 && z2_dot * z2_dot > max_perp_sq) - goto subdivide; - - if (z1_dot + z1_dot > z3_0_dot) - goto subdivide; - - if (z2_dot + z2_dot > z3_0_dot) - goto subdivide; - - nosubdivide: - art_vpath_add_point (p_vpath, pn, pn_max, ART_LINETO, x3, y3); - return; - - subdivide: - xa1 = (x0 + x1) * 0.5; - ya1 = (y0 + y1) * 0.5; - xa2 = (x0 + 2 * x1 + x2) * 0.25; - ya2 = (y0 + 2 * y1 + y2) * 0.25; - xb1 = (x1 + 2 * x2 + x3) * 0.25; - yb1 = (y1 + 2 * y2 + y3) * 0.25; - xb2 = (x2 + x3) * 0.5; - yb2 = (y2 + y3) * 0.5; - x_m = (xa2 + xb1) * 0.5; - y_m = (ya2 + yb1) * 0.5; - art_vpath_render_bez (p_vpath, pn, pn_max, x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, flatness); - art_vpath_render_bez (p_vpath, pn, pn_max, x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, flatness); - } - - ArtVpath *art_bez_path_to_vec(const ArtBpath *bez, double flatness) - { - ArtVpath *vec; - int vec_n, vec_n_max; - int bez_index; - double x, y; - - vec_n = 0; - vec_n_max = (1 << 4); - vec = art_new (ArtVpath, vec_n_max); - - x = 0; - y = 0; - - bez_index = 0; - do - { - if(vec_n >= vec_n_max) - art_expand (vec, ArtVpath, vec_n_max); - - switch (bez[bez_index].code) - { - case ART_MOVETO_OPEN: - case ART_MOVETO: - case ART_LINETO: - x = bez[bez_index].x3; - y = bez[bez_index].y3; - vec[vec_n].code = bez[bez_index].code; - vec[vec_n].x = x; - vec[vec_n].y = y; - vec_n++; - break; - case ART_END: - vec[vec_n].code = ART_END; - vec[vec_n].x = 0; - vec[vec_n].y = 0; - vec_n++; - break; - case ART_END2: - vec[vec_n].code = (ArtPathcode)ART_END2; - vec[vec_n].x = bez[bez_index].x3; - vec[vec_n].y = bez[bez_index].y3; - vec_n++; - break; - case ART_CURVETO: - art_vpath_render_bez (&vec, &vec_n, &vec_n_max, - x, y, - bez[bez_index].x1, bez[bez_index].y1, - bez[bez_index].x2, bez[bez_index].y2, - bez[bez_index].x3, bez[bez_index].y3, - flatness); - x = bez[bez_index].x3; - y = bez[bez_index].y3; - break; - } - } - - while (bez[bez_index++].code != ART_END); - return vec; - } - - static void art_rgb_affine_run(int *p_x0, int *p_x1, int y, - int src_width, int src_height, - const double affine[6]) - { - int x0, x1; - double z; - double x_intercept; - int xi; - - x0 = *p_x0; - x1 = *p_x1; - - if (affine[0] > 1e-6) - { - z = affine[2] * (y + 0.5) + affine[4]; - x_intercept = -z / affine[0]; - xi = (int) (int) ceil (x_intercept + 1e-6 - 0.5); - if (xi > x0) - x0 = xi; - x_intercept = (-z + src_width) / affine[0]; - xi = (int) ceil (x_intercept - 1e-6 - 0.5); - if (xi < x1) - x1 = xi; - } - else if (affine[0] < -1e-6) - { - z = affine[2] * (y + 0.5) + affine[4]; - x_intercept = (-z + src_width) / affine[0]; - xi = (int) ceil (x_intercept + 1e-6 - 0.5); - if (xi > x0) - x0 = xi; - x_intercept = -z / affine[0]; - xi = (int) ceil (x_intercept - 1e-6 - 0.5); - if (xi < x1) - x1 = xi; - } - else - { - z = affine[2] * (y + 0.5) + affine[4]; - if (z < 0 || z >= src_width) - { - *p_x1 = *p_x0; - return; - } - } - if (affine[1] > 1e-6) - { - z = affine[3] * (y + 0.5) + affine[5]; - x_intercept = -z / affine[1]; - xi = (int) ceil (x_intercept + 1e-6 - 0.5); - if (xi > x0) - x0 = xi; - x_intercept = (-z + src_height) / affine[1]; - xi = (int) ceil (x_intercept - 1e-6 - 0.5); - if (xi < x1) - x1 = xi; - } - else if (affine[1] < -1e-6) - { - z = affine[3] * (y + 0.5) + affine[5]; - x_intercept = (-z + src_height) / affine[1]; - xi = (int) ceil (x_intercept + 1e-6 - 0.5); - if (xi > x0) - x0 = xi; - x_intercept = -z / affine[1]; - xi = (int) ceil (x_intercept - 1e-6 - 0.5); - if (xi < x1) - x1 = xi; - } - else - { - z = affine[3] * (y + 0.5) + affine[5]; - if (z < 0 || z >= src_height) - { - *p_x1 = *p_x0; - return; - } - } - - *p_x0 = x0; - *p_x1 = x1; - } - - // Slightly modified version to support RGBA buffers, copied from gnome-print - static void art_rgba_rgba_affine(art_u8 *dst, - int x0, int y0, int x1, int y1, int dst_rowstride, - const art_u8 *src, - int src_width, int src_height, int src_rowstride, - const double affine[6]) - { - int x, y; - double inv[6]; - art_u8 *dst_p, *dst_linestart; - const art_u8 *src_p; - ArtPoint pt, src_pt; - int src_x, src_y; - int alpha; - art_u8 bg_r, bg_g, bg_b, bg_a, cr, cg, cb; - art_u8 fg_r, fg_g, fg_b; - int tmp; - int run_x0, run_x1; - - dst_linestart = dst; - art_affine_invert (inv, affine); - for (y = y0; y < y1; y++) - { - pt.y = y + 0.5; - run_x0 = x0; - run_x1 = x1; - art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height, - inv); - dst_p = dst_linestart + (run_x0 - x0) * 4; - for (x = run_x0; x < run_x1; x++) - { - pt.x = x + 0.5; - art_affine_point (&src_pt, &pt, inv); - src_x = (int) floor (src_pt.x); - src_y = (int) floor (src_pt.y); - src_p = src + (src_y * src_rowstride) + src_x * 4; - if (src_x >= 0 && src_x < src_width && - src_y >= 0 && src_y < src_height) - { - - alpha = src_p[3]; - if (alpha) - { - if (alpha == 255) - { - dst_p[0] = src_p[0]; - dst_p[1] = src_p[1]; - dst_p[2] = src_p[2]; - dst_p[3] = 255; - } - else - { - bg_r = dst_p[0]; - bg_g = dst_p[1]; - bg_b = dst_p[2]; - bg_a = dst_p[3]; - - cr = (bg_r * bg_a + 0x80) >> 8; - cg = (bg_g * bg_g + 0x80) >> 8; - cb = (bg_b * bg_b + 0x80) >> 8; - - tmp = (src_p[0] - bg_r) * alpha; - fg_r = bg_r + ((tmp + (tmp >> 8) + 0x80) >> 8); - tmp = (src_p[1] - bg_g) * alpha; - fg_g = bg_g + ((tmp + (tmp >> 8) + 0x80) >> 8); - tmp = (src_p[2] - bg_b) * alpha; - fg_b = bg_b + ((tmp + (tmp >> 8) + 0x80) >> 8); - - dst_p[0] = fg_r; - dst_p[1] = fg_g; - dst_p[2] = fg_b; - dst_p[3] = bg_a + (((255 - bg_a) * alpha + 0x80) >> 8); - } - } - } else { dst_p[0] = 255; dst_p[1] = 0; dst_p[2] = 0; dst_p[3] = 255;} - dst_p += 4; - } - dst_linestart += dst_rowstride; - } - } - -private: - friend class KSVGIconPainter; - ArtSVP *m_clipSVP; - - TQImage *m_image; - TQWMatrix *m_tqworldMatrix; - - TQString m_fillRule; - TQString m_joinStyle; - TQString m_capStyle; - - int m_strokeMiterLimit; - - TQString m_dashes; - unsigned short m_dashOffset; - - TQColor m_fillColor; - TQColor m_strokeColor; - - art_u8 *m_buffer; - art_u8 *m_tempBuffer; - - int m_width; - int m_height; - - int m_rowstride; - - double m_opacity; - double m_fillOpacity; - double m_strokeOpacity; - - bool m_useFill; - bool m_useStroke; - - bool m_useFillGradient; - bool m_useStrokeGradient; - - TQString m_fillGradientReference; - TQString m_strokeGradientReference; - - TQMap<TQString, ArtGradientLinear *> m_linearGradientMap; - TQMap<ArtGradientLinear *, TQDomElement> m_linearGradientElementMap; - - TQMap<TQString, ArtGradientRadial *> m_radialGradientMap; - TQMap<ArtGradientRadial *, TQDomElement> m_radialGradientElementMap; - - KSVGIconPainter *m_painter; - - double m_strokeWidth; -}; - -struct KSVGIconPainter::Private -{ - KSVGIconPainterHelper *helper; - - int drawWidth; - int drawHeight; -}; - -KSVGIconPainter::KSVGIconPainter(int width, int height) : d(new Private()) -{ - d->helper = new KSVGIconPainterHelper(width, height, this); - - d->drawWidth = width; - d->drawHeight = height; -} - -KSVGIconPainter::~KSVGIconPainter() -{ - delete d->helper; - delete d; -} - -void KSVGIconPainter::setDrawWidth(int dwidth) -{ - d->drawWidth = dwidth; -} - -void KSVGIconPainter::setDrawHeight(int dheight) -{ - d->drawHeight = dheight; -} - -void KSVGIconPainter::finish() -{ - d->helper->blit(); -} - -TQImage *KSVGIconPainter::image() -{ - return new TQImage(*d->helper->m_image); -} - -TQWMatrix *KSVGIconPainter::tqworldMatrix() -{ - return d->helper->m_tqworldMatrix; -} - -void KSVGIconPainter::setWorldMatrix(TQWMatrix *matrix) -{ - if(d->helper->m_tqworldMatrix) - delete d->helper->m_tqworldMatrix; - - d->helper->m_tqworldMatrix = matrix; -} - -void KSVGIconPainter::setStrokeWidth(double width) -{ - d->helper->m_strokeWidth = width; -} - -void KSVGIconPainter::setStrokeMiterLimit(const TQString &miter) -{ - d->helper->m_strokeMiterLimit = miter.toInt(); -} - -void KSVGIconPainter::setStrokeDashOffset(const TQString &dashOffset) -{ - d->helper->m_dashOffset = dashOffset.toUInt(); -} - -void KSVGIconPainter::setStrokeDashArray(const TQString &dashes) -{ - d->helper->m_dashes = dashes; -} - -void KSVGIconPainter::setCapStyle(const TQString &cap) -{ - d->helper->m_capStyle = cap; -} - -void KSVGIconPainter::setJoinStyle(const TQString &join) -{ - d->helper->m_joinStyle = join; -} - -void KSVGIconPainter::setStrokeColor(const TQString &stroke) -{ - if(stroke.startsWith("url")) - { - d->helper->m_useStroke = false; - d->helper->m_useStrokeGradient = true; - - TQString url = stroke; - - unsigned int start = url.find("#") + 1; - unsigned int end = url.findRev(")"); - - d->helper->m_strokeGradientReference = url.mid(start, end - start); - } - else - { - d->helper->m_strokeColor = parseColor(stroke); - - d->helper->m_useStrokeGradient = false; - d->helper->m_strokeGradientReference = TQString::null; - - if(stroke.stripWhiteSpace().lower() != "none") - setUseStroke(true); - else - setUseStroke(false); - } -} - -void KSVGIconPainter::setFillColor(const TQString &fill) -{ - if(fill.startsWith("url")) - { - d->helper->m_useFill = false; - d->helper->m_useFillGradient = true; - - TQString url = fill; - - unsigned int start = url.find("#") + 1; - unsigned int end = url.findRev(")"); - - d->helper->m_fillGradientReference = url.mid(start, end - start); - } - else - { - d->helper->m_fillColor = parseColor(fill); - - d->helper->m_useFillGradient = false; - d->helper->m_fillGradientReference = TQString::null; - - if(fill.stripWhiteSpace().lower() != "none") - setUseFill(true); - else - setUseFill(false); - } -} - -void KSVGIconPainter::setFillRule(const TQString &fillRule) -{ - d->helper->m_fillRule = fillRule; -} - -TQ_UINT32 KSVGIconPainter::parseOpacity(const TQString &data) -{ - int opacity = 255; - - if(!data.isEmpty()) - { - double temp; - - if(data.contains("%")) - { - TQString tempString = data.left(data.length() - 1); - temp = double(255 * tempString.toDouble()) / 100.0; - } - else - temp = data.toDouble(); - - opacity = (int) floor(temp * 255 + 0.5); - } - - return opacity; -} - -void KSVGIconPainter::setFillOpacity(const TQString &fillOpacity) -{ - d->helper->m_fillOpacity = parseOpacity(fillOpacity); -} - -void KSVGIconPainter::setStrokeOpacity(const TQString &strokeOpacity) -{ - d->helper->m_strokeOpacity = parseOpacity(strokeOpacity); -} - -void KSVGIconPainter::setOpacity(const TQString &opacity) -{ - d->helper->m_opacity = parseOpacity(opacity); -} - -void KSVGIconPainter::setUseFill(bool fill) -{ - d->helper->m_useFill = fill; -} - -void KSVGIconPainter::setUseStroke(bool stroke) -{ - d->helper->m_useStroke = stroke; -} - -void KSVGIconPainter::setClippingRect(int x, int y, int w, int h) -{ - ArtVpath *vec = d->helper->allocVPath(6); - - vec[0].code = ART_MOVETO; - vec[0].x = x; - vec[0].y = y; - - vec[1].code = ART_LINETO; - vec[1].x = x; - vec[1].y = y + h; - - vec[2].code = ART_LINETO; - vec[2].x = x + w; - vec[2].y = y + h; - - vec[3].code = ART_LINETO; - vec[3].x = x + w; - vec[3].y = y; - - vec[4].code = ART_LINETO; - vec[4].x = x; - vec[4].y = y; - - vec[5].code = ART_END; - - if(d->helper->m_clipSVP) - art_svp_free(d->helper->m_clipSVP); - - d->helper->m_clipSVP = art_svp_from_vpath(vec); - - art_free(vec); -} - -void KSVGIconPainter::drawRectangle(double x, double y, double w, double h, double rx, double ry) -{ - if((int) rx != 0 && (int) ry != 0) - { - ArtVpath *res; - ArtBpath *vec = d->helper->allocBPath(10); - - int i = 0; - - if(rx > w / 2) - rx = w / 2; - - if(ry > h / 2) - ry = h / 2; - - vec[i].code = ART_MOVETO_OPEN; - vec[i].x3 = x + rx; - vec[i].y3 = y; - - i++; - - vec[i].code = ART_CURVETO; - vec[i].x1 = x + rx * (1 - 0.552); - vec[i].y1 = y; - vec[i].x2 = x; - vec[i].y2 = y + ry * (1 - 0.552); - vec[i].x3 = x; - vec[i].y3 = y + ry; - - i++; - - if(ry < h / 2) - { - vec[i].code = ART_LINETO; - vec[i].x3 = x; - vec[i].y3 = y + h - ry; - - i++; - } - - vec[i].code = ART_CURVETO; - vec[i].x1 = x; - vec[i].y1 = y + h - ry * (1 - 0.552); - vec[i].x2 = x + rx * (1 - 0.552); - vec[i].y2 = y + h; - vec[i].x3 = x + rx; - vec[i].y3 = y + h; - - i++; - - if(rx < w / 2) - { - vec[i].code = ART_LINETO; - vec[i].x3 = x + w - rx; - vec[i].y3 = y + h; - - i++; - } - - vec[i].code = ART_CURVETO; - vec[i].x1 = x + w - rx * (1 - 0.552); - vec[i].y1 = y + h; - vec[i].x2 = x + w; - vec[i].y2 = y + h - ry * (1 - 0.552); - vec[i].x3 = x + w; - - vec[i].y3 = y + h - ry; - - i++; - - if(ry < h / 2) - { - vec[i].code = ART_LINETO; - vec[i].x3 = x + w; - vec[i].y3 = y + ry; - - i++; - } - - vec[i].code = ART_CURVETO; - vec[i].x1 = x + w; - vec[i].y1 = y + ry * (1 - 0.552); - vec[i].x2 = x + w - rx * (1 - 0.552); - vec[i].y2 = y; - vec[i].x3 = x + w - rx; - vec[i].y3 = y; - - i++; - - if(rx < w / 2) - { - vec[i].code = ART_LINETO; - vec[i].x3 = x + rx; - vec[i].y3 = y; - - i++; - } - - vec[i].code = ART_END; - - res = d->helper->art_bez_path_to_vec(vec, 0.25); - art_free(vec); - d->helper->drawVPath(res); - } - else - { - ArtVpath *vec = d->helper->allocVPath(6); - - vec[0].code = ART_MOVETO; - vec[0].x = x; - vec[0].y = y; - - vec[1].code = ART_LINETO; - vec[1].x = x; - vec[1].y = y + h; - - vec[2].code = ART_LINETO; - vec[2].x = x + w; - vec[2].y = y + h; - - vec[3].code = ART_LINETO; - vec[3].x = x + w; - vec[3].y = y; - - vec[4].code = ART_LINETO; - vec[4].x = x; - vec[4].y = y; - - vec[5].code = ART_END; - - d->helper->drawVPath(vec); - } -} - -void KSVGIconPainter::drawEllipse(double cx, double cy, double rx, double ry) -{ - ArtBpath *temp; - - temp = d->helper->allocBPath(6); - - double x1, y1, x2, y2, x3, y3; - double len = 0.55228474983079356; - double cos4[] = {1.0, 0.0, -1.0, 0.0, 1.0}; - double sin4[] = {0.0, 1.0, 0.0, -1.0, 0.0}; - int i = 0; - - temp[i].code = ART_MOVETO; - temp[i].x3 = cx + rx; - temp[i].y3 = cy; - - i++; - - while(i < 5) - { - x1 = cos4[i-1] + len * cos4[i]; - y1 = sin4[i-1] + len * sin4[i]; - x2 = cos4[i] + len * cos4[i-1]; - y2 = sin4[i] + len * sin4[i-1]; - x3 = cos4[i]; - y3 = sin4[i]; - - temp[i].code = ART_CURVETO; - temp[i].x1 = cx + x1 * rx; - temp[i].y1 = cy + y1 * ry; - temp[i].x2 = cx + x2 * rx; - temp[i].y2 = cy + y2 * ry; - temp[i].x3 = cx + x3 * rx; - temp[i].y3 = cy + y3 * ry; - - i++; - } - - temp[i].code = ART_END; - - d->helper->drawBPath(temp); - - art_free(temp); -} - -void KSVGIconPainter::drawLine(double x1, double y1, double x2, double y2) -{ - ArtVpath *vec; - - vec = d->helper->allocVPath(3); - - vec[0].code = ART_MOVETO_OPEN; - vec[0].x = x1; - vec[0].y = y1; - - vec[1].code = ART_LINETO; - vec[1].x = x2; - vec[1].y = y2; - - vec[2].code = ART_END; - - d->helper->drawVPath(vec); -} - -void KSVGIconPainter::drawPolyline(TQPointArray polyArray, int points) -{ - if(polyArray.point(0).x() == -1 || polyArray.point(0).y() == -1) - return; - - ArtVpath *polyline; - - if(points == -1) - points = polyArray.count(); - - polyline = d->helper->allocVPath(3 + points); - polyline[0].code = ART_MOVETO; - polyline[0].x = polyArray.point(0).x(); - polyline[0].y = polyArray.point(0).y(); - - int index; - for(index = 1; index < points; index++) - { - TQPoint point = polyArray.point(index); - polyline[index].code = ART_LINETO; - polyline[index].x = point.x(); - polyline[index].y = point.y(); - } - - if(d->helper->m_useFill) // if the polyline must be filled, inform libart that it should not be closed. - { - polyline[index].code = (ArtPathcode)ART_END2; - polyline[index].x = polyArray.point(0).x(); - polyline[index++].y = polyArray.point(0).y(); - } - - polyline[index].code = ART_END; - - d->helper->drawVPath(polyline); -} - -void KSVGIconPainter::drawPolygon(TQPointArray polyArray) -{ - ArtVpath *polygon; - - polygon = d->helper->allocVPath(3 + polyArray.count()); - polygon[0].code = ART_MOVETO; - polygon[0].x = polyArray.point(0).x(); - polygon[0].y = polyArray.point(0).y(); - - unsigned int index; - for(index = 1; index < polyArray.count(); index++) - { - TQPoint point = polyArray.point(index); - polygon[index].code = ART_LINETO; - polygon[index].x = point.x(); - polygon[index].y = point.y(); - } - - polygon[index].code = ART_LINETO; - polygon[index].x = polyArray.point(0).x(); - polygon[index].y = polyArray.point(0).y(); - - index++; - polygon[index].code = ART_END; - - d->helper->drawVPath(polygon); -} - -// Path parsing tool -// parses the coord into number and forwards to the next token -static const char *getCoord(const char *ptr, double &number) -{ - int integer, exponent; - double decimal, frac; - int sign, expsign; - - exponent = 0; - integer = 0; - frac = 1.0; - decimal = 0; - sign = 1; - expsign = 1; - - // read the sign - if(*ptr == '+') - ptr++; - else if(*ptr == '-') - { - ptr++; - sign = -1; - } - // read the integer part - while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9') - integer = (integer * 10) + *(ptr++) - '0'; - - if(*ptr == '.') // read the decimals - { - ptr++; - while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9') - decimal += (*(ptr++) - '0') * (frac *= 0.1); - } - - if(*ptr == 'e' || *ptr == 'E') // read the exponent part - { - ptr++; - - // read the sign of the exponent - if(*ptr == '+') - ptr++; - else if(*ptr == '-') - { - ptr++; - expsign = -1; - } - - exponent = 0; - while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9') - { - exponent *= 10; - exponent += *ptr - '0'; - ptr++; - } - } - - number = integer + decimal; - number *= sign * pow(10.0, expsign * exponent); - - // skip the following space - if(*ptr == ' ') - ptr++; - - return ptr; -} - -void KSVGIconPainter::drawPath(const TQString &data, bool filled) -{ - if (!data.isEmpty()) - { - TQString value = data; - - TQMemArray<ArtBpath> vec; - int index = -1; - - double curx = 0.0, cury = 0.0, contrlx = 0.0, contrly = 0.0, xc, yc; - unsigned int lastCommand = 0; - - TQString _d = value.replace(",", " "); - _d = _d.simplifyWhiteSpace(); - const char *ptr = _d.latin1(); - const char *end = _d.latin1() + _d.length() + 1; - - double tox, toy, x1, y1, x2, y2, rx, ry, angle; - bool largeArc, sweep; - char command = *(ptr++); - - while(ptr < end) - { - if(*ptr == ' ') - ptr++; - - switch(command) - { - case 'm': - ptr = getCoord(ptr, tox); - ptr = getCoord(ptr, toy); - - if(index != -1 && lastCommand != 'z') - { - // Find last subpath - int find = -1; - for(int i = index; i >= 0; i--) - { - if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO) - { - find = i; - break; - } - } - - index++; - - if(vec.size() == (unsigned int) index) - vec.resize(index + 1); - - vec[index].code = (ArtPathcode)ART_END2; - vec[index].x3 = vec[find].x3; - vec[index].y3 = vec[find].y3; - } - - curx += tox; - cury += toy; - - index++; - - d->helper->ensureSpace(vec, index); - - vec[index].code = (index == 0) ? ART_MOVETO : ART_MOVETO_OPEN; - vec[index].x3 = curx; - vec[index].y3 = cury; - - lastCommand = 'm'; - break; - case 'M': - ptr = getCoord(ptr, tox); - ptr = getCoord(ptr, toy); - if(index != -1 && lastCommand != 'z') - { - // Find last subpath - int find = -1; - for(int i = index; i >= 0; i--) - { - if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO) - { - find = i; - break; - } - } - - index++; - - if(vec.size() == (unsigned int) index) - vec.resize(index + 1); - - vec[index].code = (ArtPathcode)ART_END2; - vec[index].x3 = vec[find].x3; - vec[index].y3 = vec[find].y3; - } - - curx = tox; - cury = toy; - - index++; - - d->helper->ensureSpace(vec, index); - - vec[index].code = (index == 0) ? ART_MOVETO : ART_MOVETO_OPEN; - vec[index].x3 = curx; - vec[index].y3 = cury; - - lastCommand = 'M'; - break; - case 'l': - ptr = getCoord(ptr, tox); - ptr = getCoord(ptr, toy); - - index++; - - d->helper->ensureSpace(vec, index); - - vec[index].code = ART_LINETO; - vec[index].x3 = curx + tox; - vec[index].y3 = cury + toy; - - curx += tox; - cury += toy; - - lastCommand = 'l'; - break; - case 'L': - ptr = getCoord(ptr, tox); - ptr = getCoord(ptr, toy); - - index++; - - d->helper->ensureSpace(vec, index); - - vec[index].code = ART_LINETO; - vec[index].x3 = tox; - vec[index].y3 = toy; - - curx = tox; - cury = toy; - - lastCommand = 'L'; - break; - case 'h': - ptr = getCoord(ptr, tox); - - index++; - - curx += tox; - - d->helper->ensureSpace(vec, index); - - vec[index].code = ART_LINETO; - vec[index].x3 = curx; - vec[index].y3 = cury; - - lastCommand = 'h'; - break; - case 'H': - ptr = getCoord(ptr, tox); - - index++; - - curx = tox; - - d->helper->ensureSpace(vec, index); - - vec[index].code = ART_LINETO; - vec[index].x3 = curx; - vec[index].y3 = cury; - - lastCommand = 'H'; - break; - case 'v': - ptr = getCoord(ptr, toy); - - index++; - - cury += toy; - - d->helper->ensureSpace(vec, index); - - vec[index].code = ART_LINETO; - vec[index].x3 = curx; - vec[index].y3 = cury; - - lastCommand = 'v'; - break; - case 'V': - ptr = getCoord(ptr, toy); - - index++; - - cury = toy; - - d->helper->ensureSpace(vec, index); - - vec[index].code = ART_LINETO; - vec[index].x3 = curx; - vec[index].y3 = cury; - - lastCommand = 'V'; - break; - case 'c': - ptr = getCoord(ptr, x1); - ptr = getCoord(ptr, y1); - ptr = getCoord(ptr, x2); - ptr = getCoord(ptr, y2); - ptr = getCoord(ptr, tox); - ptr = getCoord(ptr, toy); - - index++; - - d->helper->ensureSpace(vec, index); - - vec[index].code = ART_CURVETO; - vec[index].x1 = curx + x1; - vec[index].y1 = cury + y1; - vec[index].x2 = curx + x2; - vec[index].y2 = cury + y2; - vec[index].x3 = curx + tox; - vec[index].y3 = cury + toy; - - curx += tox; - cury += toy; - - contrlx = vec[index].x2; - contrly = vec[index].y2; - - lastCommand = 'c'; - break; - case 'C': - ptr = getCoord(ptr, x1); - ptr = getCoord(ptr, y1); - ptr = getCoord(ptr, x2); - ptr = getCoord(ptr, y2); - ptr = getCoord(ptr, tox); - ptr = getCoord(ptr, toy); - - index++; - - d->helper->ensureSpace(vec, index); - - vec[index].code = ART_CURVETO; - vec[index].x1 = x1; - vec[index].y1 = y1; - vec[index].x2 = x2; - vec[index].y2 = y2; - vec[index].x3 = tox; - vec[index].y3 = toy; - - curx = vec[index].x3; - cury = vec[index].y3; - contrlx = vec[index].x2; - contrly = vec[index].y2; - - lastCommand = 'C'; - break; - case 's': - ptr = getCoord(ptr, x2); - ptr = getCoord(ptr, y2); - ptr = getCoord(ptr, tox); - ptr = getCoord(ptr, toy); - - index++; - - d->helper->ensureSpace(vec, index); - - vec[index].code = ART_CURVETO; - vec[index].x1 = 2 * curx - contrlx; - vec[index].y1 = 2 * cury - contrly; - vec[index].x2 = curx + x2; - vec[index].y2 = cury + y2; - vec[index].x3 = curx + tox; - vec[index].y3 = cury + toy; - - curx += tox; - cury += toy; - - contrlx = vec[index].x2; - contrly = vec[index].y2; - - lastCommand = 's'; - break; - case 'S': - ptr = getCoord(ptr, x2); - ptr = getCoord(ptr, y2); - ptr = getCoord(ptr, tox); - ptr = getCoord(ptr, toy); - - index++; - - d->helper->ensureSpace(vec, index); - - vec[index].code = ART_CURVETO; - vec[index].x1 = 2 * curx - contrlx; - vec[index].y1 = 2 * cury - contrly; - vec[index].x2 = x2; - vec[index].y2 = y2; - vec[index].x3 = tox; - vec[index].y3 = toy; - - curx = vec[index].x3; - cury = vec[index].y3; - contrlx = vec[index].x2; - contrly = vec[index].y2; - - lastCommand = 'S'; - break; - case 'q': - ptr = getCoord(ptr, x1); - ptr = getCoord(ptr, y1); - ptr = getCoord(ptr, tox); - ptr = getCoord(ptr, toy); - - index++; - - d->helper->ensureSpace(vec, index); - - vec[index].code = ART_CURVETO; - vec[index].x1 = (curx + 2 * (x1 + curx)) * (1.0 / 3.0); - vec[index].y1 = (cury + 2 * (y1 + cury)) * (1.0 / 3.0); - vec[index].x2 = ((curx + tox) + 2 * (x1 + curx)) * (1.0 / 3.0); - vec[index].y2 = ((cury + toy) + 2 * (y1 + cury)) * (1.0 / 3.0); - vec[index].x3 = curx + tox; - vec[index].y3 = cury + toy; - - contrlx = curx + x1; - contrly = cury + y1; - curx += tox; - cury += toy; - - lastCommand = 'q'; - break; - case 'Q': - ptr = getCoord(ptr, x1); - ptr = getCoord(ptr, y1); - ptr = getCoord(ptr, tox); - ptr = getCoord(ptr, toy); - - index++; - - d->helper->ensureSpace(vec, index); - - // TODO : if this fails make it more like QuadraticRel - vec[index].code = ART_CURVETO; - vec[index].x1 = (curx + 2 * x1) * (1.0 / 3.0); - vec[index].y1 = (cury + 2 * y1) * (1.0 / 3.0); - vec[index].x2 = (tox + 2 * x1) * (1.0 / 3.0); - vec[index].y2 = (toy + 2 * y1) * (1.0 / 3.0); - vec[index].x3 = tox; - vec[index].y3 = toy; - - curx = vec[index].x3; - cury = vec[index].y3; - contrlx = vec[index].x2; - contrly = vec[index].y2; - - lastCommand = 'Q'; - break; - case 't': - ptr = getCoord(ptr, tox); - ptr = getCoord(ptr, toy); - - xc = 2 * curx - contrlx; - yc = 2 * cury - contrly; - - index++; - - d->helper->ensureSpace(vec, index); - - vec[index].code = ART_CURVETO; - vec[index].x1 = (curx + 2 * xc) * (1.0 / 3.0); - vec[index].y1 = (cury + 2 * yc) * (1.0 / 3.0); - vec[index].x2 = ((curx + tox) + 2 * xc) * (1.0 / 3.0); - vec[index].y2 = ((cury + toy) + 2 * yc) * (1.0 / 3.0); - - vec[index].x3 = curx + tox; - vec[index].y3 = cury + toy; - - curx += tox; - cury += toy; - contrlx = xc; - contrly = yc; - - lastCommand = 't'; - break; - case 'T': - ptr = getCoord(ptr, tox); - ptr = getCoord(ptr, toy); - - xc = 2 * curx - contrlx; - yc = 2 * cury - contrly; - - index++; - - d->helper->ensureSpace(vec, index); - - vec[index].code = ART_CURVETO; - vec[index].x1 = (curx + 2 * xc) * (1.0 / 3.0); - vec[index].y1 = (cury + 2 * yc) * (1.0 / 3.0); - vec[index].x2 = (tox + 2 * xc) * (1.0 / 3.0); - vec[index].y2 = (toy + 2 * yc) * (1.0 / 3.0); - vec[index].x3 = tox; - vec[index].y3 = toy; - - curx = tox; - cury = toy; - contrlx = xc; - contrly = yc; - - lastCommand = 'T'; - break; - case 'z': - case 'Z': - int find; - find = -1; - for(int i = index; i >= 0; i--) - { - if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO) - { - find = i; - break; - } - } - - if(find != -1) - { - if(vec[find].x3 != curx || vec[find].y3 != cury) - { - index++; - - d->helper->ensureSpace(vec, index); - - vec[index].code = ART_LINETO; - vec[index].x3 = vec[find].x3; - vec[index].y3 = vec[find].y3; - } - } - - // reset for next (sub)path - curx = vec[find].x3; - cury = vec[find].y3; - - lastCommand = 'z'; - break; - case 'a': - ptr = getCoord(ptr, rx); - ptr = getCoord(ptr, ry); - ptr = getCoord(ptr, angle); - ptr = getCoord(ptr, tox); - largeArc = tox == 1; - ptr = getCoord(ptr, tox); - sweep = tox == 1; - ptr = getCoord(ptr, tox); - ptr = getCoord(ptr, toy); - - // Spec: radii are nonnegative numbers - rx = fabs(rx); - ry = fabs(ry); - - d->helper->calculateArc(true, vec, index, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep); - - lastCommand = 'a'; - break; - case 'A': - ptr = getCoord(ptr, rx); - ptr = getCoord(ptr, ry); - ptr = getCoord(ptr, angle); - ptr = getCoord(ptr, tox); - largeArc = tox == 1; - ptr = getCoord(ptr, tox); - sweep = tox == 1; - ptr = getCoord(ptr, tox); - ptr = getCoord(ptr, toy); - - // Spec: radii are nonnegative numbers - rx = fabs(rx); - ry = fabs(ry); - - d->helper->calculateArc(false, vec, index, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep); - - lastCommand = 'A'; - break; - } - - if(*ptr == '+' || *ptr == '-' || (*ptr >= '0' && *ptr <= '9')) - { - // there are still coords in this command - if(command == 'M') - command = 'L'; - else if(command == 'm') - command = 'l'; - } - else - command = *(ptr++); - - // Detect reflection points - if(lastCommand != 'C' && lastCommand != 'c' && - lastCommand != 'S' && lastCommand != 's' && - lastCommand != 'Q' && lastCommand != 'q' && - lastCommand != 'T' && lastCommand != 't') - { - contrlx = curx; - contrly = cury; - } - } - - // Find last subpath - int find = -1; - for(int i = index; i >= 0; i--) - { - if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO) - { - find = i; - break; - } - } - - // Fix a problem where the .svg file used doubles as values... (sofico.svg) - if(curx != vec[find].x3 && cury != vec[find].y3) - { - if((int) curx == (int) vec[find].x3 && (int) cury == (int) vec[find].y3) - { - index++; - - if(vec.size() == (unsigned int) index) - vec.resize(index + 1); - - vec[index].code = ART_LINETO; - vec[index].x3 = vec[find].x3; - vec[index].y3 = vec[find].y3; - - curx = vec[find].x3; - cury = vec[find].y3; - } - } - - // Handle filled paths that are not closed explicitly - if(filled) - { - if((int) curx != (int) vec[find].x3 || (int) cury != (int) vec[find].y3) - { - index++; - - if(vec.size() == (unsigned int) index) - vec.resize(index + 1); - - vec[index].code = (ArtPathcode)ART_END2; - vec[index].x3 = vec[find].x3; - vec[index].y3 = vec[find].y3; - - curx = vec[find].x3; - cury = vec[find].y3; - } - } - - // Close - index++; - - if(vec.size() == (unsigned int) index) - vec.resize(index + 1); - - vec[index].code = ART_END; - - // There are pure-moveto paths which reference paint servers *bah* - // Do NOT render them - bool render = false; - for(int i = index; i >= 0; i--) - { - if(vec[i].code != ART_MOVETO_OPEN && vec[i].code != ART_MOVETO && !(vec[i].code >= ART_END)) - { - render = true; - break; - } - } - - if(render) - d->helper->drawBPath(vec.data()); - } -} - -void KSVGIconPainter::drawImage(double x, double y, TQImage &image) -{ - if(image.depth() != 32) - image = image.convertDepth(32); - - double affine[6]; - affine[0] = d->helper->m_tqworldMatrix->m11(); - affine[1] = d->helper->m_tqworldMatrix->m12(); - affine[2] = d->helper->m_tqworldMatrix->m21(); - affine[3] = d->helper->m_tqworldMatrix->m22(); - // use the world matrix to convert the coordinates - d->helper->m_tqworldMatrix->map(x, y, &affine[4], &affine[5]); - - d->helper->art_rgba_rgba_affine(d->helper->m_buffer, 0, 0, d->helper->m_width, d->helper->m_height, - d->helper->m_rowstride, image.bits(), image.width(), image.height(), - image.width() * 4, affine); -} - -TQColor KSVGIconPainter::parseColor(const TQString ¶m) -{ - if(param.stripWhiteSpace().startsWith("#")) - { - TQColor color; - color.setNamedColor(param.stripWhiteSpace()); - return color; - } - else if(param.stripWhiteSpace().startsWith("rgb(")) - { - TQString parse = param.stripWhiteSpace(); - TQStringList colors = TQStringList::split(',', parse); - TQString r = colors[0].right((colors[0].length() - 4)); - TQString g = colors[1]; - TQString b = colors[2].left((colors[2].length() - 1)); - - if(r.contains("%")) - { - r = r.left(r.length() - 1); - r = TQString::number(int((double(255 * r.toDouble()) / 100.0))); - } - - if(g.contains("%")) - { - g = g.left(g.length() - 1); - g = TQString::number(int((double(255 * g.toDouble()) / 100.0))); - } - - if(b.contains("%")) - { - b = b.left(b.length() - 1); - b = TQString::number(int((double(255 * b.toDouble()) / 100.0))); - } - - return TQColor(r.toInt(), g.toInt(), b.toInt()); - } - else - { - TQString rgbColor = param.stripWhiteSpace(); - - if(rgbColor == "aliceblue") - return TQColor(240, 248, 255); - else if(rgbColor == "antiquewhite") - return TQColor(250, 235, 215); - else if(rgbColor == "aqua") - return TQColor(0, 255, 255); - else if(rgbColor == "aquamarine") - return TQColor(127, 255, 212); - else if(rgbColor == "azure") - return TQColor(240, 255, 255); - else if(rgbColor == "beige") - return TQColor(245, 245, 220); - else if(rgbColor == "bisque") - return TQColor(255, 228, 196); - else if(rgbColor == "black") - return TQColor(0, 0, 0); - else if(rgbColor == "blanchedalmond") - return TQColor(255, 235, 205); - else if(rgbColor == "blue") - return TQColor(0, 0, 255); - else if(rgbColor == "blueviolet") - return TQColor(138, 43, 226); - else if(rgbColor == "brown") - return TQColor(165, 42, 42); - else if(rgbColor == "burlywood") - return TQColor(222, 184, 135); - else if(rgbColor == "cadetblue") - return TQColor(95, 158, 160); - else if(rgbColor == "chartreuse") - return TQColor(127, 255, 0); - else if(rgbColor == "chocolate") - return TQColor(210, 105, 30); - else if(rgbColor == "coral") - return TQColor(255, 127, 80); - else if(rgbColor == "cornflowerblue") - return TQColor(100, 149, 237); - else if(rgbColor == "cornsilk") - return TQColor(255, 248, 220); - else if(rgbColor == "crimson") - return TQColor(220, 20, 60); - else if(rgbColor == "cyan") - return TQColor(0, 255, 255); - else if(rgbColor == "darkblue") - return TQColor(0, 0, 139); - else if(rgbColor == "darkcyan") - return TQColor(0, 139, 139); - else if(rgbColor == "darkgoldenrod") - return TQColor(184, 134, 11); - else if(rgbColor == "darkgray") - return TQColor(169, 169, 169); - else if(rgbColor == "darkgrey") - return TQColor(169, 169, 169); - else if(rgbColor == "darkgreen") - return TQColor(0, 100, 0); - else if(rgbColor == "darkkhaki") - return TQColor(189, 183, 107); - else if(rgbColor == "darkmagenta") - return TQColor(139, 0, 139); - else if(rgbColor == "darkolivegreen") - return TQColor(85, 107, 47); - else if(rgbColor == "darkorange") - return TQColor(255, 140, 0); - else if(rgbColor == "darkorchid") - return TQColor(153, 50, 204); - else if(rgbColor == "darkred") - return TQColor(139, 0, 0); - else if(rgbColor == "darksalmon") - return TQColor(233, 150, 122); - else if(rgbColor == "darkseagreen") - return TQColor(143, 188, 143); - else if(rgbColor == "darkslateblue") - return TQColor(72, 61, 139); - else if(rgbColor == "darkslategray") - return TQColor(47, 79, 79); - else if(rgbColor == "darkslategrey") - return TQColor(47, 79, 79); - else if(rgbColor == "darkturquoise") - return TQColor(0, 206, 209); - else if(rgbColor == "darkviolet") - return TQColor(148, 0, 211); - else if(rgbColor == "deeppink") - return TQColor(255, 20, 147); - else if(rgbColor == "deepskyblue") - return TQColor(0, 191, 255); - else if(rgbColor == "dimgray") - return TQColor(105, 105, 105); - else if(rgbColor == "dimgrey") - return TQColor(105, 105, 105); - else if(rgbColor == "dodgerblue") - return TQColor(30, 144, 255); - else if(rgbColor == "firebrick") - return TQColor(178, 34, 34); - else if(rgbColor == "floralwhite") - return TQColor(255, 250, 240); - else if(rgbColor == "forestgreen") - return TQColor(34, 139, 34); - else if(rgbColor == "fuchsia") - return TQColor(255, 0, 255); - else if(rgbColor == "gainsboro") - return TQColor(220, 220, 220); - else if(rgbColor == "ghostwhite") - return TQColor(248, 248, 255); - else if(rgbColor == "gold") - return TQColor(255, 215, 0); - else if(rgbColor == "goldenrod") - return TQColor(218, 165, 32); - else if(rgbColor == "gray") - return TQColor(128, 128, 128); - else if(rgbColor == "grey") - return TQColor(128, 128, 128); - else if(rgbColor == "green") - return TQColor(0, 128, 0); - else if(rgbColor == "greenyellow") - return TQColor(173, 255, 47); - else if(rgbColor == "honeydew") - return TQColor(240, 255, 240); - else if(rgbColor == "hotpink") - return TQColor(255, 105, 180); - else if(rgbColor == "indianred") - return TQColor(205, 92, 92); - else if(rgbColor == "indigo") - return TQColor(75, 0, 130); - else if(rgbColor == "ivory") - return TQColor(255, 255, 240); - else if(rgbColor == "khaki") - return TQColor(240, 230, 140); - else if(rgbColor == "lavender") - return TQColor(230, 230, 250); - else if(rgbColor == "lavenderblush") - return TQColor(255, 240, 245); - else if(rgbColor == "lawngreen") - return TQColor(124, 252, 0); - else if(rgbColor == "lemonchiffon") - return TQColor(255, 250, 205); - else if(rgbColor == "lightblue") - return TQColor(173, 216, 230); - else if(rgbColor == "lightcoral") - return TQColor(240, 128, 128); - else if(rgbColor == "lightcyan") - return TQColor(224, 255, 255); - else if(rgbColor == "lightgoldenrodyellow") - return TQColor(250, 250, 210); - else if(rgbColor == "lightgray") - return TQColor(211, 211, 211); - else if(rgbColor == "lightgrey") - return TQColor(211, 211, 211); - else if(rgbColor == "lightgreen") - return TQColor(144, 238, 144); - else if(rgbColor == "lightpink") - return TQColor(255, 182, 193); - else if(rgbColor == "lightsalmon") - return TQColor(255, 160, 122); - else if(rgbColor == "lightseagreen") - return TQColor(32, 178, 170); - else if(rgbColor == "lightskyblue") - return TQColor(135, 206, 250); - else if(rgbColor == "lightslategray") - return TQColor(119, 136, 153); - else if(rgbColor == "lightslategrey") - return TQColor(119, 136, 153); - else if(rgbColor == "lightsteelblue") - return TQColor(176, 196, 222); - else if(rgbColor == "lightyellow") - return TQColor(255, 255, 224); - else if(rgbColor == "lime") - return TQColor(0, 255, 0); - else if(rgbColor == "limegreen") - return TQColor(50, 205, 50); - else if(rgbColor == "linen") - return TQColor(250, 240, 230); - else if(rgbColor == "magenta") - return TQColor(255, 0, 255); - else if(rgbColor == "maroon") - return TQColor(128, 0, 0); - else if(rgbColor == "mediumaquamarine") - return TQColor(102, 205, 170); - else if(rgbColor == "mediumblue") - return TQColor(0, 0, 205); - else if(rgbColor == "mediumorchid") - return TQColor(186, 85, 211); - else if(rgbColor == "mediumpurple") - return TQColor(147, 112, 219); - else if(rgbColor == "mediumseagreen") - return TQColor(60, 179, 113); - else if(rgbColor == "mediumslateblue") - return TQColor(123, 104, 238); - else if(rgbColor == "mediumspringgreen") - return TQColor(0, 250, 154); - else if(rgbColor == "mediumturquoise") - return TQColor(72, 209, 204); - else if(rgbColor == "mediumvioletred") - return TQColor(199, 21, 133); - else if(rgbColor == "midnightblue") - return TQColor(25, 25, 112); - else if(rgbColor == "mintcream") - return TQColor(245, 255, 250); - else if(rgbColor == "mistyrose") - return TQColor(255, 228, 225); - else if(rgbColor == "tqmoccasin") - return TQColor(255, 228, 181); - else if(rgbColor == "navajowhite") - return TQColor(255, 222, 173); - else if(rgbColor == "navy") - return TQColor(0, 0, 128); - else if(rgbColor == "oldlace") - return TQColor(253, 245, 230); - else if(rgbColor == "olive") - return TQColor(128, 128, 0); - else if(rgbColor == "olivedrab") - return TQColor(107, 142, 35); - else if(rgbColor == "orange") - return TQColor(255, 165, 0); - else if(rgbColor == "orangered") - return TQColor(255, 69, 0); - else if(rgbColor == "orchid") - return TQColor(218, 112, 214); - else if(rgbColor == "palegoldenrod") - return TQColor(238, 232, 170); - else if(rgbColor == "palegreen") - return TQColor(152, 251, 152); - else if(rgbColor == "paleturquoise") - return TQColor(175, 238, 238); - else if(rgbColor == "palevioletred") - return TQColor(219, 112, 147); - else if(rgbColor == "papayawhip") - return TQColor(255, 239, 213); - else if(rgbColor == "peachpuff") - return TQColor(255, 218, 185); - else if(rgbColor == "peru") - return TQColor(205, 133, 63); - else if(rgbColor == "pink") - return TQColor(255, 192, 203); - else if(rgbColor == "plum") - return TQColor(221, 160, 221); - else if(rgbColor == "powderblue") - return TQColor(176, 224, 230); - else if(rgbColor == "purple") - return TQColor(128, 0, 128); - else if(rgbColor == "red") - return TQColor(255, 0, 0); - else if(rgbColor == "rosybrown") - return TQColor(188, 143, 143); - else if(rgbColor == "royalblue") - return TQColor(65, 105, 225); - else if(rgbColor == "saddlebrown") - return TQColor(139, 69, 19); - else if(rgbColor == "salmon") - return TQColor(250, 128, 114); - else if(rgbColor == "sandybrown") - return TQColor(244, 164, 96); - else if(rgbColor == "seagreen") - return TQColor(46, 139, 87); - else if(rgbColor == "seashell") - return TQColor(255, 245, 238); - else if(rgbColor == "sienna") - return TQColor(160, 82, 45); - else if(rgbColor == "silver") - return TQColor(192, 192, 192); - else if(rgbColor == "skyblue") - return TQColor(135, 206, 235); - else if(rgbColor == "slateblue") - return TQColor(106, 90, 205); - else if(rgbColor == "slategray") - return TQColor(112, 128, 144); - else if(rgbColor == "slategrey") - return TQColor(112, 128, 144); - else if(rgbColor == "snow") - return TQColor(255, 250, 250); - else if(rgbColor == "springgreen") - return TQColor(0, 255, 127); - else if(rgbColor == "steelblue") - return TQColor(70, 130, 180); - else if(rgbColor == "tan") - return TQColor(210, 180, 140); - else if(rgbColor == "teal") - return TQColor(0, 128, 128); - else if(rgbColor == "thistle") - return TQColor(216, 191, 216); - else if(rgbColor == "tomato") - return TQColor(255, 99, 71); - else if(rgbColor == "turquoise") - return TQColor(64, 224, 208); - else if(rgbColor == "violet") - return TQColor(238, 130, 238); - else if(rgbColor == "wheat") - return TQColor(245, 222, 179); - else if(rgbColor == "white") - return TQColor(255, 255, 255); - else if(rgbColor == "whitesmoke") - return TQColor(245, 245, 245); - else if(rgbColor == "yellow") - return TQColor(255, 255, 0); - else if(rgbColor == "yellowgreen") - return TQColor(154, 205, 50); - } - - return TQColor(); -} - -double KSVGIconPainter::dpi() -{ - return 90.0; // TODO: make modal? -} - -double KSVGIconPainter::toPixel(const TQString &s, bool hmode) -{ - if(s.isEmpty()) - return 0.0; - - TQString check = s; - - double ret = 0.0; - - double value = 0; - const char *start = check.latin1(); - const char *end = getCoord(start, value); - - if(uint(end - start) < check.length()) - { - if(check.endsWith("px")) - ret = value; - else if(check.endsWith("cm")) - ret = (value / 2.54) * dpi(); - else if(check.endsWith("pc")) - ret = (value / 6.0) * dpi(); - else if(check.endsWith("mm")) - ret = (value / 25.4) * dpi(); - else if(check.endsWith("in")) - ret = value * dpi(); - else if(check.endsWith("pt")) - ret = (value / 72.0) * dpi(); - else if(check.endsWith("%")) - { - ret = value / 100.0; - - if(hmode) - ret *= d->drawWidth; - else - ret *= d->drawHeight; - } - else if(check.endsWith("em")) - { - ret = value * 10.0; // TODO make this depend on actual font size - } - } - else - ret = value; - - return ret; -} - -ArtGradientLinear *KSVGIconPainter::linearGradient(const TQString &id) -{ - return d->helper->m_linearGradientMap[id]; -} - -void KSVGIconPainter::addLinearGradient(const TQString &id, ArtGradientLinear *gradient) -{ - d->helper->m_linearGradientMap.insert(id, gradient); -} - -TQDomElement KSVGIconPainter::linearGradientElement(ArtGradientLinear *linear) -{ - return d->helper->m_linearGradientElementMap[linear]; -} - -void KSVGIconPainter::addLinearGradientElement(ArtGradientLinear *gradient, TQDomElement element) -{ - d->helper->m_linearGradientElementMap.insert(gradient, element); -} - -ArtGradientRadial *KSVGIconPainter::radialGradient(const TQString &id) -{ - return d->helper->m_radialGradientMap[id]; -} - -void KSVGIconPainter::addRadialGradient(const TQString &id, ArtGradientRadial *gradient) -{ - d->helper->m_radialGradientMap.insert(id, gradient); -} - -TQDomElement KSVGIconPainter::radialGradientElement(ArtGradientRadial *radial) -{ - return d->helper->m_radialGradientElementMap[radial]; -} - -void KSVGIconPainter::addRadialGradientElement(ArtGradientRadial *gradient, TQDomElement element) -{ - d->helper->m_radialGradientElementMap.insert(gradient, element); -} - -TQ_UINT32 KSVGIconPainter::toArtColor(const TQColor &color) -{ - return d->helper->toArtColor(color); -} - -TQWMatrix KSVGIconPainter::parseTransform(const TQString &transform) -{ - TQWMatrix result; - - // Split string for handling 1 transform statement at a time - TQStringList subtransforms = TQStringList::split(')', transform); - TQStringList::ConstIterator it = subtransforms.begin(); - TQStringList::ConstIterator end = subtransforms.end(); - for(; it != end; ++it) - { - TQStringList subtransform = TQStringList::split('(', (*it)); - - subtransform[0] = subtransform[0].stripWhiteSpace().lower(); - subtransform[1] = subtransform[1].simplifyWhiteSpace(); - TQRegExp reg("([-]?\\d*\\.?\\d+(?:e[-]?\\d+)?)"); - - int pos = 0; - TQStringList params; - - while(pos >= 0) - { - pos = reg.search(subtransform[1], pos); - if(pos != -1) - { - params += reg.cap(1); - pos += reg.matchedLength(); - } - } - - if(subtransform[0].startsWith(";") || subtransform[0].startsWith(",")) - subtransform[0] = subtransform[0].right(subtransform[0].length() - 1); - - if(subtransform[0] == "rotate") - { - if(params.count() == 3) - { - double x = params[1].toDouble(); - double y = params[2].toDouble(); - - result.translate(x, y); - result.rotate(params[0].toDouble()); - result.translate(-x, -y); - } - else - result.rotate(params[0].toDouble()); - } - else if(subtransform[0] == "translate") - { - if(params.count() == 2) - result.translate(params[0].toDouble(), params[1].toDouble()); - else // Spec : if only one param given, assume 2nd param to be 0 - result.translate(params[0].toDouble() , 0); - } - else if(subtransform[0] == "scale") - { - if(params.count() == 2) - result.scale(params[0].toDouble(), params[1].toDouble()); - else // Spec : if only one param given, assume uniform scaling - result.scale(params[0].toDouble(), params[0].toDouble()); - } - else if(subtransform[0] == "skewx") - result.shear(tan(params[0].toDouble() * deg2rad), 0.0F); - else if(subtransform[0] == "skewy") - result.shear(tan(params[0].toDouble() * deg2rad), 0.0F); - else if(subtransform[0] == "skewy") - result.shear(0.0F, tan(params[0].toDouble() * deg2rad)); - else if(subtransform[0] == "matrix") - { - if(params.count() >= 6) - { - result.setMatrix(params[0].toDouble(), params[1].toDouble(), params[2].toDouble(), params[3].toDouble(), params[4].toDouble(), params[5].toDouble()); - } - } - } - - return result; -} diff --git a/kdecore/svgicons/ksvgiconpainter.h b/kdecore/svgicons/ksvgiconpainter.h deleted file mode 100644 index 6b00d9d7c..000000000 --- a/kdecore/svgicons/ksvgiconpainter.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - Copyright (C) 2002 Nikolas Zimmermann <wildfox@kde.org> - This file is part of the KDE project - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - aint with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#ifndef KSVGIconPainter_H -#define KSVGIconPainter_H - -#include <libart_lgpl/art_render.h> -#include <libart_lgpl/art_render_gradient.h> - -class TQImage; -class TQColor; -class TQWMatrix; -class TQDomElement; -class TQPointArray; - -class KDECORE_EXPORT KSVGIconPainter -{ -public: - KSVGIconPainter(int width, int height); - ~KSVGIconPainter(); - - void setDrawWidth(int dwidth); - void setDrawHeight(int dheight); - - TQImage *image(); - - TQWMatrix *tqworldMatrix(); - - void finish(); - - void setUseFill(bool fill); - void setUseStroke(bool stroke); - - void setStrokeWidth(double width); - void setStrokeMiterLimit(const TQString &miter); - void setCapStyle(const TQString &cap); - void setJoinStyle(const TQString &join); - void setStrokeColor(const TQString &stroke); - void setFillColor(const TQString &fill); - void setFillRule(const TQString &fillRule); - void setOpacity(const TQString &opacity); - void setFillOpacity(const TQString &fillOpacity); - void setStrokeOpacity(const TQString &strokeOpacity); - void setStrokeDashOffset(const TQString &dashOffset); - void setStrokeDashArray(const TQString &dashes); - - void setWorldMatrix(TQWMatrix *tqworldMatrix); - void setClippingRect(int x, int y, int w, int h); - - void drawRectangle(double x, double y, double w, double h, double rx, double ry); - void drawEllipse(double cx, double cy, double rx, double ry); - void drawLine(double x1, double y1, double x2, double y2); - void drawPolyline(TQPointArray polyArray, int points = -1); - void drawPolygon(TQPointArray polyArray); - void drawPath(const TQString &data, bool fill); - void drawImage(double x, double y, TQImage &image); - - TQColor parseColor(const TQString ¶m); - TQ_UINT32 toArtColor(const TQColor &color); - TQ_UINT32 parseOpacity(const TQString &data); - - double toPixel(const TQString &s, bool hmode); - double dpi(); - - ArtGradientLinear *linearGradient(const TQString &id); - void addLinearGradient(const TQString &id, ArtGradientLinear *gradient); - - TQDomElement linearGradientElement(ArtGradientLinear *linear); - void addLinearGradientElement(ArtGradientLinear *gradient, TQDomElement element); - - ArtGradientRadial *radialGradient(const TQString &id); - void addRadialGradient(const TQString &id, ArtGradientRadial *gradient); - - TQDomElement radialGradientElement(ArtGradientRadial *radial); - void addRadialGradientElement(ArtGradientRadial *gradient, TQDomElement element); - - TQWMatrix parseTransform(const TQString &transform); - -private: - struct Private; - Private *d; -}; - -#endif |