| 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 |