summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/layout/ng/list/list_marker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/core/layout/ng/list/list_marker.cc')
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/list_marker.cc256
1 files changed, 256 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/list/list_marker.cc b/chromium/third_party/blink/renderer/core/layout/ng/list/list_marker.cc
new file mode 100644
index 00000000000..b2533d42d7a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/list/list_marker.cc
@@ -0,0 +1,256 @@
+// Copyright 2020 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.
+
+#include "third_party/blink/renderer/core/layout/ng/list/list_marker.h"
+
+#include "third_party/blink/renderer/core/layout/layout_image_resource_style_image.h"
+#include "third_party/blink/renderer/core/layout/list_marker_text.h"
+#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.h"
+#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.h"
+#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.h"
+
+namespace blink {
+
+ListMarker::ListMarker() : marker_text_type_(kNotText) {}
+
+const ListMarker* ListMarker::Get(const LayoutObject* object) {
+ if (!object)
+ return nullptr;
+ if (object->IsLayoutNGOutsideListMarker())
+ return &ToLayoutNGOutsideListMarker(object)->Marker();
+ if (object->IsLayoutNGInsideListMarker())
+ return &ToLayoutNGInsideListMarker(object)->Marker();
+ return nullptr;
+}
+
+ListMarker* ListMarker::Get(LayoutObject* object) {
+ return const_cast<ListMarker*>(
+ ListMarker::Get(static_cast<const LayoutObject*>(object)));
+}
+
+// If the value of ListStyleType changed, we need to the marker text has been
+// updated.
+void ListMarker::ListStyleTypeChanged(LayoutObject& marker) {
+ if (marker_text_type_ == kNotText || marker_text_type_ == kUnresolved)
+ return;
+
+ marker_text_type_ = kUnresolved;
+ marker.SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
+ layout_invalidation_reason::kListStyleTypeChange);
+}
+
+void ListMarker::OrdinalValueChanged(LayoutObject& marker) {
+ if (marker_text_type_ == kOrdinalValue) {
+ marker_text_type_ = kUnresolved;
+ marker.SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
+ layout_invalidation_reason::kListValueChange);
+ }
+}
+
+void ListMarker::UpdateMarkerText(LayoutObject& marker, LayoutText* text) {
+ DCHECK(text);
+ DCHECK_EQ(marker_text_type_, kUnresolved);
+ StringBuilder marker_text_builder;
+ marker_text_type_ = MarkerText(marker, &marker_text_builder, kWithSuffix);
+ text->SetTextIfNeeded(marker_text_builder.ToString().ReleaseImpl());
+ DCHECK_NE(marker_text_type_, kNotText);
+ DCHECK_NE(marker_text_type_, kUnresolved);
+}
+
+void ListMarker::UpdateMarkerText(LayoutObject& marker) {
+ UpdateMarkerText(marker, ToLayoutText(marker.SlowFirstChild()));
+}
+
+LayoutNGListItem* ListMarker::ListItem(const LayoutObject& marker) {
+ return ToLayoutNGListItem(marker.GetNode()->parentNode()->GetLayoutObject());
+}
+
+ListMarker::MarkerTextType ListMarker::MarkerText(
+ const LayoutObject& marker,
+ StringBuilder* text,
+ MarkerTextFormat format) const {
+ if (IsMarkerImage(marker)) {
+ if (format == kWithSuffix)
+ text->Append(' ');
+ return kNotText;
+ }
+
+ LayoutNGListItem* list_item = ListItem(marker);
+ const ComputedStyle& style = list_item->StyleRef();
+ switch (style.ListStyleType()) {
+ case EListStyleType::kNone:
+ return kNotText;
+ case EListStyleType::kString: {
+ text->Append(style.ListStyleStringValue());
+ return kStatic;
+ }
+ case EListStyleType::kDisc:
+ case EListStyleType::kCircle:
+ case EListStyleType::kSquare:
+ // value is ignored for these types
+ text->Append(list_marker_text::GetText(style.ListStyleType(), 0));
+ if (format == kWithSuffix)
+ text->Append(' ');
+ return kSymbolValue;
+ case EListStyleType::kArabicIndic:
+ case EListStyleType::kArmenian:
+ case EListStyleType::kBengali:
+ case EListStyleType::kCambodian:
+ case EListStyleType::kCjkIdeographic:
+ case EListStyleType::kCjkEarthlyBranch:
+ case EListStyleType::kCjkHeavenlyStem:
+ case EListStyleType::kDecimalLeadingZero:
+ case EListStyleType::kDecimal:
+ case EListStyleType::kDevanagari:
+ case EListStyleType::kEthiopicHalehame:
+ case EListStyleType::kEthiopicHalehameAm:
+ case EListStyleType::kEthiopicHalehameTiEr:
+ case EListStyleType::kEthiopicHalehameTiEt:
+ case EListStyleType::kGeorgian:
+ case EListStyleType::kGujarati:
+ case EListStyleType::kGurmukhi:
+ case EListStyleType::kHangul:
+ case EListStyleType::kHangulConsonant:
+ case EListStyleType::kHebrew:
+ case EListStyleType::kHiragana:
+ case EListStyleType::kHiraganaIroha:
+ case EListStyleType::kKannada:
+ case EListStyleType::kKatakana:
+ case EListStyleType::kKatakanaIroha:
+ case EListStyleType::kKhmer:
+ case EListStyleType::kKoreanHangulFormal:
+ case EListStyleType::kKoreanHanjaFormal:
+ case EListStyleType::kKoreanHanjaInformal:
+ case EListStyleType::kLao:
+ case EListStyleType::kLowerAlpha:
+ case EListStyleType::kLowerArmenian:
+ case EListStyleType::kLowerGreek:
+ case EListStyleType::kLowerLatin:
+ case EListStyleType::kLowerRoman:
+ case EListStyleType::kMalayalam:
+ case EListStyleType::kMongolian:
+ case EListStyleType::kMyanmar:
+ case EListStyleType::kOriya:
+ case EListStyleType::kPersian:
+ case EListStyleType::kSimpChineseFormal:
+ case EListStyleType::kSimpChineseInformal:
+ case EListStyleType::kTelugu:
+ case EListStyleType::kThai:
+ case EListStyleType::kTibetan:
+ case EListStyleType::kTradChineseFormal:
+ case EListStyleType::kTradChineseInformal:
+ case EListStyleType::kUpperAlpha:
+ case EListStyleType::kUpperArmenian:
+ case EListStyleType::kUpperLatin:
+ case EListStyleType::kUpperRoman:
+ case EListStyleType::kUrdu: {
+ int value = list_item->Value();
+ text->Append(list_marker_text::GetText(style.ListStyleType(), value));
+ if (format == kWithSuffix) {
+ text->Append(list_marker_text::Suffix(style.ListStyleType(), value));
+ text->Append(' ');
+ }
+ return kOrdinalValue;
+ }
+ }
+ NOTREACHED();
+ return kStatic;
+}
+
+String ListMarker::MarkerTextWithSuffix(const LayoutObject& marker) const {
+ StringBuilder text;
+ MarkerText(marker, &text, kWithSuffix);
+ return text.ToString();
+}
+
+String ListMarker::MarkerTextWithoutSuffix(const LayoutObject& marker) const {
+ StringBuilder text;
+ MarkerText(marker, &text, kWithoutSuffix);
+ return text.ToString();
+}
+
+String ListMarker::TextAlternative(const LayoutObject& marker) const {
+ // For accessibility, return the marker string in the logical order even in
+ // RTL, reflecting speech order.
+ return MarkerTextWithSuffix(marker);
+}
+
+void ListMarker::UpdateMarkerContentIfNeeded(LayoutObject& marker) {
+ LayoutNGListItem* list_item = ListItem(marker);
+
+ if (!marker.StyleRef().ContentBehavesAsNormal()) {
+ marker_text_type_ = kNotText;
+ return;
+ }
+
+ // There should be at most one child.
+ LayoutObject* child = marker.SlowFirstChild();
+ DCHECK(!child || !child->NextSibling());
+
+ if (IsMarkerImage(marker)) {
+ StyleImage* list_style_image = list_item->StyleRef().ListStyleImage();
+ if (child) {
+ // If the url of `list-style-image` changed, create a new LayoutImage.
+ if (!child->IsLayoutImage() ||
+ ToLayoutImage(child)->ImageResource()->ImagePtr() !=
+ list_style_image->Data()) {
+ child->Destroy();
+ child = nullptr;
+ }
+ }
+ if (!child) {
+ LayoutNGListMarkerImage* image =
+ LayoutNGListMarkerImage::CreateAnonymous(&marker.GetDocument());
+ scoped_refptr<ComputedStyle> image_style =
+ ComputedStyle::CreateAnonymousStyleWithDisplay(marker.StyleRef(),
+ EDisplay::kInline);
+ image->SetStyle(image_style);
+ image->SetImageResource(
+ MakeGarbageCollected<LayoutImageResourceStyleImage>(
+ list_style_image));
+ image->SetIsGeneratedContent();
+ marker.AddChild(image);
+ }
+ marker_text_type_ = kNotText;
+ return;
+ }
+
+ if (list_item->StyleRef().ListStyleType() == EListStyleType::kNone) {
+ marker_text_type_ = kNotText;
+ return;
+ }
+
+ // Create a LayoutText in it.
+ LayoutText* text = nullptr;
+ // |text_style| should be as same as style propagated in
+ // |LayoutObject::PropagateStyleToAnonymousChildren()| to avoid unexpected
+ // full layout due by style difference. See http://crbug.com/980399
+ scoped_refptr<ComputedStyle> text_style =
+ ComputedStyle::CreateAnonymousStyleWithDisplay(
+ marker.StyleRef(), marker.StyleRef().Display());
+ if (child) {
+ if (child->IsText()) {
+ text = ToLayoutText(child);
+ text->SetStyle(text_style);
+ } else {
+ child->Destroy();
+ child = nullptr;
+ }
+ }
+ if (!child) {
+ text = LayoutText::CreateEmptyAnonymous(marker.GetDocument(), text_style,
+ LegacyLayout::kAuto);
+ marker.AddChild(text);
+ marker_text_type_ = kUnresolved;
+ }
+}
+
+LayoutObject* ListMarker::SymbolMarkerLayoutText(
+ const LayoutObject& marker) const {
+ if (marker_text_type_ != kSymbolValue)
+ return nullptr;
+ return marker.SlowFirstChild();
+}
+
+} // namespace blink