xref: /aosp_15_r20/external/skia/fuzz/FuzzSkParagraph.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2020 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 "fuzz/Fuzz.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "fuzz/FuzzCommon.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontMgr.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontStyle.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSpan.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypeface.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/include/DartTypes.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/include/FontCollection.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/include/Paragraph.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/include/ParagraphCache.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/include/ParagraphStyle.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/include/TextShadow.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/include/TextStyle.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/include/TypefaceFontProvider.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/src/ParagraphBuilderImpl.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/src/ParagraphImpl.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/src/Run.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/src/TextLine.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/utils/TestFontCollection.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skshaper/utils/FactoryHelpers.h"
39*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkOSFile.h"
40*c8dee2aaSAndroid Build Coastguard Worker #include "src/utils/SkOSPath.h"
41*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
42*c8dee2aaSAndroid Build Coastguard Worker #include "tools/Resources.h"
43*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h"
44*c8dee2aaSAndroid Build Coastguard Worker 
45*c8dee2aaSAndroid Build Coastguard Worker #include <string.h>
46*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
47*c8dee2aaSAndroid Build Coastguard Worker #include <limits>
48*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
49*c8dee2aaSAndroid Build Coastguard Worker #include <string>
50*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
51*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
52*c8dee2aaSAndroid Build Coastguard Worker 
53*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_ENABLE_PARAGRAPH)
54*c8dee2aaSAndroid Build Coastguard Worker 
55*c8dee2aaSAndroid Build Coastguard Worker using namespace skia::textlayout;
56*c8dee2aaSAndroid Build Coastguard Worker namespace {
57*c8dee2aaSAndroid Build Coastguard Worker const uint8_t MAX_TEXT_LENGTH = 255;
58*c8dee2aaSAndroid Build Coastguard Worker const uint8_t MAX_TEXT_ADDITIONS = 4;
59*c8dee2aaSAndroid Build Coastguard Worker // Use 250 so uint8 can create text and layout width larger than the canvas.
60*c8dee2aaSAndroid Build Coastguard Worker const uint16_t TEST_CANVAS_DIM = 250;
61*c8dee2aaSAndroid Build Coastguard Worker 
62*c8dee2aaSAndroid Build Coastguard Worker class ResourceFontCollection : public FontCollection {
63*c8dee2aaSAndroid Build Coastguard Worker public:
ResourceFontCollection(bool testOnly=false)64*c8dee2aaSAndroid Build Coastguard Worker     ResourceFontCollection(bool testOnly = false)
65*c8dee2aaSAndroid Build Coastguard Worker             : fFontsFound(false)
66*c8dee2aaSAndroid Build Coastguard Worker             , fResolvedFonts(0)
67*c8dee2aaSAndroid Build Coastguard Worker             , fResourceDir(GetResourcePath("fonts").c_str())
68*c8dee2aaSAndroid Build Coastguard Worker             , fFontProvider(sk_make_sp<TypefaceFontProvider>()) {
69*c8dee2aaSAndroid Build Coastguard Worker         std::vector<SkString> fonts;
70*c8dee2aaSAndroid Build Coastguard Worker         SkOSFile::Iter iter(fResourceDir.c_str());
71*c8dee2aaSAndroid Build Coastguard Worker 
72*c8dee2aaSAndroid Build Coastguard Worker         SkString path;
73*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<SkFontMgr> mgr = ToolUtils::TestFontMgr();
74*c8dee2aaSAndroid Build Coastguard Worker         while (iter.next(&path)) {
75*c8dee2aaSAndroid Build Coastguard Worker             if (path.endsWith("Roboto-Italic.ttf")) {
76*c8dee2aaSAndroid Build Coastguard Worker                 fFontsFound = true;
77*c8dee2aaSAndroid Build Coastguard Worker             }
78*c8dee2aaSAndroid Build Coastguard Worker             fonts.emplace_back(path);
79*c8dee2aaSAndroid Build Coastguard Worker         }
80*c8dee2aaSAndroid Build Coastguard Worker 
81*c8dee2aaSAndroid Build Coastguard Worker         if (!fFontsFound) {
82*c8dee2aaSAndroid Build Coastguard Worker             // SkDebugf("Fonts not found, skipping all the tests\n");
83*c8dee2aaSAndroid Build Coastguard Worker             return;
84*c8dee2aaSAndroid Build Coastguard Worker         }
85*c8dee2aaSAndroid Build Coastguard Worker         // Only register fonts if we have to
86*c8dee2aaSAndroid Build Coastguard Worker         for (auto& font : fonts) {
87*c8dee2aaSAndroid Build Coastguard Worker             SkString file_path;
88*c8dee2aaSAndroid Build Coastguard Worker             file_path.printf("%s/%s", fResourceDir.c_str(), font.c_str());
89*c8dee2aaSAndroid Build Coastguard Worker             fFontProvider->registerTypeface(mgr->makeFromFile(file_path.c_str(), 0));
90*c8dee2aaSAndroid Build Coastguard Worker         }
91*c8dee2aaSAndroid Build Coastguard Worker 
92*c8dee2aaSAndroid Build Coastguard Worker         if (testOnly) {
93*c8dee2aaSAndroid Build Coastguard Worker             this->setTestFontManager(std::move(fFontProvider));
94*c8dee2aaSAndroid Build Coastguard Worker         } else {
95*c8dee2aaSAndroid Build Coastguard Worker             this->setAssetFontManager(std::move(fFontProvider));
96*c8dee2aaSAndroid Build Coastguard Worker         }
97*c8dee2aaSAndroid Build Coastguard Worker         this->disableFontFallback();
98*c8dee2aaSAndroid Build Coastguard Worker     }
99*c8dee2aaSAndroid Build Coastguard Worker 
resolvedFonts() const100*c8dee2aaSAndroid Build Coastguard Worker     size_t resolvedFonts() const { return fResolvedFonts; }
101*c8dee2aaSAndroid Build Coastguard Worker 
102*c8dee2aaSAndroid Build Coastguard Worker     // TODO: temp solution until we check in fonts
fontsFound() const103*c8dee2aaSAndroid Build Coastguard Worker     bool fontsFound() const { return fFontsFound; }
104*c8dee2aaSAndroid Build Coastguard Worker 
105*c8dee2aaSAndroid Build Coastguard Worker private:
106*c8dee2aaSAndroid Build Coastguard Worker     bool fFontsFound;
107*c8dee2aaSAndroid Build Coastguard Worker     size_t fResolvedFonts;
108*c8dee2aaSAndroid Build Coastguard Worker     std::string fResourceDir;
109*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<TypefaceFontProvider> fFontProvider;
110*c8dee2aaSAndroid Build Coastguard Worker };
111*c8dee2aaSAndroid Build Coastguard Worker 
112*c8dee2aaSAndroid Build Coastguard Worker // buffer must be at least MAX_TEXT_LENGTH in length.
113*c8dee2aaSAndroid Build Coastguard Worker // Returns size of text placed in buffer.
114*c8dee2aaSAndroid Build Coastguard Worker template <typename T>
RandomText(T * buffer,Fuzz * fuzz)115*c8dee2aaSAndroid Build Coastguard Worker uint8_t RandomText(T* buffer, Fuzz* fuzz) {
116*c8dee2aaSAndroid Build Coastguard Worker     uint8_t text_length;
117*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextRange(&text_length, 0, MAX_TEXT_LENGTH);
118*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextN(buffer, text_length);
119*c8dee2aaSAndroid Build Coastguard Worker     return text_length;
120*c8dee2aaSAndroid Build Coastguard Worker }
121*c8dee2aaSAndroid Build Coastguard Worker 
122*c8dee2aaSAndroid Build Coastguard Worker // Add random bytes to the paragraph.
AddASCIIText(ParagraphBuilder * builder,Fuzz * fuzz)123*c8dee2aaSAndroid Build Coastguard Worker void AddASCIIText(ParagraphBuilder* builder,Fuzz* fuzz) {
124*c8dee2aaSAndroid Build Coastguard Worker     char text[MAX_TEXT_LENGTH];
125*c8dee2aaSAndroid Build Coastguard Worker     const auto text_length = RandomText(text, fuzz);
126*c8dee2aaSAndroid Build Coastguard Worker     builder->addText(text, text_length);
127*c8dee2aaSAndroid Build Coastguard Worker }
128*c8dee2aaSAndroid Build Coastguard Worker // Add random bytes to the paragraph.
AddUnicodeText(ParagraphBuilder * builder,Fuzz * fuzz)129*c8dee2aaSAndroid Build Coastguard Worker void AddUnicodeText(ParagraphBuilder* builder,Fuzz* fuzz) {
130*c8dee2aaSAndroid Build Coastguard Worker     char16_t text[MAX_TEXT_LENGTH];
131*c8dee2aaSAndroid Build Coastguard Worker     const auto text_length = RandomText(text, fuzz);
132*c8dee2aaSAndroid Build Coastguard Worker     builder->addText(std::u16string(text, text_length));
133*c8dee2aaSAndroid Build Coastguard Worker }
134*c8dee2aaSAndroid Build Coastguard Worker 
135*c8dee2aaSAndroid Build Coastguard Worker // Combining characters to produce 'Zalgo' text.
136*c8dee2aaSAndroid Build Coastguard Worker const std::u16string COMBINING_DOWN = u"\u0316\u0317\u0318\u0319\u031c\u031d\u031e\u031f\u0320\u0324\u0325\u0326\u0329\u032a\u032b\u032c\u032d\u032e\u032f\u0330\u0331\u0332\u0333\u0339\u033a\u033b\u033c\u0345\u0347\u0348\u0349\u034d\u034e\u0353\u0354\u0355\u0356\u0359\u035a\u0323";
137*c8dee2aaSAndroid Build Coastguard Worker const std::u16string COMBINING_UP = u"\u030d\u030e\u0304\u0305\u033f\u0311\u0306\u0310\u0352\u0357\u0351\u0307\u0308\u030a\u0342\u0343\u0344\u034a\u034b\u034c\u0303\u0302\u030c\u0350\u0300\u0301\u030b\u030f\u0312\u0313\u0314\u033d\u0309\u0363\u0364\u0365\u0366\u0367\u0368\u0369\u036a\u036b\u036c\u036d\u036e\u035b\u0346\u031a";
138*c8dee2aaSAndroid Build Coastguard Worker const std::u16string COMBINING_MIDDLE = u"\u0315\u031b\u0340\u0341\u0358\u0321\u0322\u0327\u0328\u0334\u0335\u0336\u034f\u035c\u035d\u035e\u035f\u0360\u0362\u0338\u0337\u0361\u0489";
139*c8dee2aaSAndroid Build Coastguard Worker // Add random Zalgo text to the paragraph.
AddZalgoText(ParagraphBuilder * builder,Fuzz * fuzz)140*c8dee2aaSAndroid Build Coastguard Worker void AddZalgoText(ParagraphBuilder* builder, Fuzz* fuzz) {
141*c8dee2aaSAndroid Build Coastguard Worker     char text[MAX_TEXT_LENGTH];
142*c8dee2aaSAndroid Build Coastguard Worker     const auto text_length = RandomText(text, fuzz);
143*c8dee2aaSAndroid Build Coastguard Worker     std::u16string result;
144*c8dee2aaSAndroid Build Coastguard Worker 
145*c8dee2aaSAndroid Build Coastguard Worker     for (auto& c : std::string(text, text_length)) {
146*c8dee2aaSAndroid Build Coastguard Worker         result += c;
147*c8dee2aaSAndroid Build Coastguard Worker         uint8_t mark_count;
148*c8dee2aaSAndroid Build Coastguard Worker         fuzz->next(&mark_count);
149*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < mark_count; i++) {
150*c8dee2aaSAndroid Build Coastguard Worker             uint8_t mark_type, mark_index;
151*c8dee2aaSAndroid Build Coastguard Worker             fuzz->next(&mark_type, &mark_index);
152*c8dee2aaSAndroid Build Coastguard Worker             switch (mark_type % 3) {
153*c8dee2aaSAndroid Build Coastguard Worker                 case 0:
154*c8dee2aaSAndroid Build Coastguard Worker                     result += COMBINING_UP[mark_index % COMBINING_UP.size()];
155*c8dee2aaSAndroid Build Coastguard Worker                     break;
156*c8dee2aaSAndroid Build Coastguard Worker                 case 1:
157*c8dee2aaSAndroid Build Coastguard Worker                     result += COMBINING_MIDDLE[mark_index % COMBINING_MIDDLE.size()];
158*c8dee2aaSAndroid Build Coastguard Worker                     break;
159*c8dee2aaSAndroid Build Coastguard Worker                 case 2:
160*c8dee2aaSAndroid Build Coastguard Worker                 default:
161*c8dee2aaSAndroid Build Coastguard Worker                     result += COMBINING_DOWN[mark_index % COMBINING_DOWN.size()];
162*c8dee2aaSAndroid Build Coastguard Worker                     break;
163*c8dee2aaSAndroid Build Coastguard Worker             }
164*c8dee2aaSAndroid Build Coastguard Worker         }
165*c8dee2aaSAndroid Build Coastguard Worker     }
166*c8dee2aaSAndroid Build Coastguard Worker     builder->addText(result);
167*c8dee2aaSAndroid Build Coastguard Worker }
168*c8dee2aaSAndroid Build Coastguard Worker 
AddStyle(ParagraphBuilder * builder,Fuzz * fuzz)169*c8dee2aaSAndroid Build Coastguard Worker void AddStyle(ParagraphBuilder* builder, Fuzz*  fuzz) {
170*c8dee2aaSAndroid Build Coastguard Worker     // TODO(westont): Make this probabilistic, and fill in the remaining TextStyle fields.
171*c8dee2aaSAndroid Build Coastguard Worker     TextStyle ts;
172*c8dee2aaSAndroid Build Coastguard Worker     ts.setFontFamilies({SkString("Roboto")});
173*c8dee2aaSAndroid Build Coastguard Worker     //ts.setColor(SK_ColorBLACK);
174*c8dee2aaSAndroid Build Coastguard Worker     //ts.setForegroundColor
175*c8dee2aaSAndroid Build Coastguard Worker     //ts.setBackgroundColor
176*c8dee2aaSAndroid Build Coastguard Worker     //ts.setDecoration(TextDecoration decoration);
177*c8dee2aaSAndroid Build Coastguard Worker     //ts.setDecorationMode(TextDecorationMode mode);
178*c8dee2aaSAndroid Build Coastguard Worker     //ts.setDecorationStyle(TextDecorationStyle style);
179*c8dee2aaSAndroid Build Coastguard Worker     //ts.setDecorationColor(SkColor color);
180*c8dee2aaSAndroid Build Coastguard Worker     //ts.setDecorationThicknessMultiplier(SkScalar m);
181*c8dee2aaSAndroid Build Coastguard Worker     //ts.setFontStyle
182*c8dee2aaSAndroid Build Coastguard Worker     //ts.addShadow
183*c8dee2aaSAndroid Build Coastguard Worker     //ts.addFontFeature
184*c8dee2aaSAndroid Build Coastguard Worker     //ts.setFontSize
185*c8dee2aaSAndroid Build Coastguard Worker     //ts.setHeight
186*c8dee2aaSAndroid Build Coastguard Worker     //ts.setHeightOverride
187*c8dee2aaSAndroid Build Coastguard Worker     //ts.setletterSpacing
188*c8dee2aaSAndroid Build Coastguard Worker     //ts.setWordSpacing
189*c8dee2aaSAndroid Build Coastguard Worker     //ts.setTypeface
190*c8dee2aaSAndroid Build Coastguard Worker     //ts.setLocale
191*c8dee2aaSAndroid Build Coastguard Worker     //ts.setTextBaseline
192*c8dee2aaSAndroid Build Coastguard Worker     //ts.setPlaceholder
193*c8dee2aaSAndroid Build Coastguard Worker 
194*c8dee2aaSAndroid Build Coastguard Worker     builder->pushStyle(ts);
195*c8dee2aaSAndroid Build Coastguard Worker }
RemoveStyle(ParagraphBuilder * builder,Fuzz * fuzz)196*c8dee2aaSAndroid Build Coastguard Worker void RemoveStyle(ParagraphBuilder* builder, Fuzz*  fuzz) {
197*c8dee2aaSAndroid Build Coastguard Worker     bool pop;
198*c8dee2aaSAndroid Build Coastguard Worker     fuzz->next(&pop);
199*c8dee2aaSAndroid Build Coastguard Worker     if (pop) {
200*c8dee2aaSAndroid Build Coastguard Worker         builder->pop();
201*c8dee2aaSAndroid Build Coastguard Worker     }
202*c8dee2aaSAndroid Build Coastguard Worker }
203*c8dee2aaSAndroid Build Coastguard Worker 
AddStyleAndText(ParagraphBuilder * builder,Fuzz * fuzz)204*c8dee2aaSAndroid Build Coastguard Worker void AddStyleAndText(ParagraphBuilder* builder, Fuzz*  fuzz) {
205*c8dee2aaSAndroid Build Coastguard Worker     AddStyle(builder, fuzz);
206*c8dee2aaSAndroid Build Coastguard Worker     uint8_t text_type;
207*c8dee2aaSAndroid Build Coastguard Worker     fuzz->next(&text_type);
208*c8dee2aaSAndroid Build Coastguard Worker     switch (text_type % 3) {
209*c8dee2aaSAndroid Build Coastguard Worker         case 0:
210*c8dee2aaSAndroid Build Coastguard Worker             AddASCIIText(builder, fuzz);
211*c8dee2aaSAndroid Build Coastguard Worker             break;
212*c8dee2aaSAndroid Build Coastguard Worker         case 1:
213*c8dee2aaSAndroid Build Coastguard Worker             AddUnicodeText(builder, fuzz);
214*c8dee2aaSAndroid Build Coastguard Worker             break;
215*c8dee2aaSAndroid Build Coastguard Worker         case 2:
216*c8dee2aaSAndroid Build Coastguard Worker             AddZalgoText(builder, fuzz);
217*c8dee2aaSAndroid Build Coastguard Worker             break;
218*c8dee2aaSAndroid Build Coastguard Worker     }
219*c8dee2aaSAndroid Build Coastguard Worker     RemoveStyle(builder, fuzz);
220*c8dee2aaSAndroid Build Coastguard Worker 
221*c8dee2aaSAndroid Build Coastguard Worker }
222*c8dee2aaSAndroid Build Coastguard Worker 
BuildParagraphStyle(Fuzz * fuzz)223*c8dee2aaSAndroid Build Coastguard Worker ParagraphStyle BuildParagraphStyle(Fuzz* fuzz) {
224*c8dee2aaSAndroid Build Coastguard Worker     ParagraphStyle ps;
225*c8dee2aaSAndroid Build Coastguard Worker     bool hinting;
226*c8dee2aaSAndroid Build Coastguard Worker     fuzz->next(&hinting);
227*c8dee2aaSAndroid Build Coastguard Worker     if (hinting) {
228*c8dee2aaSAndroid Build Coastguard Worker         ps.turnHintingOff();
229*c8dee2aaSAndroid Build Coastguard Worker     }
230*c8dee2aaSAndroid Build Coastguard Worker     StrutStyle ss;
231*c8dee2aaSAndroid Build Coastguard Worker     // TODO(westont): Fuzz this object.
232*c8dee2aaSAndroid Build Coastguard Worker     ps.setStrutStyle(ss);
233*c8dee2aaSAndroid Build Coastguard Worker     TextDirection td;
234*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextEnum(&td, TextDirection::kRtl);
235*c8dee2aaSAndroid Build Coastguard Worker     ps.setTextDirection(td);
236*c8dee2aaSAndroid Build Coastguard Worker     TextAlign ta;
237*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextEnum(&ta, TextAlign::kEnd);
238*c8dee2aaSAndroid Build Coastguard Worker     ps.setTextAlign(ta);
239*c8dee2aaSAndroid Build Coastguard Worker     size_t ml;
240*c8dee2aaSAndroid Build Coastguard Worker     fuzz->next(&ml);
241*c8dee2aaSAndroid Build Coastguard Worker     ps.setMaxLines(ml);
242*c8dee2aaSAndroid Build Coastguard Worker     // TODO(westont): Randomize with other values and no value.
243*c8dee2aaSAndroid Build Coastguard Worker     ps.setEllipsis(u"\u2026");
244*c8dee2aaSAndroid Build Coastguard Worker     SkScalar h;
245*c8dee2aaSAndroid Build Coastguard Worker     fuzz->next(&h);
246*c8dee2aaSAndroid Build Coastguard Worker     ps.setHeight(h);
247*c8dee2aaSAndroid Build Coastguard Worker     TextHeightBehavior thb = TextHeightBehavior::kAll;
248*c8dee2aaSAndroid Build Coastguard Worker     // TODO(westont): This crashes our seed test case, why?
249*c8dee2aaSAndroid Build Coastguard Worker     //fuzz->nextEnum(&thb, TextHeightBehavior::kDisableAll);
250*c8dee2aaSAndroid Build Coastguard Worker     ps.setTextHeightBehavior(thb);
251*c8dee2aaSAndroid Build Coastguard Worker 
252*c8dee2aaSAndroid Build Coastguard Worker     return ps;
253*c8dee2aaSAndroid Build Coastguard Worker }
254*c8dee2aaSAndroid Build Coastguard Worker 
get_unicode()255*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkUnicode> get_unicode() {
256*c8dee2aaSAndroid Build Coastguard Worker     auto factory = SkShapers::BestAvailable();
257*c8dee2aaSAndroid Build Coastguard Worker     return sk_ref_sp<SkUnicode>(factory->getUnicode());
258*c8dee2aaSAndroid Build Coastguard Worker }
259*c8dee2aaSAndroid Build Coastguard Worker 
260*c8dee2aaSAndroid Build Coastguard Worker }  // namespace
261*c8dee2aaSAndroid Build Coastguard Worker 
DEF_FUZZ(SkParagraph,fuzz)262*c8dee2aaSAndroid Build Coastguard Worker DEF_FUZZ(SkParagraph, fuzz) {
263*c8dee2aaSAndroid Build Coastguard Worker     static sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
264*c8dee2aaSAndroid Build Coastguard Worker     ParagraphStyle paragraph_style = BuildParagraphStyle(fuzz);
265*c8dee2aaSAndroid Build Coastguard Worker     ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
266*c8dee2aaSAndroid Build Coastguard Worker 
267*c8dee2aaSAndroid Build Coastguard Worker     uint8_t iterations;
268*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextRange(&iterations, 1, MAX_TEXT_ADDITIONS);
269*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < iterations; i++) {
270*c8dee2aaSAndroid Build Coastguard Worker         AddStyleAndText(&builder, fuzz);
271*c8dee2aaSAndroid Build Coastguard Worker     }
272*c8dee2aaSAndroid Build Coastguard Worker     // TODO(westont): Figure out if we can get more converage by having fontsFound, current
273*c8dee2aaSAndroid Build Coastguard Worker     // they're not.
274*c8dee2aaSAndroid Build Coastguard Worker     // if (!fontCollection->fontsFound()) return;
275*c8dee2aaSAndroid Build Coastguard Worker 
276*c8dee2aaSAndroid Build Coastguard Worker     builder.pop();
277*c8dee2aaSAndroid Build Coastguard Worker     auto paragraph = builder.Build();
278*c8dee2aaSAndroid Build Coastguard Worker 
279*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap bm;
280*c8dee2aaSAndroid Build Coastguard Worker     if (!bm.tryAllocN32Pixels(TEST_CANVAS_DIM, TEST_CANVAS_DIM)) {
281*c8dee2aaSAndroid Build Coastguard Worker         return;
282*c8dee2aaSAndroid Build Coastguard Worker     }
283*c8dee2aaSAndroid Build Coastguard Worker     SkCanvas canvas(bm);
284*c8dee2aaSAndroid Build Coastguard Worker     uint8_t layout_width;
285*c8dee2aaSAndroid Build Coastguard Worker     fuzz->next(&layout_width);
286*c8dee2aaSAndroid Build Coastguard Worker     paragraph->layout(layout_width);
287*c8dee2aaSAndroid Build Coastguard Worker     paragraph->paint(&canvas, 0, 0);
288*c8dee2aaSAndroid Build Coastguard Worker }
289*c8dee2aaSAndroid Build Coastguard Worker 
290*c8dee2aaSAndroid Build Coastguard Worker #endif // SK_ENABLE_PARAGRAPH
291