[canvaskit] Always serialize Typeface data into SKPs

Before: http://screen/4gnRTnRGyBuEsA9
After: http://screen/5jdoRcED7X3Taf7

There's a few misc fixes related to Bazel rules and tests too.

Change-Id: I2ac272fe5312c2a825944259f2f9031fff9887e0
Bug: skia:13247
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/535477
Reviewed-by: Ben Wagner <bungeman@google.com>
diff --git a/modules/canvaskit/CHANGELOG.md b/modules/canvaskit/CHANGELOG.md
index f088dd7..25da42a 100644
--- a/modules/canvaskit/CHANGELOG.md
+++ b/modules/canvaskit/CHANGELOG.md
@@ -22,6 +22,10 @@
  - If an invalid matrix type is passed in (e.g. not an array, TypedArray, or DOMMatrix), CanvasKit
    will throw instead of drawing incorrectly.
 
+### Fixed
+ - SkParagraph objects no longer have their glyphs garbled when stored to an SkPicture.
+   (skbug.com/13247)
+
 ## [0.33.0] - 2022-02-03
 
 ### Added
diff --git a/modules/canvaskit/canvaskit_bindings.cpp b/modules/canvaskit/canvaskit_bindings.cpp
index 6377c07..e2fc488 100644
--- a/modules/canvaskit/canvaskit_bindings.cpp
+++ b/modules/canvaskit/canvaskit_bindings.cpp
@@ -31,6 +31,7 @@
 #include "include/core/SkRRect.h"
 #include "include/core/SkSamplingOptions.h"
 #include "include/core/SkScalar.h"
+#include "include/core/SkSerialProcs.h"
 #include "include/core/SkShader.h"
 #include "include/core/SkString.h"
 #include "include/core/SkStrokeRec.h"
@@ -680,6 +681,10 @@
 }
 #endif
 
+sk_sp<SkData> alwaysSaveTypefaceBytes(SkTypeface* face, void*) {
+    return face->serialize(SkTypeface::SerializeBehavior::kDoIncludeData);
+}
+
 // These objects have private destructors / delete methods - I don't think
 // we need to do anything other than tell emscripten to do nothing.
 namespace emscripten {
@@ -1664,9 +1669,15 @@
         // that clients should ever rely on.  The format may change at anytime and no promises
         // are made for backwards or forward compatibility.
         .function("serialize", optional_override([](SkPicture& self) -> Uint8Array {
-            // Emscripten doesn't play well with optional arguments, which we don't
-            // want to expose anyway.
-            sk_sp<SkData> data = self.serialize();
+            // We want to make sure we always save the underlying data of the Typeface to the
+            // SkPicture. By default, the data for "system" fonts is not saved, just an identifier
+            // (e.g. the family name and style). We do not want the user to have to supply a
+            // FontMgr with the correct fonts by name when deserializing, so we choose to always
+            // serialize the underlying data. This makes the SKPs a bit bigger, but easier to use.
+            SkSerialProcs sp;
+            sp.fTypefaceProc = &alwaysSaveTypefaceBytes;
+
+            sk_sp<SkData> data = self.serialize(&sp);
             if (!data) {
                 return emscripten::val::null();
             }
diff --git a/modules/canvaskit/tests/bazel/paragraph_test.js b/modules/canvaskit/tests/bazel/paragraph_test.js
index cb7442f..333271a 100644
--- a/modules/canvaskit/tests/bazel/paragraph_test.js
+++ b/modules/canvaskit/tests/bazel/paragraph_test.js
@@ -1030,4 +1030,46 @@
         fontMgr.delete();
         builder.delete();
     });
+
+    // This helped find and resolve skbug.com/13247
+    gm('paragraph saved to skpicture', (canvas) => {
+        canvas.clear(CanvasKit.WHITE);
+        const fontMgr = CanvasKit.FontMgr.FromData(notoSerifFontBuffer, notoSerifBoldItalicFontBuffer);
+
+        const wrapTo = 250;
+
+        const paraStyle = new CanvasKit.ParagraphStyle({
+            textStyle: {
+                fontSize: 20,
+            },
+        });
+
+        const builder = CanvasKit.ParagraphBuilder.Make(paraStyle, fontMgr);
+        builder.addText('This was saved to an SkPicture\n');
+
+        const boldItalic = new CanvasKit.TextStyle({
+            fontStyle: {
+                weight: CanvasKit.FontWeight.Bold,
+                slant: CanvasKit.FontSlant.Italic,
+            }
+        });
+        builder.pushStyle(boldItalic);
+        builder.addText(`Bold, Italic\n`);
+        builder.pop();
+        const paragraph = builder.build();
+        paragraph.layout(wrapTo);
+
+        const recorder = new CanvasKit.PictureRecorder();
+        const skpCanvas = recorder.beginRecording(CanvasKit.LTRBRect(0, 0, 200, 200));
+        skpCanvas.drawParagraph(paragraph, 10, 10);
+        const picture = recorder.finishRecordingAsPicture();
+
+        canvas.drawPicture(CanvasKit.MakePicture(picture.serialize()));
+
+        picture.delete();
+        recorder.delete();
+        paragraph.delete();
+        fontMgr.delete();
+        builder.delete();
+    });
 });
diff --git a/modules/canvaskit/tests/bazel/test_reporter.js b/modules/canvaskit/tests/bazel/test_reporter.js
index b8b9e67..408a1e6 100644
--- a/modules/canvaskit/tests/bazel/test_reporter.js
+++ b/modules/canvaskit/tests/bazel/test_reporter.js
@@ -2,7 +2,8 @@
 const pngPrefx = 'data:image/png;base64,'
 
 function reportCanvas(canvas, testname) {
-        // toDataURL returns a base64 encoded string with a data prefix. We only
+    testname = testname.replaceAll(' ', '_');
+    // toDataURL returns a base64 encoded string with a data prefix. We only
     // want the PNG data itself, so we strip that off before submitting it.
     const b64 = canvas.toDataURL('image/png')
                       .substring(pngPrefx.length);
diff --git a/third_party/BUILD.bazel b/third_party/BUILD.bazel
index e94b5ad..966344d 100644
--- a/third_party/BUILD.bazel
+++ b/third_party/BUILD.bazel
@@ -158,6 +158,7 @@
 
 ZLIB_COPTS = [
     "-Wno-unused-function",
+    "-Wno-deprecated-non-prototype",
     # Make the headers in contrib available, without exposing them in hdrs.
     "-isystem third_party/externals/zlib/",
 ] + select({
@@ -481,6 +482,7 @@
 })
 
 WEBP_COPTS = [
+    "-Wno-unused-but-set-variable",
     "-isystem third_party/externals/libwebp/",
 ] + select({
     "@platforms//cpu:x86_64": ["-msse4.1"],