1 #include "SampleCode.h" 2 #include "SkView.h" 3 #include "SkCanvas.h" 4 #include "SkGradientShader.h" 5 #include "SkGraphics.h" 6 #include "SkImageDecoder.h" 7 #include "SkPath.h" 8 #include "SkRandom.h" 9 #include "SkRegion.h" 10 #include "SkShader.h" 11 #include "SkUtils.h" 12 #include "SkXfermode.h" 13 #include "SkColorPriv.h" 14 #include "SkColorFilter.h" 15 #include "SkTime.h" 16 #include "SkTypeface.h" 17 18 #include "SkOSFile.h" 19 #include "SkStream.h" 20 21 #include "SkGeometry.h" // private include :( 22 23 static void drawtriangle(SkCanvas* canvas, const SkPaint& paint, 24 const SkPoint pts[3]) { 25 SkPath path; 26 27 path.moveTo(pts[0]); 28 path.lineTo(pts[1]); 29 path.lineTo(pts[2]); 30 31 canvas->drawPath(path, paint); 32 } 33 34 static SkShader* make_shader0(SkIPoint* size) { 35 SkBitmap bm; 36 37 // SkImageDecoder::DecodeFile("/skimages/progressivejpg.jpg", &bm); 38 SkImageDecoder::DecodeFile("/skimages/logo.png", &bm); 39 size->set(bm.width(), bm.height()); 40 return SkShader::CreateBitmapShader(bm, SkShader::kClamp_TileMode, 41 SkShader::kClamp_TileMode); 42 } 43 44 static SkShader* make_shader1(const SkIPoint& size) { 45 SkPoint pts[] = { { 0, 0, }, 46 { SkIntToScalar(size.fX), SkIntToScalar(size.fY) } }; 47 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorRED }; 48 return SkGradientShader::CreateLinear(pts, colors, NULL, 49 SK_ARRAY_COUNT(colors), SkShader::kMirror_TileMode, NULL); 50 } 51 52 /////////////////////////////////////////////////////////////////////////////// 53 54 class Patch { 55 public: 56 Patch() { sk_bzero(fPts, sizeof(fPts)); } 57 ~Patch() {} 58 59 void setPatch(const SkPoint pts[12]) { 60 memcpy(fPts, pts, 12 * sizeof(SkPoint)); 61 fPts[12] = pts[0]; // the last shall be first 62 } 63 void setBounds(int w, int h) { fW = w; fH = h; } 64 65 void draw(SkCanvas*, const SkPaint&, int segsU, int segsV, 66 bool doTextures, bool doColors); 67 68 private: 69 SkPoint fPts[13]; 70 int fW, fH; 71 }; 72 73 static void eval_patch_edge(const SkPoint cubic[], SkPoint samples[], int segs) { 74 SkScalar t = 0; 75 SkScalar dt = SK_Scalar1 / segs; 76 77 samples[0] = cubic[0]; 78 for (int i = 1; i < segs; i++) { 79 t += dt; 80 SkEvalCubicAt(cubic, t, &samples[i], NULL, NULL); 81 } 82 } 83 84 static void eval_sheet(const SkPoint edge[], int nu, int nv, int iu, int iv, 85 SkPoint* pt) { 86 const int TL = 0; 87 const int TR = nu; 88 const int BR = TR + nv; 89 const int BL = BR + nu; 90 91 SkScalar u = SkIntToScalar(iu) / nu; 92 SkScalar v = SkIntToScalar(iv) / nv; 93 94 SkScalar uv = SkScalarMul(u, v); 95 SkScalar Uv = SkScalarMul(SK_Scalar1 - u, v); 96 SkScalar uV = SkScalarMul(u, SK_Scalar1 - v); 97 SkScalar UV = SkScalarMul(SK_Scalar1 - u, SK_Scalar1 - v); 98 99 SkScalar x0 = SkScalarMul(UV, edge[TL].fX) + SkScalarMul(uV, edge[TR].fX) + 100 SkScalarMul(Uv, edge[BL].fX) + SkScalarMul(uv, edge[BR].fX); 101 SkScalar y0 = SkScalarMul(UV, edge[TL].fY) + SkScalarMul(uV, edge[TR].fY) + 102 SkScalarMul(Uv, edge[BL].fY) + SkScalarMul(uv, edge[BR].fY); 103 104 SkScalar x = SkScalarMul(SK_Scalar1 - v, edge[TL+iu].fX) + 105 SkScalarMul(u, edge[TR+iv].fX) + 106 SkScalarMul(v, edge[BR+nu-iu].fX) + 107 SkScalarMul(SK_Scalar1 - u, edge[BL+nv-iv].fX) - x0; 108 SkScalar y = SkScalarMul(SK_Scalar1 - v, edge[TL+iu].fY) + 109 SkScalarMul(u, edge[TR+iv].fY) + 110 SkScalarMul(v, edge[BR+nu-iu].fY) + 111 SkScalarMul(SK_Scalar1 - u, edge[BL+nv-iv].fY) - y0; 112 pt->set(x, y); 113 } 114 115 static int ScalarTo255(SkScalar v) { 116 int scale = SkScalarToFixed(v) >> 8; 117 if (scale < 0) { 118 scale = 0; 119 } else if (scale > 255) { 120 scale = 255; 121 } 122 return scale; 123 } 124 125 static SkColor make_color(SkScalar s, SkScalar t) { 126 int cs = ScalarTo255(s); 127 int ct = ScalarTo255(t); 128 return SkColorSetARGB(0xFF, cs, 0, 0) + SkColorSetARGB(0, 0, ct, 0); 129 } 130 131 void Patch::draw(SkCanvas* canvas, const SkPaint& paint, int nu, int nv, 132 bool doTextures, bool doColors) { 133 if (nu < 1 || nv < 1) { 134 return; 135 } 136 137 int i, npts = (nu + nv) * 2; 138 SkAutoSTMalloc<16, SkPoint> storage(npts + 1); 139 SkPoint* edge0 = storage.get(); 140 SkPoint* edge1 = edge0 + nu; 141 SkPoint* edge2 = edge1 + nv; 142 SkPoint* edge3 = edge2 + nu; 143 144 // evaluate the edge points 145 eval_patch_edge(fPts + 0, edge0, nu); 146 eval_patch_edge(fPts + 3, edge1, nv); 147 eval_patch_edge(fPts + 6, edge2, nu); 148 eval_patch_edge(fPts + 9, edge3, nv); 149 edge3[nv] = edge0[0]; // the last shall be first 150 151 for (i = 0; i < npts; i++) { 152 // canvas->drawLine(edge0[i].fX, edge0[i].fY, edge0[i+1].fX, edge0[i+1].fY, paint); 153 } 154 155 int row, vertCount = (nu + 1) * (nv + 1); 156 SkAutoTMalloc<SkPoint> vertStorage(vertCount); 157 SkPoint* verts = vertStorage.get(); 158 159 // first row 160 memcpy(verts, edge0, (nu + 1) * sizeof(SkPoint)); 161 // rows 162 SkPoint* r = verts; 163 for (row = 1; row < nv; row++) { 164 r += nu + 1; 165 r[0] = edge3[nv - row]; 166 for (int col = 1; col < nu; col++) { 167 eval_sheet(edge0, nu, nv, col, row, &r[col]); 168 } 169 r[nu] = edge1[row]; 170 } 171 // last row 172 SkPoint* last = verts + nv * (nu + 1); 173 for (i = 0; i <= nu; i++) { 174 last[i] = edge2[nu - i]; 175 } 176 177 // canvas->drawPoints(verts, vertCount, paint); 178 179 int stripCount = (nu + 1) * 2; 180 SkAutoTMalloc<SkPoint> stripStorage(stripCount * 2); 181 SkAutoTMalloc<SkColor> colorStorage(stripCount); 182 SkPoint* strip = stripStorage.get(); 183 SkPoint* tex = strip + stripCount; 184 SkColor* colors = colorStorage.get(); 185 SkScalar t = 0; 186 const SkScalar ds = SK_Scalar1 * fW / nu; 187 const SkScalar dt = SK_Scalar1 * fH / nv; 188 r = verts; 189 for (row = 0; row < nv; row++) { 190 SkPoint* upper = r; 191 SkPoint* lower = r + nu + 1; 192 r = lower; 193 SkScalar s = 0; 194 for (i = 0; i <= nu; i++) { 195 strip[i*2 + 0] = *upper++; 196 strip[i*2 + 1] = *lower++; 197 tex[i*2 + 0].set(s, t); 198 tex[i*2 + 1].set(s, t + dt); 199 colors[i*2 + 0] = make_color(s/fW, t/fH); 200 colors[i*2 + 1] = make_color(s/fW, (t + dt)/fH); 201 s += ds; 202 } 203 t += dt; 204 canvas->drawVertices(SkCanvas::kTriangleStrip_VertexMode, stripCount, 205 strip, doTextures ? tex : NULL, 206 doColors ? colors : NULL, NULL, 207 NULL, 0, paint); 208 } 209 } 210 211 static void drawpatches(SkCanvas* canvas, const SkPaint& paint, int nu, int nv, 212 Patch* patch) { 213 214 SkAutoCanvasRestore ar(canvas, true); 215 216 patch->draw(canvas, paint, 10, 10, false, false); 217 canvas->translate(SkIntToScalar(180), 0); 218 patch->draw(canvas, paint, 10, 10, true, false); 219 canvas->translate(SkIntToScalar(180), 0); 220 patch->draw(canvas, paint, 10, 10, false, true); 221 canvas->translate(SkIntToScalar(180), 0); 222 patch->draw(canvas, paint, 10, 10, true, true); 223 } 224 225 class PatchView : public SampleView { 226 SkShader* fShader0; 227 SkShader* fShader1; 228 SkIPoint fSize0, fSize1; 229 SkPoint fPts[12]; 230 231 public: 232 PatchView() { 233 fShader0 = make_shader0(&fSize0); 234 fSize1 = fSize0; 235 if (fSize0.fX == 0 || fSize0.fY == 0) { 236 fSize1.set(2, 2); 237 } 238 fShader1 = make_shader1(fSize1); 239 240 const SkScalar S = SkIntToScalar(50); 241 const SkScalar T = SkIntToScalar(40); 242 fPts[0].set(S*0, T); 243 fPts[1].set(S*1, T); 244 fPts[2].set(S*2, T); 245 fPts[3].set(S*3, T); 246 fPts[4].set(S*3, T*2); 247 fPts[5].set(S*3, T*3); 248 fPts[6].set(S*3, T*4); 249 fPts[7].set(S*2, T*4); 250 fPts[8].set(S*1, T*4); 251 fPts[9].set(S*0, T*4); 252 fPts[10].set(S*0, T*3); 253 fPts[11].set(S*0, T*2); 254 255 this->setBGColor(SK_ColorGRAY); 256 } 257 258 virtual ~PatchView() { 259 SkSafeUnref(fShader0); 260 SkSafeUnref(fShader1); 261 } 262 263 protected: 264 // overrides from SkEventSink 265 virtual bool onQuery(SkEvent* evt) { 266 if (SampleCode::TitleQ(*evt)) 267 { 268 SkString str("Patch"); 269 SampleCode::TitleR(evt, str.c_str()); 270 return true; 271 } 272 return this->INHERITED::onQuery(evt); 273 } 274 275 virtual void onDrawContent(SkCanvas* canvas) { 276 SkPaint paint; 277 paint.setDither(true); 278 paint.setFilterBitmap(true); 279 280 canvas->translate(SkIntToScalar(20), 0); 281 282 Patch patch; 283 284 paint.setShader(fShader0); 285 if (fSize0.fX == 0) { 286 fSize0.fX = 1; 287 } 288 if (fSize0.fY == 0) { 289 fSize0.fY = 1; 290 } 291 patch.setBounds(fSize0.fX, fSize0.fY); 292 293 patch.setPatch(fPts); 294 drawpatches(canvas, paint, 10, 10, &patch); 295 296 paint.setShader(NULL); 297 paint.setAntiAlias(true); 298 paint.setStrokeWidth(SkIntToScalar(5)); 299 canvas->drawPoints(SkCanvas::kPoints_PointMode, SK_ARRAY_COUNT(fPts), fPts, paint); 300 301 canvas->translate(0, SkIntToScalar(300)); 302 303 paint.setAntiAlias(false); 304 paint.setShader(fShader1); 305 patch.setBounds(fSize1.fX, fSize1.fY); 306 drawpatches(canvas, paint, 10, 10, &patch); 307 } 308 309 class PtClick : public Click { 310 public: 311 int fIndex; 312 PtClick(SkView* view, int index) : Click(view), fIndex(index) {} 313 }; 314 315 static bool hittest(const SkPoint& pt, SkScalar x, SkScalar y) { 316 return SkPoint::Length(pt.fX - x, pt.fY - y) < SkIntToScalar(5); 317 } 318 319 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) { 320 for (size_t i = 0; i < SK_ARRAY_COUNT(fPts); i++) { 321 if (hittest(fPts[i], x, y)) { 322 return new PtClick(this, i); 323 } 324 } 325 return this->INHERITED::onFindClickHandler(x, y); 326 } 327 328 virtual bool onClick(Click* click) { 329 fPts[((PtClick*)click)->fIndex].set(click->fCurr.fX, click->fCurr.fY); 330 this->inval(NULL); 331 return true; 332 } 333 334 private: 335 typedef SampleView INHERITED; 336 }; 337 338 ////////////////////////////////////////////////////////////////////////////// 339 340 static SkView* MyFactory() { return new PatchView; } 341 static SkViewRegister reg(MyFactory); 342 343