1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2011 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci#include "samplecode/Sample.h"
8cb93a386Sopenharmony_ci
9cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
10cb93a386Sopenharmony_ci#include "include/core/SkColorFilter.h"
11cb93a386Sopenharmony_ci#include "include/core/SkColorPriv.h"
12cb93a386Sopenharmony_ci#include "include/core/SkGraphics.h"
13cb93a386Sopenharmony_ci#include "include/core/SkPath.h"
14cb93a386Sopenharmony_ci#include "include/core/SkRegion.h"
15cb93a386Sopenharmony_ci#include "include/core/SkShader.h"
16cb93a386Sopenharmony_ci#include "include/core/SkStream.h"
17cb93a386Sopenharmony_ci#include "include/core/SkTextBlob.h"
18cb93a386Sopenharmony_ci#include "include/core/SkTime.h"
19cb93a386Sopenharmony_ci#include "include/core/SkTypeface.h"
20cb93a386Sopenharmony_ci#include "include/effects/SkGradientShader.h"
21cb93a386Sopenharmony_ci#include "include/utils/SkRandom.h"
22cb93a386Sopenharmony_ci#include "modules/skshaper/include/SkShaper.h"
23cb93a386Sopenharmony_ci#include "src/core/SkOSFile.h"
24cb93a386Sopenharmony_ci#include "src/shaders/SkColorShader.h"
25cb93a386Sopenharmony_ci#include "src/utils/SkUTF.h"
26cb93a386Sopenharmony_ci
27cb93a386Sopenharmony_citypedef std::unique_ptr<SkShaper> (*ShaperFactory)();
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_cistatic const char gText[] =
30cb93a386Sopenharmony_ci    "When in the Course of human events it becomes necessary for one people "
31cb93a386Sopenharmony_ci    "to dissolve the political bands which have connected them with another "
32cb93a386Sopenharmony_ci    "and to assume among the powers of the earth, the separate and equal "
33cb93a386Sopenharmony_ci    "station to which the Laws of Nature and of Nature's God entitle them, "
34cb93a386Sopenharmony_ci    "a decent respect to the opinions of mankind requires that they should "
35cb93a386Sopenharmony_ci    "declare the causes which impel them to the separation.";
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_ciclass TextBoxView : public Sample {
38cb93a386Sopenharmony_ci    SkString fName;
39cb93a386Sopenharmony_cipublic:
40cb93a386Sopenharmony_ci    TextBoxView(ShaperFactory fact, const char suffix[]) : fShaper(fact()) {
41cb93a386Sopenharmony_ci        fName.printf("TextBox_%s", suffix);
42cb93a386Sopenharmony_ci    }
43cb93a386Sopenharmony_ci
44cb93a386Sopenharmony_ciprotected:
45cb93a386Sopenharmony_ci    SkString name() override { return fName; }
46cb93a386Sopenharmony_ci
47cb93a386Sopenharmony_ci    void drawTest(SkCanvas* canvas, SkScalar w, SkScalar h, SkColor fg, SkColor bg) {
48cb93a386Sopenharmony_ci        SkAutoCanvasRestore acr(canvas, true);
49cb93a386Sopenharmony_ci
50cb93a386Sopenharmony_ci        canvas->clipRect(SkRect::MakeWH(w, h));
51cb93a386Sopenharmony_ci        canvas->drawColor(bg);
52cb93a386Sopenharmony_ci
53cb93a386Sopenharmony_ci        SkScalar margin = 20;
54cb93a386Sopenharmony_ci
55cb93a386Sopenharmony_ci        SkPaint paint;
56cb93a386Sopenharmony_ci        paint.setColor(fg);
57cb93a386Sopenharmony_ci
58cb93a386Sopenharmony_ci        for (int i = 9; i < 24; i += 2) {
59cb93a386Sopenharmony_ci            SkShaper::PurgeCaches();
60cb93a386Sopenharmony_ci            SkTextBlobBuilderRunHandler builder(gText, { margin, margin });
61cb93a386Sopenharmony_ci            SkFont srcFont(nullptr, SkIntToScalar(i));
62cb93a386Sopenharmony_ci            srcFont.setEdging(SkFont::Edging::kSubpixelAntiAlias);
63cb93a386Sopenharmony_ci            srcFont.setSubpixel(true);
64cb93a386Sopenharmony_ci
65cb93a386Sopenharmony_ci            const char* utf8 = gText;
66cb93a386Sopenharmony_ci            size_t utf8Bytes = sizeof(gText) - 1;
67cb93a386Sopenharmony_ci
68cb93a386Sopenharmony_ci            std::unique_ptr<SkShaper::BiDiRunIterator> bidi(
69cb93a386Sopenharmony_ci                SkShaper::MakeBiDiRunIterator(utf8, utf8Bytes, 0xfe));
70cb93a386Sopenharmony_ci            if (!bidi) {
71cb93a386Sopenharmony_ci                return;
72cb93a386Sopenharmony_ci            }
73cb93a386Sopenharmony_ci
74cb93a386Sopenharmony_ci            std::unique_ptr<SkShaper::LanguageRunIterator> language(
75cb93a386Sopenharmony_ci                SkShaper::MakeStdLanguageRunIterator(utf8, utf8Bytes));
76cb93a386Sopenharmony_ci            if (!language) {
77cb93a386Sopenharmony_ci                return;
78cb93a386Sopenharmony_ci            }
79cb93a386Sopenharmony_ci
80cb93a386Sopenharmony_ci            SkFourByteTag undeterminedScript = SkSetFourByteTag('Z','y','y','y');
81cb93a386Sopenharmony_ci            std::unique_ptr<SkShaper::ScriptRunIterator> script(
82cb93a386Sopenharmony_ci                SkShaper::MakeScriptRunIterator(utf8, utf8Bytes, undeterminedScript));
83cb93a386Sopenharmony_ci            if (!script) {
84cb93a386Sopenharmony_ci                return;
85cb93a386Sopenharmony_ci            }
86cb93a386Sopenharmony_ci
87cb93a386Sopenharmony_ci            std::unique_ptr<SkShaper::FontRunIterator> font(
88cb93a386Sopenharmony_ci                SkShaper::MakeFontMgrRunIterator(utf8, utf8Bytes, srcFont, SkFontMgr::RefDefault(),
89cb93a386Sopenharmony_ci                                                 "Arial", SkFontStyle::Bold(), &*language));
90cb93a386Sopenharmony_ci            if (!font) {
91cb93a386Sopenharmony_ci                return;
92cb93a386Sopenharmony_ci            }
93cb93a386Sopenharmony_ci
94cb93a386Sopenharmony_ci            fShaper->shape(utf8, utf8Bytes, *font, *bidi, *script, *language, w - margin, &builder);
95cb93a386Sopenharmony_ci            canvas->drawTextBlob(builder.makeBlob(), 0, 0, paint);
96cb93a386Sopenharmony_ci
97cb93a386Sopenharmony_ci            canvas->translate(0, builder.endPoint().y());
98cb93a386Sopenharmony_ci        }
99cb93a386Sopenharmony_ci    }
100cb93a386Sopenharmony_ci
101cb93a386Sopenharmony_ci    void onDrawContent(SkCanvas* canvas) override {
102cb93a386Sopenharmony_ci        SkScalar width = this->width() / 3;
103cb93a386Sopenharmony_ci        drawTest(canvas, width, this->height(), SK_ColorBLACK, SK_ColorWHITE);
104cb93a386Sopenharmony_ci        canvas->translate(width, 0);
105cb93a386Sopenharmony_ci        drawTest(canvas, width, this->height(), SK_ColorWHITE, SK_ColorBLACK);
106cb93a386Sopenharmony_ci        canvas->translate(width, 0);
107cb93a386Sopenharmony_ci        drawTest(canvas, width, this->height()/2, SK_ColorGRAY, SK_ColorWHITE);
108cb93a386Sopenharmony_ci        canvas->translate(0, this->height()/2);
109cb93a386Sopenharmony_ci        drawTest(canvas, width, this->height()/2, SK_ColorGRAY, SK_ColorBLACK);
110cb93a386Sopenharmony_ci    }
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_ciprivate:
113cb93a386Sopenharmony_ci    std::unique_ptr<SkShaper> fShaper;
114cb93a386Sopenharmony_ci    using INHERITED = Sample;
115cb93a386Sopenharmony_ci};
116cb93a386Sopenharmony_ci
117cb93a386Sopenharmony_ciDEF_SAMPLE( return new TextBoxView([](){ return SkShaper::Make(); }, "default"); );
118cb93a386Sopenharmony_ci#ifdef SK_SHAPER_CORETEXT_AVAILABLE
119cb93a386Sopenharmony_ciDEF_SAMPLE( return new TextBoxView(SkShaper::MakeCoreText, "coretext"); );
120cb93a386Sopenharmony_ci#endif
121cb93a386Sopenharmony_ci
122cb93a386Sopenharmony_ciclass SampleShaper : public Sample {
123cb93a386Sopenharmony_cipublic:
124cb93a386Sopenharmony_ci    SampleShaper() {}
125cb93a386Sopenharmony_ci
126cb93a386Sopenharmony_ciprotected:
127cb93a386Sopenharmony_ci    SkString name() override { return SkString("shaper"); }
128cb93a386Sopenharmony_ci
129cb93a386Sopenharmony_ci    void drawTest(SkCanvas* canvas, const char str[], SkScalar size,
130cb93a386Sopenharmony_ci                  std::unique_ptr<SkShaper> shaper) {
131cb93a386Sopenharmony_ci        if (!shaper) return;
132cb93a386Sopenharmony_ci
133cb93a386Sopenharmony_ci        SkTextBlobBuilderRunHandler builder(str, {0, 0});
134cb93a386Sopenharmony_ci        SkFont srcFont;
135cb93a386Sopenharmony_ci        srcFont.setSize(size);
136cb93a386Sopenharmony_ci        srcFont.setEdging(SkFont::Edging::kSubpixelAntiAlias);
137cb93a386Sopenharmony_ci        srcFont.setSubpixel(true);
138cb93a386Sopenharmony_ci
139cb93a386Sopenharmony_ci        size_t len = strlen(str);
140cb93a386Sopenharmony_ci
141cb93a386Sopenharmony_ci        std::unique_ptr<SkShaper::BiDiRunIterator> bidi(
142cb93a386Sopenharmony_ci            SkShaper::MakeBiDiRunIterator(str, len, 0xfe));
143cb93a386Sopenharmony_ci        if (!bidi) {
144cb93a386Sopenharmony_ci            return;
145cb93a386Sopenharmony_ci        }
146cb93a386Sopenharmony_ci
147cb93a386Sopenharmony_ci        std::unique_ptr<SkShaper::LanguageRunIterator> language(
148cb93a386Sopenharmony_ci            SkShaper::MakeStdLanguageRunIterator(str, len));
149cb93a386Sopenharmony_ci        if (!language) {
150cb93a386Sopenharmony_ci            return;
151cb93a386Sopenharmony_ci        }
152cb93a386Sopenharmony_ci
153cb93a386Sopenharmony_ci        SkFourByteTag undeterminedScript = SkSetFourByteTag('Z','y','y','y');
154cb93a386Sopenharmony_ci        std::unique_ptr<SkShaper::ScriptRunIterator> script(
155cb93a386Sopenharmony_ci            SkShaper::MakeScriptRunIterator(str, len, undeterminedScript));
156cb93a386Sopenharmony_ci        if (!script) {
157cb93a386Sopenharmony_ci            return;
158cb93a386Sopenharmony_ci        }
159cb93a386Sopenharmony_ci
160cb93a386Sopenharmony_ci        std::unique_ptr<SkShaper::FontRunIterator> font(
161cb93a386Sopenharmony_ci            SkShaper::MakeFontMgrRunIterator(str, len, srcFont, SkFontMgr::RefDefault(),
162cb93a386Sopenharmony_ci                                             "Arial", SkFontStyle::Bold(), &*language));
163cb93a386Sopenharmony_ci        if (!font) {
164cb93a386Sopenharmony_ci            return;
165cb93a386Sopenharmony_ci        }
166cb93a386Sopenharmony_ci
167cb93a386Sopenharmony_ci        shaper->shape(str, len, *font, *bidi, *script, *language, 2000, &builder);
168cb93a386Sopenharmony_ci
169cb93a386Sopenharmony_ci        canvas->drawTextBlob(builder.makeBlob(), 0, 0, SkPaint());
170cb93a386Sopenharmony_ci    }
171cb93a386Sopenharmony_ci
172cb93a386Sopenharmony_ci    void onDrawContent(SkCanvas* canvas) override {
173cb93a386Sopenharmony_ci        canvas->translate(10, 30);
174cb93a386Sopenharmony_ci
175cb93a386Sopenharmony_ci        const char text[] = "world";
176cb93a386Sopenharmony_ci
177cb93a386Sopenharmony_ci        for (SkScalar size = 30; size <= 30; size += 10) {
178cb93a386Sopenharmony_ci            this->drawTest(canvas, text, size, SkShaper::Make());
179cb93a386Sopenharmony_ci            canvas->translate(0, size + 5);
180cb93a386Sopenharmony_ci            #ifdef SK_SHAPER_CORETEXT_AVAILABLE
181cb93a386Sopenharmony_ci            this->drawTest(canvas, text, size, SkShaper::MakeCoreText());
182cb93a386Sopenharmony_ci            #endif
183cb93a386Sopenharmony_ci            canvas->translate(0, size*2);
184cb93a386Sopenharmony_ci        }
185cb93a386Sopenharmony_ci    }
186cb93a386Sopenharmony_ci
187cb93a386Sopenharmony_ciprivate:
188cb93a386Sopenharmony_ci    using INHERITED = Sample;
189cb93a386Sopenharmony_ci};
190cb93a386Sopenharmony_ciDEF_SAMPLE( return new SampleShaper; );
191