summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/paint/object_painter.cc
blob: 112deedc4ef0ec35a40ee611e0e5aadb8aa260c0 (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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Copyright 2014 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/object_painter.h"

#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/style/border_edge.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/geometry/layout_point.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"

namespace blink {

void ObjectPainter::PaintOutline(const PaintInfo& paint_info,
                                 const LayoutPoint& paint_offset) {
  DCHECK(ShouldPaintSelfOutline(paint_info.phase));

  const ComputedStyle& style_to_use = layout_object_.StyleRef();
  if (!style_to_use.HasOutline() ||
      style_to_use.Visibility() != EVisibility::kVisible)
    return;

  // Only paint the focus ring by hand if the theme isn't able to draw the focus
  // ring.
  if (style_to_use.OutlineStyleIsAuto() &&
      !LayoutTheme::GetTheme().ShouldDrawDefaultFocusRing(
          layout_object_.GetNode(), style_to_use)) {
    return;
  }

  auto outline_rects = layout_object_.PhysicalOutlineRects(
      paint_offset,
      layout_object_.OutlineRectsShouldIncludeBlockVisualOverflow());
  if (outline_rects.IsEmpty())
    return;

  if (DrawingRecorder::UseCachedDrawingIfPossible(
          paint_info.context, layout_object_, paint_info.phase))
    return;

  DrawingRecorder recorder(paint_info.context, layout_object_,
                           paint_info.phase);
  PaintOutlineRects(paint_info, outline_rects, style_to_use);
}

void ObjectPainter::PaintInlineChildrenOutlines(const PaintInfo& paint_info) {
  DCHECK(ShouldPaintDescendantOutlines(paint_info.phase));

  PaintInfo paint_info_for_descendants = paint_info.ForDescendants();
  for (LayoutObject* child = layout_object_.SlowFirstChild(); child;
       child = child->NextSibling()) {
    if (child->IsLayoutInline() &&
        !ToLayoutInline(child)->HasSelfPaintingLayer())
      child->Paint(paint_info_for_descendants);
  }
}

void ObjectPainter::AddPDFURLRectIfNeeded(const PaintInfo& paint_info,
                                          const LayoutPoint& paint_offset) {
  DCHECK(paint_info.IsPrinting());
  if (layout_object_.IsElementContinuation() || !layout_object_.GetNode() ||
      !layout_object_.GetNode()->IsLink() ||
      layout_object_.StyleRef().Visibility() != EVisibility::kVisible)
    return;

  KURL url = ToElement(layout_object_.GetNode())->HrefURL();
  if (!url.IsValid())
    return;

  auto outline_rects = layout_object_.PhysicalOutlineRects(
      paint_offset, NGOutlineType::kIncludeBlockVisualOverflow);
  IntRect rect = PixelSnappedIntRect(UnionRect(outline_rects));
  if (rect.IsEmpty())
    return;

  if (DrawingRecorder::UseCachedDrawingIfPossible(
          paint_info.context, layout_object_,
          DisplayItem::kPrintedContentPDFURLRect))
    return;

  DrawingRecorder recorder(paint_info.context, layout_object_,
                           DisplayItem::kPrintedContentPDFURLRect);
  if (url.HasFragmentIdentifier() &&
      EqualIgnoringFragmentIdentifier(url,
                                      layout_object_.GetDocument().BaseURL())) {
    String fragment_name = url.FragmentIdentifier();
    if (layout_object_.GetDocument().FindAnchor(fragment_name))
      paint_info.context.SetURLFragmentForRect(fragment_name, rect);
    return;
  }
  paint_info.context.SetURLForRect(url, rect);
}

void ObjectPainter::PaintAllPhasesAtomically(const PaintInfo& paint_info) {
  // Pass kSelection and kTextClip to the descendants so that
  // they will paint for selection and text clip respectively. We don't need
  // complete painting for these phases.
  if (paint_info.phase == PaintPhase::kSelection ||
      paint_info.phase == PaintPhase::kTextClip) {
    layout_object_.Paint(paint_info);
    return;
  }

  if (paint_info.phase != PaintPhase::kForeground)
    return;

  PaintInfo info(paint_info);
  info.phase = PaintPhase::kBlockBackground;
  layout_object_.Paint(info);
  info.phase = PaintPhase::kFloat;
  layout_object_.Paint(info);
  info.phase = PaintPhase::kForeground;
  layout_object_.Paint(info);
  info.phase = PaintPhase::kOutline;
  layout_object_.Paint(info);
}

}  // namespace blink