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 13 matching lines...) Expand all Loading... | |
24 #include "config.h" | 24 #include "config.h" |
25 #include "core/rendering/RenderBlock.h" | 25 #include "core/rendering/RenderBlock.h" |
26 | 26 |
27 #include "HTMLFormElement.h" | 27 #include "HTMLFormElement.h" |
28 #include "HTMLNames.h" | 28 #include "HTMLNames.h" |
29 #include "core/accessibility/AXObjectCache.h" | 29 #include "core/accessibility/AXObjectCache.h" |
30 #include "core/dom/Document.h" | 30 #include "core/dom/Document.h" |
31 #include "core/dom/Element.h" | 31 #include "core/dom/Element.h" |
32 #include "core/dom/OverflowEvent.h" | 32 #include "core/dom/OverflowEvent.h" |
33 #include "core/dom/ShadowRoot.h" | 33 #include "core/dom/ShadowRoot.h" |
34 #include "core/dom/Text.h" | |
34 #include "core/dom/WebCoreMemoryInstrumentation.h" | 35 #include "core/dom/WebCoreMemoryInstrumentation.h" |
35 #include "core/editing/Editor.h" | 36 #include "core/editing/Editor.h" |
36 #include "core/editing/FrameSelection.h" | 37 #include "core/editing/FrameSelection.h" |
37 #include "core/page/Frame.h" | 38 #include "core/page/Frame.h" |
38 #include "core/page/FrameView.h" | 39 #include "core/page/FrameView.h" |
39 #include "core/page/Page.h" | 40 #include "core/page/Page.h" |
40 #include "core/page/Settings.h" | 41 #include "core/page/Settings.h" |
41 #include "core/platform/PODFreeListArena.h" | 42 #include "core/platform/PODFreeListArena.h" |
42 #include "core/platform/graphics/FloatQuad.h" | 43 #include "core/platform/graphics/FloatQuad.h" |
43 #include "core/platform/graphics/GraphicsContext.h" | 44 #include "core/platform/graphics/GraphicsContext.h" |
(...skipping 6569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6613 firstLetterContainer->addChild(firstLetter, nextSibling); | 6614 firstLetterContainer->addChild(firstLetter, nextSibling); |
6614 } else | 6615 } else |
6615 firstLetter->setStyle(pseudoStyle); | 6616 firstLetter->setStyle(pseudoStyle); |
6616 | 6617 |
6617 for (RenderObject* genChild = firstLetter->firstChild(); genChild; genChild = genChild->nextSibling()) { | 6618 for (RenderObject* genChild = firstLetter->firstChild(); genChild; genChild = genChild->nextSibling()) { |
6618 if (genChild->isText()) | 6619 if (genChild->isText()) |
6619 genChild->setStyle(pseudoStyle); | 6620 genChild->setStyle(pseudoStyle); |
6620 } | 6621 } |
6621 } | 6622 } |
6622 | 6623 |
6624 static inline unsigned whiteSpaceLength(PassRefPtr<StringImpl> oldText) | |
esprehn
2013/05/06 20:43:58
Just take a String not a RefPtr<StringImpl>
| |
6625 { | |
6626 unsigned length = 0; | |
6627 // Account for leading spaces and punctuation. | |
6628 while (length < oldText->length() && shouldSkipForFirstLetter((*oldText)[len gth])) | |
6629 length++; | |
6630 | |
6631 // Account for first letter. | |
6632 length++; | |
6633 | |
6634 // Keep looking for whitespace and allowed punctuation, but avoid | |
6635 // accumulating just whitespace into the :first-letter. | |
6636 for (unsigned scanLength = length; scanLength < oldText->length(); ++scanLen gth) { | |
6637 UChar c = (*oldText)[scanLength]; | |
6638 | |
6639 if (!shouldSkipForFirstLetter(c)) | |
6640 break; | |
6641 | |
6642 if (isPunctuationForFirstLetter(c)) | |
6643 length = scanLength + 1; | |
6644 } | |
6645 | |
6646 return length; | |
6647 } | |
6648 | |
6623 void RenderBlock::createFirstLetterRenderer(RenderObject* firstLetterBlock, Rend erObject* currentChild) | 6649 void RenderBlock::createFirstLetterRenderer(RenderObject* firstLetterBlock, Rend erObject* currentChild) |
6624 { | 6650 { |
6625 RenderObject* firstLetterContainer = currentChild->parent(); | 6651 RenderObject* firstLetterContainer = currentChild->parent(); |
6626 RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetter Container); | 6652 RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetter Container); |
6627 RenderObject* firstLetter = 0; | 6653 RenderObject* firstLetter = 0; |
6628 if (pseudoStyle->display() == INLINE) | 6654 if (pseudoStyle->display() == INLINE) |
6629 firstLetter = RenderInline::createAnonymous(document()); | 6655 firstLetter = RenderInline::createAnonymous(document()); |
6630 else | 6656 else |
6631 firstLetter = RenderBlock::createAnonymous(document()); | 6657 firstLetter = RenderBlock::createAnonymous(document()); |
6632 firstLetter->setStyle(pseudoStyle); | 6658 firstLetter->setStyle(pseudoStyle); |
6633 firstLetterContainer->addChild(firstLetter, currentChild); | 6659 firstLetterContainer->addChild(firstLetter, currentChild); |
6634 | 6660 |
6635 RenderText* textObj = toRenderText(currentChild); | 6661 RenderText* textObj = toRenderText(currentChild); |
6636 | 6662 |
6637 // The original string is going to be either a generated content string or a DOM node's | 6663 // The original string is going to be either a generated content string or a DOM node's |
6638 // string. We want the original string before it got transformed in case fi rst-letter has | 6664 // string. We want the original string before it got transformed in case fi rst-letter has |
6639 // no text-transform or a different text-transform applied to it. | 6665 // no text-transform or a different text-transform applied to it. |
6640 RefPtr<StringImpl> oldText = textObj->originalText(); | 6666 RefPtr<StringImpl> oldText = textObj->originalText(); |
esprehn
2013/05/06 20:43:58
Change to String
| |
6641 ASSERT(oldText); | 6667 ASSERT(oldText); |
6642 | 6668 |
6643 if (oldText && oldText->length() > 0) { | 6669 if (oldText && oldText->length() > 0) { |
6644 unsigned length = 0; | 6670 unsigned length = 0; |
6671 length = whiteSpaceLength(oldText); | |
6645 | 6672 |
6646 // Account for leading spaces and punctuation. | |
6647 while (length < oldText->length() && shouldSkipForFirstLetter((*oldText) [length])) | |
6648 length++; | |
6649 | |
6650 // Account for first letter. | |
6651 length++; | |
6652 | |
6653 // Keep looking for whitespace and allowed punctuation, but avoid | |
6654 // accumulating just whitespace into the :first-letter. | |
6655 for (unsigned scanLength = length; scanLength < oldText->length(); ++sca nLength) { | |
6656 UChar c = (*oldText)[scanLength]; | |
6657 | |
6658 if (!shouldSkipForFirstLetter(c)) | |
6659 break; | |
6660 | |
6661 if (isPunctuationForFirstLetter(c)) | |
6662 length = scanLength + 1; | |
6663 } | |
6664 | |
6665 // Construct a text fragment for the text after the first letter. | 6673 // Construct a text fragment for the text after the first letter. |
6666 // This text fragment might be empty. | 6674 // This text fragment might be empty. |
6667 RenderTextFragment* remainingText = | 6675 RenderTextFragment* remainingText = |
6668 new (renderArena()) RenderTextFragment(textObj->node() ? textObj->no de() : textObj->document(), oldText.get(), length, oldText->length() - length); | 6676 new (renderArena()) RenderTextFragment(textObj->node() ? textObj->no de() : textObj->document(), oldText.get(), length, oldText->length() - length); |
6669 remainingText->setStyle(textObj->style()); | 6677 remainingText->setStyle(textObj->style()); |
6670 if (remainingText->node()) | 6678 if (remainingText->node()) |
6671 remainingText->node()->setRenderer(remainingText); | 6679 remainingText->node()->setRenderer(remainingText); |
6672 | 6680 |
6673 firstLetterContainer->addChild(remainingText, textObj); | 6681 firstLetterContainer->addChild(remainingText, textObj); |
6674 firstLetterContainer->removeChild(textObj); | 6682 firstLetterContainer->removeChild(textObj); |
(...skipping 19 matching lines...) Expand all Loading... | |
6694 return; | 6702 return; |
6695 | 6703 |
6696 // FIXME: We need to destroy the first-letter object if it is no longer the first child. Need to find | 6704 // FIXME: We need to destroy the first-letter object if it is no longer the first child. Need to find |
6697 // an efficient way to check for that situation though before implementing a nything. | 6705 // an efficient way to check for that situation though before implementing a nything. |
6698 RenderObject* firstLetterBlock = findFirstLetterBlock(this); | 6706 RenderObject* firstLetterBlock = findFirstLetterBlock(this); |
6699 if (!firstLetterBlock) | 6707 if (!firstLetterBlock) |
6700 return; | 6708 return; |
6701 | 6709 |
6702 // Drill into inlines looking for our first text child. | 6710 // Drill into inlines looking for our first text child. |
6703 RenderObject* currChild = firstLetterBlock->firstChild(); | 6711 RenderObject* currChild = firstLetterBlock->firstChild(); |
6712 RenderObject* firstLetter = currChild; | |
6713 | |
6704 while (currChild) { | 6714 while (currChild) { |
6705 if (currChild->isText()) | 6715 if (currChild->isText()) |
6706 break; | 6716 break; |
6707 if (currChild->isListMarker()) | 6717 if (currChild->isListMarker()) |
6708 currChild = currChild->nextSibling(); | 6718 currChild = currChild->nextSibling(); |
6709 else if (currChild->isFloatingOrOutOfFlowPositioned()) { | 6719 else if (currChild->isFloatingOrOutOfFlowPositioned()) { |
6710 if (currChild->style()->styleType() == FIRST_LETTER) { | 6720 if (currChild->style()->styleType() == FIRST_LETTER) { |
6711 currChild = currChild->firstChild(); | 6721 currChild = currChild->firstChild(); |
6712 break; | 6722 break; |
6713 } | 6723 } |
6714 currChild = currChild->nextSibling(); | 6724 currChild = currChild->nextSibling(); |
6715 } else if (currChild->isReplaced() || currChild->isRenderButton() || cur rChild->isMenuList()) | 6725 } else if (currChild->isReplaced() || currChild->isRenderButton() || cur rChild->isMenuList()) |
6716 break; | 6726 break; |
6717 else if (currChild->style()->hasPseudoStyle(FIRST_LETTER) && currChild-> canHaveGeneratedChildren()) { | 6727 else if (currChild->style()->hasPseudoStyle(FIRST_LETTER) && currChild-> canHaveGeneratedChildren()) { |
6718 // We found a lower-level node with first-letter, which supersedes t he higher-level style | 6728 // We found a lower-level node with first-letter, which supersedes t he higher-level style |
6719 firstLetterBlock = currChild; | 6729 firstLetterBlock = currChild; |
6720 currChild = currChild->firstChild(); | 6730 currChild = currChild->firstChild(); |
6721 } else | 6731 } else |
6722 currChild = currChild->firstChild(); | 6732 currChild = currChild->firstChild(); |
6723 } | 6733 } |
6724 | 6734 |
6725 if (!currChild) | 6735 if (!currChild) |
6726 return; | 6736 return; |
6727 | 6737 |
6728 // If the child already has style, then it has already been created, so we j ust want | 6738 // If the child already has style, then it has already been created, so we j ust want |
6729 // to update it. | 6739 // to update it. |
6730 if (currChild->parent()->style()->styleType() == FIRST_LETTER) { | 6740 if (currChild->parent()->style()->styleType() == FIRST_LETTER) { |
6741 RenderText* remainingText = toRenderText(currChild->parent()->nextSiblin g()); | |
6742 // When the first line is changed by adding a new text at its start, | |
6743 // the first letter has to be updated. | |
6744 if (toRenderBoxModelObject(firstLetter)->firstLetterRemainingText() != r emainingText) { | |
6745 RenderText* firstLetterText = toRenderText(currChild); | |
6746 RefPtr<StringImpl> updatedTextImp = remainingText->originalText(); | |
esprehn
2013/05/06 20:43:58
Just use String. A String is just a RefPtr to a St
| |
6747 ASSERT(updatedTextImp); | |
esprehn
2013/05/06 20:43:58
This assert should be inside whiteSpaceLength
| |
6748 unsigned length = 0; | |
6749 if (updatedTextImp && updatedTextImp->length() > 0) | |
esprehn
2013/05/06 20:43:58
This check should be inside whiteSpaceLength() and
| |
6750 length = whiteSpaceLength(updatedTextImp); | |
6751 | |
6752 firstLetterText->setText(updatedTextImp->substring(0, length)); | |
6753 remainingText->setText(updatedTextImp->substring(length)); | |
6754 | |
6755 RenderObject* oldRemainingText = currChild->parent()->nextSibling()- >nextSibling(); | |
esprehn
2013/05/06 20:43:58
This doesn't look safe at all. How do you know you
| |
6756 // Replace the previous remaining text with the original text. | |
6757 // because it doesn't have the first letter. | |
6758 if (oldRemainingText->isText()) { | |
6759 RefPtr<StringImpl> oldString = toText(oldRemainingText->node())- >dataImpl(); | |
esprehn
2013/05/06 20:43:58
This is going to crash if it's an anonymous text r
| |
6760 | |
6761 // Before calling setText, we need to set m_firstLetter to 0 in order not to delete it. | |
6762 if (toRenderText(oldRemainingText)->isTextFragment()) | |
6763 toRenderTextFragment(oldRemainingText)->setFirstLetter(0); | |
6764 | |
6765 toRenderText(oldRemainingText)->setText(oldString); | |
6766 } | |
6767 toRenderBoxModelObject(firstLetter)->setFirstLetterRemainingText(rem ainingText); | |
6768 } | |
6769 | |
6731 updateFirstLetterStyle(firstLetterBlock, currChild); | 6770 updateFirstLetterStyle(firstLetterBlock, currChild); |
6732 return; | 6771 return; |
6733 } | 6772 } |
6734 | 6773 |
6735 if (!currChild->isText() || currChild->isBR()) | 6774 if (!currChild->isText() || currChild->isBR()) |
6736 return; | 6775 return; |
6737 | 6776 |
6738 // Our layout state is not valid for the repaints we are going to trigger by | 6777 // Our layout state is not valid for the repaints we are going to trigger by |
6739 // adding and removing children of firstLetterContainer. | 6778 // adding and removing children of firstLetterContainer. |
6740 LayoutStateDisabler layoutStateDisabler(view()); | 6779 LayoutStateDisabler layoutStateDisabler(view()); |
(...skipping 1373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8114 { | 8153 { |
8115 memoryInstrumentation->addRootObject(gColumnInfoMap, WebCoreMemoryTypes::Ren deringStructures); | 8154 memoryInstrumentation->addRootObject(gColumnInfoMap, WebCoreMemoryTypes::Ren deringStructures); |
8116 memoryInstrumentation->addRootObject(gPositionedDescendantsMap, WebCoreMemor yTypes::RenderingStructures); | 8155 memoryInstrumentation->addRootObject(gPositionedDescendantsMap, WebCoreMemor yTypes::RenderingStructures); |
8117 memoryInstrumentation->addRootObject(gPercentHeightDescendantsMap, WebCoreMe moryTypes::RenderingStructures); | 8156 memoryInstrumentation->addRootObject(gPercentHeightDescendantsMap, WebCoreMe moryTypes::RenderingStructures); |
8118 memoryInstrumentation->addRootObject(gPositionedContainerMap, WebCoreMemoryT ypes::RenderingStructures); | 8157 memoryInstrumentation->addRootObject(gPositionedContainerMap, WebCoreMemoryT ypes::RenderingStructures); |
8119 memoryInstrumentation->addRootObject(gPercentHeightContainerMap, WebCoreMemo ryTypes::RenderingStructures); | 8158 memoryInstrumentation->addRootObject(gPercentHeightContainerMap, WebCoreMemo ryTypes::RenderingStructures); |
8120 memoryInstrumentation->addRootObject(gDelayedUpdateScrollInfoSet, WebCoreMem oryTypes::RenderingStructures); | 8159 memoryInstrumentation->addRootObject(gDelayedUpdateScrollInfoSet, WebCoreMem oryTypes::RenderingStructures); |
8121 } | 8160 } |
8122 | 8161 |
8123 } // namespace WebCore | 8162 } // namespace WebCore |
OLD | NEW |