blob: 4ac2468f3519c85af51e45a1632b911ab7e56360 [file] [log] [blame]
// 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 NGInlineNode_h
#define NGInlineNode_h
#include "core/CoreExport.h"
#include "core/layout/ng/ng_layout_input_node.h"
#include "platform/fonts/FontFallbackPriority.h"
#include "platform/fonts/shaping/ShapeResult.h"
#include "platform/heap/Handle.h"
#include "platform/text/TextDirection.h"
#include "wtf/text/WTFString.h"
#include <unicode/ubidi.h>
#include <unicode/uscript.h>
namespace blink {
class ComputedStyle;
class LayoutBlockFlow;
class LayoutObject;
class LayoutUnit;
class NGConstraintSpace;
class NGLayoutInlineItem;
class NGLayoutInlineItemRange;
class NGLayoutInlineItemsBuilder;
class NGLineBuilder;
class NGPhysicalFragment;
// Represents an inline node to be laid out.
class CORE_EXPORT NGInlineNode : public NGLayoutInputNode {
public:
NGInlineNode(LayoutObject* start_inline, const ComputedStyle* block_style);
~NGInlineNode() override;
RefPtr<NGPhysicalFragment> Layout(NGConstraintSpace*) override;
void LayoutInline(NGConstraintSpace*, NGLineBuilder*);
NGInlineNode* NextSibling() override;
LayoutObject* GetLayoutObject() override;
// Prepare inline and text content for layout. Must be called before
// calling the Layout method.
void PrepareLayout();
String Text(unsigned start_offset, unsigned end_offset) const {
return text_content_.substring(start_offset, end_offset);
}
Vector<NGLayoutInlineItem>& Items() { return items_; }
NGLayoutInlineItemRange Items(unsigned start_index, unsigned end_index);
LayoutBlockFlow* GetLayoutBlockFlow() const;
void GetLayoutTextOffsets(Vector<unsigned, 32>*);
bool IsBidiEnabled() const { return is_bidi_enabled_; }
DECLARE_VIRTUAL_TRACE();
protected:
NGInlineNode(); // This constructor is only for testing.
void CollectInlines(LayoutObject* start, LayoutObject* last);
void CollectInlines(LayoutObject* start,
LayoutObject* last,
NGLayoutInlineItemsBuilder*);
void SegmentText();
void ShapeText();
LayoutObject* start_inline_;
LayoutObject* last_inline_;
RefPtr<const ComputedStyle> block_style_;
Member<NGInlineNode> next_sibling_;
// Text content for all inline items represented by a single NGInlineNode
// instance. Encoded either as UTF-16 or latin-1 depending on content.
String text_content_;
Vector<NGLayoutInlineItem> items_;
// TODO(kojii): This should move to somewhere else when we move PrepareLayout
// to the correct place.
bool is_bidi_enabled_ = false;
};
// Class representing a single text node or styled inline element with text
// content segmented by style, text direction, sideways rotation, font fallback
// priority (text, symbol, emoji, etc) and script (but not by font).
// In this representation TextNodes are merged up into their parent inline
// element where possible.
class NGLayoutInlineItem {
public:
NGLayoutInlineItem(unsigned start,
unsigned end,
const ComputedStyle* style,
LayoutObject* layout_object = nullptr)
: start_offset_(start),
end_offset_(end),
bidi_level_(UBIDI_LTR),
script_(USCRIPT_INVALID_CODE),
fallback_priority_(FontFallbackPriority::Invalid),
rotate_sideways_(false),
style_(style),
layout_object_(layout_object) {
DCHECK(end >= start);
}
unsigned StartOffset() const { return start_offset_; }
unsigned EndOffset() const { return end_offset_; }
TextDirection Direction() const {
return bidi_level_ & 1 ? TextDirection::kRtl : TextDirection::kLtr;
}
UBiDiLevel BidiLevel() const { return bidi_level_; }
UScriptCode Script() const { return script_; }
const ComputedStyle* Style() const { return style_; }
LayoutObject* GetLayoutObject() const { return layout_object_; }
void SetEndOffset(unsigned);
LayoutUnit InlineSize() const;
static void Split(Vector<NGLayoutInlineItem>&,
unsigned index,
unsigned offset);
static unsigned SetBidiLevel(Vector<NGLayoutInlineItem>&,
unsigned index,
unsigned end_offset,
UBiDiLevel);
private:
unsigned start_offset_;
unsigned end_offset_;
UBiDiLevel bidi_level_;
UScriptCode script_;
FontFallbackPriority fallback_priority_;
bool rotate_sideways_;
const ComputedStyle* style_;
Vector<RefPtr<const ShapeResult>> shape_results_;
LayoutObject* layout_object_;
friend class NGInlineNode;
};
DEFINE_TYPE_CASTS(NGInlineNode,
NGLayoutInputNode,
node,
node->Type() == NGLayoutInputNode::kLegacyInline,
node.Type() == NGLayoutInputNode::kLegacyInline);
// A vector-like object that points to a subset of an array of
// |NGLayoutInlineItem|.
// The source vector must keep alive and must not resize while this object
// is alive.
class NGLayoutInlineItemRange {
STACK_ALLOCATED();
public:
NGLayoutInlineItemRange(Vector<NGLayoutInlineItem>*,
unsigned start_index,
unsigned end_index);
unsigned StartIndex() const { return start_index_; }
unsigned EndIndex() const { return start_index_ + size_; }
unsigned Size() const { return size_; }
NGLayoutInlineItem& operator[](unsigned index) {
RELEASE_ASSERT(index < size_);
return start_item_[index];
}
const NGLayoutInlineItem& operator[](unsigned index) const {
RELEASE_ASSERT(index < size_);
return start_item_[index];
}
using iterator = NGLayoutInlineItem*;
using const_iterator = const NGLayoutInlineItem*;
iterator begin() { return start_item_; }
iterator end() { return start_item_ + size_; }
const_iterator begin() const { return start_item_; }
const_iterator end() const { return start_item_ + size_; }
private:
NGLayoutInlineItem* start_item_;
unsigned size_;
unsigned start_index_;
};
} // namespace blink
#endif // NGInlineNode_h