OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SampleCode.h" | 8 #include "SampleCode.h" |
9 #include "SkCanvas.h" | 9 #include "SkCanvas.h" |
10 #include "SkLightingShader.h" | 10 #include "SkLightingShader.h" |
11 #include "SkNormalSource.h" | 11 #include "SkNormalSource.h" |
12 #include "sk_tool_utils.h" | 12 #include "sk_tool_utils.h" |
13 | 13 |
| 14 class ParentControl; |
| 15 |
| 16 // Abstract base class for all components that a control panel must have |
| 17 class Control : public SkRefCnt { |
| 18 public: |
| 19 Control(SkString name) |
| 20 : fName(name) |
| 21 , fParent(nullptr) |
| 22 , fRelativePos(SkPoint::Make(0.0f, 0.0f)) {} |
| 23 |
| 24 // Use this to propagate a click's position down to a control. Gets modulate
d by the component's |
| 25 // relative position |
| 26 bool click(const SkPoint& clickPos) { |
| 27 SkPoint relativeClickPos = SkPoint::Make(clickPos.fX - fRelativePos.fX, |
| 28 clickPos.fY - fRelativePos.fY); |
| 29 return this->onClick(relativeClickPos); |
| 30 } |
| 31 |
| 32 // Use this to draw the control and its appropriate children. Gets modulated
by the component's |
| 33 // relative position. |
| 34 void drawContent(SkCanvas *canvas) { |
| 35 canvas->save(); |
| 36 canvas->translate(fRelativePos.fX, fRelativePos.fY); |
| 37 this->onDrawContent(canvas); |
| 38 canvas->restore(); |
| 39 } |
| 40 |
| 41 /* Returns true when click position argumend lands over a control region in
this control. Click |
| 42 * position gets modulated by the component's relative position. |
| 43 * |
| 44 * @param click The position of the click in the coordinate space relative t
o the parent |
| 45 */ |
| 46 bool isInCtrlRegion(const SkPoint& click) { |
| 47 SkPoint relativeClickPos = SkPoint::Make(click.fX - fRelativePos.fX, |
| 48 click.fY - fRelativePos.fY); |
| 49 return this->onIsInCtrlRegion(relativeClickPos); |
| 50 } |
| 51 |
| 52 // Returns height of content drawn |
| 53 virtual SkScalar height() const = 0; |
| 54 |
| 55 // Sets the parent of this component. May only be used once. Height must rem
ain constant after |
| 56 // parent is set. |
| 57 void setParent(ParentControl *parent, const SkPoint& relativePos) { |
| 58 SkASSERT(parent); |
| 59 SkASSERT(!fParent); // No chidren transfer since relativeY would get inv
alid for younger kid |
| 60 |
| 61 fParent = parent; |
| 62 fRelativePos = relativePos; |
| 63 this->onSetParent(); |
| 64 } |
| 65 |
| 66 // Overriden by sub-classes that need to recompute fields after parent is se
t. Called after |
| 67 // setting fParent. |
| 68 virtual void onSetParent() {} |
| 69 |
| 70 // Overriden by sub-classes that need to know when a click is released. |
| 71 virtual void onClickRelease() {} |
| 72 |
| 73 protected: |
| 74 |
| 75 // Draws a label for the component, using its name and a passed value. Does
NOT modulate by |
| 76 // relative height, expects CTM to have been adjusted in advance. |
| 77 void drawLabel(SkCanvas *canvas, const SkString& valueStr) const { |
| 78 // TODO Cache this |
| 79 sk_sp<SkTypeface> fLabelTypeface = |
| 80 sk_tool_utils::create_portable_typeface("sans-serif", SkFontStyl
e()); |
| 81 |
| 82 SkString label; |
| 83 label.append(fName); |
| 84 label.append(": "); |
| 85 label.append(valueStr); |
| 86 |
| 87 SkPaint labelPaint; |
| 88 labelPaint.setTypeface(fLabelTypeface); |
| 89 labelPaint.setAntiAlias(true); |
| 90 labelPaint.setColor(0xFFFFFFFF); |
| 91 labelPaint.setTextSize(12.0f); |
| 92 |
| 93 canvas->drawText(label.c_str(), label.size(), 0, kLabelHeight - 6.0f, la
belPaint); |
| 94 } |
| 95 |
| 96 SkString fName; |
| 97 ParentControl* fParent; |
| 98 |
| 99 static constexpr SkScalar kLabelHeight = 20.0f; |
| 100 |
| 101 private: |
| 102 // Overriden by sub-class to draw component. Do not call directly, drawConte
nt() modulates by |
| 103 // relative position. |
| 104 virtual void onDrawContent(SkCanvas *canvas) = 0; |
| 105 |
| 106 // Overriden by sub-class to handle clicks. Do not call directly, click() mo
dulates by relative |
| 107 // position. Return true if holding mouse capture |
| 108 virtual bool onClick(const SkPoint& clickPos) { return false; }; |
| 109 |
| 110 // Overriden by sub-classes with controls. Should return true if clickPos la
nds inside a control |
| 111 // region, to enable mouse caputre. |
| 112 virtual bool onIsInCtrlRegion(const SkPoint& clickPos) const { return false;
}; |
| 113 |
| 114 // The position of the control relative to it's parent |
| 115 SkPoint fRelativePos; |
| 116 }; |
| 117 |
| 118 class ParentControl : public Control { // Interface for all controls that have c
hildren |
| 119 public: |
| 120 ParentControl(const SkString& name) : INHERITED(name) {} |
| 121 |
| 122 // Adds a child |
| 123 virtual void add(sk_sp<Control> control) = 0; |
| 124 |
| 125 // Returns the control's width. Used to propagate width down to components t
hat don't specify it |
| 126 virtual SkScalar width() const = 0; |
| 127 |
| 128 private: |
| 129 typedef Control INHERITED; |
| 130 }; |
| 131 |
| 132 class ControlPanel : public ParentControl { |
| 133 public: |
| 134 |
| 135 ControlPanel(SkScalar width) |
| 136 : ParentControl(SkString("ControlPanel")) |
| 137 , fWidth(width) |
| 138 , fHeight(0.0f) |
| 139 , fSelectedControl(-1) {} |
| 140 |
| 141 // Width unspecified, expectation is inheritance from parent |
| 142 ControlPanel() : ControlPanel(-1.0f) {} |
| 143 |
| 144 // Use this for introducing clicks on a ControlPanel from outside of the fra
mework. It |
| 145 // propagates click release or position down the chain. Returns false when c
lick capture is |
| 146 // being released. |
| 147 bool inClick(SkView::Click *inClick) { |
| 148 if (SkView::Click::State::kUp_State == inClick->fState) { |
| 149 this->onClickRelease(); |
| 150 return false; |
| 151 } |
| 152 return this->click(inClick->fCurr); |
| 153 } |
| 154 |
| 155 // Add children |
| 156 void add(sk_sp<Control> control) override { |
| 157 SkASSERT(!fParent); // Validity of parent's relativeY and fHeight depend
s on immutability |
| 158 fControls.push_back(control); |
| 159 control->setParent(this, SkPoint::Make(0.0f, fHeight)); |
| 160 fHeight += control->height(); |
| 161 } |
| 162 |
| 163 SkScalar width() const override { |
| 164 return fParent ? fParent->width() : fWidth; // Width inherited from pare
nt if there is one |
| 165 } |
| 166 |
| 167 SkScalar height() const override { |
| 168 return fHeight; |
| 169 } |
| 170 |
| 171 // Propagate click release to selected control, deselect control |
| 172 void onClickRelease() override { |
| 173 if (fSelectedControl >= 0) { |
| 174 fControls[fSelectedControl]->onClickRelease(); |
| 175 } |
| 176 fSelectedControl = -1; |
| 177 } |
| 178 |
| 179 // Propagate onSetParent() down to children, some might need fParent->width(
) refresh |
| 180 void onSetParent() override { |
| 181 for (int i = 0; i < fControls.count(); i++) { |
| 182 fControls[i]->onSetParent(); |
| 183 } |
| 184 } |
| 185 |
| 186 // Holds a vertical shelf of controls. Can't be hierarchy root if not given
a width value. |
| 187 static sk_sp<ParentControl> Make() { |
| 188 return sk_sp<ParentControl>(new ControlPanel()); |
| 189 } |
| 190 |
| 191 // Holds a vertical shelf of controls. Only control that can be hooked from
outside the |
| 192 // framework. |
| 193 static sk_sp<ParentControl> Make(SkScalar width) { |
| 194 return sk_sp<ParentControl>(new ControlPanel(width)); |
| 195 } |
| 196 |
| 197 protected: |
| 198 // Returns true if control panel has mouse captured, false when it is ready
to release |
| 199 // capture |
| 200 bool onClick(const SkPoint& click) override { |
| 201 |
| 202 if (fSelectedControl == -1) { // If no child control selected, check eve
ry child |
| 203 for (int i = 0; i < fControls.count(); i++) { |
| 204 if (fControls[i]->isInCtrlRegion(click)) { |
| 205 fSelectedControl = i; |
| 206 break; |
| 207 } |
| 208 } |
| 209 } |
| 210 |
| 211 if (fSelectedControl >= 0) { // If child control selected, propagate cli
ck |
| 212 bool keepSelection = fControls[fSelectedControl]->click(click); |
| 213 if (!keepSelection) { |
| 214 fSelectedControl = -1; |
| 215 } |
| 216 return keepSelection; |
| 217 } |
| 218 |
| 219 return false; |
| 220 } |
| 221 |
| 222 // Draw all children |
| 223 void onDrawContent(SkCanvas* canvas) override { |
| 224 canvas->save(); |
| 225 for (int i = 0; i < fControls.count(); i++) { |
| 226 fControls[i]->drawContent(canvas); |
| 227 } |
| 228 canvas->restore(); |
| 229 } |
| 230 |
| 231 // Check all children's control regions |
| 232 bool onIsInCtrlRegion(const SkPoint& clickPos) const override { |
| 233 for (int i = 0; i < fControls.count(); i++) { |
| 234 if (fControls[i]->isInCtrlRegion(clickPos)) { |
| 235 return true; |
| 236 } |
| 237 } |
| 238 |
| 239 return false; |
| 240 } |
| 241 |
| 242 private: |
| 243 SkScalar fWidth; |
| 244 SkScalar fHeight; |
| 245 |
| 246 SkTArray<sk_sp<Control>> fControls; |
| 247 int fSelectedControl; |
| 248 }; |
| 249 |
| 250 class DiscreteSliderControl : public Control { |
| 251 public: |
| 252 SkScalar height() const override { |
| 253 return 2.0f * kLabelHeight; |
| 254 } |
| 255 |
| 256 // Set width-dependant variables when new parent is set |
| 257 void onSetParent() override { |
| 258 fCtrlRegion = SkRect::MakeXYWH(0.0f, kLabelHeight, fParent->width(), kSl
iderHeight); |
| 259 fSliderRange = fParent->width() - kSliderWidth; |
| 260 } |
| 261 |
| 262 /* Make a slider for an integer value. Snaps to discrete positions. |
| 263 * |
| 264 * @params name The name of the control, displayed in the label |
| 265 * @params output Pointer to the integer that will be set by the slider |
| 266 * @params min Min value for output. |
| 267 * @params max Max value for output. |
| 268 */ |
| 269 static sk_sp<Control> Make(SkString name, int* output, int min, int max) { |
| 270 return sk_sp<Control>(new DiscreteSliderControl(name, output, min, max))
; |
| 271 } |
| 272 |
| 273 protected: |
| 274 void onDrawContent(SkCanvas* canvas) override { |
| 275 SkASSERT(fParent); |
| 276 int numChoices = fMax - fMin + 1; |
| 277 fSlider.offsetTo(fSliderRange * ( (*fOutput)/SkIntToScalar(numChoices) |
| 278 + 1.0f/(2.0f * numChoices) ), |
| 279 fSlider.fTop); |
| 280 |
| 281 SkString valueStr; |
| 282 valueStr.appendS32(*fOutput); |
| 283 this->drawLabel(canvas, valueStr); |
| 284 |
| 285 SkPaint sliderPaint; |
| 286 sliderPaint.setColor(0xFFF3F3F3); |
| 287 canvas->drawRect(fSlider, sliderPaint); |
| 288 |
| 289 SkPaint ctrlRegionPaint; |
| 290 ctrlRegionPaint.setColor(0xFFFFFFFF); |
| 291 ctrlRegionPaint.setStyle(SkPaint::kStroke_Style); |
| 292 ctrlRegionPaint.setStrokeWidth(2.0f); |
| 293 canvas->drawRect(fCtrlRegion, ctrlRegionPaint); |
| 294 } |
| 295 |
| 296 bool onClick(const SkPoint& clickPos) override { |
| 297 SkASSERT(fParent); |
| 298 SkScalar x = SkScalarPin(clickPos.fX, 0.0f, fSliderRange); |
| 299 int numChoices = fMax - fMin + 1; |
| 300 *fOutput = SkTMin(SkScalarFloorToInt(numChoices * x / fSliderRange) + fM
in, fMax); |
| 301 |
| 302 return true; |
| 303 } |
| 304 |
| 305 bool onIsInCtrlRegion(const SkPoint& clickPos) const override { |
| 306 SkASSERT(fParent); |
| 307 return fCtrlRegion.contains(SkRect::MakeXYWH(clickPos.fX, clickPos.fY, 1
, 1)); |
| 308 } |
| 309 |
| 310 private: |
| 311 DiscreteSliderControl(SkString name, int* output, int min, int max) |
| 312 : INHERITED(name) |
| 313 , fOutput(output) |
| 314 , fMin(min) |
| 315 , fMax(max) { |
| 316 fSlider = SkRect::MakeXYWH(0, kLabelHeight, kSliderWidth, kSliderHeight)
; |
| 317 } |
| 318 |
| 319 int* fOutput; |
| 320 int fMin; |
| 321 int fMax; |
| 322 SkRect fSlider; // The rectangle that slides |
| 323 // The region in which the rectangle slides. Also the region in which mouse
is caputred |
| 324 SkRect fCtrlRegion; |
| 325 SkScalar fSliderRange; // The width in pixels over which the slider can slid
e |
| 326 |
| 327 static constexpr SkScalar kSliderHeight = 20.0f; |
| 328 static constexpr SkScalar kSliderWidth = 10.0f; |
| 329 |
| 330 typedef Control INHERITED; |
| 331 }; |
| 332 |
| 333 class ControlSwitcher : public ParentControl { |
| 334 public: |
| 335 // Add children |
| 336 void add(sk_sp<Control> control) override { |
| 337 SkASSERT(!fParent); // Validity of parent's relativeY and fHeight depend
s on immutability |
| 338 fControls.push_back(control); |
| 339 control->setParent(this, SkPoint::Make(0.0f, kSelectorHeight)); |
| 340 fHeight = SkMaxScalar(fHeight, control->height()); // Setting height to
max child height. |
| 341 } |
| 342 |
| 343 SkScalar width() const override { return fParent ? (fParent->width()) : 0; } |
| 344 |
| 345 SkScalar height() const override { |
| 346 return fHeight; |
| 347 } |
| 348 |
| 349 // Propagate onClickRelease to control that currently captures mouse |
| 350 void onClickRelease() override { |
| 351 if (fCtrlOnClick) { |
| 352 fCtrlOnClick->onClickRelease(); |
| 353 } |
| 354 fCtrlOnClick = nullptr; |
| 355 } |
| 356 |
| 357 void onSetParent() override { |
| 358 for (int i = 0; i < fControls.count(); i++) { |
| 359 fControls[i]->onSetParent(); // Propagate to children |
| 360 } |
| 361 |
| 362 // Finalize control selector |
| 363 // TODO can be moved to constructor if list-initialized |
| 364 if (!finalizedChildren) { |
| 365 fControlSelector = DiscreteSliderControl::Make( |
| 366 SkString(fName), &fSelectedControl, 0, fControls.count()-1); |
| 367 fControlSelector->setParent(this, SkPoint::Make(0.0f, 0.0f)); |
| 368 fHeight += kSelectorHeight; |
| 369 |
| 370 SkASSERT(fControlSelector->height() <= kSelectorHeight); |
| 371 } |
| 372 } |
| 373 |
| 374 /* A set of a selector and a list of controls. Displays the control from the
list of controls |
| 375 * with the index set by the aforementioned selector. |
| 376 * |
| 377 * @param name The name of the switcher. Will be displayed in the selector's
label. |
| 378 */ |
| 379 static sk_sp<ParentControl> Make(const SkString& name) { |
| 380 return sk_sp<ParentControl>(new ControlSwitcher(name)); |
| 381 } |
| 382 |
| 383 protected: |
| 384 // Draw selector and currently selected control |
| 385 void onDrawContent(SkCanvas* canvas) override { |
| 386 fControlSelector->drawContent(canvas); |
| 387 fControls[fSelectedControl]->drawContent(canvas); |
| 388 } |
| 389 |
| 390 // Returns true if control panel has mouse captured, false when it is ready
to release |
| 391 // capture |
| 392 bool onClick(const SkPoint& click) override { |
| 393 if (!fCtrlOnClick) { |
| 394 if (fControlSelector->isInCtrlRegion(click)) { |
| 395 fCtrlOnClick = fControlSelector.get(); |
| 396 } else if (fControls[fSelectedControl]->isInCtrlRegion(click)) { |
| 397 fCtrlOnClick = fControls[fSelectedControl].get(); |
| 398 } |
| 399 } |
| 400 if (fCtrlOnClick) { |
| 401 return fCtrlOnClick->click(click); |
| 402 } |
| 403 |
| 404 return false; |
| 405 } |
| 406 |
| 407 // Is in control region of selector or currently selected control |
| 408 bool onIsInCtrlRegion(const SkPoint& clickPos) const override { |
| 409 if (fControlSelector->isInCtrlRegion(clickPos)) { |
| 410 return true; |
| 411 } |
| 412 if (fControls[fSelectedControl]->isInCtrlRegion(clickPos)) { |
| 413 return true; |
| 414 } |
| 415 |
| 416 return false; |
| 417 } |
| 418 |
| 419 private: |
| 420 ControlSwitcher(const SkString& name) |
| 421 : INHERITED(name) |
| 422 , fHeight(0.0) |
| 423 , fSelectedControl(0) |
| 424 , fCtrlOnClick(nullptr){} |
| 425 |
| 426 bool finalizedChildren = false; |
| 427 |
| 428 sk_sp<Control> fControlSelector; |
| 429 SkScalar fHeight; |
| 430 SkTArray<sk_sp<Control>> fControls; |
| 431 int fSelectedControl; |
| 432 |
| 433 Control* fCtrlOnClick; |
| 434 |
| 435 static constexpr SkScalar kSelectorHeight = 40.0f; |
| 436 |
| 437 typedef ParentControl INHERITED; |
| 438 }; |
| 439 |
| 440 class ContinuousSliderControl : public Control { |
| 441 public: |
| 442 SkScalar height() const override { |
| 443 return 2.0f * kLabelHeight; |
| 444 } |
| 445 |
| 446 void onSetParent() override { |
| 447 fSlider = SkRect::MakeXYWH(0, kLabelHeight, kSliderWidth, kSliderHeight)
; |
| 448 fCtrlRegion = SkRect::MakeXYWH(0.0f, kLabelHeight, fParent->width(), kSl
iderHeight); |
| 449 fSliderRange = fParent->width() - kSliderWidth; |
| 450 } |
| 451 |
| 452 /* Make a slider for an SkScalar. |
| 453 * |
| 454 * @params name The name of the control, displayed in the label |
| 455 * @params output Pointer to the SkScalar that will be set by the slider |
| 456 * @params min Min value for output |
| 457 * @params max Max value for output |
| 458 */ |
| 459 static sk_sp<Control> Make(const SkString& name, SkScalar* output, SkScalar
min, SkScalar max) { |
| 460 return sk_sp<Control>(new ContinuousSliderControl(name, output, min, max)
); |
| 461 } |
| 462 |
| 463 protected: |
| 464 void onDrawContent(SkCanvas* canvas) override { |
| 465 SkASSERT(fParent); |
| 466 SkScalar x = fSliderRange * (*fOutput - fMin) / (fMax - fMin); |
| 467 fSlider.offsetTo(SkScalarPin(x, 0.0f, fSliderRange), fSlider.fTop); |
| 468 |
| 469 SkString valueStr; |
| 470 valueStr.appendScalar(*fOutput); |
| 471 this->drawLabel(canvas, valueStr); |
| 472 |
| 473 SkPaint sliderPaint; |
| 474 sliderPaint.setColor(0xFFF3F3F3); |
| 475 canvas->drawRect(fSlider, sliderPaint); |
| 476 |
| 477 SkPaint ctrlRegionPaint; |
| 478 ctrlRegionPaint.setColor(0xFFFFFFFF); |
| 479 ctrlRegionPaint.setStyle(SkPaint::kStroke_Style); |
| 480 ctrlRegionPaint.setStrokeWidth(2.0f); |
| 481 canvas->drawRect(fCtrlRegion, ctrlRegionPaint); |
| 482 } |
| 483 |
| 484 bool onClick(const SkPoint& clickPos) override { |
| 485 SkASSERT(fParent); |
| 486 SkScalar x = SkScalarPin(clickPos.fX, 0.0f, fSliderRange); |
| 487 *fOutput = (x/fSliderRange) * (fMax - fMin) + fMin; |
| 488 return true; |
| 489 } |
| 490 |
| 491 bool onIsInCtrlRegion(const SkPoint& clickPos) const override { |
| 492 SkASSERT(fParent); |
| 493 return fCtrlRegion.contains(SkRect::MakeXYWH(clickPos.fX, clickPos.fY, 1
, 1)); |
| 494 } |
| 495 |
| 496 private: |
| 497 ContinuousSliderControl(const SkString& name, SkScalar* output, SkScalar min
, SkScalar max) |
| 498 : INHERITED(name) |
| 499 , fOutput(output) |
| 500 , fMin(min) |
| 501 , fMax(max) {} |
| 502 |
| 503 SkScalar* fOutput; |
| 504 SkScalar fMin; |
| 505 SkScalar fMax; |
| 506 SkRect fSlider; |
| 507 SkRect fCtrlRegion; |
| 508 SkScalar fSliderRange; |
| 509 |
| 510 static constexpr SkScalar kSliderHeight = 20.0f; |
| 511 static constexpr SkScalar kSliderWidth = 10.0f; |
| 512 |
| 513 typedef Control INHERITED; |
| 514 }; |
| 515 |
| 516 class RadialDirectionControl : public Control { |
| 517 public: |
| 518 SkScalar height() const override { |
| 519 return kLabelHeight + 2.0f * kRegionRadius; |
| 520 } |
| 521 |
| 522 /* Make a direction selector. |
| 523 * |
| 524 * @params name The name of the control, displayed in the label |
| 525 * @params output Pointer to the SkVector that will be set by the slider |
| 526 */ |
| 527 static sk_sp<Control> Make(const SkString& name, SkVector* output) { |
| 528 return sk_sp<Control>(new RadialDirectionControl(name, output)); |
| 529 } |
| 530 |
| 531 protected: |
| 532 void onDrawContent(SkCanvas* canvas) override { |
| 533 SkASSERT(fParent); |
| 534 |
| 535 SkString valueStr; |
| 536 valueStr.appendf("%.2f, %.2f", fOutput->fX, fOutput->fY); |
| 537 this->drawLabel(canvas, valueStr); |
| 538 |
| 539 SkPoint lineEnd = SkPoint::Make(fCtrlRegion.centerX(), fCtrlRegion.cente
rY()) |
| 540 + (*fOutput * (kRegionRadius - kCapRadius)); |
| 541 SkPaint linePaint; |
| 542 linePaint.setColor(0xFFF3F3F3); |
| 543 linePaint.setStrokeWidth(kStrokeWidth); |
| 544 linePaint.setAntiAlias(true); |
| 545 linePaint.setStrokeCap(SkPaint::kRound_Cap); |
| 546 canvas->drawLine(fCtrlRegion.centerX(), fCtrlRegion.centerY(), |
| 547 lineEnd.fX, lineEnd.fY, linePaint); |
| 548 |
| 549 SkPaint ctrlRegionPaint; |
| 550 ctrlRegionPaint.setColor(0xFFFFFFFF); |
| 551 ctrlRegionPaint.setStyle(SkPaint::kStroke_Style); |
| 552 ctrlRegionPaint.setStrokeWidth(2.0f); |
| 553 ctrlRegionPaint.setAntiAlias(true); |
| 554 canvas->drawCircle(fCtrlRegion.centerX(), fCtrlRegion.centerY(), kRegion
Radius, |
| 555 ctrlRegionPaint); |
| 556 } |
| 557 |
| 558 bool onClick(const SkPoint& clickPos) override { |
| 559 SkASSERT(fParent); |
| 560 fOutput->fX = clickPos.fX - fCtrlRegion.centerX(); |
| 561 fOutput->fY = clickPos.fY - fCtrlRegion.centerY(); |
| 562 fOutput->normalize(); |
| 563 |
| 564 return true; |
| 565 } |
| 566 |
| 567 bool onIsInCtrlRegion(const SkPoint& clickPos) const override { |
| 568 SkASSERT(fParent); |
| 569 return fCtrlRegion.contains(SkRect::MakeXYWH(clickPos.fX, clickPos.fY, |
| 570 1, 1)); |
| 571 } |
| 572 |
| 573 private: |
| 574 RadialDirectionControl(const SkString& name, SkVector* output) |
| 575 : INHERITED(name) |
| 576 , fOutput(output) { |
| 577 fCtrlRegion = SkRect::MakeXYWH(0.0f, kLabelHeight, |
| 578 kRegionRadius * 2.0f, kRegionRadius * 2.0
f); |
| 579 } |
| 580 |
| 581 SkVector* fOutput; |
| 582 SkRect fCtrlRegion; |
| 583 |
| 584 static constexpr SkScalar kRegionRadius = 50.0f; |
| 585 static constexpr SkScalar kStrokeWidth = 6.0f; |
| 586 static constexpr SkScalar kCapRadius = kStrokeWidth / 2.0f; |
| 587 |
| 588 typedef Control INHERITED; |
| 589 }; |
| 590 |
| 591 class ColorDisplay: public Control { |
| 592 public: |
| 593 SkScalar height() const override { |
| 594 return kHeight; |
| 595 } |
| 596 |
| 597 void onSetParent() override { |
| 598 fDisplayRect = SkRect::MakeXYWH(0.0f, kPadding, fParent->width(), kHeigh
t - kPadding); |
| 599 } |
| 600 |
| 601 /* Make a display that shows an SkColor3f. |
| 602 * |
| 603 * @params output Pointer to the SkColor3f that will be displayed |
| 604 */ |
| 605 static sk_sp<Control> Make(SkColor3f* input) { |
| 606 return sk_sp<Control>(new ColorDisplay(SkString("ColorDisplay"), input))
; |
| 607 } |
| 608 |
| 609 protected: |
| 610 void onDrawContent(SkCanvas* canvas) override { |
| 611 SkASSERT(fParent); |
| 612 |
| 613 SkPaint displayPaint; |
| 614 displayPaint.setColor(SkColor4f::FromColor3f(*fInput, 1.0f).toSkColor())
; |
| 615 canvas->drawRect(fDisplayRect, displayPaint); |
| 616 } |
| 617 |
| 618 private: |
| 619 ColorDisplay(const SkString& name, SkColor3f* input) |
| 620 : INHERITED(name) |
| 621 , fInput(input) {} |
| 622 |
| 623 SkColor3f* fInput; |
| 624 SkRect fDisplayRect; |
| 625 |
| 626 static constexpr SkScalar kHeight = 24.0f; |
| 627 static constexpr SkScalar kPadding = 4.0f; |
| 628 |
| 629 typedef Control INHERITED; |
| 630 }; |
14 | 631 |
15 class BevelView : public SampleView { | 632 class BevelView : public SampleView { |
16 public: | 633 public: |
17 BevelView() | 634 BevelView() |
18 : fShapeBounds(SkRect::MakeWH(kShapeBoundsSize, kShapeBoundsSize)) | 635 : fShapeBounds(SkRect::MakeWH(kShapeBoundsSize, kShapeBoundsSize)) |
19 , fRedLight(SkLights::Light::MakeDirectional(SkColor3f::Make(0.6f, 0.45f
, 0.3f), | 636 , fControlPanel(kCtrlRange) { |
20 SkVector3::Make(0.0f, -5.0f
, 1.0f))) | |
21 , fBlueLight(SkLights::Light::MakeDirectional(SkColor3f::Make(0.3f, 0.45
f, 0.6f), | |
22 SkVector3::Make(0.0f, 5.0f
, 1.0f))) { | |
23 this->setBGColor(0xFF666868); // Slightly colorized gray for contrast | 637 this->setBGColor(0xFF666868); // Slightly colorized gray for contrast |
24 | 638 |
25 // Lights | |
26 SkLights::Builder builder; | |
27 builder.add(fRedLight); | |
28 builder.add(fBlueLight); | |
29 builder.add(SkLights::Light::MakeAmbient(SkColor3f::Make(0.4f, 0.4f, 0.4
f))); | |
30 fLights = builder.finish(); | |
31 | |
32 // Controls | 639 // Controls |
33 | 640 fBevelWidth = 25.0f; |
34 SkScalar currY = kSliderHeight; | 641 fBevelHeight = 25.0f; |
35 | 642 fBevelType = 0; |
36 const SkScalar kWidthCtrlInitialPos = 0.2f; | 643 |
37 fCtrlRangeRects[0] = SkRect::MakeXYWH(0.0f, currY, | 644 int currLight = 0; |
38 kCtrlRange + kSliderWidth, | 645 fLightDefs[currLight++] = |
39 kSliderHeight); | 646 {SkVector::Make(0.0f, 1.0f), 1.0f, SkColor3f::Make(0.6f, 0.45f,
0.3f)}; |
40 fWidthCtrlRect = SkRect::MakeXYWH(kWidthCtrlInitialPos * kCtrlRange, cur
rY, | 647 fLightDefs[currLight++] = |
41 kSliderWidth, kSliderHeight); | 648 {SkVector::Make(0.0f, -1.0f), 1.0f, SkColor3f::Make(0.3f, 0.45f,
0.6f)}; |
42 fBevelWidth = kBevelWidthMax * kWidthCtrlInitialPos; | 649 fLightDefs[currLight++] = |
43 currY += 2 * kSliderHeight; | 650 {SkVector::Make(1.0f, 0.0f), 1.0f, SkColor3f::Make(0.0f, 0.0f, 0
.0f)}; |
44 | 651 // Making sure we initialized all lights |
45 const SkScalar kHeightCtrlInitialPos = 0.75f; | 652 SkASSERT(currLight == kNumLights); |
46 fCtrlRangeRects[1] = SkRect::MakeXYWH(0.0f, currY, | 653 |
47 kCtrlRange + kSliderWidth, | 654 fControlPanel.add(ContinuousSliderControl::Make(SkString("BevelWidth"),
&fBevelWidth, |
48 kSliderHeight); | 655 1.0f, kShapeBoundsSize))
; |
49 fHeightCtrlRect = SkRect::MakeXYWH(kHeightCtrlInitialPos * kCtrlRange, c
urrY, | 656 fControlPanel.add(ContinuousSliderControl::Make(SkString("BevelHeight"),
&fBevelHeight, |
50 kSliderWidth, kSliderHeight); | 657 -50.0f, 50.0f)); |
51 // Mapping from (0, 1) to (-1, 1) | 658 fControlPanel.add(DiscreteSliderControl::Make(SkString("BevelType"), &fB
evelType, |
52 fBevelHeight = kBevelHeightMax * (kHeightCtrlInitialPos * 2.0f - 1.0f); | 659 0, 2)); |
53 currY += 2 * kSliderHeight; | 660 sk_sp<ParentControl> lightCtrlSelector = ControlSwitcher::Make(SkString(
"SelectedLight")); |
54 | 661 for (int i = 0; i < kNumLights; i++) { |
55 const SkScalar kTypeCtrlInitialPos = 1.0f / (2.0f * kBevelTypeCount); | 662 SkString name("Light"); |
56 fCtrlRangeRects[2] = SkRect::MakeXYWH(0.0f, currY, | 663 name.appendS32(i); |
57 kCtrlRange + kSliderWidth, | 664 sk_sp<ParentControl> currLightPanel = ControlPanel::Make(); |
58 kSliderHeight); | 665 SkString dirName(name); |
59 fTypeCtrlRect = SkRect::MakeXYWH(kTypeCtrlInitialPos * kCtrlRange, currY
, | 666 dirName.append("Dir"); |
60 kSliderWidth, kSliderHeight); | 667 currLightPanel->add(RadialDirectionControl::Make(dirName, &(fLightDe
fs[i].fDirXY))); |
61 fBevelType = (SkNormalSource::BevelType) SkScalarFloorToInt(kTypeCtrlIni
tialPos); | 668 SkString heightName(name); |
62 currY += 2 * kSliderHeight; | 669 heightName.append("Height"); |
63 | 670 currLightPanel->add(ContinuousSliderControl::Make(heightName, &(fLig
htDefs[i].fDirZ), |
64 fSelectedCtrlRect = nullptr; | 671 0.0f, 2.0f)); |
| 672 SkString redName(name); |
| 673 redName.append("Red"); |
| 674 currLightPanel->add(ContinuousSliderControl::Make(redName, &(fLightD
efs[i].fColor.fX), |
| 675 0.0f, 1.0f)); |
| 676 SkString greenName(name); |
| 677 greenName.append("Green"); |
| 678 currLightPanel->add(ContinuousSliderControl::Make(greenName, &(fLigh
tDefs[i].fColor.fY), |
| 679 0.0f, 1.0f)); |
| 680 SkString blueName(name); |
| 681 blueName.append("Blue"); |
| 682 currLightPanel->add(ContinuousSliderControl::Make(blueName, &(fLight
Defs[i].fColor.fZ), |
| 683 0.0f, 1.0f)); |
| 684 currLightPanel->add(ColorDisplay::Make(&(fLightDefs[i].fColor))); |
| 685 lightCtrlSelector->add(currLightPanel); |
| 686 } |
| 687 fControlPanel.add(lightCtrlSelector); |
| 688 |
| 689 fControlPanelSelected = false; |
65 fDirtyNormalSource = true; | 690 fDirtyNormalSource = true; |
66 | 691 |
67 fLabelTypeface = sk_tool_utils::create_portable_typeface("sans-serif", S
kFontStyle()); | 692 fLabelTypeface = sk_tool_utils::create_portable_typeface("sans-serif", S
kFontStyle()); |
68 } | 693 } |
69 | 694 |
70 protected: | 695 protected: |
71 bool onQuery(SkEvent *evt) override { | 696 bool onQuery(SkEvent *evt) override { |
72 if (SampleCode::TitleQ(*evt)) { | 697 if (SampleCode::TitleQ(*evt)) { |
73 SampleCode::TitleR(evt, "Bevel"); | 698 SampleCode::TitleR(evt, "Bevel"); |
74 return true; | 699 return true; |
75 } | 700 } |
76 | 701 |
77 return this->INHERITED::onQuery(evt); | 702 return this->INHERITED::onQuery(evt); |
78 } | 703 } |
79 | 704 |
80 enum Shape { | 705 enum Shape { |
81 kCircle_Shape, | 706 kCircle_Shape, |
82 kRect_Shape, | 707 kRect_Shape, |
83 }; | 708 }; |
84 void drawShape(enum Shape shape, SkCanvas* canvas) { | 709 void drawShape(enum Shape shape, SkCanvas* canvas) { |
85 canvas->save(); | 710 canvas->save(); |
86 | 711 |
87 SkPaint paint; | 712 SkPaint paint; |
88 | 713 |
89 if (fDirtyNormalSource) { | 714 if (fDirtyNormalSource) { |
90 fNormalSource = SkNormalSource::MakeBevel(fBevelType, fBevelWidth, f
BevelHeight); | 715 fNormalSource = SkNormalSource::MakeBevel((SkNormalSource::BevelType
)fBevelType, |
| 716 fBevelWidth, fBevelHeight)
; |
91 fDirtyNormalSource = false; | 717 fDirtyNormalSource = false; |
92 } | 718 } |
93 | 719 |
94 paint.setShader(SkLightingShader::Make(nullptr, fNormalSource, fLights))
; | 720 paint.setShader(SkLightingShader::Make(nullptr, fNormalSource, fLights))
; |
95 paint.setAntiAlias(true); | 721 paint.setAntiAlias(true); |
96 paint.setColor(0xFFDDDDDD); | 722 paint.setColor(0xFFDDDDDD); |
97 switch (shape) { | 723 switch (shape) { |
98 case kCircle_Shape: | 724 case kCircle_Shape: |
99 canvas->drawCircle(fShapeBounds.centerX(), fShapeBounds.centerY(
), | 725 canvas->drawCircle(fShapeBounds.centerX(), fShapeBounds.centerY(
), |
100 fShapeBounds.width()/2.0f, paint); | 726 fShapeBounds.width()/2.0f, paint); |
101 break; | 727 break; |
102 case kRect_Shape: | 728 case kRect_Shape: |
103 canvas->drawRect(fShapeBounds, paint); | 729 canvas->drawRect(fShapeBounds, paint); |
104 break; | 730 break; |
105 default: | 731 default: |
106 SkDEBUGFAIL("Invalid shape enum for drawShape"); | 732 SkDEBUGFAIL("Invalid shape enum for drawShape"); |
107 } | 733 } |
108 | 734 |
109 canvas->restore(); | 735 canvas->restore(); |
110 } | 736 } |
111 | 737 |
112 void onDrawContent(SkCanvas *canvas) override { | 738 void onDrawContent(SkCanvas *canvas) override { |
113 | 739 |
114 canvas->save(); | 740 canvas->save(); |
115 canvas->resetMatrix(); // Force static controls and labels | 741 canvas->resetMatrix(); // Force static control panel position |
| 742 fControlPanel.drawContent(canvas); |
| 743 canvas->restore(); |
116 | 744 |
117 // Draw controls | 745 SkLights::Builder builder; |
118 | 746 for (int i = 0; i < kNumLights; i++) { |
119 SkPaint ctrlRectPaint; | 747 builder.add(SkLights::Light::MakeDirectional(fLightDefs[i].fColor, |
120 ctrlRectPaint.setColor(0xFFF3F3F3); | 748 SkPoint3::Make(fLightDe
fs[i].fDirXY.fX, |
121 canvas->drawRect(fWidthCtrlRect, ctrlRectPaint); | 749 fLightDe
fs[i].fDirXY.fY, |
122 canvas->drawRect(fHeightCtrlRect, ctrlRectPaint); | 750 fLightDe
fs[i].fDirZ))); |
123 canvas->drawRect(fTypeCtrlRect, ctrlRectPaint); | |
124 | |
125 SkPaint ctrlRectRangePaint; | |
126 ctrlRectRangePaint.setColor(0xFFFFFFFF); | |
127 ctrlRectRangePaint.setStyle(SkPaint::kStroke_Style); | |
128 ctrlRectRangePaint.setStrokeWidth(2.0f); | |
129 | |
130 for (size_t i = 0; i < kNumControls; i++) { | |
131 canvas->drawRect(fCtrlRangeRects[i], ctrlRectRangePaint); | |
132 } | 751 } |
133 | 752 builder.add(SkLights::Light::MakeAmbient(SkColor3f::Make(0.4f, 0.4f, 0.4
f))); |
134 // Draw labels | 753 fLights = builder.finish(); |
135 constexpr SkScalar kTextSize = 12.0f; | |
136 SkString widthLabel, heightLabel, typeLabel; | |
137 SkPaint labelPaint; | |
138 labelPaint.setTypeface(fLabelTypeface); | |
139 labelPaint.setAntiAlias(true); | |
140 labelPaint.setColor(0xFFFFFFFF); | |
141 labelPaint.setTextSize(kTextSize); | |
142 | |
143 widthLabel.appendf("BevelWidth: %f", fBevelWidth); | |
144 heightLabel.appendf("BevelHeight: %f", fBevelHeight); | |
145 typeLabel.append("BevelType: "); | |
146 | |
147 switch (fBevelType) { | |
148 case SkNormalSource::BevelType::kLinear: | |
149 typeLabel.append("Linear"); | |
150 break; | |
151 case SkNormalSource::BevelType::kRoundedIn: | |
152 typeLabel.append("RoundedIn"); | |
153 break; | |
154 case SkNormalSource::BevelType::kRoundedOut: | |
155 typeLabel.append("RoundedOut"); | |
156 break; | |
157 } | |
158 | |
159 canvas->drawText(widthLabel.c_str(), widthLabel.size(), 0, | |
160 fWidthCtrlRect.fTop - kTextSize/2.0f, labelPaint); | |
161 canvas->drawText(heightLabel.c_str(), heightLabel.size(), 0, | |
162 fHeightCtrlRect.fTop - kTextSize/2.0f, labelPaint); | |
163 canvas->drawText(typeLabel.c_str(), typeLabel.size(), 0, | |
164 fTypeCtrlRect.fTop - kTextSize/2.0f, labelPaint); | |
165 | |
166 canvas->restore(); // Return to modified matrix when drawing shapes | |
167 | 754 |
168 // Draw shapes | 755 // Draw shapes |
169 SkScalar xPos = kCtrlRange + 25.0f; | 756 SkScalar xPos = kCtrlRange + 25.0f; |
170 SkScalar yPos = fShapeBounds.height(); | 757 SkScalar yPos = fShapeBounds.height(); |
171 for (Shape shape : { kCircle_Shape, kRect_Shape }) { | 758 for (Shape shape : { kCircle_Shape, kRect_Shape }) { |
172 canvas->save(); | 759 canvas->save(); |
173 canvas->translate(xPos, yPos); | 760 canvas->translate(xPos, yPos); |
174 this->drawShape(shape, canvas); | 761 this->drawShape(shape, canvas); |
175 canvas->restore(); | 762 canvas->restore(); |
176 | 763 |
177 xPos += 1.2f * fShapeBounds.width(); | 764 xPos += 1.2f * fShapeBounds.width(); |
178 } | 765 } |
179 } | 766 } |
180 | 767 |
181 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) ove
rride { | 768 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) ove
rride { |
182 return new SkView::Click(this); | 769 return new SkView::Click(this); |
183 } | 770 } |
184 | 771 |
185 bool onClick(Click *click) override { | 772 bool onClick(Click *click) override { |
186 SkScalar x = click->fCurr.fX; | 773 // Control panel mouse handling |
187 SkScalar y = click->fCurr.fY; | 774 fControlPanelSelected = fControlPanel.inClick(click); |
188 | 775 |
189 SkScalar dx = x - click->fPrev.fX; | 776 if (fControlPanelSelected) { // Control modification |
190 SkScalar dy = y - click->fPrev.fY; | |
191 | |
192 // Control deselection | |
193 if (Click::State::kUp_State == click->fState) { | |
194 fSelectedCtrlRect = nullptr; | |
195 return true; | |
196 } | |
197 | |
198 // Control selection | |
199 if (nullptr == fSelectedCtrlRect && Click::State::kDown_State == click->
fState) { | |
200 if (fWidthCtrlRect.contains(SkRect::MakeXYWH(x, y, 1, 1))) { | |
201 fSelectedCtrlRect = &fWidthCtrlRect; | |
202 } else if (fHeightCtrlRect.contains(SkRect::MakeXYWH(x, y, 1, 1))) { | |
203 fSelectedCtrlRect = &fHeightCtrlRect; | |
204 } else if (fTypeCtrlRect.contains(SkRect::MakeXYWH(x, y, 1, 1))) { | |
205 fSelectedCtrlRect = &fTypeCtrlRect; | |
206 } | |
207 } | |
208 | |
209 if (nullptr != fSelectedCtrlRect) { // Control modification | |
210 fSelectedCtrlRect->offsetTo(SkScalarPin(x, 0.0f, kCtrlRange), fSelec
tedCtrlRect->fTop); | |
211 | |
212 fBevelHeight = (fHeightCtrlRect.fLeft / kCtrlRange) * kBevelHeightMa
x * 2.0f | |
213 - kBevelHeightMax; | |
214 fBevelWidth = (fWidthCtrlRect.fLeft / kCtrlRange) * kBevelWidthMax; | |
215 fBevelType = (SkNormalSource::BevelType)SkTMin( | |
216 SkScalarFloorToInt(kBevelTypeCount * fTypeCtrlRect.fLeft / k
CtrlRange), | |
217 kBevelTypeCount - 1); | |
218 | |
219 // Snap type controls to 3 positions | |
220 fTypeCtrlRect.offsetTo(kCtrlRange * ( ((int)fBevelType)/SkIntToScala
r(kBevelTypeCount) | |
221 + 1.0f/(2.0f * kBevelTypeCount
) ), | |
222 fTypeCtrlRect.fTop); | |
223 | |
224 // Ensuring width is non-zero | |
225 fBevelWidth = SkMaxScalar(1.0f, fBevelWidth); | |
226 | |
227 fDirtyNormalSource = true; | 777 fDirtyNormalSource = true; |
228 | 778 |
229 this->inval(nullptr); | 779 this->inval(nullptr); |
230 return true; | 780 return true; |
231 } else { // Moving light | |
232 if (dx != 0 || dy != 0) { | |
233 float recipX = 1.0f / kAppWidth; | |
234 float recipY = 1.0f / kAppHeight; | |
235 | |
236 if (0 == click->fModifierKeys) { // No modifier | |
237 fBlueLight = SkLights::Light::MakeDirectional(fBlueLight.col
or(), | |
238 SkVector3::Make((kAppWidth/2.0f - x) * recipX * -3.0
f, | |
239 (kAppHeight/2.0f - y) * recipY * -3.
0f, | |
240 1.0f)); | |
241 } else if (1 == click->fModifierKeys) { // Shift key | |
242 fRedLight = SkLights::Light::MakeDirectional(fRedLight.color
(), | |
243 SkVector3::Make((kAppWidth/2.0f - x) * recipX * -3.0
f, | |
244 (kAppHeight/2.0f - y) * recipY * -3.
0f, | |
245 1.0f)); | |
246 } | |
247 | |
248 SkLights::Builder builder; | |
249 builder.add(fRedLight); | |
250 builder.add(fBlueLight); | |
251 builder.add(SkLights::Light::MakeAmbient( | |
252 SkColor3f::Make(0.4f, 0.4f, 0.4f))); | |
253 fLights = builder.finish(); | |
254 | |
255 this->inval(nullptr); | |
256 } | |
257 return true; | |
258 } | 781 } |
259 | 782 |
| 783 // TODO move shapes |
| 784 this->inval(nullptr); |
260 return true; | 785 return true; |
261 } | 786 } |
262 | 787 |
263 private: | 788 private: |
264 static constexpr int kNumTestRects = 3; | 789 static constexpr int kNumTestRects = 3; |
265 | 790 |
266 static constexpr SkScalar kAppWidth = 400.0f; | |
267 static constexpr SkScalar kAppHeight = 400.0f; | |
268 static constexpr SkScalar kShapeBoundsSize = 120.0f; | 791 static constexpr SkScalar kShapeBoundsSize = 120.0f; |
269 | 792 |
270 static constexpr SkScalar kCtrlRange = 150.0f; | 793 static constexpr SkScalar kCtrlRange = 150.0f; |
271 static constexpr SkScalar kBevelWidthMax = kShapeBoundsSize; | |
272 static constexpr SkScalar kBevelHeightMax = 50.0f; | |
273 static constexpr int kBevelTypeCount = 3; | |
274 | 794 |
275 static constexpr SkScalar kSliderHeight = 20.0f; | 795 static constexpr int kNumLights = 3; |
276 static constexpr SkScalar kSliderWidth = 10.0f; | |
277 | 796 |
278 const SkRect fShapeBounds; | 797 const SkRect fShapeBounds; |
279 | 798 |
280 static constexpr int kNumControls = 3; | |
281 SkRect fCtrlRangeRects[kNumControls]; | |
282 SkRect* fSelectedCtrlRect; | |
283 SkRect fWidthCtrlRect; | |
284 SkRect fHeightCtrlRect; | |
285 SkRect fTypeCtrlRect; | |
286 | |
287 SkScalar fBevelWidth; | 799 SkScalar fBevelWidth; |
288 SkScalar fBevelHeight; | 800 SkScalar fBevelHeight; |
289 SkNormalSource::BevelType fBevelType; | 801 int fBevelType; |
| 802 |
290 sk_sp<SkNormalSource> fNormalSource; | 803 sk_sp<SkNormalSource> fNormalSource; |
291 bool fDirtyNormalSource; | 804 bool fDirtyNormalSource; |
292 | 805 |
293 sk_sp<SkLights> fLights; | 806 sk_sp<SkLights> fLights; |
294 SkLights::Light fRedLight; | 807 |
295 SkLights::Light fBlueLight; | 808 struct LightDef { |
| 809 SkVector fDirXY; |
| 810 SkScalar fDirZ; |
| 811 SkColor3f fColor; |
| 812 |
| 813 LightDef() {} |
| 814 LightDef(SkVector dirXY, SkScalar dirZ, SkColor3f color) |
| 815 : fDirXY(dirXY) |
| 816 , fDirZ(dirZ) |
| 817 , fColor(color) {} |
| 818 }; |
| 819 LightDef fLightDefs[kNumLights]; |
| 820 |
| 821 ControlPanel fControlPanel; |
| 822 bool fControlPanelSelected; |
296 | 823 |
297 sk_sp<SkTypeface> fLabelTypeface; | 824 sk_sp<SkTypeface> fLabelTypeface; |
298 | 825 |
299 typedef SampleView INHERITED; | 826 typedef SampleView INHERITED; |
300 }; | 827 }; |
301 | 828 |
302 ////////////////////////////////////////////////////////////////////////////// | 829 ////////////////////////////////////////////////////////////////////////////// |
303 | 830 |
304 static SkView* MyFactory() { return new BevelView; } | 831 static SkView* MyFactory() { return new BevelView; } |
305 static SkViewRegister reg(MyFactory); | 832 static SkViewRegister reg(MyFactory); |
306 | 833 |
OLD | NEW |