1 /* 2 * Copyright 2013 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 10 #include "Resources.h" 11 #include "SkCanvas.h" 12 #include "SkGradientShader.h" 13 #include "SkStream.h" 14 #include "SkTextBlob.h" 15 #include "SkTypeface.h" 16 17 namespace skiagm { 18 19 static void draw_blob(SkCanvas* canvas, const SkTextBlob* blob, const SkPaint& skPaint, 20 const SkRect& clipRect) { 21 SkPaint clipHairline; 22 clipHairline.setColor(SK_ColorWHITE); 23 clipHairline.setStyle(SkPaint::kStroke_Style); 24 25 SkPaint paint(skPaint); 26 canvas->save(); 27 canvas->drawRect(clipRect, clipHairline); 28 paint.setAlpha(0x20); 29 canvas->drawTextBlob(blob, 0, 0, paint); 30 canvas->clipRect(clipRect); 31 paint.setAlpha(0xFF); 32 canvas->drawTextBlob(blob, 0, 0, paint); 33 canvas->restore(); 34 } 35 36 class MixedTextBlobsGM : public GM { 37 public: 38 MixedTextBlobsGM() { } 39 40 protected: 41 void onOnceBeforeDraw() override { 42 sk_tool_utils::emoji_typeface(&fEmojiTypeface); 43 fEmojiText = sk_tool_utils::emoji_sample_text(); 44 fReallyBigATypeface.reset(GetResourceAsTypeface("/fonts/ReallyBigA.ttf")); 45 46 SkTextBlobBuilder builder; 47 48 // make textblob 49 // Text so large we draw as paths 50 SkPaint paint; 51 paint.setTextSize(385); 52 const char* text = "O"; 53 sk_tool_utils::set_portable_typeface(&paint); 54 55 SkRect bounds; 56 paint.measureText(text, strlen(text), &bounds); 57 58 SkScalar yOffset = bounds.height(); 59 sk_tool_utils::add_to_text_blob(&builder, text, paint, 10, yOffset); 60 SkScalar corruptedAx = bounds.width(); 61 SkScalar corruptedAy = yOffset; 62 63 const SkScalar boundsHalfWidth = bounds.width() * SK_ScalarHalf; 64 const SkScalar boundsHalfHeight = bounds.height() * SK_ScalarHalf; 65 66 SkScalar xOffset = boundsHalfWidth; 67 yOffset = boundsHalfHeight; 68 69 // LCD 70 paint.setTextSize(32); 71 text = "LCD!!!!!"; 72 paint.setAntiAlias(true); 73 paint.setSubpixelText(true); 74 paint.setLCDRenderText(true); 75 paint.measureText(text, strlen(text), &bounds); 76 sk_tool_utils::add_to_text_blob(&builder, text, paint, xOffset - bounds.width() * 0.25f, 77 yOffset - bounds.height() * 0.5f); 78 yOffset += bounds.height(); 79 80 // color emoji 81 if (fEmojiTypeface) { 82 paint.setAntiAlias(false); 83 paint.setSubpixelText(false); 84 paint.setLCDRenderText(false); 85 paint.setTypeface(fEmojiTypeface); 86 text = fEmojiText; 87 paint.measureText(text, strlen(text), &bounds); 88 sk_tool_utils::add_to_text_blob(&builder, text, paint, xOffset - bounds.width() * 0.3f, 89 yOffset); 90 } 91 92 // Corrupted font 93 paint.setTextSize(12); 94 text = "aA"; 95 paint.setTypeface(fReallyBigATypeface); 96 sk_tool_utils::add_to_text_blob(&builder, text, paint, corruptedAx, corruptedAy); 97 fBlob.reset(builder.build()); 98 } 99 100 SkString onShortName() override { 101 SkString name("mixedtextblobs"); 102 name.append(sk_tool_utils::platform_os_emoji()); 103 return name; 104 } 105 106 SkISize onISize() override { 107 return SkISize::Make(kWidth, kHeight); 108 } 109 110 void onDraw(SkCanvas* canvas) override { 111 112 canvas->drawColor(sk_tool_utils::color_to_565(SK_ColorGRAY)); 113 114 SkPaint paint; 115 116 // setup work needed to draw text with different clips 117 paint.setColor(SK_ColorBLACK); 118 canvas->translate(10, 40); 119 120 paint.setTextSize(40); 121 122 // compute the bounds of the text and setup some clips 123 SkRect bounds = fBlob->bounds(); 124 125 const SkScalar boundsHalfWidth = bounds.width() * SK_ScalarHalf; 126 const SkScalar boundsHalfHeight = bounds.height() * SK_ScalarHalf; 127 const SkScalar boundsQuarterWidth = boundsHalfWidth * SK_ScalarHalf; 128 const SkScalar boundsQuarterHeight = boundsHalfHeight * SK_ScalarHalf; 129 130 SkRect upperLeftClip = SkRect::MakeXYWH(bounds.left(), bounds.top(), 131 boundsHalfWidth, boundsHalfHeight); 132 SkRect lowerRightClip = SkRect::MakeXYWH(bounds.centerX(), bounds.centerY(), 133 boundsHalfWidth, boundsHalfHeight); 134 SkRect interiorClip = bounds; 135 interiorClip.inset(boundsQuarterWidth, boundsQuarterHeight); 136 137 const SkRect clipRects[] = { bounds, upperLeftClip, lowerRightClip, interiorClip}; 138 139 size_t count = sizeof(clipRects) / sizeof(SkRect); 140 for (size_t x = 0; x < count; ++x) { 141 draw_blob(canvas, fBlob, paint, clipRects[x]); 142 if (x == (count >> 1) - 1) { 143 canvas->translate(SkScalarFloorToScalar(bounds.width() + SkIntToScalar(25)), 144 -(x * SkScalarFloorToScalar(bounds.height() + 145 SkIntToScalar(25)))); 146 } else { 147 canvas->translate(0, SkScalarFloorToScalar(bounds.height() + SkIntToScalar(25))); 148 } 149 } 150 } 151 152 private: 153 SkAutoTUnref<SkTypeface> fEmojiTypeface; 154 SkAutoTUnref<SkTypeface> fReallyBigATypeface; 155 const char* fEmojiText; 156 SkAutoTUnref<const SkTextBlob> fBlob; 157 158 static const int kWidth = 1250; 159 static const int kHeight = 700; 160 161 typedef GM INHERITED; 162 }; 163 164 ////////////////////////////////////////////////////////////////////////////// 165 166 DEF_GM(return new MixedTextBlobsGM;) 167 } 168