1 // Copyright 2016 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 THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_PHYSICAL_TEXT_FRAGMENT_H_
6 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_PHYSICAL_TEXT_FRAGMENT_H_
7 
8 #include "third_party/blink/renderer/core/core_export.h"
9 #include "third_party/blink/renderer/core/layout/ng/inline/ng_text_offset.h"
10 #include "third_party/blink/renderer/core/layout/ng/inline/ng_text_type.h"
11 #include "third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h"
12 #include "third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h"
13 #include "third_party/blink/renderer/platform/fonts/ng_text_fragment_paint_info.h"
14 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h"
15 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
16 #include "third_party/blink/renderer/platform/wtf/casting.h"
17 #include "third_party/blink/renderer/platform/wtf/text/string_view.h"
18 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
19 
20 namespace blink {
21 
22 class NGTextFragmentBuilder;
23 class NGPhysicalTextFragment;
24 struct PhysicalRect;
25 
26 enum class AdjustMidCluster;
27 
28 class CORE_EXPORT NGPhysicalTextFragment final : public NGPhysicalFragment {
29  public:
30   NGPhysicalTextFragment(NGTextFragmentBuilder*);
31 
TextType()32   NGTextType TextType() const { return static_cast<NGTextType>(sub_type_); }
33   // Returns true if the text is generated (from, e.g., list marker,
34   // pseudo-element, ...) instead of from a DOM text node.
35   bool IsGeneratedText() const;
36   // True if this is a forced line break.
IsLineBreak()37   bool IsLineBreak() const {
38     return TextType() == NGTextType::kForcedLineBreak;
39   }
40   // True if this is not for painting; i.e., a forced line break, a tabulation,
41   // or a soft-wrap opportunity.
IsFlowControl()42   bool IsFlowControl() const {
43     return IsLineBreak() || TextType() == NGTextType::kFlowControl;
44   }
45   // True if this is an ellpisis generated by `text-overflow: ellipsis`.
IsEllipsis()46   bool IsEllipsis() const {
47     return StyleVariant() == NGStyleVariant::kEllipsis;
48   }
49 
IsSymbolMarker()50   bool IsSymbolMarker() const {
51     return TextType() == NGTextType::kSymbolMarker;
52   }
53 
TextContent()54   const String& TextContent() const { return text_; }
55 
56   // ShapeResult may be nullptr if |IsFlowControl()|.
TextShapeResult()57   const ShapeResultView* TextShapeResult() const { return shape_result_.get(); }
58 
59   // Start/end offset to the text of the block container.
TextOffset()60   const NGTextOffset& TextOffset() const { return text_offset_; }
StartOffset()61   unsigned StartOffset() const { return text_offset_.start; }
EndOffset()62   unsigned EndOffset() const { return text_offset_.end; }
TextLength()63   unsigned TextLength() const { return text_offset_.Length(); }
Text()64   StringView Text() const {
65     return StringView(text_, text_offset_.start, TextLength());
66   }
67 
GetWritingMode()68   WritingMode GetWritingMode() const { return Style().GetWritingMode(); }
IsHorizontal()69   bool IsHorizontal() const {
70     return IsHorizontalWritingMode(GetWritingMode());
71   }
72 
73   // Compute the inline position from text offset, in logical coordinate
74   // relative to this fragment.
75   LayoutUnit InlinePositionForOffset(unsigned offset) const;
76 
77   // The layout box of text in (start, end) range in local coordinate.
78   // Start and end offsets must be between StartOffset() and EndOffset().
79   PhysicalRect LocalRect(unsigned start_offset, unsigned end_offset) const;
80   using NGPhysicalFragment::LocalRect;
81 
82   // The visual bounding box that includes glpyh bounding box and CSS
83   // properties, in local coordinates.
84   PhysicalRect SelfInkOverflow() const;
85 
86   scoped_refptr<const NGPhysicalTextFragment> CloneAsHiddenForPaint() const;
87 
88   scoped_refptr<const NGPhysicalFragment> CloneWithoutOffset() const;
89 
PaintInfo()90   NGTextFragmentPaintInfo PaintInfo() const {
91     return NGTextFragmentPaintInfo{text_, StartOffset(), EndOffset(),
92                                    TextShapeResult()};
93   }
94 
95   // Returns the text offset in the fragment placed closest to the given point.
96   unsigned TextOffsetForPoint(const PhysicalOffset&) const;
97 
98   UBiDiLevel BidiLevel() const;
ResolvedDirection()99   TextDirection ResolvedDirection() const {
100     return static_cast<TextDirection>(base_or_resolved_direction_);
101   }
102 
103   // Compute line-relative coordinates for given offsets, this is not
104   // flow-relative:
105   // https://drafts.csswg.org/css-writing-modes-3/#line-directions
106   std::pair<LayoutUnit, LayoutUnit> LineLeftAndRightForOffsets(
107       unsigned start_offset,
108       unsigned end_offset) const;
109 
110  private:
111   LayoutUnit InlinePositionForOffset(unsigned offset,
112                                      LayoutUnit (*round)(float),
113                                      AdjustMidCluster) const;
114 
115   void ComputeSelfInkOverflow() const;
116 
117   // The text of NGInlineNode; i.e., of a parent block. The text for this
118   // fragment is a substring(start_offset_, end_offset_) of this string.
119   const String text_;
120 
121   // Start and end offset of the parent block text.
122   const NGTextOffset text_offset_;
123   const scoped_refptr<const ShapeResultView> shape_result_;
124 
125   // Fragments are immutable but allow certain expensive data, specifically ink
126   // overflow, to be cached as long as it is guaranteed to always recompute to
127   // the same value.
128   mutable std::unique_ptr<NGSingleInkOverflow> ink_overflow_;
129 
130   friend class NGTextFragmentBuilder;
131 };
132 
133 template <>
134 struct DowncastTraits<NGPhysicalTextFragment> {
135   static bool AllowFrom(const NGPhysicalFragment& fragment) {
136     return fragment.IsText();
137   }
138 };
139 
140 }  // namespace blink
141 
142 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_PHYSICAL_TEXT_FRAGMENT_H_
143