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

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) 16:16:21 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
« no previous file with comments | « src/pdf/SkPDFGraphicState.h ('k') | src/pdf/SkPDFShader.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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())
114 107 , fAlpha(p.getAlpha())
115 SkPDFGraphicState::~SkPDFGraphicState() {} 108 , fStrokeCap(SkToU8(p.getStrokeCap()))
116 109 , fStrokeJoin(SkToU8(p.getStrokeJoin()))
117 void SkPDFGraphicState::emitObject(SkWStream* stream, 110 , fMode(SkToU8(mode_for_pdf(p.getXfermode()))) {}
118 const SkPDFObjNumMap& objNumMap,
119 const SkPDFSubstituteMap& substitutes) {
120 populateDict();
121 SkPDFDict::emitObject(stream, objNumMap, substitutes);
122 }
123 111
124 // static 112 // static
125 SkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint( 113 SkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint(
126 SkPDFCanon* canon, const SkPaint& paint) { 114 SkPDFCanon* canon, const SkPaint& paint) {
127 SkASSERT(canon); 115 SkASSERT(canon);
128 SkPDFGraphicState* pdfGraphicState = canon->findGraphicState(paint); 116 SkPDFGraphicState key(paint);
129 if (pdfGraphicState) { 117 if (const SkPDFGraphicState* canonGS = canon->findGraphicState(key)) {
130 return SkRef(pdfGraphicState); 118 // The returned SkPDFGraphicState must be made non-const,
119 // since the emitObject() interface is non-const. But We
120 // promise that there is no way to mutate this object from
121 // here on out.
122 return SkRef(const_cast<SkPDFGraphicState*>(canonGS));
131 } 123 }
132 pdfGraphicState = new SkPDFGraphicState(paint); 124 SkPDFGraphicState* pdfGraphicState = new SkPDFGraphicState(paint);
133 canon->addGraphicState(pdfGraphicState); 125 canon->addGraphicState(pdfGraphicState);
134 return pdfGraphicState; 126 return pdfGraphicState;
135 } 127 }
136 128
137 namespace { 129 namespace {
138 SkPDFObject* create_invert_function() { 130 SkPDFObject* create_invert_function() {
139 // Acrobat crashes if we use a type 0 function, kpdf crashes if we use 131 // Acrobat crashes if we use a type 0 function, kpdf crashes if we use
140 // a type 2 function, so we use a type 4 function. 132 // a type 2 function, so we use a type 4 function.
141 SkAutoTUnref<SkPDFArray> domainAndRange(new SkPDFArray); 133 SkAutoTUnref<SkPDFArray> domainAndRange(new SkPDFArray);
142 domainAndRange->reserve(2); 134 domainAndRange->reserve(2);
143 domainAndRange->appendInt(0); 135 domainAndRange->appendInt(0);
144 domainAndRange->appendInt(1); 136 domainAndRange->appendInt(1);
145 137
146 static const char psInvert[] = "{1 exch sub}"; 138 static const char psInvert[] = "{1 exch sub}";
147 // Do not copy the trailing '\0' into the SkData. 139 // Do not copy the trailing '\0' into the SkData.
148 SkAutoTUnref<SkData> psInvertStream( 140 SkAutoTUnref<SkData> psInvertStream(
149 SkData::NewWithoutCopy(psInvert, strlen(psInvert))); 141 SkData::NewWithoutCopy(psInvert, strlen(psInvert)));
150 142
151 SkPDFStream* invertFunction = SkNEW_ARGS( 143 SkPDFStream* invertFunction = SkNEW_ARGS(
152 SkPDFStream, (psInvertStream.get())); 144 SkPDFStream, (psInvertStream.get()));
153 invertFunction->insertInt("FunctionType", 4); 145 invertFunction->insertInt("FunctionType", 4);
154 invertFunction->insert("Domain", domainAndRange.get()); 146 invertFunction->insert("Domain", domainAndRange.get());
155 invertFunction->insert("Range", domainAndRange.get()); 147 invertFunction->insert("Range", domainAndRange.get());
156 return invertFunction; 148 return invertFunction;
157 } 149 }
158 150
159 template <typename T> void unref(T* ptr) { ptr->unref(); } 151 template <typename T> void unref(T* ptr) { ptr->unref(); }
160 } // namespace 152 } // namespace
161 153
162 SK_DECLARE_STATIC_LAZY_PTR(SkPDFObject, invertFunction, 154 SK_DECLARE_STATIC_LAZY_PTR(SkPDFObject,
163 create_invert_function, unref<SkPDFObject>); 155 invertFunction,
156 create_invert_function,
157 unref<SkPDFObject>);
164 158
165 // static 159 // static
166 SkPDFGraphicState* SkPDFGraphicState::GetSMaskGraphicState( 160 SkPDFDict* SkPDFGraphicState::GetSMaskGraphicState(SkPDFFormXObject* sMask,
167 SkPDFFormXObject* sMask, bool invert, SkPDFSMaskMode sMaskMode) { 161 bool invert,
162 SkPDFSMaskMode sMaskMode) {
168 // The practical chances of using the same mask more than once are unlikely 163 // The practical chances of using the same mask more than once are unlikely
169 // enough that it's not worth canonicalizing. 164 // enough that it's not worth canonicalizing.
170 SkAutoTUnref<SkPDFDict> sMaskDict(new SkPDFDict("Mask")); 165 SkAutoTUnref<SkPDFDict> sMaskDict(new SkPDFDict("Mask"));
171 if (sMaskMode == kAlpha_SMaskMode) { 166 if (sMaskMode == kAlpha_SMaskMode) {
172 sMaskDict->insertName("S", "Alpha"); 167 sMaskDict->insertName("S", "Alpha");
173 } else if (sMaskMode == kLuminosity_SMaskMode) { 168 } else if (sMaskMode == kLuminosity_SMaskMode) {
174 sMaskDict->insertName("S", "Luminosity"); 169 sMaskDict->insertName("S", "Luminosity");
175 } 170 }
176 sMaskDict->insert("G", new SkPDFObjRef(sMask))->unref(); 171 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) { 172 if (invert) {
184 sMaskDict->insert("TR", new SkPDFObjRef(invertFunction.get()))->unref(); 173 sMaskDict->insert("TR", new SkPDFObjRef(invertFunction.get()))->unref();
185 } 174 }
186 175
176 SkPDFDict* result = new SkPDFDict("ExtGState");
177 result->insert("SMask", sMaskDict.get());
187 return result; 178 return result;
188 } 179 }
189 180
190 SkPDFGraphicState* SkPDFGraphicState::CreateNoSMaskGraphicState() { 181 namespace {
191 SkPDFGraphicState* noSMaskGS = SkNEW(SkPDFGraphicState); 182 SkPDFDict* create_no_smask_graphic_state() {
192 noSMaskGS->fPopulated = true; 183 SkPDFDict* noSMaskGS = new SkPDFDict("ExtGState");
193 noSMaskGS->insertName("Type", "ExtGState");
194 noSMaskGS->insertName("SMask", "None"); 184 noSMaskGS->insertName("SMask", "None");
195 return noSMaskGS; 185 return noSMaskGS;
196 } 186 }
197 187 } // namespace
198 SK_DECLARE_STATIC_LAZY_PTR( 188 SK_DECLARE_STATIC_LAZY_PTR(SkPDFDict,
199 SkPDFGraphicState, noSMaskGraphicState, 189 noSMaskGraphicState,
200 SkPDFGraphicState::CreateNoSMaskGraphicState, unref<SkPDFGraphicState>); 190 create_no_smask_graphic_state,
191 unref<SkPDFDict>);
201 192
202 // static 193 // static
203 SkPDFGraphicState* SkPDFGraphicState::GetNoSMaskGraphicState() { 194 SkPDFDict* SkPDFGraphicState::GetNoSMaskGraphicState() {
204 return SkRef(noSMaskGraphicState.get()); 195 return SkRef(noSMaskGraphicState.get());
205 } 196 }
206 197
207 SkPDFGraphicState::SkPDFGraphicState() 198 void SkPDFGraphicState::emitObject(SkWStream* stream,
208 : fPopulated(false) {} 199 const SkPDFObjNumMap& objNumMap,
200 const SkPDFSubstituteMap& substitutes) {
201 SkAutoTUnref<SkPDFDict> dict(SkNEW_ARGS(SkPDFDict, ("ExtGState")));
202 dict->insertName("Type", "ExtGState");
209 203
210 SkPDFGraphicState::SkPDFGraphicState(const SkPaint& paint) 204 SkAutoTUnref<SkPDFScalar> alpha(new SkPDFScalar(SkScalarDiv(fAlpha, 0xFF)));
211 : fPaint(paint), fPopulated(false) {} 205 dict->insert("CA", alpha.get());
206 dict->insert("ca", alpha.get());
212 207
213 // populateDict and operator== have to stay in sync with each other. 208 SkPaint::Cap strokeCap = (SkPaint::Cap)fStrokeCap;
214 void SkPDFGraphicState::populateDict() { 209 SkPaint::Join strokeJoin = (SkPaint::Join)fStrokeJoin;
215 if (!fPopulated) { 210 SkXfermode::Mode xferMode = (SkXfermode::Mode)fMode;
216 fPopulated = true;
217 insertName("Type", "ExtGState");
218 211
219 SkAutoTUnref<SkPDFScalar> alpha( 212 SK_COMPILE_ASSERT(SkPaint::kButt_Cap == 0, paint_cap_mismatch);
220 new SkPDFScalar(SkScalarDiv(fPaint.getAlpha(), 0xFF))); 213 SK_COMPILE_ASSERT(SkPaint::kRound_Cap == 1, paint_cap_mismatch);
221 insert("CA", alpha.get()); 214 SK_COMPILE_ASSERT(SkPaint::kSquare_Cap == 2, paint_cap_mismatch);
222 insert("ca", alpha.get()); 215 SK_COMPILE_ASSERT(SkPaint::kCapCount == 3, paint_cap_mismatch);
216 SkASSERT(strokeCap >= 0 && strokeCap <= 2);
217 dict->insertInt("LC", strokeCap);
223 218
224 SK_COMPILE_ASSERT(SkPaint::kButt_Cap == 0, paint_cap_mismatch); 219 SK_COMPILE_ASSERT(SkPaint::kMiter_Join == 0, paint_join_mismatch);
225 SK_COMPILE_ASSERT(SkPaint::kRound_Cap == 1, paint_cap_mismatch); 220 SK_COMPILE_ASSERT(SkPaint::kRound_Join == 1, paint_join_mismatch);
226 SK_COMPILE_ASSERT(SkPaint::kSquare_Cap == 2, paint_cap_mismatch); 221 SK_COMPILE_ASSERT(SkPaint::kBevel_Join == 2, paint_join_mismatch);
227 SK_COMPILE_ASSERT(SkPaint::kCapCount == 3, paint_cap_mismatch); 222 SK_COMPILE_ASSERT(SkPaint::kJoinCount == 3, paint_join_mismatch);
228 SkASSERT(fPaint.getStrokeCap() >= 0 && fPaint.getStrokeCap() <= 2); 223 SkASSERT(strokeJoin >= 0 && strokeJoin <= 2);
229 insertInt("LC", fPaint.getStrokeCap()); 224 dict->insertInt("LJ", strokeJoin);
230 225
231 SK_COMPILE_ASSERT(SkPaint::kMiter_Join == 0, paint_join_mismatch); 226 dict->insertScalar("LW", fStrokeWidth);
232 SK_COMPILE_ASSERT(SkPaint::kRound_Join == 1, paint_join_mismatch); 227 dict->insertScalar("ML", fStrokeMiter);
233 SK_COMPILE_ASSERT(SkPaint::kBevel_Join == 2, paint_join_mismatch); 228 // SA = Auto stroke adjustment.
234 SK_COMPILE_ASSERT(SkPaint::kJoinCount == 3, paint_join_mismatch); 229 dict->insert("SA", new SkPDFBool(true))->unref();
235 SkASSERT(fPaint.getStrokeJoin() >= 0 && fPaint.getStrokeJoin() <= 2); 230 dict->insertName("BM", as_blend_mode(xferMode));
236 insertInt("LJ", fPaint.getStrokeJoin()); 231 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 } 232 }
OLDNEW
« no previous file with comments | « src/pdf/SkPDFGraphicState.h ('k') | src/pdf/SkPDFShader.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698