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 "Resources.h" 9 #include "SkCanvas.h" 10 #include "SkFont.h" 11 #include "SkStream.h" 12 #include "SkSurface.h" 13 #include "SkTextBlob.h" 14 #include "SkTo.h" 15 #include "SkTypeface.h" 16 #include "gm.h" 17 #include "sk_tool_utils.h" 18 19 class DFTextGM : public skiagm::GM { 20 public: DFTextGM()21 DFTextGM() { 22 this->setBGColor(0xFFFFFFFF); 23 } 24 25 protected: onOnceBeforeDraw()26 void onOnceBeforeDraw() override { 27 fEmojiTypeface = sk_tool_utils::emoji_typeface(); 28 fEmojiText = sk_tool_utils::emoji_sample_text(); 29 } 30 onShortName()31 SkString onShortName() override { 32 SkString name("dftext"); 33 name.append(sk_tool_utils::platform_font_manager()); 34 return name; 35 } 36 onISize()37 SkISize onISize() override { 38 return SkISize::Make(1024, 768); 39 } 40 onDraw(SkCanvas * inputCanvas)41 virtual void onDraw(SkCanvas* inputCanvas) override { 42 SkScalar textSizes[] = { 9.0f, 9.0f*2.0f, 9.0f*5.0f, 9.0f*2.0f*5.0f }; 43 SkScalar scales[] = { 2.0f*5.0f, 5.0f, 2.0f, 1.0f }; 44 45 // set up offscreen rendering with distance field text 46 GrContext* ctx = inputCanvas->getGrContext(); 47 SkISize size = onISize(); 48 SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(), kPremul_SkAlphaType, 49 inputCanvas->imageInfo().refColorSpace()); 50 SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag, 51 SkSurfaceProps::kLegacyFontHost_InitType); 52 auto surface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props)); 53 SkCanvas* canvas = surface ? surface->getCanvas() : inputCanvas; 54 // init our new canvas with the old canvas's matrix 55 canvas->setMatrix(inputCanvas->getTotalMatrix()); 56 // apply global scale to test glyph positioning 57 canvas->scale(1.05f, 1.05f); 58 canvas->clear(0xffffffff); 59 60 SkPaint paint; 61 paint.setAntiAlias(true); 62 63 SkFont font(sk_tool_utils::create_portable_typeface("serif", SkFontStyle())); 64 font.setSubpixel(true); 65 66 const char* text = "Hamburgefons"; 67 const size_t textLen = strlen(text); 68 69 // check scaling up 70 SkScalar x = SkIntToScalar(0); 71 SkScalar y = SkIntToScalar(78); 72 for (size_t i = 0; i < SK_ARRAY_COUNT(textSizes); ++i) { 73 SkAutoCanvasRestore acr(canvas, true); 74 canvas->translate(x, y); 75 canvas->scale(scales[i], scales[i]); 76 font.setSize(textSizes[i]); 77 canvas->drawSimpleText(text, textLen, kUTF8_SkTextEncoding, 0, 0, font, paint); 78 y += font.getMetrics(nullptr)*scales[i]; 79 } 80 81 // check rotation 82 for (size_t i = 0; i < 5; ++i) { 83 SkScalar rotX = SkIntToScalar(10); 84 SkScalar rotY = y; 85 86 SkAutoCanvasRestore acr(canvas, true); 87 canvas->translate(SkIntToScalar(10 + i * 200), -80); 88 canvas->rotate(SkIntToScalar(i * 5), rotX, rotY); 89 for (int ps = 6; ps <= 32; ps += 3) { 90 font.setSize(SkIntToScalar(ps)); 91 canvas->drawSimpleText(text, textLen, kUTF8_SkTextEncoding, rotX, rotY, font, paint); 92 rotY += font.getMetrics(nullptr); 93 } 94 } 95 96 // check scaling down 97 font.setEdging(SkFont::Edging::kSubpixelAntiAlias); 98 x = SkIntToScalar(680); 99 y = SkIntToScalar(20); 100 size_t arraySize = SK_ARRAY_COUNT(textSizes); 101 for (size_t i = 0; i < arraySize; ++i) { 102 SkAutoCanvasRestore acr(canvas, true); 103 canvas->translate(x, y); 104 SkScalar scaleFactor = SkScalarInvert(scales[arraySize - i - 1]); 105 canvas->scale(scaleFactor, scaleFactor); 106 font.setSize(textSizes[i]); 107 canvas->drawSimpleText(text, textLen, kUTF8_SkTextEncoding, 0, 0, font, paint); 108 y += font.getMetrics(nullptr)*scaleFactor; 109 } 110 111 // check pos text 112 { 113 SkAutoCanvasRestore acr(canvas, true); 114 115 canvas->scale(2.0f, 2.0f); 116 117 SkAutoTArray<SkGlyphID> glyphs(SkToInt(textLen)); 118 int count = font.textToGlyphs(text, textLen, kUTF8_SkTextEncoding, glyphs.get(), textLen); 119 SkAutoTArray<SkPoint> pos(count); 120 font.setSize(textSizes[0]); 121 font.getPos(glyphs.get(), count, pos.get(), {340, 75}); 122 123 auto blob = SkTextBlob::MakeFromPosText(glyphs.get(), count * sizeof(SkGlyphID), 124 pos.get(), font, kGlyphID_SkTextEncoding); 125 canvas->drawTextBlob(blob, 0, 0, paint); 126 } 127 128 129 // check gamma-corrected blending 130 const SkColor fg[] = { 131 0xFFFFFFFF, 132 0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF, 133 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 134 0xFF000000, 135 }; 136 137 paint.setColor(0xFFF7F3F7); 138 SkRect r = SkRect::MakeLTRB(670, 215, 820, 397); 139 canvas->drawRect(r, paint); 140 141 x = SkIntToScalar(680); 142 y = SkIntToScalar(235); 143 font.setSize(SkIntToScalar(19)); 144 for (size_t i = 0; i < SK_ARRAY_COUNT(fg); ++i) { 145 paint.setColor(fg[i]); 146 147 canvas->drawSimpleText(text, textLen, kUTF8_SkTextEncoding, x, y, font, paint); 148 y += font.getMetrics(nullptr); 149 } 150 151 paint.setColor(0xFF181C18); 152 r = SkRect::MakeLTRB(820, 215, 970, 397); 153 canvas->drawRect(r, paint); 154 155 x = SkIntToScalar(830); 156 y = SkIntToScalar(235); 157 font.setSize(SkIntToScalar(19)); 158 for (size_t i = 0; i < SK_ARRAY_COUNT(fg); ++i) { 159 paint.setColor(fg[i]); 160 161 canvas->drawSimpleText(text, textLen, kUTF8_SkTextEncoding, x, y, font, paint); 162 y += font.getMetrics(nullptr); 163 } 164 165 // check skew 166 { 167 font.setEdging(SkFont::Edging::kAntiAlias); 168 SkAutoCanvasRestore acr(canvas, true); 169 canvas->skew(0.0f, 0.151515f); 170 font.setSize(SkIntToScalar(32)); 171 canvas->drawSimpleText(text, textLen, kUTF8_SkTextEncoding, 745, 70, font, paint); 172 } 173 { 174 font.setEdging(SkFont::Edging::kSubpixelAntiAlias); 175 SkAutoCanvasRestore acr(canvas, true); 176 canvas->skew(0.5f, 0.0f); 177 font.setSize(SkIntToScalar(32)); 178 canvas->drawSimpleText(text, textLen, kUTF8_SkTextEncoding, 580, 125, font, paint); 179 } 180 181 // check perspective 182 { 183 font.setEdging(SkFont::Edging::kAntiAlias); 184 SkAutoCanvasRestore acr(canvas, true); 185 SkMatrix persp; 186 persp.setAll(0.9839f, 0, 0, 187 0.2246f, 0.6829f, 0, 188 0.0002352f, -0.0003844f, 1); 189 canvas->concat(persp); 190 canvas->translate(1100, -295); 191 font.setSize(37.5f); 192 canvas->drawSimpleText(text, textLen, kUTF8_SkTextEncoding, 0, 0, font, paint); 193 } 194 { 195 font.setSubpixel(false); 196 font.setEdging(SkFont::Edging::kAlias); 197 SkAutoCanvasRestore acr(canvas, true); 198 SkMatrix persp; 199 persp.setAll(0.9839f, 0, 0, 200 0.2246f, 0.6829f, 0, 201 0.0002352f, -0.0003844f, 1); 202 canvas->concat(persp); 203 canvas->translate(1075, -245); 204 canvas->scale(375, 375); 205 font.setSize(0.1f); 206 canvas->drawSimpleText(text, textLen, kUTF8_SkTextEncoding, 0, 0, font, paint); 207 } 208 209 // check color emoji 210 if (fEmojiTypeface) { 211 SkFont emoiFont; 212 emoiFont.setSubpixel(true); 213 emoiFont.setTypeface(fEmojiTypeface); 214 emoiFont.setSize(SkIntToScalar(19)); 215 canvas->drawSimpleText(fEmojiText, strlen(fEmojiText), kUTF8_SkTextEncoding, 670, 90, emoiFont, paint); 216 } 217 218 // render offscreen buffer 219 if (surface) { 220 SkAutoCanvasRestore acr(inputCanvas, true); 221 // since we prepended this matrix already, we blit using identity 222 inputCanvas->resetMatrix(); 223 inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0, nullptr); 224 } 225 } 226 227 private: 228 sk_sp<SkTypeface> fEmojiTypeface; 229 const char* fEmojiText; 230 231 typedef skiagm::GM INHERITED; 232 }; 233 234 DEF_GM(return new DFTextGM;) 235