• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

  • tdecore
  • svgicons
ksvgiconpainter.cpp
1/*
2 Copyright (C) 2002 Nikolas Zimmermann <wildfox@kde.org>
3 This file is part of the KDE project
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 aint with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21#include <tqvaluevector.h>
22#include <tqstringlist.h>
23#include <tqwmatrix.h>
24#include <tqregexp.h>
25#include <tqimage.h>
26#include <tqdict.h>
27#include <tqmap.h>
28#include <tqdom.h>
29
30#include <math.h>
31
32#include <kdebug.h>
33
34#include <libart_lgpl/art_rgba.h>
35#include <libart_lgpl/art_bpath.h>
36#include <libart_lgpl/art_vpath.h>
37#include <libart_lgpl/art_vpath_dash.h>
38#include <libart_lgpl/art_affine.h>
39#include <libart_lgpl/art_render_svp.h>
40#include <libart_lgpl/art_svp.h>
41#include <libart_lgpl/art_svp_vpath.h>
42#include <libart_lgpl/art_svp_intersect.h>
43#include <libart_lgpl/art_svp_vpath_stroke.h>
44
45#include "ksvgiconpainter.h"
46
47#define ART_END2 10
48
49const double deg2rad = 0.017453292519943295769; // pi/180
50
51class KSVGIconPainterHelper
52{
53public:
54 KSVGIconPainterHelper(int width, int height, KSVGIconPainter *painter)
55 {
56 m_painter = painter;
57
58 m_clipSVP = 0;
59
60 m_fillColor = TQt::black;
61
62 m_useFill = true;
63 m_useStroke = false;
64
65 m_useFillGradient = false;
66 m_useStrokeGradient = false;
67
68 m_worldMatrix = new TQWMatrix();
69
70 // Create new image with alpha support
71 m_image = new TQImage(width, height, 32);
72 m_image->setAlphaBuffer(true);
73
74 m_strokeWidth = 1.0;
75 m_strokeMiterLimit = 4;
76 m_dashOffset = 0;
77 m_dashes = "";
78
79 m_opacity = 0xff;
80 m_fillOpacity = 0xff;
81 m_strokeOpacity = 0xff;
82
83 m_fillRule = "nonzero";
84
85 m_width = width;
86 m_height = height;
87
88 m_rowstride = m_width * 4;
89
90 // Make internal libart rendering buffer transparent
91 m_buffer = art_new(art_u8, m_rowstride * m_height);
92 memset(m_buffer, 0, m_rowstride * m_height);
93
94 m_tempBuffer = 0;
95 }
96
97 ~KSVGIconPainterHelper()
98 {
99 if(m_clipSVP)
100 art_svp_free(m_clipSVP);
101
102 art_free(m_buffer);
103
104 delete m_image;
105 delete m_worldMatrix;
106
107 for(TQMap<TQString, ArtGradientLinear *>::Iterator it = m_linearGradientMap.begin(); it != m_linearGradientMap.end(); ++it)
108 {
109 if (!it.data())
110 continue;
111 delete [] it.data()->stops;
112 delete it.data();
113 }
114 for(TQMap<TQString, ArtGradientRadial *>::Iterator it = m_radialGradientMap.begin(); it != m_radialGradientMap.end(); ++it)
115 {
116 if (!it.data())
117 continue;
118 delete [] it.data()->stops;
119 delete it.data();
120 }
121 }
122
123 ArtVpath *allocVPath(int number)
124 {
125 return art_new(ArtVpath, number);
126 }
127
128 ArtBpath *allocBPath(int number)
129 {
130 return art_new(ArtBpath, number);
131 }
132
133 void ensureSpace(TQMemArray<ArtBpath> &vec, int index)
134 {
135 if(vec.size() == (unsigned int) index)
136 vec.resize(index + 1);
137 }
138
139 void createBuffer()
140 {
141 m_tempBuffer = art_new(art_u8, m_rowstride * m_height);
142 memset(m_tempBuffer, 0, m_rowstride * m_height);
143
144 // Swap buffers, so we work with the new one internally...
145 art_u8 *temp = m_buffer;
146 m_buffer = m_tempBuffer;
147 m_tempBuffer = temp;
148 }
149
150 void mixBuffer(int opacity)
151 {
152 art_u8 *srcPixel = m_buffer;
153 art_u8 *dstPixel = m_tempBuffer;
154
155 for(int y = 0; y < m_height; y++)
156 {
157 for(int x = 0; x < m_width; x++)
158 {
159 art_u8 r, g, b, a;
160
161 a = srcPixel[4 * x + 3];
162
163 if(a)
164 {
165 r = srcPixel[4 * x];
166 g = srcPixel[4 * x + 1];
167 b = srcPixel[4 * x + 2];
168
169 int temp = a * opacity + 0x80;
170 a = (temp + (temp >> 8)) >> 8;
171 art_rgba_run_alpha(dstPixel + 4 * x, r, g, b, a, 1);
172 }
173 }
174
175 srcPixel += m_rowstride;
176 dstPixel += m_rowstride;
177 }
178
179 // Re-swap again...
180 art_u8 *temp = m_buffer;
181 m_buffer = m_tempBuffer;
182 m_tempBuffer = temp;
183
184 art_free(m_tempBuffer);
185 m_tempBuffer = 0;
186 }
187
188 TQ_UINT32 toArtColor(const TQColor &color)
189 {
190 // Convert in a libart suitable form
191 TQString tempName = color.name();
192 const char *str = tempName.latin1();
193
194 int result = 0;
195
196 for(int i = 1; str[i]; i++)
197 {
198 int hexval;
199 if(str[i] >= '0' && str[i] <= '9')
200 hexval = str[i] - '0';
201 else if (str[i] >= 'A' && str[i] <= 'F')
202 hexval = str[i] - 'A' + 10;
203 else if (str[i] >= 'a' && str[i] <= 'f')
204 hexval = str[i] - 'a' + 10;
205 else
206 break;
207
208 result = (result << 4) + hexval;
209 }
210
211 return result;
212 }
213
214 void drawSVP(ArtSVP *svp, TQ_UINT32 rgb, int opacity)
215 {
216 if(!svp)
217 return;
218
219 ArtRender *render = art_render_new(0, 0, m_width, m_height, m_buffer, m_rowstride, 3, 8, ART_ALPHA_SEPARATE, 0);
220 art_render_svp(render, svp);
221
222 art_render_mask_solid(render, (opacity << 8) + opacity + (opacity >> 7));
223
224 ArtPixMaxDepth color[3];
225 color[0] = ART_PIX_MAX_FROM_8(rgb >> 16);
226 color[1] = ART_PIX_MAX_FROM_8((rgb >> 8) & 0xff);
227 color[2] = ART_PIX_MAX_FROM_8(rgb & 0xff);
228
229 art_render_image_solid(render, color);
230 art_render_invoke(render);
231 }
232
233 void drawBPath(ArtBpath *bpath)
234 {
235 double affine[6];
236 affine[0] = m_worldMatrix->m11();
237 affine[1] = m_worldMatrix->m12();
238 affine[2] = m_worldMatrix->m21();
239 affine[3] = m_worldMatrix->m22();
240 affine[4] = m_worldMatrix->dx();
241 affine[5] = m_worldMatrix->dy();
242
243 ArtBpath *temp = art_bpath_affine_transform(bpath, affine);
244 ArtVpath *vec = art_bez_path_to_vec(temp, 0.25);
245 art_free(temp);
246 drawPathInternal(vec, affine);
247 }
248
249 void drawVPath(ArtVpath *vec)
250 {
251 double affine[6];
252 affine[0] = m_worldMatrix->m11();
253 affine[1] = m_worldMatrix->m12();
254 affine[2] = m_worldMatrix->m21();
255 affine[3] = m_worldMatrix->m22();
256 affine[4] = m_worldMatrix->dx();
257 affine[5] = m_worldMatrix->dy();
258
259 ArtVpath *temp = art_vpath_affine_transform(vec, affine);
260 art_free(vec);
261 vec = temp;
262 drawPathInternal(vec, affine);
263 }
264
265 void drawPathInternal(ArtVpath *vec, double *affine)
266 {
267 ArtSVP *svp;
268 ArtSVP *fillSVP = 0, *strokeSVP = 0;
269
270 TQ_UINT32 fillColor = 0, strokeColor = 0;
271
272 // Filling
273 {
274 int index = -1;
275 TQValueVector<int> toCorrect;
276 while(vec[++index].code != ART_END)
277 {
278 if(vec[index].code == ART_END2)
279 {
280 vec[index].code = ART_LINETO;
281 toCorrect.push_back(index);
282 }
283 }
284
285 fillColor = toArtColor(m_fillColor);
286
287 ArtSvpWriter *swr;
288 ArtSVP *temp;
289 temp = art_svp_from_vpath(vec);
290
291 if(m_fillRule == "evenodd")
292 swr = art_svp_writer_rewind_new(ART_WIND_RULE_ODDEVEN);
293 else
294 swr = art_svp_writer_rewind_new(ART_WIND_RULE_NONZERO);
295
296 art_svp_intersector(temp, swr);
297 svp = art_svp_writer_rewind_reap(swr);
298
299 fillSVP = svp;
300
301 art_svp_free(temp);
302
303 TQValueVector<int>::iterator it;
304 for(it = toCorrect.begin(); it != toCorrect.end(); ++it)
305 vec[(*it)].code = (ArtPathcode)ART_END2;
306 }
307
308 // There seems to be a problem when stroke width is zero, this is a quick
309 // fix (Rob).
310 if(m_strokeWidth <= 0)
311 m_useStroke = m_useStrokeGradient = false;
312
313 // Stroking
314 if(m_useStroke || m_useStrokeGradient)
315 {
316 strokeColor = toArtColor(m_strokeColor);
317
318 double ratio = art_affine_expansion(affine);
319 double strokeWidth = m_strokeWidth * ratio;
320
321 ArtPathStrokeJoinType joinStyle = ART_PATH_STROKE_JOIN_MITER;
322 ArtPathStrokeCapType capStyle = ART_PATH_STROKE_CAP_BUTT;
323
324 if(m_joinStyle == "miter")
325 joinStyle = ART_PATH_STROKE_JOIN_MITER;
326 else if(m_joinStyle == "round")
327 joinStyle = ART_PATH_STROKE_JOIN_ROUND;
328 else if(m_joinStyle == "bevel")
329 joinStyle = ART_PATH_STROKE_JOIN_BEVEL;
330
331 if(m_capStyle == "butt")
332 capStyle = ART_PATH_STROKE_CAP_BUTT;
333 else if(m_capStyle == "round")
334 capStyle = ART_PATH_STROKE_CAP_ROUND;
335 else if(m_capStyle == "square")
336 capStyle = ART_PATH_STROKE_CAP_SQUARE;
337
338 if(m_dashes.length() > 0)
339 {
340 TQRegExp reg("[, ]");
341 TQStringList dashList = TQStringList::split(reg, m_dashes);
342
343 double *dashes = new double[dashList.count()];
344 for(unsigned int i = 0; i < dashList.count(); i++)
345 dashes[i] = m_painter->toPixel(dashList[i], true);
346
347 ArtVpathDash dash;
348 dash.offset = m_dashOffset;
349 dash.n_dash = dashList.count();
350
351 dash.dash = dashes;
352
353 ArtVpath *vec2 = art_vpath_dash(vec, &dash);
354 art_free(vec);
355
356 delete[] dashes;
357
358 vec = vec2;
359 }
360
361 svp = art_svp_vpath_stroke(vec, joinStyle, capStyle, strokeWidth, m_strokeMiterLimit, 0.25);
362
363 strokeSVP = svp;
364 }
365
366 // Apply opacity
367 int fillOpacity = static_cast<int>(m_fillOpacity);
368 int strokeOpacity = static_cast<int>(m_strokeOpacity);
369 int opacity = static_cast<int>(m_opacity);
370
371 // Needed hack, to support both transparent
372 // paths and transparent gradients
373 if(fillOpacity == strokeOpacity && fillOpacity == opacity && !m_useFillGradient && !m_useStrokeGradient)
374 opacity = 255;
375
376 if(fillOpacity != 255)
377 {
378 int temp = fillOpacity * opacity + 0x80;
379 fillOpacity = (temp + (temp >> 8)) >> 8;
380 }
381
382 if(strokeOpacity != 255)
383 {
384 int temp = strokeOpacity * opacity + 0x80;
385 strokeOpacity = (temp + (temp >> 8)) >> 8;
386 }
387
388 // Create temporary buffer if necessary
389 bool tempDone = false;
390 if(m_opacity != 0xff)
391 {
392 tempDone = true;
393 createBuffer();
394 }
395
396 // Apply Gradients on fill/stroke
397 if(m_useFillGradient)
398 applyGradient(fillSVP, true);
399 else if(m_useFill)
400 drawSVP(fillSVP, fillColor, fillOpacity);
401
402 if(m_useStrokeGradient)
403 applyGradient(strokeSVP, false);
404 else if(m_useStroke)
405 drawSVP(strokeSVP, strokeColor, strokeOpacity);
406
407 // Mix in temporary buffer, if possible
408 if(tempDone)
409 mixBuffer(opacity);
410
411 if(m_clipSVP)
412 {
413 art_svp_free(m_clipSVP);
414 m_clipSVP = 0;
415 }
416
417 if(fillSVP)
418 art_svp_free(fillSVP);
419
420 if(strokeSVP)
421 art_svp_free(strokeSVP);
422
423 // Reset opacity values
424 m_opacity = 255.0;
425 m_fillOpacity = 255.0;
426 m_strokeOpacity = 255.0;
427
428 art_free(vec);
429 }
430
431 void applyLinearGradient(ArtSVP *svp, const TQString &ref)
432 {
433 ArtGradientLinear *linear = m_linearGradientMap[ref];
434 if(linear)
435 {
436 TQDomElement element = m_linearGradientElementMap[linear];
437
438 double x1, y1, x2, y2;
439 if(element.hasAttribute("x1"))
440 x1 = m_painter->toPixel(element.attribute("x1"), true);
441 else
442 x1 = 0;
443
444 if(element.hasAttribute("y1"))
445 y1 = m_painter->toPixel(element.attribute("y1"), false);
446 else
447 y1 = 0;
448
449 if(element.hasAttribute("x2"))
450 x2 = m_painter->toPixel(element.attribute("x2"), true);
451 else
452 x2 = 100;
453
454 if(element.hasAttribute("y2"))
455 y2 = m_painter->toPixel(element.attribute("y2"), false);
456 else
457 y2 = 0;
458
459 // Adjust to gradientTransform
460 TQWMatrix m = m_painter->parseTransform(element.attribute("gradientTransform"));
461 m.map(x1, y1, &x1, &y1);
462 m.map(x2, y2, &x2, &y2);
463
464 double x1n = x1 * m_worldMatrix->m11() + y1 * m_worldMatrix->m21() + m_worldMatrix->dx();
465 double y1n = x1 * m_worldMatrix->m12() + y1 * m_worldMatrix->m22() + m_worldMatrix->dy();
466 double x2n = x2 * m_worldMatrix->m11() + y2 * m_worldMatrix->m21() + m_worldMatrix->dx();
467 double y2n = x2 * m_worldMatrix->m12() + y2 * m_worldMatrix->m22() + m_worldMatrix->dy();
468
469 double dx = x2n - x1n;
470 double dy = y2n - y1n;
471 double scale = 1.0 / (dx * dx + dy * dy);
472
473 linear->a = dx * scale;
474 linear->b = dy * scale;
475 linear->c = -(x1n * linear->a + y1n * linear->b);
476
477 ArtRender *render = art_render_new(0, 0, m_width, m_height, m_buffer, m_rowstride, 3, 8, ART_ALPHA_SEPARATE, 0);
478 art_render_svp(render, svp);
479
480 art_render_gradient_linear(render, linear, ART_FILTER_HYPER);
481 art_render_invoke(render);
482 }
483 }
484
485 void applyRadialGradient(ArtSVP *svp, const TQString &ref)
486 {
487 ArtGradientRadial *radial = m_radialGradientMap[ref];
488 if(radial)
489 {
490 TQDomElement element = m_radialGradientElementMap[radial];
491
492 double cx, cy, r, fx, fy;
493 if(element.hasAttribute("cx"))
494 cx = m_painter->toPixel(element.attribute("cx"), true);
495 else
496 cx = 50;
497
498 if(element.hasAttribute("cy"))
499 cy = m_painter->toPixel(element.attribute("cy"), false);
500 else
501 cy = 50;
502
503 if(element.hasAttribute("r"))
504 r = m_painter->toPixel(element.attribute("r"), true);
505 else
506 r = 50;
507
508 if(element.hasAttribute("fx"))
509 fx = m_painter->toPixel(element.attribute("fx"), false);
510 else
511 fx = cx;
512
513 if(element.hasAttribute("fy"))
514 fy = m_painter->toPixel(element.attribute("fy"), false);
515 else
516 fy = cy;
517
518 radial->affine[0] = m_worldMatrix->m11();
519 radial->affine[1] = m_worldMatrix->m12();
520 radial->affine[2] = m_worldMatrix->m21();
521 radial->affine[3] = m_worldMatrix->m22();
522 radial->affine[4] = m_worldMatrix->dx();
523 radial->affine[5] = m_worldMatrix->dy();
524
525 radial->fx = (fx - cx) / r;
526 radial->fy = (fy - cy) / r;
527
528 double aff1[6], aff2[6], gradTransform[6];
529
530 // Respect gradientTransform
531 TQWMatrix m = m_painter->parseTransform(element.attribute("gradientTransform"));
532
533 gradTransform[0] = m.m11();
534 gradTransform[1] = m.m12();
535 gradTransform[2] = m.m21();
536 gradTransform[3] = m.m22();
537 gradTransform[4] = m.dx();
538 gradTransform[5] = m.dy();
539
540 art_affine_scale(aff1, r, r);
541 art_affine_translate(aff2, cx, cy);
542
543 art_affine_multiply(aff1, aff1, aff2);
544 art_affine_multiply(aff1, aff1, gradTransform);
545 art_affine_multiply(aff1, aff1, radial->affine);
546 art_affine_invert(radial->affine, aff1);
547
548 ArtRender *render = art_render_new(0, 0, m_width, m_height, m_buffer, m_rowstride, 3, 8, ART_ALPHA_SEPARATE, 0);
549 art_render_svp(render, svp);
550
551 art_render_gradient_radial(render, radial, ART_FILTER_HYPER);
552 art_render_invoke(render);
553 }
554 }
555
556 void applyGradient(ArtSVP *svp, const TQString &ref)
557 {
558 ArtGradientLinear *linear = m_linearGradientMap[ref];
559 if(linear)
560 {
561 TQDomElement element = m_linearGradientElementMap[linear];
562
563 if(!element.hasAttribute("xlink:href"))
564 {
565 applyLinearGradient(svp, ref);
566 return;
567 }
568 else
569 {
570 ArtGradientLinear *linear = m_linearGradientMap[element.attribute("xlink:href").mid(1)];
571 TQDomElement newElement = m_linearGradientElementMap[linear];
572
573 // Saved 'old' attributes
574 TQDict<TQString> refattrs;
575 refattrs.setAutoDelete(true);
576
577 for(unsigned int i = 0; i < newElement.attributes().length(); ++i)
578 refattrs.insert(newElement.attributes().item(i).nodeName(), new TQString(newElement.attributes().item(i).nodeValue()));
579
580 // Copy attributes
581 if(!newElement.isNull())
582 {
583 TQDomNamedNodeMap attr = element.attributes();
584
585 for(unsigned int i = 0; i < attr.length(); i++)
586 {
587 TQString name = attr.item(i).nodeName();
588 if(name != "xlink:href" && name != "id")
589 newElement.setAttribute(name, attr.item(i).nodeValue());
590 }
591 }
592
593 applyGradient(svp, element.attribute("xlink:href").mid(1));
594
595 // Restore attributes
596 TQDictIterator<TQString> itr(refattrs);
597 for(; itr.current(); ++itr)
598 newElement.setAttribute(itr.currentKey(), *(itr.current()));
599
600 return;
601 }
602 }
603
604 ArtGradientRadial *radial = m_radialGradientMap[ref];
605 if(radial)
606 {
607 TQDomElement element = m_radialGradientElementMap[radial];
608
609 if(!element.hasAttribute("xlink:href"))
610 {
611 applyRadialGradient(svp, ref);
612 return;
613 }
614 else
615 {
616 ArtGradientRadial *radial = m_radialGradientMap[element.attribute("xlink:href").mid(1)];
617 TQDomElement newElement = m_radialGradientElementMap[radial];
618
619 // Saved 'old' attributes
620 TQDict<TQString> refattrs;
621 refattrs.setAutoDelete(true);
622
623 for(unsigned int i = 0; i < newElement.attributes().length(); ++i)
624 refattrs.insert(newElement.attributes().item(i).nodeName(), new TQString(newElement.attributes().item(i).nodeValue()));
625
626 // Copy attributes
627 if(!newElement.isNull())
628 {
629 TQDomNamedNodeMap attr = element.attributes();
630
631 for(unsigned int i = 0; i < attr.length(); i++)
632 {
633 TQString name = attr.item(i).nodeName();
634 if(name != "xlink:href" && name != "id")
635 newElement.setAttribute(name, attr.item(i).nodeValue());
636 }
637 }
638
639 applyGradient(svp, element.attribute("xlink:href").mid(1));
640
641 // Restore attributes
642 TQDictIterator<TQString> itr(refattrs);
643 for(; itr.current(); ++itr)
644 newElement.setAttribute(itr.currentKey(), *(itr.current()));
645
646 return;
647 }
648 }
649 }
650
651 void applyGradient(ArtSVP *svp, bool fill)
652 {
653 TQString ref;
654
655 if(fill)
656 {
657 m_useFillGradient = false;
658 ref = m_fillGradientReference;
659 }
660 else
661 {
662 m_useStrokeGradient = false;
663 ref = m_strokeGradientReference;
664 }
665
666 applyGradient(svp, ref);
667 }
668
669 void blit()
670 {
671 unsigned char *line = m_buffer;
672
673 for(int y = 0; y < m_height; y++)
674 {
675 TQRgb *sl = reinterpret_cast<TQRgb *>(m_image->scanLine(y));
676 for(int x = 0; x < m_width; x++)
677 sl[x] = tqRgba(line[x * 4], line[x * 4 + 1], line[x * 4 + 2], line[x * 4 + 3]);
678
679 line += m_rowstride;
680 }
681 }
682
683 void calculateArc(bool relative, TQMemArray<ArtBpath> &vec, int &index, double &curx, double &cury, double angle, double x, double y, double r1, double r2, bool largeArcFlag, bool sweepFlag)
684 {
685 double sin_th, cos_th;
686 double a00, a01, a10, a11;
687 double x0, y0, x1, y1, xc, yc;
688 double d, sfactor, sfactor_sq;
689 double th0, th1, th_arc;
690 int i, n_segs;
691
692 sin_th = sin(angle * (M_PI / 180.0));
693 cos_th = cos(angle * (M_PI / 180.0));
694
695 double dx;
696
697 if(!relative)
698 dx = (curx - x) / 2.0;
699 else
700 dx = -x / 2.0;
701
702 double dy;
703
704 if(!relative)
705 dy = (cury - y) / 2.0;
706 else
707 dy = -y / 2.0;
708
709 double _x1 = cos_th * dx + sin_th * dy;
710 double _y1 = -sin_th * dx + cos_th * dy;
711 double Pr1 = r1 * r1;
712 double Pr2 = r2 * r2;
713 double Px = _x1 * _x1;
714 double Py = _y1 * _y1;
715
716 // Spec : check if radii are large enough
717 double check = Px / Pr1 + Py / Pr2;
718 if(check > 1)
719 {
720 r1 = r1 * sqrt(check);
721 r2 = r2 * sqrt(check);
722 }
723
724 a00 = cos_th / r1;
725 a01 = sin_th / r1;
726 a10 = -sin_th / r2;
727 a11 = cos_th / r2;
728
729 x0 = a00 * curx + a01 * cury;
730 y0 = a10 * curx + a11 * cury;
731
732 if(!relative)
733 x1 = a00 * x + a01 * y;
734 else
735 x1 = a00 * (curx + x) + a01 * (cury + y);
736
737 if(!relative)
738 y1 = a10 * x + a11 * y;
739 else
740 y1 = a10 * (curx + x) + a11 * (cury + y);
741
742 /* (x0, y0) is current point in transformed coordinate space.
743 (x1, y1) is new point in transformed coordinate space.
744
745 The arc fits a unit-radius circle in this space.
746 */
747
748 d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
749
750 if (d)
751 {
752 sfactor_sq = 1.0 / d - 0.25;
753 }
754 else
755 {
756 sfactor_sq = 0;
757 }
758
759 if(sfactor_sq < 0)
760 sfactor_sq = 0;
761
762 sfactor = sqrt(sfactor_sq);
763
764 if(sweepFlag == largeArcFlag)
765 sfactor = -sfactor;
766
767 xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
768 yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
769
770 /* (xc, yc) is center of the circle. */
771 th0 = atan2(y0 - yc, x0 - xc);
772 th1 = atan2(y1 - yc, x1 - xc);
773
774 th_arc = th1 - th0;
775 if(th_arc < 0 && sweepFlag)
776 th_arc += 2 * M_PI;
777 else if(th_arc > 0 && !sweepFlag)
778 th_arc -= 2 * M_PI;
779
780 n_segs = (int) ceil(fabs(th_arc / (M_PI * 0.5 + 0.001)));
781
782 for(i = 0; i < n_segs; i++)
783 {
784 index++;
785
786 ensureSpace(vec, index);
787
788 {
789 double sin_th, cos_th;
790 double a00, a01, a10, a11;
791 double x1, y1, x2, y2, x3, y3;
792 double t;
793 double th_half;
794
795 double _th0 = th0 + i * th_arc / n_segs;
796 double _th1 = th0 + (i + 1) * th_arc / n_segs;
797
798 sin_th = sin(angle * (M_PI / 180.0));
799 cos_th = cos(angle * (M_PI / 180.0));
800
801 /* inverse transform compared with rsvg_path_arc */
802 a00 = cos_th * r1;
803 a01 = -sin_th * r2;
804 a10 = sin_th * r1;
805 a11 = cos_th * r2;
806
807 th_half = 0.5 * (_th1 - _th0);
808 t = (8.0 / 3.0) * sin(th_half * 0.5) * sin(th_half * 0.5) / sin(th_half);
809 x1 = xc + cos(_th0) - t * sin(_th0);
810 y1 = yc + sin(_th0) + t * cos(_th0);
811 x3 = xc + cos(_th1);
812 y3 = yc + sin(_th1);
813 x2 = x3 + t * sin(_th1);
814 y2 = y3 - t * cos(_th1);
815
816 ensureSpace(vec, index);
817
818 vec[index].code = ART_CURVETO;
819 vec[index].x1 = a00 * x1 + a01 * y1;
820 vec[index].y1 = a10 * x1 + a11 * y1;
821 vec[index].x2 = a00 * x2 + a01 * y2;
822 vec[index].y2 = a10 * x2 + a11 * y2;
823 vec[index].x3 = a00 * x3 + a01 * y3;
824 vec[index].y3 = a10 * x3 + a11 * y3;
825 }
826 }
827
828 if(!relative)
829 curx = x;
830 else
831 curx += x;
832
833 if(!relative)
834 cury = y;
835 else
836 cury += y;
837 }
838
839 // For any docs, see the libart library
840 static void art_vpath_render_bez(ArtVpath **p_vpath, int *pn, int *pn_max,
841 double x0, double y0,
842 double x1, double y1,
843 double x2, double y2,
844 double x3, double y3,
845 double flatness)
846 {
847 double x3_0, y3_0, z3_0_dot, z1_dot, z2_dot;
848 double z1_perp, z2_perp, max_perp_sq;
849
850 double x_m, y_m, xa1, ya1, xa2, ya2, xb1, yb1, xb2, yb2;
851
852 x3_0 = x3 - x0;
853 y3_0 = y3 - y0;
854
855 z3_0_dot = x3_0 * x3_0 + y3_0 * y3_0;
856
857 if (z3_0_dot < 0.001)
858 goto nosubdivide;
859
860 max_perp_sq = flatness * flatness * z3_0_dot;
861
862 z1_perp = (y1 - y0) * x3_0 - (x1 - x0) * y3_0;
863 if (z1_perp * z1_perp > max_perp_sq)
864 goto subdivide;
865
866 z2_perp = (y3 - y2) * x3_0 - (x3 - x2) * y3_0;
867 if (z2_perp * z2_perp > max_perp_sq)
868 goto subdivide;
869
870 z1_dot = (x1 - x0) * x3_0 + (y1 - y0) * y3_0;
871 if (z1_dot < 0 && z1_dot * z1_dot > max_perp_sq)
872 goto subdivide;
873
874 z2_dot = (x3 - x2) * x3_0 + (y3 - y2) * y3_0;
875 if (z2_dot < 0 && z2_dot * z2_dot > max_perp_sq)
876 goto subdivide;
877
878 if (z1_dot + z1_dot > z3_0_dot)
879 goto subdivide;
880
881 if (z2_dot + z2_dot > z3_0_dot)
882 goto subdivide;
883
884 nosubdivide:
885 art_vpath_add_point (p_vpath, pn, pn_max, ART_LINETO, x3, y3);
886 return;
887
888 subdivide:
889 xa1 = (x0 + x1) * 0.5;
890 ya1 = (y0 + y1) * 0.5;
891 xa2 = (x0 + 2 * x1 + x2) * 0.25;
892 ya2 = (y0 + 2 * y1 + y2) * 0.25;
893 xb1 = (x1 + 2 * x2 + x3) * 0.25;
894 yb1 = (y1 + 2 * y2 + y3) * 0.25;
895 xb2 = (x2 + x3) * 0.5;
896 yb2 = (y2 + y3) * 0.5;
897 x_m = (xa2 + xb1) * 0.5;
898 y_m = (ya2 + yb1) * 0.5;
899 art_vpath_render_bez (p_vpath, pn, pn_max, x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, flatness);
900 art_vpath_render_bez (p_vpath, pn, pn_max, x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, flatness);
901 }
902
903 ArtVpath *art_bez_path_to_vec(const ArtBpath *bez, double flatness)
904 {
905 ArtVpath *vec;
906 int vec_n, vec_n_max;
907 int bez_index;
908 double x, y;
909
910 vec_n = 0;
911 vec_n_max = (1 << 4);
912 vec = art_new (ArtVpath, vec_n_max);
913
914 x = 0;
915 y = 0;
916
917 bez_index = 0;
918 do
919 {
920 if(vec_n >= vec_n_max)
921 art_expand (vec, ArtVpath, vec_n_max);
922
923 switch (bez[bez_index].code)
924 {
925 case ART_MOVETO_OPEN:
926 case ART_MOVETO:
927 case ART_LINETO:
928 x = bez[bez_index].x3;
929 y = bez[bez_index].y3;
930 vec[vec_n].code = bez[bez_index].code;
931 vec[vec_n].x = x;
932 vec[vec_n].y = y;
933 vec_n++;
934 break;
935 case ART_END:
936 vec[vec_n].code = ART_END;
937 vec[vec_n].x = 0;
938 vec[vec_n].y = 0;
939 vec_n++;
940 break;
941 case ART_END2:
942 vec[vec_n].code = (ArtPathcode)ART_END2;
943 vec[vec_n].x = bez[bez_index].x3;
944 vec[vec_n].y = bez[bez_index].y3;
945 vec_n++;
946 break;
947 case ART_CURVETO:
948 art_vpath_render_bez (&vec, &vec_n, &vec_n_max,
949 x, y,
950 bez[bez_index].x1, bez[bez_index].y1,
951 bez[bez_index].x2, bez[bez_index].y2,
952 bez[bez_index].x3, bez[bez_index].y3,
953 flatness);
954 x = bez[bez_index].x3;
955 y = bez[bez_index].y3;
956 break;
957 }
958 }
959
960 while (bez[bez_index++].code != ART_END);
961 return vec;
962 }
963
964 static void art_rgb_affine_run(int *p_x0, int *p_x1, int y,
965 int src_width, int src_height,
966 const double affine[6])
967 {
968 int x0, x1;
969 double z;
970 double x_intercept;
971 int xi;
972
973 x0 = *p_x0;
974 x1 = *p_x1;
975
976 if (affine[0] > 1e-6)
977 {
978 z = affine[2] * (y + 0.5) + affine[4];
979 x_intercept = -z / affine[0];
980 xi = (int) (int) ceil (x_intercept + 1e-6 - 0.5);
981 if (xi > x0)
982 x0 = xi;
983 x_intercept = (-z + src_width) / affine[0];
984 xi = (int) ceil (x_intercept - 1e-6 - 0.5);
985 if (xi < x1)
986 x1 = xi;
987 }
988 else if (affine[0] < -1e-6)
989 {
990 z = affine[2] * (y + 0.5) + affine[4];
991 x_intercept = (-z + src_width) / affine[0];
992 xi = (int) ceil (x_intercept + 1e-6 - 0.5);
993 if (xi > x0)
994 x0 = xi;
995 x_intercept = -z / affine[0];
996 xi = (int) ceil (x_intercept - 1e-6 - 0.5);
997 if (xi < x1)
998 x1 = xi;
999 }
1000 else
1001 {
1002 z = affine[2] * (y + 0.5) + affine[4];
1003 if (z < 0 || z >= src_width)
1004 {
1005 *p_x1 = *p_x0;
1006 return;
1007 }
1008 }
1009 if (affine[1] > 1e-6)
1010 {
1011 z = affine[3] * (y + 0.5) + affine[5];
1012 x_intercept = -z / affine[1];
1013 xi = (int) ceil (x_intercept + 1e-6 - 0.5);
1014 if (xi > x0)
1015 x0 = xi;
1016 x_intercept = (-z + src_height) / affine[1];
1017 xi = (int) ceil (x_intercept - 1e-6 - 0.5);
1018 if (xi < x1)
1019 x1 = xi;
1020 }
1021 else if (affine[1] < -1e-6)
1022 {
1023 z = affine[3] * (y + 0.5) + affine[5];
1024 x_intercept = (-z + src_height) / affine[1];
1025 xi = (int) ceil (x_intercept + 1e-6 - 0.5);
1026 if (xi > x0)
1027 x0 = xi;
1028 x_intercept = -z / affine[1];
1029 xi = (int) ceil (x_intercept - 1e-6 - 0.5);
1030 if (xi < x1)
1031 x1 = xi;
1032 }
1033 else
1034 {
1035 z = affine[3] * (y + 0.5) + affine[5];
1036 if (z < 0 || z >= src_height)
1037 {
1038 *p_x1 = *p_x0;
1039 return;
1040 }
1041 }
1042
1043 *p_x0 = x0;
1044 *p_x1 = x1;
1045 }
1046
1047 // Slightly modified version to support RGBA buffers, copied from gnome-print
1048 static void art_rgba_rgba_affine(art_u8 *dst,
1049 int x0, int y0, int x1, int y1, int dst_rowstride,
1050 const art_u8 *src,
1051 int src_width, int src_height, int src_rowstride,
1052 const double affine[6])
1053 {
1054 int x, y;
1055 double inv[6];
1056 art_u8 *dst_p, *dst_linestart;
1057 const art_u8 *src_p;
1058 ArtPoint pt, src_pt;
1059 int src_x, src_y;
1060 int alpha;
1061 art_u8 bg_r, bg_g, bg_b, bg_a, cr, cg, cb;
1062 art_u8 fg_r, fg_g, fg_b;
1063 int tmp;
1064 int run_x0, run_x1;
1065
1066 dst_linestart = dst;
1067 art_affine_invert (inv, affine);
1068 for (y = y0; y < y1; y++)
1069 {
1070 pt.y = y + 0.5;
1071 run_x0 = x0;
1072 run_x1 = x1;
1073 art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
1074 inv);
1075 dst_p = dst_linestart + (run_x0 - x0) * 4;
1076 for (x = run_x0; x < run_x1; x++)
1077 {
1078 pt.x = x + 0.5;
1079 art_affine_point (&src_pt, &pt, inv);
1080 src_x = (int) floor (src_pt.x);
1081 src_y = (int) floor (src_pt.y);
1082 src_p = src + (src_y * src_rowstride) + src_x * 4;
1083 if (src_x >= 0 && src_x < src_width &&
1084 src_y >= 0 && src_y < src_height)
1085 {
1086
1087 alpha = src_p[3];
1088 if (alpha)
1089 {
1090 if (alpha == 255)
1091 {
1092 dst_p[0] = src_p[0];
1093 dst_p[1] = src_p[1];
1094 dst_p[2] = src_p[2];
1095 dst_p[3] = 255;
1096 }
1097 else
1098 {
1099 bg_r = dst_p[0];
1100 bg_g = dst_p[1];
1101 bg_b = dst_p[2];
1102 bg_a = dst_p[3];
1103
1104 cr = (bg_r * bg_a + 0x80) >> 8;
1105 cg = (bg_g * bg_g + 0x80) >> 8;
1106 cb = (bg_b * bg_b + 0x80) >> 8;
1107
1108 tmp = (src_p[0] - bg_r) * alpha;
1109 fg_r = bg_r + ((tmp + (tmp >> 8) + 0x80) >> 8);
1110 tmp = (src_p[1] - bg_g) * alpha;
1111 fg_g = bg_g + ((tmp + (tmp >> 8) + 0x80) >> 8);
1112 tmp = (src_p[2] - bg_b) * alpha;
1113 fg_b = bg_b + ((tmp + (tmp >> 8) + 0x80) >> 8);
1114
1115 dst_p[0] = fg_r;
1116 dst_p[1] = fg_g;
1117 dst_p[2] = fg_b;
1118 dst_p[3] = bg_a + (((255 - bg_a) * alpha + 0x80) >> 8);
1119 }
1120 }
1121 } else { dst_p[0] = 255; dst_p[1] = 0; dst_p[2] = 0; dst_p[3] = 255;}
1122 dst_p += 4;
1123 }
1124 dst_linestart += dst_rowstride;
1125 }
1126 }
1127
1128private:
1129 friend class KSVGIconPainter;
1130 ArtSVP *m_clipSVP;
1131
1132 TQImage *m_image;
1133 TQWMatrix *m_worldMatrix;
1134
1135 TQString m_fillRule;
1136 TQString m_joinStyle;
1137 TQString m_capStyle;
1138
1139 int m_strokeMiterLimit;
1140
1141 TQString m_dashes;
1142 unsigned short m_dashOffset;
1143
1144 TQColor m_fillColor;
1145 TQColor m_strokeColor;
1146
1147 art_u8 *m_buffer;
1148 art_u8 *m_tempBuffer;
1149
1150 int m_width;
1151 int m_height;
1152
1153 int m_rowstride;
1154
1155 double m_opacity;
1156 double m_fillOpacity;
1157 double m_strokeOpacity;
1158
1159 bool m_useFill;
1160 bool m_useStroke;
1161
1162 bool m_useFillGradient;
1163 bool m_useStrokeGradient;
1164
1165 TQString m_fillGradientReference;
1166 TQString m_strokeGradientReference;
1167
1168 TQMap<TQString, ArtGradientLinear *> m_linearGradientMap;
1169 TQMap<ArtGradientLinear *, TQDomElement> m_linearGradientElementMap;
1170
1171 TQMap<TQString, ArtGradientRadial *> m_radialGradientMap;
1172 TQMap<ArtGradientRadial *, TQDomElement> m_radialGradientElementMap;
1173
1174 KSVGIconPainter *m_painter;
1175
1176 double m_strokeWidth;
1177};
1178
1179struct KSVGIconPainter::Private
1180{
1181 KSVGIconPainterHelper *helper;
1182
1183 int drawWidth;
1184 int drawHeight;
1185};
1186
1187KSVGIconPainter::KSVGIconPainter(int width, int height) : d(new Private())
1188{
1189 d->helper = new KSVGIconPainterHelper(width, height, this);
1190
1191 d->drawWidth = width;
1192 d->drawHeight = height;
1193}
1194
1195KSVGIconPainter::~KSVGIconPainter()
1196{
1197 delete d->helper;
1198 delete d;
1199}
1200
1201void KSVGIconPainter::setDrawWidth(int dwidth)
1202{
1203 d->drawWidth = dwidth;
1204}
1205
1206void KSVGIconPainter::setDrawHeight(int dheight)
1207{
1208 d->drawHeight = dheight;
1209}
1210
1211void KSVGIconPainter::finish()
1212{
1213 d->helper->blit();
1214}
1215
1216TQImage *KSVGIconPainter::image()
1217{
1218 return new TQImage(*d->helper->m_image);
1219}
1220
1221TQWMatrix *KSVGIconPainter::worldMatrix()
1222{
1223 return d->helper->m_worldMatrix;
1224}
1225
1226void KSVGIconPainter::setWorldMatrix(TQWMatrix *matrix)
1227{
1228 if(d->helper->m_worldMatrix)
1229 delete d->helper->m_worldMatrix;
1230
1231 d->helper->m_worldMatrix = matrix;
1232}
1233
1234void KSVGIconPainter::setStrokeWidth(double width)
1235{
1236 d->helper->m_strokeWidth = width;
1237}
1238
1239void KSVGIconPainter::setStrokeMiterLimit(const TQString &miter)
1240{
1241 d->helper->m_strokeMiterLimit = miter.toInt();
1242}
1243
1244void KSVGIconPainter::setStrokeDashOffset(const TQString &dashOffset)
1245{
1246 d->helper->m_dashOffset = dashOffset.toUInt();
1247}
1248
1249void KSVGIconPainter::setStrokeDashArray(const TQString &dashes)
1250{
1251 d->helper->m_dashes = dashes;
1252}
1253
1254void KSVGIconPainter::setCapStyle(const TQString &cap)
1255{
1256 d->helper->m_capStyle = cap;
1257}
1258
1259void KSVGIconPainter::setJoinStyle(const TQString &join)
1260{
1261 d->helper->m_joinStyle = join;
1262}
1263
1264void KSVGIconPainter::setStrokeColor(const TQString &stroke)
1265{
1266 if(stroke.startsWith("url"))
1267 {
1268 d->helper->m_useStroke = false;
1269 d->helper->m_useStrokeGradient = true;
1270
1271 TQString url = stroke;
1272
1273 unsigned int start = url.find("#") + 1;
1274 unsigned int end = url.findRev(")");
1275
1276 d->helper->m_strokeGradientReference = url.mid(start, end - start);
1277 }
1278 else
1279 {
1280 d->helper->m_strokeColor = parseColor(stroke);
1281
1282 d->helper->m_useStrokeGradient = false;
1283 d->helper->m_strokeGradientReference = TQString::null;
1284
1285 if(stroke.stripWhiteSpace().lower() != "none")
1286 setUseStroke(true);
1287 else
1288 setUseStroke(false);
1289 }
1290}
1291
1292void KSVGIconPainter::setFillColor(const TQString &fill)
1293{
1294 if(fill.startsWith("url"))
1295 {
1296 d->helper->m_useFill = false;
1297 d->helper->m_useFillGradient = true;
1298
1299 TQString url = fill;
1300
1301 unsigned int start = url.find("#") + 1;
1302 unsigned int end = url.findRev(")");
1303
1304 d->helper->m_fillGradientReference = url.mid(start, end - start);
1305 }
1306 else
1307 {
1308 d->helper->m_fillColor = parseColor(fill);
1309
1310 d->helper->m_useFillGradient = false;
1311 d->helper->m_fillGradientReference = TQString::null;
1312
1313 if(fill.stripWhiteSpace().lower() != "none")
1314 setUseFill(true);
1315 else
1316 setUseFill(false);
1317 }
1318}
1319
1320void KSVGIconPainter::setFillRule(const TQString &fillRule)
1321{
1322 d->helper->m_fillRule = fillRule;
1323}
1324
1325TQ_UINT32 KSVGIconPainter::parseOpacity(const TQString &data)
1326{
1327 int opacity = 255;
1328
1329 if(!data.isEmpty())
1330 {
1331 double temp;
1332
1333 if(data.contains("%"))
1334 {
1335 TQString tempString = data.left(data.length() - 1);
1336 temp = double(255 * tempString.toDouble()) / 100.0;
1337 }
1338 else
1339 temp = data.toDouble();
1340
1341 opacity = (int) floor(temp * 255 + 0.5);
1342 }
1343
1344 return opacity;
1345}
1346
1347void KSVGIconPainter::setFillOpacity(const TQString &fillOpacity)
1348{
1349 d->helper->m_fillOpacity = parseOpacity(fillOpacity);
1350}
1351
1352void KSVGIconPainter::setStrokeOpacity(const TQString &strokeOpacity)
1353{
1354 d->helper->m_strokeOpacity = parseOpacity(strokeOpacity);
1355}
1356
1357void KSVGIconPainter::setOpacity(const TQString &opacity)
1358{
1359 d->helper->m_opacity = parseOpacity(opacity);
1360}
1361
1362void KSVGIconPainter::setUseFill(bool fill)
1363{
1364 d->helper->m_useFill = fill;
1365}
1366
1367void KSVGIconPainter::setUseStroke(bool stroke)
1368{
1369 d->helper->m_useStroke = stroke;
1370}
1371
1372void KSVGIconPainter::setClippingRect(int x, int y, int w, int h)
1373{
1374 ArtVpath *vec = d->helper->allocVPath(6);
1375
1376 vec[0].code = ART_MOVETO;
1377 vec[0].x = x;
1378 vec[0].y = y;
1379
1380 vec[1].code = ART_LINETO;
1381 vec[1].x = x;
1382 vec[1].y = y + h;
1383
1384 vec[2].code = ART_LINETO;
1385 vec[2].x = x + w;
1386 vec[2].y = y + h;
1387
1388 vec[3].code = ART_LINETO;
1389 vec[3].x = x + w;
1390 vec[3].y = y;
1391
1392 vec[4].code = ART_LINETO;
1393 vec[4].x = x;
1394 vec[4].y = y;
1395
1396 vec[5].code = ART_END;
1397
1398 if(d->helper->m_clipSVP)
1399 art_svp_free(d->helper->m_clipSVP);
1400
1401 d->helper->m_clipSVP = art_svp_from_vpath(vec);
1402
1403 art_free(vec);
1404}
1405
1406void KSVGIconPainter::drawRectangle(double x, double y, double w, double h, double rx, double ry)
1407{
1408 if((int) rx != 0 && (int) ry != 0)
1409 {
1410 ArtVpath *res;
1411 ArtBpath *vec = d->helper->allocBPath(10);
1412
1413 int i = 0;
1414
1415 if(rx > w / 2)
1416 rx = w / 2;
1417
1418 if(ry > h / 2)
1419 ry = h / 2;
1420
1421 vec[i].code = ART_MOVETO_OPEN;
1422 vec[i].x3 = x + rx;
1423 vec[i].y3 = y;
1424
1425 i++;
1426
1427 vec[i].code = ART_CURVETO;
1428 vec[i].x1 = x + rx * (1 - 0.552);
1429 vec[i].y1 = y;
1430 vec[i].x2 = x;
1431 vec[i].y2 = y + ry * (1 - 0.552);
1432 vec[i].x3 = x;
1433 vec[i].y3 = y + ry;
1434
1435 i++;
1436
1437 if(ry < h / 2)
1438 {
1439 vec[i].code = ART_LINETO;
1440 vec[i].x3 = x;
1441 vec[i].y3 = y + h - ry;
1442
1443 i++;
1444 }
1445
1446 vec[i].code = ART_CURVETO;
1447 vec[i].x1 = x;
1448 vec[i].y1 = y + h - ry * (1 - 0.552);
1449 vec[i].x2 = x + rx * (1 - 0.552);
1450 vec[i].y2 = y + h;
1451 vec[i].x3 = x + rx;
1452 vec[i].y3 = y + h;
1453
1454 i++;
1455
1456 if(rx < w / 2)
1457 {
1458 vec[i].code = ART_LINETO;
1459 vec[i].x3 = x + w - rx;
1460 vec[i].y3 = y + h;
1461
1462 i++;
1463 }
1464
1465 vec[i].code = ART_CURVETO;
1466 vec[i].x1 = x + w - rx * (1 - 0.552);
1467 vec[i].y1 = y + h;
1468 vec[i].x2 = x + w;
1469 vec[i].y2 = y + h - ry * (1 - 0.552);
1470 vec[i].x3 = x + w;
1471
1472 vec[i].y3 = y + h - ry;
1473
1474 i++;
1475
1476 if(ry < h / 2)
1477 {
1478 vec[i].code = ART_LINETO;
1479 vec[i].x3 = x + w;
1480 vec[i].y3 = y + ry;
1481
1482 i++;
1483 }
1484
1485 vec[i].code = ART_CURVETO;
1486 vec[i].x1 = x + w;
1487 vec[i].y1 = y + ry * (1 - 0.552);
1488 vec[i].x2 = x + w - rx * (1 - 0.552);
1489 vec[i].y2 = y;
1490 vec[i].x3 = x + w - rx;
1491 vec[i].y3 = y;
1492
1493 i++;
1494
1495 if(rx < w / 2)
1496 {
1497 vec[i].code = ART_LINETO;
1498 vec[i].x3 = x + rx;
1499 vec[i].y3 = y;
1500
1501 i++;
1502 }
1503
1504 vec[i].code = ART_END;
1505
1506 res = d->helper->art_bez_path_to_vec(vec, 0.25);
1507 art_free(vec);
1508 d->helper->drawVPath(res);
1509 }
1510 else
1511 {
1512 ArtVpath *vec = d->helper->allocVPath(6);
1513
1514 vec[0].code = ART_MOVETO;
1515 vec[0].x = x;
1516 vec[0].y = y;
1517
1518 vec[1].code = ART_LINETO;
1519 vec[1].x = x;
1520 vec[1].y = y + h;
1521
1522 vec[2].code = ART_LINETO;
1523 vec[2].x = x + w;
1524 vec[2].y = y + h;
1525
1526 vec[3].code = ART_LINETO;
1527 vec[3].x = x + w;
1528 vec[3].y = y;
1529
1530 vec[4].code = ART_LINETO;
1531 vec[4].x = x;
1532 vec[4].y = y;
1533
1534 vec[5].code = ART_END;
1535
1536 d->helper->drawVPath(vec);
1537 }
1538}
1539
1540void KSVGIconPainter::drawEllipse(double cx, double cy, double rx, double ry)
1541{
1542 ArtBpath *temp;
1543
1544 temp = d->helper->allocBPath(6);
1545
1546 double x1, y1, x2, y2, x3, y3;
1547 double len = 0.55228474983079356;
1548 double cos4[] = {1.0, 0.0, -1.0, 0.0, 1.0};
1549 double sin4[] = {0.0, 1.0, 0.0, -1.0, 0.0};
1550 int i = 0;
1551
1552 temp[i].code = ART_MOVETO;
1553 temp[i].x3 = cx + rx;
1554 temp[i].y3 = cy;
1555
1556 i++;
1557
1558 while(i < 5)
1559 {
1560 x1 = cos4[i-1] + len * cos4[i];
1561 y1 = sin4[i-1] + len * sin4[i];
1562 x2 = cos4[i] + len * cos4[i-1];
1563 y2 = sin4[i] + len * sin4[i-1];
1564 x3 = cos4[i];
1565 y3 = sin4[i];
1566
1567 temp[i].code = ART_CURVETO;
1568 temp[i].x1 = cx + x1 * rx;
1569 temp[i].y1 = cy + y1 * ry;
1570 temp[i].x2 = cx + x2 * rx;
1571 temp[i].y2 = cy + y2 * ry;
1572 temp[i].x3 = cx + x3 * rx;
1573 temp[i].y3 = cy + y3 * ry;
1574
1575 i++;
1576 }
1577
1578 temp[i].code = ART_END;
1579
1580 d->helper->drawBPath(temp);
1581
1582 art_free(temp);
1583}
1584
1585void KSVGIconPainter::drawLine(double x1, double y1, double x2, double y2)
1586{
1587 ArtVpath *vec;
1588
1589 vec = d->helper->allocVPath(3);
1590
1591 vec[0].code = ART_MOVETO_OPEN;
1592 vec[0].x = x1;
1593 vec[0].y = y1;
1594
1595 vec[1].code = ART_LINETO;
1596 vec[1].x = x2;
1597 vec[1].y = y2;
1598
1599 vec[2].code = ART_END;
1600
1601 d->helper->drawVPath(vec);
1602}
1603
1604void KSVGIconPainter::drawPolyline(TQPointArray polyArray, int points)
1605{
1606 if(polyArray.point(0).x() == -1 || polyArray.point(0).y() == -1)
1607 return;
1608
1609 ArtVpath *polyline;
1610
1611 if(points == -1)
1612 points = polyArray.count();
1613
1614 polyline = d->helper->allocVPath(3 + points);
1615 polyline[0].code = ART_MOVETO;
1616 polyline[0].x = polyArray.point(0).x();
1617 polyline[0].y = polyArray.point(0).y();
1618
1619 int index;
1620 for(index = 1; index < points; index++)
1621 {
1622 TQPoint point = polyArray.point(index);
1623 polyline[index].code = ART_LINETO;
1624 polyline[index].x = point.x();
1625 polyline[index].y = point.y();
1626 }
1627
1628 if(d->helper->m_useFill) // if the polyline must be filled, inform libart that it should not be closed.
1629 {
1630 polyline[index].code = (ArtPathcode)ART_END2;
1631 polyline[index].x = polyArray.point(0).x();
1632 polyline[index++].y = polyArray.point(0).y();
1633 }
1634
1635 polyline[index].code = ART_END;
1636
1637 d->helper->drawVPath(polyline);
1638}
1639
1640void KSVGIconPainter::drawPolygon(TQPointArray polyArray)
1641{
1642 ArtVpath *polygon;
1643
1644 polygon = d->helper->allocVPath(3 + polyArray.count());
1645 polygon[0].code = ART_MOVETO;
1646 polygon[0].x = polyArray.point(0).x();
1647 polygon[0].y = polyArray.point(0).y();
1648
1649 unsigned int index;
1650 for(index = 1; index < polyArray.count(); index++)
1651 {
1652 TQPoint point = polyArray.point(index);
1653 polygon[index].code = ART_LINETO;
1654 polygon[index].x = point.x();
1655 polygon[index].y = point.y();
1656 }
1657
1658 polygon[index].code = ART_LINETO;
1659 polygon[index].x = polyArray.point(0).x();
1660 polygon[index].y = polyArray.point(0).y();
1661
1662 index++;
1663 polygon[index].code = ART_END;
1664
1665 d->helper->drawVPath(polygon);
1666}
1667
1668// Path parsing tool
1669// parses the coord into number and forwards to the next token
1670static const char *getCoord(const char *ptr, double &number)
1671{
1672 int integer, exponent;
1673 double decimal, frac;
1674 int sign, expsign;
1675
1676 exponent = 0;
1677 integer = 0;
1678 frac = 1.0;
1679 decimal = 0;
1680 sign = 1;
1681 expsign = 1;
1682
1683 // read the sign
1684 if(*ptr == '+')
1685 ptr++;
1686 else if(*ptr == '-')
1687 {
1688 ptr++;
1689 sign = -1;
1690 }
1691 // read the integer part
1692 while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
1693 integer = (integer * 10) + *(ptr++) - '0';
1694
1695 if(*ptr == '.') // read the decimals
1696 {
1697 ptr++;
1698 while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
1699 decimal += (*(ptr++) - '0') * (frac *= 0.1);
1700 }
1701
1702 if(*ptr == 'e' || *ptr == 'E') // read the exponent part
1703 {
1704 ptr++;
1705
1706 // read the sign of the exponent
1707 if(*ptr == '+')
1708 ptr++;
1709 else if(*ptr == '-')
1710 {
1711 ptr++;
1712 expsign = -1;
1713 }
1714
1715 exponent = 0;
1716 while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
1717 {
1718 exponent *= 10;
1719 exponent += *ptr - '0';
1720 ptr++;
1721 }
1722 }
1723
1724 number = integer + decimal;
1725 number *= sign * pow(10.0, expsign * exponent);
1726
1727 // skip the following space
1728 if(*ptr == ' ')
1729 ptr++;
1730
1731 return ptr;
1732}
1733
1734void KSVGIconPainter::drawPath(const TQString &data, bool filled)
1735{
1736 if (!data.isEmpty())
1737 {
1738 TQString value = data;
1739
1740 TQMemArray<ArtBpath> vec;
1741 int index = -1;
1742
1743 double curx = 0.0, cury = 0.0, contrlx = 0.0, contrly = 0.0, xc, yc;
1744 unsigned int lastCommand = 0;
1745
1746 TQCString _d = value.replace(",", " ").simplifyWhiteSpace().latin1();
1747 const char *ptr = _d.data();
1748 const char *end = _d.data() + _d.length();
1749
1750 double tox, toy, x1, y1, x2, y2, rx, ry, angle;
1751 bool largeArc, sweep;
1752 char command = *ptr;
1753
1754 while(ptr < end)
1755 {
1756
1757 if(*ptr == '+' || *ptr == '-' || *ptr == '.' || (*ptr >= '0' && *ptr <= '9'))
1758 {
1759 // there are still coords in this command
1760 if(command == 'M')
1761 {
1762 command = 'L';
1763 }
1764 else if(command == 'm')
1765 {
1766 command = 'l';
1767 }
1768 }
1769 else
1770 {
1771 command = *(ptr++);
1772 }
1773
1774 if(*ptr == ' ')
1775 ptr++;
1776
1777 switch(command)
1778 {
1779 case 'm':
1780 ptr = getCoord(ptr, tox);
1781 ptr = getCoord(ptr, toy);
1782
1783 if(index != -1 && lastCommand != 'z')
1784 {
1785 // Find last subpath
1786 int find = -1;
1787 for(int i = index; i >= 0; i--)
1788 {
1789 if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO)
1790 {
1791 find = i;
1792 break;
1793 }
1794 }
1795
1796 index++;
1797
1798 if(vec.size() == (unsigned int) index)
1799 vec.resize(index + 1);
1800
1801 vec[index].code = (ArtPathcode)ART_END2;
1802 vec[index].x3 = vec[find].x3;
1803 vec[index].y3 = vec[find].y3;
1804 }
1805
1806 curx += tox;
1807 cury += toy;
1808
1809 index++;
1810
1811 d->helper->ensureSpace(vec, index);
1812
1813 vec[index].code = (index == 0) ? ART_MOVETO : ART_MOVETO_OPEN;
1814 vec[index].x3 = curx;
1815 vec[index].y3 = cury;
1816
1817 lastCommand = 'm';
1818 break;
1819 case 'M':
1820 ptr = getCoord(ptr, tox);
1821 ptr = getCoord(ptr, toy);
1822 if(index != -1 && lastCommand != 'z')
1823 {
1824 // Find last subpath
1825 int find = -1;
1826 for(int i = index; i >= 0; i--)
1827 {
1828 if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO)
1829 {
1830 find = i;
1831 break;
1832 }
1833 }
1834
1835 index++;
1836
1837 if(vec.size() == (unsigned int) index)
1838 vec.resize(index + 1);
1839
1840 vec[index].code = (ArtPathcode)ART_END2;
1841 vec[index].x3 = vec[find].x3;
1842 vec[index].y3 = vec[find].y3;
1843 }
1844
1845 curx = tox;
1846 cury = toy;
1847
1848 index++;
1849
1850 d->helper->ensureSpace(vec, index);
1851
1852 vec[index].code = (index == 0) ? ART_MOVETO : ART_MOVETO_OPEN;
1853 vec[index].x3 = curx;
1854 vec[index].y3 = cury;
1855
1856 lastCommand = 'M';
1857 break;
1858 case 'l':
1859 ptr = getCoord(ptr, tox);
1860 ptr = getCoord(ptr, toy);
1861
1862 index++;
1863
1864 d->helper->ensureSpace(vec, index);
1865
1866 vec[index].code = ART_LINETO;
1867 vec[index].x3 = curx + tox;
1868 vec[index].y3 = cury + toy;
1869
1870 curx += tox;
1871 cury += toy;
1872
1873 lastCommand = 'l';
1874 break;
1875 case 'L':
1876 ptr = getCoord(ptr, tox);
1877 ptr = getCoord(ptr, toy);
1878
1879 index++;
1880
1881 d->helper->ensureSpace(vec, index);
1882
1883 vec[index].code = ART_LINETO;
1884 vec[index].x3 = tox;
1885 vec[index].y3 = toy;
1886
1887 curx = tox;
1888 cury = toy;
1889
1890 lastCommand = 'L';
1891 break;
1892 case 'h':
1893 ptr = getCoord(ptr, tox);
1894
1895 index++;
1896
1897 curx += tox;
1898
1899 d->helper->ensureSpace(vec, index);
1900
1901 vec[index].code = ART_LINETO;
1902 vec[index].x3 = curx;
1903 vec[index].y3 = cury;
1904
1905 lastCommand = 'h';
1906 break;
1907 case 'H':
1908 ptr = getCoord(ptr, tox);
1909
1910 index++;
1911
1912 curx = tox;
1913
1914 d->helper->ensureSpace(vec, index);
1915
1916 vec[index].code = ART_LINETO;
1917 vec[index].x3 = curx;
1918 vec[index].y3 = cury;
1919
1920 lastCommand = 'H';
1921 break;
1922 case 'v':
1923 ptr = getCoord(ptr, toy);
1924
1925 index++;
1926
1927 cury += toy;
1928
1929 d->helper->ensureSpace(vec, index);
1930
1931 vec[index].code = ART_LINETO;
1932 vec[index].x3 = curx;
1933 vec[index].y3 = cury;
1934
1935 lastCommand = 'v';
1936 break;
1937 case 'V':
1938 ptr = getCoord(ptr, toy);
1939
1940 index++;
1941
1942 cury = toy;
1943
1944 d->helper->ensureSpace(vec, index);
1945
1946 vec[index].code = ART_LINETO;
1947 vec[index].x3 = curx;
1948 vec[index].y3 = cury;
1949
1950 lastCommand = 'V';
1951 break;
1952 case 'c':
1953 ptr = getCoord(ptr, x1);
1954 ptr = getCoord(ptr, y1);
1955 ptr = getCoord(ptr, x2);
1956 ptr = getCoord(ptr, y2);
1957 ptr = getCoord(ptr, tox);
1958 ptr = getCoord(ptr, toy);
1959
1960 index++;
1961
1962 d->helper->ensureSpace(vec, index);
1963
1964 vec[index].code = ART_CURVETO;
1965 vec[index].x1 = curx + x1;
1966 vec[index].y1 = cury + y1;
1967 vec[index].x2 = curx + x2;
1968 vec[index].y2 = cury + y2;
1969 vec[index].x3 = curx + tox;
1970 vec[index].y3 = cury + toy;
1971
1972 curx += tox;
1973 cury += toy;
1974
1975 contrlx = vec[index].x2;
1976 contrly = vec[index].y2;
1977
1978 lastCommand = 'c';
1979 break;
1980 case 'C':
1981 ptr = getCoord(ptr, x1);
1982 ptr = getCoord(ptr, y1);
1983 ptr = getCoord(ptr, x2);
1984 ptr = getCoord(ptr, y2);
1985 ptr = getCoord(ptr, tox);
1986 ptr = getCoord(ptr, toy);
1987
1988 index++;
1989
1990 d->helper->ensureSpace(vec, index);
1991
1992 vec[index].code = ART_CURVETO;
1993 vec[index].x1 = x1;
1994 vec[index].y1 = y1;
1995 vec[index].x2 = x2;
1996 vec[index].y2 = y2;
1997 vec[index].x3 = tox;
1998 vec[index].y3 = toy;
1999
2000 curx = vec[index].x3;
2001 cury = vec[index].y3;
2002 contrlx = vec[index].x2;
2003 contrly = vec[index].y2;
2004
2005 lastCommand = 'C';
2006 break;
2007 case 's':
2008 ptr = getCoord(ptr, x2);
2009 ptr = getCoord(ptr, y2);
2010 ptr = getCoord(ptr, tox);
2011 ptr = getCoord(ptr, toy);
2012
2013 index++;
2014
2015 d->helper->ensureSpace(vec, index);
2016
2017 vec[index].code = ART_CURVETO;
2018 vec[index].x1 = 2 * curx - contrlx;
2019 vec[index].y1 = 2 * cury - contrly;
2020 vec[index].x2 = curx + x2;
2021 vec[index].y2 = cury + y2;
2022 vec[index].x3 = curx + tox;
2023 vec[index].y3 = cury + toy;
2024
2025 curx += tox;
2026 cury += toy;
2027
2028 contrlx = vec[index].x2;
2029 contrly = vec[index].y2;
2030
2031 lastCommand = 's';
2032 break;
2033 case 'S':
2034 ptr = getCoord(ptr, x2);
2035 ptr = getCoord(ptr, y2);
2036 ptr = getCoord(ptr, tox);
2037 ptr = getCoord(ptr, toy);
2038
2039 index++;
2040
2041 d->helper->ensureSpace(vec, index);
2042
2043 vec[index].code = ART_CURVETO;
2044 vec[index].x1 = 2 * curx - contrlx;
2045 vec[index].y1 = 2 * cury - contrly;
2046 vec[index].x2 = x2;
2047 vec[index].y2 = y2;
2048 vec[index].x3 = tox;
2049 vec[index].y3 = toy;
2050
2051 curx = vec[index].x3;
2052 cury = vec[index].y3;
2053 contrlx = vec[index].x2;
2054 contrly = vec[index].y2;
2055
2056 lastCommand = 'S';
2057 break;
2058 case 'q':
2059 ptr = getCoord(ptr, x1);
2060 ptr = getCoord(ptr, y1);
2061 ptr = getCoord(ptr, tox);
2062 ptr = getCoord(ptr, toy);
2063
2064 index++;
2065
2066 d->helper->ensureSpace(vec, index);
2067
2068 vec[index].code = ART_CURVETO;
2069 vec[index].x1 = (curx + 2 * (x1 + curx)) * (1.0 / 3.0);
2070 vec[index].y1 = (cury + 2 * (y1 + cury)) * (1.0 / 3.0);
2071 vec[index].x2 = ((curx + tox) + 2 * (x1 + curx)) * (1.0 / 3.0);
2072 vec[index].y2 = ((cury + toy) + 2 * (y1 + cury)) * (1.0 / 3.0);
2073 vec[index].x3 = curx + tox;
2074 vec[index].y3 = cury + toy;
2075
2076 contrlx = curx + x1;
2077 contrly = cury + y1;
2078 curx += tox;
2079 cury += toy;
2080
2081 lastCommand = 'q';
2082 break;
2083 case 'Q':
2084 ptr = getCoord(ptr, x1);
2085 ptr = getCoord(ptr, y1);
2086 ptr = getCoord(ptr, tox);
2087 ptr = getCoord(ptr, toy);
2088
2089 index++;
2090
2091 d->helper->ensureSpace(vec, index);
2092
2093 // TODO : if this fails make it more like QuadraticRel
2094 vec[index].code = ART_CURVETO;
2095 vec[index].x1 = (curx + 2 * x1) * (1.0 / 3.0);
2096 vec[index].y1 = (cury + 2 * y1) * (1.0 / 3.0);
2097 vec[index].x2 = (tox + 2 * x1) * (1.0 / 3.0);
2098 vec[index].y2 = (toy + 2 * y1) * (1.0 / 3.0);
2099 vec[index].x3 = tox;
2100 vec[index].y3 = toy;
2101
2102 curx = vec[index].x3;
2103 cury = vec[index].y3;
2104 contrlx = vec[index].x2;
2105 contrly = vec[index].y2;
2106
2107 lastCommand = 'Q';
2108 break;
2109 case 't':
2110 ptr = getCoord(ptr, tox);
2111 ptr = getCoord(ptr, toy);
2112
2113 xc = 2 * curx - contrlx;
2114 yc = 2 * cury - contrly;
2115
2116 index++;
2117
2118 d->helper->ensureSpace(vec, index);
2119
2120 vec[index].code = ART_CURVETO;
2121 vec[index].x1 = (curx + 2 * xc) * (1.0 / 3.0);
2122 vec[index].y1 = (cury + 2 * yc) * (1.0 / 3.0);
2123 vec[index].x2 = ((curx + tox) + 2 * xc) * (1.0 / 3.0);
2124 vec[index].y2 = ((cury + toy) + 2 * yc) * (1.0 / 3.0);
2125
2126 vec[index].x3 = curx + tox;
2127 vec[index].y3 = cury + toy;
2128
2129 curx += tox;
2130 cury += toy;
2131 contrlx = xc;
2132 contrly = yc;
2133
2134 lastCommand = 't';
2135 break;
2136 case 'T':
2137 ptr = getCoord(ptr, tox);
2138 ptr = getCoord(ptr, toy);
2139
2140 xc = 2 * curx - contrlx;
2141 yc = 2 * cury - contrly;
2142
2143 index++;
2144
2145 d->helper->ensureSpace(vec, index);
2146
2147 vec[index].code = ART_CURVETO;
2148 vec[index].x1 = (curx + 2 * xc) * (1.0 / 3.0);
2149 vec[index].y1 = (cury + 2 * yc) * (1.0 / 3.0);
2150 vec[index].x2 = (tox + 2 * xc) * (1.0 / 3.0);
2151 vec[index].y2 = (toy + 2 * yc) * (1.0 / 3.0);
2152 vec[index].x3 = tox;
2153 vec[index].y3 = toy;
2154
2155 curx = tox;
2156 cury = toy;
2157 contrlx = xc;
2158 contrly = yc;
2159
2160 lastCommand = 'T';
2161 break;
2162 case 'z':
2163 case 'Z':
2164 int find;
2165 find = -1;
2166 for(int i = index; i >= 0; i--)
2167 {
2168 if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO)
2169 {
2170 find = i;
2171 break;
2172 }
2173 }
2174
2175 if(find != -1)
2176 {
2177 if(vec[find].x3 != curx || vec[find].y3 != cury)
2178 {
2179 index++;
2180
2181 d->helper->ensureSpace(vec, index);
2182
2183 vec[index].code = ART_LINETO;
2184 vec[index].x3 = vec[find].x3;
2185 vec[index].y3 = vec[find].y3;
2186 }
2187 }
2188
2189 // reset for next (sub)path
2190 curx = vec[find].x3;
2191 cury = vec[find].y3;
2192
2193 lastCommand = 'z';
2194 break;
2195 case 'a':
2196 ptr = getCoord(ptr, rx);
2197 ptr = getCoord(ptr, ry);
2198 ptr = getCoord(ptr, angle);
2199 // 'largeArc' and 'sweep' are single digit flags. Some non conforming svg files do not
2200 // separate those fields with separators, so we can't use getCoord() here.
2201 // See TDE/tde issue #46 on TGW
2202 largeArc = ((*ptr++) != '0');
2203 while (*ptr == ' ')
2204 {
2205 ptr++;
2206 }
2207 sweep = ((*ptr++) != '0');
2208 while (*ptr == ' ')
2209 {
2210 ptr++;
2211 }
2212 ptr = getCoord(ptr, tox);
2213 ptr = getCoord(ptr, toy);
2214
2215 // Spec: radii are nonnegative numbers
2216 rx = fabs(rx);
2217 ry = fabs(ry);
2218
2219 d->helper->calculateArc(true, vec, index, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep);
2220
2221 lastCommand = 'a';
2222 break;
2223 case 'A':
2224 ptr = getCoord(ptr, rx);
2225 ptr = getCoord(ptr, ry);
2226 ptr = getCoord(ptr, angle);
2227 // 'largeArc' and 'sweep' are single digit flags. Some non conforming svg files do not
2228 // separate those fields with separators, so we can't use getCoord() here.
2229 // See TDE/tde issue #46 on TGW
2230 largeArc = ((*ptr++) != '0');
2231 while (*ptr == ' ')
2232 {
2233 ptr++;
2234 }
2235 sweep = ((*ptr++) != '0');
2236 while (*ptr == ' ')
2237 {
2238 ptr++;
2239 }
2240 ptr = getCoord(ptr, tox);
2241 ptr = getCoord(ptr, toy);
2242
2243 // Spec: radii are nonnegative numbers
2244 rx = fabs(rx);
2245 ry = fabs(ry);
2246
2247 d->helper->calculateArc(false, vec, index, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep);
2248
2249 lastCommand = 'A';
2250 break;
2251 }
2252
2253 // Detect reflection points
2254 if(lastCommand != 'C' && lastCommand != 'c' &&
2255 lastCommand != 'S' && lastCommand != 's' &&
2256 lastCommand != 'Q' && lastCommand != 'q' &&
2257 lastCommand != 'T' && lastCommand != 't')
2258 {
2259 contrlx = curx;
2260 contrly = cury;
2261 }
2262 }
2263
2264 // Find last subpath
2265 int find = -1;
2266 for(int i = index; i >= 0; i--)
2267 {
2268 if(vec[i].code == ART_MOVETO_OPEN || vec[i].code == ART_MOVETO)
2269 {
2270 find = i;
2271 break;
2272 }
2273 }
2274
2275 // Fix a problem where the .svg file used doubles as values... (sofico.svg)
2276 if(curx != vec[find].x3 && cury != vec[find].y3)
2277 {
2278 if((int) curx == (int) vec[find].x3 && (int) cury == (int) vec[find].y3)
2279 {
2280 index++;
2281
2282 if(vec.size() == (unsigned int) index)
2283 vec.resize(index + 1);
2284
2285 vec[index].code = ART_LINETO;
2286 vec[index].x3 = vec[find].x3;
2287 vec[index].y3 = vec[find].y3;
2288
2289 curx = vec[find].x3;
2290 cury = vec[find].y3;
2291 }
2292 }
2293
2294 // Handle filled paths that are not closed explicitly
2295 if(filled)
2296 {
2297 if((int) curx != (int) vec[find].x3 || (int) cury != (int) vec[find].y3)
2298 {
2299 index++;
2300
2301 if(vec.size() == (unsigned int) index)
2302 vec.resize(index + 1);
2303
2304 vec[index].code = (ArtPathcode)ART_END2;
2305 vec[index].x3 = vec[find].x3;
2306 vec[index].y3 = vec[find].y3;
2307
2308 curx = vec[find].x3;
2309 cury = vec[find].y3;
2310 }
2311 }
2312
2313 // Close
2314 index++;
2315
2316 if(vec.size() == (unsigned int) index)
2317 vec.resize(index + 1);
2318
2319 vec[index].code = ART_END;
2320
2321 // There are pure-moveto paths which reference paint servers *bah*
2322 // Do NOT render them
2323 bool render = false;
2324 for(int i = index; i >= 0; i--)
2325 {
2326 if(vec[i].code != ART_MOVETO_OPEN && vec[i].code != ART_MOVETO && !(vec[i].code >= ART_END))
2327 {
2328 render = true;
2329 break;
2330 }
2331 }
2332
2333 if(render)
2334 d->helper->drawBPath(vec.data());
2335 }
2336}
2337
2338void KSVGIconPainter::drawImage(double x, double y, TQImage &image)
2339{
2340 if(image.depth() != 32)
2341 image = image.convertDepth(32);
2342
2343 double affine[6];
2344 affine[0] = d->helper->m_worldMatrix->m11();
2345 affine[1] = d->helper->m_worldMatrix->m12();
2346 affine[2] = d->helper->m_worldMatrix->m21();
2347 affine[3] = d->helper->m_worldMatrix->m22();
2348 // use the world matrix to convert the coordinates
2349 d->helper->m_worldMatrix->map(x, y, &affine[4], &affine[5]);
2350
2351 d->helper->art_rgba_rgba_affine(d->helper->m_buffer, 0, 0, d->helper->m_width, d->helper->m_height,
2352 d->helper->m_rowstride, image.bits(), image.width(), image.height(),
2353 image.width() * 4, affine);
2354}
2355
2356TQColor KSVGIconPainter::parseColor(const TQString &param)
2357{
2358 if(param.stripWhiteSpace().startsWith("#"))
2359 {
2360 TQColor color;
2361 color.setNamedColor(param.stripWhiteSpace());
2362 return color;
2363 }
2364 else if(param.stripWhiteSpace().startsWith("rgb("))
2365 {
2366 TQString parse = param.stripWhiteSpace();
2367 TQStringList colors = TQStringList::split(',', parse);
2368 TQString r = colors[0].right((colors[0].length() - 4));
2369 TQString g = colors[1];
2370 TQString b = colors[2].left((colors[2].length() - 1));
2371
2372 if(r.contains("%"))
2373 {
2374 r = r.left(r.length() - 1);
2375 r = TQString::number(int((double(255 * r.toDouble()) / 100.0)));
2376 }
2377
2378 if(g.contains("%"))
2379 {
2380 g = g.left(g.length() - 1);
2381 g = TQString::number(int((double(255 * g.toDouble()) / 100.0)));
2382 }
2383
2384 if(b.contains("%"))
2385 {
2386 b = b.left(b.length() - 1);
2387 b = TQString::number(int((double(255 * b.toDouble()) / 100.0)));
2388 }
2389
2390 return TQColor(r.toInt(), g.toInt(), b.toInt());
2391 }
2392 else
2393 {
2394 TQString rgbColor = param.stripWhiteSpace();
2395
2396 if(rgbColor == "aliceblue")
2397 return TQColor(240, 248, 255);
2398 else if(rgbColor == "antiquewhite")
2399 return TQColor(250, 235, 215);
2400 else if(rgbColor == "aqua")
2401 return TQColor(0, 255, 255);
2402 else if(rgbColor == "aquamarine")
2403 return TQColor(127, 255, 212);
2404 else if(rgbColor == "azure")
2405 return TQColor(240, 255, 255);
2406 else if(rgbColor == "beige")
2407 return TQColor(245, 245, 220);
2408 else if(rgbColor == "bisque")
2409 return TQColor(255, 228, 196);
2410 else if(rgbColor == "black")
2411 return TQColor(0, 0, 0);
2412 else if(rgbColor == "blanchedalmond")
2413 return TQColor(255, 235, 205);
2414 else if(rgbColor == "blue")
2415 return TQColor(0, 0, 255);
2416 else if(rgbColor == "blueviolet")
2417 return TQColor(138, 43, 226);
2418 else if(rgbColor == "brown")
2419 return TQColor(165, 42, 42);
2420 else if(rgbColor == "burlywood")
2421 return TQColor(222, 184, 135);
2422 else if(rgbColor == "cadetblue")
2423 return TQColor(95, 158, 160);
2424 else if(rgbColor == "chartreuse")
2425 return TQColor(127, 255, 0);
2426 else if(rgbColor == "chocolate")
2427 return TQColor(210, 105, 30);
2428 else if(rgbColor == "coral")
2429 return TQColor(255, 127, 80);
2430 else if(rgbColor == "cornflowerblue")
2431 return TQColor(100, 149, 237);
2432 else if(rgbColor == "cornsilk")
2433 return TQColor(255, 248, 220);
2434 else if(rgbColor == "crimson")
2435 return TQColor(220, 20, 60);
2436 else if(rgbColor == "cyan")
2437 return TQColor(0, 255, 255);
2438 else if(rgbColor == "darkblue")
2439 return TQColor(0, 0, 139);
2440 else if(rgbColor == "darkcyan")
2441 return TQColor(0, 139, 139);
2442 else if(rgbColor == "darkgoldenrod")
2443 return TQColor(184, 134, 11);
2444 else if(rgbColor == "darkgray")
2445 return TQColor(169, 169, 169);
2446 else if(rgbColor == "darkgrey")
2447 return TQColor(169, 169, 169);
2448 else if(rgbColor == "darkgreen")
2449 return TQColor(0, 100, 0);
2450 else if(rgbColor == "darkkhaki")
2451 return TQColor(189, 183, 107);
2452 else if(rgbColor == "darkmagenta")
2453 return TQColor(139, 0, 139);
2454 else if(rgbColor == "darkolivegreen")
2455 return TQColor(85, 107, 47);
2456 else if(rgbColor == "darkorange")
2457 return TQColor(255, 140, 0);
2458 else if(rgbColor == "darkorchid")
2459 return TQColor(153, 50, 204);
2460 else if(rgbColor == "darkred")
2461 return TQColor(139, 0, 0);
2462 else if(rgbColor == "darksalmon")
2463 return TQColor(233, 150, 122);
2464 else if(rgbColor == "darkseagreen")
2465 return TQColor(143, 188, 143);
2466 else if(rgbColor == "darkslateblue")
2467 return TQColor(72, 61, 139);
2468 else if(rgbColor == "darkslategray")
2469 return TQColor(47, 79, 79);
2470 else if(rgbColor == "darkslategrey")
2471 return TQColor(47, 79, 79);
2472 else if(rgbColor == "darkturquoise")
2473 return TQColor(0, 206, 209);
2474 else if(rgbColor == "darkviolet")
2475 return TQColor(148, 0, 211);
2476 else if(rgbColor == "deeppink")
2477 return TQColor(255, 20, 147);
2478 else if(rgbColor == "deepskyblue")
2479 return TQColor(0, 191, 255);
2480 else if(rgbColor == "dimgray")
2481 return TQColor(105, 105, 105);
2482 else if(rgbColor == "dimgrey")
2483 return TQColor(105, 105, 105);
2484 else if(rgbColor == "dodgerblue")
2485 return TQColor(30, 144, 255);
2486 else if(rgbColor == "firebrick")
2487 return TQColor(178, 34, 34);
2488 else if(rgbColor == "floralwhite")
2489 return TQColor(255, 250, 240);
2490 else if(rgbColor == "forestgreen")
2491 return TQColor(34, 139, 34);
2492 else if(rgbColor == "fuchsia")
2493 return TQColor(255, 0, 255);
2494 else if(rgbColor == "gainsboro")
2495 return TQColor(220, 220, 220);
2496 else if(rgbColor == "ghostwhite")
2497 return TQColor(248, 248, 255);
2498 else if(rgbColor == "gold")
2499 return TQColor(255, 215, 0);
2500 else if(rgbColor == "goldenrod")
2501 return TQColor(218, 165, 32);
2502 else if(rgbColor == "gray")
2503 return TQColor(128, 128, 128);
2504 else if(rgbColor == "grey")
2505 return TQColor(128, 128, 128);
2506 else if(rgbColor == "green")
2507 return TQColor(0, 128, 0);
2508 else if(rgbColor == "greenyellow")
2509 return TQColor(173, 255, 47);
2510 else if(rgbColor == "honeydew")
2511 return TQColor(240, 255, 240);
2512 else if(rgbColor == "hotpink")
2513 return TQColor(255, 105, 180);
2514 else if(rgbColor == "indianred")
2515 return TQColor(205, 92, 92);
2516 else if(rgbColor == "indigo")
2517 return TQColor(75, 0, 130);
2518 else if(rgbColor == "ivory")
2519 return TQColor(255, 255, 240);
2520 else if(rgbColor == "khaki")
2521 return TQColor(240, 230, 140);
2522 else if(rgbColor == "lavender")
2523 return TQColor(230, 230, 250);
2524 else if(rgbColor == "lavenderblush")
2525 return TQColor(255, 240, 245);
2526 else if(rgbColor == "lawngreen")
2527 return TQColor(124, 252, 0);
2528 else if(rgbColor == "lemonchiffon")
2529 return TQColor(255, 250, 205);
2530 else if(rgbColor == "lightblue")
2531 return TQColor(173, 216, 230);
2532 else if(rgbColor == "lightcoral")
2533 return TQColor(240, 128, 128);
2534 else if(rgbColor == "lightcyan")
2535 return TQColor(224, 255, 255);
2536 else if(rgbColor == "lightgoldenrodyellow")
2537 return TQColor(250, 250, 210);
2538 else if(rgbColor == "lightgray")
2539 return TQColor(211, 211, 211);
2540 else if(rgbColor == "lightgrey")
2541 return TQColor(211, 211, 211);
2542 else if(rgbColor == "lightgreen")
2543 return TQColor(144, 238, 144);
2544 else if(rgbColor == "lightpink")
2545 return TQColor(255, 182, 193);
2546 else if(rgbColor == "lightsalmon")
2547 return TQColor(255, 160, 122);
2548 else if(rgbColor == "lightseagreen")
2549 return TQColor(32, 178, 170);
2550 else if(rgbColor == "lightskyblue")
2551 return TQColor(135, 206, 250);
2552 else if(rgbColor == "lightslategray")
2553 return TQColor(119, 136, 153);
2554 else if(rgbColor == "lightslategrey")
2555 return TQColor(119, 136, 153);
2556 else if(rgbColor == "lightsteelblue")
2557 return TQColor(176, 196, 222);
2558 else if(rgbColor == "lightyellow")
2559 return TQColor(255, 255, 224);
2560 else if(rgbColor == "lime")
2561 return TQColor(0, 255, 0);
2562 else if(rgbColor == "limegreen")
2563 return TQColor(50, 205, 50);
2564 else if(rgbColor == "linen")
2565 return TQColor(250, 240, 230);
2566 else if(rgbColor == "magenta")
2567 return TQColor(255, 0, 255);
2568 else if(rgbColor == "maroon")
2569 return TQColor(128, 0, 0);
2570 else if(rgbColor == "mediumaquamarine")
2571 return TQColor(102, 205, 170);
2572 else if(rgbColor == "mediumblue")
2573 return TQColor(0, 0, 205);
2574 else if(rgbColor == "mediumorchid")
2575 return TQColor(186, 85, 211);
2576 else if(rgbColor == "mediumpurple")
2577 return TQColor(147, 112, 219);
2578 else if(rgbColor == "mediumseagreen")
2579 return TQColor(60, 179, 113);
2580 else if(rgbColor == "mediumslateblue")
2581 return TQColor(123, 104, 238);
2582 else if(rgbColor == "mediumspringgreen")
2583 return TQColor(0, 250, 154);
2584 else if(rgbColor == "mediumturquoise")
2585 return TQColor(72, 209, 204);
2586 else if(rgbColor == "mediumvioletred")
2587 return TQColor(199, 21, 133);
2588 else if(rgbColor == "midnightblue")
2589 return TQColor(25, 25, 112);
2590 else if(rgbColor == "mintcream")
2591 return TQColor(245, 255, 250);
2592 else if(rgbColor == "mistyrose")
2593 return TQColor(255, 228, 225);
2594 else if(rgbColor == "moccasin")
2595 return TQColor(255, 228, 181);
2596 else if(rgbColor == "navajowhite")
2597 return TQColor(255, 222, 173);
2598 else if(rgbColor == "navy")
2599 return TQColor(0, 0, 128);
2600 else if(rgbColor == "oldlace")
2601 return TQColor(253, 245, 230);
2602 else if(rgbColor == "olive")
2603 return TQColor(128, 128, 0);
2604 else if(rgbColor == "olivedrab")
2605 return TQColor(107, 142, 35);
2606 else if(rgbColor == "orange")
2607 return TQColor(255, 165, 0);
2608 else if(rgbColor == "orangered")
2609 return TQColor(255, 69, 0);
2610 else if(rgbColor == "orchid")
2611 return TQColor(218, 112, 214);
2612 else if(rgbColor == "palegoldenrod")
2613 return TQColor(238, 232, 170);
2614 else if(rgbColor == "palegreen")
2615 return TQColor(152, 251, 152);
2616 else if(rgbColor == "paleturquoise")
2617 return TQColor(175, 238, 238);
2618 else if(rgbColor == "palevioletred")
2619 return TQColor(219, 112, 147);
2620 else if(rgbColor == "papayawhip")
2621 return TQColor(255, 239, 213);
2622 else if(rgbColor == "peachpuff")
2623 return TQColor(255, 218, 185);
2624 else if(rgbColor == "peru")
2625 return TQColor(205, 133, 63);
2626 else if(rgbColor == "pink")
2627 return TQColor(255, 192, 203);
2628 else if(rgbColor == "plum")
2629 return TQColor(221, 160, 221);
2630 else if(rgbColor == "powderblue")
2631 return TQColor(176, 224, 230);
2632 else if(rgbColor == "purple")
2633 return TQColor(128, 0, 128);
2634 else if(rgbColor == "red")
2635 return TQColor(255, 0, 0);
2636 else if(rgbColor == "rosybrown")
2637 return TQColor(188, 143, 143);
2638 else if(rgbColor == "royalblue")
2639 return TQColor(65, 105, 225);
2640 else if(rgbColor == "saddlebrown")
2641 return TQColor(139, 69, 19);
2642 else if(rgbColor == "salmon")
2643 return TQColor(250, 128, 114);
2644 else if(rgbColor == "sandybrown")
2645 return TQColor(244, 164, 96);
2646 else if(rgbColor == "seagreen")
2647 return TQColor(46, 139, 87);
2648 else if(rgbColor == "seashell")
2649 return TQColor(255, 245, 238);
2650 else if(rgbColor == "sienna")
2651 return TQColor(160, 82, 45);
2652 else if(rgbColor == "silver")
2653 return TQColor(192, 192, 192);
2654 else if(rgbColor == "skyblue")
2655 return TQColor(135, 206, 235);
2656 else if(rgbColor == "slateblue")
2657 return TQColor(106, 90, 205);
2658 else if(rgbColor == "slategray")
2659 return TQColor(112, 128, 144);
2660 else if(rgbColor == "slategrey")
2661 return TQColor(112, 128, 144);
2662 else if(rgbColor == "snow")
2663 return TQColor(255, 250, 250);
2664 else if(rgbColor == "springgreen")
2665 return TQColor(0, 255, 127);
2666 else if(rgbColor == "steelblue")
2667 return TQColor(70, 130, 180);
2668 else if(rgbColor == "tan")
2669 return TQColor(210, 180, 140);
2670 else if(rgbColor == "teal")
2671 return TQColor(0, 128, 128);
2672 else if(rgbColor == "thistle")
2673 return TQColor(216, 191, 216);
2674 else if(rgbColor == "tomato")
2675 return TQColor(255, 99, 71);
2676 else if(rgbColor == "turquoise")
2677 return TQColor(64, 224, 208);
2678 else if(rgbColor == "violet")
2679 return TQColor(238, 130, 238);
2680 else if(rgbColor == "wheat")
2681 return TQColor(245, 222, 179);
2682 else if(rgbColor == "white")
2683 return TQColor(255, 255, 255);
2684 else if(rgbColor == "whitesmoke")
2685 return TQColor(245, 245, 245);
2686 else if(rgbColor == "yellow")
2687 return TQColor(255, 255, 0);
2688 else if(rgbColor == "yellowgreen")
2689 return TQColor(154, 205, 50);
2690 }
2691
2692 return TQColor();
2693}
2694
2695double KSVGIconPainter::dpi()
2696{
2697 return 90.0; // TODO: make modal?
2698}
2699
2700double KSVGIconPainter::toPixel(const TQString &s, bool hmode)
2701{
2702 if(s.isEmpty())
2703 return 0.0;
2704
2705 TQString check = s;
2706
2707 double ret = 0.0;
2708
2709 double value = 0;
2710 const char *start = check.latin1();
2711 const char *end = getCoord(start, value);
2712
2713 if(uint(end - start) < check.length())
2714 {
2715 if(check.endsWith("px"))
2716 ret = value;
2717 else if(check.endsWith("cm"))
2718 ret = (value / 2.54) * dpi();
2719 else if(check.endsWith("pc"))
2720 ret = (value / 6.0) * dpi();
2721 else if(check.endsWith("mm"))
2722 ret = (value / 25.4) * dpi();
2723 else if(check.endsWith("in"))
2724 ret = value * dpi();
2725 else if(check.endsWith("pt"))
2726 ret = (value / 72.0) * dpi();
2727 else if(check.endsWith("%"))
2728 {
2729 ret = value / 100.0;
2730
2731 if(hmode)
2732 ret *= d->drawWidth;
2733 else
2734 ret *= d->drawHeight;
2735 }
2736 else if(check.endsWith("em"))
2737 {
2738 ret = value * 10.0; // TODO make this depend on actual font size
2739 }
2740 }
2741 else
2742 ret = value;
2743
2744 return ret;
2745}
2746
2747ArtGradientLinear *KSVGIconPainter::linearGradient(const TQString &id)
2748{
2749 return d->helper->m_linearGradientMap[id];
2750}
2751
2752void KSVGIconPainter::addLinearGradient(const TQString &id, ArtGradientLinear *gradient)
2753{
2754 d->helper->m_linearGradientMap.insert(id, gradient);
2755}
2756
2757TQDomElement KSVGIconPainter::linearGradientElement(ArtGradientLinear *linear)
2758{
2759 return d->helper->m_linearGradientElementMap[linear];
2760}
2761
2762void KSVGIconPainter::addLinearGradientElement(ArtGradientLinear *gradient, TQDomElement element)
2763{
2764 d->helper->m_linearGradientElementMap.insert(gradient, element);
2765}
2766
2767ArtGradientRadial *KSVGIconPainter::radialGradient(const TQString &id)
2768{
2769 return d->helper->m_radialGradientMap[id];
2770}
2771
2772void KSVGIconPainter::addRadialGradient(const TQString &id, ArtGradientRadial *gradient)
2773{
2774 d->helper->m_radialGradientMap.insert(id, gradient);
2775}
2776
2777TQDomElement KSVGIconPainter::radialGradientElement(ArtGradientRadial *radial)
2778{
2779 return d->helper->m_radialGradientElementMap[radial];
2780}
2781
2782void KSVGIconPainter::addRadialGradientElement(ArtGradientRadial *gradient, TQDomElement element)
2783{
2784 d->helper->m_radialGradientElementMap.insert(gradient, element);
2785}
2786
2787TQ_UINT32 KSVGIconPainter::toArtColor(const TQColor &color)
2788{
2789 return d->helper->toArtColor(color);
2790}
2791
2792TQWMatrix KSVGIconPainter::parseTransform(const TQString &transform)
2793{
2794 TQWMatrix result;
2795
2796 // Split string for handling 1 transform statement at a time
2797 TQStringList subtransforms = TQStringList::split(')', transform);
2798 TQStringList::ConstIterator it = subtransforms.begin();
2799 TQStringList::ConstIterator end = subtransforms.end();
2800 for(; it != end; ++it)
2801 {
2802 TQStringList subtransform = TQStringList::split('(', (*it));
2803
2804 subtransform[0] = subtransform[0].stripWhiteSpace().lower();
2805 subtransform[1] = subtransform[1].simplifyWhiteSpace();
2806 TQRegExp reg("([-]?\\d*\\.?\\d+(?:e[-]?\\d+)?)");
2807
2808 int pos = 0;
2809 TQStringList params;
2810
2811 while(pos >= 0)
2812 {
2813 pos = reg.search(subtransform[1], pos);
2814 if(pos != -1)
2815 {
2816 params += reg.cap(1);
2817 pos += reg.matchedLength();
2818 }
2819 }
2820
2821 if(subtransform[0].startsWith(";") || subtransform[0].startsWith(","))
2822 subtransform[0] = subtransform[0].right(subtransform[0].length() - 1);
2823
2824 if(subtransform[0] == "rotate")
2825 {
2826 if(params.count() == 3)
2827 {
2828 double x = params[1].toDouble();
2829 double y = params[2].toDouble();
2830
2831 result.translate(x, y);
2832 result.rotate(params[0].toDouble());
2833 result.translate(-x, -y);
2834 }
2835 else
2836 result.rotate(params[0].toDouble());
2837 }
2838 else if(subtransform[0] == "translate")
2839 {
2840 if(params.count() == 2)
2841 result.translate(params[0].toDouble(), params[1].toDouble());
2842 else // Spec : if only one param given, assume 2nd param to be 0
2843 result.translate(params[0].toDouble() , 0);
2844 }
2845 else if(subtransform[0] == "scale")
2846 {
2847 if(params.count() == 2)
2848 result.scale(params[0].toDouble(), params[1].toDouble());
2849 else // Spec : if only one param given, assume uniform scaling
2850 result.scale(params[0].toDouble(), params[0].toDouble());
2851 }
2852 else if(subtransform[0] == "skewx")
2853 result.shear(tan(params[0].toDouble() * deg2rad), 0.0F);
2854 else if(subtransform[0] == "skewy")
2855 result.shear(tan(params[0].toDouble() * deg2rad), 0.0F);
2856 else if(subtransform[0] == "skewy")
2857 result.shear(0.0F, tan(params[0].toDouble() * deg2rad));
2858 else if(subtransform[0] == "matrix")
2859 {
2860 if(params.count() >= 6)
2861 {
2862 result.setMatrix(params[0].toDouble(), params[1].toDouble(), params[2].toDouble(), params[3].toDouble(), params[4].toDouble(), params[5].toDouble());
2863 }
2864 }
2865 }
2866
2867 return result;
2868}
KStdAction::find
TDEAction * find(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
KStdAction::name
const char * name(StdAction id)
TDEStdAccel::end
const TDEShortcut & end()
Goto end of the document.
Definition: tdestdaccel.cpp:289

tdecore

Skip menu "tdecore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.9.4
This website is maintained by Timothy Pearson.