Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(183)

Side by Side Diff: src/pdf/SkPDFGraphicState.cpp

Issue 842253003: SkPDFCanon (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkData.h" 8 #include "SkData.h"
9 #include "SkPDFCanon.h"
9 #include "SkPDFFormXObject.h" 10 #include "SkPDFFormXObject.h"
10 #include "SkPDFGraphicState.h" 11 #include "SkPDFGraphicState.h"
11 #include "SkPDFUtils.h" 12 #include "SkPDFUtils.h"
12 #include "SkTypes.h" 13 #include "SkTypes.h"
13 14
14 static const char* blend_mode_from_xfermode(SkXfermode::Mode mode) {
15 switch (mode) {
16 case SkXfermode::kSrcOver_Mode: return "Normal";
17 case SkXfermode::kMultiply_Mode: return "Multiply";
18 case SkXfermode::kScreen_Mode: return "Screen";
19 case SkXfermode::kOverlay_Mode: return "Overlay";
20 case SkXfermode::kDarken_Mode: return "Darken";
21 case SkXfermode::kLighten_Mode: return "Lighten";
22 case SkXfermode::kColorDodge_Mode: return "ColorDodge";
23 case SkXfermode::kColorBurn_Mode: return "ColorBurn";
24 case SkXfermode::kHardLight_Mode: return "HardLight";
25 case SkXfermode::kSoftLight_Mode: return "SoftLight";
26 case SkXfermode::kDifference_Mode: return "Difference";
27 case SkXfermode::kExclusion_Mode: return "Exclusion";
28 case SkXfermode::kHue_Mode: return "Hue";
29 case SkXfermode::kSaturation_Mode: return "Saturation";
30 case SkXfermode::kColor_Mode: return "Color";
31 case SkXfermode::kLuminosity_Mode: return "Luminosity";
32
33 // These are handled in SkPDFDevice::setUpContentEntry.
34 case SkXfermode::kClear_Mode:
35 case SkXfermode::kSrc_Mode:
36 case SkXfermode::kDst_Mode:
37 case SkXfermode::kDstOver_Mode:
38 case SkXfermode::kSrcIn_Mode:
39 case SkXfermode::kDstIn_Mode:
40 case SkXfermode::kSrcOut_Mode:
41 case SkXfermode::kDstOut_Mode:
42 case SkXfermode::kSrcATop_Mode:
43 case SkXfermode::kDstATop_Mode:
44 case SkXfermode::kModulate_Mode:
45 return "Normal";
46
47 // TODO(vandebo): Figure out if we can support more of these modes.
48 case SkXfermode::kXor_Mode:
49 case SkXfermode::kPlus_Mode:
50 return NULL;
51 }
52 return NULL;
53 }
54
55 SkPDFGraphicState::~SkPDFGraphicState() { 15 SkPDFGraphicState::~SkPDFGraphicState() {
56 SkAutoMutexAcquire lock(CanonicalPaintsMutex()); 16 SkAutoMutexAcquire lock(SkPDFCanon::GetPaintMutex());
57 if (!fSMask) { 17 if (!fSMask) {
58 int index = Find(fPaint); 18 SkPDFCanon::GetCanon().removeGraphicState(this);
59 SkASSERT(index >= 0);
60 SkASSERT(CanonicalPaints()[index].fGraphicState == this);
61 CanonicalPaints().removeShuffle(index);
62 } 19 }
63 fResources.unrefAll(); 20 fResources.unrefAll();
64 } 21 }
65 22
66 void SkPDFGraphicState::getResources( 23 void SkPDFGraphicState::getResources(
67 const SkTSet<SkPDFObject*>& knownResourceObjects, 24 const SkTSet<SkPDFObject*>& knownResourceObjects,
68 SkTSet<SkPDFObject*>* newResourceObjects) { 25 SkTSet<SkPDFObject*>* newResourceObjects) {
69 GetResourcesHelper(&fResources, knownResourceObjects, newResourceObjects); 26 GetResourcesHelper(&fResources, knownResourceObjects, newResourceObjects);
70 } 27 }
71 28
72 void SkPDFGraphicState::emitObject(SkWStream* stream, SkPDFCatalog* catalog, 29 void SkPDFGraphicState::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
73 bool indirect) { 30 bool indirect) {
74 populateDict(); 31 populateDict();
75 SkPDFDict::emitObject(stream, catalog, indirect); 32 SkPDFDict::emitObject(stream, catalog, indirect);
76 } 33 }
77 34
78 // static 35 // static
79 size_t SkPDFGraphicState::getOutputSize(SkPDFCatalog* catalog, bool indirect) { 36 size_t SkPDFGraphicState::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
80 populateDict(); 37 populateDict();
81 return SkPDFDict::getOutputSize(catalog, indirect); 38 return SkPDFDict::getOutputSize(catalog, indirect);
82 } 39 }
83 40
84 // static 41 // static
85 SkTDArray<SkPDFGraphicState::GSCanonicalEntry>& SkPDFGraphicState::CanonicalPain ts() {
86 CanonicalPaintsMutex().assertHeld();
87 static SkTDArray<SkPDFGraphicState::GSCanonicalEntry> gCanonicalPaints;
88 return gCanonicalPaints;
89 }
90
91 SK_DECLARE_STATIC_MUTEX(gCanonicalPaintsMutex);
92 // static
93 SkBaseMutex& SkPDFGraphicState::CanonicalPaintsMutex() {
94 return gCanonicalPaintsMutex;
95 }
96
97 // static
98 SkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint(const SkPaint& pai nt) { 42 SkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint(const SkPaint& pai nt) {
99 SkAutoMutexAcquire lock(CanonicalPaintsMutex()); 43 SkAutoMutexAcquire lock(SkPDFCanon::GetPaintMutex());
100 int index = Find(paint); 44 SkPDFGraphicState* pdfGraphicState =
101 if (index >= 0) { 45 SkPDFCanon::GetCanon().findGraphicState(paint);
102 CanonicalPaints()[index].fGraphicState->ref(); 46 if (pdfGraphicState) {
103 return CanonicalPaints()[index].fGraphicState; 47 return SkRef(pdfGraphicState);
104 } 48 }
105 GSCanonicalEntry newEntry(new SkPDFGraphicState(paint)); 49 pdfGraphicState = new SkPDFGraphicState(paint);
106 CanonicalPaints().push(newEntry); 50 SkPDFCanon::GetCanon().addGraphicState(pdfGraphicState);
107 return newEntry.fGraphicState; 51 return pdfGraphicState;
108 } 52 }
109 53
110 // static 54 // static
111 SkPDFObject* SkPDFGraphicState::GetInvertFunction() { 55 SkPDFObject* SkPDFGraphicState::GetInvertFunction() {
112 // This assumes that canonicalPaintsMutex is held. 56 // This assumes that canonicalPaintsMutex is held.
113 CanonicalPaintsMutex().assertHeld(); 57 SkPDFCanon::GetPaintMutex().assertHeld();
114 static SkPDFStream* invertFunction = NULL; 58 static SkPDFStream* invertFunction = NULL;
115 if (!invertFunction) { 59 if (!invertFunction) {
116 // Acrobat crashes if we use a type 0 function, kpdf crashes if we use 60 // Acrobat crashes if we use a type 0 function, kpdf crashes if we use
117 // a type 2 function, so we use a type 4 function. 61 // a type 2 function, so we use a type 4 function.
118 SkAutoTUnref<SkPDFArray> domainAndRange(new SkPDFArray); 62 SkAutoTUnref<SkPDFArray> domainAndRange(new SkPDFArray);
119 domainAndRange->reserve(2); 63 domainAndRange->reserve(2);
120 domainAndRange->appendInt(0); 64 domainAndRange->appendInt(0);
121 domainAndRange->appendInt(1); 65 domainAndRange->appendInt(1);
122 66
123 static const char psInvert[] = "{1 exch sub}"; 67 static const char psInvert[] = "{1 exch sub}";
124 // Do not copy the trailing '\0' into the SkData. 68 // Do not copy the trailing '\0' into the SkData.
125 SkAutoTUnref<SkData> psInvertStream( 69 SkAutoTUnref<SkData> psInvertStream(
126 SkData::NewWithoutCopy(psInvert, strlen(psInvert))); 70 SkData::NewWithoutCopy(psInvert, strlen(psInvert)));
127 71
128 invertFunction = new SkPDFStream(psInvertStream.get()); 72 invertFunction = new SkPDFStream(psInvertStream.get());
129 invertFunction->insertInt("FunctionType", 4); 73 invertFunction->insertInt("FunctionType", 4);
130 invertFunction->insert("Domain", domainAndRange.get()); 74 invertFunction->insert("Domain", domainAndRange.get());
131 invertFunction->insert("Range", domainAndRange.get()); 75 invertFunction->insert("Range", domainAndRange.get());
132 } 76 }
133 return invertFunction; 77 return invertFunction;
134 } 78 }
135 79
136 // static 80 // static
137 SkPDFGraphicState* SkPDFGraphicState::GetSMaskGraphicState( 81 SkPDFGraphicState* SkPDFGraphicState::GetSMaskGraphicState(
138 SkPDFFormXObject* sMask, bool invert, SkPDFSMaskMode sMaskMode) { 82 SkPDFFormXObject* sMask, bool invert, SkPDFSMaskMode sMaskMode) {
139 // The practical chances of using the same mask more than once are unlikely 83 // The practical chances of using the same mask more than once are unlikely
140 // enough that it's not worth canonicalizing. 84 // enough that it's not worth canonicalizing.
141 SkAutoMutexAcquire lock(CanonicalPaintsMutex()); 85 SkAutoMutexAcquire lock(SkPDFCanon::GetPaintMutex());
142
143 SkAutoTUnref<SkPDFDict> sMaskDict(new SkPDFDict("Mask")); 86 SkAutoTUnref<SkPDFDict> sMaskDict(new SkPDFDict("Mask"));
144 if (sMaskMode == kAlpha_SMaskMode) { 87 if (sMaskMode == kAlpha_SMaskMode) {
145 sMaskDict->insertName("S", "Alpha"); 88 sMaskDict->insertName("S", "Alpha");
146 } else if (sMaskMode == kLuminosity_SMaskMode) { 89 } else if (sMaskMode == kLuminosity_SMaskMode) {
147 sMaskDict->insertName("S", "Luminosity"); 90 sMaskDict->insertName("S", "Luminosity");
148 } 91 }
149 sMaskDict->insert("G", new SkPDFObjRef(sMask))->unref(); 92 sMaskDict->insert("G", new SkPDFObjRef(sMask))->unref();
150 93
151 SkPDFGraphicState* result = new SkPDFGraphicState; 94 SkPDFGraphicState* result = new SkPDFGraphicState;
152 result->fPopulated = true; 95 result->fPopulated = true;
153 result->fSMask = true; 96 result->fSMask = true;
154 result->insertName("Type", "ExtGState"); 97 result->insertName("Type", "ExtGState");
155 result->insert("SMask", sMaskDict.get()); 98 result->insert("SMask", sMaskDict.get());
156 result->fResources.push(sMask); 99 result->fResources.push(sMask);
157 sMask->ref(); 100 sMask->ref();
158 101
159 if (invert) { 102 if (invert) {
160 SkPDFObject* invertFunction = GetInvertFunction(); 103 SkPDFObject* invertFunction = GetInvertFunction();
161 result->fResources.push(invertFunction); 104 result->fResources.push(invertFunction);
162 invertFunction->ref(); 105 invertFunction->ref();
163 sMaskDict->insert("TR", new SkPDFObjRef(invertFunction))->unref(); 106 sMaskDict->insert("TR", new SkPDFObjRef(invertFunction))->unref();
164 } 107 }
165 108
166 return result; 109 return result;
167 } 110 }
168 111
169 // static 112 // static
170 SkPDFGraphicState* SkPDFGraphicState::GetNoSMaskGraphicState() { 113 SkPDFGraphicState* SkPDFGraphicState::GetNoSMaskGraphicState() {
171 SkAutoMutexAcquire lock(CanonicalPaintsMutex()); 114 SkAutoMutexAcquire lock(SkPDFCanon::GetPaintMutex());
172 static SkPDFGraphicState* noSMaskGS = NULL; 115 static SkPDFGraphicState* noSMaskGS = NULL;
173 if (!noSMaskGS) { 116 if (!noSMaskGS) {
174 noSMaskGS = new SkPDFGraphicState; 117 noSMaskGS = new SkPDFGraphicState;
175 noSMaskGS->fPopulated = true; 118 noSMaskGS->fPopulated = true;
176 noSMaskGS->fSMask = true; 119 noSMaskGS->fSMask = true;
177 noSMaskGS->insertName("Type", "ExtGState"); 120 noSMaskGS->insertName("Type", "ExtGState");
178 noSMaskGS->insertName("SMask", "None"); 121 noSMaskGS->insertName("SMask", "None");
179 } 122 }
180 noSMaskGS->ref(); 123 noSMaskGS->ref();
181 return noSMaskGS; 124 return noSMaskGS;
182 } 125 }
183 126
184 // static
185 int SkPDFGraphicState::Find(const SkPaint& paint) {
186 CanonicalPaintsMutex().assertHeld();
187 GSCanonicalEntry search(&paint);
188 return CanonicalPaints().find(search);
189 }
190
191 SkPDFGraphicState::SkPDFGraphicState() 127 SkPDFGraphicState::SkPDFGraphicState()
192 : fPopulated(false), 128 : fPopulated(false),
193 fSMask(false) { 129 fSMask(false) {
194 } 130 }
195 131
196 SkPDFGraphicState::SkPDFGraphicState(const SkPaint& paint) 132 SkPDFGraphicState::SkPDFGraphicState(const SkPaint& paint)
197 : fPaint(paint), 133 : fPaint(paint),
198 fPopulated(false), 134 fPopulated(false),
199 fSMask(false) { 135 fSMask(false) {
200 } 136 }
(...skipping 26 matching lines...) Expand all
227 insertScalar("LW", fPaint.getStrokeWidth()); 163 insertScalar("LW", fPaint.getStrokeWidth());
228 insertScalar("ML", fPaint.getStrokeMiter()); 164 insertScalar("ML", fPaint.getStrokeMiter());
229 insert("SA", new SkPDFBool(true))->unref(); // Auto stroke adjustment. 165 insert("SA", new SkPDFBool(true))->unref(); // Auto stroke adjustment.
230 166
231 SkXfermode::Mode xfermode = SkXfermode::kSrcOver_Mode; 167 SkXfermode::Mode xfermode = SkXfermode::kSrcOver_Mode;
232 // If asMode fails, default to kSrcOver_Mode. 168 // If asMode fails, default to kSrcOver_Mode.
233 if (fPaint.getXfermode()) 169 if (fPaint.getXfermode())
234 fPaint.getXfermode()->asMode(&xfermode); 170 fPaint.getXfermode()->asMode(&xfermode);
235 // If we don't support the mode, just use kSrcOver_Mode. 171 // If we don't support the mode, just use kSrcOver_Mode.
236 if (xfermode < 0 || xfermode > SkXfermode::kLastMode || 172 if (xfermode < 0 || xfermode > SkXfermode::kLastMode ||
237 blend_mode_from_xfermode(xfermode) == NULL) { 173 PDFBlendModeFromXfermode(xfermode) == NULL) {
238 xfermode = SkXfermode::kSrcOver_Mode; 174 xfermode = SkXfermode::kSrcOver_Mode;
239 NOT_IMPLEMENTED("unsupported xfermode", false); 175 NOT_IMPLEMENTED("unsupported xfermode", false);
240 } 176 }
241 insertName("BM", blend_mode_from_xfermode(xfermode)); 177 insertName("BM", PDFBlendModeFromXfermode(xfermode));
242 } 178 }
243 } 179 }
244 180
245 // We're only interested in some fields of the SkPaint, so we have a custom
246 // operator== function.
247 bool SkPDFGraphicState::GSCanonicalEntry::operator==(
248 const SkPDFGraphicState::GSCanonicalEntry& gs) const {
249 const SkPaint* a = fPaint;
250 const SkPaint* b = gs.fPaint;
251 SkASSERT(a != NULL);
252 SkASSERT(b != NULL);
253
254 if (SkColorGetA(a->getColor()) != SkColorGetA(b->getColor()) ||
255 a->getStrokeCap() != b->getStrokeCap() ||
256 a->getStrokeJoin() != b->getStrokeJoin() ||
257 a->getStrokeWidth() != b->getStrokeWidth() ||
258 a->getStrokeMiter() != b->getStrokeMiter()) {
259 return false;
260 }
261
262 SkXfermode::Mode aXfermodeName = SkXfermode::kSrcOver_Mode;
263 SkXfermode* aXfermode = a->getXfermode();
264 if (aXfermode) {
265 aXfermode->asMode(&aXfermodeName);
266 }
267 if (aXfermodeName < 0 || aXfermodeName > SkXfermode::kLastMode ||
268 blend_mode_from_xfermode(aXfermodeName) == NULL) {
269 aXfermodeName = SkXfermode::kSrcOver_Mode;
270 }
271 const char* aXfermodeString = blend_mode_from_xfermode(aXfermodeName);
272 SkASSERT(aXfermodeString != NULL);
273
274 SkXfermode::Mode bXfermodeName = SkXfermode::kSrcOver_Mode;
275 SkXfermode* bXfermode = b->getXfermode();
276 if (bXfermode) {
277 bXfermode->asMode(&bXfermodeName);
278 }
279 if (bXfermodeName < 0 || bXfermodeName > SkXfermode::kLastMode ||
280 blend_mode_from_xfermode(bXfermodeName) == NULL) {
281 bXfermodeName = SkXfermode::kSrcOver_Mode;
282 }
283 const char* bXfermodeString = blend_mode_from_xfermode(bXfermodeName);
284 SkASSERT(bXfermodeString != NULL);
285
286 return strcmp(aXfermodeString, bXfermodeString) == 0;
287 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698