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);