blob: 340c73e7fed51f6bea3276a00f44d9fe8bfe1a75 [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
29 // These helpers fill out all fields, because emscripten complains if we
30 // have undefined and it expects, for example, a float.
31 CanvasKit.ParagraphStyle = function(s) {
32 // Use [''] to tell closure not to minify the names
Kevin Lubickd3b1fe62019-10-21 10:50:26 -040033 // TODO(kjlubick): strutStyle
34 s['disableHinting'] = s['disableHinting'] || false;
35 if (s['ellipsis']) {
36 var str = s['ellipsis'];
Kevin Lubick0c8884b2020-05-14 08:27:53 -040037 s['_ellipsisPtr'] = cacheOrCopyString(str);
38 s['_ellipsisLen'] = lengthBytesUTF8(str) + 1; // add 1 for the null terminator.
Kevin Lubickd3b1fe62019-10-21 10:50:26 -040039 } else {
40 s['_ellipsisPtr'] = nullptr;
41 s['_ellipsisLen'] = 0;
42 }
43
Kevin Lubick369f6a52019-10-03 11:22:08 -040044 s['heightMultiplier'] = s['heightMultiplier'] || 0;
45 s['maxLines'] = s['maxLines'] || 0;
46 s['textAlign'] = s['textAlign'] || CanvasKit.TextAlign.Start;
Kevin Lubickd3b1fe62019-10-21 10:50:26 -040047 s['textDirection'] = s['textDirection'] || CanvasKit.TextDirection.LTR;
Kevin Lubick369f6a52019-10-03 11:22:08 -040048 s['textStyle'] = CanvasKit.TextStyle(s['textStyle']);
49 return s;
Kevin Lubick0c8884b2020-05-14 08:27:53 -040050 };
Kevin Lubick369f6a52019-10-03 11:22:08 -040051
Kevin Lubickd3b1fe62019-10-21 10:50:26 -040052 function fontStyle(s) {
53 s = s || {};
54 // Can't check for falsey as 0 width means "invisible".
55 if (s['weight'] === undefined) {
56 s['weight'] = CanvasKit.FontWeight.Normal;
57 }
58 s['width'] = s['width'] || CanvasKit.FontWidth.Normal;
59 s['slant'] = s['slant'] || CanvasKit.FontSlant.Upright;
60 return s;
61 }
62
Kevin Lubick369f6a52019-10-03 11:22:08 -040063 CanvasKit.TextStyle = function(s) {
64 // Use [''] to tell closure not to minify the names
Nathaniel Nifonge5d32542020-03-26 09:27:48 -040065 if (!isCanvasKitColor(s['color'])) {
Kevin Lubickd3b1fe62019-10-21 10:50:26 -040066 s['color'] = CanvasKit.BLACK;
67 }
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -040068
Kevin Lubick369f6a52019-10-03 11:22:08 -040069 s['decoration'] = s['decoration'] || 0;
70 s['decorationThickness'] = s['decorationThickness'] || 0;
71 s['fontSize'] = s['fontSize'] || 0;
Kevin Lubickd3b1fe62019-10-21 10:50:26 -040072 s['fontStyle'] = fontStyle(s['fontStyle']);
Kevin Lubick369f6a52019-10-03 11:22:08 -040073 return s;
Kevin Lubick0c8884b2020-05-14 08:27:53 -040074 };
Kevin Lubick369f6a52019-10-03 11:22:08 -040075
76 // returns a pointer to a place on the heap that has an array
77 // of char* (effectively a char**). For now, this does the naive thing
78 // and depends on the string being null-terminated. This should be used
79 // for simple, well-formed things (e.g. font-families), not arbitrary
80 // text that should be drawn. If we need this to handle more complex
81 // strings, it should return two pointers, a pointer of the
82 // string array and a pointer to an array of the strings byte lengths.
83 function naiveCopyStrArray(strings) {
84 if (!strings || !strings.length) {
85 return nullptr;
86 }
87 var sPtrs = [];
88 for (var i = 0; i < strings.length; i++) {
Kevin Lubick0c8884b2020-05-14 08:27:53 -040089 var strPtr = cacheOrCopyString(strings[i]);
Kevin Lubick369f6a52019-10-03 11:22:08 -040090 sPtrs.push(strPtr);
91 }
Kevin Lubick69e46da2020-06-05 07:13:48 -040092 return copy1dArray(sPtrs, "HEAPU32");
Kevin Lubick369f6a52019-10-03 11:22:08 -040093 }
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -040094
Kevin Lubick0c8884b2020-05-14 08:27:53 -040095 // maps string -> malloc'd pointer
96 var stringCache = {};
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -040097
Kevin Lubick0c8884b2020-05-14 08:27:53 -040098 // cacheOrCopyString copies a string from JS into WASM on the heap and returns the pointer
99 // to the memory of the string. It is expected that a caller to this helper will *not* free
100 // that memory, so it is cached. Thus, if a future call to this function with the same string
101 // will return the cached pointer, preventing the memory usage from growing unbounded (in
102 // a normal use case).
103 function cacheOrCopyString(str) {
104 if (stringCache[str]) {
105 return stringCache[str];
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400106 }
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400107 // Add 1 for null terminator, which we need when copying/converting
108 var strLen = lengthBytesUTF8(str) + 1;
109 var strPtr = CanvasKit._malloc(strLen);
110 stringToUTF8(str, strPtr, strLen);
111 stringCache[str] = strPtr;
112 return strPtr;
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400113 }
114
Kevin Lubick6aa38692020-06-01 11:25:47 -0400115 // These scratch arrays are allocated once to copy the color data into, which saves us
116 // having to free them after every invocation.
117 var scratchForegroundColorPtr = CanvasKit._malloc(4 * 4); // room for 4 32bit floats
118 var scratchBackgroundColorPtr = CanvasKit._malloc(4 * 4); // room for 4 32bit floats
119
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400120 function copyArrays(textStyle) {
121 // These color fields were arrays, but will set to WASM pointers before we pass this
122 // object over the WASM interface.
Kevin Lubick6aa38692020-06-01 11:25:47 -0400123 textStyle['_colorPtr'] = copyColorToWasm(textStyle['color']);
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400124 textStyle['_foregroundColorPtr'] = nullptr; // nullptr is 0, from helper.js
125 textStyle['_backgroundColorPtr'] = nullptr;
126
Kevin Lubick6aa38692020-06-01 11:25:47 -0400127 if (textStyle['foregroundColor']) {
128 textStyle['_foregroundColorPtr'] = copyColorToWasm(textStyle['foregroundColor'], scratchForegroundColorPtr);
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400129 }
Kevin Lubick6aa38692020-06-01 11:25:47 -0400130 if (textStyle['backgroundColor']) {
131 textStyle['_backgroundColorPtr'] = copyColorToWasm(textStyle['backgroundColor'], scratchBackgroundColorPtr);
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400132 }
133
134 if (Array.isArray(textStyle['fontFamilies']) && textStyle['fontFamilies'].length) {
135 textStyle['_fontFamiliesPtr'] = naiveCopyStrArray(textStyle['fontFamilies']);
136 textStyle['_fontFamiliesLen'] = textStyle['fontFamilies'].length;
137 } else {
138 textStyle['_fontFamiliesPtr'] = nullptr;
139 textStyle['_fontFamiliesLen'] = 0;
140 SkDebug('no font families provided, text may draw wrong or not at all');
141 }
142 }
143
144 function freeArrays(textStyle) {
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400145 // The font family strings will get copied to a vector on the C++ side, which is owned by
146 // the text style.
147 CanvasKit._free(textStyle['_fontFamiliesPtr']);
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400148 }
149
150 CanvasKit.ParagraphBuilder.Make = function(paragraphStyle, fontManager) {
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400151 copyArrays(paragraphStyle['textStyle']);
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400152
153 var result = CanvasKit.ParagraphBuilder._Make(paragraphStyle, fontManager);
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400154 freeArrays(paragraphStyle['textStyle']);
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400155 return result;
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400156 };
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400157
158 CanvasKit.ParagraphBuilder.prototype.pushStyle = function(textStyle) {
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400159 copyArrays(textStyle);
160 this._pushStyle(textStyle);
161 freeArrays(textStyle);
Nathaniel Nifong1bedbeb2020-05-04 16:46:17 -0400162 }
Kevin Lubick369f6a52019-10-03 11:22:08 -0400163});
Kevin Lubick0c8884b2020-05-14 08:27:53 -0400164}(Module)); // When this file is loaded in, the high level object is "Module";