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