blob: ef9300066081d97bf11f0cbcc3b318f5c12bf579 [file] [log] [blame]
djsollen@google.com6def2a22013-09-17 15:30:21 +00001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -05009#include "include/core/SkCanvas.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040010#include "include/core/SkColor.h"
11#include "include/core/SkColorFilter.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/core/SkFont.h"
13#include "include/core/SkFontMetrics.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040014#include "include/core/SkFontTypes.h"
15#include "include/core/SkImageFilter.h"
16#include "include/core/SkPaint.h"
17#include "include/core/SkPoint.h"
18#include "include/core/SkRect.h"
19#include "include/core/SkRefCnt.h"
20#include "include/core/SkScalar.h"
21#include "include/core/SkShader.h"
22#include "include/core/SkSize.h"
23#include "include/core/SkString.h"
24#include "include/core/SkTileMode.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050025#include "include/core/SkTypeface.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040026#include "include/core/SkTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050027#include "include/effects/SkBlurImageFilter.h"
28#include "include/effects/SkColorFilterImageFilter.h"
29#include "include/effects/SkColorMatrixFilter.h"
30#include "include/effects/SkGradientShader.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040031#include "tools/ToolUtils.h"
32
33#include <string.h>
34#include <initializer_list>
35#include <utility>
djsollen@google.com6def2a22013-09-17 15:30:21 +000036
joshualitt290c09b2014-12-19 13:45:20 -080037/*
38 * Spits out a dummy gradient to test blur with shader on paint
39 */
reed2ad1aa62016-03-09 09:50:50 -080040static sk_sp<SkShader> MakeLinear() {
mtkleindbfd7ab2016-09-01 11:24:54 -070041 constexpr SkPoint kPts[] = { { 0, 0 }, { 32, 32 } };
42 constexpr SkScalar kPos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
43 constexpr SkColor kColors[] = {0x80F00080, 0xF0F08000, 0x800080F0 };
reed2ad1aa62016-03-09 09:50:50 -080044 return SkGradientShader::MakeLinear(kPts, kColors, kPos, SK_ARRAY_COUNT(kColors),
Mike Reedfae8fce2019-04-03 10:27:45 -040045 SkTileMode::kClamp);
joshualitt290c09b2014-12-19 13:45:20 -080046}
47
robertphillips6e7025a2016-04-04 04:31:25 -070048static sk_sp<SkImageFilter> make_grayscale(sk_sp<SkImageFilter> input) {
Mike Reede869a1e2019-04-30 12:18:54 -040049 float matrix[20];
50 memset(matrix, 0, 20 * sizeof(float));
joshualitt290c09b2014-12-19 13:45:20 -080051 matrix[0] = matrix[5] = matrix[10] = 0.2126f;
52 matrix[1] = matrix[6] = matrix[11] = 0.7152f;
53 matrix[2] = matrix[7] = matrix[12] = 0.0722f;
54 matrix[18] = 1.0f;
Mike Reede869a1e2019-04-30 12:18:54 -040055 sk_sp<SkColorFilter> filter(SkColorFilters::Matrix(matrix));
robertphillips5605b562016-04-05 11:50:42 -070056 return SkColorFilterImageFilter::Make(std::move(filter), std::move(input));
joshualitt290c09b2014-12-19 13:45:20 -080057}
58
robertphillips6e7025a2016-04-04 04:31:25 -070059static sk_sp<SkImageFilter> make_blur(float amount, sk_sp<SkImageFilter> input) {
60 return SkBlurImageFilter::Make(amount, amount, std::move(input));
joshualitt290c09b2014-12-19 13:45:20 -080061}
62
Brian Salomon6f1d36c2017-01-13 12:02:17 -050063static sk_sp<SkColorFilter> make_color_filter() {
64 return SkColorMatrixFilter::MakeLightingFilter(SkColorSetRGB(0x00, 0x80, 0xFF),
65 SkColorSetRGB(0xFF, 0x20, 0x00));
66}
67
djsollen@google.com6def2a22013-09-17 15:30:21 +000068namespace skiagm {
69
70class ColorEmojiGM : public GM {
71public:
caryclarkc3dcb672015-07-21 12:27:36 -070072 ColorEmojiGM() { }
djsollen@google.com6def2a22013-09-17 15:30:21 +000073
djsollen@google.com6def2a22013-09-17 15:30:21 +000074protected:
bungeman6bdc9cd2015-01-26 14:08:52 -080075 struct EmojiFont {
bungeman13b9c952016-05-12 10:09:30 -070076 sk_sp<SkTypeface> typeface;
bungeman6bdc9cd2015-01-26 14:08:52 -080077 const char* text;
caryclarkc3dcb672015-07-21 12:27:36 -070078 } emojiFont;
mtklein36352bf2015-03-25 18:17:31 -070079 virtual void onOnceBeforeDraw() override {
Mike Kleinea3f0142019-03-20 11:12:10 -050080 emojiFont.typeface = ToolUtils::emoji_typeface();
81 emojiFont.text = ToolUtils::emoji_sample_text();
djsollen@google.com6def2a22013-09-17 15:30:21 +000082 }
83
mtklein36352bf2015-03-25 18:17:31 -070084 SkString onShortName() override {
Mike Kleinbea1f942019-03-08 11:11:55 -060085 return SkString("coloremoji");
djsollen@google.com6def2a22013-09-17 15:30:21 +000086 }
87
Brian Salomon6f1d36c2017-01-13 12:02:17 -050088 SkISize onISize() override { return SkISize::Make(650, 1200); }
djsollen@google.com6def2a22013-09-17 15:30:21 +000089
mtklein36352bf2015-03-25 18:17:31 -070090 void onDraw(SkCanvas* canvas) override {
djsollen@google.com6def2a22013-09-17 15:30:21 +000091
Mike Kleind46dce32018-08-16 10:17:03 -040092 canvas->drawColor(SK_ColorGRAY);
djsollen@google.com6def2a22013-09-17 15:30:21 +000093
Mike Reed2e6db182018-12-15 13:45:33 -050094 SkFont font(emojiFont.typeface);
Ben Wagner51e15a62019-05-07 15:38:46 -040095 char const * const text = emojiFont.text;
96 size_t textLen = strlen(text);
djsollen@google.com6def2a22013-09-17 15:30:21 +000097
caryclarkc3dcb672015-07-21 12:27:36 -070098 // draw text at different point sizes
mtkleindbfd7ab2016-09-01 11:24:54 -070099 constexpr SkScalar textSizes[] = { 10, 30, 50, };
Mike Reedb5784ac2018-11-12 09:35:15 -0500100 SkFontMetrics metrics;
bungeman53790512016-07-21 13:32:09 -0700101 SkScalar y = 0;
Ben Wagner1e26ba92017-11-07 15:47:01 -0500102 for (const bool& fakeBold : { false, true }) {
Mike Reed2e6db182018-12-15 13:45:33 -0500103 font.setEmbolden(fakeBold);
Ben Wagner1e26ba92017-11-07 15:47:01 -0500104 for (const SkScalar& textSize : textSizes) {
Mike Reed2e6db182018-12-15 13:45:33 -0500105 font.setSize(textSize);
106 font.getMetrics(&metrics);
Ben Wagner1e26ba92017-11-07 15:47:01 -0500107 y += -metrics.fAscent;
Ben Wagner51e15a62019-05-07 15:38:46 -0400108 canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8,
109 10, y, font, SkPaint());
Ben Wagner1e26ba92017-11-07 15:47:01 -0500110 y += metrics.fDescent + metrics.fLeading;
111 }
caryclarkc3dcb672015-07-21 12:27:36 -0700112 }
djsollen@google.com6def2a22013-09-17 15:30:21 +0000113
bungeman53790512016-07-21 13:32:09 -0700114 y += 20;
115 SkScalar savedY = y;
caryclarkc3dcb672015-07-21 12:27:36 -0700116 // draw with shaders and image filters
117 for (int makeLinear = 0; makeLinear < 2; makeLinear++) {
118 for (int makeBlur = 0; makeBlur < 2; makeBlur++) {
119 for (int makeGray = 0; makeGray < 2; makeGray++) {
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500120 for (int makeMode = 0; makeMode < 2; ++makeMode) {
121 for (int alpha = 0; alpha < 2; ++alpha) {
Herb Derby087fad72019-01-22 14:45:16 -0500122 SkFont shaderFont(font.refTypefaceOrDefault());
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500123 SkPaint shaderPaint;
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500124 if (SkToBool(makeLinear)) {
125 shaderPaint.setShader(MakeLinear());
126 }
caryclarkc3dcb672015-07-21 12:27:36 -0700127
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500128 if (SkToBool(makeBlur) && SkToBool(makeGray)) {
129 sk_sp<SkImageFilter> grayScale(make_grayscale(nullptr));
130 sk_sp<SkImageFilter> blur(make_blur(3.0f, std::move(grayScale)));
131 shaderPaint.setImageFilter(std::move(blur));
132 } else if (SkToBool(makeBlur)) {
133 shaderPaint.setImageFilter(make_blur(3.0f, nullptr));
134 } else if (SkToBool(makeGray)) {
135 shaderPaint.setImageFilter(make_grayscale(nullptr));
136 }
137 if (makeMode) {
138 shaderPaint.setColorFilter(make_color_filter());
139 }
140 if (alpha) {
Mike Reed9407e242019-02-15 16:13:57 -0500141 shaderPaint.setAlphaf(0.5f);
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500142 }
Mike Reed2e6db182018-12-15 13:45:33 -0500143 shaderFont.setSize(30);
144 shaderFont.getMetrics(&metrics);
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500145 y += -metrics.fAscent;
Ben Wagner51e15a62019-05-07 15:38:46 -0400146 canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, 380, y,
Mike Reed2e6db182018-12-15 13:45:33 -0500147 shaderFont, shaderPaint);
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500148 y += metrics.fDescent + metrics.fLeading;
149 }
caryclarkc3dcb672015-07-21 12:27:36 -0700150 }
joshualitt290c09b2014-12-19 13:45:20 -0800151 }
152 }
caryclarkc3dcb672015-07-21 12:27:36 -0700153 }
caryclarkc3dcb672015-07-21 12:27:36 -0700154 // setup work needed to draw text with different clips
bungeman53790512016-07-21 13:32:09 -0700155 canvas->translate(10, savedY);
Mike Reed2e6db182018-12-15 13:45:33 -0500156 font.setSize(40);
djsollen@google.com6def2a22013-09-17 15:30:21 +0000157
caryclarkc3dcb672015-07-21 12:27:36 -0700158 // compute the bounds of the text
159 SkRect bounds;
Ben Wagner51e15a62019-05-07 15:38:46 -0400160 font.measureText(text, textLen, SkTextEncoding::kUTF8, &bounds);
djsollen@google.com6def2a22013-09-17 15:30:21 +0000161
caryclarkc3dcb672015-07-21 12:27:36 -0700162 const SkScalar boundsHalfWidth = bounds.width() * SK_ScalarHalf;
163 const SkScalar boundsHalfHeight = bounds.height() * SK_ScalarHalf;
164 const SkScalar boundsQuarterWidth = boundsHalfWidth * SK_ScalarHalf;
165 const SkScalar boundsQuarterHeight = boundsHalfHeight * SK_ScalarHalf;
djsollen@google.com6def2a22013-09-17 15:30:21 +0000166
caryclarkc3dcb672015-07-21 12:27:36 -0700167 SkRect upperLeftClip = SkRect::MakeXYWH(bounds.left(), bounds.top(),
168 boundsHalfWidth, boundsHalfHeight);
169 SkRect lowerRightClip = SkRect::MakeXYWH(bounds.centerX(), bounds.centerY(),
170 boundsHalfWidth, boundsHalfHeight);
171 SkRect interiorClip = bounds;
172 interiorClip.inset(boundsQuarterWidth, boundsQuarterHeight);
djsollen@google.com6def2a22013-09-17 15:30:21 +0000173
mtkleindbfd7ab2016-09-01 11:24:54 -0700174 const SkRect clipRects[] = { bounds, upperLeftClip, lowerRightClip, interiorClip };
djsollen@google.com6def2a22013-09-17 15:30:21 +0000175
caryclarkc3dcb672015-07-21 12:27:36 -0700176 SkPaint clipHairline;
177 clipHairline.setColor(SK_ColorWHITE);
178 clipHairline.setStyle(SkPaint::kStroke_Style);
djsollen@google.com6def2a22013-09-17 15:30:21 +0000179
Mike Reed2e6db182018-12-15 13:45:33 -0500180 SkPaint paint;
bungeman53790512016-07-21 13:32:09 -0700181 for (const SkRect& clipRect : clipRects) {
182 canvas->translate(0, bounds.height());
caryclarkc3dcb672015-07-21 12:27:36 -0700183 canvas->save();
bungeman53790512016-07-21 13:32:09 -0700184 canvas->drawRect(clipRect, clipHairline);
caryclarkc3dcb672015-07-21 12:27:36 -0700185 paint.setAlpha(0x20);
Ben Wagner51e15a62019-05-07 15:38:46 -0400186 canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, 0, 0, font, paint);
bungeman53790512016-07-21 13:32:09 -0700187 canvas->clipRect(clipRect);
Mike Reed9407e242019-02-15 16:13:57 -0500188 paint.setAlphaf(1.0f);
Ben Wagner51e15a62019-05-07 15:38:46 -0400189 canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, 0, 0, font, paint);
caryclarkc3dcb672015-07-21 12:27:36 -0700190 canvas->restore();
bungeman53790512016-07-21 13:32:09 -0700191 canvas->translate(0, SkIntToScalar(25));
djsollen@google.com6def2a22013-09-17 15:30:21 +0000192 }
193 }
194
djsollen@google.com6def2a22013-09-17 15:30:21 +0000195 typedef GM INHERITED;
196};
197
198//////////////////////////////////////////////////////////////////////////////
199
robertphillips6e7025a2016-04-04 04:31:25 -0700200DEF_GM(return new ColorEmojiGM;)
djsollen@google.com6def2a22013-09-17 15:30:21 +0000201
202}