Flutter Engine
paragraph.h
Go to the documentation of this file.
1 
2 /*
3  * Copyright 2017 Google Inc.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #ifndef LIB_TXT_SRC_PARAGRAPH_H_
19 #define LIB_TXT_SRC_PARAGRAPH_H_
20 
21 #include "line_metrics.h"
22 #include "paragraph_style.h"
23 
24 class SkCanvas;
25 
26 namespace txt {
27 
28 // Interface for text layout engines. The original implementation was based on
29 // the Minikin text layout library used by Android. Another implementation is
30 // available based on Skia's SkShaper/SkParagraph text layout module.
31 class Paragraph {
32  public:
34 
35  // Options for various types of bounding boxes provided by
36  // GetRectsForRange(...).
37  enum class RectHeightStyle {
38  // Provide tight bounding boxes that fit heights per run.
39  kTight,
40 
41  // The height of the boxes will be the maximum height of all runs in the
42  // line. All rects in the same line will be the same height.
43  kMax,
44 
45  // Extends the top and/or bottom edge of the bounds to fully cover any line
46  // spacing. The top edge of each line should be the same as the bottom edge
47  // of the line above. There should be no gaps in vertical coverage given any
48  // ParagraphStyle line_height.
49  //
50  // The top and bottom of each rect will cover half of the
51  // space above and half of the space below the line.
53  // The line spacing will be added to the top of the rect.
55  // The line spacing will be added to the bottom of the rect.
57 
58  // Calculate boxes based on the strut's metrics.
59  kStrut
60  };
61 
62  enum class RectWidthStyle {
63  // Provide tight bounding boxes that fit widths to the runs of each line
64  // independently.
65  kTight,
66 
67  // Extends the width of the last rect of each line to match the position of
68  // the widest rect over all the lines.
69  kMax
70  };
71 
73  const size_t position;
75 
76  PositionWithAffinity(size_t p, Affinity a) : position(p), affinity(a) {}
77  };
78 
79  struct TextBox {
80  SkRect rect;
82 
83  TextBox(SkRect r, TextDirection d) : rect(r), direction(d) {}
84  };
85 
86  template <typename T>
87  struct Range {
88  Range() : start(), end() {}
89  Range(T s, T e) : start(s), end(e) {}
90 
91  T start, end;
92 
93  bool operator==(const Range<T>& other) const {
94  return start == other.start && end == other.end;
95  }
96 
97  T width() const { return end - start; }
98 
99  void Shift(T delta) {
100  start += delta;
101  end += delta;
102  }
103  };
104 
105  virtual ~Paragraph() = default;
106 
107  // Returns the width provided in the Layout() method. This is the maximum
108  // width any line in the laid out paragraph can occupy. We expect that
109  // GetMaxWidth() >= GetLayoutWidth().
110  virtual double GetMaxWidth() = 0;
111 
112  // Returns the height of the laid out paragraph. NOTE this is not a tight
113  // bounding height of the glyphs, as some glyphs do not reach as low as they
114  // can.
115  virtual double GetHeight() = 0;
116 
117  // Returns the width of the longest line as found in Layout(), which is
118  // defined as the horizontal distance from the left edge of the leftmost glyph
119  // to the right edge of the rightmost glyph. We expect that
120  // GetLongestLine() <= GetMaxWidth().
121  virtual double GetLongestLine() = 0;
122 
123  // Returns the actual max width of the longest line after Layout().
124  virtual double GetMinIntrinsicWidth() = 0;
125 
126  // Returns the total width covered by the paragraph without linebreaking.
127  virtual double GetMaxIntrinsicWidth() = 0;
128 
129  // Distance from top of paragraph to the Alphabetic baseline of the first
130  // line. Used for alphabetic fonts (A-Z, a-z, greek, etc.)
131  virtual double GetAlphabeticBaseline() = 0;
132 
133  // Distance from top of paragraph to the Ideographic baseline of the first
134  // line. Used for ideographic fonts (Chinese, Japanese, Korean, etc.)
135  virtual double GetIdeographicBaseline() = 0;
136 
137  // Checks if the layout extends past the maximum lines and had to be
138  // truncated.
139  virtual bool DidExceedMaxLines() = 0;
140 
141  // Layout calculates the positioning of all the glyphs. Must call this method
142  // before Painting and getting any statistics from this class.
143  virtual void Layout(double width) = 0;
144 
145  // Paints the laid out text onto the supplied SkCanvas at (x, y) offset from
146  // the origin. Only valid after Layout() is called.
147  virtual void Paint(SkCanvas* canvas, double x, double y) = 0;
148 
149  // Returns a vector of bounding boxes that enclose all text between start and
150  // end glyph indexes, including start and excluding end.
151  virtual std::vector<TextBox> GetRectsForRange(
152  size_t start,
153  size_t end,
154  RectHeightStyle rect_height_style,
155  RectWidthStyle rect_width_style) = 0;
156 
157  // Returns a vector of bounding boxes that bound all inline placeholders in
158  // the paragraph.
159  //
160  // There will be one box for each inline placeholder. The boxes will be in the
161  // same order as they were added to the paragraph. The bounds will always be
162  // tight and should fully enclose the area where the placeholder should be.
163  //
164  // More granular boxes may be obtained through GetRectsForRange, which will
165  // return bounds on both text as well as inline placeholders.
166  virtual std::vector<TextBox> GetRectsForPlaceholders() = 0;
167 
168  // Returns the index of the glyph that corresponds to the provided coordinate,
169  // with the top left corner as the origin, and +y direction as down.
171  double dy) = 0;
172 
173  // Finds the first and last glyphs that define a word containing the glyph at
174  // index offset.
175  virtual Range<size_t> GetWordBoundary(size_t offset) = 0;
176 
177  virtual std::vector<LineMetrics>& GetLineMetrics() = 0;
178 };
179 
180 } // namespace txt
181 
182 #endif // LIB_TXT_SRC_PARAGRAPH_H_
virtual bool DidExceedMaxLines()=0
virtual PositionWithAffinity GetGlyphPositionAtCoordinate(double dx, double dy)=0
virtual double GetMinIntrinsicWidth()=0
virtual std::vector< TextBox > GetRectsForPlaceholders()=0
virtual double GetIdeographicBaseline()=0
virtual void Layout(double width)=0
virtual std::vector< LineMetrics > & GetLineMetrics()=0
virtual double GetLongestLine()=0
PositionWithAffinity(size_t p, Affinity a)
Definition: paragraph.h:76
TextDirection direction
Definition: paragraph.h:81
virtual std::vector< TextBox > GetRectsForRange(size_t start, size_t end, RectHeightStyle rect_height_style, RectWidthStyle rect_width_style)=0
int32_t width
bool operator==(const Range< T > &other) const
Definition: paragraph.h:93
virtual double GetMaxWidth()=0
void Shift(T delta)
Definition: paragraph.h:99
virtual double GetAlphabeticBaseline()=0
virtual ~Paragraph()=default
TextBox(SkRect r, TextDirection d)
Definition: paragraph.h:83
virtual void Paint(SkCanvas *canvas, double x, double y)=0
virtual double GetHeight()=0
virtual double GetMaxIntrinsicWidth()=0
virtual Range< size_t > GetWordBoundary(size_t offset)=0