File: shaping_line_breaker.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 (177 lines) | stat: -rw-r--r-- 7,081 bytes parent folder | download | duplicates (5)
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
// 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_PLATFORM_FONTS_SHAPING_SHAPING_LINE_BREAKER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPING_LINE_BREAKER_H_

#include <optional>

#include "third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_options.h"
#include "third_party/blink/renderer/platform/fonts/shaping/text_spacing_trim.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/text/text_direction.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"

namespace blink {

class Font;
class ShapeResult;
class ShapeResultView;
class Hyphenation;
class LazyLineBreakIterator;

// Shapes a line of text by finding the ideal break position as indicated by the
// available space and the shape results for the entire paragraph. Once an ideal
// break position has been found the text is scanned backwards until a valid and
// and appropriate break opportunity is identified. Unless the break opportunity
// is at a safe-to-break boundary (as identified by HarfBuzz) the beginning and/
// or end of the line is reshaped to account for differences caused by breaking.
//
// This allows for significantly faster and more efficient line breaking by only
// reshaping when absolutely necessarily and by only evaluating likely candidate
// break opportunities instead of measuring and evaluating all possible options.
class PLATFORM_EXPORT ShapingLineBreaker {
  STACK_ALLOCATED();

 public:
  // Construct a ShapingLineBreaker.
  ShapingLineBreaker(const ShapeResult* result,
                     const LazyLineBreakIterator* break_iterator,
                     const Hyphenation* hyphenation,
                     const Font* font);

  // Represents details of the result of |ShapeLine()|.
  struct Result {
    STACK_ALLOCATED();

   public:
    // Indicates the resulting break offset.
    unsigned break_offset;

    // Indicates that the shape result contains trailing spaces
    bool has_trailing_spaces;

    // True if there were no break opportunities that can fit. When this is
    // false, the result width should be smaller than or equal to the available
    // space.
    bool is_overflow;

    // True if the break is hyphenated, either by automatic hyphenation or
    // soft-hyphen characters.
    // The hyphen glyph is not included in the |ShapeResult|, and that appending
    // a hyphen glyph may overflow the specified available space.
    bool is_hyphenated;
  };

  // Set the start of the current line.
  void SetLineStart(unsigned offset) { line_start_ = offset; }
  // Disable reshaping the end edge if it is at a breakable space, even if it
  // is not safe-to-break. Good for performance if accurate width is not
  // critical.
  void SetDontReshapeEndIfAtSpace() { dont_reshape_end_if_at_space_ = true; }
  // Returns nullptr if this line overflows. When the word is very long, such
  // as URL or data, creating ShapeResult is expensive. Set this option to
  // suppress if ShapeResult is not needed when this line overflows.
  bool NoResultIfOverflow() const { return no_result_if_overflow_; }
  void SetNoResultIfOverflow() { no_result_if_overflow_ = true; }
  void SetIsAfterForcedBreak(bool value) { is_after_forced_break_ = value; }
  void SetTextSpacingTrim(TextSpacingTrim value) { text_spacing_trim_ = value; }

  const ShapeResultView* ShapeLine(unsigned start_offset,
                                   LayoutUnit available_space,
                                   Result* result_out);

  const ShapeResultView* ShapeLineAt(unsigned start, unsigned end);

 protected:
  const ShapeResult& GetShapeResult() const { return *result_; }

  virtual const ShapeResult* Shape(unsigned start,
                                   unsigned end,
                                   ShapeOptions = ShapeOptions()) = 0;

 private:
  struct EdgeOffset {
    unsigned offset = 0;
    bool han_kerning = false;
  };

  const String& GetText() const;

  // True if the `offset` is start of a line, except the first line.
  bool IsStartOfWrappedLine(unsigned offset) const {
    return offset && offset == line_start_ && !is_after_forced_break_;
  }
  EdgeOffset FirstSafeOffset(unsigned start) const;

  // Represents a break opportunity offset and its properties.
  struct BreakOpportunity {
    STACK_ALLOCATED();

   public:
    BreakOpportunity() = default;
    BreakOpportunity(unsigned new_offset, bool hyphenated)
        : offset(new_offset),
          is_hyphenated(hyphenated) {}
    BreakOpportunity(unsigned new_offset, unsigned run_end, bool hyphenated)
        : offset(new_offset),
          non_hangable_run_end(run_end),
          is_hyphenated(hyphenated) {}

    unsigned offset = 0;
    std::optional<unsigned> non_hangable_run_end;
    bool is_hyphenated = false;
  };
  BreakOpportunity PreviousBreakOpportunity(unsigned offset,
                                            unsigned start) const;
  BreakOpportunity NextBreakOpportunity(unsigned offset,
                                        unsigned start,
                                        unsigned len) const;
  BreakOpportunity Hyphenate(unsigned offset,
                             unsigned start,
                             bool backwards) const;
  unsigned Hyphenate(unsigned offset,
                     unsigned word_start,
                     unsigned word_end,
                     bool backwards) const;

  const ShapeResultView* ShapeToEnd(unsigned start,
                                    const ShapeResult* line_start_result,
                                    unsigned first_safe,
                                    unsigned range_start,
                                    unsigned range_end);
  const ShapeResultView* ConcatShapeResults(
      unsigned start,
      unsigned end,
      unsigned first_safe,
      unsigned last_safe,
      const ShapeResult* line_start_result,
      const ShapeResult* line_end_result);

  void SetBreakOffset(unsigned break_offset, const String&, Result*);
  void SetBreakOffset(const BreakOpportunity&, const String&, Result*);

  template <TextDirection>
  const ShapeResultView* ShapeLine(unsigned start_offset,
                                   LayoutUnit available_space,
                                   Result* result_out);

  const ShapeResult* result_;
  const LazyLineBreakIterator* break_iterator_;
  const Hyphenation* hyphenation_;
  const Font* font_;
  unsigned line_start_ = 0;
  bool dont_reshape_end_if_at_space_ = false;
  bool no_result_if_overflow_ = false;
  bool is_after_forced_break_ = false;
  TextSpacingTrim text_spacing_trim_ = TextSpacingTrim::kInitial;

  friend class ShapingLineBreakerTest;
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPING_LINE_BREAKER_H_