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
reset()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
assert_ptr(T * p)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>
find_item(const SkTDArray<T * > & ptrArray,const U & object)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
findFont(uint32_t fontID,uint16_t glyphID,SkPDFFont ** relatedFontPtr) const55 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
addFont(SkPDFFont * font,uint32_t fontID,uint16_t fGlyphID)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
findFunctionShader(const SkPDFShader::State & state) const84 SkPDFFunctionShader* SkPDFCanon::findFunctionShader(
85 const SkPDFShader::State& state) const {
86 return find_item(fFunctionShaderRecords, state);
87 }
addFunctionShader(SkPDFFunctionShader * pdfShader)88 void SkPDFCanon::addFunctionShader(SkPDFFunctionShader* pdfShader) {
89 fFunctionShaderRecords.push(SkRef(pdfShader));
90 }
91
92 ////////////////////////////////////////////////////////////////////////////////
93
findAlphaShader(const SkPDFShader::State & state) const94 SkPDFAlphaFunctionShader* SkPDFCanon::findAlphaShader(
95 const SkPDFShader::State& state) const {
96 return find_item(fAlphaShaderRecords, state);
97 }
addAlphaShader(SkPDFAlphaFunctionShader * pdfShader)98 void SkPDFCanon::addAlphaShader(SkPDFAlphaFunctionShader* pdfShader) {
99 fAlphaShaderRecords.push(SkRef(pdfShader));
100 }
101
102 ////////////////////////////////////////////////////////////////////////////////
103
findImageShader(const SkPDFShader::State & state) const104 SkPDFImageShader* SkPDFCanon::findImageShader(
105 const SkPDFShader::State& state) const {
106 return find_item(fImageShaderRecords, state);
107 }
108
addImageShader(SkPDFImageShader * pdfShader)109 void SkPDFCanon::addImageShader(SkPDFImageShader* pdfShader) {
110 fImageShaderRecords.push(SkRef(pdfShader));
111 }
112
113 ////////////////////////////////////////////////////////////////////////////////
114
findGraphicState(const SkPDFGraphicState & key) const115 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
addGraphicState(const SkPDFGraphicState * state)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
findPDFBitmap(const SkImage * image) const130 SkPDFObject* SkPDFCanon::findPDFBitmap(const SkImage* image) const {
131 SkPDFObject** ptr = fPDFBitmapMap.find(image->uniqueID());
132 return ptr ? *ptr : nullptr;
133 }
134
addPDFBitmap(uint32_t imageUniqueID,SkPDFObject * pdfBitmap)135 void SkPDFCanon::addPDFBitmap(uint32_t imageUniqueID, SkPDFObject* pdfBitmap) {
136 fPDFBitmapMap.set(imageUniqueID, SkRef(pdfBitmap));
137 }
138
bitmapToImage(const SkBitmap & bm)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