summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/skia/samplecode/SampleWarp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/skia/samplecode/SampleWarp.cpp')
-rw-r--r--chromium/third_party/skia/samplecode/SampleWarp.cpp473
1 files changed, 473 insertions, 0 deletions
diff --git a/chromium/third_party/skia/samplecode/SampleWarp.cpp b/chromium/third_party/skia/samplecode/SampleWarp.cpp
new file mode 100644
index 00000000000..e9455a6c395
--- /dev/null
+++ b/chromium/third_party/skia/samplecode/SampleWarp.cpp
@@ -0,0 +1,473 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkImageDecoder.h"
+
+#include "SkBlurMaskFilter.h"
+#include "SkTableMaskFilter.h"
+
+#define kNearlyZero (SK_Scalar1 / 8092)
+
+static void test_bigblur(SkCanvas* canvas) {
+ canvas->drawColor(SK_ColorBLACK);
+
+ SkBitmap orig, mask;
+ SkImageDecoder::DecodeFile("/skimages/app_icon.png", &orig);
+
+ SkMaskFilter* mf = SkBlurMaskFilter::Create(8, SkBlurMaskFilter::kNormal_BlurStyle);
+ SkPaint paint;
+ paint.setMaskFilter(mf)->unref();
+ SkIPoint offset;
+ orig.extractAlpha(&mask, &paint, &offset);
+
+ paint.setColor(0xFFBB8800);
+ paint.setColor(SK_ColorWHITE);
+
+ int i;
+ canvas->save();
+ float gamma = 0.8;
+ for (i = 0; i < 5; i++) {
+ paint.setMaskFilter(SkTableMaskFilter::CreateGamma(gamma))->unref();
+ canvas->drawBitmap(mask, 0, 0, &paint);
+ paint.setMaskFilter(NULL);
+ canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
+ gamma -= 0.1;
+ canvas->translate(120, 0);
+ }
+ canvas->restore();
+ canvas->translate(0, 160);
+
+ for (i = 0; i < 5; i++) {
+ paint.setMaskFilter(SkTableMaskFilter::CreateClip(i*30, 255 - 20))->unref();
+ canvas->drawBitmap(mask, 0, 0, &paint);
+ paint.setMaskFilter(NULL);
+ canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
+ canvas->translate(120, 0);
+ }
+
+#if 0
+ paint.setColor(0xFFFFFFFF);
+ canvas->drawBitmap(mask, 0, 0, &paint);
+ paint.setMaskFilter(NULL);
+ canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
+
+ canvas->translate(120, 0);
+
+ canvas->drawBitmap(mask, 0, 0, &paint);
+ canvas->drawBitmap(mask, 0, 0, &paint);
+ canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
+
+ canvas->translate(120, 0);
+
+ canvas->drawBitmap(mask, 0, 0, &paint);
+ canvas->drawBitmap(mask, 0, 0, &paint);
+ canvas->drawBitmap(mask, 0, 0, &paint);
+ canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
+
+ canvas->translate(120, 0);
+
+ canvas->drawBitmap(mask, 0, 0, &paint);
+ canvas->drawBitmap(mask, 0, 0, &paint);
+ canvas->drawBitmap(mask, 0, 0, &paint);
+ canvas->drawBitmap(mask, 0, 0, &paint);
+ canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
+
+ canvas->translate(120, 0);
+
+ canvas->drawBitmap(mask, 0, 0, &paint);
+ canvas->drawBitmap(mask, 0, 0, &paint);
+ canvas->drawBitmap(mask, 0, 0, &paint);
+ canvas->drawBitmap(mask, 0, 0, &paint);
+ canvas->drawBitmap(mask, 0, 0, &paint);
+ canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
+#endif
+}
+
+#include "SkMeshUtils.h"
+
+static SkPoint SkMakePoint(SkScalar x, SkScalar y) {
+ SkPoint pt;
+ pt.set(x, y);
+ return pt;
+}
+
+static SkPoint SkPointInterp(const SkPoint& a, const SkPoint& b, SkScalar t) {
+ return SkMakePoint(SkScalarInterp(a.fX, b.fX, t),
+ SkScalarInterp(a.fY, b.fY, t));
+}
+
+#include "SkBoundaryPatch.h"
+
+static void set_cubic(SkPoint pts[4], SkScalar x0, SkScalar y0,
+ SkScalar x3, SkScalar y3, SkScalar scale = 1) {
+ SkPoint tmp, tmp2;
+
+ pts[0].set(x0, y0);
+ pts[3].set(x3, y3);
+
+ tmp = SkPointInterp(pts[0], pts[3], SK_Scalar1/3);
+ tmp2 = pts[0] - tmp;
+ tmp2.rotateCW();
+ tmp2.scale(scale);
+ pts[1] = tmp + tmp2;
+
+ tmp = SkPointInterp(pts[0], pts[3], 2*SK_Scalar1/3);
+ tmp2 = pts[3] - tmp;
+ tmp2.rotateCW();
+ tmp2.scale(scale);
+ pts[2] = tmp + tmp2;
+}
+
+static void test_patch(SkCanvas* canvas, const SkBitmap& bm, SkScalar scale) {
+ SkCubicBoundary cubic;
+ set_cubic(cubic.fPts + 0, 0, 0, 100, 0, scale);
+ set_cubic(cubic.fPts + 3, 100, 0, 100, 100, scale);
+ set_cubic(cubic.fPts + 6, 100, 100, 0, 100, -scale);
+ set_cubic(cubic.fPts + 9, 0, 100, 0, 0, 0);
+
+ SkBoundaryPatch patch;
+ patch.setBoundary(&cubic);
+
+ const int Rows = 16;
+ const int Cols = 16;
+ SkPoint pts[Rows * Cols];
+ patch.evalPatch(pts, Rows, Cols);
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setFilterBitmap(true);
+ paint.setStrokeWidth(1);
+ paint.setStrokeCap(SkPaint::kRound_Cap);
+
+ canvas->translate(50, 50);
+ canvas->scale(3, 3);
+
+ SkMeshUtils::Draw(canvas, bm, Rows, Cols, pts, NULL, paint);
+}
+
+static void test_drag(SkCanvas* canvas, const SkBitmap& bm,
+ const SkPoint& p0, const SkPoint& p1) {
+ SkCubicBoundary cubic;
+ set_cubic(cubic.fPts + 0, 0, 0, 100, 0, 0);
+ set_cubic(cubic.fPts + 3, 100, 0, 100, 100, 0);
+ set_cubic(cubic.fPts + 6, 100, 100, 0, 100, 0);
+ set_cubic(cubic.fPts + 9, 0, 100, 0, 0, 0);
+
+#if 0
+ cubic.fPts[1] += p1 - p0;
+ cubic.fPts[2] += p1 - p0;
+#else
+ SkScalar dx = p1.fX - p0.fX;
+ if (dx > 0) dx = 0;
+ SkScalar dy = p1.fY - p0.fY;
+ if (dy > 0) dy = 0;
+
+ cubic.fPts[1].fY += dy;
+ cubic.fPts[2].fY += dy;
+ cubic.fPts[10].fX += dx;
+ cubic.fPts[11].fX += dx;
+#endif
+
+ SkBoundaryPatch patch;
+ patch.setBoundary(&cubic);
+
+ const int Rows = 16;
+ const int Cols = 16;
+ SkPoint pts[Rows * Cols];
+ patch.evalPatch(pts, Rows, Cols);
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setFilterBitmap(true);
+ paint.setStrokeWidth(1);
+ paint.setStrokeCap(SkPaint::kRound_Cap);
+
+ canvas->translate(50, 50);
+ canvas->scale(3, 3);
+
+ SkAutoCanvasRestore acr(canvas, true);
+
+ SkRect r = { 0, 0, 100, 100 };
+ canvas->clipRect(r);
+ SkMeshUtils::Draw(canvas, bm, Rows, Cols, pts, NULL, paint);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+class Mesh {
+public:
+ Mesh();
+ ~Mesh();
+
+ Mesh& operator=(const Mesh& src);
+
+ void init(const SkRect& bounds, int rows, int cols,
+ const SkRect& texture);
+
+ const SkRect& bounds() const { return fBounds; }
+
+ int rows() const { return fRows; }
+ int cols() const { return fCols; }
+ SkPoint& pt(int row, int col) {
+ return fPts[row * (fRows + 1) + col];
+ }
+
+ void draw(SkCanvas*, const SkPaint&);
+ void drawWireframe(SkCanvas* canvas, const SkPaint& paint);
+
+private:
+ SkRect fBounds;
+ int fRows, fCols;
+ SkPoint* fPts;
+ SkPoint* fTex; // just points into fPts, not separately allocated
+ int fCount;
+ uint16_t* fIndices;
+ int fIndexCount;
+};
+
+Mesh::Mesh() : fPts(NULL), fCount(0), fIndices(NULL), fIndexCount(0) {}
+
+Mesh::~Mesh() {
+ delete[] fPts;
+ delete[] fIndices;
+}
+
+Mesh& Mesh::operator=(const Mesh& src) {
+ delete[] fPts;
+ delete[] fIndices;
+
+ fBounds = src.fBounds;
+ fRows = src.fRows;
+ fCols = src.fCols;
+
+ fCount = src.fCount;
+ fPts = new SkPoint[fCount * 2];
+ fTex = fPts + fCount;
+ memcpy(fPts, src.fPts, fCount * 2 * sizeof(SkPoint));
+
+ delete[] fIndices;
+ fIndexCount = src.fIndexCount;
+ fIndices = new uint16_t[fIndexCount];
+ memcpy(fIndices, src.fIndices, fIndexCount * sizeof(uint16_t));
+
+ return *this;
+}
+
+void Mesh::init(const SkRect& bounds, int rows, int cols,
+ const SkRect& texture) {
+ SkASSERT(rows > 0 && cols > 0);
+
+ fBounds = bounds;
+ fRows = rows;
+ fCols = cols;
+
+ delete[] fPts;
+ fCount = (rows + 1) * (cols + 1);
+ fPts = new SkPoint[fCount * 2];
+ fTex = fPts + fCount;
+
+ delete[] fIndices;
+ fIndexCount = rows * cols * 6;
+ fIndices = new uint16_t[fIndexCount];
+
+ SkPoint* pts = fPts;
+ const SkScalar dx = bounds.width() / rows;
+ const SkScalar dy = bounds.height() / cols;
+ SkPoint* tex = fTex;
+ const SkScalar dtx = texture.width() / rows;
+ const SkScalar dty = texture.height() / cols;
+ uint16_t* idx = fIndices;
+ int index = 0;
+ for (int y = 0; y <= cols; y++) {
+ for (int x = 0; x <= rows; x++) {
+ pts->set(bounds.fLeft + x*dx, bounds.fTop + y*dy);
+ pts += 1;
+ tex->set(texture.fLeft + x*dtx, texture.fTop + y*dty);
+ tex += 1;
+
+ if (y < cols && x < rows) {
+ *idx++ = index;
+ *idx++ = index + rows + 1;
+ *idx++ = index + 1;
+
+ *idx++ = index + 1;
+ *idx++ = index + rows + 1;
+ *idx++ = index + rows + 2;
+
+ index += 1;
+ }
+ }
+ index += 1;
+ }
+}
+
+void Mesh::draw(SkCanvas* canvas, const SkPaint& paint) {
+ canvas->drawVertices(SkCanvas::kTriangles_VertexMode, fCount,
+ fPts, fTex, NULL, NULL, fIndices, fIndexCount,
+ paint);
+}
+
+void Mesh::drawWireframe(SkCanvas* canvas, const SkPaint& paint) {
+ canvas->drawVertices(SkCanvas::kTriangles_VertexMode, fCount,
+ fPts, NULL, NULL, NULL, fIndices, fIndexCount,
+ paint);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+class WarpView : public SkView {
+ Mesh fMesh, fOrig;
+ SkBitmap fBitmap;
+ SkMatrix fMatrix, fInverse;
+public:
+ WarpView() {
+ SkBitmap bm;
+// SkImageDecoder::DecodeFile("/skimages/marker.png", &bm);
+ SkImageDecoder::DecodeFile("/skimages/logo.gif", &bm);
+ // SkImageDecoder::DecodeFile("/beach_shot.JPG", &bm);
+ fBitmap = bm;
+
+ SkRect bounds, texture;
+ texture.set(0, 0, SkIntToScalar(fBitmap.width()),
+ SkIntToScalar(fBitmap.height()));
+ bounds = texture;
+
+// fMesh.init(bounds, fBitmap.width() / 40, fBitmap.height() / 40, texture);
+ fMesh.init(bounds, fBitmap.width()/16, fBitmap.height()/16, texture);
+ fOrig = fMesh;
+
+ fP0.set(0, 0);
+ fP1 = fP0;
+
+ fMatrix.setScale(2, 2);
+ fMatrix.invert(&fInverse);
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "Warp");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ static SkPoint apply_warp(const SkVector& drag, SkScalar dragLength,
+ const SkPoint& dragStart, const SkPoint& dragCurr,
+ const SkPoint& orig) {
+ SkVector delta = orig - dragCurr;
+ SkScalar length = SkPoint::Normalize(&delta);
+ if (length <= kNearlyZero) {
+ return orig;
+ }
+
+ const SkScalar period = 20;
+ const SkScalar mag = dragLength / 3;
+
+ SkScalar d = length / (period);
+ d = mag * SkScalarSin(d) / d;
+ SkScalar dx = delta.fX * d;
+ SkScalar dy = delta.fY * d;
+ SkScalar px = orig.fX + dx;
+ SkScalar py = orig.fY + dy;
+ return SkPoint::Make(px, py);
+ }
+
+ static SkPoint apply_warp2(const SkVector& drag, SkScalar dragLength,
+ const SkPoint& dragStart, const SkPoint& dragCurr,
+ const SkPoint& orig) {
+ SkVector delta = orig - dragCurr;
+ SkScalar length = SkPoint::Normalize(&delta);
+ if (length <= kNearlyZero) {
+ return orig;
+ }
+
+ const SkScalar period = 10 + dragLength/4;
+ const SkScalar mag = dragLength / 3;
+
+ SkScalar d = length / (period);
+ if (d > SK_ScalarPI) {
+ d = SK_ScalarPI;
+ }
+
+ d = -mag * SkScalarSin(d);
+
+ SkScalar dx = delta.fX * d;
+ SkScalar dy = delta.fY * d;
+ SkScalar px = orig.fX + dx;
+ SkScalar py = orig.fY + dy;
+ return SkPoint::Make(px, py);
+ }
+
+ typedef SkPoint (*WarpProc)(const SkVector& drag, SkScalar dragLength,
+ const SkPoint& dragStart, const SkPoint& dragCurr,
+ const SkPoint& orig);
+
+ void warp(const SkPoint& p0, const SkPoint& p1) {
+ WarpProc proc = apply_warp2;
+ SkPoint delta = p1 - p0;
+ SkScalar length = SkPoint::Normalize(&delta);
+ for (int y = 0; y < fMesh.rows(); y++) {
+ for (int x = 0; x < fMesh.cols(); x++) {
+ fMesh.pt(x, y) = proc(delta, length, p0, p1, fOrig.pt(x, y));
+ }
+ }
+ fP0 = p0;
+ fP1 = p1;
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ canvas->drawColor(SK_ColorLTGRAY);
+ // test_bigblur(canvas); return;
+
+ canvas->concat(fMatrix);
+
+ SkPaint paint;
+ paint.setFilterBitmap(true);
+ paint.setShader(SkShader::CreateBitmapShader(fBitmap,
+ SkShader::kClamp_TileMode,
+ SkShader::kClamp_TileMode))->unref();
+ fMesh.draw(canvas, paint); //return;
+
+ paint.setShader(NULL);
+ paint.setColor(SK_ColorRED);
+ fMesh.draw(canvas, paint);
+
+ // test_drag(canvas, fBitmap, fP0, fP1);
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
+ return new Click(this);
+ }
+
+ virtual bool onClick(Click* click) {
+ SkPoint pts[2] = { click->fOrig, click->fCurr };
+ fInverse.mapPoints(pts, 2);
+ this->warp(pts[0], pts[1]);
+ this->inval(NULL);
+ return true;
+ }
+
+private:
+ SkIRect fBase, fRect;
+ SkPoint fP0, fP1;
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new WarpView; }
+static SkViewRegister reg(MyFactory);