コード例 #1
0
bool SVGLayoutSupport::updateGraphicsContext(const PaintInfo& paintInfo, GraphicsContextStateSaver& stateSaver, const ComputedStyle& style, LayoutObject& layoutObject, LayoutSVGResourceMode resourceMode, const AffineTransform* additionalPaintServerTransform)
{
    ASSERT(paintInfo.context == stateSaver.context());

    GraphicsContext& context = *paintInfo.context;
    if (paintInfo.isRenderingClipPathAsMaskImage()) {
        if (resourceMode == ApplyToStrokeMode)
            return false;
        context.setFillColor(SVGComputedStyle::initialFillPaintColor());
        return true;
    }

    SVGPaintServer paintServer = SVGPaintServer::requestForLayoutObject(layoutObject, style, resourceMode);
    if (!paintServer.isValid())
        return false;

    if (additionalPaintServerTransform && paintServer.isTransformDependent())
        paintServer.prependTransform(*additionalPaintServerTransform);

    const SVGComputedStyle& svgStyle = style.svgStyle();
    float paintAlpha = resourceMode == ApplyToFillMode ? svgStyle.fillOpacity() : svgStyle.strokeOpacity();
    paintServer.apply(context, resourceMode, paintAlpha, stateSaver);

    if (resourceMode == ApplyToFillMode)
        context.setFillRule(svgStyle.fillRule());
    else
        applyStrokeStyleToContext(context, style, layoutObject);

    return true;
}
コード例 #2
0
ファイル: CgSupport.cpp プロジェクト: jackiekaon/owb-mirror
FloatRect strokeBoundingBox(const Path& path, RenderStyle* style, const RenderObject* object)
{
    // the bbox might grow if the path is stroked.
    // and CGPathGetBoundingBox doesn't support that, so we'll have
    // to make an alternative call...

    // FIXME: since this is mainly used to decide what to repaint,
    // perhaps it would be sufficient to just outset the fill bbox by
    // the stroke width - that should be way cheaper and simpler than
    // what we do here.

    CGPathRef cgPath = path.platformPath();

    CGContextRef context = scratchContext();
    CGContextSaveGState(context);

    CGContextBeginPath(context);
    CGContextAddPath(context, cgPath);

    GraphicsContext gc(context);
    applyStrokeStyleToContext(&gc, style, object);

    CGContextReplacePathWithStrokedPath(context);
    if (CGContextIsPathEmpty(context)) {
        // CGContextReplacePathWithStrokedPath seems to fail to create a path sometimes, this is not well understood.
        // returning here prevents CG from logging to the console from CGContextGetPathBoundingBox
        CGContextRestoreGState(context);
        return FloatRect();
    }

    CGRect box = CGContextGetPathBoundingBox(context);
    CGContextRestoreGState(context);

    return FloatRect(box);
}
コード例 #3
0
ファイル: SVGRenderSupport.cpp プロジェクト: kjthegod/WebKit
bool SVGRenderSupport::updateGraphicsContext(const PaintInfo& paintInfo, GraphicsContextStateSaver& stateSaver, RenderStyle* style, RenderObject& renderer, RenderSVGResourceMode resourceMode, const AffineTransform* additionalPaintServerTransform)
{
    ASSERT(style);
    ASSERT(paintInfo.context == stateSaver.context());

    GraphicsContext* context = paintInfo.context;
    if (paintInfo.isRenderingClipPathAsMaskImage()) {
        if (resourceMode == ApplyToStrokeMode)
            return false;
        context->setAlphaAsFloat(1);
        context->setFillColor(SVGRenderStyle::initialFillPaintColor());
        return true;
    }

    SVGPaintServer paintServer = SVGPaintServer::requestForRenderer(renderer, style, resourceMode);
    if (!paintServer.isValid())
        return false;

    if (additionalPaintServerTransform && paintServer.isTransformDependent())
        paintServer.prependTransform(*additionalPaintServerTransform);

    paintServer.apply(*context, resourceMode, &stateSaver);

    const SVGRenderStyle& svgStyle = style->svgStyle();

    if (resourceMode == ApplyToFillMode) {
        context->setAlphaAsFloat(svgStyle.fillOpacity());
        context->setFillRule(svgStyle.fillRule());
    } else {
        context->setAlphaAsFloat(svgStyle.strokeOpacity());
        applyStrokeStyleToContext(context, style, &renderer);
    }
    return true;
}
コード例 #4
0
bool SVGPaintServerSolid::setup(GraphicsContext*& context, const RenderObject* object, const RenderStyle* style, SVGPaintTargetType type, bool isPaintingText) const
{
    const SVGRenderStyle* svgStyle = style ? style->svgStyle() : 0;
    ColorSpace colorSpace = style ? style->colorSpace() : DeviceColorSpace;

    if ((type & ApplyToFillTargetType) && (!style || svgStyle->hasFill())) {
        context->setAlpha(style ? svgStyle->fillOpacity() : 1);
        context->setFillColor(color().rgb(), colorSpace);
        context->setFillRule(style ? svgStyle->fillRule() : RULE_NONZERO);

        if (isPaintingText)
            context->setTextDrawingMode(cTextFill);
    }

    if ((type & ApplyToStrokeTargetType) && (!style || svgStyle->hasStroke())) {
        context->setAlpha(style ? svgStyle->strokeOpacity() : 1);
        context->setStrokeColor(color().rgb(), colorSpace);

        if (style)
            applyStrokeStyleToContext(context, style, object);

        if (isPaintingText)
            context->setTextDrawingMode(cTextStroke);
    }

    return true;
}
bool SVGPaintServerGradient::setup(GraphicsContext*& context, const RenderObject* object, SVGPaintTargetType type, bool isPaintingText) const
{
    m_ownerElement->buildGradient();

    const SVGRenderStyle* style = object->style()->svgStyle();
    bool isFilled = (type & ApplyToFillTargetType) && style->hasFill();
    bool isStroked = (type & ApplyToStrokeTargetType) && style->hasStroke();

    ASSERT(isFilled && !isStroked || !isFilled && isStroked);

    context->save();

    if (isPaintingText) {
#if PLATFORM(CG)
        if (!createMaskAndSwapContextForTextGradient(context, m_savedContext, m_imageBuffer, object)) {
            context->restore();
            return false;
        }
#endif
        context->setTextDrawingMode(isFilled ? cTextFill : cTextStroke);
    }

    if (isFilled) {
        context->setAlpha(style->fillOpacity());
        context->setFillGradient(m_gradient);
        context->setFillRule(style->fillRule());
    }
    if (isStroked) {
        context->setAlpha(style->strokeOpacity());
        context->setStrokeGradient(m_gradient);
        applyStrokeStyleToContext(context, object->style(), object);
    }

    if (boundingBoxMode() && !isPaintingText) {
        FloatRect bbox = object->relativeBBox(false);
        // Don't use gradientes for 1d objects like horizontal/vertical 
        // lines or rectangles without width or height.
        if (bbox.width() == 0 || bbox.height() == 0) {
            Color color(0, 0, 0);
            context->setStrokeColor(color);
            return true;
        }
        context->translate(bbox.x(), bbox.y());
        context->scale(FloatSize(bbox.width(), bbox.height()));

        // With scaling the context, the strokeThickness is scaled too. We have to
        // undo this.
        float strokeThickness = std::max((context->strokeThickness() / ((bbox.width() + bbox.height()) / 2) - 0.001f), 0.f);
        context->setStrokeThickness(strokeThickness);
    }
    context->concatCTM(gradientTransform());
    context->setSpreadMethod(spreadMethod());

    return true;
}
コード例 #6
0
ファイル: SkiaSupport.cpp プロジェクト: Czerrr/ISeeBrowser
FloatRect strokeBoundingBox(const Path& path, RenderStyle* style, const RenderObject* object)
 {
     GraphicsContext* scratch = scratchContext();

     scratch->save();
     applyStrokeStyleToContext(scratch, style, object);
     FloatRect bbox = scratch->getPathBoundingBox(path);
     scratch->restore();

     return bbox;
}
コード例 #7
0
bool SVGPaintServerGradient::setup(GraphicsContext*& context, const RenderObject* object,
                                   SVGPaintTargetType type, bool isPaintingText) const
{
    m_ownerElement->buildGradient();

    QPainter* painter(context ? context->platformContext() : 0);
    Q_ASSERT(painter);

    QPainterPath* path(context ? context->currentPath() : 0);
    Q_ASSERT(path);

    const SVGRenderStyle* svgStyle = object->style()->svgStyle();
    RenderStyle* style = object->style();

    QGradient gradient = setupGradient(context, object);

    painter->setPen(Qt::NoPen);
    painter->setBrush(Qt::NoBrush);

    if (spreadMethod() == SpreadMethodRepeat)
        gradient.setSpread(QGradient::RepeatSpread);
    else if (spreadMethod() == SpreadMethodReflect)
        gradient.setSpread(QGradient::ReflectSpread);
    else
        gradient.setSpread(QGradient::PadSpread);    
    double opacity = 1.0;

    if ((type & ApplyToFillTargetType) && svgStyle->hasFill()) {
        fillColorArray(gradient, gradientStops(), opacity);

        QBrush brush(gradient);
        brush.setMatrix(gradientTransform());

        painter->setBrush(brush);
        context->setFillRule(svgStyle->fillRule());
    }

    if ((type & ApplyToStrokeTargetType) && svgStyle->hasStroke()) {
        fillColorArray(gradient, gradientStops(), opacity);

        QPen pen;
        QBrush brush(gradient);
        brush.setMatrix(gradientTransform());
        pen.setBrush(brush);
        painter->setPen(pen);

        applyStrokeStyleToContext(context, style, object);
    }

    return true;
}
コード例 #8
0
bool SVGPaintServerGradient::setup(GraphicsContext*& context, const RenderObject* object, SVGPaintTargetType type, bool isPaintingText) const
{
    m_ownerElement->buildGradient();

    // We need a hook to call this when the gradient gets updated, before drawn.
    if (!m_shadingCache)
        const_cast<SVGPaintServerGradient*>(this)->updateQuartzGradientCache(this);

    CGContextRef contextRef = context->platformContext(); 
    RenderStyle* style = object->style();
    ASSERT(contextRef);

    context->save();
    CGContextSetAlpha(contextRef, style->opacity());

    if ((type & ApplyToFillTargetType) && style->svgStyle()->hasFill()) {
        context->save();      

        if (isPaintingText)
            context->setTextDrawingMode(cTextClip);
    }

    if ((type & ApplyToStrokeTargetType) && style->svgStyle()->hasStroke()) {
        context->save();
        applyStrokeStyleToContext(contextRef, style, object);

        if (isPaintingText) {
            IntRect maskRect = const_cast<RenderObject*>(object)->absoluteBoundingBoxRect();
            maskRect = object->absoluteTransform().inverse().mapRect(maskRect);

            auto_ptr<ImageBuffer> maskImage = ImageBuffer::create(IntSize(maskRect.width(), maskRect.height()), false);
            // FIXME: maskImage could be NULL

            GraphicsContext* maskImageContext = maskImage->context();

            maskImageContext->save();
            maskImageContext->translate(-maskRect.x(), -maskRect.y());

            const_cast<RenderObject*>(object)->style()->setColor(Color(255, 255, 255));
            maskImageContext->setTextDrawingMode(cTextStroke);

            m_imageBuffer = maskImage.release();
            m_savedContext = context;
            context = maskImageContext;
        }
    }

    return true;
}
コード例 #9
0
ファイル: RenderPathCg.cpp プロジェクト: Czerrr/ISeeBrowser
bool RenderPath::strokeContains(const FloatPoint& point, bool requiresStroke) const
{
    if (path().isEmpty())
        return false;

    if (requiresStroke && !SVGPaintServer::strokePaintServer(style(), this))
        return false;

    CGMutablePathRef cgPath = path().platformPath();
    
    CGContextRef context = scratchContext();
    CGContextSaveGState(context);
    
    CGContextBeginPath(context);
    CGContextAddPath(context, cgPath);

    GraphicsContext gc(context);
    applyStrokeStyleToContext(&gc, style(), this);

    bool hitSuccess = CGContextPathContainsPoint(context, point, kCGPathStroke);
    CGContextRestoreGState(context);
    
    return hitSuccess;
}
コード例 #10
0
bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle* style, GraphicsContext*& context, unsigned short resourceMode)
{
    ASSERT(object);
    ASSERT(style);
    ASSERT(context);
    ASSERT(resourceMode != ApplyToDefaultMode);

    // Be sure to synchronize all SVG properties on the patternElement _before_ processing any further.
    // Otherwhise the call to collectPatternAttributes() in createTileImage(), may cause the SVG DOM property
    // synchronization to kick in, which causes invalidateClients() to be called, which in turn deletes our
    // PatternData object! Leaving out the line below will cause svg/dynamic-updates/SVGPatternElement-svgdom* to crash.
    SVGPatternElement* patternElement = static_cast<SVGPatternElement*>(node());
    if (!patternElement)
        return false;

    patternElement->updateAnimatedSVGAttribute(anyQName());

    if (!m_pattern.contains(object))
        m_pattern.set(object, new PatternData);

    PatternData* patternData = m_pattern.get(object);
    if (!patternData->pattern) {

        // Create tile image
        OwnPtr<ImageBuffer> tileImage = createTileImage(patternData, patternElement, object);
        if (!tileImage)
            return false;

        // Create pattern object
        buildPattern(patternData, tileImage.release());

        if (!patternData->pattern)
            return false;

        patternData->pattern->setPatternSpaceTransform(patternData->transform);
    }

    // Draw pattern
    context->save();

    const SVGRenderStyle* svgStyle = style->svgStyle();
    ASSERT(svgStyle);

    if (resourceMode & ApplyToFillMode) {
        context->setAlpha(svgStyle->fillOpacity());
        context->setFillPattern(patternData->pattern);
        context->setFillRule(svgStyle->fillRule());
    } else if (resourceMode & ApplyToStrokeMode) {
        if (svgStyle->vectorEffect() == VE_NON_SCALING_STROKE)
            patternData->pattern->setPatternSpaceTransform(transformOnNonScalingStroke(object, patternData->transform));
        context->setAlpha(svgStyle->strokeOpacity());
        context->setStrokePattern(patternData->pattern);
        applyStrokeStyleToContext(context, style, object);
    }

    if (resourceMode & ApplyToTextMode) {
        if (resourceMode & ApplyToFillMode) {
            context->setTextDrawingMode(cTextFill);

#if PLATFORM(CG)
            context->applyFillPattern();
#endif
        } else if (resourceMode & ApplyToStrokeMode) {
            context->setTextDrawingMode(cTextStroke);

#if PLATFORM(CG)
            context->applyStrokePattern();
#endif
        }
    }

    return true;
}
コード例 #11
0
bool SVGPaintServerPattern::setup(GraphicsContext*& context, const RenderObject* object, SVGPaintTargetType type, bool isPaintingText) const
{
    FloatRect targetRect = object->objectBoundingBox();

    const SVGRenderStyle* style = object->style()->svgStyle();
    bool isFilled = (type & ApplyToFillTargetType) && style->hasFill();
    bool isStroked = (type & ApplyToStrokeTargetType) && style->hasStroke();

    ASSERT(isFilled && !isStroked || !isFilled && isStroked);

    m_ownerElement->buildPattern(targetRect);
    if (!tile())
        return false;

    context->save();

    ASSERT(!m_pattern);

    IntRect tileRect = tile()->image()->rect();
    if (tileRect.width() > patternBoundaries().width() || tileRect.height() > patternBoundaries().height()) {
        // Draw the first cell of the pattern manually to support overflow="visible" on all platforms.
        int tileWidth = static_cast<int>(patternBoundaries().width() + 0.5f);
        int tileHeight = static_cast<int>(patternBoundaries().height() + 0.5f);
        OwnPtr<ImageBuffer> tileImage = ImageBuffer::create(IntSize(tileWidth, tileHeight));
  
        GraphicsContext* tileImageContext = tileImage->context();

        int numY = static_cast<int>(ceilf(tileRect.height() / tileHeight)) + 1;
        int numX = static_cast<int>(ceilf(tileRect.width() / tileWidth)) + 1;

        tileImageContext->save();
        tileImageContext->translate(-patternBoundaries().width() * numX, -patternBoundaries().height() * numY);
        for (int i = numY; i > 0; i--) {
            tileImageContext->translate(0, patternBoundaries().height());
            for (int j = numX; j > 0; j--) {
                tileImageContext->translate(patternBoundaries().width(), 0);
                tileImageContext->drawImage(tile()->image(), object->style()->colorSpace(), tileRect, tileRect);
            }
            tileImageContext->translate(-patternBoundaries().width() * numX, 0);
        }
        tileImageContext->restore();

        m_pattern = Pattern::create(tileImage->image(), true, true);
    }
    else
        m_pattern = Pattern::create(tile()->image(), true, true);

    if (isFilled) {
        context->setAlpha(style->fillOpacity());
        context->setFillPattern(m_pattern);
        context->setFillRule(style->fillRule());
    }
    if (isStroked) {
        context->setAlpha(style->strokeOpacity());
        context->setStrokePattern(m_pattern);
        applyStrokeStyleToContext(context, object->style(), object);
    }

    TransformationMatrix matrix;
    matrix.translate(patternBoundaries().x(), patternBoundaries().y());
    matrix.multiply(patternTransform());
    m_pattern->setPatternSpaceTransform(matrix);

    if (isPaintingText) {
        context->setTextDrawingMode(isFilled ? cTextFill : cTextStroke);
#if PLATFORM(CG)
        if (isFilled)
            context->applyFillPattern();
        else
            context->applyStrokePattern();
#endif
    }

    return true;
}
コード例 #12
0
bool SVGPaintServerGradient::setup(GraphicsContext*& context, 
    const RenderObject* object, 
    SVGPaintTargetType type, 
    bool isPaintingText) const
{
    m_ownerElement->buildGradient();

    RenderStyle* style = object->style();
    bool isFilled = 
        (type & ApplyToFillTargetType) && 
         style->svgStyle()->hasFill();
    bool isStroked = 
        (type & ApplyToStrokeTargetType) && 
         style->svgStyle()->hasStroke();

    if(!gradientStops().size())
        return false;

    if(gradientStops().size()==1) {
        context->setFillColor(gradientStops()[0].second);
        return true;
    }

    // Create a gradient builder helper to generate the data 
    // we'll need to provide Skia
    SkiaGradientBuilder builder(gradientStops(), 
        isFilled ? style->svgStyle()->fillOpacity() : 
                   style->svgStyle()->strokeOpacity());

    SkShader::TileMode tile_mode;

    // Convert SVG spread modes to Skia tile modes
    switch(spreadMethod())
    {
    default:
    case SPREADMETHOD_PAD:     
        tile_mode = SkShader::kClamp_TileMode; break;
    case SPREADMETHOD_REFLECT: 
        tile_mode = SkShader::kMirror_TileMode; break;
    case SPREADMETHOD_REPEAT:  
        tile_mode = SkShader::kRepeat_TileMode; break;
    }

    SkShader* shader = NULL;

    SkMatrix matrix;

    // Calculate a matrix to transform a gradient to fit the bounding box
    if (boundingBoxMode()) {
        matrix.reset();
        SkRect rc = context->getBoundingBoxForCurrentPath(true);

        matrix.preTranslate(rc.fLeft, rc.fTop);
        matrix.preScale(rc.width(), rc.height());
        matrix.preConcat(gradientTransform());
    } else
        matrix = gradientTransform();

    if (this->type() == LinearGradientPaintServer) {
        const SVGPaintServerLinearGradient* linear = 
            static_cast<const SVGPaintServerLinearGradient*>(this);

        SkPoint pts[2];

        pts[0].fX = linear->gradientStart().x();
        pts[0].fY = linear->gradientStart().y();
        pts[1].fX = linear->gradientEnd().x();
        pts[1].fY = linear->gradientEnd().y();

        shader = SkGradientShader::CreateLinear(pts, 
            builder.colors(), builder.pos(), builder.count(), tile_mode);
    } else if (this->type() == RadialGradientPaintServer) {
        const SVGPaintServerRadialGradient* radial = 
            static_cast<const SVGPaintServerRadialGradient*>(this);

        SkPoint center;
        SkScalar radius;

        center.fX = radial->gradientCenter().x();
        center.fY = radial->gradientCenter().y();
        radius = radial->gradientRadius();

        shader = SkGradientShader::CreateRadial(
            center, radius, builder.colors(), builder.pos(), 
            builder.count(), tile_mode);

    } else {
        return false;
    }

    if (isPaintingText) {
        if (isFilled) {
            context->setTextDrawingMode(cTextFill);
        }

        if (isStroked) {
            context->setTextDrawingMode(cTextStroke);
        }
    }

    if (isStroked) {
        applyStrokeStyleToContext(context, style, object);
    }

    if (shader) {
        shader->setLocalMatrix(matrix);
        context->platformContext()->setGradient(shader);

        return true;
    }

    return false;
}
コード例 #13
0
ファイル: RenderPath.cpp プロジェクト: 325116067/semc-qsd8x50
 void strokeStyle(GraphicsContext* gc)
 {
     applyStrokeStyleToContext(gc, m_style, m_object);
 }
コード例 #14
0
bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle* style, GraphicsContext*& context, unsigned short resourceMode)
{
    ASSERT(object);
    ASSERT(style);
    ASSERT(context);
    ASSERT(resourceMode != ApplyToDefaultMode);

    // Be sure to synchronize all SVG properties on the gradientElement _before_ processing any further.
    // Otherwhise the call to collectGradientAttributes() in createTileImage(), may cause the SVG DOM property
    // synchronization to kick in, which causes invalidateClients() to be called, which in turn deletes our
    // GradientData object! Leaving out the line below will cause svg/dynamic-updates/SVG*GradientElement-svgdom* to crash.
    SVGGradientElement* gradientElement = static_cast<SVGGradientElement*>(node());
    if (!gradientElement)
        return false;

    gradientElement->updateAnimatedSVGAttribute(anyQName());

    if (!m_gradient.contains(object))
        m_gradient.set(object, new GradientData);

    GradientData* gradientData = m_gradient.get(object);

    // Create gradient object
    if (!gradientData->gradient)
        buildGradient(gradientData, gradientElement);

    if (!gradientData->gradient)
        return false;

    // Draw gradient
    context->save();

    bool isPaintingText = resourceMode & ApplyToTextMode;
    if (isPaintingText) {
#if PLATFORM(CG)
        if (!createMaskAndSwapContextForTextGradient(context, m_savedContext, m_imageBuffer, object)) {
            context->restore();
            return false;
        }
#endif

        context->setTextDrawingMode(resourceMode & ApplyToFillMode ? cTextFill : cTextStroke);
    }

    AffineTransform transform;

    // CG platforms will handle the gradient space transform for text after applying the
    // resource, so don't apply it here. For non-CG platforms, we want the text bounding
    // box applied to the gradient space transform now, so the gradient shader can use it.
#if PLATFORM(CG)
    if (gradientData->boundingBoxMode && !isPaintingText) {
#else
    if (gradientData->boundingBoxMode) {
#endif
        FloatRect objectBoundingBox = object->objectBoundingBox();
        transform.translate(objectBoundingBox.x(), objectBoundingBox.y());
        transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
    }

    transform.multiply(gradientData->transform);
    gradientData->gradient->setGradientSpaceTransform(transform);

    const SVGRenderStyle* svgStyle = style->svgStyle();
    ASSERT(svgStyle);

    if (resourceMode & ApplyToFillMode) {
        context->setAlpha(svgStyle->fillOpacity());
        context->setFillGradient(gradientData->gradient);
        context->setFillRule(svgStyle->fillRule());
    } else if (resourceMode & ApplyToStrokeMode) {
        context->setAlpha(svgStyle->strokeOpacity());
        context->setStrokeGradient(gradientData->gradient);
        applyStrokeStyleToContext(context, style, object);
    }

    return true;
}

void RenderSVGResourceGradient::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode)
{
    ASSERT(context);
    ASSERT(resourceMode != ApplyToDefaultMode);

    if (resourceMode & ApplyToTextMode) {
#if PLATFORM(CG)
        // CG requires special handling for gradient on text
        if (m_savedContext && m_gradient.contains(object)) {
            GradientData* gradientData = m_gradient.get(object);

            // Restore on-screen drawing context
            context = m_savedContext;
            m_savedContext = 0;

            gradientData->gradient->setGradientSpaceTransform(clipToTextMask(context, m_imageBuffer, object, gradientData));
            context->setFillGradient(gradientData->gradient);

            const RenderObject* textRootBlock = findTextRootObject(object);
            context->fillRect(textRootBlock->repaintRectInLocalCoordinates());

            m_imageBuffer.clear();
        }
#else
        UNUSED_PARAM(object);
#endif
    } else {
        if (resourceMode & ApplyToFillMode)
            context->fillPath();
        else if (resourceMode & ApplyToStrokeMode)
            context->strokePath();
    }

    context->restore();
}
コード例 #15
0
bool SVGPaintServerPattern::setup(GraphicsContext*& context, const RenderObject* object, SVGPaintTargetType type, bool isPaintingText) const
{
    CGContextRef contextRef = context->platformContext();

    // Build pattern tile, passing destination object bounding box
    FloatRect targetRect;
    if (isPaintingText) {
        IntRect textBoundary = const_cast<RenderObject*>(object)->absoluteBoundingBoxRect();
        targetRect = object->absoluteTransform().inverse().mapRect(textBoundary);
    } else
        targetRect = CGContextGetPathBoundingBox(contextRef);

    m_ownerElement->buildPattern(targetRect);

    if (!tile())
        return false;

    CGSize cellSize = CGSize(tile()->size());
    CGFloat alpha = 1; // canvasStyle->opacity(); //which?

    context->save();

    // Repesct local pattern transformations
    CGContextConcatCTM(contextRef, patternTransform());

    // Pattern space seems to start in the lower-left, so we flip the Y here. 
    CGSize phase = CGSizeMake(patternBoundaries().x(), -patternBoundaries().y());
    CGContextSetPatternPhase(contextRef, phase);

    RenderStyle* style = object->style();
    CGContextSetAlpha(contextRef, style->opacity()); // or do I set the alpha above?

    ASSERT(!m_pattern);
    CGPatternCallbacks callbacks = {0, patternCallback, NULL};
    m_pattern = CGPatternCreate(tile(),
                                CGRectMake(0, 0, cellSize.width, cellSize.height),
                                CGContextGetCTM(contextRef),
                                patternBoundaries().width(),
                                patternBoundaries().height(),
                                kCGPatternTilingConstantSpacing, // FIXME: should ask CG guys.
                                true, // has color
                                &callbacks);

    if (!m_patternSpace)
        m_patternSpace = CGColorSpaceCreatePattern(0);

    if ((type & ApplyToFillTargetType) && style->svgStyle()->hasFill()) {
        CGContextSetFillColorSpace(contextRef, m_patternSpace);
        CGContextSetFillPattern(contextRef, m_pattern, &alpha);
 
        if (isPaintingText) 
            context->setTextDrawingMode(cTextFill);
    }

    if ((type & ApplyToStrokeTargetType) && style->svgStyle()->hasStroke()) {
        CGContextSetStrokeColorSpace(contextRef, m_patternSpace);
        CGContextSetStrokePattern(contextRef, m_pattern, &alpha);
        applyStrokeStyleToContext(contextRef, style, object);

        if (isPaintingText) 
            context->setTextDrawingMode(cTextStroke);
    }

    return true;
}