OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2009 Google Inc. All rights reserved. | 2 * Copyright (C) 2009 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 | 58 |
59 bool LayoutRubyRun::hasRubyBase() const | 59 bool LayoutRubyRun::hasRubyBase() const |
60 { | 60 { |
61 // The only place where a ruby base can be is in the last position | 61 // The only place where a ruby base can be is in the last position |
62 // Note: As anonymous blocks, ruby runs do not have ':before' or ':after' co
ntent themselves. | 62 // Note: As anonymous blocks, ruby runs do not have ':before' or ':after' co
ntent themselves. |
63 return lastChild() && lastChild()->isRubyBase(); | 63 return lastChild() && lastChild()->isRubyBase(); |
64 } | 64 } |
65 | 65 |
66 LayoutRubyText* LayoutRubyRun::rubyText() const | 66 LayoutRubyText* LayoutRubyRun::rubyText() const |
67 { | 67 { |
68 RenderObject* child = firstChild(); | 68 LayoutObject* child = firstChild(); |
69 // If in future it becomes necessary to support floating or positioned ruby
text, | 69 // If in future it becomes necessary to support floating or positioned ruby
text, |
70 // layout will have to be changed to handle them properly. | 70 // layout will have to be changed to handle them properly. |
71 ASSERT(!child || !child->isRubyText() || !child->isFloatingOrOutOfFlowPositi
oned()); | 71 ASSERT(!child || !child->isRubyText() || !child->isFloatingOrOutOfFlowPositi
oned()); |
72 return child && child->isRubyText() ? static_cast<LayoutRubyText*>(child) :
0; | 72 return child && child->isRubyText() ? static_cast<LayoutRubyText*>(child) :
0; |
73 } | 73 } |
74 | 74 |
75 LayoutRubyBase* LayoutRubyRun::rubyBase() const | 75 LayoutRubyBase* LayoutRubyRun::rubyBase() const |
76 { | 76 { |
77 RenderObject* child = lastChild(); | 77 LayoutObject* child = lastChild(); |
78 return child && child->isRubyBase() ? static_cast<LayoutRubyBase*>(child) :
0; | 78 return child && child->isRubyBase() ? static_cast<LayoutRubyBase*>(child) :
0; |
79 } | 79 } |
80 | 80 |
81 LayoutRubyBase* LayoutRubyRun::rubyBaseSafe() | 81 LayoutRubyBase* LayoutRubyRun::rubyBaseSafe() |
82 { | 82 { |
83 LayoutRubyBase* base = rubyBase(); | 83 LayoutRubyBase* base = rubyBase(); |
84 if (!base) { | 84 if (!base) { |
85 base = createRubyBase(); | 85 base = createRubyBase(); |
86 RenderBlockFlow::addChild(base); | 86 RenderBlockFlow::addChild(base); |
87 } | 87 } |
88 return base; | 88 return base; |
89 } | 89 } |
90 | 90 |
91 bool LayoutRubyRun::isChildAllowed(RenderObject* child, const RenderStyle&) cons
t | 91 bool LayoutRubyRun::isChildAllowed(LayoutObject* child, const RenderStyle&) cons
t |
92 { | 92 { |
93 return child->isRubyText() || child->isInline(); | 93 return child->isRubyText() || child->isInline(); |
94 } | 94 } |
95 | 95 |
96 void LayoutRubyRun::addChild(RenderObject* child, RenderObject* beforeChild) | 96 void LayoutRubyRun::addChild(LayoutObject* child, LayoutObject* beforeChild) |
97 { | 97 { |
98 ASSERT(child); | 98 ASSERT(child); |
99 | 99 |
100 if (child->isRubyText()) { | 100 if (child->isRubyText()) { |
101 if (!beforeChild) { | 101 if (!beforeChild) { |
102 // LayoutRuby has already ascertained that we can add the child here
. | 102 // LayoutRuby has already ascertained that we can add the child here
. |
103 ASSERT(!hasRubyText()); | 103 ASSERT(!hasRubyText()); |
104 // prepend ruby texts as first child | 104 // prepend ruby texts as first child |
105 RenderBlockFlow::addChild(child, firstChild()); | 105 RenderBlockFlow::addChild(child, firstChild()); |
106 } else if (beforeChild->isRubyText()) { | 106 } else if (beforeChild->isRubyText()) { |
107 // New text is inserted just before another. | 107 // New text is inserted just before another. |
108 // In this case the new text takes the place of the old one, and | 108 // In this case the new text takes the place of the old one, and |
109 // the old text goes into a new run that is inserted as next sibling
. | 109 // the old text goes into a new run that is inserted as next sibling
. |
110 ASSERT(beforeChild->parent() == this); | 110 ASSERT(beforeChild->parent() == this); |
111 RenderObject* ruby = parent(); | 111 LayoutObject* ruby = parent(); |
112 ASSERT(ruby->isRuby()); | 112 ASSERT(ruby->isRuby()); |
113 RenderBlock* newRun = staticCreateRubyRun(ruby); | 113 RenderBlock* newRun = staticCreateRubyRun(ruby); |
114 ruby->addChild(newRun, nextSibling()); | 114 ruby->addChild(newRun, nextSibling()); |
115 // Add the new ruby text and move the old one to the new run | 115 // Add the new ruby text and move the old one to the new run |
116 // Note: Doing it in this order and not using LayoutRubyRun's method
s, | 116 // Note: Doing it in this order and not using LayoutRubyRun's method
s, |
117 // in order to avoid automatic removal of the ruby run in case there
is no | 117 // in order to avoid automatic removal of the ruby run in case there
is no |
118 // other child besides the old ruby text. | 118 // other child besides the old ruby text. |
119 RenderBlockFlow::addChild(child, beforeChild); | 119 RenderBlockFlow::addChild(child, beforeChild); |
120 RenderBlockFlow::removeChild(beforeChild); | 120 RenderBlockFlow::removeChild(beforeChild); |
121 newRun->addChild(beforeChild); | 121 newRun->addChild(beforeChild); |
122 } else if (hasRubyBase()) { | 122 } else if (hasRubyBase()) { |
123 // Insertion before a ruby base object. | 123 // Insertion before a ruby base object. |
124 // In this case we need insert a new run before the current one and
split the base. | 124 // In this case we need insert a new run before the current one and
split the base. |
125 RenderObject* ruby = parent(); | 125 LayoutObject* ruby = parent(); |
126 LayoutRubyRun* newRun = staticCreateRubyRun(ruby); | 126 LayoutRubyRun* newRun = staticCreateRubyRun(ruby); |
127 ruby->addChild(newRun, this); | 127 ruby->addChild(newRun, this); |
128 newRun->addChild(child); | 128 newRun->addChild(child); |
129 rubyBaseSafe()->moveChildren(newRun->rubyBaseSafe(), beforeChild); | 129 rubyBaseSafe()->moveChildren(newRun->rubyBaseSafe(), beforeChild); |
130 } | 130 } |
131 } else { | 131 } else { |
132 // child is not a text -> insert it into the base | 132 // child is not a text -> insert it into the base |
133 // (append it instead if beforeChild is the ruby text) | 133 // (append it instead if beforeChild is the ruby text) |
134 LayoutRubyBase* base = rubyBaseSafe(); | 134 LayoutRubyBase* base = rubyBaseSafe(); |
135 if (beforeChild == base) | 135 if (beforeChild == base) |
136 beforeChild = base->firstChild(); | 136 beforeChild = base->firstChild(); |
137 if (beforeChild && beforeChild->isRubyText()) | 137 if (beforeChild && beforeChild->isRubyText()) |
138 beforeChild = 0; | 138 beforeChild = 0; |
139 ASSERT(!beforeChild || beforeChild->isDescendantOf(base)); | 139 ASSERT(!beforeChild || beforeChild->isDescendantOf(base)); |
140 base->addChild(child, beforeChild); | 140 base->addChild(child, beforeChild); |
141 } | 141 } |
142 } | 142 } |
143 | 143 |
144 void LayoutRubyRun::removeChild(RenderObject* child) | 144 void LayoutRubyRun::removeChild(LayoutObject* child) |
145 { | 145 { |
146 // If the child is a ruby text, then merge the ruby base with the base of | 146 // If the child is a ruby text, then merge the ruby base with the base of |
147 // the right sibling run, if possible. | 147 // the right sibling run, if possible. |
148 if (!beingDestroyed() && !documentBeingDestroyed() && child->isRubyText()) { | 148 if (!beingDestroyed() && !documentBeingDestroyed() && child->isRubyText()) { |
149 LayoutRubyBase* base = rubyBase(); | 149 LayoutRubyBase* base = rubyBase(); |
150 RenderObject* rightNeighbour = nextSibling(); | 150 LayoutObject* rightNeighbour = nextSibling(); |
151 if (base && rightNeighbour && rightNeighbour->isRubyRun()) { | 151 if (base && rightNeighbour && rightNeighbour->isRubyRun()) { |
152 // Ruby run without a base can happen only at the first run. | 152 // Ruby run without a base can happen only at the first run. |
153 LayoutRubyRun* rightRun = toLayoutRubyRun(rightNeighbour); | 153 LayoutRubyRun* rightRun = toLayoutRubyRun(rightNeighbour); |
154 if (rightRun->hasRubyBase()) { | 154 if (rightRun->hasRubyBase()) { |
155 LayoutRubyBase* rightBase = rightRun->rubyBaseSafe(); | 155 LayoutRubyBase* rightBase = rightRun->rubyBaseSafe(); |
156 // Collect all children in a single base, then swap the bases. | 156 // Collect all children in a single base, then swap the bases. |
157 rightBase->moveChildren(base); | 157 rightBase->moveChildren(base); |
158 moveChildTo(rightRun, base); | 158 moveChildTo(rightRun, base); |
159 rightRun->moveChildTo(this, rightBase); | 159 rightRun->moveChildTo(this, rightBase); |
160 // The now empty ruby base will be removed below. | 160 // The now empty ruby base will be removed below. |
(...skipping 23 matching lines...) Expand all Loading... |
184 | 184 |
185 LayoutRubyBase* LayoutRubyRun::createRubyBase() const | 185 LayoutRubyBase* LayoutRubyRun::createRubyBase() const |
186 { | 186 { |
187 LayoutRubyBase* layoutObject = LayoutRubyBase::createAnonymous(&document()); | 187 LayoutRubyBase* layoutObject = LayoutRubyBase::createAnonymous(&document()); |
188 RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(
style(), BLOCK); | 188 RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(
style(), BLOCK); |
189 newStyle->setTextAlign(CENTER); // FIXME: use WEBKIT_CENTER? | 189 newStyle->setTextAlign(CENTER); // FIXME: use WEBKIT_CENTER? |
190 layoutObject->setStyle(newStyle.release()); | 190 layoutObject->setStyle(newStyle.release()); |
191 return layoutObject; | 191 return layoutObject; |
192 } | 192 } |
193 | 193 |
194 LayoutRubyRun* LayoutRubyRun::staticCreateRubyRun(const RenderObject* parentRuby
) | 194 LayoutRubyRun* LayoutRubyRun::staticCreateRubyRun(const LayoutObject* parentRuby
) |
195 { | 195 { |
196 ASSERT(parentRuby && parentRuby->isRuby()); | 196 ASSERT(parentRuby && parentRuby->isRuby()); |
197 LayoutRubyRun* rr = new LayoutRubyRun(); | 197 LayoutRubyRun* rr = new LayoutRubyRun(); |
198 rr->setDocumentForAnonymous(&parentRuby->document()); | 198 rr->setDocumentForAnonymous(&parentRuby->document()); |
199 RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(
parentRuby->style(), INLINE_BLOCK); | 199 RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(
parentRuby->style(), INLINE_BLOCK); |
200 rr->setStyle(newStyle.release()); | 200 rr->setStyle(newStyle.release()); |
201 return rr; | 201 return rr; |
202 } | 202 } |
203 | 203 |
204 RenderObject* LayoutRubyRun::layoutSpecialExcludedChild(bool relayoutChildren, S
ubtreeLayoutScope& layoutScope) | 204 LayoutObject* LayoutRubyRun::layoutSpecialExcludedChild(bool relayoutChildren, S
ubtreeLayoutScope& layoutScope) |
205 { | 205 { |
206 // Don't bother positioning the LayoutRubyRun yet. | 206 // Don't bother positioning the LayoutRubyRun yet. |
207 LayoutRubyText* rt = rubyText(); | 207 LayoutRubyText* rt = rubyText(); |
208 if (!rt) | 208 if (!rt) |
209 return 0; | 209 return 0; |
210 if (relayoutChildren) | 210 if (relayoutChildren) |
211 layoutScope.setChildNeedsLayout(rt); | 211 layoutScope.setChildNeedsLayout(rt); |
212 rt->layoutIfNeeded(); | 212 rt->layoutIfNeeded(); |
213 return rt; | 213 return rt; |
214 } | 214 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 lastLineBottom += rb->logicalTop(); | 252 lastLineBottom += rb->logicalTop(); |
253 } | 253 } |
254 | 254 |
255 rt->setLogicalTop(-firstLineRubyTextTop + lastLineBottom); | 255 rt->setLogicalTop(-firstLineRubyTextTop + lastLineBottom); |
256 } | 256 } |
257 | 257 |
258 // Update our overflow to account for the new LayoutRubyText position. | 258 // Update our overflow to account for the new LayoutRubyText position. |
259 computeOverflow(clientLogicalBottom()); | 259 computeOverflow(clientLogicalBottom()); |
260 } | 260 } |
261 | 261 |
262 void LayoutRubyRun::getOverhang(bool firstLine, RenderObject* startRenderer, Ren
derObject* endRenderer, int& startOverhang, int& endOverhang) const | 262 void LayoutRubyRun::getOverhang(bool firstLine, LayoutObject* startRenderer, Lay
outObject* endRenderer, int& startOverhang, int& endOverhang) const |
263 { | 263 { |
264 ASSERT(!needsLayout()); | 264 ASSERT(!needsLayout()); |
265 | 265 |
266 startOverhang = 0; | 266 startOverhang = 0; |
267 endOverhang = 0; | 267 endOverhang = 0; |
268 | 268 |
269 LayoutRubyBase* rubyBase = this->rubyBase(); | 269 LayoutRubyBase* rubyBase = this->rubyBase(); |
270 LayoutRubyText* rubyText = this->rubyText(); | 270 LayoutRubyText* rubyText = this->rubyText(); |
271 | 271 |
272 if (!rubyBase || !rubyText) | 272 if (!rubyBase || !rubyText) |
(...skipping 23 matching lines...) Expand all Loading... |
296 // We can overhang the ruby by no more than half the width of the neighborin
g text | 296 // We can overhang the ruby by no more than half the width of the neighborin
g text |
297 // and no more than half the font size. | 297 // and no more than half the font size. |
298 int halfWidthOfFontSize = rubyText->style(firstLine)->fontSize() / 2; | 298 int halfWidthOfFontSize = rubyText->style(firstLine)->fontSize() / 2; |
299 if (startOverhang) | 299 if (startOverhang) |
300 startOverhang = std::min<int>(startOverhang, std::min<int>(toRenderText(
startRenderer)->minLogicalWidth(), halfWidthOfFontSize)); | 300 startOverhang = std::min<int>(startOverhang, std::min<int>(toRenderText(
startRenderer)->minLogicalWidth(), halfWidthOfFontSize)); |
301 if (endOverhang) | 301 if (endOverhang) |
302 endOverhang = std::min<int>(endOverhang, std::min<int>(toRenderText(endR
enderer)->minLogicalWidth(), halfWidthOfFontSize)); | 302 endOverhang = std::min<int>(endOverhang, std::min<int>(toRenderText(endR
enderer)->minLogicalWidth(), halfWidthOfFontSize)); |
303 } | 303 } |
304 | 304 |
305 } // namespace blink | 305 } // namespace blink |
OLD | NEW |