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 "SkPDFBitmap.h"
9 #include "SkPDFCanon.h"
10 #include "SkPDFFont.h"
11 #include "SkPDFShader.h"
12 
13 ////////////////////////////////////////////////////////////////////////////////
14 
reset()15 void SkPDFCanon::reset() {
16     for (int i = 0; i < fFontRecords.count(); ++i) {
17         fFontRecords[i].fFont->unref();
18     }
19     fFontRecords.reset();
20     fFunctionShaderRecords.unrefAll();
21     fFunctionShaderRecords.reset();
22     fAlphaShaderRecords.unrefAll();
23     fAlphaShaderRecords.reset();
24     fImageShaderRecords.unrefAll();
25     fImageShaderRecords.reset();
26     fGraphicStateRecords.foreach ([](WrapGS w) { w.fPtr->unref(); });
27     fGraphicStateRecords.reset();
28     fBitmapRecords.unrefAll();
29     fBitmapRecords.reset();
30 }
31 
32 ////////////////////////////////////////////////////////////////////////////////
33 
assert_ptr(T * p)34 template <class T> T* assert_ptr(T* p) { SkASSERT(p); return p; }
35 
36 // requires `bool T::equals(const U&) const`
37 template <typename T, typename U>
find_item(const SkTDArray<T * > & ptrArray,const U & object)38 T* find_item(const SkTDArray<T*>& ptrArray, const U& object) {
39     for (int i = 0; i < ptrArray.count(); ++i) {
40         if (ptrArray[i]->equals(object)) {
41             return ptrArray[i];
42         }
43     }
44     return NULL;
45 }
46 
47 ////////////////////////////////////////////////////////////////////////////////
48 
findFont(uint32_t fontID,uint16_t glyphID,SkPDFFont ** relatedFontPtr) const49 SkPDFFont* SkPDFCanon::findFont(uint32_t fontID,
50                                 uint16_t glyphID,
51                                 SkPDFFont** relatedFontPtr) const {
52     SkASSERT(relatedFontPtr);
53 
54     SkPDFFont* relatedFont = NULL;
55     for (int i = 0; i < fFontRecords.count(); ++i) {
56         SkPDFFont::Match match = SkPDFFont::IsMatch(
57                 fFontRecords[i].fFont, fFontRecords[i].fFontID,
58                 fFontRecords[i].fGlyphID, fontID, glyphID);
59         if (SkPDFFont::kExact_Match == match) {
60             return fFontRecords[i].fFont;
61         } else if (!relatedFont && SkPDFFont::kRelated_Match == match) {
62             relatedFont = fFontRecords[i].fFont;
63         }
64     }
65     *relatedFontPtr = relatedFont;  // May still be NULL.
66     return NULL;
67 }
68 
addFont(SkPDFFont * font,uint32_t fontID,uint16_t fGlyphID)69 void SkPDFCanon::addFont(SkPDFFont* font, uint32_t fontID, uint16_t fGlyphID) {
70     SkPDFCanon::FontRec* rec = fFontRecords.push();
71     rec->fFont = SkRef(font);
72     rec->fFontID = fontID;
73     rec->fGlyphID = fGlyphID;
74 }
75 
76 ////////////////////////////////////////////////////////////////////////////////
77 
findFunctionShader(const SkPDFShader::State & state) const78 SkPDFFunctionShader* SkPDFCanon::findFunctionShader(
79         const SkPDFShader::State& state) const {
80     return find_item(fFunctionShaderRecords, state);
81 }
addFunctionShader(SkPDFFunctionShader * pdfShader)82 void SkPDFCanon::addFunctionShader(SkPDFFunctionShader* pdfShader) {
83     fFunctionShaderRecords.push(SkRef(pdfShader));
84 }
85 
86 ////////////////////////////////////////////////////////////////////////////////
87 
findAlphaShader(const SkPDFShader::State & state) const88 SkPDFAlphaFunctionShader* SkPDFCanon::findAlphaShader(
89         const SkPDFShader::State& state) const {
90     return find_item(fAlphaShaderRecords, state);
91 }
addAlphaShader(SkPDFAlphaFunctionShader * pdfShader)92 void SkPDFCanon::addAlphaShader(SkPDFAlphaFunctionShader* pdfShader) {
93     fAlphaShaderRecords.push(SkRef(pdfShader));
94 }
95 
96 ////////////////////////////////////////////////////////////////////////////////
97 
findImageShader(const SkPDFShader::State & state) const98 SkPDFImageShader* SkPDFCanon::findImageShader(
99         const SkPDFShader::State& state) const {
100     return find_item(fImageShaderRecords, state);
101 }
102 
addImageShader(SkPDFImageShader * pdfShader)103 void SkPDFCanon::addImageShader(SkPDFImageShader* pdfShader) {
104     fImageShaderRecords.push(SkRef(pdfShader));
105 }
106 
107 ////////////////////////////////////////////////////////////////////////////////
108 
findGraphicState(const SkPDFGraphicState & key) const109 const SkPDFGraphicState* SkPDFCanon::findGraphicState(
110         const SkPDFGraphicState& key) const {
111     const WrapGS* ptr = fGraphicStateRecords.find(WrapGS(&key));
112     return ptr ? ptr->fPtr : NULL;
113 }
114 
addGraphicState(const SkPDFGraphicState * state)115 void SkPDFCanon::addGraphicState(const SkPDFGraphicState* state) {
116     SkASSERT(state);
117     WrapGS w(SkRef(state));
118     SkASSERT(!fGraphicStateRecords.contains(w));
119     fGraphicStateRecords.add(w);
120 }
121 
122 ////////////////////////////////////////////////////////////////////////////////
123 
findBitmap(const SkBitmap & bm) const124 SkPDFBitmap* SkPDFCanon::findBitmap(const SkBitmap& bm) const {
125     return find_item(fBitmapRecords, bm);
126 }
127 
addBitmap(SkPDFBitmap * pdfBitmap)128 void SkPDFCanon::addBitmap(SkPDFBitmap* pdfBitmap) {
129     fBitmapRecords.push(SkRef(pdfBitmap));
130 }
131