blob: f94d0afd08988b1abc11205db10610a99c03fd36 [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/SkColorMatrixFilter.h"
28#include "include/effects/SkGradientShader.h"
Michael Ludwig898bbfa2019-08-02 15:21:23 -040029#include "include/effects/SkImageFilters.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040030#include "tools/ToolUtils.h"
31
32#include <string.h>
33#include <initializer_list>
34#include <utility>
djsollen@google.com6def2a22013-09-17 15:30:21 +000035
joshualitt290c09b2014-12-19 13:45:20 -080036/*
37 * Spits out a dummy gradient to test blur with shader on paint
38 */
reed2ad1aa62016-03-09 09:50:50 -080039static sk_sp<SkShader> MakeLinear() {
mtkleindbfd7ab2016-09-01 11:24:54 -070040 constexpr SkPoint kPts[] = { { 0, 0 }, { 32, 32 } };
41 constexpr SkScalar kPos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
42 constexpr SkColor kColors[] = {0x80F00080, 0xF0F08000, 0x800080F0 };
reed2ad1aa62016-03-09 09:50:50 -080043 return SkGradientShader::MakeLinear(kPts, kColors, kPos, SK_ARRAY_COUNT(kColors),
Mike Reedfae8fce2019-04-03 10:27:45 -040044 SkTileMode::kClamp);
joshualitt290c09b2014-12-19 13:45:20 -080045}
46
robertphillips6e7025a2016-04-04 04:31:25 -070047static sk_sp<SkImageFilter> make_grayscale(sk_sp<SkImageFilter> input) {
Mike Reede869a1e2019-04-30 12:18:54 -040048 float matrix[20];
49 memset(matrix, 0, 20 * sizeof(float));
joshualitt290c09b2014-12-19 13:45:20 -080050 matrix[0] = matrix[5] = matrix[10] = 0.2126f;
51 matrix[1] = matrix[6] = matrix[11] = 0.7152f;
52 matrix[2] = matrix[7] = matrix[12] = 0.0722f;
53 matrix[18] = 1.0f;
Mike Reede869a1e2019-04-30 12:18:54 -040054 sk_sp<SkColorFilter> filter(SkColorFilters::Matrix(matrix));
Michael Ludwig898bbfa2019-08-02 15:21:23 -040055 return SkImageFilters::ColorFilter(std::move(filter), std::move(input));
joshualitt290c09b2014-12-19 13:45:20 -080056}
57
robertphillips6e7025a2016-04-04 04:31:25 -070058static sk_sp<SkImageFilter> make_blur(float amount, sk_sp<SkImageFilter> input) {
Michael Ludwig898bbfa2019-08-02 15:21:23 -040059 return SkImageFilters::Blur(amount, amount, std::move(input));
joshualitt290c09b2014-12-19 13:45:20 -080060}
61
Brian Salomon6f1d36c2017-01-13 12:02:17 -050062static sk_sp<SkColorFilter> make_color_filter() {
63 return SkColorMatrixFilter::MakeLightingFilter(SkColorSetRGB(0x00, 0x80, 0xFF),
64 SkColorSetRGB(0xFF, 0x20, 0x00));
65}
66
djsollen@google.com6def2a22013-09-17 15:30:21 +000067namespace skiagm {
68
69class ColorEmojiGM : public GM {
70public:
caryclarkc3dcb672015-07-21 12:27:36 -070071 ColorEmojiGM() { }
djsollen@google.com6def2a22013-09-17 15:30:21 +000072
djsollen@google.com6def2a22013-09-17 15:30:21 +000073protected:
bungeman6bdc9cd2015-01-26 14:08:52 -080074 struct EmojiFont {
bungeman13b9c952016-05-12 10:09:30 -070075 sk_sp<SkTypeface> typeface;
bungeman6bdc9cd2015-01-26 14:08:52 -080076 const char* text;
caryclarkc3dcb672015-07-21 12:27:36 -070077 } emojiFont;
mtklein36352bf2015-03-25 18:17:31 -070078 virtual void onOnceBeforeDraw() override {
Mike Kleinea3f0142019-03-20 11:12:10 -050079 emojiFont.typeface = ToolUtils::emoji_typeface();
80 emojiFont.text = ToolUtils::emoji_sample_text();
djsollen@google.com6def2a22013-09-17 15:30:21 +000081 }
82
mtklein36352bf2015-03-25 18:17:31 -070083 SkString onShortName() override {
Mike Kleinbea1f942019-03-08 11:11:55 -060084 return SkString("coloremoji");
djsollen@google.com6def2a22013-09-17 15:30:21 +000085 }
86
Brian Salomon6f1d36c2017-01-13 12:02:17 -050087 SkISize onISize() override { return SkISize::Make(650, 1200); }
djsollen@google.com6def2a22013-09-17 15:30:21 +000088
mtklein36352bf2015-03-25 18:17:31 -070089 void onDraw(SkCanvas* canvas) override {
djsollen@google.com6def2a22013-09-17 15:30:21 +000090
Mike Kleind46dce32018-08-16 10:17:03 -040091 canvas->drawColor(SK_ColorGRAY);
djsollen@google.com6def2a22013-09-17 15:30:21 +000092
Mike Reed2e6db182018-12-15 13:45:33 -050093 SkFont font(emojiFont.typeface);
Ben Wagner51e15a62019-05-07 15:38:46 -040094 char const * const text = emojiFont.text;
95 size_t textLen = strlen(text);
djsollen@google.com6def2a22013-09-17 15:30:21 +000096
caryclarkc3dcb672015-07-21 12:27:36 -070097 // draw text at different point sizes
mtkleindbfd7ab2016-09-01 11:24:54 -070098 constexpr SkScalar textSizes[] = { 10, 30, 50, };
Mike Reedb5784ac2018-11-12 09:35:15 -050099 SkFontMetrics metrics;
bungeman53790512016-07-21 13:32:09 -0700100 SkScalar y = 0;
Ben Wagner1e26ba92017-11-07 15:47:01 -0500101 for (const bool& fakeBold : { false, true }) {
Mike Reed2e6db182018-12-15 13:45:33 -0500102 font.setEmbolden(fakeBold);
Ben Wagner1e26ba92017-11-07 15:47:01 -0500103 for (const SkScalar& textSize : textSizes) {
Mike Reed2e6db182018-12-15 13:45:33 -0500104 font.setSize(textSize);
105 font.getMetrics(&metrics);
Ben Wagner1e26ba92017-11-07 15:47:01 -0500106 y += -metrics.fAscent;
Ben Wagner51e15a62019-05-07 15:38:46 -0400107 canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8,
108 10, y, font, SkPaint());
Ben Wagner1e26ba92017-11-07 15:47:01 -0500109 y += metrics.fDescent + metrics.fLeading;
110 }
caryclarkc3dcb672015-07-21 12:27:36 -0700111 }
djsollen@google.com6def2a22013-09-17 15:30:21 +0000112
bungeman53790512016-07-21 13:32:09 -0700113 y += 20;
114 SkScalar savedY = y;
caryclarkc3dcb672015-07-21 12:27:36 -0700115 // draw with shaders and image filters
116 for (int makeLinear = 0; makeLinear < 2; makeLinear++) {
117 for (int makeBlur = 0; makeBlur < 2; makeBlur++) {
118 for (int makeGray = 0; makeGray < 2; makeGray++) {
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500119 for (int makeMode = 0; makeMode < 2; ++makeMode) {
120 for (int alpha = 0; alpha < 2; ++alpha) {
Herb Derby087fad72019-01-22 14:45:16 -0500121 SkFont shaderFont(font.refTypefaceOrDefault());
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500122 SkPaint shaderPaint;
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500123 if (SkToBool(makeLinear)) {
124 shaderPaint.setShader(MakeLinear());
125 }
caryclarkc3dcb672015-07-21 12:27:36 -0700126
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500127 if (SkToBool(makeBlur) && SkToBool(makeGray)) {
128 sk_sp<SkImageFilter> grayScale(make_grayscale(nullptr));
129 sk_sp<SkImageFilter> blur(make_blur(3.0f, std::move(grayScale)));
130 shaderPaint.setImageFilter(std::move(blur));
131 } else if (SkToBool(makeBlur)) {
132 shaderPaint.setImageFilter(make_blur(3.0f, nullptr));
133 } else if (SkToBool(makeGray)) {
134 shaderPaint.setImageFilter(make_grayscale(nullptr));
135 }
136 if (makeMode) {
137 shaderPaint.setColorFilter(make_color_filter());
138 }
139 if (alpha) {
Mike Reed9407e242019-02-15 16:13:57 -0500140 shaderPaint.setAlphaf(0.5f);
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500141 }
Mike Reed2e6db182018-12-15 13:45:33 -0500142 shaderFont.setSize(30);
143 shaderFont.getMetrics(&metrics);
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500144 y += -metrics.fAscent;
Ben Wagner51e15a62019-05-07 15:38:46 -0400145 canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, 380, y,
Mike Reed2e6db182018-12-15 13:45:33 -0500146 shaderFont, shaderPaint);
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500147 y += metrics.fDescent + metrics.fLeading;
148 }
caryclarkc3dcb672015-07-21 12:27:36 -0700149 }
joshualitt290c09b2014-12-19 13:45:20 -0800150 }
151 }
caryclarkc3dcb672015-07-21 12:27:36 -0700152 }
caryclarkc3dcb672015-07-21 12:27:36 -0700153 // setup work needed to draw text with different clips
bungeman53790512016-07-21 13:32:09 -0700154 canvas->translate(10, savedY);
Mike Reed2e6db182018-12-15 13:45:33 -0500155 font.setSize(40);
djsollen@google.com6def2a22013-09-17 15:30:21 +0000156
caryclarkc3dcb672015-07-21 12:27:36 -0700157 // compute the bounds of the text
158 SkRect bounds;
Ben Wagner51e15a62019-05-07 15:38:46 -0400159 font.measureText(text, textLen, SkTextEncoding::kUTF8, &bounds);
djsollen@google.com6def2a22013-09-17 15:30:21 +0000160
caryclarkc3dcb672015-07-21 12:27:36 -0700161 const SkScalar boundsHalfWidth = bounds.width() * SK_ScalarHalf;
162 const SkScalar boundsHalfHeight = bounds.height() * SK_ScalarHalf;
163 const SkScalar boundsQuarterWidth = boundsHalfWidth * SK_ScalarHalf;
164 const SkScalar boundsQuarterHeight = boundsHalfHeight * SK_ScalarHalf;
djsollen@google.com6def2a22013-09-17 15:30:21 +0000165
caryclarkc3dcb672015-07-21 12:27:36 -0700166 SkRect upperLeftClip = SkRect::MakeXYWH(bounds.left(), bounds.top(),
167 boundsHalfWidth, boundsHalfHeight);
168 SkRect lowerRightClip = SkRect::MakeXYWH(bounds.centerX(), bounds.centerY(),
169 boundsHalfWidth, boundsHalfHeight);
170 SkRect interiorClip = bounds;
171 interiorClip.inset(boundsQuarterWidth, boundsQuarterHeight);
djsollen@google.com6def2a22013-09-17 15:30:21 +0000172
mtkleindbfd7ab2016-09-01 11:24:54 -0700173 const SkRect clipRects[] = { bounds, upperLeftClip, lowerRightClip, interiorClip };
djsollen@google.com6def2a22013-09-17 15:30:21 +0000174
caryclarkc3dcb672015-07-21 12:27:36 -0700175 SkPaint clipHairline;
176 clipHairline.setColor(SK_ColorWHITE);
177 clipHairline.setStyle(SkPaint::kStroke_Style);
djsollen@google.com6def2a22013-09-17 15:30:21 +0000178
Mike Reed2e6db182018-12-15 13:45:33 -0500179 SkPaint paint;
bungeman53790512016-07-21 13:32:09 -0700180 for (const SkRect& clipRect : clipRects) {
181 canvas->translate(0, bounds.height());
caryclarkc3dcb672015-07-21 12:27:36 -0700182 canvas->save();
bungeman53790512016-07-21 13:32:09 -0700183 canvas->drawRect(clipRect, clipHairline);
caryclarkc3dcb672015-07-21 12:27:36 -0700184 paint.setAlpha(0x20);
Ben Wagner51e15a62019-05-07 15:38:46 -0400185 canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, 0, 0, font, paint);
bungeman53790512016-07-21 13:32:09 -0700186 canvas->clipRect(clipRect);
Mike Reed9407e242019-02-15 16:13:57 -0500187 paint.setAlphaf(1.0f);
Ben Wagner51e15a62019-05-07 15:38:46 -0400188 canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, 0, 0, font, paint);
caryclarkc3dcb672015-07-21 12:27:36 -0700189 canvas->restore();
bungeman53790512016-07-21 13:32:09 -0700190 canvas->translate(0, SkIntToScalar(25));
djsollen@google.com6def2a22013-09-17 15:30:21 +0000191 }
192 }
193
djsollen@google.com6def2a22013-09-17 15:30:21 +0000194 typedef GM INHERITED;
195};
196
197//////////////////////////////////////////////////////////////////////////////
198
robertphillips6e7025a2016-04-04 04:31:25 -0700199DEF_GM(return new ColorEmojiGM;)
djsollen@google.com6def2a22013-09-17 15:30:21 +0000200
201}