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 "sk_tool_utils.h" 9 #include "SkSurface.h" 10 #include "Resources.h" 11 #include "gm.h" 12 13 #include "SkMath.h" 14 #include "SkColorPriv.h" 15 16 static SkBitmap copy_bitmap(const SkBitmap& src, SkColorType colorType) { 17 SkBitmap copy; 18 src.copyTo(©, colorType); 19 copy.setImmutable(); 20 return copy; 21 } 22 23 #define SCALE 128 24 25 // Make either A8 or gray8 bitmap. 26 static 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 53 static 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 65 static 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; 78 sk_tool_utils::set_portable_typeface(&p, nullptr, SkTypeface::kBold); 79 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 89 template <typename T> 90 int 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 99 static SkPMColor premultiply_color(SkColor c) { 100 return SkPremultiplyARGBInline(SkColorGetA(c), SkColorGetR(c), 101 SkColorGetG(c), SkColorGetB(c)); 102 } 103 104 static 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; 127 SkAutoTUnref<SkColorTable> ctable(new SkColorTable(pmColors, SK_ARRAY_COUNT(pmColors))); 128 SkImageInfo info = SkImageInfo::Make(SCALE, SCALE, kIndex_8_SkColorType, 129 kPremul_SkAlphaType); 130 bm.allocPixels(info, nullptr, ctable); 131 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 143 static 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 153 DEF_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); 158 sk_tool_utils::set_portable_typeface(&p, nullptr); 159 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 } 193 194 // Works on Ganesh, fails on Raster. 195 SkImage* make_not_native32_color_wheel() { 196 SkBitmap n32bitmap, notN32bitmap; 197 n32bitmap.allocN32Pixels(SCALE, SCALE); 198 n32bitmap.eraseColor(SK_ColorTRANSPARENT); 199 SkCanvas n32canvas(n32bitmap); 200 color_wheel_native(&n32canvas); 201 n32canvas.flush(); 202 #if SK_PMCOLOR_BYTE_ORDER(B,G,R,A) 203 const SkColorType ct = kRGBA_8888_SkColorType; 204 #elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A) 205 const SkColorType ct = kBGRA_8888_SkColorType; 206 #endif 207 static_assert(ct != kN32_SkColorType, "BRGA!=RGBA"); 208 SkAssertResult(n32bitmap.copyTo(¬N32bitmap, ct)); 209 SkASSERT(notN32bitmap.colorType() == ct); 210 return SkImage::NewFromBitmap(notN32bitmap); 211 } 212 213 DEF_SIMPLE_GM(not_native32_bitmap_config, canvas, SCALE, SCALE) { 214 SkAutoTUnref<SkImage> notN32image(make_not_native32_color_wheel()); 215 SkASSERT(notN32image); 216 sk_tool_utils::draw_checkerboard(canvas, SK_ColorLTGRAY, SK_ColorWHITE, 8); 217 canvas->drawImage(notN32image, 0.0f, 0.0f); 218 } 219