Commit 267cec87 authored by Kent Tamura's avatar Kent Tamura Committed by Commit Bot

TextControl NG: Prepare to implement ::placeholder layout for INPUT elements

A textfield INPUT element has one or two block children;
 - Optional ::placeholder
 - TextControlInnerEditorElement or
   ::-webkit-textfield-decoration-container

We need to lay out the latter first because the former's baseline
should be aligned to the baseline of the latter, and the former
should be painted earlier than the latter.

This CL is a preparation to implement it.
 * NGContainerFragmentBuilder::AddChildInternal() inserts the fragment
   for ::placeholder before another child.
 * NGBlockLayoutAlgorithm::Layout() lays ::placeholder out after other
   children.

This CL has no behavior changes.

Bug: 1040826
Change-Id: Ib8768194c2a7e86cb162cb4470eac9881a22d11d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2503379
Commit-Queue: Kent Tamura <tkent@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#822531}
parent 49a2651a
...@@ -609,6 +609,7 @@ inline scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::Layout( ...@@ -609,6 +609,7 @@ inline scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::Layout(
child_iterator = NGBlockChildIterator(NGBlockNode(nullptr), nullptr); child_iterator = NGBlockChildIterator(NGBlockNode(nullptr), nullptr);
NGLayoutInputNode ruby_text_child(nullptr); NGLayoutInputNode ruby_text_child(nullptr);
NGBlockNode placeholder_child(nullptr);
for (auto entry = child_iterator.NextChild(); for (auto entry = child_iterator.NextChild();
NGLayoutInputNode child = entry.node; NGLayoutInputNode child = entry.node;
entry = child_iterator.NextChild(previous_inline_break_token.get())) { entry = child_iterator.NextChild(previous_inline_break_token.get())) {
...@@ -653,8 +654,7 @@ inline scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::Layout( ...@@ -653,8 +654,7 @@ inline scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::Layout(
} else if (IsRubyText(child)) { } else if (IsRubyText(child)) {
ruby_text_child = child; ruby_text_child = child;
} else if (child.IsTextControlPlaceholder()) { } else if (child.IsTextControlPlaceholder()) {
HandleTextControlPlaceholder(To<NGBlockNode>(child), placeholder_child = To<NGBlockNode>(child);
previous_inflow_position);
} else { } else {
// If this is the child we had previously determined to break before, do // If this is the child we had previously determined to break before, do
// so now and finish layout. // so now and finish layout.
...@@ -713,6 +713,8 @@ inline scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::Layout( ...@@ -713,6 +713,8 @@ inline scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::Layout(
if (ruby_text_child) if (ruby_text_child)
LayoutRubyText(&ruby_text_child); LayoutRubyText(&ruby_text_child);
if (placeholder_child)
HandleTextControlPlaceholder(placeholder_child, previous_inflow_position);
if (UNLIKELY(ConstraintSpace().IsNewFormattingContext() && if (UNLIKELY(ConstraintSpace().IsNewFormattingContext() &&
!ignore_line_clamp_ && lines_until_clamp_ == 0 && !ignore_line_clamp_ && lines_until_clamp_ == 0 &&
...@@ -2979,6 +2981,8 @@ void NGBlockLayoutAlgorithm::HandleTextControlPlaceholder( ...@@ -2979,6 +2981,8 @@ void NGBlockLayoutAlgorithm::HandleTextControlPlaceholder(
ChildAvailableSize(), is_new_fc); ChildAvailableSize(), is_new_fc);
scoped_refptr<const NGLayoutResult> result = placeholder.Layout(space); scoped_refptr<const NGLayoutResult> result = placeholder.Layout(space);
// TODO(crbug.com/1040826): For LayoutNGTextControlSingleLine, we should
// compute the placeholder position from the baseline of the last child.
container_builder_.AddResult(*result, BorderScrollbarPadding().StartOffset()); container_builder_.AddResult(*result, BorderScrollbarPadding().StartOffset());
// This function doesn't update previous_inflow_position. Other children in // This function doesn't update previous_inflow_position. Other children in
// this container should ignore |placeholder|. // this container should ignore |placeholder|.
......
...@@ -181,6 +181,17 @@ void NGContainerFragmentBuilder::AddChildInternal( ...@@ -181,6 +181,17 @@ void NGContainerFragmentBuilder::AddChildInternal(
return; return;
} }
if (child->IsTextControlPlaceholder()) {
// ::placeholder should be followed by another block in order to paint
// ::placeholder earlier.
const wtf_size_t size = children_.size();
if (size > 0) {
children_.insert(size - 1,
ChildWithOffset(child_offset, std::move(child)));
return;
}
}
children_.emplace_back(child_offset, std::move(child)); children_.emplace_back(child_offset, std::move(child));
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h" #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/dom/document_lifecycle.h" #include "third_party/blink/renderer/core/dom/document_lifecycle.h"
#include "third_party/blink/renderer/core/html/shadow/shadow_element_utils.h"
#include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h" #include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h"
#include "third_party/blink/renderer/core/layout/layout_block.h" #include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h" #include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
...@@ -376,6 +377,10 @@ bool NGPhysicalFragment::IsBlockFlow() const { ...@@ -376,6 +377,10 @@ bool NGPhysicalFragment::IsBlockFlow() const {
return !IsLineBox() && layout_object_->IsLayoutBlockFlow(); return !IsLineBox() && layout_object_->IsLayoutBlockFlow();
} }
bool NGPhysicalFragment::IsTextControlPlaceholder() const {
return blink::IsTextControlPlaceholder(layout_object_->GetNode());
}
bool NGPhysicalFragment::IsPlacedByLayoutNG() const { bool NGPhysicalFragment::IsPlacedByLayoutNG() const {
// TODO(kojii): Move this to a flag for |LayoutNGBlockFlow::UpdateBlockLayout| // TODO(kojii): Move this to a flag for |LayoutNGBlockFlow::UpdateBlockLayout|
// to set. // to set.
......
...@@ -171,6 +171,8 @@ class CORE_EXPORT NGPhysicalFragment ...@@ -171,6 +171,8 @@ class CORE_EXPORT NGPhysicalFragment
!layout_object_->IsTableCellLegacy(); !layout_object_->IsTableCellLegacy();
} }
bool IsTextControlPlaceholder() const;
// Return true if this fragment is a container established by a fieldset // Return true if this fragment is a container established by a fieldset
// element. Such a fragment contains an optional rendered legend fragment and // element. Such a fragment contains an optional rendered legend fragment and
// an optional fieldset contents wrapper fragment (which holds everything // an optional fieldset contents wrapper fragment (which holds everything
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment