1 2 /* 3 * Copyright 2011 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 #include "SampleCode.h" 9 #include "SkView.h" 10 #include "SkCanvas.h" 11 #include "SkGradientShader.h" 12 #include "SkPath.h" 13 #include "SkRegion.h" 14 #include "SkShader.h" 15 #include "SkUtils.h" 16 #include "SkImageDecoder.h" 17 18 #include "SkBlurMaskFilter.h" 19 #include "SkTableMaskFilter.h" 20 21 #define kNearlyZero (SK_Scalar1 / 8092) 22 23 static void test_bigblur(SkCanvas* canvas) { 24 canvas->drawColor(SK_ColorBLACK); 25 26 SkBitmap orig, mask; 27 SkImageDecoder::DecodeFile("/skimages/app_icon.png", &orig); 28 29 SkMaskFilter* mf = SkBlurMaskFilter::Create(8, SkBlurMaskFilter::kNormal_BlurStyle); 30 SkPaint paint; 31 paint.setMaskFilter(mf)->unref(); 32 SkIPoint offset; 33 orig.extractAlpha(&mask, &paint, &offset); 34 35 paint.setColor(0xFFBB8800); 36 paint.setColor(SK_ColorWHITE); 37 38 int i; 39 canvas->save(); 40 float gamma = 0.8; 41 for (i = 0; i < 5; i++) { 42 paint.setMaskFilter(SkTableMaskFilter::CreateGamma(gamma))->unref(); 43 canvas->drawBitmap(mask, 0, 0, &paint); 44 paint.setMaskFilter(NULL); 45 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint); 46 gamma -= 0.1; 47 canvas->translate(120, 0); 48 } 49 canvas->restore(); 50 canvas->translate(0, 160); 51 52 for (i = 0; i < 5; i++) { 53 paint.setMaskFilter(SkTableMaskFilter::CreateClip(i*30, 255 - 20))->unref(); 54 canvas->drawBitmap(mask, 0, 0, &paint); 55 paint.setMaskFilter(NULL); 56 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint); 57 canvas->translate(120, 0); 58 } 59 60 #if 0 61 paint.setColor(0xFFFFFFFF); 62 canvas->drawBitmap(mask, 0, 0, &paint); 63 paint.setMaskFilter(NULL); 64 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint); 65 66 canvas->translate(120, 0); 67 68 canvas->drawBitmap(mask, 0, 0, &paint); 69 canvas->drawBitmap(mask, 0, 0, &paint); 70 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint); 71 72 canvas->translate(120, 0); 73 74 canvas->drawBitmap(mask, 0, 0, &paint); 75 canvas->drawBitmap(mask, 0, 0, &paint); 76 canvas->drawBitmap(mask, 0, 0, &paint); 77 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint); 78 79 canvas->translate(120, 0); 80 81 canvas->drawBitmap(mask, 0, 0, &paint); 82 canvas->drawBitmap(mask, 0, 0, &paint); 83 canvas->drawBitmap(mask, 0, 0, &paint); 84 canvas->drawBitmap(mask, 0, 0, &paint); 85 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint); 86 87 canvas->translate(120, 0); 88 89 canvas->drawBitmap(mask, 0, 0, &paint); 90 canvas->drawBitmap(mask, 0, 0, &paint); 91 canvas->drawBitmap(mask, 0, 0, &paint); 92 canvas->drawBitmap(mask, 0, 0, &paint); 93 canvas->drawBitmap(mask, 0, 0, &paint); 94 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint); 95 #endif 96 } 97 98 #include "SkMeshUtils.h" 99 100 static SkPoint SkMakePoint(SkScalar x, SkScalar y) { 101 SkPoint pt; 102 pt.set(x, y); 103 return pt; 104 } 105 106 static SkPoint SkPointInterp(const SkPoint& a, const SkPoint& b, SkScalar t) { 107 return SkMakePoint(SkScalarInterp(a.fX, b.fX, t), 108 SkScalarInterp(a.fY, b.fY, t)); 109 } 110 111 #include "SkBoundaryPatch.h" 112 113 static void set_cubic(SkPoint pts[4], SkScalar x0, SkScalar y0, 114 SkScalar x3, SkScalar y3, SkScalar scale = 1) { 115 SkPoint tmp, tmp2; 116 117 pts[0].set(x0, y0); 118 pts[3].set(x3, y3); 119 120 tmp = SkPointInterp(pts[0], pts[3], SK_Scalar1/3); 121 tmp2 = pts[0] - tmp; 122 tmp2.rotateCW(); 123 tmp2.scale(scale); 124 pts[1] = tmp + tmp2; 125 126 tmp = SkPointInterp(pts[0], pts[3], 2*SK_Scalar1/3); 127 tmp2 = pts[3] - tmp; 128 tmp2.rotateCW(); 129 tmp2.scale(scale); 130 pts[2] = tmp + tmp2; 131 } 132 133 static void test_patch(SkCanvas* canvas, const SkBitmap& bm, SkScalar scale) { 134 SkCubicBoundary cubic; 135 set_cubic(cubic.fPts + 0, 0, 0, 100, 0, scale); 136 set_cubic(cubic.fPts + 3, 100, 0, 100, 100, scale); 137 set_cubic(cubic.fPts + 6, 100, 100, 0, 100, -scale); 138 set_cubic(cubic.fPts + 9, 0, 100, 0, 0, 0); 139 140 SkBoundaryPatch patch; 141 patch.setBoundary(&cubic); 142 143 const int Rows = 16; 144 const int Cols = 16; 145 SkPoint pts[Rows * Cols]; 146 patch.evalPatch(pts, Rows, Cols); 147 148 SkPaint paint; 149 paint.setAntiAlias(true); 150 paint.setFilterBitmap(true); 151 paint.setStrokeWidth(1); 152 paint.setStrokeCap(SkPaint::kRound_Cap); 153 154 canvas->translate(50, 50); 155 canvas->scale(3, 3); 156 157 SkMeshUtils::Draw(canvas, bm, Rows, Cols, pts, NULL, paint); 158 } 159 160 static void test_drag(SkCanvas* canvas, const SkBitmap& bm, 161 const SkPoint& p0, const SkPoint& p1) { 162 SkCubicBoundary cubic; 163 set_cubic(cubic.fPts + 0, 0, 0, 100, 0, 0); 164 set_cubic(cubic.fPts + 3, 100, 0, 100, 100, 0); 165 set_cubic(cubic.fPts + 6, 100, 100, 0, 100, 0); 166 set_cubic(cubic.fPts + 9, 0, 100, 0, 0, 0); 167 168 #if 0 169 cubic.fPts[1] += p1 - p0; 170 cubic.fPts[2] += p1 - p0; 171 #else 172 SkScalar dx = p1.fX - p0.fX; 173 if (dx > 0) dx = 0; 174 SkScalar dy = p1.fY - p0.fY; 175 if (dy > 0) dy = 0; 176 177 cubic.fPts[1].fY += dy; 178 cubic.fPts[2].fY += dy; 179 cubic.fPts[10].fX += dx; 180 cubic.fPts[11].fX += dx; 181 #endif 182 183 SkBoundaryPatch patch; 184 patch.setBoundary(&cubic); 185 186 const int Rows = 16; 187 const int Cols = 16; 188 SkPoint pts[Rows * Cols]; 189 patch.evalPatch(pts, Rows, Cols); 190 191 SkPaint paint; 192 paint.setAntiAlias(true); 193 paint.setFilterBitmap(true); 194 paint.setStrokeWidth(1); 195 paint.setStrokeCap(SkPaint::kRound_Cap); 196 197 canvas->translate(50, 50); 198 canvas->scale(3, 3); 199 200 SkAutoCanvasRestore acr(canvas, true); 201 202 SkRect r = { 0, 0, 100, 100 }; 203 canvas->clipRect(r); 204 SkMeshUtils::Draw(canvas, bm, Rows, Cols, pts, NULL, paint); 205 } 206 207 /////////////////////////////////////////////////////////////////////////////// 208 209 class Mesh { 210 public: 211 Mesh(); 212 ~Mesh(); 213 214 Mesh& operator=(const Mesh& src); 215 216 void init(const SkRect& bounds, int rows, int cols, 217 const SkRect& texture); 218 219 const SkRect& bounds() const { return fBounds; } 220 221 int rows() const { return fRows; } 222 int cols() const { return fCols; } 223 SkPoint& pt(int row, int col) { 224 return fPts[row * (fRows + 1) + col]; 225 } 226 227 void draw(SkCanvas*, const SkPaint&); 228 void drawWireframe(SkCanvas* canvas, const SkPaint& paint); 229 230 private: 231 SkRect fBounds; 232 int fRows, fCols; 233 SkPoint* fPts; 234 SkPoint* fTex; // just points into fPts, not separately allocated 235 int fCount; 236 uint16_t* fIndices; 237 int fIndexCount; 238 }; 239 240 Mesh::Mesh() : fPts(NULL), fCount(0), fIndices(NULL), fIndexCount(0) {} 241 242 Mesh::~Mesh() { 243 delete[] fPts; 244 delete[] fIndices; 245 } 246 247 Mesh& Mesh::operator=(const Mesh& src) { 248 delete[] fPts; 249 delete[] fIndices; 250 251 fBounds = src.fBounds; 252 fRows = src.fRows; 253 fCols = src.fCols; 254 255 fCount = src.fCount; 256 fPts = new SkPoint[fCount * 2]; 257 fTex = fPts + fCount; 258 memcpy(fPts, src.fPts, fCount * 2 * sizeof(SkPoint)); 259 260 delete[] fIndices; 261 fIndexCount = src.fIndexCount; 262 fIndices = new uint16_t[fIndexCount]; 263 memcpy(fIndices, src.fIndices, fIndexCount * sizeof(uint16_t)); 264 265 return *this; 266 } 267 268 void Mesh::init(const SkRect& bounds, int rows, int cols, 269 const SkRect& texture) { 270 SkASSERT(rows > 0 && cols > 0); 271 272 fBounds = bounds; 273 fRows = rows; 274 fCols = cols; 275 276 delete[] fPts; 277 fCount = (rows + 1) * (cols + 1); 278 fPts = new SkPoint[fCount * 2]; 279 fTex = fPts + fCount; 280 281 delete[] fIndices; 282 fIndexCount = rows * cols * 6; 283 fIndices = new uint16_t[fIndexCount]; 284 285 SkPoint* pts = fPts; 286 const SkScalar dx = bounds.width() / rows; 287 const SkScalar dy = bounds.height() / cols; 288 SkPoint* tex = fTex; 289 const SkScalar dtx = texture.width() / rows; 290 const SkScalar dty = texture.height() / cols; 291 uint16_t* idx = fIndices; 292 int index = 0; 293 for (int y = 0; y <= cols; y++) { 294 for (int x = 0; x <= rows; x++) { 295 pts->set(bounds.fLeft + x*dx, bounds.fTop + y*dy); 296 pts += 1; 297 tex->set(texture.fLeft + x*dtx, texture.fTop + y*dty); 298 tex += 1; 299 300 if (y < cols && x < rows) { 301 *idx++ = index; 302 *idx++ = index + rows + 1; 303 *idx++ = index + 1; 304 305 *idx++ = index + 1; 306 *idx++ = index + rows + 1; 307 *idx++ = index + rows + 2; 308 309 index += 1; 310 } 311 } 312 index += 1; 313 } 314 } 315 316 void Mesh::draw(SkCanvas* canvas, const SkPaint& paint) { 317 canvas->drawVertices(SkCanvas::kTriangles_VertexMode, fCount, 318 fPts, fTex, NULL, NULL, fIndices, fIndexCount, 319 paint); 320 } 321 322 void Mesh::drawWireframe(SkCanvas* canvas, const SkPaint& paint) { 323 canvas->drawVertices(SkCanvas::kTriangles_VertexMode, fCount, 324 fPts, NULL, NULL, NULL, fIndices, fIndexCount, 325 paint); 326 } 327 328 /////////////////////////////////////////////////////////////////////////////// 329 330 class WarpView : public SkView { 331 Mesh fMesh, fOrig; 332 SkBitmap fBitmap; 333 SkMatrix fMatrix, fInverse; 334 public: 335 WarpView() { 336 SkBitmap bm; 337 // SkImageDecoder::DecodeFile("/skimages/marker.png", &bm); 338 SkImageDecoder::DecodeFile("/skimages/logo.gif", &bm); 339 // SkImageDecoder::DecodeFile("/beach_shot.JPG", &bm); 340 fBitmap = bm; 341 342 SkRect bounds, texture; 343 texture.set(0, 0, SkIntToScalar(fBitmap.width()), 344 SkIntToScalar(fBitmap.height())); 345 bounds = texture; 346 347 // fMesh.init(bounds, fBitmap.width() / 40, fBitmap.height() / 40, texture); 348 fMesh.init(bounds, fBitmap.width()/16, fBitmap.height()/16, texture); 349 fOrig = fMesh; 350 351 fP0.set(0, 0); 352 fP1 = fP0; 353 354 fMatrix.setScale(2, 2); 355 fMatrix.invert(&fInverse); 356 } 357 358 protected: 359 // overrides from SkEventSink 360 virtual bool onQuery(SkEvent* evt) { 361 if (SampleCode::TitleQ(*evt)) { 362 SampleCode::TitleR(evt, "Warp"); 363 return true; 364 } 365 return this->INHERITED::onQuery(evt); 366 } 367 368 static SkPoint apply_warp(const SkVector& drag, SkScalar dragLength, 369 const SkPoint& dragStart, const SkPoint& dragCurr, 370 const SkPoint& orig) { 371 SkVector delta = orig - dragCurr; 372 SkScalar length = SkPoint::Normalize(&delta); 373 if (length <= kNearlyZero) { 374 return orig; 375 } 376 377 const SkScalar period = 20; 378 const SkScalar mag = dragLength / 3; 379 380 SkScalar d = length / (period); 381 d = mag * SkScalarSin(d) / d; 382 SkScalar dx = delta.fX * d; 383 SkScalar dy = delta.fY * d; 384 SkScalar px = orig.fX + dx; 385 SkScalar py = orig.fY + dy; 386 return SkPoint::Make(px, py); 387 } 388 389 static SkPoint apply_warp2(const SkVector& drag, SkScalar dragLength, 390 const SkPoint& dragStart, const SkPoint& dragCurr, 391 const SkPoint& orig) { 392 SkVector delta = orig - dragCurr; 393 SkScalar length = SkPoint::Normalize(&delta); 394 if (length <= kNearlyZero) { 395 return orig; 396 } 397 398 const SkScalar period = 10 + dragLength/4; 399 const SkScalar mag = dragLength / 3; 400 401 SkScalar d = length / (period); 402 if (d > SK_ScalarPI) { 403 d = SK_ScalarPI; 404 } 405 406 d = -mag * SkScalarSin(d); 407 408 SkScalar dx = delta.fX * d; 409 SkScalar dy = delta.fY * d; 410 SkScalar px = orig.fX + dx; 411 SkScalar py = orig.fY + dy; 412 return SkPoint::Make(px, py); 413 } 414 415 typedef SkPoint (*WarpProc)(const SkVector& drag, SkScalar dragLength, 416 const SkPoint& dragStart, const SkPoint& dragCurr, 417 const SkPoint& orig); 418 419 void warp(const SkPoint& p0, const SkPoint& p1) { 420 WarpProc proc = apply_warp2; 421 SkPoint delta = p1 - p0; 422 SkScalar length = SkPoint::Normalize(&delta); 423 for (int y = 0; y < fMesh.rows(); y++) { 424 for (int x = 0; x < fMesh.cols(); x++) { 425 fMesh.pt(x, y) = proc(delta, length, p0, p1, fOrig.pt(x, y)); 426 } 427 } 428 fP0 = p0; 429 fP1 = p1; 430 } 431 432 virtual void onDraw(SkCanvas* canvas) { 433 canvas->drawColor(SK_ColorLTGRAY); 434 // test_bigblur(canvas); return; 435 436 canvas->concat(fMatrix); 437 438 SkPaint paint; 439 paint.setFilterBitmap(true); 440 paint.setShader(SkShader::CreateBitmapShader(fBitmap, 441 SkShader::kClamp_TileMode, 442 SkShader::kClamp_TileMode))->unref(); 443 fMesh.draw(canvas, paint); //return; 444 445 paint.setShader(NULL); 446 paint.setColor(SK_ColorRED); 447 fMesh.draw(canvas, paint); 448 449 // test_drag(canvas, fBitmap, fP0, fP1); 450 } 451 452 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) { 453 return new Click(this); 454 } 455 456 virtual bool onClick(Click* click) { 457 SkPoint pts[2] = { click->fOrig, click->fCurr }; 458 fInverse.mapPoints(pts, 2); 459 this->warp(pts[0], pts[1]); 460 this->inval(NULL); 461 return true; 462 } 463 464 private: 465 SkIRect fBase, fRect; 466 SkPoint fP0, fP1; 467 typedef SkView INHERITED; 468 }; 469 470 ////////////////////////////////////////////////////////////////////////////// 471 472 static SkView* MyFactory() { return new WarpView; } 473 static SkViewRegister reg(MyFactory); 474