Home | History | Annotate | Download | only in rendering
      1 /*
      2  * (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  * (C) 2000 Dirk Mueller (mueller (at) kde.org)
      4  * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
      5  *
      6  * This library is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU Library General Public
      8  * License as published by the Free Software Foundation; either
      9  * version 2 of the License, or (at your option) any later version.
     10  *
     11  * This library is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  * Library General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU Library General Public License
     17  * along with this library; see the file COPYING.LIB.  If not, write to
     18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     19  * Boston, MA 02110-1301, USA.
     20  *
     21  */
     22 
     23 #include "config.h"
     24 #include "core/rendering/RenderTextFragment.h"
     25 
     26 #include "core/dom/Text.h"
     27 #include "core/rendering/HitTestResult.h"
     28 #include "core/rendering/RenderBlock.h"
     29 
     30 namespace WebCore {
     31 
     32 RenderTextFragment::RenderTextFragment(Node* node, StringImpl* str, int startOffset, int length)
     33     : RenderText(node, str ? str->substring(startOffset, length) : PassRefPtr<StringImpl>(0))
     34     , m_start(startOffset)
     35     , m_end(length)
     36     , m_firstLetter(0)
     37 {
     38 }
     39 
     40 RenderTextFragment::RenderTextFragment(Node* node, StringImpl* str)
     41     : RenderText(node, str)
     42     , m_start(0)
     43     , m_end(str ? str->length() : 0)
     44     , m_contentString(str)
     45     , m_firstLetter(0)
     46 {
     47 }
     48 
     49 RenderTextFragment::~RenderTextFragment()
     50 {
     51 }
     52 
     53 RenderText* RenderTextFragment::firstRenderTextInFirstLetter() const
     54 {
     55     for (RenderObject* current = m_firstLetter; current; current = current->nextInPreOrder(m_firstLetter)) {
     56         if (current->isText())
     57             return toRenderText(current);
     58     }
     59     return 0;
     60 }
     61 
     62 PassRefPtr<StringImpl> RenderTextFragment::originalText() const
     63 {
     64     Node* e = node();
     65     RefPtr<StringImpl> result = ((e && e->isTextNode()) ? toText(e)->dataImpl() : contentString());
     66     if (!result)
     67         return 0;
     68     return result->substring(start(), end());
     69 }
     70 
     71 void RenderTextFragment::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
     72 {
     73     RenderText::styleDidChange(diff, oldStyle);
     74 
     75     if (RenderBlock* block = blockForAccompanyingFirstLetter()) {
     76         block->style()->removeCachedPseudoStyle(FIRST_LETTER);
     77         block->updateFirstLetter();
     78     }
     79 }
     80 
     81 void RenderTextFragment::willBeDestroyed()
     82 {
     83     if (m_firstLetter)
     84         m_firstLetter->destroy();
     85     RenderText::willBeDestroyed();
     86 }
     87 
     88 void RenderTextFragment::setText(PassRefPtr<StringImpl> text, bool force)
     89 {
     90     RenderText::setText(text, force);
     91 
     92     m_start = 0;
     93     m_end = textLength();
     94     if (m_firstLetter) {
     95         ASSERT(!m_contentString);
     96         m_firstLetter->destroy();
     97         m_firstLetter = 0;
     98         if (Node* t = node()) {
     99             ASSERT(!t->renderer());
    100             t->setRenderer(this);
    101         }
    102     }
    103 }
    104 
    105 void RenderTextFragment::transformText()
    106 {
    107     // Don't reset first-letter here because we are only transforming the truncated fragment.
    108     if (RefPtr<StringImpl> textToTransform = originalText())
    109         RenderText::setText(textToTransform.release(), true);
    110 }
    111 
    112 UChar RenderTextFragment::previousCharacter() const
    113 {
    114     if (start()) {
    115         Node* e = node();
    116         StringImpl* original = ((e && e->isTextNode()) ? toText(e)->dataImpl() : contentString());
    117         if (original && start() <= original->length())
    118             return (*original)[start() - 1];
    119     }
    120 
    121     return RenderText::previousCharacter();
    122 }
    123 
    124 RenderBlock* RenderTextFragment::blockForAccompanyingFirstLetter() const
    125 {
    126     if (!m_firstLetter)
    127         return 0;
    128     for (RenderObject* block = m_firstLetter->parent(); block; block = block->parent()) {
    129         if (block->style()->hasPseudoStyle(FIRST_LETTER) && block->canHaveChildren() && block->isRenderBlock())
    130             return toRenderBlock(block);
    131     }
    132     return 0;
    133 }
    134 
    135 void RenderTextFragment::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
    136 {
    137     if (result.innerNode())
    138         return;
    139 
    140     RenderObject::updateHitTestResult(result, point);
    141     if (m_firstLetter || !node())
    142         return;
    143     RenderObject* nodeRenderer = node()->renderer();
    144     if (!nodeRenderer || !nodeRenderer->isText() || !toRenderText(nodeRenderer)->isTextFragment())
    145         return;
    146 
    147     if (isDescendantOf(toRenderTextFragment(nodeRenderer)->m_firstLetter))
    148         result.setIsFirstLetter(true);
    149 }
    150 
    151 } // namespace WebCore
    152