diff options
Diffstat (limited to 'chromium/third_party/skia/samplecode/SampleWarp.cpp')
-rw-r--r-- | chromium/third_party/skia/samplecode/SampleWarp.cpp | 473 |
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); |