| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) |
| 3 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010 Apple Inc. All right r
eserved. | 3 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010 Apple Inc. All right r
eserved. |
| 4 * Copyright (C) 2010 Google Inc. All rights reserved. | 4 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 5 * | 5 * |
| 6 * This library is free software; you can redistribute it and/or | 6 * This library is free software; you can redistribute it and/or |
| 7 * modify it under the terms of the GNU Library General Public | 7 * modify it under the terms of the GNU Library General Public |
| 8 * License as published by the Free Software Foundation; either | 8 * License as published by the Free Software Foundation; either |
| 9 * version 2 of the License, or (at your option) any later version. | 9 * version 2 of the License, or (at your option) any later version. |
| 10 * | 10 * |
| 11 * This library is distributed in the hope that it will be useful, | 11 * This library is distributed in the hope that it will be useful, |
| 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 * Library General Public License for more details. | 14 * Library General Public License for more details. |
| 15 * | 15 * |
| 16 * You should have received a copy of the GNU Library General Public License | 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 | 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, | 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 19 * Boston, MA 02110-1301, USA. | 19 * Boston, MA 02110-1301, USA. |
| 20 * | 20 * |
| 21 */ | 21 */ |
| 22 | 22 |
| 23 #ifndef InlineIterator_h | 23 #ifndef InlineIterator_h |
| 24 #define InlineIterator_h | 24 #define InlineIterator_h |
| 25 | 25 |
| 26 #include "core/layout/BidiRun.h" | 26 #include "core/layout/BidiRun.h" |
| 27 #include "core/layout/LayoutText.h" |
| 27 #include "core/rendering/RenderBlockFlow.h" | 28 #include "core/rendering/RenderBlockFlow.h" |
| 28 #include "core/rendering/RenderInline.h" | 29 #include "core/rendering/RenderInline.h" |
| 29 #include "core/rendering/RenderText.h" | |
| 30 #include "wtf/StdLibExtras.h" | 30 #include "wtf/StdLibExtras.h" |
| 31 | 31 |
| 32 namespace blink { | 32 namespace blink { |
| 33 | 33 |
| 34 // This class is used to RenderInline subtrees, stepping by character within the | 34 // This class is used to RenderInline subtrees, stepping by character within the |
| 35 // text children. InlineIterator will use bidiNext to find the next RenderText | 35 // text children. InlineIterator will use bidiNext to find the next LayoutText |
| 36 // optionally notifying a BidiResolver every time it steps into/out of a RenderI
nline. | 36 // optionally notifying a BidiResolver every time it steps into/out of a RenderI
nline. |
| 37 class InlineIterator { | 37 class InlineIterator { |
| 38 public: | 38 public: |
| 39 enum IncrementRule { | 39 enum IncrementRule { |
| 40 FastIncrementInIsolatedRenderer, | 40 FastIncrementInIsolatedRenderer, |
| 41 FastIncrementInTextNode | 41 FastIncrementInTextNode |
| 42 }; | 42 }; |
| 43 | 43 |
| 44 InlineIterator() | 44 InlineIterator() |
| 45 : m_root(0) | 45 : m_root(0) |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 unsigned offset() const { return m_pos; } | 80 unsigned offset() const { return m_pos; } |
| 81 void setOffset(unsigned position) { m_pos = position; } | 81 void setOffset(unsigned position) { m_pos = position; } |
| 82 LayoutObject* root() const { return m_root; } | 82 LayoutObject* root() const { return m_root; } |
| 83 | 83 |
| 84 void fastIncrementInTextNode(); | 84 void fastIncrementInTextNode(); |
| 85 void increment(InlineBidiResolver* = 0, IncrementRule = FastIncrementInTextN
ode); | 85 void increment(InlineBidiResolver* = 0, IncrementRule = FastIncrementInTextN
ode); |
| 86 bool atEnd() const; | 86 bool atEnd() const; |
| 87 | 87 |
| 88 inline bool atTextParagraphSeparator() const | 88 inline bool atTextParagraphSeparator() const |
| 89 { | 89 { |
| 90 return m_obj && m_obj->preservesNewline() && m_obj->isText() && toRender
Text(m_obj)->textLength() | 90 return m_obj && m_obj->preservesNewline() && m_obj->isText() && toLayout
Text(m_obj)->textLength() |
| 91 && !toRenderText(m_obj)->isWordBreak() && toRenderText(m_obj)->chara
cterAt(m_pos) == '\n'; | 91 && !toLayoutText(m_obj)->isWordBreak() && toLayoutText(m_obj)->chara
cterAt(m_pos) == '\n'; |
| 92 } | 92 } |
| 93 | 93 |
| 94 inline bool atParagraphSeparator() const | 94 inline bool atParagraphSeparator() const |
| 95 { | 95 { |
| 96 return (m_obj && m_obj->isBR()) || atTextParagraphSeparator(); | 96 return (m_obj && m_obj->isBR()) || atTextParagraphSeparator(); |
| 97 } | 97 } |
| 98 | 98 |
| 99 UChar characterAt(unsigned) const; | 99 UChar characterAt(unsigned) const; |
| 100 UChar current() const; | 100 UChar current() const; |
| 101 UChar previousInSameNode() const; | 101 UChar previousInSameNode() const; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 }; | 186 }; |
| 187 | 187 |
| 188 static bool isEmptyInline(LayoutObject* object) | 188 static bool isEmptyInline(LayoutObject* object) |
| 189 { | 189 { |
| 190 if (!object->isRenderInline()) | 190 if (!object->isRenderInline()) |
| 191 return false; | 191 return false; |
| 192 | 192 |
| 193 for (LayoutObject* curr = toRenderInline(object)->firstChild(); curr; curr =
curr->nextSibling()) { | 193 for (LayoutObject* curr = toRenderInline(object)->firstChild(); curr; curr =
curr->nextSibling()) { |
| 194 if (curr->isFloatingOrOutOfFlowPositioned()) | 194 if (curr->isFloatingOrOutOfFlowPositioned()) |
| 195 continue; | 195 continue; |
| 196 if (curr->isText() && toRenderText(curr)->isAllCollapsibleWhitespace()) | 196 if (curr->isText() && toLayoutText(curr)->isAllCollapsibleWhitespace()) |
| 197 continue; | 197 continue; |
| 198 | 198 |
| 199 if (!isEmptyInline(curr)) | 199 if (!isEmptyInline(curr)) |
| 200 return false; | 200 return false; |
| 201 } | 201 } |
| 202 return true; | 202 return true; |
| 203 } | 203 } |
| 204 | 204 |
| 205 // FIXME: This function is misleadingly named. It has little to do with bidi. | 205 // FIXME: This function is misleadingly named. It has little to do with bidi. |
| 206 // This function will iterate over inlines within a block, optionally notifying | 206 // This function will iterate over inlines within a block, optionally notifying |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 if (!o || o->isRenderInline() || isIteratorTarget(o)) | 319 if (!o || o->isRenderInline() || isIteratorTarget(o)) |
| 320 return o; | 320 return o; |
| 321 | 321 |
| 322 return bidiNextIncludingEmptyInlines(root, o); | 322 return bidiNextIncludingEmptyInlines(root, o); |
| 323 } | 323 } |
| 324 | 324 |
| 325 inline void InlineIterator::fastIncrementInTextNode() | 325 inline void InlineIterator::fastIncrementInTextNode() |
| 326 { | 326 { |
| 327 ASSERT(m_obj); | 327 ASSERT(m_obj); |
| 328 ASSERT(m_obj->isText()); | 328 ASSERT(m_obj->isText()); |
| 329 ASSERT(m_pos <= toRenderText(m_obj)->textLength()); | 329 ASSERT(m_pos <= toLayoutText(m_obj)->textLength()); |
| 330 if (m_pos < INT_MAX) | 330 if (m_pos < INT_MAX) |
| 331 m_pos++; | 331 m_pos++; |
| 332 } | 332 } |
| 333 | 333 |
| 334 // FIXME: This is used by RenderBlockFlow for simplified layout, and has nothing
to do with bidi | 334 // FIXME: This is used by RenderBlockFlow for simplified layout, and has nothing
to do with bidi |
| 335 // it shouldn't use functions called bidiFirst and bidiNext. | 335 // it shouldn't use functions called bidiFirst and bidiNext. |
| 336 class InlineWalker { | 336 class InlineWalker { |
| 337 public: | 337 public: |
| 338 InlineWalker(RenderBlock* root) | 338 InlineWalker(RenderBlock* root) |
| 339 : m_root(root) | 339 : m_root(root) |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 | 383 |
| 384 if (rule == FastIncrementInIsolatedRenderer | 384 if (rule == FastIncrementInIsolatedRenderer |
| 385 && resolver && resolver->inIsolate() | 385 && resolver && resolver->inIsolate() |
| 386 && !endOfLineHasIsolatedObjectAncestor(resolver->endOfLine(), resolver->
position())) { | 386 && !endOfLineHasIsolatedObjectAncestor(resolver->endOfLine(), resolver->
position())) { |
| 387 moveTo(bidiNextSkippingEmptyInlines(m_root, m_obj, resolver), 0); | 387 moveTo(bidiNextSkippingEmptyInlines(m_root, m_obj, resolver), 0); |
| 388 return; | 388 return; |
| 389 } | 389 } |
| 390 | 390 |
| 391 if (m_obj->isText()) { | 391 if (m_obj->isText()) { |
| 392 fastIncrementInTextNode(); | 392 fastIncrementInTextNode(); |
| 393 if (m_pos < toRenderText(m_obj)->textLength()) | 393 if (m_pos < toLayoutText(m_obj)->textLength()) |
| 394 return; | 394 return; |
| 395 } | 395 } |
| 396 // bidiNext can return 0, so use moveTo instead of moveToStartOf | 396 // bidiNext can return 0, so use moveTo instead of moveToStartOf |
| 397 moveTo(bidiNextSkippingEmptyInlines(m_root, m_obj, resolver), 0); | 397 moveTo(bidiNextSkippingEmptyInlines(m_root, m_obj, resolver), 0); |
| 398 } | 398 } |
| 399 | 399 |
| 400 inline bool InlineIterator::atEnd() const | 400 inline bool InlineIterator::atEnd() const |
| 401 { | 401 { |
| 402 return !m_obj; | 402 return !m_obj; |
| 403 } | 403 } |
| 404 | 404 |
| 405 inline UChar InlineIterator::characterAt(unsigned index) const | 405 inline UChar InlineIterator::characterAt(unsigned index) const |
| 406 { | 406 { |
| 407 if (!m_obj || !m_obj->isText()) | 407 if (!m_obj || !m_obj->isText()) |
| 408 return 0; | 408 return 0; |
| 409 | 409 |
| 410 return toRenderText(m_obj)->characterAt(index); | 410 return toLayoutText(m_obj)->characterAt(index); |
| 411 } | 411 } |
| 412 | 412 |
| 413 inline UChar InlineIterator::current() const | 413 inline UChar InlineIterator::current() const |
| 414 { | 414 { |
| 415 return characterAt(m_pos); | 415 return characterAt(m_pos); |
| 416 } | 416 } |
| 417 | 417 |
| 418 inline UChar InlineIterator::previousInSameNode() const | 418 inline UChar InlineIterator::previousInSameNode() const |
| 419 { | 419 { |
| 420 if (!m_pos) | 420 if (!m_pos) |
| (...skipping 24 matching lines...) Expand all Loading... |
| 445 { | 445 { |
| 446 bool inEndOfLine = m_current == end || m_current.atEnd() || (inIsolate() &&
m_current.object() == end.object()); | 446 bool inEndOfLine = m_current == end || m_current.atEnd() || (inIsolate() &&
m_current.object() == end.object()); |
| 447 if (inIsolate() && inEndOfLine) { | 447 if (inIsolate() && inEndOfLine) { |
| 448 m_current.moveTo(m_current.object(), end.offset(), m_current.nextBreakab
lePosition()); | 448 m_current.moveTo(m_current.object(), end.offset(), m_current.nextBreakab
lePosition()); |
| 449 m_last = m_current; | 449 m_last = m_current; |
| 450 updateStatusLastFromCurrentDirection(WTF::Unicode::OtherNeutral); | 450 updateStatusLastFromCurrentDirection(WTF::Unicode::OtherNeutral); |
| 451 } | 451 } |
| 452 return inEndOfLine; | 452 return inEndOfLine; |
| 453 } | 453 } |
| 454 | 454 |
| 455 static inline bool isCollapsibleSpace(UChar character, RenderText* renderer) | 455 static inline bool isCollapsibleSpace(UChar character, LayoutText* renderer) |
| 456 { | 456 { |
| 457 if (character == ' ' || character == '\t' || character == softHyphen) | 457 if (character == ' ' || character == '\t' || character == softHyphen) |
| 458 return true; | 458 return true; |
| 459 if (character == '\n') | 459 if (character == '\n') |
| 460 return !renderer->style()->preserveNewline(); | 460 return !renderer->style()->preserveNewline(); |
| 461 return false; | 461 return false; |
| 462 } | 462 } |
| 463 | 463 |
| 464 template <typename CharacterType> | 464 template <typename CharacterType> |
| 465 static inline int findFirstTrailingSpace(RenderText* lastText, const CharacterTy
pe* characters, int start, int stop) | 465 static inline int findFirstTrailingSpace(LayoutText* lastText, const CharacterTy
pe* characters, int start, int stop) |
| 466 { | 466 { |
| 467 int firstSpace = stop; | 467 int firstSpace = stop; |
| 468 while (firstSpace > start) { | 468 while (firstSpace > start) { |
| 469 UChar current = characters[firstSpace - 1]; | 469 UChar current = characters[firstSpace - 1]; |
| 470 if (!isCollapsibleSpace(current, lastText)) | 470 if (!isCollapsibleSpace(current, lastText)) |
| 471 break; | 471 break; |
| 472 firstSpace--; | 472 firstSpace--; |
| 473 } | 473 } |
| 474 | 474 |
| 475 return firstSpace; | 475 return firstSpace; |
| 476 } | 476 } |
| 477 | 477 |
| 478 template <> | 478 template <> |
| 479 inline int InlineBidiResolver::findFirstTrailingSpaceAtRun(BidiRun* run) | 479 inline int InlineBidiResolver::findFirstTrailingSpaceAtRun(BidiRun* run) |
| 480 { | 480 { |
| 481 ASSERT(run); | 481 ASSERT(run); |
| 482 LayoutObject* lastObject = run->m_object; | 482 LayoutObject* lastObject = run->m_object; |
| 483 if (!lastObject->isText()) | 483 if (!lastObject->isText()) |
| 484 return run->m_stop; | 484 return run->m_stop; |
| 485 | 485 |
| 486 RenderText* lastText = toRenderText(lastObject); | 486 LayoutText* lastText = toLayoutText(lastObject); |
| 487 int firstSpace; | 487 int firstSpace; |
| 488 if (lastText->is8Bit()) | 488 if (lastText->is8Bit()) |
| 489 firstSpace = findFirstTrailingSpace(lastText, lastText->characters8(), r
un->start(), run->stop()); | 489 firstSpace = findFirstTrailingSpace(lastText, lastText->characters8(), r
un->start(), run->stop()); |
| 490 else | 490 else |
| 491 firstSpace = findFirstTrailingSpace(lastText, lastText->characters16(),
run->start(), run->stop()); | 491 firstSpace = findFirstTrailingSpace(lastText, lastText->characters16(),
run->start(), run->stop()); |
| 492 return firstSpace; | 492 return firstSpace; |
| 493 } | 493 } |
| 494 | 494 |
| 495 template <> | 495 template <> |
| 496 inline BidiRun* InlineBidiResolver::addTrailingRun(BidiRunList<BidiRun>& runs, i
nt start, int stop, BidiRun* run, BidiContext* context, TextDirection direction)
const | 496 inline BidiRun* InlineBidiResolver::addTrailingRun(BidiRunList<BidiRun>& runs, i
nt start, int stop, BidiRun* run, BidiContext* context, TextDirection direction)
const |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 736 m_sor = m_eor; | 736 m_sor = m_eor; |
| 737 } | 737 } |
| 738 | 738 |
| 739 m_direction = WTF::Unicode::OtherNeutral; | 739 m_direction = WTF::Unicode::OtherNeutral; |
| 740 m_status.eor = WTF::Unicode::OtherNeutral; | 740 m_status.eor = WTF::Unicode::OtherNeutral; |
| 741 } | 741 } |
| 742 | 742 |
| 743 } | 743 } |
| 744 | 744 |
| 745 #endif // InlineIterator_h | 745 #endif // InlineIterator_h |
| OLD | NEW |