• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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