1 /* 2 * Copyright 2014 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/gm.h" 9 #include "include/core/SkBitmap.h" 10 #include "include/core/SkBlendMode.h" 11 #include "include/core/SkCanvas.h" 12 #include "include/core/SkColor.h" 13 #include "include/core/SkFont.h" 14 #include "include/core/SkFontStyle.h" 15 #include "include/core/SkFontTypes.h" 16 #include "include/core/SkImageInfo.h" 17 #include "include/core/SkMatrix.h" 18 #include "include/core/SkPaint.h" 19 #include "include/core/SkRect.h" 20 #include "include/core/SkRefCnt.h" 21 #include "include/core/SkScalar.h" 22 #include "include/core/SkShader.h" 23 #include "include/core/SkSize.h" 24 #include "include/core/SkString.h" 25 #include "include/core/SkTileMode.h" 26 #include "include/core/SkTypeface.h" 27 #include "include/core/SkTypes.h" 28 #include "include/effects/SkGradientShader.h" 29 #include "include/utils/SkTextUtils.h" 30 #include "src/base/SkUTF.h" 31 #include "tools/ToolUtils.h" 32 #include "tools/fonts/FontToolUtils.h" 33 34 #include <string.h> 35 36 namespace { 37 38 static uint16_t gData[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF }; 39 40 class ColorEmojiBlendModesGM : public skiagm::GM { 41 public: 42 const static int W = 64; 43 const static int H = 64; ColorEmojiBlendModesGM(ToolUtils::EmojiFontFormat format)44 ColorEmojiBlendModesGM(ToolUtils::EmojiFontFormat format) : fFormat(format) {} 45 46 protected: onOnceBeforeDraw()47 void onOnceBeforeDraw() override { 48 const SkColor colors[] = { 49 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, 50 SK_ColorMAGENTA, SK_ColorCYAN, SK_ColorYELLOW 51 }; 52 SkMatrix local; 53 local.setRotate(180); 54 SkPaint paint; 55 paint.setAntiAlias(true); 56 paint.setShader(SkGradientShader::MakeSweep(0, 0, colors, nullptr, std::size(colors), 57 0, &local)); 58 59 sk_sp<SkTypeface> orig(ToolUtils::CreatePortableTypeface("serif", SkFontStyle::Bold())); 60 SkASSERT(orig); 61 fColorSample = ToolUtils::EmojiSample(fFormat); 62 63 fBG.installPixels(SkImageInfo::Make(2, 2, kARGB_4444_SkColorType, 64 kOpaque_SkAlphaType), gData, 4); 65 } 66 getName() const67 SkString getName() const override { 68 return SkString("coloremoji_blendmodes_") += ToolUtils::NameForFontFormat(fFormat); 69 } 70 getISize()71 SkISize getISize() override { return {400, 640}; } 72 onDraw(SkCanvas * canvas,SkString * errorMsg)73 DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override { 74 75 if (!fColorSample.typeface) { 76 *errorMsg = SkStringPrintf("Unable to instantiate emoji test font of format %s.", 77 ToolUtils::NameForFontFormat(fFormat).c_str()); 78 return DrawResult::kSkip; 79 } 80 81 canvas->translate(SkIntToScalar(10), SkIntToScalar(20)); 82 83 const SkBlendMode gModes[] = { 84 SkBlendMode::kClear, 85 SkBlendMode::kSrc, 86 SkBlendMode::kDst, 87 SkBlendMode::kSrcOver, 88 SkBlendMode::kDstOver, 89 SkBlendMode::kSrcIn, 90 SkBlendMode::kDstIn, 91 SkBlendMode::kSrcOut, 92 SkBlendMode::kDstOut, 93 SkBlendMode::kSrcATop, 94 SkBlendMode::kDstATop, 95 96 SkBlendMode::kXor, 97 SkBlendMode::kPlus, 98 SkBlendMode::kModulate, 99 SkBlendMode::kScreen, 100 SkBlendMode::kOverlay, 101 SkBlendMode::kDarken, 102 SkBlendMode::kLighten, 103 SkBlendMode::kColorDodge, 104 SkBlendMode::kColorBurn, 105 SkBlendMode::kHardLight, 106 SkBlendMode::kSoftLight, 107 SkBlendMode::kDifference, 108 SkBlendMode::kExclusion, 109 SkBlendMode::kMultiply, 110 SkBlendMode::kHue, 111 SkBlendMode::kSaturation, 112 SkBlendMode::kColor, 113 SkBlendMode::kLuminosity, 114 }; 115 116 const SkScalar w = SkIntToScalar(W); 117 const SkScalar h = SkIntToScalar(H); 118 SkMatrix m; 119 m.setScale(SkIntToScalar(6), SkIntToScalar(6)); 120 auto s = fBG.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, SkSamplingOptions(), m); 121 122 SkFont labelFont(ToolUtils::DefaultPortableTypeface()); 123 124 SkPaint textP; 125 textP.setAntiAlias(true); 126 SkFont textFont(fColorSample.typeface, 70); 127 128 const int kWrap = 5; 129 130 SkScalar x0 = 0; 131 SkScalar y0 = 0; 132 SkScalar x = x0, y = y0; 133 for (size_t i = 0; i < std::size(gModes); i++) { 134 SkRect r; 135 r.setLTRB(x, y, x+w, y+h); 136 137 SkPaint p; 138 p.setStyle(SkPaint::kFill_Style); 139 p.setShader(s); 140 canvas->drawRect(r, p); 141 142 r.inset(-SK_ScalarHalf, -SK_ScalarHalf); 143 p.setStyle(SkPaint::kStroke_Style); 144 p.setShader(nullptr); 145 canvas->drawRect(r, p); 146 147 { 148 SkAutoCanvasRestore arc(canvas, true); 149 canvas->clipRect(r); 150 textP.setBlendMode(gModes[i]); 151 const char* text = fColorSample.sampleText; 152 SkUnichar unichar = SkUTF::NextUTF8(&text, text + strlen(text)); 153 SkASSERT(unichar >= 0); 154 canvas->drawSimpleText(&unichar, 4, SkTextEncoding::kUTF32, 155 x+ w/10.f, y + 7.f*h/8.f, textFont, textP); 156 } 157 #if 1 158 const char* label = SkBlendMode_Name(gModes[i]); 159 SkTextUtils::DrawString(canvas, label, x + w/2, y - labelFont.getSize()/2, 160 labelFont, SkPaint(), SkTextUtils::kCenter_Align); 161 #endif 162 x += w + SkIntToScalar(10); 163 if ((i % kWrap) == kWrap - 1) { 164 x = x0; 165 y += h + SkIntToScalar(30); 166 } 167 } 168 169 return DrawResult::kOk; 170 } 171 172 private: 173 SkBitmap fBG; 174 ToolUtils::EmojiFontFormat fFormat; 175 ToolUtils::EmojiTestSample fColorSample; 176 177 using INHERITED = GM; 178 }; 179 } // namespace 180 181 DEF_GM(return new ColorEmojiBlendModesGM(ToolUtils::EmojiFontFormat::ColrV0);) 182 DEF_GM(return new ColorEmojiBlendModesGM(ToolUtils::EmojiFontFormat::Sbix);) 183 DEF_GM(return new ColorEmojiBlendModesGM(ToolUtils::EmojiFontFormat::Cbdt);) 184 DEF_GM(return new ColorEmojiBlendModesGM(ToolUtils::EmojiFontFormat::Test);) 185 DEF_GM(return new ColorEmojiBlendModesGM(ToolUtils::EmojiFontFormat::Svg);) 186