Commit 48bdfcea authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

Fix :first-letter pseudo element to inherit correctly

The :first-letter pseudo element may not be a child of the element in
style/box tree.

For example:
  <div><span>text</span></div>
creates:
  <div>
    <span>
      <div:first-letter>t</div:first-letter>
      ext
    </span>
  </div>

FirstLetterPseudoElement computes this correctly on creation, but
inherited from <div> on RecalcStyle(). This patch fixes the inheritance
on RecalcStyle() too.

Inline layout code assumes that a text box has the same style as its
parent inline box. The incorrect style on FirstLetterPseudoElement
breaks this assumption.

Bug: 450002, 507757, 739800
Change-Id: Icda675f5ffbb705c4b87f9d23cca34f24c4763ee
Reviewed-on: https://chromium-review.googlesource.com/593067Reviewed-by: default avatarEmil A Eklund <eae@chromium.org>
Commit-Queue: Emil A Eklund <eae@chromium.org>
Commit-Queue: Koji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#490692}
parent 26f38f3f
<!DOCTYPE html>
<style>
p:first-letter {
color:red;
}
#block { color: blue; }
#inline { font-size: 128px; }
</style>
<body>
<p id="block"><span id="inline">Examples</span></p>
</body>
<!DOCTYPE html>
<style>
p:first-letter {
color:red;
}
#inline { font-size: 128px; }
</style>
<script>
window.onload = function () {
// Force layout and change style to kick RecalcStyle().
block.offsetTop;
block.style.color = 'blue';
}
</script>
<body>
<p id="block"><span id="inline">Examples</span></p>
</body>
PASS getComputedStyle(p, '::first-letter').color is green
FAIL getComputedStyle(p, '::first-letter').color should be rgb(0, 128, 0). Was rgb(255, 0, 0).
PASS successfullyParsed is true
TEST COMPLETE
hover me.
<!DOCTYPE html>
<script src="../../../resources/js-test.js"></script>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<style>
#p { color: red }
#p::first-line { color: green }
......@@ -9,10 +10,14 @@
<p id="p">Hover me.</p>
<script>
var green = "rgb(0, 128, 0)";
shouldBe("getComputedStyle(p, '::first-letter').color", "green");
test(() => {
assert_equals(getComputedStyle(p, '::first-letter').color, green);
}, 'before :hover');
if (eventSender)
eventSender.mouseMoveTo(p.offsetLeft+1, p.offsetTop+1);
test(() => {
if (eventSender)
eventSender.mouseMoveTo(p.offsetLeft + 1, p.offsetTop + 1);
shouldBe("getComputedStyle(p, '::first-letter').color", "green");
assert_equals(getComputedStyle(p, '::first-letter').color, green);
}, 'after :hover');
</script>
......@@ -296,6 +296,8 @@ void FirstLetterPseudoElement::AttachFirstLetterTextLayoutObjects() {
: ToLayoutText(next_layout_object)->OriginalText();
DCHECK(old_text.Impl());
// :first-letter inehrits from the parent of the text. It may not be
// this->Parent() when e.g., <div><span>text</span></div>.
ComputedStyle* pseudo_style =
StyleForFirstLetter(next_layout_object->Parent());
GetLayoutObject()->SetStyle(pseudo_style);
......@@ -341,23 +343,28 @@ void FirstLetterPseudoElement::AttachFirstLetterTextLayoutObjects() {
}
void FirstLetterPseudoElement::DidRecalcStyle() {
if (!GetLayoutObject())
LayoutObject* layout_object = this->GetLayoutObject();
if (!layout_object)
return;
// :first-letter inehrits from the parent of the text. It may not be
// this->Parent() when e.g., <div><span>text</span></div>.
DCHECK(remaining_text_layout_object_);
ComputedStyle* pseudo_style =
StyleForFirstLetter(remaining_text_layout_object_->Parent());
DCHECK(pseudo_style);
layout_object->SetStyle(pseudo_style);
// The layoutObjects inside pseudo elements are anonymous so they don't get
// notified of recalcStyle and must have
// the style propagated downward manually similar to
// LayoutObject::propagateStyleToAnonymousChildren.
LayoutObject* layout_object = this->GetLayoutObject();
for (LayoutObject* child = layout_object->NextInPreOrder(layout_object);
child; child = child->NextInPreOrder(layout_object)) {
// We need to re-calculate the correct style for the first letter element
// and then apply that to the container and the text fragment inside.
if (child->Style()->StyleType() == kPseudoIdFirstLetter &&
remaining_text_layout_object_) {
if (ComputedStyle* pseudo_style =
StyleForFirstLetter(remaining_text_layout_object_->Parent()))
child->SetPseudoStyle(pseudo_style);
if (child->Style()->StyleType() == kPseudoIdFirstLetter) {
child->SetPseudoStyle(pseudo_style);
continue;
}
......
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