Home | History | Annotate | Download | only in samplecode
      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 "Sk64.h"
     12 #include "SkCornerPathEffect.h"
     13 #include "SkGradientShader.h"
     14 #include "SkGraphics.h"
     15 #include "SkImageDecoder.h"
     16 #include "SkKernel33MaskFilter.h"
     17 #include "SkPath.h"
     18 #include "SkRandom.h"
     19 #include "SkRegion.h"
     20 #include "SkShader.h"
     21 #include "SkUtils.h"
     22 #include "SkColorPriv.h"
     23 #include "SkColorFilter.h"
     24 #include "SkTime.h"
     25 #include "SkTypeface.h"
     26 #include "SkXfermode.h"
     27 
     28 #include "SkStream.h"
     29 #include "SkXMLParser.h"
     30 #include "SkColorPriv.h"
     31 #include "SkImageDecoder.h"
     32 
     33 static SkRandom gRand;
     34 
     35 static void test_chromium_9005() {
     36     SkBitmap bm;
     37     bm.setConfig(SkBitmap::kARGB_8888_Config, 800, 600);
     38     bm.allocPixels();
     39 
     40     SkCanvas canvas(bm);
     41 
     42     SkPoint pt0 = { SkFloatToScalar(799.33374f), SkFloatToScalar(1.2360189f) };
     43     SkPoint pt1 = { SkFloatToScalar(808.49969f), SkFloatToScalar(-7.4338055f) };
     44 
     45     SkPaint paint;
     46     paint.setAntiAlias(true);
     47     canvas.drawLine(pt0.fX, pt0.fY, pt1.fX, pt1.fY, paint);
     48 }
     49 
     50 static void generate_pts(SkPoint pts[], int count, int w, int h) {
     51     for (int i = 0; i < count; i++) {
     52         pts[i].set(gRand.nextUScalar1() * 3 * w - SkIntToScalar(w),
     53                    gRand.nextUScalar1() * 3 * h - SkIntToScalar(h));
     54     }
     55 }
     56 
     57 static bool check_zeros(const SkPMColor pixels[], int count, int skip) {
     58     for (int i = 0; i < count; i++) {
     59         if (*pixels) {
     60             return false;
     61         }
     62         pixels += skip;
     63     }
     64     return true;
     65 }
     66 
     67 static bool check_bitmap_margin(const SkBitmap& bm, int margin) {
     68     size_t rb = bm.rowBytes();
     69     for (int i = 0; i < margin; i++) {
     70         if (!check_zeros(bm.getAddr32(0, i), bm.width(), 1)) {
     71             return false;
     72         }
     73         int bottom = bm.height() - i - 1;
     74         if (!check_zeros(bm.getAddr32(0, bottom), bm.width(), 1)) {
     75             return false;
     76         }
     77         // left column
     78         if (!check_zeros(bm.getAddr32(i, 0), bm.height(), rb >> 2)) {
     79             return false;
     80         }
     81         int right = bm.width() - margin + i;
     82         if (!check_zeros(bm.getAddr32(right, 0), bm.height(), rb >> 2)) {
     83             return false;
     84         }
     85     }
     86     return true;
     87 }
     88 
     89 #define WIDTH   620
     90 #define HEIGHT  460
     91 #define MARGIN  10
     92 
     93 static void line_proc(SkCanvas* canvas, const SkPaint& paint,
     94                       const SkBitmap& bm) {
     95     const int N = 2;
     96     SkPoint pts[N];
     97     for (int i = 0; i < 400; i++) {
     98         generate_pts(pts, N, WIDTH, HEIGHT);
     99 
    100         canvas->drawLine(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, paint);
    101         if (!check_bitmap_margin(bm, MARGIN)) {
    102             SkDebugf("---- hairline failure (%g %g) (%g %g)\n",
    103                      pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY);
    104             break;
    105         }
    106     }
    107 }
    108 
    109 static void poly_proc(SkCanvas* canvas, const SkPaint& paint,
    110                       const SkBitmap& bm) {
    111     const int N = 8;
    112     SkPoint pts[N];
    113     for (int i = 0; i < 50; i++) {
    114         generate_pts(pts, N, WIDTH, HEIGHT);
    115 
    116         SkPath path;
    117         path.moveTo(pts[0]);
    118         for (int j = 1; j < N; j++) {
    119             path.lineTo(pts[j]);
    120         }
    121         canvas->drawPath(path, paint);
    122     }
    123 }
    124 
    125 static SkPoint ave(const SkPoint& a, const SkPoint& b) {
    126     SkPoint c = a + b;
    127     c.fX = SkScalarHalf(c.fX);
    128     c.fY = SkScalarHalf(c.fY);
    129     return c;
    130 }
    131 
    132 static void quad_proc(SkCanvas* canvas, const SkPaint& paint,
    133                       const SkBitmap& bm) {
    134     const int N = 30;
    135     SkPoint pts[N];
    136     for (int i = 0; i < 10; i++) {
    137         generate_pts(pts, N, WIDTH, HEIGHT);
    138 
    139         SkPath path;
    140         path.moveTo(pts[0]);
    141         for (int j = 1; j < N - 2; j++) {
    142             path.quadTo(pts[j], ave(pts[j], pts[j+1]));
    143         }
    144         path.quadTo(pts[N - 2], pts[N - 1]);
    145 
    146         canvas->drawPath(path, paint);
    147     }
    148 }
    149 
    150 static void add_cubic(SkPath* path, const SkPoint& mid, const SkPoint& end) {
    151     SkPoint start;
    152     path->getLastPt(&start);
    153     path->cubicTo(ave(start, mid), ave(mid, end), end);
    154 }
    155 
    156 static void cube_proc(SkCanvas* canvas, const SkPaint& paint,
    157                       const SkBitmap& bm) {
    158     const int N = 30;
    159     SkPoint pts[N];
    160     for (int i = 0; i < 10; i++) {
    161         generate_pts(pts, N, WIDTH, HEIGHT);
    162 
    163         SkPath path;
    164         path.moveTo(pts[0]);
    165         for (int j = 1; j < N - 2; j++) {
    166             add_cubic(&path, pts[j], ave(pts[j], pts[j+1]));
    167         }
    168         add_cubic(&path, pts[N - 2], pts[N - 1]);
    169 
    170         canvas->drawPath(path, paint);
    171     }
    172 }
    173 
    174 typedef void (*HairProc)(SkCanvas*, const SkPaint&, const SkBitmap&);
    175 
    176 static const struct {
    177     const char* fName;
    178     HairProc    fProc;
    179 } gProcs[] = {
    180     { "line",   line_proc },
    181     { "poly",   poly_proc },
    182     { "quad",   quad_proc },
    183     { "cube",   cube_proc },
    184 };
    185 
    186 static int cycle_hairproc_index(int index) {
    187     return (index + 1) % SK_ARRAY_COUNT(gProcs);
    188 }
    189 
    190 class HairlineView : public SampleView {
    191     SkMSec fNow;
    192     int fProcIndex;
    193     bool fDoAA;
    194 public:
    195 	HairlineView() {
    196         fCounter = 0;
    197         fProcIndex = 0;
    198         fDoAA = true;
    199         fNow = 0;
    200     }
    201 
    202 protected:
    203     // overrides from SkEventSink
    204     virtual bool onQuery(SkEvent* evt) {
    205         if (SampleCode::TitleQ(*evt)) {
    206             SkString str;
    207             str.printf("Hair-%s", gProcs[fProcIndex].fName);
    208             SampleCode::TitleR(evt, str.c_str());
    209             return true;
    210         }
    211         return this->INHERITED::onQuery(evt);
    212     }
    213 
    214     void show_bitmaps(SkCanvas* canvas, const SkBitmap& b0, const SkBitmap& b1,
    215                       const SkIRect& inset) {
    216         canvas->drawBitmap(b0, 0, 0, NULL);
    217         canvas->drawBitmap(b1, SkIntToScalar(b0.width()), 0, NULL);
    218     }
    219 
    220     int fCounter;
    221 
    222     virtual void onDrawContent(SkCanvas* canvas) {
    223         gRand.setSeed(fNow);
    224 
    225         if (false) {
    226             test_chromium_9005();
    227         }
    228 
    229         SkBitmap bm, bm2;
    230         bm.setConfig(SkBitmap::kARGB_8888_Config,
    231                      WIDTH + MARGIN*2,
    232                      HEIGHT + MARGIN*2);
    233         bm.allocPixels();
    234         // this will erase our margin, which we want to always stay 0
    235         bm.eraseColor(0);
    236 
    237         bm2.setConfig(SkBitmap::kARGB_8888_Config, WIDTH, HEIGHT,
    238                       bm.rowBytes());
    239         bm2.setPixels(bm.getAddr32(MARGIN, MARGIN));
    240 
    241         SkCanvas c2(bm2);
    242         SkPaint paint;
    243         paint.setAntiAlias(fDoAA);
    244         paint.setStyle(SkPaint::kStroke_Style);
    245 
    246         bm2.eraseColor(0);
    247         gProcs[fProcIndex].fProc(&c2, paint, bm);
    248         canvas->drawBitmap(bm2, SkIntToScalar(10), SkIntToScalar(10), NULL);
    249 
    250         SkMSec now = SampleCode::GetAnimTime();
    251         if (fNow != now) {
    252             fNow = now;
    253             fCounter += 1;
    254             fDoAA = !fDoAA;
    255             if (fCounter > 50) {
    256                 fProcIndex = cycle_hairproc_index(fProcIndex);
    257                 // todo: signal that we want to rebuild our TITLE
    258                 fCounter = 0;
    259             }
    260             this->inval(NULL);
    261         }
    262     }
    263 
    264     virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
    265         fDoAA = !fDoAA;
    266         this->inval(NULL);
    267         return this->INHERITED::onFindClickHandler(x, y);
    268     }
    269 
    270 
    271 private:
    272     typedef SampleView INHERITED;
    273 };
    274 
    275 //////////////////////////////////////////////////////////////////////////////
    276 
    277 static SkView* MyFactory() { return new HairlineView; }
    278 static SkViewRegister reg(MyFactory);
    279 
    280