summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/paint/svg_object_painter.cc
blob: f675b25f63dea8710443d3d81fcea9178c1a3bd4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// 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(const 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_.SelfNeedsLayout());

  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 GraphicsContext& context,
    bool is_rendering_clip_path_as_mask_image,
    const ComputedStyle& style,
    LayoutSVGResourceMode resource_mode,
    PaintFlags& flags,
    const AffineTransform* additional_paint_server_transform) {
  if (is_rendering_clip_path_as_mask_image) {
    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(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(context, flags);
    return true;
  }
  return false;
}

}  // namespace blink