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 "SkBlurImageFilter.h" 13#include "SkCanvas.h" 14#include "SkColorFilterImageFilter.h" 15#include "SkColorMatrixFilter.h" 16#include "SkGradientShader.h" 17#include "SkStream.h" 18#include "SkTypeface.h" 19 20/* 21 * Spits out a dummy gradient to test blur with shader on paint 22 */ 23static sk_sp<SkShader> MakeLinear() { 24 constexpr SkPoint kPts[] = { { 0, 0 }, { 32, 32 } }; 25 constexpr SkScalar kPos[] = { 0, SK_Scalar1/2, SK_Scalar1 }; 26 constexpr SkColor kColors[] = {0x80F00080, 0xF0F08000, 0x800080F0 }; 27 return SkGradientShader::MakeLinear(kPts, kColors, kPos, SK_ARRAY_COUNT(kColors), 28 SkShader::kClamp_TileMode); 29} 30 31static sk_sp<SkImageFilter> make_grayscale(sk_sp<SkImageFilter> input) { 32 SkScalar matrix[20]; 33 memset(matrix, 0, 20 * sizeof(SkScalar)); 34 matrix[0] = matrix[5] = matrix[10] = 0.2126f; 35 matrix[1] = matrix[6] = matrix[11] = 0.7152f; 36 matrix[2] = matrix[7] = matrix[12] = 0.0722f; 37 matrix[18] = 1.0f; 38 sk_sp<SkColorFilter> filter(SkColorFilter::MakeMatrixFilterRowMajor255(matrix)); 39 return SkColorFilterImageFilter::Make(std::move(filter), std::move(input)); 40} 41 42static sk_sp<SkImageFilter> make_blur(float amount, sk_sp<SkImageFilter> input) { 43 return SkBlurImageFilter::Make(amount, amount, std::move(input)); 44} 45 46static sk_sp<SkColorFilter> make_color_filter() { 47 return SkColorMatrixFilter::MakeLightingFilter(SkColorSetRGB(0x00, 0x80, 0xFF), 48 SkColorSetRGB(0xFF, 0x20, 0x00)); 49} 50 51namespace skiagm { 52 53class ColorEmojiGM : public GM { 54public: 55 ColorEmojiGM() { } 56 57protected: 58 struct EmojiFont { 59 sk_sp<SkTypeface> typeface; 60 const char* text; 61 } emojiFont; 62 virtual void onOnceBeforeDraw() override { 63 emojiFont.typeface = sk_tool_utils::emoji_typeface(); 64 emojiFont.text = sk_tool_utils::emoji_sample_text(); 65 } 66 67 SkString onShortName() override { 68 SkString name("coloremoji"); 69 name.append(sk_tool_utils::platform_os_emoji()); 70 return name; 71 } 72 73 SkISize onISize() override { return SkISize::Make(650, 1200); } 74 75 void onDraw(SkCanvas* canvas) override { 76 77 canvas->drawColor(sk_tool_utils::color_to_565(SK_ColorGRAY)); 78 79 SkPaint paint; 80 paint.setTypeface(emojiFont.typeface); 81 const char* text = emojiFont.text; 82 83 // draw text at different point sizes 84 constexpr SkScalar textSizes[] = { 10, 30, 50, }; 85 SkPaint::FontMetrics metrics; 86 SkScalar y = 0; 87 for (const SkScalar& textSize : textSizes) { 88 paint.setTextSize(textSize); 89 paint.getFontMetrics(&metrics); 90 y += -metrics.fAscent; 91 canvas->drawText(text, strlen(text), 10, y, paint); 92 y += metrics.fDescent + metrics.fLeading; 93 } 94 95 y += 20; 96 SkScalar savedY = y; 97 // draw with shaders and image filters 98 for (int makeLinear = 0; makeLinear < 2; makeLinear++) { 99 for (int makeBlur = 0; makeBlur < 2; makeBlur++) { 100 for (int makeGray = 0; makeGray < 2; makeGray++) { 101 for (int makeMode = 0; makeMode < 2; ++makeMode) { 102 for (int alpha = 0; alpha < 2; ++alpha) { 103 SkPaint shaderPaint; 104 shaderPaint.setTypeface(sk_ref_sp(paint.getTypeface())); 105 if (SkToBool(makeLinear)) { 106 shaderPaint.setShader(MakeLinear()); 107 } 108 109 if (SkToBool(makeBlur) && SkToBool(makeGray)) { 110 sk_sp<SkImageFilter> grayScale(make_grayscale(nullptr)); 111 sk_sp<SkImageFilter> blur(make_blur(3.0f, std::move(grayScale))); 112 shaderPaint.setImageFilter(std::move(blur)); 113 } else if (SkToBool(makeBlur)) { 114 shaderPaint.setImageFilter(make_blur(3.0f, nullptr)); 115 } else if (SkToBool(makeGray)) { 116 shaderPaint.setImageFilter(make_grayscale(nullptr)); 117 } 118 if (makeMode) { 119 shaderPaint.setColorFilter(make_color_filter()); 120 } 121 if (alpha) { 122 shaderPaint.setAlpha(0x80); 123 } 124 shaderPaint.setTextSize(30); 125 shaderPaint.getFontMetrics(&metrics); 126 y += -metrics.fAscent; 127 canvas->drawText(text, strlen(text), 380, y, shaderPaint); 128 y += metrics.fDescent + metrics.fLeading; 129 } 130 } 131 } 132 } 133 } 134 // setup work needed to draw text with different clips 135 canvas->translate(10, savedY); 136 paint.setTextSize(40); 137 138 // compute the bounds of the text 139 SkRect bounds; 140 paint.measureText(text, strlen(text), &bounds); 141 142 const SkScalar boundsHalfWidth = bounds.width() * SK_ScalarHalf; 143 const SkScalar boundsHalfHeight = bounds.height() * SK_ScalarHalf; 144 const SkScalar boundsQuarterWidth = boundsHalfWidth * SK_ScalarHalf; 145 const SkScalar boundsQuarterHeight = boundsHalfHeight * SK_ScalarHalf; 146 147 SkRect upperLeftClip = SkRect::MakeXYWH(bounds.left(), bounds.top(), 148 boundsHalfWidth, boundsHalfHeight); 149 SkRect lowerRightClip = SkRect::MakeXYWH(bounds.centerX(), bounds.centerY(), 150 boundsHalfWidth, boundsHalfHeight); 151 SkRect interiorClip = bounds; 152 interiorClip.inset(boundsQuarterWidth, boundsQuarterHeight); 153 154 const SkRect clipRects[] = { bounds, upperLeftClip, lowerRightClip, interiorClip }; 155 156 SkPaint clipHairline; 157 clipHairline.setColor(SK_ColorWHITE); 158 clipHairline.setStyle(SkPaint::kStroke_Style); 159 160 for (const SkRect& clipRect : clipRects) { 161 canvas->translate(0, bounds.height()); 162 canvas->save(); 163 canvas->drawRect(clipRect, clipHairline); 164 paint.setAlpha(0x20); 165 canvas->drawText(text, strlen(text), 0, 0, paint); 166 canvas->clipRect(clipRect); 167 paint.setAlpha(0xFF); 168 canvas->drawText(text, strlen(text), 0, 0, paint); 169 canvas->restore(); 170 canvas->translate(0, SkIntToScalar(25)); 171 } 172 } 173 174 typedef GM INHERITED; 175}; 176 177////////////////////////////////////////////////////////////////////////////// 178 179DEF_GM(return new ColorEmojiGM;) 180 181} 182