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 15 matching lines...) Expand all Loading... | |
| 26 #include "core/layout/LayoutVTTCue.h" | 26 #include "core/layout/LayoutVTTCue.h" |
| 27 | 27 |
| 28 #include "core/frame/Settings.h" | 28 #include "core/frame/Settings.h" |
| 29 #include "core/html/shadow/MediaControls.h" | 29 #include "core/html/shadow/MediaControls.h" |
| 30 #include "core/layout/LayoutInline.h" | 30 #include "core/layout/LayoutInline.h" |
| 31 #include "core/layout/LayoutState.h" | 31 #include "core/layout/LayoutState.h" |
| 32 #include "wtf/MathExtras.h" | 32 #include "wtf/MathExtras.h" |
| 33 | 33 |
| 34 namespace blink { | 34 namespace blink { |
| 35 | 35 |
| 36 LayoutVTTCue::LayoutVTTCue(ContainerNode* node, float snapToLinesPosition) | 36 namespace { |
| 37 : LayoutBlockFlow(node) | |
| 38 , m_snapToLinesPosition(snapToLinesPosition) | |
| 39 { | |
| 40 } | |
| 41 | 37 |
| 42 class SnapToLinesLayouter { | 38 class SnapToLinesLayouter { |
| 43 STACK_ALLOCATED(); | 39 STACK_ALLOCATED(); |
| 44 public: | 40 public: |
| 45 SnapToLinesLayouter(LayoutVTTCue& cueBox, const IntRect& controlsRect) | 41 SnapToLinesLayouter(LayoutVTTCue& cueBox, const IntRect& controlsRect) |
| 46 : m_cueBox(cueBox) | 42 : m_cueBox(cueBox) |
| 47 , m_controlsRect(controlsRect) | 43 , m_controlsRect(controlsRect) |
| 48 , m_margin(0.0) | 44 , m_margin(0.0) |
| 49 { | 45 { |
| 50 if (Settings* settings = m_cueBox.document().settings()) | 46 if (Settings* settings = m_cueBox.document().settings()) |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 75 InlineFlowBox* SnapToLinesLayouter::findFirstLineBox() const | 71 InlineFlowBox* SnapToLinesLayouter::findFirstLineBox() const |
| 76 { | 72 { |
| 77 if (!m_cueBox.firstChild()->isLayoutInline()) | 73 if (!m_cueBox.firstChild()->isLayoutInline()) |
| 78 return nullptr; | 74 return nullptr; |
| 79 return toLayoutInline(m_cueBox.firstChild())->firstLineBox(); | 75 return toLayoutInline(m_cueBox.firstChild())->firstLineBox(); |
| 80 } | 76 } |
| 81 | 77 |
| 82 LayoutUnit SnapToLinesLayouter::computeInitialPositionAdjustment(LayoutUnit& ste p, LayoutUnit maxDimension, | 78 LayoutUnit SnapToLinesLayouter::computeInitialPositionAdjustment(LayoutUnit& ste p, LayoutUnit maxDimension, |
| 83 LayoutUnit margin) const | 79 LayoutUnit margin) const |
| 84 { | 80 { |
| 85 ASSERT(std::isfinite(m_cueBox.snapToLinesPosition())); | 81 DCHECK(std::isfinite(m_cueBox.snapToLinesPosition())); |
| 86 | 82 |
| 87 // 6. Let line be cue's computed line. | 83 // 6. Let line be cue's computed line. |
| 88 // 7. Round line to an integer by adding 0.5 and then flooring it. | 84 // 7. Round line to an integer by adding 0.5 and then flooring it. |
| 89 LayoutUnit linePosition(floorf(m_cueBox.snapToLinesPosition() + 0.5f)); | 85 LayoutUnit linePosition(floorf(m_cueBox.snapToLinesPosition() + 0.5f)); |
| 90 | 86 |
| 91 WritingMode writingMode = m_cueBox.style()->getWritingMode(); | 87 WritingMode writingMode = m_cueBox.style()->getWritingMode(); |
| 92 // 8. Vertical Growing Left: Add one to line then negate it. | 88 // 8. Vertical Growing Left: Add one to line then negate it. |
| 93 if (writingMode == RightToLeftWritingMode) | 89 if (writingMode == RightToLeftWritingMode) |
| 94 linePosition = -(linePosition + 1); | 90 linePosition = -(linePosition + 1); |
| 95 | 91 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 110 | 106 |
| 111 // ... and negate step. | 107 // ... and negate step. |
| 112 step = -step; | 108 step = -step; |
| 113 } else { | 109 } else { |
| 114 // ... Otherwise, increase position by margin. | 110 // ... Otherwise, increase position by margin. |
| 115 position += margin; | 111 position += margin; |
| 116 } | 112 } |
| 117 return position; | 113 return position; |
| 118 } | 114 } |
| 119 | 115 |
| 116 // We use this helper to make sure all (bounding) boxes used for comparisons | |
| 117 // are relative to the same coordinate space. If we didn't the (bounding) boxes | |
| 118 // could be affect by transforms on an ancestor et.c, which could yield | |
| 119 // incorrect results. | |
| 120 IntRect contentBoxRelativeToAncestor( | |
| 121 const LayoutBox& box, const LayoutBoxModelObject& ancestor) | |
| 122 { | |
| 123 FloatRect cueContentBox(box.contentBoxRect()); | |
| 124 // We pass UseTransforms here primarily because we use a transform for | |
|
foolip
2016/09/30 08:12:09
Ah, this I did not realize, thanks for documenting
| |
| 125 // non-snap-to-lines positioning (see VTTCue.cpp.) | |
| 126 FloatQuad mappedContentQuad = box.localToAncestorQuad(cueContentBox, &ancest or, UseTransforms); | |
| 127 return mappedContentQuad.enclosingBoundingBox(); | |
| 128 } | |
| 129 | |
| 130 IntRect cueBoundingBox(const LayoutBox& cueBox) | |
| 131 { | |
| 132 return contentBoxRelativeToAncestor(cueBox, *cueBox.containingBlock()); | |
| 133 } | |
| 134 | |
| 120 bool SnapToLinesLayouter::isOutside(const IntRect& titleArea) const | 135 bool SnapToLinesLayouter::isOutside(const IntRect& titleArea) const |
| 121 { | 136 { |
| 122 return !titleArea.contains(m_cueBox.absoluteContentBox()); | 137 return !titleArea.contains(cueBoundingBox(m_cueBox)); |
| 123 } | 138 } |
| 124 | 139 |
| 125 bool SnapToLinesLayouter::isOverlapping() const | 140 bool SnapToLinesLayouter::isOverlapping() const |
| 126 { | 141 { |
| 127 IntRect cueBoxRect = m_cueBox.absoluteBoundingBoxRect(); | 142 IntRect cueBoxRect = cueBoundingBox(m_cueBox); |
| 128 for (LayoutObject* box = m_cueBox.previousSibling(); box; box = box->previou sSibling()) { | 143 for (LayoutBox* box = m_cueBox.previousSiblingBox(); box; box = box->previou sSiblingBox()) { |
| 129 IntRect boxRect = box->absoluteBoundingBoxRect(); | 144 if (cueBoxRect.intersects(cueBoundingBox(*box))) |
| 130 | |
| 131 if (cueBoxRect.intersects(boxRect)) | |
| 132 return true; | 145 return true; |
| 133 } | 146 } |
| 134 | 147 return cueBoxRect.intersects(m_controlsRect); |
| 135 if (cueBoxRect.intersects(m_controlsRect)) | |
| 136 return true; | |
| 137 | |
| 138 return false; | |
| 139 } | 148 } |
| 140 | 149 |
| 141 bool SnapToLinesLayouter::shouldSwitchDirection(InlineFlowBox* firstLineBox, Lay outUnit step, LayoutUnit margin) const | 150 bool SnapToLinesLayouter::shouldSwitchDirection(InlineFlowBox* firstLineBox, Lay outUnit step, LayoutUnit margin) const |
| 142 { | 151 { |
| 143 // 17. Horizontal: If step is negative and the top of the first line box in | 152 // 17. Horizontal: If step is negative and the top of the first line box in |
| 144 // boxes is now above the top of the title area, or if step is positive and | 153 // boxes is now above the top of the title area, or if step is positive and |
| 145 // the bottom of the first line box in boxes is now below the bottom of the | 154 // the bottom of the first line box in boxes is now below the bottom of the |
| 146 // title area, jump to the step labeled switch direction. | 155 // title area, jump to the step labeled switch direction. |
| 147 // Vertical: If step is negative and the left edge of the first line | 156 // Vertical: If step is negative and the left edge of the first line |
| 148 // box in boxes is now to the left of the left edge of the title area, or | 157 // box in boxes is now to the left of the left edge of the title area, or |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 204 | 213 |
| 205 // XX. Let switched be false. | 214 // XX. Let switched be false. |
| 206 bool switched = false; | 215 bool switched = false; |
| 207 | 216 |
| 208 // 14. Horizontal: Let title area be a box that covers all of the video's | 217 // 14. Horizontal: Let title area be a box that covers all of the video's |
| 209 // rendering area except for a height of margin at the top of the rendering | 218 // rendering area except for a height of margin at the top of the rendering |
| 210 // area and a height of margin at the bottom of the rendering area. | 219 // area and a height of margin at the bottom of the rendering area. |
| 211 // Vertical: Let title area be a box that covers all of the video’s | 220 // Vertical: Let title area be a box that covers all of the video’s |
| 212 // rendering area except for a width of margin at the left of the rendering | 221 // rendering area except for a width of margin at the left of the rendering |
| 213 // area and a width of margin at the right of the rendering area. | 222 // area and a width of margin at the right of the rendering area. |
| 214 IntRect titleArea = m_cueBox.containingBlock()->absoluteBoundingBoxRect(); | 223 IntRect titleArea = enclosingIntRect(m_cueBox.containingBlock()->contentBoxR ect()); |
| 215 if (blink::isHorizontalWritingMode(writingMode)) { | 224 if (blink::isHorizontalWritingMode(writingMode)) { |
| 216 titleArea.move(0, margin.toInt()); | 225 titleArea.move(0, margin.toInt()); |
| 217 titleArea.contract(0, (2 * margin).toInt()); | 226 titleArea.contract(0, (2 * margin).toInt()); |
| 218 } else { | 227 } else { |
| 219 titleArea.move(margin.toInt(), 0); | 228 titleArea.move(margin.toInt(), 0); |
| 220 titleArea.contract((2 * margin).toInt(), 0); | 229 titleArea.contract((2 * margin).toInt(), 0); |
| 221 } | 230 } |
| 222 | 231 |
| 223 // 15. Step loop: If none of the boxes in boxes would overlap any of the | 232 // 15. Step loop: If none of the boxes in boxes would overlap any of the |
| 224 // boxes in output, and all of the boxes in output are entirely within the | 233 // boxes in output, and all of the boxes in output are entirely within the |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 257 // 22. Negate step. | 266 // 22. Negate step. |
| 258 step = -step; | 267 step = -step; |
| 259 | 268 |
| 260 // 23. Set switched to true. | 269 // 23. Set switched to true. |
| 261 switched = true; | 270 switched = true; |
| 262 | 271 |
| 263 // 24. Jump back to the step labeled step loop. | 272 // 24. Jump back to the step labeled step loop. |
| 264 } | 273 } |
| 265 } | 274 } |
| 266 | 275 |
| 276 } // unnamed namespace | |
| 277 | |
| 278 LayoutVTTCue::LayoutVTTCue(ContainerNode* node, float snapToLinesPosition) | |
| 279 : LayoutBlockFlow(node) | |
| 280 , m_snapToLinesPosition(snapToLinesPosition) | |
| 281 { | |
| 282 } | |
| 283 | |
| 267 void LayoutVTTCue::repositionCueSnapToLinesNotSet() | 284 void LayoutVTTCue::repositionCueSnapToLinesNotSet() |
| 268 { | 285 { |
| 269 // FIXME: Implement overlapping detection when snap-to-lines is not set. htt p://wkb.ug/84296 | 286 // FIXME: Implement overlapping detection when snap-to-lines is not set. htt p://wkb.ug/84296 |
| 270 | 287 |
| 271 // http://dev.w3.org/html5/webvtt/#dfn-apply-webvtt-cue-settings | 288 // http://dev.w3.org/html5/webvtt/#dfn-apply-webvtt-cue-settings |
| 272 // Step 13, "If cue's text track cue snap-to-lines flag is not set". | 289 // Step 13, "If cue's text track cue snap-to-lines flag is not set". |
| 273 | 290 |
| 274 // 1. Let bounding box be the bounding box of the boxes in boxes. | 291 // 1. Let bounding box be the bounding box of the boxes in boxes. |
| 275 | 292 |
| 276 // 2. Run the appropriate steps from the following list: | 293 // 2. Run the appropriate steps from the following list: |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 301 // position to their current position, and then jump to the step labeled | 318 // position to their current position, and then jump to the step labeled |
| 302 // done positioning below. If there are multiple such positions that are | 319 // done positioning below. If there are multiple such positions that are |
| 303 // equidistant from their current position, use the highest one amongst | 320 // equidistant from their current position, use the highest one amongst |
| 304 // them; if there are several at that height, then use the leftmost one | 321 // them; if there are several at that height, then use the leftmost one |
| 305 // amongst them. | 322 // amongst them. |
| 306 | 323 |
| 307 // 5. Otherwise, jump to the step labeled done positioning below. (The | 324 // 5. Otherwise, jump to the step labeled done positioning below. (The |
| 308 // boxes will unfortunately overlap.) | 325 // boxes will unfortunately overlap.) |
| 309 } | 326 } |
| 310 | 327 |
| 328 IntRect LayoutVTTCue::computeControlsRect() const | |
| 329 { | |
| 330 // Determine the area covered by the media controls, if any. If the controls | |
| 331 // are present, they are the next sibling of the text track container, which | |
| 332 // is our parent. (LayoutMedia ensures that the media controls are laid out | |
| 333 // before text tracks, so that the layout is up to date here.) | |
| 334 DCHECK(parent()->node()->isTextTrackContainer()); | |
| 335 LayoutObject* controlsContainer = parent()->nextSibling(); | |
| 336 if (!controlsContainer) | |
| 337 return IntRect(); | |
| 338 // Only a part of the media controls is used for overlap avoidance. | |
| 339 MediaControls* controls = toMediaControls(controlsContainer->node()); | |
| 340 LayoutObject* controlsLayout = controls->layoutObjectForTextTrackLayout(); | |
| 341 // The (second part of the) following is mostly defensive - in general | |
| 342 // there should be a LayoutBox representing the part of the controls that | |
| 343 // are relevant for overlap avoidance. (The controls pseudo elements are | |
| 344 // generally reachable from outside the shadow tree though, hence the | |
| 345 // "mostly".) | |
| 346 if (!controlsLayout || !controlsLayout->isBox()) | |
| 347 return IntRect(); | |
| 348 // Assume that the controls container are positioned in the same relative | |
| 349 // position as the text track container. (LayoutMedia::layout ensures this.) | |
| 350 return contentBoxRelativeToAncestor( | |
| 351 toLayoutBox(*controlsLayout), toLayoutBox(*controlsContainer)); | |
| 352 } | |
| 353 | |
| 311 void LayoutVTTCue::layout() | 354 void LayoutVTTCue::layout() |
| 312 { | 355 { |
| 313 LayoutBlockFlow::layout(); | 356 LayoutBlockFlow::layout(); |
| 314 | 357 |
| 315 ASSERT(firstChild()); | 358 DCHECK(firstChild()); |
| 316 | 359 |
| 317 LayoutState state(*this, locationOffset()); | 360 LayoutState state(*this, locationOffset()); |
| 318 | 361 |
| 319 // Determine the area covered by the media controls, if any. If the controls | |
| 320 // are present, they are the next sibling of the text track container, which | |
| 321 // is our parent. (LayoutMedia ensures that the media controls are laid out | |
| 322 // before text tracks, so that the layout is up to date here.) | |
| 323 ASSERT(parent()->node()->isTextTrackContainer()); | |
| 324 IntRect controlsRect; | |
| 325 if (LayoutObject* parentSibling = parent()->nextSibling()) { | |
| 326 // Only a part of the media controls is used for overlap avoidance. | |
| 327 MediaControls* controls = toMediaControls(parentSibling->node()); | |
| 328 if (LayoutObject* controlsLayout = controls->layoutObjectForTextTrackLay out()) | |
| 329 controlsRect = controlsLayout->absoluteBoundingBoxRect(); | |
| 330 } | |
| 331 | |
| 332 // http://dev.w3.org/html5/webvtt/#dfn-apply-webvtt-cue-settings - step 13. | 362 // http://dev.w3.org/html5/webvtt/#dfn-apply-webvtt-cue-settings - step 13. |
| 333 if (!std::isnan(m_snapToLinesPosition)) | 363 if (!std::isnan(m_snapToLinesPosition)) |
| 334 SnapToLinesLayouter(*this, controlsRect).layout(); | 364 SnapToLinesLayouter(*this, computeControlsRect()).layout(); |
| 335 else | 365 else |
| 336 repositionCueSnapToLinesNotSet(); | 366 repositionCueSnapToLinesNotSet(); |
| 337 } | 367 } |
| 338 | 368 |
| 339 } // namespace blink | 369 } // namespace blink |
| OLD | NEW |