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
make_heatGradient(const SkPoint pts[2])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
setFont(SkPaint * paint,const char name[])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
makeCG(const SkBitmap & bm)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
typefaceToCGFont(const SkTypeface * face)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
cgSetPaintForText(CGContextRef cg,const SkPaint & paint)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
cgDrawText(CGContextRef cg,const void * text,size_t len,float x,float y,const SkPaint & paint)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:
GammaTextGM()113 GammaTextGM() {
114
115 }
116
117 protected:
onShortName()118 virtual SkString onShortName() {
119 return SkString("gammatext");
120 }
121
onISize()122 virtual SkISize onISize() {
123 return make_isize(1024, HEIGHT);
124 }
125
drawGrad(SkCanvas * canvas)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
onDraw(SkCanvas * canvas)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
MyFactory(void *)189 static GM* MyFactory(void*) { return new GammaTextGM; }
190 static GMRegistry reg(MyFactory);
191
192 }
193