Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(861)

Side by Side Diff: Source/core/rendering/RenderBlock.cpp

Issue 26315006: Avoid creating first-letter RenderTextFragments for unsuitable text nodes (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/rendering/RenderBlock.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2007 David Smith (catfish.man@gmail.com) 4 * (C) 2007 David Smith (catfish.man@gmail.com)
5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
6 * Copyright (C) Research In Motion Limited 2010. All rights reserved. 6 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
7 * 7 *
8 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public 9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
(...skipping 5723 matching lines...) Expand 10 before | Expand all | Expand 10 after
5734 } 5734 }
5735 5735
5736 static inline unsigned firstLetterLength(const String& text) 5736 static inline unsigned firstLetterLength(const String& text)
5737 { 5737 {
5738 unsigned length = 0; 5738 unsigned length = 0;
5739 5739
5740 // Account for leading spaces and punctuation. 5740 // Account for leading spaces and punctuation.
5741 while (length < text.length() && shouldSkipForFirstLetter((text)[length])) 5741 while (length < text.length() && shouldSkipForFirstLetter((text)[length]))
5742 length++; 5742 length++;
5743 5743
5744 // Bail if we didn't find a letter
5745 if (text.length() && length == text.length())
eseidel 2013/10/07 22:27:25 So when you just have <div>F<div> and a first-lett
leviw_travelin_and_unemployed 2013/10/07 22:33:19 Yup :) In that case length will simply be 0 here.
5746 return 0;
5747
5744 // Account for first letter. 5748 // Account for first letter.
5745 length++; 5749 length++;
5746 5750
5747 // Keep looking for whitespace and allowed punctuation, but avoid 5751 // Keep looking for whitespace and allowed punctuation, but avoid
5748 // accumulating just whitespace into the :first-letter. 5752 // accumulating just whitespace into the :first-letter.
5749 for (unsigned scanLength = length; scanLength < text.length(); ++scanLength) { 5753 for (unsigned scanLength = length; scanLength < text.length(); ++scanLength) {
5750 UChar c = (text)[scanLength]; 5754 UChar c = (text)[scanLength];
5751 5755
5752 if (!shouldSkipForFirstLetter(c)) 5756 if (!shouldSkipForFirstLetter(c))
5753 break; 5757 break;
5754 5758
5755 if (isPunctuationForFirstLetter(c)) 5759 if (isPunctuationForFirstLetter(c))
5756 length = scanLength + 1; 5760 length = scanLength + 1;
5757 } 5761 }
5758 5762
5759 return length; 5763 return length;
5760 } 5764 }
5761 5765
5762 void RenderBlock::createFirstLetterRenderer(RenderObject* firstLetterBlock, Rend erObject* currentChild) 5766 void RenderBlock::createFirstLetterRenderer(RenderObject* firstLetterBlock, Rend erObject* currentChild, unsigned length)
5763 { 5767 {
5768 ASSERT(length);
5769 ASSERT(currentChild->isText() && !toRenderText(currentChild)->isTextFragment ());
5770
5764 RenderObject* firstLetterContainer = currentChild->parent(); 5771 RenderObject* firstLetterContainer = currentChild->parent();
5765 RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetter Container); 5772 RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetter Container);
5766 RenderObject* firstLetter = 0; 5773 RenderObject* firstLetter = 0;
5767 if (pseudoStyle->display() == INLINE) 5774 if (pseudoStyle->display() == INLINE)
5768 firstLetter = RenderInline::createAnonymous(&document()); 5775 firstLetter = RenderInline::createAnonymous(&document());
5769 else 5776 else
5770 firstLetter = RenderBlock::createAnonymous(&document()); 5777 firstLetter = RenderBlock::createAnonymous(&document());
5771 firstLetter->setStyle(pseudoStyle); 5778 firstLetter->setStyle(pseudoStyle);
5772 firstLetterContainer->addChild(firstLetter, currentChild); 5779 firstLetterContainer->addChild(firstLetter, currentChild);
5773 5780
5774 RenderText* textObj = toRenderText(currentChild); 5781 RenderText* textObj = toRenderText(currentChild);
5775 5782
5776 // The original string is going to be either a generated content string or a DOM node's 5783 // The original string is going to be either a generated content string or a DOM node's
5777 // string. We want the original string before it got transformed in case fi rst-letter has 5784 // string. We want the original string before it got transformed in case fi rst-letter has
5778 // no text-transform or a different text-transform applied to it. 5785 // no text-transform or a different text-transform applied to it.
5779 String oldText = textObj->originalText(); 5786 String oldText = textObj->originalText();
5780 ASSERT(oldText.impl()); 5787 ASSERT(oldText.impl());
5781 5788
5782 unsigned length = firstLetterLength(oldText);
5783
5784 if (!length)
5785 return;
5786
5787 // Construct a text fragment for the text after the first letter. 5789 // Construct a text fragment for the text after the first letter.
5788 // This text fragment might be empty. 5790 // This text fragment might be empty.
5789 RenderTextFragment* remainingText = 5791 RenderTextFragment* remainingText =
5790 new RenderTextFragment(textObj->node() ? textObj->node() : &textObj->doc ument(), oldText.impl(), length, oldText.length() - length); 5792 new RenderTextFragment(textObj->node() ? textObj->node() : &textObj->doc ument(), oldText.impl(), length, oldText.length() - length);
5791 remainingText->setStyle(textObj->style()); 5793 remainingText->setStyle(textObj->style());
5792 if (remainingText->node()) 5794 if (remainingText->node())
5793 remainingText->node()->setRenderer(remainingText); 5795 remainingText->node()->setRenderer(remainingText);
5794 5796
5795 firstLetterContainer->addChild(remainingText, textObj); 5797 firstLetterContainer->addChild(remainingText, textObj);
5796 firstLetterContainer->removeChild(textObj); 5798 firstLetterContainer->removeChild(textObj);
(...skipping 16 matching lines...) Expand all
5813 // Don't recur 5815 // Don't recur
5814 if (style()->styleType() == FIRST_LETTER) 5816 if (style()->styleType() == FIRST_LETTER)
5815 return; 5817 return;
5816 5818
5817 RenderObject* firstLetterBlock = findFirstLetterBlock(this); 5819 RenderObject* firstLetterBlock = findFirstLetterBlock(this);
5818 if (!firstLetterBlock) 5820 if (!firstLetterBlock)
5819 return; 5821 return;
5820 5822
5821 // Drill into inlines looking for our first text child. 5823 // Drill into inlines looking for our first text child.
5822 RenderObject* currChild = firstLetterBlock->firstChild(); 5824 RenderObject* currChild = firstLetterBlock->firstChild();
5825 unsigned length = 0;
5823 while (currChild) { 5826 while (currChild) {
5824 if (currChild->isText()) 5827 if (currChild->isText()) {
5825 break; 5828 // FIXME: If there is leading punctuation in a different RenderText than
5826 if (currChild->isListMarker()) 5829 // the first letter, we'll not apply the correct style to it.
5830 length = firstLetterLength(toRenderText(currChild)->originalText());
5831 if (length)
5832 break;
5827 currChild = currChild->nextSibling(); 5833 currChild = currChild->nextSibling();
5828 else if (currChild->isFloatingOrOutOfFlowPositioned()) { 5834 } else if (currChild->isListMarker()) {
5835 currChild = currChild->nextSibling();
5836 } else if (currChild->isFloatingOrOutOfFlowPositioned()) {
5829 if (currChild->style()->styleType() == FIRST_LETTER) { 5837 if (currChild->style()->styleType() == FIRST_LETTER) {
5830 currChild = currChild->firstChild(); 5838 currChild = currChild->firstChild();
5831 break; 5839 break;
5832 } 5840 }
5833 currChild = currChild->nextSibling(); 5841 currChild = currChild->nextSibling();
5834 } else if (currChild->isReplaced() || currChild->isRenderButton() || cur rChild->isMenuList()) 5842 } else if (currChild->isReplaced() || currChild->isRenderButton() || cur rChild->isMenuList())
5835 break; 5843 break;
5836 else if (currChild->style()->hasPseudoStyle(FIRST_LETTER) && currChild-> canHaveGeneratedChildren()) { 5844 else if (currChild->style()->hasPseudoStyle(FIRST_LETTER) && currChild-> canHaveGeneratedChildren()) {
5837 // We found a lower-level node with first-letter, which supersedes t he higher-level style 5845 // We found a lower-level node with first-letter, which supersedes t he higher-level style
5838 firstLetterBlock = currChild; 5846 firstLetterBlock = currChild;
5839 currChild = currChild->firstChild(); 5847 currChild = currChild->firstChild();
5840 } else 5848 } else
5841 currChild = currChild->firstChild(); 5849 currChild = currChild->firstChild();
5842 } 5850 }
5843 5851
5844 if (!currChild) 5852 if (!currChild)
5845 return; 5853 return;
5846 5854
5847 if (currChild->parent()->style()->styleType() == FIRST_LETTER) { 5855 if (currChild->parent()->style()->styleType() == FIRST_LETTER) {
5848 // Destroy the first-letter object if it is no longer the first child. 5856 // Destroy the first-letter object if it is no longer the first child.
5849 RenderObject* remainingText = currChild->parent()->nextSibling(); 5857 RenderObject* remainingText = currChild->parent()->nextSibling();
5850 if (remainingText && currChild->node() != remainingText->node()) { 5858 if (remainingText && currChild->node() != remainingText->node()) {
5851 if (!remainingText->isText() || remainingText->isBR()) 5859 if (!remainingText->isText() || remainingText->isBR())
5852 return; 5860 return;
5853 5861
5862 RenderText* newFirstText = toRenderText(remainingText);
5863 length = firstLetterLength(newFirstText->originalText());
5864
5865 if (!length)
5866 return;
5867
5854 LayoutStateDisabler layoutStateDisabler(view()); 5868 LayoutStateDisabler layoutStateDisabler(view());
5855 5869
5856 if (RenderObject* oldRemainingText = toRenderBoxModelObject(currChil d->parent())->firstLetterRemainingText()) 5870 if (RenderObject* oldRemainingText = toRenderBoxModelObject(currChil d->parent())->firstLetterRemainingText())
5857 toRenderText(oldRemainingText)->setText(toText(oldRemainingText- >node())->data().impl()); 5871 toRenderText(oldRemainingText)->setText(toText(oldRemainingText- >node())->data().impl());
5858 5872
5859 createFirstLetterRenderer(firstLetterBlock, remainingText); 5873 createFirstLetterRenderer(firstLetterBlock, newFirstText, length);
5860 return; 5874 return;
5861 } 5875 }
5862 5876
5863 // If the child already has style, then it has already been created, so we just want 5877 // If the child already has style, then it has already been created, so we just want
5864 // to update it. 5878 // to update it.
5865 updateFirstLetterStyle(firstLetterBlock, currChild); 5879 updateFirstLetterStyle(firstLetterBlock, currChild);
5866 return; 5880 return;
5867 } 5881 }
5868 5882
5869 if (!currChild->isText() || currChild->isBR()) 5883 if (!currChild->isText() || currChild->isBR())
5870 return; 5884 return;
5871 5885
5872 // Our layout state is not valid for the repaints we are going to trigger by 5886 // Our layout state is not valid for the repaints we are going to trigger by
5873 // adding and removing children of firstLetterContainer. 5887 // adding and removing children of firstLetterContainer.
5874 LayoutStateDisabler layoutStateDisabler(view()); 5888 LayoutStateDisabler layoutStateDisabler(view());
5875 5889
5876 createFirstLetterRenderer(firstLetterBlock, currChild); 5890 createFirstLetterRenderer(firstLetterBlock, currChild, length);
5877 } 5891 }
5878 5892
5879 // Helper methods for obtaining the last line, computing line counts and heights for line counts 5893 // Helper methods for obtaining the last line, computing line counts and heights for line counts
5880 // (crawling into blocks). 5894 // (crawling into blocks).
5881 static bool shouldCheckLines(RenderObject* obj) 5895 static bool shouldCheckLines(RenderObject* obj)
5882 { 5896 {
5883 return !obj->isFloatingOrOutOfFlowPositioned() && !obj->isRunIn() 5897 return !obj->isFloatingOrOutOfFlowPositioned() && !obj->isRunIn()
5884 && obj->isRenderBlock() && obj->style()->height().isAuto() 5898 && obj->isRenderBlock() && obj->style()->height().isAuto()
5885 && (!obj->isDeprecatedFlexibleBox() || obj->style()->boxOrient() == VERT ICAL); 5899 && (!obj->isDeprecatedFlexibleBox() || obj->style()->boxOrient() == VERT ICAL);
5886 } 5900 }
(...skipping 928 matching lines...) Expand 10 before | Expand all | Expand 10 after
6815 void RenderBlock::showLineTreeAndMark(const InlineBox* markedBox1, const char* m arkedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const Render Object* obj) const 6829 void RenderBlock::showLineTreeAndMark(const InlineBox* markedBox1, const char* m arkedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const Render Object* obj) const
6816 { 6830 {
6817 showRenderObject(); 6831 showRenderObject();
6818 for (const RootInlineBox* root = firstRootBox(); root; root = root->nextRoot Box()) 6832 for (const RootInlineBox* root = firstRootBox(); root; root = root->nextRoot Box())
6819 root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLa bel2, obj, 1); 6833 root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLa bel2, obj, 1);
6820 } 6834 }
6821 6835
6822 #endif 6836 #endif
6823 6837
6824 } // namespace WebCore 6838 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/rendering/RenderBlock.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698