SkPDF: elimate old IMAGE_STATS, de-dupe image code.

  - remove SkPDFDict::emitAll()
  - all stream serialization moved into SkPDFDocument.
  - SkPDFDocument::endObject() and ::beginOject() now private.

Change-Id: I4d8a5643027f859e1c0307a379c74859faae0d06
Reviewed-on: https://skia-review.googlesource.com/c/180370
Commit-Queue: Hal Canary <halcanary@google.com>
Reviewed-by: Herb Derby <herb@google.com>
diff --git a/src/pdf/SkPDFBitmap.cpp b/src/pdf/SkPDFBitmap.cpp
index 4f7ae95..e254156 100644
--- a/src/pdf/SkPDFBitmap.cpp
+++ b/src/pdf/SkPDFBitmap.cpp
@@ -65,37 +65,40 @@
                  : SK_ColorTRANSPARENT;
 }
 
-static void emit_stream(SkDynamicMemoryWStream* src, SkWStream* dst) {
-    dst->writeText(" stream\n");
-    src->writeToAndReset(dst);
-    dst->writeText("\nendstream");
-}
-
-static void emit_dict(SkWStream* stream, SkISize size, const char* colorSpace,
-                      const SkPDFIndirectReference* smask, int length) {
+template <typename T>
+static void emit_image_stream(SkPDFDocument* doc,
+                              SkPDFIndirectReference ref,
+                              T writeStream,
+                              SkISize size,
+                              const char* colorSpace,
+                              SkPDFIndirectReference sMask,
+                              int length,
+                              bool isJpeg) {
     SkPDFDict pdfDict("XObject");
     pdfDict.insertName("Subtype", "Image");
     pdfDict.insertInt("Width", size.width());
     pdfDict.insertInt("Height", size.height());
     pdfDict.insertName("ColorSpace", colorSpace);
-    if (smask) {
-        pdfDict.insertRef("SMask", *smask);
+    if (sMask) {
+        pdfDict.insertRef("SMask", sMask);
     }
     pdfDict.insertInt("BitsPerComponent", 8);
     #ifdef SK_PDF_BASE85_BINARY
     auto filters = SkPDFMakeArray();
     filters->appendName("ASCII85Decode");
-    filters->appendName("FlateDecode");
+    filters->appendName(isJpeg ? "DCTDecode" : "FlateDecode");
     pdfDict.insertObject("Filter", std::move(filters));
     #else
-    pdfDict.insertName("Filter", "FlateDecode");
+    pdfDict.insertName("Filter", isJpeg ? "DCTDecode" : "FlateDecode");
     #endif
+    if (isJpeg) {
+        pdfDict.insertInt("ColorTransform", 0);
+    }
     pdfDict.insertInt("Length", length);
-    pdfDict.emitObject(stream);
+    doc->emitStream(pdfDict, std::move(writeStream), ref);
 }
 
-static SkPDFIndirectReference do_deflated_alpha(const SkPixmap& pm, SkPDFDocument* doc,
-                                                SkPDFIndirectReference ref) {
+static void do_deflated_alpha(const SkPixmap& pm, SkPDFDocument* doc, SkPDFIndirectReference ref) {
     SkDynamicMemoryWStream buffer;
     SkDeflateWStream deflateWStream(&buffer);
     if (kAlpha_8_SkColorType == pm.colorType()) {
@@ -125,17 +128,16 @@
     #ifdef SK_PDF_BASE85_BINARY
     SkPDFUtils::Base85Encode(buffer.detachAsStream(), &buffer);
     #endif
-    SkWStream* stream = doc->beginObject(ref);
-    emit_dict(stream, pm.info().dimensions(), "DeviceGray", nullptr, buffer.bytesWritten());
-    emit_stream(&buffer, stream);
-    doc->endObject();
-    return ref;
+    int length = SkToInt(buffer.bytesWritten());
+    emit_image_stream(doc, ref, [&buffer](SkWStream* stream) { buffer.writeToAndReset(stream); },
+                      pm.info().dimensions(), "DeviceGray", SkPDFIndirectReference(),
+                      length, false);
 }
 
-static void  do_deflated_image(const SkPixmap& pm,
-                               SkPDFDocument* doc,
-                               bool isOpaque,
-                               SkPDFIndirectReference ref) {
+static void do_deflated_image(const SkPixmap& pm,
+                              SkPDFDocument* doc,
+                              bool isOpaque,
+                              SkPDFIndirectReference ref) {
     SkPDFIndirectReference sMask;
     if (!isOpaque) {
         sMask = doc->reserveRef();
@@ -183,23 +185,20 @@
     #ifdef SK_PDF_BASE85_BINARY
     SkPDFUtils::Base85Encode(buffer.detachAsStream(), &buffer);
     #endif
-    SkWStream* stream = doc->beginObject(ref);
-    emit_dict(stream, pm.info().dimensions(), colorSpace,
-              sMask.fValue != -1 ? &sMask : nullptr,
-              buffer.bytesWritten());
-    emit_stream(&buffer, stream);
-    doc->endObject();
+    int length = SkToInt(buffer.bytesWritten());
+    emit_image_stream(doc, ref, [&buffer](SkWStream* stream) { buffer.writeToAndReset(stream); },
+                      pm.info().dimensions(), colorSpace, sMask, length, false);
     if (!isOpaque) {
         do_deflated_alpha(pm, doc, sMask);
     }
 }
 
-static bool do_jpeg(const SkData& data, SkPDFDocument* doc, SkISize size,
+static bool do_jpeg(sk_sp<SkData> data, SkPDFDocument* doc, SkISize size,
                     SkPDFIndirectReference ref) {
     SkISize jpegSize;
     SkEncodedInfo::Color jpegColorType;
     SkEncodedOrigin exifOrientation;
-    if (!SkGetJpegInfo(data.data(), data.size(), &jpegSize,
+    if (!SkGetJpegInfo(data->data(), data->size(), &jpegSize,
                        &jpegColorType, &exifOrientation)) {
         return false;
     }
@@ -210,48 +209,16 @@
             || kTopLeft_SkEncodedOrigin != exifOrientation) {
         return false;
     }
-    #ifdef SK_PDF_IMAGE_STATS
-    gJpegImageObjects.fetch_add(1);
-    #endif
-
     #ifdef SK_PDF_BASE85_BINARY
     SkDynamicMemoryWStream buffer;
-    SkPDFUtils::Base85Encode(SkMemoryStream::MakeDirect(data.data(), data.size()), &buffer);
-    int length = SkToInt(buffer.bytesWritten());
-    #else
-    int length = SkToInt(data.size());
+    SkPDFUtils::Base85Encode(SkMemoryStream::MakeDirect(data->data(), data->size()), &buffer);
+    data = buffer.detachAsData();
     #endif
-    SkPDFDict pdfDict("XObject");
-    pdfDict.insertName("Subtype", "Image");
-    pdfDict.insertInt("Width", jpegSize.width());
-    pdfDict.insertInt("Height", jpegSize.height());
-    if (yuv) {
-        pdfDict.insertName("ColorSpace", "DeviceRGB");
-    } else {
-        pdfDict.insertName("ColorSpace", "DeviceGray");
-    }
-    pdfDict.insertInt("BitsPerComponent", 8);
-    #ifdef SK_PDF_BASE85_BINARY
-    auto filters = SkPDFMakeArray();
-    filters->appendName("ASCII85Decode");
-    filters->appendName("DCTDecode");
-    pdfDict.insertObject("Filter", std::move(filters));
-    #else
-    pdfDict.insertName("Filter", "DCTDecode");
-    #endif
-    pdfDict.insertInt("ColorTransform", 0);
-    pdfDict.insertInt("Length", length);
 
-    SkWStream* stream = doc->beginObject(ref);
-    pdfDict.emitObject(stream);
-    stream->writeText(" stream\n");
-    #ifdef SK_PDF_BASE85_BINARY
-    buffer.writeToAndReset(stream);
-    #else
-    stream->write(data.data(), data.size());
-    #endif
-    stream->writeText("\nendstream");
-    doc->endObject();
+    emit_image_stream(doc, ref,
+                      [&data](SkWStream* dst) { dst->write(data->data(), data->size()); },
+                      jpegSize, yuv ? "DeviceRGB" : "DeviceGray",
+                      SkPDFIndirectReference(), SkToInt(data->size()), true);
     return true;
 }
 
@@ -287,7 +254,7 @@
     SkASSERT(encodingQuality >= 0);
     SkISize dimensions = img->dimensions();
     sk_sp<SkData> data = img->refEncodedData();
-    if (data && do_jpeg(*data, doc, dimensions, ref)) {
+    if (data && do_jpeg(std::move(data), doc, dimensions, ref)) {
         return;
     }
     SkBitmap bm = to_pixels(img);
@@ -295,7 +262,7 @@
     bool isOpaque = pm.isOpaque() || pm.computeIsOpaque();
     if (encodingQuality <= 100 && isOpaque) {
         sk_sp<SkData> data = img->encodeToData(SkEncodedImageFormat::kJPEG, encodingQuality);
-        if (data && do_jpeg(*data, doc, dimensions, ref)) {
+        if (data && do_jpeg(std::move(data), doc, dimensions, ref)) {
             return;
         }
     }