Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright (C) 2013 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "core/rendering/AbstractInlineTextBox.h"
     33 
     34 #include "core/editing/TextIterator.h"
     35 #include "platform/text/TextBreakIterator.h"
     36 
     37 namespace WebCore {
     38 
     39 AbstractInlineTextBox::InlineToAbstractInlineTextBoxHashMap* AbstractInlineTextBox::gAbstractInlineTextBoxMap = 0;
     40 
     41 PassRefPtr<AbstractInlineTextBox> AbstractInlineTextBox::getOrCreate(RenderText* renderText, InlineTextBox* inlineTextBox)
     42 {
     43     if (!inlineTextBox)
     44         return nullptr;
     45 
     46     if (!gAbstractInlineTextBoxMap)
     47         gAbstractInlineTextBoxMap = new InlineToAbstractInlineTextBoxHashMap();
     48 
     49     InlineToAbstractInlineTextBoxHashMap::const_iterator it = gAbstractInlineTextBoxMap->find(inlineTextBox);
     50     if (it != gAbstractInlineTextBoxMap->end())
     51         return it->value;
     52 
     53     RefPtr<AbstractInlineTextBox> obj = adoptRef(new AbstractInlineTextBox(renderText, inlineTextBox));
     54     gAbstractInlineTextBoxMap->set(inlineTextBox, obj);
     55     return obj;
     56 }
     57 
     58 void AbstractInlineTextBox::willDestroy(InlineTextBox* inlineTextBox)
     59 {
     60     if (!gAbstractInlineTextBoxMap)
     61         return;
     62 
     63     InlineToAbstractInlineTextBoxHashMap::const_iterator it = gAbstractInlineTextBoxMap->find(inlineTextBox);
     64     if (it != gAbstractInlineTextBoxMap->end()) {
     65         it->value->detach();
     66         gAbstractInlineTextBoxMap->remove(inlineTextBox);
     67     }
     68 }
     69 
     70 void AbstractInlineTextBox::detach()
     71 {
     72     m_renderText = 0;
     73     m_inlineTextBox = 0;
     74 }
     75 
     76 PassRefPtr<AbstractInlineTextBox> AbstractInlineTextBox::nextInlineTextBox() const
     77 {
     78     if (!m_inlineTextBox)
     79         return nullptr;
     80 
     81     return getOrCreate(m_renderText, m_inlineTextBox->nextTextBox());
     82 }
     83 
     84 LayoutRect AbstractInlineTextBox::bounds() const
     85 {
     86     if (!m_inlineTextBox || !m_renderText)
     87         return LayoutRect();
     88 
     89     FloatRect boundaries = m_inlineTextBox->calculateBoundaries();
     90     return m_renderText->localToAbsoluteQuad(boundaries).enclosingBoundingBox();
     91 }
     92 
     93 unsigned AbstractInlineTextBox::start() const
     94 {
     95     if (!m_inlineTextBox)
     96         return 0;
     97 
     98     return m_inlineTextBox->start();
     99 }
    100 
    101 unsigned AbstractInlineTextBox::len() const
    102 {
    103     if (!m_inlineTextBox)
    104         return 0;
    105 
    106     return m_inlineTextBox->len();
    107 }
    108 
    109 AbstractInlineTextBox::Direction AbstractInlineTextBox::direction() const
    110 {
    111     if (!m_inlineTextBox || !m_renderText)
    112         return LeftToRight;
    113 
    114     if (m_renderText->style()->isHorizontalWritingMode())
    115         return (m_inlineTextBox->direction() == RTL ? RightToLeft : LeftToRight);
    116     return (m_inlineTextBox->direction() == RTL ? BottomToTop : TopToBottom);
    117 }
    118 
    119 void AbstractInlineTextBox::characterWidths(Vector<float>& widths) const
    120 {
    121     if (!m_inlineTextBox)
    122         return;
    123 
    124     m_inlineTextBox->characterWidths(widths);
    125 }
    126 
    127 void AbstractInlineTextBox::wordBoundaries(Vector<WordBoundaries>& words) const
    128 {
    129     if (!m_inlineTextBox)
    130         return;
    131 
    132     String text = this->text();
    133     int len = text.length();
    134     TextBreakIterator* iterator = wordBreakIterator(text, 0, len);
    135     int pos = iterator->first();
    136     while (pos >= 0 && pos < len) {
    137         int next = iterator->next();
    138         if (isWordTextBreak(iterator))
    139             words.append(WordBoundaries(pos, next));
    140         pos = next;
    141     }
    142 }
    143 
    144 String AbstractInlineTextBox::text() const
    145 {
    146     if (!m_inlineTextBox || !m_renderText)
    147         return String();
    148 
    149     unsigned start = m_inlineTextBox->start();
    150     unsigned len = m_inlineTextBox->len();
    151     if (Node* node = m_renderText->node()) {
    152         RefPtrWillBeRawPtr<Range> range = Range::create(node->document());
    153         range->setStart(node, start, IGNORE_EXCEPTION);
    154         range->setEnd(node, start + len, IGNORE_EXCEPTION);
    155         return plainText(range.get(), TextIteratorIgnoresStyleVisibility);
    156     }
    157 
    158     String result = m_renderText->text().substring(start, len).simplifyWhiteSpace(WTF::DoNotStripWhiteSpace);
    159     if (m_inlineTextBox->nextTextBox() && m_inlineTextBox->nextTextBox()->start() > m_inlineTextBox->end() && result.length() && !result.right(1).containsOnlyWhitespace())
    160         return result + " ";
    161     return result;
    162 }
    163 
    164 } // namespace WebCore
    165