blob: eb127bf8c2798fbc4ca83f59429afa9cf32893f8 [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
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.
Bryce Thomas1fa54042020-01-14 13:46:30 -080042 var widths = new Float32Array(CanvasKit.HEAPU8.buffer, widthPtr, codePoints);
Kevin Lubick933ea8c2020-01-06 08:10:05 -050043 // 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
Nathaniel Nifong2e307962020-03-10 10:44:04 -0400164 var blob = CanvasKit.SkTextBlob._MakeFromRSXform(strPtr, strLen - 1, rptr, font);
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500165 if (!blob) {
166 SkDebug('Could not make textblob from string "' + str + '"');
167 return null;
168 }
169
170 var origDelete = blob.delete.bind(blob);
171 blob.delete = function() {
172 CanvasKit._free(strPtr);
173 origDelete();
174 }
175 return blob;
176 }
177
178 CanvasKit.SkTextBlob.MakeFromText = function(str, font) {
179 // lengthBytesUTF8 and stringToUTF8Array are defined in the emscripten
180 // JS. See https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#stringToUTF8
181 // Add 1 for null terminator
182 var strLen = lengthBytesUTF8(str) + 1;
183 var strPtr = CanvasKit._malloc(strLen);
184 // Add 1 for the null terminator.
185 stringToUTF8(str, strPtr, strLen);
186
Nathaniel Nifong2e307962020-03-10 10:44:04 -0400187 var blob = CanvasKit.SkTextBlob._MakeFromText(strPtr, strLen - 1, font);
Kevin Lubick933ea8c2020-01-06 08:10:05 -0500188 if (!blob) {
189 SkDebug('Could not make textblob from string "' + str + '"');
190 return null;
191 }
192
193 var origDelete = blob.delete.bind(blob);
194 blob.delete = function() {
195 CanvasKit._free(strPtr);
196 origDelete();
197 }
198 return blob;
199 }
Bryce Thomas1fa54042020-01-14 13:46:30 -0800200});