| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "third_party/blink/renderer/core/paint/svg_object_painter.h" |
| |
| #include "third_party/blink/renderer/core/layout/layout_object.h" |
| #include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_paint_server.h" |
| #include "third_party/blink/renderer/core/layout/svg/svg_resources.h" |
| #include "third_party/blink/renderer/core/paint/paint_info.h" |
| #include "third_party/blink/renderer/core/paint/paint_layer.h" |
| |
| namespace blink { |
| |
| namespace { |
| |
| void CopyStateFromGraphicsContext(GraphicsContext& context, PaintFlags& flags) { |
| // TODO(fs): The color filter can be 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 flags pipe may want to farther tweak the color filter, which could |
| // yield incorrect results. (Consider just using saveLayer() w/ this color |
| // filter explicitly instead.) |
| flags.setColorFilter(sk_ref_sp(context.GetColorFilter())); |
| } |
| |
| } // namespace |
| |
| void SVGObjectPainter::PaintResourceSubtree(GraphicsContext& context) { |
| DCHECK(!layout_object_.NeedsLayout()); |
| |
| PaintInfo info(context, CullRect::Infinite(), PaintPhase::kForeground, |
| kGlobalPaintNormalPhase | kGlobalPaintFlattenCompositingLayers, |
| kPaintLayerPaintingRenderingResourceSubtree, |
| &layout_object_.PaintingLayer()->GetLayoutObject()); |
| layout_object_.Paint(info); |
| } |
| |
| bool SVGObjectPainter::ApplyPaintResource( |
| const SVGPaint& paint, |
| const AffineTransform* additional_paint_server_transform, |
| PaintFlags& flags) { |
| SVGElementResourceClient* client = SVGResources::GetClient(layout_object_); |
| auto* uri_resource = GetSVGResourceAsType<LayoutSVGResourcePaintServer>( |
| *client, paint.Resource()); |
| if (!uri_resource) |
| return false; |
| if (!uri_resource->ApplyShader( |
| *client, SVGResources::ReferenceBoxForEffects(layout_object_), |
| additional_paint_server_transform, flags)) |
| return false; |
| return true; |
| } |
| |
| bool SVGObjectPainter::PreparePaint( |
| const PaintInfo& paint_info, |
| const ComputedStyle& style, |
| LayoutSVGResourceMode resource_mode, |
| PaintFlags& flags, |
| const AffineTransform* additional_paint_server_transform) { |
| if (paint_info.IsRenderingClipPathAsMaskImage()) { |
| if (resource_mode == kApplyToStrokeMode) |
| return false; |
| flags.setColor(SK_ColorBLACK); |
| flags.setShader(nullptr); |
| return true; |
| } |
| |
| const bool apply_to_fill = resource_mode == kApplyToFillMode; |
| const SVGPaint& paint = |
| apply_to_fill ? style.FillPaint() : style.StrokePaint(); |
| const float alpha = |
| apply_to_fill ? style.FillOpacity() : style.StrokeOpacity(); |
| if (paint.HasUrl()) { |
| if (ApplyPaintResource(paint, additional_paint_server_transform, flags)) { |
| flags.setColor(ScaleAlpha(SK_ColorBLACK, alpha)); |
| CopyStateFromGraphicsContext(paint_info.context, flags); |
| return true; |
| } |
| } |
| if (paint.HasColor()) { |
| const CSSProperty& property = |
| apply_to_fill ? GetCSSPropertyFill() : GetCSSPropertyStroke(); |
| const Color color = style.VisitedDependentColor(property); |
| flags.setColor(ScaleAlpha(color.Rgb(), alpha)); |
| flags.setShader(nullptr); |
| CopyStateFromGraphicsContext(paint_info.context, flags); |
| return true; |
| } |
| return false; |
| } |
| |
| } // namespace blink |