keep SkRSXforms aligned in SkLiteDL

We've been copying the text first, then the transforms.
That's a good way to get the transforms out of alignment.

This CL swaps the order of the two.

Bug: skia:7133

Change-Id: If8cd402b9ffba1787345dc4b5ffd4ee6abb14f33
Reviewed-on: https://skia-review.googlesource.com/57941
Reviewed-by: Derek Sollenberger <djsollen@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
diff --git a/src/core/SkLiteDL.cpp b/src/core/SkLiteDL.cpp
index c5144e5..ab5cce3 100644
--- a/src/core/SkLiteDL.cpp
+++ b/src/core/SkLiteDL.cpp
@@ -391,16 +391,21 @@
     };
     struct DrawTextRSXform final : Op {
         static const auto kType = Type::DrawTextRSXform;
-        DrawTextRSXform(size_t bytes, const SkRect* cull, const SkPaint& paint)
-            : bytes(bytes), paint(paint) {
+        DrawTextRSXform(size_t bytes, int xforms, const SkRect* cull, const SkPaint& paint)
+            : bytes(bytes), xforms(xforms), paint(paint) {
             if (cull) { this->cull = *cull; }
         }
         size_t  bytes;
+        int     xforms;
         SkRect  cull = kUnset;
         SkPaint paint;
         void draw(SkCanvas* c, const SkMatrix&) const {
-            c->drawTextRSXform(pod<void>(this), bytes, pod<SkRSXform>(this, bytes),
-                               maybe_unset(cull), paint);
+            // For alignment, the SkRSXforms are first in the pod section, followed by the text.
+            c->drawTextRSXform(pod<void>(this,xforms*sizeof(SkRSXform)),
+                               bytes,
+                               pod<SkRSXform>(this),
+                               maybe_unset(cull),
+                               paint);
         }
     };
     struct DrawTextBlob final : Op {
@@ -649,8 +654,8 @@
 void SkLiteDL::drawTextRSXform(const void* text, size_t bytes,
                                const SkRSXform xforms[], const SkRect* cull, const SkPaint& paint) {
     int n = paint.countText(text, bytes);
-    void* pod = this->push<DrawTextRSXform>(bytes+n*sizeof(SkRSXform), bytes, cull, paint);
-    copy_v(pod, (const char*)text,bytes, xforms,n);
+    void* pod = this->push<DrawTextRSXform>(bytes+n*sizeof(SkRSXform), bytes, n, cull, paint);
+    copy_v(pod, xforms,n, (const char*)text,bytes);
 }
 void SkLiteDL::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) {
     this->push<DrawTextBlob>(0, blob, x,y, paint);
diff --git a/tests/SkLiteDLTest.cpp b/tests/SkLiteDLTest.cpp
index d719c0b..4dfce09 100644
--- a/tests/SkLiteDLTest.cpp
+++ b/tests/SkLiteDLTest.cpp
@@ -5,9 +5,10 @@
  * found in the LICENSE file.
  */
 
-#include "Test.h"
 #include "SkLiteDL.h"
 #include "SkLiteRecorder.h"
+#include "SkRSXform.h"
+#include "Test.h"
 
 DEF_TEST(SkLiteDL_basics, r) {
     SkLiteDL p;
@@ -62,3 +63,28 @@
     canvas.flush();
     REPORTER_ASSERT(r, !dl.empty());
 }
+
+// skia:7133 regression test.
+// At one point we recorded text before the transforms, which makes it easy for
+// the recording buffer to not be suitably aligned for the transforms.
+DEF_TEST(SkLiteRecorder_RSXformAlignment, r) {
+    SkLiteDL dl;
+    SkLiteRecorder canvas;
+    canvas.reset(&dl, {0,0,100,100});
+
+    SkPaint paint;
+    paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
+
+    // These values don't really matter... we just need 5 valid transforms.
+    SkRSXform xforms[] = {
+        {1,0, 1,1},
+        {1,0, 2,2},
+        {1,0, 3,3},
+        {1,0, 4,4},
+        {1,0, 5,5},
+    };
+    canvas.drawTextRSXform("hello", 5, xforms, nullptr, paint);
+
+    // We're just checking that this recorded our draw without SkASSERTing in Debug builds.
+    REPORTER_ASSERT(r, !dl.empty());
+}