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 = art_affine_expansion(affine);
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
if (!data.isEmpty())
01724 {
01725
QString value = data;
01726
01727
QMemArray<ArtBpath> vec;
01728
int index = -1;
01729
01730
double curx = 0.0, cury = 0.0, contrlx = 0.0, contrly = 0.0, xc, yc;
01731
unsigned int lastCommand = 0;
01732
01733
QString _d = value.replace(
",",
" ");
01734 _d = _d.simplifyWhiteSpace();
01735
const char *ptr = _d.latin1();
01736
const char *
end = _d.latin1() + _d.length() + 1;
01737
01738
double tox, toy, x1, y1, x2, y2, rx, ry, angle;
01739
bool largeArc, sweep;
01740
char command = *(ptr++);
01741
01742
while(ptr <
end)
01743 {
01744
if(*ptr ==
' ')
01745 ptr++;
01746
01747
switch(command)
01748 {
01749
case 'm':
01750 ptr = getCoord(ptr, tox);
01751 ptr = getCoord(ptr, toy);
01752
01753
if(index != -1 && lastCommand !=
'z')
01754 {
01755
01756
int find = -1;
01757
for(
int i = index; i >= 0; i--)
01758 {
01759
if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO)
01760 {
01761
find = i;
01762
break;
01763 }
01764 }
01765
01766 index++;
01767
01768
if(vec.size() == (
unsigned int) index)
01769 vec.resize(index + 1);
01770
01771 vec[index].code = (ArtPathcode)ART_END2;
01772 vec[index].x3 = vec[
find].x3;
01773 vec[index].y3 = vec[
find].y3;
01774 }
01775
01776 curx += tox;
01777 cury += toy;
01778
01779 index++;
01780
01781 d->helper->ensureSpace(vec, index);
01782
01783 vec[index].code = (index == 0) ? ART_MOVETO : ART_MOVETO_OPEN;
01784 vec[index].x3 = curx;
01785 vec[index].y3 = cury;
01786
01787 lastCommand =
'm';
01788
break;
01789
case 'M':
01790 ptr = getCoord(ptr, tox);
01791 ptr = getCoord(ptr, toy);
01792
if(index != -1 && lastCommand !=
'z')
01793 {
01794
01795
int find = -1;
01796
for(
int i = index; i >= 0; i--)
01797 {
01798
if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO)
01799 {
01800
find = i;
01801
break;
01802 }
01803 }
01804
01805 index++;
01806
01807
if(vec.size() == (
unsigned int) index)
01808 vec.resize(index + 1);
01809
01810 vec[index].code = (ArtPathcode)ART_END2;
01811 vec[index].x3 = vec[
find].x3;
01812 vec[index].y3 = vec[
find].y3;
01813 }
01814
01815 curx = tox;
01816 cury = toy;
01817
01818 index++;
01819
01820 d->helper->ensureSpace(vec, index);
01821
01822 vec[index].code = (index == 0) ? ART_MOVETO : ART_MOVETO_OPEN;
01823 vec[index].x3 = curx;
01824 vec[index].y3 = cury;
01825
01826 lastCommand =
'M';
01827
break;
01828
case 'l':
01829 ptr = getCoord(ptr, tox);
01830 ptr = getCoord(ptr, toy);
01831
01832 index++;
01833
01834 d->helper->ensureSpace(vec, index);
01835
01836 vec[index].code = ART_LINETO;
01837 vec[index].x3 = curx + tox;
01838 vec[index].y3 = cury + toy;
01839
01840 curx += tox;
01841 cury += toy;
01842
01843 lastCommand =
'l';
01844
break;
01845
case 'L':
01846 ptr = getCoord(ptr, tox);
01847 ptr = getCoord(ptr, toy);
01848
01849 index++;
01850
01851 d->helper->ensureSpace(vec, index);
01852
01853 vec[index].code = ART_LINETO;
01854 vec[index].x3 = tox;
01855 vec[index].y3 = toy;
01856
01857 curx = tox;
01858 cury = toy;
01859
01860 lastCommand =
'L';
01861
break;
01862
case 'h':
01863 ptr = getCoord(ptr, tox);
01864
01865 index++;
01866
01867 curx += tox;
01868
01869 d->helper->ensureSpace(vec, index);
01870
01871 vec[index].code = ART_LINETO;
01872 vec[index].x3 = curx;
01873 vec[index].y3 = cury;
01874
01875 lastCommand =
'h';
01876
break;
01877
case 'H':
01878 ptr = getCoord(ptr, tox);
01879
01880 index++;
01881
01882 curx = tox;
01883
01884 d->helper->ensureSpace(vec, index);
01885
01886 vec[index].code = ART_LINETO;
01887 vec[index].x3 = curx;
01888 vec[index].y3 = cury;
01889
01890 lastCommand =
'H';
01891
break;
01892
case 'v':
01893 ptr = getCoord(ptr, toy);
01894
01895 index++;
01896
01897 cury += toy;
01898
01899 d->helper->ensureSpace(vec, index);
01900
01901 vec[index].code = ART_LINETO;
01902 vec[index].x3 = curx;
01903 vec[index].y3 = cury;
01904
01905 lastCommand =
'v';
01906
break;
01907
case 'V':
01908 ptr = getCoord(ptr, toy);
01909
01910 index++;
01911
01912 cury = toy;
01913
01914 d->helper->ensureSpace(vec, index);
01915
01916 vec[index].code = ART_LINETO;
01917 vec[index].x3 = curx;
01918 vec[index].y3 = cury;
01919
01920 lastCommand =
'V';
01921
break;
01922
case 'c':
01923 ptr = getCoord(ptr, x1);
01924 ptr = getCoord(ptr, y1);
01925 ptr = getCoord(ptr, x2);
01926 ptr = getCoord(ptr, y2);
01927 ptr = getCoord(ptr, tox);
01928 ptr = getCoord(ptr, toy);
01929
01930 index++;
01931
01932 d->helper->ensureSpace(vec, index);
01933
01934 vec[index].code = ART_CURVETO;
01935 vec[index].x1 = curx + x1;
01936 vec[index].y1 = cury + y1;
01937 vec[index].x2 = curx + x2;
01938 vec[index].y2 = cury + y2;
01939 vec[index].x3 = curx + tox;
01940 vec[index].y3 = cury + toy;
01941
01942 curx += tox;
01943 cury += toy;
01944
01945 contrlx = vec[index].x2;
01946 contrly = vec[index].y2;
01947
01948 lastCommand =
'c';
01949
break;
01950
case 'C':
01951 ptr = getCoord(ptr, x1);
01952 ptr = getCoord(ptr, y1);
01953 ptr = getCoord(ptr, x2);
01954 ptr = getCoord(ptr, y2);
01955 ptr = getCoord(ptr, tox);
01956 ptr = getCoord(ptr, toy);
01957
01958 index++;
01959
01960 d->helper->ensureSpace(vec, index);
01961
01962 vec[index].code = ART_CURVETO;
01963 vec[index].x1 = x1;
01964 vec[index].y1 = y1;
01965 vec[index].x2 = x2;
01966 vec[index].y2 = y2;
01967 vec[index].x3 = tox;
01968 vec[index].y3 = toy;
01969
01970 curx = vec[index].x3;
01971 cury = vec[index].y3;
01972 contrlx = vec[index].x2;
01973 contrly = vec[index].y2;
01974
01975 lastCommand =
'C';
01976
break;
01977
case 's':
01978 ptr = getCoord(ptr, x2);
01979 ptr = getCoord(ptr, y2);
01980 ptr = getCoord(ptr, tox);
01981 ptr = getCoord(ptr, toy);
01982
01983 index++;
01984
01985 d->helper->ensureSpace(vec, index);
01986
01987 vec[index].code = ART_CURVETO;
01988 vec[index].x1 = 2 * curx - contrlx;
01989 vec[index].y1 = 2 * cury - contrly;
01990 vec[index].x2 = curx + x2;
01991 vec[index].y2 = cury + y2;
01992 vec[index].x3 = curx + tox;
01993 vec[index].y3 = cury + toy;
01994
01995 curx += tox;
01996 cury += toy;
01997
01998 contrlx = vec[index].x2;
01999 contrly = vec[index].y2;
02000
02001 lastCommand =
's';
02002
break;
02003
case 'S':
02004 ptr = getCoord(ptr, x2);
02005 ptr = getCoord(ptr, y2);
02006 ptr = getCoord(ptr, tox);
02007 ptr = getCoord(ptr, toy);
02008
02009 index++;
02010
02011 d->helper->ensureSpace(vec, index);
02012
02013 vec[index].code = ART_CURVETO;
02014 vec[index].x1 = 2 * curx - contrlx;
02015 vec[index].y1 = 2 * cury - contrly;
02016 vec[index].x2 = x2;
02017 vec[index].y2 = y2;
02018 vec[index].x3 = tox;
02019 vec[index].y3 = toy;
02020
02021 curx = vec[index].x3;
02022 cury = vec[index].y3;
02023 contrlx = vec[index].x2;
02024 contrly = vec[index].y2;
02025
02026 lastCommand =
'S';
02027
break;
02028
case 'q':
02029 ptr = getCoord(ptr, x1);
02030 ptr = getCoord(ptr, y1);
02031 ptr = getCoord(ptr, tox);
02032 ptr = getCoord(ptr, toy);
02033
02034 index++;
02035
02036 d->helper->ensureSpace(vec, index);
02037
02038 vec[index].code = ART_CURVETO;
02039 vec[index].x1 = (curx + 2 * (x1 + curx)) * (1.0 / 3.0);
02040 vec[index].y1 = (cury + 2 * (y1 + cury)) * (1.0 / 3.0);
02041 vec[index].x2 = ((curx + tox) + 2 * (x1 + curx)) * (1.0 / 3.0);
02042 vec[index].y2 = ((cury + toy) + 2 * (y1 + cury)) * (1.0 / 3.0);
02043 vec[index].x3 = curx + tox;
02044 vec[index].y3 = cury + toy;
02045
02046 contrlx = curx + x1;
02047 contrly = cury + y1;
02048 curx += tox;
02049 cury += toy;
02050
02051 lastCommand =
'q';
02052
break;
02053
case 'Q':
02054 ptr = getCoord(ptr, x1);
02055 ptr = getCoord(ptr, y1);
02056 ptr = getCoord(ptr, tox);
02057 ptr = getCoord(ptr, toy);
02058
02059 index++;
02060
02061 d->helper->ensureSpace(vec, index);
02062
02063
02064 vec[index].code = ART_CURVETO;
02065 vec[index].x1 = (curx + 2 * x1) * (1.0 / 3.0);
02066 vec[index].y1 = (cury + 2 * y1) * (1.0 / 3.0);
02067 vec[index].x2 = (tox + 2 * x1) * (1.0 / 3.0);
02068 vec[index].y2 = (toy + 2 * y1) * (1.0 / 3.0);
02069 vec[index].x3 = tox;
02070 vec[index].y3 = toy;
02071
02072 curx = vec[index].x3;
02073 cury = vec[index].y3;
02074 contrlx = vec[index].x2;
02075 contrly = vec[index].y2;
02076
02077 lastCommand =
'Q';
02078
break;
02079
case 't':
02080 ptr = getCoord(ptr, tox);
02081 ptr = getCoord(ptr, toy);
02082
02083 xc = 2 * curx - contrlx;
02084 yc = 2 * cury - contrly;
02085
02086 index++;
02087
02088 d->helper->ensureSpace(vec, index);
02089
02090 vec[index].code = ART_CURVETO;
02091 vec[index].x1 = (curx + 2 * xc) * (1.0 / 3.0);
02092 vec[index].y1 = (cury + 2 * yc) * (1.0 / 3.0);
02093 vec[index].x2 = ((curx + tox) + 2 * xc) * (1.0 / 3.0);
02094 vec[index].y2 = ((cury + toy) + 2 * yc) * (1.0 / 3.0);
02095
02096 vec[index].x3 = curx + tox;
02097 vec[index].y3 = cury + toy;
02098
02099 curx += tox;
02100 cury += toy;
02101 contrlx = xc;
02102 contrly = yc;
02103
02104 lastCommand =
't';
02105
break;
02106
case 'T':
02107 ptr = getCoord(ptr, tox);
02108 ptr = getCoord(ptr, toy);
02109
02110 xc = 2 * curx - contrlx;
02111 yc = 2 * cury - contrly;
02112
02113 index++;
02114
02115 d->helper->ensureSpace(vec, index);
02116
02117 vec[index].code = ART_CURVETO;
02118 vec[index].x1 = (curx + 2 * xc) * (1.0 / 3.0);
02119 vec[index].y1 = (cury + 2 * yc) * (1.0 / 3.0);
02120 vec[index].x2 = (tox + 2 * xc) * (1.0 / 3.0);
02121 vec[index].y2 = (toy + 2 * yc) * (1.0 / 3.0);
02122 vec[index].x3 = tox;
02123 vec[index].y3 = toy;
02124
02125 curx = tox;
02126 cury = toy;
02127 contrlx = xc;
02128 contrly = yc;
02129
02130 lastCommand =
'T';
02131
break;
02132
case 'z':
02133
case 'Z':
02134
int find;
02135
find = -1;
02136
for(
int i = index; i >= 0; i--)
02137 {
02138
if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO)
02139 {
02140
find = i;
02141
break;
02142 }
02143 }
02144
02145
if(
find != -1)
02146 {
02147
if(vec[
find].x3 != curx || vec[
find].y3 != cury)
02148 {
02149 index++;
02150
02151 d->helper->ensureSpace(vec, index);
02152
02153 vec[index].code = ART_LINETO;
02154 vec[index].x3 = vec[
find].x3;
02155 vec[index].y3 = vec[
find].y3;
02156 }
02157 }
02158
02159
02160 curx = vec[
find].x3;
02161 cury = vec[
find].y3;
02162
02163 lastCommand =
'z';
02164
break;
02165
case 'a':
02166 ptr = getCoord(ptr, rx);
02167 ptr = getCoord(ptr, ry);
02168 ptr = getCoord(ptr, angle);
02169 ptr = getCoord(ptr, tox);
02170 largeArc = tox == 1;
02171 ptr = getCoord(ptr, tox);
02172 sweep = tox == 1;
02173 ptr = getCoord(ptr, tox);
02174 ptr = getCoord(ptr, toy);
02175
02176
02177 rx = fabs(rx);
02178 ry = fabs(ry);
02179
02180 d->helper->calculateArc(
true, vec, index, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep);
02181
02182 lastCommand =
'a';
02183
break;
02184
case 'A':
02185 ptr = getCoord(ptr, rx);
02186 ptr = getCoord(ptr, ry);
02187 ptr = getCoord(ptr, angle);
02188 ptr = getCoord(ptr, tox);
02189 largeArc = tox == 1;
02190 ptr = getCoord(ptr, tox);
02191 sweep = tox == 1;
02192 ptr = getCoord(ptr, tox);
02193 ptr = getCoord(ptr, toy);
02194
02195
02196 rx = fabs(rx);
02197 ry = fabs(ry);
02198
02199 d->helper->calculateArc(
false, vec, index, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep);
02200
02201 lastCommand =
'A';
02202
break;
02203 }
02204
02205
if(*ptr ==
'+' || *ptr ==
'-' || (*ptr >=
'0' && *ptr <=
'9'))
02206 {
02207
02208
if(command ==
'M')
02209 command =
'L';
02210
else if(command ==
'm')
02211 command =
'l';
02212 }
02213
else
02214 command = *(ptr++);
02215
02216
02217
if(lastCommand !=
'C' && lastCommand !=
'c' &&
02218 lastCommand !=
'S' && lastCommand !=
's' &&
02219 lastCommand !=
'Q' && lastCommand !=
'q' &&
02220 lastCommand !=
'T' && lastCommand !=
't')
02221 {
02222 contrlx = curx;
02223 contrly = cury;
02224 }
02225 }
02226
02227
02228
int find = -1;
02229
for(
int i = index; i >= 0; i--)
02230 {
02231
if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO)
02232 {
02233
find = i;
02234
break;
02235 }
02236 }
02237
02238
02239
if(curx != vec[
find].x3 && cury != vec[
find].y3)
02240 {
02241
if((
int) curx == (
int) vec[
find].x3 && (
int) cury == (
int) vec[
find].y3)
02242 {
02243 index++;
02244
02245
if(vec.size() == (
unsigned int) index)
02246 vec.resize(index + 1);
02247
02248 vec[index].code = ART_LINETO;
02249 vec[index].x3 = vec[
find].x3;
02250 vec[index].y3 = vec[
find].y3;
02251
02252 curx = vec[
find].x3;
02253 cury = vec[
find].y3;
02254 }
02255 }
02256
02257
02258
if(filled)
02259 {
02260
if((
int) curx != (
int) vec[
find].x3 || (
int) cury != (
int) vec[
find].y3)
02261 {
02262 index++;
02263
02264
if(vec.size() == (
unsigned int) index)
02265 vec.resize(index + 1);
02266
02267 vec[index].code = (ArtPathcode)ART_END2;
02268 vec[index].x3 = vec[
find].x3;
02269 vec[index].y3 = vec[
find].y3;
02270
02271 curx = vec[
find].x3;
02272 cury = vec[
find].y3;
02273 }
02274 }
02275
02276
02277 index++;
02278
02279
if(vec.size() == (
unsigned int) index)
02280 vec.resize(index + 1);
02281
02282 vec[index].code = ART_END;
02283
02284
02285
02286
bool render =
false;
02287
for(
int i = index; i >= 0; i--)
02288 {
02289
if(vec[i].code != ART_MOVETO_OPEN && vec[i].code != ART_MOVETO && !(vec[i].code >= ART_END))
02290 {
02291 render =
true;
02292
break;
02293 }
02294 }
02295
02296
if(render)
02297 d->helper->drawBPath(vec.data());
02298 }
02299 }
02300
02301
void KSVGIconPainter::drawImage(
double x,
double y,
QImage &image)
02302 {
02303
if(image.depth() != 32)
02304 image = image.convertDepth(32);
02305
02306
double affine[6];
02307 affine[0] = d->helper->m_worldMatrix->m11();
02308 affine[1] = d->helper->m_worldMatrix->m12();
02309 affine[2] = d->helper->m_worldMatrix->m21();
02310 affine[3] = d->helper->m_worldMatrix->m22();
02311 affine[4] = d->helper->m_worldMatrix->dx() + x;
02312 affine[5] = d->helper->m_worldMatrix->dy() + y;
02313
02314 d->helper->art_rgba_rgba_affine(d->helper->m_buffer, 0, 0, d->helper->m_width, d->helper->m_height,
02315 d->helper->m_rowstride, image.bits(), image.width(), image.height(),
02316 image.width() * 4, affine);
02317 }
02318
02319
QColor KSVGIconPainter::parseColor(
const QString ¶m)
02320 {
02321
if(param.stripWhiteSpace().startsWith(
"#"))
02322 {
02323
QColor color;
02324 color.setNamedColor(param.stripWhiteSpace());
02325
return color;
02326 }
02327
else if(param.stripWhiteSpace().startsWith(
"rgb("))
02328 {
02329
QString parse = param.stripWhiteSpace();
02330
QStringList colors = QStringList::split(
',', parse);
02331
QString r = colors[0].right((colors[0].length() - 4));
02332
QString g = colors[1];
02333
QString b = colors[2].left((colors[2].length() - 1));
02334
02335
if(r.contains(
"%"))
02336 {
02337 r = r.left(r.length() - 1);
02338 r = QString::number(
int((
double(255 * r.toDouble()) / 100.0)));
02339 }
02340
02341
if(g.contains(
"%"))
02342 {
02343 g = g.left(g.length() - 1);
02344 g = QString::number(
int((
double(255 * g.toDouble()) / 100.0)));
02345 }
02346
02347
if(b.contains(
"%"))
02348 {
02349 b = b.left(b.length() - 1);
02350 b = QString::number(
int((
double(255 * b.toDouble()) / 100.0)));
02351 }
02352
02353
return QColor(r.toInt(), g.toInt(), b.toInt());
02354 }
02355
else
02356 {
02357
QString rgbColor = param.stripWhiteSpace();
02358
02359
if(rgbColor ==
"aliceblue")
02360
return QColor(240, 248, 255);
02361
else if(rgbColor ==
"antiquewhite")
02362
return QColor(250, 235, 215);
02363
else if(rgbColor ==
"aqua")
02364
return QColor(0, 255, 255);
02365
else if(rgbColor ==
"aquamarine")
02366
return QColor(127, 255, 212);
02367
else if(rgbColor ==
"azure")
02368
return QColor(240, 255, 255);
02369
else if(rgbColor ==
"beige")
02370
return QColor(245, 245, 220);
02371
else if(rgbColor ==
"bisque")
02372
return QColor(255, 228, 196);
02373
else if(rgbColor ==
"black")
02374
return QColor(0, 0, 0);
02375
else if(rgbColor ==
"blanchedalmond")
02376
return QColor(255, 235, 205);
02377
else if(rgbColor ==
"blue")
02378
return QColor(0, 0, 255);
02379
else if(rgbColor ==
"blueviolet")
02380
return QColor(138, 43, 226);
02381
else if(rgbColor ==
"brown")
02382
return QColor(165, 42, 42);
02383
else if(rgbColor ==
"burlywood")
02384
return QColor(222, 184, 135);
02385
else if(rgbColor ==
"cadetblue")
02386
return QColor(95, 158, 160);
02387
else if(rgbColor ==
"chartreuse")
02388
return QColor(127, 255, 0);
02389
else if(rgbColor ==
"chocolate")
02390
return QColor(210, 105, 30);
02391
else if(rgbColor ==
"coral")
02392
return QColor(255, 127, 80);
02393
else if(rgbColor ==
"cornflowerblue")
02394
return QColor(100, 149, 237);
02395
else if(rgbColor ==
"cornsilk")
02396
return QColor(255, 248, 220);
02397
else if(rgbColor ==
"crimson")
02398
return QColor(220, 20, 60);
02399
else if(rgbColor ==
"cyan")
02400
return QColor(0, 255, 255);
02401
else if(rgbColor ==
"darkblue")
02402
return QColor(0, 0, 139);
02403
else if(rgbColor ==
"darkcyan")
02404
return QColor(0, 139, 139);
02405
else if(rgbColor ==
"darkgoldenrod")
02406
return QColor(184, 134, 11);
02407
else if(rgbColor ==
"darkgray")
02408
return QColor(169, 169, 169);
02409
else if(rgbColor ==
"darkgrey")
02410
return QColor(169, 169, 169);
02411
else if(rgbColor ==
"darkgreen")
02412
return QColor(0, 100, 0);
02413
else if(rgbColor ==
"darkkhaki")
02414
return QColor(189, 183, 107);
02415
else if(rgbColor ==
"darkmagenta")
02416
return QColor(139, 0, 139);
02417
else if(rgbColor ==
"darkolivegreen")
02418
return QColor(85, 107, 47);
02419
else if(rgbColor ==
"darkorange")
02420
return QColor(255, 140, 0);
02421
else if(rgbColor ==
"darkorchid")
02422
return QColor(153, 50, 204);
02423
else if(rgbColor ==
"darkred")
02424
return QColor(139, 0, 0);
02425
else if(rgbColor ==
"darksalmon")
02426
return QColor(233, 150, 122);
02427
else if(rgbColor ==
"darkseagreen")
02428
return QColor(143, 188, 143);
02429
else if(rgbColor ==
"darkslateblue")
02430
return QColor(72, 61, 139);
02431
else if(rgbColor ==
"darkslategray")
02432
return QColor(47, 79, 79);
02433
else if(rgbColor ==
"darkslategrey")
02434
return QColor(47, 79, 79);
02435
else if(rgbColor ==
"darkturquoise")
02436
return QColor(0, 206, 209);
02437
else if(rgbColor ==
"darkviolet")
02438
return QColor(148, 0, 211);
02439
else if(rgbColor ==
"deeppink")
02440
return QColor(255, 20, 147);
02441
else if(rgbColor ==
"deepskyblue")
02442
return QColor(0, 191, 255);
02443
else if(rgbColor ==
"dimgray")
02444
return QColor(105, 105, 105);
02445
else if(rgbColor ==
"dimgrey")
02446
return QColor(105, 105, 105);
02447
else if(rgbColor ==
"dodgerblue")
02448
return QColor(30, 144, 255);
02449
else if(rgbColor ==
"firebrick")
02450
return QColor(178, 34, 34);
02451
else if(rgbColor ==
"floralwhite")
02452
return QColor(255, 250, 240);
02453
else if(rgbColor ==
"forestgreen")
02454
return QColor(34, 139, 34);
02455
else if(rgbColor ==
"fuchsia")
02456
return QColor(255, 0, 255);
02457
else if(rgbColor ==
"gainsboro")
02458
return QColor(220, 220, 220);
02459
else if(rgbColor ==
"ghostwhite")
02460
return QColor(248, 248, 255);
02461
else if(rgbColor ==
"gold")
02462
return QColor(255, 215, 0);
02463
else if(rgbColor ==
"goldenrod")
02464
return QColor(218, 165, 32);
02465
else if(rgbColor ==
"gray")
02466
return QColor(128, 128, 128);
02467
else if(rgbColor ==
"grey")
02468
return QColor(128, 128, 128);
02469
else if(rgbColor ==
"green")
02470
return QColor(0, 128, 0);
02471
else if(rgbColor ==
"greenyellow")
02472
return QColor(173, 255, 47);
02473
else if(rgbColor ==
"honeydew")
02474
return QColor(240, 255, 240);
02475
else if(rgbColor ==
"hotpink")
02476
return QColor(255, 105, 180);
02477
else if(rgbColor ==
"indianred")
02478
return QColor(205, 92, 92);
02479
else if(rgbColor ==
"indigo")
02480
return QColor(75, 0, 130);
02481
else if(rgbColor ==
"ivory")
02482
return QColor(255, 255, 240);
02483
else if(rgbColor ==
"khaki")
02484
return QColor(240, 230, 140);
02485
else if(rgbColor ==
"lavender")
02486
return QColor(230, 230, 250);
02487
else if(rgbColor ==
"lavenderblush")
02488
return QColor(255, 240, 245);
02489
else if(rgbColor ==
"lawngreen")
02490
return QColor(124, 252, 0);
02491
else if(rgbColor ==
"lemonchiffon")
02492
return QColor(255, 250, 205);
02493
else if(rgbColor ==
"lightblue")
02494
return QColor(173, 216, 230);
02495
else if(rgbColor ==
"lightcoral")
02496
return QColor(240, 128, 128);
02497
else if(rgbColor ==
"lightcyan")
02498
return QColor(224, 255, 255);
02499
else if(rgbColor ==
"lightgoldenrodyellow")
02500
return QColor(250, 250, 210);
02501
else if(rgbColor ==
"lightgray")
02502
return QColor(211, 211, 211);
02503
else if(rgbColor ==
"lightgrey")
02504
return QColor(211, 211, 211);
02505
else if(rgbColor ==
"lightgreen")
02506
return QColor(144, 238, 144);
02507
else if(rgbColor ==
"lightpink")
02508
return QColor(255, 182, 193);
02509
else if(rgbColor ==
"lightsalmon")
02510
return QColor(255, 160, 122);
02511
else if(rgbColor ==
"lightseagreen")
02512
return QColor(32, 178, 170);
02513
else if(rgbColor ==
"lightskyblue")
02514
return QColor(135, 206, 250);
02515
else if(rgbColor ==
"lightslategray")
02516
return QColor(119, 136, 153);
02517
else if(rgbColor ==
"lightslategrey")
02518
return QColor(119, 136, 153);
02519
else if(rgbColor ==
"lightsteelblue")
02520
return QColor(176, 196, 222);
02521
else if(rgbColor ==
"lightyellow")
02522
return QColor(255, 255, 224);
02523
else if(rgbColor ==
"lime")
02524
return QColor(0, 255, 0);
02525
else if(rgbColor ==
"limegreen")
02526
return QColor(50, 205, 50);
02527
else if(rgbColor ==
"linen")
02528
return QColor(250, 240, 230);
02529
else if(rgbColor ==
"magenta")
02530
return QColor(255, 0, 255);
02531
else if(rgbColor ==
"maroon")
02532
return QColor(128, 0, 0);
02533
else if(rgbColor ==
"mediumaquamarine")
02534
return QColor(102, 205, 170);
02535
else if(rgbColor ==
"mediumblue")
02536
return QColor(0, 0, 205);
02537
else if(rgbColor ==
"mediumorchid")
02538
return QColor(186, 85, 211);
02539
else if(rgbColor ==
"mediumpurple")
02540
return QColor(147, 112, 219);
02541
else if(rgbColor ==
"mediumseagreen")
02542
return QColor(60, 179, 113);
02543
else if(rgbColor ==
"mediumslateblue")
02544
return QColor(123, 104, 238);
02545
else if(rgbColor ==
"mediumspringgreen")
02546
return QColor(0, 250, 154);
02547
else if(rgbColor ==
"mediumturquoise")
02548
return QColor(72, 209, 204);
02549
else if(rgbColor ==
"mediumvioletred")
02550
return QColor(199, 21, 133);
02551
else if(rgbColor ==
"midnightblue")
02552
return QColor(25, 25, 112);
02553
else if(rgbColor ==
"mintcream")
02554
return QColor(245, 255, 250);
02555
else if(rgbColor ==
"mistyrose")
02556
return QColor(255, 228, 225);
02557
else if(rgbColor ==
"moccasin")
02558
return QColor(255, 228, 181);
02559
else if(rgbColor ==
"navajowhite")
02560
return QColor(255, 222, 173);
02561
else if(rgbColor ==
"navy")
02562
return QColor(0, 0, 128);
02563
else if(rgbColor ==
"oldlace")
02564
return QColor(253, 245, 230);
02565
else if(rgbColor ==
"olive")
02566
return QColor(128, 128, 0);
02567
else if(rgbColor ==
"olivedrab")
02568
return QColor(107, 142, 35);
02569
else if(rgbColor ==
"orange")
02570
return QColor(255, 165, 0);
02571
else if(rgbColor ==
"orangered")
02572
return QColor(255, 69, 0);
02573
else if(rgbColor ==
"orchid")
02574
return QColor(218, 112, 214);
02575
else if(rgbColor ==
"palegoldenrod")
02576
return QColor(238, 232, 170);
02577
else if(rgbColor ==
"palegreen")
02578
return QColor(152, 251, 152);
02579
else if(rgbColor ==
"paleturquoise")
02580
return QColor(175, 238, 238);
02581
else if(rgbColor ==
"palevioletred")
02582
return QColor(219, 112, 147);
02583
else if(rgbColor ==
"papayawhip")
02584
return QColor(255, 239, 213);
02585
else if(rgbColor ==
"peachpuff")
02586
return QColor(255, 218, 185);
02587
else if(rgbColor ==
"peru")
02588
return QColor(205, 133, 63);
02589
else if(rgbColor ==
"pink")
02590
return QColor(255, 192, 203);
02591
else if(rgbColor ==
"plum")
02592
return QColor(221, 160, 221);
02593
else if(rgbColor ==
"powderblue")
02594
return QColor(176, 224, 230);
02595
else if(rgbColor ==
"purple")
02596
return QColor(128, 0, 128);
02597
else if(rgbColor ==
"red")
02598
return QColor(255, 0, 0);
02599
else if(rgbColor ==
"rosybrown")
02600
return QColor(188, 143, 143);
02601
else if(rgbColor ==
"royalblue")
02602
return QColor(65, 105, 225);
02603
else if(rgbColor ==
"saddlebrown")
02604
return QColor(139, 69, 19);
02605
else if(rgbColor ==
"salmon")
02606
return QColor(250, 128, 114);
02607
else if(rgbColor ==
"sandybrown")
02608
return QColor(244, 164, 96);
02609
else if(rgbColor ==
"seagreen")
02610
return QColor(46, 139, 87);
02611
else if(rgbColor ==
"seashell")
02612
return QColor(255, 245, 238);
02613
else if(rgbColor ==
"sienna")
02614
return QColor(160, 82, 45);
02615
else if(rgbColor ==
"silver")
02616
return QColor(192, 192, 192);
02617
else if(rgbColor ==
"skyblue")
02618
return QColor(135, 206, 235);
02619
else if(rgbColor ==
"slateblue")
02620
return QColor(106, 90, 205);
02621
else if(rgbColor ==
"slategray")
02622
return QColor(112, 128, 144);
02623
else if(rgbColor ==
"slategrey")
02624
return QColor(112, 128, 144);
02625
else if(rgbColor ==
"snow")
02626
return QColor(255, 250, 250);
02627
else if(rgbColor ==
"springgreen")
02628
return QColor(0, 255, 127);
02629
else if(rgbColor ==
"steelblue")
02630
return QColor(70, 130, 180);
02631
else if(rgbColor ==
"tan")
02632
return QColor(210, 180, 140);
02633
else if(rgbColor ==
"teal")
02634
return QColor(0, 128, 128);
02635
else if(rgbColor ==
"thistle")
02636
return QColor(216, 191, 216);
02637
else if(rgbColor ==
"tomato")
02638
return QColor(255, 99, 71);
02639
else if(rgbColor ==
"turquoise")
02640
return QColor(64, 224, 208);
02641
else if(rgbColor ==
"violet")
02642
return QColor(238, 130, 238);
02643
else if(rgbColor ==
"wheat")
02644
return QColor(245, 222, 179);
02645
else if(rgbColor ==
"white")
02646
return QColor(255, 255, 255);
02647
else if(rgbColor ==
"whitesmoke")
02648
return QColor(245, 245, 245);
02649
else if(rgbColor ==
"yellow")
02650
return QColor(255, 255, 0);
02651
else if(rgbColor ==
"yellowgreen")
02652
return QColor(154, 205, 50);
02653 }
02654
02655
return QColor();
02656 }
02657
02658
double KSVGIconPainter::dpi()
02659 {
02660
return 90.0;
02661 }
02662
02663
double KSVGIconPainter::toPixel(
const QString &s,
bool hmode)
02664 {
02665
if(s.isEmpty())
02666
return 0.0;
02667
02668
QString check = s;
02669
02670
double ret = 0.0;
02671
02672
double value = 0;
02673
const char *start = check.latin1();
02674
const char *
end = getCoord(start, value);
02675
02676
if(uint(end - start) < check.length())
02677 {
02678
if(check.endsWith(
"px"))
02679 ret = value;
02680
else if(check.endsWith(
"cm"))
02681 ret = (value / 2.54) * dpi();
02682
else if(check.endsWith(
"pc"))
02683 ret = (value / 6.0) * dpi();
02684
else if(check.endsWith(
"mm"))
02685 ret = (value / 25.4) * dpi();
02686
else if(check.endsWith(
"in"))
02687 ret = value * dpi();
02688
else if(check.endsWith(
"pt"))
02689 ret = (value / 72.0) * dpi();
02690
else if(check.endsWith(
"%"))
02691 {
02692 ret = value / 100.0;
02693
02694
if(hmode)
02695 ret *= d->drawWidth;
02696
else
02697 ret *= d->drawHeight;
02698 }
02699
else if(check.endsWith(
"em"))
02700 {
02701 ret = value * 10.0;
02702 }
02703 }
02704
else
02705 ret = value;
02706
02707
return ret;
02708 }
02709
02710 ArtGradientLinear *KSVGIconPainter::linearGradient(
const QString &
id)
02711 {
02712
return d->helper->m_linearGradientMap[
id];
02713 }
02714
02715
void KSVGIconPainter::addLinearGradient(
const QString &
id, ArtGradientLinear *gradient)
02716 {
02717 d->helper->m_linearGradientMap.insert(
id, gradient);
02718 }
02719
02720
QDomElement KSVGIconPainter::linearGradientElement(ArtGradientLinear *linear)
02721 {
02722
return d->helper->m_linearGradientElementMap[linear];
02723 }
02724
02725
void KSVGIconPainter::addLinearGradientElement(ArtGradientLinear *gradient,
QDomElement element)
02726 {
02727 d->helper->m_linearGradientElementMap.insert(gradient, element);
02728 }
02729
02730 ArtGradientRadial *KSVGIconPainter::radialGradient(
const QString &
id)
02731 {
02732
return d->helper->m_radialGradientMap[
id];
02733 }
02734
02735
void KSVGIconPainter::addRadialGradient(
const QString &
id, ArtGradientRadial *gradient)
02736 {
02737 d->helper->m_radialGradientMap.insert(
id, gradient);
02738 }
02739
02740
QDomElement KSVGIconPainter::radialGradientElement(ArtGradientRadial *radial)
02741 {
02742
return d->helper->m_radialGradientElementMap[radial];
02743 }
02744
02745
void KSVGIconPainter::addRadialGradientElement(ArtGradientRadial *gradient,
QDomElement element)
02746 {
02747 d->helper->m_radialGradientElementMap.insert(gradient, element);
02748 }
02749
02750 Q_UINT32 KSVGIconPainter::toArtColor(
const QColor &color)
02751 {
02752
return d->helper->toArtColor(color);
02753 }
02754
02755
QWMatrix KSVGIconPainter::parseTransform(
const QString &transform)
02756 {
02757
QWMatrix result;
02758
02759
02760
QStringList subtransforms = QStringList::split(
')', transform);
02761 QStringList::ConstIterator it = subtransforms.begin();
02762 QStringList::ConstIterator
end = subtransforms.end();
02763
for(; it !=
end; ++it)
02764 {
02765
QStringList subtransform = QStringList::split(
'(', (*it));
02766
02767 subtransform[0] = subtransform[0].stripWhiteSpace().lower();
02768 subtransform[1] = subtransform[1].simplifyWhiteSpace();
02769
QRegExp reg(
"([-]?\\d*\\.?\\d+(?:e[-]?\\d+)?)");
02770
02771
int pos = 0;
02772
QStringList params;
02773
02774
while(pos >= 0)
02775 {
02776 pos = reg.search(subtransform[1], pos);
02777
if(pos != -1)
02778 {
02779 params += reg.cap(1);
02780 pos += reg.matchedLength();
02781 }
02782 }
02783
02784
if(subtransform[0].startsWith(
";") || subtransform[0].startsWith(
","))
02785 subtransform[0] = subtransform[0].right(subtransform[0].length() - 1);
02786
02787
if(subtransform[0] ==
"rotate")
02788 {
02789
if(params.count() == 3)
02790 {
02791
double x = params[1].toDouble();
02792
double y = params[2].toDouble();
02793
02794 result.translate(x, y);
02795 result.rotate(params[0].toDouble());
02796 result.translate(-x, -y);
02797 }
02798
else
02799 result.rotate(params[0].toDouble());
02800 }
02801
else if(subtransform[0] ==
"translate")
02802 {
02803
if(params.count() == 2)
02804 result.translate(params[0].toDouble(), params[1].toDouble());
02805
else
02806 result.translate(params[0].toDouble() , 0);
02807 }
02808
else if(subtransform[0] ==
"scale")
02809 {
02810
if(params.count() == 2)
02811 result.scale(params[0].toDouble(), params[1].toDouble());
02812
else
02813 result.scale(params[0].toDouble(), params[0].toDouble());
02814 }
02815
else if(subtransform[0] ==
"skewx")
02816 result.shear(tan(params[0].toDouble() * deg2rad), 0.0F);
02817
else if(subtransform[0] ==
"skewy")
02818 result.shear(tan(params[0].toDouble() * deg2rad), 0.0F);
02819
else if(subtransform[0] ==
"skewy")
02820 result.shear(0.0F, tan(params[0].toDouble() * deg2rad));
02821
else if(subtransform[0] ==
"matrix")
02822 {
02823
if(params.count() >= 6)
02824 {
02825 result.setMatrix(params[0].toDouble(), params[1].toDouble(), params[2].toDouble(), params[3].toDouble(), params[4].toDouble(), params[5].toDouble());
02826 }
02827 }
02828 }
02829
02830
return result;
02831 }