diff options
author | 2015-01-06 09:30:10 -0800 | |
---|---|---|
committer | 2015-01-06 09:30:10 -0800 | |
commit | 8b1f761365df6652ea9304b6572d2dd91917b9aa (patch) | |
tree | 232ad41f3beeb6481f84dac93a7cb5e81c1100fc /src/pdf/SkPDFDevice.h | |
parent | c4bd39c903cc5da16f50d711063b01723b59281c (diff) |
Remove SkPDFDocument and SkPDFDevice from the public headers.
Review URL: https://codereview.chromium.org/841533002
Diffstat (limited to 'src/pdf/SkPDFDevice.h')
-rw-r--r-- | src/pdf/SkPDFDevice.h | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h new file mode 100644 index 0000000000..495354a0be --- /dev/null +++ b/src/pdf/SkPDFDevice.h @@ -0,0 +1,339 @@ + +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#ifndef SkPDFDevice_DEFINED +#define SkPDFDevice_DEFINED + +#include "SkDevice.h" +#include "SkBitmap.h" +#include "SkCanvas.h" +#include "SkPaint.h" +#include "SkPath.h" +#include "SkPicture.h" +#include "SkRect.h" +#include "SkRefCnt.h" +#include "SkStream.h" +#include "SkTDArray.h" +#include "SkTemplates.h" + +class SkPDFArray; +class SkPDFDevice; +class SkPDFDict; +class SkPDFFont; +class SkPDFFormXObject; +class SkPDFGlyphSetMap; +class SkPDFGraphicState; +class SkPDFObject; +class SkPDFResourceDict; +class SkPDFShader; +class SkPDFStream; +class SkRRect; +template <typename T> class SkTSet; + +// Private classes. +struct ContentEntry; +struct GraphicStateEntry; +struct NamedDestination; + +/** \class SkPDFDevice + + The drawing context for the PDF backend. +*/ +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. + */ + // Deprecated, please use SkDocument::CreatePdf() instead. + SK_API SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize, + const SkMatrix& initialTransform); + SK_API 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, + and are handling any looping from the paint, and any effects from the + DrawFilter. + */ + void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE; + void drawPoints(const SkDraw&, SkCanvas::PointMode mode, + size_t count, const SkPoint[], + const SkPaint& paint) SK_OVERRIDE; + void drawRect(const SkDraw&, const SkRect& r, const SkPaint& paint) SK_OVERRIDE; + void drawOval(const SkDraw&, const SkRect& oval, const SkPaint& paint) SK_OVERRIDE; + void drawRRect(const SkDraw&, const SkRRect& rr, const SkPaint& paint) SK_OVERRIDE; + void drawPath(const SkDraw&, const SkPath& origpath, + const SkPaint& paint, const SkMatrix* prePathMatrix, + bool pathIsMutable) SK_OVERRIDE; + void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, + const SkRect* src, const SkRect& dst, + const SkPaint& paint, + SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE; + void drawBitmap(const SkDraw&, const SkBitmap& bitmap, + const SkMatrix& matrix, const SkPaint&) SK_OVERRIDE; + void drawSprite(const SkDraw&, const SkBitmap& bitmap, int x, int y, + const SkPaint& paint) SK_OVERRIDE; + void drawText(const SkDraw&, const void* text, size_t len, + SkScalar x, SkScalar y, const SkPaint&) SK_OVERRIDE; + void drawPosText(const SkDraw&, const void* text, size_t len, + const SkScalar pos[], int scalarsPerPos, + const SkPoint& offset, const SkPaint&) SK_OVERRIDE; + void drawTextOnPath(const SkDraw&, const void* text, size_t len, + const SkPath& path, const SkMatrix* matrix, + const SkPaint& paint) SK_OVERRIDE; + void drawVertices(const SkDraw&, SkCanvas::VertexMode, + int vertexCount, const SkPoint verts[], + const SkPoint texs[], const SkColor colors[], + SkXfermode* xmode, const uint16_t indices[], + int indexCount, const SkPaint& paint) SK_OVERRIDE; + void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, + const SkPaint&) SK_OVERRIDE; + + void onAttachToCanvas(SkCanvas* canvas) SK_OVERRIDE; + void onDetachFromCanvas() SK_OVERRIDE; + SkImageInfo imageInfo() const SK_OVERRIDE; + + enum DrawingArea { + kContent_DrawingArea, // Drawing area for the page content. + kMargin_DrawingArea, // Drawing area for the margin content. + }; + + /** Sets the drawing area for the device. Subsequent draw calls are directed + * to the specific drawing area (margin or content). The default drawing + * area is the content drawing area. + * + * Currently if margin content is drawn and then a complex (for PDF) xfer + * mode is used, like SrcIn, Clear, etc, the margin content will get + * clipped. A simple way to avoid the bug is to always draw the margin + * content last. + */ + SK_API void setDrawingArea(DrawingArea drawingArea); + + /** Sets the DCTEncoder for images. + * @param encoder The encoder to encode a bitmap as JPEG (DCT). + * Result of encodings are cached, if the encoder changes the + * behaivor dynamically and an image is added to a second catalog, + * we will likely use the result of the first encoding call. + * By returning false from the encoder function, the encoder result + * is not used. + * Callers might not want to encode small images, as the time spent + * encoding and decoding might not be worth the space savings, + * if any at all. + */ + void setDCTEncoder(SkPicture::EncodeBitmap encoder) { + fEncoder = encoder; + } + + // PDF specific methods. + + /** Returns the resource dictionary for this device. + */ + SK_API SkPDFResourceDict* getResourceDict(); + + /** Get the fonts used on this device. + */ + SK_API const SkTDArray<SkPDFFont*>& getFontResources() const; + + /** Add our named destinations to the supplied dictionary. + * @param dict Dictionary to add destinations to. + * @param page The PDF object representing the page for this device. + */ + void appendDestinations(SkPDFDict* dict, SkPDFObject* page); + + /** Returns a copy of the media box for this device. The caller is required + * to unref() this when it is finished. + */ + SK_API SkPDFArray* copyMediaBox() const; + + /** Get the annotations from this page, or NULL if there are none. + */ + SK_API SkPDFArray* getAnnotations() const { return fAnnotations; } + + /** Returns a SkStream with the page contents. The caller is responsible + for a reference to the returned value. + DEPRECATED: use copyContentToData() + */ + SK_API SkStream* content() const; + + /** Returns a SkStream with the page contents. The caller is responsible + * for calling data->unref() when it is finished. + */ + SK_API SkData* copyContentToData() const; + + SK_API const SkMatrix& initialTransform() const { + return fInitialTransform; + } + + /** Returns a SkPDFGlyphSetMap which represents glyph usage of every font + * that shows on this device. + */ + const SkPDFGlyphSetMap& getFontGlyphUsage() const { + 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: + virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE { + return fLegacyBitmap; + } + + virtual SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps&) SK_OVERRIDE; + +private: + // TODO(vandebo): push most of SkPDFDevice's state into a core object in + // order to get the right access levels without using friend. + friend class ScopedContentEntry; + + SkISize fPageSize; + SkISize fContentSize; + SkMatrix fInitialTransform; + SkClipStack fExistingClipStack; + SkRegion fExistingClipRegion; + SkPDFArray* fAnnotations; + SkPDFResourceDict* fResourceDict; + SkTDArray<NamedDestination*> fNamedDestinations; + + SkTDArray<SkPDFGraphicState*> fGraphicStateResources; + SkTDArray<SkPDFObject*> fXObjectResources; + SkTDArray<SkPDFFont*> fFontResources; + SkTDArray<SkPDFObject*> fShaderResources; + + SkAutoTDelete<ContentEntry> fContentEntries; + ContentEntry* fLastContentEntry; + SkAutoTDelete<ContentEntry> fMarginContentEntries; + ContentEntry* fLastMarginContentEntry; + DrawingArea fDrawingArea; + + const SkClipStack* fClipStack; + + // 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; + + SkPicture::EncodeBitmap fEncoder; + SkScalar fRasterDpi; + + SkBitmap fLegacyBitmap; + + SkPDFDevice(const SkISize& layerSize, const SkClipStack& existingClipStack, + const SkRegion& existingClipRegion); + + // override from SkBaseDevice + virtual SkBaseDevice* onCreateCompatibleDevice(const CreateInfo&) SK_OVERRIDE; + + void init(); + void cleanUp(bool clearFontUsage); + SkPDFFormXObject* createFormXObjectFromDevice(); + + void drawFormXObjectWithMask(int xObjectIndex, + SkPDFFormXObject* mask, + const SkClipStack* clipStack, + const SkRegion& clipRegion, + SkXfermode::Mode mode, + bool invertClip); + + // If the paint or clip is such that we shouldn't draw anything, this + // returns NULL and does not create a content entry. + // setUpContentEntry and finishContentEntry can be used directly, but + // the preferred method is to use the ScopedContentEntry helper class. + ContentEntry* setUpContentEntry(const SkClipStack* clipStack, + const SkRegion& clipRegion, + const SkMatrix& matrix, + const SkPaint& paint, + bool hasText, + SkPDFFormXObject** dst); + void finishContentEntry(SkXfermode::Mode xfermode, + SkPDFFormXObject* dst, + SkPath* shape); + bool isContentEmpty(); + + void populateGraphicStateEntryFromPaint(const SkMatrix& matrix, + const SkClipStack& clipStack, + const SkRegion& clipRegion, + const SkPaint& paint, + bool hasText, + GraphicStateEntry* entry); + int addGraphicStateResource(SkPDFGraphicState* gs); + int addXObjectResource(SkPDFObject* xObject); + + void updateFont(const SkPaint& paint, uint16_t glyphID, + ContentEntry* contentEntry); + int getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID); + + void internalDrawPaint(const SkPaint& paint, ContentEntry* contentEntry); + void internalDrawBitmap(const SkMatrix& matrix, + const SkClipStack* clipStack, + const SkRegion& clipRegion, + const SkBitmap& bitmap, + const SkIRect* srcRect, + const SkPaint& paint); + + /** Helper method for copyContentToData. It is responsible for copying the + * list of content entries |entry| to |data|. + */ + void copyContentEntriesToData(ContentEntry* entry, SkWStream* data) const; + +#ifdef SK_PDF_USE_PATHOPS + bool handleInversePath(const SkDraw& d, const SkPath& origPath, + const SkPaint& paint, bool pathIsMutable, + const SkMatrix* prePathMatrix = NULL); +#endif + bool handleRectAnnotation(const SkRect& r, const SkMatrix& matrix, + const SkPaint& paint); + bool handlePointAnnotation(const SkPoint* points, size_t count, + const SkMatrix& matrix, const SkPaint& paint); + SkPDFDict* createLinkAnnotation(const SkRect& r, const SkMatrix& matrix); + void handleLinkToURL(SkData* urlData, const SkRect& r, + const SkMatrix& matrix); + void handleLinkToNamedDest(SkData* nameData, const SkRect& r, + const SkMatrix& matrix); + void defineNamedDestination(SkData* nameData, const SkPoint& point, + const SkMatrix& matrix); + + typedef SkBaseDevice INHERITED; + + // TODO(edisonn): Only SkDocument_PDF and SkPDFImageShader should be able to create + // an SkPDFDevice + //friend class SkDocument_PDF; + //friend class SkPDFImageShader; +}; + +#endif |