SkPDF: do all rasterScale calculations in one place.

This is just clearer to me.

Change-Id: I4fb512cf70ceac39417d8d6020e707f4436ec209
Reviewed-on: https://skia-review.googlesource.com/153663
Commit-Queue: Hal Canary <halcanary@google.com>
Auto-Submit: Hal Canary <halcanary@google.com>
Reviewed-by: Leon Scroggins <scroggo@google.com>
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index eaf75e1..9852b05 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -546,25 +546,15 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-SkPDFDevice::SkPDFDevice(SkISize pageSize, SkPDFDocument* doc)
+SkPDFDevice::SkPDFDevice(SkISize pageSize, SkPDFDocument* doc, const SkMatrix& transform)
     : INHERITED(SkImageInfo::MakeUnknown(pageSize.width(), pageSize.height()),
                 SkSurfaceProps(0, kUnknown_SkPixelGeometry))
-    , fInitialTransform(SkMatrix::I())
+    , fInitialTransform(transform)
     , fDocument(doc)
 {
     SkASSERT(!pageSize.isEmpty());
 }
 
-void SkPDFDevice::setFlip() {
-    // Skia generally uses the top left as the origin but PDF
-    // natively has the origin at the bottom left. This matrix
-    // corrects for that.  But that only needs to be done once, we
-    // don't do it when layering.
-    SkScalar rasterScale = SkPDFUtils::kDpiForRasterScaleOne / fDocument->rasterDpi();
-    fInitialTransform.setConcat(SkMatrix::MakeScale(rasterScale, -rasterScale),
-                                SkMatrix::MakeTrans(0, -this->height()));
-}
-
 SkPDFDevice::~SkPDFDevice() = default;
 
 void SkPDFDevice::reset() {
diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h
index d02c671..9a916ed 100644
--- a/src/pdf/SkPDFDevice.h
+++ b/src/pdf/SkPDFDevice.h
@@ -52,14 +52,10 @@
      *         de-duplicating across pages (via the SkPDFCanon) and
      *         for early serializing of large immutable objects, such
      *         as images (via SkPDFDocument::serialize()).
+     *  @param initialTransform Transform to be applied to the entire page.
      */
-    SkPDFDevice(SkISize pageSize, SkPDFDocument* document);
-
-    /**
-     *  Apply a scale-and-translate transform to move the origin from the
-     *  bottom left (PDF default) to the top left (Skia default).
-     */
-    void setFlip();
+    SkPDFDevice(SkISize pageSize, SkPDFDocument* document,
+                const SkMatrix& initialTransform = SkMatrix::I());
 
     sk_sp<SkPDFDevice> makeCongruentDevice() {
         return sk_make_sp<SkPDFDevice>(this->imageInfo().dimensions(), fDocument);
diff --git a/src/pdf/SkPDFDocument.cpp b/src/pdf/SkPDFDocument.cpp
index 5fcdd88..74c78af 100644
--- a/src/pdf/SkPDFDocument.cpp
+++ b/src/pdf/SkPDFDocument.cpp
@@ -186,6 +186,11 @@
                              const SkDocument::PDFMetadata& metadata)
     : SkDocument(stream)
     , fMetadata(metadata) {
+    constexpr float kDpiForRasterScaleOne = 72.0f;
+    if (fMetadata.fRasterDPI != kDpiForRasterScaleOne) {
+        fInverseRasterScale = kDpiForRasterScaleOne / fMetadata.fRasterDPI;
+        fRasterScale        = fMetadata.fRasterDPI / kDpiForRasterScaleOne;
+    }
 }
 
 SkPDFDocument::~SkPDFDocument() {
@@ -198,6 +203,9 @@
     fObjectSerializer.serializeObjects(this->getStream());
 }
 
+static SkSize operator*(SkISize u, SkScalar s) { return SkSize{u.width() * s, u.height() * s}; }
+static SkSize operator*(SkSize u, SkScalar s) { return SkSize{u.width() * s, u.height() * s}; }
+
 SkCanvas* SkPDFDocument::onBeginPage(SkScalar width, SkScalar height) {
     SkASSERT(fCanvas.imageInfo().dimensions().isZero());
     if (fPages.empty()) {
@@ -217,22 +225,22 @@
             fObjectSerializer.serializeObjects(this->getStream());
         }
     }
-    SkScalar rasterScale = this->rasterDpi() / SkPDFUtils::kDpiForRasterScaleOne;
-    SkISize pageSize = {SkScalarRoundToInt(width  * rasterScale),
-                        SkScalarRoundToInt(height * rasterScale)};
-
-    fPageDevice = sk_make_sp<SkPDFDevice>(pageSize, this);
-    fPageDevice->setFlip();  // Only the top-level device needs to be flipped.
+    // By scaling the page at the device level, we will create bitmap layer
+    // devices at the rasterized scale, not the 72dpi scale.  Bitmap layer
+    // devices are created when saveLayer is called with an ImageFilter;  see
+    // SkPDFDevice::onCreateDevice().
+    SkISize pageSize = (SkSize{width, height} * fRasterScale).toRound();
+    SkMatrix initialTransform;
+    // Skia uses the top left as the origin but PDF natively has the origin at the
+    // bottom left. This matrix corrects for that, as well as the raster scale.
+    initialTransform.setScaleTranslate(fInverseRasterScale, -fInverseRasterScale,
+                                       0, fInverseRasterScale * pageSize.height());
+    fPageDevice = sk_make_sp<SkPDFDevice>(pageSize, this, initialTransform);
     reset_object(&fCanvas, fPageDevice);
-    fCanvas.scale(rasterScale, rasterScale);
+    fCanvas.scale(fRasterScale, fRasterScale);
     return &fCanvas;
 }
 
-static sk_sp<SkPDFArray> calculate_page_size(SkScalar rasterDpi, SkISize size) {
-    SkScalar scale = SkPDFUtils::kDpiForRasterScaleOne / rasterDpi;
-    return SkPDFUtils::RectToArray({0, 0, size.width() * scale, size.height() * scale});
-}
-
 void SkPDFDocument::onEndPage() {
     SkASSERT(!fCanvas.imageInfo().dimensions().isZero());
     fCanvas.flush();
@@ -241,7 +249,7 @@
 
     auto page = sk_make_sp<SkPDFDict>("Page");
 
-    SkISize pageSize = fPageDevice->imageInfo().dimensions();
+    SkSize mediaSize = fPageDevice->imageInfo().dimensions() * fInverseRasterScale;
     auto contentObject = sk_make_sp<SkPDFStream>(fPageDevice->content());
     auto resourceDict = fPageDevice->makeResourceDict();
     auto annotations = fPageDevice->getAnnotations();
@@ -249,7 +257,8 @@
     fPageDevice = nullptr;
 
     page->insertObject("Resources", resourceDict);
-    page->insertObject("MediaBox", calculate_page_size(this->rasterDpi(), pageSize));
+    page->insertObject("MediaBox", SkPDFUtils::RectToArray(SkRect::MakeSize(mediaSize)));
+
     if (annotations) {
         page->insertObject("Annots", std::move(annotations));
     }
@@ -273,6 +282,8 @@
     fID = nullptr;
     fXMP = nullptr;
     fMetadata = SkDocument::PDFMetadata();
+    fRasterScale = 1;
+    fInverseRasterScale = 1;
 }
 
 static sk_sp<SkData> SkSrgbIcm() {
diff --git a/src/pdf/SkPDFDocument.h b/src/pdf/SkPDFDocument.h
index 2d7be50..e8df1f5 100644
--- a/src/pdf/SkPDFDocument.h
+++ b/src/pdf/SkPDFDocument.h
@@ -75,7 +75,6 @@
      */
     void serialize(const sk_sp<SkPDFObject>&);
     SkPDFCanon* canon() { return &fCanon; }
-    SkScalar rasterDpi() const { return fMetadata.fRasterDPI; }
     void registerFont(SkPDFFont* f) { fFonts.add(f); }
     const PDFMetadata& metadata() const { return fMetadata; }
 
@@ -90,6 +89,8 @@
     sk_sp<SkPDFObject> fID;
     sk_sp<SkPDFObject> fXMP;
     SkDocument::PDFMetadata fMetadata;
+    SkScalar fRasterScale = 1;
+    SkScalar fInverseRasterScale = 1;
 
     void reset();
 };
diff --git a/src/pdf/SkPDFUtils.h b/src/pdf/SkPDFUtils.h
index a05b52b..325245b 100644
--- a/src/pdf/SkPDFUtils.h
+++ b/src/pdf/SkPDFUtils.h
@@ -42,8 +42,6 @@
 
 namespace SkPDFUtils {
 
-constexpr float kDpiForRasterScaleOne = 72.0f;
-
 sk_sp<SkPDFArray> RectToArray(const SkRect& rect);
 sk_sp<SkPDFArray> MatrixToArray(const SkMatrix& matrix);
 void AppendTransform(const SkMatrix& matrix, SkWStream* content);