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; }
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; }
bool SVGPaintContext::paintForLayoutObject( const PaintInfo& paintInfo, const ComputedStyle& style, const LayoutObject& layoutObject, LayoutSVGResourceMode resourceMode, SkPaint& paint, const AffineTransform* additionalPaintServerTransform) { if (paintInfo.isRenderingClipPathAsMaskImage()) { if (resourceMode == ApplyToStrokeMode) return false; paint.setColor(SVGComputedStyle::initialFillPaintColor().rgb()); paint.setShader(nullptr); 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.applyToSkPaint(paint, paintAlpha); // We always set filter quality to 'low' here. This value will only have an // effect for patterns, which are SkPictures, so using high-order filter // should have little effect on the overall quality. paint.setFilterQuality(kLow_SkFilterQuality); // TODO(fs): The color filter can set when generating a picture for a mask - // due to color-interpolation. We could also just apply the // color-interpolation property from the the shape itself (which could mean // the paintserver if it has it specified), since that would be more in line // with the spec for color-interpolation. For now, just steal it from the GC // though. // Additionally, it's not really safe/guaranteed to be correct, as // something down the paint pipe may want to farther tweak the color // filter, which could yield incorrect results. (Consider just using // saveLayer() w/ this color filter explicitly instead.) paint.setColorFilter(sk_ref_sp(paintInfo.context.getColorFilter())); return true; }
static SkPath::FillType fillRuleFromStyle(const PaintInfo& paintInfo, const SVGComputedStyle& svgStyle) { return WebCoreWindRuleToSkFillType(paintInfo.isRenderingClipPathAsMaskImage() ? svgStyle.clipRule() : svgStyle.fillRule()); }
void SVGInlineTextBoxPainter::paintTextFragments(const PaintInfo& paintInfo, LayoutObject& parentLayoutObject) { const ComputedStyle& style = parentLayoutObject.styleRef(); const SVGComputedStyle& svgStyle = style.svgStyle(); bool hasFill = svgStyle.hasFill(); bool hasVisibleStroke = svgStyle.hasVisibleStroke(); const ComputedStyle* selectionStyle = &style; bool shouldPaintSelection = this->shouldPaintSelection(); if (shouldPaintSelection) { selectionStyle = parentLayoutObject.getCachedPseudoStyle(SELECTION); if (selectionStyle) { const SVGComputedStyle& svgSelectionStyle = selectionStyle->svgStyle(); if (!hasFill) hasFill = svgSelectionStyle.hasFill(); if (!hasVisibleStroke) hasVisibleStroke = svgSelectionStyle.hasVisibleStroke(); } else { selectionStyle = &style; } } if (paintInfo.isRenderingClipPathAsMaskImage()) { hasFill = true; hasVisibleStroke = false; } AffineTransform fragmentTransform; unsigned textFragmentsSize = m_svgInlineTextBox.textFragments().size(); for (unsigned i = 0; i < textFragmentsSize; ++i) { SVGTextFragment& fragment = m_svgInlineTextBox.textFragments().at(i); GraphicsContextStateSaver stateSaver(*paintInfo.context, false); fragment.buildFragmentTransform(fragmentTransform); if (!fragmentTransform.isIdentity()) { stateSaver.save(); paintInfo.context->concatCTM(fragmentTransform); } // Spec: All text decorations except line-through should be drawn before the text is filled and stroked; thus, the text is rendered on top of these decorations. unsigned decorations = style.textDecorationsInEffect(); if (decorations & TextDecorationUnderline) paintDecoration(paintInfo, TextDecorationUnderline, fragment); if (decorations & TextDecorationOverline) paintDecoration(paintInfo, TextDecorationOverline, fragment); for (int i = 0; i < 3; i++) { switch (svgStyle.paintOrderType(i)) { case PT_FILL: if (hasFill) paintText(paintInfo, style, *selectionStyle, fragment, ApplyToFillMode, shouldPaintSelection); break; case PT_STROKE: if (hasVisibleStroke) paintText(paintInfo, style, *selectionStyle, fragment, ApplyToStrokeMode, shouldPaintSelection); break; case PT_MARKERS: // Markers don't apply to text break; default: ASSERT_NOT_REACHED(); break; } } // Spec: Line-through should be drawn after the text is filled and stroked; thus, the line-through is rendered on top of the text. if (decorations & TextDecorationLineThrough) paintDecoration(paintInfo, TextDecorationLineThrough, fragment); } }