Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutVTTCue.cpp

Issue 2377193003: Don't use absolute bounding boxes in LayoutVTTCue (Closed)
Patch Set: Extend comments; adjust test Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/core/layout/LayoutVTTCue.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/layout/LayoutVTTCue.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698