lib

kogradientmanager.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2005 Tim Beaulen <tbscope@gmail.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "kogradientmanager.h"
00021 
00022 #include "svgnamedcolors.h"
00023 
00024 #include <qtextstream.h>
00025 #include <qcstring.h>
00026 
00027 #include <kdebug.h>
00028 
00029 KoGradientManager::KoGradientManager()
00030 {
00031 }
00032 
00033 KoGradientManager::~KoGradientManager()
00034 {
00035     // XXX: Should we delete the gradients here?
00036 }
00037 
00038 KoGradient* KoGradientManager::loadGradient(const QString& filename)
00039 {
00040     QString strExt;
00041     const int result=filename.findRev('.');
00042     if (result>=0)
00043     {
00044         strExt=filename.mid(result).lower();
00045     }
00046 
00047     QFile f(filename);
00048 
00049     if(f.open(IO_ReadOnly))
00050     {
00051         if(strExt == ".ggr")
00052         {
00053             return loadKritaGradient(&f);
00054         }
00055         else if(strExt==".kgr")
00056         {
00057             return loadKarbonGradient(&f);
00058         }
00059         else if(strExt==".svg")
00060         {
00061             return loadSvgGradient(&f);
00062         }
00063     }
00064 
00065     return 0;
00066 }
00067 
00068 KoGradient* KoGradientManager::loadKarbonGradient(QFile* file)
00069 {
00070     QDomDocument doc;
00071         
00072     if(!(doc.setContent(file)))
00073         file->close();
00074     else
00075     {
00076         QDomElement e;
00077         QDomNode n = doc.documentElement().firstChild();
00078         
00079         if(!n.isNull())
00080         {
00081             e = n.toElement();
00082         
00083             if(!e.isNull())
00084                 if( e.tagName() == "GRADIENT" )
00085                     return parseKarbonGradient(e);
00086         }
00087     }
00088 
00089     return 0;
00090 }
00091 
00092 KoGradient* KoGradientManager::loadKritaGradient(QFile* file)
00093 {
00094     KoGradient* grad = new KoGradient();
00095     
00096     QByteArray m_data = file->readAll();
00097     file->close();
00098 
00099     QTextIStream fileContent(m_data);
00100     fileContent.setEncoding(QTextStream::UnicodeUTF8);
00101 
00102     QString header = fileContent.readLine();
00103 
00104     if (header != "GIMP Gradient") 
00105     {
00106         delete grad;
00107         return 0;
00108     }
00109 
00110     QString nameDefinition = fileContent.readLine();
00111     QString numSegmentsText;
00112 
00113     if (nameDefinition.startsWith("Name: ")) 
00114     {
00115         QString nameText = nameDefinition.right(nameDefinition.length() - 6);
00116         numSegmentsText = fileContent.readLine();
00117     }
00118     else 
00119     {
00120         // Older format without name.
00121 
00122         numSegmentsText = nameDefinition;
00123     }
00124 
00125     int numSegments;
00126     bool ok;
00127 
00128     numSegments = numSegmentsText.toInt(&ok);
00129 
00130     if (!ok || numSegments < 1) 
00131     {
00132         return 0;
00133     }
00134 
00135     for (int i = 0; i < numSegments; i++) 
00136     {
00137         KoColorStop *stop = new KoColorStop();
00138 
00139         QString segmentText = fileContent.readLine();
00140         QTextIStream segmentFields(&segmentText);
00141 
00142         double leftOffset;
00143         double middleOffset;
00144         double rightOffset;
00145 
00146         segmentFields >> leftOffset >> middleOffset >> rightOffset;
00147 
00148         double leftRed;
00149         double leftGreen;
00150         double leftBlue;
00151         double leftAlpha;
00152 
00153         segmentFields >> leftRed >> leftGreen >> leftBlue >> leftAlpha;
00154 
00155         double rightRed;
00156         double rightGreen;
00157         double rightBlue;
00158         double rightAlpha;
00159 
00160         segmentFields >> rightRed >> rightGreen >> rightBlue >> rightAlpha;
00161 
00162         int interpolationType;
00163         int colorInterpolationType;
00164 
00165         segmentFields >> interpolationType >> colorInterpolationType;
00166 
00167         middleOffset = (middleOffset - leftOffset) / (rightOffset - leftOffset);
00168 
00169         stop->opacity = leftAlpha;
00170         stop->midpoint = middleOffset;
00171         stop->offset = leftOffset;
00172 
00173         stop->color1 = leftRed;
00174         stop->color2 = leftGreen;
00175         stop->color3 = leftBlue;
00176         stop->color4 = 0.0;
00177         stop->colorType = colorInterpolationType;
00178         stop->interpolation = interpolationType; 
00179 
00180         grad->colorStops.append(stop);
00181 
00182         if(rightOffset == 1.0)
00183         {
00184             KoColorStop *lastStop = new KoColorStop();
00185             lastStop->opacity = rightAlpha;
00186             lastStop->midpoint = middleOffset;
00187             lastStop->offset = rightOffset;
00188             lastStop->color1 = rightRed;
00189             lastStop->color2 = rightGreen;
00190             lastStop->color3 = rightBlue;
00191             lastStop->color4 = 0.0;
00192             lastStop->colorType = colorInterpolationType;
00193             lastStop->interpolation = interpolationType; 
00194             grad->colorStops.append(lastStop);
00195         }
00196     }
00197 
00198     if (!grad->colorStops.isEmpty())
00199     {
00200         grad->originX = 0.0;
00201         grad->originY = 1.0;
00202         grad->vectorX = 0.0;
00203         grad->vectorY = 0.0;
00204         grad->focalpointX = 0.0;
00205         grad->focalpointY = 0.0;
00206         grad->gradientType = gradient_type_linear;
00207         grad->gradientRepeatMethod = repeat_method_none;
00208         
00209         return grad;
00210     }
00211     else 
00212     {
00213         delete grad;
00214         return 0;
00215     }
00216 }
00217 
00218 KoGradient* KoGradientManager::loadSvgGradient(QFile* file)
00219 {
00220     QDomDocument doc;
00221         
00222     if(!(doc.setContent(file)))
00223         file->close();
00224     else
00225     {
00226         for( QDomNode n = doc.documentElement().firstChild(); !n.isNull(); n = n.nextSibling() )
00227         {
00228             QDomElement e = n.toElement();
00229             if( e.isNull() ) continue;
00230         
00231             if( e.tagName() == "linearGradient" || e.tagName() == "radialGradient" )
00232                 return parseSvgGradient(e);
00233         }
00234     }
00235 
00236     return 0;
00237 }
00238 
00239 KoGradient* KoGradientManager::parseKarbonGradient(const QDomElement& element)
00240 {
00241     KoGradient* grad = new KoGradient();
00242 
00243     grad->originX = element.attribute("originX", "0.0").toDouble();
00244     grad->originY = element.attribute("originY", "0.0").toDouble();
00245     grad->focalpointX = element.attribute("focalX", "0.0").toDouble();
00246     grad->focalpointY = element.attribute("focalY", "0.0").toDouble();
00247     grad->vectorX = element.attribute("vectorX", "0.0").toDouble();
00248     grad->vectorY = element.attribute("vectorY", "0.0").toDouble();
00249     grad->gradientType = (KoGradientType)element.attribute("type", 0).toInt();
00250     grad->gradientRepeatMethod = (KoGradientRepeatMethod)element.attribute("repeatMethod", 0).toInt();
00251 
00252     grad->colorStops.clear();
00253 
00254     // load stops
00255     QDomNodeList list = element.childNodes();
00256     for( uint i = 0; i < list.count(); ++i )
00257     {
00258         if( list.item( i ).isElement() )
00259         {
00260             QDomElement colorstop = list.item( i ).toElement();
00261 
00262             if( colorstop.tagName() == "COLORSTOP" )
00263             {
00264                 KoColorStop *stop = new KoColorStop();
00265 
00266                 QDomElement e = colorstop.firstChild().toElement();
00267 
00268                 switch(e.attribute("colorSpace").toUShort())
00269                 {
00270                     case 1: // cmyk
00271                         stop->color1 = e.attribute( "v1", "0.0" ).toFloat();
00272                         stop->color2 = e.attribute( "v2", "0.0" ).toFloat();
00273                         stop->color3 = e.attribute( "v3", "0.0" ).toFloat();
00274                         stop->color4 = e.attribute( "v4", "0.0" ).toFloat();
00275                         stop->colorType = color_type_cmyk;
00276                         stop->interpolation = interpolation_linear;
00277                         break;
00278                     case 2: // hsv
00279                         stop->color1 = e.attribute( "v1", "0.0" ).toFloat();
00280                         stop->color2 = e.attribute( "v2", "0.0" ).toFloat();
00281                         stop->color3 = e.attribute( "v3", "0.0" ).toFloat();
00282                         stop->color4 = 0.0;
00283                         stop->colorType = color_type_hsv_cw;
00284                         stop->interpolation = interpolation_linear;
00285                         break;
00286                     case 3: // gray
00287                         stop->color1 = e.attribute( "v1", "0.0" ).toFloat();
00288                         stop->color2 = 0.0;
00289                         stop->color3 = 0.0;
00290                         stop->color4 = 0.0;
00291                         stop->colorType = color_type_gray;
00292                         stop->interpolation = interpolation_linear;
00293                         break;
00294                     default: // rgb
00295                         stop->color1 = e.attribute( "v1", "0.0" ).toFloat();
00296                         stop->color2 = e.attribute( "v2", "0.0" ).toFloat();
00297                         stop->color3 = e.attribute( "v3", "0.0" ).toFloat();
00298                         stop->color4 = 0.0;
00299                         stop->colorType = color_type_rgb;
00300                         stop->interpolation = interpolation_linear;
00301                 }
00302 
00303                 stop->opacity = e.attribute("opacity", "1.0").toFloat();
00304 
00305                 stop->offset = colorstop.attribute("ramppoint", "0.0").toFloat();
00306                 stop->midpoint = colorstop.attribute("midpoint", "0.5").toFloat();
00307 
00308                 grad->colorStops.append(stop);
00309             }
00310         }
00311     }
00312 
00313     return grad;
00314 }
00315 
00316 KoGradient* KoGradientManager::parseSvgGradient(const QDomElement& element)
00317 {
00318     KoGradient* grad = new KoGradient;
00319 
00320     grad->colorStops.clear();
00321     grad->gradientRepeatMethod = repeat_method_none;
00322 
00323     /*QString href = e.attribute( "xlink:href" ).mid( 1 );
00324     if( !href.isEmpty() )
00325     {
00326     }*/
00327 
00328     bool bbox = element.attribute( "gradientUnits" ) != "userSpaceOnUse";
00329 
00330     if( element.tagName() == "linearGradient" )
00331     {
00332         if( bbox )
00333         {
00334             QString s;
00335 
00336             s = element.attribute( "x1", "0%" );
00337             double xOrigin;
00338             if( s.endsWith( "%" ) )
00339                 xOrigin = s.remove( '%' ).toDouble();
00340             else
00341                 xOrigin = s.toDouble() * 100.0;
00342 
00343             s = element.attribute( "y1", "0%" );
00344             double yOrigin;
00345             if( s.endsWith( "%" ) )
00346                 yOrigin = s.remove( '%' ).toDouble();
00347             else
00348                 yOrigin = s.toDouble() * 100.0;
00349 
00350             s = element.attribute( "x2", "100%" );
00351             double xVector;
00352             if( s.endsWith( "%" ) )
00353                 xVector = s.remove( '%' ).toDouble();
00354             else
00355                 xVector = s.toDouble() * 100.0;
00356 
00357             s = element.attribute( "y2", "0%" );
00358             double yVector;
00359             if( s.endsWith( "%" ) )
00360                 yVector = s.remove( '%' ).toDouble();
00361             else
00362                 yVector = s.toDouble() * 100.0;
00363 
00364             grad->originX = xOrigin;
00365             grad->originY = yOrigin;
00366             grad->vectorX = xVector;
00367             grad->vectorY = yVector;
00368         }
00369         else
00370         {
00371             grad->originX = element.attribute( "x1" ).toDouble();
00372             grad->originY = element.attribute( "y1" ).toDouble();
00373             grad->vectorX = element.attribute( "x2" ).toDouble();
00374             grad->vectorY = element.attribute( "y2" ).toDouble();
00375         }
00376         grad->gradientType = gradient_type_linear;
00377     }
00378     else
00379     {
00380         if( bbox )
00381         {
00382             QString s;
00383 
00384             s = element.attribute( "cx", "50%" );
00385             double xOrigin;
00386             if( s.endsWith( "%" ) )
00387                 xOrigin = s.remove( '%' ).toDouble();
00388             else
00389                 xOrigin = s.toDouble() * 100.0;
00390 
00391             s = element.attribute( "cy", "50%" );
00392             double yOrigin;
00393             if( s.endsWith( "%" ) )
00394                 yOrigin = s.remove( '%' ).toDouble();
00395             else
00396                 yOrigin = s.toDouble() * 100.0;
00397 
00398             s = element.attribute( "cx", "50%" );
00399             double xVector;
00400             if( s.endsWith( "%" ) )
00401                 xVector = s.remove( '%' ).toDouble();
00402             else
00403                 xVector = s.toDouble() * 100.0;
00404 
00405             s = element.attribute( "r", "50%" );
00406             if( s.endsWith( "%" ) )
00407                 xVector += s.remove( '%' ).toDouble();
00408             else
00409                 xVector += s.toDouble() * 100.0;
00410 
00411             s = element.attribute( "cy", "50%" );
00412             double yVector;
00413             if( s.endsWith( "%" ) )
00414                 yVector = s.remove( '%' ).toDouble();
00415             else
00416                 yVector = s.toDouble() * 100.0;
00417 
00418             s = element.attribute( "fx", "50%" );
00419             double xFocal;
00420             if( s.endsWith( "%" ) )
00421                 xFocal = s.remove( '%' ).toDouble();
00422             else
00423                 xFocal = s.toDouble() * 100.0;
00424 
00425             s = element.attribute( "fy", "50%" );
00426             double yFocal;
00427             if( s.endsWith( "%" ) )
00428                 yFocal = s.remove( '%' ).toDouble();
00429             else
00430                 yFocal = s.toDouble() * 100.0;
00431 
00432             grad->originX = xOrigin;
00433             grad->originY = yOrigin;
00434             grad->vectorX = xVector;
00435             grad->vectorY = yVector;
00436             grad->focalpointX = xFocal;
00437             grad->focalpointY = yFocal;
00438         }
00439         else
00440         {
00441             grad->originX = element.attribute( "cx" ).toDouble();
00442             grad->originY = element.attribute( "cy" ).toDouble();
00443             grad->vectorX = element.attribute( "cx" ).toDouble() + element.attribute( "r" ).toDouble();
00444             grad->vectorY = element.attribute( "cy" ).toDouble();
00445             grad->focalpointX = element.attribute( "fx" ).toDouble();
00446             grad->focalpointY = element.attribute( "fy" ).toDouble();
00447         }
00448         grad->gradientType = gradient_type_radial;
00449     }
00450     // handle spread method
00451     QString spreadMethod = element.attribute( "spreadMethod" );
00452     if( !spreadMethod.isEmpty() )
00453     {
00454         if( spreadMethod == "reflect" )
00455             grad->gradientRepeatMethod = repeat_method_reflect;
00456         else if( spreadMethod == "repeat" )
00457             grad->gradientRepeatMethod = repeat_method_repeat;
00458     }
00459 
00460     for( QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() )
00461     {
00462         QDomElement colorstop = n.toElement();
00463         if( colorstop.tagName() == "stop" )
00464         {
00465             KoColorStop *stop = new KoColorStop();
00466             QColor c;
00467             float off;
00468             QString temp = colorstop.attribute( "offset" );
00469             if( temp.contains( '%' ) )
00470             {
00471                 temp = temp.left( temp.length() - 1 );
00472                 off = temp.toFloat() / 100.0;
00473             }
00474             else
00475                 off = temp.toFloat();
00476 
00477             if( !colorstop.attribute( "stop-color" ).isEmpty() )
00478                 parseSvgColor( c, colorstop.attribute( "stop-color" ) );
00479             else
00480             {
00481                 // try style attr
00482                 QString style = colorstop.attribute( "style" ).simplifyWhiteSpace();
00483                 QStringList substyles = QStringList::split( ';', style );
00484                 for( QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it )
00485                 {
00486                     QStringList substyle = QStringList::split( ':', (*it) );
00487                     QString command = substyle[0].stripWhiteSpace();
00488                     QString params  = substyle[1].stripWhiteSpace();
00489                     if( command == "stop-color" )
00490                         parseSvgColor( c, params );
00491                     if( command == "stop-opacity" )
00492                         stop->opacity = params.toDouble();
00493                 }
00494 
00495             }
00496             if( !colorstop.attribute( "stop-opacity" ).isEmpty() )
00497                 stop->opacity = colorstop.attribute( "stop-opacity" ).toDouble();
00498 
00499             stop->offset = off;
00500             stop->midpoint = 0.5;
00501             stop->color1 = c.red() / 255.0;
00502             stop->color2 = c.green() / 255.0;
00503             stop->color3 = c.blue() / 255.0;
00504             stop->color4 = 0.0;
00505             stop->colorType = color_type_rgb;
00506             stop->interpolation = interpolation_linear;
00507             grad->colorStops.append(stop);
00508         }
00509     }
00510 
00511     return grad;
00512 }
00513 
00514 void KoGradientManager::parseSvgColor(QColor &color, const QString &s)
00515 {
00516     if( s.startsWith( "rgb(" ) )
00517     {
00518         QString parse = s.stripWhiteSpace();
00519         QStringList colors = QStringList::split( ',', parse );
00520         QString r = colors[0].right( ( colors[0].length() - 4 ) );
00521         QString g = colors[1];
00522         QString b = colors[2].left( ( colors[2].length() - 1 ) );
00523 
00524         if( r.contains( "%" ) )
00525         {
00526             r = r.left( r.length() - 1 );
00527             r = QString::number( int( ( double( 255 * r.toDouble() ) / 100.0 ) ) );
00528         }
00529 
00530         if( g.contains( "%" ) )
00531         {
00532             g = g.left( g.length() - 1 );
00533             g = QString::number( int( ( double( 255 * g.toDouble() ) / 100.0 ) ) );
00534         }
00535 
00536         if( b.contains( "%" ) )
00537         {
00538             b = b.left( b.length() - 1 );
00539             b = QString::number( int( ( double( 255 * b.toDouble() ) / 100.0 ) ) );
00540         }
00541 
00542         color = QColor( r.toInt(), g.toInt(), b.toInt() );
00543     }
00544     else
00545     {
00546         QString rgbColor = s.stripWhiteSpace();
00547         QColor c;
00548         if( rgbColor.startsWith( "#" ) )
00549             c.setNamedColor( rgbColor );
00550         else
00551         {
00552             int r, g, b;
00553             svgNamedColorToRGB( rgbColor, r, g, b );
00554             c = QColor( r, g, b );
00555         }
00556         color = c;
00557     }
00558 }
00559     
KDE Home | KDE Accessibility Home | Description of Access Keys