blob: 252c7e8b5ff537aa127cc575492c47751bc376da [file] [log] [blame]
// Copyright 2017 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 NGInlineItem_h
#define NGInlineItem_h
#include "core/CoreExport.h"
#include "platform/LayoutUnit.h"
#include "platform/fonts/FontFallbackPriority.h"
#include "platform/fonts/SimpleFontData.h"
#include "platform/fonts/shaping/ShapeResult.h"
#include "platform/text/TextDirection.h"
#include "platform/wtf/HashSet.h"
#include <unicode/ubidi.h>
namespace blink {
class ComputedStyle;
class LayoutObject;
// 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 CORE_EXPORT NGInlineItem {
public:
enum NGInlineItemType {
kText,
kControl,
kAtomicInline,
kOpenTag,
kCloseTag,
kFloating,
kOutOfFlowPositioned,
kListMarker,
kBidiControl
// When adding new values, make sure the bit size of |type_| is large
// enough to store.
};
// Whether pre- and post-context should be used for shaping.
enum NGLayoutInlineShapeOptions {
kNoContext = 0,
kPreContext = 1,
kPostContext = 2
};
// The constructor and destructor can't be implicit or inlined, because they
// require full definition of ComputedStyle.
NGInlineItem(NGInlineItemType type,
unsigned start,
unsigned end,
const ComputedStyle* style = nullptr,
LayoutObject* layout_object = nullptr);
~NGInlineItem();
NGInlineItemType Type() const { return static_cast<NGInlineItemType>(type_); }
const char* NGInlineItemTypeToString(int val) const;
const ShapeResult* TextShapeResult() const { return shape_result_.get(); }
NGLayoutInlineShapeOptions ShapeOptions() const {
return static_cast<NGLayoutInlineShapeOptions>(shape_options_);
}
// If this item is "empty" for the purpose of empty block calculation.
bool IsEmptyItem() const { return is_empty_item_; }
unsigned StartOffset() const { return start_offset_; }
unsigned EndOffset() const { return end_offset_; }
unsigned Length() const { return end_offset_ - start_offset_; }
TextDirection Direction() const { return DirectionFromLevel(BidiLevel()); }
UBiDiLevel BidiLevel() const { return static_cast<UBiDiLevel>(bidi_level_); }
// Resolved bidi level for the reordering algorithm. Certain items have
// artificial bidi level for the reordering algorithm without affecting its
// direction.
UBiDiLevel BidiLevelForReorder() const;
UScriptCode GetScript() const { return script_; }
const ComputedStyle* Style() const { return style_.get(); }
LayoutObject* GetLayoutObject() const { return layout_object_; }
void SetOffset(unsigned start, unsigned end);
void SetEndOffset(unsigned);
LayoutUnit InlineSize() const;
LayoutUnit InlineSize(unsigned start, unsigned end) const;
bool HasStartEdge() const;
bool HasEndEdge() const;
static void Split(Vector<NGInlineItem>&, unsigned index, unsigned offset);
static unsigned SetBidiLevel(Vector<NGInlineItem>&,
unsigned index,
unsigned end_offset,
UBiDiLevel);
void AssertOffset(unsigned offset) const;
void AssertEndOffset(unsigned offset) const;
String ToString() const;
private:
unsigned start_offset_;
unsigned end_offset_;
UScriptCode script_;
scoped_refptr<const ShapeResult> shape_result_;
scoped_refptr<const ComputedStyle> style_;
LayoutObject* layout_object_;
unsigned type_ : 4;
unsigned bidi_level_ : 8; // UBiDiLevel is defined as uint8_t.
unsigned shape_options_ : 2;
unsigned is_empty_item_ : 1;
friend class NGInlineNode;
};
inline void NGInlineItem::AssertOffset(unsigned offset) const {
DCHECK((offset >= start_offset_ && offset < end_offset_) ||
(offset == start_offset_ && start_offset_ == end_offset_));
}
inline void NGInlineItem::AssertEndOffset(unsigned offset) const {
DCHECK_GE(offset, start_offset_);
DCHECK_LE(offset, end_offset_);
}
// A vector-like object that points to a subset of an array of |NGInlineItem|.
// The source vector must keep alive and must not resize while this object
// is alive.
class NGInlineItemRange {
STACK_ALLOCATED();
public:
NGInlineItemRange(Vector<NGInlineItem>*,
unsigned start_index,
unsigned end_index);
unsigned StartIndex() const { return start_index_; }
unsigned EndIndex() const { return start_index_ + size_; }
unsigned Size() const { return size_; }
NGInlineItem& operator[](unsigned index) {
CHECK_LT(index, size_);
return start_item_[index];
}
const NGInlineItem& operator[](unsigned index) const {
CHECK_LT(index, size_);
return start_item_[index];
}
using iterator = NGInlineItem*;
using const_iterator = const NGInlineItem*;
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:
NGInlineItem* start_item_;
unsigned size_;
unsigned start_index_;
};
} // namespace blink
#endif // NGInlineItem_h