blob: ea7b73483b328a37e70c85b8dd50a48a6a10114e [file] [log] [blame]
halcanarydb0dcc72015-03-20 12:31:52 -07001/*
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
halcanarydb0dcc72015-03-20 12:31:52 -07008#include "SkSurface.h"
9#include "Resources.h"
10#include "gm.h"
Mike Klein33d20552017-03-22 13:47:51 -040011#include "sk_tool_utils.h"
halcanarydb0dcc72015-03-20 12:31:52 -070012
13#include "SkMath.h"
14#include "SkColorPriv.h"
15
16static SkBitmap copy_bitmap(const SkBitmap& src, SkColorType colorType) {
17 SkBitmap copy;
18 src.copyTo(&copy, colorType);
19 copy.setImmutable();
20 return copy;
21}
22
23#define SCALE 128
24
25// Make either A8 or gray8 bitmap.
26static SkBitmap make_bitmap(SkColorType ct) {
27 SkBitmap bm;
28 switch (ct) {
29 case kAlpha_8_SkColorType:
30 bm.allocPixels(SkImageInfo::MakeA8(SCALE, SCALE));
31 break;
32 case kGray_8_SkColorType:
33 bm.allocPixels(
34 SkImageInfo::Make(SCALE, SCALE, ct, kOpaque_SkAlphaType));
35 break;
36 default:
37 SkASSERT(false);
38 return bm;
39 }
40 SkAutoLockPixels autoLockPixels(bm);
41 uint8_t spectrum[256];
42 for (int y = 0; y < 256; ++y) {
43 spectrum[y] = y;
44 }
45 for (int y = 0; y < 128; ++y) {
46 // Shift over one byte each scanline.
47 memcpy(bm.getAddr8(0, y), &spectrum[y], 128);
48 }
49 bm.setImmutable();
50 return bm;
51}
52
53static void draw_center_letter(char c,
54 SkPaint* p,
55 SkColor color,
56 SkScalar x,
57 SkScalar y,
58 SkCanvas* canvas) {
59 SkRect bounds;
60 p->setColor(color);
61 p->measureText(&c, 1, &bounds);
62 canvas->drawText(&c, 1, x - bounds.centerX(), y - bounds.centerY(), *p);
63}
64
65static void color_wheel_native(SkCanvas* canvas) {
66 SkAutoCanvasRestore autoCanvasRestore(canvas, true);
67 canvas->translate(0.5f * SCALE, 0.5f * SCALE);
68 SkPaint p;
69 p.setAntiAlias(false);
70 p.setColor(SK_ColorWHITE);
71 canvas->drawCircle(0.0f, 0.0f, SCALE * 0.5f, p);
72
73 const double sqrt_3_over_2 = 0.8660254037844387;
74 const SkScalar Z = 0.0f;
75 const SkScalar D = 0.3f * SkIntToScalar(SCALE);
76 const SkScalar X = SkDoubleToScalar(D * sqrt_3_over_2);
77 const SkScalar Y = D * SK_ScalarHalf;
mbocee6a9912016-05-31 11:42:36 -070078 sk_tool_utils::set_portable_typeface(&p, nullptr, SkFontStyle::FromOldStyle(SkTypeface::kBold));
halcanarydb0dcc72015-03-20 12:31:52 -070079 p.setTextSize(0.28125f * SCALE);
80 draw_center_letter('K', &p, SK_ColorBLACK, Z, Z, canvas);
81 draw_center_letter('R', &p, SK_ColorRED, Z, D, canvas);
82 draw_center_letter('G', &p, SK_ColorGREEN, -X, -Y, canvas);
83 draw_center_letter('B', &p, SK_ColorBLUE, X, -Y, canvas);
84 draw_center_letter('C', &p, SK_ColorCYAN, Z, -D, canvas);
85 draw_center_letter('M', &p, SK_ColorMAGENTA, X, Y, canvas);
86 draw_center_letter('Y', &p, SK_ColorYELLOW, -X, Y, canvas);
87}
88
89template <typename T>
90int find(T* array, int N, T item) {
91 for (int i = 0; i < N; ++i) {
92 if (array[i] == item) {
93 return i;
94 }
95 }
96 return -1;
97}
98
99static SkPMColor premultiply_color(SkColor c) {
100 return SkPremultiplyARGBInline(SkColorGetA(c), SkColorGetR(c),
101 SkColorGetG(c), SkColorGetB(c));
102}
103
104static SkBitmap indexed_bitmap() {
105 SkBitmap n32bitmap;
106 n32bitmap.allocN32Pixels(SCALE, SCALE);
107 n32bitmap.eraseColor(SK_ColorTRANSPARENT);
108
109 SkCanvas canvas(n32bitmap);
110 color_wheel_native(&canvas);
111 const SkColor colors[] = {
112 SK_ColorTRANSPARENT,
113 SK_ColorWHITE,
114 SK_ColorBLACK,
115 SK_ColorRED,
116 SK_ColorGREEN,
117 SK_ColorBLUE,
118 SK_ColorCYAN,
119 SK_ColorMAGENTA,
120 SK_ColorYELLOW,
121 };
122 SkPMColor pmColors[SK_ARRAY_COUNT(colors)];
123 for (size_t i = 0; i < SK_ARRAY_COUNT(colors); ++i) {
124 pmColors[i] = premultiply_color(colors[i]);
125 }
126 SkBitmap bm;
Hal Canarycefc4312016-11-04 16:26:16 -0400127 sk_sp<SkColorTable> ctable(new SkColorTable(pmColors, SK_ARRAY_COUNT(pmColors)));
halcanarydb0dcc72015-03-20 12:31:52 -0700128 SkImageInfo info = SkImageInfo::Make(SCALE, SCALE, kIndex_8_SkColorType,
129 kPremul_SkAlphaType);
Hal Canarycefc4312016-11-04 16:26:16 -0400130 bm.allocPixels(info, nullptr, ctable.get());
halcanarydb0dcc72015-03-20 12:31:52 -0700131 SkAutoLockPixels autoLockPixels1(n32bitmap);
132 SkAutoLockPixels autoLockPixels2(bm);
133 for (int y = 0; y < SCALE; ++y) {
134 for (int x = 0; x < SCALE; ++x) {
135 SkPMColor c = *n32bitmap.getAddr32(x, y);
136 int idx = find(pmColors, SK_ARRAY_COUNT(pmColors), c);
137 *bm.getAddr8(x, y) = SkClampMax(idx, SK_ARRAY_COUNT(pmColors) - 1);
138 }
139 }
140 return bm;
141}
142
143static void draw(SkCanvas* canvas,
144 const SkPaint& p,
145 const SkBitmap& src,
146 SkColorType colorType,
147 const char text[]) {
148 SkASSERT(src.colorType() == colorType);
149 canvas->drawBitmap(src, 0.0f, 0.0f);
150 canvas->drawText(text, strlen(text), 0.0f, 12.0f, p);
151}
152
153DEF_SIMPLE_GM(all_bitmap_configs, canvas, SCALE, 6 * SCALE) {
154 SkAutoCanvasRestore autoCanvasRestore(canvas, true);
155 SkPaint p;
156 p.setColor(SK_ColorBLACK);
157 p.setAntiAlias(true);
halcanary96fcdcc2015-08-27 07:41:13 -0700158 sk_tool_utils::set_portable_typeface(&p, nullptr);
halcanarydb0dcc72015-03-20 12:31:52 -0700159
160 sk_tool_utils::draw_checkerboard(canvas, SK_ColorLTGRAY, SK_ColorWHITE, 8);
161
162 SkBitmap bitmap;
163 if (GetResourceAsBitmap("color_wheel.png", &bitmap)) {
164 bitmap.setImmutable();
165 draw(canvas, p, bitmap, kN32_SkColorType, "Native 32");
166
167 canvas->translate(0.0f, SkIntToScalar(SCALE));
168 SkBitmap copy565 = copy_bitmap(bitmap, kRGB_565_SkColorType);
169 p.setColor(SK_ColorRED);
170 draw(canvas, p, copy565, kRGB_565_SkColorType, "RGB 565");
171 p.setColor(SK_ColorBLACK);
172
173 canvas->translate(0.0f, SkIntToScalar(SCALE));
174 SkBitmap copy4444 = copy_bitmap(bitmap, kARGB_4444_SkColorType);
175 draw(canvas, p, copy4444, kARGB_4444_SkColorType, "ARGB 4444");
176 } else {
177 canvas->translate(0.0f, SkIntToScalar(2 * SCALE));
178 }
179
180 canvas->translate(0.0f, SkIntToScalar(SCALE));
181 SkBitmap bitmapIndexed = indexed_bitmap();
182 draw(canvas, p, bitmapIndexed, kIndex_8_SkColorType, "Index 8");
183
184 canvas->translate(0.0f, SkIntToScalar(SCALE));
185 SkBitmap bitmapA8 = make_bitmap(kAlpha_8_SkColorType);
186 draw(canvas, p, bitmapA8, kAlpha_8_SkColorType, "Alpha 8");
187
188 p.setColor(SK_ColorRED);
189 canvas->translate(0.0f, SkIntToScalar(SCALE));
190 SkBitmap bitmapG8 = make_bitmap(kGray_8_SkColorType);
191 draw(canvas, p, bitmapG8, kGray_8_SkColorType, "Gray 8");
192}
halcanaryaa4ba902015-11-06 07:27:23 -0800193
reed9ce9d672016-03-17 10:51:11 -0700194sk_sp<SkImage> make_not_native32_color_wheel() {
halcanaryaa4ba902015-11-06 07:27:23 -0800195 SkBitmap n32bitmap, notN32bitmap;
196 n32bitmap.allocN32Pixels(SCALE, SCALE);
197 n32bitmap.eraseColor(SK_ColorTRANSPARENT);
198 SkCanvas n32canvas(n32bitmap);
199 color_wheel_native(&n32canvas);
200 n32canvas.flush();
201 #if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
202 const SkColorType ct = kRGBA_8888_SkColorType;
203 #elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
204 const SkColorType ct = kBGRA_8888_SkColorType;
205 #endif
206 static_assert(ct != kN32_SkColorType, "BRGA!=RGBA");
207 SkAssertResult(n32bitmap.copyTo(&notN32bitmap, ct));
208 SkASSERT(notN32bitmap.colorType() == ct);
reed9ce9d672016-03-17 10:51:11 -0700209 return SkImage::MakeFromBitmap(notN32bitmap);
halcanaryaa4ba902015-11-06 07:27:23 -0800210}
211
212DEF_SIMPLE_GM(not_native32_bitmap_config, canvas, SCALE, SCALE) {
reed9ce9d672016-03-17 10:51:11 -0700213 sk_sp<SkImage> notN32image(make_not_native32_color_wheel());
halcanaryaa4ba902015-11-06 07:27:23 -0800214 SkASSERT(notN32image);
215 sk_tool_utils::draw_checkerboard(canvas, SK_ColorLTGRAY, SK_ColorWHITE, 8);
reed9ce9d672016-03-17 10:51:11 -0700216 canvas->drawImage(notN32image.get(), 0.0f, 0.0f);
halcanaryaa4ba902015-11-06 07:27:23 -0800217}
herb58238462016-06-03 09:44:53 -0700218
219static uint32_t make_pixel(int x, int y, SkAlphaType alphaType) {
220 SkASSERT(x >= 0 && x < SCALE);
221 SkASSERT(y >= 0 && y < SCALE);
222
223 SkScalar R = SCALE / 2.0f;
224
225 uint32_t alpha = 0x00;
226
227 if ((x - R) * (x - R) + (y - R) * (y - R) < R * R) {
228 alpha = 0xFF;
229 }
230
231 uint32_t component;
232 switch (alphaType) {
233 case kPremul_SkAlphaType:
234 component = alpha;
235 break;
236 case kUnpremul_SkAlphaType:
237 component = 0xFF;
238 break;
239 default:
240 SkFAIL("Should not get here - invalid alpha type");
241 return 0xFF000000;
242 }
243 return alpha << 24 | component;
244}
245
246static void make_color_test_bitmap_variant(
247 SkColorType colorType,
248 SkAlphaType alphaType,
brianosman52ede1d2016-06-20 08:25:02 -0700249 sk_sp<SkColorSpace> colorSpace,
herb58238462016-06-03 09:44:53 -0700250 SkBitmap* bm)
251{
252 SkASSERT(colorType == kRGBA_8888_SkColorType || colorType == kBGRA_8888_SkColorType);
253 SkASSERT(alphaType == kPremul_SkAlphaType || alphaType == kUnpremul_SkAlphaType);
254 bm->allocPixels(
brianosman52ede1d2016-06-20 08:25:02 -0700255 SkImageInfo::Make(SCALE, SCALE, colorType, alphaType, colorSpace));
herb58238462016-06-03 09:44:53 -0700256 SkPixmap pm;
257 bm->peekPixels(&pm);
258 for (int y = 0; y < bm->height(); y++) {
259 for (int x = 0; x < bm->width(); x++) {
260 *pm.writable_addr32(x, y) = make_pixel(x, y, alphaType);
261 }
262 }
263}
264
Joe Gregorioc4859072017-01-20 14:21:27 +0000265DEF_SIMPLE_GM(all_variants_8888, canvas, 4 * SCALE + 30, 2 * SCALE + 10) {
herb58238462016-06-03 09:44:53 -0700266 sk_tool_utils::draw_checkerboard(canvas, SK_ColorLTGRAY, SK_ColorWHITE, 8);
267
brianosman52ede1d2016-06-20 08:25:02 -0700268 sk_sp<SkColorSpace> colorSpaces[] {
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500269 SkColorSpace::MakeSRGB(),
brianosman52ede1d2016-06-20 08:25:02 -0700270 nullptr,
brianosman52ede1d2016-06-20 08:25:02 -0700271 };
272 for (auto colorSpace : colorSpaces) {
herb58238462016-06-03 09:44:53 -0700273 canvas->save();
274 for (auto alphaType : {kPremul_SkAlphaType, kUnpremul_SkAlphaType}) {
275 canvas->save();
276 for (auto colorType : {kRGBA_8888_SkColorType, kBGRA_8888_SkColorType}) {
277 SkBitmap bm;
brianosman52ede1d2016-06-20 08:25:02 -0700278 make_color_test_bitmap_variant(colorType, alphaType, colorSpace, &bm);
herb58238462016-06-03 09:44:53 -0700279 canvas->drawBitmap(bm, 0.0f, 0.0f);
280 canvas->translate(SCALE + 10, 0.0f);
281 }
282 canvas->restore();
Joe Gregorioc4859072017-01-20 14:21:27 +0000283 canvas->translate(0.0f, SCALE + 10);
herb58238462016-06-03 09:44:53 -0700284 }
285 canvas->restore();
286 canvas->translate(2 * (SCALE + 10), 0.0f);
287 }
288}