2 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
3 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "GraphicsContext.h"
32 #include "AffineTransform.h"
33 #include "CairoPath.h"
34 #include "FloatRect.h"
36 #include "ImageBuffer.h"
38 #include "NotImplemented.h"
40 #include "SimpleFontData.h"
44 #include <wtf/MathExtras.h>
48 #include <pango/pango.h>
50 #include <cairo-win32.h>
52 #include "GraphicsContextPlatformPrivateCairo.h"
55 #define M_PI 3.14159265358979323846
60 static inline void setColor(cairo_t* cr, const Color& col)
62 float red, green, blue, alpha;
63 col.getRGBA(red, green, blue, alpha);
64 cairo_set_source_rgba(cr, red, green, blue, alpha);
68 static inline void fillRectSourceOver(cairo_t* cr, const FloatRect& rect, const Color& col)
71 cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
72 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
76 GraphicsContext::GraphicsContext(PlatformGraphicsContext* cr)
77 : m_common(createGraphicsContextPrivate())
78 , m_data(new GraphicsContextPlatformPrivate)
80 m_data->cr = cairo_reference(cr);
81 setPaintingDisabled(!cr);
84 GraphicsContext::~GraphicsContext()
86 destroyGraphicsContextPrivate(m_common);
90 AffineTransform GraphicsContext::getCTM() const
92 cairo_t* cr = platformContext();
94 cairo_get_matrix(cr, &m);
98 cairo_t* GraphicsContext::platformContext() const
103 void GraphicsContext::savePlatformState()
105 cairo_save(m_data->cr);
108 void GraphicsContext::restorePlatformState()
110 cairo_restore(m_data->cr);
113 // Draws a filled rectangle with a stroked border.
114 void GraphicsContext::drawRect(const IntRect& rect)
116 if (paintingDisabled())
119 cairo_t* cr = m_data->cr;
122 if (fillColor().alpha())
123 fillRectSourceOver(cr, rect, fillColor());
125 if (strokeStyle() != NoStroke) {
126 setColor(cr, strokeColor());
129 cairo_rectangle(cr, r.x(), r.y(), r.width(), r.height());
130 cairo_set_line_width(cr, 1.0);
137 // FIXME: Now that this is refactored, it should be shared by all contexts.
138 static void adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, StrokeStyle style)
140 // For odd widths, we add in 0.5 to the appropriate x/y so that the float arithmetic
141 // works out. For example, with a border width of 3, KHTML will pass us (y1+y2)/2, e.g.,
142 // (50+53)/2 = 103/2 = 51 when we want 51.5. It is always true that an even width gave
143 // us a perfect position, but an odd width gave us a position that is off by exactly 0.5.
144 if (style == DottedStroke || style == DashedStroke) {
145 if (p1.x() == p2.x()) {
146 p1.setY(p1.y() + strokeWidth);
147 p2.setY(p2.y() - strokeWidth);
150 p1.setX(p1.x() + strokeWidth);
151 p2.setX(p2.x() - strokeWidth);
155 if (static_cast<int>(strokeWidth) % 2) {
156 if (p1.x() == p2.x()) {
157 // We're a vertical line. Adjust our x.
158 p1.setX(p1.x() + 0.5);
159 p2.setX(p2.x() + 0.5);
162 // We're a horizontal line. Adjust our y.
163 p1.setY(p1.y() + 0.5);
164 p2.setY(p2.y() + 0.5);
169 // This is only used to draw borders.
170 void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
172 if (paintingDisabled())
175 StrokeStyle style = strokeStyle();
176 if (style == NoStroke)
179 cairo_t* cr = m_data->cr;
182 float width = strokeThickness();
186 FloatPoint p1 = point1;
187 FloatPoint p2 = point2;
188 bool isVerticalLine = (p1.x() == p2.x());
190 adjustLineToPixelBoundaries(p1, p2, width, style);
191 cairo_set_line_width(cr, width);
199 patWidth = static_cast<int>(width);
202 patWidth = 3*static_cast<int>(width);
206 setColor(cr, strokeColor());
208 cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
211 // Do a rect fill of our endpoints. This ensures we always have the
212 // appearance of being a border. We then draw the actual dotted/dashed line.
213 if (isVerticalLine) {
214 fillRectSourceOver(cr, FloatRect(p1.x() - width/2, p1.y() - width, width, width), strokeColor());
215 fillRectSourceOver(cr, FloatRect(p2.x() - width/2, p2.y(), width, width), strokeColor());
217 fillRectSourceOver(cr, FloatRect(p1.x() - width, p1.y() - width/2, width, width), strokeColor());
218 fillRectSourceOver(cr, FloatRect(p2.x(), p2.y() - width/2, width, width), strokeColor());
221 // Example: 80 pixels with a width of 30 pixels.
222 // Remainder is 20. The maximum pixels of line we could paint
223 // will be 50 pixels.
224 int distance = (isVerticalLine ? (point2.y() - point1.y()) : (point2.x() - point1.x())) - 2*static_cast<int>(width);
225 int remainder = distance%patWidth;
226 int coverage = distance-remainder;
227 int numSegments = coverage/patWidth;
229 float patternOffset = 0;
230 // Special case 1px dotted borders for speed.
234 bool evenNumberOfSegments = numSegments%2 == 0;
236 evenNumberOfSegments = !evenNumberOfSegments;
237 if (evenNumberOfSegments) {
239 patternOffset += patWidth - remainder;
240 patternOffset += remainder/2;
243 patternOffset = patWidth/2;
245 else if (!evenNumberOfSegments) {
247 patternOffset = (patWidth - remainder)/2;
251 double dash = patWidth;
252 cairo_set_dash(cr, &dash, 1, patternOffset);
255 cairo_move_to(cr, p1.x(), p1.y());
256 cairo_line_to(cr, p2.x(), p2.y());
262 // This method is only used to draw the little circles used in lists.
263 void GraphicsContext::drawEllipse(const IntRect& rect)
265 if (paintingDisabled())
268 cairo_t* cr = m_data->cr;
270 float yRadius = .5 * rect.height();
271 float xRadius = .5 * rect.width();
272 cairo_translate(cr, rect.x() + xRadius, rect.y() + yRadius);
273 cairo_scale(cr, xRadius, yRadius);
274 cairo_arc(cr, 0., 0., 1., 0., 2 * M_PI);
277 if (fillColor().alpha()) {
278 setColor(cr, fillColor());
279 cairo_fill_preserve(cr);
282 if (strokeStyle() != NoStroke) {
283 setColor(cr, strokeColor());
284 cairo_set_line_width(cr, strokeThickness());
291 // FIXME: This function needs to be adjusted to match the functionality on the Mac side.
292 void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan)
294 if (paintingDisabled())
297 if (strokeStyle() == NoStroke)
302 float w = rect.width();
303 #if 0 // FIXME: unused so far
304 float h = rect.height();
305 float scaleFactor = h / w;
306 float reverseScaleFactor = w / h;
309 float fa = startAngle;
310 float falen = fa + angleSpan;
312 cairo_t* cr = m_data->cr;
314 cairo_arc_negative(cr, x + r, y + r, r, -fa * M_PI/180, -falen * M_PI/180);
315 setColor(cr, strokeColor());
316 cairo_set_line_width(cr, strokeThickness());
321 void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool shouldAntialias)
323 if (paintingDisabled())
329 cairo_t* cr = m_data->cr;
332 cairo_set_antialias(cr, shouldAntialias ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE);
333 cairo_move_to(cr, points[0].x(), points[0].y());
334 for (size_t i = 1; i < npoints; i++)
335 cairo_line_to(cr, points[i].x(), points[i].y());
336 cairo_close_path(cr);
338 if (fillColor().alpha()) {
339 setColor(cr, fillColor());
340 cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
341 cairo_fill_preserve(cr);
344 if (strokeStyle() != NoStroke) {
345 setColor(cr, strokeColor());
346 cairo_set_line_width(cr, strokeThickness());
354 void GraphicsContext::fillRect(const IntRect& rect, const Color& color)
356 if (paintingDisabled())
360 fillRectSourceOver(m_data->cr, rect, color);
363 void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
365 if (paintingDisabled())
369 fillRectSourceOver(m_data->cr, rect, color);
372 void GraphicsContext::clip(const IntRect& rect)
374 if (paintingDisabled())
377 cairo_t* cr = m_data->cr;
378 cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
379 cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
380 cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
382 cairo_set_fill_rule(cr, savedFillRule);
385 void GraphicsContext::drawFocusRing(const Color& color)
387 if (paintingDisabled())
390 int radius = (focusRingWidth() - 1) / 2;
391 int offset = radius + focusRingOffset();
393 const Vector<IntRect>& rects = focusRingRects();
394 unsigned rectCount = rects.size();
395 IntRect finalFocusRect;
396 for (unsigned i = 0; i < rectCount; i++) {
397 IntRect focusRect = rects[i];
398 focusRect.inflate(offset);
399 finalFocusRect.unite(focusRect);
402 cairo_t* cr = m_data->cr;
404 // FIXME: These rects should be rounded
405 cairo_rectangle(cr, finalFocusRect.x(), finalFocusRect.y(), finalFocusRect.width(), finalFocusRect.height());
407 // Force the alpha to 50%. This matches what the Mac does with outline rings.
408 Color ringColor(color.red(), color.green(), color.blue(), 127);
409 setColor(cr, ringColor);
414 void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool printing)
416 if (paintingDisabled())
419 // This is a workaround for http://bugs.webkit.org/show_bug.cgi?id=15659
420 StrokeStyle savedStrokeStyle = strokeStyle();
421 setStrokeStyle(SolidStroke);
423 IntPoint endPoint = origin + IntSize(width, 0);
424 drawLine(origin, endPoint);
426 setStrokeStyle(savedStrokeStyle);
429 void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& origin, int width, bool grammar)
431 if (paintingDisabled())
435 cairo_t* cr = m_data->cr;
438 // Convention is green for grammar, red for spelling
439 // These need to become configurable
441 cairo_set_source_rgb(cr, 0, 1, 0);
443 cairo_set_source_rgb(cr, 1, 0, 0);
445 // We ignore most of the provided constants in favour of the platform style
446 pango_cairo_show_error_underline(cr, origin.x(), origin.y(), width, cMisspellingLineThickness);
454 FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect)
457 double x = frect.x();
458 double y = frect.y();
459 cairo_t* cr = m_data->cr;
460 cairo_user_to_device(cr, &x, &y);
463 cairo_device_to_user(cr, &x, &y);
464 result.setX(static_cast<float>(x));
465 result.setY(static_cast<float>(y));
468 cairo_user_to_device_distance(cr, &x, &y);
471 cairo_device_to_user_distance(cr, &x, &y);
472 result.setWidth(static_cast<float>(x));
473 result.setHeight(static_cast<float>(y));
477 void GraphicsContext::translate(float x, float y)
479 if (paintingDisabled())
482 cairo_t* cr = m_data->cr;
483 cairo_translate(cr, x, y);
486 IntPoint GraphicsContext::origin()
488 cairo_matrix_t matrix;
489 cairo_t* cr = m_data->cr;
490 cairo_get_matrix(cr, &matrix);
491 return IntPoint(static_cast<int>(matrix.x0), static_cast<int>(matrix.y0));
494 void GraphicsContext::setPlatformFillColor(const Color& col)
496 // FIXME: this is probably a no-op but I'm not sure
497 // notImplemented(); // commented-out because it's chatty and clutters output
500 void GraphicsContext::setPlatformStrokeColor(const Color& col)
502 // FIXME: this is probably a no-op but I'm not sure
503 //notImplemented(); // commented-out because it's chatty and clutters output
506 void GraphicsContext::setPlatformStrokeThickness(float strokeThickness)
508 if (paintingDisabled())
511 cairo_set_line_width(m_data->cr, strokeThickness);
514 void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle& strokeStyle)
516 static double dashPattern[] = {5.0, 5.0};
517 static double dotPattern[] = {1.0, 1.0};
519 if (paintingDisabled())
522 switch (strokeStyle) {
524 // FIXME: is it the right way to emulate NoStroke?
525 cairo_set_line_width(m_data->cr, 0);
528 cairo_set_dash(m_data->cr, 0, 0, 0);
531 cairo_set_dash(m_data->cr, dotPattern, 2, 0);
534 cairo_set_dash(m_data->cr, dashPattern, 2, 0);
542 void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
548 // FIXME: This should be moved to something like GraphicsContextCairoGTK.cpp,
549 // as there is a Windows implementation in platform/graphics/win/GraphicsContextCairoWin.cpp
550 void GraphicsContext::concatCTM(const AffineTransform& transform)
552 if (paintingDisabled())
555 cairo_t* cr = m_data->cr;
556 const cairo_matrix_t* matrix = reinterpret_cast<const cairo_matrix_t*>(&transform);
557 cairo_transform(cr, matrix);
561 void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
563 if (paintingDisabled())
573 r.inflate(-thickness);
577 cairo_t* cr = m_data->cr;
578 cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
579 cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
581 cairo_set_fill_rule(cr, savedFillRule);
585 void GraphicsContext::setShadow(IntSize const&, int, Color const&)
590 void GraphicsContext::clearShadow()
595 void GraphicsContext::beginTransparencyLayer(float opacity)
597 if (paintingDisabled())
600 cairo_t* cr = m_data->cr;
601 cairo_push_group(cr);
602 m_data->layers.append(opacity);
605 void GraphicsContext::endTransparencyLayer()
607 if (paintingDisabled())
610 cairo_t* cr = m_data->cr;
612 cairo_pop_group_to_source(cr);
613 cairo_paint_with_alpha(cr, m_data->layers.last());
614 m_data->layers.removeLast();
617 void GraphicsContext::clearRect(const FloatRect& rect)
619 if (paintingDisabled())
622 cairo_t* cr = m_data->cr;
625 cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
626 cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
631 void GraphicsContext::strokeRect(const FloatRect& rect, float width)
633 if (paintingDisabled())
636 cairo_t* cr = m_data->cr;
638 cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
639 setColor(cr, strokeColor());
640 cairo_set_line_width(cr, width);
645 void GraphicsContext::setLineCap(LineCap lineCap)
647 if (paintingDisabled())
650 cairo_line_cap_t cairoCap = CAIRO_LINE_CAP_BUTT;
656 cairoCap = CAIRO_LINE_CAP_ROUND;
659 cairoCap = CAIRO_LINE_CAP_SQUARE;
662 cairo_set_line_cap(m_data->cr, cairoCap);
665 void GraphicsContext::setLineJoin(LineJoin lineJoin)
667 if (paintingDisabled())
670 cairo_line_join_t cairoJoin = CAIRO_LINE_JOIN_MITER;
676 cairoJoin = CAIRO_LINE_JOIN_ROUND;
679 cairoJoin = CAIRO_LINE_JOIN_BEVEL;
682 cairo_set_line_join(m_data->cr, cairoJoin);
685 void GraphicsContext::setMiterLimit(float miter)
687 if (paintingDisabled())
690 cairo_set_miter_limit(m_data->cr, miter);
693 void GraphicsContext::setAlpha(float)
698 static inline cairo_operator_t toCairoOperator(CompositeOperator op)
702 return CAIRO_OPERATOR_CLEAR;
704 return CAIRO_OPERATOR_SOURCE;
705 case CompositeSourceOver:
706 return CAIRO_OPERATOR_OVER;
707 case CompositeSourceIn:
708 return CAIRO_OPERATOR_IN;
709 case CompositeSourceOut:
710 return CAIRO_OPERATOR_OUT;
711 case CompositeSourceAtop:
712 return CAIRO_OPERATOR_ATOP;
713 case CompositeDestinationOver:
714 return CAIRO_OPERATOR_DEST_OVER;
715 case CompositeDestinationIn:
716 return CAIRO_OPERATOR_DEST_IN;
717 case CompositeDestinationOut:
718 return CAIRO_OPERATOR_DEST_OUT;
719 case CompositeDestinationAtop:
720 return CAIRO_OPERATOR_DEST_ATOP;
722 return CAIRO_OPERATOR_XOR;
723 case CompositePlusDarker:
724 return CAIRO_OPERATOR_SATURATE;
725 case CompositeHighlight:
726 // There is no Cairo equivalent for CompositeHighlight.
727 return CAIRO_OPERATOR_OVER;
728 case CompositePlusLighter:
729 return CAIRO_OPERATOR_ADD;
731 return CAIRO_OPERATOR_SOURCE;
735 void GraphicsContext::setCompositeOperation(CompositeOperator op)
737 if (paintingDisabled())
740 cairo_set_operator(m_data->cr, toCairoOperator(op));
743 void GraphicsContext::beginPath()
745 if (paintingDisabled())
748 cairo_t* cr = m_data->cr;
752 void GraphicsContext::addPath(const Path& path)
754 if (paintingDisabled())
757 cairo_t* cr = m_data->cr;
758 cairo_path_t* p = cairo_copy_path(path.platformPath()->m_cr);
759 cairo_append_path(cr, p);
760 cairo_path_destroy(p);
763 void GraphicsContext::clip(const Path& path)
765 if (paintingDisabled())
768 cairo_t* cr = m_data->cr;
769 cairo_path_t* p = cairo_copy_path(path.platformPath()->m_cr);
770 cairo_append_path(cr, p);
771 cairo_path_destroy(p);
772 cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
773 cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
775 cairo_set_fill_rule(cr, savedFillRule);
778 void GraphicsContext::clipOut(const Path& path)
780 if (paintingDisabled())
783 cairo_t* cr = m_data->cr;
784 double x1, y1, x2, y2;
785 cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
786 cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1);
789 cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
790 cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
792 cairo_set_fill_rule(cr, savedFillRule);
795 void GraphicsContext::rotate(float radians)
797 if (paintingDisabled())
800 cairo_rotate(m_data->cr, radians);
803 void GraphicsContext::scale(const FloatSize& size)
805 if (paintingDisabled())
808 cairo_scale(m_data->cr, size.width(), size.height());
811 void GraphicsContext::clipOut(const IntRect& r)
813 if (paintingDisabled())
816 cairo_t* cr = m_data->cr;
817 double x1, y1, x2, y2;
818 cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
819 cairo_rectangle(cr, x1, x2, x2 - x1, y2 - y1);
820 cairo_rectangle(cr, r.x(), r.y(), r.width(), r.height());
821 cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
822 cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
824 cairo_set_fill_rule(cr, savedFillRule);
827 void GraphicsContext::clipOutEllipseInRect(const IntRect& r)
829 if (paintingDisabled())
837 void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
839 if (paintingDisabled())
842 cairo_t* cr = m_data->cr;
845 addPath(Path::createRoundedRectangle(r, topLeft, topRight, bottomLeft, bottomRight));
852 void GraphicsContext::setGdkExposeEvent(GdkEventExpose* expose)
854 m_data->expose = expose;
857 GdkEventExpose* GraphicsContext::gdkExposeEvent() const
859 return m_data->expose;
862 GdkDrawable* GraphicsContext::gdkDrawable() const
867 return GDK_DRAWABLE(m_data->expose->window);
870 IntPoint GraphicsContext::translatePoint(const IntPoint& point) const
873 cairo_get_matrix(m_data->cr, &tm);
874 double x = point.x();
875 double y = point.y();
877 cairo_matrix_transform_point(&tm, &x, &y);
878 return IntPoint(x, y);
882 void GraphicsContext::setUseAntialiasing(bool enable)
884 if (paintingDisabled())
887 // When true, use the default Cairo backend antialias mode (usually this
888 // enables standard 'grayscale' antialiasing); false to explicitly disable
889 // antialiasing. This is the same strategy as used in drawConvexPolygon().
890 cairo_set_antialias(m_data->cr, enable ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE);
893 void GraphicsContext::paintBuffer(ImageBuffer* buffer, const IntRect& r)
895 if (paintingDisabled())
897 cairo_surface_t* image = buffer->surface();
900 cairo_surface_flush(image);
901 cairo_surface_reference(image);
902 cairo_t* cr = platformContext();
904 cairo_translate(cr, r.x(), r.y());
905 cairo_set_source_surface(cr, image, 0, 0);
906 cairo_surface_destroy(image);
907 cairo_rectangle(cr, 0, 0, r.width(), r.height());
912 void GraphicsContext::drawImage(ImageBuffer* buffer, const FloatRect& srcRect, const FloatRect& destRect)
914 cairo_surface_flush(m_data->surface());
915 cairo_save(platformContext());
916 cairo_set_source_surface(platformContext(), m_data->surface(), srcRect.x(), srcRect.y());
917 cairo_rectangle(platformContext(), dstRect.x(), dstRect.y(), dstRect.width(), dstRect.height());
918 cairo_fill(platformContext());
919 cairo_restore(platformContext());
922 } // namespace WebCore
924 #endif // PLATFORM(CAIRO)