OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SampleCode.h" | 8 #include "SampleCode.h" |
9 #include "SkView.h" | 9 #include "SkView.h" |
10 #include "SkCanvas.h" | 10 #include "SkCanvas.h" |
11 #include "SkRandom.h" | 11 #include "SkRandom.h" |
12 #include "SkRRect.h" | 12 #include "SkRRect.h" |
13 #include "SkColorPriv.h" | 13 #include "SkColorPriv.h" |
| 14 #include "SkStrokerPriv.h" |
14 | 15 |
15 static void rotateAbout(SkCanvas* canvas, SkScalar degrees, | 16 static void rotateAbout(SkCanvas* canvas, SkScalar degrees, |
16 SkScalar cx, SkScalar cy) { | 17 SkScalar cx, SkScalar cy) { |
17 canvas->translate(cx, cy); | 18 canvas->translate(cx, cy); |
18 canvas->rotate(degrees); | 19 canvas->rotate(degrees); |
19 canvas->translate(-cx, -cy); | 20 canvas->translate(-cx, -cy); |
20 } | 21 } |
21 | 22 |
22 class RotateCirclesView : public SampleView { | 23 class RotateCirclesView : public SampleView { |
23 public: | 24 public: |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 break; | 171 break; |
171 default: | 172 default: |
172 break; | 173 break; |
173 } | 174 } |
174 } | 175 } |
175 return count; | 176 return count; |
176 } | 177 } |
177 | 178 |
178 #include "SkPathMeasure.h" | 179 #include "SkPathMeasure.h" |
179 | 180 |
| 181 struct StrokeTypeButton { |
| 182 SkRect fBounds; |
| 183 char fLabel; |
| 184 bool fEnabled; |
| 185 }; |
| 186 |
180 class TestStrokeView : public SampleView { | 187 class TestStrokeView : public SampleView { |
181 enum { | 188 enum { |
182 SKELETON_COLOR = 0xFF0000FF, | 189 SKELETON_COLOR = 0xFF0000FF, |
183 WIREFRAME_COLOR = 0x80FF0000 | 190 WIREFRAME_COLOR = 0x80FF0000 |
184 }; | 191 }; |
185 | 192 |
186 enum { | 193 enum { |
187 kCount = 9 | 194 kCount = 9 |
188 }; | 195 }; |
189 SkPoint fPts[kCount]; | 196 SkPoint fPts[kCount]; |
| 197 SkRect fErrorControl; |
| 198 SkRect fWidthControl; |
| 199 StrokeTypeButton fCubicButton; |
| 200 StrokeTypeButton fQuadButton; |
| 201 StrokeTypeButton fRRectButton; |
190 SkScalar fWidth, fDWidth; | 202 SkScalar fWidth, fDWidth; |
| 203 bool fAnimate; |
| 204 #if QUAD_STROKE_APPROXIMATION && defined(SK_DEBUG) |
| 205 #define kStrokerErrorMin 0.001f |
| 206 #define kStrokerErrorMax 5 |
| 207 #endif |
| 208 #define kWidthMin 1 |
| 209 #define kWidthMax 100 |
191 public: | 210 public: |
192 TestStrokeView() { | 211 TestStrokeView() { |
193 this->setBGColor(SK_ColorLTGRAY); | 212 this->setBGColor(SK_ColorLTGRAY); |
194 | 213 |
195 fPts[0].set(50, 200); | 214 fPts[0].set(50, 200); |
196 fPts[1].set(50, 100); | 215 fPts[1].set(50, 100); |
197 fPts[2].set(150, 50); | 216 fPts[2].set(150, 50); |
198 fPts[3].set(300, 50); | 217 fPts[3].set(300, 50); |
199 | 218 |
200 fPts[4].set(350, 200); | 219 fPts[4].set(350, 200); |
201 fPts[5].set(350, 100); | 220 fPts[5].set(350, 100); |
202 fPts[6].set(450, 50); | 221 fPts[6].set(450, 50); |
203 | 222 |
204 fPts[7].set(200, 200); | 223 fPts[7].set(200, 200); |
205 fPts[8].set(400, 400); | 224 fPts[8].set(400, 400); |
206 | 225 |
207 fWidth = 50; | 226 fWidth = 50; |
208 fDWidth = 0.25f; | 227 fDWidth = 0.25f; |
| 228 |
| 229 fCubicButton.fLabel = 'C'; |
| 230 fCubicButton.fEnabled = true; |
| 231 fQuadButton.fLabel = 'Q'; |
| 232 fQuadButton.fEnabled = true; |
| 233 fRRectButton.fLabel = 'R'; |
| 234 fRRectButton.fEnabled = true; |
| 235 fAnimate = true; |
209 } | 236 } |
210 | 237 |
211 protected: | 238 protected: |
212 virtual bool onQuery(SkEvent* evt) SK_OVERRIDE { | 239 virtual bool onQuery(SkEvent* evt) SK_OVERRIDE { |
213 if (SampleCode::TitleQ(*evt)) { | 240 if (SampleCode::TitleQ(*evt)) { |
214 SampleCode::TitleR(evt, "RotateCircles3"); | 241 SampleCode::TitleR(evt, "RotateCircles3"); |
215 return true; | 242 return true; |
216 } | 243 } |
217 return this->INHERITED::onQuery(evt); | 244 return this->INHERITED::onQuery(evt); |
218 } | 245 } |
219 | 246 |
| 247 virtual void onSizeChange() { |
| 248 fErrorControl.setXYWH(this->width() - 100, 30, 30, 400); |
| 249 fWidthControl.setXYWH(this->width() - 50, 30, 30, 400); |
| 250 fCubicButton.fBounds.setXYWH(this->width() - 50, 450, 30, 30); |
| 251 fQuadButton.fBounds.setXYWH(this->width() - 50, 500, 30, 30); |
| 252 fRRectButton.fBounds.setXYWH(this->width() - 50, 550, 30, 30); |
| 253 this->INHERITED::onSizeChange(); |
| 254 } |
| 255 |
220 void draw_points(SkCanvas* canvas, const SkPath& path, SkColor color, | 256 void draw_points(SkCanvas* canvas, const SkPath& path, SkColor color, |
221 bool show_lines) { | 257 bool show_lines) { |
222 SkPaint paint; | 258 SkPaint paint; |
223 paint.setColor(color); | 259 paint.setColor(color); |
224 paint.setAlpha(0x80); | 260 paint.setAlpha(0x80); |
225 | 261 paint.setAntiAlias(true); |
226 int n = path.countPoints(); | 262 int n = path.countPoints(); |
227 SkAutoSTArray<32, SkPoint> pts(n); | 263 SkAutoSTArray<32, SkPoint> pts(n); |
228 if (show_lines) { | 264 if (show_lines) { |
229 path.getPoints(pts.get(), n); | 265 path.getPoints(pts.get(), n); |
230 canvas->drawPoints(SkCanvas::kPolygon_PointMode, n, pts.get(), paint
); | 266 canvas->drawPoints(SkCanvas::kPolygon_PointMode, n, pts.get(), paint
); |
231 } else { | 267 } else { |
232 n = getOnCurvePoints(path, pts.get()); | 268 n = getOnCurvePoints(path, pts.get()); |
233 } | 269 } |
234 paint.setStrokeWidth(5); | 270 paint.setStrokeWidth(5); |
235 canvas->drawPoints(SkCanvas::kPoints_PointMode, n, pts.get(), paint); | 271 canvas->drawPoints(SkCanvas::kPoints_PointMode, n, pts.get(), paint); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 SkPaint p; | 309 SkPaint p; |
274 p.setStyle(SkPaint::kStroke_Style); | 310 p.setStyle(SkPaint::kStroke_Style); |
275 p.setStrokeWidth(width); | 311 p.setStrokeWidth(width); |
276 p.getFillPath(path, &fill); | 312 p.getFillPath(path, &fill); |
277 | 313 |
278 paint.setColor(WIREFRAME_COLOR); | 314 paint.setColor(WIREFRAME_COLOR); |
279 canvas->drawPath(fill, paint); | 315 canvas->drawPath(fill, paint); |
280 draw_points(canvas, fill, WIREFRAME_COLOR, false); | 316 draw_points(canvas, fill, WIREFRAME_COLOR, false); |
281 } | 317 } |
282 | 318 |
| 319 void draw_button(SkCanvas* canvas, const StrokeTypeButton& button) { |
| 320 SkPaint paint; |
| 321 paint.setAntiAlias(true); |
| 322 paint.setStyle(SkPaint::kStroke_Style); |
| 323 paint.setColor(button.fEnabled ? 0xFF3F0000 : 0x6F3F0000); |
| 324 canvas->drawRect(button.fBounds, paint); |
| 325 paint.setTextSize(25.0f); |
| 326 paint.setColor(button.fEnabled ? 0xFF3F0000 : 0x6F3F0000); |
| 327 paint.setTextAlign(SkPaint::kCenter_Align); |
| 328 paint.setStyle(SkPaint::kFill_Style); |
| 329 canvas->drawText(&button.fLabel, 1, button.fBounds.centerX(), button.fBo
unds.fBottom - 5, |
| 330 paint); |
| 331 } |
| 332 |
| 333 void draw_control(SkCanvas* canvas, const SkRect& bounds, SkScalar value, |
| 334 SkScalar min, SkScalar max, const char* name) { |
| 335 SkPaint paint; |
| 336 paint.setAntiAlias(true); |
| 337 paint.setStyle(SkPaint::kStroke_Style); |
| 338 canvas->drawRect(bounds, paint); |
| 339 SkScalar scale = max - min; |
| 340 SkScalar yPos = bounds.fTop + (value - min) * bounds.height() / scale; |
| 341 paint.setColor(0xFFFF0000); |
| 342 canvas->drawLine(bounds.fLeft - 5, yPos, bounds.fRight + 5, yPos, paint)
; |
| 343 SkString label; |
| 344 label.printf("%0.3g", value); |
| 345 paint.setColor(0xFF000000); |
| 346 paint.setTextSize(11.0f); |
| 347 paint.setStyle(SkPaint::kFill_Style); |
| 348 canvas->drawText(label.c_str(), label.size(), bounds.fLeft + 5, yPos - 5
, paint); |
| 349 paint.setTextSize(13.0f); |
| 350 canvas->drawText(name, strlen(name), bounds.fLeft, bounds.bottom() + 11,
paint); |
| 351 } |
| 352 |
283 virtual void onDrawContent(SkCanvas* canvas) { | 353 virtual void onDrawContent(SkCanvas* canvas) { |
284 SkPath path; | 354 SkPath path; |
285 SkScalar width = fWidth; | 355 SkScalar width = fWidth; |
286 | 356 |
287 path.moveTo(fPts[0]); | 357 if (fCubicButton.fEnabled) { |
288 path.cubicTo(fPts[1], fPts[2], fPts[3]); | 358 path.moveTo(fPts[0]); |
289 draw_stroke(canvas, path, width); | 359 path.cubicTo(fPts[1], fPts[2], fPts[3]); |
| 360 draw_stroke(canvas, path, width); |
| 361 } |
290 | 362 |
291 path.reset(); | 363 if (fQuadButton.fEnabled) { |
292 path.moveTo(fPts[4]); | 364 path.reset(); |
293 path.quadTo(fPts[5], fPts[6]); | 365 path.moveTo(fPts[4]); |
294 draw_stroke(canvas, path, width); | 366 path.quadTo(fPts[5], fPts[6]); |
| 367 draw_stroke(canvas, path, width); |
| 368 } |
295 | 369 |
296 SkScalar rad = 32; | 370 if (fRRectButton.fEnabled) { |
297 SkRect r; | 371 SkScalar rad = 32; |
298 r.set(&fPts[7], 2); | 372 SkRect r; |
299 path.reset(); | 373 r.set(&fPts[7], 2); |
300 SkRRect rr; | 374 path.reset(); |
301 rr.setRectXY(r, rad, rad); | 375 SkRRect rr; |
302 path.addRRect(rr); | 376 rr.setRectXY(r, rad, rad); |
303 draw_stroke(canvas, path, width); | 377 path.addRRect(rr); |
| 378 draw_stroke(canvas, path, width); |
304 | 379 |
305 path.reset(); | 380 path.reset(); |
306 SkRRect rr2; | 381 SkRRect rr2; |
307 rr.inset(width/2, width/2, &rr2); | 382 rr.inset(width/2, width/2, &rr2); |
308 path.addRRect(rr2, SkPath::kCCW_Direction); | 383 path.addRRect(rr2, SkPath::kCCW_Direction); |
309 rr.inset(-width/2, -width/2, &rr2); | 384 rr.inset(-width/2, -width/2, &rr2); |
310 path.addRRect(rr2, SkPath::kCW_Direction); | 385 path.addRRect(rr2, SkPath::kCW_Direction); |
311 SkPaint paint; | 386 SkPaint paint; |
312 paint.setAntiAlias(true); | 387 paint.setAntiAlias(true); |
313 paint.setColor(0x40FF8844); | 388 paint.setColor(0x40FF8844); |
314 canvas->drawPath(path, paint); | 389 canvas->drawPath(path, paint); |
| 390 } |
315 | 391 |
316 fWidth += fDWidth; | 392 if (fAnimate) { |
317 if (fDWidth > 0 && fWidth > 100) { | 393 fWidth += fDWidth; |
318 fDWidth = -fDWidth; | 394 if (fDWidth > 0 && fWidth > kWidthMax) { |
319 } else if (fDWidth < 0 && fWidth < 10) { | 395 fDWidth = -fDWidth; |
320 fDWidth = -fDWidth; | 396 } else if (fDWidth < 0 && fWidth < kWidthMin) { |
| 397 fDWidth = -fDWidth; |
| 398 } |
321 } | 399 } |
| 400 #if QUAD_STROKE_APPROXIMATION && defined(SK_DEBUG) |
| 401 draw_control(canvas, fErrorControl, gDebugStrokerError, kStrokerErrorMin
, kStrokerErrorMax, |
| 402 "error"); |
| 403 #endif |
| 404 draw_control(canvas, fWidthControl, fWidth, kWidthMin, kWidthMax, "width
"); |
| 405 draw_button(canvas, fQuadButton); |
| 406 draw_button(canvas, fCubicButton); |
| 407 draw_button(canvas, fRRectButton); |
322 this->inval(NULL); | 408 this->inval(NULL); |
323 } | 409 } |
324 | 410 |
325 class MyClick : public Click { | 411 class MyClick : public Click { |
326 public: | 412 public: |
327 int fIndex; | 413 int fIndex; |
328 MyClick(SkView* target, int index) : Click(target), fIndex(index) {} | 414 MyClick(SkView* target, int index) : Click(target), fIndex(index) {} |
329 }; | 415 }; |
330 | 416 |
331 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, | 417 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, |
332 unsigned modi) SK_OVERRIDE { | 418 unsigned modi) SK_OVERRIDE { |
333 for (size_t i = 0; i < SK_ARRAY_COUNT(fPts); ++i) { | 419 for (size_t i = 0; i < SK_ARRAY_COUNT(fPts); ++i) { |
334 if (hittest(fPts[i], x, y)) { | 420 if (hittest(fPts[i], x, y)) { |
335 return new MyClick(this, (int)i); | 421 return new MyClick(this, (int)i); |
336 } | 422 } |
337 } | 423 } |
| 424 const SkRect& rectPt = SkRect::MakeXYWH(x, y, 1, 1); |
| 425 #if QUAD_STROKE_APPROXIMATION && defined(SK_DEBUG) |
| 426 if (fErrorControl.contains(rectPt)) { |
| 427 return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 1); |
| 428 } |
| 429 #endif |
| 430 if (fWidthControl.contains(rectPt)) { |
| 431 return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 3); |
| 432 } |
| 433 if (fCubicButton.fBounds.contains(rectPt)) { |
| 434 fCubicButton.fEnabled ^= true; |
| 435 return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 4); |
| 436 } |
| 437 if (fQuadButton.fBounds.contains(rectPt)) { |
| 438 fQuadButton.fEnabled ^= true; |
| 439 return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 5); |
| 440 } |
| 441 if (fRRectButton.fBounds.contains(rectPt)) { |
| 442 fRRectButton.fEnabled ^= true; |
| 443 return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 6); |
| 444 } |
338 return this->INHERITED::onFindClickHandler(x, y, modi); | 445 return this->INHERITED::onFindClickHandler(x, y, modi); |
339 } | 446 } |
340 | 447 |
| 448 static SkScalar MapScreenYtoValue(int y, const SkRect& control, SkScalar min
, |
| 449 SkScalar max) { |
| 450 return (SkIntToScalar(y) - control.fTop) / control.height() * (max - min
) + min; |
| 451 } |
| 452 |
341 virtual bool onClick(Click* click) { | 453 virtual bool onClick(Click* click) { |
342 int index = ((MyClick*)click)->fIndex; | 454 int index = ((MyClick*)click)->fIndex; |
343 fPts[index].offset(SkIntToScalar(click->fICurr.fX - click->fIPrev.fX), | 455 if (index < (int) SK_ARRAY_COUNT(fPts)) { |
344 SkIntToScalar(click->fICurr.fY - click->fIPrev.fY)); | 456 fPts[index].offset(SkIntToScalar(click->fICurr.fX - click->fIPrev.fX
), |
345 this->inval(NULL); | 457 SkIntToScalar(click->fICurr.fY - click->fIPrev.fY
)); |
| 458 this->inval(NULL); |
| 459 } |
| 460 #if QUAD_STROKE_APPROXIMATION && defined(SK_DEBUG) |
| 461 else if (index == (int) SK_ARRAY_COUNT(fPts) + 1) { |
| 462 gDebugStrokerError = MapScreenYtoValue(click->fICurr.fY, fErrorContr
ol, |
| 463 kStrokerErrorMin, kStrokerErrorMax); |
| 464 gDebugStrokerErrorSet = true; |
| 465 } |
| 466 #endif |
| 467 else if (index == (int) SK_ARRAY_COUNT(fPts) + 3) { |
| 468 fWidth = MapScreenYtoValue(click->fICurr.fY, fWidthControl, kWidthMi
n, kWidthMax); |
| 469 fAnimate = fWidth <= kWidthMin; |
| 470 } |
346 return true; | 471 return true; |
347 } | 472 } |
348 | 473 |
349 private: | 474 private: |
350 typedef SkView INHERITED; | 475 typedef SkView INHERITED; |
351 }; | 476 }; |
352 | 477 |
353 /////////////////////////////////////////////////////////////////////////////// | 478 /////////////////////////////////////////////////////////////////////////////// |
354 | 479 |
355 static SkView* F0() { return new RotateCirclesView; } | 480 static SkView* F0() { return new RotateCirclesView; } |
356 static SkViewRegister gR0(F0); | 481 static SkViewRegister gR0(F0); |
357 static SkView* F1() { return new TestCirclesView; } | 482 static SkView* F1() { return new TestCirclesView; } |
358 static SkViewRegister gR1(F1); | 483 static SkViewRegister gR1(F1); |
359 static SkView* F2() { return new TestStrokeView; } | 484 static SkView* F2() { return new TestStrokeView; } |
360 static SkViewRegister gR2(F2); | 485 static SkViewRegister gR2(F2); |
OLD | NEW |