blob: 6a70f996397c9207e5a0028bcf43febad3d27725 [file] [log] [blame]
Kevin Lubick933ea8c2020-01-06 08:10:05 -05001CanvasKit._extraInitializations = CanvasKit._extraInitializations || [];
2CanvasKit._extraInitializations.push(function() {
3
4 // str can be either a text string or a ShapedText object
Kevin Lubick54c1b3d2020-10-07 16:09:22 -04005 CanvasKit.Canvas.prototype.drawText = function(str, x, y, paint, font) {
Kevin Lubick933ea8c2020-01-06 08:10:05 -05006 if (typeof str === 'string') {
7 // lengthBytesUTF8 and stringToUTF8Array are defined in the emscripten
8 // JS. See https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#stringToUTF8
9 var strLen = lengthBytesUTF8(str);
10 // Add 1 for null terminator, which we need when copying/converting, but can ignore
11 // when we call into Skia.
12 var strPtr = CanvasKit._malloc(strLen + 1);
13 stringToUTF8(str, strPtr, strLen + 1);
14 this._drawSimpleText(strPtr, strLen, x, y, font, paint);
Kevin Lubick30793852020-09-25 10:52:16 -040015 CanvasKit._free(strPtr);
Kevin Lubick933ea8c2020-01-06 08:10:05 -050016 } else {
17 this._drawShapedText(str, x, y, paint);
18 }
19 }
20
Kevin Lubick54c1b3d2020-10-07 16:09:22 -040021 // Glyphs should be a Uint32Array of glyph ids, e.g. provided by Font.getGlyphIDs.
Kevin Lubick30793852020-09-25 10:52:16 -040022 // If using a Malloc'd array, be sure to use CanvasKit.MallocGlyphIDs() to get the right type.
23 // The return value will be a Float32Array that is 4 times as long as the input array. For each
24 // glyph, there will be 4 floats for left, top, right, bottom (relative to 0, 0) for that glyph.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -040025 CanvasKit.Font.prototype.getGlyphBounds = function(glyphs, paint, optionalOutputArray) {
Kevin Lubick30793852020-09-25 10:52:16 -040026 var glyphPtr = copy1dArray(glyphs, 'HEAPU16');
27 var bytesPerRect = 4 * 4;
28 var rectPtr = CanvasKit._malloc(glyphs.length * bytesPerRect);
29 this._getGlyphWidthBounds(glyphPtr, glyphs.length, nullptr, rectPtr, paint || null);
30
31 var rects = new Float32Array(CanvasKit.HEAPU8.buffer, rectPtr, glyphs.length * 4);
32 freeArraysThatAreNotMallocedByUsers(glyphPtr, glyphs);
33 if (optionalOutputArray) {
34 optionalOutputArray.set(rects);
35 CanvasKit._free(rectPtr);
36 return optionalOutputArray;
37 }
38 var rv = Float32Array.from(rects);
39 CanvasKit._free(rectPtr);
40 return rv;
41 };
42
Kevin Lubick54c1b3d2020-10-07 16:09:22 -040043 CanvasKit.Font.prototype.getGlyphIDs = function(str, numGlyphIDs, optionalOutputArray) {
Kevin Lubick30793852020-09-25 10:52:16 -040044 if (!numGlyphIDs) {
45 numGlyphIDs = str.length;
46 }
47 // lengthBytesUTF8 and stringToUTF8Array are defined in the emscripten
48 // JS. See https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#stringToUTF8
49 // Add 1 for null terminator
50 var strBytes = lengthBytesUTF8(str) + 1;
51 var strPtr = CanvasKit._malloc(strBytes);
52 stringToUTF8(str, strPtr, strBytes); // This includes the null terminator
53
54 var bytesPerGlyph = 2;
55 var glyphPtr = CanvasKit._malloc(numGlyphIDs * bytesPerGlyph);
56 // We don't need to compute the id for the null terminator, so subtract 1.
57 var actualIDs = this._getGlyphIDs(strPtr, strBytes - 1, numGlyphIDs, glyphPtr);
58 CanvasKit._free(strPtr);
59 if (actualIDs < 0) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -040060 Debug('Could not get glyphIDs');
Kevin Lubick30793852020-09-25 10:52:16 -040061 CanvasKit._free(glyphPtr);
62 return null;
63 }
64 var glyphs = new Uint16Array(CanvasKit.HEAPU8.buffer, glyphPtr, actualIDs);
65 if (optionalOutputArray) {
66 optionalOutputArray.set(glyphs);
67 CanvasKit._free(glyphPtr);
68 return optionalOutputArray;
69 }
70 var rv = Uint32Array.from(glyphs);
71 CanvasKit._free(glyphPtr);
72 return rv;
73 };
74
Kevin Lubick54c1b3d2020-10-07 16:09:22 -040075 // Glyphs should be a Uint32Array of glyph ids, e.g. provided by Font.getGlyphIDs.
Kevin Lubick30793852020-09-25 10:52:16 -040076 // If using a Malloc'd array, be sure to use CanvasKit.MallocGlyphIDs() to get the right type.
77 // The return value will be a Float32Array that has one width per input glyph.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -040078 CanvasKit.Font.prototype.getGlyphWidths = function(glyphs, paint, optionalOutputArray) {
Kevin Lubick30793852020-09-25 10:52:16 -040079 var glyphPtr = copy1dArray(glyphs, 'HEAPU16');
80 var bytesPerWidth = 4;
81 var widthPtr = CanvasKit._malloc(glyphs.length * bytesPerWidth);
82 this._getGlyphWidthBounds(glyphPtr, glyphs.length, widthPtr, nullptr, paint || null);
83
84 var widths = new Float32Array(CanvasKit.HEAPU8.buffer, widthPtr, glyphs.length);
85 freeArraysThatAreNotMallocedByUsers(glyphPtr, glyphs);
86 if (optionalOutputArray) {
87 optionalOutputArray.set(widths);
88 CanvasKit._free(widthPtr);
89 return optionalOutputArray;
90 }
91 var rv = Float32Array.from(widths);
92 CanvasKit._free(widthPtr);
93 return rv;
94 };
95
Kevin Lubick166d6332020-10-02 09:08:07 -040096 // Returns an array of the widths of the glyphs in this string.
97 // TODO(kjlubick) Remove this API - getGlyphWidths is the better API.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -040098 CanvasKit.Font.prototype.getWidths = function(str) {
Kevin Lubick933ea8c2020-01-06 08:10:05 -050099 // add 1 for null terminator
100 var codePoints = str.length + 1;
101 // lengthBytesUTF8 and stringToUTF8Array are defined in the emscripten
102 // JS. See https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#stringToUTF8
103 // Add 1 for null terminator
104 var strBytes = lengthBytesUTF8(str) + 1;
105 var strPtr = CanvasKit._malloc(strBytes);
106 stringToUTF8(str, strPtr, strBytes);
107
108 var bytesPerFloat = 4;
109 // allocate widths == numCodePoints
110 var widthPtr = CanvasKit._malloc(codePoints * bytesPerFloat);
111 if (!this._getWidths(strPtr, strBytes, codePoints, widthPtr)) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400112 Debug('Could not compute widths');
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500113 CanvasKit._free(strPtr);
114 CanvasKit._free(widthPtr);
115 return null;
116 }
117 // reminder, this shouldn't copy the data, just is a nice way to
118 // wrap 4 bytes together into a float.
Bryce Thomas1fa54042020-01-14 13:46:30 -0800119 var widths = new Float32Array(CanvasKit.HEAPU8.buffer, widthPtr, codePoints);
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500120 // This copies the data so we can free the CanvasKit memory
121 var retVal = Array.from(widths);
122 CanvasKit._free(strPtr);
123 CanvasKit._free(widthPtr);
124 return retVal;
125 }
126
127 // arguments should all be arrayBuffers or be an array of arrayBuffers.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400128 CanvasKit.FontMgr.FromData = function() {
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500129 if (!arguments.length) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400130 Debug('Could not make FontMgr from no font sources');
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500131 return null;
132 }
133 var fonts = arguments;
134 if (fonts.length === 1 && Array.isArray(fonts[0])) {
135 fonts = arguments[0];
136 }
137 if (!fonts.length) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400138 Debug('Could not make FontMgr from no font sources');
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500139 return null;
140 }
141 var dPtrs = [];
142 var sizes = [];
143 for (var i = 0; i < fonts.length; i++) {
144 var data = new Uint8Array(fonts[i]);
Kevin Lubick30793852020-09-25 10:52:16 -0400145 var dptr = copy1dArray(data, 'HEAPU8');
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500146 dPtrs.push(dptr);
147 sizes.push(data.byteLength);
148 }
149 // Pointers are 32 bit unsigned ints
Kevin Lubick30793852020-09-25 10:52:16 -0400150 var datasPtr = copy1dArray(dPtrs, 'HEAPU32');
151 var sizesPtr = copy1dArray(sizes, 'HEAPU32');
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400152 var fm = CanvasKit.FontMgr._fromData(datasPtr, sizesPtr, fonts.length);
153 // The FontMgr has taken ownership of the bytes we allocated in the for loop.
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500154 CanvasKit._free(datasPtr);
155 CanvasKit._free(sizesPtr);
156 return fm;
157 }
158
159 // fontData should be an arrayBuffer
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400160 CanvasKit.FontMgr.prototype.MakeTypefaceFromData = function(fontData) {
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500161 var data = new Uint8Array(fontData);
162
Kevin Lubick30793852020-09-25 10:52:16 -0400163 var fptr = copy1dArray(data, 'HEAPU8');
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500164 var font = this._makeTypefaceFromData(fptr, data.byteLength);
165 if (!font) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400166 Debug('Could not decode font data');
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500167 // We do not need to free the data since the C++ will do that for us
168 // when the font is deleted (or fails to decode);
169 return null;
170 }
171 return font;
172 }
173
Kevin Lubickf8823b52020-09-03 10:02:10 -0400174 // Clients can pass in a Float32Array with length 4 to this and the results
175 // will be copied into that array. Otherwise, a new TypedArray will be allocated
176 // and returned.
177 CanvasKit.ShapedText.prototype.getBounds = function(optionalOutputArray) {
178 this._getBounds(_scratchRectPtr);
179 var ta = _scratchRect['toTypedArray']();
180 if (optionalOutputArray) {
181 optionalOutputArray.set(ta);
182 return optionalOutputArray;
183 }
184 return ta.slice();
185 }
186
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400187 CanvasKit.TextBlob.MakeOnPath = function(str, path, font, initialOffset) {
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500188 if (!str || !str.length) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400189 Debug('ignoring 0 length string');
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500190 return;
191 }
192 if (!path || !path.countPoints()) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400193 Debug('ignoring empty path');
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500194 return;
195 }
196 if (path.countPoints() === 1) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400197 Debug('path has 1 point, returning normal textblob');
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500198 return this.MakeFromText(str, font);
199 }
200
201 if (!initialOffset) {
202 initialOffset = 0;
203 }
204
205 var widths = font.getWidths(str);
206
207 var rsx = new CanvasKit.RSXFormBuilder();
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400208 var meas = new CanvasKit.PathMeasure(path, false, 1);
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500209 var dist = initialOffset;
210 for (var i = 0; i < str.length; i++) {
211 var width = widths[i];
212 dist += width/2;
213 if (dist > meas.getLength()) {
214 // jump to next contour
215 if (!meas.nextContour()) {
216 // We have come to the end of the path - terminate the string
217 // right here.
218 str = str.substring(0, i);
219 break;
220 }
221 dist = width/2;
222 }
223
224 // Gives us the (x, y) coordinates as well as the cos/sin of the tangent
225 // line at that position.
226 var xycs = meas.getPosTan(dist);
227 var cx = xycs[0];
228 var cy = xycs[1];
229 var cosT = xycs[2];
230 var sinT = xycs[3];
231
232 var adjustedX = cx - (width/2 * cosT);
233 var adjustedY = cy - (width/2 * sinT);
234
235 rsx.push(cosT, sinT, adjustedX, adjustedY);
236 dist += width/2;
237 }
238 var retVal = this.MakeFromRSXform(str, rsx, font);
239 rsx.delete();
240 meas.delete();
241 return retVal;
242 }
243
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400244 CanvasKit.TextBlob.MakeFromRSXform = function(str, rsxBuilderOrArray, font) {
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500245 // lengthBytesUTF8 and stringToUTF8Array are defined in the emscripten
246 // JS. See https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#stringToUTF8
247 // Add 1 for null terminator
248 var strLen = lengthBytesUTF8(str) + 1;
249 var strPtr = CanvasKit._malloc(strLen);
250 // Add 1 for the null terminator.
251 stringToUTF8(str, strPtr, strLen);
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500252
Kevin Lubick30793852020-09-25 10:52:16 -0400253 var rPtr = nullptr;
254 if (rsxBuilderOrArray.build) {
255 rPtr = rsxBuilderOrArray.build();
256 } else {
257 rPtr = copy1dArray(rsxBuilderOrArray, 'HEAPF32');
258 }
259
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400260 var blob = CanvasKit.TextBlob._MakeFromRSXform(strPtr, strLen - 1, rPtr, font);
Kevin Lubick30793852020-09-25 10:52:16 -0400261 CanvasKit._free(strPtr);
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500262 if (!blob) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400263 Debug('Could not make textblob from string "' + str + '"');
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500264 return null;
265 }
Kevin Lubick30793852020-09-25 10:52:16 -0400266 return blob;
267 }
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500268
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400269 // Glyphs should be a Uint32Array of glyph ids, e.g. provided by Font.getGlyphIDs.
Kevin Lubick30793852020-09-25 10:52:16 -0400270 // If using a Malloc'd array, be sure to use CanvasKit.MallocGlyphIDs() to get the right type.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400271 CanvasKit.TextBlob.MakeFromRSXformGlyphs = function(glyphs, rsxBuilderOrArray, font) {
Kevin Lubick30793852020-09-25 10:52:16 -0400272 // Currently on the C++ side, glyph ids are 16bit, but there is an effort to change that.
273 var glyphPtr = copy1dArray(glyphs, 'HEAPU16');
274 var bytesPerGlyph = 2;
275
276 var rPtr = nullptr;
277 if (rsxBuilderOrArray.build) {
278 rPtr = rsxBuilderOrArray.build();
279 } else {
280 rPtr = copy1dArray(rsxBuilderOrArray, 'HEAPF32');
281 }
282
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400283 var blob = CanvasKit.TextBlob._MakeFromRSXformGlyphs(glyphPtr, glyphs.length * bytesPerGlyph, rPtr, font);
Kevin Lubick30793852020-09-25 10:52:16 -0400284 freeArraysThatAreNotMallocedByUsers(glyphPtr, glyphs);
285 if (!blob) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400286 Debug('Could not make textblob from glyphs "' + glyphs + '"');
Kevin Lubick30793852020-09-25 10:52:16 -0400287 return null;
288 }
289 return blob;
290 }
291
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400292 // Glyphs should be a Uint32Array of glyph ids, e.g. provided by Font.getGlyphIDs.
Kevin Lubick30793852020-09-25 10:52:16 -0400293 // If using a Malloc'd array, be sure to use CanvasKit.MallocGlyphIDs() to get the right type.
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400294 CanvasKit.TextBlob.MakeFromGlyphs = function(glyphs, font) {
Kevin Lubick30793852020-09-25 10:52:16 -0400295 // Currently on the C++ side, glyph ids are 16bit, but there is an effort to change that.
296 var glyphPtr = copy1dArray(glyphs, 'HEAPU16');
297 var bytesPerGlyph = 2;
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400298 var blob = CanvasKit.TextBlob._MakeFromGlyphs(glyphPtr, glyphs.length * bytesPerGlyph, font);
Kevin Lubick30793852020-09-25 10:52:16 -0400299 freeArraysThatAreNotMallocedByUsers(glyphPtr, glyphs);
300 if (!blob) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400301 Debug('Could not make textblob from glyphs "' + glyphs + '"');
Kevin Lubick30793852020-09-25 10:52:16 -0400302 return null;
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500303 }
304 return blob;
305 }
306
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400307 CanvasKit.TextBlob.MakeFromText = function(str, font) {
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500308 // lengthBytesUTF8 and stringToUTF8Array are defined in the emscripten
309 // JS. See https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#stringToUTF8
310 // Add 1 for null terminator
311 var strLen = lengthBytesUTF8(str) + 1;
312 var strPtr = CanvasKit._malloc(strLen);
313 // Add 1 for the null terminator.
314 stringToUTF8(str, strPtr, strLen);
315
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400316 var blob = CanvasKit.TextBlob._MakeFromText(strPtr, strLen - 1, font);
Kevin Lubick30793852020-09-25 10:52:16 -0400317 CanvasKit._free(strPtr);
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500318 if (!blob) {
Kevin Lubick54c1b3d2020-10-07 16:09:22 -0400319 Debug('Could not make textblob from string "' + str + '"');
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500320 return null;
321 }
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500322 return blob;
323 }
Kevin Lubick30793852020-09-25 10:52:16 -0400324
325 // A helper to return the right type for GlyphIDs stored internally. When that changes, this
326 // will also be changed, which will help avoid future breakages.
327 CanvasKit.MallocGlyphIDs = function(numGlyphIDs) {
328 return CanvasKit.Malloc(Uint16Array, numGlyphIDs);
329 }
Bryce Thomas1fa54042020-01-14 13:46:30 -0800330});