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