Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |