1 /*
2  * Copyright 2015 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 #ifndef SkPDFCanon_DEFINED
8 #define SkPDFCanon_DEFINED
9 
10 #include "SkPDFGraphicState.h"
11 #include "SkPDFShader.h"
12 #include "SkTDArray.h"
13 #include "SkTHash.h"
14 
15 class SkBitmap;
16 class SkPDFFont;
17 class SkPDFBitmap;
18 class SkPaint;
19 
20 /**
21  *  The SkPDFCanon canonicalizes objects across PDF pages(SkPDFDevices).
22  *
23  *  The PDF backend works correctly if:
24  *  -  There is no more than one SkPDFCanon for each thread.
25  *  -  Every SkPDFDevice is given a pointer to a SkPDFCanon on creation.
26  *  -  All SkPDFDevices in a document share the same SkPDFCanon.
27  *  The SkDocument_PDF class makes this happen by owning a single
28  *  SkPDFCanon.
29  *
30  *  The addFoo() methods will ref the Foo; the canon's destructor will
31  *  call foo->unref() on all of these objects.
32  *
33  *  The findFoo() methods do not change the ref count of the Foo
34  *  objects.
35  */
36 class SkPDFCanon : SkNoncopyable {
37 public:
~SkPDFCanon()38     ~SkPDFCanon() { this->reset(); }
39 
40     // reset to original setting, unrefs all objects.
41     void reset();
42 
43     // Returns exact match if there is one.  If not, it returns NULL.
44     // If there is no exact match, but there is a related font, we
45     // still return NULL, but also set *relatedFont.
46     SkPDFFont* findFont(uint32_t fontID,
47                         uint16_t glyphID,
48                         SkPDFFont** relatedFont) const;
49     void addFont(SkPDFFont* font, uint32_t fontID, uint16_t fGlyphID);
50 
51     SkPDFFunctionShader* findFunctionShader(const SkPDFShader::State&) const;
52     void addFunctionShader(SkPDFFunctionShader*);
53 
54     SkPDFAlphaFunctionShader* findAlphaShader(const SkPDFShader::State&) const;
55     void addAlphaShader(SkPDFAlphaFunctionShader*);
56 
57     SkPDFImageShader* findImageShader(const SkPDFShader::State&) const;
58     void addImageShader(SkPDFImageShader*);
59 
60     const SkPDFGraphicState* findGraphicState(const SkPDFGraphicState&) const;
61     void addGraphicState(const SkPDFGraphicState*);
62 
63     SkPDFBitmap* findBitmap(const SkBitmap&) const;
64     void addBitmap(SkPDFBitmap*);
65 
66 private:
67     struct FontRec {
68         SkPDFFont* fFont;
69         uint32_t fFontID;
70         uint16_t fGlyphID;
71     };
72     SkTDArray<FontRec> fFontRecords;
73 
74     SkTDArray<SkPDFFunctionShader*> fFunctionShaderRecords;
75 
76     SkTDArray<SkPDFAlphaFunctionShader*> fAlphaShaderRecords;
77 
78     SkTDArray<SkPDFImageShader*> fImageShaderRecords;
79 
80     struct WrapGS {
fPtrWrapGS81         explicit WrapGS(const SkPDFGraphicState* ptr = NULL) : fPtr(ptr) {}
82         const SkPDFGraphicState* fPtr;
83         bool operator==(const WrapGS& rhs) const {
84             SkASSERT(fPtr);
85             SkASSERT(rhs.fPtr);
86             return *fPtr == *rhs.fPtr;
87         }
HashWrapGS88         static uint32_t Hash(const WrapGS& w) {
89             SkASSERT(w.fPtr);
90             return w.fPtr->hash();
91         }
92     };
93     SkTHashSet<WrapGS, WrapGS::Hash> fGraphicStateRecords;
94 
95     SkTDArray<SkPDFBitmap*> fBitmapRecords;
96 };
97 #endif  // SkPDFCanon_DEFINED
98