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 "SkBitmap.h"
11 #include "SkPDFGraphicState.h"
12 #include "SkPDFShader.h"
13 #include "SkPixelSerializer.h"
14 #include "SkTDArray.h"
15 #include "SkTHash.h"
16 
17 class SkPDFFont;
18 class SkPaint;
19 class SkImage;
20 
21 class SkBitmapKey {
22 public:
SkBitmapKey()23     SkBitmapKey() : fSubset(SkIRect::MakeEmpty()), fGenID(0) {}
SkBitmapKey(const SkBitmap & bm)24     explicit SkBitmapKey(const SkBitmap& bm)
25         : fSubset(bm.getSubset()), fGenID(bm.getGenerationID()) {}
26     bool operator==(const SkBitmapKey& rhs) const {
27         return fGenID == rhs.fGenID && fSubset == rhs.fSubset;
28     }
29 
30 private:
31     SkIRect fSubset;
32     uint32_t fGenID;
33 };
34 
35 /**
36  *  The SkPDFCanon canonicalizes objects across PDF pages(SkPDFDevices).
37  *
38  *  The PDF backend works correctly if:
39  *  -  There is no more than one SkPDFCanon for each thread.
40  *  -  Every SkPDFDevice is given a pointer to a SkPDFCanon on creation.
41  *  -  All SkPDFDevices in a document share the same SkPDFCanon.
42  *  The SkDocument_PDF class makes this happen by owning a single
43  *  SkPDFCanon.
44  *
45  *  The addFoo() methods will ref the Foo; the canon's destructor will
46  *  call foo->unref() on all of these objects.
47  *
48  *  The findFoo() methods do not change the ref count of the Foo
49  *  objects.
50  */
51 class SkPDFCanon : SkNoncopyable {
52 public:
~SkPDFCanon()53     ~SkPDFCanon() { this->reset(); }
54 
55     // reset to original setting, unrefs all objects.
56     void reset();
57 
58     // Returns exact match if there is one.  If not, it returns nullptr.
59     // If there is no exact match, but there is a related font, we
60     // still return nullptr, but also set *relatedFont.
61     SkPDFFont* findFont(uint32_t fontID,
62                         uint16_t glyphID,
63                         SkPDFFont** relatedFont) const;
64     void addFont(SkPDFFont* font, uint32_t fontID, uint16_t fGlyphID);
65 
66     SkPDFFunctionShader* findFunctionShader(const SkPDFShader::State&) const;
67     void addFunctionShader(SkPDFFunctionShader*);
68 
69     SkPDFAlphaFunctionShader* findAlphaShader(const SkPDFShader::State&) const;
70     void addAlphaShader(SkPDFAlphaFunctionShader*);
71 
72     SkPDFImageShader* findImageShader(const SkPDFShader::State&) const;
73     void addImageShader(SkPDFImageShader*);
74 
75     const SkPDFGraphicState* findGraphicState(const SkPDFGraphicState&) const;
76     void addGraphicState(const SkPDFGraphicState*);
77 
78     SkPDFObject* findPDFBitmap(const SkImage* image) const;
79     void addPDFBitmap(uint32_t imageUniqueID, SkPDFObject*);
80     const SkImage* bitmapToImage(const SkBitmap&);
81 
82     SkTHashMap<uint32_t, bool> fCanEmbedTypeface;
83 
84     SkAutoTUnref<SkPixelSerializer> fPixelSerializer;
85 
86 private:
87     struct FontRec {
88         SkPDFFont* fFont;
89         uint32_t fFontID;
90         uint16_t fGlyphID;
91     };
92     SkTDArray<FontRec> fFontRecords;
93 
94     SkTDArray<SkPDFFunctionShader*> fFunctionShaderRecords;
95 
96     SkTDArray<SkPDFAlphaFunctionShader*> fAlphaShaderRecords;
97 
98     SkTDArray<SkPDFImageShader*> fImageShaderRecords;
99 
100     struct WrapGS {
fPtrWrapGS101         explicit WrapGS(const SkPDFGraphicState* ptr = nullptr) : fPtr(ptr) {}
102         const SkPDFGraphicState* fPtr;
103         bool operator==(const WrapGS& rhs) const {
104             SkASSERT(fPtr);
105             SkASSERT(rhs.fPtr);
106             return *fPtr == *rhs.fPtr;
107         }
108         struct Hash {
operatorWrapGS::Hash109             uint32_t operator()(const WrapGS& w) const {
110                 SkASSERT(w.fPtr);
111                 return w.fPtr->hash();
112             }
113         };
114     };
115     SkTHashSet<WrapGS, WrapGS::Hash> fGraphicStateRecords;
116 
117     SkTHashMap<SkBitmapKey, const SkImage*> fBitmapToImageMap;
118     SkTHashMap<uint32_t /*ImageUniqueID*/, SkPDFObject*> fPDFBitmapMap;
119 };
120 #endif  // SkPDFCanon_DEFINED
121