Reviewed by Eric.
[WebKit-https.git] / WebCore / platform / qt / GraphicsContextQt.cpp
1 /*
2  * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
3  * Copyright (C) 2006 Zack Rusin <zack@kde.org>
4  * Copyright (C) 2006 George Staikos <staikos@kde.org>
5  * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
6  * Copyright (C) 2006 Allan Sandfeld Jensen <sandfeld@kde.org>
7  * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
8  *
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
21  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
28  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include "config.h"
34
35 #include "GraphicsContext.h"
36 #include "Path.h"
37
38 #include <QPainter>
39 #include <QPainterPath>
40 #include <QPaintDevice>
41 #include <QStack>
42
43 #ifndef M_PI
44 #define M_PI 3.14159265358979323846
45 #endif
46
47 #if SVG_SUPPORT
48 #include "KRenderingDeviceQt.h"
49 #endif
50
51 #define notImplemented() do { fprintf(stderr, "FIXME: UNIMPLEMENTED: %s:%d\n", __FILE__, __LINE__); } while(0)
52
53 namespace WebCore {
54
55 static QPainter::CompositionMode toQtCompositionMode(CompositeOperator op)
56 {
57     switch (op) {
58         case CompositeClear:
59             return QPainter::CompositionMode_Clear;
60         case CompositeCopy:
61             return QPainter::CompositionMode_Source;
62         case CompositeSourceOver:
63             return QPainter::CompositionMode_SourceOver;
64         case CompositeSourceIn:
65             return QPainter::CompositionMode_SourceIn;
66         case CompositeSourceOut:
67             return QPainter::CompositionMode_SourceOut;
68         case CompositeSourceAtop:
69             return QPainter::CompositionMode_SourceAtop;
70         case CompositeDestinationOver:
71             return QPainter::CompositionMode_DestinationOver;
72         case CompositeDestinationIn:
73             return QPainter::CompositionMode_DestinationIn;
74         case CompositeDestinationOut:
75             return QPainter::CompositionMode_DestinationOut;
76         case CompositeDestinationAtop:
77             return QPainter::CompositionMode_DestinationAtop;
78         case CompositeXOR:
79             return QPainter::CompositionMode_Xor;
80         case CompositePlusDarker:
81             return QPainter::CompositionMode_SourceOver;
82         case CompositeHighlight:
83             return QPainter::CompositionMode_SourceOver;
84         case CompositePlusLighter:
85             return QPainter::CompositionMode_SourceOver;
86     }
87
88     return QPainter::CompositionMode_SourceOver;
89 }
90
91 static Qt::PenCapStyle toQtLineCap(LineCap lc)
92 {
93     switch (lc) {
94         case ButtCap:
95             return Qt::FlatCap;
96         case RoundCap:
97             return Qt::RoundCap;
98         case SquareCap:
99             return Qt::SquareCap;
100     }
101
102     return Qt::FlatCap;
103 }
104
105 static Qt::PenJoinStyle toQtLineJoin(LineJoin lj)
106 {
107     switch (lj) {
108         case MiterJoin:
109             return Qt::SvgMiterJoin;
110         case RoundJoin:
111             return Qt::RoundJoin;
112         case BevelJoin:
113             return Qt::BevelJoin;
114     }
115
116     return Qt::MiterJoin;
117 }
118
119 struct TransparencyLayer
120 {
121     TransparencyLayer(const QPainter& p, int width, int height)
122     {
123         pixmap = QPixmap(width, height);
124
125         painter = new QPainter(&pixmap);
126         painter->setPen(p.pen());
127         painter->setBrush(p.brush());
128         painter->setMatrix(p.matrix());
129     }
130
131     TransparencyLayer()
132         : painter(0)
133     {
134     }
135
136     void cleanup()
137     {
138         delete painter;
139     }
140
141     QPixmap pixmap;
142     QPainter* painter;
143     qreal opacity;
144 };
145
146 struct TextShadow
147 {
148     TextShadow()
149         : x(0)
150         , y(0)
151         , blur(0)
152     {
153     }
154
155     bool isNull() { return !x && !y && !blur; }
156
157     int x;
158     int y;
159     int blur;
160
161     Color color;
162 };
163
164 class GraphicsContextPlatformPrivate
165 {
166 public:
167     GraphicsContextPlatformPrivate(QPainter* painter);
168     ~GraphicsContextPlatformPrivate();
169
170     QPainter& p()
171     {
172         if (layers.isEmpty()) {
173             if (redirect)
174                 return *redirect;
175
176             return *painter;
177         } else
178             return *layers.top().painter;
179     }
180
181     QPaintDevice* device;
182
183     QStack<TransparencyLayer> layers;
184     QPainter* redirect;
185
186     IntRect focusRingClip;
187     TextShadow shadow;
188
189 private:
190     QPainter* painter;
191 };
192
193
194 GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(QPainter* p)
195     : device(p->device())
196 {
197     painter = p;
198     redirect = 0;
199
200     // FIXME: Maybe only enable in SVG mode?
201     painter->setRenderHint(QPainter::Antialiasing);
202 }
203
204 GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate()
205 {
206 }
207
208 GraphicsContext::GraphicsContext(PlatformGraphicsContext* context)
209     : m_common(createGraphicsContextPrivate())
210     , m_data(new GraphicsContextPlatformPrivate(context))
211 {
212     setPaintingDisabled(!context);
213 }
214
215 GraphicsContext::~GraphicsContext()
216 {
217     while(!m_data->layers.isEmpty())
218         endTransparencyLayer();
219
220     destroyGraphicsContextPrivate(m_common);
221     delete m_data;
222 }
223
224 PlatformGraphicsContext* GraphicsContext::platformContext() const
225 {
226     return &m_data->p();
227 }
228
229 void GraphicsContext::savePlatformState()
230 {
231     m_data->p().save();
232 }
233
234 void GraphicsContext::restorePlatformState()
235 {
236     m_data->p().restore();
237 }
238
239 /* FIXME: DISABLED WHILE MERGING BACK FROM UNITY
240 void GraphicsContext::drawTextShadow(const TextRun& run, const IntPoint& point, const TextStyle& style)
241 {
242     if (paintingDisabled())
243         return;
244
245     if (m_data->shadow.isNull())
246         return;
247
248     TextShadow* shadow = &m_data->shadow;
249
250     if (shadow->blur <= 0) {
251         Pen p = pen();
252         setPen(shadow->color);
253         font().drawText(this, run, style, IntPoint(point.x() + shadow->x, point.y() + shadow->y));
254         setPen(p);
255     } else {
256         const int thickness = shadow->blur;
257         // FIXME: OPTIMIZE: limit the area to only the actually painted area + 2*thickness
258         const int w = m_data->p().device()->width();
259         const int h = m_data->p().device()->height();
260         const QRgb color = qRgb(255, 255, 255);
261         const QRgb bgColor = qRgb(0, 0, 0);
262         QImage image(QSize(w, h), QImage::Format_ARGB32);
263         image.fill(bgColor);
264         QPainter p;
265
266         Pen curPen = pen();
267         p.begin(&image);
268         setPen(color);
269         m_data->redirect = &p;
270         font().drawText(this, run, style, IntPoint(point.x() + shadow->x, point.y() + shadow->y));
271         m_data->redirect = 0;
272         p.end();
273         setPen(curPen);
274
275         int md = thickness * thickness; // max-dist^2
276
277         // blur map/precalculated shadow-decay
278         float* bmap = (float*) alloca(sizeof(float) * (md + 1));
279         for (int n = 0; n <= md; n++) {
280             float f;
281             f = n / (float) (md + 1);
282             f = 1.0 - f * f;
283             bmap[n] = f;
284         }
285
286         float factor = 0.0; // maximal potential opacity-sum
287         for (int n = -thickness; n <= thickness; n++) {
288             for (int m = -thickness; m <= thickness; m++) {
289                 int d = n * n + m * m;
290                 if (d <= md)
291                     factor += bmap[d];
292             }
293         }
294
295         // alpha map
296         float* amap = (float*) alloca(sizeof(float) * (h * w));
297         memset(amap, 0, h * w * (sizeof(float)));
298
299         for (int j = thickness; j<h-thickness; j++) {
300             for (int i = thickness; i<w-thickness; i++) {
301                 QRgb col = image.pixel(i,j);
302                 if (col == bgColor)
303                     continue;
304
305                 float g = qAlpha(col);
306                 g = g / 255;
307
308                 for (int n = -thickness; n <= thickness; n++) {
309                     for (int m = -thickness; m <= thickness; m++) {
310                         int d = n * n + m * m;
311                         if (d > md)
312                             continue;
313
314                         float f = bmap[d];
315                         amap[(i + m) + (j + n) * w] += (g * f);
316                     }
317                 }
318             }
319         }
320
321         QImage res(QSize(w,h),QImage::Format_ARGB32);
322         int r = shadow->color.red();
323         int g = shadow->color.green();
324         int b = shadow->color.blue();
325         int a1 = shadow->color.alpha();
326
327         // arbitratry factor adjustment to make shadows more solid.
328         factor = 1.333 / factor;
329
330         for (int j = 0; j < h; j++) {
331             for (int i = 0; i < w; i++) {
332                 int a = (int) (amap[i + j * w] * factor * a1);
333                 if (a > 255)
334                     a = 255;
335
336                 res.setPixel(i,j, qRgba(r, g, b, a));
337             }
338         }
339
340         m_data->p().drawImage(0, 0, res, 0, 0, -1, -1, Qt::DiffuseAlphaDither | Qt::ColorOnly | Qt::PreferDither);
341     }
342 }
343 */
344
345 // Draws a filled rectangle with a stroked border.
346 void GraphicsContext::drawRect(const IntRect& rect)
347 {
348     if (paintingDisabled())
349         return;
350
351     m_data->p().drawRect(rect);
352 }
353
354 // FIXME: Now that this is refactored, it should be shared by all contexts.
355 static void adjustLineToPixelBounderies(FloatPoint& p1, FloatPoint& p2, float strokeWidth,
356                                         const Pen::PenStyle& penStyle)
357 {
358     // For odd widths, we add in 0.5 to the appropriate x/y so that the float arithmetic
359     // works out.  For example, with a border width of 3, KHTML will pass us (y1+y2)/2, e.g.,
360     // (50+53)/2 = 103/2 = 51 when we want 51.5.  It is always true that an even width gave
361     // us a perfect position, but an odd width gave us a position that is off by exactly 0.5.
362     if (penStyle == Pen::DotLine || penStyle == Pen::DashLine) {
363         if (p1.x() == p2.x()) {
364             p1.setY(p1.y() + strokeWidth);
365             p2.setY(p2.y() - strokeWidth);
366         } else {
367             p1.setX(p1.x() + strokeWidth);
368             p2.setX(p2.x() - strokeWidth);
369         }
370     }
371
372     if (((int) strokeWidth) % 2) {
373         if (p1.x() == p2.x()) {
374             // We're a vertical line.  Adjust our x.
375             p1.setX(p1.x() + 0.5);
376             p2.setX(p2.x() + 0.5);
377         } else {
378             // We're a horizontal line. Adjust our y.
379             p1.setY(p1.y() + 0.5);
380             p2.setY(p2.y() + 0.5);
381         }
382     }
383 }
384
385 // This is only used to draw borders.
386 void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
387 {
388     if (paintingDisabled())
389         return;
390
391     FloatPoint p1 = point1;
392     FloatPoint p2 = point2;
393
394     adjustLineToPixelBounderies(p1, p2, pen().width(), pen().style());
395     m_data->p().drawLine(p1, p2);
396 }
397
398 // This method is only used to draw the little circles used in lists.
399 void GraphicsContext::drawEllipse(const IntRect& rect)
400 {
401     if (paintingDisabled())
402         return;
403
404     m_data->p().drawEllipse(rect);
405 }
406
407 void GraphicsContext::drawArc(const IntRect& rect, float thickness,
408                               int startAngle, int angleSpan)
409 {
410     if (paintingDisabled())
411         return;
412
413     const QPen oldPen = m_data->p().pen();
414     QPen nPen = oldPen;
415     nPen.setWidthF(thickness);
416     m_data->p().setPen(nPen);
417     m_data->p().drawArc(rect, startAngle, angleSpan);
418     m_data->p().setPen(oldPen);
419 }
420
421 void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool shouldAntialias)
422 {
423     if (paintingDisabled())
424         return;
425
426     // FIXME: Take 'shouldAntialias' into account...
427     m_data->p().drawConvexPolygon(reinterpret_cast<const QPointF*>(points), npoints);
428 }
429
430 void GraphicsContext::fillRect(const IntRect& rect, const Color& c)
431 {
432     if (paintingDisabled())
433         return;
434
435     m_data->p().fillRect(rect, QColor(c.red(), c.green(), c.blue(), c.alpha()));
436 }
437
438 void GraphicsContext::fillRect(const FloatRect& rect, const Color& c)
439 {
440     if (paintingDisabled())
441         return;
442
443     m_data->p().fillRect(rect, QColor(c.red(), c.green(), c.blue(), c.alpha()));
444 }
445
446 void GraphicsContext::addClip(const IntRect& rect)
447 {
448     if (paintingDisabled())
449         return;
450
451     QPainterPath path;
452     path.addRect(QRectF(rect));
453     m_data->p().setClipPath(path, Qt::UniteClip);
454 }
455
456 void GraphicsContext::drawFocusRing(const Color& color)
457 {
458     if (paintingDisabled())
459         return;
460
461     notImplemented();
462 }
463
464 void GraphicsContext::setFocusRingClip(const IntRect& rect)
465 {
466     if (paintingDisabled())
467         return;
468
469     m_data->focusRingClip = rect;
470 }
471
472 void GraphicsContext::clearFocusRingClip()
473 {
474     if (paintingDisabled())
475         return;
476
477     m_data->focusRingClip = IntRect();
478 }
479
480 void GraphicsContext::drawLineForText(const IntPoint& point, int yOffset,
481                                       int width, bool printing)
482 {
483     if (paintingDisabled())
484         return;
485
486     IntPoint origin = point + IntSize(0, yOffset + 1);
487     IntPoint endPoint = origin + IntSize(width, 0);
488     drawLine(origin, endPoint);
489 }
490
491 void GraphicsContext::drawLineForMisspelling(const IntPoint& point, int width)
492 {
493     if (paintingDisabled())
494         return;
495
496     notImplemented();
497 }
498
499 FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect)
500 {
501     QRectF rect(frect);
502     rect = m_data->p().deviceMatrix().mapRect(rect);
503
504     QRect result = rect.toRect(); //round it
505     return FloatRect(QRectF(result));
506 }
507
508 void GraphicsContext::setShadow(const IntSize& pos, int blur, const Color &color)
509 {
510     if (paintingDisabled())
511         return;
512
513     m_data->shadow.x = pos.width();
514     m_data->shadow.y = pos.height();
515     m_data->shadow.blur = blur;
516     m_data->shadow.color = color;
517 }
518
519 void GraphicsContext::clearShadow()
520 {
521     if (paintingDisabled())
522         return;
523
524     m_data->shadow = TextShadow();
525 }
526
527 void GraphicsContext::beginTransparencyLayer(float opacity)
528 {
529     if (paintingDisabled())
530         return;
531
532     TransparencyLayer layer(m_data->p(),
533                             m_data->device->width(),
534                             m_data->device->height());
535
536     layer.opacity = opacity;
537     m_data->layers.push(layer);
538 }
539
540 void GraphicsContext::endTransparencyLayer()
541 {
542     if (paintingDisabled())
543         return;
544
545     TransparencyLayer layer = m_data->layers.pop();
546     layer.painter->end();
547
548     m_data->p().save();
549     m_data->p().setOpacity(layer.opacity);
550     m_data->p().drawPixmap(0, 0, layer.pixmap);
551     m_data->p().restore();
552     m_data->p().end();
553
554     layer.cleanup();
555 }
556
557 void GraphicsContext::clearRect(const FloatRect& rect)
558 {
559     if (paintingDisabled())
560         return;
561
562     m_data->p().eraseRect(rect);
563 }
564
565 void GraphicsContext::strokeRect(const FloatRect& rect, float width)
566 {
567     if (paintingDisabled())
568         return;
569
570     QPainterPath path; path.addRect(rect);
571     QPen nPen = m_data->p().pen();
572     nPen.setWidthF(width);
573     m_data->p().strokePath(path, nPen);
574 }
575
576 void GraphicsContext::setLineWidth(float width)
577 {
578     if (paintingDisabled())
579         return;
580
581     QPen nPen = m_data->p().pen();
582     nPen.setWidthF(width);
583     m_data->p().setPen(nPen);
584 }
585
586 void GraphicsContext::setLineCap(LineCap lc)
587 {
588     if (paintingDisabled())
589         return;
590
591     QPen nPen = m_data->p().pen();
592     nPen.setCapStyle(toQtLineCap(lc));
593     m_data->p().setPen(nPen);
594 }
595
596 void GraphicsContext::setLineJoin(LineJoin lj)
597 {
598     if (paintingDisabled())
599         return;
600
601     QPen nPen = m_data->p().pen();
602     nPen.setJoinStyle(toQtLineJoin(lj));
603     m_data->p().setPen(nPen);
604 }
605
606 void GraphicsContext::setMiterLimit(float limit)
607 {
608     if (paintingDisabled())
609         return;
610
611     QPen nPen = m_data->p().pen();
612     nPen.setMiterLimit(limit);
613     m_data->p().setPen(nPen);
614 }
615
616 void GraphicsContext::setAlpha(float opacity)
617 {
618     if (paintingDisabled())
619         return;
620
621     m_data->p().setOpacity(opacity);
622 }
623
624 void GraphicsContext::setCompositeOperation(CompositeOperator op)
625 {
626     if (paintingDisabled())
627         return;
628
629     m_data->p().setCompositionMode(toQtCompositionMode(op));
630 }
631
632 void GraphicsContext::clip(const Path& path)
633 {
634     if (paintingDisabled())
635         return;
636
637     m_data->p().setClipPath(*path.platformPath());
638 }
639
640 void GraphicsContext::translate(const FloatSize& s)
641 {
642     if (paintingDisabled())
643         return;
644
645     m_data->p().scale(s.width(), s.height());
646 }
647
648 void GraphicsContext::rotate(float radians)
649 {
650     if (paintingDisabled())
651         return;
652
653     m_data->p().rotate(radians);
654 }
655
656 void GraphicsContext::scale(const FloatSize& s)
657 {
658     if (paintingDisabled())
659         return;
660
661     m_data->p().scale(s.width(), s.height());
662 }
663
664 void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect,
665                                               int thickness)
666 {
667     if (paintingDisabled())
668         return;
669
670     addClip(rect);
671     QPainterPath path;
672
673     // Add outer ellipse
674     path.addEllipse(QRectF(rect.x(), rect.y(), rect.width(), rect.height()));
675
676     // Add inner ellipse.
677     path.addEllipse(QRectF(rect.x() + thickness, rect.y() + thickness,
678                            rect.width() - (thickness * 2), rect.height() - (thickness * 2)));
679
680     path.setFillRule(Qt::OddEvenFill);
681     m_data->p().setClipPath(path, Qt::IntersectClip);
682 }
683
684 void GraphicsContext::addRoundedRectClip(const IntRect& rect, const IntSize& topLeft,
685                                          const IntSize& topRight, const IntSize& bottomLeft,
686                                          const IntSize& bottomRight)
687 {
688     if (paintingDisabled())
689         return;
690
691     // Need sufficient width and height to contain these curves.  Sanity check our top/bottom
692     // values and our width/height values to make sure the curves can all fit.
693     int requiredWidth = qMax(topLeft.width() + topRight.width(), bottomLeft.width() + bottomRight.width());
694     if (requiredWidth > rect.width())
695         return;
696
697     int requiredHeight = qMax(topLeft.height() + bottomLeft.height(), topRight.height() + bottomRight.height());
698     if (requiredHeight > rect.height())
699         return;
700
701     // Clip to our rect.
702     addClip(rect);
703
704     // OK, the curves can fit.
705     QPainterPath path;
706
707     // Add the four ellipses to the path.  Technically this really isn't good enough, since we could end up
708     // not clipping the other 3/4 of the ellipse we don't care about.  We're relying on the fact that for
709     // normal use cases these ellipses won't overlap one another (or when they do the curvature of one will
710     // be subsumed by the other).
711     path.addEllipse(QRectF(rect.x(), rect.y(), topLeft.width() * 2, topLeft.height() * 2));
712     path.addEllipse(QRectF(rect.right() - topRight.width() * 2, rect.y(),
713                            topRight.width() * 2, topRight.height() * 2));
714     path.addEllipse(QRectF(rect.x(), rect.bottom() - bottomLeft.height() * 2,
715                            bottomLeft.width() * 2, bottomLeft.height() * 2));
716     path.addEllipse(QRectF(rect.right() - bottomRight.width() * 2,
717                            rect.bottom() - bottomRight.height() * 2,
718                            bottomRight.width() * 2, bottomRight.height() * 2));
719
720     int topLeftRightHeightMax = qMax(topLeft.height(), topRight.height());
721     int bottomLeftRightHeightMax = qMax(bottomLeft.height(), bottomRight.height());
722     
723     int topBottomLeftWidthMax = qMax(topLeft.width(), bottomLeft.width());  
724     int topBottomRightWidthMax = qMax(topRight.width(), bottomRight.width());
725     
726     // Now add five rects (one for each edge rect in between the rounded corners and one for the interior).
727     path.addRect(QRectF(rect.x() + topLeft.width(),
728                         rect.y(),
729                         rect.width() - topLeft.width() - topRight.width(),
730                         topLeftRightHeightMax));
731
732     path.addRect(QRectF(rect.x() + bottomLeft.width(), rect.bottom() - bottomLeftRightHeightMax,
733                         rect.width() - bottomLeft.width() - bottomRight.width(), bottomLeftRightHeightMax));
734
735     path.addRect(QRectF(rect.x(),
736                         rect.y() + topLeft.height(),
737                         topBottomLeftWidthMax,
738                         rect.height() - topLeft.height() - bottomLeft.height()));
739     
740     path.addRect(QRectF(rect.right() - topBottomRightWidthMax,
741                         rect.y() + topRight.height(),
742                         topBottomRightWidthMax,
743                         rect.height() - topRight.height() - bottomRight.height()));
744     
745     path.addRect(QRectF(rect.x() + topBottomLeftWidthMax,
746                         rect.y() + topLeftRightHeightMax,
747                         rect.width() - topBottomLeftWidthMax - topBottomRightWidthMax,
748                         rect.height() - topLeftRightHeightMax - bottomLeftRightHeightMax));
749
750     path.setFillRule(Qt::WindingFill);
751     m_data->p().setClipPath(path, Qt::IntersectClip);
752 }
753
754 #if SVG_SUPPORT
755 KRenderingDeviceContext* GraphicsContext::createRenderingDeviceContext()
756 {
757     return new KRenderingDeviceContextQt(platformContext());
758 }
759 #endif
760
761 }
762
763 // vim: ts=4 sw=4 et