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 0; 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 0; 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 RefPtr<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