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
15void 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
34template <class T> T* assert_ptr(T* p) { SkASSERT(p); return p; }
35
36// requires `bool T::equals(const U&) const`
37template <typename T, typename U>
38T* 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
49SkPDFFont* 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
69void 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
78SkPDFFunctionShader* SkPDFCanon::findFunctionShader(
79        const SkPDFShader::State& state) const {
80    return find_item(fFunctionShaderRecords, state);
81}
82void SkPDFCanon::addFunctionShader(SkPDFFunctionShader* pdfShader) {
83    fFunctionShaderRecords.push(SkRef(pdfShader));
84}
85
86////////////////////////////////////////////////////////////////////////////////
87
88SkPDFAlphaFunctionShader* SkPDFCanon::findAlphaShader(
89        const SkPDFShader::State& state) const {
90    return find_item(fAlphaShaderRecords, state);
91}
92void SkPDFCanon::addAlphaShader(SkPDFAlphaFunctionShader* pdfShader) {
93    fAlphaShaderRecords.push(SkRef(pdfShader));
94}
95
96////////////////////////////////////////////////////////////////////////////////
97
98SkPDFImageShader* SkPDFCanon::findImageShader(
99        const SkPDFShader::State& state) const {
100    return find_item(fImageShaderRecords, state);
101}
102
103void SkPDFCanon::addImageShader(SkPDFImageShader* pdfShader) {
104    fImageShaderRecords.push(SkRef(pdfShader));
105}
106
107////////////////////////////////////////////////////////////////////////////////
108
109const SkPDFGraphicState* SkPDFCanon::findGraphicState(
110        const SkPDFGraphicState& key) const {
111    const WrapGS* ptr = fGraphicStateRecords.find(WrapGS(&key));
112    return ptr ? ptr->fPtr : NULL;
113}
114
115void 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
124SkPDFBitmap* SkPDFCanon::findBitmap(const SkBitmap& bm) const {
125    return find_item(fBitmapRecords, bm);
126}
127
128void SkPDFCanon::addBitmap(SkPDFBitmap* pdfBitmap) {
129    fBitmapRecords.push(SkRef(pdfBitmap));
130}
131