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