1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef UI_GFX_RENDER_TEXT_H_
6 #define UI_GFX_RENDER_TEXT_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <algorithm>
12 #include <cstring>
13 #include <memory>
14 #include <string>
15 #include <utility>
16 #include <vector>
17 
18 #include "base/i18n/rtl.h"
19 #include "base/macros.h"
20 #include "base/strings/string16.h"
21 #include "cc/paint/paint_canvas.h"
22 #include "cc/paint/paint_flags.h"
23 #include "third_party/skia/include/core/SkColor.h"
24 #include "third_party/skia/include/core/SkFont.h"
25 #include "third_party/skia/include/core/SkRefCnt.h"
26 #include "ui/gfx/break_list.h"
27 #include "ui/gfx/font_list.h"
28 #include "ui/gfx/font_render_params.h"
29 #include "ui/gfx/geometry/point.h"
30 #include "ui/gfx/geometry/rect.h"
31 #include "ui/gfx/geometry/rect_f.h"
32 #include "ui/gfx/geometry/size_f.h"
33 #include "ui/gfx/geometry/vector2d.h"
34 #include "ui/gfx/range/range.h"
35 #include "ui/gfx/range/range_f.h"
36 #include "ui/gfx/selection_model.h"
37 #include "ui/gfx/shadow_value.h"
38 #include "ui/gfx/text_constants.h"
39 
40 class SkDrawLooper;
41 struct SkPoint;
42 class SkTypeface;
43 
44 namespace gfx {
45 namespace test {
46 class RenderTextTestApi;
47 }
48 
49 class Canvas;
50 struct DecoratedText;
51 class Font;
52 
53 namespace internal {
54 
55 class TextRunList;
56 
57 // Internal helper class used by derived classes to draw text through Skia.
58 class GFX_EXPORT SkiaTextRenderer {
59  public:
60   explicit SkiaTextRenderer(Canvas* canvas);
61   virtual ~SkiaTextRenderer();
62 
63   void SetDrawLooper(sk_sp<SkDrawLooper> draw_looper);
64   void SetFontRenderParams(const FontRenderParams& params,
65                            bool subpixel_rendering_suppressed);
66   void SetTypeface(sk_sp<SkTypeface> typeface);
67   void SetTextSize(SkScalar size);
68   void SetForegroundColor(SkColor foreground);
69   void SetShader(sk_sp<cc::PaintShader> shader);
70   // TODO(vmpstr): Change this API to mimic SkCanvas::drawTextBlob instead.
71   virtual void DrawPosText(const SkPoint* pos,
72                            const uint16_t* glyphs,
73                            size_t glyph_count);
74   void DrawUnderline(int x, int y, int width, SkScalar thickness_factor = 1.0);
75   void DrawStrike(int x, int y, int width, SkScalar thickness_factor);
76 
77  private:
78   friend class test::RenderTextTestApi;
79 
80   Canvas* canvas_;
81   cc::PaintCanvas* canvas_skia_;
82   cc::PaintFlags flags_;
83   SkFont font_;
84 
85   DISALLOW_COPY_AND_ASSIGN(SkiaTextRenderer);
86 };
87 
88 struct TextToDisplayIndex {
89   size_t text_index = 0;
90   size_t display_index = 0;
91 };
92 using TextToDisplaySequence = std::vector<TextToDisplayIndex>;
93 using GraphemeIterator = TextToDisplaySequence::const_iterator;
94 
95 // Internal helper class used to iterate colors, baselines, and styles.
96 class StyleIterator {
97  public:
98   StyleIterator(const BreakList<SkColor>* colors,
99                 const BreakList<BaselineStyle>* baselines,
100                 const BreakList<int>* font_size_overrides,
101                 const BreakList<Font::Weight>* weights,
102                 const std::vector<BreakList<bool>>* styles);
103   StyleIterator(const StyleIterator& style);
104   ~StyleIterator();
105   StyleIterator& operator=(const StyleIterator& style);
106 
107   // Get the colors and styles at the current iterator position.
color()108   SkColor color() const { return color_->second; }
baseline()109   BaselineStyle baseline() const { return baseline_->second; }
font_size_override()110   int font_size_override() const { return font_size_override_->second; }
style(TextStyle s)111   bool style(TextStyle s) const { return style_[s]->second; }
weight()112   Font::Weight weight() const { return weight_->second; }
113 
114   // Get the intersecting range of the current iterator set.
115   Range GetRange() const;
116 
117   // Get the intersecting range of the current iterator set for attributes that
118   // can break text (e.g. not color).
119   Range GetTextBreakingRange() const;
120 
121   // Update the iterator to point to colors and styles applicable at |position|.
122   void IncrementToPosition(size_t position);
123 
124  private:
125   // Pointers to the breaklists to iterate through. These pointers can't be
126   // nullptr and the breaklists must outlive this object.
127   const BreakList<SkColor>* colors_;
128   const BreakList<BaselineStyle>* baselines_;
129   const BreakList<int>* font_size_overrides_;
130   const BreakList<Font::Weight>* weights_;
131   const std::vector<BreakList<bool>>* styles_;
132 
133   BreakList<SkColor>::const_iterator color_;
134   BreakList<BaselineStyle>::const_iterator baseline_;
135   BreakList<int>::const_iterator font_size_override_;
136   BreakList<Font::Weight>::const_iterator weight_;
137   std::vector<BreakList<bool>::const_iterator> style_;
138 };
139 
140 // Line segments are slices of the display text to be rendered on a single line.
141 struct LineSegment {
142   LineSegment();
143   ~LineSegment();
144 
145   // X coordinates of this line segment in text space.
146   RangeF x_range;
147 
148   // The character range this segment corresponds to.
149   Range char_range;
150 
151   // Index of the text run that generated this segment.
152   size_t run;
153 
154   // Returns the width of this line segment in text space.
widthLineSegment155   float width() const { return x_range.length(); }
156 };
157 
158 // A line of display text, comprised of a line segment list and some metrics.
159 struct Line {
160   Line();
161   Line(const Line& other);
162   ~Line();
163 
164   // Segments that make up this line in visual order.
165   std::vector<LineSegment> segments;
166 
167   // The sum of segment widths and the maximum of segment heights.
168   SizeF size;
169 
170   // Sum of preceding lines' heights.
171   int preceding_heights;
172 
173   // Maximum baseline of all segments on this line.
174   int baseline;
175 };
176 
177 // Internal class that contains the results of the text layout and shaping.
178 class ShapedText {
179  public:
180   explicit ShapedText(std::vector<Line> lines);
181   ~ShapedText();
182 
lines()183   const std::vector<Line>& lines() const { return lines_; }
184 
185  private:
186   std::vector<Line> lines_;
187 };
188 
189 // Creates an SkTypeface from a font, |italic| and a desired |weight|.
190 // May return null.
191 sk_sp<SkTypeface> CreateSkiaTypeface(const Font& font,
192                                      bool italic,
193                                      Font::Weight weight);
194 
195 // Applies the given FontRenderParams to the SkFont.
196 void ApplyRenderParams(const FontRenderParams& params,
197                        bool subpixel_rendering_suppressed,
198                        SkFont* font);
199 
200 }  // namespace internal
201 
202 // RenderText represents an abstract model of styled text and its corresponding
203 // visual layout. Support is built in for a cursor, a selection, simple styling,
204 // complex scripts, and bi-directional text. Implementations provide mechanisms
205 // for rendering and translation between logical and visual data.
206 class GFX_EXPORT RenderText {
207  public:
208 #if defined(OS_MACOSX)
209   // On Mac, while selecting text if the cursor is outside the vertical text
210   // bounds, drag to the end of the text.
211   static constexpr bool kDragToEndIfOutsideVerticalBounds = true;
212   // Mac supports a selection that is "undirected". When undirected, the cursor
213   // doesn't know which end of the selection it's at until it first moves.
214   static constexpr bool kSelectionIsAlwaysDirected = false;
215 #else
216   static constexpr bool kDragToEndIfOutsideVerticalBounds = false;
217   static constexpr bool kSelectionIsAlwaysDirected = true;
218 #endif
219 
220   // The character used for displaying obscured text. Use a bullet character.
221   // TODO(pbos): This is highly font dependent, consider replacing the character
222   // with a vector glyph.
223   static constexpr base::char16 kPasswordReplacementChar = 0x2022;
224 
225   virtual ~RenderText();
226 
227   // Creates a RenderText instance.
228   static std::unique_ptr<RenderText> CreateRenderText();
229 
230   // Like above but copies all style settings too.
231   std::unique_ptr<RenderText> CreateInstanceOfSameStyle(
232       const base::string16& text) const;
233 
text()234   const base::string16& text() const { return text_; }
235   void SetText(const base::string16& text);
236   void AppendText(const base::string16& text);
237 
horizontal_alignment()238   HorizontalAlignment horizontal_alignment() const {
239     return horizontal_alignment_;
240   }
241   void SetHorizontalAlignment(HorizontalAlignment alignment);
242 
vertical_alignment()243   VerticalAlignment vertical_alignment() const { return vertical_alignment_; }
244   void SetVerticalAlignment(VerticalAlignment alignment);
245 
font_list()246   const FontList& font_list() const { return font_list_; }
247   void SetFontList(const FontList& font_list);
248 
cursor_enabled()249   bool cursor_enabled() const { return cursor_enabled_; }
250   void SetCursorEnabled(bool cursor_enabled);
251 
selection_color()252   SkColor selection_color() const { return selection_color_; }
set_selection_color(SkColor color)253   void set_selection_color(SkColor color) { selection_color_ = color; }
254 
selection_background_focused_color()255   SkColor selection_background_focused_color() const {
256     return selection_background_focused_color_;
257   }
set_selection_background_focused_color(SkColor color)258   void set_selection_background_focused_color(SkColor color) {
259     selection_background_focused_color_ = color;
260   }
261 
symmetric_selection_visual_bounds()262   bool symmetric_selection_visual_bounds() const {
263     return symmetric_selection_visual_bounds_;
264   }
set_symmetric_selection_visual_bounds(bool symmetric)265   void set_symmetric_selection_visual_bounds(bool symmetric) {
266     symmetric_selection_visual_bounds_ = symmetric;
267   }
268 
focused()269   bool focused() const { return focused_; }
set_focused(bool focused)270   void set_focused(bool focused) { focused_ = focused; }
271 
clip_to_display_rect()272   bool clip_to_display_rect() const { return clip_to_display_rect_; }
set_clip_to_display_rect(bool clip)273   void set_clip_to_display_rect(bool clip) { clip_to_display_rect_ = clip; }
274 
275   // In an obscured (password) field, all text is drawn as bullets.
obscured()276   bool obscured() const { return obscured_; }
277   void SetObscured(bool obscured);
278 
279   // Makes a char in obscured text at |index| to be revealed. |index| should be
280   // a UTF16 text index. If there is a previous revealed index, the previous one
281   // is cleared and only the last set index will be revealed. If |index| is -1
282   // or out of range, no char will be revealed. The revealed index is also
283   // cleared when SetText or SetObscured is called.
284   void SetObscuredRevealIndex(int index);
285 
286   // For obscured (password) fields, the extra spacing between glyphs.
obscured_glyph_spacing()287   int obscured_glyph_spacing() const { return obscured_glyph_spacing_; }
288   void SetObscuredGlyphSpacing(int spacing);
289 
multiline()290   bool multiline() const { return multiline_; }
291   void SetMultiline(bool multiline);
292 
293   // If multiline, a non-zero value will cap the number of lines rendered,
294   // and elide the rest (currently only ELIDE_TAIL supported.)
295   void SetMaxLines(size_t max_lines);
max_lines()296   size_t max_lines() const { return max_lines_; }
297 
298   // Returns the actual number of lines, broken by |lines_|.
299   size_t GetNumLines();
300 
301   // TODO(mukai): ELIDE_LONG_WORDS is not supported.
word_wrap_behavior()302   WordWrapBehavior word_wrap_behavior() const { return word_wrap_behavior_; }
303   void SetWordWrapBehavior(WordWrapBehavior behavior);
304 
305   // TODO(ckocagil): Add vertical alignment and line spacing support instead.
min_line_height()306   int min_line_height() const { return min_line_height_; }
307   void SetMinLineHeight(int line_height);
308 
309   // Set the maximum length of the layout text, not the actual text.
310   // A |length| of 0 forgoes a hard limit, but does not guarantee proper
311   // functionality of very long strings. Applies to subsequent SetText calls.
312   // WARNING: Only use this for system limits, it lacks complex text support.
set_truncate_length(size_t length)313   void set_truncate_length(size_t length) { truncate_length_ = length; }
314 
315   // The display text will be elided to fit |display_rect| using this behavior.
316   void SetElideBehavior(ElideBehavior elide_behavior);
elide_behavior()317   ElideBehavior elide_behavior() const { return elide_behavior_; }
318 
319   // When display text is elided, determines how whitespace is handled.
320   // If base::nullopt is specified, the default elision for the current elide
321   // behavior will be applied.
322   void SetWhitespaceElision(base::Optional<bool> elide_whitespace);
whitespace_elision()323   base::Optional<bool> whitespace_elision() const {
324     return whitespace_elision_;
325   }
326 
display_rect()327   const Rect& display_rect() const { return display_rect_; }
328   void SetDisplayRect(const Rect& r);
329 
subpixel_rendering_suppressed()330   bool subpixel_rendering_suppressed() const {
331     return subpixel_rendering_suppressed_;
332   }
set_subpixel_rendering_suppressed(bool suppressed)333   void set_subpixel_rendering_suppressed(bool suppressed) {
334     subpixel_rendering_suppressed_ = suppressed;
335   }
336 
selection_model()337   const SelectionModel& selection_model() const { return selection_model_; }
selection()338   const Range& selection() const { return selection_model_.selection(); }
cursor_position()339   size_t cursor_position() const { return selection_model_.caret_pos(); }
340 
341   // Set the cursor to |position|, with the caret affinity trailing the previous
342   // grapheme, or if there is no previous grapheme, leading the cursor position.
343   // See SelectionModel::caret_affinity_ for details.
344   void SetCursorPosition(size_t position);
345 
346   // Moves the cursor left or right. Cursor movement is visual, meaning that
347   // left and right are relative to screen, not the directionality of the text.
348   // |selection_behavior| determines whether a selection is to be made and it's
349   // behavior.
350   void MoveCursor(BreakType break_type,
351                   VisualCursorDirection direction,
352                   SelectionBehavior selection_behavior);
353 
354   // Set the selection_model_ to the value of |selection|.
355   // The selection range is clamped to text().length() if out of range.
356   // Returns true if the cursor position or selection range changed.
357   // If any index in |selection_model| is not a cursorable position (not on a
358   // grapheme boundary), it is a no-op and returns false.
359   bool SetSelection(const SelectionModel& selection);
360 
361   // Moves the cursor to the text index corresponding to |point|. If |select| is
362   // true, a selection is made with the current selection start index. If the
363   // resultant text indices do not lie on valid grapheme boundaries, it is a no-
364   // op and returns false. If this move is happening because of a drag causing a
365   // selection change, and |drag_origin| is not the zero point, then
366   // |drag_origin| overrides the default origin for a select-to-drag
367   // (usually the existing text insertion cursor).
368   bool MoveCursorToPoint(const gfx::Point& point,
369                          bool select,
370                          const gfx::Point& drag_origin = gfx::Point());
371 
372   // Set the selection_model_ based on |range|.
373   // If the |range| start or end is greater than text length, it is modified
374   // to be the text length.
375   // If the |range| start or end is not a cursorable position (not on grapheme
376   // boundary), it is a NO-OP and returns false. Otherwise, returns true.
377   bool SelectRange(const Range& range);
378 
379   // Returns true if the local point is over selected text.
380   bool IsPointInSelection(const Point& point);
381 
382   // Selects no text, keeping the current cursor position and caret affinity.
383   void ClearSelection();
384 
385   // Select the entire text range. If |reversed| is true, the range will end at
386   // the logical beginning of the text; this generally shows the leading portion
387   // of text that overflows its display area.
388   void SelectAll(bool reversed);
389 
390   // Selects the word at the current cursor position. If there is a non-empty
391   // selection, the selection bounds are extended to their nearest word
392   // boundaries.
393   void SelectWord();
394 
395   void SetCompositionRange(const Range& composition_range);
396 
397   // Set the text color over the entire text or a logical character range.
398   // The |range| should be valid, non-reversed, and within [0, text().length()].
399   void SetColor(SkColor value);
400   void ApplyColor(SkColor value, const Range& range);
401 
402   // DEPRECATED.
403   // Set the baseline style over the entire text or a logical character range.
404   // The |range| should be valid, non-reversed, and within [0, text().length()].
405   // TODO(tapted): Remove this. The only client is moving to
406   // ApplyFontSizeOverride.
407   void SetBaselineStyle(BaselineStyle value);
408   void ApplyBaselineStyle(BaselineStyle value, const Range& range);
409 
410   // Alters the font size in |range|.
411   void ApplyFontSizeOverride(int font_size_override, const Range& range);
412 
413   // Set various text styles over the entire text or a logical character range.
414   // The respective |style| is applied if |value| is true, or removed if false.
415   // The |range| should be valid, non-reversed, and within [0, text().length()].
416   void SetStyle(TextStyle style, bool value);
417   void ApplyStyle(TextStyle style, bool value, const Range& range);
418 
419   void SetWeight(Font::Weight weight);
420   void ApplyWeight(Font::Weight weight, const Range& range);
421 
422   // Returns whether this style is enabled consistently across the entire
423   // RenderText.
424   bool GetStyle(TextStyle style) const;
425 
426   // Set or get the text directionality mode and get the text direction yielded.
427   void SetDirectionalityMode(DirectionalityMode mode);
directionality_mode()428   DirectionalityMode directionality_mode() const {
429       return directionality_mode_;
430   }
431   base::i18n::TextDirection GetDisplayTextDirection();
432 
433   // Returns the visual movement direction corresponding to the logical
434   // end/beginning of the text, considering only the dominant direction returned
435   // by |GetDisplayTextDirection()|, not the direction of a particular run.
436   VisualCursorDirection GetVisualDirectionOfLogicalEnd();
437   VisualCursorDirection GetVisualDirectionOfLogicalBeginning();
438 
439   // Returns the text used to display, which may be obscured, truncated or
440   // elided. The subclass may compute elided text on the fly, or use
441   // precomputed the elided text.
442   virtual const base::string16& GetDisplayText() = 0;
443 
444   // Returns the size required to display the current string (which is the
445   // wrapped size in multiline mode). The returned size does not include space
446   // reserved for the cursor or the offset text shadows.
447   Size GetStringSize();
448 
449   // This is same as GetStringSize except that fractional size is returned.
450   // The default implementation is same as GetStringSize. Certain platforms that
451   // compute the text size as floating-point values, like Mac, will override
452   // this method.
453   // See comment in Canvas::GetStringWidthF for its usage.
454   virtual SizeF GetStringSizeF() = 0;
455 
456   // Returns the size of the line containing |caret|.
457   virtual Size GetLineSize(const SelectionModel& caret) = 0;
458 
459   // Returns the sum of all the line widths.
460   float TotalLineWidth();
461 
462   // Returns the width of the content (which is the wrapped width in multiline
463   // mode). Reserves room for the cursor if |cursor_enabled_| is true.
464   float GetContentWidthF();
465 
466   // Same as GetContentWidthF with the width rounded up.
467   int GetContentWidth();
468 
469   // Returns the common baseline of the text. The return value is the vertical
470   // offset from the top of |display_rect_| to the text baseline, in pixels.
471   // The baseline is determined from the font list and display rect, and does
472   // not depend on the text.
473   int GetBaseline();
474 
475   // If |select_all| is true, draws as focused with all text selected.
476   void Draw(Canvas* canvas, bool select_all = false);
477 
478   // Gets the SelectionModel from a visual point in local coordinates. If
479   // |drag_origin| is nonzero, it is used as the baseline for
480   // out-of-vertical-bounds drags on platforms that have them, instead of the
481   // default origin (the insertion cursor's position).
482   SelectionModel FindCursorPosition(const Point& point,
483                                     const Point& drag_origin = gfx::Point());
484 
485   // Returns true if the position is a valid logical index into text(). Indices
486   // amid multi-character graphemes are allowed here, unlike IsValidCursorIndex.
487   bool IsValidLogicalIndex(size_t index) const;
488 
489   // Returns true if the position is a valid logical index into text(), and is
490   // also a valid grapheme boundary, which may be used as a cursor position.
491   bool IsValidCursorIndex(size_t index) const;
492 
493   // Get the visual bounds of a cursor at |caret|. These bounds typically
494   // represent a vertical line if |insert_mode| is true. Pass false for
495   // |insert_mode| to retrieve the bounds of the associated glyph. These bounds
496   // are in local coordinates, but may be outside the visible region if the text
497   // is longer than the textfield. Subsequent text, cursor, or bounds changes
498   // may invalidate returned values. Note that |caret| must be placed at
499   // grapheme boundary, i.e. caret.caret_pos() must be a cursorable position.
500   // TODO(crbug.com/248597): Add multiline support.
501   Rect GetCursorBounds(const SelectionModel& caret, bool insert_mode);
502 
503   // Compute the current cursor bounds, panning the text to show the cursor in
504   // the display rect if necessary. These bounds are in local coordinates.
505   // Subsequent text, cursor, or bounds changes may invalidate returned values.
506   const Rect& GetUpdatedCursorBounds();
507 
508   // Returns a grapheme iterator that contains the codepoint at |index|.
509   internal::GraphemeIterator GetGraphemeIteratorAtTextIndex(size_t index) const;
510   internal::GraphemeIterator GetGraphemeIteratorAtDisplayTextIndex(
511       size_t index) const;
512 
513   // For a given grapheme iterator, returns its index.
514   size_t GetTextIndex(internal::GraphemeIterator iter) const;
515   size_t GetDisplayTextIndex(internal::GraphemeIterator iter) const;
516 
517   // Returns true of the current index is at the start of a grapheme.
518   bool IsGraphemeBoundary(size_t index) const;
519 
520   // Given an |index| in text(), return the next or previous grapheme boundary
521   // in logical order (i.e. the nearest cursorable index). The return value is
522   // in the range 0 to text().length() inclusive (the input is clamped if it is
523   // out of that range). Always moves by at least one character index unless the
524   // supplied index is already at the boundary of the string.
525   size_t IndexOfAdjacentGrapheme(size_t index,
526                                  LogicalCursorDirection direction) const;
527 
528   // Return a SelectionModel with the cursor at the current selection's start.
529   // The returned value represents a cursor/caret position without a selection.
530   SelectionModel GetSelectionModelForSelectionStart() const;
531 
532   // Sets shadows to drawn with text.
set_shadows(const ShadowValues & shadows)533   void set_shadows(const ShadowValues& shadows) { shadows_ = shadows; }
shadows()534   const ShadowValues& shadows() const { return shadows_; }
535 
536   // Returns rectangle surrounding the current string (from origin to size)
537   RectF GetStringRect();
538 
539   // Get the visual bounds containing the logical substring within the |range|.
540   // If |range| is empty, the result is empty. These bounds could be visually
541   // discontinuous if the substring is split by a LTR/RTL level change.
542   // These bounds are in local coordinates, but may be outside the visible
543   // region if the text is longer than the textfield. Subsequent text, cursor,
544   // or bounds changes may invalidate returned values.
545   virtual std::vector<Rect> GetSubstringBounds(const Range& range) = 0;
546 
547   // Gets the horizontal span (relative to the left of the text, not the view)
548   // of the sequence of glyphs in |text_range|, over which the cursor will
549   // jump when breaking by characters. If the glyphs are RTL then the returned
550   // Range will have is_reversed() true.  (This does not return a Rect because a
551   // Rect can't have a negative width.)
552   virtual RangeF GetCursorSpan(const Range& text_range) = 0;
553 
554   const Vector2d& GetUpdatedDisplayOffset();
555   void SetDisplayOffset(int horizontal_offset);
556 
557   // Returns the line offset from the origin after applying the text alignment
558   // and the display offset.
559   Vector2d GetLineOffset(size_t line_number);
560 
561   // Retrieves the word displayed at the given |point| along with its styling
562   // information. |point| is in the view's coordinates. If no word is displayed
563   // at the point, returns a nearby word. |baseline_point| should correspond to
564   // the baseline point of the leftmost glyph of the |word| in the view's
565   // coordinates. Returns false, if no word can be retrieved.
566   bool GetWordLookupDataAtPoint(const Point& point,
567                                 DecoratedText* decorated_word,
568                                 Point* baseline_point);
569 
570   // Retrieves the text at |range| along with its styling information.
571   // |baseline_point| should correspond to the baseline point of
572   // the leftmost glyph of the text in the view's coordinates. If the text
573   // spans multiple lines, |baseline_point| will correspond with the leftmost
574   // glyph on the first line in the range. Returns false, if no text can be
575   // retrieved.
576   bool GetLookupDataForRange(const Range& range,
577                              DecoratedText* decorated_text,
578                              Point* baseline_point);
579 
580   // Retrieves the text in the given |range|.
581   base::string16 GetTextFromRange(const Range& range) const;
582 
set_strike_thickness_factor(SkScalar f)583   void set_strike_thickness_factor(SkScalar f) { strike_thickness_factor_ = f; }
584 
585   // Return the line index that contains the argument; or the index of the last
586   // line if the |caret| exceeds the text length.
587   virtual size_t GetLineContainingCaret(const SelectionModel& caret) = 0;
588 
589   // Expands |range| to its nearest grapheme boundaries and returns the
590   // resulting range. Maintains directionality of |range|.
591   Range ExpandRangeToGraphemeBoundary(const Range& range) const;
592 
593  protected:
594   RenderText();
595 
596   // Whether |segment| corresponds to the newline character. This uses |text_|
597   // to look up the corresponding character.
598   bool IsNewlineSegment(const internal::LineSegment& segment) const;
599 
600   // Whether |segment| corresponds to the newline character inside |text|.
601   bool IsNewlineSegment(const base::string16& text,
602                         const internal::LineSegment& segment) const;
603 
604   // Returns the character range of segments in |line| excluding the trailing
605   // newline segment.
606   Range GetLineRange(const base::string16& text,
607                      const internal::Line& line) const;
608 
609   // Returns the text used for layout (e.g. after rewriting, eliding and
610   // obscuring characters).
611   const base::string16& GetLayoutText() const;
612 
613   // NOTE: The value of these accessors may be stale. Please make sure
614   // that these fields are up to date before accessing them.
display_text()615   const base::string16& display_text() const { return display_text_; }
text_elided()616   bool text_elided() const { return text_elided_; }
617 
618   // Returns an iterator over the |text_| attributes.
619   internal::StyleIterator GetTextStyleIterator() const;
620   // Returns an iterator over the |layout_text_| attributes.
621   internal::StyleIterator GetLayoutTextStyleIterator() const;
622 
colors()623   const BreakList<SkColor>& colors() const { return colors_; }
baselines()624   const BreakList<BaselineStyle>& baselines() const { return baselines_; }
font_size_overrides()625   const BreakList<int>& font_size_overrides() const {
626     return font_size_overrides_;
627   }
weights()628   const BreakList<Font::Weight>& weights() const { return weights_; }
styles()629   const std::vector<BreakList<bool> >& styles() const { return styles_; }
strike_thickness_factor()630   SkScalar strike_thickness_factor() const { return strike_thickness_factor_; }
631 
layout_colors()632   const BreakList<SkColor>& layout_colors() const { return layout_colors_; }
633 
634   // Whether all the BreakLists have only one break.
635   bool IsHomogeneous() const;
636 
637   // Returns the shaped text structure. The shaped text contains the visual
638   // positions of glyphs required to render the text.
has_shaped_text()639   bool has_shaped_text() const { return shaped_text_ != nullptr; }
640   internal::ShapedText* GetShapedText();
set_shaped_text(std::unique_ptr<internal::ShapedText> shaped_text)641   void set_shaped_text(std::unique_ptr<internal::ShapedText> shaped_text) {
642     shaped_text_ = std::move(shaped_text);
643   }
644 
645   // Returns the baseline of the current text.  The return value depends on
646   // the text and its layout while the return value of GetBaseline() doesn't.
647   // GetAlignmentOffset() takes into account the difference between them.
648   //
649   // We'd like a RenderText to show the text always on the same baseline
650   // regardless of the text, so the text does not jump up or down depending
651   // on the text.  However, underlying layout engines return different baselines
652   // depending on the text.  In general, layout engines determine the minimum
653   // bounding box for the text and return the baseline from the top of the
654   // bounding box.  So the baseline changes depending on font metrics used to
655   // layout the text.
656   //
657   // For example, suppose there are FontA and FontB and the baseline of FontA
658   // is smaller than the one of FontB.  If the text is laid out only with FontA,
659   // then the baseline of FontA may be returned.  If the text includes some
660   // characters which are laid out with FontB, then the baseline of FontB may
661   // be returned.
662   //
663   // GetBaseline() returns the fixed baseline regardless of the text.
664   // GetDisplayTextBaseline() returns the baseline determined by the underlying
665   // layout engine, and it changes depending on the text.  GetAlignmentOffset()
666   // returns the difference between them.
667   int GetDisplayTextBaseline();
668 
669   // Get the selection model that visually neighbors |position| by |break_type|.
670   // The returned value represents a cursor/caret position without a selection.
671   SelectionModel GetAdjacentSelectionModel(const SelectionModel& current,
672                                            BreakType break_type,
673                                            VisualCursorDirection direction);
674 
675   // Get the selection model visually left/right of |selection| by one grapheme.
676   // The returned value represents a cursor/caret position without a selection.
677   virtual SelectionModel AdjacentCharSelectionModel(
678       const SelectionModel& selection,
679       VisualCursorDirection direction) = 0;
680 
681   // Get the selection model visually left/right of |selection| by one word.
682   // The returned value represents a cursor/caret position without a selection.
683   virtual SelectionModel AdjacentWordSelectionModel(
684       const SelectionModel& selection,
685       VisualCursorDirection direction) = 0;
686 
687   // Get the selection model visually above/below |selection| by one line.
688   // The returned value represents a cursor/caret position without a selection.
689   virtual SelectionModel AdjacentLineSelectionModel(
690       const SelectionModel& selection,
691       VisualCursorDirection direction) = 0;
692 
693   // Get the selection model corresponding to visual text ends.
694   // The returned value represents a cursor/caret position without a selection.
695   SelectionModel EdgeSelectionModel(VisualCursorDirection direction);
696 
697   // Get the selection model corresponding to visual text ends for |line_index|.
698   // The returned value represents a cursor/caret position without a selection.
699   SelectionModel LineSelectionModel(size_t line_index,
700                                     gfx::VisualCursorDirection direction);
701 
702   // Sets the selection model, |model| is assumed to be valid.
703   void SetSelectionModel(const SelectionModel& model);
704 
705   // Convert between indices into |text_| and indices into
706   // GetDisplayText(), which differ when the text is obscured,
707   // truncated or elided.
708   size_t TextIndexToDisplayIndex(size_t index) const;
709   size_t DisplayIndexToTextIndex(size_t index) const;
710 
711   // Notifies that layout text, or attributes that affect the layout text
712   // shape have changed. |text_changed| is true if the content of the
713   // |layout_text_| has changed, not just attributes.
714   virtual void OnLayoutTextAttributeChanged(bool text_changed);
715 
716   // Notifies that attributes that affect the display text shape have changed.
717   virtual void OnDisplayTextAttributeChanged() = 0;
718 
719   // Ensure the text is laid out, lines are computed, and |lines_| is valid.
720   virtual void EnsureLayout() = 0;
721 
722   // Draw all text and make the given range appear selected.
723   virtual void DrawVisualText(internal::SkiaTextRenderer* renderer,
724                               const Range& selection) = 0;
725 
726   // Update the display text.
727   void UpdateDisplayText(float text_width);
728 
729   // Returns display text positions that are suitable for breaking lines.
730   const BreakList<size_t>& GetLineBreaks();
731 
732   // Convert points from the text space to the view space. Handles the display
733   // area, display offset, application LTR/RTL mode and multiline.
734   Point ToViewPoint(const PointF& point, LogicalCursorDirection caret_affinity);
735 
736   // Get the alignment, resolving ALIGN_TO_HEAD with the current text direction.
737   HorizontalAlignment GetCurrentHorizontalAlignment();
738 
739   // Returns the line offset from the origin, accounts for text alignment only.
740   Vector2d GetAlignmentOffset(size_t line_number);
741 
742   // Applies fade effects to |renderer|.
743   void ApplyFadeEffects(internal::SkiaTextRenderer* renderer);
744 
745   // Applies text shadows to |renderer|.
746   void ApplyTextShadows(internal::SkiaTextRenderer* renderer);
747 
748   // Get the text direction for the current directionality mode and given
749   // |text|.
750   base::i18n::TextDirection GetTextDirection(const base::string16& text);
751 
752   // Adjust ranged styles to accommodate a new |text_| length.
753   void UpdateStyleLengths();
754 
755   // Adjust ranged styles to accommodate a new |layout_text_| length.
756   void UpdateLayoutStyleLengths(size_t max_length) const;
757 
758   // Returns the line index for the given argument. |text_y| is relative to
759   // the text bounds. Returns -1 if |text_y| is above the text and
760   // lines().size() if |text_y| is below it.
761   int GetLineContainingYCoord(float text_y);
762 
763   // A convenience function to check whether the glyph attached to the caret
764   // is within the given range.
765   static bool RangeContainsCaret(const Range& range,
766                                  size_t caret_pos,
767                                  LogicalCursorDirection caret_affinity);
768 
769   // Returns the baseline, with which the text best appears vertically centered.
770   static int DetermineBaselineCenteringText(const int display_height,
771                                             const FontList& font_list);
772 
773   // Returns an expanded version of |rect| that is vertically symmetric with
774   // respect to the center of |display_rect|.
775   static gfx::Rect ExpandToBeVerticallySymmetric(const gfx::Rect& rect,
776                                                  const gfx::Rect& display_rect);
777 
778   // Resets |cached_cursor_x_| to null. When non-null, CURSOR_UP, CURSOR_DOWN
779   // movements use this value instead of the current cursor x position to
780   // determine the next cursor x position.
reset_cached_cursor_x()781   void reset_cached_cursor_x() { cached_cursor_x_.reset(); }
782 
set_cached_cursor_x(int x)783   void set_cached_cursor_x(int x) { cached_cursor_x_ = x; }
cached_cursor_x()784   base::Optional<int> cached_cursor_x() const { return cached_cursor_x_; }
785 
786   // Fixed width of glyphs. This should only be set in test environments.
787   float glyph_width_for_test_ = 0;
788 
789  private:
790   friend class test::RenderTextTestApi;
791 
792   // Resets |layout_text_| and |display_text_| and marks them dirty.
793   void OnTextAttributeChanged();
794 
795   // Computes the |layout_text_| by rewriting it from |text_|, if needed.
796   // Computes the layout break lists, if needed.
797   void EnsureLayoutTextUpdated() const;
798 
799   // Elides |text| as needed to fit in the |available_width| using |behavior|.
800   // |text_width| is the pre-calculated width of the text shaped by this render
801   // text, or pass 0 if the width is unknown.
802   base::string16 Elide(const base::string16& text,
803                        float text_width,
804                        float available_width,
805                        ElideBehavior behavior);
806 
807   // Elides |email| as needed to fit the |available_width|.
808   base::string16 ElideEmail(const base::string16& email, float available_width);
809 
810   // Update the cached bounds and display offset to ensure that the current
811   // cursor is within the visible display area.
812   void UpdateCachedBoundsAndOffset();
813 
814   // Draws the specified range of text with a selected appearance.
815   void DrawSelection(Canvas* canvas, const Range& selection);
816 
817   // Returns a grapheme iterator that contains the codepoint at |index|.
818   internal::GraphemeIterator GetGraphemeIteratorAtIndex(
819       const base::string16& text,
820       const size_t internal::TextToDisplayIndex::*field,
821       size_t index) const;
822 
823   // Returns the nearest word start boundary for |index|. First searches in the
824   // CURSOR_BACKWARD direction, then in the CURSOR_FORWARD direction. Returns
825   // the text length if no valid boundary is found.
826   size_t GetNearestWordStartBoundary(size_t index) const;
827 
828   // Expands |range| to its nearest word boundaries and returns the resulting
829   // range. Maintains directionality of |range|.
830   Range ExpandRangeToWordBoundary(const Range& range) const;
831 
832   // Returns an implementation-specific run list, if implemented.
833   virtual internal::TextRunList* GetRunList() = 0;
834   virtual const internal::TextRunList* GetRunList() const = 0;
835 
836   // Returns the decorated text corresponding to |range|. Returns false if the
837   // text cannot be retrieved, e.g. if the text is obscured.
838   virtual bool GetDecoratedTextForRange(const Range& range,
839                                         DecoratedText* decorated_text) = 0;
840 
841   // Specify the width of a glyph for test. The width of glyphs is very
842   // platform-dependent and environment-dependent. Otherwise multiline text
843   // will become really flaky.
set_glyph_width_for_test(float width)844   void set_glyph_width_for_test(float width) { glyph_width_for_test_ = width; }
845 
846   // Logical UTF-16 string data to be drawn.
847   base::string16 text_;
848 
849   // Horizontal alignment of the text with respect to |display_rect_|.  The
850   // default is to align left if the application UI is LTR and right if RTL.
851   HorizontalAlignment horizontal_alignment_;
852 
853   // Vertical alignment of the text with respect to |display_rect_|. Only
854   // applicable when |multiline_| is true. The default is to align center.
855   VerticalAlignment vertical_alignment_;
856 
857   // The text directionality mode, defaults to DIRECTIONALITY_FROM_TEXT.
858   DirectionalityMode directionality_mode_;
859 
860   // The cached text direction, potentially computed from the text or UI locale.
861   // Use GetTextDirection(), do not use this potentially invalid value directly!
862   base::i18n::TextDirection text_direction_;
863 
864   // A list of fonts used to render |text_|.
865   FontList font_list_;
866 
867   // Logical selection range and visual cursor position.
868   SelectionModel selection_model_;
869 
870   // The cached cursor bounds; get these bounds with GetUpdatedCursorBounds.
871   Rect cursor_bounds_;
872 
873   // Specifies whether the cursor is enabled. If disabled, no space is reserved
874   // for the cursor when positioning text.
875   bool cursor_enabled_;
876 
877   // Whether the current selection has a known direction. That is, whether a
878   // directional input (e.g. arrow key) has been received for the current
879   // selection to indicate which end of the selection has the caret. When true,
880   // directed inputs preserve (rather than replace) the selection affinity.
881   bool has_directed_selection_;
882 
883   // The color used for drawing selected text.
884   SkColor selection_color_;
885 
886   // The background color used for drawing the selection when focused.
887   SkColor selection_background_focused_color_;
888 
889   // Whether the selection visual bounds should be expanded vertically to be
890   // vertically symmetric with respect to the display rect. Note this flag has
891   // no effect on multi-line text.
892   bool symmetric_selection_visual_bounds_ = false;
893 
894   // The focus state of the text.
895   bool focused_;
896 
897   // Composition text range.
898   Range composition_range_;
899 
900   // Color, baseline, and style breaks, used to modify ranges of text.
901   // BreakList positions are stored with text indices, not display indices.
902   // TODO(msw): Expand to support cursor, selection, background, etc. colors.
903   BreakList<SkColor> colors_;
904   BreakList<BaselineStyle> baselines_;
905   BreakList<int> font_size_overrides_;
906   BreakList<Font::Weight> weights_;
907   std::vector<BreakList<bool> > styles_;
908 
909   mutable BreakList<SkColor> layout_colors_;
910   mutable BreakList<BaselineStyle> layout_baselines_;
911   mutable BreakList<int> layout_font_size_overrides_;
912   mutable BreakList<Font::Weight> layout_weights_;
913   mutable std::vector<BreakList<bool>> layout_styles_;
914 
915   // A mapping from text to display text indices for each grapheme. The vector
916   // contains an ordered sequence of indice pairs. Both sequence |text_index|
917   // and |display_index| are sorted.
918   mutable internal::TextToDisplaySequence text_to_display_indices_;
919 
920   // A flag to obscure actual text with asterisks for password fields.
921   bool obscured_;
922   // The index at which the char should be revealed in the obscured text.
923   int obscured_reveal_index_;
924 
925   // The maximum length of text to display, 0 forgoes a hard limit.
926   size_t truncate_length_;
927 
928   // The obscured and/or truncated text used to layout the text to display.
929   mutable base::string16 layout_text_;
930 
931   // The elided text displayed visually. This is empty if the text
932   // does not have to be elided, or became empty as a result of eliding.
933   // TODO(oshima): When the text is elided, painting can be done only with
934   // display text info, so it should be able to clear the |layout_text_| and
935   // associated information.
936   mutable base::string16 display_text_;
937 
938   // The behavior for eliding, fading, or truncating.
939   ElideBehavior elide_behavior_;
940 
941   // The behavior for eliding whitespace when eliding or truncating.
942   base::Optional<bool> whitespace_elision_ = base::nullopt;
943 
944   // True if the text is elided given the current behavior and display area.
945   bool text_elided_;
946 
947   // The minimum height a line should have.
948   int min_line_height_;
949 
950   // Whether the text should be broken into multiple lines. Uses the width of
951   // |display_rect_| as the width cap.
952   bool multiline_;
953 
954   // If multiple lines, the maximum number of lines to render, or 0.
955   size_t max_lines_;
956 
957   // The wrap behavior when the text is broken into lines. Do nothing unless
958   // |multiline_| is set. The default value is IGNORE_LONG_WORDS.
959   WordWrapBehavior word_wrap_behavior_;
960 
961   // Set to true to suppress subpixel rendering due to non-font reasons (eg.
962   // if the background is transparent). The default value is false.
963   bool subpixel_rendering_suppressed_;
964 
965   // The local display area for rendering the text.
966   Rect display_rect_;
967 
968   // Flag to work around a Skia bug with the PDF path (http://crbug.com/133548)
969   // that results in incorrect clipping when drawing to the document margins.
970   // This field allows disabling clipping to work around the issue.
971   // TODO(asvitkine): Remove this when the underlying Skia bug is fixed.
972   bool clip_to_display_rect_;
973 
974   // The offset for the text to be drawn, relative to the display area.
975   // Get this point with GetUpdatedDisplayOffset (or risk using a stale value).
976   Vector2d display_offset_;
977 
978   // The baseline of the text.  This is determined from the height of the
979   // display area and the cap height of the font list so the text is vertically
980   // centered.
981   int baseline_;
982 
983   // The cached bounds and offset are invalidated by changes to the cursor,
984   // selection, font, and other operations that adjust the visible text bounds.
985   bool cached_bounds_and_offset_valid_;
986 
987   // Text shadows to be drawn.
988   ShadowValues shadows_;
989 
990   // A list of valid display text line break positions.
991   BreakList<size_t> line_breaks_;
992 
993   // Text shaping computed by EnsureLayout. This should be invalidated upon
994   // OnLayoutTextAttributeChanged and OnDisplayTextAttributeChanged calls.
995   std::unique_ptr<internal::ShapedText> shaped_text_;
996 
997   // The ratio of strike-through line thickness to text height.
998   SkScalar strike_thickness_factor_;
999 
1000   // Extra spacing placed between glyphs; used only for obscured text styling.
1001   int obscured_glyph_spacing_ = 0;
1002 
1003   // The cursor position in view space, used to traverse lines of varied widths.
1004   base::Optional<int> cached_cursor_x_;
1005 
1006   // Tell whether or not the |layout_text_| needs an update or is up to date.
1007   mutable bool layout_text_up_to_date_ = false;
1008 
1009   DISALLOW_COPY_AND_ASSIGN(RenderText);
1010 };
1011 
1012 }  // namespace gfx
1013 
1014 #endif  // UI_GFX_RENDER_TEXT_H_
1015