| Index: samplecode/SampleClipDrawMatch.cpp
|
| diff --git a/samplecode/SampleClipDrawMatch.cpp b/samplecode/SampleClipDrawMatch.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8e2fb46dc9e7ddce4f2aec3ccb55c566e2e304be
|
| --- /dev/null
|
| +++ b/samplecode/SampleClipDrawMatch.cpp
|
| @@ -0,0 +1,249 @@
|
| +/*
|
| + * Copyright 2015 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 "SkCanvas.h"
|
| +#include "SkInterpolator.h"
|
| +#include "SkTime.h"
|
| +
|
| +// This slide tests out the match up between BW clipping and rendering. It can
|
| +// draw a large rect through some clip geometry and draw the same geometry
|
| +// normally. Which one is drawn first can be toggled. The pair of objects is translated
|
| +// fractionally (via an animator) to expose snapping bugs. The key bindings are:
|
| +// 1-9: the different geometries
|
| +// t: toggle which is drawn first the clip or the normal geometry
|
| +
|
| +// The possible geometric combinations to test
|
| +enum Geometry {
|
| + kRect_Geometry,
|
| + kRRect_Geometry,
|
| + kCircle_Geometry,
|
| + kConvexPath_Geometry,
|
| + kConcavePath_Geometry,
|
| + kRectAndRect_Geometry,
|
| + kRectAndRRect_Geometry,
|
| + kRectAndConvex_Geometry,
|
| + kRectAndConcave_Geometry
|
| +};
|
| +
|
| +// The basic rect used is [kMin,kMin]..[kMax,kMax]
|
| +static const float kMin = 100.5f;
|
| +static const float kMid = 200.0f;
|
| +static const float kMax = 299.5f;
|
| +
|
| +SkRect create_rect(const SkPoint& offset) {
|
| + SkRect r = SkRect::MakeLTRB(kMin, kMin, kMax, kMax);
|
| + r.offset(offset);
|
| + return r;
|
| +}
|
| +
|
| +SkRRect create_rrect(const SkPoint& offset) {
|
| + SkRRect rrect;
|
| + rrect.setRectXY(create_rect(offset), 10, 10);
|
| + return rrect;
|
| +}
|
| +
|
| +SkRRect create_circle(const SkPoint& offset) {
|
| + SkRRect circle;
|
| + circle.setOval(create_rect(offset));
|
| + return circle;
|
| +}
|
| +
|
| +SkPath create_convex_path(const SkPoint& offset) {
|
| + SkPath convexPath;
|
| + convexPath.moveTo(kMin, kMin);
|
| + convexPath.lineTo(kMax, kMax);
|
| + convexPath.lineTo(kMin, kMax);
|
| + convexPath.close();
|
| + convexPath.offset(offset.fX, offset.fY);
|
| + return convexPath;
|
| +}
|
| +
|
| +SkPath create_concave_path(const SkPoint& offset) {
|
| + SkPath concavePath;
|
| + concavePath.moveTo(kMin, kMin);
|
| + concavePath.lineTo(kMid, 105.0f);
|
| + concavePath.lineTo(kMax, kMin);
|
| + concavePath.lineTo(295.0f, kMid);
|
| + concavePath.lineTo(kMax, kMax);
|
| + concavePath.lineTo(kMid, 295.0f);
|
| + concavePath.lineTo(kMin, kMax);
|
| + concavePath.lineTo(105.0f, kMid);
|
| + concavePath.close();
|
| +
|
| + concavePath.offset(offset.fX, offset.fY);
|
| + return concavePath;
|
| +}
|
| +
|
| +static void draw_clipped_geom(SkCanvas* canvas, const SkPoint& offset, int geom, bool useAA) {
|
| +
|
| + int count = canvas->save();
|
| +
|
| + switch (geom) {
|
| + case kRect_Geometry:
|
| + canvas->clipRect(create_rect(offset), SkRegion::kReplace_Op, useAA);
|
| + break;
|
| + case kRRect_Geometry:
|
| + canvas->clipRRect(create_rrect(offset), SkRegion::kReplace_Op, useAA);
|
| + break;
|
| + case kCircle_Geometry:
|
| + canvas->clipRRect(create_circle(offset), SkRegion::kReplace_Op, useAA);
|
| + break;
|
| + case kConvexPath_Geometry:
|
| + canvas->clipPath(create_convex_path(offset), SkRegion::kReplace_Op, useAA);
|
| + break;
|
| + case kConcavePath_Geometry:
|
| + canvas->clipPath(create_concave_path(offset), SkRegion::kReplace_Op, useAA);
|
| + break;
|
| + case kRectAndRect_Geometry: {
|
| + SkRect r = create_rect(offset);
|
| + r.offset(-100.0f, -100.0f);
|
| + canvas->clipRect(r, SkRegion::kReplace_Op, true); // AA here forces shader clips
|
| + canvas->clipRect(create_rect(offset), SkRegion::kIntersect_Op, useAA);
|
| + } break;
|
| + case kRectAndRRect_Geometry: {
|
| + SkRect r = create_rect(offset);
|
| + r.offset(-100.0f, -100.0f);
|
| + canvas->clipRect(r, SkRegion::kReplace_Op, true); // AA here forces shader clips
|
| + canvas->clipRRect(create_rrect(offset), SkRegion::kIntersect_Op, useAA);
|
| + } break;
|
| + case kRectAndConvex_Geometry: {
|
| + SkRect r = create_rect(offset);
|
| + r.offset(-100.0f, -100.0f);
|
| + canvas->clipRect(r, SkRegion::kReplace_Op, true); // AA here forces shader clips
|
| + canvas->clipPath(create_convex_path(offset), SkRegion::kIntersect_Op, useAA);
|
| + } break;
|
| + case kRectAndConcave_Geometry: {
|
| + SkRect r = create_rect(offset);
|
| + r.offset(-100.0f, -100.0f);
|
| + canvas->clipRect(r, SkRegion::kReplace_Op, true); // AA here forces shader clips
|
| + canvas->clipPath(create_concave_path(offset), SkRegion::kIntersect_Op, useAA);
|
| + } break;
|
| + }
|
| +
|
| + SkISize size = canvas->getDeviceSize();
|
| + SkRect bigR = SkRect::MakeWH(SkIntToScalar(size.width()), SkIntToScalar(size.height()));
|
| +
|
| + SkPaint p;
|
| + p.setColor(SK_ColorRED);
|
| +
|
| + canvas->drawRect(bigR, p);
|
| + canvas->restoreToCount(count);
|
| +}
|
| +
|
| +static void draw_normal_geom(SkCanvas* canvas, const SkPoint& offset, int geom, bool useAA) {
|
| + SkPaint p;
|
| + p.setAntiAlias(useAA);
|
| + p.setColor(SK_ColorBLACK);
|
| +
|
| + switch (geom) {
|
| + case kRect_Geometry: // fall thru
|
| + case kRectAndRect_Geometry:
|
| + canvas->drawRect(create_rect(offset), p);
|
| + break;
|
| + case kRRect_Geometry: // fall thru
|
| + case kRectAndRRect_Geometry:
|
| + canvas->drawRRect(create_rrect(offset), p);
|
| + break;
|
| + case kCircle_Geometry:
|
| + canvas->drawRRect(create_circle(offset), p);
|
| + break;
|
| + case kConvexPath_Geometry: // fall thru
|
| + case kRectAndConvex_Geometry:
|
| + canvas->drawPath(create_convex_path(offset), p);
|
| + break;
|
| + case kConcavePath_Geometry: // fall thru
|
| + case kRectAndConcave_Geometry:
|
| + canvas->drawPath(create_concave_path(offset), p);
|
| + break;
|
| + }
|
| +}
|
| +
|
| +class ClipDrawMatchView : public SampleView {
|
| +public:
|
| + ClipDrawMatchView() : fTrans(2, 5), fGeom(kRect_Geometry), fClipFirst(true) {
|
| + SkScalar values[2];
|
| +
|
| + fTrans.setRepeatCount(999);
|
| + values[0] = values[1] = 0;
|
| + fTrans.setKeyFrame(0, SkTime::GetMSecs() + 1000, values);
|
| + values[1] = 1;
|
| + fTrans.setKeyFrame(1, SkTime::GetMSecs() + 2000, values);
|
| + values[0] = values[1] = 1;
|
| + fTrans.setKeyFrame(2, SkTime::GetMSecs() + 3000, values);
|
| + values[1] = 0;
|
| + fTrans.setKeyFrame(3, SkTime::GetMSecs() + 4000, values);
|
| + values[0] = 0;
|
| + fTrans.setKeyFrame(4, SkTime::GetMSecs() + 5000, values);
|
| + }
|
| +
|
| +protected:
|
| + bool onQuery(SkEvent* evt) SK_OVERRIDE {
|
| + if (SampleCode::TitleQ(*evt)) {
|
| + SampleCode::TitleR(evt, "ClipDrawMatch");
|
| + return true;
|
| + }
|
| + SkUnichar uni;
|
| + if (SampleCode::CharQ(*evt, &uni)) {
|
| + switch (uni) {
|
| + case '1': fGeom = kRect_Geometry; this->inval(NULL); return true;
|
| + case '2': fGeom = kRRect_Geometry; this->inval(NULL); return true;
|
| + case '3': fGeom = kCircle_Geometry; this->inval(NULL); return true;
|
| + case '4': fGeom = kConvexPath_Geometry; this->inval(NULL); return true;
|
| + case '5': fGeom = kConcavePath_Geometry; this->inval(NULL); return true;
|
| + case '6': fGeom = kRectAndRect_Geometry; this->inval(NULL); return true;
|
| + case '7': fGeom = kRectAndRRect_Geometry; this->inval(NULL); return true;
|
| + case '8': fGeom = kRectAndConvex_Geometry; this->inval(NULL); return true;
|
| + case '9': fGeom = kRectAndConcave_Geometry; this->inval(NULL); return true;
|
| + case 't': fClipFirst = !fClipFirst; this->inval(NULL); return true;
|
| + default: break;
|
| + }
|
| + }
|
| + return this->INHERITED::onQuery(evt);
|
| + }
|
| +
|
| + // Draw a big red rect through some clip geometry and also draw that same
|
| + // geometry in black. The order in which they are drawn can be swapped.
|
| + // This tests whether the clip and normally drawn geometry match up.
|
| + void drawGeometry(SkCanvas* canvas, const SkPoint& offset, bool useAA) {
|
| + if (fClipFirst) {
|
| + draw_clipped_geom(canvas, offset, fGeom, useAA);
|
| + }
|
| +
|
| + draw_normal_geom(canvas, offset, fGeom, useAA);
|
| +
|
| + if (!fClipFirst) {
|
| + draw_clipped_geom(canvas, offset, fGeom, useAA);
|
| + }
|
| + }
|
| +
|
| + void onDrawContent(SkCanvas* canvas) SK_OVERRIDE {
|
| + SkScalar trans[2];
|
| + fTrans.timeToValues(SkTime::GetMSecs(), trans);
|
| +
|
| + SkPoint offset;
|
| + offset.set(trans[0], trans[1]);
|
| +
|
| + int saveCount = canvas->save();
|
| + this->drawGeometry(canvas, offset, false);
|
| + canvas->restoreToCount(saveCount);
|
| +
|
| + this->inval(NULL);
|
| + }
|
| +
|
| +private:
|
| + SkInterpolator fTrans;
|
| + Geometry fGeom;
|
| + bool fClipFirst;
|
| +
|
| + typedef SampleView INHERITED;
|
| +};
|
| +
|
| +//////////////////////////////////////////////////////////////////////////////
|
| +
|
| +static SkView* MyFactory() { return new ClipDrawMatchView; }
|
| +static SkViewRegister reg(MyFactory);
|
|
|