1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2019 Google LLC
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 #include "include/core/SkColor.h"
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontStyle.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPictureRecorder.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
11*c8dee2aaSAndroid Build Coastguard Worker
12*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/include/DartTypes.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/include/Paragraph.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/include/TextStyle.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/include/TypefaceFontProvider.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/src/ParagraphBuilderImpl.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/src/ParagraphImpl.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skunicode/include/SkUnicode.h"
19*c8dee2aaSAndroid Build Coastguard Worker
20*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_UNICODE_ICU_IMPLEMENTATION)
21*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skunicode/include/SkUnicode_icu.h"
22*c8dee2aaSAndroid Build Coastguard Worker #endif
23*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
24*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skunicode/include/SkUnicode_client.h"
25*c8dee2aaSAndroid Build Coastguard Worker #endif
26*c8dee2aaSAndroid Build Coastguard Worker
27*c8dee2aaSAndroid Build Coastguard Worker #include <string>
28*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
29*c8dee2aaSAndroid Build Coastguard Worker
30*c8dee2aaSAndroid Build Coastguard Worker #include <emscripten.h>
31*c8dee2aaSAndroid Build Coastguard Worker #include <emscripten/bind.h>
32*c8dee2aaSAndroid Build Coastguard Worker #include "modules/canvaskit/WasmCommon.h"
33*c8dee2aaSAndroid Build Coastguard Worker
34*c8dee2aaSAndroid Build Coastguard Worker using namespace emscripten;
35*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
36*c8dee2aaSAndroid Build Coastguard Worker
37*c8dee2aaSAndroid Build Coastguard Worker namespace para = skia::textlayout;
38*c8dee2aaSAndroid Build Coastguard Worker
39*c8dee2aaSAndroid Build Coastguard Worker // switch to ptrToSkColor4f (canvaskit_bindings.cpp)
toSkColor4f(WASMPointerF32 cPtr)40*c8dee2aaSAndroid Build Coastguard Worker SkColor4f toSkColor4f(WASMPointerF32 cPtr) {
41*c8dee2aaSAndroid Build Coastguard Worker float* fourFloats = reinterpret_cast<float*>(cPtr);
42*c8dee2aaSAndroid Build Coastguard Worker SkColor4f color = {fourFloats[0], fourFloats[1], fourFloats[2], fourFloats[3]};
43*c8dee2aaSAndroid Build Coastguard Worker return color;
44*c8dee2aaSAndroid Build Coastguard Worker }
45*c8dee2aaSAndroid Build Coastguard Worker
46*c8dee2aaSAndroid Build Coastguard Worker struct SimpleFontStyle {
47*c8dee2aaSAndroid Build Coastguard Worker SkFontStyle::Slant slant;
48*c8dee2aaSAndroid Build Coastguard Worker SkFontStyle::Weight weight;
49*c8dee2aaSAndroid Build Coastguard Worker SkFontStyle::Width width;
50*c8dee2aaSAndroid Build Coastguard Worker };
51*c8dee2aaSAndroid Build Coastguard Worker
52*c8dee2aaSAndroid Build Coastguard Worker // TODO(jlavrova, kjlubick) This should probably be created explicitly by the client
53*c8dee2aaSAndroid Build Coastguard Worker // (either one based on ICU data or a client explicitly made) and passed in to build().
get_unicode()54*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkUnicode> get_unicode() {
55*c8dee2aaSAndroid Build Coastguard Worker // For code size reasons, we prefer to use the unicode implementation first
56*c8dee2aaSAndroid Build Coastguard Worker // over the full ICU version.
57*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_UNICODE_ICU_IMPLEMENTATION)
58*c8dee2aaSAndroid Build Coastguard Worker return SkUnicodes::ICU::Make();
59*c8dee2aaSAndroid Build Coastguard Worker #else
60*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
61*c8dee2aaSAndroid Build Coastguard Worker #endif
62*c8dee2aaSAndroid Build Coastguard Worker }
63*c8dee2aaSAndroid Build Coastguard Worker
64*c8dee2aaSAndroid Build Coastguard Worker struct SimpleTextStyle {
65*c8dee2aaSAndroid Build Coastguard Worker WASMPointerF32 colorPtr;
66*c8dee2aaSAndroid Build Coastguard Worker WASMPointerF32 foregroundColorPtr;
67*c8dee2aaSAndroid Build Coastguard Worker WASMPointerF32 backgroundColorPtr;
68*c8dee2aaSAndroid Build Coastguard Worker uint8_t decoration;
69*c8dee2aaSAndroid Build Coastguard Worker SkScalar decorationThickness;
70*c8dee2aaSAndroid Build Coastguard Worker WASMPointerF32 decorationColorPtr;
71*c8dee2aaSAndroid Build Coastguard Worker para::TextDecorationStyle decorationStyle;
72*c8dee2aaSAndroid Build Coastguard Worker para::TextBaseline textBaseline;
73*c8dee2aaSAndroid Build Coastguard Worker SkScalar fontSize;
74*c8dee2aaSAndroid Build Coastguard Worker SkScalar letterSpacing;
75*c8dee2aaSAndroid Build Coastguard Worker SkScalar wordSpacing;
76*c8dee2aaSAndroid Build Coastguard Worker SkScalar heightMultiplier;
77*c8dee2aaSAndroid Build Coastguard Worker bool halfLeading;
78*c8dee2aaSAndroid Build Coastguard Worker WASMPointerU8 localePtr;
79*c8dee2aaSAndroid Build Coastguard Worker int localeLen;
80*c8dee2aaSAndroid Build Coastguard Worker SimpleFontStyle fontStyle;
81*c8dee2aaSAndroid Build Coastguard Worker
82*c8dee2aaSAndroid Build Coastguard Worker WASMPointerU8 fontFamiliesPtr;
83*c8dee2aaSAndroid Build Coastguard Worker int fontFamiliesLen;
84*c8dee2aaSAndroid Build Coastguard Worker
85*c8dee2aaSAndroid Build Coastguard Worker int shadowLen;
86*c8dee2aaSAndroid Build Coastguard Worker WASMPointerF32 shadowColorsPtr;
87*c8dee2aaSAndroid Build Coastguard Worker WASMPointerF32 shadowOffsetsPtr;
88*c8dee2aaSAndroid Build Coastguard Worker WASMPointerF32 shadowBlurRadiiPtr;
89*c8dee2aaSAndroid Build Coastguard Worker
90*c8dee2aaSAndroid Build Coastguard Worker int fontFeatureLen;
91*c8dee2aaSAndroid Build Coastguard Worker WASMPointerF32 fontFeatureNamesPtr;
92*c8dee2aaSAndroid Build Coastguard Worker WASMPointerF32 fontFeatureValuesPtr;
93*c8dee2aaSAndroid Build Coastguard Worker
94*c8dee2aaSAndroid Build Coastguard Worker int fontVariationLen;
95*c8dee2aaSAndroid Build Coastguard Worker WASMPointerF32 fontVariationAxesPtr;
96*c8dee2aaSAndroid Build Coastguard Worker WASMPointerF32 fontVariationValuesPtr;
97*c8dee2aaSAndroid Build Coastguard Worker };
98*c8dee2aaSAndroid Build Coastguard Worker
99*c8dee2aaSAndroid Build Coastguard Worker struct SimpleStrutStyle {
100*c8dee2aaSAndroid Build Coastguard Worker WASMPointerU32 fontFamiliesPtr;
101*c8dee2aaSAndroid Build Coastguard Worker int fontFamiliesLen;
102*c8dee2aaSAndroid Build Coastguard Worker SimpleFontStyle fontStyle;
103*c8dee2aaSAndroid Build Coastguard Worker SkScalar fontSize;
104*c8dee2aaSAndroid Build Coastguard Worker SkScalar heightMultiplier;
105*c8dee2aaSAndroid Build Coastguard Worker bool halfLeading;
106*c8dee2aaSAndroid Build Coastguard Worker SkScalar leading;
107*c8dee2aaSAndroid Build Coastguard Worker bool strutEnabled;
108*c8dee2aaSAndroid Build Coastguard Worker bool forceStrutHeight;
109*c8dee2aaSAndroid Build Coastguard Worker };
110*c8dee2aaSAndroid Build Coastguard Worker
toStrutStyle(const SimpleStrutStyle & s)111*c8dee2aaSAndroid Build Coastguard Worker para::StrutStyle toStrutStyle(const SimpleStrutStyle& s) {
112*c8dee2aaSAndroid Build Coastguard Worker para::StrutStyle ss;
113*c8dee2aaSAndroid Build Coastguard Worker
114*c8dee2aaSAndroid Build Coastguard Worker const char** fontFamilies = reinterpret_cast<const char**>(s.fontFamiliesPtr);
115*c8dee2aaSAndroid Build Coastguard Worker if (fontFamilies != nullptr) {
116*c8dee2aaSAndroid Build Coastguard Worker std::vector<SkString> ff;
117*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < s.fontFamiliesLen; i++) {
118*c8dee2aaSAndroid Build Coastguard Worker ff.emplace_back(fontFamilies[i]);
119*c8dee2aaSAndroid Build Coastguard Worker }
120*c8dee2aaSAndroid Build Coastguard Worker ss.setFontFamilies(ff);
121*c8dee2aaSAndroid Build Coastguard Worker }
122*c8dee2aaSAndroid Build Coastguard Worker
123*c8dee2aaSAndroid Build Coastguard Worker SkFontStyle fs(s.fontStyle.weight, s.fontStyle.width, s.fontStyle.slant);
124*c8dee2aaSAndroid Build Coastguard Worker ss.setFontStyle(fs);
125*c8dee2aaSAndroid Build Coastguard Worker
126*c8dee2aaSAndroid Build Coastguard Worker if (s.fontSize != -1) {
127*c8dee2aaSAndroid Build Coastguard Worker ss.setFontSize(s.fontSize);
128*c8dee2aaSAndroid Build Coastguard Worker }
129*c8dee2aaSAndroid Build Coastguard Worker if (s.heightMultiplier != -1) {
130*c8dee2aaSAndroid Build Coastguard Worker ss.setHeight(s.heightMultiplier);
131*c8dee2aaSAndroid Build Coastguard Worker ss.setHeightOverride(true);
132*c8dee2aaSAndroid Build Coastguard Worker }
133*c8dee2aaSAndroid Build Coastguard Worker ss.setHalfLeading(s.halfLeading);
134*c8dee2aaSAndroid Build Coastguard Worker
135*c8dee2aaSAndroid Build Coastguard Worker if (s.leading != 0) {
136*c8dee2aaSAndroid Build Coastguard Worker ss.setLeading(s.leading);
137*c8dee2aaSAndroid Build Coastguard Worker }
138*c8dee2aaSAndroid Build Coastguard Worker
139*c8dee2aaSAndroid Build Coastguard Worker ss.setStrutEnabled(s.strutEnabled);
140*c8dee2aaSAndroid Build Coastguard Worker ss.setForceStrutHeight(s.forceStrutHeight);
141*c8dee2aaSAndroid Build Coastguard Worker
142*c8dee2aaSAndroid Build Coastguard Worker return ss;
143*c8dee2aaSAndroid Build Coastguard Worker }
144*c8dee2aaSAndroid Build Coastguard Worker
toTextStyle(const SimpleTextStyle & s)145*c8dee2aaSAndroid Build Coastguard Worker para::TextStyle toTextStyle(const SimpleTextStyle& s) {
146*c8dee2aaSAndroid Build Coastguard Worker para::TextStyle ts;
147*c8dee2aaSAndroid Build Coastguard Worker
148*c8dee2aaSAndroid Build Coastguard Worker // textstyle.color doesn't support a 4f color, however the foreground and background fields
149*c8dee2aaSAndroid Build Coastguard Worker // below do.
150*c8dee2aaSAndroid Build Coastguard Worker ts.setColor(toSkColor4f(s.colorPtr).toSkColor());
151*c8dee2aaSAndroid Build Coastguard Worker
152*c8dee2aaSAndroid Build Coastguard Worker // It is functionally important that these paints be unset when no value was provided.
153*c8dee2aaSAndroid Build Coastguard Worker if (s.foregroundColorPtr) {
154*c8dee2aaSAndroid Build Coastguard Worker SkPaint p1;
155*c8dee2aaSAndroid Build Coastguard Worker p1.setColor4f(toSkColor4f(s.foregroundColorPtr));
156*c8dee2aaSAndroid Build Coastguard Worker ts.setForegroundColor(p1);
157*c8dee2aaSAndroid Build Coastguard Worker }
158*c8dee2aaSAndroid Build Coastguard Worker
159*c8dee2aaSAndroid Build Coastguard Worker if (s.backgroundColorPtr) {
160*c8dee2aaSAndroid Build Coastguard Worker SkPaint p2;
161*c8dee2aaSAndroid Build Coastguard Worker p2.setColor4f(toSkColor4f(s.backgroundColorPtr));
162*c8dee2aaSAndroid Build Coastguard Worker ts.setBackgroundColor(p2);
163*c8dee2aaSAndroid Build Coastguard Worker }
164*c8dee2aaSAndroid Build Coastguard Worker
165*c8dee2aaSAndroid Build Coastguard Worker if (s.fontSize != -1) {
166*c8dee2aaSAndroid Build Coastguard Worker ts.setFontSize(s.fontSize);
167*c8dee2aaSAndroid Build Coastguard Worker }
168*c8dee2aaSAndroid Build Coastguard Worker if (s.letterSpacing != 0) {
169*c8dee2aaSAndroid Build Coastguard Worker ts.setLetterSpacing(s.letterSpacing);
170*c8dee2aaSAndroid Build Coastguard Worker }
171*c8dee2aaSAndroid Build Coastguard Worker if (s.wordSpacing != 0) {
172*c8dee2aaSAndroid Build Coastguard Worker ts.setWordSpacing(s.wordSpacing);
173*c8dee2aaSAndroid Build Coastguard Worker }
174*c8dee2aaSAndroid Build Coastguard Worker
175*c8dee2aaSAndroid Build Coastguard Worker if (s.heightMultiplier != -1) {
176*c8dee2aaSAndroid Build Coastguard Worker ts.setHeight(s.heightMultiplier);
177*c8dee2aaSAndroid Build Coastguard Worker ts.setHeightOverride(true);
178*c8dee2aaSAndroid Build Coastguard Worker }
179*c8dee2aaSAndroid Build Coastguard Worker
180*c8dee2aaSAndroid Build Coastguard Worker ts.setHalfLeading(s.halfLeading);
181*c8dee2aaSAndroid Build Coastguard Worker
182*c8dee2aaSAndroid Build Coastguard Worker ts.setDecoration(para::TextDecoration(s.decoration));
183*c8dee2aaSAndroid Build Coastguard Worker ts.setDecorationStyle(s.decorationStyle);
184*c8dee2aaSAndroid Build Coastguard Worker if (s.decorationThickness != 0) {
185*c8dee2aaSAndroid Build Coastguard Worker ts.setDecorationThicknessMultiplier(s.decorationThickness);
186*c8dee2aaSAndroid Build Coastguard Worker }
187*c8dee2aaSAndroid Build Coastguard Worker if (s.decorationColorPtr) {
188*c8dee2aaSAndroid Build Coastguard Worker ts.setDecorationColor(toSkColor4f(s.decorationColorPtr).toSkColor());
189*c8dee2aaSAndroid Build Coastguard Worker }
190*c8dee2aaSAndroid Build Coastguard Worker
191*c8dee2aaSAndroid Build Coastguard Worker if (s.localeLen > 0) {
192*c8dee2aaSAndroid Build Coastguard Worker const char* localePtr = reinterpret_cast<const char*>(s.localePtr);
193*c8dee2aaSAndroid Build Coastguard Worker SkString lStr(localePtr, s.localeLen);
194*c8dee2aaSAndroid Build Coastguard Worker ts.setLocale(lStr);
195*c8dee2aaSAndroid Build Coastguard Worker }
196*c8dee2aaSAndroid Build Coastguard Worker
197*c8dee2aaSAndroid Build Coastguard Worker const char** fontFamilies = reinterpret_cast<const char**>(s.fontFamiliesPtr);
198*c8dee2aaSAndroid Build Coastguard Worker if (fontFamilies != nullptr) {
199*c8dee2aaSAndroid Build Coastguard Worker std::vector<SkString> ff;
200*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < s.fontFamiliesLen; i++) {
201*c8dee2aaSAndroid Build Coastguard Worker ff.emplace_back(fontFamilies[i]);
202*c8dee2aaSAndroid Build Coastguard Worker }
203*c8dee2aaSAndroid Build Coastguard Worker ts.setFontFamilies(ff);
204*c8dee2aaSAndroid Build Coastguard Worker }
205*c8dee2aaSAndroid Build Coastguard Worker
206*c8dee2aaSAndroid Build Coastguard Worker ts.setTextBaseline(s.textBaseline);
207*c8dee2aaSAndroid Build Coastguard Worker
208*c8dee2aaSAndroid Build Coastguard Worker SkFontStyle fs(s.fontStyle.weight, s.fontStyle.width, s.fontStyle.slant);
209*c8dee2aaSAndroid Build Coastguard Worker ts.setFontStyle(fs);
210*c8dee2aaSAndroid Build Coastguard Worker
211*c8dee2aaSAndroid Build Coastguard Worker if (s.shadowLen > 0) {
212*c8dee2aaSAndroid Build Coastguard Worker const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(s.shadowColorsPtr);
213*c8dee2aaSAndroid Build Coastguard Worker const SkPoint* offsets = reinterpret_cast<const SkPoint*>(s.shadowOffsetsPtr);
214*c8dee2aaSAndroid Build Coastguard Worker const float* blurRadii = reinterpret_cast<const float*>(s.shadowBlurRadiiPtr);
215*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < s.shadowLen; i++) {
216*c8dee2aaSAndroid Build Coastguard Worker para::TextShadow shadow(colors[i].toSkColor(), offsets[i], blurRadii[i]);
217*c8dee2aaSAndroid Build Coastguard Worker ts.addShadow(shadow);
218*c8dee2aaSAndroid Build Coastguard Worker }
219*c8dee2aaSAndroid Build Coastguard Worker }
220*c8dee2aaSAndroid Build Coastguard Worker
221*c8dee2aaSAndroid Build Coastguard Worker
222*c8dee2aaSAndroid Build Coastguard Worker if (s.fontFeatureLen > 0) {
223*c8dee2aaSAndroid Build Coastguard Worker const char** fontFeatureNames = reinterpret_cast<const char**>(s.fontFeatureNamesPtr);
224*c8dee2aaSAndroid Build Coastguard Worker const int* fontFeatureValues = reinterpret_cast<const int*>(s.fontFeatureValuesPtr);
225*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < s.fontFeatureLen; i++) {
226*c8dee2aaSAndroid Build Coastguard Worker // Font features names are 4-character simple strings.
227*c8dee2aaSAndroid Build Coastguard Worker SkString name(fontFeatureNames[i], 4);
228*c8dee2aaSAndroid Build Coastguard Worker ts.addFontFeature(name, fontFeatureValues[i]);
229*c8dee2aaSAndroid Build Coastguard Worker }
230*c8dee2aaSAndroid Build Coastguard Worker }
231*c8dee2aaSAndroid Build Coastguard Worker
232*c8dee2aaSAndroid Build Coastguard Worker if (s.fontVariationLen > 0) {
233*c8dee2aaSAndroid Build Coastguard Worker const char** fontVariationAxes = reinterpret_cast<const char**>(s.fontVariationAxesPtr);
234*c8dee2aaSAndroid Build Coastguard Worker const float* fontVariationValues = reinterpret_cast<const float*>(s.fontVariationValuesPtr);
235*c8dee2aaSAndroid Build Coastguard Worker std::vector<SkFontArguments::VariationPosition::Coordinate> coordinates;
236*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < s.fontVariationLen; i++) {
237*c8dee2aaSAndroid Build Coastguard Worker // Font variation axis tags are 4-character simple strings.
238*c8dee2aaSAndroid Build Coastguard Worker SkString axis(fontVariationAxes[i]);
239*c8dee2aaSAndroid Build Coastguard Worker if (axis.size() != 4) {
240*c8dee2aaSAndroid Build Coastguard Worker continue;
241*c8dee2aaSAndroid Build Coastguard Worker }
242*c8dee2aaSAndroid Build Coastguard Worker coordinates.push_back({
243*c8dee2aaSAndroid Build Coastguard Worker SkSetFourByteTag(axis[0], axis[1], axis[2], axis[3]),
244*c8dee2aaSAndroid Build Coastguard Worker fontVariationValues[i]
245*c8dee2aaSAndroid Build Coastguard Worker });
246*c8dee2aaSAndroid Build Coastguard Worker }
247*c8dee2aaSAndroid Build Coastguard Worker SkFontArguments::VariationPosition position = {
248*c8dee2aaSAndroid Build Coastguard Worker coordinates.data(),
249*c8dee2aaSAndroid Build Coastguard Worker static_cast<int>(coordinates.size())
250*c8dee2aaSAndroid Build Coastguard Worker };
251*c8dee2aaSAndroid Build Coastguard Worker ts.setFontArguments(SkFontArguments().setVariationDesignPosition(position));
252*c8dee2aaSAndroid Build Coastguard Worker }
253*c8dee2aaSAndroid Build Coastguard Worker
254*c8dee2aaSAndroid Build Coastguard Worker return ts;
255*c8dee2aaSAndroid Build Coastguard Worker }
256*c8dee2aaSAndroid Build Coastguard Worker
257*c8dee2aaSAndroid Build Coastguard Worker struct SimpleParagraphStyle {
258*c8dee2aaSAndroid Build Coastguard Worker bool disableHinting;
259*c8dee2aaSAndroid Build Coastguard Worker WASMPointerU8 ellipsisPtr;
260*c8dee2aaSAndroid Build Coastguard Worker size_t ellipsisLen;
261*c8dee2aaSAndroid Build Coastguard Worker SkScalar heightMultiplier;
262*c8dee2aaSAndroid Build Coastguard Worker size_t maxLines;
263*c8dee2aaSAndroid Build Coastguard Worker bool replaceTabCharacters;
264*c8dee2aaSAndroid Build Coastguard Worker para::TextAlign textAlign;
265*c8dee2aaSAndroid Build Coastguard Worker para::TextDirection textDirection;
266*c8dee2aaSAndroid Build Coastguard Worker para::TextHeightBehavior textHeightBehavior;
267*c8dee2aaSAndroid Build Coastguard Worker SimpleTextStyle textStyle;
268*c8dee2aaSAndroid Build Coastguard Worker SimpleStrutStyle strutStyle;
269*c8dee2aaSAndroid Build Coastguard Worker bool applyRoundingHack;
270*c8dee2aaSAndroid Build Coastguard Worker };
271*c8dee2aaSAndroid Build Coastguard Worker
toParagraphStyle(const SimpleParagraphStyle & s)272*c8dee2aaSAndroid Build Coastguard Worker para::ParagraphStyle toParagraphStyle(const SimpleParagraphStyle& s) {
273*c8dee2aaSAndroid Build Coastguard Worker para::ParagraphStyle ps;
274*c8dee2aaSAndroid Build Coastguard Worker if (s.disableHinting) {
275*c8dee2aaSAndroid Build Coastguard Worker ps.turnHintingOff();
276*c8dee2aaSAndroid Build Coastguard Worker }
277*c8dee2aaSAndroid Build Coastguard Worker
278*c8dee2aaSAndroid Build Coastguard Worker if (s.ellipsisLen > 0) {
279*c8dee2aaSAndroid Build Coastguard Worker const char* ellipsisPtr = reinterpret_cast<const char*>(s.ellipsisPtr);
280*c8dee2aaSAndroid Build Coastguard Worker SkString eStr(ellipsisPtr, s.ellipsisLen);
281*c8dee2aaSAndroid Build Coastguard Worker ps.setEllipsis(eStr);
282*c8dee2aaSAndroid Build Coastguard Worker }
283*c8dee2aaSAndroid Build Coastguard Worker ps.setTextAlign(s.textAlign);
284*c8dee2aaSAndroid Build Coastguard Worker ps.setTextDirection(s.textDirection);
285*c8dee2aaSAndroid Build Coastguard Worker auto ts = toTextStyle(s.textStyle);
286*c8dee2aaSAndroid Build Coastguard Worker ps.setTextStyle(ts);
287*c8dee2aaSAndroid Build Coastguard Worker auto ss = toStrutStyle(s.strutStyle);
288*c8dee2aaSAndroid Build Coastguard Worker ps.setStrutStyle(ss);
289*c8dee2aaSAndroid Build Coastguard Worker if (s.heightMultiplier != -1) {
290*c8dee2aaSAndroid Build Coastguard Worker ps.setHeight(s.heightMultiplier);
291*c8dee2aaSAndroid Build Coastguard Worker }
292*c8dee2aaSAndroid Build Coastguard Worker if (s.maxLines != 0) {
293*c8dee2aaSAndroid Build Coastguard Worker ps.setMaxLines(s.maxLines);
294*c8dee2aaSAndroid Build Coastguard Worker }
295*c8dee2aaSAndroid Build Coastguard Worker ps.setApplyRoundingHack(s.applyRoundingHack);
296*c8dee2aaSAndroid Build Coastguard Worker ps.setTextHeightBehavior(s.textHeightBehavior);
297*c8dee2aaSAndroid Build Coastguard Worker ps.setReplaceTabCharacters(s.replaceTabCharacters);
298*c8dee2aaSAndroid Build Coastguard Worker return ps;
299*c8dee2aaSAndroid Build Coastguard Worker }
300*c8dee2aaSAndroid Build Coastguard Worker
301*c8dee2aaSAndroid Build Coastguard Worker struct SimpleTextBox {
302*c8dee2aaSAndroid Build Coastguard Worker SkRect rect;
303*c8dee2aaSAndroid Build Coastguard Worker // This isn't the most efficient way to represent this, but it is much easier to keep
304*c8dee2aaSAndroid Build Coastguard Worker // everything as floats when unpacking on the JS side.
305*c8dee2aaSAndroid Build Coastguard Worker // 0.0 = RTL, 1.0 = LTr
306*c8dee2aaSAndroid Build Coastguard Worker SkScalar direction;
307*c8dee2aaSAndroid Build Coastguard Worker };
308*c8dee2aaSAndroid Build Coastguard Worker
TextBoxesToFloat32Array(std::vector<para::TextBox> boxes)309*c8dee2aaSAndroid Build Coastguard Worker Float32Array TextBoxesToFloat32Array(std::vector<para::TextBox> boxes) {
310*c8dee2aaSAndroid Build Coastguard Worker // Pack these text boxes into an array of n groups of 5 SkScalar (floats)
311*c8dee2aaSAndroid Build Coastguard Worker if (!boxes.size()) {
312*c8dee2aaSAndroid Build Coastguard Worker return emscripten::val::null();
313*c8dee2aaSAndroid Build Coastguard Worker }
314*c8dee2aaSAndroid Build Coastguard Worker SimpleTextBox* rects = new SimpleTextBox[boxes.size()];
315*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < boxes.size(); i++) {
316*c8dee2aaSAndroid Build Coastguard Worker rects[i].rect = boxes[i].rect;
317*c8dee2aaSAndroid Build Coastguard Worker if (boxes[i].direction == para::TextDirection::kRtl) {
318*c8dee2aaSAndroid Build Coastguard Worker rects[i].direction = 0;
319*c8dee2aaSAndroid Build Coastguard Worker } else {
320*c8dee2aaSAndroid Build Coastguard Worker rects[i].direction = 1;
321*c8dee2aaSAndroid Build Coastguard Worker }
322*c8dee2aaSAndroid Build Coastguard Worker }
323*c8dee2aaSAndroid Build Coastguard Worker float* fPtr = reinterpret_cast<float*>(rects);
324*c8dee2aaSAndroid Build Coastguard Worker // Of note: now that we have cast rects to float*, emscripten is smart enough to wrap this
325*c8dee2aaSAndroid Build Coastguard Worker // into a Float32Array for us.
326*c8dee2aaSAndroid Build Coastguard Worker return Float32Array(typed_memory_view(boxes.size() * 5, fPtr));
327*c8dee2aaSAndroid Build Coastguard Worker }
328*c8dee2aaSAndroid Build Coastguard Worker
GetRectsForRange(para::Paragraph & self,unsigned start,unsigned end,para::RectHeightStyle heightStyle,para::RectWidthStyle widthStyle)329*c8dee2aaSAndroid Build Coastguard Worker Float32Array GetRectsForRange(para::Paragraph& self,
330*c8dee2aaSAndroid Build Coastguard Worker unsigned start,
331*c8dee2aaSAndroid Build Coastguard Worker unsigned end,
332*c8dee2aaSAndroid Build Coastguard Worker para::RectHeightStyle heightStyle,
333*c8dee2aaSAndroid Build Coastguard Worker para::RectWidthStyle widthStyle) {
334*c8dee2aaSAndroid Build Coastguard Worker std::vector<para::TextBox> boxes = self.getRectsForRange(start, end, heightStyle, widthStyle);
335*c8dee2aaSAndroid Build Coastguard Worker return TextBoxesToFloat32Array(boxes);
336*c8dee2aaSAndroid Build Coastguard Worker }
337*c8dee2aaSAndroid Build Coastguard Worker
GetRectsForPlaceholders(para::Paragraph & self)338*c8dee2aaSAndroid Build Coastguard Worker Float32Array GetRectsForPlaceholders(para::Paragraph& self) {
339*c8dee2aaSAndroid Build Coastguard Worker std::vector<para::TextBox> boxes = self.getRectsForPlaceholders();
340*c8dee2aaSAndroid Build Coastguard Worker return TextBoxesToFloat32Array(boxes);
341*c8dee2aaSAndroid Build Coastguard Worker }
342*c8dee2aaSAndroid Build Coastguard Worker
JSObjectFromLineMetrics(skia::textlayout::LineMetrics & metrics)343*c8dee2aaSAndroid Build Coastguard Worker JSObject JSObjectFromLineMetrics(skia::textlayout::LineMetrics& metrics) {
344*c8dee2aaSAndroid Build Coastguard Worker JSObject m = emscripten::val::object();
345*c8dee2aaSAndroid Build Coastguard Worker m.set("startIndex", metrics.fStartIndex);
346*c8dee2aaSAndroid Build Coastguard Worker m.set("endIndex", metrics.fEndIndex);
347*c8dee2aaSAndroid Build Coastguard Worker m.set("endExcludingWhitespaces", metrics.fEndExcludingWhitespaces);
348*c8dee2aaSAndroid Build Coastguard Worker m.set("endIncludingNewline", metrics.fEndIncludingNewline);
349*c8dee2aaSAndroid Build Coastguard Worker m.set("isHardBreak", metrics.fHardBreak);
350*c8dee2aaSAndroid Build Coastguard Worker m.set("ascent", metrics.fAscent);
351*c8dee2aaSAndroid Build Coastguard Worker m.set("descent", metrics.fDescent);
352*c8dee2aaSAndroid Build Coastguard Worker m.set("height", metrics.fHeight);
353*c8dee2aaSAndroid Build Coastguard Worker m.set("width", metrics.fWidth);
354*c8dee2aaSAndroid Build Coastguard Worker m.set("left", metrics.fLeft);
355*c8dee2aaSAndroid Build Coastguard Worker m.set("baseline", metrics.fBaseline);
356*c8dee2aaSAndroid Build Coastguard Worker m.set("lineNumber", metrics.fLineNumber);
357*c8dee2aaSAndroid Build Coastguard Worker return m;
358*c8dee2aaSAndroid Build Coastguard Worker }
359*c8dee2aaSAndroid Build Coastguard Worker
JSObjectFromGlyphInfo(skia::textlayout::Paragraph::GlyphInfo & glyphInfo)360*c8dee2aaSAndroid Build Coastguard Worker JSObject JSObjectFromGlyphInfo(skia::textlayout::Paragraph::GlyphInfo& glyphInfo) {
361*c8dee2aaSAndroid Build Coastguard Worker JSObject object = emscripten::val::object();
362*c8dee2aaSAndroid Build Coastguard Worker
363*c8dee2aaSAndroid Build Coastguard Worker JSObject range = emscripten::val::object();
364*c8dee2aaSAndroid Build Coastguard Worker range.set("start", glyphInfo.fGraphemeClusterTextRange.start);
365*c8dee2aaSAndroid Build Coastguard Worker range.set("end", glyphInfo.fGraphemeClusterTextRange.end);
366*c8dee2aaSAndroid Build Coastguard Worker object.set("graphemeClusterTextRange", range);
367*c8dee2aaSAndroid Build Coastguard Worker
368*c8dee2aaSAndroid Build Coastguard Worker JSArray rect = emscripten::val::array();
369*c8dee2aaSAndroid Build Coastguard Worker rect.call<void>("push", glyphInfo.fGraphemeLayoutBounds.left());
370*c8dee2aaSAndroid Build Coastguard Worker rect.call<void>("push", glyphInfo.fGraphemeLayoutBounds.top());
371*c8dee2aaSAndroid Build Coastguard Worker rect.call<void>("push", glyphInfo.fGraphemeLayoutBounds.right());
372*c8dee2aaSAndroid Build Coastguard Worker rect.call<void>("push", glyphInfo.fGraphemeLayoutBounds.bottom());
373*c8dee2aaSAndroid Build Coastguard Worker object.set("graphemeLayoutBounds", rect);
374*c8dee2aaSAndroid Build Coastguard Worker
375*c8dee2aaSAndroid Build Coastguard Worker object.set("dir", glyphInfo.fDirection == skia::textlayout::TextDirection::kRtl ? 0 : 1);
376*c8dee2aaSAndroid Build Coastguard Worker object.set("isEllipsis", glyphInfo.fIsEllipsis);
377*c8dee2aaSAndroid Build Coastguard Worker return object;
378*c8dee2aaSAndroid Build Coastguard Worker }
379*c8dee2aaSAndroid Build Coastguard Worker
GetLineMetrics(para::Paragraph & self)380*c8dee2aaSAndroid Build Coastguard Worker JSArray GetLineMetrics(para::Paragraph& self) {
381*c8dee2aaSAndroid Build Coastguard Worker std::vector<skia::textlayout::LineMetrics> metrics;
382*c8dee2aaSAndroid Build Coastguard Worker self.getLineMetrics(metrics);
383*c8dee2aaSAndroid Build Coastguard Worker JSArray result = emscripten::val::array();
384*c8dee2aaSAndroid Build Coastguard Worker for (auto metric : metrics) {
385*c8dee2aaSAndroid Build Coastguard Worker result.call<void>("push", JSObjectFromLineMetrics(metric));
386*c8dee2aaSAndroid Build Coastguard Worker }
387*c8dee2aaSAndroid Build Coastguard Worker return result;
388*c8dee2aaSAndroid Build Coastguard Worker }
389*c8dee2aaSAndroid Build Coastguard Worker
GetLineMetricsAt(para::Paragraph & self,size_t lineNumber)390*c8dee2aaSAndroid Build Coastguard Worker JSObject GetLineMetricsAt(para::Paragraph& self, size_t lineNumber) {
391*c8dee2aaSAndroid Build Coastguard Worker skia::textlayout::LineMetrics metrics;
392*c8dee2aaSAndroid Build Coastguard Worker return self.getLineMetricsAt(lineNumber, &metrics)
393*c8dee2aaSAndroid Build Coastguard Worker ? JSObjectFromLineMetrics(metrics)
394*c8dee2aaSAndroid Build Coastguard Worker : emscripten::val::null();
395*c8dee2aaSAndroid Build Coastguard Worker }
396*c8dee2aaSAndroid Build Coastguard Worker
GetGlyphInfoAt(para::Paragraph & self,size_t index)397*c8dee2aaSAndroid Build Coastguard Worker JSObject GetGlyphInfoAt(para::Paragraph& self, size_t index) {
398*c8dee2aaSAndroid Build Coastguard Worker skia::textlayout::Paragraph::GlyphInfo glyphInfo;
399*c8dee2aaSAndroid Build Coastguard Worker return self.getGlyphInfoAtUTF16Offset(index, &glyphInfo)
400*c8dee2aaSAndroid Build Coastguard Worker ? JSObjectFromGlyphInfo(glyphInfo)
401*c8dee2aaSAndroid Build Coastguard Worker : emscripten::val::null();
402*c8dee2aaSAndroid Build Coastguard Worker }
403*c8dee2aaSAndroid Build Coastguard Worker
GetClosestGlyphInfoAtCoordinate(para::Paragraph & self,SkScalar dx,SkScalar dy)404*c8dee2aaSAndroid Build Coastguard Worker JSObject GetClosestGlyphInfoAtCoordinate(para::Paragraph& self, SkScalar dx, SkScalar dy) {
405*c8dee2aaSAndroid Build Coastguard Worker skia::textlayout::Paragraph::GlyphInfo glyphInfo;
406*c8dee2aaSAndroid Build Coastguard Worker return self.getClosestUTF16GlyphInfoAt(dx, dy, &glyphInfo)
407*c8dee2aaSAndroid Build Coastguard Worker ? JSObjectFromGlyphInfo(glyphInfo)
408*c8dee2aaSAndroid Build Coastguard Worker : emscripten::val::null();
409*c8dee2aaSAndroid Build Coastguard Worker }
410*c8dee2aaSAndroid Build Coastguard Worker
411*c8dee2aaSAndroid Build Coastguard Worker /*
412*c8dee2aaSAndroid Build Coastguard Worker * Returns Lines[]
413*c8dee2aaSAndroid Build Coastguard Worker */
GetShapedLines(para::Paragraph & self)414*c8dee2aaSAndroid Build Coastguard Worker JSArray GetShapedLines(para::Paragraph& self) {
415*c8dee2aaSAndroid Build Coastguard Worker struct LineAccumulate {
416*c8dee2aaSAndroid Build Coastguard Worker int lineNumber = -1; // deliberately -1 from starting value
417*c8dee2aaSAndroid Build Coastguard Worker uint32_t minOffset = 0xFFFFFFFF;
418*c8dee2aaSAndroid Build Coastguard Worker uint32_t maxOffset = 0;
419*c8dee2aaSAndroid Build Coastguard Worker float minAscent = 0;
420*c8dee2aaSAndroid Build Coastguard Worker float maxDescent = 0;
421*c8dee2aaSAndroid Build Coastguard Worker // not really accumulated, but definitely set
422*c8dee2aaSAndroid Build Coastguard Worker float baseline = 0;
423*c8dee2aaSAndroid Build Coastguard Worker
424*c8dee2aaSAndroid Build Coastguard Worker void reset(int newLineNum) {
425*c8dee2aaSAndroid Build Coastguard Worker new (this) LineAccumulate;
426*c8dee2aaSAndroid Build Coastguard Worker this->lineNumber = newLineNum;
427*c8dee2aaSAndroid Build Coastguard Worker }
428*c8dee2aaSAndroid Build Coastguard Worker };
429*c8dee2aaSAndroid Build Coastguard Worker
430*c8dee2aaSAndroid Build Coastguard Worker // where we accumulate our js output
431*c8dee2aaSAndroid Build Coastguard Worker JSArray jlines = emscripten::val::array();
432*c8dee2aaSAndroid Build Coastguard Worker JSObject jline = emscripten::val::null();
433*c8dee2aaSAndroid Build Coastguard Worker JSArray jruns = emscripten::val::null();
434*c8dee2aaSAndroid Build Coastguard Worker LineAccumulate accum;
435*c8dee2aaSAndroid Build Coastguard Worker
436*c8dee2aaSAndroid Build Coastguard Worker self.visit([&](int lineNumber, const para::Paragraph::VisitorInfo* info) {
437*c8dee2aaSAndroid Build Coastguard Worker if (!info) {
438*c8dee2aaSAndroid Build Coastguard Worker if (!jline) return; // how???
439*c8dee2aaSAndroid Build Coastguard Worker // end of current line
440*c8dee2aaSAndroid Build Coastguard Worker JSObject range = emscripten::val::object();
441*c8dee2aaSAndroid Build Coastguard Worker range.set("first", accum.minOffset);
442*c8dee2aaSAndroid Build Coastguard Worker range.set("last", accum.maxOffset);
443*c8dee2aaSAndroid Build Coastguard Worker jline.set("textRange", range);
444*c8dee2aaSAndroid Build Coastguard Worker
445*c8dee2aaSAndroid Build Coastguard Worker jline.set("top", accum.baseline + accum.minAscent);
446*c8dee2aaSAndroid Build Coastguard Worker jline.set("bottom", accum.baseline + accum.maxDescent);
447*c8dee2aaSAndroid Build Coastguard Worker jline.set("baseline", accum.baseline);
448*c8dee2aaSAndroid Build Coastguard Worker return;
449*c8dee2aaSAndroid Build Coastguard Worker }
450*c8dee2aaSAndroid Build Coastguard Worker
451*c8dee2aaSAndroid Build Coastguard Worker if (lineNumber != accum.lineNumber) {
452*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(lineNumber == accum.lineNumber + 1); // assume monotonic
453*c8dee2aaSAndroid Build Coastguard Worker
454*c8dee2aaSAndroid Build Coastguard Worker accum.reset(lineNumber);
455*c8dee2aaSAndroid Build Coastguard Worker jruns = emscripten::val::array();
456*c8dee2aaSAndroid Build Coastguard Worker
457*c8dee2aaSAndroid Build Coastguard Worker jline = emscripten::val::object();
458*c8dee2aaSAndroid Build Coastguard Worker jline.set("runs", jruns);
459*c8dee2aaSAndroid Build Coastguard Worker // will assign textRange and metrics on end-of-line signal
460*c8dee2aaSAndroid Build Coastguard Worker
461*c8dee2aaSAndroid Build Coastguard Worker jlines.call<void>("push", jline);
462*c8dee2aaSAndroid Build Coastguard Worker }
463*c8dee2aaSAndroid Build Coastguard Worker
464*c8dee2aaSAndroid Build Coastguard Worker // append the run
465*c8dee2aaSAndroid Build Coastguard Worker const int N = info->count; // glyphs
466*c8dee2aaSAndroid Build Coastguard Worker const int N1 = N + 1; // positions, offsets have 1 extra (trailing) slot
467*c8dee2aaSAndroid Build Coastguard Worker
468*c8dee2aaSAndroid Build Coastguard Worker JSObject jrun = emscripten::val::object();
469*c8dee2aaSAndroid Build Coastguard Worker
470*c8dee2aaSAndroid Build Coastguard Worker jrun.set("flags", info->flags);
471*c8dee2aaSAndroid Build Coastguard Worker
472*c8dee2aaSAndroid Build Coastguard Worker // TODO: figure out how to set a wrapped sk_sp<SkTypeface>
473*c8dee2aaSAndroid Build Coastguard Worker // jrun.set("typeface", info->font.getTypeface());
474*c8dee2aaSAndroid Build Coastguard Worker jrun.set("typeface", emscripten::val::null());
475*c8dee2aaSAndroid Build Coastguard Worker jrun.set("size", info->font.getSize());
476*c8dee2aaSAndroid Build Coastguard Worker if (info->font.getScaleX()) {
477*c8dee2aaSAndroid Build Coastguard Worker jrun.set("scaleX", info->font.getScaleX());
478*c8dee2aaSAndroid Build Coastguard Worker }
479*c8dee2aaSAndroid Build Coastguard Worker
480*c8dee2aaSAndroid Build Coastguard Worker jrun.set("glyphs", MakeTypedArray(N, info->glyphs));
481*c8dee2aaSAndroid Build Coastguard Worker jrun.set("offsets", MakeTypedArray(N1, info->utf8Starts));
482*c8dee2aaSAndroid Build Coastguard Worker
483*c8dee2aaSAndroid Build Coastguard Worker // we need to modify the positions, so make a temp copy
484*c8dee2aaSAndroid Build Coastguard Worker AutoSTMalloc<32, SkPoint> positions(N1);
485*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < N; ++i) {
486*c8dee2aaSAndroid Build Coastguard Worker positions.get()[i] = info->positions[i] + info->origin;
487*c8dee2aaSAndroid Build Coastguard Worker }
488*c8dee2aaSAndroid Build Coastguard Worker positions.get()[N] = { info->advanceX, positions.get()[N - 1].fY };
489*c8dee2aaSAndroid Build Coastguard Worker jrun.set("positions", MakeTypedArray(N1*2, (const float*)positions.get()));
490*c8dee2aaSAndroid Build Coastguard Worker
491*c8dee2aaSAndroid Build Coastguard Worker jruns.call<void>("push", jrun);
492*c8dee2aaSAndroid Build Coastguard Worker
493*c8dee2aaSAndroid Build Coastguard Worker // update accum
494*c8dee2aaSAndroid Build Coastguard Worker { SkFontMetrics fm;
495*c8dee2aaSAndroid Build Coastguard Worker info->font.getMetrics(&fm);
496*c8dee2aaSAndroid Build Coastguard Worker
497*c8dee2aaSAndroid Build Coastguard Worker accum.minAscent = std::min(accum.minAscent, fm.fAscent);
498*c8dee2aaSAndroid Build Coastguard Worker accum.maxDescent = std::max(accum.maxDescent, fm.fDescent);
499*c8dee2aaSAndroid Build Coastguard Worker accum.baseline = info->origin.fY;
500*c8dee2aaSAndroid Build Coastguard Worker
501*c8dee2aaSAndroid Build Coastguard Worker accum.minOffset = std::min(accum.minOffset, info->utf8Starts[0]);
502*c8dee2aaSAndroid Build Coastguard Worker accum.maxOffset = std::max(accum.maxOffset, info->utf8Starts[N]);
503*c8dee2aaSAndroid Build Coastguard Worker }
504*c8dee2aaSAndroid Build Coastguard Worker
505*c8dee2aaSAndroid Build Coastguard Worker });
506*c8dee2aaSAndroid Build Coastguard Worker return jlines;
507*c8dee2aaSAndroid Build Coastguard Worker }
508*c8dee2aaSAndroid Build Coastguard Worker
convertArrayU32(WASMPointerU32 array,size_t count)509*c8dee2aaSAndroid Build Coastguard Worker std::vector<SkUnicode::Position> convertArrayU32(WASMPointerU32 array, size_t count) {
510*c8dee2aaSAndroid Build Coastguard Worker std::vector<size_t> vec;
511*c8dee2aaSAndroid Build Coastguard Worker vec.resize(count);
512*c8dee2aaSAndroid Build Coastguard Worker SkUnicode::Position* data = reinterpret_cast<SkUnicode::Position*>(array);
513*c8dee2aaSAndroid Build Coastguard Worker std::memcpy(vec.data(), data, count * sizeof(size_t));
514*c8dee2aaSAndroid Build Coastguard Worker return vec;
515*c8dee2aaSAndroid Build Coastguard Worker }
516*c8dee2aaSAndroid Build Coastguard Worker
UnresolvedCodepoints(para::Paragraph & self)517*c8dee2aaSAndroid Build Coastguard Worker JSArray UnresolvedCodepoints(para::Paragraph& self) {
518*c8dee2aaSAndroid Build Coastguard Worker JSArray result = emscripten::val::array();
519*c8dee2aaSAndroid Build Coastguard Worker for (auto cp : self.unresolvedCodepoints()) {
520*c8dee2aaSAndroid Build Coastguard Worker result.call<void>("push", cp);
521*c8dee2aaSAndroid Build Coastguard Worker }
522*c8dee2aaSAndroid Build Coastguard Worker return result;
523*c8dee2aaSAndroid Build Coastguard Worker }
524*c8dee2aaSAndroid Build Coastguard Worker
EMSCRIPTEN_BINDINGS(Paragraph)525*c8dee2aaSAndroid Build Coastguard Worker EMSCRIPTEN_BINDINGS(Paragraph) {
526*c8dee2aaSAndroid Build Coastguard Worker
527*c8dee2aaSAndroid Build Coastguard Worker class_<para::Paragraph>("Paragraph")
528*c8dee2aaSAndroid Build Coastguard Worker .function("didExceedMaxLines", ¶::Paragraph::didExceedMaxLines)
529*c8dee2aaSAndroid Build Coastguard Worker .function("getAlphabeticBaseline", ¶::Paragraph::getAlphabeticBaseline)
530*c8dee2aaSAndroid Build Coastguard Worker .function("getGlyphPositionAtCoordinate", ¶::Paragraph::getGlyphPositionAtCoordinate)
531*c8dee2aaSAndroid Build Coastguard Worker .function("getHeight", ¶::Paragraph::getHeight)
532*c8dee2aaSAndroid Build Coastguard Worker .function("getIdeographicBaseline", ¶::Paragraph::getIdeographicBaseline)
533*c8dee2aaSAndroid Build Coastguard Worker .function("getLineMetrics", &GetLineMetrics)
534*c8dee2aaSAndroid Build Coastguard Worker .function("getLineMetricsAt", &GetLineMetricsAt)
535*c8dee2aaSAndroid Build Coastguard Worker .function("getLineNumberAt", ¶::Paragraph::getLineNumberAt)
536*c8dee2aaSAndroid Build Coastguard Worker .function("getLongestLine", ¶::Paragraph::getLongestLine)
537*c8dee2aaSAndroid Build Coastguard Worker .function("getMaxIntrinsicWidth", ¶::Paragraph::getMaxIntrinsicWidth)
538*c8dee2aaSAndroid Build Coastguard Worker .function("getMaxWidth", ¶::Paragraph::getMaxWidth)
539*c8dee2aaSAndroid Build Coastguard Worker .function("getMinIntrinsicWidth", ¶::Paragraph::getMinIntrinsicWidth)
540*c8dee2aaSAndroid Build Coastguard Worker .function("getNumberOfLines", ¶::Paragraph::lineNumber)
541*c8dee2aaSAndroid Build Coastguard Worker .function("_getClosestGlyphInfoAtCoordinate", &GetClosestGlyphInfoAtCoordinate)
542*c8dee2aaSAndroid Build Coastguard Worker .function("_getGlyphInfoAt", &GetGlyphInfoAt)
543*c8dee2aaSAndroid Build Coastguard Worker .function("_getRectsForPlaceholders", &GetRectsForPlaceholders)
544*c8dee2aaSAndroid Build Coastguard Worker .function("_getRectsForRange", &GetRectsForRange)
545*c8dee2aaSAndroid Build Coastguard Worker .function("getShapedLines", &GetShapedLines)
546*c8dee2aaSAndroid Build Coastguard Worker .function("getWordBoundary", ¶::Paragraph::getWordBoundary)
547*c8dee2aaSAndroid Build Coastguard Worker .function("layout", ¶::Paragraph::layout)
548*c8dee2aaSAndroid Build Coastguard Worker .function("unresolvedCodepoints", &UnresolvedCodepoints);
549*c8dee2aaSAndroid Build Coastguard Worker
550*c8dee2aaSAndroid Build Coastguard Worker class_<para::ParagraphBuilderImpl>("ParagraphBuilder")
551*c8dee2aaSAndroid Build Coastguard Worker .class_function(
552*c8dee2aaSAndroid Build Coastguard Worker "_Make",
553*c8dee2aaSAndroid Build Coastguard Worker optional_override([](SimpleParagraphStyle style, sk_sp<SkFontMgr> fontMgr)
554*c8dee2aaSAndroid Build Coastguard Worker -> std::unique_ptr<para::ParagraphBuilderImpl> {
555*c8dee2aaSAndroid Build Coastguard Worker auto fc = sk_make_sp<para::FontCollection>();
556*c8dee2aaSAndroid Build Coastguard Worker fc->setDefaultFontManager(fontMgr);
557*c8dee2aaSAndroid Build Coastguard Worker fc->enableFontFallback();
558*c8dee2aaSAndroid Build Coastguard Worker auto ps = toParagraphStyle(style);
559*c8dee2aaSAndroid Build Coastguard Worker auto pb = para::ParagraphBuilderImpl::make(ps, fc, get_unicode());
560*c8dee2aaSAndroid Build Coastguard Worker return std::unique_ptr<para::ParagraphBuilderImpl>(
561*c8dee2aaSAndroid Build Coastguard Worker static_cast<para::ParagraphBuilderImpl*>(pb.release()));
562*c8dee2aaSAndroid Build Coastguard Worker }),
563*c8dee2aaSAndroid Build Coastguard Worker allow_raw_pointers())
564*c8dee2aaSAndroid Build Coastguard Worker .class_function(
565*c8dee2aaSAndroid Build Coastguard Worker "_MakeFromFontProvider",
566*c8dee2aaSAndroid Build Coastguard Worker optional_override([](SimpleParagraphStyle style,
567*c8dee2aaSAndroid Build Coastguard Worker sk_sp<para::TypefaceFontProvider> fontProvider)
568*c8dee2aaSAndroid Build Coastguard Worker -> std::unique_ptr<para::ParagraphBuilderImpl> {
569*c8dee2aaSAndroid Build Coastguard Worker auto fc = sk_make_sp<para::FontCollection>();
570*c8dee2aaSAndroid Build Coastguard Worker fc->setDefaultFontManager(fontProvider);
571*c8dee2aaSAndroid Build Coastguard Worker fc->enableFontFallback();
572*c8dee2aaSAndroid Build Coastguard Worker auto ps = toParagraphStyle(style);
573*c8dee2aaSAndroid Build Coastguard Worker auto pb = para::ParagraphBuilderImpl::make(ps, fc, get_unicode());
574*c8dee2aaSAndroid Build Coastguard Worker return std::unique_ptr<para::ParagraphBuilderImpl>(
575*c8dee2aaSAndroid Build Coastguard Worker static_cast<para::ParagraphBuilderImpl*>(pb.release()));
576*c8dee2aaSAndroid Build Coastguard Worker }),
577*c8dee2aaSAndroid Build Coastguard Worker allow_raw_pointers())
578*c8dee2aaSAndroid Build Coastguard Worker .class_function(
579*c8dee2aaSAndroid Build Coastguard Worker "_MakeFromFontCollection",
580*c8dee2aaSAndroid Build Coastguard Worker optional_override([](SimpleParagraphStyle style,
581*c8dee2aaSAndroid Build Coastguard Worker sk_sp<para::FontCollection> fontCollection)
582*c8dee2aaSAndroid Build Coastguard Worker -> std::unique_ptr<para::ParagraphBuilderImpl> {
583*c8dee2aaSAndroid Build Coastguard Worker auto ps = toParagraphStyle(style);
584*c8dee2aaSAndroid Build Coastguard Worker auto pb = para::ParagraphBuilderImpl::make(ps, fontCollection, get_unicode());
585*c8dee2aaSAndroid Build Coastguard Worker return std::unique_ptr<para::ParagraphBuilderImpl>(
586*c8dee2aaSAndroid Build Coastguard Worker static_cast<para::ParagraphBuilderImpl*>(pb.release()));
587*c8dee2aaSAndroid Build Coastguard Worker }),
588*c8dee2aaSAndroid Build Coastguard Worker allow_raw_pointers())
589*c8dee2aaSAndroid Build Coastguard Worker .class_function(
590*c8dee2aaSAndroid Build Coastguard Worker "_ShapeText",
591*c8dee2aaSAndroid Build Coastguard Worker optional_override([](JSString jtext, JSArray jruns, float width) -> JSArray {
592*c8dee2aaSAndroid Build Coastguard Worker std::string textStorage = jtext.as<std::string>();
593*c8dee2aaSAndroid Build Coastguard Worker const char* text = textStorage.data();
594*c8dee2aaSAndroid Build Coastguard Worker size_t textCount = textStorage.size();
595*c8dee2aaSAndroid Build Coastguard Worker
596*c8dee2aaSAndroid Build Coastguard Worker auto fc = sk_make_sp<para::FontCollection>();
597*c8dee2aaSAndroid Build Coastguard Worker fc->setDefaultFontManager(SkFontMgr::RefEmpty());
598*c8dee2aaSAndroid Build Coastguard Worker fc->enableFontFallback();
599*c8dee2aaSAndroid Build Coastguard Worker
600*c8dee2aaSAndroid Build Coastguard Worker para::ParagraphStyle pstyle;
601*c8dee2aaSAndroid Build Coastguard Worker {
602*c8dee2aaSAndroid Build Coastguard Worker // For the most part this is ignored, since we set an explicit TextStyle
603*c8dee2aaSAndroid Build Coastguard Worker // for all of our text runs, but it is required by SkParagraph.
604*c8dee2aaSAndroid Build Coastguard Worker para::TextStyle style;
605*c8dee2aaSAndroid Build Coastguard Worker style.setFontFamilies({SkString("sans-serif")});
606*c8dee2aaSAndroid Build Coastguard Worker style.setFontSize(32);
607*c8dee2aaSAndroid Build Coastguard Worker pstyle.setTextStyle(style);
608*c8dee2aaSAndroid Build Coastguard Worker }
609*c8dee2aaSAndroid Build Coastguard Worker
610*c8dee2aaSAndroid Build Coastguard Worker auto pb = para::ParagraphBuilder::make(pstyle, fc, get_unicode());
611*c8dee2aaSAndroid Build Coastguard Worker
612*c8dee2aaSAndroid Build Coastguard Worker // tease apart the FontBlock runs
613*c8dee2aaSAndroid Build Coastguard Worker size_t runCount = jruns["length"].as<size_t>();
614*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < runCount; ++i) {
615*c8dee2aaSAndroid Build Coastguard Worker emscripten::val r = jruns[i];
616*c8dee2aaSAndroid Build Coastguard Worker
617*c8dee2aaSAndroid Build Coastguard Worker para::TextStyle style;
618*c8dee2aaSAndroid Build Coastguard Worker style.setTypeface(r["typeface"].as< sk_sp<SkTypeface> >());
619*c8dee2aaSAndroid Build Coastguard Worker style.setFontSize(r["size"].as<float>());
620*c8dee2aaSAndroid Build Coastguard Worker
621*c8dee2aaSAndroid Build Coastguard Worker const size_t subTextCount = r["length"].as<size_t>();
622*c8dee2aaSAndroid Build Coastguard Worker if (subTextCount > textCount) {
623*c8dee2aaSAndroid Build Coastguard Worker return emscripten::val("block runs exceed text length!");
624*c8dee2aaSAndroid Build Coastguard Worker }
625*c8dee2aaSAndroid Build Coastguard Worker
626*c8dee2aaSAndroid Build Coastguard Worker pb->pushStyle(style);
627*c8dee2aaSAndroid Build Coastguard Worker pb->addText(text, subTextCount);
628*c8dee2aaSAndroid Build Coastguard Worker pb->pop();
629*c8dee2aaSAndroid Build Coastguard Worker
630*c8dee2aaSAndroid Build Coastguard Worker text += subTextCount;
631*c8dee2aaSAndroid Build Coastguard Worker textCount -= subTextCount;
632*c8dee2aaSAndroid Build Coastguard Worker }
633*c8dee2aaSAndroid Build Coastguard Worker if (textCount != 0) {
634*c8dee2aaSAndroid Build Coastguard Worker return emscripten::val("Didn't have enough block runs to cover text");
635*c8dee2aaSAndroid Build Coastguard Worker }
636*c8dee2aaSAndroid Build Coastguard Worker
637*c8dee2aaSAndroid Build Coastguard Worker auto pa = pb->Build();
638*c8dee2aaSAndroid Build Coastguard Worker pa->layout(width);
639*c8dee2aaSAndroid Build Coastguard Worker
640*c8dee2aaSAndroid Build Coastguard Worker // workaround until this is fixed in SkParagraph
641*c8dee2aaSAndroid Build Coastguard Worker {
642*c8dee2aaSAndroid Build Coastguard Worker SkPictureRecorder rec;
643*c8dee2aaSAndroid Build Coastguard Worker pa->paint(rec.beginRecording({0,0,9999,9999}), 0, 0);
644*c8dee2aaSAndroid Build Coastguard Worker }
645*c8dee2aaSAndroid Build Coastguard Worker return GetShapedLines(*pa);
646*c8dee2aaSAndroid Build Coastguard Worker }),
647*c8dee2aaSAndroid Build Coastguard Worker allow_raw_pointers())
648*c8dee2aaSAndroid Build Coastguard Worker .class_function("RequiresClientICU", ¶::ParagraphBuilderImpl::RequiresClientICU)
649*c8dee2aaSAndroid Build Coastguard Worker .function("addText",
650*c8dee2aaSAndroid Build Coastguard Worker optional_override([](para::ParagraphBuilderImpl& self, std::string text) {
651*c8dee2aaSAndroid Build Coastguard Worker return self.addText(text.c_str(), text.length());
652*c8dee2aaSAndroid Build Coastguard Worker }))
653*c8dee2aaSAndroid Build Coastguard Worker .function("build", ¶::ParagraphBuilderImpl::Build, allow_raw_pointers())
654*c8dee2aaSAndroid Build Coastguard Worker .function("build", optional_override([](para::ParagraphBuilderImpl& self) {
655*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
656*c8dee2aaSAndroid Build Coastguard Worker auto [words, graphemeBreaks, lineBreaks] = self.getClientICUData();
657*c8dee2aaSAndroid Build Coastguard Worker auto text = self.getText();
658*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkUnicode> clientICU = SkUnicodes::Client::Make(text, words, graphemeBreaks, lineBreaks);
659*c8dee2aaSAndroid Build Coastguard Worker self.SetUnicode(clientICU);
660*c8dee2aaSAndroid Build Coastguard Worker #endif
661*c8dee2aaSAndroid Build Coastguard Worker return self.Build();
662*c8dee2aaSAndroid Build Coastguard Worker }), allow_raw_pointers())
663*c8dee2aaSAndroid Build Coastguard Worker .function("pop", ¶::ParagraphBuilderImpl::pop)
664*c8dee2aaSAndroid Build Coastguard Worker .function("reset", ¶::ParagraphBuilderImpl::Reset, allow_raw_pointers())
665*c8dee2aaSAndroid Build Coastguard Worker .function("_pushStyle", optional_override([](para::ParagraphBuilderImpl& self,
666*c8dee2aaSAndroid Build Coastguard Worker SimpleTextStyle textStyle) {
667*c8dee2aaSAndroid Build Coastguard Worker auto ts = toTextStyle(textStyle);
668*c8dee2aaSAndroid Build Coastguard Worker self.pushStyle(ts);
669*c8dee2aaSAndroid Build Coastguard Worker }))
670*c8dee2aaSAndroid Build Coastguard Worker // A method of pushing a textStyle with paints instead of colors for foreground and
671*c8dee2aaSAndroid Build Coastguard Worker // background. Since SimpleTextStyle is a value object, it cannot contain paints, which
672*c8dee2aaSAndroid Build Coastguard Worker // are not primitives. This binding is here to accept them. Any color that is specified
673*c8dee2aaSAndroid Build Coastguard Worker // in the textStyle is overridden.
674*c8dee2aaSAndroid Build Coastguard Worker .function("_pushPaintStyle",
675*c8dee2aaSAndroid Build Coastguard Worker optional_override([](para::ParagraphBuilderImpl& self,
676*c8dee2aaSAndroid Build Coastguard Worker SimpleTextStyle textStyle, SkPaint foreground,
677*c8dee2aaSAndroid Build Coastguard Worker SkPaint background) {
678*c8dee2aaSAndroid Build Coastguard Worker auto ts = toTextStyle(textStyle);
679*c8dee2aaSAndroid Build Coastguard Worker ts.setForegroundColor(foreground);
680*c8dee2aaSAndroid Build Coastguard Worker ts.setBackgroundColor(background);
681*c8dee2aaSAndroid Build Coastguard Worker self.pushStyle(ts);
682*c8dee2aaSAndroid Build Coastguard Worker }))
683*c8dee2aaSAndroid Build Coastguard Worker .function("_addPlaceholder", optional_override([](para::ParagraphBuilderImpl& self,
684*c8dee2aaSAndroid Build Coastguard Worker SkScalar width,
685*c8dee2aaSAndroid Build Coastguard Worker SkScalar height,
686*c8dee2aaSAndroid Build Coastguard Worker para::PlaceholderAlignment alignment,
687*c8dee2aaSAndroid Build Coastguard Worker para::TextBaseline baseline,
688*c8dee2aaSAndroid Build Coastguard Worker SkScalar offset) {
689*c8dee2aaSAndroid Build Coastguard Worker para::PlaceholderStyle ps(width, height, alignment, baseline, offset);
690*c8dee2aaSAndroid Build Coastguard Worker self.addPlaceholder(ps);
691*c8dee2aaSAndroid Build Coastguard Worker }))
692*c8dee2aaSAndroid Build Coastguard Worker .function("getText",
693*c8dee2aaSAndroid Build Coastguard Worker optional_override([](para::ParagraphBuilderImpl& self) -> JSString {
694*c8dee2aaSAndroid Build Coastguard Worker auto text = self.getText();
695*c8dee2aaSAndroid Build Coastguard Worker return emscripten::val(std::string(text.data(), text.size()).c_str());
696*c8dee2aaSAndroid Build Coastguard Worker }))
697*c8dee2aaSAndroid Build Coastguard Worker .function("_setWordsUtf8",
698*c8dee2aaSAndroid Build Coastguard Worker optional_override([](para::ParagraphBuilderImpl& self,
699*c8dee2aaSAndroid Build Coastguard Worker WASMPointerU32 clientWords, size_t wordsNum) {
700*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
701*c8dee2aaSAndroid Build Coastguard Worker self.setWordsUtf8(convertArrayU32(clientWords, wordsNum));
702*c8dee2aaSAndroid Build Coastguard Worker #endif
703*c8dee2aaSAndroid Build Coastguard Worker }))
704*c8dee2aaSAndroid Build Coastguard Worker .function("_setWordsUtf16",
705*c8dee2aaSAndroid Build Coastguard Worker optional_override([](para::ParagraphBuilderImpl& self,
706*c8dee2aaSAndroid Build Coastguard Worker WASMPointerU32 clientWords, size_t wordsNum) {
707*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
708*c8dee2aaSAndroid Build Coastguard Worker self.setWordsUtf16(convertArrayU32(clientWords, wordsNum));
709*c8dee2aaSAndroid Build Coastguard Worker #endif
710*c8dee2aaSAndroid Build Coastguard Worker }))
711*c8dee2aaSAndroid Build Coastguard Worker .function("_setGraphemeBreaksUtf8",
712*c8dee2aaSAndroid Build Coastguard Worker optional_override([](para::ParagraphBuilderImpl& self,
713*c8dee2aaSAndroid Build Coastguard Worker WASMPointerU32 clientGraphemes, size_t graphemesNum) {
714*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
715*c8dee2aaSAndroid Build Coastguard Worker self.setGraphemeBreaksUtf8(convertArrayU32(clientGraphemes, graphemesNum));
716*c8dee2aaSAndroid Build Coastguard Worker #endif
717*c8dee2aaSAndroid Build Coastguard Worker }))
718*c8dee2aaSAndroid Build Coastguard Worker .function("_setGraphemeBreaksUtf16",
719*c8dee2aaSAndroid Build Coastguard Worker optional_override([](para::ParagraphBuilderImpl& self,
720*c8dee2aaSAndroid Build Coastguard Worker WASMPointerU32 clientGraphemes, size_t graphemesNum) {
721*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
722*c8dee2aaSAndroid Build Coastguard Worker self.setGraphemeBreaksUtf16(convertArrayU32(clientGraphemes, graphemesNum));
723*c8dee2aaSAndroid Build Coastguard Worker #endif
724*c8dee2aaSAndroid Build Coastguard Worker }))
725*c8dee2aaSAndroid Build Coastguard Worker .function("_setLineBreaksUtf8",
726*c8dee2aaSAndroid Build Coastguard Worker optional_override([](para::ParagraphBuilderImpl& self,
727*c8dee2aaSAndroid Build Coastguard Worker WASMPointerU32 clientLineBreaks, size_t lineBreaksNum) {
728*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
729*c8dee2aaSAndroid Build Coastguard Worker SkUnicode::Position* lineBreakData = reinterpret_cast<SkUnicode::Position*>(clientLineBreaks);
730*c8dee2aaSAndroid Build Coastguard Worker std::vector<SkUnicode::LineBreakBefore> lineBreaks;
731*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < lineBreaksNum; i += 2) {
732*c8dee2aaSAndroid Build Coastguard Worker auto pos = lineBreakData[i];
733*c8dee2aaSAndroid Build Coastguard Worker auto breakType = lineBreakData[i+1];
734*c8dee2aaSAndroid Build Coastguard Worker if (breakType == 0) {
735*c8dee2aaSAndroid Build Coastguard Worker lineBreaks.emplace_back(pos, SkUnicode::LineBreakType::kSoftLineBreak);
736*c8dee2aaSAndroid Build Coastguard Worker } else {
737*c8dee2aaSAndroid Build Coastguard Worker lineBreaks.emplace_back(pos, SkUnicode::LineBreakType::kHardLineBreak);
738*c8dee2aaSAndroid Build Coastguard Worker }
739*c8dee2aaSAndroid Build Coastguard Worker }
740*c8dee2aaSAndroid Build Coastguard Worker self.setLineBreaksUtf8(std::move(lineBreaks));
741*c8dee2aaSAndroid Build Coastguard Worker #endif
742*c8dee2aaSAndroid Build Coastguard Worker }))
743*c8dee2aaSAndroid Build Coastguard Worker .function("_setLineBreaksUtf16",
744*c8dee2aaSAndroid Build Coastguard Worker optional_override([](para::ParagraphBuilderImpl& self,
745*c8dee2aaSAndroid Build Coastguard Worker WASMPointerU32 clientLineBreaks, size_t lineBreaksNum) {
746*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_UNICODE_CLIENT_IMPLEMENTATION)
747*c8dee2aaSAndroid Build Coastguard Worker SkUnicode::Position* lineBreakData = reinterpret_cast<SkUnicode::Position*>(clientLineBreaks);
748*c8dee2aaSAndroid Build Coastguard Worker std::vector<SkUnicode::LineBreakBefore> lineBreaks;
749*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < lineBreaksNum; i += 2) {
750*c8dee2aaSAndroid Build Coastguard Worker auto pos = lineBreakData[i];
751*c8dee2aaSAndroid Build Coastguard Worker auto breakType = lineBreakData[i+1];
752*c8dee2aaSAndroid Build Coastguard Worker if (breakType == 0) {
753*c8dee2aaSAndroid Build Coastguard Worker lineBreaks.emplace_back(pos, SkUnicode::LineBreakType::kSoftLineBreak);
754*c8dee2aaSAndroid Build Coastguard Worker } else {
755*c8dee2aaSAndroid Build Coastguard Worker lineBreaks.emplace_back(pos, SkUnicode::LineBreakType::kHardLineBreak);
756*c8dee2aaSAndroid Build Coastguard Worker }
757*c8dee2aaSAndroid Build Coastguard Worker }
758*c8dee2aaSAndroid Build Coastguard Worker self.setLineBreaksUtf16(std::move(lineBreaks));
759*c8dee2aaSAndroid Build Coastguard Worker #endif
760*c8dee2aaSAndroid Build Coastguard Worker }));
761*c8dee2aaSAndroid Build Coastguard Worker
762*c8dee2aaSAndroid Build Coastguard Worker class_<para::TypefaceFontProvider, base<SkFontMgr>>("TypefaceFontProvider")
763*c8dee2aaSAndroid Build Coastguard Worker .smart_ptr<sk_sp<para::TypefaceFontProvider>>("sk_sp<TypefaceFontProvider>")
764*c8dee2aaSAndroid Build Coastguard Worker .class_function("Make", optional_override([]()-> sk_sp<para::TypefaceFontProvider> {
765*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<para::TypefaceFontProvider>();
766*c8dee2aaSAndroid Build Coastguard Worker }))
767*c8dee2aaSAndroid Build Coastguard Worker .function("_registerFont", optional_override([](para::TypefaceFontProvider& self,
768*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> typeface,
769*c8dee2aaSAndroid Build Coastguard Worker WASMPointerU8 familyPtr) {
770*c8dee2aaSAndroid Build Coastguard Worker const char* fPtr = reinterpret_cast<const char*>(familyPtr);
771*c8dee2aaSAndroid Build Coastguard Worker SkString fStr(fPtr);
772*c8dee2aaSAndroid Build Coastguard Worker self.registerTypeface(typeface, fStr);
773*c8dee2aaSAndroid Build Coastguard Worker }), allow_raw_pointers());
774*c8dee2aaSAndroid Build Coastguard Worker
775*c8dee2aaSAndroid Build Coastguard Worker class_<para::FontCollection>("FontCollection")
776*c8dee2aaSAndroid Build Coastguard Worker .smart_ptr<sk_sp<para::FontCollection>>("sk_sp<FontCollection>")
777*c8dee2aaSAndroid Build Coastguard Worker .class_function("Make", optional_override([]()-> sk_sp<para::FontCollection> {
778*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<para::FontCollection>();
779*c8dee2aaSAndroid Build Coastguard Worker }))
780*c8dee2aaSAndroid Build Coastguard Worker .function("setDefaultFontManager", optional_override([](para::FontCollection& self,
781*c8dee2aaSAndroid Build Coastguard Worker const sk_sp<para::TypefaceFontProvider>& fontManager) {
782*c8dee2aaSAndroid Build Coastguard Worker self.setDefaultFontManager(fontManager);
783*c8dee2aaSAndroid Build Coastguard Worker }), allow_raw_pointers())
784*c8dee2aaSAndroid Build Coastguard Worker .function("enableFontFallback", ¶::FontCollection::enableFontFallback);
785*c8dee2aaSAndroid Build Coastguard Worker
786*c8dee2aaSAndroid Build Coastguard Worker // These value objects make it easier to send data across the wire.
787*c8dee2aaSAndroid Build Coastguard Worker value_object<para::PositionWithAffinity>("PositionWithAffinity")
788*c8dee2aaSAndroid Build Coastguard Worker .field("pos", ¶::PositionWithAffinity::position)
789*c8dee2aaSAndroid Build Coastguard Worker .field("affinity", ¶::PositionWithAffinity::affinity);
790*c8dee2aaSAndroid Build Coastguard Worker
791*c8dee2aaSAndroid Build Coastguard Worker value_object<SimpleFontStyle>("FontStyle")
792*c8dee2aaSAndroid Build Coastguard Worker .field("slant", &SimpleFontStyle::slant)
793*c8dee2aaSAndroid Build Coastguard Worker .field("weight", &SimpleFontStyle::weight)
794*c8dee2aaSAndroid Build Coastguard Worker .field("width", &SimpleFontStyle::width);
795*c8dee2aaSAndroid Build Coastguard Worker
796*c8dee2aaSAndroid Build Coastguard Worker value_object<SimpleParagraphStyle>("ParagraphStyle")
797*c8dee2aaSAndroid Build Coastguard Worker .field("disableHinting", &SimpleParagraphStyle::disableHinting)
798*c8dee2aaSAndroid Build Coastguard Worker .field("_ellipsisPtr", &SimpleParagraphStyle::ellipsisPtr)
799*c8dee2aaSAndroid Build Coastguard Worker .field("_ellipsisLen", &SimpleParagraphStyle::ellipsisLen)
800*c8dee2aaSAndroid Build Coastguard Worker .field("heightMultiplier", &SimpleParagraphStyle::heightMultiplier)
801*c8dee2aaSAndroid Build Coastguard Worker .field("maxLines", &SimpleParagraphStyle::maxLines)
802*c8dee2aaSAndroid Build Coastguard Worker .field("replaceTabCharacters", &SimpleParagraphStyle::replaceTabCharacters)
803*c8dee2aaSAndroid Build Coastguard Worker .field("textAlign", &SimpleParagraphStyle::textAlign)
804*c8dee2aaSAndroid Build Coastguard Worker .field("textDirection", &SimpleParagraphStyle::textDirection)
805*c8dee2aaSAndroid Build Coastguard Worker .field("textHeightBehavior", &SimpleParagraphStyle::textHeightBehavior)
806*c8dee2aaSAndroid Build Coastguard Worker .field("textStyle", &SimpleParagraphStyle::textStyle)
807*c8dee2aaSAndroid Build Coastguard Worker .field("strutStyle", &SimpleParagraphStyle::strutStyle)
808*c8dee2aaSAndroid Build Coastguard Worker .field("applyRoundingHack", &SimpleParagraphStyle::applyRoundingHack);
809*c8dee2aaSAndroid Build Coastguard Worker
810*c8dee2aaSAndroid Build Coastguard Worker value_object<SimpleStrutStyle>("StrutStyle")
811*c8dee2aaSAndroid Build Coastguard Worker .field("_fontFamiliesPtr", &SimpleStrutStyle::fontFamiliesPtr)
812*c8dee2aaSAndroid Build Coastguard Worker .field("_fontFamiliesLen", &SimpleStrutStyle::fontFamiliesLen)
813*c8dee2aaSAndroid Build Coastguard Worker .field("strutEnabled", &SimpleStrutStyle::strutEnabled)
814*c8dee2aaSAndroid Build Coastguard Worker .field("fontSize", &SimpleStrutStyle::fontSize)
815*c8dee2aaSAndroid Build Coastguard Worker .field("fontStyle", &SimpleStrutStyle::fontStyle)
816*c8dee2aaSAndroid Build Coastguard Worker .field("heightMultiplier", &SimpleStrutStyle::heightMultiplier)
817*c8dee2aaSAndroid Build Coastguard Worker .field("halfLeading", &SimpleStrutStyle::halfLeading)
818*c8dee2aaSAndroid Build Coastguard Worker .field("leading", &SimpleStrutStyle::leading)
819*c8dee2aaSAndroid Build Coastguard Worker .field("forceStrutHeight", &SimpleStrutStyle::forceStrutHeight);
820*c8dee2aaSAndroid Build Coastguard Worker
821*c8dee2aaSAndroid Build Coastguard Worker value_object<SimpleTextStyle>("TextStyle")
822*c8dee2aaSAndroid Build Coastguard Worker .field("_colorPtr", &SimpleTextStyle::colorPtr)
823*c8dee2aaSAndroid Build Coastguard Worker .field("_foregroundColorPtr", &SimpleTextStyle::foregroundColorPtr)
824*c8dee2aaSAndroid Build Coastguard Worker .field("_backgroundColorPtr", &SimpleTextStyle::backgroundColorPtr)
825*c8dee2aaSAndroid Build Coastguard Worker .field("decoration", &SimpleTextStyle::decoration)
826*c8dee2aaSAndroid Build Coastguard Worker .field("decorationThickness", &SimpleTextStyle::decorationThickness)
827*c8dee2aaSAndroid Build Coastguard Worker .field("_decorationColorPtr", &SimpleTextStyle::decorationColorPtr)
828*c8dee2aaSAndroid Build Coastguard Worker .field("decorationStyle", &SimpleTextStyle::decorationStyle)
829*c8dee2aaSAndroid Build Coastguard Worker .field("_fontFamiliesPtr", &SimpleTextStyle::fontFamiliesPtr)
830*c8dee2aaSAndroid Build Coastguard Worker .field("_fontFamiliesLen", &SimpleTextStyle::fontFamiliesLen)
831*c8dee2aaSAndroid Build Coastguard Worker .field("fontSize", &SimpleTextStyle::fontSize)
832*c8dee2aaSAndroid Build Coastguard Worker .field("letterSpacing", &SimpleTextStyle::letterSpacing)
833*c8dee2aaSAndroid Build Coastguard Worker .field("wordSpacing", &SimpleTextStyle::wordSpacing)
834*c8dee2aaSAndroid Build Coastguard Worker .field("heightMultiplier", &SimpleTextStyle::heightMultiplier)
835*c8dee2aaSAndroid Build Coastguard Worker .field("halfLeading", &SimpleTextStyle::halfLeading)
836*c8dee2aaSAndroid Build Coastguard Worker .field("_localePtr", &SimpleTextStyle::localePtr)
837*c8dee2aaSAndroid Build Coastguard Worker .field("_localeLen", &SimpleTextStyle::localeLen)
838*c8dee2aaSAndroid Build Coastguard Worker .field("fontStyle", &SimpleTextStyle::fontStyle)
839*c8dee2aaSAndroid Build Coastguard Worker .field("_shadowLen", &SimpleTextStyle::shadowLen)
840*c8dee2aaSAndroid Build Coastguard Worker .field("_shadowColorsPtr", &SimpleTextStyle::shadowColorsPtr)
841*c8dee2aaSAndroid Build Coastguard Worker .field("_shadowOffsetsPtr", &SimpleTextStyle::shadowOffsetsPtr)
842*c8dee2aaSAndroid Build Coastguard Worker .field("_shadowBlurRadiiPtr", &SimpleTextStyle::shadowBlurRadiiPtr)
843*c8dee2aaSAndroid Build Coastguard Worker .field("_fontFeatureLen", &SimpleTextStyle::fontFeatureLen)
844*c8dee2aaSAndroid Build Coastguard Worker .field("_fontFeatureNamesPtr", &SimpleTextStyle::fontFeatureNamesPtr)
845*c8dee2aaSAndroid Build Coastguard Worker .field("_fontFeatureValuesPtr", &SimpleTextStyle::fontFeatureValuesPtr)
846*c8dee2aaSAndroid Build Coastguard Worker .field("_fontVariationLen", &SimpleTextStyle::fontVariationLen)
847*c8dee2aaSAndroid Build Coastguard Worker .field("_fontVariationAxesPtr", &SimpleTextStyle::fontVariationAxesPtr)
848*c8dee2aaSAndroid Build Coastguard Worker .field("_fontVariationValuesPtr", &SimpleTextStyle::fontVariationValuesPtr);
849*c8dee2aaSAndroid Build Coastguard Worker
850*c8dee2aaSAndroid Build Coastguard Worker // The U stands for unsigned - we can't bind a generic/template object, so we have to specify it
851*c8dee2aaSAndroid Build Coastguard Worker // with the type we are using.
852*c8dee2aaSAndroid Build Coastguard Worker // TODO(kjlubick) make this a typedarray.
853*c8dee2aaSAndroid Build Coastguard Worker value_object<para::SkRange<size_t>>("URange")
854*c8dee2aaSAndroid Build Coastguard Worker .field("start", ¶::SkRange<size_t>::start)
855*c8dee2aaSAndroid Build Coastguard Worker .field("end", ¶::SkRange<size_t>::end);
856*c8dee2aaSAndroid Build Coastguard Worker
857*c8dee2aaSAndroid Build Coastguard Worker // TextDecoration should be a const because they can be combined
858*c8dee2aaSAndroid Build Coastguard Worker constant("NoDecoration", int(para::TextDecoration::kNoDecoration));
859*c8dee2aaSAndroid Build Coastguard Worker constant("UnderlineDecoration", int(para::TextDecoration::kUnderline));
860*c8dee2aaSAndroid Build Coastguard Worker constant("OverlineDecoration", int(para::TextDecoration::kOverline));
861*c8dee2aaSAndroid Build Coastguard Worker constant("LineThroughDecoration", int(para::TextDecoration::kLineThrough));
862*c8dee2aaSAndroid Build Coastguard Worker }
863