blob: 35c58b45412f4ada445a66c03581555a1c113be1 [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 NGInlineItemsBuilder_h
#define NGInlineItemsBuilder_h
#include "core/CoreExport.h"
#include "core/layout/ng/inline/empty_offset_mapping_builder.h"
#include "core/layout/ng/inline/ng_inline_node.h"
#include "core/layout/ng/inline/ng_offset_mapping_builder.h"
#include "platform/wtf/Allocator.h"
#include "platform/wtf/Vector.h"
#include "platform/wtf/text/StringBuilder.h"
#include "platform/wtf/text/WTFString.h"
namespace blink {
class ComputedStyle;
class LayoutObject;
class NGInlineItem;
// NGInlineItemsBuilder builds a string and a list of NGInlineItem from inlines.
//
// When appending, spaces are collapsed according to CSS Text, The white space
// processing rules
// https://drafts.csswg.org/css-text-3/#white-space-rules
//
// By calling EnterInline/ExitInline, it inserts bidirectional control
// characters as defined in:
// https://drafts.csswg.org/css-writing-modes-3/#bidi-control-codes-injection-table
//
// NGInlineItemsBuilder may optionally take an NGOffsetMappingBuilder template
// parameter to construct the white-space collapsed offset mapping, which maps
// offsets in the concatenation of all appended strings and characters to
// offsets in |text_|.
// See https://goo.gl/CJbxky for more details about offset mapping.
template <typename OffsetMappingBuilder>
class CORE_TEMPLATE_CLASS_EXPORT NGInlineItemsBuilderTemplate {
STACK_ALLOCATED();
public:
explicit NGInlineItemsBuilderTemplate(Vector<NGInlineItem>* items)
: items_(items) {}
~NGInlineItemsBuilderTemplate();
String ToString();
void SetIsSVGText(bool value) { is_svgtext_ = value; }
// Returns whether the items contain any Bidi controls.
bool HasBidiControls() const { return has_bidi_controls_; }
// Returns if the inline node has no content. For example:
// <span></span> or <span><float></float></span>.
bool IsEmptyInline() const { return is_empty_inline_; }
// Append a string.
// When appending, spaces are collapsed according to CSS Text, The white space
// processing rules
// https://drafts.csswg.org/css-text-3/#white-space-rules
// @param style The style for the string.
// If a nullptr, it should skip shaping. Atomic inlines and bidi controls use
// this.
// @param LayoutObject The LayoutObject for the string.
// If a nullptr, it does not generate BidiRun. Bidi controls use this.
void Append(const String&, const ComputedStyle*, LayoutObject* = nullptr);
// Append a character.
// Currently this function is for adding control characters such as
// objectReplacementCharacter, and does not support all space collapsing logic
// as its String version does.
// See the String version for using nullptr for ComputedStyle and
// LayoutObject.
void Append(NGInlineItem::NGInlineItemType,
UChar,
const ComputedStyle* = nullptr,
LayoutObject* = nullptr);
// Append a character.
// The character is opaque to space collapsing; i.e., spaces before this
// character and after this character can collapse as if this character does
// not exist.
void AppendOpaque(NGInlineItem::NGInlineItemType, UChar);
// Append a non-character item that is opaque to space collapsing.
void AppendOpaque(NGInlineItem::NGInlineItemType,
const ComputedStyle* = nullptr,
LayoutObject* = nullptr);
// Append a Bidi control character, for LTR or RTL depends on the style.
void AppendBidiControl(const ComputedStyle*, UChar ltr, UChar rtl);
void EnterBlock(const ComputedStyle*);
void ExitBlock();
void EnterInline(LayoutObject*);
void ExitInline(LayoutObject*);
OffsetMappingBuilder& GetOffsetMappingBuilder() { return mapping_builder_; }
private:
Vector<NGInlineItem>* items_;
StringBuilder text_;
OffsetMappingBuilder mapping_builder_;
typedef struct OnExitNode {
LayoutObject* node;
UChar character;
} OnExitNode;
Vector<OnExitNode> exits_;
enum class CollapsibleSpace { kNone, kSpace, kNewline };
CollapsibleSpace last_collapsible_space_ = CollapsibleSpace::kSpace;
bool is_svgtext_ = false;
bool has_bidi_controls_ = false;
bool is_empty_inline_ = true;
void AppendWithWhiteSpaceCollapsing(const String&,
unsigned start,
unsigned end,
const ComputedStyle*,
LayoutObject*);
void AppendWithoutWhiteSpaceCollapsing(const String&,
const ComputedStyle*,
LayoutObject*);
void AppendWithPreservingNewlines(const String&,
const ComputedStyle*,
LayoutObject*);
void AppendForcedBreak(const ComputedStyle*, LayoutObject*);
void RemoveTrailingCollapsibleSpaceIfExists();
void RemoveTrailingCollapsibleSpace(unsigned);
void RemoveTrailingCollapsibleNewlineIfNeeded(const String&,
unsigned,
const ComputedStyle*);
void Enter(LayoutObject*, UChar);
void Exit(LayoutObject*);
};
extern template class CORE_EXTERN_TEMPLATE_EXPORT
NGInlineItemsBuilderTemplate<EmptyOffsetMappingBuilder>;
extern template class CORE_EXTERN_TEMPLATE_EXPORT
NGInlineItemsBuilderTemplate<NGOffsetMappingBuilder>;
using NGInlineItemsBuilder =
NGInlineItemsBuilderTemplate<EmptyOffsetMappingBuilder>;
using NGInlineItemsBuilderForOffsetMapping =
NGInlineItemsBuilderTemplate<NGOffsetMappingBuilder>;
} // namespace blink
#endif // NGInlineItemsBuilder_h