1 /* 2 * Copyright 2011 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 "gm.h" 9 #include "SkCanvas.h" 10 #include "SkPath.h" 11 #include "SkGradientShader.h" 12 #include "SkTypeface.h" 13 14 static SkShader* make_heatGradient(const SkPoint pts[2]) { 15 const SkColor colors[] = { 16 SK_ColorBLACK, SK_ColorBLUE, SK_ColorCYAN, SK_ColorGREEN, 17 SK_ColorYELLOW, SK_ColorRED, SK_ColorWHITE 18 }; 19 const SkColor bw[] = { SK_ColorBLACK, SK_ColorWHITE }; 20 21 return SkGradientShader::CreateLinear(pts, bw, NULL, 22 SK_ARRAY_COUNT(bw), 23 SkShader::kClamp_TileMode); 24 } 25 26 static bool setFont(SkPaint* paint, const char name[]) { 27 SkTypeface* tf = SkTypeface::CreateFromName(name, SkTypeface::kNormal); 28 if (tf) { 29 paint->setTypeface(tf)->unref(); 30 return true; 31 } 32 return false; 33 } 34 35 #ifdef SK_BUILD_FOR_MAC 36 #import <ApplicationServices/ApplicationServices.h> 37 #define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host) 38 39 static CGContextRef makeCG(const SkBitmap& bm) { 40 if (SkBitmap::kARGB_8888_Config != bm.config() || 41 NULL == bm.getPixels()) { 42 return NULL; 43 } 44 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB(); 45 CGContextRef cg = CGBitmapContextCreate(bm.getPixels(), bm.width(), bm.height(), 46 8, bm.rowBytes(), space, BITMAP_INFO_RGB); 47 CFRelease(space); 48 49 CGContextSetAllowsFontSubpixelQuantization(cg, false); 50 CGContextSetShouldSubpixelQuantizeFonts(cg, false); 51 52 return cg; 53 } 54 55 extern CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face); 56 57 static CGFontRef typefaceToCGFont(const SkTypeface* face) { 58 if (NULL == face) { 59 return 0; 60 } 61 62 CTFontRef ct = SkTypeface_GetCTFontRef(face); 63 return CTFontCopyGraphicsFont(ct, NULL); 64 } 65 66 static void cgSetPaintForText(CGContextRef cg, const SkPaint& paint) { 67 SkColor c = paint.getColor(); 68 CGFloat rgba[] = { 69 SkColorGetB(c) / 255.0, 70 SkColorGetG(c) / 255.0, 71 SkColorGetR(c) / 255.0, 72 SkColorGetA(c) / 255.0, 73 }; 74 CGContextSetRGBFillColor(cg, rgba[0], rgba[1], rgba[2], rgba[3]); 75 76 CGContextSetTextDrawingMode(cg, kCGTextFill); 77 CGContextSetFont(cg, typefaceToCGFont(paint.getTypeface())); 78 CGContextSetFontSize(cg, SkScalarToFloat(paint.getTextSize())); 79 80 CGContextSetAllowsFontSubpixelPositioning(cg, paint.isSubpixelText()); 81 CGContextSetShouldSubpixelPositionFonts(cg, paint.isSubpixelText()); 82 83 CGContextSetShouldAntialias(cg, paint.isAntiAlias()); 84 CGContextSetShouldSmoothFonts(cg, paint.isLCDRenderText()); 85 } 86 87 static void cgDrawText(CGContextRef cg, const void* text, size_t len, 88 float x, float y, const SkPaint& paint) { 89 if (cg) { 90 cgSetPaintForText(cg, paint); 91 92 uint16_t glyphs[200]; 93 int count = paint.textToGlyphs(text, len, glyphs); 94 95 CGContextShowGlyphsAtPoint(cg, x, y, glyphs, count); 96 } 97 } 98 #endif 99 100 namespace skiagm { 101 102 /** 103 Test a set of clipping problems discovered while writing blitAntiRect, 104 and test all the code paths through the clipping blitters. 105 Each region should show as a blue center surrounded by a 2px green 106 border, with no red. 107 */ 108 109 #define HEIGHT 480 110 111 class GammaTextGM : public GM { 112 public: 113 GammaTextGM() { 114 115 } 116 117 protected: 118 virtual SkString onShortName() { 119 return SkString("gammatext"); 120 } 121 122 virtual SkISize onISize() { 123 return make_isize(1024, HEIGHT); 124 } 125 126 static void drawGrad(SkCanvas* canvas) { 127 SkPoint pts[] = { { 0, 0 }, { 0, HEIGHT } }; 128 #if 0 129 const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE }; 130 SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode); 131 #else 132 SkShader* s = make_heatGradient(pts); 133 #endif 134 135 canvas->clear(SK_ColorRED); 136 SkPaint paint; 137 paint.setShader(s)->unref(); 138 SkRect r = { 0, 0, 1024, HEIGHT }; 139 canvas->drawRect(r, paint); 140 } 141 142 virtual void onDraw(SkCanvas* canvas) { 143 #ifdef SK_BUILD_FOR_MAC 144 CGContextRef cg = makeCG(canvas->getDevice()->accessBitmap(false)); 145 #endif 146 147 drawGrad(canvas); 148 149 const SkColor fg[] = { 150 0xFFFFFFFF, 151 0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF, 152 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 153 0xFF000000, 154 }; 155 156 const char* text = "Hamburgefons"; 157 size_t len = strlen(text); 158 159 SkPaint paint; 160 setFont(&paint, "Times"); 161 paint.setTextSize(SkIntToScalar(16)); 162 paint.setAntiAlias(true); 163 paint.setLCDRenderText(true); 164 165 SkScalar x = 10; 166 for (size_t i = 0; i < SK_ARRAY_COUNT(fg); ++i) { 167 paint.setColor(fg[i]); 168 169 SkScalar y = 40; 170 SkScalar stopy = HEIGHT; 171 while (y < stopy) { 172 #if 1 173 canvas->drawText(text, len, x, y, paint); 174 #else 175 cgDrawText(cg, text, len, x, HEIGHT - y, paint); 176 #endif 177 y += paint.getTextSize() * 2; 178 } 179 x += SkIntToScalar(1024) / SK_ARRAY_COUNT(fg); 180 } 181 } 182 183 private: 184 typedef GM INHERITED; 185 }; 186 187 ////////////////////////////////////////////////////////////////////////////// 188 189 static GM* MyFactory(void*) { return new GammaTextGM; } 190 static GMRegistry reg(MyFactory); 191 192 } 193