Bug 1429299 - Part 3: Layout update for offset-distance. r=birtles
authorBoris Chiou <boris.chiou@gmail.com>
Mon, 20 May 2019 23:42:54 +0000
changeset 474642 e6343b742e91be084079764c242a4cca569423d1
parent 474641 9d417fb6fcc29efd42b2b3f8070fca6518ae0c89
child 474643 6ceb38a8197408f055b05b205bc412f2c77850a9
push id36042
push userdvarga@mozilla.com
push dateTue, 21 May 2019 04:19:40 +0000
treeherdermozilla-central@ca560ff55451 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbirtles
bugs1429299
milestone69.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 1429299 - Part 3: Layout update for offset-distance. r=birtles Just need to take offset-distance into account to get the final matrix. Differential Revision: https://phabricator.services.mozilla.com/D30583
layout/base/nsLayoutUtils.cpp
testing/web-platform/meta/css/motion/offset-path-string-001.html.ini
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -9954,45 +9954,64 @@ ComputedStyle* nsLayoutUtils::StyleForSc
 Maybe<MotionPathData> nsLayoutUtils::ResolveMotionPath(const nsIFrame* aFrame) {
   MOZ_ASSERT(aFrame);
 
   const nsStyleDisplay* display = aFrame->StyleDisplay();
   if (display->mOffsetPath.IsNone()) {
     return Nothing();
   }
 
-  // Bug 1429299 - Implement offset-distance for motion path. For now, we use
-  // the default value, i.e. 0%.
-  float distance = 0.0;
-  float angle = 0.0;
+  gfx::Float angle = 0.0;
   Point point;
   if (display->mOffsetPath.IsPath()) {
+    const Span<const StylePathCommand>& path =
+        display->mOffsetPath.AsPath()._0.AsSpan();
     // Build the path and compute the point and angle for creating the
     // equivalent translate and rotate.
     // Here we only need to build a valid path for motion path, so
     // using the default values of stroke-width, stoke-linecap, and fill-rule
     // is fine for now because what we want is get the point and its normal
     // vector along the path, instead of rendering it.
     // FIXME: Bug 1484780, we should cache the path to avoid rebuilding it here
     // at every restyle. (Caching the path avoids the cost of flattening it
     // again each time.)
     RefPtr<DrawTarget> drawTarget =
         gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
     RefPtr<PathBuilder> builder =
         drawTarget->CreatePathBuilder(FillRule::FILL_WINDING);
-    RefPtr<gfx::Path> gfxPath =
-        SVGPathData::BuildPath(display->mOffsetPath.AsPath()._0.AsSpan(),
-                               builder, NS_STYLE_STROKE_LINECAP_BUTT, 0.0);
+    RefPtr<gfx::Path> gfxPath = SVGPathData::BuildPath(
+        path, builder, NS_STYLE_STROKE_LINECAP_BUTT, 0.0);
     if (!gfxPath) {
       return Nothing();
     }
-    float pathLength = gfxPath->ComputeLength();
-    float computedDistance = distance * pathLength;
+
+    // Per the spec, we have to convert offset distance to pixels, with 100%
+    // being converted to total length. So here |gfxPath| is built with CSS
+    // pixel, and we calculate |pathLength| and |computedDistance| with CSS
+    // pixel as well.
+    gfx::Float pathLength = gfxPath->ComputeLength();
+    gfx::Float usedDistance =
+      display->mOffsetDistance.ResolveToCSSPixels(CSSCoord(pathLength));
+    if (!path.empty() && path.rbegin()->IsClosePath()) {
+      // Per the spec, let used offset distance be equal to offset distance
+      // modulus the total length of the path. If the total length of the path
+      // is 0, used offset distance is also 0.
+      usedDistance = pathLength > 0.0 ? fmod(usedDistance, pathLength) : 0.0;
+      // We make sure |usedDistance| is 0.0 or a positive value.
+      // https://github.com/w3c/fxtf-drafts/issues/339
+      if (usedDistance < 0.0) {
+        usedDistance += pathLength;
+      }
+    } else {
+      // Per the spec, for unclosed interval, let used offset distance be equal
+      // to offset distance clamped by 0 and the total length of the path.
+      usedDistance = clamped(usedDistance, 0.0f, pathLength);
+    }
     Point tangent;
-    point = gfxPath->ComputePointAtLength(computedDistance, &tangent);
+    point = gfxPath->ComputePointAtLength(usedDistance, &tangent);
     // Bug 1429301 - Implement offset-rotate for motion path.
     // After implement offset-rotate, |angle| will be adjusted more.
     // For now, the default value of offset-rotate is "auto", so we use the
     // directional tangent vector.
     angle = atan2(tangent.y, tangent.x);
   } else {
     // Bug 1480665: Implement ray() function.
     NS_WARNING("Unsupported offset-path value");
deleted file mode 100644
--- a/testing/web-platform/meta/css/motion/offset-path-string-001.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[offset-path-string-001.html]
-  expected: FAIL
-  bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1429299