Chromium Code Reviews| 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 |