| /* |
| * Copyright 2012 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "SampleCode.h" |
| #include "SkView.h" |
| #include "SkCanvas.h" |
| #include "SkRandom.h" |
| #include "SkRRect.h" |
| #include "SkColorPriv.h" |
| |
| static void rotateAbout(SkCanvas* canvas, SkScalar degrees, |
| SkScalar cx, SkScalar cy) { |
| canvas->translate(cx, cy); |
| canvas->rotate(degrees); |
| canvas->translate(-cx, -cy); |
| } |
| |
| class RotateCirclesView : public SampleView { |
| public: |
| RotateCirclesView() { |
| this->setBGColor(SK_ColorLTGRAY); |
| |
| fAngle = 0; |
| } |
| |
| protected: |
| // overrides from SkEventSink |
| virtual bool onQuery(SkEvent* evt) { |
| if (SampleCode::TitleQ(*evt)) { |
| SampleCode::TitleR(evt, "RotateCircles"); |
| return true; |
| } |
| return this->INHERITED::onQuery(evt); |
| } |
| |
| virtual void onDrawContent(SkCanvas* canvas) { |
| SkRandom rand; |
| SkPaint paint; |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(20); |
| |
| SkScalar cx = 240; |
| SkScalar cy = 240; |
| SkScalar DX = 240 * 2; |
| SkColor color = 0; |
| |
| float scale = 1; |
| float sign = 0.3f; |
| for (SkScalar rad = 200; rad >= 20; rad -= 15) { |
| sign = -sign; |
| scale += 0.2f; |
| |
| paint.setColor(rand.nextU()); |
| paint.setAlpha(0xFF); |
| color = ~color; |
| |
| paint.setStyle(SkPaint::kFill_Style); |
| |
| canvas->save(); |
| rotateAbout(canvas, fAngle * scale * sign, cx, cy); |
| canvas->drawCircle(cx, cy, rad, paint); |
| canvas->restore(); |
| |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setStrokeWidth(rad*2); |
| |
| canvas->save(); |
| rotateAbout(canvas, fAngle * scale * sign, cx + DX, cy); |
| canvas->drawCircle(cx + DX, cy, 10, paint); |
| canvas->restore(); |
| |
| canvas->save(); |
| rotateAbout(canvas, fAngle * scale * sign, cx + DX, cy + DX); |
| canvas->drawCircle(cx + DX, cy + DX, 10, paint); |
| canvas->restore(); |
| |
| } |
| |
| fAngle = (fAngle + 1) % 360; |
| this->inval(NULL); |
| } |
| |
| private: |
| int fAngle; |
| typedef SkView INHERITED; |
| }; |
| |
| class TestCirclesView : public SampleView { |
| public: |
| TestCirclesView() { |
| } |
| |
| protected: |
| virtual bool onQuery(SkEvent* evt) SK_OVERRIDE { |
| if (SampleCode::TitleQ(*evt)) { |
| SampleCode::TitleR(evt, "RotateCircles2"); |
| return true; |
| } |
| return this->INHERITED::onQuery(evt); |
| } |
| |
| void draw_real_circle(SkCanvas* canvas, SkScalar radius) { |
| int w = SkScalarCeilToInt(radius * 2); |
| int h = w; |
| |
| SkBitmap bm; |
| bm.setConfig(SkBitmap::kARGB_8888_Config, w, h); |
| bm.allocPixels(); |
| bm.eraseColor(0); |
| |
| SkAutoLockPixels alp(bm); |
| |
| SkScalar cx = radius; |
| SkScalar cy = radius; |
| for (int y = 0; y < h; y += 1) { |
| for (int x = 0; x < w; x += 1) { |
| float d = sqrtf((x - cx)*(x - cx) + (y - cy)*(y - cy)); |
| if (d <= radius) { |
| *bm.getAddr32(x, y) = SkPackARGB32(0xFF, 0, 0, 0); |
| } |
| } |
| } |
| |
| canvas->drawBitmap(bm, 0, 0, NULL); |
| } |
| |
| virtual void onDrawContent(SkCanvas* canvas) { |
| SkScalar radius = 256; |
| canvas->translate(10, 10); |
| |
| draw_real_circle(canvas, radius); |
| |
| SkPaint paint; |
| paint.setAntiAlias(true); |
| |
| paint.setColor(0x80FF0000); |
| canvas->drawCircle(radius, radius, radius, paint); |
| |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setStrokeWidth(radius); |
| paint.setColor(0x8000FF00); |
| canvas->drawCircle(radius, radius, radius/2, paint); |
| } |
| |
| private: |
| typedef SkView INHERITED; |
| }; |
| |
| static bool hittest(const SkPoint& target, SkScalar x, SkScalar y) { |
| const SkScalar TOL = 7; |
| return SkPoint::Distance(target, SkPoint::Make(x, y)) <= TOL; |
| } |
| |
| static int getOnCurvePoints(const SkPath& path, SkPoint storage[]) { |
| SkPath::RawIter iter(path); |
| SkPoint pts[4]; |
| SkPath::Verb verb; |
| |
| int count = 0; |
| while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { |
| switch (verb) { |
| case SkPath::kMove_Verb: |
| case SkPath::kLine_Verb: |
| case SkPath::kQuad_Verb: |
| case SkPath::kCubic_Verb: |
| storage[count++] = pts[0]; |
| break; |
| default: |
| break; |
| } |
| } |
| return count; |
| } |
| |
| #include "SkPathMeasure.h" |
| |
| class TestStrokeView : public SampleView { |
| enum { |
| SKELETON_COLOR = 0xFF0000FF, |
| WIREFRAME_COLOR = 0x80FF0000 |
| }; |
| |
| enum { |
| kCount = 9 |
| }; |
| SkPoint fPts[kCount]; |
| SkScalar fWidth, fDWidth; |
| public: |
| TestStrokeView() { |
| this->setBGColor(SK_ColorLTGRAY); |
| |
| fPts[0].set(50, 200); |
| fPts[1].set(50, 100); |
| fPts[2].set(150, 50); |
| fPts[3].set(300, 50); |
| |
| fPts[4].set(350, 200); |
| fPts[5].set(350, 100); |
| fPts[6].set(450, 50); |
| |
| fPts[7].set(200, 200); |
| fPts[8].set(400, 400); |
| |
| fWidth = 50; |
| fDWidth = 0.25f; |
| } |
| |
| protected: |
| virtual bool onQuery(SkEvent* evt) SK_OVERRIDE { |
| if (SampleCode::TitleQ(*evt)) { |
| SampleCode::TitleR(evt, "RotateCircles3"); |
| return true; |
| } |
| return this->INHERITED::onQuery(evt); |
| } |
| |
| void draw_points(SkCanvas* canvas, const SkPath& path, SkColor color, |
| bool show_lines) { |
| SkPaint paint; |
| paint.setColor(color); |
| paint.setAlpha(0x80); |
| |
| int n = path.countPoints(); |
| SkAutoSTArray<32, SkPoint> pts(n); |
| if (show_lines) { |
| path.getPoints(pts.get(), n); |
| canvas->drawPoints(SkCanvas::kPolygon_PointMode, n, pts.get(), paint); |
| } else { |
| n = getOnCurvePoints(path, pts.get()); |
| } |
| paint.setStrokeWidth(5); |
| canvas->drawPoints(SkCanvas::kPoints_PointMode, n, pts.get(), paint); |
| } |
| |
| void draw_ribs(SkCanvas* canvas, const SkPath& path, SkScalar width, |
| SkColor color) { |
| const SkScalar radius = width / 2; |
| |
| SkPathMeasure meas(path, false); |
| SkScalar total = meas.getLength(); |
| |
| SkScalar delta = 8; |
| SkPaint paint; |
| paint.setColor(color); |
| |
| SkPoint pos, tan; |
| for (SkScalar dist = 0; dist <= total; dist += delta) { |
| if (meas.getPosTan(dist, &pos, &tan)) { |
| tan.scale(radius); |
| tan.rotateCCW(); |
| canvas->drawLine(pos.x() + tan.x(), pos.y() + tan.y(), |
| pos.x() - tan.x(), pos.y() - tan.y(), paint); |
| } |
| } |
| } |
| |
| void draw_stroke(SkCanvas* canvas, const SkPath& path, SkScalar width) { |
| SkPaint paint; |
| paint.setAntiAlias(true); |
| paint.setStyle(SkPaint::kStroke_Style); |
| |
| paint.setColor(SKELETON_COLOR); |
| canvas->drawPath(path, paint); |
| draw_points(canvas, path, SKELETON_COLOR, true); |
| |
| draw_ribs(canvas, path, width, 0xFF00FF00); |
| |
| SkPath fill; |
| |
| SkPaint p; |
| p.setStyle(SkPaint::kStroke_Style); |
| p.setStrokeWidth(width); |
| p.getFillPath(path, &fill); |
| |
| paint.setColor(WIREFRAME_COLOR); |
| canvas->drawPath(fill, paint); |
| draw_points(canvas, fill, WIREFRAME_COLOR, false); |
| } |
| |
| virtual void onDrawContent(SkCanvas* canvas) { |
| SkPath path; |
| SkScalar width = fWidth; |
| |
| path.moveTo(fPts[0]); |
| path.cubicTo(fPts[1], fPts[2], fPts[3]); |
| draw_stroke(canvas, path, width); |
| |
| path.reset(); |
| path.moveTo(fPts[4]); |
| path.quadTo(fPts[5], fPts[6]); |
| draw_stroke(canvas, path, width); |
| |
| SkScalar rad = 32; |
| SkRect r; |
| r.set(&fPts[7], 2); |
| path.reset(); |
| SkRRect rr; |
| rr.setRectXY(r, rad, rad); |
| path.addRRect(rr); |
| draw_stroke(canvas, path, width); |
| |
| path.reset(); |
| SkRRect rr2; |
| rr.inset(width/2, width/2, &rr2); |
| path.addRRect(rr2, SkPath::kCCW_Direction); |
| rr.inset(-width/2, -width/2, &rr2); |
| path.addRRect(rr2, SkPath::kCW_Direction); |
| SkPaint paint; |
| paint.setAntiAlias(true); |
| paint.setColor(0x40FF8844); |
| canvas->drawPath(path, paint); |
| |
| fWidth += fDWidth; |
| if (fDWidth > 0 && fWidth > 100) { |
| fDWidth = -fDWidth; |
| } else if (fDWidth < 0 && fWidth < 10) { |
| fDWidth = -fDWidth; |
| } |
| this->inval(NULL); |
| } |
| |
| class MyClick : public Click { |
| public: |
| int fIndex; |
| MyClick(SkView* target, int index) : Click(target), fIndex(index) {} |
| }; |
| |
| virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) { |
| for (size_t i = 0; i < SK_ARRAY_COUNT(fPts); ++i) { |
| if (hittest(fPts[i], x, y)) { |
| return new MyClick(this, i); |
| } |
| } |
| return this->INHERITED::onFindClickHandler(x, y); |
| } |
| |
| virtual bool onClick(Click* click) { |
| int index = ((MyClick*)click)->fIndex; |
| fPts[index].offset(SkIntToScalar(click->fICurr.fX - click->fIPrev.fX), |
| SkIntToScalar(click->fICurr.fY - click->fIPrev.fY)); |
| this->inval(NULL); |
| return true; |
| } |
| |
| private: |
| typedef SkView INHERITED; |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| static SkView* F0() { return new RotateCirclesView; } |
| static SkViewRegister gR0(F0); |
| static SkView* F1() { return new TestCirclesView; } |
| static SkViewRegister gR1(F1); |
| static SkView* F2() { return new TestStrokeView; } |
| static SkViewRegister gR2(F2); |
| |