blob: d88efa51bf50edbad15489461a9cbdbfe8635729 [file] [log] [blame]
scroggo@google.com3cb969f2012-07-27 20:39:19 +00001/*
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
reed@google.com35fe7372013-10-30 15:07:03 +000014static void getGlyphPositions(const SkPaint& paint, const uint16_t glyphs[],
15 int count, SkScalar x, SkScalar y, SkPoint pos[]) {
16 SkASSERT(SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding());
17
18 SkAutoSTMalloc<128, SkScalar> widthStorage(count);
19 SkScalar* widths = widthStorage.get();
20 paint.getTextWidths(glyphs, count * sizeof(uint16_t), widths);
skia.committer@gmail.com7ed98df2013-10-31 07:01:53 +000021
reed@google.com35fe7372013-10-30 15:07:03 +000022 for (int i = 0; i < count; ++i) {
23 pos[i].set(x, y);
24 x += widths[i];
25 }
26}
27
28static void applyKerning(SkPoint pos[], const int32_t adjustments[], int count,
29 const SkPaint& paint) {
30 SkScalar scale = paint.getTextSize() / paint.getTypeface()->getUnitsPerEm();
31
32 SkScalar globalAdj = 0;
33 for (int i = 0; i < count - 1; ++i) {
34 globalAdj += adjustments[i] * scale;
35 pos[i + 1].fX += globalAdj;
36 }
37}
38
39static void drawKernText(SkCanvas* canvas, const void* text, size_t len,
40 SkScalar x, SkScalar y, const SkPaint& paint) {
41 SkTypeface* face = paint.getTypeface();
42 if (!face) {
43 canvas->drawText(text, len, x, y, paint);
44 return;
45 }
46
47 SkAutoSTMalloc<128, uint16_t> glyphStorage(len);
48 uint16_t* glyphs = glyphStorage.get();
49 int glyphCount = paint.textToGlyphs(text, len, glyphs);
50 if (glyphCount < 1) {
51 return;
52 }
53
54 SkAutoSTMalloc<128, int32_t> adjustmentStorage(glyphCount - 1);
55 int32_t* adjustments = adjustmentStorage.get();
56 if (!face->getKerningPairAdjustments(glyphs, glyphCount, adjustments)) {
57 canvas->drawText(text, len, x, y, paint);
58 return;
59 }
60
61 SkPaint glyphPaint(paint);
62 glyphPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
63
64 SkAutoSTMalloc<128, SkPoint> posStorage(glyphCount);
65 SkPoint* pos = posStorage.get();
66 getGlyphPositions(glyphPaint, glyphs, glyphCount, x, y, pos);
67
68 applyKerning(pos, adjustments, glyphCount, glyphPaint);
69 canvas->drawPosText(glyphs, glyphCount * sizeof(uint16_t), pos, glyphPaint);
70}
71
reed@google.com92abe482013-02-26 16:57:16 +000072static const struct {
73 const char* fName;
74 SkTypeface::Style fStyle;
75} gFaceStyles[] = {
76 { "sans-serif", SkTypeface::kNormal },
77 { "sans-serif", SkTypeface::kBold },
78 { "sans-serif", SkTypeface::kItalic },
79 { "sans-serif", SkTypeface::kBoldItalic },
80 { "serif", SkTypeface::kNormal },
81 { "serif", SkTypeface::kBold },
82 { "serif", SkTypeface::kItalic },
83 { "serif", SkTypeface::kBoldItalic },
84 { "monospace", SkTypeface::kNormal },
85 { "monospace", SkTypeface::kBold },
86 { "monospace", SkTypeface::kItalic },
87 { "monospace", SkTypeface::kBoldItalic },
88};
scroggo@google.com3cb969f2012-07-27 20:39:19 +000089
reed@google.com92abe482013-02-26 16:57:16 +000090static const int gFaceStylesCount = SK_ARRAY_COUNT(gFaceStyles);
91
92class TypefaceStylesGM : public skiagm::GM {
93 SkTypeface* fFaces[gFaceStylesCount];
reed@google.com35fe7372013-10-30 15:07:03 +000094 bool fApplyKerning;
skia.committer@gmail.com12eea2b2013-02-27 07:10:10 +000095
reed@google.com92abe482013-02-26 16:57:16 +000096public:
kkinnunenb4a797f2015-05-21 06:15:28 -070097 TypefaceStylesGM(bool applyKerning)
98 : fApplyKerning(applyKerning) {
99 memset(fFaces, 0, sizeof(fFaces));
reed@google.com92abe482013-02-26 16:57:16 +0000100 }
skia.committer@gmail.com12eea2b2013-02-27 07:10:10 +0000101
reed@google.com92abe482013-02-26 16:57:16 +0000102 virtual ~TypefaceStylesGM() {
103 for (int i = 0; i < gFaceStylesCount; i++) {
104 SkSafeUnref(fFaces[i]);
105 }
106 }
skia.committer@gmail.com12eea2b2013-02-27 07:10:10 +0000107
reed@google.com92abe482013-02-26 16:57:16 +0000108protected:
kkinnunenb4a797f2015-05-21 06:15:28 -0700109 void onOnceBeforeDraw() override {
110 for (int i = 0; i < gFaceStylesCount; i++) {
caryclark37213552015-07-24 11:08:01 -0700111 fFaces[i] = SkTypeface::CreateFromName(
112 sk_tool_utils::platform_font_name(gFaceStyles[i].fName), gFaceStyles[i].fStyle);
kkinnunenb4a797f2015-05-21 06:15:28 -0700113 }
114 }
115
mtklein36352bf2015-03-25 18:17:31 -0700116 SkString onShortName() override {
reed@google.com35fe7372013-10-30 15:07:03 +0000117 SkString name("typefacestyles");
118 if (fApplyKerning) {
119 name.append("_kerning");
120 }
caryclark37213552015-07-24 11:08:01 -0700121 name.append(sk_tool_utils::major_platform_os_name());
reed@google.com35fe7372013-10-30 15:07:03 +0000122 return name;
reed@google.com92abe482013-02-26 16:57:16 +0000123 }
skia.committer@gmail.com12eea2b2013-02-27 07:10:10 +0000124
mtklein36352bf2015-03-25 18:17:31 -0700125 SkISize onISize() override {
reed@google.com92abe482013-02-26 16:57:16 +0000126 return SkISize::Make(640, 480);
127 }
skia.committer@gmail.com12eea2b2013-02-27 07:10:10 +0000128
mtklein36352bf2015-03-25 18:17:31 -0700129 void onDraw(SkCanvas* canvas) override {
reed@google.com92abe482013-02-26 16:57:16 +0000130 SkPaint paint;
131 paint.setAntiAlias(true);
132 paint.setTextSize(SkIntToScalar(30));
skia.committer@gmail.com12eea2b2013-02-27 07:10:10 +0000133
reed@google.com35fe7372013-10-30 15:07:03 +0000134 const char* text = fApplyKerning ? "Type AWAY" : "Hamburgefons";
reed@google.com92abe482013-02-26 16:57:16 +0000135 const size_t textLen = strlen(text);
skia.committer@gmail.com12eea2b2013-02-27 07:10:10 +0000136
reed@google.com92abe482013-02-26 16:57:16 +0000137 SkScalar x = SkIntToScalar(10);
halcanary96fcdcc2015-08-27 07:41:13 -0700138 SkScalar dy = paint.getFontMetrics(nullptr);
reed@google.com92abe482013-02-26 16:57:16 +0000139 SkScalar y = dy;
skia.committer@gmail.com12eea2b2013-02-27 07:10:10 +0000140
reed@google.com35fe7372013-10-30 15:07:03 +0000141 if (fApplyKerning) {
142 paint.setSubpixelText(true);
143 } else {
144 paint.setLinearText(true);
145 }
reed@google.com92abe482013-02-26 16:57:16 +0000146 for (int i = 0; i < gFaceStylesCount; i++) {
147 paint.setTypeface(fFaces[i]);
148 canvas->drawText(text, textLen, x, y, paint);
reed@google.com35fe7372013-10-30 15:07:03 +0000149 if (fApplyKerning) {
150 drawKernText(canvas, text, textLen, x + 240, y, paint);
151 }
reed@google.com92abe482013-02-26 16:57:16 +0000152 y += dy;
153 }
154 }
skia.committer@gmail.com12eea2b2013-02-27 07:10:10 +0000155
reed@google.com92abe482013-02-26 16:57:16 +0000156private:
157 typedef skiagm::GM INHERITED;
158};
skia.committer@gmail.com12eea2b2013-02-27 07:10:10 +0000159
reed@google.com92abe482013-02-26 16:57:16 +0000160///////////////////////////////////////////////////////////////////////////////
161
reed@google.com35fe7372013-10-30 15:07:03 +0000162DEF_GM( return new TypefaceStylesGM(false); )
163DEF_GM( return new TypefaceStylesGM(true); )