summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp')
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp1149
1 files changed, 0 insertions, 1149 deletions
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
deleted file mode 100644
index a6edaf7..0000000
--- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ /dev/null
@@ -1,1149 +0,0 @@
-/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- * Copyright (C) 2007 Alp Toker <alp@atoker.com>
- * Copyright (C) 2008, 2009 Dirk Schulze <krit@webkit.org>
- * Copyright (C) 2008 Nuanti Ltd.
- * Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org>
- * Copyright (C) 2010 Igalia S.L.
- * Copyright (C) Research In Motion Limited 2010. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "GraphicsContext.h"
-
-#if PLATFORM(CAIRO)
-
-#include "AffineTransform.h"
-#include "CairoPath.h"
-#include "CairoUtilities.h"
-#include "ContextShadow.h"
-#include "FloatRect.h"
-#include "Font.h"
-#include "GraphicsContextPlatformPrivateCairo.h"
-#include "OwnPtrCairo.h"
-#include "IntRect.h"
-#include "NotImplemented.h"
-#include "Path.h"
-#include "Pattern.h"
-#include "RefPtrCairo.h"
-#include "SimpleFontData.h"
-#include <cairo.h>
-#include <math.h>
-#include <stdio.h>
-#include <wtf/MathExtras.h>
-
-#if PLATFORM(GTK)
-#include <gdk/gdk.h>
-#include <pango/pango.h>
-#elif PLATFORM(WIN)
-#include <cairo-win32.h>
-#endif
-
-using namespace std;
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-namespace WebCore {
-
-static inline void setPlatformFill(GraphicsContext* context, cairo_t* cr)
-{
- cairo_pattern_t* pattern = 0;
- cairo_save(cr);
-
- const GraphicsContextState& state = context->state();
- if (state.fillPattern) {
- AffineTransform affine;
- pattern = state.fillPattern->createPlatformPattern(affine);
- cairo_set_source(cr, pattern);
- } else if (state.fillGradient)
- cairo_set_source(cr, state.fillGradient->platformGradient());
- else
- setSourceRGBAFromColor(cr, context->fillColor());
- cairo_clip_preserve(cr);
- cairo_paint_with_alpha(cr, state.globalAlpha);
- cairo_restore(cr);
- if (pattern)
- cairo_pattern_destroy(pattern);
-}
-
-static inline void setPlatformStroke(GraphicsContext* context, cairo_t* cr)
-{
- cairo_pattern_t* pattern = 0;
- cairo_save(cr);
-
- const GraphicsContextState& state = context->state();
- if (state.strokePattern) {
- AffineTransform affine;
- pattern = state.strokePattern->createPlatformPattern(affine);
- cairo_set_source(cr, pattern);
- } else if (state.strokeGradient)
- cairo_set_source(cr, state.strokeGradient->platformGradient());
- else {
- Color strokeColor = colorWithOverrideAlpha(context->strokeColor().rgb(), context->strokeColor().alpha() / 255.f * state.globalAlpha);
- setSourceRGBAFromColor(cr, strokeColor);
- }
- if (state.globalAlpha < 1.0f && (state.strokePattern || state.strokeGradient)) {
- cairo_push_group(cr);
- cairo_paint_with_alpha(cr, state.globalAlpha);
- cairo_pop_group_to_source(cr);
- }
- cairo_stroke_preserve(cr);
- cairo_restore(cr);
- if (pattern)
- cairo_pattern_destroy(pattern);
-}
-
-// A fillRect helper
-static inline void fillRectSourceOver(cairo_t* cr, const FloatRect& rect, const Color& col)
-{
- setSourceRGBAFromColor(cr, col);
- cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
- cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
- cairo_fill(cr);
-}
-
-static void addConvexPolygonToContext(cairo_t* context, size_t numPoints, const FloatPoint* points)
-{
- cairo_move_to(context, points[0].x(), points[0].y());
- for (size_t i = 1; i < numPoints; i++)
- cairo_line_to(context, points[i].x(), points[i].y());
- cairo_close_path(context);
-}
-
-enum PathDrawingStyle {
- Fill = 1,
- Stroke = 2,
- FillAndStroke = Fill + Stroke
-};
-
-static inline void drawPathShadow(GraphicsContext* context, PathDrawingStyle drawingStyle)
-{
- ContextShadow* shadow = context->contextShadow();
- ASSERT(shadow);
- if (shadow->m_type == ContextShadow::NoShadow)
- return;
-
- // Calculate the extents of the rendered solid paths.
- cairo_t* cairoContext = context->platformContext();
- OwnPtr<cairo_path_t> path(cairo_copy_path(cairoContext));
-
- FloatRect solidFigureExtents;
- double x0 = 0;
- double x1 = 0;
- double y0 = 0;
- double y1 = 0;
- if (drawingStyle & Stroke) {
- cairo_stroke_extents(cairoContext, &x0, &y0, &x1, &y1);
- solidFigureExtents = FloatRect(x0, y0, x1 - x0, y1 - y0);
- }
- if (drawingStyle & Fill) {
- cairo_fill_extents(cairoContext, &x0, &y0, &x1, &y1);
- FloatRect fillExtents(x0, y0, x1 - x0, y1 - y0);
- solidFigureExtents.unite(fillExtents);
- }
-
- cairo_t* shadowContext = shadow->beginShadowLayer(cairoContext, solidFigureExtents);
- if (!shadowContext)
- return;
-
- // It's important to copy the context properties to the new shadow
- // context to preserve things such as the fill rule and stroke width.
- copyContextProperties(cairoContext, shadowContext);
- cairo_append_path(shadowContext, path.get());
-
- if (drawingStyle & Fill)
- setPlatformFill(context, shadowContext);
- if (drawingStyle & Stroke)
- setPlatformStroke(context, shadowContext);
-
- shadow->endShadowLayer(cairoContext);
-}
-
-static void fillCurrentCairoPath(GraphicsContext* context, cairo_t* cairoContext)
-{
- cairo_set_fill_rule(cairoContext, context->fillRule() == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
- drawPathShadow(context, Fill);
-
- setPlatformFill(context, cairoContext);
- cairo_new_path(cairoContext);
-}
-
-static void strokeCurrentCairoPath(GraphicsContext* context, cairo_t* cairoContext)
-{
- drawPathShadow(context, Stroke);
- setPlatformStroke(context, cairoContext);
- cairo_new_path(cairoContext);
-}
-
-void GraphicsContext::platformInit(PlatformGraphicsContext* cr)
-{
- m_data = new GraphicsContextPlatformPrivate;
- m_data->cr = cairo_reference(cr);
- m_data->syncContext(cr);
- setPaintingDisabled(!cr);
-}
-
-void GraphicsContext::platformDestroy()
-{
- delete m_data;
-}
-
-AffineTransform GraphicsContext::getCTM() const
-{
- cairo_t* cr = platformContext();
- cairo_matrix_t m;
- cairo_get_matrix(cr, &m);
- return AffineTransform(m.xx, m.yx, m.xy, m.yy, m.x0, m.y0);
-}
-
-cairo_t* GraphicsContext::platformContext() const
-{
- return m_data->cr;
-}
-
-void GraphicsContext::savePlatformState()
-{
- cairo_save(m_data->cr);
- m_data->save();
- m_data->shadowStack.append(m_data->shadow);
-}
-
-void GraphicsContext::restorePlatformState()
-{
- cairo_restore(m_data->cr);
- m_data->restore();
-
- if (m_data->shadowStack.isEmpty())
- m_data->shadow = ContextShadow();
- else {
- m_data->shadow = m_data->shadowStack.last();
- m_data->shadowStack.removeLast();
- }
-}
-
-// Draws a filled rectangle with a stroked border.
-void GraphicsContext::drawRect(const IntRect& rect)
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = m_data->cr;
- cairo_save(cr);
-
- if (fillColor().alpha())
- fillRectSourceOver(cr, rect, fillColor());
-
- if (strokeStyle() != NoStroke) {
- setSourceRGBAFromColor(cr, strokeColor());
- FloatRect r(rect);
- r.inflate(-.5f);
- cairo_rectangle(cr, r.x(), r.y(), r.width(), r.height());
- cairo_set_line_width(cr, 1.0);
- cairo_stroke(cr);
- }
-
- cairo_restore(cr);
-}
-
-// This is only used to draw borders.
-void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
-{
- if (paintingDisabled())
- return;
-
- StrokeStyle style = strokeStyle();
- if (style == NoStroke)
- return;
-
- cairo_t* cr = m_data->cr;
- cairo_save(cr);
-
- float width = strokeThickness();
- if (width < 1)
- width = 1;
-
- FloatPoint p1 = point1;
- FloatPoint p2 = point2;
- bool isVerticalLine = (p1.x() == p2.x());
-
- adjustLineToPixelBoundaries(p1, p2, width, style);
- cairo_set_line_width(cr, width);
-
- int patWidth = 0;
- switch (style) {
- case NoStroke:
- case SolidStroke:
- break;
- case DottedStroke:
- patWidth = static_cast<int>(width);
- break;
- case DashedStroke:
- patWidth = 3*static_cast<int>(width);
- break;
- }
-
- setSourceRGBAFromColor(cr, strokeColor());
-
- cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
-
- if (patWidth) {
- // Do a rect fill of our endpoints. This ensures we always have the
- // appearance of being a border. We then draw the actual dotted/dashed line.
- if (isVerticalLine) {
- fillRectSourceOver(cr, FloatRect(p1.x() - width/2, p1.y() - width, width, width), strokeColor());
- fillRectSourceOver(cr, FloatRect(p2.x() - width/2, p2.y(), width, width), strokeColor());
- } else {
- fillRectSourceOver(cr, FloatRect(p1.x() - width, p1.y() - width/2, width, width), strokeColor());
- fillRectSourceOver(cr, FloatRect(p2.x(), p2.y() - width/2, width, width), strokeColor());
- }
-
- // Example: 80 pixels with a width of 30 pixels.
- // Remainder is 20. The maximum pixels of line we could paint
- // will be 50 pixels.
- int distance = (isVerticalLine ? (point2.y() - point1.y()) : (point2.x() - point1.x())) - 2*static_cast<int>(width);
- int remainder = distance%patWidth;
- int coverage = distance-remainder;
- int numSegments = coverage/patWidth;
-
- float patternOffset = 0;
- // Special case 1px dotted borders for speed.
- if (patWidth == 1)
- patternOffset = 1.0;
- else {
- bool evenNumberOfSegments = !(numSegments % 2);
- if (remainder)
- evenNumberOfSegments = !evenNumberOfSegments;
- if (evenNumberOfSegments) {
- if (remainder) {
- patternOffset += patWidth - remainder;
- patternOffset += remainder / 2;
- } else
- patternOffset = patWidth / 2;
- } else if (!evenNumberOfSegments) {
- if (remainder)
- patternOffset = (patWidth - remainder) / 2;
- }
- }
-
- double dash = patWidth;
- cairo_set_dash(cr, &dash, 1, patternOffset);
- }
-
- cairo_move_to(cr, p1.x(), p1.y());
- cairo_line_to(cr, p2.x(), p2.y());
-
- cairo_stroke(cr);
- cairo_restore(cr);
-}
-
-// This method is only used to draw the little circles used in lists.
-void GraphicsContext::drawEllipse(const IntRect& rect)
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = m_data->cr;
- cairo_save(cr);
- float yRadius = .5 * rect.height();
- float xRadius = .5 * rect.width();
- cairo_translate(cr, rect.x() + xRadius, rect.y() + yRadius);
- cairo_scale(cr, xRadius, yRadius);
- cairo_arc(cr, 0., 0., 1., 0., 2 * M_PI);
- cairo_restore(cr);
-
- if (fillColor().alpha()) {
- setSourceRGBAFromColor(cr, fillColor());
- cairo_fill_preserve(cr);
- }
-
- if (strokeStyle() != NoStroke) {
- setSourceRGBAFromColor(cr, strokeColor());
- cairo_set_line_width(cr, strokeThickness());
- cairo_stroke(cr);
- } else
- cairo_new_path(cr);
-}
-
-void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan)
-{
- if (paintingDisabled() || strokeStyle() == NoStroke)
- return;
-
- int x = rect.x();
- int y = rect.y();
- float w = rect.width();
- float h = rect.height();
- float scaleFactor = h / w;
- float reverseScaleFactor = w / h;
-
- float hRadius = w / 2;
- float vRadius = h / 2;
- float fa = startAngle;
- float falen = fa + angleSpan;
-
- cairo_t* cr = m_data->cr;
- cairo_save(cr);
-
- if (w != h)
- cairo_scale(cr, 1., scaleFactor);
-
- cairo_arc_negative(cr, x + hRadius, (y + vRadius) * reverseScaleFactor, hRadius, -fa * M_PI/180, -falen * M_PI/180);
-
- if (w != h)
- cairo_scale(cr, 1., reverseScaleFactor);
-
- float width = strokeThickness();
- int patWidth = 0;
-
- switch (strokeStyle()) {
- case DottedStroke:
- patWidth = static_cast<int>(width / 2);
- break;
- case DashedStroke:
- patWidth = 3 * static_cast<int>(width / 2);
- break;
- default:
- break;
- }
-
- setSourceRGBAFromColor(cr, strokeColor());
-
- if (patWidth) {
- // Example: 80 pixels with a width of 30 pixels.
- // Remainder is 20. The maximum pixels of line we could paint
- // will be 50 pixels.
- int distance;
- if (hRadius == vRadius)
- distance = static_cast<int>((M_PI * hRadius) / 2.0);
- else // We are elliptical and will have to estimate the distance
- distance = static_cast<int>((M_PI * sqrtf((hRadius * hRadius + vRadius * vRadius) / 2.0)) / 2.0);
-
- int remainder = distance % patWidth;
- int coverage = distance - remainder;
- int numSegments = coverage / patWidth;
-
- float patternOffset = 0.0;
- // Special case 1px dotted borders for speed.
- if (patWidth == 1)
- patternOffset = 1.0;
- else {
- bool evenNumberOfSegments = !(numSegments % 2);
- if (remainder)
- evenNumberOfSegments = !evenNumberOfSegments;
- if (evenNumberOfSegments) {
- if (remainder) {
- patternOffset += patWidth - remainder;
- patternOffset += remainder / 2.0;
- } else
- patternOffset = patWidth / 2.0;
- } else {
- if (remainder)
- patternOffset = (patWidth - remainder) / 2.0;
- }
- }
-
- double dash = patWidth;
- cairo_set_dash(cr, &dash, 1, patternOffset);
- }
-
- cairo_stroke(cr);
- cairo_restore(cr);
-}
-
-void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool shouldAntialias)
-{
- if (paintingDisabled())
- return;
-
- if (npoints <= 1)
- return;
-
- cairo_t* cr = m_data->cr;
-
- cairo_save(cr);
- cairo_set_antialias(cr, shouldAntialias ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE);
- addConvexPolygonToContext(cr, npoints, points);
-
- if (fillColor().alpha()) {
- setSourceRGBAFromColor(cr, fillColor());
- cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
- cairo_fill_preserve(cr);
- }
-
- if (strokeStyle() != NoStroke) {
- setSourceRGBAFromColor(cr, strokeColor());
- cairo_set_line_width(cr, strokeThickness());
- cairo_stroke(cr);
- } else
- cairo_new_path(cr);
-
- cairo_restore(cr);
-}
-
-void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points, bool antialiased)
-{
- if (paintingDisabled())
- return;
-
- if (numPoints <= 1)
- return;
-
- cairo_t* cr = m_data->cr;
-
- cairo_new_path(cr);
- cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
- cairo_antialias_t savedAntialiasRule = cairo_get_antialias(cr);
-
- cairo_set_antialias(cr, antialiased ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE);
- cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
- addConvexPolygonToContext(cr, numPoints, points);
- cairo_clip(cr);
-
- cairo_set_antialias(cr, savedAntialiasRule);
- cairo_set_fill_rule(cr, savedFillRule);
-}
-
-void GraphicsContext::fillPath(const Path& path)
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = m_data->cr;
- setPathOnCairoContext(cr, path.platformPath()->context());
- fillCurrentCairoPath(this, cr);
-}
-
-void GraphicsContext::strokePath(const Path& path)
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = m_data->cr;
- setPathOnCairoContext(cr, path.platformPath()->context());
- strokeCurrentCairoPath(this, cr);
-}
-
-void GraphicsContext::fillRect(const FloatRect& rect)
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = m_data->cr;
- cairo_save(cr);
- cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
- fillCurrentCairoPath(this, cr);
- cairo_restore(cr);
-}
-
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace)
-{
- if (paintingDisabled())
- return;
-
- if (m_data->hasShadow())
- m_data->shadow.drawRectShadow(this, enclosingIntRect(rect));
-
- if (color.alpha())
- fillRectSourceOver(m_data->cr, rect, color);
-}
-
-void GraphicsContext::clip(const FloatRect& rect)
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = m_data->cr;
- cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
- cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
- cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
- cairo_clip(cr);
- cairo_set_fill_rule(cr, savedFillRule);
- m_data->clip(rect);
-}
-
-void GraphicsContext::clipPath(const Path& path, WindRule clipRule)
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = m_data->cr;
- setPathOnCairoContext(cr, path.platformPath()->context());
- cairo_set_fill_rule(cr, clipRule == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
- cairo_clip(cr);
-}
-
-static inline void adjustFocusRingColor(Color& color)
-{
-#if !PLATFORM(GTK)
- // Force the alpha to 50%. This matches what the Mac does with outline rings.
- color.setRGB(makeRGBA(color.red(), color.green(), color.blue(), 127));
-#endif
-}
-
-static inline void adjustFocusRingLineWidth(int& width)
-{
-#if PLATFORM(GTK)
- width = 2;
-#endif
-}
-
-static inline StrokeStyle focusRingStrokeStyle()
-{
-#if PLATFORM(GTK)
- return DottedStroke;
-#else
- return SolidStroke;
-#endif
-}
-
-void GraphicsContext::drawFocusRing(const Path& path, int width, int /* offset */, const Color& color)
-{
- // FIXME: We should draw paths that describe a rectangle with rounded corners
- // so as to be consistent with how we draw rectangular focus rings.
- Color ringColor = color;
- adjustFocusRingColor(ringColor);
- adjustFocusRingLineWidth(width);
-
- cairo_t* cr = m_data->cr;
- cairo_save(cr);
- appendWebCorePathToCairoContext(cr, path);
- setSourceRGBAFromColor(cr, ringColor);
- cairo_set_line_width(cr, width);
- setPlatformStrokeStyle(focusRingStrokeStyle());
- cairo_stroke(cr);
- cairo_restore(cr);
-}
-
-void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int /* offset */, const Color& color)
-{
- if (paintingDisabled())
- return;
-
- unsigned rectCount = rects.size();
-
- cairo_t* cr = m_data->cr;
- cairo_save(cr);
- cairo_push_group(cr);
- cairo_new_path(cr);
-
-#if PLATFORM(GTK)
-#ifdef GTK_API_VERSION_2
- GdkRegion* reg = gdk_region_new();
-#else
- cairo_region_t* reg = cairo_region_create();
-#endif
-
- for (unsigned i = 0; i < rectCount; i++) {
-#ifdef GTK_API_VERSION_2
- GdkRectangle rect = rects[i];
- gdk_region_union_with_rect(reg, &rect);
-#else
- cairo_rectangle_int_t rect = rects[i];
- cairo_region_union_rectangle(reg, &rect);
-#endif
- }
- gdk_cairo_region(cr, reg);
-#ifdef GTK_API_VERSION_2
- gdk_region_destroy(reg);
-#else
- cairo_region_destroy(reg);
-#endif
-#else
- int radius = (width - 1) / 2;
- Path path;
- for (unsigned i = 0; i < rectCount; ++i) {
- if (i > 0)
- path.clear();
- path.addRoundedRect(rects[i], FloatSize(radius, radius));
- appendWebCorePathToCairoContext(cr, path);
- }
-#endif
- Color ringColor = color;
- adjustFocusRingColor(ringColor);
- adjustFocusRingLineWidth(width);
- setSourceRGBAFromColor(cr, ringColor);
- cairo_set_line_width(cr, width);
- setPlatformStrokeStyle(focusRingStrokeStyle());
-
- cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
- cairo_stroke_preserve(cr);
-
- cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
- cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
- cairo_fill(cr);
-
- cairo_pop_group_to_source(cr);
- cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
- cairo_paint(cr);
- cairo_restore(cr);
-}
-
-void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool printing)
-{
- if (paintingDisabled())
- return;
-
- IntPoint endPoint = origin + IntSize(width, 0);
- drawLine(origin, endPoint);
-}
-
-#if !PLATFORM(GTK)
-#include "DrawErrorUnderline.h"
-#endif
-
-void GraphicsContext::drawLineForTextChecking(const IntPoint& origin, int width, TextCheckingLineStyle style)
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = m_data->cr;
- cairo_save(cr);
-
- switch (style) {
- case TextCheckingSpellingLineStyle:
- cairo_set_source_rgb(cr, 1, 0, 0);
- break;
- case TextCheckingGrammarLineStyle:
- cairo_set_source_rgb(cr, 0, 1, 0);
- break;
- default:
- cairo_restore(cr);
- return;
- }
-
-#if PLATFORM(GTK)
- // We ignore most of the provided constants in favour of the platform style
- pango_cairo_show_error_underline(cr, origin.x(), origin.y(), width, cMisspellingLineThickness);
-#else
- drawErrorUnderline(cr, origin.x(), origin.y(), width, cMisspellingLineThickness);
-#endif
-
- cairo_restore(cr);
-}
-
-FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect)
-{
- FloatRect result;
- double x = frect.x();
- double y = frect.y();
- cairo_t* cr = m_data->cr;
- cairo_user_to_device(cr, &x, &y);
- x = round(x);
- y = round(y);
- cairo_device_to_user(cr, &x, &y);
- result.setX(static_cast<float>(x));
- result.setY(static_cast<float>(y));
- x = frect.width();
- y = frect.height();
- cairo_user_to_device_distance(cr, &x, &y);
- x = round(x);
- y = round(y);
- cairo_device_to_user_distance(cr, &x, &y);
- result.setWidth(static_cast<float>(x));
- result.setHeight(static_cast<float>(y));
- return result;
-}
-
-void GraphicsContext::translate(float x, float y)
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = m_data->cr;
- cairo_translate(cr, x, y);
- m_data->translate(x, y);
-}
-
-void GraphicsContext::setPlatformFillColor(const Color& col, ColorSpace colorSpace)
-{
- // Cairo contexts can't hold separate fill and stroke colors
- // so we set them just before we actually fill or stroke
-}
-
-void GraphicsContext::setPlatformStrokeColor(const Color& col, ColorSpace colorSpace)
-{
- // Cairo contexts can't hold separate fill and stroke colors
- // so we set them just before we actually fill or stroke
-}
-
-void GraphicsContext::setPlatformStrokeThickness(float strokeThickness)
-{
- if (paintingDisabled())
- return;
-
- cairo_set_line_width(m_data->cr, strokeThickness);
-}
-
-void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle& strokeStyle)
-{
- static double dashPattern[] = {5.0, 5.0};
- static double dotPattern[] = {1.0, 1.0};
-
- if (paintingDisabled())
- return;
-
- switch (strokeStyle) {
- case NoStroke:
- // FIXME: is it the right way to emulate NoStroke?
- cairo_set_line_width(m_data->cr, 0);
- break;
- case SolidStroke:
- cairo_set_dash(m_data->cr, 0, 0, 0);
- break;
- case DottedStroke:
- cairo_set_dash(m_data->cr, dotPattern, 2, 0);
- break;
- case DashedStroke:
- cairo_set_dash(m_data->cr, dashPattern, 2, 0);
- break;
- }
-}
-
-void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
-{
- notImplemented();
-}
-
-void GraphicsContext::concatCTM(const AffineTransform& transform)
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = m_data->cr;
- const cairo_matrix_t matrix = cairo_matrix_t(transform);
- cairo_transform(cr, &matrix);
- m_data->concatCTM(transform);
-}
-
-void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = m_data->cr;
- clip(rect);
-
- Path p;
- FloatRect r(rect);
- // Add outer ellipse
- p.addEllipse(r);
- // Add inner ellipse
- r.inflate(-thickness);
- p.addEllipse(r);
- appendWebCorePathToCairoContext(cr, p);
-
- cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
- cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
- cairo_clip(cr);
- cairo_set_fill_rule(cr, savedFillRule);
-}
-
-void GraphicsContext::setPlatformShadow(FloatSize const& size, float blur, Color const& color, ColorSpace)
-{
- // Cairo doesn't support shadows natively, they are drawn manually in the draw* functions
- if (m_state.shadowsIgnoreTransforms) {
- // Meaning that this graphics context is associated with a CanvasRenderingContext
- // We flip the height since CG and HTML5 Canvas have opposite Y axis
- m_state.shadowOffset = FloatSize(size.width(), -size.height());
- m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), -size.height()));
- } else
- m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), size.height()));
-
- m_data->shadow.setShadowsIgnoreTransforms(m_state.shadowsIgnoreTransforms);
-}
-
-ContextShadow* GraphicsContext::contextShadow()
-{
- return &m_data->shadow;
-}
-
-void GraphicsContext::clearPlatformShadow()
-{
- m_data->shadow.clear();
-}
-
-void GraphicsContext::beginTransparencyLayer(float opacity)
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = m_data->cr;
- cairo_push_group(cr);
- m_data->layers.append(opacity);
- m_data->beginTransparencyLayer();
-}
-
-void GraphicsContext::endTransparencyLayer()
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = m_data->cr;
-
- cairo_pop_group_to_source(cr);
- cairo_paint_with_alpha(cr, m_data->layers.last());
- m_data->layers.removeLast();
- m_data->endTransparencyLayer();
-}
-
-void GraphicsContext::clearRect(const FloatRect& rect)
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = m_data->cr;
-
- cairo_save(cr);
- cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
- cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
- cairo_fill(cr);
- cairo_restore(cr);
-}
-
-void GraphicsContext::strokeRect(const FloatRect& rect, float width)
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = m_data->cr;
- cairo_save(cr);
- cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
- cairo_set_line_width(cr, width);
- strokeCurrentCairoPath(this, cr);
- cairo_restore(cr);
-}
-
-void GraphicsContext::setLineCap(LineCap lineCap)
-{
- if (paintingDisabled())
- return;
-
- cairo_line_cap_t cairoCap = CAIRO_LINE_CAP_BUTT;
- switch (lineCap) {
- case ButtCap:
- // no-op
- break;
- case RoundCap:
- cairoCap = CAIRO_LINE_CAP_ROUND;
- break;
- case SquareCap:
- cairoCap = CAIRO_LINE_CAP_SQUARE;
- break;
- }
- cairo_set_line_cap(m_data->cr, cairoCap);
-}
-
-void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
-{
- cairo_set_dash(m_data->cr, dashes.data(), dashes.size(), dashOffset);
-}
-
-void GraphicsContext::setLineJoin(LineJoin lineJoin)
-{
- if (paintingDisabled())
- return;
-
- cairo_line_join_t cairoJoin = CAIRO_LINE_JOIN_MITER;
- switch (lineJoin) {
- case MiterJoin:
- // no-op
- break;
- case RoundJoin:
- cairoJoin = CAIRO_LINE_JOIN_ROUND;
- break;
- case BevelJoin:
- cairoJoin = CAIRO_LINE_JOIN_BEVEL;
- break;
- }
- cairo_set_line_join(m_data->cr, cairoJoin);
-}
-
-void GraphicsContext::setMiterLimit(float miter)
-{
- if (paintingDisabled())
- return;
-
- cairo_set_miter_limit(m_data->cr, miter);
-}
-
-void GraphicsContext::setAlpha(float alpha)
-{
- m_state.globalAlpha = alpha;
-}
-
-float GraphicsContext::getAlpha()
-{
- return m_state.globalAlpha;
-}
-
-void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op)
-{
- if (paintingDisabled())
- return;
-
- cairo_set_operator(m_data->cr, toCairoOperator(op));
-}
-
-void GraphicsContext::clip(const Path& path)
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = m_data->cr;
- OwnPtr<cairo_path_t> p(cairo_copy_path(path.platformPath()->context()));
- cairo_append_path(cr, p.get());
- cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
- cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
- cairo_clip(cr);
- cairo_set_fill_rule(cr, savedFillRule);
- m_data->clip(path);
-}
-
-void GraphicsContext::canvasClip(const Path& path)
-{
- clip(path);
-}
-
-void GraphicsContext::clipOut(const Path& path)
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = m_data->cr;
- double x1, y1, x2, y2;
- cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
- cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1);
- appendWebCorePathToCairoContext(cr, path);
-
- cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
- cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
- cairo_clip(cr);
- cairo_set_fill_rule(cr, savedFillRule);
-}
-
-void GraphicsContext::rotate(float radians)
-{
- if (paintingDisabled())
- return;
-
- cairo_rotate(m_data->cr, radians);
- m_data->rotate(radians);
-}
-
-void GraphicsContext::scale(const FloatSize& size)
-{
- if (paintingDisabled())
- return;
-
- cairo_scale(m_data->cr, size.width(), size.height());
- m_data->scale(size);
-}
-
-void GraphicsContext::clipOut(const IntRect& r)
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = m_data->cr;
- double x1, y1, x2, y2;
- cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
- cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1);
- cairo_rectangle(cr, r.x(), r.y(), r.width(), r.height());
- cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
- cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
- cairo_clip(cr);
- cairo_set_fill_rule(cr, savedFillRule);
-}
-
-static inline FloatPoint getPhase(const FloatRect& dest, const FloatRect& tile)
-{
- FloatPoint phase = dest.location();
- phase.move(-tile.x(), -tile.y());
-
- return phase;
-}
-
-void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
-{
- if (paintingDisabled())
- return;
-
- if (m_data->hasShadow())
- m_data->shadow.drawRectShadow(this, r, topLeft, topRight, bottomLeft, bottomRight);
-
- cairo_t* cr = m_data->cr;
- cairo_save(cr);
- Path path;
- path.addRoundedRect(r, topLeft, topRight, bottomLeft, bottomRight);
- appendWebCorePathToCairoContext(cr, path);
- setSourceRGBAFromColor(cr, color);
- cairo_fill(cr);
- cairo_restore(cr);
-}
-
-#if PLATFORM(GTK)
-void GraphicsContext::setGdkExposeEvent(GdkEventExpose* expose)
-{
- m_data->expose = expose;
-}
-
-GdkEventExpose* GraphicsContext::gdkExposeEvent() const
-{
- return m_data->expose;
-}
-
-GdkWindow* GraphicsContext::gdkWindow() const
-{
- if (!m_data->expose)
- return 0;
-
- return m_data->expose->window;
-}
-#endif
-
-void GraphicsContext::setPlatformShouldAntialias(bool enable)
-{
- if (paintingDisabled())
- return;
-
- // When true, use the default Cairo backend antialias mode (usually this
- // enables standard 'grayscale' antialiasing); false to explicitly disable
- // antialiasing. This is the same strategy as used in drawConvexPolygon().
- cairo_set_antialias(m_data->cr, enable ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE);
-}
-
-void GraphicsContext::setImageInterpolationQuality(InterpolationQuality)
-{
-}
-
-InterpolationQuality GraphicsContext::imageInterpolationQuality() const
-{
- return InterpolationDefault;
-}
-
-} // namespace WebCore
-
-#endif // PLATFORM(CAIRO)