コード例 #1
0
SVGPaintServerPattern::~SVGPaintServerPattern()
{
#if PLATFORM(CG)
    CGPatternRelease(m_pattern);
    CGColorSpaceRelease(m_patternSpace);
#endif
}
コード例 #2
0
void CanvasRenderingContext2D::applyFillPattern()
{
    GraphicsContext* c = drawingContext();
    if (!c)
        return;

#if PLATFORM(CG)
    // Check for case where the pattern is already set.
    CGAffineTransform m = CGContextGetCTM(c->platformContext());
    if (state().m_appliedFillPattern
            && CGAffineTransformEqualToTransform(m, state().m_fillStylePatternTransform))
        return;

    CanvasPattern* pattern = state().m_fillStyle->pattern();
    if (!pattern)
        return;

    CGPatternRef platformPattern = pattern->createPattern(m);
    if (!platformPattern)
        return;

    CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(0);
    CGContextSetFillColorSpace(c->platformContext(), patternSpace);
    CGColorSpaceRelease(patternSpace);

    const CGFloat patternAlpha = 1;
    CGContextSetFillPattern(c->platformContext(), platformPattern, &patternAlpha);
    CGPatternRelease(platformPattern);

    state().m_fillStylePatternTransform = m;
#elif PLATFORM(QT)
    fprintf(stderr, "FIXME: CanvasRenderingContext2D::applyFillPattern\n");
#endif
    state().m_appliedFillPattern = true;
}
コード例 #3
0
void SVGPaintServerPattern::teardown(GraphicsContext*& context, const RenderObject*, SVGPaintTargetType, bool) const
{
    CGPatternRelease(m_pattern);
    m_pattern = 0;

    context->restore();
}
コード例 #4
0
void CanvasRenderingContext2D::applyFillPattern()
{
    GraphicsContext* c = drawingContext();
    if (!c)
        return;

#if PLATFORM(CG)
    // Check for case where the pattern is already set.
    CGAffineTransform m = CGContextGetCTM(c->platformContext());
    if (state().m_appliedFillPattern
            && CGAffineTransformEqualToTransform(m, state().m_fillStylePatternTransform))
        return;

    CanvasPattern* pattern = state().m_fillStyle->pattern();
    if (!pattern)
        return;

    CGPatternRef platformPattern = pattern->createPattern(m);
    if (!platformPattern)
        return;

    CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(0);
    CGContextSetFillColorSpace(c->platformContext(), patternSpace);
    CGColorSpaceRelease(patternSpace);

    const CGFloat patternAlpha = 1;
    CGContextSetFillPattern(c->platformContext(), platformPattern, &patternAlpha);
    CGPatternRelease(platformPattern);

    state().m_fillStylePatternTransform = m;
#elif PLATFORM(QT)
    notImplemented();
#elif PLATFORM(CAIRO) && !PLATFORM(BAL)
    CanvasPattern* pattern = state().m_fillStyle->pattern();
    if (!pattern)
        return;

    cairo_t* cr = c->platformContext();
    cairo_matrix_t m;
    cairo_get_matrix(cr, &m);

    cairo_pattern_t* platformPattern = pattern->createPattern(m);
    if (!platformPattern)
        return;

    cairo_set_source(cr, platformPattern);
    cairo_pattern_destroy(platformPattern);
#elif PLATFORM(BAL)
    notImplemented();
#endif
    state().m_appliedFillPattern = true;
}
コード例 #5
0
void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const TransformationMatrix& patternTransform,
                        const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
{
    if (!nativeImageForCurrentFrame())
        return;

    ASSERT(patternTransform.isInvertible());
    if (!patternTransform.isInvertible())
        // Avoid a hang under CGContextDrawTiledImage on release builds.
        return;

    CGContextRef context = ctxt->platformContext();
    ctxt->save();
    CGContextClipToRect(context, destRect);
    ctxt->setCompositeOperation(op);
    CGContextTranslateCTM(context, destRect.x(), destRect.y() + destRect.height());
    CGContextScaleCTM(context, 1, -1);
    
    // Compute the scaled tile size.
    float scaledTileHeight = tileRect.height() * narrowPrecisionToFloat(patternTransform.d());
    
    // We have to adjust the phase to deal with the fact we're in Cartesian space now (with the bottom left corner of destRect being
    // the origin).
    float adjustedX = phase.x() - destRect.x() + tileRect.x() * narrowPrecisionToFloat(patternTransform.a()); // We translated the context so that destRect.x() is the origin, so subtract it out.
    float adjustedY = destRect.height() - (phase.y() - destRect.y() + tileRect.y() * narrowPrecisionToFloat(patternTransform.d()) + scaledTileHeight);

    CGImageRef tileImage = nativeImageForCurrentFrame();
    float h = CGImageGetHeight(tileImage);

    CGImageRef subImage;
    if (tileRect.size() == size())
        subImage = tileImage;
    else {
        // Copying a sub-image out of a partially-decoded image stops the decoding of the original image. It should never happen
        // because sub-images are only used for border-image, which only renders when the image is fully decoded.
        ASSERT(h == height());
        subImage = CGImageCreateWithImageInRect(tileImage, tileRect);
    }
    
#ifndef BUILDING_ON_TIGER
    // Leopard has an optimized call for the tiling of image patterns, but we can only use it if the image has been decoded enough that
    // its buffer is the same size as the overall image.  Because a partially decoded CGImageRef with a smaller width or height than the
    // overall image buffer needs to tile with "gaps", we can't use the optimized tiling call in that case.
    // FIXME: Could create WebKitSystemInterface SPI for CGCreatePatternWithImage2 and probably make Tiger tile faster as well.
    // FIXME: We cannot use CGContextDrawTiledImage with scaled tiles on Leopard, because it suffers from rounding errors.  Snow Leopard is ok.
    float scaledTileWidth = tileRect.width() * narrowPrecisionToFloat(patternTransform.a());
    float w = CGImageGetWidth(tileImage);
#ifdef BUILDING_ON_LEOPARD
    if (w == size().width() && h == size().height() && scaledTileWidth == tileRect.width() && scaledTileHeight == tileRect.height())
#else
    if (w == size().width() && h == size().height())
#endif
        CGContextDrawTiledImage(context, FloatRect(adjustedX, adjustedY, scaledTileWidth, scaledTileHeight), subImage);
    else {
#endif

    // On Leopard, this code now only runs for partially decoded images whose buffers do not yet match the overall size of the image.
    // On Tiger this code runs all the time.  This code is suboptimal because the pattern does not reference the image directly, and the
    // pattern is destroyed before exiting the function.  This means any decoding the pattern does doesn't end up cached anywhere, so we
    // redecode every time we paint.
    static const CGPatternCallbacks patternCallbacks = { 0, drawPatternCallback, NULL };
    CGAffineTransform matrix = CGAffineTransformMake(narrowPrecisionToCGFloat(patternTransform.a()), 0, 0, narrowPrecisionToCGFloat(patternTransform.d()), adjustedX, adjustedY);
    matrix = CGAffineTransformConcat(matrix, CGContextGetCTM(context));
    // The top of a partially-decoded image is drawn at the bottom of the tile. Map it to the top.
    matrix = CGAffineTransformTranslate(matrix, 0, size().height() - h);
    CGPatternRef pattern = CGPatternCreate(subImage, CGRectMake(0, 0, tileRect.width(), tileRect.height()),
                                           matrix, tileRect.width(), tileRect.height(), 
                                           kCGPatternTilingConstantSpacing, true, &patternCallbacks);
    if (pattern == NULL) {
        if (subImage != tileImage)
            CGImageRelease(subImage);
        ctxt->restore();
        return;
    }

    CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
    
    CGFloat alpha = 1;
    CGColorRef color = CGColorCreateWithPattern(patternSpace, pattern, &alpha);
    CGContextSetFillColorSpace(context, patternSpace);
    CGColorSpaceRelease(patternSpace);
    CGPatternRelease(pattern);

    // FIXME: Really want a public API for this.  It is just CGContextSetBaseCTM(context, CGAffineTransformIdentiy).
    wkSetPatternBaseCTM(context, CGAffineTransformIdentity);
    CGContextSetPatternPhase(context, CGSizeZero);

    CGContextSetFillColorWithColor(context, color);
    CGContextFillRect(context, CGContextGetClipBoundingBox(context));
    
    CGColorRelease(color);
    
#ifndef BUILDING_ON_TIGER
    }
#endif

    if (subImage != tileImage)
        CGImageRelease(subImage);
    ctxt->restore();

    if (imageObserver())
        imageObserver()->didDraw(this);
}