diff options
author | Hal Canary <halcanary@google.com> | 2017-06-29 18:51:35 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-06-30 15:37:45 +0000 |
commit | a062258e76e28ef0ec88ef827ae84a90730393cc (patch) | |
tree | 1806f06e43425696b2fad918dd7c4e7fd10d508b /src | |
parent | 1c9686bfa5e2de3e06f1d1b9691105afb6659e85 (diff) |
SkPDF: clean up fRasterDpi
- PDFDevice no longer has a fRasterDpi; simply queries document.
- #define DPI_FOR_RASTER_SCALE_ONE becomes constexpr float.
- PDFShader::GetPDFShader no longer takes rasterScale or dpi
- Remove un-needed factory functions. We're all adults here.
Change-Id: Id2ce75d4e61af385763ccfb1db210465a1600067
Reviewed-on: https://skia-review.googlesource.com/21348
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Hal Canary <halcanary@google.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 48 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.h | 61 | ||||
-rw-r--r-- | src/pdf/SkPDFDocument.cpp | 6 | ||||
-rw-r--r-- | src/pdf/SkPDFDocument.h | 11 | ||||
-rw-r--r-- | src/pdf/SkPDFShader.cpp | 41 | ||||
-rw-r--r-- | src/pdf/SkPDFShader.h | 6 | ||||
-rw-r--r-- | src/pdf/SkPDFUtils.h | 2 |
7 files changed, 77 insertions, 98 deletions
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index c81bd9b8b0..5fc914d3ab 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -58,8 +58,6 @@ // encoding. #endif -#define DPI_FOR_RASTER_SCALE_ONE 72 - // Utility functions // This function destroys the mask and either frees or takes the pixels. @@ -460,13 +458,11 @@ SkBaseDevice* SkPDFDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint return SkBitmapDevice::Create(cinfo.fInfo, SkSurfaceProps(0, kUnknown_SkPixelGeometry)); } SkISize size = SkISize::Make(cinfo.fInfo.width(), cinfo.fInfo.height()); - return SkPDFDevice::Make(size, fRasterDpi, fDocument).release(); + return new SkPDFDevice(size, fDocument); } SkPDFCanon* SkPDFDevice::getCanon() const { return fDocument->canon(); } - - // A helper class to automatically finish a ContentEntry at the end of a // drawing method and maintain the state needed between set up and finish. class ScopedContentEntry { @@ -549,25 +545,24 @@ private: //////////////////////////////////////////////////////////////////////////////// -SkPDFDevice::SkPDFDevice(SkISize pageSize, SkScalar rasterDpi, SkPDFDocument* doc, bool flip) +SkPDFDevice::SkPDFDevice(SkISize pageSize, SkPDFDocument* doc) : INHERITED(SkImageInfo::MakeUnknown(pageSize.width(), pageSize.height()), SkSurfaceProps(0, kUnknown_SkPixelGeometry)) , fPageSize(pageSize) - , fRasterDpi(rasterDpi) - , fDocument(doc) { + , fInitialTransform(SkMatrix::I()) + , fDocument(doc) +{ SkASSERT(pageSize.width() > 0); SkASSERT(pageSize.height() > 0); +} - 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(); - } +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. + fInitialTransform.setTranslate(0, SkIntToScalar(fPageSize.fHeight)); + fInitialTransform.preScale(SK_Scalar1, -SK_Scalar1); } SkPDFDevice::~SkPDFDevice() { @@ -845,8 +840,8 @@ void SkPDFDevice::internalDrawPathWithFilter(const SkClipStack& clipStack, : SkStrokeRec::kHairline_InitStyle; path.transform(ctm, &path); - // TODO(halcanary): respect fRasterDpi. - // SkScalar rasterScale = (float)fRasterDpi / DPI_FOR_RASTER_SCALE_ONE; + // TODO(halcanary): respect fDocument->rasterDpi(). + // SkScalar rasterScale = (float)rasterDpi / SkPDFUtils::kDpiForRasterScaleOne; // Would it be easier to just change the device size (and pre-scale the canvas)? SkIRect bounds = clipStack.bounds(size(*this)).roundOut(); SkMask sourceMask; @@ -2177,10 +2172,7 @@ void SkPDFDevice::populateGraphicStateEntryFromPaint( SkIRect bounds; clipStackBounds.roundOut(&bounds); - SkScalar rasterScale = - SkIntToScalar(fRasterDpi) / DPI_FOR_RASTER_SCALE_ONE; - pdfShader = SkPDFShader::GetPDFShader( - fDocument, fRasterDpi, shader, transform, bounds, rasterScale); + pdfShader = SkPDFShader::GetPDFShader(fDocument, shader, transform, bounds); if (pdfShader.get()) { // pdfShader has been canonicalized so we can directly compare @@ -2284,9 +2276,7 @@ void SkPDFDevice::internalDrawImage(const SkMatrix& origMatrix, // Rasterize the bitmap using perspective in a new bitmap. if (origMatrix.hasPerspective()) { - if (fRasterDpi == 0) { - return; - } + SkASSERT(fDocument->rasterDpi() > 0); // Transform the bitmap in the new space, without taking into // account the initial transform. SkPath perspectiveOutline; @@ -2302,8 +2292,8 @@ void SkPDFDevice::internalDrawImage(const SkMatrix& origMatrix, // account the initial transform. SkMatrix total = origMatrix; total.postConcat(fInitialTransform); - SkScalar dpiScale = SkIntToScalar(fRasterDpi) / - SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE); + SkScalar dpiScale = SkIntToScalar(fDocument->rasterDpi()) / + SkIntToScalar(SkPDFUtils::kDpiForRasterScaleOne); total.postScale(dpiScale, dpiScale); SkPath physicalPerspectiveOutline; diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h index ad44bcd12d..8d2c511be0 100644 --- a/src/pdf/SkPDFDevice.h +++ b/src/pdf/SkPDFDevice.h @@ -33,53 +33,42 @@ class SkPDFObject; class SkPDFStream; class SkRRect; -/** \class SkPDFDevice - - The drawing context for the PDF backend. -*/ +/** + * \class SkPDFDevice + * + * An SkPDFDevice is the drawing context for a page or layer of PDF + * content. + */ class SkPDFDevice final : public SkClipStackDevice { public: - /** 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 SkPDFDocument. A non-null pointer back to the - * document. The document is repsonsible for + * @param document A non-null pointer back to the + * PDFDocument object. The document is repsonsible for * de-duplicating across pages (via the SkPDFCanon) and * for early serializing of large immutable objects, such * as images (via SkPDFDocument::serialize()). */ - static sk_sp<SkPDFDevice> Make(SkISize pageSize, SkScalar rasterDpi, SkPDFDocument* doc) { - return sk_sp<SkPDFDevice>(new SkPDFDevice(pageSize, rasterDpi, doc, true)); - } + SkPDFDevice(SkISize pageSize, SkPDFDocument* document); - /** Create a PDF drawing context without fipping the y-axis. */ - static sk_sp<SkPDFDevice> MakeUnflipped(SkISize pageSize, - SkScalar rasterDpi, - SkPDFDocument* doc) { - return sk_sp<SkPDFDevice>(new SkPDFDevice(pageSize, rasterDpi, doc, false)); - } + /** + * Apply a scale-and-translate transform to move the origin from the + * bottom left (PDF default) to the top left (Skia default). + */ + void setFlip(); sk_sp<SkPDFDevice> makeCongruentDevice() { - return sk_sp<SkPDFDevice>(new SkPDFDevice(fPageSize, fRasterDpi, fDocument, false)); + return sk_make_sp<SkPDFDevice>(fPageSize, fDocument); } ~SkPDFDevice() override; - /** These are called inside the per-device-layer loop for each draw call. - When these are called, we have already applied any saveLayer operations, - and are handling any looping from the paint, and any effects from the - DrawFilter. + /** + * These are called inside the per-device-layer loop for each draw call. + * When these are called, we have already applied any saveLayer + * operations, and are handling any looping from the paint, and any + * effects from the DrawFilter. */ void drawPaint(const SkPaint& paint) override; void drawPoints(SkCanvas::PointMode mode, @@ -212,15 +201,9 @@ private: }; SkSinglyLinkedList<ContentEntry> fContentEntries; - SkScalar fRasterDpi; - SkPDFDocument* fDocument; - //////////////////////////////////////////////////////////////////////////// - SkPDFDevice(SkISize pageSize, - SkScalar rasterDpi, - SkPDFDocument* doc, - bool flip); + //////////////////////////////////////////////////////////////////////////// SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override; diff --git a/src/pdf/SkPDFDocument.cpp b/src/pdf/SkPDFDocument.cpp index 774d023db6..96a79aedb8 100644 --- a/src/pdf/SkPDFDocument.cpp +++ b/src/pdf/SkPDFDocument.cpp @@ -215,7 +215,8 @@ SkCanvas* SkPDFDocument::onBeginPage(SkScalar width, SkScalar height, } SkISize pageSize = SkISize::Make( SkScalarRoundToInt(width), SkScalarRoundToInt(height)); - fPageDevice = SkPDFDevice::Make(pageSize, fRasterDpi, this); + fPageDevice = sk_make_sp<SkPDFDevice>(pageSize, this); + fPageDevice->setFlip(); // Only the top-level device needs to be flipped. fCanvas.reset(new SkPDFCanvas(fPageDevice)); if (SkRect::MakeWH(width, height) != trimBox) { fCanvas->clipRect(trimBox); @@ -439,6 +440,9 @@ sk_sp<SkDocument> SkPDFMakeDocument(SkWStream* stream, const SkDocument::PDFMetadata& metadata, sk_sp<SkPixelSerializer> jpeg, bool pdfa) { + if (dpi <= 0) { + dpi = 72.0f; + } return stream ? sk_make_sp<SkPDFDocument>(stream, proc, dpi, metadata, std::move(jpeg), pdfa) : nullptr; diff --git a/src/pdf/SkPDFDocument.h b/src/pdf/SkPDFDocument.h index aa6dcb286f..7f8b6c84a3 100644 --- a/src/pdf/SkPDFDocument.h +++ b/src/pdf/SkPDFDocument.h @@ -14,6 +14,16 @@ class SkPDFDevice; +/* @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). + */ sk_sp<SkDocument> SkPDFMakeDocument(SkWStream* stream, void (*doneProc)(SkWStream*, bool), SkScalar rasterDpi, @@ -67,6 +77,7 @@ public: */ void serialize(const sk_sp<SkPDFObject>&); SkPDFCanon* canon() { return &fCanon; } + SkScalar rasterDpi() const { return fRasterDpi; } void registerFont(SkPDFFont* f) { fFonts.add(f); } private: diff --git a/src/pdf/SkPDFShader.cpp b/src/pdf/SkPDFShader.cpp index 235d66341b..7369abf8ac 100644 --- a/src/pdf/SkPDFShader.cpp +++ b/src/pdf/SkPDFShader.cpp @@ -275,7 +275,7 @@ static sk_sp<SkPDFDict> gradientStitchCode(const SkShader::GradientInfo& info) { encode->appendScalar(0); encode->appendScalar(1.0f); - + functions->appendObject(createInterpolationFunction(colorData[i-1], colorData[i])); } @@ -525,19 +525,16 @@ static void drawBitmapMatrix(SkCanvas* canvas, const SkBitmap& bm, const SkMatri //////////////////////////////////////////////////////////////////////////////// static sk_sp<SkPDFStream> make_alpha_function_shader(SkPDFDocument* doc, - SkScalar dpi, const SkPDFShader::State& state); static sk_sp<SkPDFDict> make_function_shader(SkPDFCanon* canon, const SkPDFShader::State& state); static sk_sp<SkPDFStream> make_image_shader(SkPDFDocument* doc, - SkScalar dpi, const SkPDFShader::State& state, SkBitmap image); static sk_sp<SkPDFObject> get_pdf_shader_by_state( SkPDFDocument* doc, - SkScalar dpi, SkPDFShader::State state, SkBitmap image) { SkPDFCanon* canon = doc->canon(); @@ -550,14 +547,14 @@ static sk_sp<SkPDFObject> get_pdf_shader_by_state( } else if (state.fType == SkShader::kNone_GradientType) { sk_sp<SkPDFObject> shader = canon->findImageShader(state); if (!shader) { - shader = make_image_shader(doc, dpi, state, std::move(image)); + shader = make_image_shader(doc, state, std::move(image)); canon->addImageShader(shader, std::move(state)); } return shader; } else if (state.GradientHasAlpha()) { sk_sp<SkPDFObject> shader = canon->findAlphaShader(state); if (!shader) { - shader = make_alpha_function_shader(doc, dpi, state); + shader = make_alpha_function_shader(doc, state); canon->addAlphaShader(shader, std::move(state)); } return shader; @@ -572,18 +569,17 @@ static sk_sp<SkPDFObject> get_pdf_shader_by_state( } sk_sp<SkPDFObject> SkPDFShader::GetPDFShader(SkPDFDocument* doc, - SkScalar dpi, SkShader* shader, const SkMatrix& matrix, - const SkIRect& surfaceBBox, - SkScalar rasterScale) { + const SkIRect& surfaceBBox) { if (surfaceBBox.isEmpty()) { return nullptr; } + SkScalar rasterDpi = doc->rasterDpi(); + SkScalar rasterScale = SkIntToScalar(rasterDpi) / SkPDFUtils::kDpiForRasterScaleOne; SkBitmap image; State state(shader, matrix, surfaceBBox, rasterScale, &image); - return get_pdf_shader_by_state( - doc, dpi, std::move(state), std::move(image)); + return get_pdf_shader_by_state(doc, std::move(state), std::move(image)); } static sk_sp<SkPDFDict> get_gradient_resource_dict( @@ -644,14 +640,13 @@ static std::unique_ptr<SkStreamAsset> create_pattern_fill_content( * Creates a ExtGState with the SMask set to the luminosityShader in * luminosity mode. The shader pattern extends to the bbox. */ -static sk_sp<SkPDFObject> create_smask_graphic_state( - SkPDFDocument* doc, SkScalar dpi, const SkPDFShader::State& state) { +static sk_sp<SkPDFObject> create_smask_graphic_state(SkPDFDocument* doc, + const SkPDFShader::State& state) { SkRect bbox; bbox.set(state.fBBox); sk_sp<SkPDFObject> luminosityShader( - get_pdf_shader_by_state(doc, dpi, state.MakeAlphaToLuminosityState(), - SkBitmap())); + get_pdf_shader_by_state(doc, state.MakeAlphaToLuminosityState(), SkBitmap())); std::unique_ptr<SkStreamAsset> alphaStream(create_pattern_fill_content(-1, bbox)); @@ -670,7 +665,6 @@ static sk_sp<SkPDFObject> create_smask_graphic_state( } static sk_sp<SkPDFStream> make_alpha_function_shader(SkPDFDocument* doc, - SkScalar dpi, const SkPDFShader::State& state) { SkRect bbox; bbox.set(state.fBBox); @@ -678,14 +672,14 @@ static sk_sp<SkPDFStream> make_alpha_function_shader(SkPDFDocument* doc, SkPDFShader::State opaqueState(state.MakeOpaqueState()); sk_sp<SkPDFObject> colorShader( - get_pdf_shader_by_state(doc, dpi, std::move(opaqueState), SkBitmap())); + get_pdf_shader_by_state(doc, std::move(opaqueState), SkBitmap())); if (!colorShader) { return nullptr; } // Create resource dict with alpha graphics state as G0 and // pattern shader as P0, then write content stream. - sk_sp<SkPDFObject> alphaGs = create_smask_graphic_state(doc, dpi, state); + sk_sp<SkPDFObject> alphaGs = create_smask_graphic_state(doc, state); sk_sp<SkPDFDict> resourceDict = get_gradient_resource_dict(colorShader.get(), alphaGs.get()); @@ -695,7 +689,7 @@ static sk_sp<SkPDFStream> make_alpha_function_shader(SkPDFDocument* doc, auto alphaFunctionShader = sk_make_sp<SkPDFStream>(std::move(colorStream)); populate_tiling_pattern_dict(alphaFunctionShader->dict(), bbox, - std::move(resourceDict), SkMatrix::I()); + std::move(resourceDict), SkMatrix::I()); return alphaFunctionShader; } @@ -912,9 +906,9 @@ static sk_sp<SkPDFDict> make_function_shader(SkPDFCanon* canon, domain->appendScalar(bbox.fRight); domain->appendScalar(bbox.fTop); domain->appendScalar(bbox.fBottom); - + SkDynamicMemoryWStream functionCode; - + if (state.fType == SkShader::kConical_GradientType) { SkShader::GradientInfo twoPointRadialInfo = *info; SkMatrix inverseMapperMatrix; @@ -930,7 +924,7 @@ static sk_sp<SkPDFDict> make_function_shader(SkPDFCanon* canon, } else { codeFunction(*info, perspectiveInverseOnly, &functionCode); } - + pdfShader->insertObject("Domain", domain); std::unique_ptr<SkStreamAsset> functionStream(functionCode.detachAsStream()); @@ -957,7 +951,6 @@ static sk_sp<SkPDFDict> make_function_shader(SkPDFCanon* canon, } static sk_sp<SkPDFStream> make_image_shader(SkPDFDocument* doc, - SkScalar dpi, const SkPDFShader::State& state, SkBitmap image) { SkASSERT(state.fBitmapKey == @@ -994,7 +987,7 @@ static sk_sp<SkPDFStream> make_image_shader(SkPDFDocument* doc, SkISize size = SkISize::Make(SkScalarRoundToInt(deviceBounds.width()), SkScalarRoundToInt(deviceBounds.height())); - sk_sp<SkPDFDevice> patternDevice = SkPDFDevice::MakeUnflipped(size, dpi, doc); + auto patternDevice = sk_make_sp<SkPDFDevice>(size, doc); SkCanvas canvas(patternDevice.get()); SkRect patternBBox; diff --git a/src/pdf/SkPDFShader.h b/src/pdf/SkPDFShader.h index db13cd50b3..fe561b6d43 100644 --- a/src/pdf/SkPDFShader.h +++ b/src/pdf/SkPDFShader.h @@ -37,15 +37,11 @@ public: * positioned, relative to where the page is drawn.) * @param surfceBBox The bounding box of the drawing surface (with matrix * already applied). - * @param rasterScale Additional scale to be applied for early - * rasterization. */ static sk_sp<SkPDFObject> GetPDFShader(SkPDFDocument* doc, - SkScalar dpi, SkShader* shader, const SkMatrix& matrix, - const SkIRect& surfaceBBox, - SkScalar rasterScale); + const SkIRect& surfaceBBox); static sk_sp<SkPDFArray> MakeRangeObject(); diff --git a/src/pdf/SkPDFUtils.h b/src/pdf/SkPDFUtils.h index 4d0447c194..dfc10b3463 100644 --- a/src/pdf/SkPDFUtils.h +++ b/src/pdf/SkPDFUtils.h @@ -35,6 +35,8 @@ struct SkRect; 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); |