1 /* 2 * Copyright 2015 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/gm.h" 9 #include "include/core/SkCanvas.h" 10 #include "include/core/SkColor.h" 11 #include "include/core/SkFont.h" 12 #include "include/core/SkFontTypes.h" 13 #include "include/core/SkPaint.h" 14 #include "include/core/SkRect.h" 15 #include "include/core/SkRefCnt.h" 16 #include "include/core/SkScalar.h" 17 #include "include/core/SkSize.h" 18 #include "include/core/SkString.h" 19 #include "include/core/SkTextBlob.h" 20 #include "include/core/SkTypeface.h" 21 #include "tools/ToolUtils.h" 22 23 #include <string.h> 24 25 namespace skiagm { 26 class TextBlobTransforms : public GM { 27 public: 28 // This gm tests that textblobs can be translated, rotated, and scaled TextBlobTransforms()29 TextBlobTransforms() {} 30 31 protected: onOnceBeforeDraw()32 void onOnceBeforeDraw() override { 33 SkTextBlobBuilder builder; 34 35 // make textblob. To stress distance fields, we choose sizes appropriately 36 SkFont font(ToolUtils::create_portable_typeface(), 162); 37 font.setEdging(SkFont::Edging::kAlias); 38 const char* text = "A"; 39 40 SkRect bounds; 41 font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds); 42 ToolUtils::add_to_text_blob(&builder, text, font, 0, 0); 43 44 // Medium 45 SkScalar xOffset = bounds.width() + 5; 46 font.setSize(72); 47 text = "B"; 48 ToolUtils::add_to_text_blob(&builder, text, font, xOffset, 0); 49 50 font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds); 51 SkScalar yOffset = bounds.height(); 52 53 // Small 54 font.setSize(32); 55 text = "C"; 56 ToolUtils::add_to_text_blob(&builder, text, font, xOffset, -yOffset - 10); 57 58 // build 59 fBlob = builder.make(); 60 } 61 onShortName()62 SkString onShortName() override { 63 return SkString("textblobtransforms"); 64 } 65 onISize()66 SkISize onISize() override { 67 return SkISize::Make(kWidth, kHeight); 68 } 69 onDraw(SkCanvas * canvas)70 void onDraw(SkCanvas* canvas) override { 71 72 canvas->drawColor(SK_ColorGRAY); 73 74 SkPaint paint; 75 76 SkRect bounds = fBlob->bounds(); 77 canvas->translate(20, 20); 78 79 // Colors were chosen to map to pairs of canonical colors. The GPU Backend will cache A8 80 // Texture Blobs based on the canonical color they map to. Canonical colors are used to 81 // create masks. For A8 there are 8 of them. 82 //SkColor colors[] = {SK_ColorCYAN, SK_ColorLTGRAY, SK_ColorYELLOW, SK_ColorWHITE}; 83 84 SkScalar xOffset = SkScalarCeilToScalar(bounds.width()); 85 SkScalar yOffset = SkScalarCeilToScalar(bounds.height()); 86 // first translate 87 canvas->translate(xOffset, 2 * yOffset); 88 canvas->drawTextBlob(fBlob, 0, 0, paint); 89 canvas->translate(-xOffset, 0); 90 canvas->drawTextBlob(fBlob, 0, 0, paint); 91 canvas->translate(2 * xOffset, 0); 92 canvas->drawTextBlob(fBlob, 0, 0, paint); 93 canvas->translate(-xOffset, -yOffset); 94 canvas->drawTextBlob(fBlob, 0, 0, paint); 95 canvas->translate(0, 2 * yOffset); 96 canvas->drawTextBlob(fBlob, 0, 0, paint); 97 98 // now rotate 99 canvas->translate(4 * xOffset, -yOffset); 100 canvas->rotate(180.f); 101 canvas->drawTextBlob(fBlob, 0, 0, paint); 102 canvas->rotate(-180.f); 103 canvas->translate(0, -yOffset); 104 canvas->rotate(-180.f); 105 canvas->drawTextBlob(fBlob, 0, 0, paint); 106 canvas->rotate(270.f); 107 canvas->drawTextBlob(fBlob, 0, 0, paint); 108 canvas->rotate(-90.f); 109 canvas->translate(-xOffset, yOffset); 110 canvas->rotate(-90.f); 111 canvas->drawTextBlob(fBlob, 0, 0, paint); 112 canvas->rotate(90.f); 113 114 // and scales 115 canvas->translate(- 3 * xOffset, 3 * yOffset); 116 canvas->scale(1.5f, 1.5f); 117 canvas->drawTextBlob(fBlob, 0, 0, paint); 118 canvas->translate(xOffset, 0); 119 canvas->scale(.25f, .25f); 120 canvas->drawTextBlob(fBlob, 0, 0, paint); 121 canvas->translate(xOffset, 0); 122 canvas->scale(3.f, 2.f); 123 canvas->drawTextBlob(fBlob, 0, 0, paint); 124 125 // finally rotates, scales, and translates together 126 canvas->translate(xOffset, 0); 127 canvas->rotate(23.f); 128 canvas->scale(.33f, .5f); 129 canvas->drawTextBlob(fBlob, 0, 0, paint); 130 131 canvas->rotate(-46.f); 132 canvas->translate(xOffset, 0); 133 canvas->scale(1.2f, 1.1f); 134 canvas->drawTextBlob(fBlob, 0, 0, paint); 135 136 canvas->rotate(46.f); 137 canvas->translate(xOffset, 0); 138 canvas->scale(1.1f, 1.2f); 139 canvas->drawTextBlob(fBlob, 0, 0, paint); 140 141 canvas->rotate(46.f); 142 canvas->translate(xOffset, 0); 143 canvas->scale(.95f, 1.1f); 144 canvas->drawTextBlob(fBlob, 0, 0, paint); 145 146 canvas->rotate(46.f); 147 canvas->translate(xOffset, 0); 148 canvas->scale(1.3f, .7f); 149 canvas->drawTextBlob(fBlob, 0, 0, paint); 150 151 canvas->rotate(46.f); 152 canvas->translate(xOffset, 0); 153 canvas->scale(.8f, 1.1f); 154 canvas->drawTextBlob(fBlob, 0, 0, paint); 155 156 canvas->rotate(10.f); 157 canvas->translate(xOffset, 0); 158 canvas->scale(1.f, 5.f); 159 canvas->drawTextBlob(fBlob, 0, 0, paint); 160 161 canvas->rotate(5.f); 162 canvas->translate(xOffset, 0); 163 canvas->scale(5.f, 1.f); 164 canvas->drawTextBlob(fBlob, 0, 0, paint); 165 } 166 167 private: 168 sk_sp<SkTextBlob> fBlob; 169 170 inline static constexpr int kWidth = 1000; 171 inline static constexpr int kHeight = 1200; 172 173 using INHERITED = GM; 174 }; 175 176 ////////////////////////////////////////////////////////////////////////////// 177 178 DEF_GM(return new TextBlobTransforms;) 179 } // namespace skiagm 180