diff --git a/include/pdf/SkPDFDevice.h b/include/pdf/SkPDFDevice.h index 5bcc8e3d36..f9247a7122 100644 --- a/include/pdf/SkPDFDevice.h +++ b/include/pdf/SkPDFDevice.h @@ -42,12 +42,24 @@ class SkPDFDeviceFactory : public SkDeviceFactory { */ class SkPDFDevice : public SkDevice { public: + /** Skia generally uses the top left as the origin and PDFs natively use + the bottom left. We can move the origin to the top left in the PDF + with a transform, but we have to be careful to apply the transform + only once. + */ + enum OriginTransform { + kFlip_OriginTransform, + kNoFlip_OriginTransform, + }; + /** Create a PDF drawing context with the given width and height. * 72 points/in means letter paper is 612x792. * @param width Page width in points. * @param height Page height in points. + * @param flipOrigin Flip the origin from lower left to upper left. */ - SkPDFDevice(int width, int height); + SkPDFDevice(int width, int height, + OriginTransform flipOrigin = kFlip_OriginTransform); virtual ~SkPDFDevice(); virtual SkDeviceFactory* getDeviceFactory() { @@ -121,13 +133,13 @@ public: SkRefPtr getMediaBox() const; /** Returns a string with the page contents. - * @param flipOrigin Flip the origin between top and bottom. */ - SkString content(bool flipOrigin) const; + SkString content() const; private: int fWidth; int fHeight; + OriginTransform fFlipOrigin; SkRefPtr fResourceDict; SkTDArray fGraphicStateResources; diff --git a/include/pdf/SkPDFFormXObject.h b/include/pdf/SkPDFFormXObject.h index ed1656680b..41719f0820 100644 --- a/include/pdf/SkPDFFormXObject.h +++ b/include/pdf/SkPDFFormXObject.h @@ -28,7 +28,7 @@ class SkPDFCatalog; /** \class SkPDFFormXObject - A form XObject; a self containted description of graphics objects. A form + A form XObject; a self contained description of graphics objects. A form XObject is basically a page object with slightly different syntax, that can be drawn onto a page. */ diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index 72b2e1bf6a..1c6477f9ba 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -120,8 +120,12 @@ void alignText(SkDrawCacheProc glyphCacheProc, const SkPaint& paint, SkDevice* SkPDFDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config, int width, int height, bool isOpaque, - bool /*isForLayer*/) { - return SkNEW_ARGS(SkPDFDevice, (width, height)); + bool isForLayer) { + SkPDFDevice::OriginTransform flip = SkPDFDevice::kFlip_OriginTransform; + if (isForLayer) { + flip = SkPDFDevice::kNoFlip_OriginTransform; + } + return SkNEW_ARGS(SkPDFDevice, (width, height, flip)); } static inline SkBitmap makeABitmap(int width, int height) { @@ -130,10 +134,11 @@ static inline SkBitmap makeABitmap(int width, int height) { return bitmap; } -SkPDFDevice::SkPDFDevice(int width, int height) +SkPDFDevice::SkPDFDevice(int width, int height, OriginTransform flipOrigin) : SkDevice(NULL, makeABitmap(width, height), false), fWidth(width), fHeight(height), + fFlipOrigin(flipOrigin), fGraphicStackIndex(0) { fGraphicStack[0].fColor = SK_ColorBLACK; fGraphicStack[0].fTextSize = SK_ScalarNaN; // This has no default value. @@ -143,6 +148,10 @@ SkPDFDevice::SkPDFDevice(int width, int height) fGraphicStack[0].fGraphicState = NULL; fGraphicStack[0].fClip.setRect(0,0, width, height); fGraphicStack[0].fTransform.reset(); + + if (flipOrigin == kFlip_OriginTransform) { + fContent.printf("1 0 0 -1 0 %d cm\n", fHeight); + } } SkPDFDevice::~SkPDFDevice() { @@ -549,13 +558,8 @@ SkRefPtr SkPDFDevice::getMediaBox() const { return mediaBox; } -SkString SkPDFDevice::content(bool flipOrigin) const { - SkString result; - // Scale and translate to move the origin from the lower left to the - // upper left. - if (flipOrigin) - result.printf("1 0 0 -1 0 %d cm\n", fHeight); - result.append(fContent); +SkString SkPDFDevice::content() const { + SkString result = fContent; for (int i = 0; i < fGraphicStackIndex; i++) result.append("Q\n"); return result; diff --git a/src/pdf/SkPDFFormXObject.cpp b/src/pdf/SkPDFFormXObject.cpp index ef839a3b4e..40bfad74e3 100644 --- a/src/pdf/SkPDFFormXObject.cpp +++ b/src/pdf/SkPDFFormXObject.cpp @@ -28,7 +28,7 @@ SkPDFFormXObject::SkPDFFormXObject(SkPDFDevice* device) { // resources). device->getResources(&fResources); - SkString content = device->content(false); + SkString content = device->content(); SkMemoryStream* stream_data = new SkMemoryStream(content.c_str(), content.size()); SkAutoUnref stream_data_unref(stream_data); diff --git a/src/pdf/SkPDFPage.cpp b/src/pdf/SkPDFPage.cpp index 1c470c7d01..2bec90744e 100644 --- a/src/pdf/SkPDFPage.cpp +++ b/src/pdf/SkPDFPage.cpp @@ -32,7 +32,7 @@ void SkPDFPage::finalizePage(SkPDFCatalog* catalog, bool firstPage, insert("Resources", fDevice->getResourceDict().get()); insert("MediaBox", fDevice->getMediaBox().get()); - fContent = fDevice->content(true); + fContent = fDevice->content(); SkRefPtr contentStream = new SkMemoryStream( fContent.c_str(), fContent.size()); contentStream->unref(); // SkRefPtr and new both took a reference.