UNPKG

8.47 kBJavaScriptView Raw
1/**
2* Sutton SignWriting TrueType Font Module v1.2.0 (https://github.com/sutton-signwriting/font-ttf)
3* Author: Steve Slevinski (https://SteveSlevinski.me)
4* font.mjs is released under the MIT License.
5*/
6
7/**
8 * Function that appends font-face CSS for the Sutton SignWriting fonts for system installed fonts, relative directory fonts, or content delivery network
9 * @function font.cssAppend
10 * @param {string} dir - an optional relative directory for font location
11 * @example
12 * font.cssAppend('./font/')
13 */
14const cssAppend = function (dir = '') {
15 const id = "SgnwFontCss";
16
17 if (!document.getElementById(id)) {
18 const style = document.createElement('style');
19 style.setAttribute("id", "SgnwFontCss");
20 style.appendChild(document.createTextNode(`
21 @font-face {
22 font-family: "SuttonSignWritingLine";
23 src:
24 local('SuttonSignWritingLine'),
25 ${dir ? `url('${dir}SuttonSignWritingLine.ttf') format('truetype'),` : ""}
26 url('https://cdn.jsdelivr.net/npm/@sutton-signwriting/font-ttf@1.0.0/font/SuttonSignWritingLine.ttf') format('truetype');
27 }
28 @font-face {
29 font-family: "SuttonSignWritingFill";
30 src:
31 local('SuttonSignWritingFill'),
32 ${dir ? `url('${dir}SuttonSignWritingFill.ttf') format('truetype'),` : ""}
33 url('https://cdn.jsdelivr.net/npm/@sutton-signwriting/font-ttf@1.0.0/font/SuttonSignWritingFill.ttf') format('truetype');
34 }
35 @font-face {
36 font-family: "SuttonSignWritingOneD";
37 src:
38 local('SuttonSignWritingOneD'),
39 ${dir ? `url('${dir}SuttonSignWritingOneD.ttf') format('truetype'),` : ""}
40 url('https://cdn.jsdelivr.net/npm/@sutton-signwriting/font-ttf@1.0.0/font/SuttonSignWritingOneD.ttf') format('truetype');
41 }
42 `));
43 document.head.appendChild(style);
44 }
45};
46
47let sizes = {};
48const zoom = 2;
49const bound = 76 * zoom;
50const canvaser = document.createElement("canvas");
51canvaser.width = bound;
52canvaser.height = bound;
53const context = canvaser.getContext("2d");
54/**
55 * Function that returns the size of a symbol using an id
56 * @function font.symbolSize
57 * @param {number} id - a 16-bit number of a symbol
58 * @example
59 * font.symbolSize(1)
60 *
61 * return [15,30]
62 */
63
64const symbolSize = function (id) {
65 if (id in sizes) {
66 return [...sizes[id]];
67 }
68
69 context.clearRect(0, 0, bound, bound);
70 context.font = 30 * zoom + "px 'SuttonSignWritingLine'";
71 context.fillText(String.fromCodePoint(id + 0xF0000), 0, 0);
72 const imgData = context.getImageData(0, 0, bound, bound).data;
73 let w, h, i, s;
74
75 wloop: for (w = bound - 1; w >= 0; w--) {
76 for (h = 0; h < bound; h += 1) {
77 for (s = 0; s < 4; s += 1) {
78 i = w * 4 + h * 4 * bound + s;
79
80 if (imgData[i]) {
81 break wloop;
82 }
83 }
84 }
85 }
86
87 var width = w;
88
89 hloop: for (h = bound - 1; h >= 0; h--) {
90 for (w = 0; w < width; w += 1) {
91 for (s = 0; s < 4; s += 1) {
92 i = w * 4 + h * 4 * bound + s;
93
94 if (imgData[i]) {
95 break hloop;
96 }
97 }
98 }
99 }
100
101 var height = h + 1;
102 width = Math.ceil(width / zoom);
103 height = Math.ceil(height / zoom); // Rounding error in chrome. Manual fixes.
104
105 if (14394 == id) {
106 width = 19;
107 }
108
109 if ([10468, 10480, 10496, 10512, 10500, 10532, 10548, 10862, 10878, 10894, 11058, 11074, 11476, 11488, 11492, 11504, 11508, 11520, 10516, 10910, 10926, 11042, 11082, 10942].includes(id)) {
110 width = 20;
111 }
112
113 if (31921 == id) {
114 width = 22;
115 }
116
117 if (38460 == id) {
118 width = 23;
119 }
120
121 if ([20164, 20212].includes(id)) {
122 width = 25;
123 }
124
125 if (31894 == id) {
126 width = 28;
127 }
128
129 if (46698 == id) {
130 width = 29;
131 }
132
133 if (29606 == id) {
134 width = 30;
135 }
136
137 if (44855 == id) {
138 width = 40;
139 }
140
141 if (32667 == id) {
142 width = 50;
143 }
144
145 if ([11088, 11474, 11490, 11506].includes(id)) {
146 height = 20;
147 }
148
149 if (6285 == id) {
150 height = 21;
151 }
152
153 if (40804 == id) {
154 height = 31;
155 }
156
157 if (41475 == id) {
158 height = 36;
159 } // Error in chrome. Manual fix.
160 // if (width==0 && height==0) {
161
162
163 if (width == 0 && height == 0) {
164 const sizefix = {
165 9: [15, 30],
166 10: [21, 30],
167 11: [30, 15],
168 12: [30, 21],
169 13: [15, 30],
170 14: [21, 30]
171 };
172
173 if (id in sizefix) {
174 width = sizefix[id][0];
175 height = sizefix[id][1];
176 }
177 }
178
179 if (width == 0 && height == 0) {
180 return undefined;
181 }
182
183 sizes[id] = [width, height];
184 return [width, height];
185};
186
187/**
188 * Function that returns a plane 15 character for a symbol line using an id
189 * @function font.symbolLine
190 * @param {number} id - a 16-bit number of a symbol
191 * @example
192 * font.symbolLine(1)
193 *
194 * return '󰀁'
195 */
196const symbolLine = function (id) {
197 return String.fromCodePoint(id + 0xF0000);
198};
199/**
200 * Function that returns a plane 16 character for a symbol fill using an id
201 * @function font.symbolFill
202 * @param {number} id - a 16-bit number of a symbol
203 * @example
204 * font.symbolFill(1)
205 *
206 * return '􀀁'
207 */
208
209
210const symbolFill = function (id) {
211 return String.fromCodePoint(id + 0x100000);
212};
213/**
214 * Function that creates two text elements for a symbol using an id
215 * @function font.symbolText
216 * @param {number} id - a 16-bit number of a symbol
217 * @example
218 * font.symbolText(1)
219 *
220 * return ` <text class="sym-fill" fill="white" style="pointer-events:none;font-family:'SuttonSignWritingFill';font-size:30px;">􀀁</text>
221 * <text class="sym-line" fill="black" style="pointer-events:none;font-family:'SuttonSignWritingLine';font-size:30px;">󰀁</text>`
222 */
223
224
225const symbolText = function (id) {
226 return ` <text class="sym-fill" fill="white" style="pointer-events:none;font-family:'SuttonSignWritingFill';font-size:30px;">${symbolFill(id)}</text>
227 <text class="sym-line" fill="black" style="pointer-events:none;font-family:'SuttonSignWritingLine';font-size:30px;">${symbolLine(id)}</text>`;
228};
229
230/**
231 * Function that executes a callback function once the Sutton SignWriiting Line and Fill fonts are ready to use
232 * @function font.cssLoaded
233 * @param {function} callback - a callback function to execute when fonts are ready
234 * @example
235 * const callback = () => {
236 * console.log("Sutton SignWriting Line and Fill fonts are ready to use")
237 * }
238 *
239 * font.cssLoaded( callback )
240 */
241
242const cssLoaded = function (callback) {
243 let lineReady = false;
244 let fillReady = false;
245 cssLoadedLine(() => {
246 lineReady = true;
247 });
248 cssLoadedFill(() => {
249 fillReady = true;
250 });
251 const cssCheck = setInterval(function () {
252 if (lineReady && fillReady) {
253 clearInterval(cssCheck);
254 callback();
255 }
256 }, 100);
257};
258/**
259 * Function that executes a callback function once the Sutton SignWriiting Line font is ready to use
260 * @function font.cssLoadedLine
261 * @param {function} callback - a callback function to execute when line font is ready
262 * @example
263 * const callback = () => {
264 * console.log("Sutton SignWriting Line font is ready to use")
265 * }
266 *
267 * font.cssLoadedLine( callback )
268 */
269
270
271const cssLoadedLine = function (callback) {
272 if (!symbolSize(1)) {
273 const cssCheck = setInterval(function () {
274 if (symbolSize(1)) {
275 clearInterval(cssCheck);
276 callback();
277 }
278 }, 100);
279 } else {
280 callback();
281 }
282};
283/**
284 * Function that executes a callback function once the Sutton SignWriiting Fill font is ready to use
285 * @function font.cssLoadedFill
286 * @param {function} callback - a callback function to execute when fill font is ready
287 * @example
288 * const callback = () => {
289 * console.log("Sutton SignWriting Fill font is ready to use")
290 * }
291 *
292 * font.cssLoadedFill( callback )
293 */
294
295
296const cssLoadedFill = function (callback) {
297 const fillReady = function () {
298 const canvaser = document.createElement("canvas");
299 canvaser.width = 15;
300 canvaser.height = 30;
301 const context = canvaser.getContext("2d");
302 context.font = "30px 'SuttonSignWritingFill'";
303 context.fillText(symbolFill(1), 0, 0);
304 const imgData = context.getImageData(0, 0, 15, 30).data;
305 return !imgData.every(item => item === 0);
306 };
307
308 if (!fillReady()) {
309 const cssCheck = setInterval(function () {
310 if (fillReady()) {
311 clearInterval(cssCheck);
312 callback();
313 }
314 }, 100);
315 } else {
316 callback();
317 }
318};
319
320export { cssAppend, cssLoaded, cssLoadedFill, cssLoadedLine, symbolFill, symbolLine, symbolSize, symbolText };
321
322/* support ongoing development on https://patreon.com/signwriting */