| epoger@google.com | ec3ed6a | 2011-07-28 14:26:00 +0000 | [diff] [blame] | 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 |  */ | 
| reed@android.com | 8898363 | 2009-03-23 16:05:19 +0000 | [diff] [blame] | 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 |  | 
| reed@android.com | 2893728 | 2009-08-28 15:34:46 +0000 | [diff] [blame] | 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 | } | 
| reed@android.com | 8898363 | 2009-03-23 16:05:19 +0000 | [diff] [blame] | 189 |  | 
| mike@reedtribe.org | 5fd9243 | 2011-05-05 01:59:48 +0000 | [diff] [blame] | 190 | class HairlineView : public SampleView { | 
| reed@android.com | a3d9010 | 2009-11-30 12:48:33 +0000 | [diff] [blame] | 191 |     SkMSec fNow; | 
| reed@android.com | 2893728 | 2009-08-28 15:34:46 +0000 | [diff] [blame] | 192 |     int fProcIndex; | 
 | 193 |     bool fDoAA; | 
| reed@android.com | 8898363 | 2009-03-23 16:05:19 +0000 | [diff] [blame] | 194 | public: | 
| reed@android.com | 2893728 | 2009-08-28 15:34:46 +0000 | [diff] [blame] | 195 | 	HairlineView() { | 
| senorblanco@chromium.org | 50108cd | 2011-05-24 20:25:32 +0000 | [diff] [blame] | 196 |         fCounter = 0; | 
| reed@android.com | 2893728 | 2009-08-28 15:34:46 +0000 | [diff] [blame] | 197 |         fProcIndex = 0; | 
 | 198 |         fDoAA = true; | 
| reed@android.com | a3d9010 | 2009-11-30 12:48:33 +0000 | [diff] [blame] | 199 |         fNow = 0; | 
| reed@android.com | 2893728 | 2009-08-28 15:34:46 +0000 | [diff] [blame] | 200 |     } | 
| reed@android.com | 8898363 | 2009-03-23 16:05:19 +0000 | [diff] [blame] | 201 |      | 
 | 202 | protected: | 
 | 203 |     // overrides from SkEventSink | 
 | 204 |     virtual bool onQuery(SkEvent* evt) { | 
 | 205 |         if (SampleCode::TitleQ(*evt)) { | 
| reed@android.com | 2893728 | 2009-08-28 15:34:46 +0000 | [diff] [blame] | 206 |             SkString str; | 
 | 207 |             str.printf("Hair-%s", gProcs[fProcIndex].fName); | 
 | 208 |             SampleCode::TitleR(evt, str.c_str()); | 
| reed@android.com | 8898363 | 2009-03-23 16:05:19 +0000 | [diff] [blame] | 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 |  | 
| reed@android.com | 2893728 | 2009-08-28 15:34:46 +0000 | [diff] [blame] | 220 |     int fCounter; | 
 | 221 |  | 
| mike@reedtribe.org | 5fd9243 | 2011-05-05 01:59:48 +0000 | [diff] [blame] | 222 |     virtual void onDrawContent(SkCanvas* canvas) { | 
| reed@android.com | a3d9010 | 2009-11-30 12:48:33 +0000 | [diff] [blame] | 223 |         gRand.setSeed(fNow); | 
 | 224 |          | 
| caryclark@google.com | e351050 | 2012-06-06 12:13:40 +0000 | [diff] [blame] | 225 |         if (false) { // avoid bit rot, suppress warning | 
| reed@android.com | 8898363 | 2009-03-23 16:05:19 +0000 | [diff] [blame] | 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; | 
| reed@android.com | 2893728 | 2009-08-28 15:34:46 +0000 | [diff] [blame] | 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); | 
| reed@android.com | a3d9010 | 2009-11-30 12:48:33 +0000 | [diff] [blame] | 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); | 
| reed@android.com | 2893728 | 2009-08-28 15:34:46 +0000 | [diff] [blame] | 261 |         } | 
| reed@android.com | 8898363 | 2009-03-23 16:05:19 +0000 | [diff] [blame] | 262 |     } | 
 | 263 |  | 
| reed@android.com | 2893728 | 2009-08-28 15:34:46 +0000 | [diff] [blame] | 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 |  | 
| reed@android.com | 8898363 | 2009-03-23 16:05:19 +0000 | [diff] [blame] | 271 | private: | 
| mike@reedtribe.org | 5fd9243 | 2011-05-05 01:59:48 +0000 | [diff] [blame] | 272 |     typedef SampleView INHERITED; | 
| reed@android.com | 8898363 | 2009-03-23 16:05:19 +0000 | [diff] [blame] | 273 | }; | 
 | 274 |  | 
 | 275 | ////////////////////////////////////////////////////////////////////////////// | 
 | 276 |  | 
 | 277 | static SkView* MyFactory() { return new HairlineView; } | 
 | 278 | static SkViewRegister reg(MyFactory); | 
 | 279 |  |