OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2012 Victor Carbune (victor@rosedu.org) | 2 * Copyright (C) 2012 Victor Carbune (victor@rosedu.org) |
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 | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 26 matching lines...) Expand all Loading... | |
37 , m_cue(element->getCue()) | 37 , m_cue(element->getCue()) |
38 { | 38 { |
39 } | 39 } |
40 | 40 |
41 void RenderVTTCue::trace(Visitor* visitor) | 41 void RenderVTTCue::trace(Visitor* visitor) |
42 { | 42 { |
43 visitor->trace(m_cue); | 43 visitor->trace(m_cue); |
44 RenderBlockFlow::trace(visitor); | 44 RenderBlockFlow::trace(visitor); |
45 } | 45 } |
46 | 46 |
47 void RenderVTTCue::layout() | 47 class SnapToLinesLayouter { |
48 STACK_ALLOCATED(); | |
49 public: | |
50 SnapToLinesLayouter(RenderVTTCue& cueBox, VTTCue::WritingDirection writingDi rection, float linePosition) | |
51 : m_cueBox(cueBox) | |
52 , m_cueWritingDirection(writingDirection) | |
53 , m_linePosition(linePosition) | |
54 { | |
55 } | |
56 | |
57 void layout(); | |
58 | |
59 private: | |
60 bool isOutside() const; | |
61 bool isOverlapping() const; | |
62 bool shouldSwitchDirection(InlineFlowBox*, LayoutUnit) const; | |
63 | |
64 void moveBoxesByStep(LayoutUnit); | |
65 bool switchDirection(bool&, LayoutUnit&); | |
66 | |
67 bool findFirstLineBox(InlineFlowBox*&); | |
68 bool initializeLayoutParameters(InlineFlowBox*, LayoutUnit&, LayoutUnit&); | |
69 void placeBoxInDefaultPosition(LayoutUnit, bool&); | |
70 | |
71 LayoutPoint m_specifiedPosition; | |
72 RenderVTTCue& m_cueBox; | |
73 VTTCue::WritingDirection m_cueWritingDirection; | |
74 float m_linePosition; | |
75 }; | |
76 | |
77 bool SnapToLinesLayouter::findFirstLineBox(InlineFlowBox*& firstLineBox) | |
48 { | 78 { |
49 RenderBlockFlow::layout(); | 79 if (m_cueBox.firstChild()->isRenderInline()) |
50 | 80 firstLineBox = toRenderInline(m_cueBox.firstChild())->firstLineBox(); |
51 // If WebVTT Regions are used, the regular WebVTT layout algorithm is no | |
52 // longer necessary, since cues having the region parameter set do not have | |
53 // any positioning parameters. Also, in this case, the regions themselves | |
54 // have positioning information. | |
55 if (!m_cue->regionId().isEmpty()) | |
56 return; | |
57 | |
58 LayoutState state(*this, locationOffset()); | |
59 | |
60 // http://dev.w3.org/html5/webvtt/#dfn-apply-webvtt-cue-settings - step 13. | |
61 if (m_cue->snapToLines()) | |
62 repositionCueSnapToLinesSet(); | |
63 else | |
64 repositionCueSnapToLinesNotSet(); | |
65 } | |
66 | |
67 bool RenderVTTCue::findFirstLineBox(InlineFlowBox*& firstLineBox) | |
68 { | |
69 if (firstChild()->isRenderInline()) | |
70 firstLineBox = toRenderInline(firstChild())->firstLineBox(); | |
71 else | 81 else |
72 return false; | 82 return false; |
73 | 83 |
74 return true; | 84 return true; |
75 } | 85 } |
76 | 86 |
77 bool RenderVTTCue::initializeLayoutParameters(InlineFlowBox* firstLineBox, Layou tUnit& step, LayoutUnit& position) | 87 bool SnapToLinesLayouter::initializeLayoutParameters(InlineFlowBox* firstLineBox , LayoutUnit& step, LayoutUnit& position) |
78 { | 88 { |
79 ASSERT(firstChild()); | 89 ASSERT(m_cueBox.firstChild()); |
80 | 90 |
81 // 4. Horizontal: Let step be the height of the first line box in boxes. | 91 // 4. Horizontal: Let step be the height of the first line box in boxes. |
82 // Vertical: Let step be the width of the first line box in boxes. | 92 // Vertical: Let step be the width of the first line box in boxes. |
83 step = m_cue->getWritingDirection() == VTTCue::Horizontal ? firstLineBox->si ze().height() : firstLineBox->size().width(); | 93 step = m_cueWritingDirection == VTTCue::Horizontal ? firstLineBox->size().he ight() : firstLineBox->size().width(); |
84 | 94 |
85 // 5. If step is zero, then jump to the step labeled done positioning below. | 95 // 5. If step is zero, then jump to the step labeled done positioning below. |
86 if (!step) | 96 if (!step) |
87 return false; | 97 return false; |
88 | 98 |
89 // 6. Let line position be the text track cue computed line position. | 99 // 6. Let line position be the text track cue computed line position. |
90 // 7. Round line position to an integer by adding 0.5 and then flooring it. | 100 // 7. Round line position to an integer by adding 0.5 and then flooring it. |
91 LayoutUnit linePosition = floorf(m_cue->calculateComputedLinePosition() + 0. 5f); | 101 LayoutUnit linePosition = floorf(m_linePosition + 0.5f); |
92 | 102 |
93 // 8. Vertical Growing Left: Add one to line position then negate it. | 103 // 8. Vertical Growing Left: Add one to line position then negate it. |
94 if (m_cue->getWritingDirection() == VTTCue::VerticalGrowingLeft) | 104 if (m_cueWritingDirection == VTTCue::VerticalGrowingLeft) |
95 linePosition = -(linePosition + 1); | 105 linePosition = -(linePosition + 1); |
96 | 106 |
97 // 9. Let position be the result of multiplying step and line position. | 107 // 9. Let position be the result of multiplying step and line position. |
98 position = step * linePosition; | 108 position = step * linePosition; |
99 | 109 |
100 // 10. Vertical Growing Left: Decrease position by the width of the | 110 // 10. Vertical Growing Left: Decrease position by the width of the |
101 // bounding box of the boxes in boxes, then increase position by step. | 111 // bounding box of the boxes in boxes, then increase position by step. |
102 if (m_cue->getWritingDirection() == VTTCue::VerticalGrowingLeft) { | 112 if (m_cueWritingDirection == VTTCue::VerticalGrowingLeft) { |
103 position -= size().width(); | 113 position -= m_cueBox.size().width(); |
104 position += step; | 114 position += step; |
105 } | 115 } |
106 | 116 |
107 // 11. If line position is less than zero... | 117 // 11. If line position is less than zero... |
108 if (linePosition < 0) { | 118 if (linePosition < 0) { |
109 RenderBlock* parentBlock = containingBlock(); | 119 RenderBlock* parentBlock = m_cueBox.containingBlock(); |
110 | 120 |
111 // Horizontal / Vertical: ... then increase position by the | 121 // Horizontal / Vertical: ... then increase position by the |
112 // height / width of the video's rendering area ... | 122 // height / width of the video's rendering area ... |
113 position += m_cue->getWritingDirection() == VTTCue::Horizontal ? parentB lock->size().height() : parentBlock->size().width(); | 123 position += m_cueWritingDirection == VTTCue::Horizontal ? parentBlock->s ize().height() : parentBlock->size().width(); |
114 | 124 |
115 // ... and negate step. | 125 // ... and negate step. |
116 step = -step; | 126 step = -step; |
117 } | 127 } |
118 return true; | 128 return true; |
119 } | 129 } |
120 | 130 |
121 void RenderVTTCue::placeBoxInDefaultPosition(LayoutUnit position, bool& switched ) | 131 void SnapToLinesLayouter::placeBoxInDefaultPosition(LayoutUnit position, bool& s witched) |
122 { | 132 { |
123 // 12. Move all boxes in boxes ... | 133 // 12. Move all boxes in boxes ... |
124 if (m_cue->getWritingDirection() == VTTCue::Horizontal) { | 134 if (m_cueWritingDirection == VTTCue::Horizontal) { |
125 // Horizontal: ... down by the distance given by position | 135 // Horizontal: ... down by the distance given by position |
126 setY(location().y() + position); | 136 m_cueBox.setY(m_cueBox.location().y() + position); |
127 } else { | 137 } else { |
128 // Vertical: ... right by the distance given by position | 138 // Vertical: ... right by the distance given by position |
129 setX(location().x() + position); | 139 m_cueBox.setX(m_cueBox.location().x() + position); |
130 } | 140 } |
131 | 141 |
132 // 13. Remember the position of all the boxes in boxes as their specified po sition. | 142 // 13. Remember the position of all the boxes in boxes as their specified po sition. |
133 m_specifiedPosition = location(); | 143 m_specifiedPosition = m_cueBox.location(); |
134 | 144 |
135 // 14. Let best position be null. It will hold a position for boxes, much li ke specified position in the previous step. | 145 // 14. Let best position be null. It will hold a position for boxes, much li ke specified position in the previous step. |
136 // 15. Let best position score be null. | 146 // 15. Let best position score be null. |
137 | 147 |
138 // 16. Let switched be false. | 148 // 16. Let switched be false. |
139 switched = false; | 149 switched = false; |
140 } | 150 } |
141 | 151 |
142 bool RenderVTTCue::isOutside() const | 152 bool SnapToLinesLayouter::isOutside() const |
143 { | 153 { |
144 return !containingBlock()->absoluteBoundingBoxRect().contains(absoluteConten tBox()); | 154 return !m_cueBox.containingBlock()->absoluteBoundingBoxRect().contains(m_cue Box.absoluteContentBox()); |
145 } | 155 } |
146 | 156 |
147 bool RenderVTTCue::isOverlapping() const | 157 bool SnapToLinesLayouter::isOverlapping() const |
148 { | 158 { |
149 for (RenderObject* box = previousSibling(); box; box = box->previousSibling( )) { | 159 for (RenderObject* box = m_cueBox.previousSibling(); box; box = box->previou sSibling()) { |
150 IntRect boxRect = box->absoluteBoundingBoxRect(); | 160 IntRect boxRect = box->absoluteBoundingBoxRect(); |
151 | 161 |
152 if (absoluteBoundingBoxRect().intersects(boxRect)) | 162 if (m_cueBox.absoluteBoundingBoxRect().intersects(boxRect)) |
153 return true; | 163 return true; |
154 } | 164 } |
155 | 165 |
156 return false; | 166 return false; |
157 } | 167 } |
158 | 168 |
159 bool RenderVTTCue::shouldSwitchDirection(InlineFlowBox* firstLineBox, LayoutUnit step) const | 169 bool SnapToLinesLayouter::shouldSwitchDirection(InlineFlowBox* firstLineBox, Lay outUnit step) const |
160 { | 170 { |
161 LayoutUnit top = location().y(); | 171 LayoutUnit top = m_cueBox.location().y(); |
162 LayoutUnit left = location().x(); | 172 LayoutUnit left = m_cueBox.location().x(); |
163 LayoutUnit bottom = top + firstLineBox->size().height(); | 173 LayoutUnit bottom = top + firstLineBox->size().height(); |
164 LayoutUnit right = left + firstLineBox->size().width(); | 174 LayoutUnit right = left + firstLineBox->size().width(); |
165 | 175 |
166 // 21. Horizontal: If step is negative and the top of the first line box in | 176 // 21. Horizontal: If step is negative and the top of the first line box in |
167 // boxes is now above the top of the title area, or if step is positive and | 177 // boxes is now above the top of the title area, or if step is positive and |
168 // the bottom of the first line box in boxes is now below the bottom of the | 178 // the bottom of the first line box in boxes is now below the bottom of the |
169 // title area, jump to the step labeled switch direction. | 179 // title area, jump to the step labeled switch direction. |
170 LayoutUnit parentHeight = containingBlock()->size().height(); | 180 LayoutUnit parentHeight = m_cueBox.containingBlock()->size().height(); |
171 if (m_cue->getWritingDirection() == VTTCue::Horizontal && ((step < 0 && top < 0) || (step > 0 && bottom > parentHeight))) | 181 if (m_cueWritingDirection == VTTCue::Horizontal && ((step < 0 && top < 0) || (step > 0 && bottom > parentHeight))) |
172 return true; | 182 return true; |
173 | 183 |
174 // 21. Vertical: If step is negative and the left edge of the first line | 184 // 21. Vertical: If step is negative and the left edge of the first line |
175 // box in boxes is now to the left of the left edge of the title area, or | 185 // box in boxes is now to the left of the left edge of the title area, or |
176 // if step is positive and the right edge of the first line box in boxes is | 186 // if step is positive and the right edge of the first line box in boxes is |
177 // now to the right of the right edge of the title area, jump to the step | 187 // now to the right of the right edge of the title area, jump to the step |
178 // labeled switch direction. | 188 // labeled switch direction. |
179 LayoutUnit parentWidth = containingBlock()->size().width(); | 189 LayoutUnit parentWidth = m_cueBox.containingBlock()->size().width(); |
180 if (m_cue->getWritingDirection() != VTTCue::Horizontal && ((step < 0 && left < 0) || (step > 0 && right > parentWidth))) | 190 if (m_cueWritingDirection != VTTCue::Horizontal && ((step < 0 && left < 0) | | (step > 0 && right > parentWidth))) |
181 return true; | 191 return true; |
182 | 192 |
183 return false; | 193 return false; |
184 } | 194 } |
185 | 195 |
186 void RenderVTTCue::moveBoxesByStep(LayoutUnit step) | 196 void SnapToLinesLayouter::moveBoxesByStep(LayoutUnit step) |
187 { | 197 { |
188 // 22. Horizontal: Move all the boxes in boxes down by the distance | 198 // 22. Horizontal: Move all the boxes in boxes down by the distance |
189 // given by step. (If step is negative, then this will actually | 199 // given by step. (If step is negative, then this will actually |
190 // result in an upwards movement of the boxes in absolute terms.) | 200 // result in an upwards movement of the boxes in absolute terms.) |
191 if (m_cue->getWritingDirection() == VTTCue::Horizontal) | 201 if (m_cueWritingDirection == VTTCue::Horizontal) |
192 setY(location().y() + step); | 202 m_cueBox.setY(m_cueBox.location().y() + step); |
193 | 203 |
194 // 22. Vertical: Move all the boxes in boxes right by the distance | 204 // 22. Vertical: Move all the boxes in boxes right by the distance |
195 // given by step. (If step is negative, then this will actually | 205 // given by step. (If step is negative, then this will actually |
196 // result in a leftwards movement of the boxes in absolute terms.) | 206 // result in a leftwards movement of the boxes in absolute terms.) |
197 else | 207 else |
198 setX(location().x() + step); | 208 m_cueBox.setX(m_cueBox.location().x() + step); |
199 } | 209 } |
200 | 210 |
201 bool RenderVTTCue::switchDirection(bool& switched, LayoutUnit& step) | 211 bool SnapToLinesLayouter::switchDirection(bool& switched, LayoutUnit& step) |
202 { | 212 { |
203 // 24. Switch direction: If switched is true, then move all the boxes in | 213 // 24. Switch direction: If switched is true, then move all the boxes in |
204 // boxes back to their best position, and jump to the step labeled done | 214 // boxes back to their best position, and jump to the step labeled done |
205 // positioning below. | 215 // positioning below. |
206 | 216 |
207 // 25. Otherwise, move all the boxes in boxes back to their specified | 217 // 25. Otherwise, move all the boxes in boxes back to their specified |
208 // position as determined in the earlier step. | 218 // position as determined in the earlier step. |
209 setLocation(m_specifiedPosition); | 219 m_cueBox.setLocation(m_specifiedPosition); |
210 | 220 |
211 // XX. If switched is true, jump to the step labeled done | 221 // XX. If switched is true, jump to the step labeled done |
212 // positioning below. | 222 // positioning below. |
213 if (switched) | 223 if (switched) |
214 return false; | 224 return false; |
215 | 225 |
216 // 26. Negate step. | 226 // 26. Negate step. |
217 step = -step; | 227 step = -step; |
218 | 228 |
219 // 27. Set switched to true. | 229 // 27. Set switched to true. |
220 switched = true; | 230 switched = true; |
221 return true; | 231 return true; |
222 } | 232 } |
223 | 233 |
224 void RenderVTTCue::repositionCueSnapToLinesSet() | 234 void SnapToLinesLayouter::layout() |
225 { | 235 { |
226 // http://dev.w3.org/html5/webvtt/#dfn-apply-webvtt-cue-settings | 236 // http://dev.w3.org/html5/webvtt/#dfn-apply-webvtt-cue-settings |
227 // Step 13, "If cue's text track cue snap-to-lines flag is set". | 237 // Step 13, "If cue's text track cue snap-to-lines flag is set". |
228 | 238 |
229 InlineFlowBox* firstLineBox; | 239 InlineFlowBox* firstLineBox; |
230 if (!findFirstLineBox(firstLineBox)) | 240 if (!findFirstLineBox(firstLineBox)) |
231 return; | 241 return; |
232 | 242 |
233 // Step 1 skipped. | 243 // Step 1 skipped. |
234 | 244 |
(...skipping 24 matching lines...) Expand all Loading... | |
259 if (!shouldSwitchDirection(firstLineBox, step)) { | 269 if (!shouldSwitchDirection(firstLineBox, step)) { |
260 // 22. Move all the boxes in boxes ... | 270 // 22. Move all the boxes in boxes ... |
261 moveBoxesByStep(step); | 271 moveBoxesByStep(step); |
262 // 23. Jump back to the step labeled step loop. | 272 // 23. Jump back to the step labeled step loop. |
263 } else if (!switchDirection(switched, step)) { | 273 } else if (!switchDirection(switched, step)) { |
264 break; | 274 break; |
265 } | 275 } |
266 | 276 |
267 // 28. Jump back to the step labeled step loop. | 277 // 28. Jump back to the step labeled step loop. |
268 } | 278 } |
269 | |
270 // Acommodate extra top and bottom padding, border or margin. | |
271 // Note: this is supported only for internal UA styling, not through the cue selector. | |
272 if (hasInlineDirectionBordersPaddingOrMargin()) { | |
273 IntRect containerRect = containingBlock()->absoluteBoundingBoxRect(); | |
274 IntRect cueRect = absoluteBoundingBoxRect(); | |
275 | |
276 int topOverflow = cueRect.y() - containerRect.y(); | |
277 int bottomOverflow = containerRect.y() + containerRect.height() - cueRec t.y() - cueRect.height(); | |
278 | |
279 int adjustment = 0; | |
280 if (topOverflow < 0) | |
281 adjustment = -topOverflow; | |
282 else if (bottomOverflow < 0) | |
283 adjustment = bottomOverflow; | |
284 | |
285 if (adjustment) | |
286 setY(location().y() + adjustment); | |
287 } | |
288 } | 279 } |
289 | 280 |
290 void RenderVTTCue::repositionCueSnapToLinesNotSet() | 281 void RenderVTTCue::repositionCueSnapToLinesNotSet() |
291 { | 282 { |
292 // FIXME: Implement overlapping detection when snap-to-lines is not set. htt p://wkb.ug/84296 | 283 // FIXME: Implement overlapping detection when snap-to-lines is not set. htt p://wkb.ug/84296 |
293 | 284 |
294 // http://dev.w3.org/html5/webvtt/#dfn-apply-webvtt-cue-settings | 285 // http://dev.w3.org/html5/webvtt/#dfn-apply-webvtt-cue-settings |
295 // Step 13, "If cue's text track cue snap-to-lines flag is not set". | 286 // Step 13, "If cue's text track cue snap-to-lines flag is not set". |
296 | 287 |
297 // 1. Let bounding box be the bounding box of the boxes in boxes. | 288 // 1. Let bounding box be the bounding box of the boxes in boxes. |
(...skipping 26 matching lines...) Expand all Loading... | |
324 // position to their current position, and then jump to the step labeled | 315 // position to their current position, and then jump to the step labeled |
325 // done positioning below. If there are multiple such positions that are | 316 // done positioning below. If there are multiple such positions that are |
326 // equidistant from their current position, use the highest one amongst | 317 // equidistant from their current position, use the highest one amongst |
327 // them; if there are several at that height, then use the leftmost one | 318 // them; if there are several at that height, then use the leftmost one |
328 // amongst them. | 319 // amongst them. |
329 | 320 |
330 // 5. Otherwise, jump to the step labeled done positioning below. (The | 321 // 5. Otherwise, jump to the step labeled done positioning below. (The |
331 // boxes will unfortunately overlap.) | 322 // boxes will unfortunately overlap.) |
332 } | 323 } |
333 | 324 |
325 void RenderVTTCue::adjustForTopAndBottomMarginBorderAndPadding() | |
philipj_slow
2015/01/27 05:06:59
Does this bit make sense to you? It looks like it'
fs
2015/01/27 12:15:53
Not really, no.
| |
326 { | |
327 // Accommodate extra top and bottom padding, border or margin. | |
328 // Note: this is supported only for internal UA styling, not through the cue selector. | |
329 if (!hasInlineDirectionBordersPaddingOrMargin()) | |
330 return; | |
331 IntRect containerRect = containingBlock()->absoluteBoundingBoxRect(); | |
332 IntRect cueRect = absoluteBoundingBoxRect(); | |
333 | |
334 int topOverflow = cueRect.y() - containerRect.y(); | |
335 int bottomOverflow = containerRect.y() + containerRect.height() - cueRect.y( ) - cueRect.height(); | |
336 | |
337 int adjustment = 0; | |
338 if (topOverflow < 0) | |
339 adjustment = -topOverflow; | |
340 else if (bottomOverflow < 0) | |
341 adjustment = bottomOverflow; | |
342 | |
343 if (!adjustment) | |
344 return; | |
345 | |
346 setY(location().y() + adjustment); | |
347 } | |
348 | |
349 void RenderVTTCue::layout() | |
350 { | |
351 RenderBlockFlow::layout(); | |
352 | |
353 // If WebVTT Regions are used, the regular WebVTT layout algorithm is no | |
354 // longer necessary, since cues having the region parameter set do not have | |
355 // any positioning parameters. Also, in this case, the regions themselves | |
356 // have positioning information. | |
357 if (!m_cue->regionId().isEmpty()) | |
358 return; | |
359 | |
360 LayoutState state(*this, locationOffset()); | |
361 | |
362 // http://dev.w3.org/html5/webvtt/#dfn-apply-webvtt-cue-settings - step 13. | |
363 if (m_cue->snapToLines()) { | |
364 SnapToLinesLayouter(*this, m_cue->getWritingDirection(), m_cue->calculat eComputedLinePosition()).layout(); | |
365 | |
366 adjustForTopAndBottomMarginBorderAndPadding(); | |
367 } else { | |
368 repositionCueSnapToLinesNotSet(); | |
369 } | |
370 } | |
371 | |
334 } // namespace blink | 372 } // namespace blink |
335 | 373 |
OLD | NEW |