| 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/LayoutBlockFlow.h" | 27 #include "core/layout/LayoutBlockFlow.h" |
| 28 #include "core/layout/LayoutInline.h" | 28 #include "core/layout/LayoutInline.h" |
| 29 #include "core/rendering/RenderText.h" | 29 #include "core/layout/LayoutText.h" |
| 30 |
| 30 #include "wtf/StdLibExtras.h" | 31 #include "wtf/StdLibExtras.h" |
| 31 | 32 |
| 32 namespace blink { | 33 namespace blink { |
| 33 | 34 |
| 34 // This class is used to LayoutInline subtrees, stepping by character within the | 35 // This class is used to LayoutInline subtrees, stepping by character within the |
| 35 // text children. InlineIterator will use bidiNext to find the next RenderText | 36 // text children. InlineIterator will use bidiNext to find the next LayoutText |
| 36 // optionally notifying a BidiResolver every time it steps into/out of a LayoutI
nline. | 37 // optionally notifying a BidiResolver every time it steps into/out of a LayoutI
nline. |
| 37 class InlineIterator { | 38 class InlineIterator { |
| 38 public: | 39 public: |
| 39 enum IncrementRule { | 40 enum IncrementRule { |
| 40 FastIncrementInIsolatedRenderer, | 41 FastIncrementInIsolatedRenderer, |
| 41 FastIncrementInTextNode | 42 FastIncrementInTextNode |
| 42 }; | 43 }; |
| 43 | 44 |
| 44 InlineIterator() | 45 InlineIterator() |
| 45 : m_root(0) | 46 : m_root(0) |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 unsigned offset() const { return m_pos; } | 81 unsigned offset() const { return m_pos; } |
| 81 void setOffset(unsigned position) { m_pos = position; } | 82 void setOffset(unsigned position) { m_pos = position; } |
| 82 LayoutObject* root() const { return m_root; } | 83 LayoutObject* root() const { return m_root; } |
| 83 | 84 |
| 84 void fastIncrementInTextNode(); | 85 void fastIncrementInTextNode(); |
| 85 void increment(InlineBidiResolver* = 0, IncrementRule = FastIncrementInTextN
ode); | 86 void increment(InlineBidiResolver* = 0, IncrementRule = FastIncrementInTextN
ode); |
| 86 bool atEnd() const; | 87 bool atEnd() const; |
| 87 | 88 |
| 88 inline bool atTextParagraphSeparator() const | 89 inline bool atTextParagraphSeparator() const |
| 89 { | 90 { |
| 90 return m_obj && m_obj->preservesNewline() && m_obj->isText() && toRender
Text(m_obj)->textLength() | 91 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'; | 92 && !toLayoutText(m_obj)->isWordBreak() && toLayoutText(m_obj)->chara
cterAt(m_pos) == '\n'; |
| 92 } | 93 } |
| 93 | 94 |
| 94 inline bool atParagraphSeparator() const | 95 inline bool atParagraphSeparator() const |
| 95 { | 96 { |
| 96 return (m_obj && m_obj->isBR()) || atTextParagraphSeparator(); | 97 return (m_obj && m_obj->isBR()) || atTextParagraphSeparator(); |
| 97 } | 98 } |
| 98 | 99 |
| 99 UChar characterAt(unsigned) const; | 100 UChar characterAt(unsigned) const; |
| 100 UChar current() const; | 101 UChar current() const; |
| 101 UChar previousInSameNode() const; | 102 UChar previousInSameNode() const; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 }; | 187 }; |
| 187 | 188 |
| 188 static bool isEmptyInline(LayoutObject* object) | 189 static bool isEmptyInline(LayoutObject* object) |
| 189 { | 190 { |
| 190 if (!object->isLayoutInline()) | 191 if (!object->isLayoutInline()) |
| 191 return false; | 192 return false; |
| 192 | 193 |
| 193 for (LayoutObject* curr = toLayoutInline(object)->firstChild(); curr; curr =
curr->nextSibling()) { | 194 for (LayoutObject* curr = toLayoutInline(object)->firstChild(); curr; curr =
curr->nextSibling()) { |
| 194 if (curr->isFloatingOrOutOfFlowPositioned()) | 195 if (curr->isFloatingOrOutOfFlowPositioned()) |
| 195 continue; | 196 continue; |
| 196 if (curr->isText() && toRenderText(curr)->isAllCollapsibleWhitespace()) | 197 if (curr->isText() && toLayoutText(curr)->isAllCollapsibleWhitespace()) |
| 197 continue; | 198 continue; |
| 198 | 199 |
| 199 if (!isEmptyInline(curr)) | 200 if (!isEmptyInline(curr)) |
| 200 return false; | 201 return false; |
| 201 } | 202 } |
| 202 return true; | 203 return true; |
| 203 } | 204 } |
| 204 | 205 |
| 205 // FIXME: This function is misleadingly named. It has little to do with bidi. | 206 // 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 | 207 // 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->isLayoutInline() || isIteratorTarget(o)) | 320 if (!o || o->isLayoutInline() || isIteratorTarget(o)) |
| 320 return o; | 321 return o; |
| 321 | 322 |
| 322 return bidiNextIncludingEmptyInlines(root, o); | 323 return bidiNextIncludingEmptyInlines(root, o); |
| 323 } | 324 } |
| 324 | 325 |
| 325 inline void InlineIterator::fastIncrementInTextNode() | 326 inline void InlineIterator::fastIncrementInTextNode() |
| 326 { | 327 { |
| 327 ASSERT(m_obj); | 328 ASSERT(m_obj); |
| 328 ASSERT(m_obj->isText()); | 329 ASSERT(m_obj->isText()); |
| 329 ASSERT(m_pos <= toRenderText(m_obj)->textLength()); | 330 ASSERT(m_pos <= toLayoutText(m_obj)->textLength()); |
| 330 if (m_pos < INT_MAX) | 331 if (m_pos < INT_MAX) |
| 331 m_pos++; | 332 m_pos++; |
| 332 } | 333 } |
| 333 | 334 |
| 334 // FIXME: This is used by LayoutBlockFlow for simplified layout, and has nothing
to do with bidi | 335 // FIXME: This is used by LayoutBlockFlow for simplified layout, and has nothing
to do with bidi |
| 335 // it shouldn't use functions called bidiFirst and bidiNext. | 336 // it shouldn't use functions called bidiFirst and bidiNext. |
| 336 class InlineWalker { | 337 class InlineWalker { |
| 337 public: | 338 public: |
| 338 InlineWalker(LayoutBlock* root) | 339 InlineWalker(LayoutBlock* root) |
| 339 : m_root(root) | 340 : m_root(root) |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 | 384 |
| 384 if (rule == FastIncrementInIsolatedRenderer | 385 if (rule == FastIncrementInIsolatedRenderer |
| 385 && resolver && resolver->inIsolate() | 386 && resolver && resolver->inIsolate() |
| 386 && !endOfLineHasIsolatedObjectAncestor(resolver->endOfLine(), resolver->
position())) { | 387 && !endOfLineHasIsolatedObjectAncestor(resolver->endOfLine(), resolver->
position())) { |
| 387 moveTo(bidiNextSkippingEmptyInlines(m_root, m_obj, resolver), 0); | 388 moveTo(bidiNextSkippingEmptyInlines(m_root, m_obj, resolver), 0); |
| 388 return; | 389 return; |
| 389 } | 390 } |
| 390 | 391 |
| 391 if (m_obj->isText()) { | 392 if (m_obj->isText()) { |
| 392 fastIncrementInTextNode(); | 393 fastIncrementInTextNode(); |
| 393 if (m_pos < toRenderText(m_obj)->textLength()) | 394 if (m_pos < toLayoutText(m_obj)->textLength()) |
| 394 return; | 395 return; |
| 395 } | 396 } |
| 396 // bidiNext can return 0, so use moveTo instead of moveToStartOf | 397 // bidiNext can return 0, so use moveTo instead of moveToStartOf |
| 397 moveTo(bidiNextSkippingEmptyInlines(m_root, m_obj, resolver), 0); | 398 moveTo(bidiNextSkippingEmptyInlines(m_root, m_obj, resolver), 0); |
| 398 } | 399 } |
| 399 | 400 |
| 400 inline bool InlineIterator::atEnd() const | 401 inline bool InlineIterator::atEnd() const |
| 401 { | 402 { |
| 402 return !m_obj; | 403 return !m_obj; |
| 403 } | 404 } |
| 404 | 405 |
| 405 inline UChar InlineIterator::characterAt(unsigned index) const | 406 inline UChar InlineIterator::characterAt(unsigned index) const |
| 406 { | 407 { |
| 407 if (!m_obj || !m_obj->isText()) | 408 if (!m_obj || !m_obj->isText()) |
| 408 return 0; | 409 return 0; |
| 409 | 410 |
| 410 return toRenderText(m_obj)->characterAt(index); | 411 return toLayoutText(m_obj)->characterAt(index); |
| 411 } | 412 } |
| 412 | 413 |
| 413 inline UChar InlineIterator::current() const | 414 inline UChar InlineIterator::current() const |
| 414 { | 415 { |
| 415 return characterAt(m_pos); | 416 return characterAt(m_pos); |
| 416 } | 417 } |
| 417 | 418 |
| 418 inline UChar InlineIterator::previousInSameNode() const | 419 inline UChar InlineIterator::previousInSameNode() const |
| 419 { | 420 { |
| 420 if (!m_pos) | 421 if (!m_pos) |
| (...skipping 24 matching lines...) Expand all Loading... |
| 445 { | 446 { |
| 446 bool inEndOfLine = m_current == end || m_current.atEnd() || (inIsolate() &&
m_current.object() == end.object()); | 447 bool inEndOfLine = m_current == end || m_current.atEnd() || (inIsolate() &&
m_current.object() == end.object()); |
| 447 if (inIsolate() && inEndOfLine) { | 448 if (inIsolate() && inEndOfLine) { |
| 448 m_current.moveTo(m_current.object(), end.offset(), m_current.nextBreakab
lePosition()); | 449 m_current.moveTo(m_current.object(), end.offset(), m_current.nextBreakab
lePosition()); |
| 449 m_last = m_current; | 450 m_last = m_current; |
| 450 updateStatusLastFromCurrentDirection(WTF::Unicode::OtherNeutral); | 451 updateStatusLastFromCurrentDirection(WTF::Unicode::OtherNeutral); |
| 451 } | 452 } |
| 452 return inEndOfLine; | 453 return inEndOfLine; |
| 453 } | 454 } |
| 454 | 455 |
| 455 static inline bool isCollapsibleSpace(UChar character, RenderText* renderer) | 456 static inline bool isCollapsibleSpace(UChar character, LayoutText* renderer) |
| 456 { | 457 { |
| 457 if (character == ' ' || character == '\t' || character == softHyphen) | 458 if (character == ' ' || character == '\t' || character == softHyphen) |
| 458 return true; | 459 return true; |
| 459 if (character == '\n') | 460 if (character == '\n') |
| 460 return !renderer->style()->preserveNewline(); | 461 return !renderer->style()->preserveNewline(); |
| 461 return false; | 462 return false; |
| 462 } | 463 } |
| 463 | 464 |
| 464 template <typename CharacterType> | 465 template <typename CharacterType> |
| 465 static inline int findFirstTrailingSpace(RenderText* lastText, const CharacterTy
pe* characters, int start, int stop) | 466 static inline int findFirstTrailingSpace(LayoutText* lastText, const CharacterTy
pe* characters, int start, int stop) |
| 466 { | 467 { |
| 467 int firstSpace = stop; | 468 int firstSpace = stop; |
| 468 while (firstSpace > start) { | 469 while (firstSpace > start) { |
| 469 UChar current = characters[firstSpace - 1]; | 470 UChar current = characters[firstSpace - 1]; |
| 470 if (!isCollapsibleSpace(current, lastText)) | 471 if (!isCollapsibleSpace(current, lastText)) |
| 471 break; | 472 break; |
| 472 firstSpace--; | 473 firstSpace--; |
| 473 } | 474 } |
| 474 | 475 |
| 475 return firstSpace; | 476 return firstSpace; |
| 476 } | 477 } |
| 477 | 478 |
| 478 template <> | 479 template <> |
| 479 inline int InlineBidiResolver::findFirstTrailingSpaceAtRun(BidiRun* run) | 480 inline int InlineBidiResolver::findFirstTrailingSpaceAtRun(BidiRun* run) |
| 480 { | 481 { |
| 481 ASSERT(run); | 482 ASSERT(run); |
| 482 LayoutObject* lastObject = run->m_object; | 483 LayoutObject* lastObject = run->m_object; |
| 483 if (!lastObject->isText()) | 484 if (!lastObject->isText()) |
| 484 return run->m_stop; | 485 return run->m_stop; |
| 485 | 486 |
| 486 RenderText* lastText = toRenderText(lastObject); | 487 LayoutText* lastText = toLayoutText(lastObject); |
| 487 int firstSpace; | 488 int firstSpace; |
| 488 if (lastText->is8Bit()) | 489 if (lastText->is8Bit()) |
| 489 firstSpace = findFirstTrailingSpace(lastText, lastText->characters8(), r
un->start(), run->stop()); | 490 firstSpace = findFirstTrailingSpace(lastText, lastText->characters8(), r
un->start(), run->stop()); |
| 490 else | 491 else |
| 491 firstSpace = findFirstTrailingSpace(lastText, lastText->characters16(),
run->start(), run->stop()); | 492 firstSpace = findFirstTrailingSpace(lastText, lastText->characters16(),
run->start(), run->stop()); |
| 492 return firstSpace; | 493 return firstSpace; |
| 493 } | 494 } |
| 494 | 495 |
| 495 template <> | 496 template <> |
| 496 inline BidiRun* InlineBidiResolver::addTrailingRun(BidiRunList<BidiRun>& runs, i
nt start, int stop, BidiRun* run, BidiContext* context, TextDirection direction)
const | 497 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; | 737 m_sor = m_eor; |
| 737 } | 738 } |
| 738 | 739 |
| 739 m_direction = WTF::Unicode::OtherNeutral; | 740 m_direction = WTF::Unicode::OtherNeutral; |
| 740 m_status.eor = WTF::Unicode::OtherNeutral; | 741 m_status.eor = WTF::Unicode::OtherNeutral; |
| 741 } | 742 } |
| 742 | 743 |
| 743 } | 744 } |
| 744 | 745 |
| 745 #endif // InlineIterator_h | 746 #endif // InlineIterator_h |
| OLD | NEW |