f2c56a591ed14a0ed5ea0277d7698faf8c87f817
[platform/framework/web/crosswalk.git] / src / third_party / skia / gm / typeface.cpp
1 /*
2  * Copyright 2012 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 "SkString.h"
11 #include "SkTypeface.h"
12 #include "SkTypes.h"
13
14 static const char* gFaces[] = {
15     "Times Roman",
16     "Hiragino Maru Gothic Pro",
17     "Papyrus",
18     "Helvetica",
19     "Courier New"
20 };
21
22 class TypefaceGM : public skiagm::GM {
23 public:
24     TypefaceGM() {
25         fFaces = new SkTypeface*[SK_ARRAY_COUNT(gFaces)];
26         for (size_t i = 0; i < SK_ARRAY_COUNT(gFaces); i++) {
27             fFaces[i] = SkTypeface::CreateFromName(gFaces[i], SkTypeface::kNormal);
28         }
29     }
30
31     virtual ~TypefaceGM() {
32         for (size_t i = 0; i < SK_ARRAY_COUNT(gFaces); i++) {
33             SkSafeUnref(fFaces[i]);
34         }
35         delete [] fFaces;
36     }
37
38 protected:
39     virtual SkString onShortName() SK_OVERRIDE {
40         return SkString("typeface");
41     }
42
43     virtual SkISize onISize() SK_OVERRIDE {
44         return SkISize::Make(640, 480);
45     }
46
47     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
48         SkString text("Typefaces are fun!");
49         SkScalar y = 0;
50
51         SkPaint paint;
52         paint.setAntiAlias(true);
53         for (int i = 0; i < (int)SK_ARRAY_COUNT(gFaces); i++) {
54             this->drawWithFace(text, i, y, paint, canvas);
55         }
56         // Now go backwards
57         for (int i = SK_ARRAY_COUNT(gFaces) - 1; i >= 0; i--) {
58             this->drawWithFace(text, i, y, paint, canvas);
59         }
60     }
61
62 private:
63     void drawWithFace(const SkString& text, int i, SkScalar& y, SkPaint& paint,
64                       SkCanvas* canvas) {
65         paint.setTypeface(fFaces[i]);
66         y += paint.getFontMetrics(NULL);
67         canvas->drawText(text.c_str(), text.size(), 0, y, paint);
68     }
69
70     SkTypeface** fFaces;
71
72     typedef skiagm::GM INHERITED;
73 };
74
75 ///////////////////////////////////////////////////////////////////////////////
76
77 static void getGlyphPositions(const SkPaint& paint, const uint16_t glyphs[],
78                              int count, SkScalar x, SkScalar y, SkPoint pos[]) {
79     SkASSERT(SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding());
80
81     SkAutoSTMalloc<128, SkScalar> widthStorage(count);
82     SkScalar* widths = widthStorage.get();
83     paint.getTextWidths(glyphs, count * sizeof(uint16_t), widths);
84
85     for (int i = 0; i < count; ++i) {
86         pos[i].set(x, y);
87         x += widths[i];
88     }
89 }
90
91 static void applyKerning(SkPoint pos[], const int32_t adjustments[], int count,
92                          const SkPaint& paint) {
93     SkScalar scale = paint.getTextSize() / paint.getTypeface()->getUnitsPerEm();
94
95     SkScalar globalAdj = 0;
96     for (int i = 0; i < count - 1; ++i) {
97         globalAdj += adjustments[i] * scale;
98         pos[i + 1].fX += globalAdj;
99     }
100 }
101
102 static void drawKernText(SkCanvas* canvas, const void* text, size_t len,
103                          SkScalar x, SkScalar y, const SkPaint& paint) {
104     SkTypeface* face = paint.getTypeface();
105     if (!face) {
106         canvas->drawText(text, len, x, y, paint);
107         return;
108     }
109
110     SkAutoSTMalloc<128, uint16_t> glyphStorage(len);
111     uint16_t* glyphs = glyphStorage.get();
112     int glyphCount = paint.textToGlyphs(text, len, glyphs);
113     if (glyphCount < 1) {
114         return;
115     }
116
117     SkAutoSTMalloc<128, int32_t> adjustmentStorage(glyphCount - 1);
118     int32_t* adjustments = adjustmentStorage.get();
119     if (!face->getKerningPairAdjustments(glyphs, glyphCount, adjustments)) {
120         canvas->drawText(text, len, x, y, paint);
121         return;
122     }
123
124     SkPaint glyphPaint(paint);
125     glyphPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
126
127     SkAutoSTMalloc<128, SkPoint> posStorage(glyphCount);
128     SkPoint* pos = posStorage.get();
129     getGlyphPositions(glyphPaint, glyphs, glyphCount, x, y, pos);
130
131     applyKerning(pos, adjustments, glyphCount, glyphPaint);
132     canvas->drawPosText(glyphs, glyphCount * sizeof(uint16_t), pos, glyphPaint);
133 }
134
135 static const struct {
136     const char* fName;
137     SkTypeface::Style   fStyle;
138 } gFaceStyles[] = {
139     { "sans-serif", SkTypeface::kNormal },
140     { "sans-serif", SkTypeface::kBold },
141     { "sans-serif", SkTypeface::kItalic },
142     { "sans-serif", SkTypeface::kBoldItalic },
143     { "serif", SkTypeface::kNormal },
144     { "serif", SkTypeface::kBold },
145     { "serif", SkTypeface::kItalic },
146     { "serif", SkTypeface::kBoldItalic },
147     { "monospace", SkTypeface::kNormal },
148     { "monospace", SkTypeface::kBold },
149     { "monospace", SkTypeface::kItalic },
150     { "monospace", SkTypeface::kBoldItalic },
151 };
152
153 static const int gFaceStylesCount = SK_ARRAY_COUNT(gFaceStyles);
154
155 class TypefaceStylesGM : public skiagm::GM {
156     SkTypeface* fFaces[gFaceStylesCount];
157     bool fApplyKerning;
158
159 public:
160     TypefaceStylesGM(bool applyKerning) : fApplyKerning(applyKerning) {
161         for (int i = 0; i < gFaceStylesCount; i++) {
162             fFaces[i] = SkTypeface::CreateFromName(gFaceStyles[i].fName,
163                                                    gFaceStyles[i].fStyle);
164         }
165     }
166
167     virtual ~TypefaceStylesGM() {
168         for (int i = 0; i < gFaceStylesCount; i++) {
169             SkSafeUnref(fFaces[i]);
170         }
171     }
172
173 protected:
174     virtual SkString onShortName() SK_OVERRIDE {
175         SkString name("typefacestyles");
176         if (fApplyKerning) {
177             name.append("_kerning");
178         }
179         return name;
180     }
181
182     virtual SkISize onISize() SK_OVERRIDE {
183         return SkISize::Make(640, 480);
184     }
185
186     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
187         SkPaint paint;
188         paint.setAntiAlias(true);
189         paint.setTextSize(SkIntToScalar(30));
190
191         const char* text = fApplyKerning ? "Type AWAY" : "Hamburgefons";
192         const size_t textLen = strlen(text);
193
194         SkScalar x = SkIntToScalar(10);
195         SkScalar dy = paint.getFontMetrics(NULL);
196         SkScalar y = dy;
197
198         if (fApplyKerning) {
199             paint.setSubpixelText(true);
200         } else {
201             paint.setLinearText(true);
202         }
203         for (int i = 0; i < gFaceStylesCount; i++) {
204             paint.setTypeface(fFaces[i]);
205             canvas->drawText(text, textLen, x, y, paint);
206             if (fApplyKerning) {
207                 drawKernText(canvas, text, textLen, x + 240, y, paint);
208             }
209             y += dy;
210         }
211     }
212
213 private:
214     typedef skiagm::GM INHERITED;
215 };
216
217 ///////////////////////////////////////////////////////////////////////////////
218
219 DEF_GM( return new TypefaceGM; )
220 DEF_GM( return new TypefaceStylesGM(false); )
221 DEF_GM( return new TypefaceStylesGM(true); )