Esempio n. 1
0
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);
}
Esempio n. 3
0
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);
}
Esempio n. 4
0
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());
}