aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar halcanary <halcanary@google.com>2015-02-20 06:17:26 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-02-20 06:17:26 -0800
commita1f1ee98a1f6d0770f6243270ca2f0e6c92efaba (patch)
tree427609a03b889602589a698834b96ea0035e6e8a
parent07d5947b886bef06621e830e9f8bf253f9bad703 (diff)
PDF : New factory function for SkPDFDevice
SkPDFDevice now has factory function that matches what callers need. Review URL: https://codereview.chromium.org/941023005
-rw-r--r--src/doc/SkDocument_PDF.cpp55
-rw-r--r--src/pdf/SkPDFCanon.h9
-rw-r--r--src/pdf/SkPDFDevice.cpp97
-rw-r--r--src/pdf/SkPDFDevice.h81
-rw-r--r--src/pdf/SkPDFShader.cpp18
-rw-r--r--tests/AnnotationTest.cpp19
-rw-r--r--tests/CanvasTest.cpp9
-rw-r--r--tests/PDFPrimitivesTest.cpp11
8 files changed, 131 insertions, 168 deletions
diff --git a/src/doc/SkDocument_PDF.cpp b/src/doc/SkDocument_PDF.cpp
index 6d6bf63526..e73b88867f 100644
--- a/src/doc/SkDocument_PDF.cpp
+++ b/src/doc/SkDocument_PDF.cpp
@@ -6,6 +6,7 @@
*/
#include "SkDocument.h"
+#include "SkPDFCanon.h"
#include "SkPDFDocument.h"
#include "SkPDFDevice.h"
@@ -16,8 +17,6 @@ public:
SkScalar rasterDpi)
: SkDocument(stream, doneProc)
, fDoc(SkNEW(SkPDFDocument))
- , fDevice(NULL)
- , fCanvas(NULL)
, fRasterDpi(rasterDpi) {}
virtual ~SkDocument_PDF() {
@@ -28,56 +27,50 @@ public:
protected:
virtual SkCanvas* onBeginPage(SkScalar width, SkScalar height,
const SkRect& trimBox) SK_OVERRIDE {
- SkASSERT(NULL == fCanvas);
- SkASSERT(NULL == fDevice);
+ SkASSERT(!fCanvas.get());
+ SkASSERT(!fDevice.get());
- SkISize mediaBoxSize;
- mediaBoxSize.set(SkScalarRoundToInt(width), SkScalarRoundToInt(height));
-
- fDevice = SkNEW_ARGS(SkPDFDevice, (mediaBoxSize, mediaBoxSize, SkMatrix::I()));
- if (fRasterDpi != 0) {
- fDevice->setRasterDpi(fRasterDpi);
- }
- fCanvas = SkNEW_ARGS(SkCanvas, (fDevice));
+ SkISize pageSize = SkISize::Make(
+ SkScalarRoundToInt(width), SkScalarRoundToInt(height));
+ fDevice.reset(SkPDFDevice::Create(pageSize, fRasterDpi, &fCanon));
+ fCanvas.reset(SkNEW_ARGS(SkCanvas, (fDevice)));
fCanvas->clipRect(trimBox);
fCanvas->translate(trimBox.x(), trimBox.y());
- return fCanvas;
+ return fCanvas.get();
}
void onEndPage() SK_OVERRIDE {
- SkASSERT(fCanvas);
- SkASSERT(fDevice);
+ SkASSERT(fCanvas.get());
+ SkASSERT(fDevice.get());
fCanvas->flush();
- fDoc->appendPage(fDevice);
-
- fCanvas->unref();
- fDevice->unref();
+ fDoc->appendPage(fDevice.get());
- fCanvas = NULL;
- fDevice = NULL;
+ fCanvas.reset(NULL);
+ fDevice.reset(NULL);
}
bool onClose(SkWStream* stream) SK_OVERRIDE {
- SkASSERT(NULL == fCanvas);
- SkASSERT(NULL == fDevice);
+ SkASSERT(!fCanvas.get());
+ SkASSERT(!fDevice.get());
bool success = fDoc->emitPDF(stream);
- SkDELETE(fDoc);
- fDoc = NULL;
+ fDoc.free();
+ SkDEBUGCODE(fCanon.assertEmpty());
return success;
}
void onAbort() SK_OVERRIDE {
- SkDELETE(fDoc);
- fDoc = NULL;
+ fDoc.free();
+ SkDEBUGCODE(fCanon.assertEmpty());
}
private:
- SkPDFDocument* fDoc;
- SkPDFDevice* fDevice;
- SkCanvas* fCanvas;
- SkScalar fRasterDpi;
+ SkPDFCanon fCanon;
+ SkAutoTDelete<SkPDFDocument> fDoc;
+ SkAutoTUnref<SkPDFDevice> fDevice;
+ SkAutoTUnref<SkCanvas> fCanvas;
+ SkScalar fRasterDpi;
};
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/pdf/SkPDFCanon.h b/src/pdf/SkPDFCanon.h
index 6a677e9a68..7c5cdf70c1 100644
--- a/src/pdf/SkPDFCanon.h
+++ b/src/pdf/SkPDFCanon.h
@@ -73,6 +73,15 @@ public:
void addBitmap(SkPDFBitmap*);
void removeBitmap(SkPDFBitmap*);
+ void assertEmpty() const {
+ SkASSERT(fFontRecords.isEmpty());
+ SkASSERT(fFunctionShaderRecords.isEmpty());
+ SkASSERT(fAlphaShaderRecords.isEmpty());
+ SkASSERT(fImageShaderRecords.isEmpty());
+ SkASSERT(fGraphicStateRecords.isEmpty());
+ SkASSERT(fBitmapRecords.isEmpty());
+ }
+
private:
struct FontRec {
SkPDFFont* fFont;
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index 329d0971dd..7c0aaa280e 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -575,11 +575,8 @@ SkBaseDevice* SkPDFDevice::onCreateCompatibleDevice(const CreateInfo& cinfo) {
if (kImageFilter_Usage == cinfo.fUsage) {
return SkBitmapDevice::Create(cinfo.fInfo);
}
-
- SkMatrix initialTransform;
- initialTransform.reset();
SkISize size = SkISize::Make(cinfo.fInfo.width(), cinfo.fInfo.height());
- return SkNEW_ARGS(SkPDFDevice, (size, size, initialTransform));
+ return SkPDFDevice::Create(size, fRasterDpi, fCanon);
}
@@ -695,76 +692,36 @@ private:
////////////////////////////////////////////////////////////////////////////////
-static inline SkImageInfo make_content_info(const SkISize& contentSize,
- const SkMatrix* initialTransform) {
- SkImageInfo info;
- if (initialTransform) {
- // Compute the size of the drawing area.
- SkVector drawingSize;
- SkMatrix inverse;
- drawingSize.set(SkIntToScalar(contentSize.fWidth),
- SkIntToScalar(contentSize.fHeight));
- if (!initialTransform->invert(&inverse)) {
- // This shouldn't happen, initial transform should be invertible.
- SkASSERT(false);
- inverse.reset();
- }
- inverse.mapVectors(&drawingSize, 1);
- SkISize size = SkSize::Make(drawingSize.fX, drawingSize.fY).toRound();
- info = SkImageInfo::MakeUnknown(abs(size.fWidth), abs(size.fHeight));
- } else {
- info = SkImageInfo::MakeUnknown(abs(contentSize.fWidth),
- abs(contentSize.fHeight));
- }
- return info;
-}
-
-// TODO(vandebo) change pageSize to SkSize.
-SkPDFDevice::SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize,
- const SkMatrix& initialTransform)
+SkPDFDevice::SkPDFDevice(SkISize pageSize,
+ SkScalar rasterDpi,
+ SkPDFCanon* canon,
+ bool flip)
: fPageSize(pageSize)
- , fContentSize(contentSize)
+ , fContentSize(pageSize)
+ , fExistingClipRegion(SkIRect::MakeSize(pageSize))
+ , fAnnotations(NULL)
+ , fResourceDict(NULL)
, fLastContentEntry(NULL)
, fLastMarginContentEntry(NULL)
+ , fDrawingArea(kContent_DrawingArea)
, fClipStack(NULL)
- , fRasterDpi(72.0f)
-{
- const SkImageInfo info = make_content_info(contentSize, &initialTransform);
-
- // Just report that PDF does not supports perspective in the
- // initial transform.
- NOT_IMPLEMENTED(initialTransform.hasPerspective(), true);
-
- // 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.
- fInitialTransform.setTranslate(0, SkIntToScalar(pageSize.fHeight));
- fInitialTransform.preScale(SK_Scalar1, -SK_Scalar1);
- fInitialTransform.preConcat(initialTransform);
- fLegacyBitmap.setInfo(info);
-
- SkIRect existingClip = info.bounds();
- fExistingClipRegion.setRect(existingClip);
- this->init();
-}
-
-// TODO(vandebo) change layerSize to SkSize.
-SkPDFDevice::SkPDFDevice(const SkISize& layerSize,
- const SkClipStack& existingClipStack,
- const SkRegion& existingClipRegion)
- : fPageSize(layerSize)
- , fContentSize(layerSize)
- , fExistingClipStack(existingClipStack)
- , fExistingClipRegion(existingClipRegion)
- , fLastContentEntry(NULL)
- , fLastMarginContentEntry(NULL)
- , fClipStack(NULL)
- , fRasterDpi(72.0f)
-{
- fInitialTransform.reset();
- fLegacyBitmap.setInfo(make_content_info(layerSize, NULL));
-
- this->init();
+ , fFontGlyphUsage(SkNEW(SkPDFGlyphSetMap))
+ , fRasterDpi(rasterDpi)
+ , fCanon(canon) {
+ SkASSERT(pageSize.width() > 0);
+ SkASSERT(pageSize.height() > 0);
+ fLegacyBitmap.setInfo(
+ SkImageInfo::MakeUnknown(pageSize.width(), pageSize.height()));
+ if (flip) {
+ // 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.
+ fInitialTransform.setTranslate(0, SkIntToScalar(pageSize.fHeight));
+ fInitialTransform.preScale(SK_Scalar1, -SK_Scalar1);
+ } else {
+ fInitialTransform.setIdentity();
+ }
}
SkPDFDevice::~SkPDFDevice() {
diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h
index 4c0f752405..fc4f208f48 100644
--- a/src/pdf/SkPDFDevice.h
+++ b/src/pdf/SkPDFDevice.h
@@ -23,6 +23,7 @@
#include "SkTemplates.h"
class SkPDFArray;
+class SkPDFCanon;
class SkPDFDevice;
class SkPDFDict;
class SkPDFFont;
@@ -47,28 +48,37 @@ struct NamedDestination;
*/
class SkPDFDevice : public SkBaseDevice {
public:
- /** Create a PDF drawing context with the given width and height.
- * 72 points/in means letter paper is 612x792.
- * @param pageSize Page size in points.
- * @param contentSize The content size of the page in points. This will be
- * combined with the initial transform to determine the drawing area
- * (as reported by the width and height methods). Anything outside
- * of the drawing area will be clipped.
- * @param initialTransform The initial transform to apply to the page.
- * This may be useful to, for example, move the origin in and
- * over a bit to account for a margin, scale the canvas,
- * or apply a rotation. Note1: the SkPDFDevice also applies
- * a scale+translate transform to move the origin from the
- * bottom left (PDF default) to the top left. Note2: drawDevice
- * (used by layer restore) draws the device after this initial
- * transform is applied, so the PDF device does an
- * inverse scale+translate to accommodate the one that SkPDFDevice
- * always does.
+ /** Create a PDF drawing context. SkPDFDevice applies a
+ * scale-and-translate transform to move the origin from the
+ * bottom left (PDF default) to the top left (Skia default).
+ * @param pageSize Page size in point units.
+ * 1 point == 127/360 mm == 1/72 inch
+ * @param rasterDpi the DPI at which features without native PDF
+ * support will be rasterized (e.g. draw image with
+ * perspective, draw text with perspective, ...). A
+ * larger DPI would create a PDF that reflects the
+ * original intent with better fidelity, but it can make
+ * for larger PDF files too, which would use more memory
+ * while rendering, and it would be slower to be processed
+ * or sent online or to printer. A good choice is
+ * SK_ScalarDefaultRasterDPI(72.0f).
+ * @param SkPDFCanon. Should be non-null, and shared by all
+ * devices in a document.
*/
- // Deprecated, please use SkDocument::CreatePdf() instead.
- SK_API SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize,
- const SkMatrix& initialTransform);
- SK_API virtual ~SkPDFDevice();
+ static SkPDFDevice* Create(SkISize pageSize,
+ SkScalar rasterDpi,
+ SkPDFCanon* canon) {
+ return SkNEW_ARGS(SkPDFDevice, (pageSize, rasterDpi, canon, true));
+ }
+
+ /** Create a PDF drawing context without fipping the y-axis. */
+ static SkPDFDevice* CreateUnflipped(SkISize pageSize,
+ SkScalar rasterDpi,
+ SkPDFCanon* canon) {
+ return SkNEW_ARGS(SkPDFDevice, (pageSize, rasterDpi, canon, false));
+ }
+
+ virtual ~SkPDFDevice();
/** These are called inside the per-device-layer loop for each draw call.
When these are called, we have already applied any saveLayer operations,
@@ -173,21 +183,6 @@ public:
return *(fFontGlyphUsage.get());
}
-
- /**
- * rasterDpi - the DPI at which features without native PDF support
- * will be rasterized (e.g. draw image with perspective,
- * draw text with perspective, ...)
- * A larger DPI would create a PDF that reflects the original
- * intent with better fidelity, but it can make for larger
- * PDF files too, which would use more memory while rendering,
- * and it would be slower to be processed or sent online or
- * to printer.
- */
- void setRasterDpi(SkScalar rasterDpi) {
- fRasterDpi = rasterDpi;
- }
-
protected:
const SkBitmap& onAccessBitmap() SK_OVERRIDE {
return fLegacyBitmap;
@@ -224,8 +219,6 @@ private:
// Accessor and setter functions based on the current DrawingArea.
SkAutoTDelete<ContentEntry>* getContentEntries();
- ContentEntry* getLastContentEntry();
- void setLastContentEntry(ContentEntry* contentEntry);
// Glyph ids used for each font on this device.
SkAutoTDelete<SkPDFGlyphSetMap> fFontGlyphUsage;
@@ -234,8 +227,16 @@ private:
SkBitmap fLegacyBitmap;
- SkPDFDevice(const SkISize& layerSize, const SkClipStack& existingClipStack,
- const SkRegion& existingClipRegion);
+ SkPDFCanon* fCanon; // Owned by SkDocument_PDF
+ ////////////////////////////////////////////////////////////////////////////
+
+ SkPDFDevice(SkISize pageSize,
+ SkScalar rasterDpi,
+ SkPDFCanon* canon,
+ bool flip);
+
+ ContentEntry* getLastContentEntry();
+ void setLastContentEntry(ContentEntry* contentEntry);
// override from SkBaseDevice
SkBaseDevice* onCreateCompatibleDevice(const CreateInfo&) SK_OVERRIDE;
diff --git a/src/pdf/SkPDFShader.cpp b/src/pdf/SkPDFShader.cpp
index e9283bc275..979ef3faea 100644
--- a/src/pdf/SkPDFShader.cpp
+++ b/src/pdf/SkPDFShader.cpp
@@ -942,15 +942,11 @@ SkPDFImageShader* SkPDFImageShader::Create(
deviceBounds.join(bitmapBounds);
}
- SkMatrix unflip;
- unflip.setTranslate(0, SkScalarRoundToScalar(deviceBounds.height()));
- unflip.preScale(SK_Scalar1, -SK_Scalar1);
SkISize size = SkISize::Make(SkScalarRoundToInt(deviceBounds.width()),
SkScalarRoundToInt(deviceBounds.height()));
- // TODO(edisonn): should we pass here the DCT encoder of the destination device?
- // TODO(edisonn): NYI Perspective, use SkPDFDeviceFlattener.
- SkPDFDevice pattern(size, size, unflip);
- SkCanvas canvas(&pattern);
+ SkAutoTUnref<SkPDFDevice> patternDevice(
+ SkPDFDevice::CreateUnflipped(size, 72.0f, NULL));
+ SkCanvas canvas(patternDevice.get());
SkRect patternBBox;
image->getBounds(&patternBBox);
@@ -1108,14 +1104,16 @@ SkPDFImageShader* SkPDFImageShader::Create(
}
// Put the canvas into the pattern stream (fContent).
- SkAutoTDelete<SkStream> content(pattern.content());
+ SkAutoTDelete<SkStream> content(patternDevice->content());
SkPDFImageShader* imageShader =
SkNEW_ARGS(SkPDFImageShader, (autoState->detach()));
imageShader->setData(content.get());
- populate_tiling_pattern_dict(imageShader, patternBBox,
- pattern.getResourceDict(), finalMatrix);
+ populate_tiling_pattern_dict(imageShader,
+ patternBBox,
+ patternDevice->getResourceDict(),
+ finalMatrix);
imageShader->fShaderState->fImage.unlockPixels();
diff --git a/tests/AnnotationTest.cpp b/tests/AnnotationTest.cpp
index 0ba3af9e9b..fc762b1493 100644
--- a/tests/AnnotationTest.cpp
+++ b/tests/AnnotationTest.cpp
@@ -8,6 +8,7 @@
#include "SkAnnotation.h"
#include "SkCanvas.h"
#include "SkData.h"
+#include "SkPDFCanon.h"
#include "SkPDFDevice.h"
#include "SkPDFDocument.h"
#include "Test.h"
@@ -41,10 +42,9 @@ DEF_TEST(Annotation_NoDraw, reporter) {
DEF_TEST(Annotation_PdfLink, reporter) {
SkISize size = SkISize::Make(612, 792);
- SkMatrix initialTransform;
- initialTransform.reset();
- SkPDFDevice device(size, size, initialTransform);
- SkCanvas canvas(&device);
+ SkPDFCanon canon;
+ SkAutoTUnref<SkPDFDevice> device(SkPDFDevice::Create(size, 72.0f, &canon));
+ SkCanvas canvas(device.get());
SkRect r = SkRect::MakeXYWH(SkIntToScalar(72), SkIntToScalar(72),
SkIntToScalar(288), SkIntToScalar(72));
@@ -52,7 +52,7 @@ DEF_TEST(Annotation_PdfLink, reporter) {
SkAnnotateRectWithURL(&canvas, r, data.get());
SkPDFDocument doc;
- doc.appendPage(&device);
+ doc.appendPage(device.get());
SkDynamicMemoryWStream outStream;
doc.emitPDF(&outStream);
SkAutoDataUnref out(outStream.copyToData());
@@ -63,17 +63,16 @@ DEF_TEST(Annotation_PdfLink, reporter) {
DEF_TEST(Annotation_NamedDestination, reporter) {
SkISize size = SkISize::Make(612, 792);
- SkMatrix initialTransform;
- initialTransform.reset();
- SkPDFDevice device(size, size, initialTransform);
- SkCanvas canvas(&device);
+ SkPDFCanon canon;
+ SkAutoTUnref<SkPDFDevice> device(SkPDFDevice::Create(size, 72.0f, &canon));
+ SkCanvas canvas(device.get());
SkPoint p = SkPoint::Make(SkIntToScalar(72), SkIntToScalar(72));
SkAutoDataUnref data(SkData::NewWithCString("example"));
SkAnnotateNamedDestination(&canvas, p, data.get());
SkPDFDocument doc;
- doc.appendPage(&device);
+ doc.appendPage(device.get());
SkDynamicMemoryWStream outStream;
doc.emitPDF(&outStream);
SkAutoDataUnref out(outStream.copyToData());
diff --git a/tests/CanvasTest.cpp b/tests/CanvasTest.cpp
index d1f0abd19f..c405fcd52c 100644
--- a/tests/CanvasTest.cpp
+++ b/tests/CanvasTest.cpp
@@ -49,6 +49,7 @@
#include "SkDevice.h"
#include "SkMatrix.h"
#include "SkNWayCanvas.h"
+#include "SkPDFCanon.h"
#include "SkPDFDevice.h"
#include "SkPDFDocument.h"
#include "SkPaint.h"
@@ -558,12 +559,14 @@ static void TestPdfDevice(skiatest::Reporter* reporter,
const TestData& d,
CanvasTestStep* testStep) {
SkISize pageSize = SkISize::Make(d.fWidth, d.fHeight);
- SkPDFDevice device(pageSize, pageSize, SkMatrix::I());
- SkCanvas canvas(&device);
+ SkPDFCanon canon;
+ SkAutoTUnref<SkPDFDevice> pdfDevice(
+ SkPDFDevice::Create(pageSize, 72.0f, &canon));
+ SkCanvas canvas(pdfDevice.get());
testStep->setAssertMessageFormat(kPdfAssertMessageFormat);
testStep->draw(&canvas, d, reporter);
SkPDFDocument doc;
- doc.appendPage(&device);
+ doc.appendPage(pdfDevice.get());
SkDynamicMemoryWStream stream;
doc.emitPDF(&stream);
}
diff --git a/tests/PDFPrimitivesTest.cpp b/tests/PDFPrimitivesTest.cpp
index 2d4ac77aa4..97ad25e09a 100644
--- a/tests/PDFPrimitivesTest.cpp
+++ b/tests/PDFPrimitivesTest.cpp
@@ -11,6 +11,7 @@
#include "SkFlate.h"
#include "SkImageEncoder.h"
#include "SkMatrix.h"
+#include "SkPDFCanon.h"
#include "SkPDFCatalog.h"
#include "SkPDFDevice.h"
#include "SkPDFStream.h"
@@ -215,8 +216,8 @@ static void TestSubstitute(skiatest::Reporter* reporter) {
// and there is no assert on input data in Debug mode.
static void test_issue1083() {
SkISize pageSize = SkISize::Make(100, 100);
- SkAutoTUnref<SkPDFDevice> dev(new SkPDFDevice(pageSize, pageSize, SkMatrix::I()));
-
+ SkPDFCanon canon;
+ SkAutoTUnref<SkPDFDevice> dev(SkPDFDevice::Create(pageSize, 72.0f, &canon));
SkCanvas c(dev);
SkPaint paint;
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
@@ -354,8 +355,10 @@ void DummyImageFilter::toString(SkString* str) const {
// CPU rasterization.
DEF_TEST(PDFImageFilter, reporter) {
SkISize pageSize = SkISize::Make(100, 100);
- SkAutoTUnref<SkPDFDevice> device(new SkPDFDevice(pageSize, pageSize, SkMatrix::I()));
- SkCanvas canvas(device.get());
+ SkPDFCanon canon;
+ SkAutoTUnref<SkPDFDevice> pdfDevice(
+ SkPDFDevice::Create(pageSize, 72.0f, &canon));
+ SkCanvas canvas(pdfDevice.get());
SkAutoTUnref<DummyImageFilter> filter(new DummyImageFilter());
// Filter just created; should be unvisited.