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 14static 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 28static 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 41static CGContextRef makeCG(const SkImageInfo& info, const void* addr, 42 size_t rowBytes) { 43 if (kN32_SkColorType != info.colorType() || NULL == addr) { 44 return NULL; 45 } 46 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB(); 47 CGContextRef cg = CGBitmapContextCreate((void*)addr, info.width(), info.height(), 48 8, rowBytes, space, BITMAP_INFO_RGB); 49 CFRelease(space); 50 51 CGContextSetAllowsFontSubpixelQuantization(cg, false); 52 CGContextSetShouldSubpixelQuantizeFonts(cg, false); 53 54 return cg; 55} 56 57extern CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face); 58 59static 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 68static 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 89static 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 102namespace 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 113class GammaTextGM : public GM { 114public: 115 GammaTextGM() { 116 117 } 118 119protected: 120 virtual SkString onShortName() { 121 return SkString("gammatext"); 122 } 123 124 virtual SkISize onISize() { 125 return SkISize::Make(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 = 0; 147 { 148 SkImageInfo info; 149 size_t rowBytes; 150 const void* addr = canvas->peekPixels(&info, &rowBytes); 151 if (addr) { 152 cg = makeCG(info, addr, rowBytes); 153 } 154 } 155#endif 156 157 drawGrad(canvas); 158 159 const SkColor fg[] = { 160 0xFFFFFFFF, 161 0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF, 162 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 163 0xFF000000, 164 }; 165 166 const char* text = "Hamburgefons"; 167 size_t len = strlen(text); 168 169 SkPaint paint; 170 setFont(&paint, "Times"); 171 paint.setTextSize(SkIntToScalar(16)); 172 paint.setAntiAlias(true); 173 paint.setLCDRenderText(true); 174 175 SkScalar x = SkIntToScalar(10); 176 for (size_t i = 0; i < SK_ARRAY_COUNT(fg); ++i) { 177 paint.setColor(fg[i]); 178 179 SkScalar y = SkIntToScalar(40); 180 SkScalar stopy = SkIntToScalar(HEIGHT); 181 while (y < stopy) { 182 if (true) { 183 canvas->drawText(text, len, x, y, paint); 184 } 185#ifdef SK_BUILD_FOR_MAC 186 else { 187 cgDrawText(cg, text, len, SkScalarToFloat(x), 188 static_cast<float>(HEIGHT) - SkScalarToFloat(y), 189 paint); 190 } 191#endif 192 y += paint.getTextSize() * 2; 193 } 194 x += SkIntToScalar(1024) / SK_ARRAY_COUNT(fg); 195 } 196#ifdef SK_BUILD_FOR_MAC 197 CGContextRelease(cg); 198#endif 199 } 200 201private: 202 typedef GM INHERITED; 203}; 204 205////////////////////////////////////////////////////////////////////////////// 206 207static GM* MyFactory(void*) { return new GammaTextGM; } 208static GMRegistry reg(MyFactory); 209 210} 211