1 /* 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 "SkSurface.h" 9 #include "Resources.h" 10 #include "gm.h" 11 #include "sk_tool_utils.h" 12 13 #include "SkMath.h" 14 #include "SkColorPriv.h" 15 16 static SkBitmap copy_bitmap(const SkBitmap& src, SkColorType colorType) { 17 const SkBitmap* srcPtr = &src; 18 SkBitmap tmp(src); 19 if (kRGB_565_SkColorType == colorType) { 20 tmp.setAlphaType(kOpaque_SkAlphaType); 21 srcPtr = &tmp; 22 } 23 24 SkBitmap copy; 25 sk_tool_utils::copy_to(©, colorType, *srcPtr); 26 copy.setImmutable(); 27 return copy; 28 } 29 30 #define SCALE 128 31 32 // Make either A8 or gray8 bitmap. 33 static SkBitmap make_bitmap(SkColorType ct) { 34 SkBitmap bm; 35 switch (ct) { 36 case kAlpha_8_SkColorType: 37 bm.allocPixels(SkImageInfo::MakeA8(SCALE, SCALE)); 38 break; 39 case kGray_8_SkColorType: 40 bm.allocPixels( 41 SkImageInfo::Make(SCALE, SCALE, ct, kOpaque_SkAlphaType)); 42 break; 43 default: 44 SkASSERT(false); 45 return bm; 46 } 47 uint8_t spectrum[256]; 48 for (int y = 0; y < 256; ++y) { 49 spectrum[y] = y; 50 } 51 for (int y = 0; y < 128; ++y) { 52 // Shift over one byte each scanline. 53 memcpy(bm.getAddr8(0, y), &spectrum[y], 128); 54 } 55 bm.setImmutable(); 56 return bm; 57 } 58 59 static void draw_center_letter(char c, 60 SkPaint* p, 61 SkColor color, 62 SkScalar x, 63 SkScalar y, 64 SkCanvas* canvas) { 65 SkRect bounds; 66 p->setColor(color); 67 p->measureText(&c, 1, &bounds); 68 canvas->drawText(&c, 1, x - bounds.centerX(), y - bounds.centerY(), *p); 69 } 70 71 static void color_wheel_native(SkCanvas* canvas) { 72 SkAutoCanvasRestore autoCanvasRestore(canvas, true); 73 canvas->translate(0.5f * SCALE, 0.5f * SCALE); 74 SkPaint p; 75 p.setAntiAlias(false); 76 p.setColor(SK_ColorWHITE); 77 canvas->drawCircle(0.0f, 0.0f, SCALE * 0.5f, p); 78 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); 93 } 94 95 template <typename T> 96 int find(T* array, int N, T item) { 97 for (int i = 0; i < N; ++i) { 98 if (array[i] == item) { 99 return i; 100 } 101 } 102 return -1; 103 } 104 105 static void draw(SkCanvas* canvas, 106 const SkPaint& p, 107 const SkBitmap& src, 108 SkColorType colorType, 109 const char text[]) { 110 SkASSERT(src.colorType() == colorType); 111 canvas->drawBitmap(src, 0.0f, 0.0f); 112 canvas->drawString(text, 0.0f, 12.0f, p); 113 } 114 115 DEF_SIMPLE_GM(all_bitmap_configs, canvas, SCALE, 5 * SCALE) { 116 SkAutoCanvasRestore autoCanvasRestore(canvas, true); 117 SkPaint p; 118 p.setColor(SK_ColorBLACK); 119 p.setAntiAlias(true); 120 sk_tool_utils::set_portable_typeface(&p, nullptr); 121 122 sk_tool_utils::draw_checkerboard(canvas, SK_ColorLTGRAY, SK_ColorWHITE, 8); 123 124 SkBitmap bitmap; 125 if (GetResourceAsBitmap("color_wheel.png", &bitmap)) { 126 bitmap.setImmutable(); 127 draw(canvas, p, bitmap, kN32_SkColorType, "Native 32"); 128 129 canvas->translate(0.0f, SkIntToScalar(SCALE)); 130 SkBitmap copy565 = copy_bitmap(bitmap, kRGB_565_SkColorType); 131 p.setColor(SK_ColorRED); 132 draw(canvas, p, copy565, kRGB_565_SkColorType, "RGB 565"); 133 p.setColor(SK_ColorBLACK); 134 135 canvas->translate(0.0f, SkIntToScalar(SCALE)); 136 SkBitmap copy4444 = copy_bitmap(bitmap, kARGB_4444_SkColorType); 137 draw(canvas, p, copy4444, kARGB_4444_SkColorType, "ARGB 4444"); 138 } else { 139 canvas->translate(0.0f, SkIntToScalar(2 * SCALE)); 140 } 141 142 canvas->translate(0.0f, SkIntToScalar(SCALE)); 143 SkBitmap bitmapA8 = make_bitmap(kAlpha_8_SkColorType); 144 draw(canvas, p, bitmapA8, kAlpha_8_SkColorType, "Alpha 8"); 145 146 p.setColor(SK_ColorRED); 147 canvas->translate(0.0f, SkIntToScalar(SCALE)); 148 SkBitmap bitmapG8 = make_bitmap(kGray_8_SkColorType); 149 draw(canvas, p, bitmapG8, kGray_8_SkColorType, "Gray 8"); 150 } 151 152 sk_sp<SkImage> make_not_native32_color_wheel() { 153 SkBitmap n32bitmap, notN32bitmap; 154 n32bitmap.allocN32Pixels(SCALE, SCALE); 155 n32bitmap.eraseColor(SK_ColorTRANSPARENT); 156 SkCanvas n32canvas(n32bitmap); 157 color_wheel_native(&n32canvas); 158 n32canvas.flush(); 159 #if SK_PMCOLOR_BYTE_ORDER(B,G,R,A) 160 const SkColorType ct = kRGBA_8888_SkColorType; 161 #elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A) 162 const SkColorType ct = kBGRA_8888_SkColorType; 163 #endif 164 static_assert(ct != kN32_SkColorType, "BRGA!=RGBA"); 165 SkAssertResult(sk_tool_utils::copy_to(¬N32bitmap, ct, n32bitmap)); 166 SkASSERT(notN32bitmap.colorType() == ct); 167 return SkImage::MakeFromBitmap(notN32bitmap); 168 } 169 170 DEF_SIMPLE_GM(not_native32_bitmap_config, canvas, SCALE, SCALE) { 171 sk_sp<SkImage> notN32image(make_not_native32_color_wheel()); 172 SkASSERT(notN32image); 173 sk_tool_utils::draw_checkerboard(canvas, SK_ColorLTGRAY, SK_ColorWHITE, 8); 174 canvas->drawImage(notN32image.get(), 0.0f, 0.0f); 175 } 176 177 static uint32_t make_pixel(int x, int y, SkAlphaType alphaType) { 178 SkASSERT(x >= 0 && x < SCALE); 179 SkASSERT(y >= 0 && y < SCALE); 180 181 SkScalar R = SCALE / 2.0f; 182 183 uint32_t alpha = 0x00; 184 185 if ((x - R) * (x - R) + (y - R) * (y - R) < R * R) { 186 alpha = 0xFF; 187 } 188 189 uint32_t component; 190 switch (alphaType) { 191 case kPremul_SkAlphaType: 192 component = alpha; 193 break; 194 case kUnpremul_SkAlphaType: 195 component = 0xFF; 196 break; 197 default: 198 SkFAIL("Should not get here - invalid alpha type"); 199 return 0xFF000000; 200 } 201 return alpha << 24 | component; 202 } 203 204 static void make_color_test_bitmap_variant( 205 SkColorType colorType, 206 SkAlphaType alphaType, 207 sk_sp<SkColorSpace> colorSpace, 208 SkBitmap* bm) 209 { 210 SkASSERT(colorType == kRGBA_8888_SkColorType || colorType == kBGRA_8888_SkColorType); 211 SkASSERT(alphaType == kPremul_SkAlphaType || alphaType == kUnpremul_SkAlphaType); 212 bm->allocPixels( 213 SkImageInfo::Make(SCALE, SCALE, colorType, alphaType, colorSpace)); 214 SkPixmap pm; 215 bm->peekPixels(&pm); 216 for (int y = 0; y < bm->height(); y++) { 217 for (int x = 0; x < bm->width(); x++) { 218 *pm.writable_addr32(x, y) = make_pixel(x, y, alphaType); 219 } 220 } 221 } 222 223 DEF_SIMPLE_GM(all_variants_8888, canvas, 4 * SCALE + 30, 2 * SCALE + 10) { 224 sk_tool_utils::draw_checkerboard(canvas, SK_ColorLTGRAY, SK_ColorWHITE, 8); 225 226 sk_sp<SkColorSpace> colorSpaces[] { 227 SkColorSpace::MakeSRGB(), 228 nullptr, 229 }; 230 for (auto colorSpace : colorSpaces) { 231 canvas->save(); 232 for (auto alphaType : {kPremul_SkAlphaType, kUnpremul_SkAlphaType}) { 233 canvas->save(); 234 for (auto colorType : {kRGBA_8888_SkColorType, kBGRA_8888_SkColorType}) { 235 SkBitmap bm; 236 make_color_test_bitmap_variant(colorType, alphaType, colorSpace, &bm); 237 canvas->drawBitmap(bm, 0.0f, 0.0f); 238 canvas->translate(SCALE + 10, 0.0f); 239 } 240 canvas->restore(); 241 canvas->translate(0.0f, SCALE + 10); 242 } 243 canvas->restore(); 244 canvas->translate(2 * (SCALE + 10), 0.0f); 245 } 246 } 247