1CanvasKit._extraInitializations = CanvasKit._extraInitializations || []; 2CanvasKit._extraInitializations.push(function() { 3 4 // str can be either a text string or a ShapedText object 5 CanvasKit.SkCanvas.prototype.drawText = function(str, x, y, paint, font) { 6 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); 15 } else { 16 this._drawShapedText(str, x, y, paint); 17 } 18 } 19 20 // Returns an array of the widths of the glyphs in this string. 21 CanvasKit.SkFont.prototype.getWidths = function(str) { 22 // add 1 for null terminator 23 var codePoints = str.length + 1; 24 // lengthBytesUTF8 and stringToUTF8Array are defined in the emscripten 25 // JS. See https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#stringToUTF8 26 // Add 1 for null terminator 27 var strBytes = lengthBytesUTF8(str) + 1; 28 var strPtr = CanvasKit._malloc(strBytes); 29 stringToUTF8(str, strPtr, strBytes); 30 31 var bytesPerFloat = 4; 32 // allocate widths == numCodePoints 33 var widthPtr = CanvasKit._malloc(codePoints * bytesPerFloat); 34 if (!this._getWidths(strPtr, strBytes, codePoints, widthPtr)) { 35 SkDebug('Could not compute widths'); 36 CanvasKit._free(strPtr); 37 CanvasKit._free(widthPtr); 38 return null; 39 } 40 // reminder, this shouldn't copy the data, just is a nice way to 41 // wrap 4 bytes together into a float. 42 var widths = new Float32Array(CanvasKit.HEAPU8.buffer, widthPtr, codePoints); 43 // This copies the data so we can free the CanvasKit memory 44 var retVal = Array.from(widths); 45 CanvasKit._free(strPtr); 46 CanvasKit._free(widthPtr); 47 return retVal; 48 } 49 50 // arguments should all be arrayBuffers or be an array of arrayBuffers. 51 CanvasKit.SkFontMgr.FromData = function() { 52 if (!arguments.length) { 53 SkDebug('Could not make SkFontMgr from no font sources'); 54 return null; 55 } 56 var fonts = arguments; 57 if (fonts.length === 1 && Array.isArray(fonts[0])) { 58 fonts = arguments[0]; 59 } 60 if (!fonts.length) { 61 SkDebug('Could not make SkFontMgr from no font sources'); 62 return null; 63 } 64 var dPtrs = []; 65 var sizes = []; 66 for (var i = 0; i < fonts.length; i++) { 67 var data = new Uint8Array(fonts[i]); 68 var dptr = copy1dArray(data, CanvasKit.HEAPU8); 69 dPtrs.push(dptr); 70 sizes.push(data.byteLength); 71 } 72 // Pointers are 32 bit unsigned ints 73 var datasPtr = copy1dArray(dPtrs, CanvasKit.HEAPU32); 74 var sizesPtr = copy1dArray(sizes, CanvasKit.HEAPU32); 75 var fm = CanvasKit.SkFontMgr._fromData(datasPtr, sizesPtr, fonts.length); 76 // The SkFontMgr has taken ownership of the bytes we allocated in the for loop. 77 CanvasKit._free(datasPtr); 78 CanvasKit._free(sizesPtr); 79 return fm; 80 } 81 82 // fontData should be an arrayBuffer 83 CanvasKit.SkFontMgr.prototype.MakeTypefaceFromData = function(fontData) { 84 var data = new Uint8Array(fontData); 85 86 var fptr = copy1dArray(data, CanvasKit.HEAPU8); 87 var font = this._makeTypefaceFromData(fptr, data.byteLength); 88 if (!font) { 89 SkDebug('Could not decode font data'); 90 // We do not need to free the data since the C++ will do that for us 91 // when the font is deleted (or fails to decode); 92 return null; 93 } 94 return font; 95 } 96 97 CanvasKit.SkTextBlob.MakeOnPath = function(str, path, font, initialOffset) { 98 if (!str || !str.length) { 99 SkDebug('ignoring 0 length string'); 100 return; 101 } 102 if (!path || !path.countPoints()) { 103 SkDebug('ignoring empty path'); 104 return; 105 } 106 if (path.countPoints() === 1) { 107 SkDebug('path has 1 point, returning normal textblob'); 108 return this.MakeFromText(str, font); 109 } 110 111 if (!initialOffset) { 112 initialOffset = 0; 113 } 114 115 var widths = font.getWidths(str); 116 117 var rsx = new CanvasKit.RSXFormBuilder(); 118 var meas = new CanvasKit.SkPathMeasure(path, false, 1); 119 var dist = initialOffset; 120 for (var i = 0; i < str.length; i++) { 121 var width = widths[i]; 122 dist += width/2; 123 if (dist > meas.getLength()) { 124 // jump to next contour 125 if (!meas.nextContour()) { 126 // We have come to the end of the path - terminate the string 127 // right here. 128 str = str.substring(0, i); 129 break; 130 } 131 dist = width/2; 132 } 133 134 // Gives us the (x, y) coordinates as well as the cos/sin of the tangent 135 // line at that position. 136 var xycs = meas.getPosTan(dist); 137 var cx = xycs[0]; 138 var cy = xycs[1]; 139 var cosT = xycs[2]; 140 var sinT = xycs[3]; 141 142 var adjustedX = cx - (width/2 * cosT); 143 var adjustedY = cy - (width/2 * sinT); 144 145 rsx.push(cosT, sinT, adjustedX, adjustedY); 146 dist += width/2; 147 } 148 var retVal = this.MakeFromRSXform(str, rsx, font); 149 rsx.delete(); 150 meas.delete(); 151 return retVal; 152 } 153 154 CanvasKit.SkTextBlob.MakeFromRSXform = function(str, rsxBuilder, font) { 155 // lengthBytesUTF8 and stringToUTF8Array are defined in the emscripten 156 // JS. See https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#stringToUTF8 157 // Add 1 for null terminator 158 var strLen = lengthBytesUTF8(str) + 1; 159 var strPtr = CanvasKit._malloc(strLen); 160 // Add 1 for the null terminator. 161 stringToUTF8(str, strPtr, strLen); 162 var rptr = rsxBuilder.build(); 163 164 var blob = CanvasKit.SkTextBlob._MakeFromRSXform(strPtr, strLen - 1, 165 rptr, font, CanvasKit.TextEncoding.UTF8); 166 if (!blob) { 167 SkDebug('Could not make textblob from string "' + str + '"'); 168 return null; 169 } 170 171 var origDelete = blob.delete.bind(blob); 172 blob.delete = function() { 173 CanvasKit._free(strPtr); 174 origDelete(); 175 } 176 return blob; 177 } 178 179 CanvasKit.SkTextBlob.MakeFromText = function(str, font) { 180 // lengthBytesUTF8 and stringToUTF8Array are defined in the emscripten 181 // JS. See https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#stringToUTF8 182 // Add 1 for null terminator 183 var strLen = lengthBytesUTF8(str) + 1; 184 var strPtr = CanvasKit._malloc(strLen); 185 // Add 1 for the null terminator. 186 stringToUTF8(str, strPtr, strLen); 187 188 var blob = CanvasKit.SkTextBlob._MakeFromText(strPtr, strLen - 1, font, CanvasKit.TextEncoding.UTF8); 189 if (!blob) { 190 SkDebug('Could not make textblob from string "' + str + '"'); 191 return null; 192 } 193 194 var origDelete = blob.delete.bind(blob); 195 blob.delete = function() { 196 CanvasKit._free(strPtr); 197 origDelete(); 198 } 199 return blob; 200 } 201}); 202