blob: 258f85b4c12ba943b003336802c86b6f4e346a44 [file] [log] [blame]
Kevin Lubick369f6a52019-10-03 11:22:08 -04001(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 * This is bytes, but we'll want to think about them as float32s
8 * @type {Float32Array}
9 */
10 var floatArray = this._getRectsForRange(start, end, hStyle, wStyle);
11
12 if (!floatArray || !floatArray.length) {
13 return [];
14 }
15 var ret = [];
Kevin Lubick4a5f4f22019-11-20 08:27:10 -050016 for (var i = 0; i < floatArray.length; i+=5) {
17 var r = CanvasKit.LTRBRect(floatArray[i], floatArray[i+1], floatArray[i+2], floatArray[i+3]);
Nathaniel Nifong59d299b2020-05-29 11:06:19 -040018 if (floatArray[i+4] === 0) {
Kevin Lubick4a5f4f22019-11-20 08:27:10 -050019 r['direction'] = CanvasKit.TextDirection.RTL;
20 } else {
21 r['direction'] = CanvasKit.TextDirection.LTR;
22 }
23 ret.push(r);
Kevin Lubick369f6a52019-10-03 11:22:08 -040024 }
25 CanvasKit._free(floatArray.byteOffset);
26 return ret;
27 }
28
Harry Terkelsen10f019c2020-08-04 13:21:09 -070029 // Registers the font (provided as an arrayBuffer) with the alias `family`.
30 CanvasKit.TypefaceFontProvider.prototype.registerFont = function(font, family) {
31 var typeface = CanvasKit.SkFontMgr.RefDefault().MakeTypefaceFromData(font);
32 if (!typeface) {
33 SkDebug('Could not decode font data');
34 // We do not need to free the data since the C++ will do that for us
35 // when the font is deleted (or fails to decode);
36 return null;
37 }
38 var familyPtr = cacheOrCopyString(family);
39 this._registerFont(typeface, familyPtr);
40 }
41
Kevin Lubick369f6a52019-10-03 11:22:08 -040042 // These helpers fill out all fields, because emscripten complains if we
43 // have undefined and it expects, for example, a float.
44 CanvasKit.ParagraphStyle = function(s) {
45 // Use [''] to tell closure not to minify the names
Kevin Lubickd3b1fe62019-10-21 10:50:26 -040046 // TODO(kjlubick): strutStyle
47 s['disableHinting'] = s['disableHinting'] || false;
48 if (s['ellipsis']) {
49 var str = s['ellipsis'];
Kevin Lubick0c8884b2020-05-14 08:27:53 -040050 s['_ellipsisPtr'] = cacheOrCopyString(str);
51 s['_ellipsisLen'] = lengthBytesUTF8(str) + 1; // add 1 for the null terminator.
Kevin Lubickd3b1fe62019-10-21 10:50:26 -040052 } else {
53 s['_ellipsisPtr'] = nullptr;
54 s['_ellipsisLen'] = 0;
55 }
56
Kevin Lubick369f6a52019-10-03 11:22:08 -040057 s['heightMultiplier'] = s['heightMultiplier'] || 0;
58 s['maxLines'] = s['maxLines'] || 0;
59 s['textAlign'] = s['textAlign'] || CanvasKit.TextAlign.Start;
Kevin Lubickd3b1fe62019-10-21 10:50:26 -040060 s['textDirection'] = s['textDirection'] || CanvasKit.TextDirection.LTR;
Kevin Lubick369f6a52019-10-03 11:22:08 -040061 s['textStyle'] = CanvasKit.TextStyle(s['textStyle']);
62 return s;
Kevin Lubick0c8884b2020-05-14 08:27:53 -040063 };
Kevin Lubick369f6a52019-10-03 11:22:08 -040064
Kevin Lubickd3b1fe62019-10-21 10:50:26 -040065 function fontStyle(s) {
66 s = s || {};
67 // Can't check for falsey as 0 width means "invisible".
68 if (s['weight'] === undefined) {
69 s['weight'] = CanvasKit.FontWeight.Normal;
70 }
71 s['width'] = s['width'] || CanvasKit.FontWidth.Normal;
72 s['slant'] = s['slant'] || CanvasKit.FontSlant.Upright;
73 return s;
74 }
75
Kevin Lubick369f6a52019-10-03 11:22:08 -040076 CanvasKit.TextStyle = function(s) {
77 // Use [''] to tell closure not to minify the names
Kevin Lubick26133322020-06-11 13:48:16 -040078 if (!s['color']) {
Kevin Lubickd3b1fe62019-10-21 10:50:26 -040079 s['color'] = CanvasKit.BLACK;
80 }
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -040081
Kevin Lubick369f6a52019-10-03 11:22:08 -040082 s['decoration'] = s['decoration'] || 0;
83 s['decorationThickness'] = s['decorationThickness'] || 0;
84 s['fontSize'] = s['fontSize'] || 0;
Kevin Lubickd3b1fe62019-10-21 10:50:26 -040085 s['fontStyle'] = fontStyle(s['fontStyle']);
Kevin Lubick369f6a52019-10-03 11:22:08 -040086 return s;
Kevin Lubick0c8884b2020-05-14 08:27:53 -040087 };
Kevin Lubick369f6a52019-10-03 11:22:08 -040088
89 // returns a pointer to a place on the heap that has an array
90 // of char* (effectively a char**). For now, this does the naive thing
91 // and depends on the string being null-terminated. This should be used
92 // for simple, well-formed things (e.g. font-families), not arbitrary
93 // text that should be drawn. If we need this to handle more complex
94 // strings, it should return two pointers, a pointer of the
95 // string array and a pointer to an array of the strings byte lengths.
96 function naiveCopyStrArray(strings) {
97 if (!strings || !strings.length) {
98 return nullptr;
99 }
100 var sPtrs = [];
101 for (var i = 0; i < strings.length; i++) {
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400102 var strPtr = cacheOrCopyString(strings[i]);
Kevin Lubick369f6a52019-10-03 11:22:08 -0400103 sPtrs.push(strPtr);
104 }
Kevin Lubick69e46da2020-06-05 07:13:48 -0400105 return copy1dArray(sPtrs, "HEAPU32");
Kevin Lubick369f6a52019-10-03 11:22:08 -0400106 }
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400107
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400108 // maps string -> malloc'd pointer
109 var stringCache = {};
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400110
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400111 // cacheOrCopyString copies a string from JS into WASM on the heap and returns the pointer
112 // to the memory of the string. It is expected that a caller to this helper will *not* free
113 // that memory, so it is cached. Thus, if a future call to this function with the same string
114 // will return the cached pointer, preventing the memory usage from growing unbounded (in
115 // a normal use case).
116 function cacheOrCopyString(str) {
117 if (stringCache[str]) {
118 return stringCache[str];
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400119 }
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400120 // Add 1 for null terminator, which we need when copying/converting
121 var strLen = lengthBytesUTF8(str) + 1;
122 var strPtr = CanvasKit._malloc(strLen);
123 stringToUTF8(str, strPtr, strLen);
124 stringCache[str] = strPtr;
125 return strPtr;
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400126 }
127
Kevin Lubick6aa38692020-06-01 11:25:47 -0400128 // These scratch arrays are allocated once to copy the color data into, which saves us
129 // having to free them after every invocation.
130 var scratchForegroundColorPtr = CanvasKit._malloc(4 * 4); // room for 4 32bit floats
131 var scratchBackgroundColorPtr = CanvasKit._malloc(4 * 4); // room for 4 32bit floats
132
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400133 function copyArrays(textStyle) {
134 // These color fields were arrays, but will set to WASM pointers before we pass this
135 // object over the WASM interface.
Kevin Lubick6aa38692020-06-01 11:25:47 -0400136 textStyle['_colorPtr'] = copyColorToWasm(textStyle['color']);
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400137 textStyle['_foregroundColorPtr'] = nullptr; // nullptr is 0, from helper.js
138 textStyle['_backgroundColorPtr'] = nullptr;
Kevin Lubick6aa38692020-06-01 11:25:47 -0400139 if (textStyle['foregroundColor']) {
140 textStyle['_foregroundColorPtr'] = copyColorToWasm(textStyle['foregroundColor'], scratchForegroundColorPtr);
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400141 }
Kevin Lubick6aa38692020-06-01 11:25:47 -0400142 if (textStyle['backgroundColor']) {
143 textStyle['_backgroundColorPtr'] = copyColorToWasm(textStyle['backgroundColor'], scratchBackgroundColorPtr);
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400144 }
145
146 if (Array.isArray(textStyle['fontFamilies']) && textStyle['fontFamilies'].length) {
147 textStyle['_fontFamiliesPtr'] = naiveCopyStrArray(textStyle['fontFamilies']);
148 textStyle['_fontFamiliesLen'] = textStyle['fontFamilies'].length;
149 } else {
150 textStyle['_fontFamiliesPtr'] = nullptr;
151 textStyle['_fontFamiliesLen'] = 0;
152 SkDebug('no font families provided, text may draw wrong or not at all');
153 }
154 }
155
156 function freeArrays(textStyle) {
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400157 // The font family strings will get copied to a vector on the C++ side, which is owned by
158 // the text style.
159 CanvasKit._free(textStyle['_fontFamiliesPtr']);
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400160 }
161
162 CanvasKit.ParagraphBuilder.Make = function(paragraphStyle, fontManager) {
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400163 copyArrays(paragraphStyle['textStyle']);
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400164
165 var result = CanvasKit.ParagraphBuilder._Make(paragraphStyle, fontManager);
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400166 freeArrays(paragraphStyle['textStyle']);
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400167 return result;
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400168 };
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400169
Harry Terkelsen10f019c2020-08-04 13:21:09 -0700170 CanvasKit.ParagraphBuilder.MakeFromFontProvider = function(paragraphStyle, fontProvider) {
171 copyArrays(paragraphStyle['textStyle']);
172
173 var result = CanvasKit.ParagraphBuilder._MakeFromFontProvider(paragraphStyle, fontProvider);
174 freeArrays(paragraphStyle['textStyle']);
175 return result;
176 };
177
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400178 CanvasKit.ParagraphBuilder.prototype.pushStyle = function(textStyle) {
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400179 copyArrays(textStyle);
180 this._pushStyle(textStyle);
181 freeArrays(textStyle);
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400182 }
Nathaniel Nifonge09b3142020-08-04 09:06:54 -0400183
184 CanvasKit.ParagraphBuilder.prototype.pushPaintStyle = function(textStyle, fg, bg) {
185 copyArrays(textStyle);
186 this._pushPaintStyle(textStyle, fg, bg);
187 freeArrays(textStyle);
188 }
Kevin Lubick369f6a52019-10-03 11:22:08 -0400189});
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400190}(Module)); // When this file is loaded in, the high level object is "Module";