diff options
author | Steve Block <steveblock@google.com> | 2009-12-15 10:12:09 +0000 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2009-12-17 17:41:10 +0000 |
commit | 643ca7872b450ea4efacab6188849e5aac2ba161 (patch) | |
tree | 6982576c228bcd1a7efe98afed544d840751094c /WebCore/platform/graphics/cairo | |
parent | d026980fde6eb3b01c1fe49441174e89cd1be298 (diff) | |
download | external_webkit-643ca7872b450ea4efacab6188849e5aac2ba161.zip external_webkit-643ca7872b450ea4efacab6188849e5aac2ba161.tar.gz external_webkit-643ca7872b450ea4efacab6188849e5aac2ba161.tar.bz2 |
Merge webkit.org at r51976 : Initial merge by git.
Change-Id: Ib0e7e2f0fb4bee5a186610272edf3186f0986b43
Diffstat (limited to 'WebCore/platform/graphics/cairo')
-rw-r--r-- | WebCore/platform/graphics/cairo/FontCairo.cpp | 32 | ||||
-rw-r--r-- | WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp | 281 | ||||
-rw-r--r-- | WebCore/platform/graphics/cairo/ImageBufferCairo.cpp | 4 | ||||
-rw-r--r-- | WebCore/platform/graphics/cairo/ImageCairo.cpp | 39 | ||||
-rw-r--r-- | WebCore/platform/graphics/cairo/PathCairo.cpp | 14 |
5 files changed, 272 insertions, 98 deletions
diff --git a/WebCore/platform/graphics/cairo/FontCairo.cpp b/WebCore/platform/graphics/cairo/FontCairo.cpp index 1a951c2..3bfa8f3 100644 --- a/WebCore/platform/graphics/cairo/FontCairo.cpp +++ b/WebCore/platform/graphics/cairo/FontCairo.cpp @@ -32,6 +32,7 @@ #include "GlyphBuffer.h" #include "Gradient.h" #include "GraphicsContext.h" +#include "ImageBuffer.h" #include "Pattern.h" #include "SimpleFontData.h" #include "TransformationMatrix.h" @@ -85,6 +86,34 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons shadowFillColor.getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha); +#if ENABLE(FILTERS) + cairo_text_extents_t extents; + cairo_scaled_font_glyph_extents(font->platformData().scaledFont(), glyphs, numGlyphs, &extents); + + FloatRect rect(FloatPoint(), FloatSize(extents.width, extents.height)); + IntSize shadowBufferSize; + FloatRect shadowRect; + float kernelSize = 0.f; + GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, kernelSize, rect, shadowSize, shadowBlur); + + // Draw shadow into a new ImageBuffer + OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize); + GraphicsContext* shadowContext = shadowBuffer->context(); + cairo_t* shadowCr = shadowContext->platformContext(); + + cairo_translate(shadowCr, kernelSize, extents.height + kernelSize); + + cairo_set_scaled_font(shadowCr, font->platformData().scaledFont()); + cairo_show_glyphs(shadowCr, glyphs, numGlyphs); + if (font->syntheticBoldOffset()) { + cairo_save(shadowCr); + cairo_translate(shadowCr, font->syntheticBoldOffset(), 0); + cairo_show_glyphs(shadowCr, glyphs, numGlyphs); + cairo_restore(shadowCr); + } + cairo_translate(cr, 0.0, -extents.height); + context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, kernelSize); +#else cairo_translate(cr, shadowSize.width(), shadowSize.height()); cairo_show_glyphs(cr, glyphs, numGlyphs); if (font->syntheticBoldOffset()) { @@ -93,6 +122,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons cairo_show_glyphs(cr, glyphs, numGlyphs); cairo_restore(cr); } +#endif cairo_restore(cr); } @@ -156,7 +186,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons // Re-enable the platform shadow we disabled earlier if (hasShadow) - context->setShadow(shadowSize, shadowBlur, shadowColor); + context->setShadow(shadowSize, shadowBlur, shadowColor, DeviceColorSpace); cairo_restore(cr); } diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp index 8741c5e..14034fd 100644 --- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp +++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp @@ -1,8 +1,9 @@ /* * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. * Copyright (C) 2007 Alp Toker <alp@atoker.com> - * Copyright (C) 2008 Dirk Schulze <vbs85@gmx.de> + * Copyright (C) 2008, 2009 Dirk Schulze <krit@webkit.org> * Copyright (C) 2008 Nuanti Ltd. + * Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,14 +33,17 @@ #if PLATFORM(CAIRO) #include "CairoPath.h" +#include "FEGaussianBlur.h" #include "FloatRect.h" #include "Font.h" #include "ImageBuffer.h" +#include "ImageBufferFilter.h" #include "IntRect.h" #include "NotImplemented.h" #include "Path.h" #include "Pattern.h" #include "SimpleFontData.h" +#include "SourceGraphic.h" #include "TransformationMatrix.h" #include <cairo.h> @@ -69,6 +73,42 @@ static inline void setColor(cairo_t* cr, const Color& col) cairo_set_source_rgba(cr, red, green, blue, alpha); } +static inline void setPlatformFill(GraphicsContext* context, cairo_t* cr, GraphicsContextPrivate* gcp) +{ + cairo_save(cr); + if (gcp->state.fillPattern) { + TransformationMatrix affine; + cairo_set_source(cr, gcp->state.fillPattern->createPlatformPattern(affine)); + } else if (gcp->state.fillGradient) + cairo_set_source(cr, gcp->state.fillGradient->platformGradient()); + else + setColor(cr, context->fillColor()); + cairo_clip_preserve(cr); + cairo_paint_with_alpha(cr, gcp->state.globalAlpha); + cairo_restore(cr); +} + +static inline void setPlatformStroke(GraphicsContext* context, cairo_t* cr, GraphicsContextPrivate* gcp) +{ + cairo_save(cr); + if (gcp->state.strokePattern) { + TransformationMatrix affine; + cairo_set_source(cr, gcp->state.strokePattern->createPlatformPattern(affine)); + } else if (gcp->state.strokeGradient) + cairo_set_source(cr, gcp->state.strokeGradient->platformGradient()); + else { + Color strokeColor = colorWithOverrideAlpha(context->strokeColor().rgb(), context->strokeColor().alpha() / 255.f * gcp->state.globalAlpha); + setColor(cr, strokeColor); + } + if (gcp->state.globalAlpha < 1.0f && (gcp->state.strokePattern || gcp->state.strokeGradient)) { + cairo_push_group(cr); + cairo_paint_with_alpha(cr, gcp->state.globalAlpha); + cairo_pop_group_to_source(cr); + } + cairo_stroke_preserve(cr); + cairo_restore(cr); +} + // A fillRect helper static inline void fillRectSourceOver(cairo_t* cr, const FloatRect& rect, const Color& col) { @@ -78,6 +118,81 @@ static inline void fillRectSourceOver(cairo_t* cr, const FloatRect& rect, const cairo_fill(cr); } +static inline void copyContextProperties(cairo_t* srcCr, cairo_t* dstCr) +{ + cairo_set_antialias(dstCr, cairo_get_antialias(srcCr)); + + size_t dashCount = cairo_get_dash_count(srcCr); + Vector<double> dashes(dashCount); + + double offset; + cairo_get_dash(srcCr, dashes.data(), &offset); + cairo_set_dash(dstCr, dashes.data(), dashCount, offset); + cairo_set_line_cap(dstCr, cairo_get_line_cap(srcCr)); + cairo_set_line_join(dstCr, cairo_get_line_join(srcCr)); + cairo_set_line_width(dstCr, cairo_get_line_width(srcCr)); + cairo_set_miter_limit(dstCr, cairo_get_miter_limit(srcCr)); + cairo_set_fill_rule(dstCr, cairo_get_fill_rule(srcCr)); +} + +void GraphicsContext::calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& kernelSize, const FloatRect& sourceRect, const IntSize& shadowSize, int shadowBlur) +{ +#if ENABLE(FILTERS) + // calculate the kernel size according to the HTML5 canvas shadow specification + kernelSize = (shadowBlur < 8 ? shadowBlur / 2.f : sqrt(shadowBlur * 2.f)); + int blurRadius = ceil(kernelSize); + + shadowBufferSize = IntSize(sourceRect.width() + blurRadius * 2, sourceRect.height() + blurRadius * 2); + + // determine dimensions of shadow rect + shadowRect = FloatRect(sourceRect.location(), shadowBufferSize); + shadowRect.move(shadowSize.width() - kernelSize, shadowSize.height() - kernelSize); +#endif +} + +static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPrivate* gcp, bool fillShadow, bool strokeShadow) +{ +#if ENABLE(FILTERS) + IntSize shadowSize; + int shadowBlur; + Color shadowColor; + if (!context->getShadow(shadowSize, shadowBlur, shadowColor)) + return; + + // Calculate filter values to create appropriate shadow. + cairo_t* cr = context->platformContext(); + cairo_path_t* path = cairo_copy_path(cr); + double x0, x1, y0, y1; + if (strokeShadow) + cairo_stroke_extents(cr, &x0, &y0, &x1, &y1); + else + cairo_fill_extents(cr, &x0, &y0, &x1, &y1); + FloatRect rect(x0, y0, x1 - x0, y1 - y0); + + IntSize shadowBufferSize; + FloatRect shadowRect; + float kernelSize = 0; + GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, kernelSize, rect, shadowSize, shadowBlur); + + // Create suitably-sized ImageBuffer to hold the shadow. + OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize); + + // Draw shadow into a new ImageBuffer. + cairo_t* shadowContext = shadowBuffer->context()->platformContext(); + copyContextProperties(cr, shadowContext); + cairo_translate(shadowContext, -rect.x() + kernelSize, -rect.y() + kernelSize); + cairo_new_path(shadowContext); + cairo_append_path(shadowContext, path); + + if (fillShadow) + setPlatformFill(context, shadowContext, gcp); + if (strokeShadow) + setPlatformStroke(context, shadowContext, gcp); + + context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, kernelSize); +#endif +} + GraphicsContext::GraphicsContext(PlatformGraphicsContext* cr) : m_common(createGraphicsContextPrivate()) , m_data(new GraphicsContextPlatformPrivate) @@ -387,30 +502,12 @@ void GraphicsContext::fillPath() return; cairo_t* cr = m_data->cr; - cairo_save(cr); cairo_set_fill_rule(cr, fillRule() == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING); - switch (m_common->state.fillColorSpace) { - case SolidColorSpace: - setColor(cr, fillColor()); - cairo_clip(cr); - cairo_paint_with_alpha(cr, m_common->state.globalAlpha); - break; - case PatternColorSpace: { - TransformationMatrix affine; - cairo_set_source(cr, m_common->state.fillPattern->createPlatformPattern(affine)); - cairo_clip(cr); - cairo_paint_with_alpha(cr, m_common->state.globalAlpha); - break; - } - case GradientColorSpace: - cairo_pattern_t* pattern = m_common->state.fillGradient->platformGradient(); - cairo_set_source(cr, pattern); - cairo_clip(cr); - cairo_paint_with_alpha(cr, m_common->state.globalAlpha); - break; - } - cairo_restore(cr); + drawPathShadow(this, m_common, true, false); + + setPlatformFill(this, cr, m_common); + cairo_new_path(cr); } void GraphicsContext::strokePath() @@ -419,45 +516,26 @@ void GraphicsContext::strokePath() return; cairo_t* cr = m_data->cr; - cairo_save(cr); - switch (m_common->state.strokeColorSpace) { - case SolidColorSpace: - float red, green, blue, alpha; - strokeColor().getRGBA(red, green, blue, alpha); - if (m_common->state.globalAlpha < 1.0f) - alpha *= m_common->state.globalAlpha; - cairo_set_source_rgba(cr, red, green, blue, alpha); - cairo_stroke(cr); - break; - case PatternColorSpace: { - TransformationMatrix affine; - cairo_set_source(cr, m_common->state.strokePattern->createPlatformPattern(affine)); - if (m_common->state.globalAlpha < 1.0f) { - cairo_push_group(cr); - cairo_paint_with_alpha(cr, m_common->state.globalAlpha); - cairo_pop_group_to_source(cr); - } - cairo_stroke(cr); - break; - } - case GradientColorSpace: - cairo_pattern_t* pattern = m_common->state.strokeGradient->platformGradient(); - cairo_set_source(cr, pattern); - if (m_common->state.globalAlpha < 1.0f) { - cairo_push_group(cr); - cairo_paint_with_alpha(cr, m_common->state.globalAlpha); - cairo_pop_group_to_source(cr); - } - cairo_stroke(cr); - break; - } - cairo_restore(cr); + drawPathShadow(this, m_common, false, true); + + setPlatformStroke(this, cr, m_common); + cairo_new_path(cr); + } void GraphicsContext::drawPath() { - fillPath(); - strokePath(); + if (paintingDisabled()) + return; + + cairo_t* cr = m_data->cr; + + cairo_set_fill_rule(cr, fillRule() == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING); + drawPathShadow(this, m_common, true, true); + + setPlatformFill(this, cr, m_common); + setPlatformStroke(this, cr, m_common); + cairo_new_path(cr); } void GraphicsContext::fillRect(const FloatRect& rect) @@ -470,11 +548,36 @@ void GraphicsContext::fillRect(const FloatRect& rect) fillPath(); } -void GraphicsContext::fillRect(const FloatRect& rect, const Color& color) +static void drawBorderlessRectShadow(GraphicsContext* context, const FloatRect& rect, const Color& rectColor) +{ +#if ENABLE(FILTERS) + IntSize shadowSize; + int shadowBlur; + Color shadowColor; + + if (!context->getShadow(shadowSize, shadowBlur, shadowColor)) + return; + + IntSize shadowBufferSize; + FloatRect shadowRect; + float kernelSize = 0; + GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, kernelSize, rect, shadowSize, shadowBlur); + + // Draw shadow into a new ImageBuffer + OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize); + GraphicsContext* shadowContext = shadowBuffer->context(); + shadowContext->fillRect(FloatRect(FloatPoint(kernelSize, kernelSize), rect.size()), rectColor, DeviceColorSpace); + + context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, kernelSize); +#endif +} + +void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace) { if (paintingDisabled()) return; + drawBorderlessRectShadow(this, rect, color); if (color.alpha()) fillRectSourceOver(m_data->cr, rect, color); } @@ -634,13 +737,13 @@ IntPoint GraphicsContext::origin() return IntPoint(static_cast<int>(matrix.x0), static_cast<int>(matrix.y0)); } -void GraphicsContext::setPlatformFillColor(const Color& col) +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) +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 @@ -726,9 +829,48 @@ void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer notImplemented(); } -void GraphicsContext::setPlatformShadow(IntSize const&, int, Color const&) +void GraphicsContext::setPlatformShadow(IntSize const& size, int, Color const&, ColorSpace) { - notImplemented(); + // Cairo doesn't support shadows natively, they are drawn manually in the draw* + // functions + + if (m_common->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_common->state.shadowSize = IntSize(size.width(), -size.height()); + } +} + +void GraphicsContext::createPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, const FloatRect& shadowRect, float kernelSize) +{ +#if ENABLE(FILTERS) + cairo_t* cr = m_data->cr; + + // draw the shadow without blurring, if kernelSize is zero + if (!kernelSize) { + setColor(cr, shadowColor); + cairo_mask_surface(cr, buffer->image()->nativeImageForCurrentFrame(), shadowRect.x(), shadowRect.y()); + return; + } + + // limit kernel size to 1000, this is what CG is doing. + kernelSize = std::min(1000.f, kernelSize); + + // create filter + RefPtr<Filter> filter = ImageBufferFilter::create(); + filter->setSourceImage(buffer.release()); + RefPtr<FilterEffect> source = SourceGraphic::create(); + source->setScaledSubRegion(FloatRect(FloatPoint(), shadowRect.size())); + source->setIsAlphaImage(true); + RefPtr<FilterEffect> blur = FEGaussianBlur::create(source.get(), kernelSize, kernelSize); + blur->setScaledSubRegion(FloatRect(FloatPoint(), shadowRect.size())); + blur->apply(filter.get()); + + // Mask the filter with the shadow color and draw it to the context. + // Masking makes it possible to just blur the alpha channel. + setColor(cr, shadowColor); + cairo_mask_surface(cr, blur->resultImage()->image()->nativeImageForCurrentFrame(), shadowRect.x(), shadowRect.y()); +#endif } void GraphicsContext::clearPlatformShadow() @@ -941,7 +1083,6 @@ void GraphicsContext::clipOut(const Path& path) if (paintingDisabled()) return; -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,4,0) cairo_t* cr = m_data->cr; double x1, y1, x2, y2; cairo_clip_extents(cr, &x1, &y1, &x2, &y2); @@ -952,9 +1093,6 @@ void GraphicsContext::clipOut(const Path& path) cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD); cairo_clip(cr); cairo_set_fill_rule(cr, savedFillRule); -#else - notImplemented(); -#endif } void GraphicsContext::rotate(float radians) @@ -980,19 +1118,15 @@ void GraphicsContext::clipOut(const IntRect& r) if (paintingDisabled()) return; -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,4,0) cairo_t* cr = m_data->cr; double x1, y1, x2, y2; cairo_clip_extents(cr, &x1, &y1, &x2, &y2); - cairo_rectangle(cr, x1, x2, x2 - x1, y2 - y1); + 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); -#else - notImplemented(); -#endif } void GraphicsContext::clipOutEllipseInRect(const IntRect& r) @@ -1005,7 +1139,7 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& r) clipOut(p); } -void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color) +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; @@ -1015,6 +1149,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft, beginPath(); addPath(Path::createRoundedRectangle(r, topLeft, topRight, bottomLeft, bottomRight)); setColor(cr, color); + drawPathShadow(this, m_common, true, false); cairo_fill(cr); cairo_restore(cr); } diff --git a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp index 0213944..d991c80 100644 --- a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp +++ b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp @@ -136,6 +136,7 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) *pixel = premultipliedARGBFromColor(pixelColor); } } + cairo_surface_mark_dirty_rectangle (m_data.m_surface, 0, 0, m_size.width(), m_size.height()); } template <Multiply multiplied> @@ -260,6 +261,9 @@ void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& } srcRows += srcBytesPerRow; } + cairo_surface_mark_dirty_rectangle (data.m_surface, + destx, desty, + numColumns, numRows); } void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint) diff --git a/WebCore/platform/graphics/cairo/ImageCairo.cpp b/WebCore/platform/graphics/cairo/ImageCairo.cpp index c8c992e..92e36fc 100644 --- a/WebCore/platform/graphics/cairo/ImageCairo.cpp +++ b/WebCore/platform/graphics/cairo/ImageCairo.cpp @@ -89,7 +89,7 @@ BitmapImage::BitmapImage(cairo_surface_t* surface, ImageObserver* observer) checkForSolidColor(); } -void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, CompositeOperator op) +void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op) { FloatRect srcRect(src); FloatRect dstRect(dst); @@ -105,7 +105,7 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo return; if (mayFillWithSolidColor()) { - fillWithSolidColor(context, dstRect, solidColor(), op); + fillWithSolidColor(context, dstRect, solidColor(), styleColorSpace, op); return; } @@ -125,17 +125,37 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo // Test using example site at http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image); - // To avoid the unwanted gradient effect (#14017) we use - // CAIRO_FILTER_NEAREST now, but the real fix will be to have - // CAIRO_EXTEND_PAD implemented for surfaces in Cairo allowing us to still - // use bilinear filtering - cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST); + cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD); float scaleX = srcRect.width() / dstRect.width(); float scaleY = srcRect.height() / dstRect.height(); cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, srcRect.x(), srcRect.y() }; cairo_pattern_set_matrix(pattern, &matrix); + // Draw the shadow +#if ENABLE(FILTERS) + IntSize shadowSize; + int shadowBlur; + Color shadowColor; + if (context->getShadow(shadowSize, shadowBlur, shadowColor)) { + IntSize shadowBufferSize; + FloatRect shadowRect; + float kernelSize (0.0); + GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, kernelSize, dstRect, shadowSize, shadowBlur); + shadowColor = colorWithOverrideAlpha(shadowColor.rgb(), (shadowColor.alpha() * context->getAlpha()) / 255.f); + + //draw shadow into a new ImageBuffer + OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize); + cairo_t* shadowContext = shadowBuffer->context()->platformContext(); + cairo_set_source(shadowContext, pattern); + cairo_translate(shadowContext, -dstRect.x(), -dstRect.y()); + cairo_rectangle(shadowContext, 0, 0, dstRect.width(), dstRect.height()); + cairo_fill(shadowContext); + + context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, kernelSize); + } +#endif + // Draw the image. cairo_translate(cr, dstRect.x(), dstRect.y()); cairo_set_source(cr, pattern); @@ -151,7 +171,7 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo } void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const TransformationMatrix& patternTransform, - const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect) + const FloatPoint& phase, ColorSpace, CompositeOperator op, const FloatRect& destRect) { cairo_surface_t* image = nativeImageForCurrentFrame(); if (!image) // If it's too early we won't have an image yet. @@ -180,9 +200,6 @@ void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, con cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image); cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); - // Workaround to avoid the unwanted gradient effect (#14017) - cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST); - cairo_matrix_t pattern_matrix = cairo_matrix_t(patternTransform); cairo_matrix_t phase_matrix = {1, 0, 0, 1, phase.x() + tileRect.x() * patternTransform.a(), phase.y() + tileRect.y() * patternTransform.d()}; cairo_matrix_t combined; diff --git a/WebCore/platform/graphics/cairo/PathCairo.cpp b/WebCore/platform/graphics/cairo/PathCairo.cpp index 75681bd..8bde57e 100644 --- a/WebCore/platform/graphics/cairo/PathCairo.cpp +++ b/WebCore/platform/graphics/cairo/PathCairo.cpp @@ -78,15 +78,7 @@ void Path::clear() bool Path::isEmpty() const { - cairo_t* cr = platformPath()->m_cr; -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,5,10) - return !cairo_has_current_point(cr); -#else - cairo_path_t* p = cairo_copy_path(cr); - bool hasData = p->num_data; - cairo_path_destroy(p); - return !hasData; -#endif + return !cairo_has_current_point(platformPath()->m_cr); } bool Path::hasCurrentPoint() const @@ -256,11 +248,7 @@ FloatRect Path::boundingRect() const { cairo_t* cr = platformPath()->m_cr; double x0, x1, y0, y1; -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 6, 0) cairo_path_extents(cr, &x0, &y0, &x1, &y1); -#else - cairo_stroke_extents(cr, &x0, &y0, &x1, &y1); -#endif return FloatRect(x0, y0, x1 - x0, y1 - y0); } |