File: highlight_painter.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (301 lines) | stat: -rw-r--r-- 13,005 bytes parent folder | download | duplicates (3)
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_HIGHLIGHT_PAINTER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_HIGHLIGHT_PAINTER_H_

#include <optional>

#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker.h"
#include "third_party/blink/renderer/core/editing/markers/highlight_pseudo_marker.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
#include "third_party/blink/renderer/core/layout/inline/inline_cursor.h"
#include "third_party/blink/renderer/core/layout/inline/text_offset_range.h"
#include "third_party/blink/renderer/core/layout/selection_state.h"
#include "third_party/blink/renderer/core/paint/highlight_overlay.h"
#include "third_party/blink/renderer/core/paint/line_relative_rect.h"
#include "third_party/blink/renderer/core/paint/text_decoration_info.h"
#include "third_party/blink/renderer/core/paint/text_paint_style.h"
#include "third_party/blink/renderer/platform/geometry/physical_offset.h"
#include "third_party/blink/renderer/platform/graphics/dom_node_id.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/gc_plugin.h"

namespace blink {

class ComputedStyle;
class FragmentItem;
class FrameSelection;
class LayoutObject;
class Node;
class TextDecorationPainter;
class TextPainter;
struct LayoutSelectionStatus;
struct PaintInfo;
struct TextFragmentPaintInfo;

using HighlightLayer = HighlightOverlay::HighlightLayer;
using HighlightPart = HighlightOverlay::HighlightPart;

// Highlight overlay painter for LayoutNG. Operates on a FragmentItem that
// IsText(). Delegates to TextPainter to paint the text itself.
class CORE_EXPORT HighlightPainter {
  STACK_ALLOCATED();

 public:
  class CORE_EXPORT SelectionPaintState {
    STACK_ALLOCATED();

   public:
    // ComputeSelectionStyle must be called to finish initializing. Until then,
    // only Status() may be called.
    explicit SelectionPaintState(
        const InlineCursor& containing_block,
        const PhysicalOffset& box_offset,
        const std::optional<AffineTransform> writing_mode_rotation = {});
    explicit SelectionPaintState(
        const InlineCursor& containing_block,
        const PhysicalOffset& box_offset,
        const std::optional<AffineTransform> writing_mode_rotation,
        const FrameSelection&);

    const LayoutSelectionStatus& Status() const { return selection_status_; }

    const TextPaintStyle& GetSelectionStyle() const { return selection_style_.style; }

    SelectionState State() const { return state_; }

    bool ShouldPaintSelectedTextOnly() const {
      return paint_selected_text_only_;
    }

    void ComputeSelectionStyle(const Document& document,
                               const ComputedStyle& style,
                               Node* node,
                               const PaintInfo& paint_info,
                               const TextPaintStyle& text_style);

    // When painting text fragments in a vertical writing-mode, we sometimes
    // need to rotate the canvas into a line-relative coordinate space. Paint
    // ops done while rotated need coordinates in this rotated space, but ops
    // done outside of these rotations need the original physical rect.
    const PhysicalRect& PhysicalSelectionRect();
    const LineRelativeRect& LineRelativeSelectionRect();

    void PaintSelectionBackground(
        GraphicsContext& context,
        Node* node,
        const Document& document,
        const ComputedStyle& style,
        const std::optional<AffineTransform>& rotation);

    void PaintSelectedText(TextPainter& text_painter,
                           const TextFragmentPaintInfo&,
                           const TextPaintStyle& text_style,
                           DOMNodeId node_id,
                           const AutoDarkMode& auto_dark_mode);

    void PaintSuppressingTextProperWhereSelected(
        TextPainter& text_painter,
        const TextFragmentPaintInfo&,
        const TextPaintStyle& text_style,
        DOMNodeId node_id,
        const AutoDarkMode& auto_dark_mode);

   private:
    struct SelectionRect {
      PhysicalRect physical;
      LineRelativeRect rotated;
      STACK_ALLOCATED();
    };

    // Lazy init |selection_rect_| only when needed, such as when we need to
    // record selection bounds or actually paint the selection. There are many
    // subtle conditions where we won’t ever need this field.
    void ComputeSelectionRectIfNeeded();

    const LayoutSelectionStatus selection_status_;
    const SelectionState state_;
    const InlineCursor& containing_block_;
    const PhysicalOffset& box_offset_;
    const std::optional<AffineTransform> writing_mode_rotation_;
    std::optional<SelectionRect> selection_rect_;
    HighlightStyleUtils::HighlightTextPaintStyle selection_style_;
    bool paint_selected_text_only_;
  };

  HighlightPainter(const TextFragmentPaintInfo& fragment_paint_info,
                   TextPainter& text_painter,
                   TextDecorationPainter& decoration_painter,
                   const PaintInfo& paint_info,
                   const InlineCursor& cursor,
                   const FragmentItem& fragment_item,
                   const PhysicalOffset& box_origin,
                   const ComputedStyle& style,
                   const TextPaintStyle& text_style,
                   SelectionPaintState*);

  enum Phase { kBackground, kForeground };

  // Paints backgrounds or foregrounds for markers that are not exposed as CSS
  // highlight pseudos. Note that when text is painted here, that text will be
  // painted two or more times, which will create antialiasing errors.
  void PaintNonCssMarkers(Phase phase);

  // Indicates the way this painter should be used by the caller, aside from
  // the Paint method, which should always be used.
  //
  // The full overlay painting algorithm (kOverlay) is not needed when there
  // are no highlights that change the text color, add backgrounds, or add
  // decorations that are required to paint under decorations from earlier
  // layers (e.g. ::target-text underline with originating overline).
  enum Case {
    // Caller should not use this painter. This happens if nothing is
    // highlighted.
    kNoHighlights,
    // Caller should use PaintOriginatingText and PaintHighlightOverlays.
    // This happens if there are highlights that may involve the text
    // fragment, except in some situations with only spelling/grammar
    // (kFastSpellingGrammar) or selection (kFastSelection).
    kOverlay,
    // Caller should use PaintSelectedText only.
    // This happens if ShouldPaintSelectedTextOnly is true, such as when
    // painting the ::selection drag image.
    kSelectionOnly,
    // Caller should use PaintSuppressingTextProperWhereSelected,
    // PaintSelectionBackground, and PaintSelectedText.
    // This happens if the only highlight that may involve the text fragment
    // is a selection, and neither the selection nor the originating content
    // has any decorations.
    kFastSelection,
    // Caller should use FastPaintSpellingGrammarDecorations.
    // This happens if the only highlights that may involve the text fragment
    // are spelling and/or grammar errors, they are completely unstyled (since
    // the default style only adds a spelling or grammar decoration), and the
    // originating content has no decorations.
    kFastSpellingGrammar
  };
  Case PaintCase() const;

  static TextOffsetRange GetFragmentDOMOffsets(const Text& text,
                                               unsigned from,
                                               unsigned to);

  // PaintCase() == kFastSpellingGrammar only
  void FastPaintSpellingGrammarDecorations();

  void PaintOriginatingShadow(const TextPaintStyle&, DOMNodeId);
  void PaintHighlightOverlays(const TextPaintStyle&,
                              DOMNodeId,
                              bool paint_marker_backgrounds,
                              std::optional<AffineTransform> rotation);

  static void PaintHighlightBackground(
      GraphicsContext& context,
      const ComputedStyle& style,
      Color color,
      const PhysicalRect& rect,
      const std::optional<AffineTransform>& rotation);

  // Query various style pieces for the given marker type
  static PseudoId PseudoFor(DocumentMarker::MarkerType type);
  static TextDecorationLine LineFor(DocumentMarker::MarkerType type);
  static Color ColorFor(DocumentMarker::MarkerType type);

  SelectionPaintState* Selection() { return selection_; }

 private:
  struct HighlightEdgeInfo {
    unsigned offset;
    float x;
  };

  Case ComputePaintCase() const;

  const PhysicalRect ComputeBackgroundRect(StringView text,
                                           unsigned start_offset,
                                           unsigned end_offset);
  const PhysicalRect ComputeBackgroundRectForSelection(unsigned start_offset,
                                                       unsigned end_offset);
  void FastPaintSpellingGrammarDecorations(const Text& text_node,
                                           const StringView& text,
                                           const DocumentMarkerVector& markers);
  void PaintOneSpellingGrammarDecoration(DocumentMarker::MarkerType,
                                         const StringView& text,
                                         unsigned paint_start_offset,
                                         unsigned paint_end_offset);
  void PaintOneSpellingGrammarDecoration(
      DocumentMarker::MarkerType,
      const StringView& text,
      unsigned paint_start_offset,
      unsigned paint_end_offset,
      const ComputedStyle& style,
      const TextPaintStyle& text_style,
      const AppliedTextDecoration* decoration_override);
  LineRelativeRect LineRelativeWorldRect(
      const HighlightOverlay::HighlightRange&);
  LineRelativeRect LocalRectInWritingModeSpace(unsigned from,
                                               unsigned to) const;
  void ClipToPartRect(const LineRelativeRect& part_rect);
  void PaintDecorationsExceptLineThrough(const HighlightOverlay::HighlightPart&,
                                         const LineRelativeRect&);
  void PaintDecorationsExceptLineThrough(const HighlightOverlay::HighlightPart&,
                                         const LineRelativeRect&,
                                         TextDecorationLine lines_to_paint);
  void PaintDecorationsOnlyLineThrough(const HighlightOverlay::HighlightPart&,
                                       const LineRelativeRect&);

  // Paints originating text and decorations (again) with the given color.
  // Used for composition markers only.
  void PaintTextForCompositionMarker(const StringView& text,
                                     const Color& text_color,
                                     unsigned paint_start_offset,
                                     unsigned paint_end_offset);

  void PaintBackgroundForGlicMarker(const DocumentMarker* marker,
                                    const StringView& text,
                                    unsigned paint_start_offset,
                                    unsigned paint_end_offset);

  const TextFragmentPaintInfo& fragment_paint_info_;

  // Offsets of the fragment in DOM space, or nullopt if |node_| is not Text or
  // the fragment is generated text (or there are no markers). Used to reject
  // markers outside the target range in dom space, without converting the
  // marker's offsets to the fragment space.
  std::optional<TextOffsetRange> fragment_dom_offsets_{};

  TextPainter& text_painter_;
  TextDecorationPainter& decoration_painter_;
  const PaintInfo& paint_info_;
  const InlineCursor& cursor_;
  InlineCursor root_inline_cursor_;
  const FragmentItem& fragment_item_;
  const PhysicalOffset& box_origin_;
  const ComputedStyle& originating_style_;
  const TextPaintStyle& originating_text_style_;
  SelectionPaintState* selection_;
  const LayoutObject* layout_object_;
  Node* node_;
  const AutoDarkMode foreground_auto_dark_mode_;
  const AutoDarkMode background_auto_dark_mode_;
  DocumentMarkerVector markers_;
  DocumentMarkerVector search_;
  DocumentMarkerVector target_;
  DocumentMarkerVector spelling_;
  DocumentMarkerVector grammar_;
  DocumentMarkerVector custom_;
  HeapVector<HighlightLayer> layers_;
  HeapVector<HighlightPart> parts_;
  Vector<HighlightEdgeInfo> edges_info_;
  Case paint_case_;
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_HIGHLIGHT_PAINTER_H_