| 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/rendering/BidiRun.h" |   26 #include "core/rendering/BidiRun.h" | 
|   27 #include "core/rendering/RenderBlockFlow.h" |   27 #include "core/rendering/RenderBlockFlow.h" | 
 |   28 #include "core/rendering/RenderInline.h" | 
|   28 #include "core/rendering/RenderText.h" |   29 #include "core/rendering/RenderText.h" | 
|   29 #include "wtf/StdLibExtras.h" |   30 #include "wtf/StdLibExtras.h" | 
|   30  |   31  | 
|   31 namespace WebCore { |   32 namespace WebCore { | 
|   32  |   33  | 
|   33 // 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 | 
|   34 // text children. InlineIterator will use bidiNext to find the next RenderText |   35 // text children. InlineIterator will use bidiNext to find the next RenderText | 
|   35 // 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. | 
|   36 class InlineIterator { |   37 class InlineIterator { | 
|   37 public: |   38 public: | 
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  182 enum EmptyInlineBehavior { |  183 enum EmptyInlineBehavior { | 
|  183     SkipEmptyInlines, |  184     SkipEmptyInlines, | 
|  184     IncludeEmptyInlines, |  185     IncludeEmptyInlines, | 
|  185 }; |  186 }; | 
|  186  |  187  | 
|  187 static bool isEmptyInline(RenderObject* object) |  188 static bool isEmptyInline(RenderObject* object) | 
|  188 { |  189 { | 
|  189     if (!object->isRenderInline()) |  190     if (!object->isRenderInline()) | 
|  190         return false; |  191         return false; | 
|  191  |  192  | 
|  192     for (RenderObject* curr = object->firstChild(); curr; curr = curr->nextSibli
     ng()) { |  193     for (RenderObject* curr = toRenderInline(object)->firstChild(); curr; curr =
      curr->nextSibling()) { | 
|  193         if (curr->isFloatingOrOutOfFlowPositioned()) |  194         if (curr->isFloatingOrOutOfFlowPositioned()) | 
|  194             continue; |  195             continue; | 
|  195         if (curr->isText() && toRenderText(curr)->isAllCollapsibleWhitespace()) |  196         if (curr->isText() && toRenderText(curr)->isAllCollapsibleWhitespace()) | 
|  196             continue; |  197             continue; | 
|  197  |  198  | 
|  198         if (!isEmptyInline(curr)) |  199         if (!isEmptyInline(curr)) | 
|  199             return false; |  200             return false; | 
|  200     } |  201     } | 
|  201     return true; |  202     return true; | 
|  202 } |  203 } | 
|  203  |  204  | 
|  204 // 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. | 
|  205 // This function will iterate over inlines within a block, optionally notifying |  206 // This function will iterate over inlines within a block, optionally notifying | 
|  206 // a bidi resolver as it enters/exits inlines (so it can push/pop embedding leve
     ls). |  207 // a bidi resolver as it enters/exits inlines (so it can push/pop embedding leve
     ls). | 
|  207 template <class Observer> |  208 template <class Observer> | 
|  208 static inline RenderObject* bidiNextShared(RenderObject* root, RenderObject* cur
     rent, Observer* observer = 0, EmptyInlineBehavior emptyInlineBehavior = SkipEmpt
     yInlines, bool* endOfInlinePtr = 0) |  209 static inline RenderObject* bidiNextShared(RenderObject* root, RenderObject* cur
     rent, Observer* observer = 0, EmptyInlineBehavior emptyInlineBehavior = SkipEmpt
     yInlines, bool* endOfInlinePtr = 0) | 
|  209 { |  210 { | 
|  210     RenderObject* next = 0; |  211     RenderObject* next = 0; | 
|  211     // oldEndOfInline denotes if when we last stopped iterating if we were at th
     e end of an inline. |  212     // oldEndOfInline denotes if when we last stopped iterating if we were at th
     e end of an inline. | 
|  212     bool oldEndOfInline = endOfInlinePtr ? *endOfInlinePtr : false; |  213     bool oldEndOfInline = endOfInlinePtr ? *endOfInlinePtr : false; | 
|  213     bool endOfInline = false; |  214     bool endOfInline = false; | 
|  214  |  215  | 
|  215     while (current) { |  216     while (current) { | 
|  216         next = 0; |  217         next = 0; | 
|  217         if (!oldEndOfInline && !isIteratorTarget(current)) { |  218         if (!oldEndOfInline && !isIteratorTarget(current)) { | 
|  218             next = current->firstChild(); |  219             next = current->slowFirstChild(); | 
|  219             notifyObserverEnteredObject(observer, next); |  220             notifyObserverEnteredObject(observer, next); | 
|  220         } |  221         } | 
|  221  |  222  | 
|  222         // We hit this when either current has no children, or when current is n
     ot a renderer we care about. |  223         // We hit this when either current has no children, or when current is n
     ot a renderer we care about. | 
|  223         if (!next) { |  224         if (!next) { | 
|  224             // If it is a renderer we care about, and we're doing our inline-wal
     k, return it. |  225             // If it is a renderer we care about, and we're doing our inline-wal
     k, return it. | 
|  225             if (emptyInlineBehavior == IncludeEmptyInlines && !oldEndOfInline &&
      current->isRenderInline()) { |  226             if (emptyInlineBehavior == IncludeEmptyInlines && !oldEndOfInline &&
      current->isRenderInline()) { | 
|  226                 next = current; |  227                 next = current; | 
|  227                 endOfInline = true; |  228                 endOfInline = true; | 
|  228                 break; |  229                 break; | 
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  275     InlineBidiResolver* observer = 0; |  276     InlineBidiResolver* observer = 0; | 
|  276     return bidiNextSkippingEmptyInlines(root, current, observer); |  277     return bidiNextSkippingEmptyInlines(root, current, observer); | 
|  277 } |  278 } | 
|  278  |  279  | 
|  279 static inline RenderObject* bidiNextIncludingEmptyInlines(RenderObject* root, Re
     nderObject* current, bool* endOfInlinePtr = 0) |  280 static inline RenderObject* bidiNextIncludingEmptyInlines(RenderObject* root, Re
     nderObject* current, bool* endOfInlinePtr = 0) | 
|  280 { |  281 { | 
|  281     InlineBidiResolver* observer = 0; // Callers who include empty inlines, neve
     r use an observer. |  282     InlineBidiResolver* observer = 0; // Callers who include empty inlines, neve
     r use an observer. | 
|  282     return bidiNextShared(root, current, observer, IncludeEmptyInlines, endOfInl
     inePtr); |  283     return bidiNextShared(root, current, observer, IncludeEmptyInlines, endOfInl
     inePtr); | 
|  283 } |  284 } | 
|  284  |  285  | 
|  285 static inline RenderObject* bidiFirstSkippingEmptyInlines(RenderObject* root, In
     lineBidiResolver* resolver = 0) |  286 static inline RenderObject* bidiFirstSkippingEmptyInlines(RenderBlockFlow* root,
      InlineBidiResolver* resolver = 0) | 
|  286 { |  287 { | 
|  287     RenderObject* o = root->firstChild(); |  288     RenderObject* o = root->firstChild(); | 
|  288     if (!o) |  289     if (!o) | 
|  289         return 0; |  290         return 0; | 
|  290  |  291  | 
|  291     if (o->isRenderInline()) { |  292     if (o->isRenderInline()) { | 
|  292         notifyObserverEnteredObject(resolver, o); |  293         notifyObserverEnteredObject(resolver, o); | 
|  293         if (!isEmptyInline(o)) |  294         if (!isEmptyInline(o)) | 
|  294             o = bidiNextSkippingEmptyInlines(root, o, resolver); |  295             o = bidiNextSkippingEmptyInlines(root, o, resolver); | 
|  295         else { |  296         else { | 
|  296             // Never skip empty inlines. |  297             // Never skip empty inlines. | 
|  297             if (resolver) |  298             if (resolver) | 
|  298                 resolver->commitExplicitEmbedding(); |  299                 resolver->commitExplicitEmbedding(); | 
|  299             return o; |  300             return o; | 
|  300         } |  301         } | 
|  301     } |  302     } | 
|  302  |  303  | 
|  303     // FIXME: Unify this with the bidiNext call above. |  304     // FIXME: Unify this with the bidiNext call above. | 
|  304     if (o && !isIteratorTarget(o)) |  305     if (o && !isIteratorTarget(o)) | 
|  305         o = bidiNextSkippingEmptyInlines(root, o, resolver); |  306         o = bidiNextSkippingEmptyInlines(root, o, resolver); | 
|  306  |  307  | 
|  307     if (resolver) |  308     if (resolver) | 
|  308         resolver->commitExplicitEmbedding(); |  309         resolver->commitExplicitEmbedding(); | 
|  309     return o; |  310     return o; | 
|  310 } |  311 } | 
|  311  |  312  | 
|  312 // FIXME: This method needs to be renamed when bidiNext finds a good name. |  313 // FIXME: This method needs to be renamed when bidiNext finds a good name. | 
|  313 static inline RenderObject* bidiFirstIncludingEmptyInlines(RenderObject* root) |  314 static inline RenderObject* bidiFirstIncludingEmptyInlines(RenderBlock* root) | 
|  314 { |  315 { | 
|  315     RenderObject* o = root->firstChild(); |  316     RenderObject* o = root->firstChild(); | 
|  316     // If either there are no children to walk, or the first one is correct |  317     // If either there are no children to walk, or the first one is correct | 
|  317     // then just return it. |  318     // then just return it. | 
|  318     if (!o || o->isRenderInline() || isIteratorTarget(o)) |  319     if (!o || o->isRenderInline() || isIteratorTarget(o)) | 
|  319         return o; |  320         return o; | 
|  320  |  321  | 
|  321     return bidiNextIncludingEmptyInlines(root, o); |  322     return bidiNextIncludingEmptyInlines(root, o); | 
|  322 } |  323 } | 
|  323  |  324  | 
|  324 inline void InlineIterator::fastIncrementInTextNode() |  325 inline void InlineIterator::fastIncrementInTextNode() | 
|  325 { |  326 { | 
|  326     ASSERT(m_obj); |  327     ASSERT(m_obj); | 
|  327     ASSERT(m_obj->isText()); |  328     ASSERT(m_obj->isText()); | 
|  328     ASSERT(m_pos <= toRenderText(m_obj)->textLength()); |  329     ASSERT(m_pos <= toRenderText(m_obj)->textLength()); | 
|  329     if (m_pos < INT_MAX) |  330     if (m_pos < INT_MAX) | 
|  330         m_pos++; |  331         m_pos++; | 
|  331 } |  332 } | 
|  332  |  333  | 
|  333 // 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 | 
|  334 // it shouldn't use functions called bidiFirst and bidiNext. |  335 // it shouldn't use functions called bidiFirst and bidiNext. | 
|  335 class InlineWalker { |  336 class InlineWalker { | 
|  336 public: |  337 public: | 
|  337     InlineWalker(RenderObject* root) |  338     InlineWalker(RenderBlock* root) | 
|  338         : m_root(root) |  339         : m_root(root) | 
|  339         , m_current(0) |  340         , m_current(0) | 
|  340         , m_atEndOfInline(false) |  341         , m_atEndOfInline(false) | 
|  341     { |  342     { | 
|  342         // FIXME: This class should be taught how to do the SkipEmptyInlines cod
     epath as well. |  343         // FIXME: This class should be taught how to do the SkipEmptyInlines cod
     epath as well. | 
|  343         m_current = bidiFirstIncludingEmptyInlines(m_root); |  344         m_current = bidiFirstIncludingEmptyInlines(m_root); | 
|  344     } |  345     } | 
|  345  |  346  | 
|  346     RenderObject* root() { return m_root; } |  347     RenderBlock* root() { return m_root; } | 
|  347     RenderObject* current() { return m_current; } |  348     RenderObject* current() { return m_current; } | 
|  348  |  349  | 
|  349     bool atEndOfInline() { return m_atEndOfInline; } |  350     bool atEndOfInline() { return m_atEndOfInline; } | 
|  350     bool atEnd() const { return !m_current; } |  351     bool atEnd() const { return !m_current; } | 
|  351  |  352  | 
|  352     RenderObject* advance() |  353     RenderObject* advance() | 
|  353     { |  354     { | 
|  354         // FIXME: Support SkipEmptyInlines and observer parameters. |  355         // FIXME: Support SkipEmptyInlines and observer parameters. | 
|  355         m_current = bidiNextIncludingEmptyInlines(m_root, m_current, &m_atEndOfI
     nline); |  356         m_current = bidiNextIncludingEmptyInlines(m_root, m_current, &m_atEndOfI
     nline); | 
|  356         return m_current; |  357         return m_current; | 
|  357     } |  358     } | 
|  358 private: |  359 private: | 
|  359     RenderObject* m_root; |  360     RenderBlock* m_root; | 
|  360     RenderObject* m_current; |  361     RenderObject* m_current; | 
|  361     bool m_atEndOfInline; |  362     bool m_atEndOfInline; | 
|  362 }; |  363 }; | 
|  363  |  364  | 
|  364 static inline bool endOfLineHasIsolatedObjectAncestor(const InlineIterator& isol
     atedIterator, const InlineIterator& ancestorItertor) |  365 static inline bool endOfLineHasIsolatedObjectAncestor(const InlineIterator& isol
     atedIterator, const InlineIterator& ancestorItertor) | 
|  365 { |  366 { | 
|  366     if (!isolatedIterator.object() || !isIsolated(isolatedIterator.object()->sty
     le()->unicodeBidi())) |  367     if (!isolatedIterator.object() || !isIsolated(isolatedIterator.object()->sty
     le()->unicodeBidi())) | 
|  367         return false; |  368         return false; | 
|  368  |  369  | 
|  369     RenderObject* innerIsolatedObject = isolatedIterator.object(); |  370     RenderObject* innerIsolatedObject = isolatedIterator.object(); | 
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  718         m_sor = m_eor; |  719         m_sor = m_eor; | 
|  719     } |  720     } | 
|  720  |  721  | 
|  721     m_direction = WTF::Unicode::OtherNeutral; |  722     m_direction = WTF::Unicode::OtherNeutral; | 
|  722     m_status.eor = WTF::Unicode::OtherNeutral; |  723     m_status.eor = WTF::Unicode::OtherNeutral; | 
|  723 } |  724 } | 
|  724  |  725  | 
|  725 } |  726 } | 
|  726  |  727  | 
|  727 #endif // InlineIterator_h |  728 #endif // InlineIterator_h | 
| OLD | NEW |