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