| 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/layout/LayoutText.h" | 29 #include "core/layout/LayoutText.h" |
| 30 #include "core/layout/api/LineLayoutBlockFlow.h" |
| 31 #include "core/layout/api/LineLayoutInline.h" |
| 32 #include "core/layout/api/LineLayoutText.h" |
| 30 | 33 |
| 31 #include "wtf/StdLibExtras.h" | 34 #include "wtf/StdLibExtras.h" |
| 32 | 35 |
| 33 namespace blink { | 36 namespace blink { |
| 34 | 37 |
| 35 // This class is used to LayoutInline subtrees, stepping by character within the | 38 // This class is used to LayoutInline subtrees, stepping by character within the |
| 36 // text children. InlineIterator will use bidiNext to find the next LayoutText | 39 // text children. InlineIterator will use bidiNext to find the next LayoutText |
| 37 // optionally notifying a BidiResolver every time it steps into/out of a LayoutI
nline. | 40 // optionally notifying a BidiResolver every time it steps into/out of a LayoutI
nline. |
| 38 class InlineIterator { | 41 class InlineIterator { |
| 39 public: | 42 public: |
| 40 enum IncrementRule { | 43 enum IncrementRule { |
| 41 FastIncrementInIsolatedLayout, | 44 FastIncrementInIsolatedLayout, |
| 42 FastIncrementInTextNode | 45 FastIncrementInTextNode |
| 43 }; | 46 }; |
| 44 | 47 |
| 45 InlineIterator() | 48 InlineIterator() |
| 46 : m_root(nullptr) | 49 : m_root(nullptr) |
| 47 , m_obj(nullptr) | 50 , m_obj(nullptr) |
| 48 , m_nextBreakablePosition(-1) | 51 , m_nextBreakablePosition(-1) |
| 49 , m_pos(0) | 52 , m_pos(0) |
| 50 { | 53 { |
| 51 } | 54 } |
| 52 | 55 |
| 53 InlineIterator(LayoutObject* root, LayoutObject* o, unsigned p) | 56 InlineIterator(LineLayoutItem root, LineLayoutItem o, unsigned p) |
| 54 : m_root(root) | 57 : m_root(root) |
| 55 , m_obj(o) | 58 , m_obj(o) |
| 56 , m_nextBreakablePosition(-1) | 59 , m_nextBreakablePosition(-1) |
| 57 , m_pos(p) | 60 , m_pos(p) |
| 58 { | 61 { |
| 59 } | 62 } |
| 60 | 63 |
| 61 void clear() { moveTo(0, 0); } | 64 void clear() { moveTo(0, 0); } |
| 62 | 65 |
| 63 void moveToStartOf(LayoutObject* object) | 66 void moveToStartOf(LineLayoutItem object) |
| 64 { | 67 { |
| 65 moveTo(object, 0); | 68 moveTo(object, 0); |
| 66 } | 69 } |
| 67 | 70 |
| 68 void moveTo(LayoutObject* object, unsigned offset, int nextBreak = -1) | 71 void moveTo(LineLayoutItem object, unsigned offset, int nextBreak = -1) |
| 69 { | 72 { |
| 70 m_obj = object; | 73 m_obj = object; |
| 71 m_pos = offset; | 74 m_pos = offset; |
| 72 m_nextBreakablePosition = nextBreak; | 75 m_nextBreakablePosition = nextBreak; |
| 73 } | 76 } |
| 74 | 77 |
| 75 LayoutObject* object() const { return m_obj; } | 78 LineLayoutItem object() const { return m_obj; } |
| 76 void setObject(LayoutObject* object) { m_obj = object; } | 79 void setObject(LineLayoutItem object) { m_obj = object; } |
| 77 | 80 |
| 78 int nextBreakablePosition() const { return m_nextBreakablePosition; } | 81 int nextBreakablePosition() const { return m_nextBreakablePosition; } |
| 79 void setNextBreakablePosition(int position) { m_nextBreakablePosition = posi
tion; } | 82 void setNextBreakablePosition(int position) { m_nextBreakablePosition = posi
tion; } |
| 80 | 83 |
| 81 unsigned offset() const { return m_pos; } | 84 unsigned offset() const { return m_pos; } |
| 82 void setOffset(unsigned position) { m_pos = position; } | 85 void setOffset(unsigned position) { m_pos = position; } |
| 83 LayoutObject* root() const { return m_root; } | 86 LineLayoutItem root() const { return m_root; } |
| 84 | 87 |
| 85 void fastIncrementInTextNode(); | 88 void fastIncrementInTextNode(); |
| 86 void increment(InlineBidiResolver* = nullptr, IncrementRule = FastIncrementI
nTextNode); | 89 void increment(InlineBidiResolver* = nullptr, IncrementRule = FastIncrementI
nTextNode); |
| 87 bool atEnd() const; | 90 bool atEnd() const; |
| 88 | 91 |
| 89 inline bool atTextParagraphSeparator() const | 92 inline bool atTextParagraphSeparator() const |
| 90 { | 93 { |
| 91 return m_obj && m_obj->preservesNewline() && m_obj->isText() && toLayout
Text(m_obj)->textLength() | 94 return m_obj && m_obj.preservesNewline() && m_obj.isText() && LineLayout
Text(m_obj).textLength() |
| 92 && !toLayoutText(m_obj)->isWordBreak() && toLayoutText(m_obj)->chara
cterAt(m_pos) == '\n'; | 95 && !LineLayoutText(m_obj).isWordBreak() && LineLayoutText(m_obj).cha
racterAt(m_pos) == '\n'; |
| 93 } | 96 } |
| 94 | 97 |
| 95 inline bool atParagraphSeparator() const | 98 inline bool atParagraphSeparator() const |
| 96 { | 99 { |
| 97 return (m_obj && m_obj->isBR()) || atTextParagraphSeparator(); | 100 return (m_obj && m_obj.isBR()) || atTextParagraphSeparator(); |
| 98 } | 101 } |
| 99 | 102 |
| 100 UChar characterAt(unsigned) const; | 103 UChar characterAt(unsigned) const; |
| 101 UChar current() const; | 104 UChar current() const; |
| 102 UChar previousInSameNode() const; | 105 UChar previousInSameNode() const; |
| 103 ALWAYS_INLINE WTF::Unicode::Direction direction() const; | 106 ALWAYS_INLINE WTF::Unicode::Direction direction() const; |
| 104 | 107 |
| 105 private: | 108 private: |
| 106 LayoutObject* m_root; | 109 LineLayoutItem m_root; |
| 107 LayoutObject* m_obj; | 110 LineLayoutItem m_obj; |
| 108 | 111 |
| 109 int m_nextBreakablePosition; | 112 int m_nextBreakablePosition; |
| 110 unsigned m_pos; | 113 unsigned m_pos; |
| 111 }; | 114 }; |
| 112 | 115 |
| 113 inline bool operator==(const InlineIterator& it1, const InlineIterator& it2) | 116 inline bool operator==(const InlineIterator& it1, const InlineIterator& it2) |
| 114 { | 117 { |
| 115 return it1.offset() == it2.offset() && it1.object() == it2.object(); | 118 return it1.offset() == it2.offset() && it1.object() == it2.object(); |
| 116 } | 119 } |
| 117 | 120 |
| 118 inline bool operator!=(const InlineIterator& it1, const InlineIterator& it2) | 121 inline bool operator!=(const InlineIterator& it1, const InlineIterator& it2) |
| 119 { | 122 { |
| 120 return it1.offset() != it2.offset() || it1.object() != it2.object(); | 123 return it1.offset() != it2.offset() || it1.object() != it2.object(); |
| 121 } | 124 } |
| 122 | 125 |
| 123 static inline WTF::Unicode::Direction embedCharFromDirection(TextDirection dir,
EUnicodeBidi unicodeBidi) | 126 static inline WTF::Unicode::Direction embedCharFromDirection(TextDirection dir,
EUnicodeBidi unicodeBidi) |
| 124 { | 127 { |
| 125 using namespace WTF::Unicode; | 128 using namespace WTF::Unicode; |
| 126 if (unicodeBidi == Embed) | 129 if (unicodeBidi == Embed) |
| 127 return dir == RTL ? RightToLeftEmbedding : LeftToRightEmbedding; | 130 return dir == RTL ? RightToLeftEmbedding : LeftToRightEmbedding; |
| 128 return dir == RTL ? RightToLeftOverride : LeftToRightOverride; | 131 return dir == RTL ? RightToLeftOverride : LeftToRightOverride; |
| 129 } | 132 } |
| 130 | 133 |
| 131 template <class Observer> | 134 template <class Observer> |
| 132 static inline void notifyObserverEnteredObject(Observer* observer, LayoutObject*
object) | 135 static inline void notifyObserverEnteredObject(Observer* observer, LineLayoutIte
m object) |
| 133 { | 136 { |
| 134 if (!observer || !object || !object->isLayoutInline()) | 137 if (!observer || !object || !object->isLayoutInline()) |
| 135 return; | 138 return; |
| 136 | 139 |
| 137 const ComputedStyle& style = object->styleRef(); | 140 const ComputedStyle& style = object->styleRef(); |
| 138 EUnicodeBidi unicodeBidi = style.unicodeBidi(); | 141 EUnicodeBidi unicodeBidi = style.unicodeBidi(); |
| 139 if (unicodeBidi == UBNormal) { | 142 if (unicodeBidi == UBNormal) { |
| 140 // http://dev.w3.org/csswg/css3-writing-modes/#unicode-bidi | 143 // http://dev.w3.org/csswg/css3-writing-modes/#unicode-bidi |
| 141 // "The element does not open an additional level of embedding with resp
ect to the bidirectional algorithm." | 144 // "The element does not open an additional level of embedding with resp
ect to the bidirectional algorithm." |
| 142 // Thus we ignore any possible dir= attribute on the span. | 145 // Thus we ignore any possible dir= attribute on the span. |
| 143 return; | 146 return; |
| 144 } | 147 } |
| 145 if (isIsolated(unicodeBidi)) { | 148 if (isIsolated(unicodeBidi)) { |
| 146 // Make sure that explicit embeddings are committed before we enter the
isolated content. | 149 // Make sure that explicit embeddings are committed before we enter the
isolated content. |
| 147 observer->commitExplicitEmbedding(observer->runs()); | 150 observer->commitExplicitEmbedding(observer->runs()); |
| 148 observer->enterIsolate(); | 151 observer->enterIsolate(); |
| 149 // Embedding/Override characters implied by dir= will be handled when | 152 // Embedding/Override characters implied by dir= will be handled when |
| 150 // we process the isolated span, not when laying out the "parent" run. | 153 // we process the isolated span, not when laying out the "parent" run. |
| 151 return; | 154 return; |
| 152 } | 155 } |
| 153 | 156 |
| 154 if (!observer->inIsolate()) | 157 if (!observer->inIsolate()) |
| 155 observer->embed(embedCharFromDirection(style.direction(), unicodeBidi),
FromStyleOrDOM); | 158 observer->embed(embedCharFromDirection(style.direction(), unicodeBidi),
FromStyleOrDOM); |
| 156 } | 159 } |
| 157 | 160 |
| 158 template <class Observer> | 161 template <class Observer> |
| 159 static inline void notifyObserverWillExitObject(Observer* observer, LayoutObject
* object) | 162 static inline void notifyObserverWillExitObject(Observer* observer, LineLayoutIt
em object) |
| 160 { | 163 { |
| 161 if (!observer || !object || !object->isLayoutInline()) | 164 if (!observer || !object || !object->isLayoutInline()) |
| 162 return; | 165 return; |
| 163 | 166 |
| 164 EUnicodeBidi unicodeBidi = object->style()->unicodeBidi(); | 167 EUnicodeBidi unicodeBidi = object->style()->unicodeBidi(); |
| 165 if (unicodeBidi == UBNormal) | 168 if (unicodeBidi == UBNormal) |
| 166 return; // Nothing to do for unicode-bidi: normal | 169 return; // Nothing to do for unicode-bidi: normal |
| 167 if (isIsolated(unicodeBidi)) { | 170 if (isIsolated(unicodeBidi)) { |
| 168 observer->exitIsolate(); | 171 observer->exitIsolate(); |
| 169 return; | 172 return; |
| 170 } | 173 } |
| 171 | 174 |
| 172 // Otherwise we pop any embed/override character we added when we opened thi
s tag. | 175 // Otherwise we pop any embed/override character we added when we opened thi
s tag. |
| 173 if (!observer->inIsolate()) | 176 if (!observer->inIsolate()) |
| 174 observer->embed(WTF::Unicode::PopDirectionalFormat, FromStyleOrDOM); | 177 observer->embed(WTF::Unicode::PopDirectionalFormat, FromStyleOrDOM); |
| 175 } | 178 } |
| 176 | 179 |
| 177 static inline bool isIteratorTarget(LayoutObject* object) | 180 static inline bool isIteratorTarget(LineLayoutItem object) |
| 178 { | 181 { |
| 179 ASSERT(object); // The iterator will of course return 0, but its not an expe
cted argument to this function. | 182 ASSERT(object); // The iterator will of course return 0, but its not an expe
cted argument to this function. |
| 180 return object->isText() || object->isFloating() || object->isOutOfFlowPositi
oned() || object->isReplaced(); | 183 return object->isText() || object->isFloating() || object->isOutOfFlowPositi
oned() || object->isReplaced(); |
| 181 } | 184 } |
| 182 | 185 |
| 183 // This enum is only used for bidiNextShared() | 186 // This enum is only used for bidiNextShared() |
| 184 enum EmptyInlineBehavior { | 187 enum EmptyInlineBehavior { |
| 185 SkipEmptyInlines, | 188 SkipEmptyInlines, |
| 186 IncludeEmptyInlines, | 189 IncludeEmptyInlines, |
| 187 }; | 190 }; |
| 188 | 191 |
| 189 static bool isEmptyInline(LayoutObject* object) | 192 static bool isEmptyInline(LineLayoutItem object) |
| 190 { | 193 { |
| 191 if (!object->isLayoutInline()) | 194 if (!object->isLayoutInline()) |
| 192 return false; | 195 return false; |
| 193 | 196 |
| 194 for (LayoutObject* curr = toLayoutInline(object)->firstChild(); curr; curr =
curr->nextSibling()) { | 197 for (LineLayoutItem curr = LineLayoutInline(object).firstChild(); curr; curr
= curr->nextSibling()) { |
| 195 if (curr->isFloatingOrOutOfFlowPositioned()) | 198 if (curr->isFloatingOrOutOfFlowPositioned()) |
| 196 continue; | 199 continue; |
| 197 if (curr->isText() && toLayoutText(curr)->isAllCollapsibleWhitespace()) | 200 if (curr->isText() && LineLayoutText(curr).isAllCollapsibleWhitespace()) |
| 198 continue; | 201 continue; |
| 199 | 202 |
| 200 if (!isEmptyInline(curr)) | 203 if (!isEmptyInline(curr)) |
| 201 return false; | 204 return false; |
| 202 } | 205 } |
| 203 return true; | 206 return true; |
| 204 } | 207 } |
| 205 | 208 |
| 206 // FIXME: This function is misleadingly named. It has little to do with bidi. | 209 // FIXME: This function is misleadingly named. It has little to do with bidi. |
| 207 // This function will iterate over inlines within a block, optionally notifying | 210 // This function will iterate over inlines within a block, optionally notifying |
| 208 // a bidi resolver as it enters/exits inlines (so it can push/pop embedding leve
ls). | 211 // a bidi resolver as it enters/exits inlines (so it can push/pop embedding leve
ls). |
| 209 template <class Observer> | 212 template <class Observer> |
| 210 static inline LayoutObject* bidiNextShared(LayoutObject* root, LayoutObject* cur
rent, Observer* observer = 0, EmptyInlineBehavior emptyInlineBehavior = SkipEmpt
yInlines, bool* endOfInlinePtr = nullptr) | 213 static inline LineLayoutItem bidiNextShared(LineLayoutItem root, LineLayoutItem
current, Observer* observer = 0, EmptyInlineBehavior emptyInlineBehavior = SkipE
mptyInlines, bool* endOfInlinePtr = nullptr) |
| 211 { | 214 { |
| 212 LayoutObject* next = nullptr; | 215 LineLayoutItem next = nullptr; |
| 213 // oldEndOfInline denotes if when we last stopped iterating if we were at th
e end of an inline. | 216 // oldEndOfInline denotes if when we last stopped iterating if we were at th
e end of an inline. |
| 214 bool oldEndOfInline = endOfInlinePtr ? *endOfInlinePtr : false; | 217 bool oldEndOfInline = endOfInlinePtr ? *endOfInlinePtr : false; |
| 215 bool endOfInline = false; | 218 bool endOfInline = false; |
| 216 | 219 |
| 217 while (current) { | 220 while (current) { |
| 218 next = 0; | 221 next = 0; |
| 219 if (!oldEndOfInline && !isIteratorTarget(current)) { | 222 if (!oldEndOfInline && !isIteratorTarget(current)) { |
| 220 next = current->slowFirstChild(); | 223 next = current->slowFirstChild(); |
| 221 notifyObserverEnteredObject(observer, next); | 224 notifyObserverEnteredObject(observer, next); |
| 222 } | 225 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 current = next; | 261 current = next; |
| 259 } | 262 } |
| 260 | 263 |
| 261 if (endOfInlinePtr) | 264 if (endOfInlinePtr) |
| 262 *endOfInlinePtr = endOfInline; | 265 *endOfInlinePtr = endOfInline; |
| 263 | 266 |
| 264 return next; | 267 return next; |
| 265 } | 268 } |
| 266 | 269 |
| 267 template <class Observer> | 270 template <class Observer> |
| 268 static inline LayoutObject* bidiNextSkippingEmptyInlines(LayoutObject* root, Lay
outObject* current, Observer* observer) | 271 static inline LineLayoutItem bidiNextSkippingEmptyInlines(LineLayoutItem root, L
ineLayoutItem current, Observer* observer) |
| 269 { | 272 { |
| 270 // The SkipEmptyInlines callers never care about endOfInlinePtr. | 273 // The SkipEmptyInlines callers never care about endOfInlinePtr. |
| 271 return bidiNextShared(root, current, observer, SkipEmptyInlines); | 274 return bidiNextShared(root, current, observer, SkipEmptyInlines); |
| 272 } | 275 } |
| 273 | 276 |
| 274 // This makes callers cleaner as they don't have to specify a type for the obser
ver when not providing one. | 277 // This makes callers cleaner as they don't have to specify a type for the obser
ver when not providing one. |
| 275 static inline LayoutObject* bidiNextSkippingEmptyInlines(LayoutObject* root, Lay
outObject* current) | 278 static inline LineLayoutItem bidiNextSkippingEmptyInlines(LineLayoutItem root, L
ineLayoutItem current) |
| 276 { | 279 { |
| 277 InlineBidiResolver* observer = nullptr; | 280 InlineBidiResolver* observer = nullptr; |
| 278 return bidiNextSkippingEmptyInlines(root, current, observer); | 281 return bidiNextSkippingEmptyInlines(root, current, observer); |
| 279 } | 282 } |
| 280 | 283 |
| 281 static inline LayoutObject* bidiNextIncludingEmptyInlines(LayoutObject* root, La
youtObject* current, bool* endOfInlinePtr = nullptr) | 284 static inline LineLayoutItem bidiNextIncludingEmptyInlines(LineLayoutItem root,
LineLayoutItem current, bool* endOfInlinePtr = nullptr) |
| 282 { | 285 { |
| 283 InlineBidiResolver* observer = nullptr; // Callers who include empty inlines
, never use an observer. | 286 InlineBidiResolver* observer = nullptr; // Callers who include empty inlines
, never use an observer. |
| 284 return bidiNextShared(root, current, observer, IncludeEmptyInlines, endOfInl
inePtr); | 287 return bidiNextShared(root, current, observer, IncludeEmptyInlines, endOfInl
inePtr); |
| 285 } | 288 } |
| 286 | 289 |
| 287 static inline LayoutObject* bidiFirstSkippingEmptyInlines(LayoutBlockFlow* root,
BidiRunList<BidiRun>& runs, InlineBidiResolver* resolver = nullptr) | 290 static inline LineLayoutItem bidiFirstSkippingEmptyInlines(LineLayoutBlockFlow r
oot, BidiRunList<BidiRun>& runs, InlineBidiResolver* resolver = nullptr) |
| 288 { | 291 { |
| 289 LayoutObject* o = root->firstChild(); | 292 LineLayoutItem o = root.firstChild(); |
| 290 if (!o) | 293 if (!o) |
| 291 return nullptr; | 294 return nullptr; |
| 292 | 295 |
| 293 if (o->isLayoutInline()) { | 296 if (o->isLayoutInline()) { |
| 294 notifyObserverEnteredObject(resolver, o); | 297 notifyObserverEnteredObject(resolver, o); |
| 295 if (!isEmptyInline(o)) { | 298 if (!isEmptyInline(o)) { |
| 296 o = bidiNextSkippingEmptyInlines(root, o, resolver); | 299 o = bidiNextSkippingEmptyInlines(root, o, resolver); |
| 297 } else { | 300 } else { |
| 298 // Never skip empty inlines. | 301 // Never skip empty inlines. |
| 299 if (resolver) | 302 if (resolver) |
| 300 resolver->commitExplicitEmbedding(runs); | 303 resolver->commitExplicitEmbedding(runs); |
| 301 return o; | 304 return o; |
| 302 } | 305 } |
| 303 } | 306 } |
| 304 | 307 |
| 305 // FIXME: Unify this with the bidiNext call above. | 308 // FIXME: Unify this with the bidiNext call above. |
| 306 if (o && !isIteratorTarget(o)) | 309 if (o && !isIteratorTarget(o)) |
| 307 o = bidiNextSkippingEmptyInlines(root, o, resolver); | 310 o = bidiNextSkippingEmptyInlines(root, o, resolver); |
| 308 | 311 |
| 309 if (resolver) | 312 if (resolver) |
| 310 resolver->commitExplicitEmbedding(runs); | 313 resolver->commitExplicitEmbedding(runs); |
| 311 return o; | 314 return o; |
| 312 } | 315 } |
| 313 | 316 |
| 314 // FIXME: This method needs to be renamed when bidiNext finds a good name. | 317 // FIXME: This method needs to be renamed when bidiNext finds a good name. |
| 315 static inline LayoutObject* bidiFirstIncludingEmptyInlines(LayoutBlock* root) | 318 static inline LineLayoutItem bidiFirstIncludingEmptyInlines(LineLayoutBlockFlow
root) |
| 316 { | 319 { |
| 317 LayoutObject* o = root->firstChild(); | 320 LineLayoutItem o = root.firstChild(); |
| 318 // If either there are no children to walk, or the first one is correct | 321 // If either there are no children to walk, or the first one is correct |
| 319 // then just return it. | 322 // then just return it. |
| 320 if (!o || o->isLayoutInline() || isIteratorTarget(o)) | 323 if (!o || o->isLayoutInline() || isIteratorTarget(o)) |
| 321 return o; | 324 return o; |
| 322 | 325 |
| 323 return bidiNextIncludingEmptyInlines(root, o); | 326 return bidiNextIncludingEmptyInlines(root, o); |
| 324 } | 327 } |
| 325 | 328 |
| 326 inline void InlineIterator::fastIncrementInTextNode() | 329 inline void InlineIterator::fastIncrementInTextNode() |
| 327 { | 330 { |
| 328 ASSERT(m_obj); | 331 ASSERT(m_obj); |
| 329 ASSERT(m_obj->isText()); | 332 ASSERT(m_obj.isText()); |
| 330 ASSERT(m_pos <= toLayoutText(m_obj)->textLength()); | 333 ASSERT(m_pos <= LineLayoutText(m_obj).textLength()); |
| 331 if (m_pos < INT_MAX) | 334 if (m_pos < INT_MAX) |
| 332 m_pos++; | 335 m_pos++; |
| 333 } | 336 } |
| 334 | 337 |
| 335 // FIXME: This is used by LayoutBlockFlow for simplified layout, and has nothing
to do with bidi | 338 // FIXME: This is used by LayoutBlockFlow for simplified layout, and has nothing
to do with bidi |
| 336 // it shouldn't use functions called bidiFirst and bidiNext. | 339 // it shouldn't use functions called bidiFirst and bidiNext. |
| 337 class InlineWalker { | 340 class InlineWalker { |
| 338 public: | 341 public: |
| 339 InlineWalker(LayoutBlock* root) | 342 InlineWalker(LayoutBlock* root) |
| 340 : m_root(root) | 343 : m_root(LineLayoutItem(root)) |
| 341 , m_current(nullptr) | 344 , m_current(nullptr) |
| 342 , m_atEndOfInline(false) | 345 , m_atEndOfInline(false) |
| 343 { | 346 { |
| 344 // FIXME: This class should be taught how to do the SkipEmptyInlines cod
epath as well. | 347 // FIXME: This class should be taught how to do the SkipEmptyInlines cod
epath as well. |
| 345 m_current = bidiFirstIncludingEmptyInlines(m_root); | 348 m_current = bidiFirstIncludingEmptyInlines(m_root); |
| 346 } | 349 } |
| 347 | 350 |
| 348 LayoutBlock* root() { return m_root; } | 351 LineLayoutBlockFlow root() { return m_root; } |
| 349 LayoutObject* current() { return m_current; } | 352 LineLayoutItem current() { return m_current; } |
| 350 | 353 |
| 351 bool atEndOfInline() { return m_atEndOfInline; } | 354 bool atEndOfInline() { return m_atEndOfInline; } |
| 352 bool atEnd() const { return !m_current; } | 355 bool atEnd() const { return !m_current; } |
| 353 | 356 |
| 354 LayoutObject* advance() | 357 LineLayoutItem advance() |
| 355 { | 358 { |
| 356 // FIXME: Support SkipEmptyInlines and observer parameters. | 359 // FIXME: Support SkipEmptyInlines and observer parameters. |
| 357 m_current = bidiNextIncludingEmptyInlines(m_root, m_current, &m_atEndOfI
nline); | 360 m_current = bidiNextIncludingEmptyInlines(m_root, m_current, &m_atEndOfI
nline); |
| 358 return m_current; | 361 return m_current; |
| 359 } | 362 } |
| 360 private: | 363 private: |
| 361 LayoutBlock* m_root; | 364 LineLayoutBlockFlow m_root; |
| 362 LayoutObject* m_current; | 365 LineLayoutItem m_current; |
| 363 bool m_atEndOfInline; | 366 bool m_atEndOfInline; |
| 364 }; | 367 }; |
| 365 | 368 |
| 366 static inline bool endOfLineHasIsolatedObjectAncestor(const InlineIterator& isol
atedIterator, const InlineIterator& ancestorItertor) | 369 static inline bool endOfLineHasIsolatedObjectAncestor(const InlineIterator& isol
atedIterator, const InlineIterator& ancestorItertor) |
| 367 { | 370 { |
| 368 if (!isolatedIterator.object() || !isIsolated(isolatedIterator.object()->sty
le()->unicodeBidi())) | 371 if (!isolatedIterator.object() || !isIsolated(isolatedIterator.object()->sty
le()->unicodeBidi())) |
| 369 return false; | 372 return false; |
| 370 | 373 |
| 371 LayoutObject* innerIsolatedObject = isolatedIterator.object(); | 374 LineLayoutItem innerIsolatedObject = isolatedIterator.object(); |
| 372 while (innerIsolatedObject && innerIsolatedObject != isolatedIterator.root()
) { | 375 while (innerIsolatedObject && innerIsolatedObject != isolatedIterator.root()
) { |
| 373 if (innerIsolatedObject == ancestorItertor.object()) | 376 if (innerIsolatedObject == ancestorItertor.object()) |
| 374 return true; | 377 return true; |
| 375 innerIsolatedObject = innerIsolatedObject->parent(); | 378 innerIsolatedObject = innerIsolatedObject->parent(); |
| 376 } | 379 } |
| 377 return false; | 380 return false; |
| 378 } | 381 } |
| 379 | 382 |
| 380 inline void InlineIterator::increment(InlineBidiResolver* resolver, IncrementRul
e rule) | 383 inline void InlineIterator::increment(InlineBidiResolver* resolver, IncrementRul
e rule) |
| 381 { | 384 { |
| 382 if (!m_obj) | 385 if (!m_obj) |
| 383 return; | 386 return; |
| 384 | 387 |
| 385 if (rule == FastIncrementInIsolatedLayout | 388 if (rule == FastIncrementInIsolatedLayout |
| 386 && resolver && resolver->inIsolate() | 389 && resolver && resolver->inIsolate() |
| 387 && !endOfLineHasIsolatedObjectAncestor(resolver->endOfLine(), resolver->
position())) { | 390 && !endOfLineHasIsolatedObjectAncestor(resolver->endOfLine(), resolver->
position())) { |
| 388 moveTo(bidiNextSkippingEmptyInlines(m_root, m_obj, resolver), 0); | 391 moveTo(bidiNextSkippingEmptyInlines(m_root, m_obj, resolver), 0); |
| 389 return; | 392 return; |
| 390 } | 393 } |
| 391 | 394 |
| 392 if (m_obj->isText()) { | 395 if (m_obj.isText()) { |
| 393 fastIncrementInTextNode(); | 396 fastIncrementInTextNode(); |
| 394 if (m_pos < toLayoutText(m_obj)->textLength()) | 397 if (m_pos < LineLayoutText(m_obj).textLength()) |
| 395 return; | 398 return; |
| 396 } | 399 } |
| 397 // bidiNext can return 0, so use moveTo instead of moveToStartOf | 400 // bidiNext can return 0, so use moveTo instead of moveToStartOf |
| 398 moveTo(bidiNextSkippingEmptyInlines(m_root, m_obj, resolver), 0); | 401 moveTo(bidiNextSkippingEmptyInlines(m_root, m_obj, resolver), 0); |
| 399 } | 402 } |
| 400 | 403 |
| 401 inline bool InlineIterator::atEnd() const | 404 inline bool InlineIterator::atEnd() const |
| 402 { | 405 { |
| 403 return !m_obj; | 406 return !m_obj; |
| 404 } | 407 } |
| 405 | 408 |
| 406 inline UChar InlineIterator::characterAt(unsigned index) const | 409 inline UChar InlineIterator::characterAt(unsigned index) const |
| 407 { | 410 { |
| 408 if (!m_obj || !m_obj->isText()) | 411 if (!m_obj || !m_obj.isText()) |
| 409 return 0; | 412 return 0; |
| 410 | 413 |
| 411 return toLayoutText(m_obj)->characterAt(index); | 414 return LineLayoutText(m_obj).characterAt(index); |
| 412 } | 415 } |
| 413 | 416 |
| 414 inline UChar InlineIterator::current() const | 417 inline UChar InlineIterator::current() const |
| 415 { | 418 { |
| 416 return characterAt(m_pos); | 419 return characterAt(m_pos); |
| 417 } | 420 } |
| 418 | 421 |
| 419 inline UChar InlineIterator::previousInSameNode() const | 422 inline UChar InlineIterator::previousInSameNode() const |
| 420 { | 423 { |
| 421 if (!m_pos) | 424 if (!m_pos) |
| 422 return 0; | 425 return 0; |
| 423 | 426 |
| 424 return characterAt(m_pos - 1); | 427 return characterAt(m_pos - 1); |
| 425 } | 428 } |
| 426 | 429 |
| 427 ALWAYS_INLINE WTF::Unicode::Direction InlineIterator::direction() const | 430 ALWAYS_INLINE WTF::Unicode::Direction InlineIterator::direction() const |
| 428 { | 431 { |
| 429 if (UChar c = current()) | 432 if (UChar c = current()) |
| 430 return WTF::Unicode::direction(c); | 433 return WTF::Unicode::direction(c); |
| 431 | 434 |
| 432 if (m_obj && m_obj->isListMarker()) | 435 if (m_obj && m_obj.isListMarker()) |
| 433 return m_obj->style()->isLeftToRightDirection() ? WTF::Unicode::LeftToRi
ght : WTF::Unicode::RightToLeft; | 436 return m_obj.style()->isLeftToRightDirection() ? WTF::Unicode::LeftToRig
ht : WTF::Unicode::RightToLeft; |
| 434 | 437 |
| 435 return WTF::Unicode::OtherNeutral; | 438 return WTF::Unicode::OtherNeutral; |
| 436 } | 439 } |
| 437 | 440 |
| 438 template<> | 441 template<> |
| 439 inline void InlineBidiResolver::increment() | 442 inline void InlineBidiResolver::increment() |
| 440 { | 443 { |
| 441 m_current.increment(this, InlineIterator::FastIncrementInIsolatedLayout); | 444 m_current.increment(this, InlineIterator::FastIncrementInIsolatedLayout); |
| 442 } | 445 } |
| 443 | 446 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 473 firstSpace--; | 476 firstSpace--; |
| 474 } | 477 } |
| 475 | 478 |
| 476 return firstSpace; | 479 return firstSpace; |
| 477 } | 480 } |
| 478 | 481 |
| 479 template <> | 482 template <> |
| 480 inline int InlineBidiResolver::findFirstTrailingSpaceAtRun(BidiRun* run) | 483 inline int InlineBidiResolver::findFirstTrailingSpaceAtRun(BidiRun* run) |
| 481 { | 484 { |
| 482 ASSERT(run); | 485 ASSERT(run); |
| 483 LayoutObject* lastObject = run->m_object; | 486 LineLayoutItem lastObject = LineLayoutItem(run->m_object); |
| 484 if (!lastObject->isText()) | 487 if (!lastObject->isText()) |
| 485 return run->m_stop; | 488 return run->m_stop; |
| 486 | 489 |
| 487 LayoutText* lastText = toLayoutText(lastObject); | 490 LayoutText* lastText = toLayoutText(lastObject); |
| 488 int firstSpace; | 491 int firstSpace; |
| 489 if (lastText->is8Bit()) | 492 if (lastText->is8Bit()) |
| 490 firstSpace = findFirstTrailingSpace(lastText, lastText->characters8(), r
un->start(), run->stop()); | 493 firstSpace = findFirstTrailingSpace(lastText, lastText->characters8(), r
un->start(), run->stop()); |
| 491 else | 494 else |
| 492 firstSpace = findFirstTrailingSpace(lastText, lastText->characters16(),
run->start(), run->stop()); | 495 firstSpace = findFirstTrailingSpace(lastText, lastText->characters16(),
run->start(), run->stop()); |
| 493 return firstSpace; | 496 return firstSpace; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 507 | 510 |
| 508 template <> | 511 template <> |
| 509 inline bool InlineBidiResolver::needsToApplyL1Rule(BidiRunList<BidiRun>& runs) | 512 inline bool InlineBidiResolver::needsToApplyL1Rule(BidiRunList<BidiRun>& runs) |
| 510 { | 513 { |
| 511 if (!runs.logicallyLastRun()->m_object->style()->breakOnlyAfterWhiteSpace() | 514 if (!runs.logicallyLastRun()->m_object->style()->breakOnlyAfterWhiteSpace() |
| 512 || !runs.logicallyLastRun()->m_object->style()->autoWrap()) | 515 || !runs.logicallyLastRun()->m_object->style()->autoWrap()) |
| 513 return false; | 516 return false; |
| 514 return true; | 517 return true; |
| 515 } | 518 } |
| 516 | 519 |
| 517 static inline bool isIsolatedInline(LayoutObject* object) | 520 static inline bool isIsolatedInline(LineLayoutItem object) |
| 518 { | 521 { |
| 519 ASSERT(object); | 522 ASSERT(object); |
| 520 return object->isLayoutInline() && isIsolated(object->style()->unicodeBidi()
); | 523 return object->isLayoutInline() && isIsolated(object->style()->unicodeBidi()
); |
| 521 } | 524 } |
| 522 | 525 |
| 523 static inline LayoutObject* highestContainingIsolateWithinRoot(LayoutObject* obj
ect, LayoutObject* root) | 526 static inline LineLayoutItem highestContainingIsolateWithinRoot(LineLayoutItem o
bject, LineLayoutItem root) |
| 524 { | 527 { |
| 525 ASSERT(object); | 528 ASSERT(object); |
| 526 LayoutObject* containingIsolateObj = 0; | 529 LineLayoutItem containingIsolateObj = 0; |
| 527 while (object && object != root) { | 530 while (object && object != root) { |
| 528 if (isIsolatedInline(object)) | 531 if (isIsolatedInline(object)) |
| 529 containingIsolateObj = object; | 532 containingIsolateObj = object; |
| 530 | 533 |
| 531 object = object->parent(); | 534 object = object->parent(); |
| 532 } | 535 } |
| 533 return containingIsolateObj; | 536 return containingIsolateObj; |
| 534 } | 537 } |
| 535 | 538 |
| 536 static inline unsigned numberOfIsolateAncestors(const InlineIterator& iter) | 539 static inline unsigned numberOfIsolateAncestors(const InlineIterator& iter) |
| 537 { | 540 { |
| 538 LayoutObject* object = iter.object(); | 541 LineLayoutItem object = iter.object(); |
| 539 if (!object) | 542 if (!object) |
| 540 return 0; | 543 return 0; |
| 541 unsigned count = 0; | 544 unsigned count = 0; |
| 542 while (object && object != iter.root()) { | 545 while (object && object != iter.root()) { |
| 543 if (isIsolatedInline(object)) | 546 if (isIsolatedInline(object)) |
| 544 count++; | 547 count++; |
| 545 object = object->parent(); | 548 object = object->parent(); |
| 546 } | 549 } |
| 547 return count; | 550 return count; |
| 548 } | 551 } |
| 549 | 552 |
| 550 // FIXME: This belongs on InlineBidiResolver, except it's a template specializat
ion | 553 // FIXME: This belongs on InlineBidiResolver, except it's a template specializat
ion |
| 551 // of BidiResolver which knows nothing about LayoutObjects. | 554 // of BidiResolver which knows nothing about LayoutObjects. |
| 552 static inline BidiRun* addPlaceholderRunForIsolatedInline(InlineBidiResolver& re
solver, LayoutObject* obj, unsigned pos) | 555 static inline BidiRun* addPlaceholderRunForIsolatedInline(InlineBidiResolver& re
solver, LineLayoutItem obj, unsigned pos) |
| 553 { | 556 { |
| 554 ASSERT(obj); | 557 ASSERT(obj); |
| 555 BidiRun* isolatedRun = new BidiRun(pos, pos, obj, resolver.context(), resolv
er.dir()); | 558 BidiRun* isolatedRun = new BidiRun(pos, pos, obj, resolver.context(), resolv
er.dir()); |
| 556 resolver.runs().addRun(isolatedRun); | 559 resolver.runs().addRun(isolatedRun); |
| 557 // FIXME: isolatedRuns() could be a hash of object->run and then we could ch
eaply | 560 // FIXME: isolatedRuns() could be a hash of object->run and then we could ch
eaply |
| 558 // ASSERT here that we didn't create multiple objects for the same inline. | 561 // ASSERT here that we didn't create multiple objects for the same inline. |
| 559 resolver.isolatedRuns().append(isolatedRun); | 562 resolver.isolatedRuns().append(isolatedRun); |
| 560 return isolatedRun; | 563 return isolatedRun; |
| 561 } | 564 } |
| 562 | 565 |
| 563 static inline BidiRun* createRun(int start, int end, LayoutObject* obj, InlineBi
diResolver& resolver) | 566 static inline BidiRun* createRun(int start, int end, LineLayoutItem obj, InlineB
idiResolver& resolver) |
| 564 { | 567 { |
| 565 return new BidiRun(start, end, obj, resolver.context(), resolver.dir()); | 568 return new BidiRun(start, end, obj, resolver.context(), resolver.dir()); |
| 566 } | 569 } |
| 567 | 570 |
| 568 enum AppendRunBehavior { | 571 enum AppendRunBehavior { |
| 569 AppendingFakeRun, | 572 AppendingFakeRun, |
| 570 AppendingRunsForObject | 573 AppendingRunsForObject |
| 571 }; | 574 }; |
| 572 | 575 |
| 573 class IsolateTracker { | 576 class IsolateTracker { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 592 if (!inIsolate()) | 595 if (!inIsolate()) |
| 593 m_haveAddedFakeRunForRootIsolate = false; | 596 m_haveAddedFakeRunForRootIsolate = false; |
| 594 } | 597 } |
| 595 bool inIsolate() const { return m_nestedIsolateCount; } | 598 bool inIsolate() const { return m_nestedIsolateCount; } |
| 596 | 599 |
| 597 // We don't care if we encounter bidi directional overrides. | 600 // We don't care if we encounter bidi directional overrides. |
| 598 void embed(WTF::Unicode::Direction, BidiEmbeddingSource) { } | 601 void embed(WTF::Unicode::Direction, BidiEmbeddingSource) { } |
| 599 void commitExplicitEmbedding(BidiRunList<BidiRun>&) { } | 602 void commitExplicitEmbedding(BidiRunList<BidiRun>&) { } |
| 600 BidiRunList<BidiRun>& runs() { return m_runs; } | 603 BidiRunList<BidiRun>& runs() { return m_runs; } |
| 601 | 604 |
| 602 void addFakeRunIfNecessary(LayoutObject* obj, unsigned pos, unsigned end, In
lineBidiResolver& resolver) | 605 void addFakeRunIfNecessary(LineLayoutItem obj, unsigned pos, unsigned end, I
nlineBidiResolver& resolver) |
| 603 { | 606 { |
| 604 // We only need to add a fake run for a given isolated span once during
each call to createBidiRunsForLine. | 607 // We only need to add a fake run for a given isolated span once during
each call to createBidiRunsForLine. |
| 605 // We'll be called for every span inside the isolated span so we just ig
nore subsequent calls. | 608 // We'll be called for every span inside the isolated span so we just ig
nore subsequent calls. |
| 606 // We also avoid creating a fake run until we hit a child that warrants
one, e.g. we skip floats. | 609 // We also avoid creating a fake run until we hit a child that warrants
one, e.g. we skip floats. |
| 607 if (LayoutBlockFlow::shouldSkipCreatingRunsForObject(obj)) | 610 if (LayoutBlockFlow::shouldSkipCreatingRunsForObject(obj)) |
| 608 return; | 611 return; |
| 609 if (!m_haveAddedFakeRunForRootIsolate) { | 612 if (!m_haveAddedFakeRunForRootIsolate) { |
| 610 BidiRun* run = addPlaceholderRunForIsolatedInline(resolver, obj, pos
); | 613 BidiRun* run = addPlaceholderRunForIsolatedInline(resolver, obj, pos
); |
| 611 resolver.setMidpointStateForIsolatedRun(run, m_midpointStateForRootI
solate); | 614 resolver.setMidpointStateForIsolatedRun(run, m_midpointStateForRootI
solate); |
| 612 m_haveAddedFakeRunForRootIsolate = true; | 615 m_haveAddedFakeRunForRootIsolate = true; |
| 613 } | 616 } |
| 614 // obj and pos together denote a single position in the inline, from whi
ch the parsing of the isolate will start. | 617 // obj and pos together denote a single position in the inline, from whi
ch the parsing of the isolate will start. |
| 615 // We don't need to mark the end of the run because this is implicit: it
is either endOfLine or the end of the | 618 // We don't need to mark the end of the run because this is implicit: it
is either endOfLine or the end of the |
| 616 // isolate, when we call createBidiRunsForLine it will stop at whichever
comes first. | 619 // isolate, when we call createBidiRunsForLine it will stop at whichever
comes first. |
| 617 } | 620 } |
| 618 | 621 |
| 619 private: | 622 private: |
| 620 unsigned m_nestedIsolateCount; | 623 unsigned m_nestedIsolateCount; |
| 621 bool m_haveAddedFakeRunForRootIsolate; | 624 bool m_haveAddedFakeRunForRootIsolate; |
| 622 LineMidpointState m_midpointStateForRootIsolate; | 625 LineMidpointState m_midpointStateForRootIsolate; |
| 623 BidiRunList<BidiRun>& m_runs; | 626 BidiRunList<BidiRun>& m_runs; |
| 624 }; | 627 }; |
| 625 | 628 |
| 626 static void inline appendRunObjectIfNecessary(LayoutObject* obj, unsigned start,
unsigned end, InlineBidiResolver& resolver, AppendRunBehavior behavior, Isolate
Tracker& tracker) | 629 static void inline appendRunObjectIfNecessary(LineLayoutItem obj, unsigned start
, unsigned end, InlineBidiResolver& resolver, AppendRunBehavior behavior, Isolat
eTracker& tracker) |
| 627 { | 630 { |
| 628 // Trailing space code creates empty BidiRun objects, start == end, so | 631 // Trailing space code creates empty BidiRun objects, start == end, so |
| 629 // that case needs to be handled specifically. | 632 // that case needs to be handled specifically. |
| 630 bool addEmptyRun = (end == start); | 633 bool addEmptyRun = (end == start); |
| 631 | 634 |
| 632 // Append BidiRun objects, at most 64K chars at a time, until all | 635 // Append BidiRun objects, at most 64K chars at a time, until all |
| 633 // text between |start| and |end| is represented. | 636 // text between |start| and |end| is represented. |
| 634 while (end > start || addEmptyRun) { | 637 while (end > start || addEmptyRun) { |
| 635 addEmptyRun = false; | 638 addEmptyRun = false; |
| 636 const int limit = USHRT_MAX; // InlineTextBox stores text length as unsi
gned short. | 639 const int limit = USHRT_MAX; // InlineTextBox stores text length as unsi
gned short. |
| 637 unsigned limitedEnd = end; | 640 unsigned limitedEnd = end; |
| 638 if (end - start > limit) | 641 if (end - start > limit) |
| 639 limitedEnd = start + limit; | 642 limitedEnd = start + limit; |
| 640 if (behavior == AppendingFakeRun) | 643 if (behavior == AppendingFakeRun) |
| 641 tracker.addFakeRunIfNecessary(obj, start, limitedEnd, resolver); | 644 tracker.addFakeRunIfNecessary(obj, start, limitedEnd, resolver); |
| 642 else | 645 else |
| 643 resolver.runs().addRun(createRun(start, limitedEnd, obj, resolver)); | 646 resolver.runs().addRun(createRun(start, limitedEnd, obj, resolver)); |
| 644 start = limitedEnd; | 647 start = limitedEnd; |
| 645 } | 648 } |
| 646 } | 649 } |
| 647 | 650 |
| 648 static void adjustMidpointsAndAppendRunsForObjectIfNeeded(LayoutObject* obj, uns
igned start, unsigned end, InlineBidiResolver& resolver, AppendRunBehavior behav
ior, IsolateTracker& tracker) | 651 static void adjustMidpointsAndAppendRunsForObjectIfNeeded(LineLayoutItem obj, un
signed start, unsigned end, InlineBidiResolver& resolver, AppendRunBehavior beha
vior, IsolateTracker& tracker) |
| 649 { | 652 { |
| 650 if (start > end || LayoutBlockFlow::shouldSkipCreatingRunsForObject(obj)) | 653 if (start > end || LayoutBlockFlow::shouldSkipCreatingRunsForObject(obj)) |
| 651 return; | 654 return; |
| 652 | 655 |
| 653 LineMidpointState& lineMidpointState = resolver.midpointState(); | 656 LineMidpointState& lineMidpointState = resolver.midpointState(); |
| 654 bool haveNextMidpoint = (lineMidpointState.currentMidpoint() < lineMidpointS
tate.numMidpoints()); | 657 bool haveNextMidpoint = (lineMidpointState.currentMidpoint() < lineMidpointS
tate.numMidpoints()); |
| 655 InlineIterator nextMidpoint; | 658 InlineIterator nextMidpoint; |
| 656 if (haveNextMidpoint) | 659 if (haveNextMidpoint) |
| 657 nextMidpoint = lineMidpointState.midpoints()[lineMidpointState.currentMi
dpoint()]; | 660 nextMidpoint = lineMidpointState.midpoints()[lineMidpointState.currentMi
dpoint()]; |
| 658 if (lineMidpointState.betweenMidpoints()) { | 661 if (lineMidpointState.betweenMidpoints()) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 680 if (nextMidpoint.offset() + 1 > start) | 683 if (nextMidpoint.offset() + 1 > start) |
| 681 appendRunObjectIfNecessary(obj, start, nextMidpoint.offset()
+ 1, resolver, behavior, tracker); | 684 appendRunObjectIfNecessary(obj, start, nextMidpoint.offset()
+ 1, resolver, behavior, tracker); |
| 682 return adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, nextMi
dpoint.offset() + 1, end, resolver, behavior, tracker); | 685 return adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, nextMi
dpoint.offset() + 1, end, resolver, behavior, tracker); |
| 683 } | 686 } |
| 684 } else { | 687 } else { |
| 685 appendRunObjectIfNecessary(obj, start, end, resolver, behavior, trac
ker); | 688 appendRunObjectIfNecessary(obj, start, end, resolver, behavior, trac
ker); |
| 686 } | 689 } |
| 687 } | 690 } |
| 688 } | 691 } |
| 689 | 692 |
| 690 static inline void addFakeRunIfNecessary(LayoutObject* obj, unsigned start, unsi
gned end, InlineBidiResolver& resolver, IsolateTracker& tracker) | 693 static inline void addFakeRunIfNecessary(LineLayoutItem obj, unsigned start, uns
igned end, InlineBidiResolver& resolver, IsolateTracker& tracker) |
| 691 { | 694 { |
| 692 tracker.setMidpointStateForRootIsolate(resolver.midpointState()); | 695 tracker.setMidpointStateForRootIsolate(resolver.midpointState()); |
| 693 adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, obj->length(), res
olver, AppendingFakeRun, tracker); | 696 adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, obj->length(), res
olver, AppendingFakeRun, tracker); |
| 694 } | 697 } |
| 695 | 698 |
| 696 template <> | 699 template <> |
| 697 inline void InlineBidiResolver::appendRun(BidiRunList<BidiRun>& runs) | 700 inline void InlineBidiResolver::appendRun(BidiRunList<BidiRun>& runs) |
| 698 { | 701 { |
| 699 if (!m_emptyRun && !m_eor.atEnd() && !m_reachedEndOfLine) { | 702 if (!m_emptyRun && !m_eor.atEnd() && !m_reachedEndOfLine) { |
| 700 // Keep track of when we enter/leave "unicode-bidi: isolate" inlines. | 703 // Keep track of when we enter/leave "unicode-bidi: isolate" inlines. |
| 701 // Initialize our state depending on if we're starting in the middle of
such an inline. | 704 // Initialize our state depending on if we're starting in the middle of
such an inline. |
| 702 // FIXME: Could this initialize from this->inIsolate() instead of walkin
g up the layout tree? | 705 // FIXME: Could this initialize from this->inIsolate() instead of walkin
g up the layout tree? |
| 703 IsolateTracker isolateTracker(runs, numberOfIsolateAncestors(m_sor)); | 706 IsolateTracker isolateTracker(runs, numberOfIsolateAncestors(m_sor)); |
| 704 int start = m_sor.offset(); | 707 int start = m_sor.offset(); |
| 705 LayoutObject* obj = m_sor.object(); | 708 LineLayoutItem obj = m_sor.object(); |
| 706 while (obj && obj != m_eor.object() && obj != m_endOfRunAtEndOfLine.obje
ct()) { | 709 while (obj && obj != m_eor.object() && obj != m_endOfRunAtEndOfLine.obje
ct()) { |
| 707 if (isolateTracker.inIsolate()) | 710 if (isolateTracker.inIsolate()) |
| 708 addFakeRunIfNecessary(obj, start, obj->length(), *this, isolateT
racker); | 711 addFakeRunIfNecessary(obj, start, obj->length(), *this, isolateT
racker); |
| 709 else | 712 else |
| 710 adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, obj->l
ength(), *this, AppendingRunsForObject, isolateTracker); | 713 adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, obj->l
ength(), *this, AppendingRunsForObject, isolateTracker); |
| 711 // FIXME: start/obj should be an InlineIterator instead of two separ
ate variables. | 714 // FIXME: start/obj should be an InlineIterator instead of two separ
ate variables. |
| 712 start = 0; | 715 start = 0; |
| 713 obj = bidiNextSkippingEmptyInlines(m_sor.root(), obj, &isolateTracke
r); | 716 obj = bidiNextSkippingEmptyInlines(m_sor.root(), obj, &isolateTracke
r); |
| 714 } | 717 } |
| 715 bool isEndOfLine = obj == m_endOfLine.object() && !m_endOfLine.offset(); | 718 bool isEndOfLine = obj == m_endOfLine.object() && !m_endOfLine.offset(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 737 m_sor = m_eor; | 740 m_sor = m_eor; |
| 738 } | 741 } |
| 739 | 742 |
| 740 m_direction = WTF::Unicode::OtherNeutral; | 743 m_direction = WTF::Unicode::OtherNeutral; |
| 741 m_status.eor = WTF::Unicode::OtherNeutral; | 744 m_status.eor = WTF::Unicode::OtherNeutral; |
| 742 } | 745 } |
| 743 | 746 |
| 744 } | 747 } |
| 745 | 748 |
| 746 #endif // InlineIterator_h | 749 #endif // InlineIterator_h |
| OLD | NEW |