diff options
author | reed <reed@google.com> | 2015-01-06 09:54:13 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-01-06 09:54:14 -0800 |
commit | efdac514a9846e4ef32e1160fe7f2dae471cef39 (patch) | |
tree | 53ab81d241b34d49e0d617e6e0c19f17b4ed8c18 /include/pdf | |
parent | 8b1f761365df6652ea9304b6572d2dd91917b9aa (diff) |
Revert "Remove SkPDFDocument and SkPDFDevice from the public headers."
This reverts commit 8b1f761365df6652ea9304b6572d2dd91917b9aa.
BUG=skia:
TBR=
NOTRY=True
NOTREECHECKS=True
Review URL: https://codereview.chromium.org/839603002
Diffstat (limited to 'include/pdf')
-rw-r--r-- | include/pdf/SkPDFDevice.h | 339 | ||||
-rw-r--r-- | include/pdf/SkPDFDocument.h | 113 |
2 files changed, 452 insertions, 0 deletions
diff --git a/include/pdf/SkPDFDevice.h b/include/pdf/SkPDFDevice.h new file mode 100644 index 0000000000..495354a0be --- /dev/null +++ b/include/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 diff --git a/include/pdf/SkPDFDocument.h b/include/pdf/SkPDFDocument.h new file mode 100644 index 0000000000..07738a210b --- /dev/null +++ b/include/pdf/SkPDFDocument.h @@ -0,0 +1,113 @@ + +/* + * Copyright 2010 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#ifndef SkPDFDocument_DEFINED +#define SkPDFDocument_DEFINED + +#include "SkAdvancedTypefaceMetrics.h" +#include "SkRefCnt.h" +#include "SkTDArray.h" +#include "SkTemplates.h" + +class SkPDFCatalog; +class SkPDFDevice; +class SkPDFDict; +class SkPDFPage; +class SkPDFObject; +class SkWStream; +template <typename T> class SkTSet; + +/** \class SkPDFDocument + + A SkPDFDocument assembles pages together and generates the final PDF file. +*/ +class SkPDFDocument { +public: + enum Flags { + kNoCompression_Flags = 0x01, //!< DEPRECATED. + kFavorSpeedOverSize_Flags = 0x01, //!< Don't compress the stream, but + // if it is already compressed return + // the compressed stream. + kNoLinks_Flags = 0x02, //!< do not honor link annotations. + + kDraftMode_Flags = 0x01, + }; + /** Create a PDF document. + */ + explicit SK_API SkPDFDocument(Flags flags = (Flags)0); + SK_API ~SkPDFDocument(); + + /** Output the PDF to the passed stream. It is an error to call this (it + * will return false and not modify stream) if no pages have been added + * or there are pages missing (i.e. page 1 and 3 have been added, but not + * page 2). + * + * @param stream The writable output stream to send the PDF to. + */ + SK_API bool emitPDF(SkWStream* stream); + + /** Sets the specific page to the passed PDF device. If the specified + * page is already set, this overrides it. Returns true if successful. + * Will fail if the document has already been emitted. + * + * @param pageNumber The position to add the passed device (1 based). + * @param pdfDevice The page to add to this document. + */ + SK_API bool setPage(int pageNumber, SkPDFDevice* pdfDevice); + + /** Append the passed pdf device to the document as a new page. Returns + * true if successful. Will fail if the document has already been emitted. + * + * @param pdfDevice The page to add to this document. + */ + SK_API bool appendPage(SkPDFDevice* pdfDevice); + + /** Get the count of unique font types used in the document. + * DEPRECATED. + */ + SK_API void getCountOfFontTypes( + int counts[SkAdvancedTypefaceMetrics::kOther_Font + 2]) const; + + /** Get the count of unique font types used in the document. + */ + SK_API void getCountOfFontTypes( + int counts[SkAdvancedTypefaceMetrics::kOther_Font + 1], + int* notSubsettableCount, + int* notEmbedddableCount) const; + +private: + SkAutoTDelete<SkPDFCatalog> fCatalog; + int64_t fXRefFileOffset; + + SkTDArray<SkPDFPage*> fPages; + SkTDArray<SkPDFDict*> fPageTree; + SkPDFDict* fDocCatalog; + SkTSet<SkPDFObject*>* fFirstPageResources; + SkTSet<SkPDFObject*>* fOtherPageResources; + SkTDArray<SkPDFObject*> fSubstitutes; + + SkPDFDict* fTrailerDict; + + /** Output the PDF header to the passed stream. + * @param stream The writable output stream to send the header to. + */ + void emitHeader(SkWStream* stream); + + /** Get the size of the header. + */ + size_t headerSize(); + + /** Output the PDF footer to the passed stream. + * @param stream The writable output stream to send the footer to. + * @param objCount The number of objects in the PDF. + */ + void emitFooter(SkWStream* stream, int64_t objCount); +}; + +#endif |