void PlatformContextCairo::drawSurfaceToContext(cairo_surface_t* surface, const FloatRect& destRect, const FloatRect& srcRect, GraphicsContext* context) { // If we're drawing a sub portion of the image or scaling then create // a pattern transformation on the image and draw the transformed pattern. // Test using example site at http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html RefPtr<cairo_pattern_t> pattern = adoptRef(cairo_pattern_create_for_surface(surface)); ASSERT(m_state); switch (m_state->m_imageInterpolationQuality) { case InterpolationNone: case InterpolationLow: cairo_pattern_set_filter(pattern.get(), CAIRO_FILTER_FAST); break; case InterpolationMedium: case InterpolationHigh: cairo_pattern_set_filter(pattern.get(), CAIRO_FILTER_BILINEAR); break; case InterpolationDefault: cairo_pattern_set_filter(pattern.get(), CAIRO_FILTER_BILINEAR); break; } cairo_pattern_set_extend(pattern.get(), CAIRO_EXTEND_PAD); float scaleX = srcRect.width() / destRect.width(); float scaleY = srcRect.height() / destRect.height(); cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, srcRect.x(), srcRect.y() }; cairo_pattern_set_matrix(pattern.get(), &matrix); ShadowBlur& shadow = context->platformContext()->shadowBlur(); if (shadow.type() != ShadowBlur::NoShadow) { if (GraphicsContext* shadowContext = shadow.beginShadowLayer(context, destRect)) { drawPatternToCairoContext(shadowContext->platformContext()->cr(), pattern.get(), destRect, 1); shadow.endShadowLayer(context); } } cairo_save(m_cr.get()); drawPatternToCairoContext(m_cr.get(), pattern.get(), destRect, globalAlpha()); cairo_restore(m_cr.get()); }
void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace 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. return; cairo_t* cr = context->platformContext()->cr(); drawPatternToCairoContext(cr, image, size(), tileRect, patternTransform, phase, toCairoOperator(op), destRect); if (imageObserver()) imageObserver()->didDraw(this); }
void Image::drawPattern(GraphicsContext& context, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator op, const FloatRect& destRect, BlendMode blendOp) { RefPtr<cairo_surface_t> surface = nativeImageForCurrentFrame(); if (!surface) // If it's too early we won't have an image yet. return; cairo_t* cr = context.platformContext()->cr(); cairo_operator_t cairoOp; if (blendOp == BlendModeNormal) cairoOp = toCairoOperator(op); else cairoOp = toCairoOperator(blendOp); drawPatternToCairoContext(cr, surface.get(), IntSize(size()), tileRect, patternTransform, phase, cairoOp, destRect); if (imageObserver()) imageObserver()->didDraw(this); }
void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace 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. return; cairo_t* cr = context->platformContext()->cr(); drawPatternToCairoContext(cr, image, size(), tileRect, patternTransform, phase, toCairoOperator(op), destRect); if (imageObserver()) imageObserver()->didDraw(this); //+EAWebKitChange //5/30/2012 #if ENABLE(IMAGE_COMPRESSION) // Check if this is a compressed surface. const void* pCompressedSurfaceUserData = cairo_surface_get_user_data (image, (cairo_user_data_key_t*) ImageCompressionGetUserDataKey()); if (pCompressedSurfaceUserData) cairo_surface_destroy(image); #endif //-EAWebKitChange }
void PlatformContextCairo::drawSurfaceToContext(cairo_surface_t* surface, const FloatRect& destRect, const FloatRect& originalSrcRect, GraphicsContext* context) { FloatRect srcRect = originalSrcRect; // We need to account for negative source dimensions by flipping the rectangle. if (originalSrcRect.width() < 0) { srcRect.setX(originalSrcRect.x() + originalSrcRect.width()); srcRect.setWidth(std::fabs(originalSrcRect.width())); } if (originalSrcRect.height() < 0) { srcRect.setY(originalSrcRect.y() + originalSrcRect.height()); srcRect.setHeight(std::fabs(originalSrcRect.height())); } // Cairo subsurfaces don't support floating point boundaries well, so we expand the rectangle. IntRect expandedSrcRect(enclosingIntRect(srcRect)); // We use a subsurface here so that we don't end up sampling outside the originalSrcRect rectangle. // See https://bugs.webkit.org/show_bug.cgi?id=58309 RefPtr<cairo_surface_t> subsurface = adoptRef(cairo_surface_create_for_rectangle( surface, expandedSrcRect.x(), expandedSrcRect.y(), expandedSrcRect.width(), expandedSrcRect.height())); RefPtr<cairo_pattern_t> pattern = adoptRef(cairo_pattern_create_for_surface(subsurface.get())); ASSERT(m_state); switch (m_state->m_imageInterpolationQuality) { case InterpolationNone: case InterpolationLow: cairo_pattern_set_filter(pattern.get(), CAIRO_FILTER_FAST); break; case InterpolationMedium: case InterpolationHigh: cairo_pattern_set_filter(pattern.get(), CAIRO_FILTER_BILINEAR); break; case InterpolationDefault: cairo_pattern_set_filter(pattern.get(), CAIRO_FILTER_BILINEAR); break; } cairo_pattern_set_extend(pattern.get(), CAIRO_EXTEND_PAD); // The pattern transformation properly scales the pattern for when the source rectangle is a // different size than the destination rectangle. We also account for any offset we introduced // by expanding floating point source rectangle sizes. It's important to take the absolute value // of the scale since the original width and height might be negative. float scaleX = std::fabs(srcRect.width() / destRect.width()); float scaleY = std::fabs(srcRect.height() / destRect.height()); float leftPadding = static_cast<float>(expandedSrcRect.x()) - floorf(srcRect.x()); float topPadding = static_cast<float>(expandedSrcRect.y()) - floorf(srcRect.y()); cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, leftPadding, topPadding }; cairo_pattern_set_matrix(pattern.get(), &matrix); ShadowBlur& shadow = context->platformContext()->shadowBlur(); if (shadow.type() != ShadowBlur::NoShadow) { if (GraphicsContext* shadowContext = shadow.beginShadowLayer(context, destRect)) { drawPatternToCairoContext(shadowContext->platformContext()->cr(), pattern.get(), destRect, 1); shadow.endShadowLayer(context); } } cairo_save(m_cr.get()); drawPatternToCairoContext(m_cr.get(), pattern.get(), destRect, globalAlpha()); cairo_restore(m_cr.get()); }