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 |