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