1fb62b3d423fa34c672df42f47017dbef087d19e9halcanary/*
2fb62b3d423fa34c672df42f47017dbef087d19e9halcanary * Copyright 2015 Google Inc.
3fb62b3d423fa34c672df42f47017dbef087d19e9halcanary *
4fb62b3d423fa34c672df42f47017dbef087d19e9halcanary * Use of this source code is governed by a BSD-style license that can be
5fb62b3d423fa34c672df42f47017dbef087d19e9halcanary * found in the LICENSE file.
6fb62b3d423fa34c672df42f47017dbef087d19e9halcanary */
7fb62b3d423fa34c672df42f47017dbef087d19e9halcanary#ifndef SkPDFCanon_DEFINED
8fb62b3d423fa34c672df42f47017dbef087d19e9halcanary#define SkPDFCanon_DEFINED
9fb62b3d423fa34c672df42f47017dbef087d19e9halcanary
107a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary#include "SkBitmap.h"
11be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary#include "SkPDFGraphicState.h"
12fb62b3d423fa34c672df42f47017dbef087d19e9halcanary#include "SkPDFShader.h"
13712fdf7603c62820b21174da9b0a2071c174936bhalcanary#include "SkPixelSerializer.h"
14fb62b3d423fa34c672df42f47017dbef087d19e9halcanary#include "SkTDArray.h"
15be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary#include "SkTHash.h"
16fb62b3d423fa34c672df42f47017dbef087d19e9halcanary
17fb62b3d423fa34c672df42f47017dbef087d19e9halcanaryclass SkPDFFont;
18fb62b3d423fa34c672df42f47017dbef087d19e9halcanaryclass SkPaint;
197a14b310d6c618fa2151d93a43b29f9599adc32ahalcanaryclass SkImage;
207a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary
217a14b310d6c618fa2151d93a43b29f9599adc32ahalcanaryclass SkBitmapKey {
227a14b310d6c618fa2151d93a43b29f9599adc32ahalcanarypublic:
237a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    SkBitmapKey() : fSubset(SkIRect::MakeEmpty()), fGenID(0) {}
247a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    explicit SkBitmapKey(const SkBitmap& bm)
257a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary        : fSubset(bm.getSubset()), fGenID(bm.getGenerationID()) {}
267a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    bool operator==(const SkBitmapKey& rhs) const {
277a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary        return fGenID == rhs.fGenID && fSubset == rhs.fSubset;
287a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    }
297a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary
307a14b310d6c618fa2151d93a43b29f9599adc32ahalcanaryprivate:
317a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    SkIRect fSubset;
327a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    uint32_t fGenID;
337a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary};
34fb62b3d423fa34c672df42f47017dbef087d19e9halcanary
35792c80f5a7b66e75d42664ccb298f31962c6654chalcanary/**
36792c80f5a7b66e75d42664ccb298f31962c6654chalcanary *  The SkPDFCanon canonicalizes objects across PDF pages(SkPDFDevices).
37792c80f5a7b66e75d42664ccb298f31962c6654chalcanary *
38792c80f5a7b66e75d42664ccb298f31962c6654chalcanary *  The PDF backend works correctly if:
39792c80f5a7b66e75d42664ccb298f31962c6654chalcanary *  -  There is no more than one SkPDFCanon for each thread.
40792c80f5a7b66e75d42664ccb298f31962c6654chalcanary *  -  Every SkPDFDevice is given a pointer to a SkPDFCanon on creation.
41792c80f5a7b66e75d42664ccb298f31962c6654chalcanary *  -  All SkPDFDevices in a document share the same SkPDFCanon.
42792c80f5a7b66e75d42664ccb298f31962c6654chalcanary *  The SkDocument_PDF class makes this happen by owning a single
43792c80f5a7b66e75d42664ccb298f31962c6654chalcanary *  SkPDFCanon.
44792c80f5a7b66e75d42664ccb298f31962c6654chalcanary *
452e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary *  The addFoo() methods will ref the Foo; the canon's destructor will
462e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary *  call foo->unref() on all of these objects.
472e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary *
482e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary *  The findFoo() methods do not change the ref count of the Foo
492e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary *  objects.
50792c80f5a7b66e75d42664ccb298f31962c6654chalcanary */
51fb62b3d423fa34c672df42f47017dbef087d19e9halcanaryclass SkPDFCanon : SkNoncopyable {
52fb62b3d423fa34c672df42f47017dbef087d19e9halcanarypublic:
532e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary    ~SkPDFCanon() { this->reset(); }
542e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary
552e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary    // reset to original setting, unrefs all objects.
562e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary    void reset();
57fb62b3d423fa34c672df42f47017dbef087d19e9halcanary
5896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    // Returns exact match if there is one.  If not, it returns nullptr.
59fb62b3d423fa34c672df42f47017dbef087d19e9halcanary    // If there is no exact match, but there is a related font, we
6096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    // still return nullptr, but also set *relatedFont.
61fb62b3d423fa34c672df42f47017dbef087d19e9halcanary    SkPDFFont* findFont(uint32_t fontID,
62fb62b3d423fa34c672df42f47017dbef087d19e9halcanary                        uint16_t glyphID,
63fb62b3d423fa34c672df42f47017dbef087d19e9halcanary                        SkPDFFont** relatedFont) const;
64fb62b3d423fa34c672df42f47017dbef087d19e9halcanary    void addFont(SkPDFFont* font, uint32_t fontID, uint16_t fGlyphID);
65fb62b3d423fa34c672df42f47017dbef087d19e9halcanary
66530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary    SkPDFFunctionShader* findFunctionShader(const SkPDFShader::State&) const;
67530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary    void addFunctionShader(SkPDFFunctionShader*);
68530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary
69530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary    SkPDFAlphaFunctionShader* findAlphaShader(const SkPDFShader::State&) const;
70530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary    void addAlphaShader(SkPDFAlphaFunctionShader*);
71530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary
72530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary    SkPDFImageShader* findImageShader(const SkPDFShader::State&) const;
73530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary    void addImageShader(SkPDFImageShader*);
74fb62b3d423fa34c672df42f47017dbef087d19e9halcanary
75be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary    const SkPDFGraphicState* findGraphicState(const SkPDFGraphicState&) const;
76be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary    void addGraphicState(const SkPDFGraphicState*);
77fb62b3d423fa34c672df42f47017dbef087d19e9halcanary
787a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    SkPDFObject* findPDFBitmap(const SkImage* image) const;
797a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    void addPDFBitmap(uint32_t imageUniqueID, SkPDFObject*);
807a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    const SkImage* bitmapToImage(const SkBitmap&);
81a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary
8266a82f3872abf4ebb98b3915b2a9ecc73ad352c5halcanary    SkTHashMap<uint32_t, bool> fCanEmbedTypeface;
8366a82f3872abf4ebb98b3915b2a9ecc73ad352c5halcanary
84712fdf7603c62820b21174da9b0a2071c174936bhalcanary    SkAutoTUnref<SkPixelSerializer> fPixelSerializer;
85712fdf7603c62820b21174da9b0a2071c174936bhalcanary
86fb62b3d423fa34c672df42f47017dbef087d19e9halcanaryprivate:
87fb62b3d423fa34c672df42f47017dbef087d19e9halcanary    struct FontRec {
88fb62b3d423fa34c672df42f47017dbef087d19e9halcanary        SkPDFFont* fFont;
89fb62b3d423fa34c672df42f47017dbef087d19e9halcanary        uint32_t fFontID;
90fb62b3d423fa34c672df42f47017dbef087d19e9halcanary        uint16_t fGlyphID;
91fb62b3d423fa34c672df42f47017dbef087d19e9halcanary    };
92fb62b3d423fa34c672df42f47017dbef087d19e9halcanary    SkTDArray<FontRec> fFontRecords;
93fb62b3d423fa34c672df42f47017dbef087d19e9halcanary
94530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary    SkTDArray<SkPDFFunctionShader*> fFunctionShaderRecords;
95530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary
96530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary    SkTDArray<SkPDFAlphaFunctionShader*> fAlphaShaderRecords;
97530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary
98530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary    SkTDArray<SkPDFImageShader*> fImageShaderRecords;
99fb62b3d423fa34c672df42f47017dbef087d19e9halcanary
100be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary    struct WrapGS {
10196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        explicit WrapGS(const SkPDFGraphicState* ptr = nullptr) : fPtr(ptr) {}
102be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary        const SkPDFGraphicState* fPtr;
103be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary        bool operator==(const WrapGS& rhs) const {
104be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary            SkASSERT(fPtr);
105be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary            SkASSERT(rhs.fPtr);
106be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary            return *fPtr == *rhs.fPtr;
107be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary        }
108c8d1dd48c01f562cfffe64da0e5cee5ed2713541mtklein        struct Hash {
109c8d1dd48c01f562cfffe64da0e5cee5ed2713541mtklein            uint32_t operator()(const WrapGS& w) const {
110c8d1dd48c01f562cfffe64da0e5cee5ed2713541mtklein                SkASSERT(w.fPtr);
111c8d1dd48c01f562cfffe64da0e5cee5ed2713541mtklein                return w.fPtr->hash();
112c8d1dd48c01f562cfffe64da0e5cee5ed2713541mtklein            }
113c8d1dd48c01f562cfffe64da0e5cee5ed2713541mtklein        };
114be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary    };
115be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary    SkTHashSet<WrapGS, WrapGS::Hash> fGraphicStateRecords;
1161b5c604d9d344537941b11b136348edfc39f236chalcanary
1177a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    SkTHashMap<SkBitmapKey, const SkImage*> fBitmapToImageMap;
1187a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    SkTHashMap<uint32_t /*ImageUniqueID*/, SkPDFObject*> fPDFBitmapMap;
119fb62b3d423fa34c672df42f47017dbef087d19e9halcanary};
120fb62b3d423fa34c672df42f47017dbef087d19e9halcanary#endif  // SkPDFCanon_DEFINED
121