summaryrefslogtreecommitdiffstats
path: root/lib/kopainter/kogradientmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kopainter/kogradientmanager.cpp')
-rw-r--r--lib/kopainter/kogradientmanager.cpp559
1 files changed, 559 insertions, 0 deletions
diff --git a/lib/kopainter/kogradientmanager.cpp b/lib/kopainter/kogradientmanager.cpp
new file mode 100644
index 000000000..c95a5671c
--- /dev/null
+++ b/lib/kopainter/kogradientmanager.cpp
@@ -0,0 +1,559 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 Tim Beaulen <tbscope@gmail.org>
+
+ 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 "kogradientmanager.h"
+
+#include "svgnamedcolors.h"
+
+#include <tqtextstream.h>
+#include <tqcstring.h>
+
+#include <kdebug.h>
+
+KoGradientManager::KoGradientManager()
+{
+}
+
+KoGradientManager::~KoGradientManager()
+{
+ // XXX: Should we delete the gradients here?
+}
+
+KoGradient* KoGradientManager::loadGradient(const TQString& filename)
+{
+ TQString strExt;
+ const int result=filename.findRev('.');
+ if (result>=0)
+ {
+ strExt=filename.mid(result).lower();
+ }
+
+ TQFile f(filename);
+
+ if(f.open(IO_ReadOnly))
+ {
+ if(strExt == ".ggr")
+ {
+ return loadChalkGradient(&f);
+ }
+ else if(strExt==".kgr")
+ {
+ return loadKarbonGradient(&f);
+ }
+ else if(strExt==".svg")
+ {
+ return loadSvgGradient(&f);
+ }
+ }
+
+ return 0;
+}
+
+KoGradient* KoGradientManager::loadKarbonGradient(TQFile* file)
+{
+ TQDomDocument doc;
+
+ if(!(doc.setContent(file)))
+ file->close();
+ else
+ {
+ TQDomElement e;
+ TQDomNode n = doc.documentElement().firstChild();
+
+ if(!n.isNull())
+ {
+ e = n.toElement();
+
+ if(!e.isNull())
+ if( e.tagName() == "GRADIENT" )
+ return parseKarbonGradient(e);
+ }
+ }
+
+ return 0;
+}
+
+KoGradient* KoGradientManager::loadChalkGradient(TQFile* file)
+{
+ KoGradient* grad = new KoGradient();
+
+ TQByteArray m_data = file->readAll();
+ file->close();
+
+ TQTextIStream fileContent(m_data);
+ fileContent.setEncoding(TQTextStream::UnicodeUTF8);
+
+ TQString header = fileContent.readLine();
+
+ if (header != "GIMP Gradient")
+ {
+ delete grad;
+ return 0;
+ }
+
+ TQString nameDefinition = fileContent.readLine();
+ TQString numSegmentsText;
+
+ if (nameDefinition.startsWith("Name: "))
+ {
+ TQString nameText = nameDefinition.right(nameDefinition.length() - 6);
+ numSegmentsText = fileContent.readLine();
+ }
+ else
+ {
+ // Older format without name.
+
+ numSegmentsText = nameDefinition;
+ }
+
+ int numSegments;
+ bool ok;
+
+ numSegments = numSegmentsText.toInt(&ok);
+
+ if (!ok || numSegments < 1)
+ {
+ return 0;
+ }
+
+ for (int i = 0; i < numSegments; i++)
+ {
+ KoColorStop *stop = new KoColorStop();
+
+ TQString segmentText = fileContent.readLine();
+ TQTextIStream segmentFields(&segmentText);
+
+ double leftOffset;
+ double middleOffset;
+ double rightOffset;
+
+ segmentFields >> leftOffset >> middleOffset >> rightOffset;
+
+ double leftRed;
+ double leftGreen;
+ double leftBlue;
+ double leftAlpha;
+
+ segmentFields >> leftRed >> leftGreen >> leftBlue >> leftAlpha;
+
+ double rightRed;
+ double rightGreen;
+ double rightBlue;
+ double rightAlpha;
+
+ segmentFields >> rightRed >> rightGreen >> rightBlue >> rightAlpha;
+
+ int interpolationType;
+ int colorInterpolationType;
+
+ segmentFields >> interpolationType >> colorInterpolationType;
+
+ middleOffset = (middleOffset - leftOffset) / (rightOffset - leftOffset);
+
+ stop->opacity = leftAlpha;
+ stop->midpoint = middleOffset;
+ stop->offset = leftOffset;
+
+ stop->color1 = leftRed;
+ stop->color2 = leftGreen;
+ stop->color3 = leftBlue;
+ stop->color4 = 0.0;
+ stop->colorType = colorInterpolationType;
+ stop->interpolation = interpolationType;
+
+ grad->colorStops.append(stop);
+
+ if(rightOffset == 1.0)
+ {
+ KoColorStop *lastStop = new KoColorStop();
+ lastStop->opacity = rightAlpha;
+ lastStop->midpoint = middleOffset;
+ lastStop->offset = rightOffset;
+ lastStop->color1 = rightRed;
+ lastStop->color2 = rightGreen;
+ lastStop->color3 = rightBlue;
+ lastStop->color4 = 0.0;
+ lastStop->colorType = colorInterpolationType;
+ lastStop->interpolation = interpolationType;
+ grad->colorStops.append(lastStop);
+ }
+ }
+
+ if (!grad->colorStops.isEmpty())
+ {
+ grad->originX = 0.0;
+ grad->originY = 1.0;
+ grad->vectorX = 0.0;
+ grad->vectorY = 0.0;
+ grad->focalpointX = 0.0;
+ grad->focalpointY = 0.0;
+ grad->gradientType = gradient_type_linear;
+ grad->gradientRepeatMethod = repeat_method_none;
+
+ return grad;
+ }
+ else
+ {
+ delete grad;
+ return 0;
+ }
+}
+
+KoGradient* KoGradientManager::loadSvgGradient(TQFile* file)
+{
+ TQDomDocument doc;
+
+ if(!(doc.setContent(file)))
+ file->close();
+ else
+ {
+ for( TQDomNode n = doc.documentElement().firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ TQDomElement e = n.toElement();
+ if( e.isNull() ) continue;
+
+ if( e.tagName() == "linearGradient" || e.tagName() == "radialGradient" )
+ return parseSvgGradient(e);
+ }
+ }
+
+ return 0;
+}
+
+KoGradient* KoGradientManager::parseKarbonGradient(const TQDomElement& element)
+{
+ KoGradient* grad = new KoGradient();
+
+ grad->originX = element.attribute("originX", "0.0").toDouble();
+ grad->originY = element.attribute("originY", "0.0").toDouble();
+ grad->focalpointX = element.attribute("focalX", "0.0").toDouble();
+ grad->focalpointY = element.attribute("focalY", "0.0").toDouble();
+ grad->vectorX = element.attribute("vectorX", "0.0").toDouble();
+ grad->vectorY = element.attribute("vectorY", "0.0").toDouble();
+ grad->gradientType = (KoGradientType)element.attribute("type", 0).toInt();
+ grad->gradientRepeatMethod = (KoGradientRepeatMethod)element.attribute("repeatMethod", 0).toInt();
+
+ grad->colorStops.clear();
+
+ // load stops
+ TQDomNodeList list = element.childNodes();
+ for( uint i = 0; i < list.count(); ++i )
+ {
+ if( list.item( i ).isElement() )
+ {
+ TQDomElement colorstop = list.item( i ).toElement();
+
+ if( colorstop.tagName() == "COLORSTOP" )
+ {
+ KoColorStop *stop = new KoColorStop();
+
+ TQDomElement e = colorstop.firstChild().toElement();
+
+ switch(e.attribute("colorSpace").toUShort())
+ {
+ case 1: // cmyk
+ stop->color1 = e.attribute( "v1", "0.0" ).toFloat();
+ stop->color2 = e.attribute( "v2", "0.0" ).toFloat();
+ stop->color3 = e.attribute( "v3", "0.0" ).toFloat();
+ stop->color4 = e.attribute( "v4", "0.0" ).toFloat();
+ stop->colorType = color_type_cmyk;
+ stop->interpolation = interpolation_linear;
+ break;
+ case 2: // hsv
+ stop->color1 = e.attribute( "v1", "0.0" ).toFloat();
+ stop->color2 = e.attribute( "v2", "0.0" ).toFloat();
+ stop->color3 = e.attribute( "v3", "0.0" ).toFloat();
+ stop->color4 = 0.0;
+ stop->colorType = color_type_hsv_cw;
+ stop->interpolation = interpolation_linear;
+ break;
+ case 3: // gray
+ stop->color1 = e.attribute( "v1", "0.0" ).toFloat();
+ stop->color2 = 0.0;
+ stop->color3 = 0.0;
+ stop->color4 = 0.0;
+ stop->colorType = color_type_gray;
+ stop->interpolation = interpolation_linear;
+ break;
+ default: // rgb
+ stop->color1 = e.attribute( "v1", "0.0" ).toFloat();
+ stop->color2 = e.attribute( "v2", "0.0" ).toFloat();
+ stop->color3 = e.attribute( "v3", "0.0" ).toFloat();
+ stop->color4 = 0.0;
+ stop->colorType = color_type_rgb;
+ stop->interpolation = interpolation_linear;
+ }
+
+ stop->opacity = e.attribute("opacity", "1.0").toFloat();
+
+ stop->offset = colorstop.attribute("ramppoint", "0.0").toFloat();
+ stop->midpoint = colorstop.attribute("midpoint", "0.5").toFloat();
+
+ grad->colorStops.append(stop);
+ }
+ }
+ }
+
+ return grad;
+}
+
+KoGradient* KoGradientManager::parseSvgGradient(const TQDomElement& element)
+{
+ KoGradient* grad = new KoGradient;
+
+ grad->colorStops.clear();
+ grad->gradientRepeatMethod = repeat_method_none;
+
+ /*TQString href = e.attribute( "xlink:href" ).mid( 1 );
+ if( !href.isEmpty() )
+ {
+ }*/
+
+ bool bbox = element.attribute( "gradientUnits" ) != "userSpaceOnUse";
+
+ if( element.tagName() == "linearGradient" )
+ {
+ if( bbox )
+ {
+ TQString s;
+
+ s = element.attribute( "x1", "0%" );
+ double xOrigin;
+ if( s.endsWith( "%" ) )
+ xOrigin = s.remove( '%' ).toDouble();
+ else
+ xOrigin = s.toDouble() * 100.0;
+
+ s = element.attribute( "y1", "0%" );
+ double yOrigin;
+ if( s.endsWith( "%" ) )
+ yOrigin = s.remove( '%' ).toDouble();
+ else
+ yOrigin = s.toDouble() * 100.0;
+
+ s = element.attribute( "x2", "100%" );
+ double xVector;
+ if( s.endsWith( "%" ) )
+ xVector = s.remove( '%' ).toDouble();
+ else
+ xVector = s.toDouble() * 100.0;
+
+ s = element.attribute( "y2", "0%" );
+ double yVector;
+ if( s.endsWith( "%" ) )
+ yVector = s.remove( '%' ).toDouble();
+ else
+ yVector = s.toDouble() * 100.0;
+
+ grad->originX = xOrigin;
+ grad->originY = yOrigin;
+ grad->vectorX = xVector;
+ grad->vectorY = yVector;
+ }
+ else
+ {
+ grad->originX = element.attribute( "x1" ).toDouble();
+ grad->originY = element.attribute( "y1" ).toDouble();
+ grad->vectorX = element.attribute( "x2" ).toDouble();
+ grad->vectorY = element.attribute( "y2" ).toDouble();
+ }
+ grad->gradientType = gradient_type_linear;
+ }
+ else
+ {
+ if( bbox )
+ {
+ TQString s;
+
+ s = element.attribute( "cx", "50%" );
+ double xOrigin;
+ if( s.endsWith( "%" ) )
+ xOrigin = s.remove( '%' ).toDouble();
+ else
+ xOrigin = s.toDouble() * 100.0;
+
+ s = element.attribute( "cy", "50%" );
+ double yOrigin;
+ if( s.endsWith( "%" ) )
+ yOrigin = s.remove( '%' ).toDouble();
+ else
+ yOrigin = s.toDouble() * 100.0;
+
+ s = element.attribute( "cx", "50%" );
+ double xVector;
+ if( s.endsWith( "%" ) )
+ xVector = s.remove( '%' ).toDouble();
+ else
+ xVector = s.toDouble() * 100.0;
+
+ s = element.attribute( "r", "50%" );
+ if( s.endsWith( "%" ) )
+ xVector += s.remove( '%' ).toDouble();
+ else
+ xVector += s.toDouble() * 100.0;
+
+ s = element.attribute( "cy", "50%" );
+ double yVector;
+ if( s.endsWith( "%" ) )
+ yVector = s.remove( '%' ).toDouble();
+ else
+ yVector = s.toDouble() * 100.0;
+
+ s = element.attribute( "fx", "50%" );
+ double xFocal;
+ if( s.endsWith( "%" ) )
+ xFocal = s.remove( '%' ).toDouble();
+ else
+ xFocal = s.toDouble() * 100.0;
+
+ s = element.attribute( "fy", "50%" );
+ double yFocal;
+ if( s.endsWith( "%" ) )
+ yFocal = s.remove( '%' ).toDouble();
+ else
+ yFocal = s.toDouble() * 100.0;
+
+ grad->originX = xOrigin;
+ grad->originY = yOrigin;
+ grad->vectorX = xVector;
+ grad->vectorY = yVector;
+ grad->focalpointX = xFocal;
+ grad->focalpointY = yFocal;
+ }
+ else
+ {
+ grad->originX = element.attribute( "cx" ).toDouble();
+ grad->originY = element.attribute( "cy" ).toDouble();
+ grad->vectorX = element.attribute( "cx" ).toDouble() + element.attribute( "r" ).toDouble();
+ grad->vectorY = element.attribute( "cy" ).toDouble();
+ grad->focalpointX = element.attribute( "fx" ).toDouble();
+ grad->focalpointY = element.attribute( "fy" ).toDouble();
+ }
+ grad->gradientType = gradient_type_radial;
+ }
+ // handle spread method
+ TQString spreadMethod = element.attribute( "spreadMethod" );
+ if( !spreadMethod.isEmpty() )
+ {
+ if( spreadMethod == "reflect" )
+ grad->gradientRepeatMethod = repeat_method_reflect;
+ else if( spreadMethod == "repeat" )
+ grad->gradientRepeatMethod = repeat_method_repeat;
+ }
+
+ for( TQDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ TQDomElement colorstop = n.toElement();
+ if( colorstop.tagName() == "stop" )
+ {
+ KoColorStop *stop = new KoColorStop();
+ TQColor c;
+ float off;
+ TQString temp = colorstop.attribute( "offset" );
+ if( temp.contains( '%' ) )
+ {
+ temp = temp.left( temp.length() - 1 );
+ off = temp.toFloat() / 100.0;
+ }
+ else
+ off = temp.toFloat();
+
+ if( !colorstop.attribute( "stop-color" ).isEmpty() )
+ parseSvgColor( c, colorstop.attribute( "stop-color" ) );
+ else
+ {
+ // try style attr
+ TQString style = colorstop.attribute( "style" ).simplifyWhiteSpace();
+ TQStringList substyles = TQStringList::split( ';', style );
+ for( TQStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it )
+ {
+ TQStringList substyle = TQStringList::split( ':', (*it) );
+ TQString command = substyle[0].stripWhiteSpace();
+ TQString params = substyle[1].stripWhiteSpace();
+ if( command == "stop-color" )
+ parseSvgColor( c, params );
+ if( command == "stop-opacity" )
+ stop->opacity = params.toDouble();
+ }
+
+ }
+ if( !colorstop.attribute( "stop-opacity" ).isEmpty() )
+ stop->opacity = colorstop.attribute( "stop-opacity" ).toDouble();
+
+ stop->offset = off;
+ stop->midpoint = 0.5;
+ stop->color1 = c.red() / 255.0;
+ stop->color2 = c.green() / 255.0;
+ stop->color3 = c.blue() / 255.0;
+ stop->color4 = 0.0;
+ stop->colorType = color_type_rgb;
+ stop->interpolation = interpolation_linear;
+ grad->colorStops.append(stop);
+ }
+ }
+
+ return grad;
+}
+
+void KoGradientManager::parseSvgColor(TQColor &color, const TQString &s)
+{
+ if( s.startsWith( "rgb(" ) )
+ {
+ TQString parse = s.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 ) ) );
+ }
+
+ color = TQColor( r.toInt(), g.toInt(), b.toInt() );
+ }
+ else
+ {
+ TQString rgbColor = s.stripWhiteSpace();
+ TQColor c;
+ if( rgbColor.startsWith( "#" ) )
+ c.setNamedColor( rgbColor );
+ else
+ {
+ int r, g, b;
+ svgNamedColorToRGB( rgbColor, r, g, b );
+ c = TQColor( r, g, b );
+ }
+ color = c;
+ }
+}
+