123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- /*
- * 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 "include/core/SkCanvas.h"
- #include "include/core/SkPath.h"
- #include "include/core/SkRRect.h"
- #include "include/core/SkTime.h"
- #include "include/utils/SkInterpolator.h"
- #include "samplecode/Sample.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
- // f: flip-flops which corner the bottom AA clip rect occupies in the complex clip cases
- // 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;
- // The translation applied to the base AA rect in the combination cases
- // (i.e., kRectAndRect through kRectAndConcave)
- static const float kXlate = 100.0f;
- 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_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 Sample {
- SkInterpolator fTrans;
- Geometry fGeom;
- bool fClipFirst = true;
- int fSign = 1;
- const double fStart = SkTime::GetMSecs();
- public:
- ClipDrawMatchView() : fTrans(2, 5), fGeom(kRect_Geometry) {}
- private:
- void onOnceBeforeDraw() override {
- SkScalar values[2];
- fTrans.setRepeatCount(999);
- values[0] = values[1] = 0;
- fTrans.setKeyFrame(0, GetMSecs() + 1000, values);
- values[1] = 1;
- fTrans.setKeyFrame(1, GetMSecs() + 2000, values);
- values[0] = values[1] = 1;
- fTrans.setKeyFrame(2, GetMSecs() + 3000, values);
- values[1] = 0;
- fTrans.setKeyFrame(3, GetMSecs() + 4000, values);
- values[0] = 0;
- fTrans.setKeyFrame(4, GetMSecs() + 5000, values);
- }
- SkString name() override { return SkString("ClipDrawMatch"); }
- bool onChar(SkUnichar uni) override {
- switch (uni) {
- case '1': fGeom = kRect_Geometry; return true;
- case '2': fGeom = kRRect_Geometry; return true;
- case '3': fGeom = kCircle_Geometry; return true;
- case '4': fGeom = kConvexPath_Geometry; return true;
- case '5': fGeom = kConcavePath_Geometry; return true;
- case '6': fGeom = kRectAndRect_Geometry; return true;
- case '7': fGeom = kRectAndRRect_Geometry; return true;
- case '8': fGeom = kRectAndConvex_Geometry; return true;
- case '9': fGeom = kRectAndConcave_Geometry; return true;
- case 'f': fSign = -fSign; return true;
- case 't': fClipFirst = !fClipFirst; return true;
- default: break;
- }
- return false;
- }
- void drawClippedGeom(SkCanvas* canvas, const SkPoint& offset, bool useAA) {
- int count = canvas->save();
- switch (fGeom) {
- case kRect_Geometry:
- canvas->clipRect(create_rect(offset), useAA);
- break;
- case kRRect_Geometry:
- canvas->clipRRect(create_rrect(offset), useAA);
- break;
- case kCircle_Geometry:
- canvas->clipRRect(create_circle(offset), useAA);
- break;
- case kConvexPath_Geometry:
- canvas->clipPath(create_convex_path(offset), useAA);
- break;
- case kConcavePath_Geometry:
- canvas->clipPath(create_concave_path(offset), useAA);
- break;
- case kRectAndRect_Geometry: {
- SkRect r = create_rect(offset);
- r.offset(fSign * kXlate, fSign * kXlate);
- canvas->clipRect(r, true); // AA here forces shader clips
- canvas->clipRect(create_rect(offset), useAA);
- } break;
- case kRectAndRRect_Geometry: {
- SkRect r = create_rect(offset);
- r.offset(fSign * kXlate, fSign * kXlate);
- canvas->clipRect(r, true); // AA here forces shader clips
- canvas->clipRRect(create_rrect(offset), useAA);
- } break;
- case kRectAndConvex_Geometry: {
- SkRect r = create_rect(offset);
- r.offset(fSign * kXlate, fSign * kXlate);
- canvas->clipRect(r, true); // AA here forces shader clips
- canvas->clipPath(create_convex_path(offset), useAA);
- } break;
- case kRectAndConcave_Geometry: {
- SkRect r = create_rect(offset);
- r.offset(fSign * kXlate, fSign * kXlate);
- canvas->clipRect(r, true); // AA here forces shader clips
- canvas->clipPath(create_concave_path(offset), useAA);
- } break;
- }
- SkISize size = canvas->getBaseLayerSize();
- SkRect bigR = SkRect::MakeWH(SkIntToScalar(size.width()), SkIntToScalar(size.height()));
- SkPaint p;
- p.setColor(SK_ColorRED);
- canvas->drawRect(bigR, p);
- canvas->restoreToCount(count);
- }
- // 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) {
- this->drawClippedGeom(canvas, offset, useAA);
- }
- draw_normal_geom(canvas, offset, fGeom, useAA);
- if (!fClipFirst) {
- this->drawClippedGeom(canvas, offset, useAA);
- }
- }
- void onDrawContent(SkCanvas* canvas) override {
- SkScalar trans[2];
- fTrans.timeToValues(GetMSecs(), trans);
- SkPoint offset;
- offset.set(trans[0], trans[1]);
- int saveCount = canvas->save();
- this->drawGeometry(canvas, offset, false);
- canvas->restoreToCount(saveCount);
- }
- SkMSec GetMSecs() const {
- return static_cast<SkMSec>(SkTime::GetMSecs() - fStart);
- }
- };
- DEF_SAMPLE( return new ClipDrawMatchView(); )
|