| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef NGPhysicalTextFragment_h |
| #define NGPhysicalTextFragment_h |
| |
| #include "third_party/blink/renderer/core/core_export.h" |
| #include "third_party/blink/renderer/core/layout/ng/inline/ng_text_end_effect.h" |
| #include "third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h" |
| #include "third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h" |
| #include "third_party/blink/renderer/platform/fonts/ng_text_fragment_paint_info.h" |
| #include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h" |
| #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h" |
| #include "third_party/blink/renderer/platform/wtf/casting.h" |
| #include "third_party/blink/renderer/platform/wtf/text/string_view.h" |
| #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" |
| |
| namespace blink { |
| |
| class NGTextFragmentBuilder; |
| class NGPhysicalTextFragment; |
| struct PhysicalRect; |
| |
| enum class AdjustMidCluster; |
| |
| class CORE_EXPORT NGPhysicalTextFragment final : public NGPhysicalFragment { |
| public: |
| enum NGTextType { |
| // |text_| holds |NGNodeInlineData::text_content_|. |
| kNormalText, |
| kForcedLineBreak, |
| // Flow controls are not to be painted. In particular, a tabulation |
| // character and a soft-wrap opportunity. |
| kFlowControl, |
| kSymbolMarker, |
| // |text_| holds generated contents instead of |text_content_| in |
| // |NGNodeInlineData|, e.g. hyphen, and ellipsis. |
| // Note: Contents generated by CSS pseudo element, e.g. ::before, ::after, |
| // are not classified to this. See IsGeneratedText() for them. |
| kGeneratedText, |
| // When adding new values, make sure the bit size of |sub_type_| is large |
| // enough to store. |
| }; |
| |
| NGPhysicalTextFragment(NGTextFragmentBuilder*); |
| |
| NGTextType TextType() const { return static_cast<NGTextType>(sub_type_); } |
| // Returns true if the text is generated (from, e.g., list marker, |
| // pseudo-element, ...) instead of from a DOM text node. |
| bool IsGeneratedText() const { return is_generated_text_; } |
| // True if this is a forced line break. |
| bool IsLineBreak() const { return TextType() == kForcedLineBreak; } |
| // True if this is not for painting; i.e., a forced line break, a tabulation, |
| // or a soft-wrap opportunity. |
| bool IsFlowControl() const { |
| return IsLineBreak() || TextType() == kFlowControl; |
| } |
| // True if this is an ellpisis generated by `text-overflow: ellipsis`. |
| bool IsEllipsis() const { |
| return StyleVariant() == NGStyleVariant::kEllipsis; |
| } |
| |
| bool IsSymbolMarker() const { return TextType() == kSymbolMarker; } |
| |
| unsigned TextLength() const { return end_offset_ - start_offset_; } |
| StringView Text() const { |
| return StringView(text_, start_offset_, TextLength()); |
| } |
| const String& TextContent() const { return text_; } |
| |
| // ShapeResult may be nullptr if |IsFlowControl()|. |
| const ShapeResultView* TextShapeResult() const { return shape_result_.get(); } |
| |
| // Start/end offset to the text of the block container. |
| unsigned StartOffset() const { return start_offset_; } |
| unsigned EndOffset() const { return end_offset_; } |
| |
| WritingMode GetWritingMode() const { return Style().GetWritingMode(); } |
| bool IsHorizontal() const { |
| return IsHorizontalWritingMode(GetWritingMode()); |
| } |
| |
| // Compute the inline position from text offset, in logical coordinate |
| // relative to this fragment. |
| LayoutUnit InlinePositionForOffset(unsigned offset) const; |
| |
| // The layout box of text in (start, end) range in local coordinate. |
| // Start and end offsets must be between StartOffset() and EndOffset(). |
| PhysicalRect LocalRect(unsigned start_offset, unsigned end_offset) const; |
| using NGPhysicalFragment::LocalRect; |
| |
| // The visual bounding box that includes glpyh bounding box and CSS |
| // properties, in local coordinates. |
| PhysicalRect SelfInkOverflow() const; |
| |
| scoped_refptr<const NGPhysicalTextFragment> CloneAsHiddenForPaint() const; |
| |
| // Create a new fragment that has part of the text of this fragment. |
| // All other properties are the same as this fragment. |
| scoped_refptr<const NGPhysicalTextFragment> TrimText( |
| unsigned start_offset, |
| unsigned end_offset) const; |
| |
| scoped_refptr<const NGPhysicalFragment> CloneWithoutOffset() const; |
| |
| NGTextFragmentPaintInfo PaintInfo() const { |
| return NGTextFragmentPaintInfo{text_, StartOffset(), EndOffset(), |
| TextShapeResult()}; |
| } |
| |
| // Returns the text offset in the fragment placed closest to the given point. |
| unsigned TextOffsetForPoint(const PhysicalOffset&) const; |
| |
| UBiDiLevel BidiLevel() const; |
| TextDirection ResolvedDirection() const; |
| |
| // Compute line-relative coordinates for given offsets, this is not |
| // flow-relative: |
| // https://drafts.csswg.org/css-writing-modes-3/#line-directions |
| std::pair<LayoutUnit, LayoutUnit> LineLeftAndRightForOffsets( |
| unsigned start_offset, |
| unsigned end_offset) const; |
| |
| private: |
| // For use by TrimText only |
| NGPhysicalTextFragment(const NGPhysicalTextFragment& source, |
| unsigned start_offset, |
| unsigned end_offset, |
| scoped_refptr<const ShapeResultView> shape_result); |
| |
| LayoutUnit InlinePositionForOffset(unsigned offset, |
| LayoutUnit (*round)(float), |
| AdjustMidCluster) const; |
| |
| void ComputeSelfInkOverflow() const; |
| |
| // The text of NGInlineNode; i.e., of a parent block. The text for this |
| // fragment is a substring(start_offset_, end_offset_) of this string. |
| const String text_; |
| |
| // Start and end offset of the parent block text. |
| const unsigned start_offset_; |
| const unsigned end_offset_; |
| const scoped_refptr<const ShapeResultView> shape_result_; |
| |
| // Fragments are immutable but allow certain expensive data, specifically ink |
| // overflow, to be cached as long as it is guaranteed to always recompute to |
| // the same value. |
| mutable std::unique_ptr<NGInkOverflow> ink_overflow_; |
| |
| friend class NGTextFragmentBuilder; |
| }; |
| |
| template <> |
| struct DowncastTraits<NGPhysicalTextFragment> { |
| static bool AllowFrom(const NGPhysicalFragment& fragment) { |
| return fragment.IsText(); |
| } |
| }; |
| |
| } // namespace blink |
| |
| #endif // NGPhysicalTextFragment_h |