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 8 #include "SkImage.h" 9 #include "SkPDFBitmap.h" 10 #include "SkPDFCanon.h" 11 #include "SkPDFFont.h" 12 #include "SkPDFShader.h" 13 14 //////////////////////////////////////////////////////////////////////////////// 15 16 void SkPDFCanon::reset() { 17 for (int i = 0; i < fFontRecords.count(); ++i) { 18 fFontRecords[i].fFont->unref(); 19 } 20 fFontRecords.reset(); 21 fFunctionShaderRecords.unrefAll(); 22 fFunctionShaderRecords.reset(); 23 fAlphaShaderRecords.unrefAll(); 24 fAlphaShaderRecords.reset(); 25 fImageShaderRecords.unrefAll(); 26 fImageShaderRecords.reset(); 27 fGraphicStateRecords.foreach ([](WrapGS w) { w.fPtr->unref(); }); 28 fGraphicStateRecords.reset(); 29 30 fBitmapToImageMap.foreach( 31 [](SkBitmapKey, const SkImage** p) { SkSafeUnref(*p); }); 32 fBitmapToImageMap.reset(); 33 34 fPDFBitmapMap.foreach([](uint32_t, SkPDFObject** p) { SkSafeUnref(*p); }); 35 fPDFBitmapMap.reset(); 36 } 37 38 //////////////////////////////////////////////////////////////////////////////// 39 40 template <class T> T* assert_ptr(T* p) { SkASSERT(p); return p; } 41 42 // requires `bool T::equals(const U&) const` 43 template <typename T, typename U> 44 T* find_item(const SkTDArray<T*>& ptrArray, const U& object) { 45 for (int i = 0; i < ptrArray.count(); ++i) { 46 if (ptrArray[i]->equals(object)) { 47 return ptrArray[i]; 48 } 49 } 50 return nullptr; 51 } 52 53 //////////////////////////////////////////////////////////////////////////////// 54 55 SkPDFFont* SkPDFCanon::findFont(uint32_t fontID, 56 uint16_t glyphID, 57 SkPDFFont** relatedFontPtr) const { 58 SkASSERT(relatedFontPtr); 59 60 SkPDFFont* relatedFont = nullptr; 61 for (int i = 0; i < fFontRecords.count(); ++i) { 62 SkPDFFont::Match match = SkPDFFont::IsMatch( 63 fFontRecords[i].fFont, fFontRecords[i].fFontID, 64 fFontRecords[i].fGlyphID, fontID, glyphID); 65 if (SkPDFFont::kExact_Match == match) { 66 return fFontRecords[i].fFont; 67 } else if (!relatedFont && SkPDFFont::kRelated_Match == match) { 68 relatedFont = fFontRecords[i].fFont; 69 } 70 } 71 *relatedFontPtr = relatedFont; // May still be nullptr. 72 return nullptr; 73 } 74 75 void SkPDFCanon::addFont(SkPDFFont* font, uint32_t fontID, uint16_t fGlyphID) { 76 SkPDFCanon::FontRec* rec = fFontRecords.push(); 77 rec->fFont = SkRef(font); 78 rec->fFontID = fontID; 79 rec->fGlyphID = fGlyphID; 80 } 81 82 //////////////////////////////////////////////////////////////////////////////// 83 84 SkPDFFunctionShader* SkPDFCanon::findFunctionShader( 85 const SkPDFShader::State& state) const { 86 return find_item(fFunctionShaderRecords, state); 87 } 88 void SkPDFCanon::addFunctionShader(SkPDFFunctionShader* pdfShader) { 89 fFunctionShaderRecords.push(SkRef(pdfShader)); 90 } 91 92 //////////////////////////////////////////////////////////////////////////////// 93 94 SkPDFAlphaFunctionShader* SkPDFCanon::findAlphaShader( 95 const SkPDFShader::State& state) const { 96 return find_item(fAlphaShaderRecords, state); 97 } 98 void SkPDFCanon::addAlphaShader(SkPDFAlphaFunctionShader* pdfShader) { 99 fAlphaShaderRecords.push(SkRef(pdfShader)); 100 } 101 102 //////////////////////////////////////////////////////////////////////////////// 103 104 SkPDFImageShader* SkPDFCanon::findImageShader( 105 const SkPDFShader::State& state) const { 106 return find_item(fImageShaderRecords, state); 107 } 108 109 void SkPDFCanon::addImageShader(SkPDFImageShader* pdfShader) { 110 fImageShaderRecords.push(SkRef(pdfShader)); 111 } 112 113 //////////////////////////////////////////////////////////////////////////////// 114 115 const SkPDFGraphicState* SkPDFCanon::findGraphicState( 116 const SkPDFGraphicState& key) const { 117 const WrapGS* ptr = fGraphicStateRecords.find(WrapGS(&key)); 118 return ptr ? ptr->fPtr : nullptr; 119 } 120 121 void SkPDFCanon::addGraphicState(const SkPDFGraphicState* state) { 122 SkASSERT(state); 123 WrapGS w(SkRef(state)); 124 SkASSERT(!fGraphicStateRecords.contains(w)); 125 fGraphicStateRecords.add(w); 126 } 127 128 //////////////////////////////////////////////////////////////////////////////// 129 130 SkPDFObject* SkPDFCanon::findPDFBitmap(const SkImage* image) const { 131 SkPDFObject** ptr = fPDFBitmapMap.find(image->uniqueID()); 132 return ptr ? *ptr : nullptr; 133 } 134 135 void SkPDFCanon::addPDFBitmap(uint32_t imageUniqueID, SkPDFObject* pdfBitmap) { 136 fPDFBitmapMap.set(imageUniqueID, SkRef(pdfBitmap)); 137 } 138 139 const SkImage* SkPDFCanon::bitmapToImage(const SkBitmap& bm) { 140 // reference remains owned by the fBitmapToImageMap! 141 SkBitmapKey key(bm); 142 if (const SkImage** img = fBitmapToImageMap.find(key)) { 143 return *img; 144 } 145 if (SkImage* image = SkImage::NewFromBitmap(bm)) { 146 return *fBitmapToImageMap.set(key, image); 147 } 148 SkBitmap n32bitmap; // SkImage::NewFromBitmap can be finicky. 149 bm.copyTo(&n32bitmap, kN32_SkColorType); 150 return *fBitmapToImageMap.set(key, SkImage::NewFromBitmap(n32bitmap)); 151 } 152