xref: /aosp_15_r20/external/skia/gm/mixedtextblobs.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2013 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFont.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontTypes.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTextBlob.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypeface.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "tools/Resources.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h"
24*c8dee2aaSAndroid Build Coastguard Worker 
25*c8dee2aaSAndroid Build Coastguard Worker #include <string.h>
26*c8dee2aaSAndroid Build Coastguard Worker 
27*c8dee2aaSAndroid Build Coastguard Worker namespace skiagm {
28*c8dee2aaSAndroid Build Coastguard Worker 
draw_blob(SkCanvas * canvas,const SkTextBlob * blob,const SkPaint & skPaint,const SkRect & clipRect)29*c8dee2aaSAndroid Build Coastguard Worker static void draw_blob(SkCanvas* canvas, const SkTextBlob* blob, const SkPaint& skPaint,
30*c8dee2aaSAndroid Build Coastguard Worker                       const SkRect& clipRect) {
31*c8dee2aaSAndroid Build Coastguard Worker     SkPaint clipHairline;
32*c8dee2aaSAndroid Build Coastguard Worker     clipHairline.setColor(SK_ColorWHITE);
33*c8dee2aaSAndroid Build Coastguard Worker     clipHairline.setStyle(SkPaint::kStroke_Style);
34*c8dee2aaSAndroid Build Coastguard Worker 
35*c8dee2aaSAndroid Build Coastguard Worker     SkPaint paint(skPaint);
36*c8dee2aaSAndroid Build Coastguard Worker     canvas->save();
37*c8dee2aaSAndroid Build Coastguard Worker     canvas->drawRect(clipRect, clipHairline);
38*c8dee2aaSAndroid Build Coastguard Worker     paint.setAlphaf(0.125f);
39*c8dee2aaSAndroid Build Coastguard Worker     canvas->drawTextBlob(blob, 0, 0, paint);
40*c8dee2aaSAndroid Build Coastguard Worker     canvas->clipRect(clipRect);
41*c8dee2aaSAndroid Build Coastguard Worker     paint.setAlphaf(1.0f);
42*c8dee2aaSAndroid Build Coastguard Worker     canvas->drawTextBlob(blob, 0, 0, paint);
43*c8dee2aaSAndroid Build Coastguard Worker     canvas->restore();
44*c8dee2aaSAndroid Build Coastguard Worker }
45*c8dee2aaSAndroid Build Coastguard Worker 
46*c8dee2aaSAndroid Build Coastguard Worker class MixedTextBlobsGM : public GM {
47*c8dee2aaSAndroid Build Coastguard Worker public:
MixedTextBlobsGM()48*c8dee2aaSAndroid Build Coastguard Worker     MixedTextBlobsGM() { }
49*c8dee2aaSAndroid Build Coastguard Worker 
50*c8dee2aaSAndroid Build Coastguard Worker protected:
onOnceBeforeDraw()51*c8dee2aaSAndroid Build Coastguard Worker     void onOnceBeforeDraw() override {
52*c8dee2aaSAndroid Build Coastguard Worker         fEmojiTypeface      = ToolUtils::PlanetTypeface();
53*c8dee2aaSAndroid Build Coastguard Worker         fEmojiText = "♁♃";
54*c8dee2aaSAndroid Build Coastguard Worker         fReallyBigATypeface = ToolUtils::CreateTypefaceFromResource("fonts/ReallyBigA.ttf");
55*c8dee2aaSAndroid Build Coastguard Worker         if (!fReallyBigATypeface) {
56*c8dee2aaSAndroid Build Coastguard Worker             fReallyBigATypeface = ToolUtils::DefaultPortableTypeface();
57*c8dee2aaSAndroid Build Coastguard Worker         }
58*c8dee2aaSAndroid Build Coastguard Worker 
59*c8dee2aaSAndroid Build Coastguard Worker         SkTextBlobBuilder builder;
60*c8dee2aaSAndroid Build Coastguard Worker 
61*c8dee2aaSAndroid Build Coastguard Worker         // make textblob
62*c8dee2aaSAndroid Build Coastguard Worker         // Text so large we draw as paths
63*c8dee2aaSAndroid Build Coastguard Worker         SkFont font(ToolUtils::DefaultPortableTypeface(), 385);
64*c8dee2aaSAndroid Build Coastguard Worker         font.setEdging(SkFont::Edging::kAlias);
65*c8dee2aaSAndroid Build Coastguard Worker         const char* text = "O";
66*c8dee2aaSAndroid Build Coastguard Worker 
67*c8dee2aaSAndroid Build Coastguard Worker         SkRect bounds;
68*c8dee2aaSAndroid Build Coastguard Worker         font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
69*c8dee2aaSAndroid Build Coastguard Worker 
70*c8dee2aaSAndroid Build Coastguard Worker         SkScalar yOffset = bounds.height();
71*c8dee2aaSAndroid Build Coastguard Worker         ToolUtils::add_to_text_blob(&builder, text, font, 10, yOffset);
72*c8dee2aaSAndroid Build Coastguard Worker         SkScalar corruptedAx = bounds.width();
73*c8dee2aaSAndroid Build Coastguard Worker         SkScalar corruptedAy = yOffset;
74*c8dee2aaSAndroid Build Coastguard Worker 
75*c8dee2aaSAndroid Build Coastguard Worker         const SkScalar boundsHalfWidth = bounds.width() * SK_ScalarHalf;
76*c8dee2aaSAndroid Build Coastguard Worker         const SkScalar boundsHalfHeight = bounds.height() * SK_ScalarHalf;
77*c8dee2aaSAndroid Build Coastguard Worker 
78*c8dee2aaSAndroid Build Coastguard Worker         SkScalar xOffset = boundsHalfWidth;
79*c8dee2aaSAndroid Build Coastguard Worker         yOffset = boundsHalfHeight;
80*c8dee2aaSAndroid Build Coastguard Worker 
81*c8dee2aaSAndroid Build Coastguard Worker         // LCD
82*c8dee2aaSAndroid Build Coastguard Worker         font.setSize(32);
83*c8dee2aaSAndroid Build Coastguard Worker         font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
84*c8dee2aaSAndroid Build Coastguard Worker         font.setSubpixel(true);
85*c8dee2aaSAndroid Build Coastguard Worker         text = "LCD!!!!!";
86*c8dee2aaSAndroid Build Coastguard Worker         font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
87*c8dee2aaSAndroid Build Coastguard Worker         ToolUtils::add_to_text_blob(&builder,
88*c8dee2aaSAndroid Build Coastguard Worker                                     text,
89*c8dee2aaSAndroid Build Coastguard Worker                                     font,
90*c8dee2aaSAndroid Build Coastguard Worker                                     xOffset - bounds.width() * 0.25f,
91*c8dee2aaSAndroid Build Coastguard Worker                                     yOffset - bounds.height() * 0.5f);
92*c8dee2aaSAndroid Build Coastguard Worker 
93*c8dee2aaSAndroid Build Coastguard Worker         // color emoji font with large glyph
94*c8dee2aaSAndroid Build Coastguard Worker         if (fEmojiTypeface) {
95*c8dee2aaSAndroid Build Coastguard Worker             font.setEdging(SkFont::Edging::kAlias);
96*c8dee2aaSAndroid Build Coastguard Worker             font.setSubpixel(false);
97*c8dee2aaSAndroid Build Coastguard Worker             font.setTypeface(fEmojiTypeface);
98*c8dee2aaSAndroid Build Coastguard Worker             font.measureText(fEmojiText, strlen(fEmojiText), SkTextEncoding::kUTF8, &bounds);
99*c8dee2aaSAndroid Build Coastguard Worker             ToolUtils::add_to_text_blob(&builder, fEmojiText, font, xOffset, yOffset);
100*c8dee2aaSAndroid Build Coastguard Worker         }
101*c8dee2aaSAndroid Build Coastguard Worker 
102*c8dee2aaSAndroid Build Coastguard Worker         // outline font with large glyph
103*c8dee2aaSAndroid Build Coastguard Worker         font.setSize(12);
104*c8dee2aaSAndroid Build Coastguard Worker         text = "aA";
105*c8dee2aaSAndroid Build Coastguard Worker         font.setTypeface(fReallyBigATypeface);
106*c8dee2aaSAndroid Build Coastguard Worker         ToolUtils::add_to_text_blob(&builder, text, font, corruptedAx, corruptedAy);
107*c8dee2aaSAndroid Build Coastguard Worker         fBlob = builder.make();
108*c8dee2aaSAndroid Build Coastguard Worker     }
109*c8dee2aaSAndroid Build Coastguard Worker 
getName() const110*c8dee2aaSAndroid Build Coastguard Worker     SkString getName() const override { return SkString("mixedtextblobs"); }
111*c8dee2aaSAndroid Build Coastguard Worker 
getISize()112*c8dee2aaSAndroid Build Coastguard Worker     SkISize getISize() override { return SkISize::Make(kWidth, kHeight); }
113*c8dee2aaSAndroid Build Coastguard Worker 
onDraw(SkCanvas * canvas)114*c8dee2aaSAndroid Build Coastguard Worker     void onDraw(SkCanvas* canvas) override {
115*c8dee2aaSAndroid Build Coastguard Worker 
116*c8dee2aaSAndroid Build Coastguard Worker         canvas->drawColor(SK_ColorGRAY);
117*c8dee2aaSAndroid Build Coastguard Worker 
118*c8dee2aaSAndroid Build Coastguard Worker         SkPaint paint;
119*c8dee2aaSAndroid Build Coastguard Worker 
120*c8dee2aaSAndroid Build Coastguard Worker         // setup work needed to draw text with different clips
121*c8dee2aaSAndroid Build Coastguard Worker         paint.setColor(SK_ColorBLACK);
122*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate(10, 40);
123*c8dee2aaSAndroid Build Coastguard Worker 
124*c8dee2aaSAndroid Build Coastguard Worker         // compute the bounds of the text and setup some clips
125*c8dee2aaSAndroid Build Coastguard Worker         SkRect bounds = fBlob->bounds();
126*c8dee2aaSAndroid Build Coastguard Worker 
127*c8dee2aaSAndroid Build Coastguard Worker         const SkScalar boundsHalfWidth = bounds.width() * SK_ScalarHalf;
128*c8dee2aaSAndroid Build Coastguard Worker         const SkScalar boundsHalfHeight = bounds.height() * SK_ScalarHalf;
129*c8dee2aaSAndroid Build Coastguard Worker         const SkScalar boundsQuarterWidth = boundsHalfWidth * SK_ScalarHalf;
130*c8dee2aaSAndroid Build Coastguard Worker         const SkScalar boundsQuarterHeight = boundsHalfHeight * SK_ScalarHalf;
131*c8dee2aaSAndroid Build Coastguard Worker 
132*c8dee2aaSAndroid Build Coastguard Worker         SkRect upperLeftClip = SkRect::MakeXYWH(bounds.left(), bounds.top(),
133*c8dee2aaSAndroid Build Coastguard Worker                                                 boundsHalfWidth, boundsHalfHeight);
134*c8dee2aaSAndroid Build Coastguard Worker         SkRect lowerRightClip = SkRect::MakeXYWH(bounds.centerX(), bounds.centerY(),
135*c8dee2aaSAndroid Build Coastguard Worker                                                  boundsHalfWidth, boundsHalfHeight);
136*c8dee2aaSAndroid Build Coastguard Worker         SkRect interiorClip = bounds;
137*c8dee2aaSAndroid Build Coastguard Worker         interiorClip.inset(boundsQuarterWidth, boundsQuarterHeight);
138*c8dee2aaSAndroid Build Coastguard Worker 
139*c8dee2aaSAndroid Build Coastguard Worker         const SkRect clipRects[] = { bounds, upperLeftClip, lowerRightClip, interiorClip};
140*c8dee2aaSAndroid Build Coastguard Worker 
141*c8dee2aaSAndroid Build Coastguard Worker         size_t count = sizeof(clipRects) / sizeof(SkRect);
142*c8dee2aaSAndroid Build Coastguard Worker         for (size_t x = 0; x < count; ++x) {
143*c8dee2aaSAndroid Build Coastguard Worker             draw_blob(canvas, fBlob.get(), paint, clipRects[x]);
144*c8dee2aaSAndroid Build Coastguard Worker             if (x == (count >> 1) - 1) {
145*c8dee2aaSAndroid Build Coastguard Worker                 canvas->translate(SkScalarFloorToScalar(bounds.width() + SkIntToScalar(25)),
146*c8dee2aaSAndroid Build Coastguard Worker                                   -(x * SkScalarFloorToScalar(bounds.height() +
147*c8dee2aaSAndroid Build Coastguard Worker                                     SkIntToScalar(25))));
148*c8dee2aaSAndroid Build Coastguard Worker             } else {
149*c8dee2aaSAndroid Build Coastguard Worker                 canvas->translate(0, SkScalarFloorToScalar(bounds.height() + SkIntToScalar(25)));
150*c8dee2aaSAndroid Build Coastguard Worker             }
151*c8dee2aaSAndroid Build Coastguard Worker         }
152*c8dee2aaSAndroid Build Coastguard Worker     }
153*c8dee2aaSAndroid Build Coastguard Worker 
154*c8dee2aaSAndroid Build Coastguard Worker private:
155*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkTypeface> fEmojiTypeface;
156*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkTypeface> fReallyBigATypeface;
157*c8dee2aaSAndroid Build Coastguard Worker     const char* fEmojiText;
158*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkTextBlob> fBlob;
159*c8dee2aaSAndroid Build Coastguard Worker 
160*c8dee2aaSAndroid Build Coastguard Worker     inline static constexpr int kWidth = 1250;
161*c8dee2aaSAndroid Build Coastguard Worker     inline static constexpr int kHeight = 700;
162*c8dee2aaSAndroid Build Coastguard Worker 
163*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = GM;
164*c8dee2aaSAndroid Build Coastguard Worker };
165*c8dee2aaSAndroid Build Coastguard Worker 
166*c8dee2aaSAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////
167*c8dee2aaSAndroid Build Coastguard Worker 
168*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new MixedTextBlobsGM;)
169*c8dee2aaSAndroid Build Coastguard Worker }  // namespace skiagm
170