OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "gm.h" | 8 #include "gm.h" |
9 #include "SkCanvas.h" | 9 #include "SkCanvas.h" |
10 #include "SkString.h" | 10 #include "SkString.h" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 canvas->drawText(text.c_str(), text.size(), 0, y, paint); | 67 canvas->drawText(text.c_str(), text.size(), 0, y, paint); |
68 } | 68 } |
69 | 69 |
70 SkTypeface** fFaces; | 70 SkTypeface** fFaces; |
71 | 71 |
72 typedef skiagm::GM INHERITED; | 72 typedef skiagm::GM INHERITED; |
73 }; | 73 }; |
74 | 74 |
75 /////////////////////////////////////////////////////////////////////////////// | 75 /////////////////////////////////////////////////////////////////////////////// |
76 | 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 |
77 static const struct { | 135 static const struct { |
78 const char* fName; | 136 const char* fName; |
79 SkTypeface::Style fStyle; | 137 SkTypeface::Style fStyle; |
80 } gFaceStyles[] = { | 138 } gFaceStyles[] = { |
81 { "sans-serif", SkTypeface::kNormal }, | 139 { "sans-serif", SkTypeface::kNormal }, |
82 { "sans-serif", SkTypeface::kBold }, | 140 { "sans-serif", SkTypeface::kBold }, |
83 { "sans-serif", SkTypeface::kItalic }, | 141 { "sans-serif", SkTypeface::kItalic }, |
84 { "sans-serif", SkTypeface::kBoldItalic }, | 142 { "sans-serif", SkTypeface::kBoldItalic }, |
85 { "serif", SkTypeface::kNormal }, | 143 { "serif", SkTypeface::kNormal }, |
86 { "serif", SkTypeface::kBold }, | 144 { "serif", SkTypeface::kBold }, |
87 { "serif", SkTypeface::kItalic }, | 145 { "serif", SkTypeface::kItalic }, |
88 { "serif", SkTypeface::kBoldItalic }, | 146 { "serif", SkTypeface::kBoldItalic }, |
89 { "monospace", SkTypeface::kNormal }, | 147 { "monospace", SkTypeface::kNormal }, |
90 { "monospace", SkTypeface::kBold }, | 148 { "monospace", SkTypeface::kBold }, |
91 { "monospace", SkTypeface::kItalic }, | 149 { "monospace", SkTypeface::kItalic }, |
92 { "monospace", SkTypeface::kBoldItalic }, | 150 { "monospace", SkTypeface::kBoldItalic }, |
93 }; | 151 }; |
94 | 152 |
95 static const int gFaceStylesCount = SK_ARRAY_COUNT(gFaceStyles); | 153 static const int gFaceStylesCount = SK_ARRAY_COUNT(gFaceStyles); |
96 | 154 |
97 class TypefaceStylesGM : public skiagm::GM { | 155 class TypefaceStylesGM : public skiagm::GM { |
98 SkTypeface* fFaces[gFaceStylesCount]; | 156 SkTypeface* fFaces[gFaceStylesCount]; |
| 157 bool fApplyKerning; |
99 | 158 |
100 public: | 159 public: |
101 TypefaceStylesGM() { | 160 TypefaceStylesGM(bool applyKerning) : fApplyKerning(applyKerning) { |
102 for (int i = 0; i < gFaceStylesCount; i++) { | 161 for (int i = 0; i < gFaceStylesCount; i++) { |
103 fFaces[i] = SkTypeface::CreateFromName(gFaceStyles[i].fName, | 162 fFaces[i] = SkTypeface::CreateFromName(gFaceStyles[i].fName, |
104 gFaceStyles[i].fStyle); | 163 gFaceStyles[i].fStyle); |
105 } | 164 } |
106 } | 165 } |
107 | 166 |
108 virtual ~TypefaceStylesGM() { | 167 virtual ~TypefaceStylesGM() { |
109 for (int i = 0; i < gFaceStylesCount; i++) { | 168 for (int i = 0; i < gFaceStylesCount; i++) { |
110 SkSafeUnref(fFaces[i]); | 169 SkSafeUnref(fFaces[i]); |
111 } | 170 } |
112 } | 171 } |
113 | 172 |
114 protected: | 173 protected: |
115 virtual SkString onShortName() SK_OVERRIDE { | 174 virtual SkString onShortName() SK_OVERRIDE { |
116 return SkString("typefacestyles"); | 175 SkString name("typefacestyles"); |
| 176 if (fApplyKerning) { |
| 177 name.append("_kerning"); |
| 178 } |
| 179 return name; |
117 } | 180 } |
118 | 181 |
119 virtual SkISize onISize() SK_OVERRIDE { | 182 virtual SkISize onISize() SK_OVERRIDE { |
120 return SkISize::Make(640, 480); | 183 return SkISize::Make(640, 480); |
121 } | 184 } |
122 | 185 |
123 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { | 186 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { |
124 SkPaint paint; | 187 SkPaint paint; |
125 paint.setAntiAlias(true); | 188 paint.setAntiAlias(true); |
126 paint.setTextSize(SkIntToScalar(30)); | 189 paint.setTextSize(SkIntToScalar(30)); |
127 | 190 |
128 const char* text = "Hamburgefons"; | 191 const char* text = fApplyKerning ? "Type AWAY" : "Hamburgefons"; |
129 const size_t textLen = strlen(text); | 192 const size_t textLen = strlen(text); |
130 | 193 |
131 SkScalar x = SkIntToScalar(10); | 194 SkScalar x = SkIntToScalar(10); |
132 SkScalar dy = paint.getFontMetrics(NULL); | 195 SkScalar dy = paint.getFontMetrics(NULL); |
133 SkScalar y = dy; | 196 SkScalar y = dy; |
134 | 197 |
135 paint.setLinearText(true); | 198 if (fApplyKerning) { |
| 199 paint.setSubpixelText(true); |
| 200 } else { |
| 201 paint.setLinearText(true); |
| 202 } |
136 for (int i = 0; i < gFaceStylesCount; i++) { | 203 for (int i = 0; i < gFaceStylesCount; i++) { |
137 paint.setTypeface(fFaces[i]); | 204 paint.setTypeface(fFaces[i]); |
138 canvas->drawText(text, textLen, x, y, paint); | 205 canvas->drawText(text, textLen, x, y, paint); |
| 206 if (fApplyKerning) { |
| 207 drawKernText(canvas, text, textLen, x + 240, y, paint); |
| 208 } |
139 y += dy; | 209 y += dy; |
140 } | 210 } |
141 } | 211 } |
142 | 212 |
143 private: | 213 private: |
144 typedef skiagm::GM INHERITED; | 214 typedef skiagm::GM INHERITED; |
145 }; | 215 }; |
146 | 216 |
147 /////////////////////////////////////////////////////////////////////////////// | 217 /////////////////////////////////////////////////////////////////////////////// |
148 | 218 |
149 DEF_GM( return new TypefaceGM; ) | 219 DEF_GM( return new TypefaceGM; ) |
150 DEF_GM( return new TypefaceStylesGM; ) | 220 DEF_GM( return new TypefaceStylesGM(false); ) |
| 221 DEF_GM( return new TypefaceStylesGM(true); ) |
OLD | NEW |