Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1413)

Unified Diff: Source/core/paint/SVGShapePainter.cpp

Issue 1052873003: Explicitly use SkPaint(s) in SVGShapePainter (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Use GC::draw*; transfer->apply. Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/paint/SVGShapePainter.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/paint/SVGShapePainter.cpp
diff --git a/Source/core/paint/SVGShapePainter.cpp b/Source/core/paint/SVGShapePainter.cpp
index 6b59e3e52975893d6cadec115cf25806bcb25608..22b0e3aa083cf46cd58c977e666f694270b38968 100644
--- a/Source/core/paint/SVGShapePainter.cpp
+++ b/Source/core/paint/SVGShapePainter.cpp
@@ -20,6 +20,7 @@
#include "core/paint/SVGPaintContext.h"
#include "core/paint/TransformRecorder.h"
#include "platform/graphics/paint/DisplayItemListContextRecorder.h"
+#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPicture.h"
namespace blink {
@@ -34,14 +35,46 @@ static bool setupNonScalingStrokeContext(AffineTransform& strokeTransform, Graph
return true;
}
-static void useStrokeStyleToFill(GraphicsContext* context)
+static bool paintForLayoutObject(const PaintInfo& paintInfo, const ComputedStyle& style, LayoutObject& layoutObject, LayoutSVGResourceMode resourceMode, SkPaint& paint, const AffineTransform* additionalPaintServerTransform = nullptr)
{
- if (Gradient* gradient = context->strokeGradient())
- context->setFillGradient(gradient);
- else if (Pattern* pattern = context->strokePattern())
- context->setFillPattern(pattern);
- else
- context->setFillColor(context->strokeColor());
+ 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);
+
+ paint.setFilterQuality(WebCoreInterpolationQualityToSkFilterQuality(InterpolationDefault));
+
+ // 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(paintInfo.context->colorFilter());
+ return true;
+}
+
+static SkPath::FillType fillRuleFromStyle(const PaintInfo& paintInfo, const SVGComputedStyle& svgStyle)
+{
+ return WebCoreWindRuleToSkFillType(paintInfo.isRenderingClipPathAsMaskImage() ? svgStyle.clipRule() : svgStyle.fillRule());
}
void SVGShapePainter::paint(const PaintInfo& paintInfo)
@@ -64,21 +97,15 @@ void SVGShapePainter::paint(const PaintInfo& paintInfo)
const SVGComputedStyle& svgStyle = m_renderSVGShape.style()->svgStyle();
bool shouldAntiAlias = svgStyle.shapeRendering() != SR_CRISPEDGES;
- // We're munging GC paint attributes without saving first (and so does
- // updateGraphicsContext below). This is in line with making GC less stateful,
- // but we should keep an eye out for unintended side effects.
- //
- // FIXME: the mutation avoidance check should be in (all) the GC setters.
- if (shouldAntiAlias != paintContext.paintInfo().context->shouldAntialias())
- paintContext.paintInfo().context->setShouldAntialias(shouldAntiAlias);
for (int i = 0; i < 3; i++) {
switch (svgStyle.paintOrderType(i)) {
case PT_FILL: {
- GraphicsContextStateSaver stateSaver(*paintContext.paintInfo().context, false);
- if (!SVGLayoutSupport::updateGraphicsContext(paintContext.paintInfo(), stateSaver, m_renderSVGShape.styleRef(), m_renderSVGShape, ApplyToFillMode))
+ SkPaint fillPaint;
+ if (!paintForLayoutObject(paintContext.paintInfo(), m_renderSVGShape.styleRef(), m_renderSVGShape, ApplyToFillMode, fillPaint))
break;
- fillShape(paintContext.paintInfo().context);
+ fillPaint.setAntiAlias(shouldAntiAlias);
+ fillShape(paintContext.paintInfo().context, fillPaint, fillRuleFromStyle(paintContext.paintInfo(), svgStyle));
break;
}
case PT_STROKE:
@@ -96,9 +123,16 @@ void SVGShapePainter::paint(const PaintInfo& paintInfo)
additionalPaintServerTransform = &nonScalingTransform;
}
- if (!SVGLayoutSupport::updateGraphicsContext(paintContext.paintInfo(), stateSaver, m_renderSVGShape.styleRef(), m_renderSVGShape, ApplyToStrokeMode, additionalPaintServerTransform))
+ SkPaint strokePaint;
+ if (!paintForLayoutObject(paintContext.paintInfo(), m_renderSVGShape.styleRef(), m_renderSVGShape, ApplyToStrokeMode, strokePaint, additionalPaintServerTransform))
break;
- strokeShape(paintContext.paintInfo().context);
+ strokePaint.setAntiAlias(shouldAntiAlias);
+
+ StrokeData strokeData;
+ SVGLayoutSupport::applyStrokeStyleToStrokeData(strokeData, m_renderSVGShape.styleRef(), m_renderSVGShape);
+ strokeData.setupPaint(&strokePaint);
+
+ strokeShape(paintContext.paintInfo().context, strokePaint);
}
break;
case PT_MARKERS:
@@ -121,39 +155,61 @@ void SVGShapePainter::paint(const PaintInfo& paintInfo)
}
}
-void SVGShapePainter::fillShape(GraphicsContext* context)
+class PathWithTemporaryWindingRule {
+public:
+ PathWithTemporaryWindingRule(Path& path, SkPath::FillType fillType)
+ : m_path(const_cast<SkPath&>(path.skPath()))
+ {
+ m_savedFillType = m_path.getFillType();
+ m_path.setFillType(fillType);
+ }
+ ~PathWithTemporaryWindingRule()
+ {
+ m_path.setFillType(m_savedFillType);
+ }
+
+ const SkPath& skPath() const { return m_path; }
+
+private:
+ SkPath& m_path;
+ SkPath::FillType m_savedFillType;
+};
+
+void SVGShapePainter::fillShape(GraphicsContext* context, const SkPaint& paint, SkPath::FillType fillType)
{
switch (m_renderSVGShape.geometryCodePath()) {
case RectGeometryFastPath:
- context->fillRect(m_renderSVGShape.objectBoundingBox());
+ context->drawRect(m_renderSVGShape.objectBoundingBox(), paint);
break;
case EllipseGeometryFastPath:
- context->fillEllipse(m_renderSVGShape.objectBoundingBox());
+ context->drawOval(m_renderSVGShape.objectBoundingBox(), paint);
break;
- default:
- context->fillPath(m_renderSVGShape.path());
+ default: {
+ PathWithTemporaryWindingRule pathWithWinding(m_renderSVGShape.path(), fillType);
+ context->drawPath(pathWithWinding.skPath(), paint);
+ }
}
}
-void SVGShapePainter::strokeShape(GraphicsContext* context)
+void SVGShapePainter::strokeShape(GraphicsContext* context, const SkPaint& paint)
{
if (!m_renderSVGShape.style()->svgStyle().hasVisibleStroke())
return;
switch (m_renderSVGShape.geometryCodePath()) {
case RectGeometryFastPath:
- context->strokeRect(m_renderSVGShape.objectBoundingBox(), m_renderSVGShape.strokeWidth());
+ context->drawRect(m_renderSVGShape.objectBoundingBox(), paint);
break;
case EllipseGeometryFastPath:
- context->strokeEllipse(m_renderSVGShape.objectBoundingBox());
+ context->drawOval(m_renderSVGShape.objectBoundingBox(), paint);
break;
default:
ASSERT(m_renderSVGShape.hasPath());
Path* usePath = &m_renderSVGShape.path();
if (m_renderSVGShape.hasNonScalingStroke())
usePath = m_renderSVGShape.nonScalingStrokePath(usePath, m_renderSVGShape.nonScalingStrokeTransform());
- context->strokePath(*usePath);
- strokeZeroLengthLineCaps(context);
+ context->drawPath(usePath->skPath(), paint);
+ strokeZeroLengthLineCaps(context, paint);
}
}
@@ -203,39 +259,35 @@ void SVGShapePainter::paintMarker(const PaintInfo& paintInfo, LayoutSVGResourceM
}
}
-void SVGShapePainter::strokeZeroLengthLineCaps(GraphicsContext* context)
+void SVGShapePainter::strokeZeroLengthLineCaps(GraphicsContext* context, const SkPaint& strokePaint)
{
const Vector<FloatPoint>* zeroLengthLineCaps = m_renderSVGShape.zeroLengthLineCaps();
if (!zeroLengthLineCaps || zeroLengthLineCaps->isEmpty())
return;
- Path* usePath;
- AffineTransform nonScalingTransform;
+ // We need a paint for filling.
+ SkPaint fillPaint = strokePaint;
+ fillPaint.setStyle(SkPaint::kFill_Style);
+ AffineTransform nonScalingTransform;
if (m_renderSVGShape.hasNonScalingStroke())
nonScalingTransform = m_renderSVGShape.nonScalingStrokeTransform();
- GraphicsContextStateSaver stateSaver(*context, true);
- useStrokeStyleToFill(context);
+ Path tempPath;
for (size_t i = 0; i < zeroLengthLineCaps->size(); ++i) {
- usePath = zeroLengthLinecapPath((*zeroLengthLineCaps)[i]);
+ FloatRect subpathRect = LayoutSVGPath::zeroLengthSubpathRect((*zeroLengthLineCaps)[i], m_renderSVGShape.strokeWidth());
+ tempPath.clear();
+ if (m_renderSVGShape.style()->svgStyle().capStyle() == SquareCap)
+ tempPath.addRect(subpathRect);
+ else
+ tempPath.addEllipse(subpathRect);
+ // This open-codes LayoutSVGShape::nonScalingStrokePath, because the
+ // requirements here differ (we have a temporary path that we can
+ // mutate.)
if (m_renderSVGShape.hasNonScalingStroke())
- usePath = m_renderSVGShape.nonScalingStrokePath(usePath, nonScalingTransform);
- context->fillPath(*usePath);
+ tempPath.transform(nonScalingTransform);
+ context->drawPath(tempPath.skPath(), fillPaint);
}
}
-Path* SVGShapePainter::zeroLengthLinecapPath(const FloatPoint& linecapPosition) const
-{
- DEFINE_STATIC_LOCAL(Path, tempPath, ());
-
- tempPath.clear();
- if (m_renderSVGShape.style()->svgStyle().capStyle() == SquareCap)
- tempPath.addRect(LayoutSVGPath::zeroLengthSubpathRect(linecapPosition, m_renderSVGShape.strokeWidth()));
- else
- tempPath.addEllipse(LayoutSVGPath::zeroLengthSubpathRect(linecapPosition, m_renderSVGShape.strokeWidth()));
-
- return &tempPath;
-}
-
} // namespace blink
« no previous file with comments | « Source/core/paint/SVGShapePainter.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698