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