Chromium Code Reviews| 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 44 RenderBlockFlow::trace(visitor); | 44 RenderBlockFlow::trace(visitor); |
| 45 } | 45 } |
| 46 | 46 |
| 47 class SnapToLinesLayouter { | 47 class SnapToLinesLayouter { |
| 48 STACK_ALLOCATED(); | 48 STACK_ALLOCATED(); |
| 49 public: | 49 public: |
| 50 SnapToLinesLayouter(RenderVTTCue& cueBox, VTTCue::WritingDirection writingDi rection, float linePosition) | 50 SnapToLinesLayouter(RenderVTTCue& cueBox, VTTCue::WritingDirection writingDi rection, float linePosition) |
| 51 : m_cueBox(cueBox) | 51 : m_cueBox(cueBox) |
| 52 , m_cueWritingDirection(writingDirection) | 52 , m_cueWritingDirection(writingDirection) |
| 53 , m_linePosition(linePosition) | 53 , m_linePosition(linePosition) |
| 54 , m_bestPositionScore(std::numeric_limits<float>::infinity()) | |
| 54 { | 55 { |
| 55 } | 56 } |
| 56 | 57 |
| 57 void layout(); | 58 void layout(); |
| 58 | 59 |
| 59 private: | 60 private: |
| 60 bool isOutside() const; | 61 bool isOutside() const; |
| 61 bool isOverlapping() const; | 62 bool isOverlapping() const; |
| 63 float computePositionScore() const; | |
| 62 bool shouldSwitchDirection(InlineFlowBox*, LayoutUnit) const; | 64 bool shouldSwitchDirection(InlineFlowBox*, LayoutUnit) const; |
| 63 | 65 |
| 64 void moveBoxesByStep(LayoutUnit); | 66 void moveBoxesByStep(LayoutUnit); |
| 65 bool switchDirection(bool&, LayoutUnit&); | 67 bool switchDirection(bool&, LayoutUnit&); |
| 66 | 68 |
| 67 bool findFirstLineBox(InlineFlowBox*&); | 69 bool findFirstLineBox(InlineFlowBox*&); |
| 68 bool initializeLayoutParameters(InlineFlowBox*, LayoutUnit&, LayoutUnit&); | 70 bool initializeLayoutParameters(InlineFlowBox*, LayoutUnit&, LayoutUnit&); |
| 69 void placeBoxInDefaultPosition(LayoutUnit, bool&); | 71 void placeBoxInDefaultPosition(LayoutUnit, bool&); |
| 70 | 72 |
| 71 LayoutPoint m_specifiedPosition; | |
| 72 RenderVTTCue& m_cueBox; | 73 RenderVTTCue& m_cueBox; |
| 73 VTTCue::WritingDirection m_cueWritingDirection; | 74 VTTCue::WritingDirection m_cueWritingDirection; |
| 74 float m_linePosition; | 75 float m_linePosition; |
| 76 LayoutPoint m_specifiedPosition; | |
| 77 LayoutPoint m_bestPosition; | |
| 78 float m_bestPositionScore; | |
| 75 }; | 79 }; |
| 76 | 80 |
| 77 bool SnapToLinesLayouter::findFirstLineBox(InlineFlowBox*& firstLineBox) | 81 bool SnapToLinesLayouter::findFirstLineBox(InlineFlowBox*& firstLineBox) |
| 78 { | 82 { |
| 79 if (m_cueBox.firstChild()->isRenderInline()) | 83 if (m_cueBox.firstChild()->isRenderInline()) |
| 80 firstLineBox = toRenderInline(m_cueBox.firstChild())->firstLineBox(); | 84 firstLineBox = toRenderInline(m_cueBox.firstChild())->firstLineBox(); |
| 81 else | 85 else |
| 82 return false; | 86 return false; |
| 83 | 87 |
| 84 return true; | 88 return true; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 136 m_cueBox.setY(m_cueBox.location().y() + position); | 140 m_cueBox.setY(m_cueBox.location().y() + position); |
| 137 } else { | 141 } else { |
| 138 // Vertical: ... right by the distance given by position | 142 // Vertical: ... right by the distance given by position |
| 139 m_cueBox.setX(m_cueBox.location().x() + position); | 143 m_cueBox.setX(m_cueBox.location().x() + position); |
| 140 } | 144 } |
| 141 | 145 |
| 142 // 13. Remember the position of all the boxes in boxes as their specified po sition. | 146 // 13. Remember the position of all the boxes in boxes as their specified po sition. |
| 143 m_specifiedPosition = m_cueBox.location(); | 147 m_specifiedPosition = m_cueBox.location(); |
| 144 | 148 |
| 145 // 14. Let best position be null. It will hold a position for boxes, much li ke specified position in the previous step. | 149 // 14. Let best position be null. It will hold a position for boxes, much li ke specified position in the previous step. |
| 150 ASSERT(m_bestPosition == LayoutPoint::zero()); | |
| 151 | |
| 146 // 15. Let best position score be null. | 152 // 15. Let best position score be null. |
| 153 // (Setting score to positive infinite that should be guaranteed to be | |
| 154 // larger than any overlap - and easily recognizable as 'best position is | |
| 155 // null' as well.) | |
| 156 ASSERT(std::isinf(m_bestPositionScore)); | |
| 147 | 157 |
| 148 // 16. Let switched be false. | 158 // 16. Let switched be false. |
| 149 switched = false; | 159 switched = false; |
| 150 } | 160 } |
| 151 | 161 |
| 152 bool SnapToLinesLayouter::isOutside() const | 162 bool SnapToLinesLayouter::isOutside() const |
| 153 { | 163 { |
| 154 return !m_cueBox.containingBlock()->absoluteBoundingBoxRect().contains(m_cue Box.absoluteContentBox()); | 164 return !m_cueBox.containingBlock()->absoluteBoundingBoxRect().contains(m_cue Box.absoluteContentBox()); |
| 155 } | 165 } |
| 156 | 166 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 206 // result in a leftwards movement of the boxes in absolute terms.) | 216 // result in a leftwards movement of the boxes in absolute terms.) |
| 207 else | 217 else |
| 208 m_cueBox.setX(m_cueBox.location().x() + step); | 218 m_cueBox.setX(m_cueBox.location().x() + step); |
| 209 } | 219 } |
| 210 | 220 |
| 211 bool SnapToLinesLayouter::switchDirection(bool& switched, LayoutUnit& step) | 221 bool SnapToLinesLayouter::switchDirection(bool& switched, LayoutUnit& step) |
| 212 { | 222 { |
| 213 // 24. Switch direction: If switched is true, then move all the boxes in | 223 // 24. Switch direction: If switched is true, then move all the boxes in |
| 214 // boxes back to their best position, and jump to the step labeled done | 224 // boxes back to their best position, and jump to the step labeled done |
| 215 // positioning below. | 225 // positioning below. |
| 226 if (switched) { | |
| 227 m_cueBox.setLocation(m_bestPosition); | |
| 228 return false; | |
| 229 } | |
| 216 | 230 |
| 217 // 25. Otherwise, move all the boxes in boxes back to their specified | 231 // 25. Otherwise, move all the boxes in boxes back to their specified |
| 218 // position as determined in the earlier step. | 232 // position as determined in the earlier step. |
| 219 m_cueBox.setLocation(m_specifiedPosition); | 233 m_cueBox.setLocation(m_specifiedPosition); |
| 220 | 234 |
| 221 // XX. If switched is true, jump to the step labeled done | |
| 222 // positioning below. | |
| 223 if (switched) | |
| 224 return false; | |
| 225 | |
| 226 // 26. Negate step. | 235 // 26. Negate step. |
| 227 step = -step; | 236 step = -step; |
| 228 | 237 |
| 229 // 27. Set switched to true. | 238 // 27. Set switched to true. |
| 230 switched = true; | 239 switched = true; |
| 231 return true; | 240 return true; |
| 232 } | 241 } |
| 233 | 242 |
| 243 static float computeArea(const LayoutRect& rect) | |
| 244 { | |
| 245 return rect.size().width().toFloat() * rect.size().height().toFloat(); | |
| 246 } | |
| 247 | |
| 248 float SnapToLinesLayouter::computePositionScore() const | |
| 249 { | |
| 250 // Compute the percentage of the area of the bounding box of the boxes in | |
| 251 // boxes that is outside the title area box. | |
| 252 LayoutRect boundingBox = m_cueBox.absoluteBoundingBoxRect(); | |
| 253 LayoutRect intersectingBox = intersection(m_cueBox.containingBlock()->absolu teBoundingBoxRect(), boundingBox); | |
|
philipj_slow
2015/01/27 10:36:09
Extract this into a LayoutRect titleAreaBox to be
fs
2015/01/27 11:54:53
Done.
| |
| 254 // We know the intersection/overlap, so compute the percentage of the | |
| 255 // overlap and then invert. | |
| 256 return 1.0f - computeArea(intersectingBox) / computeArea(boundingBox); | |
|
philipj_slow
2015/01/27 10:36:09
Can you assert that it's in the range [0,1]? The t
fs
2015/01/27 11:54:53
Modified this a bit to compute the area in LayoutU
| |
| 257 } | |
| 258 | |
| 234 void SnapToLinesLayouter::layout() | 259 void SnapToLinesLayouter::layout() |
| 235 { | 260 { |
| 236 // http://dev.w3.org/html5/webvtt/#dfn-apply-webvtt-cue-settings | 261 // http://dev.w3.org/html5/webvtt/#dfn-apply-webvtt-cue-settings |
| 237 // Step 13, "If cue's text track cue snap-to-lines flag is set". | 262 // Step 13, "If cue's text track cue snap-to-lines flag is set". |
| 238 | 263 |
| 239 InlineFlowBox* firstLineBox; | 264 InlineFlowBox* firstLineBox; |
| 240 if (!findFirstLineBox(firstLineBox)) | 265 if (!findFirstLineBox(firstLineBox)) |
| 241 return; | 266 return; |
| 242 | 267 |
| 243 // Step 1 skipped. | 268 // Step 1 skipped. |
| 244 | 269 |
| 245 LayoutUnit step; | 270 LayoutUnit step; |
| 246 LayoutUnit position; | 271 LayoutUnit position; |
| 247 if (!initializeLayoutParameters(firstLineBox, step, position)) | 272 if (!initializeLayoutParameters(firstLineBox, step, position)) |
| 248 return; | 273 return; |
| 249 | 274 |
| 250 bool switched; | 275 bool switched; |
| 251 placeBoxInDefaultPosition(position, switched); | 276 placeBoxInDefaultPosition(position, switched); |
| 252 | 277 |
| 253 // Step 17 skipped. (margin == 0; title area == video area) | 278 // Step 17 skipped. (margin == 0; title area == video area) |
| 254 | 279 |
| 255 // 18. Step loop: If none of the boxes in boxes would overlap any of the | 280 // 18. Step loop: If none of the boxes in boxes would overlap any of the |
| 256 // boxes in output, and all of the boxes in output are entirely within the | 281 // boxes in output, and all of the boxes in output are entirely within the |
| 257 // title area box, then jump to the step labeled done positioning below. | 282 // title area box, then jump to the step labeled done positioning below. |
| 258 while (isOutside() || isOverlapping()) { | 283 while (isOutside() || isOverlapping()) { |
| 259 // 19. Let current position score be the percentage of the area of the | 284 // 19. Let current position score be the percentage of the area of the |
| 260 // bounding box of the boxes in boxes that is outside the title area | 285 // bounding box of the boxes in boxes that is outside the title area |
| 261 // box. | 286 // box. |
| 287 float currentPositionScore = computePositionScore(); | |
| 288 | |
| 262 // 20. If best position is null (i.e. this is the first run through | 289 // 20. If best position is null (i.e. this is the first run through |
| 263 // this loop, switched is still false, the boxes in boxes are at their | 290 // this loop, switched is still false, the boxes in boxes are at their |
| 264 // specified position, and best position score is still null), or if | 291 // specified position, and best position score is still null), or if |
| 265 // current position score is a lower percentage than that in best | 292 // current position score is a lower percentage than that in best |
| 266 // position score, then remember the position of all the boxes in boxes | 293 // position score, then remember the position of all the boxes in boxes |
| 267 // as their best position, and set best position score to current | 294 // as their best position, and set best position score to current |
| 268 // position score. | 295 // position score. |
| 296 if (currentPositionScore < m_bestPositionScore) { | |
| 297 m_bestPosition = m_cueBox.location(); | |
| 298 m_bestPositionScore = currentPositionScore; | |
| 299 } | |
| 300 | |
| 269 if (!shouldSwitchDirection(firstLineBox, step)) { | 301 if (!shouldSwitchDirection(firstLineBox, step)) { |
| 270 // 22. Move all the boxes in boxes ... | 302 // 22. Move all the boxes in boxes ... |
| 271 moveBoxesByStep(step); | 303 moveBoxesByStep(step); |
| 272 // 23. Jump back to the step labeled step loop. | 304 // 23. Jump back to the step labeled step loop. |
| 273 } else if (!switchDirection(switched, step)) { | 305 } else if (!switchDirection(switched, step)) { |
| 274 break; | 306 break; |
| 275 } | 307 } |
| 276 | 308 |
| 277 // 28. Jump back to the step labeled step loop. | 309 // 28. Jump back to the step labeled step loop. |
| 278 } | 310 } |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 364 SnapToLinesLayouter(*this, m_cue->getWritingDirection(), m_cue->calculat eComputedLinePosition()).layout(); | 396 SnapToLinesLayouter(*this, m_cue->getWritingDirection(), m_cue->calculat eComputedLinePosition()).layout(); |
| 365 | 397 |
| 366 adjustForTopAndBottomMarginBorderAndPadding(); | 398 adjustForTopAndBottomMarginBorderAndPadding(); |
| 367 } else { | 399 } else { |
| 368 repositionCueSnapToLinesNotSet(); | 400 repositionCueSnapToLinesNotSet(); |
| 369 } | 401 } |
| 370 } | 402 } |
| 371 | 403 |
| 372 } // namespace blink | 404 } // namespace blink |
| 373 | 405 |
| OLD | NEW |