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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
50 | 50 |
51 // If WebVTT Regions are used, the regular WebVTT layout algorithm is no | 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 | 52 // longer necessary, since cues having the region parameter set do not have |
53 // any positioning parameters. Also, in this case, the regions themselves | 53 // any positioning parameters. Also, in this case, the regions themselves |
54 // have positioning information. | 54 // have positioning information. |
55 if (!m_cue->regionId().isEmpty()) | 55 if (!m_cue->regionId().isEmpty()) |
56 return; | 56 return; |
57 | 57 |
58 LayoutState state(*this, locationOffset()); | 58 LayoutState state(*this, locationOffset()); |
59 | 59 |
60 // http://dev.w3.org/html5/webvtt/#dfn-apply-webvtt-cue-settings - step 13. | |
60 if (m_cue->snapToLines()) | 61 if (m_cue->snapToLines()) |
61 repositionCueSnapToLinesSet(); | 62 repositionCueSnapToLinesSet(); |
62 else | 63 else |
63 repositionCueSnapToLinesNotSet(); | 64 repositionCueSnapToLinesNotSet(); |
64 } | 65 } |
65 | 66 |
66 bool RenderVTTCue::findFirstLineBox(InlineFlowBox*& firstLineBox) | 67 bool RenderVTTCue::findFirstLineBox(InlineFlowBox*& firstLineBox) |
67 { | 68 { |
68 if (firstChild()->isRenderInline()) | 69 if (firstChild()->isRenderInline()) |
69 firstLineBox = toRenderInline(firstChild())->firstLineBox(); | 70 firstLineBox = toRenderInline(firstChild())->firstLineBox(); |
70 else | 71 else |
71 return false; | 72 return false; |
72 | 73 |
73 return true; | 74 return true; |
74 } | 75 } |
75 | 76 |
76 bool RenderVTTCue::initializeLayoutParameters(InlineFlowBox* firstLineBox, Layou tUnit& step, LayoutUnit& position) | 77 bool RenderVTTCue::initializeLayoutParameters(InlineFlowBox* firstLineBox, Layou tUnit& step, LayoutUnit& position) |
77 { | 78 { |
78 ASSERT(firstChild()); | 79 ASSERT(firstChild()); |
79 | 80 |
80 RenderBlock* parentBlock = containingBlock(); | 81 // 4. Horizontal: Let step be the height of the first line box in boxes. |
81 | |
82 // 1. Horizontal: Let step be the height of the first line box in boxes. | |
83 // Vertical: Let step be the width of the first line box in boxes. | 82 // Vertical: Let step be the width of the first line box in boxes. |
84 step = m_cue->getWritingDirection() == VTTCue::Horizontal ? firstLineBox->si ze().height() : firstLineBox->size().width(); | 83 step = m_cue->getWritingDirection() == VTTCue::Horizontal ? firstLineBox->si ze().height() : firstLineBox->size().width(); |
85 | 84 |
86 // 2. If step is zero, then jump to the step labeled done positioning below. | 85 // 5. If step is zero, then jump to the step labeled done positioning below. |
87 if (!step) | 86 if (!step) |
88 return false; | 87 return false; |
89 | 88 |
90 // 3. Let line position be the text track cue computed line position. | 89 // 6. Let line position be the text track cue computed line position. |
91 int linePosition = m_cue->calculateComputedLinePosition(); | 90 // 7. Round line position to an integer by adding 0.5 and then flooring it. |
91 int linePosition = clampTo<int>(floorf(m_cue->calculateComputedLinePosition( ) + 0.5f)); | |
92 | 92 |
93 // 4. Vertical Growing Left: Add one to line position then negate it. | 93 // 8. Vertical Growing Left: Add one to line position then negate it. |
94 if (m_cue->getWritingDirection() == VTTCue::VerticalGrowingLeft) | 94 if (m_cue->getWritingDirection() == VTTCue::VerticalGrowingLeft) |
95 linePosition = -(linePosition + 1); | 95 linePosition = -(linePosition + 1); |
philipj_slow
2015/01/22 14:35:02
This will overflow for INT_MAX. Let linePosition b
fs
2015/01/22 15:49:49
Yes, LayoutUnit is probably (one of) the easier wa
| |
96 | 96 |
97 // 5. Let position be the result of multiplying step and line position. | 97 // 9. Let position be the result of multiplying step and line position. |
98 position = step * linePosition; | 98 position = step * linePosition; |
99 | 99 |
100 // 6. Vertical Growing Left: Decrease position by the width of the | 100 // 10. Vertical Growing Left: Decrease position by the width of the |
101 // bounding box of the boxes in boxes, then increase position by step. | 101 // bounding box of the boxes in boxes, then increase position by step. |
102 if (m_cue->getWritingDirection() == VTTCue::VerticalGrowingLeft) { | 102 if (m_cue->getWritingDirection() == VTTCue::VerticalGrowingLeft) { |
103 position -= size().width(); | 103 position -= size().width(); |
104 position += step; | 104 position += step; |
105 } | 105 } |
106 | 106 |
107 // 7. If line position is less than zero... | 107 // 11. If line position is less than zero... |
108 if (linePosition < 0) { | 108 if (linePosition < 0) { |
109 RenderBlock* parentBlock = containingBlock(); | |
110 | |
109 // Horizontal / Vertical: ... then increase position by the | 111 // Horizontal / Vertical: ... then increase position by the |
110 // height / width of the video's rendering area ... | 112 // height / width of the video's rendering area ... |
111 position += m_cue->getWritingDirection() == VTTCue::Horizontal ? parentB lock->size().height() : parentBlock->size().width(); | 113 position += m_cue->getWritingDirection() == VTTCue::Horizontal ? parentB lock->size().height() : parentBlock->size().width(); |
112 | 114 |
113 // ... and negate step. | 115 // ... and negate step. |
114 step = -step; | 116 step = -step; |
115 } | 117 } |
116 | |
117 return true; | 118 return true; |
118 } | 119 } |
119 | 120 |
120 void RenderVTTCue::placeBoxInDefaultPosition(LayoutUnit position, bool& switched ) | 121 void RenderVTTCue::placeBoxInDefaultPosition(LayoutUnit position, bool& switched ) |
121 { | 122 { |
122 // 8. Move all boxes in boxes ... | 123 // 12. Move all boxes in boxes ... |
123 if (m_cue->getWritingDirection() == VTTCue::Horizontal) { | 124 if (m_cue->getWritingDirection() == VTTCue::Horizontal) { |
124 // Horizontal: ... down by the distance given by position | 125 // Horizontal: ... down by the distance given by position |
125 setY(location().y() + position); | 126 setY(location().y() + position); |
126 } else { | 127 } else { |
127 // Vertical: ... right by the distance given by position | 128 // Vertical: ... right by the distance given by position |
128 setX(location().x() + position); | 129 setX(location().x() + position); |
129 } | 130 } |
130 | 131 |
131 // 9. Default: Remember the position of all the boxes in boxes as their | 132 // 13. Remember the position of all the boxes in boxes as their specified po sition. |
132 // default position. | 133 m_specifiedPosition = location(); |
133 m_defaultPosition = location(); | |
134 | 134 |
135 // 10. Let switched be false. | 135 // 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. | |
137 | |
138 // 16. Let switched be false. | |
136 switched = false; | 139 switched = false; |
137 } | 140 } |
138 | 141 |
139 bool RenderVTTCue::isOutside() const | 142 bool RenderVTTCue::isOutside() const |
140 { | 143 { |
141 return !containingBlock()->absoluteBoundingBoxRect().contains(absoluteConten tBox()); | 144 return !containingBlock()->absoluteBoundingBoxRect().contains(absoluteConten tBox()); |
142 } | 145 } |
143 | 146 |
144 bool RenderVTTCue::isOverlapping() const | 147 bool RenderVTTCue::isOverlapping() const |
145 { | 148 { |
146 for (RenderObject* box = previousSibling(); box; box = box->previousSibling( )) { | 149 for (RenderObject* box = previousSibling(); box; box = box->previousSibling( )) { |
147 IntRect boxRect = box->absoluteBoundingBoxRect(); | 150 IntRect boxRect = box->absoluteBoundingBoxRect(); |
148 | 151 |
149 if (absoluteBoundingBoxRect().intersects(boxRect)) | 152 if (absoluteBoundingBoxRect().intersects(boxRect)) |
150 return true; | 153 return true; |
151 } | 154 } |
152 | 155 |
153 return false; | 156 return false; |
154 } | 157 } |
155 | 158 |
156 bool RenderVTTCue::shouldSwitchDirection(InlineFlowBox* firstLineBox, LayoutUnit step) const | 159 bool RenderVTTCue::shouldSwitchDirection(InlineFlowBox* firstLineBox, LayoutUnit step) const |
157 { | 160 { |
158 LayoutUnit top = location().y(); | 161 LayoutUnit top = location().y(); |
159 LayoutUnit left = location().x(); | 162 LayoutUnit left = location().x(); |
160 LayoutUnit bottom = top + firstLineBox->size().height(); | 163 LayoutUnit bottom = top + firstLineBox->size().height(); |
161 LayoutUnit right = left + firstLineBox->size().width(); | 164 LayoutUnit right = left + firstLineBox->size().width(); |
162 | 165 |
163 // 12. Horizontal: If step is negative and the top of the first line | 166 // 21. Horizontal: If step is negative and the top of the first line box in |
164 // box in boxes is now above the top of the video's rendering area, | 167 // boxes is now above the top of the title area, or if step is positive and |
165 // or if step is positive and the bottom of the first line box in | 168 // the bottom of the first line box in boxes is now below the bottom of the |
166 // boxes is now below the bottom of the video's rendering area, jump | 169 // title area, jump to the step labeled switch direction. |
167 // to the step labeled switch direction. | |
168 LayoutUnit parentHeight = containingBlock()->size().height(); | 170 LayoutUnit parentHeight = containingBlock()->size().height(); |
169 if (m_cue->getWritingDirection() == VTTCue::Horizontal && ((step < 0 && top < 0) || (step > 0 && bottom > parentHeight))) | 171 if (m_cue->getWritingDirection() == VTTCue::Horizontal && ((step < 0 && top < 0) || (step > 0 && bottom > parentHeight))) |
170 return true; | 172 return true; |
171 | 173 |
172 // 12. Vertical: If step is negative and the left edge of the first line | 174 // 21. Vertical: If step is negative and the left edge of the first line |
173 // box in boxes is now to the left of the left edge of the video's | 175 // box in boxes is now to the left of the left edge of the title area, or |
174 // rendering area, or if step is positive and the right edge of the | 176 // if step is positive and the right edge of the first line box in boxes is |
175 // first line box in boxes is now to the right of the right edge of | 177 // now to the right of the right edge of the title area, jump to the step |
176 // the video's rendering area, jump to the step labeled switch direction. | 178 // labeled switch direction. |
177 LayoutUnit parentWidth = containingBlock()->size().width(); | 179 LayoutUnit parentWidth = containingBlock()->size().width(); |
178 if (m_cue->getWritingDirection() != VTTCue::Horizontal && ((step < 0 && left < 0) || (step > 0 && right > parentWidth))) | 180 if (m_cue->getWritingDirection() != VTTCue::Horizontal && ((step < 0 && left < 0) || (step > 0 && right > parentWidth))) |
179 return true; | 181 return true; |
180 | 182 |
181 return false; | 183 return false; |
182 } | 184 } |
183 | 185 |
184 void RenderVTTCue::moveBoxesByStep(LayoutUnit step) | 186 void RenderVTTCue::moveBoxesByStep(LayoutUnit step) |
185 { | 187 { |
186 // 13. Horizontal: Move all the boxes in boxes down by the distance | 188 // 22. Horizontal: Move all the boxes in boxes down by the distance |
187 // given by step. (If step is negative, then this will actually | 189 // given by step. (If step is negative, then this will actually |
188 // result in an upwards movement of the boxes in absolute terms.) | 190 // result in an upwards movement of the boxes in absolute terms.) |
189 if (m_cue->getWritingDirection() == VTTCue::Horizontal) | 191 if (m_cue->getWritingDirection() == VTTCue::Horizontal) |
190 setY(location().y() + step); | 192 setY(location().y() + step); |
191 | 193 |
192 // 13. Vertical: Move all the boxes in boxes right by the distance | 194 // 22. Vertical: Move all the boxes in boxes right by the distance |
193 // given by step. (If step is negative, then this will actually | 195 // given by step. (If step is negative, then this will actually |
194 // result in a leftwards movement of the boxes in absolute terms.) | 196 // result in a leftwards movement of the boxes in absolute terms.) |
195 else | 197 else |
196 setX(location().x() + step); | 198 setX(location().x() + step); |
197 } | 199 } |
198 | 200 |
199 bool RenderVTTCue::switchDirection(bool& switched, LayoutUnit& step) | 201 bool RenderVTTCue::switchDirection(bool& switched, LayoutUnit& step) |
200 { | 202 { |
201 // 15. Switch direction: Move all the boxes in boxes back to their | 203 // 24. Switch direction: If switched is true, then move all the boxes in |
202 // default position as determined in the step above labeled default. | 204 // boxes back to their best position, and jump to the step labeled done |
203 setLocation(m_defaultPosition); | 205 // positioning below. |
204 | 206 |
205 // 16. If switched is true, jump to the step labeled done | 207 // 25. Otherwise, move all the boxes in boxes back to their specified |
208 // position as determined in the earlier step. | |
209 setLocation(m_specifiedPosition); | |
210 | |
211 // XX. If switched is true, jump to the step labeled done | |
206 // positioning below. | 212 // positioning below. |
207 if (switched) | 213 if (switched) |
208 return false; | 214 return false; |
209 | 215 |
210 // 17. Negate step. | 216 // 26. Negate step. |
211 step = -step; | 217 step = -step; |
212 | 218 |
213 // 18. Set switched to true. | 219 // 27. Set switched to true. |
214 switched = true; | 220 switched = true; |
215 return true; | 221 return true; |
216 } | 222 } |
217 | 223 |
218 void RenderVTTCue::repositionCueSnapToLinesSet() | 224 void RenderVTTCue::repositionCueSnapToLinesSet() |
219 { | 225 { |
226 // 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". | |
228 | |
220 InlineFlowBox* firstLineBox; | 229 InlineFlowBox* firstLineBox; |
221 LayoutUnit step; | |
222 LayoutUnit position; | |
223 | |
224 if (!findFirstLineBox(firstLineBox)) | 230 if (!findFirstLineBox(firstLineBox)) |
225 return; | 231 return; |
226 | 232 |
233 // Step 1 skipped. | |
234 | |
235 LayoutUnit step; | |
236 LayoutUnit position; | |
227 if (!initializeLayoutParameters(firstLineBox, step, position)) | 237 if (!initializeLayoutParameters(firstLineBox, step, position)) |
228 return; | 238 return; |
229 | 239 |
230 bool switched; | 240 bool switched; |
231 placeBoxInDefaultPosition(position, switched); | 241 placeBoxInDefaultPosition(position, switched); |
232 | 242 |
233 // 11. Step loop: If none of the boxes in boxes would overlap any of the box es | 243 // Step 17 skipped. (margin == 0; title area == video area) |
234 // in output and all the boxes in output are within the video's rendering ar ea | 244 |
235 // then jump to the step labeled done positioning. | 245 // 18. Step loop: If none of the boxes in boxes would overlap any of the |
246 // boxes in output, and all of the boxes in output are entirely within the | |
247 // title area box, then jump to the step labeled done positioning below. | |
236 while (isOutside() || isOverlapping()) { | 248 while (isOutside() || isOverlapping()) { |
249 // 19. Let current position score be the percentage of the area of the | |
250 // bounding box of the boxes in boxes that is outside the title area | |
251 // box. | |
252 // 20. If best position is null (i.e. this is the first run through | |
253 // this loop, switched is still false, the boxes in boxes are at their | |
254 // specified position, and best position score is still null), or if | |
255 // current position score is a lower percentage than that in best | |
256 // position score, then remember the position of all the boxes in boxes | |
257 // as their best position, and set best position score to current | |
258 // position score. | |
237 if (!shouldSwitchDirection(firstLineBox, step)) { | 259 if (!shouldSwitchDirection(firstLineBox, step)) { |
238 // 13. Move all the boxes in boxes ... | 260 // 22. Move all the boxes in boxes ... |
239 // 14. Jump back to the step labeled step loop. | |
240 moveBoxesByStep(step); | 261 moveBoxesByStep(step); |
262 // 23. Jump back to the step labeled step loop. | |
241 } else if (!switchDirection(switched, step)) { | 263 } else if (!switchDirection(switched, step)) { |
242 break; | 264 break; |
243 } | 265 } |
244 | 266 |
245 // 19. Jump back to the step labeled step loop. | 267 // 28. Jump back to the step labeled step loop. |
246 } | 268 } |
247 | 269 |
248 // Acommodate extra top and bottom padding, border or margin. | 270 // Acommodate extra top and bottom padding, border or margin. |
249 // Note: this is supported only for internal UA styling, not through the cue selector. | 271 // Note: this is supported only for internal UA styling, not through the cue selector. |
250 if (hasInlineDirectionBordersPaddingOrMargin()) { | 272 if (hasInlineDirectionBordersPaddingOrMargin()) { |
251 IntRect containerRect = containingBlock()->absoluteBoundingBoxRect(); | 273 IntRect containerRect = containingBlock()->absoluteBoundingBoxRect(); |
252 IntRect cueRect = absoluteBoundingBoxRect(); | 274 IntRect cueRect = absoluteBoundingBoxRect(); |
253 | 275 |
254 int topOverflow = cueRect.y() - containerRect.y(); | 276 int topOverflow = cueRect.y() - containerRect.y(); |
255 int bottomOverflow = containerRect.y() + containerRect.height() - cueRec t.y() - cueRect.height(); | 277 int bottomOverflow = containerRect.y() + containerRect.height() - cueRec t.y() - cueRect.height(); |
256 | 278 |
257 int adjustment = 0; | 279 int adjustment = 0; |
258 if (topOverflow < 0) | 280 if (topOverflow < 0) |
259 adjustment = -topOverflow; | 281 adjustment = -topOverflow; |
260 else if (bottomOverflow < 0) | 282 else if (bottomOverflow < 0) |
261 adjustment = bottomOverflow; | 283 adjustment = bottomOverflow; |
262 | 284 |
263 if (adjustment) | 285 if (adjustment) |
264 setY(location().y() + adjustment); | 286 setY(location().y() + adjustment); |
265 } | 287 } |
266 } | 288 } |
267 | 289 |
268 void RenderVTTCue::repositionCueSnapToLinesNotSet() | 290 void RenderVTTCue::repositionCueSnapToLinesNotSet() |
269 { | 291 { |
270 // FIXME: Implement overlapping detection when snap-to-lines is not set. htt p://wkb.ug/84296 | 292 // FIXME: Implement overlapping detection when snap-to-lines is not set. htt p://wkb.ug/84296 |
293 | |
294 // 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". | |
296 | |
297 // 1. Let bounding box be the bounding box of the boxes in boxes. | |
298 | |
299 // 2. Run the appropriate steps from the following list: | |
300 // If the text track cue writing direction is horizontal | |
301 // If the text track cue line alignment is middle alignment | |
302 // Move all the boxes in boxes up by half of the height of | |
303 // bounding box. | |
304 // If the text track cue line alignment is end alignment | |
305 // Move all the boxes in boxes up by the height of bounding box. | |
306 // | |
307 // If the text track cue writing direction is vertical growing left or | |
308 // vertical growing right | |
309 // If the text track cue line alignment is middle alignment | |
310 // Move all the boxes in boxes left by half of the width of | |
311 // bounding box. | |
312 // If the text track cue line alignment is end alignment | |
313 // Move all the boxes in boxes left by the width of bounding box. | |
314 | |
315 // 3. If none of the boxes in boxes would overlap any of the boxes in | |
316 // output, and all the boxes in output are within the video's rendering | |
317 // area, then jump to the step labeled done positioning below. | |
318 | |
319 // 4. If there is a position to which the boxes in boxes can be moved while | |
320 // maintaining the relative positions of the boxes in boxes to each other | |
321 // such that none of the boxes in boxes would overlap any of the boxes in | |
322 // output, and all the boxes in output would be within the video's | |
323 // rendering area, then move the boxes in boxes to the closest such | |
324 // position to their current position, and then jump to the step labeled | |
325 // done positioning below. If there are multiple such positions that are | |
326 // equidistant from their current position, use the highest one amongst | |
327 // them; if there are several at that height, then use the leftmost one | |
328 // amongst them. | |
329 | |
330 // 5. Otherwise, jump to the step labeled done positioning below. (The | |
331 // boxes will unfortunately overlap.) | |
271 } | 332 } |
272 | 333 |
273 } // namespace blink | 334 } // namespace blink |
274 | 335 |
OLD | NEW |