1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2019 Google LLC
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
8cb93a386Sopenharmony_ci#include "include/core/SkColor.h"
9cb93a386Sopenharmony_ci#include "include/core/SkFontStyle.h"
10cb93a386Sopenharmony_ci#include "include/core/SkPictureRecorder.h"
11cb93a386Sopenharmony_ci#include "include/core/SkString.h"
12cb93a386Sopenharmony_ci
13cb93a386Sopenharmony_ci#include "modules/skparagraph/include/DartTypes.h"
14cb93a386Sopenharmony_ci#include "modules/skparagraph/include/Paragraph.h"
15cb93a386Sopenharmony_ci#include "modules/skparagraph/include/TextStyle.h"
16cb93a386Sopenharmony_ci#include "modules/skparagraph/include/TypefaceFontProvider.h"
17cb93a386Sopenharmony_ci#include "modules/skparagraph/src/ParagraphBuilderImpl.h"
18cb93a386Sopenharmony_ci#include "modules/skparagraph/src/ParagraphImpl.h"
19cb93a386Sopenharmony_ci
20cb93a386Sopenharmony_ci#include <string>
21cb93a386Sopenharmony_ci#include <vector>
22cb93a386Sopenharmony_ci
23cb93a386Sopenharmony_ci#include <emscripten.h>
24cb93a386Sopenharmony_ci#include <emscripten/bind.h>
25cb93a386Sopenharmony_ci#include "modules/canvaskit/WasmCommon.h"
26cb93a386Sopenharmony_ci
27cb93a386Sopenharmony_ciusing namespace emscripten;
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_cinamespace para = skia::textlayout;
30cb93a386Sopenharmony_ci
31cb93a386Sopenharmony_ciSkColor4f toSkColor4f(WASMPointerF32 cPtr) {
32cb93a386Sopenharmony_ci    float* fourFloats = reinterpret_cast<float*>(cPtr);
33cb93a386Sopenharmony_ci    SkColor4f color = {fourFloats[0], fourFloats[1], fourFloats[2], fourFloats[3]};
34cb93a386Sopenharmony_ci    return color;
35cb93a386Sopenharmony_ci}
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_cistruct SimpleFontStyle {
38cb93a386Sopenharmony_ci    SkFontStyle::Slant slant;
39cb93a386Sopenharmony_ci    SkFontStyle::Weight weight;
40cb93a386Sopenharmony_ci    SkFontStyle::Width width;
41cb93a386Sopenharmony_ci};
42cb93a386Sopenharmony_ci
43cb93a386Sopenharmony_cistruct SimpleTextStyle {
44cb93a386Sopenharmony_ci    WASMPointerF32 colorPtr;
45cb93a386Sopenharmony_ci    WASMPointerF32 foregroundColorPtr;
46cb93a386Sopenharmony_ci    WASMPointerF32 backgroundColorPtr;
47cb93a386Sopenharmony_ci    uint8_t decoration;
48cb93a386Sopenharmony_ci    SkScalar decorationThickness;
49cb93a386Sopenharmony_ci    WASMPointerF32 decorationColorPtr;
50cb93a386Sopenharmony_ci    para::TextDecorationStyle decorationStyle;
51cb93a386Sopenharmony_ci    para::TextBaseline textBaseline;
52cb93a386Sopenharmony_ci    SkScalar fontSize;
53cb93a386Sopenharmony_ci    SkScalar letterSpacing;
54cb93a386Sopenharmony_ci    SkScalar wordSpacing;
55cb93a386Sopenharmony_ci    SkScalar heightMultiplier;
56cb93a386Sopenharmony_ci    bool halfLeading;
57cb93a386Sopenharmony_ci    WASMPointerU8 localePtr;
58cb93a386Sopenharmony_ci    int localeLen;
59cb93a386Sopenharmony_ci    SimpleFontStyle fontStyle;
60cb93a386Sopenharmony_ci
61cb93a386Sopenharmony_ci    WASMPointerU8 fontFamiliesPtr;
62cb93a386Sopenharmony_ci    int fontFamiliesLen;
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_ci    int shadowLen;
65cb93a386Sopenharmony_ci    WASMPointerF32 shadowColorsPtr;
66cb93a386Sopenharmony_ci    WASMPointerF32 shadowOffsetsPtr;
67cb93a386Sopenharmony_ci    WASMPointerF32 shadowBlurRadiiPtr;
68cb93a386Sopenharmony_ci
69cb93a386Sopenharmony_ci    int fontFeatureLen;
70cb93a386Sopenharmony_ci    WASMPointerF32 fontFeatureNamesPtr;
71cb93a386Sopenharmony_ci    WASMPointerF32 fontFeatureValuesPtr;
72cb93a386Sopenharmony_ci};
73cb93a386Sopenharmony_ci
74cb93a386Sopenharmony_cistruct SimpleStrutStyle {
75cb93a386Sopenharmony_ci    WASMPointerU32 fontFamiliesPtr;
76cb93a386Sopenharmony_ci    int fontFamiliesLen;
77cb93a386Sopenharmony_ci    SimpleFontStyle fontStyle;
78cb93a386Sopenharmony_ci    SkScalar fontSize;
79cb93a386Sopenharmony_ci    SkScalar heightMultiplier;
80cb93a386Sopenharmony_ci    bool halfLeading;
81cb93a386Sopenharmony_ci    SkScalar leading;
82cb93a386Sopenharmony_ci    bool strutEnabled;
83cb93a386Sopenharmony_ci    bool forceStrutHeight;
84cb93a386Sopenharmony_ci};
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_cipara::StrutStyle toStrutStyle(const SimpleStrutStyle& s) {
87cb93a386Sopenharmony_ci    para::StrutStyle ss;
88cb93a386Sopenharmony_ci
89cb93a386Sopenharmony_ci    const char** fontFamilies = reinterpret_cast<const char**>(s.fontFamiliesPtr);
90cb93a386Sopenharmony_ci    if (fontFamilies != nullptr) {
91cb93a386Sopenharmony_ci        std::vector<SkString> ff;
92cb93a386Sopenharmony_ci        for (int i = 0; i < s.fontFamiliesLen; i++) {
93cb93a386Sopenharmony_ci            ff.emplace_back(fontFamilies[i]);
94cb93a386Sopenharmony_ci        }
95cb93a386Sopenharmony_ci        ss.setFontFamilies(ff);
96cb93a386Sopenharmony_ci    }
97cb93a386Sopenharmony_ci
98cb93a386Sopenharmony_ci    SkFontStyle fs(s.fontStyle.weight, s.fontStyle.width, s.fontStyle.slant);
99cb93a386Sopenharmony_ci    ss.setFontStyle(fs);
100cb93a386Sopenharmony_ci
101cb93a386Sopenharmony_ci    if (s.fontSize != 0) {
102cb93a386Sopenharmony_ci        ss.setFontSize(s.fontSize);
103cb93a386Sopenharmony_ci    }
104cb93a386Sopenharmony_ci    if (s.heightMultiplier != 0) {
105cb93a386Sopenharmony_ci        ss.setHeight(s.heightMultiplier);
106cb93a386Sopenharmony_ci        ss.setHeightOverride(true);
107cb93a386Sopenharmony_ci    }
108cb93a386Sopenharmony_ci    ss.setHalfLeading(s.halfLeading);
109cb93a386Sopenharmony_ci
110cb93a386Sopenharmony_ci    if (s.leading != 0) {
111cb93a386Sopenharmony_ci        ss.setLeading(s.leading);
112cb93a386Sopenharmony_ci    }
113cb93a386Sopenharmony_ci
114cb93a386Sopenharmony_ci    ss.setStrutEnabled(s.strutEnabled);
115cb93a386Sopenharmony_ci    ss.setForceStrutHeight(s.forceStrutHeight);
116cb93a386Sopenharmony_ci
117cb93a386Sopenharmony_ci    return ss;
118cb93a386Sopenharmony_ci}
119cb93a386Sopenharmony_ci
120cb93a386Sopenharmony_cipara::TextStyle toTextStyle(const SimpleTextStyle& s) {
121cb93a386Sopenharmony_ci    para::TextStyle ts;
122cb93a386Sopenharmony_ci
123cb93a386Sopenharmony_ci    // textstyle.color doesn't support a 4f color, however the foreground and background fields
124cb93a386Sopenharmony_ci    // below do.
125cb93a386Sopenharmony_ci    ts.setColor(toSkColor4f(s.colorPtr).toSkColor());
126cb93a386Sopenharmony_ci
127cb93a386Sopenharmony_ci    // It is functionally important that these paints be unset when no value was provided.
128cb93a386Sopenharmony_ci    if (s.foregroundColorPtr) {
129cb93a386Sopenharmony_ci        SkPaint p1;
130cb93a386Sopenharmony_ci        p1.setColor4f(toSkColor4f(s.foregroundColorPtr));
131cb93a386Sopenharmony_ci        ts.setForegroundColor(p1);
132cb93a386Sopenharmony_ci    }
133cb93a386Sopenharmony_ci
134cb93a386Sopenharmony_ci    if (s.backgroundColorPtr) {
135cb93a386Sopenharmony_ci        SkPaint p2;
136cb93a386Sopenharmony_ci        p2.setColor4f(toSkColor4f(s.backgroundColorPtr));
137cb93a386Sopenharmony_ci        ts.setBackgroundColor(p2);
138cb93a386Sopenharmony_ci    }
139cb93a386Sopenharmony_ci
140cb93a386Sopenharmony_ci    if (s.fontSize != 0) {
141cb93a386Sopenharmony_ci        ts.setFontSize(s.fontSize);
142cb93a386Sopenharmony_ci    }
143cb93a386Sopenharmony_ci    if (s.letterSpacing != 0) {
144cb93a386Sopenharmony_ci        ts.setLetterSpacing(s.letterSpacing);
145cb93a386Sopenharmony_ci    }
146cb93a386Sopenharmony_ci    if (s.wordSpacing != 0) {
147cb93a386Sopenharmony_ci        ts.setWordSpacing(s.wordSpacing);
148cb93a386Sopenharmony_ci    }
149cb93a386Sopenharmony_ci
150cb93a386Sopenharmony_ci    if (s.heightMultiplier != 0) {
151cb93a386Sopenharmony_ci        ts.setHeight(s.heightMultiplier);
152cb93a386Sopenharmony_ci        ts.setHeightOverride(true);
153cb93a386Sopenharmony_ci    }
154cb93a386Sopenharmony_ci
155cb93a386Sopenharmony_ci    ts.setHalfLeading(s.halfLeading);
156cb93a386Sopenharmony_ci
157cb93a386Sopenharmony_ci    ts.setDecoration(para::TextDecoration(s.decoration));
158cb93a386Sopenharmony_ci    ts.setDecorationStyle(s.decorationStyle);
159cb93a386Sopenharmony_ci    if (s.decorationThickness != 0) {
160cb93a386Sopenharmony_ci        ts.setDecorationThicknessMultiplier(s.decorationThickness);
161cb93a386Sopenharmony_ci    }
162cb93a386Sopenharmony_ci    if (s.decorationColorPtr) {
163cb93a386Sopenharmony_ci        ts.setDecorationColor(toSkColor4f(s.decorationColorPtr).toSkColor());
164cb93a386Sopenharmony_ci    }
165cb93a386Sopenharmony_ci
166cb93a386Sopenharmony_ci    if (s.localeLen > 0) {
167cb93a386Sopenharmony_ci        const char* localePtr = reinterpret_cast<const char*>(s.localePtr);
168cb93a386Sopenharmony_ci        SkString lStr(localePtr, s.localeLen);
169cb93a386Sopenharmony_ci        ts.setLocale(lStr);
170cb93a386Sopenharmony_ci    }
171cb93a386Sopenharmony_ci
172cb93a386Sopenharmony_ci    const char** fontFamilies = reinterpret_cast<const char**>(s.fontFamiliesPtr);
173cb93a386Sopenharmony_ci    if (fontFamilies != nullptr) {
174cb93a386Sopenharmony_ci        std::vector<SkString> ff;
175cb93a386Sopenharmony_ci        for (int i = 0; i < s.fontFamiliesLen; i++) {
176cb93a386Sopenharmony_ci            ff.emplace_back(fontFamilies[i]);
177cb93a386Sopenharmony_ci        }
178cb93a386Sopenharmony_ci        ts.setFontFamilies(ff);
179cb93a386Sopenharmony_ci    }
180cb93a386Sopenharmony_ci
181cb93a386Sopenharmony_ci    ts.setTextBaseline(s.textBaseline);
182cb93a386Sopenharmony_ci
183cb93a386Sopenharmony_ci    SkFontStyle fs(s.fontStyle.weight, s.fontStyle.width, s.fontStyle.slant);
184cb93a386Sopenharmony_ci    ts.setFontStyle(fs);
185cb93a386Sopenharmony_ci
186cb93a386Sopenharmony_ci    if (s.shadowLen > 0) {
187cb93a386Sopenharmony_ci        const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(s.shadowColorsPtr);
188cb93a386Sopenharmony_ci        const SkPoint* offsets = reinterpret_cast<const SkPoint*>(s.shadowOffsetsPtr);
189cb93a386Sopenharmony_ci        const float* blurRadii = reinterpret_cast<const float*>(s.shadowBlurRadiiPtr);
190cb93a386Sopenharmony_ci        for (int i = 0; i < s.shadowLen; i++) {
191cb93a386Sopenharmony_ci            para::TextShadow shadow(colors[i].toSkColor(), offsets[i], blurRadii[i]);
192cb93a386Sopenharmony_ci            ts.addShadow(shadow);
193cb93a386Sopenharmony_ci        }
194cb93a386Sopenharmony_ci    }
195cb93a386Sopenharmony_ci
196cb93a386Sopenharmony_ci
197cb93a386Sopenharmony_ci    if (s.fontFeatureLen > 0) {
198cb93a386Sopenharmony_ci        const char** fontFeatureNames = reinterpret_cast<const char**>(s.fontFeatureNamesPtr);
199cb93a386Sopenharmony_ci        const int* fontFeatureValues = reinterpret_cast<const int*>(s.fontFeatureValuesPtr);
200cb93a386Sopenharmony_ci        for (int i = 0; i < s.fontFeatureLen; i++) {
201cb93a386Sopenharmony_ci            // Font features names are 4-character simple strings.
202cb93a386Sopenharmony_ci            SkString name(fontFeatureNames[i], 4);
203cb93a386Sopenharmony_ci            ts.addFontFeature(name, fontFeatureValues[i]);
204cb93a386Sopenharmony_ci        }
205cb93a386Sopenharmony_ci    }
206cb93a386Sopenharmony_ci
207cb93a386Sopenharmony_ci    return ts;
208cb93a386Sopenharmony_ci}
209cb93a386Sopenharmony_ci
210cb93a386Sopenharmony_cistruct SimpleParagraphStyle {
211cb93a386Sopenharmony_ci    bool disableHinting;
212cb93a386Sopenharmony_ci    WASMPointerU8 ellipsisPtr;
213cb93a386Sopenharmony_ci    size_t ellipsisLen;
214cb93a386Sopenharmony_ci    SkScalar heightMultiplier;
215cb93a386Sopenharmony_ci    size_t maxLines;
216cb93a386Sopenharmony_ci    para::TextAlign textAlign;
217cb93a386Sopenharmony_ci    para::TextDirection textDirection;
218cb93a386Sopenharmony_ci    para::TextHeightBehavior textHeightBehavior;
219cb93a386Sopenharmony_ci    SimpleTextStyle textStyle;
220cb93a386Sopenharmony_ci    SimpleStrutStyle strutStyle;
221cb93a386Sopenharmony_ci};
222cb93a386Sopenharmony_ci
223cb93a386Sopenharmony_cipara::ParagraphStyle toParagraphStyle(const SimpleParagraphStyle& s) {
224cb93a386Sopenharmony_ci    para::ParagraphStyle ps;
225cb93a386Sopenharmony_ci    if (s.disableHinting) {
226cb93a386Sopenharmony_ci        ps.turnHintingOff();
227cb93a386Sopenharmony_ci    }
228cb93a386Sopenharmony_ci
229cb93a386Sopenharmony_ci    if (s.ellipsisLen > 0) {
230cb93a386Sopenharmony_ci        const char* ellipsisPtr = reinterpret_cast<const char*>(s.ellipsisPtr);
231cb93a386Sopenharmony_ci        SkString eStr(ellipsisPtr, s.ellipsisLen);
232cb93a386Sopenharmony_ci        ps.setEllipsis(eStr);
233cb93a386Sopenharmony_ci    }
234cb93a386Sopenharmony_ci    ps.setTextAlign(s.textAlign);
235cb93a386Sopenharmony_ci    ps.setTextDirection(s.textDirection);
236cb93a386Sopenharmony_ci    auto ts = toTextStyle(s.textStyle);
237cb93a386Sopenharmony_ci    ps.setTextStyle(ts);
238cb93a386Sopenharmony_ci    auto ss = toStrutStyle(s.strutStyle);
239cb93a386Sopenharmony_ci    ps.setStrutStyle(ss);
240cb93a386Sopenharmony_ci    if (s.heightMultiplier != 0) {
241cb93a386Sopenharmony_ci        ps.setHeight(s.heightMultiplier);
242cb93a386Sopenharmony_ci    }
243cb93a386Sopenharmony_ci    if (s.maxLines != 0) {
244cb93a386Sopenharmony_ci        ps.setMaxLines(s.maxLines);
245cb93a386Sopenharmony_ci    }
246cb93a386Sopenharmony_ci    ps.setTextHeightBehavior(s.textHeightBehavior);
247cb93a386Sopenharmony_ci    return ps;
248cb93a386Sopenharmony_ci}
249cb93a386Sopenharmony_ci
250cb93a386Sopenharmony_cistruct SimpleTextBox {
251cb93a386Sopenharmony_ci    SkRect rect;
252cb93a386Sopenharmony_ci    // This isn't the most efficient way to represent this, but it is much easier to keep
253cb93a386Sopenharmony_ci    // everything as floats when unpacking on the JS side.
254cb93a386Sopenharmony_ci    // 0.0 = RTL, 1.0 = LTr
255cb93a386Sopenharmony_ci    SkScalar direction;
256cb93a386Sopenharmony_ci};
257cb93a386Sopenharmony_ci
258cb93a386Sopenharmony_ciFloat32Array TextBoxesToFloat32Array(std::vector<para::TextBox> boxes) {
259cb93a386Sopenharmony_ci    // Pack these text boxes into an array of n groups of 5 SkScalar (floats)
260cb93a386Sopenharmony_ci    if (!boxes.size()) {
261cb93a386Sopenharmony_ci        return emscripten::val::null();
262cb93a386Sopenharmony_ci    }
263cb93a386Sopenharmony_ci    SimpleTextBox* rects = new SimpleTextBox[boxes.size()];
264cb93a386Sopenharmony_ci    for (int i = 0; i < boxes.size(); i++) {
265cb93a386Sopenharmony_ci        rects[i].rect = boxes[i].rect;
266cb93a386Sopenharmony_ci        if (boxes[i].direction == para::TextDirection::kRtl) {
267cb93a386Sopenharmony_ci            rects[i].direction = 0;
268cb93a386Sopenharmony_ci        } else {
269cb93a386Sopenharmony_ci            rects[i].direction = 1;
270cb93a386Sopenharmony_ci        }
271cb93a386Sopenharmony_ci    }
272cb93a386Sopenharmony_ci    float* fPtr = reinterpret_cast<float*>(rects);
273cb93a386Sopenharmony_ci    // Of note: now that we have cast rects to float*, emscripten is smart enough to wrap this
274cb93a386Sopenharmony_ci    // into a Float32Array for us.
275cb93a386Sopenharmony_ci    return Float32Array(typed_memory_view(boxes.size() * 5, fPtr));
276cb93a386Sopenharmony_ci}
277cb93a386Sopenharmony_ci
278cb93a386Sopenharmony_ciFloat32Array GetRectsForRange(para::Paragraph& self,
279cb93a386Sopenharmony_ci                              unsigned start,
280cb93a386Sopenharmony_ci                              unsigned end,
281cb93a386Sopenharmony_ci                              para::RectHeightStyle heightStyle,
282cb93a386Sopenharmony_ci                              para::RectWidthStyle widthStyle) {
283cb93a386Sopenharmony_ci    std::vector<para::TextBox> boxes = self.getRectsForRange(start, end, heightStyle, widthStyle);
284cb93a386Sopenharmony_ci    return TextBoxesToFloat32Array(boxes);
285cb93a386Sopenharmony_ci}
286cb93a386Sopenharmony_ci
287cb93a386Sopenharmony_ciFloat32Array GetRectsForPlaceholders(para::Paragraph& self) {
288cb93a386Sopenharmony_ci    std::vector<para::TextBox> boxes = self.getRectsForPlaceholders();
289cb93a386Sopenharmony_ci    return TextBoxesToFloat32Array(boxes);
290cb93a386Sopenharmony_ci}
291cb93a386Sopenharmony_ci
292cb93a386Sopenharmony_ciJSArray GetLineMetrics(para::Paragraph& self) {
293cb93a386Sopenharmony_ci    std::vector<skia::textlayout::LineMetrics> metrics;
294cb93a386Sopenharmony_ci    self.getLineMetrics(metrics);
295cb93a386Sopenharmony_ci    JSArray result = emscripten::val::array();
296cb93a386Sopenharmony_ci    for (auto metric : metrics) {
297cb93a386Sopenharmony_ci        JSObject m = emscripten::val::object();
298cb93a386Sopenharmony_ci        m.set("startIndex", metric.fStartIndex);
299cb93a386Sopenharmony_ci        m.set("endIndex", metric.fEndIndex);
300cb93a386Sopenharmony_ci        m.set("endExcludingWhitespaces", metric.fEndExcludingWhitespaces);
301cb93a386Sopenharmony_ci        m.set("endIncludingNewline", metric.fEndIncludingNewline);
302cb93a386Sopenharmony_ci        m.set("isHardBreak", metric.fHardBreak);
303cb93a386Sopenharmony_ci        m.set("ascent", metric.fAscent);
304cb93a386Sopenharmony_ci        m.set("descent", metric.fDescent);
305cb93a386Sopenharmony_ci        m.set("height", metric.fHeight);
306cb93a386Sopenharmony_ci        m.set("width", metric.fWidth);
307cb93a386Sopenharmony_ci        m.set("left", metric.fLeft);
308cb93a386Sopenharmony_ci        m.set("baseline", metric.fBaseline);
309cb93a386Sopenharmony_ci        m.set("lineNumber", metric.fLineNumber);
310cb93a386Sopenharmony_ci        result.call<void>("push", m);
311cb93a386Sopenharmony_ci    }
312cb93a386Sopenharmony_ci    return result;
313cb93a386Sopenharmony_ci}
314cb93a386Sopenharmony_ci
315cb93a386Sopenharmony_ci/*
316cb93a386Sopenharmony_ci *  Returns Lines[]
317cb93a386Sopenharmony_ci */
318cb93a386Sopenharmony_ciJSArray GetShapedLines(para::Paragraph& self) {
319cb93a386Sopenharmony_ci    struct LineAccumulate {
320cb93a386Sopenharmony_ci        int         lineNumber  = -1;   // deliberately -1 from starting value
321cb93a386Sopenharmony_ci        uint32_t    minOffset   = 0xFFFFFFFF;
322cb93a386Sopenharmony_ci        uint32_t    maxOffset   = 0;
323cb93a386Sopenharmony_ci        float       minAscent   = 0;
324cb93a386Sopenharmony_ci        float       maxDescent  = 0;
325cb93a386Sopenharmony_ci        // not really accumulated, but definitely set
326cb93a386Sopenharmony_ci        float       baseline    = 0;
327cb93a386Sopenharmony_ci
328cb93a386Sopenharmony_ci        void reset(int lineNumber) {
329cb93a386Sopenharmony_ci            new (this) LineAccumulate;
330cb93a386Sopenharmony_ci            this->lineNumber = lineNumber;
331cb93a386Sopenharmony_ci        }
332cb93a386Sopenharmony_ci    };
333cb93a386Sopenharmony_ci
334cb93a386Sopenharmony_ci    // where we accumulate our js output
335cb93a386Sopenharmony_ci    JSArray  jlines = emscripten::val::array();
336cb93a386Sopenharmony_ci    JSObject jline = emscripten::val::null();
337cb93a386Sopenharmony_ci    JSArray  jruns = emscripten::val::null();
338cb93a386Sopenharmony_ci    LineAccumulate accum;
339cb93a386Sopenharmony_ci
340cb93a386Sopenharmony_ci    self.visit([&](int lineNumber, const para::Paragraph::VisitorInfo* info) {
341cb93a386Sopenharmony_ci        if (!info) {
342cb93a386Sopenharmony_ci            if (!jline) return; // how???
343cb93a386Sopenharmony_ci            // end of current line
344cb93a386Sopenharmony_ci            JSObject range = emscripten::val::object();
345cb93a386Sopenharmony_ci            range.set("first", accum.minOffset);
346cb93a386Sopenharmony_ci            range.set("last",  accum.maxOffset);
347cb93a386Sopenharmony_ci            jline.set("textRange", range);
348cb93a386Sopenharmony_ci
349cb93a386Sopenharmony_ci            jline.set("top", accum.baseline + accum.minAscent);
350cb93a386Sopenharmony_ci            jline.set("bottom", accum.baseline + accum.maxDescent);
351cb93a386Sopenharmony_ci            jline.set("baseline", accum.baseline);
352cb93a386Sopenharmony_ci            return;
353cb93a386Sopenharmony_ci        }
354cb93a386Sopenharmony_ci
355cb93a386Sopenharmony_ci        if (lineNumber != accum.lineNumber) {
356cb93a386Sopenharmony_ci            SkASSERT(lineNumber == accum.lineNumber + 1);   // assume monotonic
357cb93a386Sopenharmony_ci
358cb93a386Sopenharmony_ci            accum.reset(lineNumber);
359cb93a386Sopenharmony_ci            jruns = emscripten::val::array();
360cb93a386Sopenharmony_ci
361cb93a386Sopenharmony_ci            jline = emscripten::val::object();
362cb93a386Sopenharmony_ci            jline.set("runs", jruns);
363cb93a386Sopenharmony_ci            // will assign textRange and metrics on end-of-line signal
364cb93a386Sopenharmony_ci
365cb93a386Sopenharmony_ci            jlines.call<void>("push", jline);
366cb93a386Sopenharmony_ci        }
367cb93a386Sopenharmony_ci
368cb93a386Sopenharmony_ci        // append the run
369cb93a386Sopenharmony_ci        const int N = info->count;   // glyphs
370cb93a386Sopenharmony_ci        const int N1 = N + 1;       // positions, offsets have 1 extra (trailing) slot
371cb93a386Sopenharmony_ci
372cb93a386Sopenharmony_ci        JSObject jrun = emscripten::val::object();
373cb93a386Sopenharmony_ci
374cb93a386Sopenharmony_ci        jrun.set("flags",    info->flags);
375cb93a386Sopenharmony_ci
376cb93a386Sopenharmony_ci// TODO: figure out how to set a wrapped sk_sp<SkTypeface>
377cb93a386Sopenharmony_ci//        jrun.set("typeface", info->font.getTypeface());
378cb93a386Sopenharmony_ci        jrun.set("typeface",    emscripten::val::null());
379cb93a386Sopenharmony_ci        jrun.set("size",        info->font.getSize());
380cb93a386Sopenharmony_ci        if (info->font.getScaleX()) {
381cb93a386Sopenharmony_ci            jrun.set("scaleX",  info->font.getScaleX());
382cb93a386Sopenharmony_ci        }
383cb93a386Sopenharmony_ci
384cb93a386Sopenharmony_ci        jrun.set("glyphs",   MakeTypedArray(N,  info->glyphs));
385cb93a386Sopenharmony_ci        jrun.set("offsets",  MakeTypedArray(N1, info->utf8Starts));
386cb93a386Sopenharmony_ci
387cb93a386Sopenharmony_ci        // we need to modify the positions, so make a temp copy
388cb93a386Sopenharmony_ci        SkAutoSTMalloc<32, SkPoint> positions(N1);
389cb93a386Sopenharmony_ci        for (int i = 0; i < N; ++i) {
390cb93a386Sopenharmony_ci            positions.get()[i] = info->positions[i] + info->origin;
391cb93a386Sopenharmony_ci        }
392cb93a386Sopenharmony_ci        positions.get()[N] = { info->advanceX, positions.get()[N - 1].fY };
393cb93a386Sopenharmony_ci        jrun.set("positions", MakeTypedArray(N1*2, (const float*)positions.get()));
394cb93a386Sopenharmony_ci
395cb93a386Sopenharmony_ci        jruns.call<void>("push", jrun);
396cb93a386Sopenharmony_ci
397cb93a386Sopenharmony_ci        // update accum
398cb93a386Sopenharmony_ci        {   SkFontMetrics fm;
399cb93a386Sopenharmony_ci            info->font.getMetrics(&fm);
400cb93a386Sopenharmony_ci
401cb93a386Sopenharmony_ci            accum.minAscent  = std::min(accum.minAscent,  fm.fAscent);
402cb93a386Sopenharmony_ci            accum.maxDescent = std::max(accum.maxDescent, fm.fDescent);
403cb93a386Sopenharmony_ci            accum.baseline   = info->origin.fY;
404cb93a386Sopenharmony_ci
405cb93a386Sopenharmony_ci            accum.minOffset  = std::min(accum.minOffset,  info->utf8Starts[0]);
406cb93a386Sopenharmony_ci            accum.maxOffset  = std::max(accum.maxOffset,  info->utf8Starts[N]);
407cb93a386Sopenharmony_ci        }
408cb93a386Sopenharmony_ci
409cb93a386Sopenharmony_ci    });
410cb93a386Sopenharmony_ci    return jlines;
411cb93a386Sopenharmony_ci}
412cb93a386Sopenharmony_ci
413cb93a386Sopenharmony_ciEMSCRIPTEN_BINDINGS(Paragraph) {
414cb93a386Sopenharmony_ci
415cb93a386Sopenharmony_ci    class_<para::Paragraph>("Paragraph")
416cb93a386Sopenharmony_ci        .function("didExceedMaxLines", &para::Paragraph::didExceedMaxLines)
417cb93a386Sopenharmony_ci        .function("getAlphabeticBaseline", &para::Paragraph::getAlphabeticBaseline)
418cb93a386Sopenharmony_ci        .function("getGlyphPositionAtCoordinate", &para::Paragraph::getGlyphPositionAtCoordinate)
419cb93a386Sopenharmony_ci        .function("getHeight", &para::Paragraph::getHeight)
420cb93a386Sopenharmony_ci        .function("getIdeographicBaseline", &para::Paragraph::getIdeographicBaseline)
421cb93a386Sopenharmony_ci        .function("getLineMetrics", &GetLineMetrics)
422cb93a386Sopenharmony_ci        .function("getLongestLine", &para::Paragraph::getLongestLine)
423cb93a386Sopenharmony_ci        .function("getMaxIntrinsicWidth", &para::Paragraph::getMaxIntrinsicWidth)
424cb93a386Sopenharmony_ci        .function("getMaxWidth", &para::Paragraph::getMaxWidth)
425cb93a386Sopenharmony_ci        .function("getMinIntrinsicWidth", &para::Paragraph::getMinIntrinsicWidth)
426cb93a386Sopenharmony_ci        .function("_getRectsForPlaceholders", &GetRectsForPlaceholders)
427cb93a386Sopenharmony_ci        .function("_getRectsForRange", &GetRectsForRange)
428cb93a386Sopenharmony_ci        .function("getShapedLines", &GetShapedLines)
429cb93a386Sopenharmony_ci        .function("getWordBoundary", &para::Paragraph::getWordBoundary)
430cb93a386Sopenharmony_ci        .function("layout", &para::Paragraph::layout);
431cb93a386Sopenharmony_ci
432cb93a386Sopenharmony_ci    class_<para::ParagraphBuilderImpl>("ParagraphBuilder")
433cb93a386Sopenharmony_ci            .class_function(
434cb93a386Sopenharmony_ci                    "_Make",
435cb93a386Sopenharmony_ci                    optional_override([](SimpleParagraphStyle style, sk_sp<SkFontMgr> fontMgr)
436cb93a386Sopenharmony_ci                                              -> std::unique_ptr<para::ParagraphBuilderImpl> {
437cb93a386Sopenharmony_ci                        auto fc = sk_make_sp<para::FontCollection>();
438cb93a386Sopenharmony_ci                        fc->setDefaultFontManager(fontMgr);
439cb93a386Sopenharmony_ci                        fc->enableFontFallback();
440cb93a386Sopenharmony_ci                        auto ps = toParagraphStyle(style);
441cb93a386Sopenharmony_ci                        auto pb = para::ParagraphBuilderImpl::make(ps, fc);
442cb93a386Sopenharmony_ci                        return std::unique_ptr<para::ParagraphBuilderImpl>(
443cb93a386Sopenharmony_ci                                static_cast<para::ParagraphBuilderImpl*>(pb.release()));
444cb93a386Sopenharmony_ci                    }),
445cb93a386Sopenharmony_ci                    allow_raw_pointers())
446cb93a386Sopenharmony_ci            .class_function(
447cb93a386Sopenharmony_ci                    "_MakeFromFontProvider",
448cb93a386Sopenharmony_ci                    optional_override([](SimpleParagraphStyle style,
449cb93a386Sopenharmony_ci                                         sk_sp<para::TypefaceFontProvider> fontProvider)
450cb93a386Sopenharmony_ci                                              -> std::unique_ptr<para::ParagraphBuilderImpl> {
451cb93a386Sopenharmony_ci                        auto fc = sk_make_sp<para::FontCollection>();
452cb93a386Sopenharmony_ci                        fc->setDefaultFontManager(fontProvider);
453cb93a386Sopenharmony_ci                        fc->enableFontFallback();
454cb93a386Sopenharmony_ci                        auto ps = toParagraphStyle(style);
455cb93a386Sopenharmony_ci                        auto pb = para::ParagraphBuilderImpl::make(ps, fc);
456cb93a386Sopenharmony_ci                        return std::unique_ptr<para::ParagraphBuilderImpl>(
457cb93a386Sopenharmony_ci                                static_cast<para::ParagraphBuilderImpl*>(pb.release()));
458cb93a386Sopenharmony_ci                    }),
459cb93a386Sopenharmony_ci                    allow_raw_pointers())
460cb93a386Sopenharmony_ci            .class_function(
461cb93a386Sopenharmony_ci                    "_ShapeText",
462cb93a386Sopenharmony_ci                    optional_override([](JSString jtext, JSArray jruns, float width) -> JSArray {
463cb93a386Sopenharmony_ci                std::string textStorage = jtext.as<std::string>();
464cb93a386Sopenharmony_ci                const char* text = textStorage.data();
465cb93a386Sopenharmony_ci                size_t      textCount = textStorage.size();
466cb93a386Sopenharmony_ci
467cb93a386Sopenharmony_ci                auto fc = sk_make_sp<para::FontCollection>();
468cb93a386Sopenharmony_ci                fc->setDefaultFontManager(SkFontMgr::RefDefault());
469cb93a386Sopenharmony_ci                fc->enableFontFallback();
470cb93a386Sopenharmony_ci
471cb93a386Sopenharmony_ci                para::ParagraphStyle pstyle;
472cb93a386Sopenharmony_ci                {
473cb93a386Sopenharmony_ci                    // For the most part this is ignored, since we set an explicit TextStyle
474cb93a386Sopenharmony_ci                    // for all of our text runs, but it is required by SkParagraph.
475cb93a386Sopenharmony_ci                    para::TextStyle style;
476cb93a386Sopenharmony_ci                    style.setFontFamilies({SkString("sans-serif")});
477cb93a386Sopenharmony_ci                    style.setFontSize(32);
478cb93a386Sopenharmony_ci                    pstyle.setTextStyle(style);
479cb93a386Sopenharmony_ci                }
480cb93a386Sopenharmony_ci
481cb93a386Sopenharmony_ci                auto pb = para::ParagraphBuilder::make(pstyle, fc);
482cb93a386Sopenharmony_ci
483cb93a386Sopenharmony_ci                // tease apart the FontBlock runs
484cb93a386Sopenharmony_ci                size_t runCount = jruns["length"].as<size_t>();
485cb93a386Sopenharmony_ci                for (size_t i = 0; i < runCount; ++i) {
486cb93a386Sopenharmony_ci                    emscripten::val r = jruns[i];
487cb93a386Sopenharmony_ci
488cb93a386Sopenharmony_ci                    para::TextStyle style;
489cb93a386Sopenharmony_ci                    style.setTypeface(r["typeface"].as< sk_sp<SkTypeface> >());
490cb93a386Sopenharmony_ci                    style.setFontSize(r["size"].as<float>());
491cb93a386Sopenharmony_ci
492cb93a386Sopenharmony_ci                    const size_t subTextCount = r["length"].as<size_t>();
493cb93a386Sopenharmony_ci                    if (subTextCount > textCount) {
494cb93a386Sopenharmony_ci                        return emscripten::val("block runs exceed text length!");
495cb93a386Sopenharmony_ci                    }
496cb93a386Sopenharmony_ci
497cb93a386Sopenharmony_ci                    pb->pushStyle(style);
498cb93a386Sopenharmony_ci                    pb->addText(text, subTextCount);
499cb93a386Sopenharmony_ci                    pb->pop();
500cb93a386Sopenharmony_ci
501cb93a386Sopenharmony_ci                    text += subTextCount;
502cb93a386Sopenharmony_ci                    textCount -= subTextCount;
503cb93a386Sopenharmony_ci                }
504cb93a386Sopenharmony_ci                if (textCount != 0) {
505cb93a386Sopenharmony_ci                    return emscripten::val("Didn't have enough block runs to cover text");
506cb93a386Sopenharmony_ci                }
507cb93a386Sopenharmony_ci
508cb93a386Sopenharmony_ci                auto pa = pb->Build();
509cb93a386Sopenharmony_ci                pa->layout(width);
510cb93a386Sopenharmony_ci
511cb93a386Sopenharmony_ci                // workaround until this is fixed in SkParagraph
512cb93a386Sopenharmony_ci                {
513cb93a386Sopenharmony_ci                    SkPictureRecorder rec;
514cb93a386Sopenharmony_ci                    pa->paint(rec.beginRecording({0,0,9999,9999}), 0, 0);
515cb93a386Sopenharmony_ci                }
516cb93a386Sopenharmony_ci                return GetShapedLines(*pa);
517cb93a386Sopenharmony_ci            }),
518cb93a386Sopenharmony_ci            allow_raw_pointers())
519cb93a386Sopenharmony_ci            .function("addText",
520cb93a386Sopenharmony_ci                      optional_override([](para::ParagraphBuilderImpl& self, std::string text) {
521cb93a386Sopenharmony_ci                          return self.addText(text.c_str(), text.length());
522cb93a386Sopenharmony_ci                      }))
523cb93a386Sopenharmony_ci            .function("build", &para::ParagraphBuilderImpl::Build, allow_raw_pointers())
524cb93a386Sopenharmony_ci            .function("pop", &para::ParagraphBuilderImpl::pop)
525cb93a386Sopenharmony_ci            .function("_pushStyle", optional_override([](para::ParagraphBuilderImpl& self,
526cb93a386Sopenharmony_ci                                                         SimpleTextStyle textStyle) {
527cb93a386Sopenharmony_ci                          auto ts = toTextStyle(textStyle);
528cb93a386Sopenharmony_ci                          self.pushStyle(ts);
529cb93a386Sopenharmony_ci                      }))
530cb93a386Sopenharmony_ci            // A method of pushing a textStyle with paints instead of colors for foreground and
531cb93a386Sopenharmony_ci            // background. Since SimpleTextStyle is a value object, it cannot contain paints, which
532cb93a386Sopenharmony_ci            // are not primitives. This binding is here to accept them. Any color that is specified
533cb93a386Sopenharmony_ci            // in the textStyle is overridden.
534cb93a386Sopenharmony_ci            .function("_pushPaintStyle",
535cb93a386Sopenharmony_ci                      optional_override([](para::ParagraphBuilderImpl& self,
536cb93a386Sopenharmony_ci                                           SimpleTextStyle textStyle, SkPaint foreground,
537cb93a386Sopenharmony_ci                                           SkPaint background) {
538cb93a386Sopenharmony_ci                          auto ts = toTextStyle(textStyle);
539cb93a386Sopenharmony_ci                          ts.setForegroundColor(foreground);
540cb93a386Sopenharmony_ci                          ts.setBackgroundColor(background);
541cb93a386Sopenharmony_ci                          self.pushStyle(ts);
542cb93a386Sopenharmony_ci                      }))
543cb93a386Sopenharmony_ci            .function("_addPlaceholder", optional_override([](para::ParagraphBuilderImpl& self,
544cb93a386Sopenharmony_ci                                                              SkScalar width,
545cb93a386Sopenharmony_ci                                                              SkScalar height,
546cb93a386Sopenharmony_ci                                                              para::PlaceholderAlignment alignment,
547cb93a386Sopenharmony_ci                                                              para::TextBaseline baseline,
548cb93a386Sopenharmony_ci                                                              SkScalar offset) {
549cb93a386Sopenharmony_ci                          para::PlaceholderStyle ps(width, height, alignment, baseline, offset);
550cb93a386Sopenharmony_ci                          self.addPlaceholder(ps);
551cb93a386Sopenharmony_ci                      }));
552cb93a386Sopenharmony_ci
553cb93a386Sopenharmony_ci    class_<para::TypefaceFontProvider, base<SkFontMgr>>("TypefaceFontProvider")
554cb93a386Sopenharmony_ci      .smart_ptr<sk_sp<para::TypefaceFontProvider>>("sk_sp<TypefaceFontProvider>")
555cb93a386Sopenharmony_ci      .class_function("Make", optional_override([]()-> sk_sp<para::TypefaceFontProvider> {
556cb93a386Sopenharmony_ci          return sk_make_sp<para::TypefaceFontProvider>();
557cb93a386Sopenharmony_ci      }))
558cb93a386Sopenharmony_ci      .function("_registerFont", optional_override([](para::TypefaceFontProvider& self,
559cb93a386Sopenharmony_ci                                                      sk_sp<SkTypeface> typeface,
560cb93a386Sopenharmony_ci                                                      WASMPointerU8 familyPtr) {
561cb93a386Sopenharmony_ci          const char* fPtr = reinterpret_cast<const char*>(familyPtr);
562cb93a386Sopenharmony_ci          SkString fStr(fPtr);
563cb93a386Sopenharmony_ci          self.registerTypeface(typeface, fStr);
564cb93a386Sopenharmony_ci      }), allow_raw_pointers());
565cb93a386Sopenharmony_ci
566cb93a386Sopenharmony_ci
567cb93a386Sopenharmony_ci    // These value objects make it easier to send data across the wire.
568cb93a386Sopenharmony_ci    value_object<para::PositionWithAffinity>("PositionWithAffinity")
569cb93a386Sopenharmony_ci        .field("pos",      &para::PositionWithAffinity::position)
570cb93a386Sopenharmony_ci        .field("affinity", &para::PositionWithAffinity::affinity);
571cb93a386Sopenharmony_ci
572cb93a386Sopenharmony_ci    value_object<SimpleFontStyle>("FontStyle")
573cb93a386Sopenharmony_ci        .field("slant",     &SimpleFontStyle::slant)
574cb93a386Sopenharmony_ci        .field("weight",    &SimpleFontStyle::weight)
575cb93a386Sopenharmony_ci        .field("width",     &SimpleFontStyle::width);
576cb93a386Sopenharmony_ci
577cb93a386Sopenharmony_ci    value_object<SimpleParagraphStyle>("ParagraphStyle")
578cb93a386Sopenharmony_ci        .field("disableHinting",     &SimpleParagraphStyle::disableHinting)
579cb93a386Sopenharmony_ci        .field("_ellipsisPtr",       &SimpleParagraphStyle::ellipsisPtr)
580cb93a386Sopenharmony_ci        .field("_ellipsisLen",       &SimpleParagraphStyle::ellipsisLen)
581cb93a386Sopenharmony_ci        .field("heightMultiplier",   &SimpleParagraphStyle::heightMultiplier)
582cb93a386Sopenharmony_ci        .field("maxLines",           &SimpleParagraphStyle::maxLines)
583cb93a386Sopenharmony_ci        .field("textAlign",          &SimpleParagraphStyle::textAlign)
584cb93a386Sopenharmony_ci        .field("textDirection",      &SimpleParagraphStyle::textDirection)
585cb93a386Sopenharmony_ci        .field("textHeightBehavior", &SimpleParagraphStyle::textHeightBehavior)
586cb93a386Sopenharmony_ci        .field("textStyle",          &SimpleParagraphStyle::textStyle)
587cb93a386Sopenharmony_ci        .field("strutStyle",         &SimpleParagraphStyle::strutStyle);
588cb93a386Sopenharmony_ci
589cb93a386Sopenharmony_ci    value_object<SimpleStrutStyle>("StrutStyle")
590cb93a386Sopenharmony_ci        .field("_fontFamiliesPtr", &SimpleStrutStyle::fontFamiliesPtr)
591cb93a386Sopenharmony_ci        .field("_fontFamiliesLen", &SimpleStrutStyle::fontFamiliesLen)
592cb93a386Sopenharmony_ci        .field("strutEnabled",     &SimpleStrutStyle::strutEnabled)
593cb93a386Sopenharmony_ci        .field("fontSize",         &SimpleStrutStyle::fontSize)
594cb93a386Sopenharmony_ci        .field("fontStyle",        &SimpleStrutStyle::fontStyle)
595cb93a386Sopenharmony_ci        .field("heightMultiplier", &SimpleStrutStyle::heightMultiplier)
596cb93a386Sopenharmony_ci        .field("halfLeading",      &SimpleStrutStyle::halfLeading)
597cb93a386Sopenharmony_ci        .field("leading",          &SimpleStrutStyle::leading)
598cb93a386Sopenharmony_ci        .field("forceStrutHeight", &SimpleStrutStyle::forceStrutHeight);
599cb93a386Sopenharmony_ci
600cb93a386Sopenharmony_ci    value_object<SimpleTextStyle>("TextStyle")
601cb93a386Sopenharmony_ci        .field("_colorPtr",             &SimpleTextStyle::colorPtr)
602cb93a386Sopenharmony_ci        .field("_foregroundColorPtr",   &SimpleTextStyle::foregroundColorPtr)
603cb93a386Sopenharmony_ci        .field("_backgroundColorPtr",   &SimpleTextStyle::backgroundColorPtr)
604cb93a386Sopenharmony_ci        .field("decoration",            &SimpleTextStyle::decoration)
605cb93a386Sopenharmony_ci        .field("decorationThickness",   &SimpleTextStyle::decorationThickness)
606cb93a386Sopenharmony_ci        .field("_decorationColorPtr",   &SimpleTextStyle::decorationColorPtr)
607cb93a386Sopenharmony_ci        .field("decorationStyle",       &SimpleTextStyle::decorationStyle)
608cb93a386Sopenharmony_ci        .field("_fontFamiliesPtr",      &SimpleTextStyle::fontFamiliesPtr)
609cb93a386Sopenharmony_ci        .field("_fontFamiliesLen",      &SimpleTextStyle::fontFamiliesLen)
610cb93a386Sopenharmony_ci        .field("fontSize",              &SimpleTextStyle::fontSize)
611cb93a386Sopenharmony_ci        .field("letterSpacing",         &SimpleTextStyle::letterSpacing)
612cb93a386Sopenharmony_ci        .field("wordSpacing",           &SimpleTextStyle::wordSpacing)
613cb93a386Sopenharmony_ci        .field("heightMultiplier",      &SimpleTextStyle::heightMultiplier)
614cb93a386Sopenharmony_ci        .field("halfLeading",           &SimpleTextStyle::halfLeading)
615cb93a386Sopenharmony_ci        .field("_localePtr",            &SimpleTextStyle::localePtr)
616cb93a386Sopenharmony_ci        .field("_localeLen",            &SimpleTextStyle::localeLen)
617cb93a386Sopenharmony_ci        .field("fontStyle",             &SimpleTextStyle::fontStyle)
618cb93a386Sopenharmony_ci        .field("_shadowLen",            &SimpleTextStyle::shadowLen)
619cb93a386Sopenharmony_ci        .field("_shadowColorsPtr",      &SimpleTextStyle::shadowColorsPtr)
620cb93a386Sopenharmony_ci        .field("_shadowOffsetsPtr",     &SimpleTextStyle::shadowOffsetsPtr)
621cb93a386Sopenharmony_ci        .field("_shadowBlurRadiiPtr",   &SimpleTextStyle::shadowBlurRadiiPtr)
622cb93a386Sopenharmony_ci        .field("_fontFeatureLen",       &SimpleTextStyle::fontFeatureLen)
623cb93a386Sopenharmony_ci        .field("_fontFeatureNamesPtr",  &SimpleTextStyle::fontFeatureNamesPtr)
624cb93a386Sopenharmony_ci        .field("_fontFeatureValuesPtr", &SimpleTextStyle::fontFeatureValuesPtr);
625cb93a386Sopenharmony_ci
626cb93a386Sopenharmony_ci    // The U stands for unsigned - we can't bind a generic/template object, so we have to specify it
627cb93a386Sopenharmony_ci    // with the type we are using.
628cb93a386Sopenharmony_ci    // TODO(kjlubick) make this a typedarray.
629cb93a386Sopenharmony_ci    value_object<para::SkRange<size_t>>("URange")
630cb93a386Sopenharmony_ci        .field("start",    &para::SkRange<size_t>::start)
631cb93a386Sopenharmony_ci        .field("end",      &para::SkRange<size_t>::end);
632cb93a386Sopenharmony_ci
633cb93a386Sopenharmony_ci    // TextDecoration should be a const because they can be combined
634cb93a386Sopenharmony_ci    constant("NoDecoration", int(para::TextDecoration::kNoDecoration));
635cb93a386Sopenharmony_ci    constant("UnderlineDecoration", int(para::TextDecoration::kUnderline));
636cb93a386Sopenharmony_ci    constant("OverlineDecoration", int(para::TextDecoration::kOverline));
637cb93a386Sopenharmony_ci    constant("LineThroughDecoration", int(para::TextDecoration::kLineThrough));
638cb93a386Sopenharmony_ci}
639