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 "SkPixelSerializer.h"
13 #include "SkTDArray.h"
14 #include "SkTHash.h"
15 #include "SkBitmapKey.h"
16 
17 class SkAdvancedTypefaceMetrics;
18 class SkPDFFont;
19 
20 /**
21  *  The SkPDFCanon canonicalizes objects across PDF pages
22  *  (SkPDFDevices) and across draw calls.
23  *
24  *  The PDF backend works correctly if:
25  *  -  There is no more than one SkPDFCanon for each thread.
26  *  -  Every SkPDFDevice is given a pointer to a SkPDFCanon on creation.
27  *  -  All SkPDFDevices in a document share the same SkPDFCanon.
28  *  The SkPDFDocument class makes this happen by owning a single
29  *  SkPDFCanon.
30  *
31  *  The addFoo() methods will ref the Foo; the canon's destructor will
32  *  call foo->unref() on all of these objects.
33  *
34  *  The findFoo() methods do not change the ref count of the Foo
35  *  objects.
36  */
37 class SkPDFCanon : SkNoncopyable {
38 public:
39     ~SkPDFCanon();
40 
41     // reset to original setting, unrefs all objects.
42     void reset();
43 
44     sk_sp<SkPDFObject> findFunctionShader(const SkPDFShader::State&) const;
45     void addFunctionShader(sk_sp<SkPDFObject>, SkPDFShader::State);
46 
47     sk_sp<SkPDFObject> findAlphaShader(const SkPDFShader::State&) const;
48     void addAlphaShader(sk_sp<SkPDFObject>, SkPDFShader::State);
49 
50     sk_sp<SkPDFObject> findImageShader(const SkPDFShader::State&) const;
51     void addImageShader(sk_sp<SkPDFObject>, SkPDFShader::State);
52 
53     const SkPDFGraphicState* findGraphicState(const SkPDFGraphicState&) const;
54     void addGraphicState(const SkPDFGraphicState*);
55 
56     sk_sp<SkPDFObject> findPDFBitmap(SkBitmapKey key) const;
57     void addPDFBitmap(SkBitmapKey key, sk_sp<SkPDFObject>);
58 
59     SkTHashMap<uint32_t, SkAdvancedTypefaceMetrics*> fTypefaceMetrics;
60     SkTHashMap<uint32_t, SkPDFDict*> fFontDescriptors;
61     SkTHashMap<uint64_t, SkPDFFont*> fFontMap;
62 
getPixelSerializer()63     SkPixelSerializer* getPixelSerializer() const { return fPixelSerializer.get(); }
setPixelSerializer(sk_sp<SkPixelSerializer> ps)64     void setPixelSerializer(sk_sp<SkPixelSerializer> ps) {
65         fPixelSerializer = std::move(ps);
66     }
67 
68     sk_sp<SkPDFStream> makeInvertFunction();
69     sk_sp<SkPDFDict> makeNoSmaskGraphicState();
70     sk_sp<SkPDFArray> makeRangeObject();
71 
72 private:
73     struct ShaderRec {
74         SkPDFShader::State fShaderState;
75         sk_sp<SkPDFObject> fShaderObject;
ShaderRecShaderRec76         ShaderRec(SkPDFShader::State s, sk_sp<SkPDFObject> o)
77             : fShaderState(std::move(s)), fShaderObject(std::move(o)) {}
78     };
79     SkTArray<ShaderRec> fFunctionShaderRecords;
80     SkTArray<ShaderRec> fAlphaShaderRecords;
81     SkTArray<ShaderRec> fImageShaderRecords;
82 
83     struct WrapGS {
fPtrWrapGS84         explicit WrapGS(const SkPDFGraphicState* ptr = nullptr) : fPtr(ptr) {}
85         const SkPDFGraphicState* fPtr;
86         bool operator==(const WrapGS& rhs) const {
87             SkASSERT(fPtr);
88             SkASSERT(rhs.fPtr);
89             return *fPtr == *rhs.fPtr;
90         }
91         struct Hash {
operatorWrapGS::Hash92             uint32_t operator()(const WrapGS& w) const {
93                 SkASSERT(w.fPtr);
94                 return w.fPtr->hash();
95             }
96         };
97     };
98     SkTHashSet<WrapGS, WrapGS::Hash> fGraphicStateRecords;
99 
100     // TODO(halcanary): make SkTHashMap<K, sk_sp<V>> work correctly.
101     SkTHashMap<SkBitmapKey, SkPDFObject*> fPDFBitmapMap;
102 
103     sk_sp<SkPixelSerializer> fPixelSerializer;
104     sk_sp<SkPDFStream> fInvertFunction;
105     sk_sp<SkPDFDict> fNoSmaskGraphicState;
106     sk_sp<SkPDFArray> fRangeObject;
107 };
108 #endif  // SkPDFCanon_DEFINED
109