gfx/skia/trunk/include/pdf/SkPDFDevice.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/include/pdf/SkPDFDevice.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,337 @@
     1.4 +
     1.5 +/*
     1.6 + * Copyright 2011 Google Inc.
     1.7 + *
     1.8 + * Use of this source code is governed by a BSD-style license that can be
     1.9 + * found in the LICENSE file.
    1.10 + */
    1.11 +
    1.12 +
    1.13 +#ifndef SkPDFDevice_DEFINED
    1.14 +#define SkPDFDevice_DEFINED
    1.15 +
    1.16 +#include "SkBitmapDevice.h"
    1.17 +#include "SkBitmap.h"
    1.18 +#include "SkCanvas.h"
    1.19 +#include "SkPaint.h"
    1.20 +#include "SkPath.h"
    1.21 +#include "SkPicture.h"
    1.22 +#include "SkRect.h"
    1.23 +#include "SkRefCnt.h"
    1.24 +#include "SkStream.h"
    1.25 +#include "SkTDArray.h"
    1.26 +#include "SkTemplates.h"
    1.27 +
    1.28 +class SkPDFArray;
    1.29 +class SkPDFDevice;
    1.30 +class SkPDFDict;
    1.31 +class SkPDFFont;
    1.32 +class SkPDFFormXObject;
    1.33 +class SkPDFGlyphSetMap;
    1.34 +class SkPDFGraphicState;
    1.35 +class SkPDFObject;
    1.36 +class SkPDFResourceDict;
    1.37 +class SkPDFShader;
    1.38 +class SkPDFStream;
    1.39 +class SkRRect;
    1.40 +template <typename T> class SkTSet;
    1.41 +
    1.42 +// Private classes.
    1.43 +struct ContentEntry;
    1.44 +struct GraphicStateEntry;
    1.45 +struct NamedDestination;
    1.46 +
    1.47 +/** \class SkPDFDevice
    1.48 +
    1.49 +    The drawing context for the PDF backend.
    1.50 +*/
    1.51 +class SkPDFDevice : public SkBitmapDevice {
    1.52 +public:
    1.53 +    /** Create a PDF drawing context with the given width and height.
    1.54 +     *  72 points/in means letter paper is 612x792.
    1.55 +     *  @param pageSize Page size in points.
    1.56 +     *  @param contentSize The content size of the page in points. This will be
    1.57 +     *         combined with the initial transform to determine the drawing area
    1.58 +     *         (as reported by the width and height methods). Anything outside
    1.59 +     *         of the drawing area will be clipped.
    1.60 +     *  @param initialTransform The initial transform to apply to the page.
    1.61 +     *         This may be useful to, for example, move the origin in and
    1.62 +     *         over a bit to account for a margin, scale the canvas,
    1.63 +     *         or apply a rotation.  Note1: the SkPDFDevice also applies
    1.64 +     *         a scale+translate transform to move the origin from the
    1.65 +     *         bottom left (PDF default) to the top left.  Note2: drawDevice
    1.66 +     *         (used by layer restore) draws the device after this initial
    1.67 +     *         transform is applied, so the PDF device does an
    1.68 +     *         inverse scale+translate to accommodate the one that SkPDFDevice
    1.69 +     *         always does.
    1.70 +     */
    1.71 +    // Deprecated, please use SkDocument::CreatePdf() instead.
    1.72 +    SK_API SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize,
    1.73 +                       const SkMatrix& initialTransform);
    1.74 +    SK_API virtual ~SkPDFDevice();
    1.75 +
    1.76 +    virtual void clear(SkColor color) SK_OVERRIDE;
    1.77 +
    1.78 +    /** These are called inside the per-device-layer loop for each draw call.
    1.79 +     When these are called, we have already applied any saveLayer operations,
    1.80 +     and are handling any looping from the paint, and any effects from the
    1.81 +     DrawFilter.
    1.82 +     */
    1.83 +    virtual void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE;
    1.84 +    virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode,
    1.85 +                            size_t count, const SkPoint[],
    1.86 +                            const SkPaint& paint) SK_OVERRIDE;
    1.87 +    virtual void drawRect(const SkDraw&, const SkRect& r, const SkPaint& paint);
    1.88 +    virtual void drawRRect(const SkDraw&, const SkRRect& rr,
    1.89 +                           const SkPaint& paint) SK_OVERRIDE;
    1.90 +    virtual void drawPath(const SkDraw&, const SkPath& origpath,
    1.91 +                          const SkPaint& paint, const SkMatrix* prePathMatrix,
    1.92 +                          bool pathIsMutable) SK_OVERRIDE;
    1.93 +    virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
    1.94 +                                const SkRect* src, const SkRect& dst,
    1.95 +                                const SkPaint& paint,
    1.96 +                                SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE;
    1.97 +    virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
    1.98 +                            const SkMatrix& matrix, const SkPaint&) SK_OVERRIDE;
    1.99 +    virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, int x, int y,
   1.100 +                            const SkPaint& paint) SK_OVERRIDE;
   1.101 +    virtual void drawText(const SkDraw&, const void* text, size_t len,
   1.102 +                          SkScalar x, SkScalar y, const SkPaint&) SK_OVERRIDE;
   1.103 +    virtual void drawPosText(const SkDraw&, const void* text, size_t len,
   1.104 +                             const SkScalar pos[], SkScalar constY,
   1.105 +                             int scalarsPerPos, const SkPaint&) SK_OVERRIDE;
   1.106 +    virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len,
   1.107 +                                const SkPath& path, const SkMatrix* matrix,
   1.108 +                                const SkPaint& paint) SK_OVERRIDE;
   1.109 +    virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode,
   1.110 +                              int vertexCount, const SkPoint verts[],
   1.111 +                              const SkPoint texs[], const SkColor colors[],
   1.112 +                              SkXfermode* xmode, const uint16_t indices[],
   1.113 +                              int indexCount, const SkPaint& paint) SK_OVERRIDE;
   1.114 +    virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
   1.115 +                            const SkPaint&) SK_OVERRIDE;
   1.116 +
   1.117 +    virtual void onAttachToCanvas(SkCanvas* canvas) SK_OVERRIDE;
   1.118 +    virtual void onDetachFromCanvas() SK_OVERRIDE;
   1.119 +
   1.120 +    enum DrawingArea {
   1.121 +        kContent_DrawingArea,  // Drawing area for the page content.
   1.122 +        kMargin_DrawingArea,   // Drawing area for the margin content.
   1.123 +    };
   1.124 +
   1.125 +    /** Sets the drawing area for the device. Subsequent draw calls are directed
   1.126 +     *  to the specific drawing area (margin or content). The default drawing
   1.127 +     *  area is the content drawing area.
   1.128 +     *
   1.129 +     *  Currently if margin content is drawn and then a complex (for PDF) xfer
   1.130 +     *  mode is used, like SrcIn, Clear, etc, the margin content will get
   1.131 +     *  clipped. A simple way to avoid the bug is to always draw the margin
   1.132 +     *  content last.
   1.133 +     */
   1.134 +    SK_API void setDrawingArea(DrawingArea drawingArea);
   1.135 +
   1.136 +    /** Sets the DCTEncoder for images.
   1.137 +     *  @param encoder The encoder to encode a bitmap as JPEG (DCT).
   1.138 +     *         Result of encodings are cached, if the encoder changes the
   1.139 +     *         behaivor dynamically and an image is added to a second catalog,
   1.140 +     *         we will likely use the result of the first encoding call.
   1.141 +     *         By returning false from the encoder function, the encoder result
   1.142 +     *         is not used.
   1.143 +     *         Callers might not want to encode small images, as the time spent
   1.144 +     *         encoding and decoding might not be worth the space savings,
   1.145 +     *         if any at all.
   1.146 +     */
   1.147 +    void setDCTEncoder(SkPicture::EncodeBitmap encoder) {
   1.148 +        fEncoder = encoder;
   1.149 +    }
   1.150 +
   1.151 +    // PDF specific methods.
   1.152 +
   1.153 +    /** Returns the resource dictionary for this device.
   1.154 +     */
   1.155 +    SK_API SkPDFResourceDict* getResourceDict();
   1.156 +
   1.157 +    /** Get the fonts used on this device.
   1.158 +     */
   1.159 +    SK_API const SkTDArray<SkPDFFont*>& getFontResources() const;
   1.160 +
   1.161 +    /** Add our named destinations to the supplied dictionary.
   1.162 +     *  @param dict  Dictionary to add destinations to.
   1.163 +     *  @param page  The PDF object representing the page for this device.
   1.164 +     */
   1.165 +    void appendDestinations(SkPDFDict* dict, SkPDFObject* page);
   1.166 +
   1.167 +    /** Returns a copy of the media box for this device. The caller is required
   1.168 +     *  to unref() this when it is finished.
   1.169 +     */
   1.170 +    SK_API SkPDFArray* copyMediaBox() const;
   1.171 +
   1.172 +    /** Get the annotations from this page, or NULL if there are none.
   1.173 +     */
   1.174 +    SK_API SkPDFArray* getAnnotations() const { return fAnnotations; }
   1.175 +
   1.176 +    /** Returns a SkStream with the page contents.  The caller is responsible
   1.177 +        for a reference to the returned value.
   1.178 +        DEPRECATED: use copyContentToData()
   1.179 +     */
   1.180 +    SK_API SkStream* content() const;
   1.181 +
   1.182 +    /** Returns a SkStream with the page contents.  The caller is responsible
   1.183 +     *  for calling data->unref() when it is finished.
   1.184 +     */
   1.185 +    SK_API SkData* copyContentToData() const;
   1.186 +
   1.187 +    SK_API const SkMatrix& initialTransform() const {
   1.188 +        return fInitialTransform;
   1.189 +    }
   1.190 +
   1.191 +    /** Returns a SkPDFGlyphSetMap which represents glyph usage of every font
   1.192 +     *  that shows on this device.
   1.193 +     */
   1.194 +    const SkPDFGlyphSetMap& getFontGlyphUsage() const {
   1.195 +        return *(fFontGlyphUsage.get());
   1.196 +    }
   1.197 +
   1.198 +
   1.199 +    /**
   1.200 +     *  rasterDpi - the DPI at which features without native PDF support
   1.201 +     *              will be rasterized (e.g. draw image with perspective,
   1.202 +     *              draw text with perspective, ...)
   1.203 +     *              A larger DPI would create a PDF that reflects the original
   1.204 +     *              intent with better fidelity, but it can make for larger
   1.205 +     *              PDF files too, which would use more memory while rendering,
   1.206 +     *              and it would be slower to be processed or sent online or
   1.207 +     *              to printer.
   1.208 +     */
   1.209 +    void setRasterDpi(SkScalar rasterDpi) {
   1.210 +        fRasterDpi = rasterDpi;
   1.211 +    }
   1.212 +
   1.213 +protected:
   1.214 +    virtual bool onReadPixels(const SkBitmap& bitmap, int x, int y,
   1.215 +                              SkCanvas::Config8888) SK_OVERRIDE;
   1.216 +
   1.217 +    virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE;
   1.218 +
   1.219 +private:
   1.220 +    // TODO(vandebo): push most of SkPDFDevice's state into a core object in
   1.221 +    // order to get the right access levels without using friend.
   1.222 +    friend class ScopedContentEntry;
   1.223 +
   1.224 +    SkISize fPageSize;
   1.225 +    SkISize fContentSize;
   1.226 +    SkMatrix fInitialTransform;
   1.227 +    SkClipStack fExistingClipStack;
   1.228 +    SkRegion fExistingClipRegion;
   1.229 +    SkPDFArray* fAnnotations;
   1.230 +    SkPDFResourceDict* fResourceDict;
   1.231 +    SkTDArray<NamedDestination*> fNamedDestinations;
   1.232 +
   1.233 +    SkTDArray<SkPDFGraphicState*> fGraphicStateResources;
   1.234 +    SkTDArray<SkPDFObject*> fXObjectResources;
   1.235 +    SkTDArray<SkPDFFont*> fFontResources;
   1.236 +    SkTDArray<SkPDFObject*> fShaderResources;
   1.237 +
   1.238 +    SkAutoTDelete<ContentEntry> fContentEntries;
   1.239 +    ContentEntry* fLastContentEntry;
   1.240 +    SkAutoTDelete<ContentEntry> fMarginContentEntries;
   1.241 +    ContentEntry* fLastMarginContentEntry;
   1.242 +    DrawingArea fDrawingArea;
   1.243 +
   1.244 +    const SkClipStack* fClipStack;
   1.245 +
   1.246 +    // Accessor and setter functions based on the current DrawingArea.
   1.247 +    SkAutoTDelete<ContentEntry>* getContentEntries();
   1.248 +    ContentEntry* getLastContentEntry();
   1.249 +    void setLastContentEntry(ContentEntry* contentEntry);
   1.250 +
   1.251 +    // Glyph ids used for each font on this device.
   1.252 +    SkAutoTDelete<SkPDFGlyphSetMap> fFontGlyphUsage;
   1.253 +
   1.254 +    SkPicture::EncodeBitmap fEncoder;
   1.255 +    SkScalar fRasterDpi;
   1.256 +
   1.257 +    SkPDFDevice(const SkISize& layerSize, const SkClipStack& existingClipStack,
   1.258 +                const SkRegion& existingClipRegion);
   1.259 +
   1.260 +    // override from SkBaseDevice
   1.261 +    virtual SkBaseDevice* onCreateDevice(const SkImageInfo&, Usage) SK_OVERRIDE;
   1.262 +
   1.263 +    void init();
   1.264 +    void cleanUp(bool clearFontUsage);
   1.265 +    SkPDFFormXObject* createFormXObjectFromDevice();
   1.266 +
   1.267 +    void drawFormXObjectWithMask(int xObjectIndex,
   1.268 +                                 SkPDFFormXObject* mask,
   1.269 +                                 const SkClipStack* clipStack,
   1.270 +                                 const SkRegion& clipRegion,
   1.271 +                                 SkXfermode::Mode mode,
   1.272 +                                 bool invertClip);
   1.273 +
   1.274 +    // If the paint or clip is such that we shouldn't draw anything, this
   1.275 +    // returns NULL and does not create a content entry.
   1.276 +    // setUpContentEntry and finishContentEntry can be used directly, but
   1.277 +    // the preferred method is to use the ScopedContentEntry helper class.
   1.278 +    ContentEntry* setUpContentEntry(const SkClipStack* clipStack,
   1.279 +                                    const SkRegion& clipRegion,
   1.280 +                                    const SkMatrix& matrix,
   1.281 +                                    const SkPaint& paint,
   1.282 +                                    bool hasText,
   1.283 +                                    SkPDFFormXObject** dst);
   1.284 +    void finishContentEntry(SkXfermode::Mode xfermode,
   1.285 +                            SkPDFFormXObject* dst,
   1.286 +                            SkPath* shape);
   1.287 +    bool isContentEmpty();
   1.288 +
   1.289 +    void populateGraphicStateEntryFromPaint(const SkMatrix& matrix,
   1.290 +                                            const SkClipStack& clipStack,
   1.291 +                                            const SkRegion& clipRegion,
   1.292 +                                            const SkPaint& paint,
   1.293 +                                            bool hasText,
   1.294 +                                            GraphicStateEntry* entry);
   1.295 +    int addGraphicStateResource(SkPDFGraphicState* gs);
   1.296 +    int addXObjectResource(SkPDFObject* xObject);
   1.297 +
   1.298 +    void updateFont(const SkPaint& paint, uint16_t glyphID,
   1.299 +                    ContentEntry* contentEntry);
   1.300 +    int getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID);
   1.301 +
   1.302 +    void internalDrawPaint(const SkPaint& paint, ContentEntry* contentEntry);
   1.303 +    void internalDrawBitmap(const SkMatrix& matrix,
   1.304 +                            const SkClipStack* clipStack,
   1.305 +                            const SkRegion& clipRegion,
   1.306 +                            const SkBitmap& bitmap,
   1.307 +                            const SkIRect* srcRect,
   1.308 +                            const SkPaint& paint);
   1.309 +
   1.310 +    /** Helper method for copyContentToData. It is responsible for copying the
   1.311 +     *  list of content entries |entry| to |data|.
   1.312 +     */
   1.313 +    void copyContentEntriesToData(ContentEntry* entry, SkWStream* data) const;
   1.314 +
   1.315 +#ifdef SK_PDF_USE_PATHOPS
   1.316 +    bool handleInversePath(const SkDraw& d, const SkPath& origPath,
   1.317 +                           const SkPaint& paint, bool pathIsMutable,
   1.318 +                           const SkMatrix* prePathMatrix = NULL);
   1.319 +#endif
   1.320 +    bool handleRectAnnotation(const SkRect& r, const SkMatrix& matrix,
   1.321 +                              const SkPaint& paint);
   1.322 +    bool handlePointAnnotation(const SkPoint* points, size_t count,
   1.323 +                               const SkMatrix& matrix, const SkPaint& paint);
   1.324 +    SkPDFDict* createLinkAnnotation(const SkRect& r, const SkMatrix& matrix);
   1.325 +    void handleLinkToURL(SkData* urlData, const SkRect& r,
   1.326 +                         const SkMatrix& matrix);
   1.327 +    void handleLinkToNamedDest(SkData* nameData, const SkRect& r,
   1.328 +                               const SkMatrix& matrix);
   1.329 +    void defineNamedDestination(SkData* nameData, const SkPoint& point,
   1.330 +                                const SkMatrix& matrix);
   1.331 +
   1.332 +    typedef SkBitmapDevice INHERITED;
   1.333 +
   1.334 +    // TODO(edisonn): Only SkDocument_PDF and SkPDFImageShader should be able to create
   1.335 +    // an SkPDFDevice
   1.336 +    //friend class SkDocument_PDF;
   1.337 +    //friend class SkPDFImageShader;
   1.338 +};
   1.339 +
   1.340 +#endif

mercurial