00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include <qvaluevector.h>
00022
#include <qstringlist.h>
00023
#include <qwmatrix.h>
00024
#include <qregexp.h>
00025
#include <qimage.h>
00026
#include <qdict.h>
00027
#include <qmap.h>
00028
#include <qdom.h>
00029
00030
#include <math.h>
00031
00032
#include <kdebug.h>
00033
00034
#include <libart_lgpl/art_rgba.h>
00035
#include <libart_lgpl/art_bpath.h>
00036
#include <libart_lgpl/art_vpath.h>
00037
#include <libart_lgpl/art_vpath_dash.h>
00038
#include <libart_lgpl/art_affine.h>
00039
#include <libart_lgpl/art_render_svp.h>
00040
#include <libart_lgpl/art_svp.h>
00041
#include <libart_lgpl/art_svp_vpath.h>
00042
#include <libart_lgpl/art_svp_intersect.h>
00043
#include <libart_lgpl/art_svp_vpath_stroke.h>
00044
00045
#include "ksvgiconpainter.h"
00046
00047
#define ART_END2 10
00048
00049
const double deg2rad = 0.017453292519943295769;
00050
00051
class KSVGIconPainterHelper
00052 {
00053
public:
00054 KSVGIconPainterHelper(
int width,
int height, KSVGIconPainter *painter)
00055 {
00056 m_painter = painter;
00057
00058 m_clipSVP = 0;
00059
00060 m_fillColor = Qt::black;
00061
00062 m_useFill =
true;
00063 m_useStroke =
false;
00064
00065 m_useFillGradient =
false;
00066 m_useStrokeGradient =
false;
00067
00068 m_worldMatrix =
new QWMatrix();
00069
00070
00071 m_image =
new QImage(width, height, 32);
00072 m_image->setAlphaBuffer(
true);
00073
00074 m_strokeWidth = 1.0;
00075 m_strokeMiterLimit = 4;
00076 m_dashOffset = 0;
00077 m_dashes =
"";
00078
00079 m_opacity = 0xff;
00080 m_fillOpacity = 0xff;
00081 m_strokeOpacity = 0xff;
00082
00083 m_fillRule =
"nonzero";
00084
00085 m_width = width;
00086 m_height = height;
00087
00088 m_rowstride = m_width * 4;
00089
00090
00091 m_buffer = art_new(art_u8, m_rowstride * m_height);
00092 memset(m_buffer, 0, m_rowstride * m_height);
00093
00094 m_tempBuffer = 0;
00095 }
00096
00097 ~KSVGIconPainterHelper()
00098 {
00099
if(m_clipSVP)
00100 art_svp_free(m_clipSVP);
00101
00102 art_free(m_buffer);
00103
00104
delete m_image;
00105
delete m_worldMatrix;
00106
00107
for(
QMap<QString, ArtGradientLinear *>::Iterator it = m_linearGradientMap.begin(); it != m_linearGradientMap.end(); ++it)
00108 {
00109
delete it.data();
00110 }
00111
for(
QMap<QString, ArtGradientRadial *>::Iterator it = m_radialGradientMap.begin(); it != m_radialGradientMap.end(); ++it)
00112 {
00113
delete it.data();
00114 }
00115 }
00116
00117 ArtVpath *allocVPath(
int number)
00118 {
00119
return art_new(ArtVpath, number);
00120 }
00121
00122 ArtBpath *allocBPath(
int number)
00123 {
00124
return art_new(ArtBpath, number);
00125 }
00126
00127
void ensureSpace(
QMemArray<ArtBpath> &vec,
int index)
00128 {
00129
if(vec.size() == (
unsigned int) index)
00130 vec.resize(index + 1);
00131 }
00132
00133
void createBuffer()
00134 {
00135 m_tempBuffer = art_new(art_u8, m_rowstride * m_height);
00136 memset(m_tempBuffer, 0, m_rowstride * m_height);
00137
00138
00139 art_u8 *temp = m_buffer;
00140 m_buffer = m_tempBuffer;
00141 m_tempBuffer = temp;
00142 }
00143
00144
void mixBuffer(
int opacity)
00145 {
00146 art_u8 *srcPixel = m_buffer;
00147 art_u8 *dstPixel = m_tempBuffer;
00148
00149
for(
int y = 0; y < m_height; y++)
00150 {
00151
for(
int x = 0; x < m_width; x++)
00152 {
00153 art_u8 r, g, b, a;
00154
00155 a = srcPixel[4 * x + 3];
00156
00157
if(a)
00158 {
00159 r = srcPixel[4 * x];
00160 g = srcPixel[4 * x + 1];
00161 b = srcPixel[4 * x + 2];
00162
00163
int temp = a * opacity + 0x80;
00164 a = (temp + (temp >> 8)) >> 8;
00165 art_rgba_run_alpha(dstPixel + 4 * x, r, g, b, a, 1);
00166 }
00167 }
00168
00169 srcPixel += m_rowstride;
00170 dstPixel += m_rowstride;
00171 }
00172
00173
00174 art_u8 *temp = m_buffer;
00175 m_buffer = m_tempBuffer;
00176 m_tempBuffer = temp;
00177
00178 art_free(m_tempBuffer);
00179 m_tempBuffer = 0;
00180 }
00181
00182 Q_UINT32 toArtColor(
const QColor &color)
00183 {
00184
00185
QString tempName = color.name();
00186
const char *str = tempName.latin1();
00187
00188
int result = 0;
00189
00190
for(
int i = 1; str[i]; i++)
00191 {
00192
int hexval;
00193
if(str[i] >=
'0' && str[i] <=
'9')
00194 hexval = str[i] -
'0';
00195
else if (str[i] >=
'A' && str[i] <=
'F')
00196 hexval = str[i] -
'A' + 10;
00197
else if (str[i] >=
'a' && str[i] <=
'f')
00198 hexval = str[i] -
'a' + 10;
00199
else
00200
break;
00201
00202 result = (result << 4) + hexval;
00203 }
00204
00205
return result;
00206 }
00207
00208
void drawSVP(ArtSVP *svp, Q_UINT32 rgb,
int opacity)
00209 {
00210
if(!svp)
00211
return;
00212
00213 ArtRender *render = art_render_new(0, 0, m_width, m_height, m_buffer, m_rowstride, 3, 8, ART_ALPHA_SEPARATE, 0);
00214 art_render_svp(render, svp);
00215
00216 art_render_mask_solid(render, (opacity << 8) + opacity + (opacity >> 7));
00217
00218 ArtPixMaxDepth color[3];
00219 color[0] = ART_PIX_MAX_FROM_8(rgb >> 16);
00220 color[1] = ART_PIX_MAX_FROM_8((rgb >> 8) & 0xff);
00221 color[2] = ART_PIX_MAX_FROM_8(rgb & 0xff);
00222
00223 art_render_image_solid(render, color);
00224 art_render_invoke(render);
00225 }
00226
00227
void drawBPath(ArtBpath *bpath)
00228 {
00229
double affine[6];
00230 affine[0] = m_worldMatrix->m11();
00231 affine[1] = m_worldMatrix->m12();
00232 affine[2] = m_worldMatrix->m21();
00233 affine[3] = m_worldMatrix->m22();
00234 affine[4] = m_worldMatrix->dx();
00235 affine[5] = m_worldMatrix->dy();
00236
00237 ArtBpath *temp = art_bpath_affine_transform(bpath, affine);
00238 ArtVpath *vec = art_bez_path_to_vec(temp, 0.25);
00239 art_free(temp);
00240 drawPathInternal(vec, affine);
00241 }
00242
00243
void drawVPath(ArtVpath *vec)
00244 {
00245
double affine[6];
00246 affine[0] = m_worldMatrix->m11();
00247 affine[1] = m_worldMatrix->m12();
00248 affine[2] = m_worldMatrix->m21();
00249 affine[3] = m_worldMatrix->m22();
00250 affine[4] = m_worldMatrix->dx();
00251 affine[5] = m_worldMatrix->dy();
00252
00253 ArtVpath *temp = art_vpath_affine_transform(vec, affine);
00254 art_free(vec);
00255 vec = temp;
00256 drawPathInternal(vec, affine);
00257 }
00258
00259
void drawPathInternal(ArtVpath *vec,
double *affine)
00260 {
00261 ArtSVP *svp;
00262 ArtSVP *fillSVP = 0, *strokeSVP = 0;
00263
00264 Q_UINT32 fillColor = 0, strokeColor = 0;
00265
00266
00267 {
00268
int index = -1;
00269
QValueVector<int> toCorrect;
00270
while(vec[++index].code != ART_END)
00271 {
00272
if(vec[index].code == ART_END2)
00273 {
00274 vec[index].code = ART_LINETO;
00275 toCorrect.push_back(index);
00276 }
00277 }
00278
00279 fillColor = toArtColor(m_fillColor);
00280
00281 ArtSvpWriter *swr;
00282 ArtSVP *temp;
00283 temp = art_svp_from_vpath(vec);
00284
00285
if(m_fillRule ==
"evenodd")
00286 swr = art_svp_writer_rewind_new(ART_WIND_RULE_ODDEVEN);
00287
else
00288 swr = art_svp_writer_rewind_new(ART_WIND_RULE_NONZERO);
00289
00290 art_svp_intersector(temp, swr);
00291 svp = art_svp_writer_rewind_reap(swr);
00292
00293 fillSVP = svp;
00294
00295 art_svp_free(temp);
00296
00297
QValueVector<int>::iterator it;
00298
for(it = toCorrect.begin(); it != toCorrect.
end(); ++it)
00299 vec[(*it)].code = (ArtPathcode)ART_END2;
00300 }
00301
00302
00303
00304
if(m_strokeWidth <= 0)
00305 m_useStroke = m_useStrokeGradient =
false;
00306
00307
00308
if(m_useStroke || m_useStrokeGradient)
00309 {
00310 strokeColor = toArtColor(m_strokeColor);
00311
00312
double ratio = sqrt(pow(affine[0], 2) + pow(affine[3], 2)) / sqrt(2.0);
00313
double strokeWidth = m_strokeWidth * ratio;
00314
00315 ArtPathStrokeJoinType joinStyle = ART_PATH_STROKE_JOIN_MITER;
00316 ArtPathStrokeCapType capStyle = ART_PATH_STROKE_CAP_BUTT;
00317
00318
if(m_joinStyle ==
"miter")
00319 joinStyle = ART_PATH_STROKE_JOIN_MITER;
00320
else if(m_joinStyle ==
"round")
00321 joinStyle = ART_PATH_STROKE_JOIN_ROUND;
00322
else if(m_joinStyle ==
"bevel")
00323 joinStyle = ART_PATH_STROKE_JOIN_BEVEL;
00324
00325
if(m_capStyle ==
"butt")
00326 capStyle = ART_PATH_STROKE_CAP_BUTT;
00327
else if(m_capStyle ==
"round")
00328 capStyle = ART_PATH_STROKE_CAP_ROUND;
00329
else if(m_capStyle ==
"square")
00330 capStyle = ART_PATH_STROKE_CAP_SQUARE;
00331
00332
if(m_dashes.length() > 0)
00333 {
00334
QRegExp reg(
"[, ]");
00335
QStringList dashList = QStringList::split(reg, m_dashes);
00336
00337
double *dashes =
new double[dashList.count()];
00338
for(
unsigned int i = 0; i < dashList.count(); i++)
00339 dashes[i] = m_painter->toPixel(dashList[i],
true);
00340
00341 ArtVpathDash dash;
00342 dash.offset = m_dashOffset;
00343 dash.n_dash = dashList.count();
00344
00345 dash.dash = dashes;
00346
00347 ArtVpath *vec2 = art_vpath_dash(vec, &dash);
00348 art_free(vec);
00349
00350
delete dashes;
00351
00352 vec = vec2;
00353 }
00354
00355 svp = art_svp_vpath_stroke(vec, joinStyle, capStyle, strokeWidth, m_strokeMiterLimit, 0.25);
00356
00357 strokeSVP = svp;
00358 }
00359
00360
00361
int fillOpacity = static_cast<int>(m_fillOpacity);
00362
int strokeOpacity = static_cast<int>(m_strokeOpacity);
00363
int opacity = static_cast<int>(m_opacity);
00364
00365
00366
00367
if(fillOpacity == strokeOpacity && fillOpacity == opacity && !m_useFillGradient && !m_useStrokeGradient)
00368 opacity = 255;
00369
00370
if(fillOpacity != 255)
00371 {
00372
int temp = fillOpacity * opacity + 0x80;
00373 fillOpacity = (temp + (temp >> 8)) >> 8;
00374 }
00375
00376
if(strokeOpacity != 255)
00377 {
00378
int temp = strokeOpacity * opacity + 0x80;
00379 strokeOpacity = (temp + (temp >> 8)) >> 8;
00380 }
00381
00382
00383
bool tempDone =
false;
00384
if(m_opacity != 0xff)
00385 {
00386 tempDone =
true;
00387 createBuffer();
00388 }
00389
00390
00391
if(m_useFillGradient)
00392 applyGradient(fillSVP,
true);
00393
else if(m_useFill)
00394 drawSVP(fillSVP, fillColor, fillOpacity);
00395
00396
if(m_useStrokeGradient)
00397 applyGradient(strokeSVP,
false);
00398
else if(m_useStroke)
00399 drawSVP(strokeSVP, strokeColor, strokeOpacity);
00400
00401
00402
if(tempDone)
00403 mixBuffer(opacity);
00404
00405
if(m_clipSVP)
00406 {
00407 art_svp_free(m_clipSVP);
00408 m_clipSVP = 0;
00409 }
00410
00411
if(fillSVP)
00412 art_svp_free(fillSVP);
00413
00414
if(strokeSVP)
00415 art_svp_free(strokeSVP);
00416
00417
00418 m_opacity = 255.0;
00419 m_fillOpacity = 255.0;
00420 m_strokeOpacity = 255.0;
00421
00422 art_free(vec);
00423 }
00424
00425
void applyLinearGradient(ArtSVP *svp,
const QString &ref)
00426 {
00427 ArtGradientLinear *linear = m_linearGradientMap[ref];
00428
if(linear)
00429 {
00430
QDomElement element = m_linearGradientElementMap[linear];
00431
00432
double x1, y1, x2, y2;
00433
if(element.hasAttribute(
"x1"))
00434 x1 = m_painter->toPixel(element.attribute(
"x1"),
true);
00435
else
00436 x1 = 0;
00437
00438
if(element.hasAttribute(
"y1"))
00439 y1 = m_painter->toPixel(element.attribute(
"y1"),
false);
00440
else
00441 y1 = 0;
00442
00443
if(element.hasAttribute(
"x2"))
00444 x2 = m_painter->toPixel(element.attribute(
"x2"),
true);
00445
else
00446 x2 = 100;
00447
00448
if(element.hasAttribute(
"y2"))
00449 y2 = m_painter->toPixel(element.attribute(
"y2"),
false);
00450
else
00451 y2 = 0;
00452
00453
00454
QWMatrix m = m_painter->parseTransform(element.attribute(
"gradientTransform"));
00455 m.map(x1, y1, &x1, &y1);
00456 m.map(x2, y2, &x2, &y2);
00457
00458
double x1n = x1 * m_worldMatrix->m11() + y1 * m_worldMatrix->m21() + m_worldMatrix->dx();
00459
double y1n = x1 * m_worldMatrix->m12() + y1 * m_worldMatrix->m22() + m_worldMatrix->dy();
00460
double x2n = x2 * m_worldMatrix->m11() + y2 * m_worldMatrix->m21() + m_worldMatrix->dx();
00461
double y2n = x2 * m_worldMatrix->m12() + y2 * m_worldMatrix->m22() + m_worldMatrix->dy();
00462
00463
double dx = x2n - x1n;
00464
double dy = y2n - y1n;
00465
double scale = 1.0 / (dx * dx + dy * dy);
00466
00467 linear->a = dx * scale;
00468 linear->b = dy * scale;
00469 linear->c = -(x1n * linear->a + y1n * linear->b);
00470
00471 ArtRender *render = art_render_new(0, 0, m_width, m_height, m_buffer, m_rowstride, 3, 8, ART_ALPHA_SEPARATE, 0);
00472 art_render_svp(render, svp);
00473
00474 art_render_gradient_linear(render, linear, ART_FILTER_HYPER);
00475 art_render_invoke(render);
00476 }
00477 }
00478
00479
void applyRadialGradient(ArtSVP *svp,
const QString &ref)
00480 {
00481 ArtGradientRadial *radial = m_radialGradientMap[ref];
00482
if(radial)
00483 {
00484
QDomElement element = m_radialGradientElementMap[radial];
00485
00486
double cx, cy, r, fx, fy;
00487
if(element.hasAttribute(
"cx"))
00488 cx = m_painter->toPixel(element.attribute(
"cx"),
true);
00489
else
00490 cx = 50;
00491
00492
if(element.hasAttribute(
"cy"))
00493 cy = m_painter->toPixel(element.attribute(
"cy"),
false);
00494
else
00495 cy = 50;
00496
00497
if(element.hasAttribute(
"r"))
00498 r = m_painter->toPixel(element.attribute(
"r"),
true);
00499
else
00500 r = 50;
00501
00502
if(element.hasAttribute(
"fx"))
00503 fx = m_painter->toPixel(element.attribute(
"fx"),
false);
00504
else
00505 fx = cx;
00506
00507
if(element.hasAttribute(
"fy"))
00508 fy = m_painter->toPixel(element.attribute(
"fy"),
false);
00509
else
00510 fy = cy;
00511
00512 radial->affine[0] = m_worldMatrix->m11();
00513 radial->affine[1] = m_worldMatrix->m12();
00514 radial->affine[2] = m_worldMatrix->m21();
00515 radial->affine[3] = m_worldMatrix->m22();
00516 radial->affine[4] = m_worldMatrix->dx();
00517 radial->affine[5] = m_worldMatrix->dy();
00518
00519 radial->fx = (fx - cx) / r;
00520 radial->fy = (fy - cy) / r;
00521
00522
double aff1[6], aff2[6], gradTransform[6];
00523
00524
00525
QWMatrix m = m_painter->parseTransform(element.attribute(
"gradientTransform"));
00526
00527 gradTransform[0] = m.m11();
00528 gradTransform[1] = m.m12();
00529 gradTransform[2] = m.m21();
00530 gradTransform[3] = m.m22();
00531 gradTransform[4] = m.dx();
00532 gradTransform[5] = m.dy();
00533
00534 art_affine_scale(aff1, r, r);
00535 art_affine_translate(aff2, cx, cy);
00536
00537 art_affine_multiply(aff1, aff1, aff2);
00538 art_affine_multiply(aff1, aff1, gradTransform);
00539 art_affine_multiply(aff1, aff1, radial->affine);
00540 art_affine_invert(radial->affine, aff1);
00541
00542 ArtRender *render = art_render_new(0, 0, m_width, m_height, m_buffer, m_rowstride, 3, 8, ART_ALPHA_SEPARATE, 0);
00543 art_render_svp(render, svp);
00544
00545 art_render_gradient_radial(render, radial, ART_FILTER_HYPER);
00546 art_render_invoke(render);
00547 }
00548 }
00549
00550
void applyGradient(ArtSVP *svp,
const QString &ref)
00551 {
00552 ArtGradientLinear *linear = m_linearGradientMap[ref];
00553
if(linear)
00554 {
00555
QDomElement element = m_linearGradientElementMap[linear];
00556
00557
if(!element.hasAttribute(
"xlink:href"))
00558 {
00559 applyLinearGradient(svp, ref);
00560
return;
00561 }
00562
else
00563 {
00564 ArtGradientLinear *linear = m_linearGradientMap[element.attribute(
"xlink:href").mid(1)];
00565
QDomElement newElement = m_linearGradientElementMap[linear];
00566
00567
00568
QDict<QString> refattrs;
00569 refattrs.setAutoDelete(
true);
00570
00571
for(
unsigned int i = 0; i < newElement.attributes().length(); ++i)
00572 refattrs.insert(newElement.attributes().item(i).nodeName(),
new QString(newElement.attributes().item(i).nodeValue()));
00573
00574
00575
if(!newElement.isNull())
00576 {
00577
QDomNamedNodeMap attr = element.attributes();
00578
00579
for(
unsigned int i = 0; i < attr.length(); i++)
00580 {
00581
QString name = attr.item(i).nodeName();
00582
if(
name !=
"xlink:href" &&
name !=
"id")
00583 newElement.setAttribute(name, attr.item(i).nodeValue());
00584 }
00585 }
00586
00587 applyGradient(svp, element.attribute(
"xlink:href").mid(1));
00588
00589
00590
QDictIterator<QString> itr(refattrs);
00591
for(; itr.current(); ++itr)
00592 newElement.setAttribute(itr.currentKey(), *(itr.current()));
00593
00594
return;
00595 }
00596 }
00597
00598 ArtGradientRadial *radial = m_radialGradientMap[ref];
00599
if(radial)
00600 {
00601
QDomElement element = m_radialGradientElementMap[radial];
00602
00603
if(!element.hasAttribute(
"xlink:href"))
00604 {
00605 applyRadialGradient(svp, ref);
00606
return;
00607 }
00608
else
00609 {
00610 ArtGradientRadial *radial = m_radialGradientMap[element.attribute(
"xlink:href").mid(1)];
00611
QDomElement newElement = m_radialGradientElementMap[radial];
00612
00613
00614
QDict<QString> refattrs;
00615 refattrs.setAutoDelete(
true);
00616
00617
for(
unsigned int i = 0; i < newElement.attributes().length(); ++i)
00618 refattrs.insert(newElement.attributes().item(i).nodeName(),
new QString(newElement.attributes().item(i).nodeValue()));
00619
00620
00621
if(!newElement.isNull())
00622 {
00623
QDomNamedNodeMap attr = element.attributes();
00624
00625
for(
unsigned int i = 0; i < attr.length(); i++)
00626 {
00627
QString name = attr.item(i).nodeName();
00628
if(
name !=
"xlink:href" &&
name !=
"id")
00629 newElement.setAttribute(name, attr.item(i).nodeValue());
00630 }
00631 }
00632
00633 applyGradient(svp, element.attribute(
"xlink:href").mid(1));
00634
00635
00636
QDictIterator<QString> itr(refattrs);
00637
for(; itr.current(); ++itr)
00638 newElement.setAttribute(itr.currentKey(), *(itr.current()));
00639
00640
return;
00641 }
00642 }
00643 }
00644
00645
void applyGradient(ArtSVP *svp,
bool fill)
00646 {
00647
QString ref;
00648
00649
if(fill)
00650 {
00651 m_useFillGradient =
false;
00652 ref = m_fillGradientReference;
00653 }
00654
else
00655 {
00656 m_useStrokeGradient =
false;
00657 ref = m_strokeGradientReference;
00658 }
00659
00660 applyGradient(svp, ref);
00661 }
00662
00663
void blit()
00664 {
00665
unsigned char *line = m_buffer;
00666
00667
for(
int y = 0; y < m_height; y++)
00668 {
00669 QRgb *sl = reinterpret_cast<QRgb *>(m_image->scanLine(y));
00670
for(
int x = 0; x < m_width; x++)
00671 sl[x] = qRgba(line[x * 4], line[x * 4 + 1], line[x * 4 + 2], line[x * 4 + 3]);
00672
00673 line += m_rowstride;
00674 }
00675 }
00676
00677
void calculateArc(
bool relative,
QMemArray<ArtBpath> &vec,
int &index,
double &curx,
double &cury,
double angle,
double x,
double y,
double r1,
double r2,
bool largeArcFlag,
bool sweepFlag)
00678 {
00679
double sin_th, cos_th;
00680
double a00, a01, a10, a11;
00681
double x0, y0, x1, y1, xc, yc;
00682
double d, sfactor, sfactor_sq;
00683
double th0, th1, th_arc;
00684
int i, n_segs;
00685
00686 sin_th = sin(angle * (M_PI / 180.0));
00687 cos_th = cos(angle * (M_PI / 180.0));
00688
00689
double dx;
00690
00691
if(!relative)
00692 dx = (curx - x) / 2.0;
00693
else
00694 dx = -x / 2.0;
00695
00696
double dy;
00697
00698
if(!relative)
00699 dy = (cury - y) / 2.0;
00700
else
00701 dy = -y / 2.0;
00702
00703
double _x1 = cos_th * dx + sin_th * dy;
00704
double _y1 = -sin_th * dx + cos_th * dy;
00705
double Pr1 = r1 * r1;
00706
double Pr2 = r2 * r2;
00707
double Px = _x1 * _x1;
00708
double Py = _y1 * _y1;
00709
00710
00711
double check = Px / Pr1 + Py / Pr2;
00712
if(check > 1)
00713 {
00714 r1 = r1 * sqrt(check);
00715 r2 = r2 * sqrt(check);
00716 }
00717
00718 a00 = cos_th / r1;
00719 a01 = sin_th / r1;
00720 a10 = -sin_th / r2;
00721 a11 = cos_th / r2;
00722
00723 x0 = a00 * curx + a01 * cury;
00724 y0 = a10 * curx + a11 * cury;
00725
00726
if(!relative)
00727 x1 = a00 * x + a01 * y;
00728
else
00729 x1 = a00 * (curx + x) + a01 * (cury + y);
00730
00731
if(!relative)
00732 y1 = a10 * x + a11 * y;
00733
else
00734 y1 = a10 * (curx + x) + a11 * (cury + y);
00735
00736
00737
00738
00739
00740
00741
00742 d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
00743
00744 sfactor_sq = 1.0 / d - 0.25;
00745
00746
if(sfactor_sq < 0)
00747 sfactor_sq = 0;
00748
00749 sfactor = sqrt(sfactor_sq);
00750
00751
if(sweepFlag == largeArcFlag)
00752 sfactor = -sfactor;
00753
00754 xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
00755 yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
00756
00757
00758 th0 = atan2(y0 - yc, x0 - xc);
00759 th1 = atan2(y1 - yc, x1 - xc);
00760
00761 th_arc = th1 - th0;
00762
if(th_arc < 0 && sweepFlag)
00763 th_arc += 2 * M_PI;
00764
else if(th_arc > 0 && !sweepFlag)
00765 th_arc -= 2 * M_PI;
00766
00767 n_segs = (
int) (
int) ceil(fabs(th_arc / (M_PI * 0.5 + 0.001)));
00768
00769
for(i = 0; i < n_segs; i++)
00770 {
00771 index++;
00772
00773 ensureSpace(vec, index);
00774
00775 {
00776
double sin_th, cos_th;
00777
double a00, a01, a10, a11;
00778
double x1, y1, x2, y2, x3, y3;
00779
double t;
00780
double th_half;
00781
00782
double _th0 = th0 + i * th_arc / n_segs;
00783
double _th1 = th0 + (i + 1) * th_arc / n_segs;
00784
00785 sin_th = sin(angle * (M_PI / 180.0));
00786 cos_th = cos(angle * (M_PI / 180.0));
00787
00788
00789 a00 = cos_th * r1;
00790 a01 = -sin_th * r2;
00791 a10 = sin_th * r1;
00792 a11 = cos_th * r2;
00793
00794 th_half = 0.5 * (_th1 - _th0);
00795 t = (8.0 / 3.0) * sin(th_half * 0.5) * sin(th_half * 0.5) / sin(th_half);
00796 x1 = xc + cos(_th0) - t * sin(_th0);
00797 y1 = yc + sin(_th0) + t * cos(_th0);
00798 x3 = xc + cos(_th1);
00799 y3 = yc + sin(_th1);
00800 x2 = x3 + t * sin(_th1);
00801 y2 = y3 - t * cos(_th1);
00802
00803 ensureSpace(vec, index);
00804
00805 vec[index].code = ART_CURVETO;
00806 vec[index].x1 = a00 * x1 + a01 * y1;
00807 vec[index].y1 = a10 * x1 + a11 * y1;
00808 vec[index].x2 = a00 * x2 + a01 * y2;
00809 vec[index].y2 = a10 * x2 + a11 * y2;
00810 vec[index].x3 = a00 * x3 + a01 * y3;
00811 vec[index].y3 = a10 * x3 + a11 * y3;
00812 }
00813 }
00814
00815
if(!relative)
00816 curx = x;
00817
else
00818 curx += x;
00819
00820
if(!relative)
00821 cury = y;
00822
else
00823 cury += y;
00824 }
00825
00826
00827
static void art_vpath_render_bez(ArtVpath **p_vpath,
int *pn,
int *pn_max,
00828
double x0,
double y0,
00829
double x1,
double y1,
00830
double x2,
double y2,
00831
double x3,
double y3,
00832
double flatness)
00833 {
00834
double x3_0, y3_0, z3_0_dot, z1_dot, z2_dot;
00835
double z1_perp, z2_perp, max_perp_sq;
00836
00837
double x_m, y_m, xa1, ya1, xa2, ya2, xb1, yb1, xb2, yb2;
00838
00839 x3_0 = x3 - x0;
00840 y3_0 = y3 - y0;
00841
00842 z3_0_dot = x3_0 * x3_0 + y3_0 * y3_0;
00843
00844
if (z3_0_dot < 0.001)
00845
goto nosubdivide;
00846
00847 max_perp_sq = flatness * flatness * z3_0_dot;
00848
00849 z1_perp = (y1 - y0) * x3_0 - (x1 - x0) * y3_0;
00850
if (z1_perp * z1_perp > max_perp_sq)
00851
goto subdivide;
00852
00853 z2_perp = (y3 - y2) * x3_0 - (x3 - x2) * y3_0;
00854
if (z2_perp * z2_perp > max_perp_sq)
00855
goto subdivide;
00856
00857 z1_dot = (x1 - x0) * x3_0 + (y1 - y0) * y3_0;
00858
if (z1_dot < 0 && z1_dot * z1_dot > max_perp_sq)
00859
goto subdivide;
00860
00861 z2_dot = (x3 - x2) * x3_0 + (y3 - y2) * y3_0;
00862
if (z2_dot < 0 && z2_dot * z2_dot > max_perp_sq)
00863
goto subdivide;
00864
00865
if (z1_dot + z1_dot > z3_0_dot)
00866
goto subdivide;
00867
00868
if (z2_dot + z2_dot > z3_0_dot)
00869
goto subdivide;
00870
00871 nosubdivide:
00872 art_vpath_add_point (p_vpath, pn, pn_max, ART_LINETO, x3, y3);
00873
return;
00874
00875 subdivide:
00876 xa1 = (x0 + x1) * 0.5;
00877 ya1 = (y0 + y1) * 0.5;
00878 xa2 = (x0 + 2 * x1 + x2) * 0.25;
00879 ya2 = (y0 + 2 * y1 + y2) * 0.25;
00880 xb1 = (x1 + 2 * x2 + x3) * 0.25;
00881 yb1 = (y1 + 2 * y2 + y3) * 0.25;
00882 xb2 = (x2 + x3) * 0.5;
00883 yb2 = (y2 + y3) * 0.5;
00884 x_m = (xa2 + xb1) * 0.5;
00885 y_m = (ya2 + yb1) * 0.5;
00886 art_vpath_render_bez (p_vpath, pn, pn_max, x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, flatness);
00887 art_vpath_render_bez (p_vpath, pn, pn_max, x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, flatness);
00888 }
00889
00890 ArtVpath *art_bez_path_to_vec(
const ArtBpath *bez,
double flatness)
00891 {
00892 ArtVpath *vec;
00893
int vec_n, vec_n_max;
00894
int bez_index;
00895
double x, y;
00896
00897 vec_n = 0;
00898 vec_n_max = (1 << 4);
00899 vec = art_new (ArtVpath, vec_n_max);
00900
00901 x = 0;
00902 y = 0;
00903
00904 bez_index = 0;
00905
do
00906 {
00907
if(vec_n >= vec_n_max)
00908 art_expand (vec, ArtVpath, vec_n_max);
00909
00910
switch (bez[bez_index].code)
00911 {
00912
case ART_MOVETO_OPEN:
00913
case ART_MOVETO:
00914
case ART_LINETO:
00915 x = bez[bez_index].x3;
00916 y = bez[bez_index].y3;
00917 vec[vec_n].code = bez[bez_index].code;
00918 vec[vec_n].x = x;
00919 vec[vec_n].y = y;
00920 vec_n++;
00921
break;
00922
case ART_END:
00923 vec[vec_n].code = ART_END;
00924 vec[vec_n].x = 0;
00925 vec[vec_n].y = 0;
00926 vec_n++;
00927
break;
00928
case ART_END2:
00929 vec[vec_n].code = (ArtPathcode)ART_END2;
00930 vec[vec_n].x = bez[bez_index].x3;
00931 vec[vec_n].y = bez[bez_index].y3;
00932 vec_n++;
00933
break;
00934
case ART_CURVETO:
00935 art_vpath_render_bez (&vec, &vec_n, &vec_n_max,
00936 x, y,
00937 bez[bez_index].x1, bez[bez_index].y1,
00938 bez[bez_index].x2, bez[bez_index].y2,
00939 bez[bez_index].x3, bez[bez_index].y3,
00940 flatness);
00941 x = bez[bez_index].x3;
00942 y = bez[bez_index].y3;
00943
break;
00944 }
00945 }
00946
00947
while (bez[bez_index++].code != ART_END);
00948
return vec;
00949 }
00950
00951
static void art_rgb_affine_run(
int *p_x0,
int *p_x1,
int y,
00952
int src_width,
int src_height,
00953
const double affine[6])
00954 {
00955
int x0, x1;
00956
double z;
00957
double x_intercept;
00958
int xi;
00959
00960 x0 = *p_x0;
00961 x1 = *p_x1;
00962
00963
if (affine[0] > 1e-6)
00964 {
00965 z = affine[2] * (y + 0.5) + affine[4];
00966 x_intercept = -z / affine[0];
00967 xi = (
int) (
int) ceil (x_intercept + 1e-6 - 0.5);
00968
if (xi > x0)
00969 x0 = xi;
00970 x_intercept = (-z + src_width) / affine[0];
00971 xi = (
int) ceil (x_intercept - 1e-6 - 0.5);
00972
if (xi < x1)
00973 x1 = xi;
00974 }
00975
else if (affine[0] < -1e-6)
00976 {
00977 z = affine[2] * (y + 0.5) + affine[4];
00978 x_intercept = (-z + src_width) / affine[0];
00979 xi = (
int) ceil (x_intercept + 1e-6 - 0.5);
00980
if (xi > x0)
00981 x0 = xi;
00982 x_intercept = -z / affine[0];
00983 xi = (
int) ceil (x_intercept - 1e-6 - 0.5);
00984
if (xi < x1)
00985 x1 = xi;
00986 }
00987
else
00988 {
00989 z = affine[2] * (y + 0.5) + affine[4];
00990
if (z < 0 || z >= src_width)
00991 {
00992 *p_x1 = *p_x0;
00993
return;
00994 }
00995 }
00996
if (affine[1] > 1e-6)
00997 {
00998 z = affine[3] * (y + 0.5) + affine[5];
00999 x_intercept = -z / affine[1];
01000 xi = (
int) ceil (x_intercept + 1e-6 - 0.5);
01001
if (xi > x0)
01002 x0 = xi;
01003 x_intercept = (-z + src_height) / affine[1];
01004 xi = (
int) ceil (x_intercept - 1e-6 - 0.5);
01005
if (xi < x1)
01006 x1 = xi;
01007 }
01008
else if (affine[1] < -1e-6)
01009 {
01010 z = affine[3] * (y + 0.5) + affine[5];
01011 x_intercept = (-z + src_height) / affine[1];
01012 xi = (
int) ceil (x_intercept + 1e-6 - 0.5);
01013
if (xi > x0)
01014 x0 = xi;
01015 x_intercept = -z / affine[1];
01016 xi = (
int) ceil (x_intercept - 1e-6 - 0.5);
01017
if (xi < x1)
01018 x1 = xi;
01019 }
01020
else
01021 {
01022 z = affine[3] * (y + 0.5) + affine[5];
01023
if (z < 0 || z >= src_height)
01024 {
01025 *p_x1 = *p_x0;
01026
return;
01027 }
01028 }
01029
01030 *p_x0 = x0;
01031 *p_x1 = x1;
01032 }
01033
01034
01035
static void art_rgba_rgba_affine(art_u8 *dst,
01036
int x0,
int y0,
int x1,
int y1,
int dst_rowstride,
01037
const art_u8 *src,
01038
int src_width,
int src_height,
int src_rowstride,
01039
const double affine[6])
01040 {
01041
int x, y;
01042
double inv[6];
01043 art_u8 *dst_p, *dst_linestart;
01044
const art_u8 *src_p;
01045 ArtPoint pt, src_pt;
01046
int src_x, src_y;
01047
int alpha;
01048 art_u8 bg_r, bg_g, bg_b, bg_a, cr, cg, cb;
01049 art_u8 fg_r, fg_g, fg_b;
01050
int tmp;
01051
int run_x0, run_x1;
01052
01053 dst_linestart = dst;
01054 art_affine_invert (inv, affine);
01055
for (y = y0; y < y1; y++)
01056 {
01057 pt.y = y + 0.5;
01058 run_x0 = x0;
01059 run_x1 = x1;
01060 art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
01061 inv);
01062 dst_p = dst_linestart + (run_x0 - x0) * 4;
01063
for (x = run_x0; x < run_x1; x++)
01064 {
01065 pt.x = x + 0.5;
01066 art_affine_point (&src_pt, &pt, inv);
01067 src_x = (
int) floor (src_pt.x);
01068 src_y = (
int) floor (src_pt.y);
01069 src_p = src + (src_y * src_rowstride) + src_x * 4;
01070
if (src_x >= 0 && src_x < src_width &&
01071 src_y >= 0 && src_y < src_height)
01072 {
01073
01074 alpha = src_p[3];
01075
if (alpha)
01076 {
01077
if (alpha == 255)
01078 {
01079 dst_p[0] = src_p[0];
01080 dst_p[1] = src_p[1];
01081 dst_p[2] = src_p[2];
01082 dst_p[3] = 255;
01083 }
01084
else
01085 {
01086 bg_r = dst_p[0];
01087 bg_g = dst_p[1];
01088 bg_b = dst_p[2];
01089 bg_a = dst_p[3];
01090
01091 cr = (bg_r * bg_a + 0x80) >> 8;
01092 cg = (bg_g * bg_g + 0x80) >> 8;
01093 cb = (bg_b * bg_b + 0x80) >> 8;
01094
01095 tmp = (src_p[0] - bg_r) * alpha;
01096 fg_r = bg_r + ((tmp + (tmp >> 8) + 0x80) >> 8);
01097 tmp = (src_p[1] - bg_g) * alpha;
01098 fg_g = bg_g + ((tmp + (tmp >> 8) + 0x80) >> 8);
01099 tmp = (src_p[2] - bg_b) * alpha;
01100 fg_b = bg_b + ((tmp + (tmp >> 8) + 0x80) >> 8);
01101
01102 dst_p[0] = fg_r;
01103 dst_p[1] = fg_g;
01104 dst_p[2] = fg_b;
01105 dst_p[3] = bg_a + (((255 - bg_a) * alpha + 0x80) >> 8);
01106 }
01107 }
01108 }
else { dst_p[0] = 255; dst_p[1] = 0; dst_p[2] = 0; dst_p[3] = 255;}
01109 dst_p += 4;
01110 }
01111 dst_linestart += dst_rowstride;
01112 }
01113 }
01114
01115
private:
01116
friend class KSVGIconPainter;
01117 ArtSVP *m_clipSVP;
01118
01119
QImage *m_image;
01120
QWMatrix *m_worldMatrix;
01121
01122
QString m_fillRule;
01123
QString m_joinStyle;
01124
QString m_capStyle;
01125
01126
int m_strokeMiterLimit;
01127
01128
QString m_dashes;
01129
unsigned short m_dashOffset;
01130
01131
QColor m_fillColor;
01132
QColor m_strokeColor;
01133
01134 art_u8 *m_buffer;
01135 art_u8 *m_tempBuffer;
01136
01137
int m_width;
01138
int m_height;
01139
01140
int m_rowstride;
01141
01142
double m_opacity;
01143
double m_fillOpacity;
01144
double m_strokeOpacity;
01145
01146
bool m_useFill;
01147
bool m_useStroke;
01148
01149
bool m_useFillGradient;
01150
bool m_useStrokeGradient;
01151
01152
QString m_fillGradientReference;
01153
QString m_strokeGradientReference;
01154
01155
QMap<QString, ArtGradientLinear *> m_linearGradientMap;
01156
QMap<ArtGradientLinear *, QDomElement> m_linearGradientElementMap;
01157
01158
QMap<QString, ArtGradientRadial *> m_radialGradientMap;
01159
QMap<ArtGradientRadial *, QDomElement> m_radialGradientElementMap;
01160
01161 KSVGIconPainter *m_painter;
01162
01163
double m_strokeWidth;
01164 };
01165
01166
struct KSVGIconPainter::Private
01167 {
01168 KSVGIconPainterHelper *helper;
01169
01170
int drawWidth;
01171
int drawHeight;
01172 };
01173
01174 KSVGIconPainter::KSVGIconPainter(
int width,
int height) : d(new Private())
01175 {
01176 d->helper =
new KSVGIconPainterHelper(width, height,
this);
01177
01178 d->drawWidth = width;
01179 d->drawHeight = height;
01180 }
01181
01182 KSVGIconPainter::~KSVGIconPainter()
01183 {
01184
delete d->helper;
01185
delete d;
01186 }
01187
01188
void KSVGIconPainter::setDrawWidth(
int dwidth)
01189 {
01190 d->drawWidth = dwidth;
01191 }
01192
01193
void KSVGIconPainter::setDrawHeight(
int dheight)
01194 {
01195 d->drawHeight = dheight;
01196 }
01197
01198
void KSVGIconPainter::finish()
01199 {
01200 d->helper->blit();
01201 }
01202
01203
QImage *KSVGIconPainter::image()
01204 {
01205
return new QImage(*d->helper->m_image);
01206 }
01207
01208
QWMatrix *KSVGIconPainter::worldMatrix()
01209 {
01210
return d->helper->m_worldMatrix;
01211 }
01212
01213
void KSVGIconPainter::setWorldMatrix(
QWMatrix *matrix)
01214 {
01215
if(d->helper->m_worldMatrix)
01216
delete d->helper->m_worldMatrix;
01217
01218 d->helper->m_worldMatrix = matrix;
01219 }
01220
01221
void KSVGIconPainter::setStrokeWidth(
double width)
01222 {
01223 d->helper->m_strokeWidth = width;
01224 }
01225
01226
void KSVGIconPainter::setStrokeMiterLimit(
const QString &miter)
01227 {
01228 d->helper->m_strokeMiterLimit = miter.toInt();
01229 }
01230
01231
void KSVGIconPainter::setStrokeDashOffset(
const QString &dashOffset)
01232 {
01233 d->helper->m_dashOffset = dashOffset.toUInt();
01234 }
01235
01236
void KSVGIconPainter::setStrokeDashArray(
const QString &dashes)
01237 {
01238 d->helper->m_dashes = dashes;
01239 }
01240
01241
void KSVGIconPainter::setCapStyle(
const QString &cap)
01242 {
01243 d->helper->m_capStyle = cap;
01244 }
01245
01246
void KSVGIconPainter::setJoinStyle(
const QString &join)
01247 {
01248 d->helper->m_joinStyle = join;
01249 }
01250
01251
void KSVGIconPainter::setStrokeColor(
const QString &stroke)
01252 {
01253
if(stroke.startsWith(
"url"))
01254 {
01255 d->helper->m_useStroke =
false;
01256 d->helper->m_useStrokeGradient =
true;
01257
01258
QString url = stroke;
01259
01260
unsigned int start = url.find(
"#") + 1;
01261
unsigned int end = url.findRev(
")");
01262
01263 d->helper->m_strokeGradientReference = url.mid(start, end - start);
01264 }
01265
else
01266 {
01267 d->helper->m_strokeColor = parseColor(stroke);
01268
01269 d->helper->m_useStrokeGradient =
false;
01270 d->helper->m_strokeGradientReference = QString::null;
01271
01272
if(stroke.stripWhiteSpace().lower() !=
"none")
01273 setUseStroke(
true);
01274
else
01275 setUseStroke(
false);
01276 }
01277 }
01278
01279
void KSVGIconPainter::setFillColor(
const QString &fill)
01280 {
01281
if(fill.startsWith(
"url"))
01282 {
01283 d->helper->m_useFill =
false;
01284 d->helper->m_useFillGradient =
true;
01285
01286
QString url = fill;
01287
01288
unsigned int start = url.find(
"#") + 1;
01289
unsigned int end = url.findRev(
")");
01290
01291 d->helper->m_fillGradientReference = url.mid(start, end - start);
01292 }
01293
else
01294 {
01295 d->helper->m_fillColor = parseColor(fill);
01296
01297 d->helper->m_useFillGradient =
false;
01298 d->helper->m_fillGradientReference = QString::null;
01299
01300
if(fill.stripWhiteSpace().lower() !=
"none")
01301 setUseFill(
true);
01302
else
01303 setUseFill(
false);
01304 }
01305 }
01306
01307
void KSVGIconPainter::setFillRule(
const QString &fillRule)
01308 {
01309 d->helper->m_fillRule = fillRule;
01310 }
01311
01312 Q_UINT32 KSVGIconPainter::parseOpacity(
const QString &data)
01313 {
01314
int opacity = 255;
01315
01316
if(!data.isEmpty())
01317 {
01318
double temp;
01319
01320
if(data.contains(
"%"))
01321 {
01322
QString tempString = data.left(data.length() - 1);
01323 temp = double(255 * tempString.toDouble()) / 100.0;
01324 }
01325
else
01326 temp = data.toDouble();
01327
01328 opacity = (
int) floor(temp * 255 + 0.5);
01329 }
01330
01331
return opacity;
01332 }
01333
01334
void KSVGIconPainter::setFillOpacity(
const QString &fillOpacity)
01335 {
01336 d->helper->m_fillOpacity = parseOpacity(fillOpacity);
01337 }
01338
01339
void KSVGIconPainter::setStrokeOpacity(
const QString &strokeOpacity)
01340 {
01341 d->helper->m_strokeOpacity = parseOpacity(strokeOpacity);
01342 }
01343
01344
void KSVGIconPainter::setOpacity(
const QString &opacity)
01345 {
01346 d->helper->m_opacity = parseOpacity(opacity);
01347 }
01348
01349
void KSVGIconPainter::setUseFill(
bool fill)
01350 {
01351 d->helper->m_useFill = fill;
01352 }
01353
01354
void KSVGIconPainter::setUseStroke(
bool stroke)
01355 {
01356 d->helper->m_useStroke = stroke;
01357 }
01358
01359
void KSVGIconPainter::setClippingRect(
int x,
int y,
int w,
int h)
01360 {
01361 ArtVpath *vec = d->helper->allocVPath(6);
01362
01363 vec[0].code = ART_MOVETO;
01364 vec[0].x = x;
01365 vec[0].y = y;
01366
01367 vec[1].code = ART_LINETO;
01368 vec[1].x = x;
01369 vec[1].y = y + h;
01370
01371 vec[2].code = ART_LINETO;
01372 vec[2].x = x + w;
01373 vec[2].y = y + h;
01374
01375 vec[3].code = ART_LINETO;
01376 vec[3].x = x + w;
01377 vec[3].y = y;
01378
01379 vec[4].code = ART_LINETO;
01380 vec[4].x = x;
01381 vec[4].y = y;
01382
01383 vec[5].code = ART_END;
01384
01385
if(d->helper->m_clipSVP)
01386 art_svp_free(d->helper->m_clipSVP);
01387
01388 d->helper->m_clipSVP = art_svp_from_vpath(vec);
01389
01390 art_free(vec);
01391 }
01392
01393
void KSVGIconPainter::drawRectangle(
double x,
double y,
double w,
double h,
double rx,
double ry)
01394 {
01395
if((
int) rx != 0 && (
int) ry != 0)
01396 {
01397 ArtVpath *res;
01398 ArtBpath *vec = d->helper->allocBPath(10);
01399
01400
int i = 0;
01401
01402
if(rx > w / 2)
01403 rx = w / 2;
01404
01405
if(ry > h / 2)
01406 ry = h / 2;
01407
01408 vec[i].code = ART_MOVETO_OPEN;
01409 vec[i].x3 = x + rx;
01410 vec[i].y3 = y;
01411
01412 i++;
01413
01414 vec[i].code = ART_CURVETO;
01415 vec[i].x1 = x + rx * (1 - 0.552);
01416 vec[i].y1 = y;
01417 vec[i].x2 = x;
01418 vec[i].y2 = y + ry * (1 - 0.552);
01419 vec[i].x3 = x;
01420 vec[i].y3 = y + ry;
01421
01422 i++;
01423
01424
if(ry < h / 2)
01425 {
01426 vec[i].code = ART_LINETO;
01427 vec[i].x3 = x;
01428 vec[i].y3 = y + h - ry;
01429
01430 i++;
01431 }
01432
01433 vec[i].code = ART_CURVETO;
01434 vec[i].x1 = x;
01435 vec[i].y1 = y + h - ry * (1 - 0.552);
01436 vec[i].x2 = x + rx * (1 - 0.552);
01437 vec[i].y2 = y + h;
01438 vec[i].x3 = x + rx;
01439 vec[i].y3 = y + h;
01440
01441 i++;
01442
01443
if(rx < w / 2)
01444 {
01445 vec[i].code = ART_LINETO;
01446 vec[i].x3 = x + w - rx;
01447 vec[i].y3 = y + h;
01448
01449 i++;
01450 }
01451
01452 vec[i].code = ART_CURVETO;
01453 vec[i].x1 = x + w - rx * (1 - 0.552);
01454 vec[i].y1 = y + h;
01455 vec[i].x2 = x + w;
01456 vec[i].y2 = y + h - ry * (1 - 0.552);
01457 vec[i].x3 = x + w;
01458
01459 vec[i].y3 = y + h - ry;
01460
01461 i++;
01462
01463
if(ry < h / 2)
01464 {
01465 vec[i].code = ART_LINETO;
01466 vec[i].x3 = x + w;
01467 vec[i].y3 = y + ry;
01468
01469 i++;
01470 }
01471
01472 vec[i].code = ART_CURVETO;
01473 vec[i].x1 = x + w;
01474 vec[i].y1 = y + ry * (1 - 0.552);
01475 vec[i].x2 = x + w - rx * (1 - 0.552);
01476 vec[i].y2 = y;
01477 vec[i].x3 = x + w - rx;
01478 vec[i].y3 = y;
01479
01480 i++;
01481
01482
if(rx < w / 2)
01483 {
01484 vec[i].code = ART_LINETO;
01485 vec[i].x3 = x + rx;
01486 vec[i].y3 = y;
01487
01488 i++;
01489 }
01490
01491 vec[i].code = ART_END;
01492
01493 res = d->helper->art_bez_path_to_vec(vec, 0.25);
01494 art_free(vec);
01495 d->helper->drawVPath(res);
01496 }
01497
else
01498 {
01499 ArtVpath *vec = d->helper->allocVPath(6);
01500
01501 vec[0].code = ART_MOVETO;
01502 vec[0].x = x;
01503 vec[0].y = y;
01504
01505 vec[1].code = ART_LINETO;
01506 vec[1].x = x;
01507 vec[1].y = y + h;
01508
01509 vec[2].code = ART_LINETO;
01510 vec[2].x = x + w;
01511 vec[2].y = y + h;
01512
01513 vec[3].code = ART_LINETO;
01514 vec[3].x = x + w;
01515 vec[3].y = y;
01516
01517 vec[4].code = ART_LINETO;
01518 vec[4].x = x;
01519 vec[4].y = y;
01520
01521 vec[5].code = ART_END;
01522
01523 d->helper->drawVPath(vec);
01524 }
01525 }
01526
01527
void KSVGIconPainter::drawEllipse(
double cx,
double cy,
double rx,
double ry)
01528 {
01529 ArtBpath *temp;
01530
01531 temp = d->helper->allocBPath(6);
01532
01533
double x1, y1, x2, y2, x3, y3;
01534
double len = 0.55228474983079356;
01535
double cos4[] = {1.0, 0.0, -1.0, 0.0, 1.0};
01536
double sin4[] = {0.0, 1.0, 0.0, -1.0, 0.0};
01537
int i = 0;
01538
01539 temp[i].code = ART_MOVETO;
01540 temp[i].x3 = cx + rx;
01541 temp[i].y3 = cy;
01542
01543 i++;
01544
01545
while(i < 5)
01546 {
01547 x1 = cos4[i-1] + len * cos4[i];
01548 y1 = sin4[i-1] + len * sin4[i];
01549 x2 = cos4[i] + len * cos4[i-1];
01550 y2 = sin4[i] + len * sin4[i-1];
01551 x3 = cos4[i];
01552 y3 = sin4[i];
01553
01554 temp[i].code = ART_CURVETO;
01555 temp[i].x1 = cx + x1 * rx;
01556 temp[i].y1 = cy + y1 * ry;
01557 temp[i].x2 = cx + x2 * rx;
01558 temp[i].y2 = cy + y2 * ry;
01559 temp[i].x3 = cx + x3 * rx;
01560 temp[i].y3 = cy + y3 * ry;
01561
01562 i++;
01563 }
01564
01565 temp[i].code = ART_END;
01566
01567 d->helper->drawBPath(temp);
01568
01569 art_free(temp);
01570 }
01571
01572
void KSVGIconPainter::drawLine(
double x1,
double y1,
double x2,
double y2)
01573 {
01574 ArtVpath *vec;
01575
01576 vec = d->helper->allocVPath(3);
01577
01578 vec[0].code = ART_MOVETO_OPEN;
01579 vec[0].x = x1;
01580 vec[0].y = y1;
01581
01582 vec[1].code = ART_LINETO;
01583 vec[1].x = x2;
01584 vec[1].y = y2;
01585
01586 vec[2].code = ART_END;
01587
01588 d->helper->drawVPath(vec);
01589 }
01590
01591
void KSVGIconPainter::drawPolyline(
QPointArray polyArray,
int points)
01592 {
01593
if(polyArray.point(0).x() == -1 || polyArray.point(0).y() == -1)
01594
return;
01595
01596 ArtVpath *polyline;
01597
01598
if(points == -1)
01599 points = polyArray.count();
01600
01601 polyline = d->helper->allocVPath(3 + points);
01602 polyline[0].code = ART_MOVETO;
01603 polyline[0].x = polyArray.point(0).x();
01604 polyline[0].y = polyArray.point(0).y();
01605
01606
int index;
01607
for(index = 1; index < points; index++)
01608 {
01609
QPoint point = polyArray.point(index);
01610 polyline[index].code = ART_LINETO;
01611 polyline[index].x = point.x();
01612 polyline[index].y = point.y();
01613 }
01614
01615
if(d->helper->m_useFill)
01616 {
01617 polyline[index].code = (ArtPathcode)ART_END2;
01618 polyline[index].x = polyArray.point(0).x();
01619 polyline[index++].y = polyArray.point(0).y();
01620 }
01621
01622 polyline[index].code = ART_END;
01623
01624 d->helper->drawVPath(polyline);
01625 }
01626
01627
void KSVGIconPainter::drawPolygon(
QPointArray polyArray)
01628 {
01629 ArtVpath *polygon;
01630
01631 polygon = d->helper->allocVPath(3 + polyArray.count());
01632 polygon[0].code = ART_MOVETO;
01633 polygon[0].x = polyArray.point(0).x();
01634 polygon[0].y = polyArray.point(0).y();
01635
01636
unsigned int index;
01637
for(index = 1; index < polyArray.count(); index++)
01638 {
01639
QPoint point = polyArray.point(index);
01640 polygon[index].code = ART_LINETO;
01641 polygon[index].x = point.x();
01642 polygon[index].y = point.y();
01643 }
01644
01645 polygon[index].code = ART_LINETO;
01646 polygon[index].x = polyArray.point(0).x();
01647 polygon[index].y = polyArray.point(0).y();
01648
01649 index++;
01650 polygon[index].code = ART_END;
01651
01652 d->helper->drawVPath(polygon);
01653 }
01654
01655
01656
01657
static const char *getCoord(
const char *ptr,
double &number)
01658 {
01659
int integer, exponent;
01660
double decimal, frac;
01661
int sign, expsign;
01662
01663 exponent = 0;
01664 integer = 0;
01665 frac = 1.0;
01666 decimal = 0;
01667 sign = 1;
01668 expsign = 1;
01669
01670
01671
if(*ptr ==
'+')
01672 ptr++;
01673
else if(*ptr ==
'-')
01674 {
01675 ptr++;
01676 sign = -1;
01677 }
01678
01679
while(*ptr !=
'\0' && *ptr >=
'0' && *ptr <=
'9')
01680 integer = (integer * 10) + *(ptr++) -
'0';
01681
01682
if(*ptr ==
'.')
01683 {
01684 ptr++;
01685
while(*ptr !=
'\0' && *ptr >=
'0' && *ptr <=
'9')
01686 decimal += (*(ptr++) -
'0') * (frac *= 0.1);
01687 }
01688
01689
if(*ptr ==
'e' || *ptr ==
'E')
01690 {
01691 ptr++;
01692
01693
01694
if(*ptr ==
'+')
01695 ptr++;
01696
else if(*ptr ==
'-')
01697 {
01698 ptr++;
01699 expsign = -1;
01700 }
01701
01702 exponent = 0;
01703
while(*ptr !=
'\0' && *ptr >=
'0' && *ptr <=
'9')
01704 {
01705 exponent *= 10;
01706 exponent += *ptr -
'0';
01707 ptr++;
01708 }
01709 }
01710
01711
number = integer + decimal;
01712
number *= sign * pow(10.0, expsign * exponent);
01713
01714
01715
if(*ptr ==
' ')
01716 ptr++;
01717
01718
return ptr;
01719 }
01720
01721
void KSVGIconPainter::drawPath(
const QString &data,
bool filled)
01722 {
01723
QString value = data;
01724
01725
QMemArray<ArtBpath> vec;
01726
int index = -1;
01727
01728
double curx = 0.0, cury = 0.0, contrlx = 0.0, contrly = 0.0, xc, yc;
01729
unsigned int lastCommand = 0;
01730
01731
QString _d = value.replace(
",",
" ");
01732 _d = _d.simplifyWhiteSpace();
01733
const char *ptr = _d.latin1();
01734
const char *
end = _d.latin1() + _d.length() + 1;
01735
01736
double tox, toy, x1, y1, x2, y2, rx, ry, angle;
01737
bool largeArc, sweep;
01738
char command = *(ptr++);
01739
01740
while(ptr <
end)
01741 {
01742
if(*ptr ==
' ')
01743 ptr++;
01744
01745
switch(command)
01746 {
01747
case 'm':
01748 ptr = getCoord(ptr, tox);
01749 ptr = getCoord(ptr, toy);
01750
01751
if(index != -1 && lastCommand !=
'z')
01752 {
01753
01754
int find = -1;
01755
for(
int i = index; i >= 0; i--)
01756 {
01757
if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO)
01758 {
01759
find = i;
01760
break;
01761 }
01762 }
01763
01764 index++;
01765
01766
if(vec.size() == (
unsigned int) index)
01767 vec.resize(index + 1);
01768
01769 vec[index].code = (ArtPathcode)ART_END2;
01770 vec[index].x3 = vec[
find].x3;
01771 vec[index].y3 = vec[
find].y3;
01772 }
01773
01774 curx += tox;
01775 cury += toy;
01776
01777 index++;
01778
01779 d->helper->ensureSpace(vec, index);
01780
01781 vec[index].code = (index == 0) ? ART_MOVETO : ART_MOVETO_OPEN;
01782 vec[index].x3 = curx;
01783 vec[index].y3 = cury;
01784
01785 lastCommand =
'm';
01786
break;
01787
case 'M':
01788 ptr = getCoord(ptr, tox);
01789 ptr = getCoord(ptr, toy);
01790
if(index != -1 && lastCommand !=
'z')
01791 {
01792
01793
int find = -1;
01794
for(
int i = index; i >= 0; i--)
01795 {
01796
if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO)
01797 {
01798
find = i;
01799
break;
01800 }
01801 }
01802
01803 index++;
01804
01805
if(vec.size() == (
unsigned int) index)
01806 vec.resize(index + 1);
01807
01808 vec[index].code = (ArtPathcode)ART_END2;
01809 vec[index].x3 = vec[
find].x3;
01810 vec[index].y3 = vec[
find].y3;
01811 }
01812
01813 curx = tox;
01814 cury = toy;
01815
01816 index++;
01817
01818 d->helper->ensureSpace(vec, index);
01819
01820 vec[index].code = (index == 0) ? ART_MOVETO : ART_MOVETO_OPEN;
01821 vec[index].x3 = curx;
01822 vec[index].y3 = cury;
01823
01824 lastCommand =
'M';
01825
break;
01826
case 'l':
01827 ptr = getCoord(ptr, tox);
01828 ptr = getCoord(ptr, toy);
01829
01830 index++;
01831
01832 d->helper->ensureSpace(vec, index);
01833
01834 vec[index].code = ART_LINETO;
01835 vec[index].x3 = curx + tox;
01836 vec[index].y3 = cury + toy;
01837
01838 curx += tox;
01839 cury += toy;
01840
01841 lastCommand =
'l';
01842
break;
01843
case 'L':
01844 ptr = getCoord(ptr, tox);
01845 ptr = getCoord(ptr, toy);
01846
01847 index++;
01848
01849 d->helper->ensureSpace(vec, index);
01850
01851 vec[index].code = ART_LINETO;
01852 vec[index].x3 = tox;
01853 vec[index].y3 = toy;
01854
01855 curx = tox;
01856 cury = toy;
01857
01858 lastCommand =
'L';
01859
break;
01860
case 'h':
01861 ptr = getCoord(ptr, tox);
01862
01863 index++;
01864
01865 curx += tox;
01866
01867 d->helper->ensureSpace(vec, index);
01868
01869 vec[index].code = ART_LINETO;
01870 vec[index].x3 = curx;
01871 vec[index].y3 = cury;
01872
01873 lastCommand =
'h';
01874
break;
01875
case 'H':
01876 ptr = getCoord(ptr, tox);
01877
01878 index++;
01879
01880 curx = tox;
01881
01882 d->helper->ensureSpace(vec, index);
01883
01884 vec[index].code = ART_LINETO;
01885 vec[index].x3 = curx;
01886 vec[index].y3 = cury;
01887
01888 lastCommand =
'H';
01889
break;
01890
case 'v':
01891 ptr = getCoord(ptr, toy);
01892
01893 index++;
01894
01895 cury += toy;
01896
01897 d->helper->ensureSpace(vec, index);
01898
01899 vec[index].code = ART_LINETO;
01900 vec[index].x3 = curx;
01901 vec[index].y3 = cury;
01902
01903 lastCommand =
'v';
01904
break;
01905
case 'V':
01906 ptr = getCoord(ptr, toy);
01907
01908 index++;
01909
01910 cury = toy;
01911
01912 d->helper->ensureSpace(vec, index);
01913
01914 vec[index].code = ART_LINETO;
01915 vec[index].x3 = curx;
01916 vec[index].y3 = cury;
01917
01918 lastCommand =
'V';
01919
break;
01920
case 'c':
01921 ptr = getCoord(ptr, x1);
01922 ptr = getCoord(ptr, y1);
01923 ptr = getCoord(ptr, x2);
01924 ptr = getCoord(ptr, y2);
01925 ptr = getCoord(ptr, tox);
01926 ptr = getCoord(ptr, toy);
01927
01928 index++;
01929
01930 d->helper->ensureSpace(vec, index);
01931
01932 vec[index].code = ART_CURVETO;
01933 vec[index].x1 = curx + x1;
01934 vec[index].y1 = cury + y1;
01935 vec[index].x2 = curx + x2;
01936 vec[index].y2 = cury + y2;
01937 vec[index].x3 = curx + tox;
01938 vec[index].y3 = cury + toy;
01939
01940 curx += tox;
01941 cury += toy;
01942
01943 contrlx = vec[index].x2;
01944 contrly = vec[index].y2;
01945
01946 lastCommand =
'c';
01947
break;
01948
case 'C':
01949 ptr = getCoord(ptr, x1);
01950 ptr = getCoord(ptr, y1);
01951 ptr = getCoord(ptr, x2);
01952 ptr = getCoord(ptr, y2);
01953 ptr = getCoord(ptr, tox);
01954 ptr = getCoord(ptr, toy);
01955
01956 index++;
01957
01958 d->helper->ensureSpace(vec, index);
01959
01960 vec[index].code = ART_CURVETO;
01961 vec[index].x1 = x1;
01962 vec[index].y1 = y1;
01963 vec[index].x2 = x2;
01964 vec[index].y2 = y2;
01965 vec[index].x3 = tox;
01966 vec[index].y3 = toy;
01967
01968 curx = vec[index].x3;
01969 cury = vec[index].y3;
01970 contrlx = vec[index].x2;
01971 contrly = vec[index].y2;
01972
01973 lastCommand =
'C';
01974
break;
01975
case 's':
01976 ptr = getCoord(ptr, x2);
01977 ptr = getCoord(ptr, y2);
01978 ptr = getCoord(ptr, tox);
01979 ptr = getCoord(ptr, toy);
01980
01981 index++;
01982
01983 d->helper->ensureSpace(vec, index);
01984
01985 vec[index].code = ART_CURVETO;
01986 vec[index].x1 = 2 * curx - contrlx;
01987 vec[index].y1 = 2 * cury - contrly;
01988 vec[index].x2 = curx + x2;
01989 vec[index].y2 = cury + y2;
01990 vec[index].x3 = curx + tox;
01991 vec[index].y3 = cury + toy;
01992
01993 curx += tox;
01994 cury += toy;
01995
01996 contrlx = vec[index].x2;
01997 contrly = vec[index].y2;
01998
01999 lastCommand =
's';
02000
break;
02001
case 'S':
02002 ptr = getCoord(ptr, x2);
02003 ptr = getCoord(ptr, y2);
02004 ptr = getCoord(ptr, tox);
02005 ptr = getCoord(ptr, toy);
02006
02007 index++;
02008
02009 d->helper->ensureSpace(vec, index);
02010
02011 vec[index].code = ART_CURVETO;
02012 vec[index].x1 = 2 * curx - contrlx;
02013 vec[index].y1 = 2 * cury - contrly;
02014 vec[index].x2 = x2;
02015 vec[index].y2 = y2;
02016 vec[index].x3 = tox;
02017 vec[index].y3 = toy;
02018
02019 curx = vec[index].x3;
02020 cury = vec[index].y3;
02021 contrlx = vec[index].x2;
02022 contrly = vec[index].y2;
02023
02024 lastCommand =
'S';
02025
break;
02026
case 'q':
02027 ptr = getCoord(ptr, x1);
02028 ptr = getCoord(ptr, y1);
02029 ptr = getCoord(ptr, tox);
02030 ptr = getCoord(ptr, toy);
02031
02032 index++;
02033
02034 d->helper->ensureSpace(vec, index);
02035
02036 vec[index].code = ART_CURVETO;
02037 vec[index].x1 = (curx + 2 * (x1 + curx)) * (1.0 / 3.0);
02038 vec[index].y1 = (cury + 2 * (y1 + cury)) * (1.0 / 3.0);
02039 vec[index].x2 = ((curx + tox) + 2 * (x1 + curx)) * (1.0 / 3.0);
02040 vec[index].y2 = ((cury + toy) + 2 * (y1 + cury)) * (1.0 / 3.0);
02041 vec[index].x3 = curx + tox;
02042 vec[index].y3 = cury + toy;
02043
02044 contrlx = curx + x1;
02045 contrly = cury + y1;
02046 curx += tox;
02047 cury += toy;
02048
02049 lastCommand =
'q';
02050
break;
02051
case 'Q':
02052 ptr = getCoord(ptr, x1);
02053 ptr = getCoord(ptr, y1);
02054 ptr = getCoord(ptr, tox);
02055 ptr = getCoord(ptr, toy);
02056
02057 index++;
02058
02059 d->helper->ensureSpace(vec, index);
02060
02061
02062 vec[index].code = ART_CURVETO;
02063 vec[index].x1 = (curx + 2 * x1) * (1.0 / 3.0);
02064 vec[index].y1 = (cury + 2 * y1) * (1.0 / 3.0);
02065 vec[index].x2 = (tox + 2 * x1) * (1.0 / 3.0);
02066 vec[index].y2 = (toy + 2 * y1) * (1.0 / 3.0);
02067 vec[index].x3 = tox;
02068 vec[index].y3 = toy;
02069
02070 curx = vec[index].x3;
02071 cury = vec[index].y3;
02072 contrlx = vec[index].x2;
02073 contrly = vec[index].y2;
02074
02075 lastCommand =
'Q';
02076
break;
02077
case 't':
02078 ptr = getCoord(ptr, tox);
02079 ptr = getCoord(ptr, toy);
02080
02081 xc = 2 * curx - contrlx;
02082 yc = 2 * cury - contrly;
02083
02084 index++;
02085
02086 d->helper->ensureSpace(vec, index);
02087
02088 vec[index].code = ART_CURVETO;
02089 vec[index].x1 = (curx + 2 * xc) * (1.0 / 3.0);
02090 vec[index].y1 = (cury + 2 * yc) * (1.0 / 3.0);
02091 vec[index].x2 = ((curx + tox) + 2 * xc) * (1.0 / 3.0);
02092 vec[index].y2 = ((cury + toy) + 2 * yc) * (1.0 / 3.0);
02093
02094 vec[index].x3 = curx + tox;
02095 vec[index].y3 = cury + toy;
02096
02097 curx += tox;
02098 cury += toy;
02099 contrlx = xc;
02100 contrly = yc;
02101
02102 lastCommand =
't';
02103
break;
02104
case 'T':
02105 ptr = getCoord(ptr, tox);
02106 ptr = getCoord(ptr, toy);
02107
02108 xc = 2 * curx - contrlx;
02109 yc = 2 * cury - contrly;
02110
02111 index++;
02112
02113 d->helper->ensureSpace(vec, index);
02114
02115 vec[index].code = ART_CURVETO;
02116 vec[index].x1 = (curx + 2 * xc) * (1.0 / 3.0);
02117 vec[index].y1 = (cury + 2 * yc) * (1.0 / 3.0);
02118 vec[index].x2 = (tox + 2 * xc) * (1.0 / 3.0);
02119 vec[index].y2 = (toy + 2 * yc) * (1.0 / 3.0);
02120 vec[index].x3 = tox;
02121 vec[index].y3 = toy;
02122
02123 curx = tox;
02124 cury = toy;
02125 contrlx = xc;
02126 contrly = yc;
02127
02128 lastCommand =
'T';
02129
break;
02130
case 'z':
02131
case 'Z':
02132
int find;
02133
find = -1;
02134
for(
int i = index; i >= 0; i--)
02135 {
02136
if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO)
02137 {
02138
find = i;
02139
break;
02140 }
02141 }
02142
02143
if(
find != -1)
02144 {
02145
if(vec[
find].x3 != curx || vec[
find].y3 != cury)
02146 {
02147 index++;
02148
02149 d->helper->ensureSpace(vec, index);
02150
02151 vec[index].code = ART_LINETO;
02152 vec[index].x3 = vec[
find].x3;
02153 vec[index].y3 = vec[
find].y3;
02154 }
02155 }
02156
02157
02158 curx = vec[
find].x3;
02159 cury = vec[
find].y3;
02160
02161 lastCommand =
'z';
02162
break;
02163
case 'a':
02164 ptr = getCoord(ptr, rx);
02165 ptr = getCoord(ptr, ry);
02166 ptr = getCoord(ptr, angle);
02167 ptr = getCoord(ptr, tox);
02168 largeArc = tox == 1;
02169 ptr = getCoord(ptr, tox);
02170 sweep = tox == 1;
02171 ptr = getCoord(ptr, tox);
02172 ptr = getCoord(ptr, toy);
02173
02174
02175 rx = fabs(rx);
02176 ry = fabs(ry);
02177
02178 d->helper->calculateArc(
true, vec, index, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep);
02179
02180 lastCommand =
'a';
02181
break;
02182
case 'A':
02183 ptr = getCoord(ptr, rx);
02184 ptr = getCoord(ptr, ry);
02185 ptr = getCoord(ptr, angle);
02186 ptr = getCoord(ptr, tox);
02187 largeArc = tox == 1;
02188 ptr = getCoord(ptr, tox);
02189 sweep = tox == 1;
02190 ptr = getCoord(ptr, tox);
02191 ptr = getCoord(ptr, toy);
02192
02193
02194 rx = fabs(rx);
02195 ry = fabs(ry);
02196
02197 d->helper->calculateArc(
false, vec, index, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep);
02198
02199 lastCommand =
'A';
02200
break;
02201 }
02202
02203
if(*ptr ==
'+' || *ptr ==
'-' || (*ptr >=
'0' && *ptr <=
'9'))
02204 {
02205
02206
if(command ==
'M')
02207 command =
'L';
02208
else if(command ==
'm')
02209 command =
'l';
02210 }
02211
else
02212 command = *(ptr++);
02213
02214
02215
if(lastCommand !=
'C' && lastCommand !=
'c' &&
02216 lastCommand !=
'S' && lastCommand !=
's' &&
02217 lastCommand !=
'Q' && lastCommand !=
'q' &&
02218 lastCommand !=
'T' && lastCommand !=
't')
02219 {
02220 contrlx = curx;
02221 contrly = cury;
02222 }
02223 }
02224
02225
02226
int find = -1;
02227
for(
int i = index; i >= 0; i--)
02228 {
02229
if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO)
02230 {
02231
find = i;
02232
break;
02233 }
02234 }
02235
02236
02237
if(curx != vec[
find].x3 && cury != vec[
find].y3)
02238 {
02239
if((
int) curx == (
int) vec[
find].x3 && (
int) cury == (
int) vec[
find].y3)
02240 {
02241 index++;
02242
02243
if(vec.size() == (
unsigned int) index)
02244 vec.resize(index + 1);
02245
02246 vec[index].code = ART_LINETO;
02247 vec[index].x3 = vec[
find].x3;
02248 vec[index].y3 = vec[
find].y3;
02249
02250 curx = vec[
find].x3;
02251 cury = vec[
find].y3;
02252 }
02253 }
02254
02255
02256
if(filled)
02257 {
02258
if((
int) curx != (
int) vec[
find].x3 || (
int) cury != (
int) vec[
find].y3)
02259 {
02260 index++;
02261
02262
if(vec.size() == (
unsigned int) index)
02263 vec.resize(index + 1);
02264
02265 vec[index].code = (ArtPathcode)ART_END2;
02266 vec[index].x3 = vec[
find].x3;
02267 vec[index].y3 = vec[
find].y3;
02268
02269 curx = vec[
find].x3;
02270 cury = vec[
find].y3;
02271 }
02272 }
02273
02274
02275 index++;
02276
02277
if(vec.size() == (
unsigned int) index)
02278 vec.resize(index + 1);
02279
02280 vec[index].code = ART_END;
02281
02282
02283
02284
bool render =
false;
02285
for(
int i = index; i >= 0; i--)
02286 {
02287
if(vec[i].code != ART_MOVETO_OPEN && vec[i].code != ART_MOVETO && !(vec[i].code >= ART_END))
02288 {
02289 render =
true;
02290
break;
02291 }
02292 }
02293
02294
if(render)
02295 d->helper->drawBPath(vec.data());
02296 }
02297
02298
void KSVGIconPainter::drawImage(
double x,
double y,
QImage &image)
02299 {
02300
if(image.depth() != 32)
02301 image = image.convertDepth(32);
02302
02303
double affine[6];
02304 affine[0] = d->helper->m_worldMatrix->m11();
02305 affine[1] = d->helper->m_worldMatrix->m12();
02306 affine[2] = d->helper->m_worldMatrix->m21();
02307 affine[3] = d->helper->m_worldMatrix->m22();
02308 affine[4] = d->helper->m_worldMatrix->dx() + x;
02309 affine[5] = d->helper->m_worldMatrix->dy() + y;
02310
02311 d->helper->art_rgba_rgba_affine(d->helper->m_buffer, 0, 0, d->helper->m_width, d->helper->m_height,
02312 d->helper->m_rowstride, image.bits(), image.width(), image.height(),
02313 image.width() * 4, affine);
02314 }
02315
02316
QColor KSVGIconPainter::parseColor(
const QString ¶m)
02317 {
02318
if(param.stripWhiteSpace().startsWith(
"#"))
02319 {
02320
QColor color;
02321 color.setNamedColor(param.stripWhiteSpace());
02322
return color;
02323 }
02324
else if(param.stripWhiteSpace().startsWith(
"rgb("))
02325 {
02326
QString parse = param.stripWhiteSpace();
02327
QStringList colors = QStringList::split(
',', parse);
02328
QString r = colors[0].right((colors[0].length() - 4));
02329
QString g = colors[1];
02330
QString b = colors[2].left((colors[2].length() - 1));
02331
02332
if(r.contains(
"%"))
02333 {
02334 r = r.left(r.length() - 1);
02335 r = QString::number(
int((
double(255 * r.toDouble()) / 100.0)));
02336 }
02337
02338
if(g.contains(
"%"))
02339 {
02340 g = g.left(g.length() - 1);
02341 g = QString::number(
int((
double(255 * g.toDouble()) / 100.0)));
02342 }
02343
02344
if(b.contains(
"%"))
02345 {
02346 b = b.left(b.length() - 1);
02347 b = QString::number(
int((
double(255 * b.toDouble()) / 100.0)));
02348 }
02349
02350
return QColor(r.toInt(), g.toInt(), b.toInt());
02351 }
02352
else
02353 {
02354
QString rgbColor = param.stripWhiteSpace();
02355
02356
if(rgbColor ==
"aliceblue")
02357
return QColor(240, 248, 255);
02358
else if(rgbColor ==
"antiquewhite")
02359
return QColor(250, 235, 215);
02360
else if(rgbColor ==
"aqua")
02361
return QColor(0, 255, 255);
02362
else if(rgbColor ==
"aquamarine")
02363
return QColor(127, 255, 212);
02364
else if(rgbColor ==
"azure")
02365
return QColor(240, 255, 255);
02366
else if(rgbColor ==
"beige")
02367
return QColor(245, 245, 220);
02368
else if(rgbColor ==
"bisque")
02369
return QColor(255, 228, 196);
02370
else if(rgbColor ==
"black")
02371
return QColor(0, 0, 0);
02372
else if(rgbColor ==
"blanchedalmond")
02373
return QColor(255, 235, 205);
02374
else if(rgbColor ==
"blue")
02375
return QColor(0, 0, 255);
02376
else if(rgbColor ==
"blueviolet")
02377
return QColor(138, 43, 226);
02378
else if(rgbColor ==
"brown")
02379
return QColor(165, 42, 42);
02380
else if(rgbColor ==
"burlywood")
02381
return QColor(222, 184, 135);
02382
else if(rgbColor ==
"cadetblue")
02383
return QColor(95, 158, 160);
02384
else if(rgbColor ==
"chartreuse")
02385
return QColor(127, 255, 0);
02386
else if(rgbColor ==
"chocolate")
02387
return QColor(210, 105, 30);
02388
else if(rgbColor ==
"coral")
02389
return QColor(255, 127, 80);
02390
else if(rgbColor ==
"cornflowerblue")
02391
return QColor(100, 149, 237);
02392
else if(rgbColor ==
"cornsilk")
02393
return QColor(255, 248, 220);
02394
else if(rgbColor ==
"crimson")
02395
return QColor(220, 20, 60);
02396
else if(rgbColor ==
"cyan")
02397
return QColor(0, 255, 255);
02398
else if(rgbColor ==
"darkblue")
02399
return QColor(0, 0, 139);
02400
else if(rgbColor ==
"darkcyan")
02401
return QColor(0, 139, 139);
02402
else if(rgbColor ==
"darkgoldenrod")
02403
return QColor(184, 134, 11);
02404
else if(rgbColor ==
"darkgray")
02405
return QColor(169, 169, 169);
02406
else if(rgbColor ==
"darkgrey")
02407
return QColor(169, 169, 169);
02408
else if(rgbColor ==
"darkgreen")
02409
return QColor(0, 100, 0);
02410
else if(rgbColor ==
"darkkhaki")
02411
return QColor(189, 183, 107);
02412
else if(rgbColor ==
"darkmagenta")
02413
return QColor(139, 0, 139);
02414
else if(rgbColor ==
"darkolivegreen")
02415
return QColor(85, 107, 47);
02416
else if(rgbColor ==
"darkorange")
02417
return QColor(255, 140, 0);
02418
else if(rgbColor ==
"darkorchid")
02419
return QColor(153, 50, 204);
02420
else if(rgbColor ==
"darkred")
02421
return QColor(139, 0, 0);
02422
else if(rgbColor ==
"darksalmon")
02423
return QColor(233, 150, 122);
02424
else if(rgbColor ==
"darkseagreen")
02425
return QColor(143, 188, 143);
02426
else if(rgbColor ==
"darkslateblue")
02427
return QColor(72, 61, 139);
02428
else if(rgbColor ==
"darkslategray")
02429
return QColor(47, 79, 79);
02430
else if(rgbColor ==
"darkslategrey")
02431
return QColor(47, 79, 79);
02432
else if(rgbColor ==
"darkturquoise")
02433
return QColor(0, 206, 209);
02434
else if(rgbColor ==
"darkviolet")
02435
return QColor(148, 0, 211);
02436
else if(rgbColor ==
"deeppink")
02437
return QColor(255, 20, 147);
02438
else if(rgbColor ==
"deepskyblue")
02439
return QColor(0, 191, 255);
02440
else if(rgbColor ==
"dimgray")
02441
return QColor(105, 105, 105);
02442
else if(rgbColor ==
"dimgrey")
02443
return QColor(105, 105, 105);
02444
else if(rgbColor ==
"dodgerblue")
02445
return QColor(30, 144, 255);
02446
else if(rgbColor ==
"firebrick")
02447
return QColor(178, 34, 34);
02448
else if(rgbColor ==
"floralwhite")
02449
return QColor(255, 250, 240);
02450
else if(rgbColor ==
"forestgreen")
02451
return QColor(34, 139, 34);
02452
else if(rgbColor ==
"fuchsia")
02453
return QColor(255, 0, 255);
02454
else if(rgbColor ==
"gainsboro")
02455
return QColor(220, 220, 220);
02456
else if(rgbColor ==
"ghostwhite")
02457
return QColor(248, 248, 255);
02458
else if(rgbColor ==
"gold")
02459
return QColor(255, 215, 0);
02460
else if(rgbColor ==
"goldenrod")
02461
return QColor(218, 165, 32);
02462
else if(rgbColor ==
"gray")
02463
return QColor(128, 128, 128);
02464
else if(rgbColor ==
"grey")
02465
return QColor(128, 128, 128);
02466
else if(rgbColor ==
"green")
02467
return QColor(0, 128, 0);
02468
else if(rgbColor ==
"greenyellow")
02469
return QColor(173, 255, 47);
02470
else if(rgbColor ==
"honeydew")
02471
return QColor(240, 255, 240);
02472
else if(rgbColor ==
"hotpink")
02473
return QColor(255, 105, 180);
02474
else if(rgbColor ==
"indianred")
02475
return QColor(205, 92, 92);
02476
else if(rgbColor ==
"indigo")
02477
return QColor(75, 0, 130);
02478
else if(rgbColor ==
"ivory")
02479
return QColor(255, 255, 240);
02480
else if(rgbColor ==
"khaki")
02481
return QColor(240, 230, 140);
02482
else if(rgbColor ==
"lavender")
02483
return QColor(230, 230, 250);
02484
else if(rgbColor ==
"lavenderblush")
02485
return QColor(255, 240, 245);
02486
else if(rgbColor ==
"lawngreen")
02487
return QColor(124, 252, 0);
02488
else if(rgbColor ==
"lemonchiffon")
02489
return QColor(255, 250, 205);
02490
else if(rgbColor ==
"lightblue")
02491
return QColor(173, 216, 230);
02492
else if(rgbColor ==
"lightcoral")
02493
return QColor(240, 128, 128);
02494
else if(rgbColor ==
"lightcyan")
02495
return QColor(224, 255, 255);
02496
else if(rgbColor ==
"lightgoldenrodyellow")
02497
return QColor(250, 250, 210);
02498
else if(rgbColor ==
"lightgray")
02499
return QColor(211, 211, 211);
02500
else if(rgbColor ==
"lightgrey")
02501
return QColor(211, 211, 211);
02502
else if(rgbColor ==
"lightgreen")
02503
return QColor(144, 238, 144);
02504
else if(rgbColor ==
"lightpink")
02505
return QColor(255, 182, 193);
02506
else if(rgbColor ==
"lightsalmon")
02507
return QColor(255, 160, 122);
02508
else if(rgbColor ==
"lightseagreen")
02509
return QColor(32, 178, 170);
02510
else if(rgbColor ==
"lightskyblue")
02511
return QColor(135, 206, 250);
02512
else if(rgbColor ==
"lightslategray")
02513
return QColor(119, 136, 153);
02514
else if(rgbColor ==
"lightslategrey")
02515
return QColor(119, 136, 153);
02516
else if(rgbColor ==
"lightsteelblue")
02517
return QColor(176, 196, 222);
02518
else if(rgbColor ==
"lightyellow")
02519
return QColor(255, 255, 224);
02520
else if(rgbColor ==
"lime")
02521
return QColor(0, 255, 0);
02522
else if(rgbColor ==
"limegreen")
02523
return QColor(50, 205, 50);
02524
else if(rgbColor ==
"linen")
02525
return QColor(250, 240, 230);
02526
else if(rgbColor ==
"magenta")
02527
return QColor(255, 0, 255);
02528
else if(rgbColor ==
"maroon")
02529
return QColor(128, 0, 0);
02530
else if(rgbColor ==
"mediumaquamarine")
02531
return QColor(102, 205, 170);
02532
else if(rgbColor ==
"mediumblue")
02533
return QColor(0, 0, 205);
02534
else if(rgbColor ==
"mediumorchid")
02535
return QColor(186, 85, 211);
02536
else if(rgbColor ==
"mediumpurple")
02537
return QColor(147, 112, 219);
02538
else if(rgbColor ==
"mediumseagreen")
02539
return QColor(60, 179, 113);
02540
else if(rgbColor ==
"mediumslateblue")
02541
return QColor(123, 104, 238);
02542
else if(rgbColor ==
"mediumspringgreen")
02543
return QColor(0, 250, 154);
02544
else if(rgbColor ==
"mediumturquoise")
02545
return QColor(72, 209, 204);
02546
else if(rgbColor ==
"mediumvioletred")
02547
return QColor(199, 21, 133);
02548
else if(rgbColor ==
"midnightblue")
02549
return QColor(25, 25, 112);
02550
else if(rgbColor ==
"mintcream")
02551
return QColor(245, 255, 250);
02552
else if(rgbColor ==
"mistyrose")
02553
return QColor(255, 228, 225);
02554
else if(rgbColor ==
"moccasin")
02555
return QColor(255, 228, 181);
02556
else if(rgbColor ==
"navajowhite")
02557
return QColor(255, 222, 173);
02558
else if(rgbColor ==
"navy")
02559
return QColor(0, 0, 128);
02560
else if(rgbColor ==
"oldlace")
02561
return QColor(253, 245, 230);
02562
else if(rgbColor ==
"olive")
02563
return QColor(128, 128, 0);
02564
else if(rgbColor ==
"olivedrab")
02565
return QColor(107, 142, 35);
02566
else if(rgbColor ==
"orange")
02567
return QColor(255, 165, 0);
02568
else if(rgbColor ==
"orangered")
02569
return QColor(255, 69, 0);
02570
else if(rgbColor ==
"orchid")
02571
return QColor(218, 112, 214);
02572
else if(rgbColor ==
"palegoldenrod")
02573
return QColor(238, 232, 170);
02574
else if(rgbColor ==
"palegreen")
02575
return QColor(152, 251, 152);
02576
else if(rgbColor ==
"paleturquoise")
02577
return QColor(175, 238, 238);
02578
else if(rgbColor ==
"palevioletred")
02579
return QColor(219, 112, 147);
02580
else if(rgbColor ==
"papayawhip")
02581
return QColor(255, 239, 213);
02582
else if(rgbColor ==
"peachpuff")
02583
return QColor(255, 218, 185);
02584
else if(rgbColor ==
"peru")
02585
return QColor(205, 133, 63);
02586
else if(rgbColor ==
"pink")
02587
return QColor(255, 192, 203);
02588
else if(rgbColor ==
"plum")
02589
return QColor(221, 160, 221);
02590
else if(rgbColor ==
"powderblue")
02591
return QColor(176, 224, 230);
02592
else if(rgbColor ==
"purple")
02593
return QColor(128, 0, 128);
02594
else if(rgbColor ==
"red")
02595
return QColor(255, 0, 0);
02596
else if(rgbColor ==
"rosybrown")
02597
return QColor(188, 143, 143);
02598
else if(rgbColor ==
"royalblue")
02599
return QColor(65, 105, 225);
02600
else if(rgbColor ==
"saddlebrown")
02601
return QColor(139, 69, 19);
02602
else if(rgbColor ==
"salmon")
02603
return QColor(250, 128, 114);
02604
else if(rgbColor ==
"sandybrown")
02605
return QColor(244, 164, 96);
02606
else if(rgbColor ==
"seagreen")
02607
return QColor(46, 139, 87);
02608
else if(rgbColor ==
"seashell")
02609
return QColor(255, 245, 238);
02610
else if(rgbColor ==
"sienna")
02611
return QColor(160, 82, 45);
02612
else if(rgbColor ==
"silver")
02613
return QColor(192, 192, 192);
02614
else if(rgbColor ==
"skyblue")
02615
return QColor(135, 206, 235);
02616
else if(rgbColor ==
"slateblue")
02617
return QColor(106, 90, 205);
02618
else if(rgbColor ==
"slategray")
02619
return QColor(112, 128, 144);
02620
else if(rgbColor ==
"slategrey")
02621
return QColor(112, 128, 144);
02622
else if(rgbColor ==
"snow")
02623
return QColor(255, 250, 250);
02624
else if(rgbColor ==
"springgreen")
02625
return QColor(0, 255, 127);
02626
else if(rgbColor ==
"steelblue")
02627
return QColor(70, 130, 180);
02628
else if(rgbColor ==
"tan")
02629
return QColor(210, 180, 140);
02630
else if(rgbColor ==
"teal")
02631
return QColor(0, 128, 128);
02632
else if(rgbColor ==
"thistle")
02633
return QColor(216, 191, 216);
02634
else if(rgbColor ==
"tomato")
02635
return QColor(255, 99, 71);
02636
else if(rgbColor ==
"turquoise")
02637
return QColor(64, 224, 208);
02638
else if(rgbColor ==
"violet")
02639
return QColor(238, 130, 238);
02640
else if(rgbColor ==
"wheat")
02641
return QColor(245, 222, 179);
02642
else if(rgbColor ==
"white")
02643
return QColor(255, 255, 255);
02644
else if(rgbColor ==
"whitesmoke")
02645
return QColor(245, 245, 245);
02646
else if(rgbColor ==
"yellow")
02647
return QColor(255, 255, 0);
02648
else if(rgbColor ==
"yellowgreen")
02649
return QColor(154, 205, 50);
02650 }
02651
02652
return QColor();
02653 }
02654
02655
double KSVGIconPainter::dpi()
02656 {
02657
return 90.0;
02658 }
02659
02660
double KSVGIconPainter::toPixel(
const QString &s,
bool hmode)
02661 {
02662
if(s.isEmpty())
02663
return 0.0;
02664
02665
QString check = s;
02666
02667
double ret = 0.0;
02668
02669
bool ok =
false;
02670
02671
double value = check.toDouble(&ok);
02672
02673
if(!ok)
02674 {
02675 check.replace(
QRegExp(
"[0-9 .-]"), QString::null);
02676
02677
if(check.compare(
"px") == 0)
02678 ret = value;
02679
else if(check.compare(
"cm") == 0)
02680 ret = (value / 2.54) * dpi();
02681
else if(check.compare(
"pc") == 0)
02682 ret = (value / 6.0) * dpi();
02683
else if(check.compare(
"mm") == 0)
02684 ret = (value / 25.4) * dpi();
02685
else if(check.compare(
"in") == 0)
02686 ret = value * dpi();
02687
else if(check.compare(
"pt") == 0)
02688 ret = (value / 72.0) * dpi();
02689
else if(check.compare(
"%") == 0)
02690 {
02691 ret = value / 100.0;
02692
02693
if(hmode)
02694 ret *= d->drawWidth;
02695
else
02696 ret *= d->drawHeight;
02697 }
02698
else if(check.compare(
"em") == 0)
02699 {
02700 ret = value * 10.0;
02701 }
02702 }
02703
else
02704 ret = value;
02705
02706
return ret;
02707 }
02708
02709 ArtGradientLinear *KSVGIconPainter::linearGradient(
const QString &
id)
02710 {
02711
return d->helper->m_linearGradientMap[
id];
02712 }
02713
02714
void KSVGIconPainter::addLinearGradient(
const QString &
id, ArtGradientLinear *gradient)
02715 {
02716 d->helper->m_linearGradientMap.insert(
id, gradient);
02717 }
02718
02719
QDomElement KSVGIconPainter::linearGradientElement(ArtGradientLinear *linear)
02720 {
02721
return d->helper->m_linearGradientElementMap[linear];
02722 }
02723
02724
void KSVGIconPainter::addLinearGradientElement(ArtGradientLinear *gradient,
QDomElement element)
02725 {
02726 d->helper->m_linearGradientElementMap.insert(gradient, element);
02727 }
02728
02729 ArtGradientRadial *KSVGIconPainter::radialGradient(
const QString &
id)
02730 {
02731
return d->helper->m_radialGradientMap[
id];
02732 }
02733
02734
void KSVGIconPainter::addRadialGradient(
const QString &
id, ArtGradientRadial *gradient)
02735 {
02736 d->helper->m_radialGradientMap.insert(
id, gradient);
02737 }
02738
02739
QDomElement KSVGIconPainter::radialGradientElement(ArtGradientRadial *radial)
02740 {
02741
return d->helper->m_radialGradientElementMap[radial];
02742 }
02743
02744
void KSVGIconPainter::addRadialGradientElement(ArtGradientRadial *gradient,
QDomElement element)
02745 {
02746 d->helper->m_radialGradientElementMap.insert(gradient, element);
02747 }
02748
02749 Q_UINT32 KSVGIconPainter::toArtColor(
const QColor &color)
02750 {
02751
return d->helper->toArtColor(color);
02752 }
02753
02754
QWMatrix KSVGIconPainter::parseTransform(
const QString &transform)
02755 {
02756
QWMatrix result;
02757
02758
02759
QStringList subtransforms = QStringList::split(
')', transform);
02760 QStringList::ConstIterator it = subtransforms.begin();
02761 QStringList::ConstIterator
end = subtransforms.end();
02762
for(; it !=
end; ++it)
02763 {
02764
QStringList subtransform = QStringList::split(
'(', (*it));
02765
02766 subtransform[0] = subtransform[0].stripWhiteSpace().lower();
02767 subtransform[1] = subtransform[1].simplifyWhiteSpace();
02768
QRegExp reg(
"[a-zA-Z,( ]");
02769
QStringList params = QStringList::split(reg, subtransform[1]);
02770
02771
if(subtransform[0].startsWith(
";") || subtransform[0].startsWith(
","))
02772 subtransform[0] = subtransform[0].right(subtransform[0].length() - 1);
02773
02774
if(subtransform[0] ==
"rotate")
02775 {
02776
if(params.count() == 3)
02777 {
02778
float x = params[1].toFloat();
02779
float y = params[2].toFloat();
02780
02781 result.translate(x, y);
02782 result.rotate(params[0].toFloat());
02783 result.translate(-x, -y);
02784 }
02785
else
02786 result.rotate(params[0].toFloat());
02787 }
02788
else if(subtransform[0] ==
"translate")
02789 {
02790
if(params.count() == 2)
02791 result.translate(params[0].toFloat(), params[1].toFloat());
02792
else
02793 result.translate(params[0].toFloat() , 0);
02794 }
02795
else if(subtransform[0] ==
"scale")
02796 {
02797
if(params.count() == 2)
02798 result.scale(params[0].toFloat(), params[1].toFloat());
02799
else
02800 result.scale(params[0].toFloat(), params[0].toFloat());
02801 }
02802
else if(subtransform[0] ==
"skewx")
02803 result.shear(tan(params[0].toFloat() * deg2rad), 0.0F);
02804
else if(subtransform[0] ==
"skewy")
02805 result.shear(tan(params[0].toFloat() * deg2rad), 0.0F);
02806
else if(subtransform[0] ==
"skewy")
02807 result.shear(0.0F, tan(params[0].toFloat() * deg2rad));
02808
else if(subtransform[0] ==
"matrix")
02809 {
02810
if(params.count() >= 6)
02811 result.setMatrix(params[0].toFloat(), params[1].toFloat(), params[2].toFloat(), params[3].toFloat(), params[4].toFloat(), params[5].toFloat());
02812 }
02813 }
02814
02815
return result;
02816 }