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 #include "sk_tool_utils.h" 10 11 #include "Resources.h" 12 #include "SkCanvas.h" 13 #include "SkGradientShader.h" 14 #include "SkStream.h" 15 #include "SkTextBlob.h" 16 #include "SkTypeface.h" 17 18 namespace skiagm { 19 20 static void draw_blob(SkCanvas* canvas, const SkTextBlob* blob, const SkPaint& skPaint, 21 const SkRect& clipRect) { 22 SkPaint clipHairline; 23 clipHairline.setColor(SK_ColorWHITE); 24 clipHairline.setStyle(SkPaint::kStroke_Style); 25 26 SkPaint paint(skPaint); 27 canvas->save(); 28 canvas->drawRect(clipRect, clipHairline); 29 paint.setAlpha(0x20); 30 canvas->drawTextBlob(blob, 0, 0, paint); 31 canvas->clipRect(clipRect); 32 paint.setAlpha(0xFF); 33 canvas->drawTextBlob(blob, 0, 0, paint); 34 canvas->restore(); 35 } 36 37 class MixedTextBlobsGM : public GM { 38 public: 39 MixedTextBlobsGM() { } 40 41 protected: 42 void onOnceBeforeDraw() override { 43 fEmojiTypeface = sk_tool_utils::emoji_typeface(); 44 fEmojiText = sk_tool_utils::emoji_sample_text(); 45 fReallyBigATypeface = MakeResourceAsTypeface("fonts/ReallyBigA.ttf"); 46 47 SkTextBlobBuilder builder; 48 49 // make textblob 50 // Text so large we draw as paths 51 SkPaint paint; 52 paint.setTextSize(385); 53 const char* text = "O"; 54 sk_tool_utils::set_portable_typeface(&paint); 55 56 SkRect bounds; 57 paint.measureText(text, strlen(text), &bounds); 58 59 SkScalar yOffset = bounds.height(); 60 sk_tool_utils::add_to_text_blob(&builder, text, paint, 10, yOffset); 61 SkScalar corruptedAx = bounds.width(); 62 SkScalar corruptedAy = yOffset; 63 64 const SkScalar boundsHalfWidth = bounds.width() * SK_ScalarHalf; 65 const SkScalar boundsHalfHeight = bounds.height() * SK_ScalarHalf; 66 67 SkScalar xOffset = boundsHalfWidth; 68 yOffset = boundsHalfHeight; 69 70 // LCD 71 paint.setTextSize(32); 72 text = "LCD!!!!!"; 73 paint.setAntiAlias(true); 74 paint.setSubpixelText(true); 75 paint.setLCDRenderText(true); 76 paint.measureText(text, strlen(text), &bounds); 77 sk_tool_utils::add_to_text_blob(&builder, text, paint, xOffset - bounds.width() * 0.25f, 78 yOffset - bounds.height() * 0.5f); 79 yOffset += bounds.height(); 80 81 // color emoji 82 if (fEmojiTypeface) { 83 paint.setAntiAlias(false); 84 paint.setSubpixelText(false); 85 paint.setLCDRenderText(false); 86 paint.setTypeface(fEmojiTypeface); 87 text = fEmojiText; 88 paint.measureText(text, strlen(text), &bounds); 89 sk_tool_utils::add_to_text_blob(&builder, text, paint, xOffset - bounds.width() * 0.3f, 90 yOffset); 91 } 92 93 // Corrupted font 94 paint.setTextSize(12); 95 text = "aA"; 96 paint.setTypeface(fReallyBigATypeface); 97 sk_tool_utils::add_to_text_blob(&builder, text, paint, corruptedAx, corruptedAy); 98 fBlob = builder.make(); 99 } 100 101 SkString onShortName() override { 102 return SkStringPrintf("mixedtextblobs%s", 103 sk_tool_utils::platform_font_manager()); 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.get(), 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 sk_sp<SkTypeface> fEmojiTypeface; 154 sk_sp<SkTypeface> fReallyBigATypeface; 155 const char* fEmojiText; 156 sk_sp<SkTextBlob> fBlob; 157 158 static constexpr int kWidth = 1250; 159 static constexpr int kHeight = 700; 160 161 typedef GM INHERITED; 162 }; 163 164 ////////////////////////////////////////////////////////////////////////////// 165 166 DEF_GM(return new MixedTextBlobsGM;) 167 } 168