Changeset 21861 in webkit


Ignore:
Timestamp:
May 29, 2007 12:39:14 PM (17 years ago)
Author:
darin
Message:

LayoutTests:

Reviewed by Maciej.

  • fast/dom/HTMLElement/set-inner-outer-optimization-expected.txt: Added.
  • fast/dom/HTMLElement/set-inner-outer-optimization.html: Added.
  • editing/execCommand/copy-without-selection.html: Added missing preventDefault calls to prevent this from being a double-paste test.
  • fast/css/first-letter-detach-expected.checksum: Updated.
  • fast/css/first-letter-detach-expected.png: Updated.
  • fast/css/first-letter-detach-expected.txt: Updated.
  • fast/css/first-letter-detach.html: Updated to test three different ways of setting the text of the first-letter element; setInnerHTML and two other ways.
  • fast/events/updateLayoutForHitTest-expected.txt: Updated result that changed slightly due to setInnerHTML improvement.
  • fast/forms/textarea-setinnerhtml-expected.txt: Ditto.

WebCore:

Reviewed by Maciej.

  • fix first-letter when the text of the affected text node is changed

Optimize setInnerHTML, setOuterHTML, and setInnerText so they don't change the DOM at all
if they don't need to.

Test: fast/dom/HTMLElement/set-inner-outer-optimization.html
Test: fast/css/first-letter-detach.html

  • html/HTMLElement.cpp: (WebCore::equal): Added. Helper function that compares two Text nodes or two NamedAttrMap attribute maps. (WebCore::shallowEqual): Added. Helper function that compares two Element nodes or two arbitrary nodes. (WebCore::childrenAreEqual): Added. Helper functions that compare children of nodes. (WebCore::hasOneChild): Added. Helper function. (WebCore::hasOneTextChild): Added. Helper function. (WebCore::replaceChildrenWithFragment): Added. Helper function used by setInnerHTML and setInnerText. Optimizes the cases where all the nodes are the same, where both the current and the new content are single text nodes, and where the current content is a single node that can be replaced with replaceChild. (WebCore::replaceChildrenWithText): Added. Helper function used by setInnerText. Optimizes the case where the current content is a single text node or a single node that can be replaced with replaceChild. (WebCore::HTMLElement::setInnerHTML): Changed to call replaceChildrenWithFragment. (WebCore::HTMLElement::setOuterHTML): Added special case to optimize when the new content exactly matches the current node. (WebCore::HTMLElement::setInnerText): Changed to call replaceChildrenWithText in a few cases instead of doing removeChildren/appendChild. Changed code that was using DeprecatedString to instead use String. Changed general case to use a document fragment and replaceChildrenWithFragment.
  • dom/CharacterData.cpp: (WebCore::CharacterData::dispatchModifiedEvent): Fixed bug where we would not dispatch the DOMSubtreeModified event unless someone was registered for the DOMCharacterDataModified event. Caused trouble in the test.
  • rendering/RenderBlock.cpp: (WebCore::RenderBlock::updateFirstLetter): Set first-letter after the setStyle call so calls to setTextInternal inside setStyle don't clear it.
  • rendering/RenderText.h: Made setTextInternal virtual so that RenderTextFragment can do appropriate work when the text changes.
  • rendering/RenderTextFragment.h: Added an override of setTextInternal. Removed the firstLetter parameter to the constructor and made it a separate setter. Also changed m_generatedContentStr to m_contentString to match the getter function.
  • rendering/RenderTextFragment.cpp: (WebCore::RenderTextFragment::RenderTextFragment): Removed firstLetter parameter. (WebCore::RenderTextFragment::setTextInternal): When the text changes, destroy the first-letter node and reset the fragment values so that RenderBlock::updateFirstLetter, which will run during layout, will create a new first-letter child. Otherwise we end up with the first letter of the old text.
Location:
trunk
Files:
2 added
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r21847 r21861  
     12007-05-29  Darin Adler  <darin@apple.com>
     2
     3        Reviewed by Maciej.
     4
     5        - test for http://bugs.webkit.org/show_bug.cgi?id=13602
     6          Amazon product pages keep repainting over and over again
     7
     8        * fast/dom/HTMLElement/set-inner-outer-optimization-expected.txt: Added.
     9        * fast/dom/HTMLElement/set-inner-outer-optimization.html: Added.
     10
     11        * editing/execCommand/copy-without-selection.html: Added missing preventDefault calls
     12        to prevent this from being a double-paste test.
     13
     14        * fast/css/first-letter-detach-expected.checksum: Updated.
     15        * fast/css/first-letter-detach-expected.png: Updated.
     16        * fast/css/first-letter-detach-expected.txt: Updated.
     17        * fast/css/first-letter-detach.html: Updated to test three different ways of setting the
     18        text of the first-letter element; setInnerHTML and two other ways.
     19
     20        * fast/events/updateLayoutForHitTest-expected.txt: Updated result that changed slightly
     21        due to setInnerHTML improvement.
     22        * fast/forms/textarea-setinnerhtml-expected.txt: Ditto.
     23
    1242007-05-28  Mitz Pettel  <mitz@webkit.org>
    225
  • trunk/LayoutTests/editing/execCommand/copy-without-selection.html

    r19109 r21861  
    66{
    77    event.clipboardData.setData('text/plain', "SUCCESS");
     8    event.preventDefault();
    89}
    910
     
    1213    var clip = event.clipboardData.getData('text/plain');
    1314    document.getElementById('result').innerHTML = clip;
     15    event.preventDefault();
    1416}
    1517
  • trunk/LayoutTests/fast/css/first-letter-detach-expected.checksum

    r13463 r21861  
    1 8a18d46db2930f0b446f96f59f3747c2
     15997df311efaf8e91463da7355bba208
  • trunk/LayoutTests/fast/css/first-letter-detach-expected.txt

    r14684 r21861  
    1717          text run at (189,18) width 4: "."
    1818      RenderBlock {P} at (0,52) size 784x18
    19         RenderText {#text} at (0,0) size 171x18
    20           text run at (0,0) width 171: "The next line should read \x{201C}"
     19        RenderText {#text} at (0,0) size 231x18
     20          text run at (0,0) width 231: "The next three lines should all read \x{201C}"
    2121        RenderInline {SPAN} at (0,0) size 9x18 [color=#0000FF]
    22           RenderText {#text} at (171,0) size 9x18
    23             text run at (171,0) width 9: "P"
    24         RenderText {#text} at (180,0) size 209x18
    25           text run at (180,0) width 209: "ASS\x{201D}, with nothing before the P."
     22          RenderText {#text} at (231,0) size 9x18
     23            text run at (231,0) width 9: "P"
     24        RenderText {#text} at (240,0) size 209x18
     25          text run at (240,0) width 209: "ASS\x{201D}, with nothing before the P."
    2626      RenderBlock {HR} at (0,86) size 784x2 [border: (1px inset #000000)]
    2727      RenderBlock {P} at (0,104) size 784x18
     
    3131        RenderText {#text} at (9,0) size 30x18
    3232          text run at (9,0) width 30: "ASS"
     33      RenderBlock {P} at (0,138) size 784x18
     34        RenderInline (generated) at (0,0) size 9x18 [color=#0000FF]
     35          RenderText {#text} at (0,0) size 9x18
     36            text run at (0,0) width 9: "P"
     37        RenderText {#text} at (9,0) size 30x18
     38          text run at (9,0) width 30: "ASS"
     39      RenderBlock {P} at (0,172) size 784x18
     40        RenderInline (generated) at (0,0) size 9x18 [color=#0000FF]
     41          RenderText {#text} at (0,0) size 9x18
     42            text run at (0,0) width 9: "P"
     43        RenderText {#text} at (9,0) size 30x18
     44          text run at (9,0) width 30: "ASS"
  • trunk/LayoutTests/fast/css/first-letter-detach.html

    r13356 r21861  
    44<title></title>
    55<style type="text/css">
    6 #target:first-letter { color: blue;     }
     6#targeta:first-letter { color: blue; }
     7#targetb:first-letter { color: blue; }
     8#targetc:first-letter { color: blue; }
    79</style>
    810
     
    1113{
    1214    document.body.offsetTop;
    13     document.getElementById("target").innerHTML = "PASS";
     15    document.getElementById("targeta").innerHTML = "PASS";
     16    document.getElementById("targetb").firstChild.data = "PASS";
     17    document.getElementById("targetc").replaceChild(document.createTextNode("PASS"), document.getElementById("targetc").firstChild);
    1418}
    1519</script>
     
    2226</p>
    2327<p>
    24 The next line should read &ldquo;<span style="color: blue;">P</span>ASS&rdquo;, with nothing before the P.
     28The next three lines should all read &ldquo;<span style="color: blue;">P</span>ASS&rdquo;, with nothing before the P.
    2529</p>
    2630<hr>
    27 <p id="target">didn&rsquo;t run</p>
     31<p id="targeta">didn&rsquo;t run</p>
     32<p id="targetb">didn&rsquo;t run</p>
     33<p id="targetc">didn&rsquo;t run</p>
    2834</body>
    2935</html>
  • trunk/LayoutTests/fast/events/updateLayoutForHitTest-expected.txt

    r19343 r21861  
    1515          text run at (14,5) width 48: " Project"
    1616        RenderText {#text} at (0,0) size 0x0
     17selection start: position 0 of child 0 {#text} of child 1 {SPAN} of child 3 {DIV} of child 1 {BODY} of child 0 {HTML} of document
     18selection end:   position 0 of child 1 {#text} of child 3 {DIV} of child 3 {DIV} of child 1 {BODY} of child 0 {HTML} of document
  • trunk/WebCore/ChangeLog

    r21860 r21861  
     12007-05-29  Darin Adler  <darin@apple.com>
     2
     3        Reviewed by Maciej.
     4
     5        - fix http://bugs.webkit.org/show_bug.cgi?id=13602
     6          Amazon product pages keep repainting over and over again
     7
     8        - fix first-letter when the text of the affected text node is changed
     9
     10        Optimize setInnerHTML, setOuterHTML, and setInnerText so they don't change the DOM at all
     11        if they don't need to.
     12
     13        Test: fast/dom/HTMLElement/set-inner-outer-optimization.html
     14        Test: fast/css/first-letter-detach.html
     15
     16        * html/HTMLElement.cpp:
     17        (WebCore::equal): Added. Helper function that compares two Text nodes or two NamedAttrMap
     18        attribute maps.
     19        (WebCore::shallowEqual): Added. Helper function that compares two Element nodes or two
     20        arbitrary nodes.
     21        (WebCore::childrenAreEqual): Added. Helper functions that compare children of nodes.
     22        (WebCore::hasOneChild): Added. Helper function.
     23        (WebCore::hasOneTextChild): Added. Helper function.
     24        (WebCore::replaceChildrenWithFragment): Added. Helper function used by setInnerHTML and
     25        setInnerText. Optimizes the cases where all the nodes are the same, where both the current
     26        and the new content are single text nodes, and where the current content is a single node
     27        that can be replaced with replaceChild.
     28        (WebCore::replaceChildrenWithText): Added. Helper function used by setInnerText. Optimizes
     29        the case where the current content is a single text node or a single node that can be
     30        replaced with replaceChild.
     31        (WebCore::HTMLElement::setInnerHTML): Changed to call replaceChildrenWithFragment.
     32        (WebCore::HTMLElement::setOuterHTML): Added special case to optimize when the new content
     33        exactly matches the current node.
     34        (WebCore::HTMLElement::setInnerText): Changed to call replaceChildrenWithText in a few
     35        cases instead of doing removeChildren/appendChild. Changed code that was using
     36        DeprecatedString to instead use String. Changed general case to use a document fragment
     37        and replaceChildrenWithFragment.
     38
     39        * dom/CharacterData.cpp: (WebCore::CharacterData::dispatchModifiedEvent):
     40        Fixed bug where we would not dispatch the DOMSubtreeModified event unless someone
     41        was registered for the DOMCharacterDataModified event. Caused trouble in the test.
     42
     43        * rendering/RenderBlock.cpp: (WebCore::RenderBlock::updateFirstLetter): Set first-letter
     44        after the setStyle call so calls to setTextInternal inside setStyle don't clear it.
     45
     46        * rendering/RenderText.h: Made setTextInternal virtual so that RenderTextFragment can do
     47        appropriate work when the text changes.
     48
     49        * rendering/RenderTextFragment.h: Added an override of setTextInternal. Removed the
     50        firstLetter parameter to the constructor and made it a separate setter. Also changed
     51        m_generatedContentStr to m_contentString to match the getter function.
     52        * rendering/RenderTextFragment.cpp:
     53        (WebCore::RenderTextFragment::RenderTextFragment): Removed firstLetter parameter.
     54        (WebCore::RenderTextFragment::setTextInternal): When the text changes, destroy the
     55        first-letter node and reset the fragment values so that RenderBlock::updateFirstLetter,
     56        which will run during layout, will create a new first-letter child. Otherwise we end up
     57        with the first letter of the old text.
     58
    1592007-05-29  Sam Weinig  <sam@webkit.org>
    260
  • trunk/WebCore/dom/CharacterData.cpp

    r21287 r21861  
    230230    if (parentNode())
    231231        parentNode()->childrenChanged();
    232     if (!document()->hasListenerType(Document::DOMCHARACTERDATAMODIFIED_LISTENER))
    233         return;
    234 
    235     StringImpl *newValue = str->copy();
    236     newValue->ref();
    237     ExceptionCode ec = 0;
    238     dispatchEvent(new MutationEvent(DOMCharacterDataModifiedEvent,
    239                   true,false,0,prevValue,newValue,String(),0),ec);
    240     newValue->deref();
     232    if (document()->hasListenerType(Document::DOMCHARACTERDATAMODIFIED_LISTENER)) {
     233        StringImpl *newValue = str->copy();
     234        newValue->ref();
     235        ExceptionCode ec = 0;
     236        dispatchEvent(new MutationEvent(DOMCharacterDataModifiedEvent,
     237                      true,false,0,prevValue,newValue,String(),0),ec);
     238        newValue->deref();
     239    }
    241240    dispatchSubtreeModifiedEvent();
    242241}
  • trunk/WebCore/html/HTMLElement.cpp

    r21856 r21861  
    281281}
    282282
    283 void HTMLElement::setInnerHTML(const String &html, ExceptionCode& ec)
     283static inline bool equal(NamedAttrMap* a, NamedAttrMap* b)
     284{
     285    // empty maps; empty and null maps are equivalent
     286    if (!a) {
     287        if (!b)
     288            return true;
     289        return !b->length();
     290    }
     291    if (!b)
     292        return !a->length();
     293
     294    unsigned len = a->length();
     295    if (b->length() != len)
     296        return false;
     297
     298    for (unsigned i = 0; i < len; ++i) {
     299        Attribute* aa = a->attributeItem(i);
     300        Attribute* ba = b->attributeItem(i);
     301        if (aa->name() != ba->name())
     302            return false;
     303        if (aa->value() != ba->value())
     304            return false;
     305    }
     306
     307    return true;
     308}
     309
     310static inline bool shallowEqual(Element* a, Element* b)
     311{
     312    return a->tagQName() == b->tagQName() && equal(a->attributes(false), b->attributes(false));
     313}
     314
     315static bool shallowEqual(Node* a, Node* b)
     316{
     317    Node::NodeType ta = a->nodeType();
     318    Node::NodeType tb = b->nodeType();
     319    if (ta != tb)
     320        return false;
     321
     322    switch (ta) {
     323        case Node::ATTRIBUTE_NODE:
     324        case Node::DOCUMENT_FRAGMENT_NODE:
     325        case Node::DOCUMENT_NODE:
     326        case Node::DOCUMENT_TYPE_NODE:
     327        case Node::ENTITY_NODE:
     328        case Node::ENTITY_REFERENCE_NODE:
     329        case Node::NOTATION_NODE:
     330        case Node::PROCESSING_INSTRUCTION_NODE:
     331        case Node::XPATH_NAMESPACE_NODE:
     332            // Don't bother comparing these node types for now; they don't typically occur.
     333            // Since these functions are used only for optimization, it's OK to have a false negative.
     334            // Also, some of these node types can't occur the subtree of an HTML element,
     335            // and we won't ever call this function for those.
     336            return false;
     337        case Node::CDATA_SECTION_NODE:
     338        case Node::COMMENT_NODE:
     339        case Node::TEXT_NODE:
     340            return equal(static_cast<CharacterData*>(a)->string(), static_cast<CharacterData*>(b)->string());
     341        case Node::ELEMENT_NODE:
     342            return shallowEqual(static_cast<Element*>(a), static_cast<Element*>(b));
     343    }
     344
     345    ASSERT_NOT_REACHED();
     346    return false;
     347}
     348
     349static bool childrenAreEqual(ContainerNode* containerA, ContainerNode* containerB)
     350{
     351    ASSERT(containerA);
     352    ASSERT(containerB);
     353    Node* a = containerA->firstChild();
     354    Node* b = containerB->firstChild();
     355    while (a && b) {
     356        if (!shallowEqual(a, b))
     357            return false;
     358        a = a->traverseNextNode(containerA);
     359        b = b->traverseNextNode(containerB);
     360    }
     361    return !a && !b;
     362}
     363
     364static bool childrenAreEqual(ContainerNode* containerA, ContainerNode* containerB, Node* startNodeA, Node* stopNodeA)
     365{
     366    ASSERT(containerA);
     367    ASSERT(containerB);
     368    ASSERT(startNodeA->parentNode() == containerA);
     369    ASSERT(!stopNodeA || stopNodeA->parentNode() == containerA);
     370    Node* a = startNodeA;
     371    Node* b = containerB->firstChild();
     372    while (a != stopNodeA && b) {
     373        if (!shallowEqual(a, b))
     374            return false;
     375        a = a->traverseNextNode(containerA);
     376        b = b->traverseNextNode(containerB);
     377    }
     378    return a == stopNodeA && !b;
     379}
     380
     381static inline bool hasOneChild(ContainerNode* node)
     382{
     383    Node* firstChild = node->firstChild();
     384    return firstChild && !firstChild->nextSibling();
     385}
     386
     387static inline bool hasOneTextChild(ContainerNode* node)
     388{
     389    return hasOneChild(node) && node->firstChild()->isTextNode();
     390}
     391
     392static void replaceChildrenWithFragment(HTMLElement* element, PassRefPtr<DocumentFragment> fragment, ExceptionCode& ec)
     393{
     394    if (!fragment->firstChild()) {
     395        element->removeChildren();
     396        return;
     397    }
     398
     399    if (childrenAreEqual(element, fragment.get()))
     400        return;
     401
     402    if (hasOneTextChild(element) && hasOneTextChild(fragment.get())) {
     403        static_cast<Text*>(element->firstChild())->setData(static_cast<Text*>(fragment->firstChild())->string(), ec);
     404        return;
     405    }
     406
     407    if (hasOneChild(element)) {
     408        element->replaceChild(fragment, element->firstChild(), ec);
     409        return;
     410    }
     411
     412    element->removeChildren();
     413    element->appendChild(fragment, ec);
     414}
     415
     416static void replaceChildrenWithText(HTMLElement* element, const String& text, ExceptionCode& ec)
     417{
     418    if (hasOneTextChild(element)) {
     419        Text* textChild = static_cast<Text*>(element->firstChild());
     420        if (equal(textChild->string(), text.impl()))
     421            return;
     422        textChild->setData(text, ec);
     423        return;
     424    }
     425
     426    RefPtr<Text> textNode = new Text(element->document(), text);
     427
     428    if (hasOneChild(element)) {
     429        element->replaceChild(textNode.release(), element->firstChild(), ec);
     430        return;
     431    }
     432
     433    element->removeChildren();
     434    element->appendChild(textNode.release(), ec);
     435}
     436
     437void HTMLElement::setInnerHTML(const String& html, ExceptionCode& ec)
    284438{
    285439    RefPtr<DocumentFragment> fragment = createContextualFragment(html);
     
    289443    }
    290444
    291     // FIXME: Add special case for when we had one text child and we just want to set its text?
    292     // FIXME: Add special case for cases where we can use replaceChild?
    293 
    294     removeChildren();
    295     appendChild(fragment.release(), ec);
    296 }
    297 
    298 void HTMLElement::setOuterHTML(const String &html, ExceptionCode& ec)
     445    replaceChildrenWithFragment(this, fragment.release(), ec);
     446}
     447
     448void HTMLElement::setOuterHTML(const String& html, ExceptionCode& ec)
    299449{
    300450    Node* p = parent();
     
    311461    }
    312462
    313     // FIXME: Add special case for when we had one text child and we just want to set its text?
    314463    // FIXME: Why doesn't this have code to merge neighboring text nodes the way setOuterText does?
     464
     465    // Check to see if content is identical.
     466    if (childrenAreEqual(parent, fragment.get(), this, nextSibling()))
     467        return;
     468
    315469    parent->replaceChild(fragment.release(), this, ec);
    316470}
     
    332486
    333487    // FIXME: This doesn't take whitespace collapsing into account at all.
    334     // FIXME: Add special case for when we had one text child and we just want to set its text?
    335     // FIXME: Add special case for cases where we can use replaceChild?
    336 
    337     removeChildren();
    338488
    339489    if (!text.contains('\n') && !text.contains('\r')) {
    340         if (text.isEmpty())
     490        if (text.isEmpty()) {
     491            removeChildren();
    341492            return;
    342         appendChild(new Text(document(), text), ec);
     493        }
     494        replaceChildrenWithText(this, text, ec);
    343495        return;
    344496    }
     
    350502    if (r && r->style()->preserveNewline()) {
    351503        if (!text.contains('\r')) {
    352             appendChild(new Text(document(), text), ec);
     504            replaceChildrenWithText(this, text, ec);
    353505            return;
    354506        }
    355         // FIXME: Stick with String once it has a replace that can do this.
    356         DeprecatedString textWithConsistentLineBreaks = text.deprecatedString();
     507        String textWithConsistentLineBreaks = text;
    357508        textWithConsistentLineBreaks.replace("\r\n", "\n");
    358509        textWithConsistentLineBreaks.replace('\r', '\n');
    359         appendChild(new Text(document(), textWithConsistentLineBreaks), ec);
     510        replaceChildrenWithText(this, textWithConsistentLineBreaks, ec);
    360511        return;
    361512    }
     
    363514    // Add text nodes and <br> elements.
    364515    ec = 0;
     516    RefPtr<DocumentFragment> fragment = new DocumentFragment(document());
    365517    int lineStart = 0;
    366518    UChar prev = 0;
     
    370522        if (c == '\n' || c == '\r') {
    371523            if (i > lineStart) {
    372                 appendChild(new Text(document(), text.substring(lineStart, i - lineStart)), ec);
     524                fragment->appendChild(new Text(document(), text.substring(lineStart, i - lineStart)), ec);
    373525                if (ec)
    374526                    return;
    375527            }
    376528            if (!(c == '\n' && i != 0 && prev == '\r')) {
    377                 appendChild(new HTMLBRElement(document()), ec);
     529                fragment->appendChild(new HTMLBRElement(document()), ec);
    378530                if (ec)
    379531                    return;
     
    384536    }
    385537    if (length > lineStart)
    386         appendChild(new Text(document(), text.substring(lineStart, length - lineStart)), ec);
     538        fragment->appendChild(new Text(document(), text.substring(lineStart, length - lineStart)), ec);
     539    replaceChildrenWithFragment(this, fragment.release(), ec);
    387540}
    388541
  • trunk/WebCore/rendering/RenderBlock.cpp

    r21747 r21861  
    41364136            // NOTE: this might empty
    41374137            RenderTextFragment* remainingText =
    4138                 new (renderArena()) RenderTextFragment(textObj->node(), oldText.get(), length, oldText->length() - length, firstLetter);
     4138                new (renderArena()) RenderTextFragment(textObj->node(), oldText.get(), length, oldText->length() - length);
    41394139            remainingText->setStyle(textObj->style());
     4140            remainingText->setFirstLetter(firstLetter);
    41404141            if (remainingText->element())
    41414142                remainingText->element()->setRenderer(remainingText);
  • trunk/WebCore/rendering/RenderText.h

    r21387 r21861  
    128128
    129129protected:
    130     void setTextInternal(PassRefPtr<StringImpl>);
     130    virtual void setTextInternal(PassRefPtr<StringImpl>);
    131131    virtual void calcPrefWidths(int leadWidth);
    132132
  • trunk/WebCore/rendering/RenderTextFragment.cpp

    r19027 r21861  
    1 /**
    2  * This file is part of the DOM implementation for KDE.
    3  *
     1/*
    42 * (C) 1999 Lars Knoll (knoll@kde.org)
    53 * (C) 2000 Dirk Mueller (mueller@kde.org)
    6  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
     4 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
    75 *
    86 * This library is free software; you can redistribute it and/or
     
    3028namespace WebCore {
    3129
    32 RenderTextFragment::RenderTextFragment(Node* node, StringImpl* str, int startOffset, int length, RenderObject* firstLetter)
     30RenderTextFragment::RenderTextFragment(Node* node, StringImpl* str, int startOffset, int length)
    3331    : RenderText(node, str ? str->substring(startOffset, length) : 0)
    3432    , m_start(startOffset)
    3533    , m_end(length)
    36     , m_firstLetter(firstLetter)
     34    , m_firstLetter(0)
    3735{
    3836}
     
    4240    , m_start(0)
    4341    , m_end(str ? str->length() : 0)
    44     , m_generatedContentStr(str)
     42    , m_contentString(str)
    4543    , m_firstLetter(0)
    4644{
     
    5856void RenderTextFragment::destroy()
    5957{
    60     if (firstLetter())
    61         firstLetter()->destroy();
     58    if (m_firstLetter)
     59        m_firstLetter->destroy();
    6260    RenderText::destroy();
    6361}
    6462
     63void RenderTextFragment::setTextInternal(PassRefPtr<StringImpl> text)
     64{
     65    RenderText::setTextInternal(text);
     66    if (m_firstLetter) {
     67        ASSERT(!m_contentString);
     68        m_firstLetter->destroy();
     69        m_firstLetter = 0;
     70        m_start = 0;
     71        m_end = textLength();
     72    }
     73}
     74
    6575} // namespace WebCore
  • trunk/WebCore/rendering/RenderTextFragment.h

    r19027 r21861  
    11/*
    2  * This file is part of the DOM implementation for KDE.
    3  *
    42 * (C) 1999 Lars Knoll (knoll@kde.org)
    53 * (C) 2000 Dirk Mueller (mueller@kde.org)
    6  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
     4 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
    75 *
    86 * This library is free software; you can redistribute it and/or
     
    3634class RenderTextFragment : public RenderText {
    3735public:
    38     RenderTextFragment(Node*, StringImpl*, int startOffset, int length, RenderObject* firstLetter = 0);
     36    RenderTextFragment(Node*, StringImpl*, int startOffset, int length);
    3937    RenderTextFragment(Node*, StringImpl*);
    4038
     
    4543    unsigned start() const { return m_start; }
    4644    unsigned end() const { return m_end; }
     45
    4746    RenderObject* firstLetter() const { return m_firstLetter; }
     47    void setFirstLetter(RenderObject* firstLetter) { m_firstLetter = firstLetter; }
    4848
    49     StringImpl* contentString() const { return m_generatedContentStr.get(); }
     49    StringImpl* contentString() const { return m_contentString.get(); }
    5050    virtual PassRefPtr<StringImpl> originalText() const;
    5151
    5252private:
     53    virtual void setTextInternal(PassRefPtr<StringImpl>);
     54
    5355    unsigned m_start;
    5456    unsigned m_end;
    55     RefPtr<StringImpl> m_generatedContentStr;
     57    RefPtr<StringImpl> m_contentString;
    5658    RenderObject* m_firstLetter;
    5759};
Note: See TracChangeset for help on using the changeset viewer.