19b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
39b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
69b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org */
79b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
89b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org#ifndef SkPDFDevice_DEFINED
99b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org#define SkPDFDevice_DEFINED
109b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
115e00989a283111cef05bed8102e45c16651e43e4commit-bot@chromium.org#include "SkBitmap.h"
12b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org#include "SkCanvas.h"
13d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkClipStack.h"
14f0fb92985ccbbfbe351d1e3969d784a067a68bf7Mike Reed#include "SkClipStackDevice.h"
1591fcb3ed58845ddd5afa98a7150f3024d87c7425halcanary#include "SkData.h"
16a518086928494319b8968abc09808eff492c194fvandebo@chromium.org#include "SkPaint.h"
17238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org#include "SkRect.h"
189fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org#include "SkRefCnt.h"
194ed2f01cf6f3a63d5185ea5b442549d20ce2ec16halcanary#include "SkSinglyLinkedList.h"
209fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org#include "SkStream.h"
21b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com#include "SkTDArray.h"
224ed2f01cf6f3a63d5185ea5b442549d20ce2ec16halcanary#include "SkTextBlob.h"
232be7e01382ee9c036de9c09585677dfd25d70253halcanary
24f50ff39f47850b86251b44381983d3b3b4f929b3Hal Canaryclass SkImageSubset;
25b8d6af169bf631dcb68ba5a796436434ff78be65martina.kollarovaclass SkPath;
269b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.orgclass SkPDFArray;
27a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanaryclass SkPDFCanon;
289b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.orgclass SkPDFDevice;
29989da4a32cd6823359f31c971c3b3f31425e905ehalcanaryclass SkPDFDocument;
309b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.orgclass SkPDFDict;
3128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.orgclass SkPDFFont;
329b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.orgclass SkPDFObject;
334b1e17edc78c0313d5cb8a415f816f654cdfa417halcanaryclass SkPDFStream;
34a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comclass SkRRect;
359b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
369b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org/** \class SkPDFDevice
379b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
389b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org    The drawing context for the PDF backend.
399b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org*/
40f0fb92985ccbbfbe351d1e3969d784a067a68bf7Mike Reedclass SkPDFDevice final : public SkClipStackDevice {
419b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.orgpublic:
42a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    /** Create a PDF drawing context.  SkPDFDevice applies a
43a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary     *  scale-and-translate transform to move the origin from the
44a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary     *  bottom left (PDF default) to the top left (Skia default).
45a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary     *  @param pageSize Page size in point units.
46a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary     *         1 point == 127/360 mm == 1/72 inch
47a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary     *  @param rasterDpi the DPI at which features without native PDF
48a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary     *         support will be rasterized (e.g. draw image with
49a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary     *         perspective, draw text with perspective, ...).  A
50a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary     *         larger DPI would create a PDF that reflects the
51a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary     *         original intent with better fidelity, but it can make
52a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary     *         for larger PDF files too, which would use more memory
53a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary     *         while rendering, and it would be slower to be processed
54a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary     *         or sent online or to printer.  A good choice is
55a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary     *         SK_ScalarDefaultRasterDPI(72.0f).
56989da4a32cd6823359f31c971c3b3f31425e905ehalcanary     *  @param SkPDFDocument.  A non-null pointer back to the
57989da4a32cd6823359f31c971c3b3f31425e905ehalcanary     *         document.  The document is repsonsible for
58989da4a32cd6823359f31c971c3b3f31425e905ehalcanary     *         de-duplicating across pages (via the SkPDFCanon) and
59989da4a32cd6823359f31c971c3b3f31425e905ehalcanary     *         for early serializing of large immutable objects, such
60989da4a32cd6823359f31c971c3b3f31425e905ehalcanary     *         as images (via SkPDFDocument::serialize()).
619b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org     */
62a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    static SkPDFDevice* Create(SkISize pageSize,
63a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary                               SkScalar rasterDpi,
64989da4a32cd6823359f31c971c3b3f31425e905ehalcanary                               SkPDFDocument* doc) {
65989da4a32cd6823359f31c971c3b3f31425e905ehalcanary        return new SkPDFDevice(pageSize, rasterDpi, doc, true);
66a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    }
67a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary
68a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    /** Create a PDF drawing context without fipping the y-axis. */
69a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    static SkPDFDevice* CreateUnflipped(SkISize pageSize,
70a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary                                        SkScalar rasterDpi,
71989da4a32cd6823359f31c971c3b3f31425e905ehalcanary                                        SkPDFDocument* doc) {
72989da4a32cd6823359f31c971c3b3f31425e905ehalcanary        return new SkPDFDevice(pageSize, rasterDpi, doc, false);
73a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    }
74a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary
75d3b65972aad96453ff4510caa3e25a2b847c6d1eBrian Salomon    ~SkPDFDevice() override;
769b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
779b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org    /** These are called inside the per-device-layer loop for each draw call.
789b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org     When these are called, we have already applied any saveLayer operations,
799b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org     and are handling any looping from the paint, and any effects from the
809b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org     DrawFilter.
819b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org     */
82a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void drawPaint(const SkPaint& paint) override;
83a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void drawPoints(SkCanvas::PointMode mode,
84fa4f6cba2f9260cec345ec51fb3687c20c50fa61tfarina                    size_t count, const SkPoint[],
8536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                    const SkPaint& paint) override;
86a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void drawRect(const SkRect& r, const SkPaint& paint) override;
87a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void drawOval(const SkRect& oval, const SkPaint& paint) override;
88a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void drawRRect(const SkRRect& rr, const SkPaint& paint) override;
89a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void drawPath(const SkPath& origpath,
90fa4f6cba2f9260cec345ec51fb3687c20c50fa61tfarina                  const SkPaint& paint, const SkMatrix* prePathMatrix,
9136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                  bool pathIsMutable) override;
92a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void drawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
93562fe4767cc73e08a4e039362bc0336aea66ecfbreed                        const SkRect& dst, const SkPaint&, SkCanvas::SrcRectConstraint) override;
94a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void drawBitmap(const SkBitmap& bitmap,
9536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                    const SkMatrix& matrix, const SkPaint&) override;
96a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void drawSprite(const SkBitmap& bitmap, int x, int y,
9736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                    const SkPaint& paint) override;
98a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void drawImage(const SkImage*,
997a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary                   SkScalar x,
1007a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary                   SkScalar y,
1017a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary                   const SkPaint&) override;
102a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void drawImageRect(const SkImage*,
1037a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary                       const SkRect* src,
1047a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary                       const SkRect& dst,
1057a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary                       const SkPaint&,
1067a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary                       SkCanvas::SrcRectConstraint) override;
107a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void drawText(const void* text, size_t len,
10836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                  SkScalar x, SkScalar y, const SkPaint&) override;
109a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void drawPosText(const void* text, size_t len,
110fa4f6cba2f9260cec345ec51fb3687c20c50fa61tfarina                     const SkScalar pos[], int scalarsPerPos,
11136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                     const SkPoint& offset, const SkPaint&) override;
112a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y,
113e06ca96174b99d451db17540a8df540035ab020dhalcanary                      const SkPaint &, SkDrawFilter*) override;
1142f6b5a47a50cdd218bc3302273be3a4a71add8fbMike Reed    void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) override;
115a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void drawDevice(SkBaseDevice*, int x, int y,
11636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                    const SkPaint&) override;
1179b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
1189b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org    // PDF specific methods.
1199b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
1208103a34300c5de2e85793a96c4738a33fc6eb46dhalcanary    /** Create the resource dictionary for this device. */
1218103a34300c5de2e85793a96c4738a33fc6eb46dhalcanary    sk_sp<SkPDFDict> makeResourceDict() const;
1229b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
123ef6c50a80f77e6da84e198a34755dd42b1b0cf1ewangxianzhu    /** Add our annotations (link to urls and destinations) to the supplied
124ef6c50a80f77e6da84e198a34755dd42b1b0cf1ewangxianzhu     *  array.
125ef6c50a80f77e6da84e198a34755dd42b1b0cf1ewangxianzhu     *  @param array Array to add annotations to.
126ef6c50a80f77e6da84e198a34755dd42b1b0cf1ewangxianzhu     */
127ef6c50a80f77e6da84e198a34755dd42b1b0cf1ewangxianzhu    void appendAnnotations(SkPDFArray* array) const;
128ef6c50a80f77e6da84e198a34755dd42b1b0cf1ewangxianzhu
129b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com    /** Add our named destinations to the supplied dictionary.
130b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com     *  @param dict  Dictionary to add destinations to.
131b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com     *  @param page  The PDF object representing the page for this device.
132b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com     */
1336d622703e578eddc64ab4e3340d0ab0033268799halcanary    void appendDestinations(SkPDFDict* dict, SkPDFObject* page) const;
134b58772f86659cfe0e8d9247fcee878dddd8fdad9epoger@google.com
1358103a34300c5de2e85793a96c4738a33fc6eb46dhalcanary    /** Returns a copy of the media box for this device. */
1368103a34300c5de2e85793a96c4738a33fc6eb46dhalcanary    sk_sp<SkPDFArray> copyMediaBox() const;
1379b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
1388103a34300c5de2e85793a96c4738a33fc6eb46dhalcanary    /** Returns a SkStream with the page contents.
1399b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org     */
1405f939ab658a228dce34a3b14a545638407150b92mtklein    std::unique_ptr<SkStreamAsset> content() const;
1419b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
142989da4a32cd6823359f31c971c3b3f31425e905ehalcanary    SkPDFCanon* getCanon() const;
14326b5d15dab81883fac05a2d3685ca6e3a3459678halcanary
1442be7e01382ee9c036de9c09585677dfd25d70253halcanary    // It is important to not confuse GraphicStateEntry with SkPDFGraphicState, the
1452be7e01382ee9c036de9c09585677dfd25d70253halcanary    // later being our representation of an object in the PDF file.
1462be7e01382ee9c036de9c09585677dfd25d70253halcanary    struct GraphicStateEntry {
1472be7e01382ee9c036de9c09585677dfd25d70253halcanary        GraphicStateEntry();
1482be7e01382ee9c036de9c09585677dfd25d70253halcanary
1492be7e01382ee9c036de9c09585677dfd25d70253halcanary        // Compare the fields we care about when setting up a new content entry.
1502be7e01382ee9c036de9c09585677dfd25d70253halcanary        bool compareInitialState(const GraphicStateEntry& b);
1512be7e01382ee9c036de9c09585677dfd25d70253halcanary
1522be7e01382ee9c036de9c09585677dfd25d70253halcanary        SkMatrix fMatrix;
1532be7e01382ee9c036de9c09585677dfd25d70253halcanary        // We can't do set operations on Paths, though PDF natively supports
1542be7e01382ee9c036de9c09585677dfd25d70253halcanary        // intersect.  If the clip stack does anything other than intersect,
1552be7e01382ee9c036de9c09585677dfd25d70253halcanary        // we have to fall back to the region.  Treat fClipStack as authoritative.
1562be7e01382ee9c036de9c09585677dfd25d70253halcanary        // See https://bugs.skia.org/221
1572be7e01382ee9c036de9c09585677dfd25d70253halcanary        SkClipStack fClipStack;
1582be7e01382ee9c036de9c09585677dfd25d70253halcanary
1592be7e01382ee9c036de9c09585677dfd25d70253halcanary        // When emitting the content entry, we will ensure the graphic state
1602be7e01382ee9c036de9c09585677dfd25d70253halcanary        // is set to these values first.
1612be7e01382ee9c036de9c09585677dfd25d70253halcanary        SkColor fColor;
1622be7e01382ee9c036de9c09585677dfd25d70253halcanary        SkScalar fTextScaleX;  // Zero means we don't care what the value is.
1632be7e01382ee9c036de9c09585677dfd25d70253halcanary        SkPaint::Style fTextFill;  // Only if TextScaleX is non-zero.
1642be7e01382ee9c036de9c09585677dfd25d70253halcanary        int fShaderIndex;
1652be7e01382ee9c036de9c09585677dfd25d70253halcanary        int fGraphicStateIndex;
1662be7e01382ee9c036de9c09585677dfd25d70253halcanary    };
1672be7e01382ee9c036de9c09585677dfd25d70253halcanary
16873a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.comprotected:
169e8f3062a36d3682f4019309a32b5b84dc9eddf8creed    sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&) override;
17073a7ea3ae0d37ee28f90d6b38c49fda052638253edisonn@google.com
171a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void drawAnnotation(const SkRect&, const char key[], SkData* value) override;
172f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
173a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&) override;
174e51c356ae4e074b9c286c50a4efce11205f7463creed    sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&) override;
175e51c356ae4e074b9c286c50a4efce11205f7463creed    sk_sp<SkSpecialImage> makeSpecial(const SkImage*) override;
176e51c356ae4e074b9c286c50a4efce11205f7463creed    sk_sp<SkSpecialImage> snapSpecial() override;
17704a44d0fd45f5596c716e99e7a3bbcc03db0e05abrianosman    SkImageFilterCache* getImageFilterCache() override;
178e51c356ae4e074b9c286c50a4efce11205f7463creed
1799b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.orgprivate:
18091fcb3ed58845ddd5afa98a7150f3024d87c7425halcanary    struct RectWithData {
18191fcb3ed58845ddd5afa98a7150f3024d87c7425halcanary        SkRect rect;
182d7b2885b90c6d248d8188cdb3720ea9150568a89halcanary        sk_sp<SkData> data;
18391fcb3ed58845ddd5afa98a7150f3024d87c7425halcanary        RectWithData(const SkRect& rect, SkData* data)
18491fcb3ed58845ddd5afa98a7150f3024d87c7425halcanary            : rect(rect), data(SkRef(data)) {}
1859be372041ec331f1b04c99890f92d24c59bf9dadhalcanary        RectWithData(RectWithData&&) = default;
1869be372041ec331f1b04c99890f92d24c59bf9dadhalcanary        RectWithData& operator=(RectWithData&& other) = default;
18791fcb3ed58845ddd5afa98a7150f3024d87c7425halcanary    };
18891fcb3ed58845ddd5afa98a7150f3024d87c7425halcanary
18991fcb3ed58845ddd5afa98a7150f3024d87c7425halcanary    struct NamedDestination {
190d7b2885b90c6d248d8188cdb3720ea9150568a89halcanary        sk_sp<SkData> nameData;
19191fcb3ed58845ddd5afa98a7150f3024d87c7425halcanary        SkPoint point;
19291fcb3ed58845ddd5afa98a7150f3024d87c7425halcanary        NamedDestination(SkData* nameData, const SkPoint& point)
19391fcb3ed58845ddd5afa98a7150f3024d87c7425halcanary            : nameData(SkRef(nameData)), point(point) {}
1949be372041ec331f1b04c99890f92d24c59bf9dadhalcanary        NamedDestination(NamedDestination&&) = default;
1959be372041ec331f1b04c99890f92d24c59bf9dadhalcanary        NamedDestination& operator=(NamedDestination&&) = default;
19691fcb3ed58845ddd5afa98a7150f3024d87c7425halcanary    };
19791fcb3ed58845ddd5afa98a7150f3024d87c7425halcanary
198769fa6a013baca6d7404e2bf096a34a7e3635fa5ctguil@chromium.org    // TODO(vandebo): push most of SkPDFDevice's state into a core object in
199b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    // order to get the right access levels without using friend.
20013d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org    friend class ScopedContentEntry;
201a0c7edbb0804144ab320951db5c741eea247fc0fvandebo@chromium.org
202152612938020fa46999f33668027d5bc0f7afd18ctguil@chromium.org    SkISize fPageSize;
20375f97e452e8f2ee55cd2b283df7d7734f48bc2bfvandebo@chromium.org    SkMatrix fInitialTransform;
2049fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    SkClipStack fExistingClipStack;
205ef6c50a80f77e6da84e198a34755dd42b1b0cf1ewangxianzhu
20691fcb3ed58845ddd5afa98a7150f3024d87c7425halcanary    SkTArray<RectWithData> fLinkToURLs;
20791fcb3ed58845ddd5afa98a7150f3024d87c7425halcanary    SkTArray<RectWithData> fLinkToDestinations;
20891fcb3ed58845ddd5afa98a7150f3024d87c7425halcanary    SkTArray<NamedDestination> fNamedDestinations;
2099b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
210be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary    SkTDArray<SkPDFObject*> fGraphicStateResources;
2119b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org    SkTDArray<SkPDFObject*> fXObjectResources;
21228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org    SkTDArray<SkPDFFont*> fFontResources;
213421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org    SkTDArray<SkPDFObject*> fShaderResources;
2149b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
2152be7e01382ee9c036de9c09585677dfd25d70253halcanary    struct ContentEntry {
2162be7e01382ee9c036de9c09585677dfd25d70253halcanary        GraphicStateEntry fState;
2172be7e01382ee9c036de9c09585677dfd25d70253halcanary        SkDynamicMemoryWStream fContent;
2182be7e01382ee9c036de9c09585677dfd25d70253halcanary    };
2192be7e01382ee9c036de9c09585677dfd25d70253halcanary    SkSinglyLinkedList<ContentEntry> fContentEntries;
2208dcf74f27690476193f5d4ca34fba2e87ca7c98dctguil@chromium.org
2218c294900f31d8d032b62182f011019276d27d5d0commit-bot@chromium.org    SkScalar fRasterDpi;
222d9dfa18372119c8e1318125d2075fa80e0819094edisonn@google.com
223989da4a32cd6823359f31c971c3b3f31425e905ehalcanary    SkPDFDocument* fDocument;
224a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    ////////////////////////////////////////////////////////////////////////////
225a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary
226a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary    SkPDFDevice(SkISize pageSize,
227a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary                SkScalar rasterDpi,
228989da4a32cd6823359f31c971c3b3f31425e905ehalcanary                SkPDFDocument* doc,
229a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary                bool flip);
230a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary
23136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override;
232e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
23377bcaa324a574584331322d98768582d9232f7fcvandebo@chromium.org    void init();
2343c35fb3310c22eb0141c8f39c5423f7bcd42adffhalcanary    void cleanUp();
2354b1e17edc78c0313d5cb8a415f816f654cdfa417halcanary    sk_sp<SkPDFObject> makeFormXObjectFromDevice();
2369fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
2373b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    void drawFormXObjectWithMask(int xObjectIndex,
238dabd4f0b799318cb6e90b69ae1ec0ed0b6d32f60halcanary                                 sk_sp<SkPDFObject> mask,
239a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed                                 const SkClipStack& clipStack,
240374772bd61951f01bf84fe17bf53d8867681c9aereed                                 SkBlendMode,
241481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org                                 bool invertClip);
242466f3d66f09285d2d988315bacde573a5359ce54vandebo@chromium.org
243b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    // If the paint or clip is such that we shouldn't draw anything, this
24496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    // returns nullptr and does not create a content entry.
245b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    // setUpContentEntry and finishContentEntry can be used directly, but
24613d14a9dbd2cf0a9654045cc967e92626690631avandebo@chromium.org    // the preferred method is to use the ScopedContentEntry helper class.
247a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    ContentEntry* setUpContentEntry(const SkClipStack& clipStack,
248b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                                    const SkMatrix& matrix,
249b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                                    const SkPaint& paint,
250b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org                                    bool hasText,
251dabd4f0b799318cb6e90b69ae1ec0ed0b6d32f60halcanary                                    sk_sp<SkPDFObject>* dst);
252374772bd61951f01bf84fe17bf53d8867681c9aereed    void finishContentEntry(SkBlendMode, sk_sp<SkPDFObject> dst, SkPath* shape);
253481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org    bool isContentEmpty();
254481aef68333e01c19badda456d8e60bd1f1bee2avandebo@chromium.org
2559fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org    void populateGraphicStateEntryFromPaint(const SkMatrix& matrix,
2569fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                                            const SkClipStack& clipStack,
2579fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                                            const SkPaint& paint,
2589fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                                            bool hasText,
2599fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org                                            GraphicStateEntry* entry);
260be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary    int addGraphicStateResource(SkPDFObject* gs);
2613b416216d1e90cb8b1bba41bb95806fe2d40da88vandebo@chromium.org    int addXObjectResource(SkPDFObject* xObject);
2629fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
2639db86bb9cd1b77be0afc504ccc07026e4282d7e7ctguil@chromium.org    int getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID);
2649fbdf875183f5142b8e0ba46ab430cc46ad701bfvandebo@chromium.org
2654ed2f01cf6f3a63d5185ea5b442549d20ce2ec16halcanary
266a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void internalDrawText( const void*, size_t, const SkScalar pos[],
267e06ca96174b99d451db17540a8df540035ab020dhalcanary                          SkTextBlob::GlyphPositioning, SkPoint, const SkPaint&,
268e06ca96174b99d451db17540a8df540035ab020dhalcanary                          const uint32_t*, uint32_t, const char*);
2694ed2f01cf6f3a63d5185ea5b442549d20ce2ec16halcanary
270b069c8cfcd5df285193eb334b3bc33438782e8davandebo@chromium.org    void internalDrawPaint(const SkPaint& paint, ContentEntry* contentEntry);
271a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary
272a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary    void internalDrawImage(const SkMatrix& origMatrix,
273a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed                           const SkClipStack& clipStack,
274f50ff39f47850b86251b44381983d3b3b4f929b3Hal Canary                           SkImageSubset imageSubset,
2757a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary                           const SkPaint& paint);
2769b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
277a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void internalDrawPath(const SkClipStack&,
278a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed                          const SkMatrix&,
279a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed                          const SkPath&,
280a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed                          const SkPaint&,
281a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed                          const SkMatrix* prePathMatrix,
282a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed                          bool pathIsMutable);
283a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
284a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    bool handleInversePath(const SkPath& origPath,
285a9ebd161a7c08515f0c4bd885e61c4b52688ececedisonn@google.com                           const SkPaint& paint, bool pathIsMutable,
28696fcdcc219d2a0d3579719b84b28bede76efba64halcanary                           const SkMatrix* prePathMatrix = nullptr);
287238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org
288f0fb92985ccbbfbe351d1e3969d784a067a68bf7Mike Reed    typedef SkClipStackDevice INHERITED;
2895e00989a283111cef05bed8102e45c16651e43e4commit-bot@chromium.org
2905e00989a283111cef05bed8102e45c16651e43e4commit-bot@chromium.org    // TODO(edisonn): Only SkDocument_PDF and SkPDFImageShader should be able to create
2915e00989a283111cef05bed8102e45c16651e43e4commit-bot@chromium.org    // an SkPDFDevice
2925e00989a283111cef05bed8102e45c16651e43e4commit-bot@chromium.org    //friend class SkDocument_PDF;
2935e00989a283111cef05bed8102e45c16651e43e4commit-bot@chromium.org    //friend class SkPDFImageShader;
2949b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org};
2959b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org
2969b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org#endif
297