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