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
10be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary#include "SkPDFGraphicState.h"
11fb62b3d423fa34c672df42f47017dbef087d19e9halcanary#include "SkPDFShader.h"
12fb62b3d423fa34c672df42f47017dbef087d19e9halcanary#include "SkTDArray.h"
13be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary#include "SkTHash.h"
14fb62b3d423fa34c672df42f47017dbef087d19e9halcanary
151b5c604d9d344537941b11b136348edfc39f236chalcanaryclass SkBitmap;
16fb62b3d423fa34c672df42f47017dbef087d19e9halcanaryclass SkPDFFont;
171b5c604d9d344537941b11b136348edfc39f236chalcanaryclass SkPDFBitmap;
18fb62b3d423fa34c672df42f47017dbef087d19e9halcanaryclass SkPaint;
19fb62b3d423fa34c672df42f47017dbef087d19e9halcanary
20792c80f5a7b66e75d42664ccb298f31962c6654chalcanary/**
21792c80f5a7b66e75d42664ccb298f31962c6654chalcanary *  The SkPDFCanon canonicalizes objects across PDF pages(SkPDFDevices).
22792c80f5a7b66e75d42664ccb298f31962c6654chalcanary *
23792c80f5a7b66e75d42664ccb298f31962c6654chalcanary *  The PDF backend works correctly if:
24792c80f5a7b66e75d42664ccb298f31962c6654chalcanary *  -  There is no more than one SkPDFCanon for each thread.
25792c80f5a7b66e75d42664ccb298f31962c6654chalcanary *  -  Every SkPDFDevice is given a pointer to a SkPDFCanon on creation.
26792c80f5a7b66e75d42664ccb298f31962c6654chalcanary *  -  All SkPDFDevices in a document share the same SkPDFCanon.
27792c80f5a7b66e75d42664ccb298f31962c6654chalcanary *  The SkDocument_PDF class makes this happen by owning a single
28792c80f5a7b66e75d42664ccb298f31962c6654chalcanary *  SkPDFCanon.
29792c80f5a7b66e75d42664ccb298f31962c6654chalcanary *
302e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary *  The addFoo() methods will ref the Foo; the canon's destructor will
312e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary *  call foo->unref() on all of these objects.
322e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary *
332e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary *  The findFoo() methods do not change the ref count of the Foo
342e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary *  objects.
35792c80f5a7b66e75d42664ccb298f31962c6654chalcanary */
36fb62b3d423fa34c672df42f47017dbef087d19e9halcanaryclass SkPDFCanon : SkNoncopyable {
37fb62b3d423fa34c672df42f47017dbef087d19e9halcanarypublic:
382e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary    ~SkPDFCanon() { this->reset(); }
392e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary
402e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary    // reset to original setting, unrefs all objects.
412e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary    void reset();
42fb62b3d423fa34c672df42f47017dbef087d19e9halcanary
43fb62b3d423fa34c672df42f47017dbef087d19e9halcanary    // Returns exact match if there is one.  If not, it returns NULL.
44fb62b3d423fa34c672df42f47017dbef087d19e9halcanary    // If there is no exact match, but there is a related font, we
45fb62b3d423fa34c672df42f47017dbef087d19e9halcanary    // still return NULL, but also set *relatedFont.
46fb62b3d423fa34c672df42f47017dbef087d19e9halcanary    SkPDFFont* findFont(uint32_t fontID,
47fb62b3d423fa34c672df42f47017dbef087d19e9halcanary                        uint16_t glyphID,
48fb62b3d423fa34c672df42f47017dbef087d19e9halcanary                        SkPDFFont** relatedFont) const;
49fb62b3d423fa34c672df42f47017dbef087d19e9halcanary    void addFont(SkPDFFont* font, uint32_t fontID, uint16_t fGlyphID);
50fb62b3d423fa34c672df42f47017dbef087d19e9halcanary
51530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary    SkPDFFunctionShader* findFunctionShader(const SkPDFShader::State&) const;
52530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary    void addFunctionShader(SkPDFFunctionShader*);
53530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary
54530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary    SkPDFAlphaFunctionShader* findAlphaShader(const SkPDFShader::State&) const;
55530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary    void addAlphaShader(SkPDFAlphaFunctionShader*);
56530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary
57530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary    SkPDFImageShader* findImageShader(const SkPDFShader::State&) const;
58530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary    void addImageShader(SkPDFImageShader*);
59fb62b3d423fa34c672df42f47017dbef087d19e9halcanary
60be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary    const SkPDFGraphicState* findGraphicState(const SkPDFGraphicState&) const;
61be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary    void addGraphicState(const SkPDFGraphicState*);
62fb62b3d423fa34c672df42f47017dbef087d19e9halcanary
631b5c604d9d344537941b11b136348edfc39f236chalcanary    SkPDFBitmap* findBitmap(const SkBitmap&) const;
641b5c604d9d344537941b11b136348edfc39f236chalcanary    void addBitmap(SkPDFBitmap*);
65a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary
66fb62b3d423fa34c672df42f47017dbef087d19e9halcanaryprivate:
67fb62b3d423fa34c672df42f47017dbef087d19e9halcanary    struct FontRec {
68fb62b3d423fa34c672df42f47017dbef087d19e9halcanary        SkPDFFont* fFont;
69fb62b3d423fa34c672df42f47017dbef087d19e9halcanary        uint32_t fFontID;
70fb62b3d423fa34c672df42f47017dbef087d19e9halcanary        uint16_t fGlyphID;
71fb62b3d423fa34c672df42f47017dbef087d19e9halcanary    };
72fb62b3d423fa34c672df42f47017dbef087d19e9halcanary    SkTDArray<FontRec> fFontRecords;
73fb62b3d423fa34c672df42f47017dbef087d19e9halcanary
74530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary    SkTDArray<SkPDFFunctionShader*> fFunctionShaderRecords;
75530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary
76530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary    SkTDArray<SkPDFAlphaFunctionShader*> fAlphaShaderRecords;
77530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary
78530ea8e24bc88f2d7973c35a703f18c1dafb56dchalcanary    SkTDArray<SkPDFImageShader*> fImageShaderRecords;
79fb62b3d423fa34c672df42f47017dbef087d19e9halcanary
80be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary    struct WrapGS {
81be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary        explicit WrapGS(const SkPDFGraphicState* ptr = NULL) : fPtr(ptr) {}
82be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary        const SkPDFGraphicState* fPtr;
83be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary        bool operator==(const WrapGS& rhs) const {
84be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary            SkASSERT(fPtr);
85be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary            SkASSERT(rhs.fPtr);
86be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary            return *fPtr == *rhs.fPtr;
87be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary        }
88be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary        static uint32_t Hash(const WrapGS& w) {
89be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary            SkASSERT(w.fPtr);
90be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary            return w.fPtr->hash();
91be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary        }
92be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary    };
93be27a118c277af23377d38e9b3bfd3fcc276114fhalcanary    SkTHashSet<WrapGS, WrapGS::Hash> fGraphicStateRecords;
941b5c604d9d344537941b11b136348edfc39f236chalcanary
951b5c604d9d344537941b11b136348edfc39f236chalcanary    SkTDArray<SkPDFBitmap*> fBitmapRecords;
96fb62b3d423fa34c672df42f47017dbef087d19e9halcanary};
97fb62b3d423fa34c672df42f47017dbef087d19e9halcanary#endif  // SkPDFCanon_DEFINED
98