Chromium Code Reviews| Index: samplecode/SampleBevel.cpp |
| diff --git a/samplecode/SampleBevel.cpp b/samplecode/SampleBevel.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..2655241be10f63cc3cc0a3fb0f9b93eb401fbb9e |
| --- /dev/null |
| +++ b/samplecode/SampleBevel.cpp |
| @@ -0,0 +1,283 @@ |
| +/* |
| + * 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::MakeIWH(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 |
| + |
| + int currY = kSliderHeight; |
| + |
|
robertphillips
2016/08/17 18:11:43
fuse these two lines with MakeLTRB ?
& for other
dvonbeck
2016/08/17 18:28:40
I feel like it is easier to read if I put it in 2
egdaniel
2016/08/17 18:34:12
There is a MakeXYWH which I think is the best opti
dvonbeck
2016/08/17 18:49:53
Done.
|
| + fCtrlRangeRects[0] = SkRect::MakeIWH(kCtrlRange + kSliderWidth, kSliderHeight); |
| + fCtrlRangeRects[0].offset(0, SkIntToScalar(currY)); |
| + fWidthCtrlRect = SkRect::MakeIWH(kSliderWidth, kSliderHeight); |
| + fWidthCtrlRect.offset(0.3*kCtrlRange, SkIntToScalar(currY)); |
| + fBevelWidth = 0.3*kBevelWidthMax; |
| + currY += 2 * kSliderHeight; |
| + |
| + fCtrlRangeRects[1] = SkRect::MakeIWH(kCtrlRange + kSliderWidth, kSliderHeight); |
| + fCtrlRangeRects[1].offset(0, SkIntToScalar(currY)); |
| + fHeightCtrlRect = SkRect::MakeIWH(kSliderWidth, kSliderHeight); |
| + fHeightCtrlRect.offset(0.3*kCtrlRange, SkIntToScalar(currY)); |
| + fBevelHeight = 0.3*kBevelHeightMax; |
| + currY += 2 * kSliderHeight; |
| + |
| + fCtrlRangeRects[2] = SkRect::MakeIWH(kCtrlRange + kSliderWidth, kSliderHeight); |
| + fCtrlRangeRects[2].offset(0, SkIntToScalar(currY)); |
| + fTypeCtrlRect = SkRect::MakeIWH(kSliderWidth, kSliderHeight); |
| + fTypeCtrlRect.offset((1.0f/6.0f)*kCtrlRange, SkIntToScalar(currY)); |
| + fBevelType = (SkNormalSource::BevelType) 0; |
| + currY += 2 * kSliderHeight; |
| + |
| + fSelectedCtrlRect = nullptr; |
| + } |
| + |
| +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; |
| + |
| + sk_sp<SkNormalSource> normalSource = SkNormalSource::MakeBevel(fBevelType, fBevelWidth, |
| + fBevelHeight); |
| + |
| + paint.setShader(SkLightingShader::Make(nullptr, std::move(normalSource), 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 { |
| + // 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(sk_tool_utils::create_portable_typeface("sans-serif", |
| + SkFontStyle())); |
| + 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); |
| + |
| + // Draw shapes |
| + SkScalar xPos = kCtrlRange + 25; |
| + 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; |
| + } |
| + } |
| + |
| + // Control modification |
| + if (nullptr != fSelectedCtrlRect) { |
| + fSelectedCtrlRect->offsetTo(SkScalarPin(x, 0.0f, kCtrlRange), fSelectedCtrlRect->fTop); |
| + |
| + fBevelHeight = (fHeightCtrlRect.fLeft / kCtrlRange) * kBevelHeightMax; |
| + fBevelWidth = (fWidthCtrlRect.fLeft / kCtrlRange) * kBevelWidthMax; |
| + fBevelType = (SkNormalSource::BevelType)SkTMin( |
| + SkScalarFloorToInt(3.0f * fTypeCtrlRect.fLeft / kCtrlRange), |
| + 2); |
| + |
| + // Snap type controls to 3 positions |
| + fTypeCtrlRect.offsetTo(kCtrlRange * ( ((int)fBevelType)/3.0f + 1.0f/6.0f ), |
| + fTypeCtrlRect.fTop); |
| + |
| + // Ensuring width is non-zero |
| + fBevelWidth = SkMaxScalar(1.0f, fBevelWidth); |
| + |
| + this->inval(nullptr); |
| + return true; |
| + } |
| + |
| + // Moving light |
| + if (nullptr == fSelectedCtrlRect) { |
| + 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 int kAppWidth = 400; |
| + static constexpr int kAppHeight = 400; |
| + static constexpr int kShapeBoundsSize = 120; |
| + |
| + static constexpr int kCtrlRange = 150; |
| + static constexpr int kBevelWidthMax = 50; |
| + static constexpr int kBevelHeightMax = 50; |
| + |
| + static constexpr int kSliderHeight = 20; |
| + static constexpr int kSliderWidth = 10; |
| + |
| + 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<SkLights> fLights; |
| + SkLights::Light fRedLight; |
| + SkLights::Light fBlueLight; |
| + |
| + typedef SampleView INHERITED; |
| +}; |
| + |
| +////////////////////////////////////////////////////////////////////////////// |
| + |
| +static SkView* MyFactory() { return new BevelView; } |
| +static SkViewRegister reg(MyFactory); |
| + |