00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kogradientmanager.h"
00021
00022 #include "svgnamedcolors.h"
00023
00024 #include <QTextStream>
00025 #include <q3cstring.h>
00026
00027 #include <kdebug.h>
00028
00029 KoGradientManager::KoGradientManager()
00030 {
00031 }
00032
00033 KoGradientManager::~KoGradientManager()
00034 {
00035
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).toLower();
00045 }
00046
00047 QFile f(filename);
00048
00049 if(f.open(QIODevice::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 QTextStream fileContent(m_data, QIODevice::ReadOnly);
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
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
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:
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:
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:
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:
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
00324
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
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
00482 QString style = colorstop.attribute( "style" ).simplified();
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].trimmed();
00488 QString params = substyle[1].trimmed();
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.trimmed();
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.trimmed();
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