[skottie] Fix range selector handling of empty lines

Range selectors operating in the line domain need accurate line-index
to fragment-span mapping.

But the text shaper does not emit any fragments for empty lines, and
the current map builder gets confused and generates incomplete maps.

E.g. for something like "\r\r\rfoo\r\r" we get line {offset, count}
tuples of

  {0,0}
  {0,3}

instead of expected

  {0,0}
  {0,0}
  {0,0}
  {0,3}
  {3,0}
  {3,0}

To fix, update SkottieShaper to emit empty fragments for empty lines.

Change-Id: Ia40562d4b39dc6c55a139ff79df94291407a6a31
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/588737
Commit-Queue: Florin Malita <fmalita@google.com>
Reviewed-by: Ben Wagner <bungeman@google.com>
diff --git a/modules/skottie/src/text/SkottieShaper.cpp b/modules/skottie/src/text/SkottieShaper.cpp
index a12bbb7..d0d7ae2 100644
--- a/modules/skottie/src/text/SkottieShaper.cpp
+++ b/modules/skottie/src/text/SkottieShaper.cpp
@@ -254,6 +254,19 @@
             // SkShaper doesn't care for empty lines.
             this->beginLine();
             this->commitLine();
+
+            // The calls above perform bookkeeping, but they do not add any fragments (since there
+            // are no runs to commit).
+            // Line-based range selectors do require accurate indexing information even for empty
+            // lines though -- so we inject empty fragments solely for line index tracking.
+            fResult.fFragments.push_back({
+                Shaper::ShapedGlyphs(),
+                {0,0},
+                0, 0,
+                fLineCount - 1,
+                false
+            });
+
             return;
         }
 
diff --git a/resources/skottie/skottie-text-emptylines.json b/resources/skottie/skottie-text-emptylines.json
new file mode 100644
index 0000000..5304c10
--- /dev/null
+++ b/resources/skottie/skottie-text-emptylines.json
@@ -0,0 +1 @@
+{"v":"5.9.5","fr":24,"ip":0,"op":72,"w":500,"h":500,"nm":"empty_lines","ddd":0,"assets":[],"fonts":{"list":[{"origin":0,"fPath":"","fClass":"","fFamily":"Arial","fWeight":"","fStyle":"Regular","fName":"ArialMT","ascent":75.6476929411292}]},"layers":[{"ddd":0,"ind":1,"ty":5,"nm":"\r\rYaY\r\r\rYaY\r\r\r","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[253.23,255.168,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"t":{"d":{"k":[{"s":{"sz":[242.894058227539,361.757110595703],"ps":[-121.44702911377,-180.878555297852],"s":36,"f":"ArialMT","t":"\r\rYaY\r\r\rYaY\r\r","ca":0,"j":2,"tr":0,"lh":43.2000007629395,"ls":0,"fc":[1,0,0]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[{"nm":"Animator 1","s":{"t":0,"xe":{"a":0,"k":0,"ix":7},"ne":{"a":0,"k":0,"ix":8},"a":{"a":0,"k":100,"ix":4},"b":4,"rn":0,"sh":1,"sm":{"a":0,"k":100,"ix":6},"e":{"a":0,"k":10,"ix":2},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[-10]},{"t":71,"s":[100]}],"ix":3},"r":1},"a":{"t":{"a":0,"k":64,"ix":89}}}]},"ip":0,"op":72,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":1,"nm":"Medium Gray-Royal Blue Solid 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[250,51,0],"to":[0,63.333,0],"ti":[0,-63.333,0]},{"t":71,"s":[250,431,0]}],"ix":2,"l":2},"a":{"a":0,"k":[80,20,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"sw":160,"sh":40,"sc":"#2c6ba7","ip":0,"op":72,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":1,"nm":"White Solid 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2,"l":2},"a":{"a":0,"k":[600,600,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"sw":1200,"sh":1200,"sc":"#ffffff","ip":0,"op":72,"st":0,"bm":0}],"markers":[]}