OLD | NEW |
---|---|
(Empty) | |
1 | |
2 /* | |
3 * Copyright 2014 Google Inc. | |
4 * | |
5 * Use of this source code is governed by a BSD-style license that can be | |
6 * found in the LICENSE file. | |
7 */ | |
8 | |
9 #include "gm.h" | |
10 #include "GrFragmentProcessor.h" | |
11 #include "GrCoordTransform.h" | |
12 #include "gl/GrGLProcessor.h" | |
13 #include "gl/builders/GrGLProgramBuilder.h" | |
14 #include "Resources.h" | |
15 #include "SkShader.h" | |
16 #include "SkStream.h" | |
17 #include "SkTypeface.h" | |
18 | |
19 namespace skiagm { | |
20 | |
21 /////////////////////////////////////////////////////////////////////////////// | |
22 | |
23 class DCShader : public SkShader { | |
24 public: | |
25 DCShader(const SkMatrix& matrix) : fDeviceMatrix(matrix) {} | |
26 | |
27 Factory getFactory() const SK_OVERRIDE { return NULL; } | |
28 | |
29 bool asFragmentProcessor(GrContext*, const SkPaint& paint, const SkMatrix& v iewM, | |
30 const SkMatrix* localMatrix, GrColor* color, | |
31 GrFragmentProcessor** fp) const SK_OVERRIDE { | |
32 class DCFP : public GrFragmentProcessor { | |
33 public: | |
34 DCFP(const SkMatrix& m) : fDeviceTransform(kDevice_GrCoordSet, m) { | |
35 this->addCoordTransform(&fDeviceTransform); | |
36 this->initClassID<DCFP>(); | |
37 } | |
38 | |
39 void getGLProcessorKey(const GrGLCaps& caps, | |
40 GrProcessorKeyBuilder* b) const SK_OVERRIDE { } | |
41 | |
42 GrGLFragmentProcessor* createGLInstance() const SK_OVERRIDE { | |
43 class DCGLFP : public GrGLFragmentProcessor { | |
44 void emitCode(GrGLFPBuilder* builder, | |
45 const GrFragmentProcessor& fp, | |
46 const char* outputColor, | |
47 const char* inputColor, | |
48 const TransformedCoordsArray& coords, | |
49 const TextureSamplerArray& samplers) { | |
50 builder->getFragmentShaderBuilder()->codeAppendf( | |
51 "vec2 r = mod(%s.xy, vec2(50.0));", coords[0].c_str( )); | |
52 builder->getFragmentShaderBuilder()->codeAppendf( | |
53 "vec4 color = vec4(0.5*sin(%s.x / 25.0) + 0.5," | |
54 "0.5*cos((%s.x + %s.y) / 25.0) + 0 .5," | |
55 "(r.x + r.y) / 25.0," | |
56 "distance(r, vec2(25.0)) / 50.0 + 0.2);", | |
57 coords[0].c_str(), coords[0].c_str(), coords[0].c_st r(), | |
58 coords[0].c_str(), coords[0].c_str()); | |
59 builder->getFragmentShaderBuilder()->codeAppendf( | |
60 "color.rgb *= color.a;" | |
61 "%s = color * %s;", | |
62 outputColor, GrGLSLExpr4(inputColor).c_str()); | |
63 } | |
64 void setData(const GrGLProgramDataManager&, const GrProcesso r&) SK_OVERRIDE {} | |
65 }; | |
66 return SkNEW(DCGLFP); | |
67 } | |
68 | |
69 const char* name() const SK_OVERRIDE { return "DCFP"; } | |
70 | |
71 void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVE RRIDE { | |
72 inout->mulByUnknownFourComponents(); | |
73 } | |
74 | |
75 private: | |
76 bool onIsEqual(const GrFragmentProcessor&) const SK_OVERRIDE { retur n true; } | |
77 | |
78 GrCoordTransform fDeviceTransform; | |
79 }; | |
80 *fp = SkNEW_ARGS(DCFP, (fDeviceMatrix)); | |
81 *color = GrColorPackA4(paint.getAlpha()); | |
82 return true; | |
83 } | |
84 private: | |
85 const SkMatrix fDeviceMatrix; | |
86 }; | |
87 | |
88 class DCShaderGM : public GM { | |
89 public: | |
90 DCShaderGM() { | |
91 this->setBGColor(0xFFAABBCC); | |
92 } | |
93 | |
94 ~DCShaderGM() SK_OVERRIDE { | |
95 for (int i = 0; i < fPrims.count(); ++i) { | |
96 SkDELETE(fPrims[i]); | |
97 } | |
98 } | |
99 | |
100 protected: | |
101 uint32_t onGetFlags() const SK_OVERRIDE { | |
102 return kGPUOnly_Flag; | |
103 } | |
104 | |
105 SkString onShortName() SK_OVERRIDE { | |
106 return SkString("dcshader"); | |
107 } | |
108 | |
109 SkISize onISize() SK_OVERRIDE { return SkISize::Make(1200, 900); } | |
110 | |
111 void onOnceBeforeDraw() SK_OVERRIDE { | |
112 struct Rect : public Prim { | |
113 SkRect draw(SkCanvas* canvas, const SkPaint& paint) SK_OVERRIDE { | |
114 SkRect rect = SkRect::MakeXYWH(0, 0, 100, 100); | |
115 canvas->drawRect(rect, paint); | |
116 return rect; | |
117 } | |
118 }; | |
119 | |
120 struct Circle : public Prim { | |
121 SkRect draw(SkCanvas* canvas, const SkPaint& paint) SK_OVERRIDE { | |
122 static const SkScalar radius = 50; | |
123 canvas->drawCircle(radius, radius, radius, paint); | |
124 return SkRect::MakeXYWH(0, 0, 2 * radius, 2 * radius); | |
125 } | |
126 }; | |
127 | |
128 struct RRect : public Prim { | |
129 SkRect draw(SkCanvas* canvas, const SkPaint& paint) SK_OVERRIDE { | |
130 SkRRect rrect; | |
131 rrect.setRectXY(SkRect::MakeXYWH(0, 0, 100, 100), 10, 10); | |
132 canvas->drawRRect(rrect, paint); | |
133 return rrect.getBounds(); | |
134 } | |
135 }; | |
136 | |
137 struct DRRect : public Prim { | |
138 SkRect draw(SkCanvas* canvas, const SkPaint& paint) SK_OVERRIDE { | |
139 SkRRect outerRRect; | |
140 outerRRect.setRectXY(SkRect::MakeXYWH(0, 0, 100, 100), 10, 10); | |
141 SkRRect innerRRect; | |
142 innerRRect.setRectXY(SkRect::MakeXYWH(10, 15, 70, 60), 5, 3); | |
143 canvas->drawDRRect(outerRRect, innerRRect, paint); | |
144 return outerRRect.getBounds(); | |
145 } | |
146 }; | |
147 struct Path : public Prim { | |
148 SkRect draw(SkCanvas* canvas, const SkPaint& paint) SK_OVERRIDE { | |
149 SkPath path; | |
150 path.addCircle(30, 30, 20); | |
151 path.addOval(SkRect::MakeXYWH(5, 5, 45, 75)); | |
152 path.setFillType(SkPath::kEvenOdd_FillType); | |
153 canvas->drawPath(path, paint); | |
154 return path.getBounds(); | |
155 } | |
156 }; | |
157 | |
158 struct Points : public Prim { | |
159 Points(SkCanvas::PointMode mode) : fMode(mode) {} | |
160 | |
161 SkRect draw(SkCanvas* canvas, const SkPaint& paint) SK_OVERRIDE { | |
162 SkRandom random; | |
163 SkPoint points[500]; | |
164 SkRect bounds = SkRect::MakeWH(100, 100); | |
165 int count = SkToInt(SK_ARRAY_COUNT(points)); | |
166 if (SkCanvas::kPoints_PointMode != fMode) { | |
167 count = SkTMin(count, 10); | |
168 } | |
169 for (int p = 0; p < count; ++p) { | |
170 points[p].fX = random.nextUScalar1() * bounds.width(); | |
171 points[p].fY = random.nextUScalar1() * bounds.width(); | |
172 } | |
173 canvas->drawPoints(fMode, count, points, paint); | |
174 return bounds; | |
175 } | |
176 SkCanvas::PointMode fMode; | |
177 }; | |
178 | |
179 struct Text : public Prim { | |
180 SkRect draw(SkCanvas* canvas, const SkPaint& origPaint) SK_OVERRIDE { | |
181 SkPaint paint = origPaint; | |
182 paint.setTextSize(20.f); | |
183 this->setFont(&paint); | |
184 const char* text = this->text(); | |
185 static const SkVector offset = SkVector::Make(10, 10); | |
186 canvas->drawText(text, strlen(text), offset.fX, offset.fY, paint ); | |
187 SkRect bounds; | |
188 paint.measureText(text, strlen(text), &bounds); | |
189 bounds.offset(offset); | |
190 return bounds; | |
191 } | |
192 | |
193 virtual void setFont(SkPaint* paint) { | |
194 sk_tool_utils::set_portable_typeface(paint); | |
195 } | |
196 | |
197 virtual char* text() const { return "Hello, Skia!"; } | |
198 }; | |
199 | |
200 struct BmpText : public Text { | |
201 void setFont(SkPaint* paint) SK_OVERRIDE { | |
202 if (!fTypeface) { | |
203 SkString filename = GetResourcePath("/Funkster.ttf"); | |
204 SkAutoTUnref<SkFILEStream> stream(new SkFILEStream(filename. c_str())); | |
205 if (!stream->isValid()) { | |
206 SkDebugf("Could not find Funkster.ttf, please set --reso urcePath correctly.\n"); | |
joshualitt
2014/12/23 02:31:51
nit, but you could line wrap
| |
207 return; | |
208 } | |
209 fTypeface.reset(SkTypeface::CreateFromStream(stream)); | |
210 } | |
211 paint->setTypeface(fTypeface); | |
212 } | |
213 | |
214 virtual char* text() const { return "Hello, Skia!"; } | |
215 | |
216 SkAutoTUnref<SkTypeface> fTypeface; | |
217 }; | |
218 fPrims.push_back(SkNEW(Rect)); | |
219 fPrims.push_back(SkNEW(Circle)); | |
220 fPrims.push_back(SkNEW(RRect)); | |
221 fPrims.push_back(SkNEW(DRRect)); | |
222 fPrims.push_back(SkNEW(Path)); | |
223 fPrims.push_back(SkNEW(Points(SkCanvas::kPoints_PointMode))); | |
224 fPrims.push_back(SkNEW(Points(SkCanvas::kLines_PointMode))); | |
225 fPrims.push_back(SkNEW(Points(SkCanvas::kPolygon_PointMode))); | |
226 fPrims.push_back(SkNEW(Text)); | |
227 fPrims.push_back(SkNEW(BmpText)); | |
228 } | |
229 | |
230 void onDraw(SkCanvas* canvas) SK_OVERRIDE { | |
231 SkPaint paint; | |
232 SkTArray<SkMatrix> devMats; | |
233 devMats.push_back().reset(); | |
234 devMats.push_back().setRotate(45, 500, 500); | |
235 | |
236 SkTArray<SkMatrix> viewMats; | |
237 viewMats.push_back().setScale(0.75f, 0.75f); | |
238 viewMats.push_back().setRotate(45, 50, 50); | |
239 viewMats.back().postScale(0.5f, 1.1f); | |
joshualitt
2014/12/23 02:31:51
I know the shader ignores perspective, but it migh
| |
240 | |
241 canvas->translate(10, 20); | |
242 canvas->save(); | |
243 SkScalar tx = 0, maxTy = 0; | |
244 static const SkScalar kW = 1100; | |
245 | |
246 for (int aa = 0; aa < 2; ++aa) { | |
247 for (int i = 0; i < fPrims.count(); ++i) { | |
248 for (int j = 0; j < devMats.count(); ++j) { | |
249 for (int k = 0; k < viewMats.count(); ++k) { | |
250 paint.setShader(SkNEW_ARGS(DCShader, (devMats[j])))->unr ef(); | |
251 paint.setAntiAlias(SkToBool(aa)); | |
252 canvas->save(); | |
253 canvas->concat(viewMats[k]); | |
254 SkRect bounds = fPrims[i]->draw(canvas, paint); | |
255 canvas->restore(); | |
256 viewMats[k].mapRect(&bounds); | |
257 // add margins | |
258 bounds.fRight += 20; | |
259 bounds.fBottom += 20; | |
260 canvas->translate(bounds.fRight, 0); | |
261 tx += bounds.fRight; | |
262 maxTy = SkTMax(bounds.fBottom, maxTy); | |
263 if (tx > kW) { | |
264 tx = 0; | |
265 canvas->restore(); | |
266 canvas->translate(0, maxTy); | |
267 canvas->save(); | |
268 maxTy = 0; | |
269 } | |
270 } | |
271 } | |
272 } | |
273 } | |
274 canvas->restore(); | |
275 } | |
276 | |
277 private: | |
278 struct Prim { | |
279 virtual SkRect draw(SkCanvas*, const SkPaint&) = 0; | |
280 }; | |
281 | |
282 SkTArray<Prim*> fPrims; | |
283 | |
284 typedef GM INHERITED; | |
285 }; | |
286 | |
287 DEF_GM( return SkNEW(DCShaderGM); ) | |
288 } | |
OLD | NEW |