1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
7339cdbfb754ff0837ad4772b4837543e1092d62freed
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SampleCode.h"
9339cdbfb754ff0837ad4772b4837543e1092d62freed#include "SkAnimTimer.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkView.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkGradientShader.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkGraphics.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkImageDecoder.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPath.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRandom.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRegion.h"
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkShader.h"
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkXfermode.h"
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorFilter.h"
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTime.h"
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTypeface.h"
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkOSFile.h"
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStream.h"
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkGeometry.h" // private include :(
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkShader* make_shader0(SkIPoint* size) {
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBitmap    bm;
3382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//    SkImageDecoder::DecodeFile("/skimages/progressivejpg.jpg", &bm);
35f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    SkImageDecoder::DecodeFile("/skimages/logo.png", &bm);
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size->set(bm.width(), bm.height());
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkShader::CreateBitmapShader(bm, SkShader::kClamp_TileMode,
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                        SkShader::kClamp_TileMode);
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkShader* make_shader1(const SkIPoint& size) {
4264cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org    SkPoint pts[] = { { 0, 0, },
4364cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org                      { SkIntToScalar(size.fX), SkIntToScalar(size.fY) } };
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorRED };
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkGradientShader::CreateLinear(pts, colors, NULL,
4683f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org                    SK_ARRAY_COUNT(colors), SkShader::kMirror_TileMode);
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Patch {
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
534516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com    Patch() { sk_bzero(fPts, sizeof(fPts)); }
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~Patch() {}
5582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void setPatch(const SkPoint pts[12]) {
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        memcpy(fPts, pts, 12 * sizeof(SkPoint));
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPts[12] = pts[0];  // the last shall be first
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void setBounds(int w, int h) { fW = w; fH = h; }
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void draw(SkCanvas*, const SkPaint&, int segsU, int segsV,
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com              bool doTextures, bool doColors);
6482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint fPts[13];
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int     fW, fH;
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void eval_patch_edge(const SkPoint cubic[], SkPoint samples[], int segs) {
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar t = 0;
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar dt = SK_Scalar1 / segs;
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    samples[0] = cubic[0];
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int i = 1; i < segs; i++) {
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        t += dt;
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkEvalCubicAt(cubic, t, &samples[i], NULL, NULL);
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void eval_sheet(const SkPoint edge[], int nu, int nv, int iu, int iv,
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkPoint* pt) {
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const int TL = 0;
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const int TR = nu;
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const int BR = TR + nv;
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const int BL = BR + nu;
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar u = SkIntToScalar(iu) / nu;
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar v = SkIntToScalar(iv) / nv;
9082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar uv = SkScalarMul(u, v);
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar Uv = SkScalarMul(SK_Scalar1 - u, v);
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar uV = SkScalarMul(u, SK_Scalar1 - v);
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar UV = SkScalarMul(SK_Scalar1 - u, SK_Scalar1 - v);
9582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar x0 = SkScalarMul(UV, edge[TL].fX) + SkScalarMul(uV, edge[TR].fX) +
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                  SkScalarMul(Uv, edge[BL].fX) + SkScalarMul(uv, edge[BR].fX);
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar y0 = SkScalarMul(UV, edge[TL].fY) + SkScalarMul(uV, edge[TR].fY) +
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                  SkScalarMul(Uv, edge[BL].fY) + SkScalarMul(uv, edge[BR].fY);
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar x =    SkScalarMul(SK_Scalar1 - v, edge[TL+iu].fX) +
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SkScalarMul(u, edge[TR+iv].fX) +
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SkScalarMul(v, edge[BR+nu-iu].fX) +
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SkScalarMul(SK_Scalar1 - u, edge[BL+nv-iv].fX) - x0;
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar y =    SkScalarMul(SK_Scalar1 - v, edge[TL+iu].fY) +
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SkScalarMul(u, edge[TR+iv].fY) +
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SkScalarMul(v, edge[BR+nu-iu].fY) +
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SkScalarMul(SK_Scalar1 - u, edge[BL+nv-iv].fY) - y0;
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt->set(x, y);
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int ScalarTo255(SkScalar v) {
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int scale = SkScalarToFixed(v) >> 8;
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (scale < 0) {
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        scale = 0;
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else if (scale > 255) {
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        scale = 255;
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return scale;
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkColor make_color(SkScalar s, SkScalar t) {
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int cs = ScalarTo255(s);
12482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    int ct = ScalarTo255(t);
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkColorSetARGB(0xFF, cs, 0, 0) + SkColorSetARGB(0, 0, ct, 0);
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid Patch::draw(SkCanvas* canvas, const SkPaint& paint, int nu, int nv,
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 bool doTextures, bool doColors) {
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (nu < 1 || nv < 1) {
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int i, npts = (nu + nv) * 2;
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoSTMalloc<16, SkPoint> storage(npts + 1);
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint* edge0 = storage.get();
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint* edge1 = edge0 + nu;
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint* edge2 = edge1 + nv;
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint* edge3 = edge2 + nu;
14082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // evaluate the edge points
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    eval_patch_edge(fPts + 0, edge0, nu);
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    eval_patch_edge(fPts + 3, edge1, nv);
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    eval_patch_edge(fPts + 6, edge2, nu);
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    eval_patch_edge(fPts + 9, edge3, nv);
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    edge3[nv] = edge0[0];   // the last shall be first
14782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (i = 0; i < npts; i++) {
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//        canvas->drawLine(edge0[i].fX, edge0[i].fY, edge0[i+1].fX, edge0[i+1].fY, paint);
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
15182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int row, vertCount = (nu + 1) * (nv + 1);
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoTMalloc<SkPoint>  vertStorage(vertCount);
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint* verts = vertStorage.get();
15582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // first row
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    memcpy(verts, edge0, (nu + 1) * sizeof(SkPoint));
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // rows
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint* r = verts;
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (row = 1; row < nv; row++) {
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r += nu + 1;
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r[0] = edge3[nv - row];
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (int col = 1; col < nu; col++) {
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            eval_sheet(edge0, nu, nv, col, row, &r[col]);
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r[nu] = edge1[row];
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // last row
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint* last = verts + nv * (nu + 1);
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (i = 0; i <= nu; i++) {
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        last[i] = edge2[nu - i];
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//    canvas->drawPoints(verts, vertCount, paint);
17582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int stripCount = (nu + 1) * 2;
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoTMalloc<SkPoint>  stripStorage(stripCount * 2);
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoTMalloc<SkColor>  colorStorage(stripCount);
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint* strip = stripStorage.get();
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint* tex = strip + stripCount;
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkColor* colors = colorStorage.get();
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar t = 0;
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkScalar ds = SK_Scalar1 * fW / nu;
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkScalar dt = SK_Scalar1 * fH / nv;
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r = verts;
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (row = 0; row < nv; row++) {
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPoint* upper = r;
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPoint* lower = r + nu + 1;
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r = lower;
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScalar s = 0;
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (i = 0; i <= nu; i++)  {
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            strip[i*2 + 0] = *upper++;
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            strip[i*2 + 1] = *lower++;
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            tex[i*2 + 0].set(s, t);
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            tex[i*2 + 1].set(s, t + dt);
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            colors[i*2 + 0] = make_color(s/fW, t/fH);
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            colors[i*2 + 1] = make_color(s/fW, (t + dt)/fH);
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            s += ds;
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        t += dt;
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        canvas->drawVertices(SkCanvas::kTriangleStrip_VertexMode, stripCount,
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             strip, doTextures ? tex : NULL,
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             doColors ? colors : NULL, NULL,
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             NULL, 0, paint);
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void drawpatches(SkCanvas* canvas, const SkPaint& paint, int nu, int nv,
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        Patch* patch) {
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoCanvasRestore ar(canvas, true);
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
212cdf2db90d97347be41cd32d43cc7ae22ae2dcf3ereed    patch->draw(canvas, paint, nu, nv, false, false);
2136b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com    canvas->translate(SkIntToScalar(180), 0);
214cdf2db90d97347be41cd32d43cc7ae22ae2dcf3ereed    patch->draw(canvas, paint, nu, nv, true, false);
2156b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com    canvas->translate(SkIntToScalar(180), 0);
216cdf2db90d97347be41cd32d43cc7ae22ae2dcf3ereed    patch->draw(canvas, paint, nu, nv, false, true);
2176b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com    canvas->translate(SkIntToScalar(180), 0);
218cdf2db90d97347be41cd32d43cc7ae22ae2dcf3ereed    patch->draw(canvas, paint, nu, nv, true, true);
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
221147476da9eb1577dbdf058edc1164b661347f48dreedconst SkScalar DX = 20;
222147476da9eb1577dbdf058edc1164b661347f48dreedconst SkScalar DY = 0;
223147476da9eb1577dbdf058edc1164b661347f48dreed
2245fd9243fd6b82aa3f2a2fae7c62310e77ab7b6d3mike@reedtribe.orgclass PatchView : public SampleView {
225339cdbfb754ff0837ad4772b4837543e1092d62freed    SkScalar    fAngle;
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkShader*   fShader0;
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkShader*   fShader1;
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIPoint    fSize0, fSize1;
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint     fPts[12];
23082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
23182065d667f64e232bcde2ad849756a6096fcbe6freed@google.compublic:
232339cdbfb754ff0837ad4772b4837543e1092d62freed    PatchView() : fAngle(0) {
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fShader0 = make_shader0(&fSize0);
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fSize1 = fSize0;
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fSize0.fX == 0 || fSize0.fY == 0) {
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fSize1.set(2, 2);
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fShader1 = make_shader1(fSize1);
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2406b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com        const SkScalar S = SkIntToScalar(50);
2416b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com        const SkScalar T = SkIntToScalar(40);
2426b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com        fPts[0].set(S*0, T);
2436b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com        fPts[1].set(S*1, T);
2446b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com        fPts[2].set(S*2, T);
2456b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com        fPts[3].set(S*3, T);
2466b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com        fPts[4].set(S*3, T*2);
2476b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com        fPts[5].set(S*3, T*3);
2486b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com        fPts[6].set(S*3, T*4);
2496b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com        fPts[7].set(S*2, T*4);
2506b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com        fPts[8].set(S*1, T*4);
2516b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com        fPts[9].set(S*0, T*4);
2526b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com        fPts[10].set(S*0, T*3);
2536b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com        fPts[11].set(S*0, T*2);
2545fd9243fd6b82aa3f2a2fae7c62310e77ab7b6d3mike@reedtribe.org
2555fd9243fd6b82aa3f2a2fae7c62310e77ab7b6d3mike@reedtribe.org        this->setBGColor(SK_ColorGRAY);
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual ~PatchView() {
25982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeUnref(fShader0);
26082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeUnref(fShader1);
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
26282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // overrides from SkEventSink
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual bool onQuery(SkEvent* evt)  {
26645369a33bb78b6b76fafd63b1334151368dc9e2atfarina@chromium.org        if (SampleCode::TitleQ(*evt)) {
26745369a33bb78b6b76fafd63b1334151368dc9e2atfarina@chromium.org            SampleCode::TitleR(evt, "Patch");
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->INHERITED::onQuery(evt);
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
27282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
2735fd9243fd6b82aa3f2a2fae7c62310e77ab7b6d3mike@reedtribe.org    virtual void onDrawContent(SkCanvas* canvas) {
274cdf2db90d97347be41cd32d43cc7ae22ae2dcf3ereed        const int nu = 10;
275cdf2db90d97347be41cd32d43cc7ae22ae2dcf3ereed        const int nv = 10;
276cdf2db90d97347be41cd32d43cc7ae22ae2dcf3ereed
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPaint paint;
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint.setDither(true);
27993a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed        paint.setFilterQuality(kLow_SkFilterQuality);
28082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
281147476da9eb1577dbdf058edc1164b661347f48dreed        canvas->translate(DX, DY);
2826b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        Patch   patch;
28482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint.setShader(fShader0);
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fSize0.fX == 0) {
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fSize0.fX = 1;
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fSize0.fY == 0) {
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fSize0.fY = 1;
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        patch.setBounds(fSize0.fX, fSize0.fY);
29382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
29482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        patch.setPatch(fPts);
295cdf2db90d97347be41cd32d43cc7ae22ae2dcf3ereed        drawpatches(canvas, paint, nu, nv, &patch);
29682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint.setShader(NULL);
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint.setAntiAlias(true);
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint.setStrokeWidth(SkIntToScalar(5));
300f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        canvas->drawPoints(SkCanvas::kPoints_PointMode, SK_ARRAY_COUNT(fPts), fPts, paint);
30182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        canvas->translate(0, SkIntToScalar(300));
30382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint.setAntiAlias(false);
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint.setShader(fShader1);
306cdf2db90d97347be41cd32d43cc7ae22ae2dcf3ereed        if (true) {
3078fae213590981b8ca37839a4e3cae1dae4e611fdcommit-bot@chromium.org            SkMatrix m;
3088fae213590981b8ca37839a4e3cae1dae4e611fdcommit-bot@chromium.org            m.setSkew(1, 0);
3098fae213590981b8ca37839a4e3cae1dae4e611fdcommit-bot@chromium.org            SkShader* s = SkShader::CreateLocalMatrixShader(paint.getShader(), m);
3108fae213590981b8ca37839a4e3cae1dae4e611fdcommit-bot@chromium.org            paint.setShader(s)->unref();
3118fae213590981b8ca37839a4e3cae1dae4e611fdcommit-bot@chromium.org        }
312cdf2db90d97347be41cd32d43cc7ae22ae2dcf3ereed        if (true) {
3138fae213590981b8ca37839a4e3cae1dae4e611fdcommit-bot@chromium.org            SkMatrix m;
314339cdbfb754ff0837ad4772b4837543e1092d62freed            m.setRotate(fAngle);
3158fae213590981b8ca37839a4e3cae1dae4e611fdcommit-bot@chromium.org            SkShader* s = SkShader::CreateLocalMatrixShader(paint.getShader(), m);
3168fae213590981b8ca37839a4e3cae1dae4e611fdcommit-bot@chromium.org            paint.setShader(s)->unref();
3178fae213590981b8ca37839a4e3cae1dae4e611fdcommit-bot@chromium.org        }
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        patch.setBounds(fSize1.fX, fSize1.fY);
319cdf2db90d97347be41cd32d43cc7ae22ae2dcf3ereed        drawpatches(canvas, paint, nu, nv, &patch);
320339cdbfb754ff0837ad4772b4837543e1092d62freed    }
321b2c82c99f891e4e846e4959c811661bf68fa43d6skia.committer@gmail.com
32236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    bool onAnimate(const SkAnimTimer& timer) override {
323339cdbfb754ff0837ad4772b4837543e1092d62freed        fAngle = timer.scaled(60, 360);
324339cdbfb754ff0837ad4772b4837543e1092d62freed        return true;
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
32682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    class PtClick : public Click {
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    public:
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int fIndex;
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        PtClick(SkView* view, int index) : Click(view), fIndex(index) {}
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
33282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static bool hittest(const SkPoint& pt, SkScalar x, SkScalar y) {
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkPoint::Length(pt.fX - x, pt.fY - y) < SkIntToScalar(5);
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
33682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
3374d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com    virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y,
33836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                                              unsigned modi) override {
339147476da9eb1577dbdf058edc1164b661347f48dreed        x -= DX;
340147476da9eb1577dbdf058edc1164b661347f48dreed        y -= DY;
34164cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org        for (size_t i = 0; i < SK_ARRAY_COUNT(fPts); i++) {
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (hittest(fPts[i], x, y)) {
3437fa2a65c0cfc714364490cb715171461143024e0reed@google.com                return new PtClick(this, (int)i);
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3464d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com        return this->INHERITED::onFindClickHandler(x, y, modi);
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
34882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual bool onClick(Click* click) {
350147476da9eb1577dbdf058edc1164b661347f48dreed        fPts[((PtClick*)click)->fIndex].set(click->fCurr.fX - DX, click->fCurr.fY - DY);
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->inval(NULL);
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
35482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3565fd9243fd6b82aa3f2a2fae7c62310e77ab7b6d3mike@reedtribe.org    typedef SampleView INHERITED;
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkView* MyFactory() { return new PatchView; }
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkViewRegister reg(MyFactory);
363