| /* | |
| * 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.allocN32Pixels(w, h); | |
| 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, | |
| unsigned modi) SK_OVERRIDE { | |
| for (size_t i = 0; i < SK_ARRAY_COUNT(fPts); ++i) { | |
| if (hittest(fPts[i], x, y)) { | |
| return new MyClick(this, (int)i); | |
| } | |
| } | |
| return this->INHERITED::onFindClickHandler(x, y, modi); | |
| } | |
| 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); |