1CanvasKit._extraInitializations = CanvasKit._extraInitializations || []; 2CanvasKit._extraInitializations.push(function() { 3 4 CanvasKit.Canvas.prototype.drawText = function(str, x, y, paint, font) { 5 // lengthBytesUTF8 and stringToUTF8Array are defined in the emscripten 6 // JS. See https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#stringToUTF8 7 var strLen = lengthBytesUTF8(str); 8 // Add 1 for null terminator, which we need when copying/converting, but can ignore 9 // when we call into Skia. 10 var strPtr = CanvasKit._malloc(strLen + 1); 11 stringToUTF8(str, strPtr, strLen + 1); 12 this._drawSimpleText(strPtr, strLen, x, y, font, paint); 13 CanvasKit._free(strPtr); 14 }; 15 16 // Glyphs should be a Uint16Array of glyph ids, e.g. provided by Font.getGlyphIDs. 17 // If using a Malloc'd array, be sure to use CanvasKit.MallocGlyphIDs() to get the right type. 18 // The return value will be a Float32Array that is 4 times as long as the input array. For each 19 // glyph, there will be 4 floats for left, top, right, bottom (relative to 0, 0) for that glyph. 20 CanvasKit.Font.prototype.getGlyphBounds = function(glyphs, paint, optionalOutputArray) { 21 var glyphPtr = copy1dArray(glyphs, 'HEAPU16'); 22 var bytesPerRect = 4 * 4; 23 var rectPtr = CanvasKit._malloc(glyphs.length * bytesPerRect); 24 this._getGlyphWidthBounds(glyphPtr, glyphs.length, nullptr, rectPtr, paint || null); 25 26 var rects = new Float32Array(CanvasKit.HEAPU8.buffer, rectPtr, glyphs.length * 4); 27 freeArraysThatAreNotMallocedByUsers(glyphPtr, glyphs); 28 if (optionalOutputArray) { 29 optionalOutputArray.set(rects); 30 CanvasKit._free(rectPtr); 31 return optionalOutputArray; 32 } 33 var rv = Float32Array.from(rects); 34 CanvasKit._free(rectPtr); 35 return rv; 36 }; 37 38 CanvasKit.Font.prototype.getGlyphIDs = function(str, numGlyphIDs, optionalOutputArray) { 39 if (!numGlyphIDs) { 40 numGlyphIDs = str.length; 41 } 42 // lengthBytesUTF8 and stringToUTF8Array are defined in the emscripten 43 // JS. See https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#stringToUTF8 44 // Add 1 for null terminator 45 var strBytes = lengthBytesUTF8(str) + 1; 46 var strPtr = CanvasKit._malloc(strBytes); 47 stringToUTF8(str, strPtr, strBytes); // This includes the null terminator 48 49 var bytesPerGlyph = 2; 50 var glyphPtr = CanvasKit._malloc(numGlyphIDs * bytesPerGlyph); 51 // We don't need to compute the id for the null terminator, so subtract 1. 52 var actualIDs = this._getGlyphIDs(strPtr, strBytes - 1, numGlyphIDs, glyphPtr); 53 CanvasKit._free(strPtr); 54 if (actualIDs < 0) { 55 Debug('Could not get glyphIDs'); 56 CanvasKit._free(glyphPtr); 57 return null; 58 } 59 var glyphs = new Uint16Array(CanvasKit.HEAPU8.buffer, glyphPtr, actualIDs); 60 if (optionalOutputArray) { 61 optionalOutputArray.set(glyphs); 62 CanvasKit._free(glyphPtr); 63 return optionalOutputArray; 64 } 65 var rv = Uint16Array.from(glyphs); 66 CanvasKit._free(glyphPtr); 67 return rv; 68 }; 69 70 CanvasKit.Font.prototype.getGlyphIntercepts = function(glyphs, positions, top, bottom) { 71 var gPtr = copy1dArray(glyphs, 'HEAPU16'); 72 var pPtr = copy1dArray(positions, 'HEAPF32'); 73 return this._getGlyphIntercepts(gPtr, glyphs.length, !wasMalloced(glyphs), 74 pPtr, positions.length, !wasMalloced(positions), 75 top, bottom); 76 }; 77 78 // Glyphs should be a Uint16Array of glyph ids, e.g. provided by Font.getGlyphIDs. 79 // If using a Malloc'd array, be sure to use CanvasKit.MallocGlyphIDs() to get the right type. 80 // The return value will be a Float32Array that has one width per input glyph. 81 CanvasKit.Font.prototype.getGlyphWidths = function(glyphs, paint, optionalOutputArray) { 82 var glyphPtr = copy1dArray(glyphs, 'HEAPU16'); 83 var bytesPerWidth = 4; 84 var widthPtr = CanvasKit._malloc(glyphs.length * bytesPerWidth); 85 this._getGlyphWidthBounds(glyphPtr, glyphs.length, widthPtr, nullptr, paint || null); 86 87 var widths = new Float32Array(CanvasKit.HEAPU8.buffer, widthPtr, glyphs.length); 88 freeArraysThatAreNotMallocedByUsers(glyphPtr, glyphs); 89 if (optionalOutputArray) { 90 optionalOutputArray.set(widths); 91 CanvasKit._free(widthPtr); 92 return optionalOutputArray; 93 } 94 var rv = Float32Array.from(widths); 95 CanvasKit._free(widthPtr); 96 return rv; 97 }; 98 99 // arguments should all be arrayBuffers or be an array of arrayBuffers. 100 CanvasKit.FontMgr.FromData = function() { 101 if (!arguments.length) { 102 Debug('Could not make FontMgr from no font sources'); 103 return null; 104 } 105 var fonts = arguments; 106 if (fonts.length === 1 && Array.isArray(fonts[0])) { 107 fonts = arguments[0]; 108 } 109 if (!fonts.length) { 110 Debug('Could not make FontMgr from no font sources'); 111 return null; 112 } 113 var dPtrs = []; 114 var sizes = []; 115 for (var i = 0; i < fonts.length; i++) { 116 var data = new Uint8Array(fonts[i]); 117 var dptr = copy1dArray(data, 'HEAPU8'); 118 dPtrs.push(dptr); 119 sizes.push(data.byteLength); 120 } 121 // Pointers are 32 bit unsigned ints 122 var datasPtr = copy1dArray(dPtrs, 'HEAPU32'); 123 var sizesPtr = copy1dArray(sizes, 'HEAPU32'); 124 var fm = CanvasKit.FontMgr._fromData(datasPtr, sizesPtr, fonts.length); 125 // The FontMgr has taken ownership of the bytes we allocated in the for loop. 126 CanvasKit._free(datasPtr); 127 CanvasKit._free(sizesPtr); 128 return fm; 129 }; 130 131 CanvasKit.Typeface.MakeFreeTypeFaceFromData = function(fontData) { 132 var data = new Uint8Array(fontData); 133 134 var fptr = copy1dArray(data, 'HEAPU8'); 135 var font = CanvasKit.Typeface._MakeFreeTypeFaceFromData(fptr, data.byteLength); 136 if (!font) { 137 Debug('Could not decode font data'); 138 // We do not need to free the data since the C++ will do that for us 139 // when the font is deleted (or fails to decode); 140 return null; 141 } 142 return font; 143 }; 144 145 CanvasKit.Typeface.prototype.getGlyphIDs = function(str, numGlyphIDs, optionalOutputArray) { 146 if (!numGlyphIDs) { 147 numGlyphIDs = str.length; 148 } 149 // lengthBytesUTF8 and stringToUTF8Array are defined in the emscripten 150 // JS. See https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#stringToUTF8 151 // Add 1 for null terminator 152 var strBytes = lengthBytesUTF8(str) + 1; 153 var strPtr = CanvasKit._malloc(strBytes); 154 stringToUTF8(str, strPtr, strBytes); // This includes the null terminator 155 156 var bytesPerGlyph = 2; 157 var glyphPtr = CanvasKit._malloc(numGlyphIDs * bytesPerGlyph); 158 // We don't need to compute the id for the null terminator, so subtract 1. 159 var actualIDs = this._getGlyphIDs(strPtr, strBytes - 1, numGlyphIDs, glyphPtr); 160 CanvasKit._free(strPtr); 161 if (actualIDs < 0) { 162 Debug('Could not get glyphIDs'); 163 CanvasKit._free(glyphPtr); 164 return null; 165 } 166 var glyphs = new Uint16Array(CanvasKit.HEAPU8.buffer, glyphPtr, actualIDs); 167 if (optionalOutputArray) { 168 optionalOutputArray.set(glyphs); 169 CanvasKit._free(glyphPtr); 170 return optionalOutputArray; 171 } 172 var rv = Uint16Array.from(glyphs); 173 CanvasKit._free(glyphPtr); 174 return rv; 175 }; 176 177 CanvasKit.TextBlob.MakeOnPath = function(str, path, font, initialOffset) { 178 if (!str || !str.length) { 179 Debug('ignoring 0 length string'); 180 return; 181 } 182 if (!path || !path.countPoints()) { 183 Debug('ignoring empty path'); 184 return; 185 } 186 if (path.countPoints() === 1) { 187 Debug('path has 1 point, returning normal textblob'); 188 return this.MakeFromText(str, font); 189 } 190 191 if (!initialOffset) { 192 initialOffset = 0; 193 } 194 195 var ids = font.getGlyphIDs(str); 196 var widths = font.getGlyphWidths(ids); 197 198 var rsx = []; 199 var meas = new CanvasKit.ContourMeasureIter(path, false, 1); 200 var cont = meas.next(); 201 var dist = initialOffset; 202 var xycs = new Float32Array(4); 203 for (var i = 0; i < str.length && cont; i++) { 204 var width = widths[i]; 205 dist += width/2; 206 if (dist > cont.length()) { 207 // jump to next contour 208 cont.delete(); 209 cont = meas.next(); 210 if (!cont) { 211 // We have come to the end of the path - terminate the string 212 // right here. 213 str = str.substring(0, i); 214 break; 215 } 216 dist = width/2; 217 } 218 219 // Gives us the (x, y) coordinates as well as the cos/sin of the tangent 220 // line at that position. 221 cont.getPosTan(dist, xycs); 222 var cx = xycs[0]; 223 var cy = xycs[1]; 224 var cosT = xycs[2]; 225 var sinT = xycs[3]; 226 227 var adjustedX = cx - (width/2 * cosT); 228 var adjustedY = cy - (width/2 * sinT); 229 230 rsx.push(cosT, sinT, adjustedX, adjustedY); 231 dist += width/2; 232 } 233 var retVal = this.MakeFromRSXform(str, rsx, font); 234 cont && cont.delete(); 235 meas.delete(); 236 return retVal; 237 }; 238 239 CanvasKit.TextBlob.MakeFromRSXform = function(str, rsxForms, font) { 240 // lengthBytesUTF8 and stringToUTF8Array are defined in the emscripten 241 // JS. See https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#stringToUTF8 242 // Add 1 for null terminator 243 var strLen = lengthBytesUTF8(str) + 1; 244 var strPtr = CanvasKit._malloc(strLen); 245 // Add 1 for the null terminator. 246 stringToUTF8(str, strPtr, strLen); 247 248 var rPtr = copy1dArray(rsxForms, 'HEAPF32'); 249 250 var blob = CanvasKit.TextBlob._MakeFromRSXform(strPtr, strLen - 1, rPtr, font); 251 CanvasKit._free(strPtr); 252 if (!blob) { 253 Debug('Could not make textblob from string "' + str + '"'); 254 return null; 255 } 256 return blob; 257 }; 258 259 // Glyphs should be a Uint32Array of glyph ids, e.g. provided by Font.getGlyphIDs. 260 // If using a Malloc'd array, be sure to use CanvasKit.MallocGlyphIDs() to get the right type. 261 CanvasKit.TextBlob.MakeFromRSXformGlyphs = function(glyphs, rsxForms, font) { 262 // Currently on the C++ side, glyph ids are 16bit, but there is an effort to change that. 263 var glyphPtr = copy1dArray(glyphs, 'HEAPU16'); 264 var bytesPerGlyph = 2; 265 266 var rPtr = copy1dArray(rsxForms, 'HEAPF32'); 267 268 var blob = CanvasKit.TextBlob._MakeFromRSXformGlyphs(glyphPtr, glyphs.length * bytesPerGlyph, rPtr, font); 269 freeArraysThatAreNotMallocedByUsers(glyphPtr, glyphs); 270 if (!blob) { 271 Debug('Could not make textblob from glyphs "' + glyphs + '"'); 272 return null; 273 } 274 return blob; 275 }; 276 277 // Glyphs should be a Uint32Array of glyph ids, e.g. provided by Font.getGlyphIDs. 278 // If using a Malloc'd array, be sure to use CanvasKit.MallocGlyphIDs() to get the right type. 279 CanvasKit.TextBlob.MakeFromGlyphs = function(glyphs, font) { 280 // Currently on the C++ side, glyph ids are 16bit, but there is an effort to change that. 281 var glyphPtr = copy1dArray(glyphs, 'HEAPU16'); 282 var bytesPerGlyph = 2; 283 var blob = CanvasKit.TextBlob._MakeFromGlyphs(glyphPtr, glyphs.length * bytesPerGlyph, font); 284 freeArraysThatAreNotMallocedByUsers(glyphPtr, glyphs); 285 if (!blob) { 286 Debug('Could not make textblob from glyphs "' + glyphs + '"'); 287 return null; 288 } 289 return blob; 290 }; 291 292 CanvasKit.TextBlob.MakeFromText = function(str, font) { 293 // lengthBytesUTF8 and stringToUTF8Array are defined in the emscripten 294 // JS. See https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#stringToUTF8 295 // Add 1 for null terminator 296 var strLen = lengthBytesUTF8(str) + 1; 297 var strPtr = CanvasKit._malloc(strLen); 298 // Add 1 for the null terminator. 299 stringToUTF8(str, strPtr, strLen); 300 301 var blob = CanvasKit.TextBlob._MakeFromText(strPtr, strLen - 1, font); 302 CanvasKit._free(strPtr); 303 if (!blob) { 304 Debug('Could not make textblob from string "' + str + '"'); 305 return null; 306 } 307 return blob; 308 }; 309 310 // A helper to return the right type for GlyphIDs stored internally. When that changes, this 311 // will also be changed, which will help avoid future breakages. 312 CanvasKit.MallocGlyphIDs = function(numGlyphIDs) { 313 return CanvasKit.Malloc(Uint16Array, numGlyphIDs); 314 } 315}); 316