148 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			148 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  * Copyright 2021 Google LLC
 | |
|  *
 | |
|  * Use of this source code is governed by a BSD-style license that can be
 | |
|  * found in the LICENSE file.
 | |
|  */
 | |
| 
 | |
| /*
 | |
|  * This GM creates the same gradients as the Chromium test fillrect_gradient:
 | |
|  * http://osscs/chromium/chromium/src/+/main:third_party/blink/web_tests/fast/canvas/fillrect_gradient.html
 | |
|  */
 | |
| 
 | |
| #include "gm/gm.h"
 | |
| #include "include/core/SkCanvas.h"
 | |
| #include "include/core/SkColor.h"
 | |
| #include "include/core/SkPaint.h"
 | |
| #include "include/core/SkPoint.h"
 | |
| #include "include/core/SkRect.h"
 | |
| #include "include/core/SkRefCnt.h"
 | |
| #include "include/core/SkScalar.h"
 | |
| #include "include/core/SkShader.h"
 | |
| #include "include/core/SkSize.h"
 | |
| #include "include/core/SkString.h"
 | |
| #include "include/core/SkTileMode.h"
 | |
| #include "include/effects/SkGradientShader.h"
 | |
| 
 | |
| const int kCellSize = 50;
 | |
| const int kNumColumns = 2;
 | |
| const int kNumRows = 9;
 | |
| const int kPadSize = 10;
 | |
| 
 | |
| class FillrectGradientGM : public skiagm::GM {
 | |
| public:
 | |
|     FillrectGradientGM() {}
 | |
| 
 | |
| protected:
 | |
|     struct GradientStop {
 | |
|         float pos;
 | |
|         SkColor color;
 | |
|     };
 | |
| 
 | |
|     SkString onShortName() override {
 | |
|         return SkString("fillrect_gradient");
 | |
|     }
 | |
| 
 | |
|     SkISize onISize() override {
 | |
|         return SkISize::Make(kNumColumns * (kCellSize + kPadSize),
 | |
|                              kNumRows * (kCellSize + kPadSize));
 | |
|     }
 | |
| 
 | |
|     void drawGradient(SkCanvas* canvas, std::initializer_list<GradientStop> stops) {
 | |
|         std::vector<SkColor> colors;
 | |
|         std::vector<SkScalar> positions;
 | |
|         colors.reserve(stops.size());
 | |
|         positions.reserve(stops.size());
 | |
| 
 | |
|         for (const GradientStop& stop : stops) {
 | |
|             colors.push_back(stop.color);
 | |
|             positions.push_back(stop.pos);
 | |
|         }
 | |
| 
 | |
|         static constexpr SkPoint points[] = {
 | |
|             SkPoint::Make(kCellSize, 0),
 | |
|             SkPoint::Make(kCellSize, kCellSize),
 | |
|         };
 | |
| 
 | |
|         // Draw the gradient linearly.
 | |
|         sk_sp<SkShader> shader = SkGradientShader::MakeLinear(points,
 | |
|                                                               colors.data(),
 | |
|                                                               positions.data(),
 | |
|                                                               colors.size(),
 | |
|                                                               SkTileMode::kClamp);
 | |
|         SkPaint paint;
 | |
|         paint.setShader(shader);
 | |
|         canvas->drawRect(SkRect::MakeXYWH(0, 0, kCellSize, kCellSize), paint);
 | |
| 
 | |
|         canvas->save();
 | |
|         canvas->translate(kCellSize + kPadSize, 0);
 | |
| 
 | |
|         // Draw the gradient radially.
 | |
|         shader = SkGradientShader::MakeRadial(SkPoint::Make(kCellSize / 2, kCellSize / 2),
 | |
|                                               kCellSize / 2,
 | |
|                                               colors.data(),
 | |
|                                               positions.data(),
 | |
|                                               colors.size(),
 | |
|                                               SkTileMode::kClamp);
 | |
|         paint.setShader(shader);
 | |
|         canvas->drawRect(SkRect::MakeXYWH(0, 0, kCellSize, kCellSize), paint);
 | |
| 
 | |
|         canvas->restore();
 | |
|         canvas->translate(0, kCellSize + kPadSize);
 | |
|     }
 | |
| 
 | |
|     void onDraw(SkCanvas* canvas) override {
 | |
|         // Simple gradient: Green to white
 | |
|         this->drawGradient(canvas, {{0.0f, SK_ColorGREEN}, {1.0f, SK_ColorWHITE}});
 | |
| 
 | |
|         // Multiple sections: Green to white to red
 | |
|         this->drawGradient(canvas,
 | |
|                            {{0.0f, SK_ColorGREEN}, {0.5f, SK_ColorWHITE}, {1.0f, SK_ColorRED}});
 | |
| 
 | |
|         // No stops at 0.0 or 1.0: Larger green to white to larger red
 | |
|         this->drawGradient(canvas,
 | |
|                            {{0.4f, SK_ColorGREEN}, {0.5f, SK_ColorWHITE}, {0.6f, SK_ColorRED}});
 | |
| 
 | |
|         // Only one stop, at zero: Solid red
 | |
|         this->drawGradient(canvas, {{0.0f, SK_ColorRED}});
 | |
| 
 | |
|         // Only one stop, at 1.0: Solid red
 | |
|         this->drawGradient(canvas, {{1.0f, SK_ColorRED}});
 | |
| 
 | |
|         // Only one stop, in the middle: Solid red
 | |
|         this->drawGradient(canvas, {{0.5f, SK_ColorRED}});
 | |
| 
 | |
|         // Disjoint gradients (multiple stops at the same offset)
 | |
|         // Blue to white in the top (inner) half, red to yellow in the bottom (outer) half
 | |
|         this->drawGradient(canvas,
 | |
|                            {{0.0f, SK_ColorBLUE},
 | |
|                             {0.5f, SK_ColorWHITE},
 | |
|                             {0.5f, SK_ColorRED},
 | |
|                             {1.0f, SK_ColorYELLOW}});
 | |
| 
 | |
|         // Ignored stops: Blue to white, red to yellow (same as previous)
 | |
|         this->drawGradient(canvas,
 | |
|                            {{0.0f, SK_ColorBLUE},
 | |
|                             {0.5f, SK_ColorWHITE},
 | |
|                             {0.5f, SK_ColorGRAY},
 | |
|                             {0.5f, SK_ColorCYAN},
 | |
|                             {0.5f, SK_ColorRED},
 | |
|                             {1.0f, SK_ColorYELLOW}});
 | |
| 
 | |
|         // Unsorted stops: Blue to white, red to yellow
 | |
|         // Unlike Chrome, we don't sort the stops, so this renders differently than the prior cell.
 | |
|         this->drawGradient(canvas,
 | |
|                            {{0.5f, SK_ColorWHITE},
 | |
|                             {0.5f, SK_ColorGRAY},
 | |
|                             {1.0f, SK_ColorYELLOW},
 | |
|                             {0.5f, SK_ColorCYAN},
 | |
|                             {0.5f, SK_ColorRED},
 | |
|                             {0.0f, SK_ColorBLUE}});
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     using INHERITED = skiagm::GM;
 | |
| };
 | |
| 
 | |
| DEF_GM(return new FillrectGradientGM;)
 |