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