• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1(function(CanvasKit){
2  CanvasKit._extraInitializations = CanvasKit._extraInitializations || [];
3  CanvasKit._extraInitializations.push(function() {
4
5    CanvasKit.Paragraph.prototype.getRectsForRange = function(start, end, hStyle, wStyle) {
6    /**
7     * @type {Float32Array}
8     */
9      var floatArray = this._getRectsForRange(start, end, hStyle, wStyle);
10      return floatArrayToRects(floatArray);
11    }
12
13    CanvasKit.Paragraph.prototype.getRectsForPlaceholders = function() {
14        /**
15        * @type {Float32Array}
16        */
17        var floatArray = this._getRectsForPlaceholders();
18        return floatArrayToRects(floatArray);
19    }
20
21    function floatArrayToRects(floatArray) {
22        if (!floatArray || !floatArray.length) {
23            return [];
24        }
25        var ret = [];
26        for (var i = 0; i < floatArray.length; i+=5) {
27            var rect = CanvasKit.LTRBRect(floatArray[i], floatArray[i+1], floatArray[i+2], floatArray[i+3]);
28            var dir = CanvasKit.TextDirection.LTR;
29            if (floatArray[i+4] === 0) {
30                dir = CanvasKit.TextDirection.RTL;
31            }
32            ret.push({'rect': rect, 'dir': dir});
33        }
34        CanvasKit._free(floatArray.byteOffset);
35        return ret;
36    }
37
38    // Registers the font (provided as an arrayBuffer) with the alias `family`.
39    CanvasKit.TypefaceFontProvider.prototype.registerFont = function(font, family) {
40      var typeface = CanvasKit.Typeface.MakeFreeTypeFaceFromData(font);
41      if (!typeface) {
42          Debug('Could not decode font data');
43          // We do not need to free the data since the C++ will do that for us
44          // when the font is deleted (or fails to decode);
45          return null;
46      }
47      var familyPtr = cacheOrCopyString(family);
48      this._registerFont(typeface, familyPtr);
49    }
50
51    // These helpers fill out all fields, because emscripten complains if we
52    // have undefined and it expects, for example, a float.
53    // TODO(kjlubick) For efficiency, we should probably just return opaque WASM objects so we do
54    //   not have to keep copying them across the wire.
55    CanvasKit.ParagraphStyle = function(s) {
56      // Use [''] to tell closure not to minify the names
57      s['disableHinting'] = s['disableHinting'] || false;
58      if (s['ellipsis']) {
59        var str = s['ellipsis'];
60        s['_ellipsisPtr'] = cacheOrCopyString(str);
61        s['_ellipsisLen'] = lengthBytesUTF8(str) + 1; // add 1 for the null terminator.
62      } else {
63        s['_ellipsisPtr'] = nullptr;
64        s['_ellipsisLen'] = 0;
65      }
66
67      if (s['heightMultiplier'] == null) {
68        s['heightMultiplier'] = -1
69      }
70      s['maxLines'] = s['maxLines'] || 0;
71      s['replaceTabCharacters'] = s['replaceTabCharacters'] || false;
72      s['strutStyle'] = strutStyle(s['strutStyle']);
73      s['textAlign'] = s['textAlign'] || CanvasKit.TextAlign.Start;
74      s['textDirection'] = s['textDirection'] || CanvasKit.TextDirection.LTR;
75      s['textHeightBehavior'] = s['textHeightBehavior'] || CanvasKit.TextHeightBehavior.All;
76      s['textStyle'] = CanvasKit.TextStyle(s['textStyle']);
77      return s;
78    };
79
80    function fontStyle(s) {
81      s = s || {};
82      // Can't check for falsey as 0 width means "invisible".
83      if (s['weight'] === undefined) {
84        s['weight'] = CanvasKit.FontWeight.Normal;
85      }
86      s['width'] = s['width'] || CanvasKit.FontWidth.Normal;
87      s['slant'] = s['slant'] || CanvasKit.FontSlant.Upright;
88      return s;
89    }
90
91    function strutStyle(s) {
92        s = s || {};
93        s['strutEnabled'] = s['strutEnabled'] || false;
94
95        if (s['strutEnabled'] && Array.isArray(s['fontFamilies']) && s['fontFamilies'].length) {
96            s['_fontFamiliesPtr'] = naiveCopyStrArray(s['fontFamilies']);
97            s['_fontFamiliesLen'] = s['fontFamilies'].length;
98        } else {
99            s['_fontFamiliesPtr'] = nullptr;
100            s['_fontFamiliesLen'] = 0;
101        }
102        s['fontStyle'] = fontStyle(s['fontStyle']);
103        if (s['fontSize'] == null) {
104          s['fontSize'] = -1
105        }
106        if (s['heightMultiplier'] == null) {
107          s['heightMultiplier'] = -1
108        }
109        s['halfLeading'] = s['halfLeading'] || false;
110        s['leading'] = s['leading'] || 0;
111        s['forceStrutHeight'] = s['forceStrutHeight'] || false;
112        return s;
113    }
114
115    CanvasKit.TextStyle = function(s) {
116       // Use [''] to tell closure not to minify the names
117      if (!s['color']) {
118        s['color'] = CanvasKit.BLACK;
119      }
120
121      s['decoration'] = s['decoration'] || 0;
122      s['decorationThickness'] = s['decorationThickness'] || 0;
123      s['decorationStyle'] = s['decorationStyle'] || CanvasKit.DecorationStyle.Solid;
124      s['textBaseline'] = s['textBaseline'] || CanvasKit.TextBaseline.Alphabetic;
125      if (s['fontSize'] == null) {
126        s['fontSize'] = -1
127      }
128      s['letterSpacing'] = s['letterSpacing'] || 0;
129      s['wordSpacing'] = s['wordSpacing'] || 0;
130      if (s['heightMultiplier'] == null) {
131        s['heightMultiplier'] = -1
132      }
133      s['halfLeading'] = s['halfLeading'] || false;
134      s['fontStyle'] = fontStyle(s['fontStyle']);
135
136      // Properties which need to be Malloc'ed are set in `copyArrays`.
137
138      return s;
139    };
140
141    // returns a pointer to a place on the heap that has an array
142    // of char* (effectively a char**). For now, this does the naive thing
143    // and depends on the string being null-terminated. This should be used
144    // for simple, well-formed things (e.g. font-families), not arbitrary
145    // text that should be drawn. If we need this to handle more complex
146    // strings, it should return two pointers, a pointer of the
147    // string array and a pointer to an array of the strings byte lengths.
148    function naiveCopyStrArray(strings) {
149      if (!strings || !strings.length) {
150        return nullptr;
151      }
152      var sPtrs = [];
153      for (var i = 0; i < strings.length; i++) {
154        var strPtr = cacheOrCopyString(strings[i]);
155        sPtrs.push(strPtr);
156      }
157      return copy1dArray(sPtrs, 'HEAPU32');
158    }
159
160    // maps string -> malloc'd pointer
161    var stringCache = {};
162
163    // cacheOrCopyString copies a string from JS into WASM on the heap and returns the pointer
164    // to the memory of the string. It is expected that a caller to this helper will *not* free
165    // that memory, so it is cached. Thus, if a future call to this function with the same string
166    // will return the cached pointer, preventing the memory usage from growing unbounded (in
167    // a normal use case).
168    function cacheOrCopyString(str) {
169      if (stringCache[str]) {
170        return stringCache[str];
171      }
172      // Add 1 for null terminator, which we need when copying/converting
173      var strLen = lengthBytesUTF8(str) + 1;
174      var strPtr = CanvasKit._malloc(strLen);
175      stringToUTF8(str, strPtr, strLen);
176      stringCache[str] = strPtr;
177      return strPtr;
178    }
179
180    // These scratch arrays are allocated once to copy the color data into, which saves us
181    // having to free them after every invocation.
182    var scratchForegroundColorPtr = CanvasKit._malloc(4 * 4); // room for 4 32bit floats
183    var scratchBackgroundColorPtr = CanvasKit._malloc(4 * 4); // room for 4 32bit floats
184    var scratchDecorationColorPtr = CanvasKit._malloc(4 * 4); // room for 4 32bit floats
185
186    function copyArrays(textStyle) {
187      // These color fields were arrays, but will set to WASM pointers before we pass this
188      // object over the WASM interface.
189      textStyle['_colorPtr'] = copyColorToWasm(textStyle['color']);
190      textStyle['_foregroundColorPtr'] = nullptr; // nullptr is 0, from helper.js
191      textStyle['_backgroundColorPtr'] = nullptr;
192      textStyle['_decorationColorPtr'] = nullptr;
193      if (textStyle['foregroundColor']) {
194        textStyle['_foregroundColorPtr'] = copyColorToWasm(textStyle['foregroundColor'], scratchForegroundColorPtr);
195      }
196      if (textStyle['backgroundColor']) {
197        textStyle['_backgroundColorPtr'] = copyColorToWasm(textStyle['backgroundColor'], scratchBackgroundColorPtr);
198      }
199      if (textStyle['decorationColor']) {
200        textStyle['_decorationColorPtr'] = copyColorToWasm(textStyle['decorationColor'], scratchDecorationColorPtr);
201      }
202
203      if (Array.isArray(textStyle['fontFamilies']) && textStyle['fontFamilies'].length) {
204        textStyle['_fontFamiliesPtr'] = naiveCopyStrArray(textStyle['fontFamilies']);
205        textStyle['_fontFamiliesLen'] = textStyle['fontFamilies'].length;
206      } else {
207        textStyle['_fontFamiliesPtr'] = nullptr;
208        textStyle['_fontFamiliesLen'] = 0;
209        Debug('no font families provided, text may draw wrong or not at all');
210      }
211
212      if (textStyle['locale']) {
213        var str = textStyle['locale'];
214        textStyle['_localePtr'] = cacheOrCopyString(str);
215        textStyle['_localeLen'] = lengthBytesUTF8(str) + 1; // add 1 for the null terminator.
216      } else {
217        textStyle['_localePtr'] = nullptr;
218        textStyle['_localeLen'] = 0;
219      }
220
221      if (Array.isArray(textStyle['shadows']) && textStyle['shadows'].length) {
222        var shadows = textStyle['shadows'];
223        var shadowColors = shadows.map(function (s) { return s['color'] || CanvasKit.BLACK; });
224        var shadowBlurRadii = shadows.map(function (s) { return s['blurRadius'] || 0.0; });
225        textStyle['_shadowLen'] = shadows.length;
226        // 2 floats per point, 4 bytes per float
227        var ptr = CanvasKit._malloc(shadows.length * 2 * 4);
228        var adjustedPtr = ptr / 4;  // 4 bytes per float
229        for (var i = 0; i < shadows.length; i++) {
230          var offset = shadows[i]['offset'] || [0, 0];
231          CanvasKit.HEAPF32[adjustedPtr] = offset[0];
232          CanvasKit.HEAPF32[adjustedPtr + 1] = offset[1];
233          adjustedPtr += 2;
234        }
235        textStyle['_shadowColorsPtr'] = copyFlexibleColorArray(shadowColors).colorPtr;
236        textStyle['_shadowOffsetsPtr'] = ptr;
237        textStyle['_shadowBlurRadiiPtr'] = copy1dArray(shadowBlurRadii, 'HEAPF32');
238      } else {
239        textStyle['_shadowLen'] = 0;
240        textStyle['_shadowColorsPtr'] = nullptr;
241        textStyle['_shadowOffsetsPtr'] = nullptr;
242        textStyle['_shadowBlurRadiiPtr'] = nullptr;
243      }
244
245      if (Array.isArray(textStyle['fontFeatures']) && textStyle['fontFeatures'].length) {
246        var fontFeatures = textStyle['fontFeatures'];
247        var fontFeatureNames = fontFeatures.map(function (s) { return s['name']; });
248        var fontFeatureValues = fontFeatures.map(function (s) { return s['value']; });
249        textStyle['_fontFeatureLen'] = fontFeatures.length;
250        textStyle['_fontFeatureNamesPtr'] = naiveCopyStrArray(fontFeatureNames);
251        textStyle['_fontFeatureValuesPtr'] = copy1dArray(fontFeatureValues, 'HEAPU32');
252      } else {
253        textStyle['_fontFeatureLen'] = 0;
254        textStyle['_fontFeatureNamesPtr'] = nullptr;
255        textStyle['_fontFeatureValuesPtr'] = nullptr;
256      }
257
258      if (Array.isArray(textStyle['fontVariations']) && textStyle['fontVariations'].length) {
259        var fontVariations = textStyle['fontVariations'];
260        var fontVariationAxes = fontVariations.map(function (s) { return s['axis']; });
261        var fontVariationValues = fontVariations.map(function (s) { return s['value']; });
262        textStyle['_fontVariationLen'] = fontVariations.length;
263        textStyle['_fontVariationAxesPtr'] = naiveCopyStrArray(fontVariationAxes);
264        textStyle['_fontVariationValuesPtr'] = copy1dArray(fontVariationValues, 'HEAPF32');
265      } else {
266        textStyle['_fontVariationLen'] = 0;
267        textStyle['_fontVariationAxesPtr'] = nullptr;
268        textStyle['_fontVariationValuesPtr'] = nullptr;
269      }
270    }
271
272    function freeArrays(textStyle) {
273      // The font family strings will get copied to a vector on the C++ side, which is owned by
274      // the text style.
275      CanvasKit._free(textStyle['_fontFamiliesPtr']);
276      CanvasKit._free(textStyle['_shadowColorsPtr']);
277      CanvasKit._free(textStyle['_shadowOffsetsPtr']);
278      CanvasKit._free(textStyle['_shadowBlurRadiiPtr']);
279      CanvasKit._free(textStyle['_fontFeatureNamesPtr']);
280      CanvasKit._free(textStyle['_fontFeatureValuesPtr']);
281    }
282
283    CanvasKit.ParagraphBuilder.Make = function(paragraphStyle, fontManager) {
284      copyArrays(paragraphStyle['textStyle']);
285
286      var result =  CanvasKit.ParagraphBuilder._Make(paragraphStyle, fontManager);
287      freeArrays(paragraphStyle['textStyle']);
288      return result;
289    };
290
291    CanvasKit.ParagraphBuilder.MakeFromFontProvider = function(paragraphStyle, fontProvider) {
292        copyArrays(paragraphStyle['textStyle']);
293
294        var result =  CanvasKit.ParagraphBuilder._MakeFromFontProvider(paragraphStyle, fontProvider);
295        freeArrays(paragraphStyle['textStyle']);
296        return result;
297    };
298
299    CanvasKit.ParagraphBuilder.ShapeText = function(text, blocks, width) {
300        let length = 0;
301        for (const b of blocks) {
302            length += b.length;
303        }
304        if (length !== text.length) {
305            throw "Accumulated block lengths must equal text.length";
306        }
307        return CanvasKit.ParagraphBuilder._ShapeText(text, blocks, width);
308    };
309
310    CanvasKit.ParagraphBuilder.prototype.pushStyle = function(textStyle) {
311      copyArrays(textStyle);
312      this._pushStyle(textStyle);
313      freeArrays(textStyle);
314    };
315
316    CanvasKit.ParagraphBuilder.prototype.pushPaintStyle = function(textStyle, fg, bg) {
317      copyArrays(textStyle);
318      this._pushPaintStyle(textStyle, fg, bg);
319      freeArrays(textStyle);
320    };
321
322    CanvasKit.ParagraphBuilder.prototype.addPlaceholder =
323          function(width, height, alignment, baseline, offset) {
324      width = width || 0;
325      height = height || 0;
326      alignment = alignment || CanvasKit.PlaceholderAlignment.Baseline;
327      baseline = baseline || CanvasKit.TextBaseline.Alphabetic;
328      offset = offset || 0;
329      this._addPlaceholder(width, height, alignment, baseline, offset);
330    };
331
332    CanvasKit.ParagraphBuilder.prototype.setWordsUtf8 = function(words) {
333      var bPtr = copy1dArray(words, 'HEAPU32');
334      this._setWordsUtf8(bPtr, words && words.length || 0);
335      freeArraysThatAreNotMallocedByUsers(bPtr,     words);
336    };
337    CanvasKit.ParagraphBuilder.prototype.setWordsUtf16 = function(words) {
338      var bPtr = copy1dArray(words, 'HEAPU32');
339      this._setWordsUtf16(bPtr, words && words.length || 0);
340      freeArraysThatAreNotMallocedByUsers(bPtr, words);
341    };
342
343    CanvasKit.ParagraphBuilder.prototype.setGraphemeBreaksUtf8 = function(graphemeBreaks) {
344      var bPtr = copy1dArray(graphemeBreaks, 'HEAPU32');
345      this._setGraphemeBreaksUtf8(bPtr, graphemeBreaks && graphemeBreaks.length || 0);
346      freeArraysThatAreNotMallocedByUsers(bPtr,     graphemeBreaks);
347    };
348    CanvasKit.ParagraphBuilder.prototype.setGraphemeBreaksUtf16 = function(graphemeBreaks) {
349      var bPtr = copy1dArray(graphemeBreaks, 'HEAPU32');
350      this._setGraphemeBreaksUtf16(bPtr, graphemeBreaks && graphemeBreaks.length || 0);
351      freeArraysThatAreNotMallocedByUsers(bPtr, graphemeBreaks);
352    };
353
354    CanvasKit.ParagraphBuilder.prototype.setLineBreaksUtf8 = function(lineBreaks) {
355      var bPtr = copy1dArray(lineBreaks, 'HEAPU32');
356      this._setLineBreaksUtf8(bPtr, lineBreaks && lineBreaks.length || 0);
357      freeArraysThatAreNotMallocedByUsers(bPtr,     lineBreaks);
358    };
359    CanvasKit.ParagraphBuilder.prototype.setLineBreaksUtf16 = function(lineBreaks) {
360      var bPtr = copy1dArray(lineBreaks, 'HEAPU32');
361      this._setLineBreaksUtf16(bPtr, lineBreaks && lineBreaks.length || 0);
362      freeArraysThatAreNotMallocedByUsers(bPtr, lineBreaks);
363    };
364});
365}(Module)); // When this file is loaded in, the high level object is "Module";
366