Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(100)

Unified Diff: samplecode/SampleBevel.cpp

Issue 2246243002: Interactive Bevel Sample App (Closed) Base URL: https://skia.googlesource.com/skia@master
Patch Set: Addressed patch set 7 comments Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gyp/samples.gypi ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: samplecode/SampleBevel.cpp
diff --git a/samplecode/SampleBevel.cpp b/samplecode/SampleBevel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..868ce35244288fa99b9c76c4ff0c75705650c173
--- /dev/null
+++ b/samplecode/SampleBevel.cpp
@@ -0,0 +1,306 @@
+/*
+ * Copyright 2016 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 "SkLightingShader.h"
+#include "SkNormalSource.h"
+#include "sk_tool_utils.h"
+
+
+class BevelView : public SampleView {
+public:
+ BevelView()
+ : fShapeBounds(SkRect::MakeWH(kShapeBoundsSize, kShapeBoundsSize))
+ , fRedLight(SkLights::Light::MakeDirectional(SkColor3f::Make(0.6f, 0.45f, 0.3f),
+ SkVector3::Make(0.0f, -5.0f, 1.0f)))
+ , fBlueLight(SkLights::Light::MakeDirectional(SkColor3f::Make(0.3f, 0.45f, 0.6f),
+ SkVector3::Make(0.0f, 5.0f, 1.0f))) {
+ this->setBGColor(0xFF666868); // Slightly colorized gray for contrast
+
+ // Lights
+ SkLights::Builder builder;
+ builder.add(fRedLight);
+ builder.add(fBlueLight);
+ builder.add(SkLights::Light::MakeAmbient(SkColor3f::Make(0.4f, 0.4f, 0.4f)));
+ fLights = builder.finish();
+
+ // Controls
+
+ SkScalar currY = kSliderHeight;
+
+ const SkScalar kWidthCtrlInitialPos = 0.2f;
+ fCtrlRangeRects[0] = SkRect::MakeXYWH(0.0f, currY,
+ kCtrlRange + kSliderWidth,
+ kSliderHeight);
+ fWidthCtrlRect = SkRect::MakeXYWH(kWidthCtrlInitialPos * kCtrlRange, currY,
+ kSliderWidth, kSliderHeight);
+ fBevelWidth = kBevelWidthMax * kWidthCtrlInitialPos;
+ currY += 2 * kSliderHeight;
+
+ const SkScalar kHeightCtrlInitialPos = 0.75f;
+ fCtrlRangeRects[1] = SkRect::MakeXYWH(0.0f, currY,
+ kCtrlRange + kSliderWidth,
+ kSliderHeight);
+ fHeightCtrlRect = SkRect::MakeXYWH(kHeightCtrlInitialPos * kCtrlRange, currY,
+ kSliderWidth, kSliderHeight);
+ // Mapping from (0, 1) to (-1, 1)
+ fBevelHeight = kBevelHeightMax * (kHeightCtrlInitialPos * 2.0f - 1.0f);
+ currY += 2 * kSliderHeight;
+
+ const SkScalar kTypeCtrlInitialPos = 1.0f / (2.0f * kBevelTypeCount);
+ fCtrlRangeRects[2] = SkRect::MakeXYWH(0.0f, currY,
+ kCtrlRange + kSliderWidth,
+ kSliderHeight);
+ fTypeCtrlRect = SkRect::MakeXYWH(kTypeCtrlInitialPos * kCtrlRange, currY,
+ kSliderWidth, kSliderHeight);
+ fBevelType = (SkNormalSource::BevelType) SkScalarFloorToInt(kTypeCtrlInitialPos);
+ currY += 2 * kSliderHeight;
+
+ fSelectedCtrlRect = nullptr;
+ fDirtyNormalSource = true;
+
+ fLabelTypeface = sk_tool_utils::create_portable_typeface("sans-serif", SkFontStyle());
+ }
+
+protected:
+ bool onQuery(SkEvent *evt) override {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "Bevel");
+ return true;
+ }
+
+ return this->INHERITED::onQuery(evt);
+ }
+
+ enum Shape {
+ kCircle_Shape,
+ kRect_Shape,
+ };
+ void drawShape(enum Shape shape, SkCanvas* canvas) {
+ canvas->save();
+
+ SkPaint paint;
+
+ if (fDirtyNormalSource) {
+ fNormalSource = SkNormalSource::MakeBevel(fBevelType, fBevelWidth, fBevelHeight);
+ fDirtyNormalSource = false;
+ }
+
+ paint.setShader(SkLightingShader::Make(nullptr, fNormalSource, fLights));
+ paint.setAntiAlias(true);
+ paint.setColor(0xFFDDDDDD);
+ switch (shape) {
+ case kCircle_Shape:
+ canvas->drawCircle(fShapeBounds.centerX(), fShapeBounds.centerY(),
+ fShapeBounds.width()/2.0f, paint);
+ break;
+ case kRect_Shape:
+ canvas->drawRect(fShapeBounds, paint);
+ break;
+ default:
+ SkDEBUGFAIL("Invalid shape enum for drawShape");
+ }
+
+ canvas->restore();
+ }
+
+ void onDrawContent(SkCanvas *canvas) override {
+
+ canvas->save();
+ canvas->resetMatrix(); // Force static controls and labels
+
+ // Draw controls
+
+ SkPaint ctrlRectPaint;
+ ctrlRectPaint.setColor(0xFFF3F3F3);
+ canvas->drawRect(fWidthCtrlRect, ctrlRectPaint);
+ canvas->drawRect(fHeightCtrlRect, ctrlRectPaint);
+ canvas->drawRect(fTypeCtrlRect, ctrlRectPaint);
+
+ SkPaint ctrlRectRangePaint;
+ ctrlRectRangePaint.setColor(0xFFFFFFFF);
+ ctrlRectRangePaint.setStyle(SkPaint::kStroke_Style);
+ ctrlRectRangePaint.setStrokeWidth(2.0f);
+
+ for (size_t i = 0; i < kNumControls; i++) {
+ canvas->drawRect(fCtrlRangeRects[i], ctrlRectRangePaint);
+ }
+
+ // Draw labels
+ constexpr SkScalar kTextSize = 12.0f;
+ SkString widthLabel, heightLabel, typeLabel;
+ SkPaint labelPaint;
+ labelPaint.setTypeface(fLabelTypeface);
+ labelPaint.setAntiAlias(true);
+ labelPaint.setColor(0xFFFFFFFF);
+ labelPaint.setTextSize(kTextSize);
+
+ widthLabel.appendf("BevelWidth: %f", fBevelWidth);
+ heightLabel.appendf("BevelHeight: %f", fBevelHeight);
+ typeLabel.append("BevelType: ");
+
+ switch (fBevelType) {
+ case SkNormalSource::BevelType::kLinear:
+ typeLabel.append("Linear");
+ break;
+ case SkNormalSource::BevelType::kRoundedIn:
+ typeLabel.append("RoundedIn");
+ break;
+ case SkNormalSource::BevelType::kRoundedOut:
+ typeLabel.append("RoundedOut");
+ break;
+ }
+
+ canvas->drawText(widthLabel.c_str(), widthLabel.size(), 0,
+ fWidthCtrlRect.fTop - kTextSize/2.0f, labelPaint);
+ canvas->drawText(heightLabel.c_str(), heightLabel.size(), 0,
+ fHeightCtrlRect.fTop - kTextSize/2.0f, labelPaint);
+ canvas->drawText(typeLabel.c_str(), typeLabel.size(), 0,
+ fTypeCtrlRect.fTop - kTextSize/2.0f, labelPaint);
+
+ canvas->restore(); // Return to modified matrix when drawing shapes
+
+ // Draw shapes
+ SkScalar xPos = kCtrlRange + 25.0f;
+ SkScalar yPos = fShapeBounds.height();
+ for (Shape shape : { kCircle_Shape, kRect_Shape }) {
+ canvas->save();
+ canvas->translate(xPos, yPos);
+ this->drawShape(shape, canvas);
+ canvas->restore();
+
+ xPos += 1.2f * fShapeBounds.width();
+ }
+ }
+
+ SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
+ return new SkView::Click(this);
+ }
+
+ bool onClick(Click *click) override {
+ SkScalar x = click->fCurr.fX;
+ SkScalar y = click->fCurr.fY;
+
+ SkScalar dx = x - click->fPrev.fX;
+ SkScalar dy = y - click->fPrev.fY;
+
+ // Control deselection
+ if (Click::State::kUp_State == click->fState) {
+ fSelectedCtrlRect = nullptr;
+ return true;
+ }
+
+ // Control selection
+ if (nullptr == fSelectedCtrlRect && Click::State::kDown_State == click->fState) {
+ if (fWidthCtrlRect.contains(SkRect::MakeXYWH(x, y, 1, 1))) {
+ fSelectedCtrlRect = &fWidthCtrlRect;
+ } else if (fHeightCtrlRect.contains(SkRect::MakeXYWH(x, y, 1, 1))) {
+ fSelectedCtrlRect = &fHeightCtrlRect;
+ } else if (fTypeCtrlRect.contains(SkRect::MakeXYWH(x, y, 1, 1))) {
+ fSelectedCtrlRect = &fTypeCtrlRect;
+ }
+ }
+
+ if (nullptr != fSelectedCtrlRect) { // Control modification
+ fSelectedCtrlRect->offsetTo(SkScalarPin(x, 0.0f, kCtrlRange), fSelectedCtrlRect->fTop);
+
+ fBevelHeight = (fHeightCtrlRect.fLeft / kCtrlRange) * kBevelHeightMax * 2.0f
+ - kBevelHeightMax;
+ fBevelWidth = (fWidthCtrlRect.fLeft / kCtrlRange) * kBevelWidthMax;
+ fBevelType = (SkNormalSource::BevelType)SkTMin(
+ SkScalarFloorToInt(kBevelTypeCount * fTypeCtrlRect.fLeft / kCtrlRange),
+ kBevelTypeCount - 1);
+
+ // Snap type controls to 3 positions
+ fTypeCtrlRect.offsetTo(kCtrlRange * ( ((int)fBevelType)/SkIntToScalar(kBevelTypeCount)
+ + 1.0f/(2.0f * kBevelTypeCount) ),
+ fTypeCtrlRect.fTop);
+
+ // Ensuring width is non-zero
+ fBevelWidth = SkMaxScalar(1.0f, fBevelWidth);
+
+ fDirtyNormalSource = true;
+
+ this->inval(nullptr);
+ return true;
+ } else { // Moving light
+ if (dx != 0 || dy != 0) {
+ float recipX = 1.0f / kAppWidth;
+ float recipY = 1.0f / kAppHeight;
+
+ if (0 == click->fModifierKeys) { // No modifier
+ fBlueLight = SkLights::Light::MakeDirectional(fBlueLight.color(),
+ SkVector3::Make((kAppWidth/2.0f - x) * recipX * -3.0f,
+ (kAppHeight/2.0f - y) * recipY * -3.0f,
+ 1.0f));
+ } else if (1 == click->fModifierKeys) { // Shift key
+ fRedLight = SkLights::Light::MakeDirectional(fRedLight.color(),
+ SkVector3::Make((kAppWidth/2.0f - x) * recipX * -3.0f,
+ (kAppHeight/2.0f - y) * recipY * -3.0f,
+ 1.0f));
+ }
+
+ SkLights::Builder builder;
+ builder.add(fRedLight);
+ builder.add(fBlueLight);
+ builder.add(SkLights::Light::MakeAmbient(
+ SkColor3f::Make(0.4f, 0.4f, 0.4f)));
+ fLights = builder.finish();
+
+ this->inval(nullptr);
+ }
+ return true;
+ }
+
+ return true;
+ }
+
+private:
+ static constexpr int kNumTestRects = 3;
+
+ static constexpr SkScalar kAppWidth = 400.0f;
+ static constexpr SkScalar kAppHeight = 400.0f;
+ static constexpr SkScalar kShapeBoundsSize = 120.0f;
+
+ static constexpr SkScalar kCtrlRange = 150.0f;
+ static constexpr SkScalar kBevelWidthMax = kShapeBoundsSize;
+ static constexpr SkScalar kBevelHeightMax = 50.0f;
+ static constexpr int kBevelTypeCount = 3;
+
+ static constexpr SkScalar kSliderHeight = 20.0f;
+ static constexpr SkScalar kSliderWidth = 10.0f;
+
+ const SkRect fShapeBounds;
+
+ static constexpr int kNumControls = 3;
+ SkRect fCtrlRangeRects[kNumControls];
+ SkRect* fSelectedCtrlRect;
+ SkRect fWidthCtrlRect;
+ SkRect fHeightCtrlRect;
+ SkRect fTypeCtrlRect;
+
+ SkScalar fBevelWidth;
+ SkScalar fBevelHeight;
+ SkNormalSource::BevelType fBevelType;
+ sk_sp<SkNormalSource> fNormalSource;
+ bool fDirtyNormalSource;
+
+ sk_sp<SkLights> fLights;
+ SkLights::Light fRedLight;
+ SkLights::Light fBlueLight;
+
+ sk_sp<SkTypeface> fLabelTypeface;
+
+ typedef SampleView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new BevelView; }
+static SkViewRegister reg(MyFactory);
+
« no previous file with comments | « gyp/samples.gypi ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698