Bug 1488673 - part4 : adjust cue's position. r=heycam
☠☠ backed out by 2e3d01a1b848 ☠ ☠
authorAlastor Wu <alwu@mozilla.com>
Wed, 13 Mar 2019 16:27:17 +0000
changeset 464746 d18858a1fe8bdb056197efabd3ff60ff1384ec92
parent 464745 e5030bf46846ed74d8da85aebb0535c40c722591
child 464747 9fa072a4b67d1fdd4be91351293cd5615dae21c9
push id112481
push userrgurzau@mozilla.com
push dateMon, 18 Mar 2019 21:51:19 +0000
treeherdermozilla-inbound@6ed5e5a3e39e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1488673
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1488673 - part4 : adjust cue's position. r=heycam According to the spec 7.2.10, step1 to step10 (snap-to-line is true) and step1 to step2 (snap-to-line is flase) [1], we would adjust cue box's position depending on the algorithm. The algorithm would calculate the cue box's top (or left) position depending on the writing direction, and move the box to the specific position. However, if the cue box is overlapping with other cue boxes in the rendering area, we would still need to adjust its postion, which will be implemented in next patch. [1] https://w3c.github.io/webvtt/#ref-for-webvtt-cue-snap-to-lines-flag-12 https://w3c.github.io/webvtt/#ref-for-webvtt-cue-snap-to-lines-flag-13 Differential Revision: https://phabricator.services.mozilla.com/D19609
dom/media/webvtt/vtt.jsm
--- a/dom/media/webvtt/vtt.jsm
+++ b/dom/media/webvtt/vtt.jsm
@@ -893,16 +893,118 @@ XPCOMUtils.defineLazyPreferenceGetter(th
         left: this.left - reference.left,
         right: reference.right - this.right,
         height: this.height,
         width: this.width
       };
     }
   }
 
+  function adjustBoxPosition(styleBox, containerBox, controlBarBox) {
+    const cue = styleBox.cue;
+    const isWritingDirectionHorizontal = cue.vertical == "";
+    let box = new BoxPosition(styleBox);
+
+    // Spec 7.2.10, adjust the positions of boxes according to the appropriate
+    // steps from the following list. Also, we use offsetHeight/offsetWidth here
+    // in order to prevent the incorrect positioning caused by CSS transform
+    // scale.
+    const fullDimension = isWritingDirectionHorizontal ?
+      containerBox.height : containerBox.width;
+    if (cue.snapToLines) {
+      // The step is the height or width of the line box. We should use font
+      // size directly, instead of using text box's width or height, because the
+      // width or height of the box would be changed when the text is wrapped to
+      // different line. Ex. if text is wrapped to two line, the height or width
+      // of the box would become 2 times of font size.
+      let step = parseFloat(styleBox.fontSize.replace("px", ""));
+      if (step == 0) {
+        return;
+      }
+
+      let line = Math.floor(cue.computedLine + 0.5);
+      if (cue.vertical == "rl") {
+        line = -1 * (line + 1);
+      }
+
+      let position = step * line;
+      if (cue.vertical == "rl") {
+        position = position - box.width + step;
+      }
+
+      if (line < 0) {
+        position += fullDimension;
+        step = -1 * step;
+      }
+
+      if (isWritingDirectionHorizontal) {
+        box.top += position;
+      } else {
+        box.left += position;
+      }
+
+      function isBoxOutsideTheRenderingArea() {
+        if (isWritingDirectionHorizontal) {
+          // the top side of the box is above the rendering area, or the bottom
+          // side of the box is below the rendering area.
+          return step < 0 && box.top < 0 ||
+                 step > 0 && box.bottom > fullDimension;
+        }
+        // the left side of the box is outside the left side of the rendering
+        // area, or the right side of the box is outside the right side of the
+        // rendering area.
+        return step < 0 && box.left < 0 ||
+               step > 0 && box.right > fullDimension;
+      }
+
+      // TODO : implement checking if current box is overlapping with any other
+      // boxes in output. 7.2.10.13
+
+      // 7.2.10.14 ~ 7.2.10.21, if the box is outside the rendering area, we
+      // should switch the direction.
+      if (isBoxOutsideTheRenderingArea()) {
+        step = -1 * step;
+        if (isWritingDirectionHorizontal) {
+          box.top += step;
+        } else {
+          box.left += step;
+        }
+      }
+    } else {
+      if (cue.lineAlign != "start") {
+        const isCenterAlign = cue.lineAlign == "center";
+        if (isWritingDirectionHorizontal) {
+          box.top += isCenterAlign ? box.height : box.height / 2;
+        } else {
+          box.left += isCenterAlign ? box.width : box.width / 2;
+        }
+      }
+      // TODO : implement finding the best position, 7.2.10.4
+    }
+
+    // In order to not be affected by CSS scale, so we use '%' to make sure the
+    // cue can stick in the right position.
+    function getPercentagePosition(position, fullDimension) {
+      return (position / fullDimension) * 100 + "%";
+    }
+    if (isWritingDirectionHorizontal) {
+      // Avoid to overlap the cue with the video control.
+      const controlOffset = controlBarBox ? controlBarBox.height : 0;
+      styleBox.applyStyles({
+        top: getPercentagePosition(box.top - controlOffset, fullDimension),
+      });
+    } else {
+      styleBox.applyStyles({
+        left: getPercentagePosition(box.left, fullDimension),
+      });
+    }
+
+    return box;
+  }
+
   // Move a StyleBox to its specified, or next best, position. The containerBox
   // is the box that contains the StyleBox, such as a div. boxPositions are
   // a list of other boxes that the styleBox can't overlap with.
   function moveBoxToLinePosition(window, styleBox, containerBox, boxPositions) {
 
     // Find the best position for a cue box, b, on the video. The axis parameter
     // is a list of axis, the order of which, it will move the box along. For example:
     // Passing ["+x", "-x"] will move the box first along the x axis in the positive
@@ -1163,24 +1265,24 @@ XPCOMUtils.defineLazyPreferenceGetter(th
           rootOfCues.appendChild(currentRegionNodeDiv);
           cue.displayState = styleBox.div;
           boxPositions.push(new BoxPosition(currentRegionBox));
         } else {
           // Compute the intial position and styles of the cue div.
           styleBox = new CueStyleBox(window, cue, containerBox);
           rootOfCues.appendChild(styleBox.div);
 
-          // Move the cue div to it's correct line position.
-          moveBoxToLinePosition(window, styleBox, containerBox, boxPositions);
+          // Move the cue to correct position.
+          let cueBox = adjustBoxPosition(styleBox, containerBox, controlBarBox);
 
           // Remember the computed div so that we don't have to recompute it later
           // if we don't have too.
           cue.displayState = styleBox.div;
 
-          boxPositions.push(new BoxPosition(styleBox));
+          boxPositions.push(cueBox);
         }
       }
     })();
   };
 
   WebVTT.Parser = function(window, decoder) {
     this.window = window;
     this.state = "INITIAL";