skia2/gm/analytic_gradients.cpp
Ben Wagner d1701ba884 IWYU for gms starting with 'a'.
There is still a bit of manual mucking about with iwyu output to get
things nice, but the checker seems to be doing ok and the process is now
a bit easier. Will see how it goes.

This also pointed out the amount of code behind ifdefs should be
minimized by using the build system and 'constexpr if' when possible.

Change-Id: Ic63fa33c65e5ff40b58858e15fc51f27d862e20d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/211349
Commit-Queue: Ben Wagner <bungeman@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
2019-04-30 19:39:37 +00:00

191 lines
6.1 KiB
C++

/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/*
* This GM presents a variety of gradients meant to test the correctness of the analytic
* GrUnrolledBinaryGradientColorizer, which can handle arbitrary gradients with 1 to 8 interpolation
* intervals. These intervals can be either hardstops or smooth color transitions.
*
* It produces an image similar to that of GM_hardstop_gradients, but is arranged as follows:
*
* | Clamp |
* |________________|
* | M1 M2 M3 M4 |
* ___________|________________|
* 1 |
* 2 |
* 3 |
* 4 |
* 5 |
* 6 |
* 7 |
* 8 |
* The M-modes are different ways of interlveaving hardstops with smooth transitions:
* - M1 = All smooth transitions
* - M2 = All hard stops
* - M5 = Alternating smooth then hard
* - M6 = Alternating hard then smooth
*
* Only clamping is tested since this is focused more on within the interpolation region behavior,
* compared to overall behavior.
*/
#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/core/SkTypes.h"
#include "include/effects/SkGradientShader.h"
#include "include/private/SkTemplates.h"
// All positions must be divided by the target interval count, which will produce the expected
// normalized position array for that interval number (assuming an appropriate color count is
// provided).
const int M1_POSITIONS[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
const int M2_POSITIONS[] = { 0, 1,1, 2,2, 3,3, 4,4, 5,5, 6,6, 7,7, 8 };
const int M3_POSITIONS[] = { 0, 1, 2,2, 3, 4,4, 5, 6,6, 7, 8 };
const int M4_POSITIONS[] = { 0, 1,1, 2, 3,3, 4, 5,5, 6, 7,7, 8 };
// Color count = index of first occurrence of interval count value in Mx_POSITIONS array.
const int INT1_COLOR_COUNTS[] = { 2, 2, 2, 2 };
const int INT2_COLOR_COUNTS[] = { 3, 4, 3, 4 };
const int INT3_COLOR_COUNTS[] = { 4, 6, 5, 5 };
const int INT4_COLOR_COUNTS[] = { 5, 8, 6, 7 };
const int INT5_COLOR_COUNTS[] = { 6, 10, 8, 8 };
const int INT6_COLOR_COUNTS[] = { 7, 12, 9, 10 };
const int INT7_COLOR_COUNTS[] = { 8, 14, 11, 11 };
const int INT8_COLOR_COUNTS[] = { 9, 16, 12, 13 };
// Cycle through defined colors for positions 0 through 8.
const SkColor COLORS[] = {
SK_ColorDKGRAY,
SK_ColorRED,
SK_ColorYELLOW,
SK_ColorGREEN,
SK_ColorCYAN,
SK_ColorBLUE,
SK_ColorMAGENTA,
SK_ColorBLACK,
SK_ColorLTGRAY
};
const int* INTERVAL_COLOR_COUNTS[] = {
INT1_COLOR_COUNTS,
INT2_COLOR_COUNTS,
INT3_COLOR_COUNTS,
INT4_COLOR_COUNTS,
INT5_COLOR_COUNTS,
INT6_COLOR_COUNTS,
INT7_COLOR_COUNTS,
INT8_COLOR_COUNTS
};
const int COLOR_COUNT = SK_ARRAY_COUNT(COLORS);
const int* M_POSITIONS[] = {
M1_POSITIONS,
M2_POSITIONS,
M3_POSITIONS,
M4_POSITIONS
};
const int WIDTH = 500;
const int HEIGHT = 500;
const int NUM_ROWS = 8;
const int NUM_COLS = 4;
const int CELL_WIDTH = WIDTH / NUM_COLS;
const int CELL_HEIGHT = HEIGHT / NUM_ROWS;
const int PAD_WIDTH = 3;
const int PAD_HEIGHT = 3;
const int RECT_WIDTH = CELL_WIDTH - (2 * PAD_WIDTH);
const int RECT_HEIGHT = CELL_HEIGHT - (2 * PAD_HEIGHT);
static void shade_rect(SkCanvas* canvas, sk_sp<SkShader> shader, int cellRow, int cellCol) {
SkPaint paint;
paint.setShader(shader);
canvas->save();
canvas->translate(SkIntToScalar(cellCol * CELL_WIDTH + PAD_WIDTH),
SkIntToScalar(cellRow * CELL_HEIGHT + PAD_HEIGHT));
const SkRect rect = SkRect::MakeWH(SkIntToScalar(RECT_WIDTH), SkIntToScalar(RECT_HEIGHT));
canvas->drawRect(rect, paint);
canvas->restore();
}
class AnalyticGradientShaderGM : public skiagm::GM {
public:
AnalyticGradientShaderGM() {
}
protected:
SkString onShortName() override {
return SkString("analytic_gradients");
}
SkISize onISize() override {
return SkISize::Make(1024, 512);
}
void onDraw(SkCanvas* canvas) override {
const SkPoint points[2] = { SkPoint::Make(0, 0), SkPoint::Make(RECT_WIDTH, 0.0) };
for (int cellRow = 0; cellRow < NUM_ROWS; cellRow++) {
// Each interval has 4 different color counts, one per mode
const int* colorCounts = INTERVAL_COLOR_COUNTS[cellRow]; // Has len = 4
for (int cellCol = 0; cellCol < NUM_COLS; cellCol++) {
// create_gradient_points(cellRow, cellCol, points);
// Get the color count dependent on interval and mode
int colorCount = colorCounts[cellCol];
// Get the positions given the mode
const int* layout = M_POSITIONS[cellCol];
// Collect positions and colors specific to the interval+mode normalizing the
// position based on the interval count (== cellRow+1)
SkAutoSTMalloc<4, SkColor> colors(colorCount);
SkAutoSTMalloc<4, SkScalar> positions(colorCount);
int j = 0;
for (int i = 0; i < colorCount; i++) {
positions[i] = SkIntToScalar(layout[i]) / (cellRow + 1);
colors[i] = COLORS[j % COLOR_COUNT];
j++;
}
auto shader = SkGradientShader::MakeLinear(
points,
colors.get(),
positions.get(),
colorCount,
SkTileMode::kClamp,
0,
nullptr);
shade_rect(canvas, shader, cellRow, cellCol);
}
}
}
private:
typedef skiagm::GM INHERITED;
};
DEF_GM(return new AnalyticGradientShaderGM;)