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 
13 ////////////////////////////////////////////////////////////////////////////////
14 
15 namespace {
16 template <typename K, typename V> struct UnrefValue {
operator ()__anonc6b326400111::UnrefValue17     void operator()(K, V** v) { SkSafeUnref(*v); }
18 };
19 }
20 
~SkPDFCanon()21 SkPDFCanon::~SkPDFCanon() {
22     // TODO(halcanary): make SkTHashSet work nicely with sk_sp<>,
23     // or use std::unordered_set<>
24     fGraphicStateRecords.foreach ([](WrapGS w) { w.fPtr->unref(); });
25     fPDFBitmapMap.foreach(UnrefValue<SkBitmapKey, SkPDFObject>());
26     fTypefaceMetrics.foreach(UnrefValue<uint32_t, SkAdvancedTypefaceMetrics>());
27     fFontDescriptors.foreach(UnrefValue<uint32_t, SkPDFDict>());
28     fFontMap.foreach(UnrefValue<uint64_t, SkPDFFont>());
29 }
30 
reset()31 void SkPDFCanon::reset() {
32     this->~SkPDFCanon();
33     new (this)SkPDFCanon;
34 }
35 
36 ////////////////////////////////////////////////////////////////////////////////
37 
38 template <typename T>
find_shader(const SkTArray<T> & records,const SkPDFShader::State & state)39 sk_sp<SkPDFObject> find_shader(const SkTArray<T>& records,
40                                const SkPDFShader::State& state) {
41     for (const T& record : records) {
42         if (record.fShaderState == state) {
43             return record.fShaderObject;
44         }
45     }
46     return nullptr;
47 }
48 
findFunctionShader(const SkPDFShader::State & state) const49 sk_sp<SkPDFObject> SkPDFCanon::findFunctionShader(
50         const SkPDFShader::State& state) const {
51     return find_shader(fFunctionShaderRecords, state);
52 }
addFunctionShader(sk_sp<SkPDFObject> pdfShader,SkPDFShader::State state)53 void SkPDFCanon::addFunctionShader(sk_sp<SkPDFObject> pdfShader,
54                                    SkPDFShader::State state) {
55     fFunctionShaderRecords.emplace_back(std::move(state), std::move(pdfShader));
56 }
57 
findAlphaShader(const SkPDFShader::State & state) const58 sk_sp<SkPDFObject> SkPDFCanon::findAlphaShader(
59         const SkPDFShader::State& state) const {
60     return find_shader(fAlphaShaderRecords, state);
61 }
addAlphaShader(sk_sp<SkPDFObject> pdfShader,SkPDFShader::State state)62 void SkPDFCanon::addAlphaShader(sk_sp<SkPDFObject> pdfShader,
63                                 SkPDFShader::State state) {
64     fAlphaShaderRecords.emplace_back(std::move(state), std::move(pdfShader));
65 }
66 
findImageShader(const SkPDFShader::State & state) const67 sk_sp<SkPDFObject> SkPDFCanon::findImageShader(
68         const SkPDFShader::State& state) const {
69     return find_shader(fImageShaderRecords, state);
70 }
71 
addImageShader(sk_sp<SkPDFObject> pdfShader,SkPDFShader::State state)72 void SkPDFCanon::addImageShader(sk_sp<SkPDFObject> pdfShader,
73                                 SkPDFShader::State state) {
74     fImageShaderRecords.emplace_back(std::move(state), std::move(pdfShader));
75 }
76 
77 ////////////////////////////////////////////////////////////////////////////////
78 
findGraphicState(const SkPDFGraphicState & key) const79 const SkPDFGraphicState* SkPDFCanon::findGraphicState(
80         const SkPDFGraphicState& key) const {
81     const WrapGS* ptr = fGraphicStateRecords.find(WrapGS(&key));
82     return ptr ? ptr->fPtr : nullptr;
83 }
84 
addGraphicState(const SkPDFGraphicState * state)85 void SkPDFCanon::addGraphicState(const SkPDFGraphicState* state) {
86     SkASSERT(state);
87     WrapGS w(SkRef(state));
88     SkASSERT(!fGraphicStateRecords.contains(w));
89     fGraphicStateRecords.add(w);
90 }
91 
92 ////////////////////////////////////////////////////////////////////////////////
93 
findPDFBitmap(SkBitmapKey key) const94 sk_sp<SkPDFObject> SkPDFCanon::findPDFBitmap(SkBitmapKey key) const {
95     SkPDFObject** ptr = fPDFBitmapMap.find(key);
96     return ptr ? sk_ref_sp(*ptr) : sk_sp<SkPDFObject>();
97 }
98 
addPDFBitmap(SkBitmapKey key,sk_sp<SkPDFObject> pdfBitmap)99 void SkPDFCanon::addPDFBitmap(SkBitmapKey key, sk_sp<SkPDFObject> pdfBitmap) {
100     fPDFBitmapMap.set(key, pdfBitmap.release());
101 }
102 
103 ////////////////////////////////////////////////////////////////////////////////
104 
makeInvertFunction()105 sk_sp<SkPDFStream> SkPDFCanon::makeInvertFunction() {
106     if (fInvertFunction) {
107         return fInvertFunction;
108     }
109     fInvertFunction = SkPDFGraphicState::MakeInvertFunction();
110     return fInvertFunction;
111 }
makeNoSmaskGraphicState()112 sk_sp<SkPDFDict> SkPDFCanon::makeNoSmaskGraphicState() {
113     if (fNoSmaskGraphicState) {
114         return fNoSmaskGraphicState;
115     }
116     fNoSmaskGraphicState = SkPDFGraphicState::MakeNoSmaskGraphicState();
117     return fNoSmaskGraphicState;
118 }
makeRangeObject()119 sk_sp<SkPDFArray> SkPDFCanon::makeRangeObject() {
120     if (fRangeObject) {
121         return fRangeObject;
122     }
123     fRangeObject = SkPDFShader::MakeRangeObject();
124     return fRangeObject;
125 }
126