Home | History | Annotate | Download | only in gm
      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(&copy, 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::Bold());
     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("images/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(&notN32bitmap, 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             SK_ABORT("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     const SkPixmap& pm = bm->pixmap();
    215     for (int y = 0; y < pm.height(); y++) {
    216         for (int x = 0; x < pm.width(); x++) {
    217             *pm.writable_addr32(x, y) = make_pixel(x, y, alphaType);
    218         }
    219     }
    220 }
    221 
    222 DEF_SIMPLE_GM(all_variants_8888, canvas, 4 * SCALE + 30, 2 * SCALE + 10) {
    223     sk_tool_utils::draw_checkerboard(canvas, SK_ColorLTGRAY, SK_ColorWHITE, 8);
    224 
    225     sk_sp<SkColorSpace> colorSpaces[] {
    226         SkColorSpace::MakeSRGB(),
    227         nullptr,
    228     };
    229     for (auto colorSpace : colorSpaces) {
    230         canvas->save();
    231         for (auto alphaType : {kPremul_SkAlphaType, kUnpremul_SkAlphaType}) {
    232             canvas->save();
    233             for (auto colorType : {kRGBA_8888_SkColorType, kBGRA_8888_SkColorType}) {
    234                 SkBitmap bm;
    235                 make_color_test_bitmap_variant(colorType, alphaType, colorSpace, &bm);
    236                 canvas->drawBitmap(bm, 0.0f, 0.0f);
    237                 canvas->translate(SCALE + 10, 0.0f);
    238             }
    239             canvas->restore();
    240             canvas->translate(0.0f, SCALE + 10);
    241         }
    242         canvas->restore();
    243         canvas->translate(2 * (SCALE + 10), 0.0f);
    244     }
    245 }
    246