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