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

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

Issue 1046293002: SkPDF: SkPDFGraphicState Lookup hashtabled (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 2015-04-01 (Wednesday) 15:28:18 EDT Created 5 years, 8 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 "SkLazyPtr.h" 9 #include "SkLazyPtr.h"
10 #include "SkPDFCanon.h" 10 #include "SkPDFCanon.h"
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 return "Normal"; 63 return "Normal";
64 64
65 // TODO(vandebo): Figure out if we can support more of these modes. 65 // TODO(vandebo): Figure out if we can support more of these modes.
66 case SkXfermode::kXor_Mode: 66 case SkXfermode::kXor_Mode:
67 case SkXfermode::kPlus_Mode: 67 case SkXfermode::kPlus_Mode:
68 return NULL; 68 return NULL;
69 } 69 }
70 return NULL; 70 return NULL;
71 } 71 }
72 72
73 static bool equivalent(const SkPaint& a, const SkPaint& b) { 73 // If a SkXfermode is unsupported in PDF, this function returns
74 // We're only interested in some fields of the SkPaint, so we have 74 // SrcOver, otherwise, it returns that Xfermode as a Mode.
75 // a custom equality function. 75 static SkXfermode::Mode mode_for_pdf(const SkXfermode* xfermode) {
76 if (SkColorGetA(a.getColor()) != SkColorGetA(b.getColor()) || 76 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode;
77 a.getStrokeCap() != b.getStrokeCap() || 77 if (xfermode) {
78 a.getStrokeJoin() != b.getStrokeJoin() || 78 xfermode->asMode(&mode);
79 a.getStrokeWidth() != b.getStrokeWidth() ||
80 a.getStrokeMiter() != b.getStrokeMiter()) {
81 return false;
82 } 79 }
83 80 switch (mode) {
84 SkXfermode::Mode aXfermodeName = SkXfermode::kSrcOver_Mode; 81 case SkXfermode::kSrcOver_Mode:
85 SkXfermode* aXfermode = a.getXfermode(); 82 case SkXfermode::kMultiply_Mode:
86 if (aXfermode) { 83 case SkXfermode::kScreen_Mode:
87 aXfermode->asMode(&aXfermodeName); 84 case SkXfermode::kOverlay_Mode:
85 case SkXfermode::kDarken_Mode:
86 case SkXfermode::kLighten_Mode:
87 case SkXfermode::kColorDodge_Mode:
88 case SkXfermode::kColorBurn_Mode:
89 case SkXfermode::kHardLight_Mode:
90 case SkXfermode::kSoftLight_Mode:
91 case SkXfermode::kDifference_Mode:
92 case SkXfermode::kExclusion_Mode:
93 case SkXfermode::kHue_Mode:
94 case SkXfermode::kSaturation_Mode:
95 case SkXfermode::kColor_Mode:
96 case SkXfermode::kLuminosity_Mode:
97 // Mode is suppported and handled by pdf graphics state.
98 return mode;
99 default:
100 return SkXfermode::kSrcOver_Mode; // Default mode.
88 } 101 }
89 if (aXfermodeName < 0 || aXfermodeName > SkXfermode::kLastMode ||
90 as_blend_mode(aXfermodeName) == NULL) {
91 aXfermodeName = SkXfermode::kSrcOver_Mode;
92 }
93 const char* aXfermodeString = as_blend_mode(aXfermodeName);
94 SkASSERT(aXfermodeString != NULL);
95
96 SkXfermode::Mode bXfermodeName = SkXfermode::kSrcOver_Mode;
97 SkXfermode* bXfermode = b.getXfermode();
98 if (bXfermode) {
99 bXfermode->asMode(&bXfermodeName);
100 }
101 if (bXfermodeName < 0 || bXfermodeName > SkXfermode::kLastMode ||
102 as_blend_mode(bXfermodeName) == NULL) {
103 bXfermodeName = SkXfermode::kSrcOver_Mode;
104 }
105 const char* bXfermodeString = as_blend_mode(bXfermodeName);
106 SkASSERT(bXfermodeString != NULL);
107
108 return strcmp(aXfermodeString, bXfermodeString) == 0;
109 } 102 }
110 103
111 bool SkPDFGraphicState::equals(const SkPaint& paint) const { 104 SkPDFGraphicState::SkPDFGraphicState(const SkPaint& p)
112 return equivalent(paint, fPaint); 105 : fStrokeWidth(p.getStrokeWidth())
113 } 106 , fStrokeMiter(p.getStrokeMiter())
107 , fAlpha(p.getAlpha())
108 , fStrokeCap(SkToU8(p.getStrokeCap()))
109 , fStrokeJoin(SkToU8(p.getStrokeJoin()))
110 , fMode(SkToU8(mode_for_pdf(p.getXfermode()))) {}
114 111
115 SkPDFGraphicState::~SkPDFGraphicState() {} 112 SkPDFGraphicState::SkPDFGraphicState(const SkPDFGraphicState& other)
116 113 : fStrokeWidth(other.fStrokeWidth)
117 void SkPDFGraphicState::emitObject(SkWStream* stream, 114 , fStrokeMiter(other.fStrokeMiter)
118 const SkPDFObjNumMap& objNumMap, 115 , fAlpha(other.fAlpha)
119 const SkPDFSubstituteMap& substitutes) { 116 , fStrokeCap(other.fStrokeCap)
120 populateDict(); 117 , fStrokeJoin(other.fStrokeJoin)
121 SkPDFDict::emitObject(stream, objNumMap, substitutes); 118 , fMode(other.fMode) {}
122 }
123 119
124 // static 120 // static
125 SkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint( 121 SkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint(
126 SkPDFCanon* canon, const SkPaint& paint) { 122 SkPDFCanon* canon, const SkPaint& paint) {
127 SkASSERT(canon); 123 SkASSERT(canon);
128 SkPDFGraphicState* pdfGraphicState = canon->findGraphicState(paint); 124 SkPDFGraphicState key(paint);
125 SkPDFGraphicState* pdfGraphicState = canon->findGraphicState(key);
129 if (pdfGraphicState) { 126 if (pdfGraphicState) {
130 return SkRef(pdfGraphicState); 127 return SkRef(pdfGraphicState);
131 } 128 }
132 pdfGraphicState = new SkPDFGraphicState(paint); 129 pdfGraphicState = new SkPDFGraphicState(paint);
133 canon->addGraphicState(pdfGraphicState); 130 canon->addGraphicState(pdfGraphicState);
134 return pdfGraphicState; 131 return pdfGraphicState;
135 } 132 }
136 133
137 namespace { 134 namespace {
138 SkPDFObject* create_invert_function() { 135 SkPDFObject* create_invert_function() {
(...skipping 13 matching lines...) Expand all
152 SkPDFStream, (psInvertStream.get())); 149 SkPDFStream, (psInvertStream.get()));
153 invertFunction->insertInt("FunctionType", 4); 150 invertFunction->insertInt("FunctionType", 4);
154 invertFunction->insert("Domain", domainAndRange.get()); 151 invertFunction->insert("Domain", domainAndRange.get());
155 invertFunction->insert("Range", domainAndRange.get()); 152 invertFunction->insert("Range", domainAndRange.get());
156 return invertFunction; 153 return invertFunction;
157 } 154 }
158 155
159 template <typename T> void unref(T* ptr) { ptr->unref(); } 156 template <typename T> void unref(T* ptr) { ptr->unref(); }
160 } // namespace 157 } // namespace
161 158
162 SK_DECLARE_STATIC_LAZY_PTR(SkPDFObject, invertFunction, 159 SK_DECLARE_STATIC_LAZY_PTR(SkPDFObject,
163 create_invert_function, unref<SkPDFObject>); 160 invertFunction,
161 create_invert_function,
162 unref<SkPDFObject>);
164 163
165 // static 164 // static
166 SkPDFGraphicState* SkPDFGraphicState::GetSMaskGraphicState( 165 SkPDFDict* SkPDFGraphicState::GetSMaskGraphicState(SkPDFFormXObject* sMask,
167 SkPDFFormXObject* sMask, bool invert, SkPDFSMaskMode sMaskMode) { 166 bool invert,
167 SkPDFSMaskMode sMaskMode) {
168 // The practical chances of using the same mask more than once are unlikely 168 // The practical chances of using the same mask more than once are unlikely
169 // enough that it's not worth canonicalizing. 169 // enough that it's not worth canonicalizing.
170 SkAutoTUnref<SkPDFDict> sMaskDict(new SkPDFDict("Mask")); 170 SkAutoTUnref<SkPDFDict> sMaskDict(new SkPDFDict("Mask"));
171 if (sMaskMode == kAlpha_SMaskMode) { 171 if (sMaskMode == kAlpha_SMaskMode) {
172 sMaskDict->insertName("S", "Alpha"); 172 sMaskDict->insertName("S", "Alpha");
173 } else if (sMaskMode == kLuminosity_SMaskMode) { 173 } else if (sMaskMode == kLuminosity_SMaskMode) {
174 sMaskDict->insertName("S", "Luminosity"); 174 sMaskDict->insertName("S", "Luminosity");
175 } 175 }
176 sMaskDict->insert("G", new SkPDFObjRef(sMask))->unref(); 176 sMaskDict->insert("G", new SkPDFObjRef(sMask))->unref();
177
178 SkPDFGraphicState* result = new SkPDFGraphicState;
179 result->fPopulated = true;
180 result->insertName("Type", "ExtGState");
181 result->insert("SMask", sMaskDict.get());
182
183 if (invert) { 177 if (invert) {
184 sMaskDict->insert("TR", new SkPDFObjRef(invertFunction.get()))->unref(); 178 sMaskDict->insert("TR", new SkPDFObjRef(invertFunction.get()))->unref();
185 } 179 }
186 180
181 SkPDFDict* result = new SkPDFDict("ExtGState");
182 result->insert("SMask", sMaskDict.get());
187 return result; 183 return result;
188 } 184 }
189 185
190 SkPDFGraphicState* SkPDFGraphicState::CreateNoSMaskGraphicState() { 186 static SkPDFDict* create_no_smask_graphic_state() {
191 SkPDFGraphicState* noSMaskGS = SkNEW(SkPDFGraphicState); 187 SkPDFDict* noSMaskGS = new SkPDFDict("ExtGState");
192 noSMaskGS->fPopulated = true;
193 noSMaskGS->insertName("Type", "ExtGState");
194 noSMaskGS->insertName("SMask", "None"); 188 noSMaskGS->insertName("SMask", "None");
195 return noSMaskGS; 189 return noSMaskGS;
196 } 190 }
197 191
198 SK_DECLARE_STATIC_LAZY_PTR( 192 SK_DECLARE_STATIC_LAZY_PTR(SkPDFDict,
199 SkPDFGraphicState, noSMaskGraphicState, 193 noSMaskGraphicState,
200 SkPDFGraphicState::CreateNoSMaskGraphicState, unref<SkPDFGraphicState>); 194 create_no_smask_graphic_state,
195 unref<SkPDFDict>);
201 196
202 // static 197 // static
203 SkPDFGraphicState* SkPDFGraphicState::GetNoSMaskGraphicState() { 198 SkPDFDict* SkPDFGraphicState::GetNoSMaskGraphicState() {
204 return SkRef(noSMaskGraphicState.get()); 199 return SkRef(noSMaskGraphicState.get());
205 } 200 }
206 201
207 SkPDFGraphicState::SkPDFGraphicState() 202 void SkPDFGraphicState::emitObject(SkWStream* stream,
208 : fPopulated(false) {} 203 const SkPDFObjNumMap& objNumMap,
204 const SkPDFSubstituteMap& substitutes) {
205 SkAutoTUnref<SkPDFDict> dict(SkNEW_ARGS(SkPDFDict, ("ExtGState")));
206 dict->insertName("Type", "ExtGState");
209 207
210 SkPDFGraphicState::SkPDFGraphicState(const SkPaint& paint) 208 SkAutoTUnref<SkPDFScalar> alpha(new SkPDFScalar(SkScalarDiv(fAlpha, 0xFF)));
211 : fPaint(paint), fPopulated(false) {} 209 dict->insert("CA", alpha.get());
210 dict->insert("ca", alpha.get());
212 211
213 // populateDict and operator== have to stay in sync with each other. 212 SkPaint::Cap strokeCap = (SkPaint::Cap)fStrokeCap;
214 void SkPDFGraphicState::populateDict() { 213 SkPaint::Join strokeJoin = (SkPaint::Join)fStrokeJoin;
215 if (!fPopulated) { 214 SkXfermode::Mode xferMode = (SkXfermode::Mode)fMode;
216 fPopulated = true;
217 insertName("Type", "ExtGState");
218 215
219 SkAutoTUnref<SkPDFScalar> alpha( 216 SK_COMPILE_ASSERT(SkPaint::kButt_Cap == 0, paint_cap_mismatch);
220 new SkPDFScalar(SkScalarDiv(fPaint.getAlpha(), 0xFF))); 217 SK_COMPILE_ASSERT(SkPaint::kRound_Cap == 1, paint_cap_mismatch);
221 insert("CA", alpha.get()); 218 SK_COMPILE_ASSERT(SkPaint::kSquare_Cap == 2, paint_cap_mismatch);
222 insert("ca", alpha.get()); 219 SK_COMPILE_ASSERT(SkPaint::kCapCount == 3, paint_cap_mismatch);
220 SkASSERT(strokeCap >= 0 && strokeCap <= 2);
221 dict->insertInt("LC", strokeCap);
223 222
224 SK_COMPILE_ASSERT(SkPaint::kButt_Cap == 0, paint_cap_mismatch); 223 SK_COMPILE_ASSERT(SkPaint::kMiter_Join == 0, paint_join_mismatch);
225 SK_COMPILE_ASSERT(SkPaint::kRound_Cap == 1, paint_cap_mismatch); 224 SK_COMPILE_ASSERT(SkPaint::kRound_Join == 1, paint_join_mismatch);
226 SK_COMPILE_ASSERT(SkPaint::kSquare_Cap == 2, paint_cap_mismatch); 225 SK_COMPILE_ASSERT(SkPaint::kBevel_Join == 2, paint_join_mismatch);
227 SK_COMPILE_ASSERT(SkPaint::kCapCount == 3, paint_cap_mismatch); 226 SK_COMPILE_ASSERT(SkPaint::kJoinCount == 3, paint_join_mismatch);
228 SkASSERT(fPaint.getStrokeCap() >= 0 && fPaint.getStrokeCap() <= 2); 227 SkASSERT(strokeJoin >= 0 && strokeJoin <= 2);
229 insertInt("LC", fPaint.getStrokeCap()); 228 dict->insertInt("LJ", strokeJoin);
230 229
231 SK_COMPILE_ASSERT(SkPaint::kMiter_Join == 0, paint_join_mismatch); 230 dict->insertScalar("LW", fStrokeWidth);
232 SK_COMPILE_ASSERT(SkPaint::kRound_Join == 1, paint_join_mismatch); 231 dict->insertScalar("ML", fStrokeMiter);
233 SK_COMPILE_ASSERT(SkPaint::kBevel_Join == 2, paint_join_mismatch); 232 // SA = Auto stroke adjustment.
234 SK_COMPILE_ASSERT(SkPaint::kJoinCount == 3, paint_join_mismatch); 233 dict->insert("SA", new SkPDFBool(true))->unref();
235 SkASSERT(fPaint.getStrokeJoin() >= 0 && fPaint.getStrokeJoin() <= 2); 234 dict->insertName("BM", as_blend_mode(xferMode));
236 insertInt("LJ", fPaint.getStrokeJoin()); 235 dict->emitObject(stream, objNumMap, substitutes);
237
238 insertScalar("LW", fPaint.getStrokeWidth());
239 insertScalar("ML", fPaint.getStrokeMiter());
240 insert("SA", new SkPDFBool(true))->unref(); // Auto stroke adjustment.
241
242 SkXfermode::Mode xfermode = SkXfermode::kSrcOver_Mode;
243 // If asMode fails, default to kSrcOver_Mode.
244 if (fPaint.getXfermode())
245 fPaint.getXfermode()->asMode(&xfermode);
246 // If we don't support the mode, just use kSrcOver_Mode.
247 if (xfermode < 0 || xfermode > SkXfermode::kLastMode ||
248 as_blend_mode(xfermode) == NULL) {
249 xfermode = SkXfermode::kSrcOver_Mode;
250 NOT_IMPLEMENTED("unsupported xfermode", false);
251 }
252 insertName("BM", as_blend_mode(xfermode));
253 }
254 } 236 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698