blob: eb4c7607feb1e4b9d9d3a2a488595dd9c215e84c [file] [log] [blame]
brianosmane5824b92016-02-26 11:57:23 -08001/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "gm.h"
9
10#include "Resources.h"
11#include "SkGradientShader.h"
reed6644d932016-06-10 11:41:47 -070012#include "SkPM4fPriv.h"
brianosmane5824b92016-02-26 11:57:23 -080013
brianosman33f6b3f2016-06-02 05:49:21 -070014DEF_SIMPLE_GM(gamma, canvas, 560, 200) {
brianosmane5824b92016-02-26 11:57:23 -080015 SkPaint p;
16 const SkScalar sz = 50.0f;
17 const int szInt = SkScalarTruncToInt(sz);
18 const SkScalar tx = sz + 5.0f;
19 const SkRect r = SkRect::MakeXYWH(0, 0, sz, sz);
20 SkShader::TileMode rpt = SkShader::kRepeat_TileMode;
brianosman52ede1d2016-06-20 08:25:02 -070021 auto srgbColorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
brianosmane5824b92016-02-26 11:57:23 -080022
23 SkBitmap ditherBmp;
24 ditherBmp.allocN32Pixels(2, 2);
25 SkPMColor* pixels = reinterpret_cast<SkPMColor*>(ditherBmp.getPixels());
26 pixels[0] = pixels[3] = SkPackARGB32(0xFF, 0xFF, 0xFF, 0xFF);
27 pixels[1] = pixels[2] = SkPackARGB32(0xFF, 0, 0, 0);
28
29 SkBitmap linearGreyBmp;
brianosman52ede1d2016-06-20 08:25:02 -070030 SkImageInfo linearGreyInfo = SkImageInfo::MakeN32(szInt, szInt, kOpaque_SkAlphaType, nullptr);
brianosmane5824b92016-02-26 11:57:23 -080031 linearGreyBmp.allocPixels(linearGreyInfo);
32 linearGreyBmp.eraseARGB(0xFF, 0x7F, 0x7F, 0x7F);
33
34 SkBitmap srgbGreyBmp;
35 SkImageInfo srgbGreyInfo = SkImageInfo::MakeN32(szInt, szInt, kOpaque_SkAlphaType,
brianosman52ede1d2016-06-20 08:25:02 -070036 srgbColorSpace);
brianosmane5824b92016-02-26 11:57:23 -080037 srgbGreyBmp.allocPixels(srgbGreyInfo);
brianosman33f6b3f2016-06-02 05:49:21 -070038 // 0xBC = 255 * linear_to_srgb(0.5f)
brianosmane5824b92016-02-26 11:57:23 -080039 srgbGreyBmp.eraseARGB(0xFF, 0xBC, 0xBC, 0xBC);
40
brianosman33f6b3f2016-06-02 05:49:21 -070041 SkBitmap mipmapBmp;
reed6644d932016-06-10 11:41:47 -070042 SkImageInfo mipmapInfo = SkImageInfo::Make(2, 2, kN32_SkColorType, kOpaque_SkAlphaType,
brianosman52ede1d2016-06-20 08:25:02 -070043 srgbColorSpace);
brianosman33f6b3f2016-06-02 05:49:21 -070044 mipmapBmp.allocPixels(mipmapInfo);
45 SkPMColor* mipmapPixels = reinterpret_cast<SkPMColor*>(mipmapBmp.getPixels());
reed6644d932016-06-10 11:41:47 -070046 unsigned s25 = 0x89; // 255 * linear_to_srgb(0.25f)
47 unsigned s75 = 0xE1; // 255 * linear_to_srgb(0.75f)
48 mipmapPixels[0] = mipmapPixels[3] = SkPackARGB32(0xFF, s25, s25, s25);
49 mipmapPixels[1] = mipmapPixels[2] = SkPackARGB32(0xFF, s75, s75, s75);
brianosman33f6b3f2016-06-02 05:49:21 -070050
brianosmane5824b92016-02-26 11:57:23 -080051 SkPaint textPaint;
52 textPaint.setColor(SK_ColorWHITE);
53
54 // Helpers:
55 auto advance = [&]() {
56 canvas->translate(tx, 0);
57 p.reset();
58 };
59
60 auto nextRect = [&](const char* label, const char* label2) {
61 canvas->drawRect(r, p);
62 canvas->drawText(label, strlen(label), 0, sz + textPaint.getFontSpacing(), textPaint);
63 if (label2) {
64 canvas->drawText(label2, strlen(label2), 0, sz + 2 * textPaint.getFontSpacing(),
65 textPaint);
66 }
67 advance();
68 };
69
70 auto nextBitmap = [&](const SkBitmap& bmp, const char* label) {
71 canvas->drawBitmap(bmp, 0, 0);
72 canvas->drawText(label, strlen(label), 0, sz + textPaint.getFontSpacing(), textPaint);
73 advance();
74 };
75
76 auto nextXferRect = [&](SkColor srcColor, SkXfermode::Mode mode, SkColor dstColor) {
77 p.setColor(dstColor);
78 canvas->drawRect(r, p);
79 p.setColor(srcColor);
80 p.setXfermodeMode(mode);
81 canvas->drawRect(r, p);
82
83 SkString srcText = SkStringPrintf("%08X", srcColor);
84 SkString dstText = SkStringPrintf("%08X", dstColor);
85 canvas->drawText(srcText.c_str(), srcText.size(), 0, sz + textPaint.getFontSpacing(),
86 textPaint);
87 const char* modeName = SkXfermode::ModeName(mode);
88 canvas->drawText(modeName, strlen(modeName), 0, sz + 2 * textPaint.getFontSpacing(),
89 textPaint);
90 canvas->drawText(dstText.c_str(), dstText.size(), 0, sz + 3 * textPaint.getFontSpacing(),
91 textPaint);
92 advance();
93 };
94
95 // Necessary for certain Xfermode tests to work (ie some of them output white @ 50% alpha):
96 canvas->clear(SK_ColorBLACK);
97
98 // *Everything* should be perceptually 50% grey. Only the first rectangle
99 // is guaranteed to draw that way, though.
100 canvas->save();
101
102 // Black/white dither, pixel perfect. This is ground truth.
reed2ad1aa62016-03-09 09:50:50 -0800103 p.setShader(SkShader::MakeBitmapShader(ditherBmp, rpt, rpt));
brianosmane5824b92016-02-26 11:57:23 -0800104 p.setFilterQuality(SkFilterQuality::kNone_SkFilterQuality);
105 nextRect("Dither", "Reference");
106
107 // Black/white dither, sampled at half-texel offset. Tests bilerp.
108 // NOTE: We need to apply a non-identity scale and/or rotation to trick
109 // the raster pipeline into *not* snapping to nearest.
110 SkMatrix offsetMatrix = SkMatrix::Concat(
111 SkMatrix::MakeScale(-1.0f), SkMatrix::MakeTrans(0.5f, 0.0f));
reed2ad1aa62016-03-09 09:50:50 -0800112 p.setShader(SkShader::MakeBitmapShader(ditherBmp, rpt, rpt, &offsetMatrix));
brianosmane5824b92016-02-26 11:57:23 -0800113 p.setFilterQuality(SkFilterQuality::kMedium_SkFilterQuality);
114 nextRect("Dither", "Bilerp");
115
116 // Black/white dither, scaled down by 2x. Tests minification.
117 SkMatrix scaleMatrix = SkMatrix::MakeScale(0.5f);
reed2ad1aa62016-03-09 09:50:50 -0800118 p.setShader(SkShader::MakeBitmapShader(ditherBmp, rpt, rpt, &scaleMatrix));
brianosmane5824b92016-02-26 11:57:23 -0800119 p.setFilterQuality(SkFilterQuality::kMedium_SkFilterQuality);
120 nextRect("Dither", "Scale");
121
brianosman33f6b3f2016-06-02 05:49:21 -0700122 // 25%/75% dither, scaled down by 2x. Tests ALL aspects of minification. Specifically, are
123 // sRGB sources decoded to linear before computing mipmaps?
124 p.setShader(SkShader::MakeBitmapShader(mipmapBmp, rpt, rpt, &scaleMatrix));
125 p.setFilterQuality(SkFilterQuality::kMedium_SkFilterQuality);
126 nextRect("MipMaps", 0);
127
brianosmane5824b92016-02-26 11:57:23 -0800128 // 50% grey via paint color.
129 p.setColor(0xff7f7f7f);
130 nextRect("Color", 0);
131
132 // Black -> White gradient, scaled to sample just the middle.
133 // Tests gradient interpolation.
134 SkPoint points[2] = {
135 SkPoint::Make(0 - (sz * 10), 0),
136 SkPoint::Make(sz + (sz * 10), 0)
137 };
138 SkColor colors[2] = { SK_ColorBLACK, SK_ColorWHITE };
reed2ad1aa62016-03-09 09:50:50 -0800139 p.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 2,
140 SkShader::kClamp_TileMode));
brianosmane5824b92016-02-26 11:57:23 -0800141 nextRect("Gradient", 0);
142
143 // 50% grey from linear bitmap, with drawBitmap
144 nextBitmap(linearGreyBmp, "Lnr BMP");
145
146 // 50% grey from sRGB bitmap, with drawBitmap
147 nextBitmap(srgbGreyBmp, "sRGB BMP");
148
149 // Bitmap wrapped in a shader (linear):
reed2ad1aa62016-03-09 09:50:50 -0800150 p.setShader(SkShader::MakeBitmapShader(linearGreyBmp, rpt, rpt));
brianosmane5824b92016-02-26 11:57:23 -0800151 p.setFilterQuality(SkFilterQuality::kMedium_SkFilterQuality);
152 nextRect("Lnr BMP", "Shader");
153
154 // Bitmap wrapped in a shader (sRGB):
reed2ad1aa62016-03-09 09:50:50 -0800155 p.setShader(SkShader::MakeBitmapShader(srgbGreyBmp, rpt, rpt));
brianosmane5824b92016-02-26 11:57:23 -0800156 p.setFilterQuality(SkFilterQuality::kMedium_SkFilterQuality);
157 nextRect("sRGB BMP", "Shader");
158
159 // Carriage return.
160 canvas->restore();
161 canvas->translate(0, 2 * sz);
162
163 const U8CPU sqrtHalf = 0xB4;
164 const SkColor sqrtHalfAlpha = SkColorSetARGB(sqrtHalf, 0, 0, 0);
165 const SkColor sqrtHalfWhite = SkColorSetARGB(0xFF, sqrtHalf, sqrtHalf, sqrtHalf);
166
167 // Xfermode tests, all done off-screen so certain modes work...
168
169 canvas->saveLayer(nullptr, nullptr);
170
171 nextXferRect(0x7fffffff, SkXfermode::kSrcOver_Mode, SK_ColorBLACK);
172 nextXferRect(0x7f000000, SkXfermode::kSrcOver_Mode, SK_ColorWHITE);
173
174 nextXferRect(SK_ColorBLACK, SkXfermode::kDstOver_Mode, 0x7fffffff);
175 nextXferRect(SK_ColorWHITE, SkXfermode::kSrcIn_Mode, 0x7fff00ff);
176 nextXferRect(0x7fff00ff, SkXfermode::kDstIn_Mode, SK_ColorWHITE);
177 nextXferRect(sqrtHalfWhite, SkXfermode::kSrcIn_Mode, sqrtHalfAlpha);
178 nextXferRect(sqrtHalfAlpha, SkXfermode::kDstIn_Mode, sqrtHalfWhite);
179
180 nextXferRect(0xff3f3f3f, SkXfermode::kPlus_Mode, 0xff3f3f3f);
181 nextXferRect(sqrtHalfWhite, SkXfermode::kModulate_Mode, sqrtHalfWhite);
182
183 canvas->restore();
brianosmane5824b92016-02-26 11:57:23 -0800184}