2 * Copyright 2015 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
11 #include "sk_tool_utils.h"
14 #include "SkColorPriv.h"
16 static SkBitmap copy_bitmap(const SkBitmap& src, SkColorType colorType) {
17 const SkBitmap* srcPtr = &src;
19 if (kRGB_565_SkColorType == colorType) {
20 tmp.setAlphaType(kOpaque_SkAlphaType);
25 sk_tool_utils::copy_to(©, colorType, *srcPtr);
32 // Make either A8 or gray8 bitmap.
33 static SkBitmap make_bitmap(SkColorType ct) {
36 case kAlpha_8_SkColorType:
37 bm.allocPixels(SkImageInfo::MakeA8(SCALE, SCALE));
39 case kGray_8_SkColorType:
41 SkImageInfo::Make(SCALE, SCALE, ct, kOpaque_SkAlphaType));
47 uint8_t spectrum[256];
48 for (int y = 0; y < 256; ++y) {
51 for (int y = 0; y < 128; ++y) {
52 // Shift over one byte each scanline.
53 memcpy(bm.getAddr8(0, y), &spectrum[y], 128);
59 static void draw_center_letter(char c,
67 p->measureText(&c, 1, &bounds);
68 canvas->drawText(&c, 1, x - bounds.centerX(), y - bounds.centerY(), *p);
71 static void color_wheel_native(SkCanvas* canvas) {
72 SkAutoCanvasRestore autoCanvasRestore(canvas, true);
73 canvas->translate(0.5f * SCALE, 0.5f * SCALE);
75 p.setAntiAlias(false);
76 p.setColor(SK_ColorWHITE);
77 canvas->drawCircle(0.0f, 0.0f, SCALE * 0.5f, p);
79 const double sqrt_3_over_2 = 0.8660254037844387;
80 const SkScalar Z = 0.0f;
81 const SkScalar D = 0.3f * SkIntToScalar(SCALE);
82 const SkScalar X = SkDoubleToScalar(D * sqrt_3_over_2);
83 const SkScalar Y = D * SK_ScalarHalf;
84 sk_tool_utils::set_portable_typeface(&p, nullptr, SkFontStyle::FromOldStyle(SkTypeface::kBold));
85 p.setTextSize(0.28125f * SCALE);
86 draw_center_letter('K', &p, SK_ColorBLACK, Z, Z, canvas);
87 draw_center_letter('R', &p, SK_ColorRED, Z, D, canvas);
88 draw_center_letter('G', &p, SK_ColorGREEN, -X, -Y, canvas);
89 draw_center_letter('B', &p, SK_ColorBLUE, X, -Y, canvas);
90 draw_center_letter('C', &p, SK_ColorCYAN, Z, -D, canvas);
91 draw_center_letter('M', &p, SK_ColorMAGENTA, X, Y, canvas);
92 draw_center_letter('Y', &p, SK_ColorYELLOW, -X, Y, canvas);
96 int find(T* array, int N, T item) {
97 for (int i = 0; i < N; ++i) {
98 if (array[i] == item) {
105 static SkPMColor premultiply_color(SkColor c) {
106 return SkPremultiplyARGBInline(SkColorGetA(c), SkColorGetR(c),
107 SkColorGetG(c), SkColorGetB(c));
110 static SkBitmap indexed_bitmap() {
112 n32bitmap.allocN32Pixels(SCALE, SCALE);
113 n32bitmap.eraseColor(SK_ColorTRANSPARENT);
115 SkCanvas canvas(n32bitmap);
116 color_wheel_native(&canvas);
117 const SkColor colors[] = {
128 SkPMColor pmColors[SK_ARRAY_COUNT(colors)];
129 for (size_t i = 0; i < SK_ARRAY_COUNT(colors); ++i) {
130 pmColors[i] = premultiply_color(colors[i]);
133 SkImageInfo info = SkImageInfo::Make(SCALE, SCALE, kIndex_8_SkColorType,
134 kPremul_SkAlphaType);
135 bm.allocPixels(info, SkColorTable::Make(pmColors, SK_ARRAY_COUNT(pmColors)));
136 for (int y = 0; y < SCALE; ++y) {
137 for (int x = 0; x < SCALE; ++x) {
138 SkPMColor c = *n32bitmap.getAddr32(x, y);
139 int idx = find(pmColors, SK_ARRAY_COUNT(pmColors), c);
140 *bm.getAddr8(x, y) = SkClampMax(idx, SK_ARRAY_COUNT(pmColors) - 1);
146 static void draw(SkCanvas* canvas,
149 SkColorType colorType,
151 SkASSERT(src.colorType() == colorType);
152 canvas->drawBitmap(src, 0.0f, 0.0f);
153 canvas->drawString(text, 0.0f, 12.0f, p);
156 DEF_SIMPLE_GM(all_bitmap_configs, canvas, SCALE, 6 * SCALE) {
157 SkAutoCanvasRestore autoCanvasRestore(canvas, true);
159 p.setColor(SK_ColorBLACK);
160 p.setAntiAlias(true);
161 sk_tool_utils::set_portable_typeface(&p, nullptr);
163 sk_tool_utils::draw_checkerboard(canvas, SK_ColorLTGRAY, SK_ColorWHITE, 8);
166 if (GetResourceAsBitmap("color_wheel.png", &bitmap)) {
167 bitmap.setImmutable();
168 draw(canvas, p, bitmap, kN32_SkColorType, "Native 32");
170 canvas->translate(0.0f, SkIntToScalar(SCALE));
171 SkBitmap copy565 = copy_bitmap(bitmap, kRGB_565_SkColorType);
172 p.setColor(SK_ColorRED);
173 draw(canvas, p, copy565, kRGB_565_SkColorType, "RGB 565");
174 p.setColor(SK_ColorBLACK);
176 canvas->translate(0.0f, SkIntToScalar(SCALE));
177 SkBitmap copy4444 = copy_bitmap(bitmap, kARGB_4444_SkColorType);
178 draw(canvas, p, copy4444, kARGB_4444_SkColorType, "ARGB 4444");
180 canvas->translate(0.0f, SkIntToScalar(2 * SCALE));
183 canvas->translate(0.0f, SkIntToScalar(SCALE));
184 SkBitmap bitmapIndexed = indexed_bitmap();
185 draw(canvas, p, bitmapIndexed, kIndex_8_SkColorType, "Index 8");
187 canvas->translate(0.0f, SkIntToScalar(SCALE));
188 SkBitmap bitmapA8 = make_bitmap(kAlpha_8_SkColorType);
189 draw(canvas, p, bitmapA8, kAlpha_8_SkColorType, "Alpha 8");
191 p.setColor(SK_ColorRED);
192 canvas->translate(0.0f, SkIntToScalar(SCALE));
193 SkBitmap bitmapG8 = make_bitmap(kGray_8_SkColorType);
194 draw(canvas, p, bitmapG8, kGray_8_SkColorType, "Gray 8");
197 sk_sp<SkImage> make_not_native32_color_wheel() {
198 SkBitmap n32bitmap, notN32bitmap;
199 n32bitmap.allocN32Pixels(SCALE, SCALE);
200 n32bitmap.eraseColor(SK_ColorTRANSPARENT);
201 SkCanvas n32canvas(n32bitmap);
202 color_wheel_native(&n32canvas);
204 #if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
205 const SkColorType ct = kRGBA_8888_SkColorType;
206 #elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
207 const SkColorType ct = kBGRA_8888_SkColorType;
209 static_assert(ct != kN32_SkColorType, "BRGA!=RGBA");
210 SkAssertResult(sk_tool_utils::copy_to(¬N32bitmap, ct, n32bitmap));
211 SkASSERT(notN32bitmap.colorType() == ct);
212 return SkImage::MakeFromBitmap(notN32bitmap);
215 DEF_SIMPLE_GM(not_native32_bitmap_config, canvas, SCALE, SCALE) {
216 sk_sp<SkImage> notN32image(make_not_native32_color_wheel());
217 SkASSERT(notN32image);
218 sk_tool_utils::draw_checkerboard(canvas, SK_ColorLTGRAY, SK_ColorWHITE, 8);
219 canvas->drawImage(notN32image.get(), 0.0f, 0.0f);
222 static uint32_t make_pixel(int x, int y, SkAlphaType alphaType) {
223 SkASSERT(x >= 0 && x < SCALE);
224 SkASSERT(y >= 0 && y < SCALE);
226 SkScalar R = SCALE / 2.0f;
228 uint32_t alpha = 0x00;
230 if ((x - R) * (x - R) + (y - R) * (y - R) < R * R) {
236 case kPremul_SkAlphaType:
239 case kUnpremul_SkAlphaType:
243 SkFAIL("Should not get here - invalid alpha type");
246 return alpha << 24 | component;
249 static void make_color_test_bitmap_variant(
250 SkColorType colorType,
251 SkAlphaType alphaType,
252 sk_sp<SkColorSpace> colorSpace,
255 SkASSERT(colorType == kRGBA_8888_SkColorType || colorType == kBGRA_8888_SkColorType);
256 SkASSERT(alphaType == kPremul_SkAlphaType || alphaType == kUnpremul_SkAlphaType);
258 SkImageInfo::Make(SCALE, SCALE, colorType, alphaType, colorSpace));
261 for (int y = 0; y < bm->height(); y++) {
262 for (int x = 0; x < bm->width(); x++) {
263 *pm.writable_addr32(x, y) = make_pixel(x, y, alphaType);
268 DEF_SIMPLE_GM(all_variants_8888, canvas, 4 * SCALE + 30, 2 * SCALE + 10) {
269 sk_tool_utils::draw_checkerboard(canvas, SK_ColorLTGRAY, SK_ColorWHITE, 8);
271 sk_sp<SkColorSpace> colorSpaces[] {
272 SkColorSpace::MakeSRGB(),
275 for (auto colorSpace : colorSpaces) {
277 for (auto alphaType : {kPremul_SkAlphaType, kUnpremul_SkAlphaType}) {
279 for (auto colorType : {kRGBA_8888_SkColorType, kBGRA_8888_SkColorType}) {
281 make_color_test_bitmap_variant(colorType, alphaType, colorSpace, &bm);
282 canvas->drawBitmap(bm, 0.0f, 0.0f);
283 canvas->translate(SCALE + 10, 0.0f);
286 canvas->translate(0.0f, SCALE + 10);
289 canvas->translate(2 * (SCALE + 10), 0.0f);