xl-public-utils 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +176 -3
- package/index.js +5 -4
- package/package.json +12 -8
- package/src/bwip-js.mjs +4008 -0
- package/src/bwipp.mjs +5774 -0
- package/src/{qrcode.js → qrcode.mjs} +20 -4
- /package/src/{window.js → utils.mjs} +0 -0
- /package/src/{vtk.js → vtkUtils.mjs} +0 -0
package/src/bwip-js.mjs
ADDED
|
@@ -0,0 +1,4008 @@
|
|
|
1
|
+
// This file is part of the bwip-js project available at:
|
|
2
|
+
//
|
|
3
|
+
// http://metafloor.github.io/bwip-js
|
|
4
|
+
//
|
|
5
|
+
// Copyright (c) 2011-2024 Mark Warren
|
|
6
|
+
//
|
|
7
|
+
// This file contains code automatically generated from:
|
|
8
|
+
// Barcode Writer in Pure PostScript - Version 2024-06-18
|
|
9
|
+
// Copyright (c) 2004-2024 Terry Burton
|
|
10
|
+
//
|
|
11
|
+
// The MIT License
|
|
12
|
+
//
|
|
13
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
// of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
// in the Software without restriction, including without limitation the rights
|
|
16
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
+
// copies of the Software, and to permit persons to whom the Software is
|
|
18
|
+
// furnished to do so, subject to the following conditions:
|
|
19
|
+
//
|
|
20
|
+
// The above copyright notice and this permission notice shall be included in
|
|
21
|
+
// all copies or substantial portions of the Software.
|
|
22
|
+
//
|
|
23
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
29
|
+
// THE SOFTWARE.
|
|
30
|
+
//
|
|
31
|
+
"use strict";
|
|
32
|
+
|
|
33
|
+
import { bwipp_datamatrix,bwipp_qrcode,bwipp_lookup,bwipp_encode,BWIPP_VERSION } from './bwipp.mjs';
|
|
34
|
+
|
|
35
|
+
// exports.js
|
|
36
|
+
const BWIPJS_VERSION = '4.5.1 (2024-08-12)';
|
|
37
|
+
|
|
38
|
+
// bwipjs.toCanvas(canvas, options)
|
|
39
|
+
// bwipjs.toCanvas(options, canvas)
|
|
40
|
+
//
|
|
41
|
+
// Uses the built-in canvas drawing.
|
|
42
|
+
//
|
|
43
|
+
// `canvas` can be an HTMLCanvasElement or an ID string or unique selector string.
|
|
44
|
+
// `options` are a bwip-js/BWIPP options object.
|
|
45
|
+
//
|
|
46
|
+
// This function is synchronous and throws on error.
|
|
47
|
+
//
|
|
48
|
+
// Returns the HTMLCanvasElement.
|
|
49
|
+
function ToCanvas(cvs, opts) {
|
|
50
|
+
if (typeof opts == 'string' || opts instanceof HTMLCanvasElement) {
|
|
51
|
+
let tmp = cvs;
|
|
52
|
+
cvs = opts;
|
|
53
|
+
opts = tmp;
|
|
54
|
+
}
|
|
55
|
+
return _ToAny(bwipp_lookup(opts.bcid), opts, cvs);
|
|
56
|
+
}
|
|
57
|
+
// Entry point for the symbol-specific exports
|
|
58
|
+
//
|
|
59
|
+
// Polymorphic internal interface
|
|
60
|
+
// _ToAny(encoder, string, opts) : HTMLCanvasElement
|
|
61
|
+
// _ToAny(encoder, HTMLCanvasElement, opts) : HTMLCanvasElement
|
|
62
|
+
// _ToAny(encoder, opts, string) : HTMLCanvasElement
|
|
63
|
+
// _ToAny(encoder, opts, HTMLCanvasElement) : HTMLCanvasElement
|
|
64
|
+
// _ToAny(encoder, opts, drawing) : any
|
|
65
|
+
//
|
|
66
|
+
// 'string` can be either an `id` or query selector returning a single canvas element.
|
|
67
|
+
function _ToAny(encoder, opts, drawing) {
|
|
68
|
+
if (typeof opts == 'string') {
|
|
69
|
+
var canvas = document.getElementById(opts) || document.querySelector(opts);
|
|
70
|
+
if (!(canvas instanceof HTMLCanvasElement)) {
|
|
71
|
+
throw new Error('bwipjs: `' + opts + '`: not a canvas');
|
|
72
|
+
}
|
|
73
|
+
opts = drawing;
|
|
74
|
+
drawing = DrawingCanvas(canvas);
|
|
75
|
+
} else if (opts instanceof HTMLCanvasElement) {
|
|
76
|
+
var canvas = opts;
|
|
77
|
+
opts = drawing;
|
|
78
|
+
drawing = DrawingCanvas(canvas);
|
|
79
|
+
} else if (typeof drawing == 'string') {
|
|
80
|
+
var canvas = document.getElementById(drawing) || document.querySelector(drawing);
|
|
81
|
+
if (!(canvas instanceof HTMLCanvasElement)) {
|
|
82
|
+
throw new Error('bwipjs: `' + drawing + '`: not a canvas');
|
|
83
|
+
}
|
|
84
|
+
drawing = DrawingCanvas(canvas);
|
|
85
|
+
} else if (drawing instanceof HTMLCanvasElement) {
|
|
86
|
+
drawing = DrawingCanvas(drawing);
|
|
87
|
+
} else if (!drawing || typeof drawing != 'object' || !drawing.init) {
|
|
88
|
+
throw new Error('bwipjs: not a canvas or drawing object');
|
|
89
|
+
}
|
|
90
|
+
return _Render(encoder, opts, drawing);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// bwipjs.toSVG(options)
|
|
94
|
+
//
|
|
95
|
+
// Uses the built-in svg drawing interface.
|
|
96
|
+
//
|
|
97
|
+
// `options` are a bwip-js/BWIPP options object.
|
|
98
|
+
//
|
|
99
|
+
// This function is synchronous and throws on error.
|
|
100
|
+
//
|
|
101
|
+
// Returns a string containing a fully qualified SVG definition,
|
|
102
|
+
// including the natural width and height of the image, in pixels:
|
|
103
|
+
//
|
|
104
|
+
// <svg viewBox="0 0 242 200" xmlns="http://www.w3.org/2000/svg">
|
|
105
|
+
// ...
|
|
106
|
+
// </svg>
|
|
107
|
+
//
|
|
108
|
+
// Available on all platforms.
|
|
109
|
+
function ToSVG(opts) {
|
|
110
|
+
return _Render(bwipp_lookup(opts.bcid), opts, DrawingSVG());
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function FixupOptions(opts) {
|
|
114
|
+
var scale = opts.scale || 2;
|
|
115
|
+
var scaleX = +opts.scaleX || scale;
|
|
116
|
+
var scaleY = +opts.scaleY || scaleX;
|
|
117
|
+
|
|
118
|
+
// Fix up padding.
|
|
119
|
+
opts.paddingleft = padding(opts.paddingleft, opts.paddingwidth, opts.padding, scaleX);
|
|
120
|
+
opts.paddingright = padding(opts.paddingright, opts.paddingwidth, opts.padding, scaleX);
|
|
121
|
+
opts.paddingtop = padding(opts.paddingtop, opts.paddingheight, opts.padding, scaleY);
|
|
122
|
+
opts.paddingbottom = padding(opts.paddingbottom, opts.paddingheight, opts.padding, scaleY);
|
|
123
|
+
|
|
124
|
+
// We override BWIPP's background color functionality. If in CMYK, convert to RRGGBB so
|
|
125
|
+
// the drawing interface is consistent. Likewise, if in CSS-style #rgb or #rrggbb.
|
|
126
|
+
if (opts.backgroundcolor) {
|
|
127
|
+
var bgc = ''+opts.backgroundcolor;
|
|
128
|
+
if (/^[0-9a-fA-F]{8}$/.test(bgc)) {
|
|
129
|
+
var c = parseInt(bgc.substr(0,2), 16) / 255;
|
|
130
|
+
var m = parseInt(bgc.substr(2,2), 16) / 255;
|
|
131
|
+
var y = parseInt(bgc.substr(4,2), 16) / 255;
|
|
132
|
+
var k = parseInt(bgc.substr(6,2), 16) / 255;
|
|
133
|
+
var r = Math.floor((1-c) * (1-k) * 255).toString(16);
|
|
134
|
+
var g = Math.floor((1-m) * (1-k) * 255).toString(16);
|
|
135
|
+
var b = Math.floor((1-y) * (1-k) * 255).toString(16);
|
|
136
|
+
opts.backgroundcolor = (r.length == 1 ? '0' : '') + r +
|
|
137
|
+
(g.length == 1 ? '0' : '') + g +
|
|
138
|
+
(b.length == 1 ? '0' : '') + b;
|
|
139
|
+
} else {
|
|
140
|
+
if (bgc[0] == '#') {
|
|
141
|
+
bgc = bgc.substr(1);
|
|
142
|
+
}
|
|
143
|
+
if (/^[0-9a-fA-F]{6}$/.test(bgc)) {
|
|
144
|
+
opts.backgroundcolor = bgc;
|
|
145
|
+
} else if (/^[0-9a-fA-F]{3}$/.test(bgc)) {
|
|
146
|
+
opts.backgroundcolor = bgc[0] + bgc[0] + bgc[1] + bgc[1] + bgc[2] + bgc[2];
|
|
147
|
+
} else {
|
|
148
|
+
throw new Error('bwip-js: invalid backgroundcolor: ' + opts.backgroundcolor);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return opts;
|
|
154
|
+
|
|
155
|
+
// a is the most specific padding value, e.g. paddingleft
|
|
156
|
+
// b is the next most specific value, e.g. paddingwidth
|
|
157
|
+
// c is the general padding value.
|
|
158
|
+
// s is the scale, either scalex or scaley
|
|
159
|
+
function padding(a, b, c, s) {
|
|
160
|
+
if (a != null) {
|
|
161
|
+
a = a >>> 0;
|
|
162
|
+
return a*s >>> 0;
|
|
163
|
+
}
|
|
164
|
+
if (b != null) {
|
|
165
|
+
b = b >>> 0;
|
|
166
|
+
return b*s >>> 0;
|
|
167
|
+
}
|
|
168
|
+
c = c >>> 0;
|
|
169
|
+
return (c*s >>> 0) || 0;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
var BWIPJS_OPTIONS = {
|
|
174
|
+
bcid:1,
|
|
175
|
+
text:1,
|
|
176
|
+
scale:1,
|
|
177
|
+
scaleX:1,
|
|
178
|
+
scaleY:1,
|
|
179
|
+
rotate:1,
|
|
180
|
+
padding:1,
|
|
181
|
+
paddingwidth:1,
|
|
182
|
+
paddingheight:1,
|
|
183
|
+
paddingtop:1,
|
|
184
|
+
paddingleft:1,
|
|
185
|
+
paddingright:1,
|
|
186
|
+
paddingbottom:1,
|
|
187
|
+
backgroundcolor:1,
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// bwipjs.render(options, drawing)
|
|
191
|
+
//
|
|
192
|
+
// Renders a barcode using the provided drawing object.
|
|
193
|
+
//
|
|
194
|
+
// This function is synchronous and throws on error.
|
|
195
|
+
//
|
|
196
|
+
// Browser and nodejs usage.
|
|
197
|
+
function Render(options, drawing) {
|
|
198
|
+
return _Render(bwipp_lookup(options.bcid), options, drawing);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Called by the public exports
|
|
202
|
+
function _Render(encoder, options, drawing) {
|
|
203
|
+
var text = options.text;
|
|
204
|
+
if (!text) {
|
|
205
|
+
throw new ReferenceError('bwip-js: bar code text not specified.');
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// setopts() is optional on the drawing object.
|
|
209
|
+
FixupOptions(options);
|
|
210
|
+
drawing.setopts && drawing.setopts(options);
|
|
211
|
+
|
|
212
|
+
// Set the bwip-js defaults
|
|
213
|
+
var scale = options.scale || 2;
|
|
214
|
+
var scaleX = +options.scaleX || scale;
|
|
215
|
+
var scaleY = +options.scaleY || scaleX;
|
|
216
|
+
var rotate = options.rotate || 'N';
|
|
217
|
+
|
|
218
|
+
// Create a barcode writer object. This is the interface between
|
|
219
|
+
// the low-level BWIPP code, the bwip-js graphics context, and the
|
|
220
|
+
// drawing interface.
|
|
221
|
+
var bw = new BWIPJS(drawing);
|
|
222
|
+
|
|
223
|
+
// Set the BWIPP options
|
|
224
|
+
var bwippopts = {};
|
|
225
|
+
for (var id in options) {
|
|
226
|
+
if (!BWIPJS_OPTIONS[id]) {
|
|
227
|
+
bwippopts[id] = options[id];
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Fix a disconnect in the BWIPP rendering logic
|
|
232
|
+
if (bwippopts.alttext) {
|
|
233
|
+
bwippopts.includetext = true;
|
|
234
|
+
}
|
|
235
|
+
// We use mm rather than inches for height - except pharmacode2 height
|
|
236
|
+
// which is already in mm.
|
|
237
|
+
// exludes bwipp_pharmacode2
|
|
238
|
+
// if (+bwippopts.height && encoder != bwipp_pharmacode2) {
|
|
239
|
+
if (+bwippopts.height) {
|
|
240
|
+
bwippopts.height = bwippopts.height / 25.4 || 0.5;
|
|
241
|
+
}
|
|
242
|
+
// Likewise, width
|
|
243
|
+
if (+bwippopts.width) {
|
|
244
|
+
bwippopts.width = bwippopts.width / 25.4 || 0;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Scale the image
|
|
248
|
+
bw.scale(scaleX, scaleY);
|
|
249
|
+
|
|
250
|
+
// Call into the BWIPP cross-compiled code and render the image.
|
|
251
|
+
bwipp_encode(bw, encoder, text, bwippopts);
|
|
252
|
+
|
|
253
|
+
// Returns whatever drawing.end() returns, or `false` if nothing rendered.
|
|
254
|
+
return bw.render();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// bwipjs.raw(options)
|
|
258
|
+
// bwipjs.raw(bcid, text, opts-string)
|
|
259
|
+
//
|
|
260
|
+
// Invokes the low level BWIPP code and returns the raw encoding data.
|
|
261
|
+
//
|
|
262
|
+
// This function is synchronous and throws on error.
|
|
263
|
+
//
|
|
264
|
+
// Browser and nodejs usage.
|
|
265
|
+
function ToRaw(bcid, text, options) {
|
|
266
|
+
if (arguments.length == 1) {
|
|
267
|
+
options = bcid;
|
|
268
|
+
bcid = options.bcid;
|
|
269
|
+
text = options.text;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// The drawing interface is just needed for the pre-init() calls.
|
|
273
|
+
// Don't need to fixup the drawing specific options.
|
|
274
|
+
var drawing = DrawingBuiltin();
|
|
275
|
+
drawing.setopts(options);
|
|
276
|
+
|
|
277
|
+
var bw = new BWIPJS(drawing);
|
|
278
|
+
var stack = bwipp_encode(bw, bwipp_lookup(bcid), text, options, true);
|
|
279
|
+
|
|
280
|
+
// bwip-js uses Maps to emulate PostScript dictionary objects; but Maps
|
|
281
|
+
// are not a typical/expected return value. Convert to plain-old-objects.
|
|
282
|
+
var ids = { pixs:1, pixx:1, pixy:1, sbs:1, bbs:1, bhs:1, width:1, height:1 };
|
|
283
|
+
for (var i = 0; i < stack.length; i++) {
|
|
284
|
+
var elt = stack[i];
|
|
285
|
+
if (elt instanceof Map) {
|
|
286
|
+
var obj = {};
|
|
287
|
+
// Could they make Maps any harder to iterate over???
|
|
288
|
+
for (var keys = elt.keys(), size = elt.size, k = 0; k < size; k++) {
|
|
289
|
+
var id = keys.next().value;
|
|
290
|
+
if (ids[id]) {
|
|
291
|
+
var val = elt.get(id);
|
|
292
|
+
if (val instanceof Array) {
|
|
293
|
+
// The postscript arrays have extra named properties
|
|
294
|
+
// to emulate array views. Return cleaned up arrays.
|
|
295
|
+
obj[id] = val.b.slice(val.o, val.o + val.length);
|
|
296
|
+
} else {
|
|
297
|
+
obj[id] = val;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
stack[i] = obj;
|
|
302
|
+
} else {
|
|
303
|
+
// This should never exec...
|
|
304
|
+
stack.splice(i--, 1);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return stack;
|
|
308
|
+
}
|
|
309
|
+
// file : bwipjs.js
|
|
310
|
+
//
|
|
311
|
+
// Graphics-context interface to the BWIPP cross-compiled code
|
|
312
|
+
|
|
313
|
+
var BWIPJS = (function() {
|
|
314
|
+
|
|
315
|
+
// Math.floor(), etc. are notoriously slow. Caching seems to help.
|
|
316
|
+
var floor = Math.floor;
|
|
317
|
+
var round = Math.round;
|
|
318
|
+
var ceil = Math.ceil;
|
|
319
|
+
var min = Math.min;
|
|
320
|
+
var max = Math.max;
|
|
321
|
+
|
|
322
|
+
function BWIPJS(drawing) {
|
|
323
|
+
if (this.constructor !== BWIPJS) {
|
|
324
|
+
return new BWIPJS(drawing);
|
|
325
|
+
}
|
|
326
|
+
this.gstk = []; // Graphics save/restore stack
|
|
327
|
+
this.cmds = []; // Graphics primitives to replay when rendering
|
|
328
|
+
this.drawing = drawing; // Drawing interface
|
|
329
|
+
|
|
330
|
+
this.reset();
|
|
331
|
+
|
|
332
|
+
// Drawing surface bounding box
|
|
333
|
+
this.minx = this.miny = Infinity;
|
|
334
|
+
this.maxx = this.maxy = -Infinity;
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
// All graphics state that must be saved/restored is given a prefix of g_
|
|
338
|
+
BWIPJS.prototype.reset = function() {
|
|
339
|
+
// Current Transform Matrix - since we don't do rotation, we can fake
|
|
340
|
+
// the matrix math
|
|
341
|
+
this.g_tdx = 0; // CTM x-offset
|
|
342
|
+
this.g_tdy = 0; // CTM y-offset
|
|
343
|
+
this.g_tsx = 1; // CTM x-scale factor
|
|
344
|
+
this.g_tsy = 1; // CTM y-scale factor
|
|
345
|
+
|
|
346
|
+
this.g_posx = 0; // current x position
|
|
347
|
+
this.g_posy = 0; // current y position
|
|
348
|
+
this.g_penw = 1; // current line/pen width
|
|
349
|
+
this.g_path = []; // current path
|
|
350
|
+
this.g_font = null; // current font object
|
|
351
|
+
this.g_rgb = [0,0,0]; // current color (black)
|
|
352
|
+
this.g_clip = false; // clip region active
|
|
353
|
+
};
|
|
354
|
+
BWIPJS.prototype.save = function() {
|
|
355
|
+
// clone all g_ properties
|
|
356
|
+
var ctx = {};
|
|
357
|
+
for (var id in this) {
|
|
358
|
+
if (id.indexOf('g_') == 0) {
|
|
359
|
+
ctx[id] = clone(this[id]);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
this.gstk.push(ctx);
|
|
363
|
+
|
|
364
|
+
// Perform a deep clone of the graphics state properties
|
|
365
|
+
function clone(v) {
|
|
366
|
+
if (v instanceof Array) {
|
|
367
|
+
var t = [];
|
|
368
|
+
for (var i = 0; i < v.length; i++)
|
|
369
|
+
t[i] = clone(v[i]);
|
|
370
|
+
return t;
|
|
371
|
+
}
|
|
372
|
+
if (v instanceof Object) {
|
|
373
|
+
var t = {};
|
|
374
|
+
for (var id in v)
|
|
375
|
+
t[id] = clone(v[id]);
|
|
376
|
+
return t;
|
|
377
|
+
}
|
|
378
|
+
return v;
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
BWIPJS.prototype.restore = function() {
|
|
382
|
+
if (!this.gstk.length) {
|
|
383
|
+
throw new Error('grestore: stack underflow');
|
|
384
|
+
}
|
|
385
|
+
var ctx = this.gstk.pop();
|
|
386
|
+
var self = this;
|
|
387
|
+
if (this.g_clip && !ctx.g_clip) {
|
|
388
|
+
this.cmds.push(function() {
|
|
389
|
+
self.drawing.unclip();
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
for (var id in ctx) {
|
|
393
|
+
this[id] = ctx[id];
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
// Per the postscript spec:
|
|
397
|
+
// As discussed in Section 4.4.1, Current Path, points entered into a path
|
|
398
|
+
// are immediately converted to device coordinates by the current
|
|
399
|
+
// transformation matrix (CTM); subsequent modifications to the CTM do not
|
|
400
|
+
// affect existing points. `currentpoint` computes the user space
|
|
401
|
+
// coordinates corresponding to the current point according to the current
|
|
402
|
+
// value of the CTM. Thus, if a current point is set and then the CTM is
|
|
403
|
+
// changed, the coordinates returned by currentpoint will be different
|
|
404
|
+
// from those that were originally specified for the point.
|
|
405
|
+
BWIPJS.prototype.currpos = function() {
|
|
406
|
+
return { x:(this.g_posx-this.g_tdx)/this.g_tsx,
|
|
407
|
+
y:(this.g_posy-this.g_tdy)/this.g_tsy
|
|
408
|
+
};
|
|
409
|
+
};
|
|
410
|
+
BWIPJS.prototype.currfont = function() {
|
|
411
|
+
return this.g_font;
|
|
412
|
+
};
|
|
413
|
+
BWIPJS.prototype.translate = function(x, y) {
|
|
414
|
+
this.g_tdx = this.g_tsx * x;
|
|
415
|
+
this.g_tdy = this.g_tsy * y;
|
|
416
|
+
};
|
|
417
|
+
BWIPJS.prototype.scale = function(x, y) {
|
|
418
|
+
this.g_tsx *= x;
|
|
419
|
+
this.g_tsy *= y;
|
|
420
|
+
var sxy = this.drawing.scale(this.g_tsx, this.g_tsy);
|
|
421
|
+
if (sxy && sxy[0] && sxy[1]) {
|
|
422
|
+
this.g_tsx = sxy[0];
|
|
423
|
+
this.g_tsy = sxy[1];
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
BWIPJS.prototype.setlinewidth = function(w) {
|
|
427
|
+
this.g_penw = w;
|
|
428
|
+
};
|
|
429
|
+
BWIPJS.prototype.selectfont = function(f, z) {
|
|
430
|
+
this.g_font = { FontName:this.jsstring(f), FontSize:+z };
|
|
431
|
+
};
|
|
432
|
+
BWIPJS.prototype.getfont = function() {
|
|
433
|
+
return this.g_font.FontName;
|
|
434
|
+
};
|
|
435
|
+
// Special function for converting a Uint8Array string to string.
|
|
436
|
+
BWIPJS.prototype.jsstring = function(s) {
|
|
437
|
+
if (s instanceof Uint8Array) {
|
|
438
|
+
// Postscript (like C) treats nul-char as end of string.
|
|
439
|
+
//for (var i = 0, l = s.length; i < l && s[i]; i++);
|
|
440
|
+
//if (i < l) {
|
|
441
|
+
// return String.fromCharCode.apply(null,s.subarray(0, i));
|
|
442
|
+
//}
|
|
443
|
+
return String.fromCharCode.apply(null,s)
|
|
444
|
+
}
|
|
445
|
+
return ''+s;
|
|
446
|
+
};
|
|
447
|
+
// Special function to replace setanycolor in BWIPP.
|
|
448
|
+
// Converts a string of hex digits either rgb, rrggbb or ccmmyykk.
|
|
449
|
+
// Or CSS-style #rgb and #rrggbb.
|
|
450
|
+
BWIPJS.prototype.setcolor = function(s) {
|
|
451
|
+
if (s instanceof Uint8Array) {
|
|
452
|
+
s = this.jsstring(s);
|
|
453
|
+
}
|
|
454
|
+
if (!s) {
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
if (!/^(?:#?[0-9a-fA-F]{3}(?:[0-9a-fA-F]{3})?|[0-9a-fA-F]{8})$/.test(s)) {
|
|
458
|
+
throw new Error('bwip-js: invalid color: ' + s);
|
|
459
|
+
}
|
|
460
|
+
if (s[0] == '#') {
|
|
461
|
+
s = s.substr(1);
|
|
462
|
+
}
|
|
463
|
+
if (s.length == 3) {
|
|
464
|
+
var r = parseInt(s[0], 16);
|
|
465
|
+
var g = parseInt(s[1], 16);
|
|
466
|
+
var b = parseInt(s[2], 16);
|
|
467
|
+
this.g_rgb = [ r<<4|r, g<<4|g, b<<4|b ];
|
|
468
|
+
} else if (s.length == 6) {
|
|
469
|
+
var r = parseInt(s.substr(0,2), 16);
|
|
470
|
+
var g = parseInt(s.substr(2,2), 16);
|
|
471
|
+
var b = parseInt(s.substr(4,2), 16);
|
|
472
|
+
this.g_rgb = [ r, g, b ];
|
|
473
|
+
} else {
|
|
474
|
+
var c = parseInt(s.substr(0,2), 16) / 255;
|
|
475
|
+
var m = parseInt(s.substr(2,2), 16) / 255;
|
|
476
|
+
var y = parseInt(s.substr(4,2), 16) / 255;
|
|
477
|
+
var k = parseInt(s.substr(6,2), 16) / 255;
|
|
478
|
+
var r = round((1-c) * (1-k) * 255);
|
|
479
|
+
var g = round((1-m) * (1-k) * 255);
|
|
480
|
+
var b = round((1-y) * (1-k) * 255);
|
|
481
|
+
this.g_rgb = [ r, g, b ];
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
// Used only by swissqrcode
|
|
485
|
+
BWIPJS.prototype.setrgbcolor = function(r,g,b) {
|
|
486
|
+
this.g_rgb = [ r, g, b ];
|
|
487
|
+
};
|
|
488
|
+
// Returns the current rgb values as a 'RRGGBB'
|
|
489
|
+
BWIPJS.prototype.getRGB = function() {
|
|
490
|
+
var r = this.g_rgb[0].toString(16);
|
|
491
|
+
var g = this.g_rgb[1].toString(16);
|
|
492
|
+
var b = this.g_rgb[2].toString(16);
|
|
493
|
+
return '00'.substr(r.length) + r + '00'.substr(g.length) + g + '00'.substr(b.length) + b;
|
|
494
|
+
};
|
|
495
|
+
BWIPJS.prototype.newpath = function() {
|
|
496
|
+
this.g_path = [];
|
|
497
|
+
};
|
|
498
|
+
BWIPJS.prototype.closepath = function() {
|
|
499
|
+
var path = this.g_path;
|
|
500
|
+
var plen = path.length;
|
|
501
|
+
if (!plen) return;
|
|
502
|
+
|
|
503
|
+
var f = plen-1;
|
|
504
|
+
for ( ; f >= 0 && path[f].op == 'l'; f--);
|
|
505
|
+
f++;
|
|
506
|
+
if (f < plen-1) {
|
|
507
|
+
var poly = [];
|
|
508
|
+
var xmin = Infinity;
|
|
509
|
+
var ymin = Infinity;
|
|
510
|
+
var xmax = -Infinity;
|
|
511
|
+
var ymax = -Infinity;
|
|
512
|
+
for (var i = f; i < plen; i++) {
|
|
513
|
+
var a = path[i];
|
|
514
|
+
poly.push([ a.x0, a.y0 ]);
|
|
515
|
+
if (xmin > a.x0) xmin = a.x0;
|
|
516
|
+
if (xmax < a.x0) xmax = a.x0;
|
|
517
|
+
if (ymin > a.y0) ymin = a.y0;
|
|
518
|
+
if (ymax < a.y0) ymax = a.y0;
|
|
519
|
+
}
|
|
520
|
+
var a = path[plen-1];
|
|
521
|
+
var b = path[f];
|
|
522
|
+
if (a.x1 != b.x0 || a.y1 != b.y0) {
|
|
523
|
+
poly.push([ a.x1, a.y1 ]);
|
|
524
|
+
if (xmin > a.x1) xmin = a.x1;
|
|
525
|
+
if (xmax < a.x1) xmax = a.x1;
|
|
526
|
+
if (ymin > a.y1) ymin = a.y1;
|
|
527
|
+
if (ymax < a.y1) ymax = a.y1;
|
|
528
|
+
}
|
|
529
|
+
path.splice(f, plen-f,
|
|
530
|
+
{ op:'p', x0:xmin, y0:ymin, x1:xmax, y1:ymax, poly:poly });
|
|
531
|
+
} else {
|
|
532
|
+
path.push({ op:'c' });
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
BWIPJS.prototype.moveto = function(x,y) {
|
|
536
|
+
this.g_posx = this.g_tdx + this.g_tsx * x;
|
|
537
|
+
this.g_posy = this.g_tdy + this.g_tsy * y;
|
|
538
|
+
};
|
|
539
|
+
BWIPJS.prototype.rmoveto = function(x,y) {
|
|
540
|
+
this.g_posx += this.g_tsx * x;
|
|
541
|
+
this.g_posy += this.g_tsy * y;
|
|
542
|
+
};
|
|
543
|
+
BWIPJS.prototype.lineto = function(x,y) {
|
|
544
|
+
var x0 = round(this.g_posx);
|
|
545
|
+
var y0 = round(this.g_posy);
|
|
546
|
+
this.g_posx = this.g_tdx + this.g_tsx * x;
|
|
547
|
+
this.g_posy = this.g_tdy + this.g_tsy * y;
|
|
548
|
+
var x1 = round(this.g_posx);
|
|
549
|
+
var y1 = round(this.g_posy);
|
|
550
|
+
|
|
551
|
+
this.g_path.push({ op:'l', x0:x0, y0:y0, x1:x1, y1:y1 });
|
|
552
|
+
};
|
|
553
|
+
BWIPJS.prototype.rlineto = function(x,y) {
|
|
554
|
+
var x0 = round(this.g_posx);
|
|
555
|
+
var y0 = round(this.g_posy);
|
|
556
|
+
this.g_posx += this.g_tsx * x;
|
|
557
|
+
this.g_posy += this.g_tsy * y;
|
|
558
|
+
var x1 = round(this.g_posx);
|
|
559
|
+
var y1 = round(this.g_posy);
|
|
560
|
+
|
|
561
|
+
this.g_path.push({ op:'l', x0:x0, y0:y0, x1:x1, y1:y1 });
|
|
562
|
+
};
|
|
563
|
+
// implements both arc and arcn
|
|
564
|
+
BWIPJS.prototype.arc = function(x,y,r,sa,ea,ccw) {
|
|
565
|
+
if (sa == ea) {
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
// For now, we only implement full circles...
|
|
569
|
+
if (sa != 0 && sa != 360 || ea != 0 && ea != 360) {
|
|
570
|
+
throw new Error('arc: not a full circle (' + sa + ',' + ea + ')');
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
x = this.g_tdx + this.g_tsx * x;
|
|
574
|
+
y = this.g_tdy + this.g_tsy * y;
|
|
575
|
+
|
|
576
|
+
// e == ellipse
|
|
577
|
+
var rx = r * this.g_tsx;
|
|
578
|
+
var ry = r * this.g_tsy;
|
|
579
|
+
this.g_path.push({ op:'e', x0:x-rx, y0:y-ry, x1:x+rx, y1:y+ry,
|
|
580
|
+
x:x, y:y, rx:rx, ry:ry, sa:sa, ea:ea, ccw:ccw });
|
|
581
|
+
};
|
|
582
|
+
BWIPJS.prototype.stringwidth = function(str) {
|
|
583
|
+
var tsx = this.g_tsx;
|
|
584
|
+
var tsy = this.g_tsy;
|
|
585
|
+
var size = +this.g_font.FontSize || 10;
|
|
586
|
+
|
|
587
|
+
// The string can be either a uint8-string or regular string
|
|
588
|
+
str = this.toUCS2(this.jsstring(str));
|
|
589
|
+
|
|
590
|
+
var bbox = this.drawing.measure(str, this.g_font.FontName, size*tsx, size*tsy);
|
|
591
|
+
|
|
592
|
+
return { w:bbox.width/tsx, h:(bbox.ascent+bbox.descent)/tsy,
|
|
593
|
+
a:bbox.ascent/tsy, d:bbox.descent/tsy };
|
|
594
|
+
};
|
|
595
|
+
BWIPJS.prototype.charpath = function(str, b) {
|
|
596
|
+
var sw = this.stringwidth(str);
|
|
597
|
+
|
|
598
|
+
// Emulate the char-path by placing a rectangle around it
|
|
599
|
+
this.rlineto(0, sw.a);
|
|
600
|
+
this.rlineto(sw.w, 0);
|
|
601
|
+
this.rlineto(0, -sw.h);
|
|
602
|
+
};
|
|
603
|
+
BWIPJS.prototype.pathbbox = function() {
|
|
604
|
+
if (!this.g_path.length) throw new Error('pathbbox: --nocurrentpoint--');
|
|
605
|
+
var path = this.g_path;
|
|
606
|
+
var llx = Infinity;
|
|
607
|
+
var lly = Infinity;
|
|
608
|
+
var urx = -Infinity;
|
|
609
|
+
var ury = -Infinity;
|
|
610
|
+
for (var i = 0; i < path.length; i++) {
|
|
611
|
+
var a = path[i];
|
|
612
|
+
if (a.op == 'c') {
|
|
613
|
+
continue;
|
|
614
|
+
}
|
|
615
|
+
if (a.x0 < a.x1) {
|
|
616
|
+
if (llx > a.x0) llx = a.x0;
|
|
617
|
+
if (urx < a.x1) urx = a.x1;
|
|
618
|
+
} else {
|
|
619
|
+
if (llx > a.x1) llx = a.x1;
|
|
620
|
+
if (urx < a.x0) urx = a.x0;
|
|
621
|
+
}
|
|
622
|
+
if (a.y0 < a.y1) {
|
|
623
|
+
if (lly > a.y0) lly = a.y0;
|
|
624
|
+
if (ury < a.y1) ury = a.y1;
|
|
625
|
+
} else {
|
|
626
|
+
if (lly > a.y1) lly = a.y1;
|
|
627
|
+
if (ury < a.y0) ury = a.y0;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// Convert to user-space coordinates
|
|
632
|
+
var rv = { llx:(llx-this.g_tdx)/this.g_tsx,
|
|
633
|
+
lly:(lly-this.g_tdy)/this.g_tsy,
|
|
634
|
+
urx:(urx-this.g_tdx)/this.g_tsx,
|
|
635
|
+
ury:(ury-this.g_tdy)/this.g_tsy };
|
|
636
|
+
return rv;
|
|
637
|
+
};
|
|
638
|
+
// Tranforms the pts array to standard (not y-inverted), unscalled values.
|
|
639
|
+
BWIPJS.prototype.transform = function(pts) {
|
|
640
|
+
var minx = this.minx;
|
|
641
|
+
var maxy = this.maxy;
|
|
642
|
+
|
|
643
|
+
for (var i = 0; i < pts.length; i++) {
|
|
644
|
+
var pt = pts[i];
|
|
645
|
+
pt[0] = pt[0] - minx;
|
|
646
|
+
pt[1] = maxy - pt[1];
|
|
647
|
+
}
|
|
648
|
+
};
|
|
649
|
+
BWIPJS.prototype.stroke = function() {
|
|
650
|
+
var tsx = this.g_tsx;
|
|
651
|
+
var tsy = this.g_tsy;
|
|
652
|
+
var path = this.g_path;
|
|
653
|
+
var rgb = this.getRGB();
|
|
654
|
+
this.g_path = [];
|
|
655
|
+
|
|
656
|
+
// This is a "super majority" round i.e. if over .66 round up.
|
|
657
|
+
var penw = floor(this.g_penw * tsx + 0.66);
|
|
658
|
+
var penh = floor(this.g_penw * tsy + 0.66);
|
|
659
|
+
|
|
660
|
+
// Calculate the bounding boxes
|
|
661
|
+
var nlines = 0, npolys = 0;
|
|
662
|
+
for (var i = 0; i < path.length; i++) {
|
|
663
|
+
var a = path[i];
|
|
664
|
+
if (a.op == 'l') {
|
|
665
|
+
// We only stroke vertical and horizontal lines. Complex shapes are
|
|
666
|
+
// always filled.
|
|
667
|
+
if (a.x0 != a.x1 && a.y0 != a.y1) {
|
|
668
|
+
throw new Error('stroke: --not-orthogonal--');
|
|
669
|
+
}
|
|
670
|
+
var x0 = a.x0;
|
|
671
|
+
var y0 = a.y0;
|
|
672
|
+
var x1 = a.x1;
|
|
673
|
+
var y1 = a.y1;
|
|
674
|
+
|
|
675
|
+
// Half widths (may be factional)
|
|
676
|
+
var penw2 = penw/2;
|
|
677
|
+
var penh2 = penh/2;
|
|
678
|
+
|
|
679
|
+
if (x0 > x1) { var t = x0; x0 = x1; x1 = t; }
|
|
680
|
+
if (y0 > y1) { var t = y0; y0 = y1; y1 = t; }
|
|
681
|
+
if (x0 == x1) {
|
|
682
|
+
this.bbox(x0-penw2, y0, x0+penw-penw2-1, y1); // vertical line
|
|
683
|
+
} else {
|
|
684
|
+
this.bbox(x0, y0-penh+penh2+1, x1, y1+penh2); // horizontal line
|
|
685
|
+
}
|
|
686
|
+
nlines++;
|
|
687
|
+
} else if (a.op == 'p') {
|
|
688
|
+
// Closed (rectangular) poly (border around the barcode)
|
|
689
|
+
var minx = Infinity;
|
|
690
|
+
var miny = Infinity;
|
|
691
|
+
var maxx = -Infinity;
|
|
692
|
+
var maxy = -Infinity;
|
|
693
|
+
var pts = a.poly;
|
|
694
|
+
if (pts.length != 4) {
|
|
695
|
+
throw new Error('stroke: --not-a-rect--');
|
|
696
|
+
}
|
|
697
|
+
for (var i = 0, j = pts.length-1; i < pts.length; j = i++) {
|
|
698
|
+
var xj = pts[j][0];
|
|
699
|
+
var yj = pts[j][1];
|
|
700
|
+
var xi = pts[i][0];
|
|
701
|
+
var yi = pts[i][1];
|
|
702
|
+
|
|
703
|
+
if (xi != xj && yi != yj) {
|
|
704
|
+
throw new Error('stroke: --not-orthogonal--');
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
if (xi < minx) minx = xi;
|
|
708
|
+
if (xi > maxx) maxx = xi;
|
|
709
|
+
if (yi < miny) miny = yi;
|
|
710
|
+
if (yi > maxy) maxy = yi;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
// Half widths (integer)
|
|
714
|
+
var penw2 = ceil(penw/2);
|
|
715
|
+
var penh2 = ceil(penh/2);
|
|
716
|
+
|
|
717
|
+
// We render these as two polygons plus a fill.
|
|
718
|
+
// When border width is odd, allocate the bigger half to the outside.
|
|
719
|
+
this.bbox(minx-penw2, miny-penh2, maxx+penw2, maxy+penh2);
|
|
720
|
+
npolys++;
|
|
721
|
+
} else {
|
|
722
|
+
throw new Error('stroke: --not-a-line--');
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
// Draw the lines
|
|
727
|
+
var self = this;
|
|
728
|
+
this.cmds.push(function() {
|
|
729
|
+
// Half widths (big half and remaining half)
|
|
730
|
+
var bigw2 = ceil(penw/2);
|
|
731
|
+
var bigh2 = ceil(penh/2);
|
|
732
|
+
var remw2 = penw - bigw2;
|
|
733
|
+
var remh2 = penh - bigh2;
|
|
734
|
+
|
|
735
|
+
for (var i = 0; i < path.length; i++) {
|
|
736
|
+
var a = path[i]
|
|
737
|
+
if (a.op == 'l') {
|
|
738
|
+
var pts = [ [ a.x0, a.y0 ], [ a.x1, a.y1 ] ];
|
|
739
|
+
self.transform(pts);
|
|
740
|
+
self.drawing.line(pts[0][0], pts[0][1], pts[1][0], pts[1][1],
|
|
741
|
+
a.x0 == a.x1 ? penw : penh, rgb);
|
|
742
|
+
self.fill(rgb);
|
|
743
|
+
} else {
|
|
744
|
+
var pts = a.poly;
|
|
745
|
+
self.transform(pts);
|
|
746
|
+
var x0 = min(pts[0][0], pts[2][0]);
|
|
747
|
+
var x1 = max(pts[0][0], pts[2][0]);
|
|
748
|
+
var y0 = min(pts[0][1], pts[2][1]);
|
|
749
|
+
var y1 = max(pts[0][1], pts[2][1]);
|
|
750
|
+
|
|
751
|
+
// Top and left edges are "inside" the polygon.
|
|
752
|
+
// Bottom and right edges are outside.
|
|
753
|
+
self.drawing.polygon([
|
|
754
|
+
[ x0-bigw2, y0-bigh2 ],
|
|
755
|
+
[ x0-bigw2, y1+bigh2+1 ],
|
|
756
|
+
[ x1+bigw2+1, y1+bigh2+1 ],
|
|
757
|
+
[ x1+bigw2+1, y0-bigh2 ]
|
|
758
|
+
]);
|
|
759
|
+
self.drawing.polygon([
|
|
760
|
+
[ x0+remw2, y0+remh2 ],
|
|
761
|
+
[ x0+remw2, y1-remh2+1 ],
|
|
762
|
+
[ x1-remw2+1, y1-remh2+1 ],
|
|
763
|
+
[ x1-remw2+1, y0+remh2 ],
|
|
764
|
+
]);
|
|
765
|
+
self.drawing.fill(rgb);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
});
|
|
769
|
+
};
|
|
770
|
+
BWIPJS.prototype.fill = function() {
|
|
771
|
+
var path = this.g_path;
|
|
772
|
+
var rgb = this.getRGB();
|
|
773
|
+
this.g_path = [];
|
|
774
|
+
|
|
775
|
+
// Calculate the bounding boxes
|
|
776
|
+
for (var p = 0; p < path.length; p++) {
|
|
777
|
+
var a = path[p];
|
|
778
|
+
if (a.op == 'p') { // polygon
|
|
779
|
+
var minx = Infinity;
|
|
780
|
+
var miny = Infinity;
|
|
781
|
+
var maxx = -Infinity;
|
|
782
|
+
var maxy = -Infinity;
|
|
783
|
+
var pts = a.poly;
|
|
784
|
+
for (var i = 0; i < pts.length; i++) {
|
|
785
|
+
var xi = pts[i][0];
|
|
786
|
+
var yi = pts[i][1];
|
|
787
|
+
|
|
788
|
+
if (xi < minx) minx = xi;
|
|
789
|
+
if (xi > maxx) maxx = xi;
|
|
790
|
+
if (yi < miny) miny = yi;
|
|
791
|
+
if (yi > maxy) maxy = yi;
|
|
792
|
+
}
|
|
793
|
+
// With polygons, the right and bottom edges are "outside" and do not
|
|
794
|
+
// contribute to the bounding box. But we are in postscript inverted-y
|
|
795
|
+
// mode.
|
|
796
|
+
this.bbox(minx, miny+1, maxx-1, maxy);
|
|
797
|
+
} else if (a.op == 'e') { // ellipse
|
|
798
|
+
this.bbox(a.x - a.rx, a.y - a.ry, a.x + a.rx, a.y + a.ry);
|
|
799
|
+
} else {
|
|
800
|
+
throw new Error('fill: --not-a-polygon--');
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
// Render the poly
|
|
805
|
+
var self = this;
|
|
806
|
+
this.cmds.push(function() {
|
|
807
|
+
for (var i = 0; i < path.length; i++) {
|
|
808
|
+
var a = path[i];
|
|
809
|
+
if (a.op == 'p') {
|
|
810
|
+
var pts = a.poly
|
|
811
|
+
self.transform(pts);
|
|
812
|
+
self.drawing.polygon(pts);
|
|
813
|
+
} else if (a.op == 'e') {
|
|
814
|
+
var pts = [ [ a.x, a.y ] ];
|
|
815
|
+
self.transform(pts);
|
|
816
|
+
self.drawing.ellipse(pts[0][0], pts[0][1], a.rx, a.ry, a.ccw);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
self.drawing.fill(rgb);
|
|
820
|
+
});
|
|
821
|
+
};
|
|
822
|
+
BWIPJS.prototype.clip = function() {
|
|
823
|
+
var path = this.g_path;
|
|
824
|
+
this.g_path = [];
|
|
825
|
+
this.g_clip = true;
|
|
826
|
+
|
|
827
|
+
var self = this;
|
|
828
|
+
this.cmds.push(function() {
|
|
829
|
+
var polys = [];
|
|
830
|
+
for (var i = 0; i < path.length; i++) {
|
|
831
|
+
var a = path[i];
|
|
832
|
+
if (a.op == 'p') {
|
|
833
|
+
var pts = a.poly
|
|
834
|
+
self.transform(pts);
|
|
835
|
+
polys.push(pts);
|
|
836
|
+
} else {
|
|
837
|
+
throw new Error('clip: only polygon regions supported');
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
self.drawing.clip(polys);
|
|
841
|
+
});
|
|
842
|
+
};
|
|
843
|
+
|
|
844
|
+
// The pix array is in standard (not y-inverted postscript) orientation.
|
|
845
|
+
BWIPJS.prototype.maxicode = function(pix) {
|
|
846
|
+
var tsx = this.g_tsx;
|
|
847
|
+
var tsy = this.g_tsy;
|
|
848
|
+
var rgb = this.getRGB();
|
|
849
|
+
|
|
850
|
+
// Module width. Module height is an integer multiple of tsy.
|
|
851
|
+
var twidth = 1.04 * tsx * 100;
|
|
852
|
+
var mwidth = (twidth / 30)|0;
|
|
853
|
+
if (twidth - (mwidth*30-1) > 9) {
|
|
854
|
+
mwidth++;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
// Dimensions needed for plotting the hexagons. These must be integer values.
|
|
858
|
+
var w, h, wgap, hgap;
|
|
859
|
+
// if (opts.??? ) {
|
|
860
|
+
// // Create a one or two pixel gap
|
|
861
|
+
// wgap = (mwidth & 1) ? 1 : 2;
|
|
862
|
+
// hgap = 1;
|
|
863
|
+
// w = mwidth - gap;
|
|
864
|
+
// h = 4 * tsy;
|
|
865
|
+
// } else {
|
|
866
|
+
// Create a 1/8mm gap
|
|
867
|
+
wgap = (tsx/2)|0;
|
|
868
|
+
hgap = (tsy/2)|0;
|
|
869
|
+
w = mwidth - wgap;
|
|
870
|
+
if (w & 1) {
|
|
871
|
+
w--;
|
|
872
|
+
}
|
|
873
|
+
h = ((4*tsy)|0) - hgap;
|
|
874
|
+
//}
|
|
875
|
+
|
|
876
|
+
// These must be integer values
|
|
877
|
+
var w2 = w / 2 - 1; // half width
|
|
878
|
+
var qh = ((w2+1) / 2)|0; // quarter height
|
|
879
|
+
var vh = h - 2 - 2 * qh; // side height
|
|
880
|
+
|
|
881
|
+
// Bounding box
|
|
882
|
+
this.bbox(0, 0, mwidth*30 - wgap, tsy * 3 * 32 + tsy * 4 - hgap);
|
|
883
|
+
|
|
884
|
+
// Render the elements
|
|
885
|
+
var self = this;
|
|
886
|
+
this.cmds.push(function() {
|
|
887
|
+
// Draw the hexagons
|
|
888
|
+
for (var i = 0; i < pix.length; i++) {
|
|
889
|
+
var c = pix[i];
|
|
890
|
+
var x = c % 30;
|
|
891
|
+
var y = (c / 30)|0;
|
|
892
|
+
|
|
893
|
+
// Adjust x,y to the top of hexagon
|
|
894
|
+
x *= mwidth;
|
|
895
|
+
x += (y & 1) ? mwidth : mwidth/2;
|
|
896
|
+
x = x|0;
|
|
897
|
+
|
|
898
|
+
y = 33 - y; // invert for postscript notation
|
|
899
|
+
y *= tsy * 3;
|
|
900
|
+
y += tsy * 2 - h/2;
|
|
901
|
+
y = y|0;
|
|
902
|
+
|
|
903
|
+
// Build bottom up so the drawing is top-down.
|
|
904
|
+
var pts = [ [ x-0.5, y-- ] ];
|
|
905
|
+
y -= qh-1;
|
|
906
|
+
pts.push([x-1-w2, y--]);
|
|
907
|
+
y -= vh;
|
|
908
|
+
pts.push([x-1-w2, y--]);
|
|
909
|
+
y -= qh-1;
|
|
910
|
+
pts.push([x-0.5, y++]);
|
|
911
|
+
y += qh-1;
|
|
912
|
+
pts.push([x+w2, y++]);
|
|
913
|
+
y += vh;
|
|
914
|
+
pts.push([x+w2, y++]);
|
|
915
|
+
|
|
916
|
+
self.transform(pts);
|
|
917
|
+
self.drawing.hexagon(pts, rgb);
|
|
918
|
+
}
|
|
919
|
+
self.drawing.fill(rgb);
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
// Draw the rings
|
|
923
|
+
var x = (14 * mwidth + mwidth/2 + 0.01)|0;
|
|
924
|
+
var y = ((12 * 4 + 3) * tsy - qh/2 + 0.01)|0;
|
|
925
|
+
self.drawing.ellipse(x, y, (0.5774*3.5*tsx+0.01)|0, (0.5774*3.5*tsy+0.01)|0, true);
|
|
926
|
+
self.drawing.ellipse(x, y, (1.3359*3.5*tsx+0.01)|0, (1.3359*3.5*tsy+0.01)|0, false);
|
|
927
|
+
self.drawing.fill(rgb);
|
|
928
|
+
self.drawing.ellipse(x, y, (2.1058*3.5*tsx+0.01)|0, (2.1058*3.5*tsy+0.01)|0, true);
|
|
929
|
+
self.drawing.ellipse(x, y, (2.8644*3.5*tsx+0.01)|0, (2.8644*3.5*tsy+0.01)|0, false);
|
|
930
|
+
self.drawing.fill(rgb);
|
|
931
|
+
self.drawing.ellipse(x, y, (3.6229*3.5*tsx+0.01)|0, (3.6229*3.5*tsy+0.01)|0, true);
|
|
932
|
+
self.drawing.ellipse(x, y, (4.3814*3.5*tsx+0.01)|0, (4.3814*3.5*tsy+0.01)|0, false);
|
|
933
|
+
self.drawing.fill(rgb);
|
|
934
|
+
|
|
935
|
+
});
|
|
936
|
+
};
|
|
937
|
+
// UTF-8 to UCS-2 (no surrogates)
|
|
938
|
+
BWIPJS.prototype.toUCS2 = function(str) {
|
|
939
|
+
return str.replace(/[\xc0-\xdf][\x80-\xbf]|[\xe0-\xff][\x80-\xbf]{2}/g,
|
|
940
|
+
function(s) {
|
|
941
|
+
var code;
|
|
942
|
+
if (s.length == 2) {
|
|
943
|
+
code = ((s.charCodeAt(0)&0x1f)<<6)|
|
|
944
|
+
(s.charCodeAt(1)&0x3f);
|
|
945
|
+
} else {
|
|
946
|
+
code = ((s.charCodeAt(0)&0x0f)<<12)|
|
|
947
|
+
((s.charCodeAt(1)&0x3f)<<6)|
|
|
948
|
+
(s.charCodeAt(2)&0x3f);
|
|
949
|
+
}
|
|
950
|
+
return String.fromCharCode(code);
|
|
951
|
+
});
|
|
952
|
+
};
|
|
953
|
+
// dx,dy are inter-character gaps
|
|
954
|
+
BWIPJS.prototype.show = function(str, dx, dy) {
|
|
955
|
+
if (!str.length) {
|
|
956
|
+
return;
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
// Capture current graphics state
|
|
960
|
+
var tsx = this.g_tsx;
|
|
961
|
+
var tsy = this.g_tsy;
|
|
962
|
+
var name = this.g_font.FontName || 'OCR-B';
|
|
963
|
+
var size = (this.g_font.FontSize || 10);
|
|
964
|
+
var szx = size * tsx;
|
|
965
|
+
var szy = size * tsy;
|
|
966
|
+
var posx = this.g_posx;
|
|
967
|
+
var posy = this.g_posy;
|
|
968
|
+
var rgb = this.getRGB();
|
|
969
|
+
|
|
970
|
+
// The string can be either a uint8-string or regular string.
|
|
971
|
+
str = this.toUCS2(this.jsstring(str));
|
|
972
|
+
|
|
973
|
+
// Convert dx,dy to device space
|
|
974
|
+
dx = tsx * dx || 0;
|
|
975
|
+
dy = tsy * dy || 0;
|
|
976
|
+
|
|
977
|
+
// Bounding box.
|
|
978
|
+
var base = posy + dy;
|
|
979
|
+
var bbox = this.drawing.measure(str, name, szx, szy);
|
|
980
|
+
var width = bbox.width + (str.length-1) * dx;
|
|
981
|
+
this.bbox(posx, base-bbox.descent+1, posx+width-1, base+bbox.ascent);
|
|
982
|
+
this.g_posx += width;
|
|
983
|
+
|
|
984
|
+
var self = this;
|
|
985
|
+
self.cmds.push(function() {
|
|
986
|
+
// self.transform()
|
|
987
|
+
var x = posx - self.minx;
|
|
988
|
+
var y = self.maxy - posy;
|
|
989
|
+
self.drawing.text(x, y, str, rgb, { name:name, width:szx, height:szy, dx:dx });
|
|
990
|
+
});
|
|
991
|
+
};
|
|
992
|
+
// drawing surface bounding box
|
|
993
|
+
BWIPJS.prototype.bbox = function(x0, y0, x1, y1) {
|
|
994
|
+
if (x0 > x1) { var t = x0; x0 = x1; x1 = t; }
|
|
995
|
+
if (y0 > y1) { var t = y0; y0 = y1; y1 = t; }
|
|
996
|
+
|
|
997
|
+
x0 = floor(x0);
|
|
998
|
+
y0 = floor(y0);
|
|
999
|
+
x1 = ceil(x1);
|
|
1000
|
+
y1 = ceil(y1);
|
|
1001
|
+
|
|
1002
|
+
if (this.minx > x0) this.minx = x0;
|
|
1003
|
+
if (this.maxx < x1) this.maxx = x1;
|
|
1004
|
+
if (this.miny > y0) this.miny = y0;
|
|
1005
|
+
if (this.maxy < y1) this.maxy = y1;
|
|
1006
|
+
};
|
|
1007
|
+
BWIPJS.prototype.render = function() {
|
|
1008
|
+
if (this.minx === Infinity) {
|
|
1009
|
+
// Most likely, `dontdraw` was set in the options
|
|
1010
|
+
return false;
|
|
1011
|
+
}
|
|
1012
|
+
// Draw the image
|
|
1013
|
+
this.drawing.init(this.maxx - this.minx + 1, this.maxy - this.miny + 1,
|
|
1014
|
+
this.g_tsx, this.g_tsy);
|
|
1015
|
+
for (var i = 0, l = this.cmds.length; i < l; i++) {
|
|
1016
|
+
this.cmds[i]();
|
|
1017
|
+
}
|
|
1018
|
+
return this.drawing.end();
|
|
1019
|
+
};
|
|
1020
|
+
|
|
1021
|
+
return BWIPJS;
|
|
1022
|
+
})(); // BWIPJS closure
|
|
1023
|
+
// drawing-builtin.js
|
|
1024
|
+
//
|
|
1025
|
+
// The aliased (except the fonts) graphics used by drawing-canvas.js and
|
|
1026
|
+
// drawing-zlibpng.js
|
|
1027
|
+
//
|
|
1028
|
+
// All x,y and lengths are integer values.
|
|
1029
|
+
//
|
|
1030
|
+
// For the methods that take a color `rgb` parameter, the value is always a
|
|
1031
|
+
// string with format RRGGBB.
|
|
1032
|
+
function DrawingBuiltin() {
|
|
1033
|
+
var floor = Math.floor;
|
|
1034
|
+
|
|
1035
|
+
// Unrolled x,y rotate/translate matrix
|
|
1036
|
+
var tx0 = 0, tx1 = 0, tx2 = 0, tx3 = 0;
|
|
1037
|
+
var ty0 = 0, ty1 = 0, ty2 = 0, ty3 = 0;
|
|
1038
|
+
|
|
1039
|
+
var opts; // see setopts()
|
|
1040
|
+
var gs_image, gs_rowbyte; // rowbyte will be 1 for png's, 0 for canvas
|
|
1041
|
+
var gs_width, gs_height; // image size, in pixels
|
|
1042
|
+
var gs_dx, gs_dy; // x,y translate (padding)
|
|
1043
|
+
var gs_r, gs_g, gs_b; // rgb
|
|
1044
|
+
var gs_xymap; // edge map
|
|
1045
|
+
var gs_xyclip; // clip region map (similar to xymap)
|
|
1046
|
+
|
|
1047
|
+
return {
|
|
1048
|
+
// setopts() is called after the options are fixed-up/normalized,
|
|
1049
|
+
// but before calling into BWIPP.
|
|
1050
|
+
// This method allows omitting the options in the constructor call.
|
|
1051
|
+
// The method is optional.
|
|
1052
|
+
setopts(options) {
|
|
1053
|
+
opts = options;
|
|
1054
|
+
},
|
|
1055
|
+
|
|
1056
|
+
// Ensure compliant bar codes by always using integer scaling factors.
|
|
1057
|
+
scale : function(sx, sy) {
|
|
1058
|
+
// swissqrcode requires clipping and drawing that are not scaled to the
|
|
1059
|
+
// the barcode module size.
|
|
1060
|
+
if (opts.bcid == 'swissqrcode') {
|
|
1061
|
+
return [ sx, sy ];
|
|
1062
|
+
} else {
|
|
1063
|
+
return [ (sx|0)||1, (sy|0)||1 ];
|
|
1064
|
+
}
|
|
1065
|
+
},
|
|
1066
|
+
|
|
1067
|
+
// Measure text. This and scale() are the only drawing primitives that
|
|
1068
|
+
// are called before init().
|
|
1069
|
+
//
|
|
1070
|
+
// `font` is the font name typically OCR-A or OCR-B.
|
|
1071
|
+
// `fwidth` and `fheight` are the requested font cell size. They will
|
|
1072
|
+
// usually be the same, except when the scaling is not symetric.
|
|
1073
|
+
measure : function(str, font, fwidth, fheight) {
|
|
1074
|
+
fwidth = fwidth|0;
|
|
1075
|
+
fheight = fheight|0;
|
|
1076
|
+
|
|
1077
|
+
var fontid = FontLib.lookup(font);
|
|
1078
|
+
var width = 0;
|
|
1079
|
+
var ascent = 0;
|
|
1080
|
+
var descent = 0;
|
|
1081
|
+
for (var i = 0, l = str.length; i < l; i++) {
|
|
1082
|
+
var ch = str.charCodeAt(i);
|
|
1083
|
+
var glyph = FontLib.getglyph(fontid, ch, fwidth, fheight);
|
|
1084
|
+
|
|
1085
|
+
ascent = Math.max(ascent, glyph.top);
|
|
1086
|
+
descent = Math.max(descent, glyph.height - glyph.top);
|
|
1087
|
+
|
|
1088
|
+
if (i == l-1) {
|
|
1089
|
+
width += glyph.left + glyph.width;
|
|
1090
|
+
} else {
|
|
1091
|
+
width += glyph.advance;
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
return { width:width, ascent:ascent, descent:descent };
|
|
1095
|
+
},
|
|
1096
|
+
|
|
1097
|
+
// width and height represent the maximum bounding box the graphics will occupy.
|
|
1098
|
+
// The dimensions are for an unrotated rendering. Adjust as necessary.
|
|
1099
|
+
init : function(width, height) {
|
|
1100
|
+
// Add in the effects of padding. These are always set before the
|
|
1101
|
+
// drawing constructor is called.
|
|
1102
|
+
var padl = opts.paddingleft;
|
|
1103
|
+
var padr = opts.paddingright;
|
|
1104
|
+
var padt = opts.paddingtop;
|
|
1105
|
+
var padb = opts.paddingbottom;
|
|
1106
|
+
var rot = opts.rotate || 'N';
|
|
1107
|
+
|
|
1108
|
+
width += padl + padr;
|
|
1109
|
+
height += padt + padb;
|
|
1110
|
+
|
|
1111
|
+
if (+opts.sizelimit && +opts.sizelimit < width * height) {
|
|
1112
|
+
throw new Error('Image size over limit');
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
// Transform indexes are: x, y, w, h
|
|
1116
|
+
switch (rot) {
|
|
1117
|
+
// tx = w-y, ty = x
|
|
1118
|
+
case 'R': tx1 = -1; tx2 = 1; ty0 = 1; break;
|
|
1119
|
+
// tx = w-x, ty = h-y
|
|
1120
|
+
case 'I': tx0 = -1; tx2 = 1; ty1 = -1; ty3 = 1; break;
|
|
1121
|
+
// tx = y, ty = h-x
|
|
1122
|
+
case 'L': tx1 = 1; ty0 = -1; ty3 = 1; break;
|
|
1123
|
+
// tx = x, ty = y
|
|
1124
|
+
default: tx0 = ty1 = 1; break;
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
// Setup the graphics state
|
|
1128
|
+
var swap = rot == 'L' || rot == 'R';
|
|
1129
|
+
gs_width = swap ? height : width;
|
|
1130
|
+
gs_height = swap ? width : height;
|
|
1131
|
+
gs_dx = padl;
|
|
1132
|
+
gs_dy = padt;
|
|
1133
|
+
gs_xymap = [];
|
|
1134
|
+
gs_xymap.min = Infinity;
|
|
1135
|
+
gs_xyclip = null;
|
|
1136
|
+
gs_r = gs_g = gs_b = 0;
|
|
1137
|
+
|
|
1138
|
+
// Get the rgba image from the constructor
|
|
1139
|
+
var res = this.image(gs_width, gs_height);
|
|
1140
|
+
gs_image = res.buffer;
|
|
1141
|
+
gs_rowbyte = res.ispng ? 1 : 0;
|
|
1142
|
+
},
|
|
1143
|
+
// Unconnected stroked lines are used to draw the bars in linear barcodes;
|
|
1144
|
+
// and the border around a linear barcode (e.g. ITF-14)
|
|
1145
|
+
// No line cap should be applied. These lines are always orthogonal.
|
|
1146
|
+
line : function(x0, y0, x1, y1, lw, rgb) {
|
|
1147
|
+
x0 = x0|0;
|
|
1148
|
+
y0 = y0|0;
|
|
1149
|
+
x1 = x1|0;
|
|
1150
|
+
y1 = y1|0;
|
|
1151
|
+
|
|
1152
|
+
// Most linear barcodes, the line width will be integral. The exceptions
|
|
1153
|
+
// are variable width barcodes (e.g. code39) and the postal 4-state codes.
|
|
1154
|
+
lw = Math.round(lw) || 1;
|
|
1155
|
+
|
|
1156
|
+
if (y1 < y0) { var t = y0; y0 = y1; y1 = t; }
|
|
1157
|
+
if (x1 < x0) { var t = x0; x0 = x1; x1 = t; }
|
|
1158
|
+
|
|
1159
|
+
gs_r = parseInt(rgb.substr(0,2), 16);
|
|
1160
|
+
gs_g = parseInt(rgb.substr(2,2), 16);
|
|
1161
|
+
gs_b = parseInt(rgb.substr(4,2), 16);
|
|
1162
|
+
|
|
1163
|
+
// Horizontal or vertical line?
|
|
1164
|
+
var w2 = (lw/2)|0;
|
|
1165
|
+
if (x0 == x1) {
|
|
1166
|
+
// Vertical line
|
|
1167
|
+
x0 = x0 - lw + w2; // big half
|
|
1168
|
+
x1 = x1 + w2 - 1; // small half
|
|
1169
|
+
} else {
|
|
1170
|
+
// Horizontal line (inverted halves)
|
|
1171
|
+
y0 = y0 - w2;
|
|
1172
|
+
y1 = y1 + lw - w2 - 1;
|
|
1173
|
+
}
|
|
1174
|
+
for (var y = y0; y <= y1; y++) {
|
|
1175
|
+
for (var x = x0; x <= x1; x++) {
|
|
1176
|
+
set(x, y, 255);
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
},
|
|
1180
|
+
|
|
1181
|
+
// Polygons are used to draw the connected regions in a 2d barcode.
|
|
1182
|
+
// These will always be unstroked, filled, orthogonal shapes.
|
|
1183
|
+
//
|
|
1184
|
+
// You will see a series of polygon() calls, followed by a fill().
|
|
1185
|
+
polygon : function(pts) {
|
|
1186
|
+
var npts = pts.length;
|
|
1187
|
+
for (var j = npts-1, i = 0; i < npts; j = i++) {
|
|
1188
|
+
if (pts[j][0] == pts[i][0]) {
|
|
1189
|
+
// Vertical lines do not get their end points. End points
|
|
1190
|
+
// are added by the horizontal line logic.
|
|
1191
|
+
var xj = pts[j][0]|0; // i or j, doesn't matter
|
|
1192
|
+
var yj = pts[j][1]|0;
|
|
1193
|
+
var yi = pts[i][1]|0;
|
|
1194
|
+
if (yj > yi) {
|
|
1195
|
+
for (var y = yi+1; y < yj; y++) {
|
|
1196
|
+
addPoint(xj, y);
|
|
1197
|
+
}
|
|
1198
|
+
} else {
|
|
1199
|
+
for (var y = yj+1; y < yi; y++) {
|
|
1200
|
+
addPoint(xj, y);
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
} else {
|
|
1204
|
+
var xj = pts[j][0]|0;
|
|
1205
|
+
var xi = pts[i][0]|0;
|
|
1206
|
+
var yj = pts[j][1]|0; // i or j, doesn't matter
|
|
1207
|
+
|
|
1208
|
+
// Horizontal lines are tricky. As a rule, top lines get filled,
|
|
1209
|
+
// bottom lines do not (similar to how left edges get filled and
|
|
1210
|
+
// right edges do not).
|
|
1211
|
+
//
|
|
1212
|
+
// Where it gets complex is deciding whether the line actually
|
|
1213
|
+
// adds edges. There are cases where a horizontal line does
|
|
1214
|
+
// not add anything to the scanline plotting. And it doesn't
|
|
1215
|
+
// actually matter whether the line is a top or bottom edge,
|
|
1216
|
+
// the logic is the same.
|
|
1217
|
+
//
|
|
1218
|
+
// A left edge is added if the edge to its left is below.
|
|
1219
|
+
// A right edge is added if the edge to its right is below.
|
|
1220
|
+
if (xj < xi) {
|
|
1221
|
+
var yl = pts[j == 0 ? npts-1 : j-1][1]; // left edge
|
|
1222
|
+
var yr = pts[i == npts-1 ? 0 : i+1][1]; // right edge
|
|
1223
|
+
if (yl > yj) {
|
|
1224
|
+
addPoint(xj, yj);
|
|
1225
|
+
}
|
|
1226
|
+
if (yr > yj) {
|
|
1227
|
+
addPoint(xi, yj);
|
|
1228
|
+
}
|
|
1229
|
+
} else {
|
|
1230
|
+
var yl = pts[i == npts-1 ? 0 : i+1][1]; // left edge
|
|
1231
|
+
var yr = pts[j == 0 ? npts-1 : j-1][1]; // right edge
|
|
1232
|
+
if (yl > yj) {
|
|
1233
|
+
addPoint(xi, yj);
|
|
1234
|
+
}
|
|
1235
|
+
if (yr > yj) {
|
|
1236
|
+
addPoint(xj, yj);
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
},
|
|
1242
|
+
// An unstroked, filled hexagon used by maxicode. You can choose to fill
|
|
1243
|
+
// each individually, or wait for the final fill().
|
|
1244
|
+
//
|
|
1245
|
+
// The hexagon is drawn from the top, counter-clockwise.
|
|
1246
|
+
//
|
|
1247
|
+
// The X-coordinate for the top and bottom points on the hexagon is always
|
|
1248
|
+
// .5 pixels. We draw our hexagons with a 2 pixel flat top.
|
|
1249
|
+
//
|
|
1250
|
+
// All other points of the polygon/hexagon are guaranteed to be integer values.
|
|
1251
|
+
hexagon : function(pts, rgb) {
|
|
1252
|
+
var x = pts[0][0]|0;
|
|
1253
|
+
var y = pts[0][1]|0;
|
|
1254
|
+
var qh = (pts[1][1] - pts[0][1])|0; // height of triangle (quarter height)
|
|
1255
|
+
var vh = (pts[2][1] - pts[1][1] - 1)|0; // height of vertical side
|
|
1256
|
+
var xl = (pts[2][0])|0; // left side
|
|
1257
|
+
var xr = (pts[4][0])|0; // right side
|
|
1258
|
+
|
|
1259
|
+
gs_r = parseInt(rgb.substr(0,2), 16);
|
|
1260
|
+
gs_g = parseInt(rgb.substr(2,2), 16);
|
|
1261
|
+
gs_b = parseInt(rgb.substr(4,2), 16);
|
|
1262
|
+
|
|
1263
|
+
fillSegment(x, x+1, y++);
|
|
1264
|
+
for (var k = 1; k < qh; k++) {
|
|
1265
|
+
fillSegment(x-2*k, x+1+2*k, y++);
|
|
1266
|
+
}
|
|
1267
|
+
for (var k = 0; k <= vh; k++) {
|
|
1268
|
+
fillSegment(xl, xr, y++);
|
|
1269
|
+
}
|
|
1270
|
+
for (var k = qh-1; k >= 1; k--) {
|
|
1271
|
+
fillSegment(x-2*k, x+1+2*k, y++);
|
|
1272
|
+
}
|
|
1273
|
+
fillSegment(x, x+1, y);
|
|
1274
|
+
},
|
|
1275
|
+
// An unstroked, filled ellipse. Used by dotcode and maxicode at present.
|
|
1276
|
+
// maxicode issues pairs of ellipse calls (one cw, one ccw) followed by a fill()
|
|
1277
|
+
// to create the bullseye rings. dotcode issues all of its ellipses then a
|
|
1278
|
+
// fill().
|
|
1279
|
+
ellipse : function(x, y, rx, ry, ccw) {
|
|
1280
|
+
drawEllipse((x-rx)|0, (y-ry)|0, (x+rx)|0, (y+ry)|0, ccw);
|
|
1281
|
+
},
|
|
1282
|
+
// PostScript's default fill rule is non-zero but since there are never
|
|
1283
|
+
// intersecting regions, we use the easier to implement even-odd.
|
|
1284
|
+
fill : function(rgb) {
|
|
1285
|
+
gs_r = parseInt(rgb.substr(0,2), 16);
|
|
1286
|
+
gs_g = parseInt(rgb.substr(2,2), 16);
|
|
1287
|
+
gs_b = parseInt(rgb.substr(4,2), 16);
|
|
1288
|
+
|
|
1289
|
+
evenodd();
|
|
1290
|
+
gs_xymap = [];
|
|
1291
|
+
gs_xymap.min = Infinity;
|
|
1292
|
+
},
|
|
1293
|
+
// Currently only used by swissqrcode. The `polys` area is an array of
|
|
1294
|
+
// arrays of points. Each array of points is identical to the `pts`
|
|
1295
|
+
// parameter passed to polygon(). The postscript default clipping rule,
|
|
1296
|
+
// like the fill rule, is even-odd winding.
|
|
1297
|
+
clip : function(polys) {
|
|
1298
|
+
if (!gs_xyclip) {
|
|
1299
|
+
gs_xyclip = [];
|
|
1300
|
+
gs_xyclip.min = Infinity;
|
|
1301
|
+
}
|
|
1302
|
+
// Swap out the xymap for the clip map so addPoint() works on it.
|
|
1303
|
+
var xymap = gs_xymap;
|
|
1304
|
+
gs_xymap = gs_xyclip;
|
|
1305
|
+
|
|
1306
|
+
// Now just use the polygon() logic to fill in the clipping regions.
|
|
1307
|
+
for (var i = 0, l = polys.length; i < l; i++) {
|
|
1308
|
+
this.polygon(polys[i]);
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
// Restore
|
|
1312
|
+
gs_xymap = xymap;
|
|
1313
|
+
},
|
|
1314
|
+
unclip : function() {
|
|
1315
|
+
gs_xyclip = null;
|
|
1316
|
+
},
|
|
1317
|
+
// Draw text with optional inter-character spacing. `y` is the baseline.
|
|
1318
|
+
// font is an object with properties { name, width, height, dx }
|
|
1319
|
+
// width and height are the font cell size.
|
|
1320
|
+
// dx is extra space requested between characters (usually zero).
|
|
1321
|
+
text : function(x, y, str, rgb, font) {
|
|
1322
|
+
x = x|0;
|
|
1323
|
+
y = y|0;
|
|
1324
|
+
|
|
1325
|
+
gs_r = parseInt(rgb.substr(0,2), 16);
|
|
1326
|
+
gs_g = parseInt(rgb.substr(2,2), 16);
|
|
1327
|
+
gs_b = parseInt(rgb.substr(4,2), 16);
|
|
1328
|
+
|
|
1329
|
+
var fontid = FontLib.lookup(font.name);
|
|
1330
|
+
var fwidth = font.width|0;
|
|
1331
|
+
var fheight = font.height|0;
|
|
1332
|
+
var dx = font.dx|0;
|
|
1333
|
+
for (var k = 0; k < str.length; k++) {
|
|
1334
|
+
var ch = str.charCodeAt(k);
|
|
1335
|
+
var glyph = FontLib.getglyph(fontid, ch, fwidth, fheight);
|
|
1336
|
+
|
|
1337
|
+
var gt = y - glyph.top;
|
|
1338
|
+
var gl = glyph.left;
|
|
1339
|
+
var gw = glyph.width;
|
|
1340
|
+
var gh = glyph.height;
|
|
1341
|
+
var gb = glyph.bytes;
|
|
1342
|
+
var go = glyph.offset; // offset into bytes
|
|
1343
|
+
|
|
1344
|
+
for (var i = 0; i < gw; i++) {
|
|
1345
|
+
for (var j = 0; j < gh; j++) {
|
|
1346
|
+
var a = gb[go + j * gw + i];
|
|
1347
|
+
if (a) {
|
|
1348
|
+
set(x+gl+i, gt+j, a);
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
x += glyph.advance + dx;
|
|
1353
|
+
}
|
|
1354
|
+
},
|
|
1355
|
+
// Called after all drawing is complete.
|
|
1356
|
+
end : function() {
|
|
1357
|
+
},
|
|
1358
|
+
};
|
|
1359
|
+
|
|
1360
|
+
// This code is specialized to deal with two types of RGBA buffers:
|
|
1361
|
+
// - canvas style, which is true RGBA
|
|
1362
|
+
// - PNG style, which has a one-byte "filter code" prefixing each row.
|
|
1363
|
+
function set(x, y, a) {
|
|
1364
|
+
if (gs_xyclip && clipped(x, y)) {
|
|
1365
|
+
return;
|
|
1366
|
+
}
|
|
1367
|
+
// translate/rotate
|
|
1368
|
+
x += gs_dx;
|
|
1369
|
+
y += gs_dy;
|
|
1370
|
+
var tx = tx0 * x + tx1 * y + tx2 * (gs_width-1) + tx3 * (gs_height-1);
|
|
1371
|
+
var ty = ty0 * x + ty1 * y + ty2 * (gs_width-1) + ty3 * (gs_height-1);
|
|
1372
|
+
|
|
1373
|
+
// https://en.wikipedia.org/wiki/Alpha_compositing
|
|
1374
|
+
var offs = (ty * gs_width + tx) * 4 + (ty+1) * gs_rowbyte;
|
|
1375
|
+
var dsta = gs_image[offs+3] / 255;
|
|
1376
|
+
var srca = a / 255;
|
|
1377
|
+
var inva = (1 - srca) * dsta;
|
|
1378
|
+
var outa = srca + inva;
|
|
1379
|
+
|
|
1380
|
+
gs_image[offs+0] = ((gs_r * srca + gs_image[offs+0] * inva) / outa)|0;
|
|
1381
|
+
gs_image[offs+1] = ((gs_g * srca + gs_image[offs+1] * inva) / outa)|0;
|
|
1382
|
+
gs_image[offs+2] = ((gs_b * srca + gs_image[offs+2] * inva) / outa)|0;
|
|
1383
|
+
gs_image[offs+3] = (255 * outa)|0;
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
// Add a point on an edge to the scanline map.
|
|
1387
|
+
function addPoint(x, y) {
|
|
1388
|
+
if (gs_xymap.min > y) gs_xymap.min = y;
|
|
1389
|
+
if (!gs_xymap[y]) {
|
|
1390
|
+
gs_xymap[y] = [ x ];
|
|
1391
|
+
} else {
|
|
1392
|
+
gs_xymap[y].push(x);
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
function fillSegment(x0, x1, y) {
|
|
1397
|
+
while (x0 <= x1) {
|
|
1398
|
+
set(x0++, y, 255);
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
// even-odd fill
|
|
1403
|
+
//
|
|
1404
|
+
// This implementation is optimized for BWIPP's simple usage.
|
|
1405
|
+
// It is not a general purpose scanline fill. It relies heavily on
|
|
1406
|
+
// polygon() creating the correct intersections.
|
|
1407
|
+
function evenodd() {
|
|
1408
|
+
var ymin = gs_xymap.min;
|
|
1409
|
+
var ymax = gs_xymap.length-1;
|
|
1410
|
+
|
|
1411
|
+
for (var y = ymin; y <= ymax; y++) {
|
|
1412
|
+
var pts = gs_xymap[y];
|
|
1413
|
+
if (!pts) {
|
|
1414
|
+
continue
|
|
1415
|
+
}
|
|
1416
|
+
pts.sort(function(a, b) { return a - b; });
|
|
1417
|
+
|
|
1418
|
+
var wn = false;
|
|
1419
|
+
var xl = 0;
|
|
1420
|
+
for (var n = 0, npts = pts.length; n < npts; n++) {
|
|
1421
|
+
var x = pts[n];
|
|
1422
|
+
if (wn) {
|
|
1423
|
+
fillSegment(xl, x-1, y);
|
|
1424
|
+
} else {
|
|
1425
|
+
xl = x;
|
|
1426
|
+
}
|
|
1427
|
+
wn = !wn;
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
function drawEllipse(x0, y0, x1, y1, dir) {
|
|
1433
|
+
x0 = x0|0;
|
|
1434
|
+
y0 = y0|0;
|
|
1435
|
+
x1 = x1|0;
|
|
1436
|
+
y1 = y1|0;
|
|
1437
|
+
|
|
1438
|
+
var a = Math.abs(x1-x0);
|
|
1439
|
+
var b = Math.abs(y1-y0);
|
|
1440
|
+
var b1 = b & 1;
|
|
1441
|
+
var dx = 4*(1-a)*b*b;
|
|
1442
|
+
var dy = 4*(b1+1)*a*a;
|
|
1443
|
+
var err = dx + dy + b1*a*a;
|
|
1444
|
+
var e2;
|
|
1445
|
+
|
|
1446
|
+
// Left and right edges
|
|
1447
|
+
var left = [], right = [];
|
|
1448
|
+
left.min = right.min = Infinity;
|
|
1449
|
+
|
|
1450
|
+
if (x0 > x1) { x0 = x1; x1 += a; }
|
|
1451
|
+
if (y0 > y1) y0 = y1;
|
|
1452
|
+
y0 += ((b+1)/2)|0;
|
|
1453
|
+
y1 = y0 - b1;
|
|
1454
|
+
a *= 8*a; b1 = 8*b*b;
|
|
1455
|
+
|
|
1456
|
+
do {
|
|
1457
|
+
maxedge(right, x1, y0); // 1st quadrant
|
|
1458
|
+
minedge(left, x0, y0); // 2nd quadrant
|
|
1459
|
+
minedge(left, x0, y1); // 3rd quadrant
|
|
1460
|
+
maxedge(right, x1, y1); // 4th quadrant
|
|
1461
|
+
e2 = 2*err;
|
|
1462
|
+
if (e2 >= dx) { x0++; x1--; dx += b1; err += dx; }
|
|
1463
|
+
if (e2 <= dy) { y0++; y1--; dy += a; err += dy; }
|
|
1464
|
+
} while (x0 <= x1);
|
|
1465
|
+
|
|
1466
|
+
while (y0-y1 < b) { // too early stop of flat ellipse
|
|
1467
|
+
maxedge(right, x1+1, y0);
|
|
1468
|
+
minedge(left, x0-1, y0++);
|
|
1469
|
+
minedge(left, x0-1, y1);
|
|
1470
|
+
maxedge(right, x1+1, y1--);
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
for (var y = left.min, max = left.length-1; y <= max; y++) {
|
|
1474
|
+
addPoint(left[y], y);
|
|
1475
|
+
}
|
|
1476
|
+
// The points we calculated are "inside". The fill algorithm excludes
|
|
1477
|
+
// right edges, so +1 on each x.
|
|
1478
|
+
for (var y = right.min, max = right.length-1; y <= max; y++) {
|
|
1479
|
+
addPoint(right[y]+1, y);
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
function minedge(e, x, y) {
|
|
1483
|
+
if (e.min > y) e.min = y;
|
|
1484
|
+
var ey = e[y];
|
|
1485
|
+
if (ey == null || ey > x) {
|
|
1486
|
+
e[y] = x;
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
function maxedge(e, x, y) {
|
|
1491
|
+
if (e.min > y) e.min = y;
|
|
1492
|
+
var ey = e[y];
|
|
1493
|
+
if (ey == null || ey < x) {
|
|
1494
|
+
e[y] = x;
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
// Returns true if outside the clipping region.
|
|
1500
|
+
function clipped(x, y) {
|
|
1501
|
+
var pts = gs_xyclip[y];
|
|
1502
|
+
if (!pts) {
|
|
1503
|
+
return true;
|
|
1504
|
+
}
|
|
1505
|
+
if (!pts.sorted) {
|
|
1506
|
+
pts.sort(function(a, b) { return a - b; });
|
|
1507
|
+
pts.sorted = true;
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
var wn = false;
|
|
1511
|
+
for (var n = 0, npts = pts.length; n < npts; n++) {
|
|
1512
|
+
var xn = pts[n];
|
|
1513
|
+
if (xn > x) {
|
|
1514
|
+
return !wn;
|
|
1515
|
+
} else if (xn == x) {
|
|
1516
|
+
return wn;
|
|
1517
|
+
}
|
|
1518
|
+
wn = !wn;
|
|
1519
|
+
}
|
|
1520
|
+
return true;
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
// Returns 1 if clockwise, -1 if ccw.
|
|
1524
|
+
function polydir(pts) {
|
|
1525
|
+
var xp = 0;
|
|
1526
|
+
for (var i = 0, l = pts.length, j = l-1; i < l; j = i++) {
|
|
1527
|
+
xp += pts[j][0] * pts[i][1] - pts[i][0] * pts[j][1];
|
|
1528
|
+
}
|
|
1529
|
+
return xp > 0 ? 1 : -1;
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
// drawing-canvas.js
|
|
1533
|
+
//
|
|
1534
|
+
// `maybe` maybe the canvas, pre v4.0.
|
|
1535
|
+
function DrawingCanvas(canvas, maybe) {
|
|
1536
|
+
// Pre setops() backward compatibility
|
|
1537
|
+
if (maybe && maybe instanceof HTMLCanvasElement) {
|
|
1538
|
+
canvas = maybe;
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
var img;
|
|
1542
|
+
var ctx = canvas.getContext('2d', { willReadFrequently:true });
|
|
1543
|
+
var drawing = DrawingBuiltin();
|
|
1544
|
+
|
|
1545
|
+
// Provide our specializations for the builtin drawing
|
|
1546
|
+
drawing.image = image;
|
|
1547
|
+
drawing.end = end;
|
|
1548
|
+
|
|
1549
|
+
// Reflect setopts() into the super
|
|
1550
|
+
var opts;
|
|
1551
|
+
var _setopts = drawing.setopts;
|
|
1552
|
+
drawing.setopts = function (options) {
|
|
1553
|
+
opts = options;
|
|
1554
|
+
_setopts && _setopts.call(drawing, options);
|
|
1555
|
+
};
|
|
1556
|
+
|
|
1557
|
+
return drawing;
|
|
1558
|
+
|
|
1559
|
+
|
|
1560
|
+
// Called by DrawingBuiltin.init() to get the ARGB bitmap for rendering.
|
|
1561
|
+
function image(width, height) {
|
|
1562
|
+
canvas.width = width;
|
|
1563
|
+
canvas.height = height;
|
|
1564
|
+
|
|
1565
|
+
// Set background
|
|
1566
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
1567
|
+
if (/^[0-9a-fA-F]{6}$/.test(''+opts.backgroundcolor)) {
|
|
1568
|
+
ctx.fillStyle = '#' + opts.backgroundcolor;
|
|
1569
|
+
ctx.fillRect(0, 0, width, height);
|
|
1570
|
+
} else {
|
|
1571
|
+
ctx.clearRect(0, 0, width, height);
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
// Prepare the bitmap
|
|
1575
|
+
img = ctx.getImageData(0, 0, width, height);
|
|
1576
|
+
|
|
1577
|
+
// The return value is designed for both canvas pure-RGBA and PNG RGBA
|
|
1578
|
+
return { buffer:img.data, ispng:false };
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
function end() {
|
|
1582
|
+
ctx.putImageData(img, 0, 0);
|
|
1583
|
+
return canvas;
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
// drawing-svg.js
|
|
1587
|
+
//
|
|
1588
|
+
// Converts the drawing primitives into the equivalent SVG. Linear barcodes
|
|
1589
|
+
// are rendered as a series of stroked paths. 2D barcodes are rendered as a
|
|
1590
|
+
// series of filled paths.
|
|
1591
|
+
//
|
|
1592
|
+
// Rotation is handled during drawing. The resulting SVG will contain the
|
|
1593
|
+
// already-rotated barcode without an SVG transform.
|
|
1594
|
+
//
|
|
1595
|
+
// If the requested barcode image contains text, the glyph paths are
|
|
1596
|
+
// extracted from the font file (via the builtin FontLib and stb_truetype.js)
|
|
1597
|
+
// and added as filled SVG paths.
|
|
1598
|
+
//
|
|
1599
|
+
function DrawingSVG() {
|
|
1600
|
+
// Unrolled x,y rotate/translate matrix
|
|
1601
|
+
var tx0 = 0, tx1 = 0, tx2 = 0, tx3 = 0;
|
|
1602
|
+
var ty0 = 0, ty1 = 0, ty2 = 0, ty3 = 0;
|
|
1603
|
+
|
|
1604
|
+
var opts;
|
|
1605
|
+
var svg = '';
|
|
1606
|
+
var path;
|
|
1607
|
+
var clipid = '';
|
|
1608
|
+
var clips = [];
|
|
1609
|
+
var lines = {};
|
|
1610
|
+
|
|
1611
|
+
// We adjust the drawing coordinates by 0.5px when stroke width is odd.
|
|
1612
|
+
// But this creates an odd effect with scale. When scale is even, we
|
|
1613
|
+
// need to add 0.5; when scale is odd, subtract 0.5.
|
|
1614
|
+
var scalex, scaley;
|
|
1615
|
+
|
|
1616
|
+
// Magic number to approximate an ellipse/circle using 4 cubic beziers.
|
|
1617
|
+
var ELLIPSE_MAGIC = 0.55228475 - 0.00045;
|
|
1618
|
+
|
|
1619
|
+
// Global graphics state
|
|
1620
|
+
var gs_width, gs_height; // image size, in pixels
|
|
1621
|
+
var gs_dx, gs_dy; // x,y translate (padding)
|
|
1622
|
+
|
|
1623
|
+
return {
|
|
1624
|
+
// setopts() is called after the options are fixed-up/normalized,
|
|
1625
|
+
// but before calling into BWIPP.
|
|
1626
|
+
// This allows omitting the options in the constructor call.
|
|
1627
|
+
// It is also your last chance to amend the options before usage.
|
|
1628
|
+
setopts(options) {
|
|
1629
|
+
opts = options;
|
|
1630
|
+
},
|
|
1631
|
+
|
|
1632
|
+
// measure() and scale() are the only drawing primitives that are called before init().
|
|
1633
|
+
|
|
1634
|
+
// Make no adjustments
|
|
1635
|
+
scale(sx, sy) {
|
|
1636
|
+
scalex = sx;
|
|
1637
|
+
scaley = sy;
|
|
1638
|
+
},
|
|
1639
|
+
// Measure text.
|
|
1640
|
+
// `font` is the font name typically OCR-A or OCR-B.
|
|
1641
|
+
// `fwidth` and `fheight` are the requested font cell size. They will
|
|
1642
|
+
// usually be the same, except when the scaling is not symetric.
|
|
1643
|
+
measure(str, font, fwidth, fheight) {
|
|
1644
|
+
fwidth = fwidth|0;
|
|
1645
|
+
fheight = fheight|0;
|
|
1646
|
+
|
|
1647
|
+
var fontid = FontLib.lookup(font);
|
|
1648
|
+
var width = 0;
|
|
1649
|
+
var ascent = 0;
|
|
1650
|
+
var descent = 0;
|
|
1651
|
+
for (var i = 0, l = str.length; i < l; i++) {
|
|
1652
|
+
var ch = str.charCodeAt(i);
|
|
1653
|
+
var glyph = FontLib.getglyph(fontid, ch, fwidth, fheight);
|
|
1654
|
+
if (!glyph) {
|
|
1655
|
+
continue;
|
|
1656
|
+
}
|
|
1657
|
+
ascent = Math.max(ascent, glyph.top);
|
|
1658
|
+
descent = Math.max(descent, glyph.height - glyph.top);
|
|
1659
|
+
if (i == l-1) {
|
|
1660
|
+
width += glyph.left + glyph.width;
|
|
1661
|
+
} else {
|
|
1662
|
+
width += glyph.advance;
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
return { width, ascent, descent };
|
|
1666
|
+
},
|
|
1667
|
+
|
|
1668
|
+
// `width` and `height` represent the maximum bounding box the graphics will
|
|
1669
|
+
// occupy. The dimensions are for an unrotated rendering. Adjust as necessary.
|
|
1670
|
+
init(width, height) {
|
|
1671
|
+
// Add in the effects of padding. These are always set before the
|
|
1672
|
+
// drawing constructor is called.
|
|
1673
|
+
var padl = opts.paddingleft;
|
|
1674
|
+
var padr = opts.paddingright;
|
|
1675
|
+
var padt = opts.paddingtop;
|
|
1676
|
+
var padb = opts.paddingbottom;
|
|
1677
|
+
var rot = opts.rotate || 'N';
|
|
1678
|
+
|
|
1679
|
+
width += padl + padr;
|
|
1680
|
+
height += padt + padb;
|
|
1681
|
+
|
|
1682
|
+
// Transform indexes are: x, y, w, h
|
|
1683
|
+
switch (rot) {
|
|
1684
|
+
// tx = w-y, ty = x
|
|
1685
|
+
case 'R': tx1 = -1; tx2 = 1; ty0 = 1; break;
|
|
1686
|
+
// tx = w-x, ty = h-y
|
|
1687
|
+
case 'I': tx0 = -1; tx2 = 1; ty1 = -1; ty3 = 1; break;
|
|
1688
|
+
// tx = y, ty = h-x
|
|
1689
|
+
case 'L': tx1 = 1; ty0 = -1; ty3 = 1; break;
|
|
1690
|
+
// tx = x, ty = y
|
|
1691
|
+
default: tx0 = ty1 = 1; break;
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
// Setup the graphics state
|
|
1695
|
+
var swap = rot == 'L' || rot == 'R';
|
|
1696
|
+
gs_width = swap ? height : width;
|
|
1697
|
+
gs_height = swap ? width : height;
|
|
1698
|
+
gs_dx = padl;
|
|
1699
|
+
gs_dy = padt;
|
|
1700
|
+
},
|
|
1701
|
+
// Unconnected stroked lines are used to draw the bars in linear barcodes.
|
|
1702
|
+
// No line cap should be applied. These lines are always orthogonal.
|
|
1703
|
+
line(x0, y0, x1, y1, lw, rgb) {
|
|
1704
|
+
x0 = x0|0;
|
|
1705
|
+
y0 = y0|0;
|
|
1706
|
+
x1 = x1|0;
|
|
1707
|
+
y1 = y1|0;
|
|
1708
|
+
lw = Math.round(lw) || 1;
|
|
1709
|
+
|
|
1710
|
+
// Try to keep the lines "crisp" by using with the SVG line drawing spec to
|
|
1711
|
+
// our advantage and adjust the coordinates by half pixel when stroke width
|
|
1712
|
+
// is odd. Work around an odd effect with scale. When scale is even, we
|
|
1713
|
+
// need to add 0.5; when scale is odd, subtract 0.5.
|
|
1714
|
+
if (lw & 1) {
|
|
1715
|
+
if (x0 == x1) {
|
|
1716
|
+
let dx = (scalex&1) ? -0.5 : 0.5;
|
|
1717
|
+
x0 += dx;
|
|
1718
|
+
x1 += dx;
|
|
1719
|
+
}
|
|
1720
|
+
if (y0 == y1) {
|
|
1721
|
+
let dy = (scaley&1) ? -0.5 : 0.5;
|
|
1722
|
+
y0 += dy;
|
|
1723
|
+
y1 += dy;
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
// The svg path does not include the start pixel, but the built-in drawing does.
|
|
1727
|
+
if (x0 == x1) {
|
|
1728
|
+
y0++;
|
|
1729
|
+
} else if (y0 == y1) {
|
|
1730
|
+
x0++;
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
// Group together all lines of the same width and emit as single paths.
|
|
1734
|
+
// Dramatically reduces the svg text size.
|
|
1735
|
+
var key = '' + lw + '#' + rgb;
|
|
1736
|
+
if (!lines[key]) {
|
|
1737
|
+
lines[key] = '<path stroke="#' + rgb + '" stroke-width="' + lw + '" d="';
|
|
1738
|
+
}
|
|
1739
|
+
lines[key] += 'M' + transform(x0, y0) + 'L' + transform(x1, y1);
|
|
1740
|
+
},
|
|
1741
|
+
// Polygons are used to draw the connected regions in a 2d barcode.
|
|
1742
|
+
// These will always be unstroked, filled, non-intersecting,
|
|
1743
|
+
// orthogonal shapes.
|
|
1744
|
+
// You will see a series of polygon() calls, followed by a fill().
|
|
1745
|
+
polygon(pts) {
|
|
1746
|
+
if (!path) {
|
|
1747
|
+
path = '<path d="';
|
|
1748
|
+
}
|
|
1749
|
+
path += 'M' + transform(pts[0][0], pts[0][1]);
|
|
1750
|
+
for (var i = 1, n = pts.length; i < n; i++) {
|
|
1751
|
+
var p = pts[i];
|
|
1752
|
+
path += 'L' + transform(p[0], p[1]);
|
|
1753
|
+
}
|
|
1754
|
+
path += 'Z';
|
|
1755
|
+
},
|
|
1756
|
+
// An unstroked, filled hexagon used by maxicode. You can choose to fill
|
|
1757
|
+
// each individually, or wait for the final fill().
|
|
1758
|
+
//
|
|
1759
|
+
// The hexagon is drawn from the top, counter-clockwise.
|
|
1760
|
+
hexagon(pts, rgb) {
|
|
1761
|
+
this.polygon(pts); // A hexagon is just a polygon...
|
|
1762
|
+
},
|
|
1763
|
+
// An unstroked, filled ellipse. Used by dotcode and maxicode at present.
|
|
1764
|
+
// maxicode issues pairs of ellipse calls (one cw, one ccw) followed by a fill()
|
|
1765
|
+
// to create the bullseye rings. dotcode issues all of its ellipses then a
|
|
1766
|
+
// fill().
|
|
1767
|
+
ellipse(x, y, rx, ry, ccw) {
|
|
1768
|
+
if (!path) {
|
|
1769
|
+
path = '<path d="';
|
|
1770
|
+
}
|
|
1771
|
+
var dx = rx * ELLIPSE_MAGIC;
|
|
1772
|
+
var dy = ry * ELLIPSE_MAGIC;
|
|
1773
|
+
|
|
1774
|
+
// Since there are never overlapping regions, we don't worry about cw/ccw.
|
|
1775
|
+
path += 'M' + transform(x - rx, y) +
|
|
1776
|
+
'C' + transform(x - rx, y - dy) + ' ' +
|
|
1777
|
+
transform(x - dx, y - ry) + ' ' +
|
|
1778
|
+
transform(x, y - ry) +
|
|
1779
|
+
'C' + transform(x + dx, y - ry) + ' ' +
|
|
1780
|
+
transform(x + rx, y - dy) + ' ' +
|
|
1781
|
+
transform(x + rx, y) +
|
|
1782
|
+
'C' + transform(x + rx, y + dy) + ' ' +
|
|
1783
|
+
transform(x + dx, y + ry) + ' ' +
|
|
1784
|
+
transform(x, y + ry) +
|
|
1785
|
+
'C' + transform(x - dx, y + ry) + ' ' +
|
|
1786
|
+
transform(x - rx, y + dy) + ' ' +
|
|
1787
|
+
transform(x - rx, y) +
|
|
1788
|
+
'Z';
|
|
1789
|
+
},
|
|
1790
|
+
// PostScript's default fill rule is non-zero but there are never intersecting
|
|
1791
|
+
// regions. The built-in drawing uses even-odd for simplicity - we match that
|
|
1792
|
+
// to be consistent.
|
|
1793
|
+
fill(rgb) {
|
|
1794
|
+
if (path) {
|
|
1795
|
+
svg += path + '" fill="#' + rgb + '" fill-rule="evenodd"' +
|
|
1796
|
+
(clipid ? ' clip-path="url(#' + clipid + ')"' : '') +
|
|
1797
|
+
' />\n';
|
|
1798
|
+
path = null;
|
|
1799
|
+
}
|
|
1800
|
+
},
|
|
1801
|
+
// Currently only used by swissqrcode. The `polys` area is an array of
|
|
1802
|
+
// arrays of points. Each array of points is identical to the `pts`
|
|
1803
|
+
// parameter passed to polygon(). The clipping rule, like the fill rule,
|
|
1804
|
+
// defaults to non-zero winding.
|
|
1805
|
+
clip : function(polys) {
|
|
1806
|
+
var path = '<clipPath id="clip' + clips.length + '"><path d="';
|
|
1807
|
+
for (let j = 0; j < polys.length; j++) {
|
|
1808
|
+
let pts = polys[j];
|
|
1809
|
+
path += 'M' + transform(pts[0][0], pts[0][1]);
|
|
1810
|
+
for (var i = 1, n = pts.length; i < n; i++) {
|
|
1811
|
+
var p = pts[i];
|
|
1812
|
+
path += 'L' + transform(p[0], p[1]);
|
|
1813
|
+
}
|
|
1814
|
+
path += 'Z';
|
|
1815
|
+
}
|
|
1816
|
+
path += '" clip-rule="nonzero" /></clipPath>';
|
|
1817
|
+
clipid = "clip" + clips.length;
|
|
1818
|
+
clips.push(path);
|
|
1819
|
+
},
|
|
1820
|
+
unclip : function() {
|
|
1821
|
+
clipid = '';
|
|
1822
|
+
},
|
|
1823
|
+
// Draw text with optional inter-character spacing. `y` is the baseline.
|
|
1824
|
+
// font is an object with properties { name, width, height, dx }
|
|
1825
|
+
// width and height are the font cell size.
|
|
1826
|
+
// dx is extra space requested between characters (usually zero).
|
|
1827
|
+
text(x, y, str, rgb, font) {
|
|
1828
|
+
var fontid = FontLib.lookup(font.name);
|
|
1829
|
+
var fwidth = font.width|0;
|
|
1830
|
+
var fheight = font.height|0;
|
|
1831
|
+
var dx = font.dx|0;
|
|
1832
|
+
var path = '';
|
|
1833
|
+
for (var k = 0; k < str.length; k++) {
|
|
1834
|
+
var ch = str.charCodeAt(k);
|
|
1835
|
+
var glyph = FontLib.getpaths(fontid, ch, fwidth, fheight);
|
|
1836
|
+
if (!glyph) {
|
|
1837
|
+
continue;
|
|
1838
|
+
}
|
|
1839
|
+
if (glyph.length) {
|
|
1840
|
+
// A glyph is composed of sequence of curve and line segments.
|
|
1841
|
+
// M is move-to
|
|
1842
|
+
// L is line-to
|
|
1843
|
+
// Q is quadratic bezier curve-to
|
|
1844
|
+
// C is cubic bezier curve-to
|
|
1845
|
+
for (var i = 0, l = glyph.length; i < l; i++) {
|
|
1846
|
+
let seg = glyph[i];
|
|
1847
|
+
if (seg.type == 'M' || seg.type == 'L') {
|
|
1848
|
+
path += seg.type + transform(seg.x + x, y - seg.y);
|
|
1849
|
+
} else if (seg.type == 'Q') {
|
|
1850
|
+
path += seg.type + transform(seg.cx + x, y - seg.cy) + ' ' +
|
|
1851
|
+
transform(seg.x + x, y - seg.y);
|
|
1852
|
+
} else if (seg.type == 'C') {
|
|
1853
|
+
path += seg.type + transform(seg.cx1 + x, y - seg.cy1) + ' ' +
|
|
1854
|
+
transform(seg.cx2 + x, y - seg.cy2) + ' ' +
|
|
1855
|
+
transform(seg.x + x, y - seg.y);
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
// Close the shape
|
|
1859
|
+
path += 'Z';
|
|
1860
|
+
}
|
|
1861
|
+
// getglyph() provides slightly different metrics than getpaths(). Keep
|
|
1862
|
+
// it consistent with the built-in drawing.
|
|
1863
|
+
x += FontLib.getglyph(fontid, ch, fwidth, fheight).advance + dx;
|
|
1864
|
+
}
|
|
1865
|
+
if (path) {
|
|
1866
|
+
svg += '<path d="' + path + '" fill="#' + rgb + '" />\n';
|
|
1867
|
+
}
|
|
1868
|
+
},
|
|
1869
|
+
// Called after all drawing is complete. The return value from this method
|
|
1870
|
+
// will be the return value from `bwipjs.render()`.
|
|
1871
|
+
end() {
|
|
1872
|
+
var linesvg = '';
|
|
1873
|
+
for (var key in lines) {
|
|
1874
|
+
linesvg += lines[key] + '" />\n';
|
|
1875
|
+
}
|
|
1876
|
+
var bg = opts.backgroundcolor;
|
|
1877
|
+
return '<svg viewBox="0 0 ' + gs_width + ' ' + gs_height + '" xmlns="http://www.w3.org/2000/svg">\n' +
|
|
1878
|
+
(clips.length ? '<defs>' + clips.join('') + '</defs>' : '') +
|
|
1879
|
+
(/^[0-9A-Fa-f]{6}$/.test(''+bg)
|
|
1880
|
+
? '<rect width="100%" height="100%" fill="#' + bg + '" />\n'
|
|
1881
|
+
: '') +
|
|
1882
|
+
linesvg + svg + '</svg>\n';
|
|
1883
|
+
},
|
|
1884
|
+
};
|
|
1885
|
+
|
|
1886
|
+
// translate/rotate and return as an SVG coordinate pair
|
|
1887
|
+
function transform(x, y) {
|
|
1888
|
+
x += gs_dx;
|
|
1889
|
+
y += gs_dy;
|
|
1890
|
+
var tx = tx0 * x + tx1 * y + tx2 * (gs_width-1) + tx3 * (gs_height-1);
|
|
1891
|
+
var ty = ty0 * x + ty1 * y + ty2 * (gs_width-1) + ty3 * (gs_height-1);
|
|
1892
|
+
return '' + ((tx|0) == tx ? tx : tx.toFixed(2)) + ' ' +
|
|
1893
|
+
((ty|0) == ty ? ty : ty.toFixed(2));
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
// fontlib.js
|
|
1897
|
+
var FontLib = (function() {
|
|
1898
|
+
var fonts = [];
|
|
1899
|
+
var names = {};
|
|
1900
|
+
var glyphcache = {};
|
|
1901
|
+
var glyphmru = {};
|
|
1902
|
+
var glyphcount = 0;
|
|
1903
|
+
|
|
1904
|
+
// Sentinel to simplify moving entries around in the list.
|
|
1905
|
+
glyphmru.next = glyphmru;
|
|
1906
|
+
glyphmru.prev = glyphmru;
|
|
1907
|
+
|
|
1908
|
+
return {
|
|
1909
|
+
lookup:lookup,
|
|
1910
|
+
monochrome:monochrome,
|
|
1911
|
+
getglyph:getglyph,
|
|
1912
|
+
getpaths:getpaths,
|
|
1913
|
+
loadFont:loadFont,
|
|
1914
|
+
};
|
|
1915
|
+
|
|
1916
|
+
// loadFont(name, data)
|
|
1917
|
+
// loadFont(name, mult, data)
|
|
1918
|
+
// loadFont(name, multy, multx, data) // note order: y,x
|
|
1919
|
+
// data must be the font data, either a binary or base64 encoded string.
|
|
1920
|
+
function loadFont(name /*...args*/) {
|
|
1921
|
+
var multx = 100;
|
|
1922
|
+
var multy = 100;
|
|
1923
|
+
var data = null;
|
|
1924
|
+
|
|
1925
|
+
if (arguments.length == 2) {
|
|
1926
|
+
data = arguments[1];
|
|
1927
|
+
} else if (arguments.length == 3) {
|
|
1928
|
+
multx = multy = +arguments[1] || 100;
|
|
1929
|
+
data = arguments[2];
|
|
1930
|
+
} else if (arguments.length == 4) {
|
|
1931
|
+
multy = +arguments[1] || 100;
|
|
1932
|
+
multx = +arguments[2] || 100;
|
|
1933
|
+
data = arguments[3];
|
|
1934
|
+
} else {
|
|
1935
|
+
throw new Error("bwipjs: loadFont: invalid number of arguments");
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1938
|
+
var font = STBTT.InitFont(toUint8Array(data));
|
|
1939
|
+
font.bwipjs_name = name;
|
|
1940
|
+
font.bwipjs_multx = multx;
|
|
1941
|
+
font.bwipjs_multy = multy;
|
|
1942
|
+
|
|
1943
|
+
var fontid = fonts.push(font)-1;
|
|
1944
|
+
names[name.toUpperCase()] = fontid;
|
|
1945
|
+
return fontid;
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
// Always returns a valid font-id (default OCR-B)
|
|
1949
|
+
function lookup(name) {
|
|
1950
|
+
var fontid = names[name.toUpperCase()];
|
|
1951
|
+
return fontid === undefined ? 1 : fontid; // OCR B default
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
// Not supported by stbtt
|
|
1955
|
+
function monochrome(mono) {
|
|
1956
|
+
if (mono) {
|
|
1957
|
+
throw new Error('bwipjs: monochrome fonts not implemented');
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
function getglyph(fontid, charcode, width, height) {
|
|
1962
|
+
fontid = fontid|0;
|
|
1963
|
+
charcode = charcode|0;
|
|
1964
|
+
width = +width;
|
|
1965
|
+
height = +height;
|
|
1966
|
+
if (!width || width < 8) {
|
|
1967
|
+
width = 8;
|
|
1968
|
+
}
|
|
1969
|
+
if (!height || height < 8) {
|
|
1970
|
+
height = width;
|
|
1971
|
+
}
|
|
1972
|
+
if (fontid < 0 || fontid >= fonts.length) {
|
|
1973
|
+
fontid = 1; // OCR B default
|
|
1974
|
+
}
|
|
1975
|
+
if (!charcode || charcode < 32) {
|
|
1976
|
+
charcode = 32;
|
|
1977
|
+
}
|
|
1978
|
+
|
|
1979
|
+
// In the cache?
|
|
1980
|
+
var cachekey = '' + fontid + 'c' + charcode + 'w' + width + 'h' + height;
|
|
1981
|
+
var glyph = glyphcache[cachekey];
|
|
1982
|
+
if (glyph) {
|
|
1983
|
+
// Unthread from the MRU
|
|
1984
|
+
glyph.prev.next = glyph.next;
|
|
1985
|
+
glyph.next.prev = glyph.prev;
|
|
1986
|
+
|
|
1987
|
+
// Thread back onto the top
|
|
1988
|
+
var sntl = glyphmru;
|
|
1989
|
+
sntl.next.prev = glyph;
|
|
1990
|
+
glyph.next = sntl.next;
|
|
1991
|
+
glyph.prev = sntl;
|
|
1992
|
+
sntl.next = glyph;
|
|
1993
|
+
|
|
1994
|
+
return glyph;
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1997
|
+
var font = fonts[fontid];
|
|
1998
|
+
var glyph = STBTT.GetGlyph(font, charcode, width * font.bwipjs_multx / 100,
|
|
1999
|
+
height * font.bwipjs_multy / 100) ||
|
|
2000
|
+
STBTT.GetGlyph(font, 0, width * font.bwipjs_multx / 100,
|
|
2001
|
+
height * font.bwipjs_multy / 100);
|
|
2002
|
+
|
|
2003
|
+
glyph.bytes = glyph.pixels;
|
|
2004
|
+
glyph.cachekey = cachekey;
|
|
2005
|
+
glyph.offset = 0;
|
|
2006
|
+
|
|
2007
|
+
//glyph = {
|
|
2008
|
+
// top:font.GlyphTop(),
|
|
2009
|
+
// left:font.GlyphLeft(),
|
|
2010
|
+
// width:font.GlyphWidth(),
|
|
2011
|
+
// height:font.GlyphHeight(),
|
|
2012
|
+
// advance:font.GlyphAdvance(),
|
|
2013
|
+
// bitmap:font.GlyphBitmap(),
|
|
2014
|
+
// offset:0,
|
|
2015
|
+
// cachekey:cachekey,
|
|
2016
|
+
// };
|
|
2017
|
+
|
|
2018
|
+
// Purge old
|
|
2019
|
+
if (glyphcount > 250) {
|
|
2020
|
+
var sntl = glyphmru;
|
|
2021
|
+
var temp = sntl.prev;
|
|
2022
|
+
temp.prev.next = sntl;
|
|
2023
|
+
sntl.prev = temp.prev;
|
|
2024
|
+
temp.next = temp.prev = null;
|
|
2025
|
+
delete glyphcache[temp.cachekey];
|
|
2026
|
+
} else {
|
|
2027
|
+
glyphcount++;
|
|
2028
|
+
}
|
|
2029
|
+
|
|
2030
|
+
// Add to cache and to the top of the MRU
|
|
2031
|
+
glyphcache[cachekey] = glyph;
|
|
2032
|
+
|
|
2033
|
+
var sntl = glyphmru;
|
|
2034
|
+
sntl.next.prev = glyph;
|
|
2035
|
+
glyph.next = sntl.next;
|
|
2036
|
+
glyph.prev = sntl;
|
|
2037
|
+
sntl.next = glyph;
|
|
2038
|
+
|
|
2039
|
+
return glyph;
|
|
2040
|
+
}
|
|
2041
|
+
|
|
2042
|
+
function getpaths(fontid, charcode, width, height) {
|
|
2043
|
+
fontid = fontid|0;
|
|
2044
|
+
charcode = charcode|0;
|
|
2045
|
+
width = +width;
|
|
2046
|
+
height = +height;
|
|
2047
|
+
if (!width || width < 8) {
|
|
2048
|
+
width = 8;
|
|
2049
|
+
}
|
|
2050
|
+
if (!height || height < 8) {
|
|
2051
|
+
height = width;
|
|
2052
|
+
}
|
|
2053
|
+
if (fontid < 0 || fontid >= fonts.length) {
|
|
2054
|
+
fontid = 1; // OCR B default
|
|
2055
|
+
}
|
|
2056
|
+
if (!charcode || charcode < 32) {
|
|
2057
|
+
charcode = 32;
|
|
2058
|
+
}
|
|
2059
|
+
|
|
2060
|
+
var font = fonts[fontid];
|
|
2061
|
+
return STBTT.GetPaths(font, charcode, width * font.bwipjs_multx / 100,
|
|
2062
|
+
height * font.bwipjs_multy / 100);
|
|
2063
|
+
}
|
|
2064
|
+
})();
|
|
2065
|
+
|
|
2066
|
+
// This is needed to make the default exports traceable by esbuild
|
|
2067
|
+
// during its tree shaking phase. See issue #298.
|
|
2068
|
+
function LoadFont() {
|
|
2069
|
+
return FontLib.loadFont.apply(FontLib, Array.prototype.slice.call(arguments));
|
|
2070
|
+
}
|
|
2071
|
+
// bwip-js/stb_trutype.js
|
|
2072
|
+
//
|
|
2073
|
+
// JavaScript implementation of stb_truetype.h @ https://github.com/nothings/stb.
|
|
2074
|
+
//
|
|
2075
|
+
// This file is part of the bwip-js project available at:
|
|
2076
|
+
//
|
|
2077
|
+
// http://metafloor.github.io/bwip-js
|
|
2078
|
+
//
|
|
2079
|
+
// Copyright (c) 2019 Mark Warren : MIT LICENSE
|
|
2080
|
+
|
|
2081
|
+
// Copyright notice from stb_truetype.h:
|
|
2082
|
+
//
|
|
2083
|
+
// MIT License
|
|
2084
|
+
//
|
|
2085
|
+
// Copyright (c) 2017 Sean Barrett
|
|
2086
|
+
//
|
|
2087
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
2088
|
+
// this software and associated documentation files (the "Software"), to deal in
|
|
2089
|
+
// the Software without restriction, including without limitation the rights to
|
|
2090
|
+
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
2091
|
+
// of the Software, and to permit persons to whom the Software is furnished to do
|
|
2092
|
+
// so, subject to the following conditions:
|
|
2093
|
+
// The above copyright notice and this permission notice shall be included in all
|
|
2094
|
+
// copies or substantial portions of the Software.
|
|
2095
|
+
//
|
|
2096
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
2097
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
2098
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
2099
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
2100
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
2101
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
2102
|
+
// SOFTWARE.
|
|
2103
|
+
|
|
2104
|
+
var STBTT = (function () {
|
|
2105
|
+
|
|
2106
|
+
var STBTT_vmove = 1,
|
|
2107
|
+
STBTT_vline = 2,
|
|
2108
|
+
STBTT_vcurve = 3,
|
|
2109
|
+
STBTT_vcubic = 4,
|
|
2110
|
+
|
|
2111
|
+
STBTT_PLATFORM_ID_UNICODE = 0,
|
|
2112
|
+
STBTT_PLATFORM_ID_MAC = 1,
|
|
2113
|
+
STBTT_PLATFORM_ID_ISO = 2,
|
|
2114
|
+
STBTT_PLATFORM_ID_MICROSOFT = 3,
|
|
2115
|
+
|
|
2116
|
+
STBTT_UNICODE_EID_UNICODE_1_0 = 0,
|
|
2117
|
+
STBTT_UNICODE_EID_UNICODE_1_1 = 1,
|
|
2118
|
+
STBTT_UNICODE_EID_ISO_10646 = 2,
|
|
2119
|
+
STBTT_UNICODE_EID_UNICODE_2_0_BMP = 3,
|
|
2120
|
+
STBTT_UNICODE_EID_UNICODE_2_0_FULL = 4,
|
|
2121
|
+
|
|
2122
|
+
STBTT_MS_EID_SYMBOL = 0,
|
|
2123
|
+
STBTT_MS_EID_UNICODE_BMP = 1,
|
|
2124
|
+
STBTT_MS_EID_SHIFTJIS = 2,
|
|
2125
|
+
STBTT_MS_EID_UNICODE_FULL = 10;
|
|
2126
|
+
|
|
2127
|
+
var floor = Math.floor;
|
|
2128
|
+
var ceil = Math.ceil;
|
|
2129
|
+
var sqrt = Math.sqrt;
|
|
2130
|
+
var abs = Math.abs;
|
|
2131
|
+
|
|
2132
|
+
// Allocate an array of objects - replaces malloc(sizeof struct * n)
|
|
2133
|
+
function oalloc(n) {
|
|
2134
|
+
var o = [];
|
|
2135
|
+
for (var i = 0; i < n; i++) {
|
|
2136
|
+
o.push({});
|
|
2137
|
+
}
|
|
2138
|
+
return o;
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
//static unsigned char stbtt__buf_get8(stbtt__buf * b)
|
|
2142
|
+
function stbtt__buf_get8(b) {
|
|
2143
|
+
return b[b.cursor++]||0;
|
|
2144
|
+
}
|
|
2145
|
+
|
|
2146
|
+
//static unsigned char stbtt__buf_peek8(stbtt__buf * b)
|
|
2147
|
+
function stbtt__buf_peek8(b) {
|
|
2148
|
+
return b[b.cursor];
|
|
2149
|
+
}
|
|
2150
|
+
|
|
2151
|
+
//static void stbtt__buf_seek(stbtt__buf * b, int o)
|
|
2152
|
+
function stbtt__buf_seek(b, o) {
|
|
2153
|
+
b.cursor = (o > b.length || o < 0) ? b.length : o;
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
//static void stbtt__buf_skip(stbtt__buf * b, int o)
|
|
2157
|
+
function stbtt__buf_skip(b, o) {
|
|
2158
|
+
stbtt__buf_seek(b, b.cursor + o);
|
|
2159
|
+
}
|
|
2160
|
+
|
|
2161
|
+
//static unsigned int stbtt__buf_get(stbtt__buf * b, int n)
|
|
2162
|
+
function stbtt__buf_get(b, n) {
|
|
2163
|
+
var v = 0;
|
|
2164
|
+
for (var i = 0; i < n; i++) {
|
|
2165
|
+
v = (v << 8) | stbtt__buf_get8(b);
|
|
2166
|
+
}
|
|
2167
|
+
return v;
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
// This function is only called once with a real 'p', all other uses are
|
|
2171
|
+
// for a NULL buffer. The for real usage, the code is inlined.
|
|
2172
|
+
//static stbtt__buf stbtt__new_buf(const void *p, int size)
|
|
2173
|
+
function stbtt__null_buf() {
|
|
2174
|
+
return { length:0 };
|
|
2175
|
+
}
|
|
2176
|
+
|
|
2177
|
+
//static stbtt__buf stbtt__buf_range(const stbtt__buf * b, int o, int s)
|
|
2178
|
+
function stbtt__buf_range(b, o, s) {
|
|
2179
|
+
if (o < 0 || s < 0 || o > b.length || s > b.length - o) {
|
|
2180
|
+
return stbtt__null_buf();
|
|
2181
|
+
}
|
|
2182
|
+
var r = b.subarray(o, o + s);
|
|
2183
|
+
r.cursor = 0;
|
|
2184
|
+
return r;
|
|
2185
|
+
}
|
|
2186
|
+
|
|
2187
|
+
//static stbtt__buf stbtt__cff_get_index(stbtt__buf * b)
|
|
2188
|
+
function stbtt__cff_get_index(b) {
|
|
2189
|
+
var start = b.cursor;
|
|
2190
|
+
var count = stbtt__buf_get(b, 2);
|
|
2191
|
+
if (count) {
|
|
2192
|
+
var offsize = stbtt__buf_get8(b);
|
|
2193
|
+
stbtt__buf_skip(b, offsize * count);
|
|
2194
|
+
stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1);
|
|
2195
|
+
}
|
|
2196
|
+
return stbtt__buf_range(b, start, b.cursor - start);
|
|
2197
|
+
}
|
|
2198
|
+
|
|
2199
|
+
//static unsigned int stbtt__cff_int(stbtt__buf * b)
|
|
2200
|
+
function stbtt__cff_int(b) {
|
|
2201
|
+
var b0 = stbtt__buf_get8(b);
|
|
2202
|
+
if (b0 >= 32 && b0 <= 246) {
|
|
2203
|
+
return b0 - 139;
|
|
2204
|
+
} else if (b0 >= 247 && b0 <= 250) {
|
|
2205
|
+
return (b0 - 247) * 256 + stbtt__buf_get8(b) + 108;
|
|
2206
|
+
} else if (b0 >= 251 && b0 <= 254) {
|
|
2207
|
+
return -(b0 - 251) * 256 - stbtt__buf_get8(b) - 108;
|
|
2208
|
+
} else if (b0 == 28) {
|
|
2209
|
+
return stbtt__buf_get(b, 2);
|
|
2210
|
+
} else if (b0 == 29) {
|
|
2211
|
+
return stbtt__buf_get(b, 4);
|
|
2212
|
+
}
|
|
2213
|
+
return 0;
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2216
|
+
//static void stbtt__cff_skip_operand(stbtt__buf * b)
|
|
2217
|
+
function stbtt__cff_skip_operand(b) {
|
|
2218
|
+
var b0 = stbtt__buf_peek8(b);
|
|
2219
|
+
if (b0 == 30) {
|
|
2220
|
+
stbtt__buf_skip(b, 1);
|
|
2221
|
+
while (b.cursor < b.length) {
|
|
2222
|
+
var v = stbtt__buf_get8(b);
|
|
2223
|
+
if ((v & 0xF) == 0xF || (v >> 4) == 0xF) {
|
|
2224
|
+
break;
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
} else {
|
|
2228
|
+
stbtt__cff_int(b);
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
//static stbtt__buf stbtt__dict_get(stbtt__buf * b, int key)
|
|
2233
|
+
function stbtt__dict_get(b, key) {
|
|
2234
|
+
stbtt__buf_seek(b, 0);
|
|
2235
|
+
while (b.cursor < b.length) {
|
|
2236
|
+
var start = b.cursor, end, op;
|
|
2237
|
+
while (stbtt__buf_peek8(b) >= 28) {
|
|
2238
|
+
stbtt__cff_skip_operand(b);
|
|
2239
|
+
}
|
|
2240
|
+
end = b.cursor;
|
|
2241
|
+
op = stbtt__buf_get8(b);
|
|
2242
|
+
if (op == 12) {
|
|
2243
|
+
op = stbtt__buf_get8(b) | 0x100;
|
|
2244
|
+
}
|
|
2245
|
+
if (op == key) {
|
|
2246
|
+
return stbtt__buf_range(b, start, end - start);
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
return stbtt__buf_range(b, 0, 0);
|
|
2250
|
+
}
|
|
2251
|
+
|
|
2252
|
+
//static void stbtt__dict_get_ints(stbtt__buf * b, int key, int outcount, unsigned int *out)
|
|
2253
|
+
function stbtt__dict_get_ints(b, key, outcount, out) {
|
|
2254
|
+
var operands = stbtt__dict_get(b, key);
|
|
2255
|
+
for (var i = 0; i < outcount && operands.cursor < operands.length; i++) {
|
|
2256
|
+
out[i] = stbtt__cff_int(operands);
|
|
2257
|
+
}
|
|
2258
|
+
}
|
|
2259
|
+
// single-integer format of above since javascript doesn't have address-of
|
|
2260
|
+
function stbtt__dict_get_int(b, key, out) {
|
|
2261
|
+
var operands = stbtt__dict_get(b, key);
|
|
2262
|
+
if (operands.cursor < operands.length) {
|
|
2263
|
+
out = stbtt__cff_int(operands);
|
|
2264
|
+
}
|
|
2265
|
+
return out;
|
|
2266
|
+
}
|
|
2267
|
+
|
|
2268
|
+
//static int stbtt__cff_index_count(stbtt__buf * b)
|
|
2269
|
+
function stbtt__cff_index_count(b) {
|
|
2270
|
+
stbtt__buf_seek(b, 0);
|
|
2271
|
+
return stbtt__buf_get(b, 2);
|
|
2272
|
+
}
|
|
2273
|
+
|
|
2274
|
+
//static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i)
|
|
2275
|
+
function stbtt__cff_index_get(b, i) {
|
|
2276
|
+
var count, offsize, start, end;
|
|
2277
|
+
stbtt__buf_seek(b, 0);
|
|
2278
|
+
count = stbtt__buf_get(b, 2);
|
|
2279
|
+
offsize = stbtt__buf_get8(b);
|
|
2280
|
+
stbtt__buf_skip(b, i * offsize);
|
|
2281
|
+
start = stbtt__buf_get(b, offsize);
|
|
2282
|
+
end = stbtt__buf_get(b, offsize);
|
|
2283
|
+
return stbtt__buf_range(b, 2 + (count + 1) * offsize + start, end - start);
|
|
2284
|
+
}
|
|
2285
|
+
|
|
2286
|
+
// Convert sign-extend a 16-bit integer to JS number
|
|
2287
|
+
function INT16(n) {
|
|
2288
|
+
return n & 0x8000 ? (0xffff0000|n)>>0 : n;
|
|
2289
|
+
}
|
|
2290
|
+
|
|
2291
|
+
//static unsigned short ttUSHORT(unsigned char *p)
|
|
2292
|
+
function ttUSHORT(b, o) {
|
|
2293
|
+
return b[o] * 256 + b[o+1];
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
//static short ttSHORT(unsigned char *p)
|
|
2297
|
+
function ttSHORT(b, o) {
|
|
2298
|
+
var n = b[o] * 256 + b[o+1];
|
|
2299
|
+
return n & 0x8000 ? (0xffff0000|n)>>0 : n;
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
//static unsigned int ttULONG(unsigned char *p)
|
|
2303
|
+
function ttULONG(b, o) {
|
|
2304
|
+
return (b[o] << 24) + (b[o+1] << 16) + (b[o+2] << 8) + b[o+3];
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2307
|
+
//static unsigned int stbtt__find_table(unsigned char *data, unsigned int fontstart, const char *tag)
|
|
2308
|
+
function stbtt__find_table(data, fontstart, tag) {
|
|
2309
|
+
var num_tables = ttUSHORT(data, fontstart + 4);
|
|
2310
|
+
var tabledir = fontstart + 12;
|
|
2311
|
+
for (var i = 0; i < num_tables; ++i) {
|
|
2312
|
+
var loc = tabledir + 16 * i;
|
|
2313
|
+
if (data[loc] == tag[0] && data[loc+1] == tag[1] && data[loc+2] == tag[2] && data[loc+3] == tag[3]) {
|
|
2314
|
+
return ttULONG(data, loc + 8);
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
return 0;
|
|
2318
|
+
}
|
|
2319
|
+
|
|
2320
|
+
//static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
|
|
2321
|
+
function stbtt__get_subrs(cff, fontdict) {
|
|
2322
|
+
var private_loc = [ 0, 0 ];
|
|
2323
|
+
stbtt__dict_get_ints(fontdict, 18, 2, private_loc);
|
|
2324
|
+
if (!private_loc[1] || !private_loc[0]) {
|
|
2325
|
+
return stbtt__null_buf();
|
|
2326
|
+
}
|
|
2327
|
+
var pdict = stbtt__buf_range(cff, private_loc[1], private_loc[0]);
|
|
2328
|
+
var subrsoff = stbtt__dict_get_int(pdict, 19, 0);
|
|
2329
|
+
if (!subrsoff) {
|
|
2330
|
+
return stbtt__null_buf();
|
|
2331
|
+
}
|
|
2332
|
+
stbtt__buf_seek(cff, private_loc[1] + subrsoff);
|
|
2333
|
+
return stbtt__cff_get_index(cff);
|
|
2334
|
+
}
|
|
2335
|
+
|
|
2336
|
+
//static int stbtt_InitFont_internal(stbtt_fontinfo * info, unsigned char *data, int fontstart)
|
|
2337
|
+
function stbtt_InitFont_internal(info, data, fontstart) {
|
|
2338
|
+
var cmap, t, i, numTables;
|
|
2339
|
+
|
|
2340
|
+
info.data = data;
|
|
2341
|
+
info.fontstart = fontstart;
|
|
2342
|
+
info.cff = stbtt__null_buf();
|
|
2343
|
+
|
|
2344
|
+
cmap = stbtt__find_table(data, fontstart, [ 99, 109, 97, 112 ]); //"cmap"
|
|
2345
|
+
info.loca = stbtt__find_table(data, fontstart, [ 108, 111, 99, 97 ]); //"loca"
|
|
2346
|
+
info.head = stbtt__find_table(data, fontstart, [ 104, 101, 97, 100 ]); //"head"
|
|
2347
|
+
info.glyf = stbtt__find_table(data, fontstart, [ 103, 108, 121, 102 ]); //"glyf"
|
|
2348
|
+
info.hhea = stbtt__find_table(data, fontstart, [ 104, 104, 101, 97 ]); //"hhea"
|
|
2349
|
+
info.hmtx = stbtt__find_table(data, fontstart, [ 104, 109, 116, 120 ]); //"hmtx"
|
|
2350
|
+
info.kern = stbtt__find_table(data, fontstart, [ 107, 101, 114, 110 ]); //"kern"
|
|
2351
|
+
|
|
2352
|
+
if (!cmap || !info.head || !info.hhea || !info.hmtx) {
|
|
2353
|
+
return 0;
|
|
2354
|
+
}
|
|
2355
|
+
if (info.glyf) {
|
|
2356
|
+
if (!info.loca) {
|
|
2357
|
+
return 0;
|
|
2358
|
+
}
|
|
2359
|
+
} else {
|
|
2360
|
+
var b, topdict, topdictidx, cff,
|
|
2361
|
+
cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0;
|
|
2362
|
+
|
|
2363
|
+
cff = stbtt__find_table(data, fontstart, [ 67, 70, 70, 32 ]); //"CFF "
|
|
2364
|
+
if (!cff) {
|
|
2365
|
+
return 0;
|
|
2366
|
+
}
|
|
2367
|
+
|
|
2368
|
+
info.fontdicts = stbtt__null_buf();
|
|
2369
|
+
info.fdselect = stbtt__null_buf();
|
|
2370
|
+
|
|
2371
|
+
info.cff = data.subarray(cff); //stbtt__new_buf(data + cff, 512 * 1024 * 1024);
|
|
2372
|
+
info.cff.cursor = 0;
|
|
2373
|
+
b = info.cff;
|
|
2374
|
+
|
|
2375
|
+
stbtt__buf_skip(b, 2);
|
|
2376
|
+
stbtt__buf_seek(b, stbtt__buf_get8(b));
|
|
2377
|
+
|
|
2378
|
+
stbtt__cff_get_index(b);
|
|
2379
|
+
topdictidx = stbtt__cff_get_index(b);
|
|
2380
|
+
topdict = stbtt__cff_index_get(topdictidx, 0);
|
|
2381
|
+
stbtt__cff_get_index(b);
|
|
2382
|
+
info.gsubrs = stbtt__cff_get_index(b);
|
|
2383
|
+
|
|
2384
|
+
charstrings = stbtt__dict_get_int(topdict, 17, charstrings);
|
|
2385
|
+
cstype = stbtt__dict_get_int(topdict, 0x100 | 6, cstype);
|
|
2386
|
+
fdarrayoff = stbtt__dict_get_int(topdict, 0x100 | 36, fdarrayoff);
|
|
2387
|
+
fdselectoff = stbtt__dict_get_int(topdict, 0x100 | 37, fdselectoff);
|
|
2388
|
+
info.subrs = stbtt__get_subrs(b, topdict);
|
|
2389
|
+
|
|
2390
|
+
if (cstype != 2) {
|
|
2391
|
+
return 0;
|
|
2392
|
+
}
|
|
2393
|
+
if (charstrings == 0) {
|
|
2394
|
+
return 0;
|
|
2395
|
+
}
|
|
2396
|
+
|
|
2397
|
+
if (fdarrayoff) {
|
|
2398
|
+
if (!fdselectoff) {
|
|
2399
|
+
return 0;
|
|
2400
|
+
}
|
|
2401
|
+
stbtt__buf_seek(b, fdarrayoff);
|
|
2402
|
+
info.fontdicts = stbtt__cff_get_index(b);
|
|
2403
|
+
info.fdselect = stbtt__buf_range(b, fdselectoff, b.length - fdselectoff);
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2406
|
+
stbtt__buf_seek(b, charstrings);
|
|
2407
|
+
info.charstrings = stbtt__cff_get_index(b);
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2410
|
+
t = stbtt__find_table(data, fontstart, [ 109, 97, 120, 112 ]); //"maxp"
|
|
2411
|
+
if (t) {
|
|
2412
|
+
info.numGlyphs = ttUSHORT(data, t + 4);
|
|
2413
|
+
}
|
|
2414
|
+
else {
|
|
2415
|
+
info.numGlyphs = 0xffff;
|
|
2416
|
+
}
|
|
2417
|
+
|
|
2418
|
+
numTables = ttUSHORT(data, cmap + 2);
|
|
2419
|
+
info.index_map = 0;
|
|
2420
|
+
for (i = 0; i < numTables; ++i) {
|
|
2421
|
+
var encoding_record = cmap + 4 + 8 * i;
|
|
2422
|
+
|
|
2423
|
+
switch (ttUSHORT(data, encoding_record)) {
|
|
2424
|
+
case STBTT_PLATFORM_ID_MICROSOFT:
|
|
2425
|
+
switch (ttUSHORT(data, encoding_record + 2)) {
|
|
2426
|
+
case STBTT_MS_EID_UNICODE_BMP:
|
|
2427
|
+
case STBTT_MS_EID_UNICODE_FULL:
|
|
2428
|
+
info.index_map = cmap + ttULONG(data, encoding_record + 4);
|
|
2429
|
+
break;
|
|
2430
|
+
}
|
|
2431
|
+
break;
|
|
2432
|
+
case STBTT_PLATFORM_ID_UNICODE:
|
|
2433
|
+
info.index_map = cmap + ttULONG(data, encoding_record + 4);
|
|
2434
|
+
break;
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
if (info.index_map == 0) {
|
|
2438
|
+
return 0;
|
|
2439
|
+
}
|
|
2440
|
+
|
|
2441
|
+
info.indexToLocFormat = ttUSHORT(data, info.head + 50);
|
|
2442
|
+
return 1;
|
|
2443
|
+
}
|
|
2444
|
+
|
|
2445
|
+
//extern int stbtt_FindGlyphIndex(const stbtt_fontinfo * info, int unicode_codepoint)
|
|
2446
|
+
function stbtt_FindGlyphIndex(info, unicode_codepoint) {
|
|
2447
|
+
var data = info.data, index_map = info.index_map;
|
|
2448
|
+
|
|
2449
|
+
var format = ttUSHORT(data, index_map + 0);
|
|
2450
|
+
if (format == 0) {
|
|
2451
|
+
var bytes = ttUSHORT(data, index_map + 2);
|
|
2452
|
+
if (unicode_codepoint < bytes - 6) {
|
|
2453
|
+
return data[index_map + 6 + unicode_codepoint];
|
|
2454
|
+
}
|
|
2455
|
+
return 0;
|
|
2456
|
+
} else if (format == 6) {
|
|
2457
|
+
var first = ttUSHORT(data, index_map + 6),
|
|
2458
|
+
count = ttUSHORT(data, index_map + 8);
|
|
2459
|
+
if (unicode_codepoint >= first && unicode_codepoint < first + count) {
|
|
2460
|
+
return ttUSHORT(data, index_map + 10 + (unicode_codepoint - first) * 2);
|
|
2461
|
+
}
|
|
2462
|
+
return 0;
|
|
2463
|
+
} else if (format == 2) {
|
|
2464
|
+
return 0;
|
|
2465
|
+
} else if (format == 4) {
|
|
2466
|
+
var segcount = ttUSHORT(data, index_map + 6) >> 1,
|
|
2467
|
+
searchRange = ttUSHORT(data, index_map + 8) >> 1,
|
|
2468
|
+
entrySelector = ttUSHORT(data, index_map + 10),
|
|
2469
|
+
rangeShift = ttUSHORT(data, index_map + 12) >> 1,
|
|
2470
|
+
endCount = index_map + 14,
|
|
2471
|
+
search = endCount;
|
|
2472
|
+
|
|
2473
|
+
if (unicode_codepoint > 0xffff) {
|
|
2474
|
+
return 0;
|
|
2475
|
+
}
|
|
2476
|
+
|
|
2477
|
+
if (unicode_codepoint >= ttUSHORT(data, search + rangeShift * 2)) {
|
|
2478
|
+
search += rangeShift * 2;
|
|
2479
|
+
}
|
|
2480
|
+
|
|
2481
|
+
search -= 2;
|
|
2482
|
+
while (entrySelector) {
|
|
2483
|
+
searchRange >>= 1;
|
|
2484
|
+
var end = ttUSHORT(data, search + searchRange * 2);
|
|
2485
|
+
if (unicode_codepoint > end) {
|
|
2486
|
+
search += searchRange * 2;
|
|
2487
|
+
}
|
|
2488
|
+
--entrySelector;
|
|
2489
|
+
}
|
|
2490
|
+
search += 2;
|
|
2491
|
+
|
|
2492
|
+
var offset, start, item = (search - endCount) >>> 1;
|
|
2493
|
+
|
|
2494
|
+
start = ttUSHORT(data, index_map + 14 + segcount * 2 + 2 + 2 * item);
|
|
2495
|
+
if (unicode_codepoint < start) {
|
|
2496
|
+
return 0;
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2499
|
+
offset = ttUSHORT(data, index_map + 14 + segcount * 6 + 2 + 2 * item);
|
|
2500
|
+
if (offset == 0) {
|
|
2501
|
+
return unicode_codepoint + ttSHORT(data, index_map + 14 + segcount * 4 + 2 + 2 * item);
|
|
2502
|
+
}
|
|
2503
|
+
return ttUSHORT(data, offset + (unicode_codepoint - start) * 2 +
|
|
2504
|
+
index_map + 14 + segcount * 6 + 2 + 2 * item);
|
|
2505
|
+
} else if (format == 12 || format == 13) {
|
|
2506
|
+
var ngroups = ttULONG(data, index_map + 12),
|
|
2507
|
+
low = 0, high = ngroups;
|
|
2508
|
+
while (low < high) {
|
|
2509
|
+
var mid = low + ((high - low) >> 1);
|
|
2510
|
+
var start_char = ttULONG(data, index_map + 16 + mid * 12);
|
|
2511
|
+
var end_char = ttULONG(data, index_map + 16 + mid * 12 + 4);
|
|
2512
|
+
if (unicode_codepoint < start_char) {
|
|
2513
|
+
high = mid;
|
|
2514
|
+
} else if (unicode_codepoint > end_char) {
|
|
2515
|
+
low = mid + 1;
|
|
2516
|
+
} else {
|
|
2517
|
+
var start_glyph = ttULONG(data, index_map + 16 + mid * 12 + 8);
|
|
2518
|
+
if (format == 12) {
|
|
2519
|
+
return start_glyph + unicode_codepoint - start_char;
|
|
2520
|
+
} else {
|
|
2521
|
+
return start_glyph;
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
return 0;
|
|
2526
|
+
}
|
|
2527
|
+
return 0;
|
|
2528
|
+
}
|
|
2529
|
+
|
|
2530
|
+
//static void stbtt_setvertex(stbtt_vertex * v, unsigned char type, int x, int y, int cx, int cy)
|
|
2531
|
+
function stbtt_setvertex(v, type, x, y, cx, cy) {
|
|
2532
|
+
v.type = type;
|
|
2533
|
+
v.x = x;
|
|
2534
|
+
v.y = y;
|
|
2535
|
+
v.cx = cx;
|
|
2536
|
+
v.cy = cy;
|
|
2537
|
+
}
|
|
2538
|
+
|
|
2539
|
+
//static int stbtt__GetGlyfOffset(const stbtt_fontinfo * info, int glyph_index)
|
|
2540
|
+
function stbtt__GetGlyfOffset(info, glyph_index) {
|
|
2541
|
+
var g1, g2;
|
|
2542
|
+
if (glyph_index >= info.numGlyphs) {
|
|
2543
|
+
return -1;
|
|
2544
|
+
}
|
|
2545
|
+
if (info.indexToLocFormat >= 2) {
|
|
2546
|
+
return -1;
|
|
2547
|
+
}
|
|
2548
|
+
|
|
2549
|
+
if (info.indexToLocFormat == 0) {
|
|
2550
|
+
g1 = info.glyf + ttUSHORT(info.data, info.loca + glyph_index * 2) * 2;
|
|
2551
|
+
g2 = info.glyf + ttUSHORT(info.data, info.loca + glyph_index * 2 + 2) * 2;
|
|
2552
|
+
} else {
|
|
2553
|
+
g1 = info.glyf + ttULONG(info.data, info.loca + glyph_index * 4);
|
|
2554
|
+
g2 = info.glyf + ttULONG(info.data, info.loca + glyph_index * 4 + 4);
|
|
2555
|
+
}
|
|
2556
|
+
|
|
2557
|
+
return g1 == g2 ? -1 : g1;
|
|
2558
|
+
}
|
|
2559
|
+
|
|
2560
|
+
//extern int stbtt_GetGlyphBox(const stbtt_fontinfo * info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
|
|
2561
|
+
function stbtt_GetGlyphBox(info, glyph_index, out) {
|
|
2562
|
+
if (info.cff.length) {
|
|
2563
|
+
stbtt__GetGlyphInfoT2(info, glyph_index, out);
|
|
2564
|
+
} else {
|
|
2565
|
+
var g = stbtt__GetGlyfOffset(info, glyph_index);
|
|
2566
|
+
if (g < 0) {
|
|
2567
|
+
return 0;
|
|
2568
|
+
}
|
|
2569
|
+
out.x0 = ttSHORT(info.data, g + 2);
|
|
2570
|
+
out.y0 = ttSHORT(info.data, g + 4);
|
|
2571
|
+
out.x1 = ttSHORT(info.data, g + 6);
|
|
2572
|
+
out.y1 = ttSHORT(info.data, g + 8);
|
|
2573
|
+
}
|
|
2574
|
+
return 1;
|
|
2575
|
+
}
|
|
2576
|
+
|
|
2577
|
+
//static int stbtt__close_shape(stbtt_vertex * vertices, int num_vertices, int was_off,
|
|
2578
|
+
// int start_off, int sx, int sy, int scx, int scy, int cx, int cy)
|
|
2579
|
+
function stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx, sy, scx, scy, cx, cy) {
|
|
2580
|
+
if (start_off) {
|
|
2581
|
+
if (was_off) {
|
|
2582
|
+
stbtt_setvertex(vertices[num_vertices++], STBTT_vcurve,
|
|
2583
|
+
(cx + scx) >> 1, (cy + scy) >> 1, cx, cy);
|
|
2584
|
+
}
|
|
2585
|
+
stbtt_setvertex(vertices[num_vertices++], STBTT_vcurve, sx, sy, scx, scy);
|
|
2586
|
+
} else {
|
|
2587
|
+
if (was_off) {
|
|
2588
|
+
stbtt_setvertex(vertices[num_vertices++], STBTT_vcurve, sx, sy, cx, cy);
|
|
2589
|
+
} else {
|
|
2590
|
+
stbtt_setvertex(vertices[num_vertices++], STBTT_vline, sx, sy, 0, 0);
|
|
2591
|
+
}
|
|
2592
|
+
}
|
|
2593
|
+
return num_vertices;
|
|
2594
|
+
}
|
|
2595
|
+
|
|
2596
|
+
//static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo * info, int glyph_index, stbtt_vertex ** pvertices)
|
|
2597
|
+
function stbtt__GetGlyphShapeTT(info, glyph_index) {
|
|
2598
|
+
var data = info.data,
|
|
2599
|
+
g = stbtt__GetGlyfOffset(info, glyph_index);
|
|
2600
|
+
|
|
2601
|
+
if (g < 0) {
|
|
2602
|
+
return null;
|
|
2603
|
+
}
|
|
2604
|
+
|
|
2605
|
+
var vertices = [];
|
|
2606
|
+
var numberOfContours = ttSHORT(data, g);
|
|
2607
|
+
if (numberOfContours > 0) {
|
|
2608
|
+
var flags = 0, flagcount,
|
|
2609
|
+
i, j = 0, m, n, next_move, was_off = 0, off, start_off = 0,
|
|
2610
|
+
x, y, cx, cy, sx, sy, scx, scy;
|
|
2611
|
+
var endPtsOfContours = g + 10;
|
|
2612
|
+
var ins = ttUSHORT(data, g + 10 + numberOfContours * 2);
|
|
2613
|
+
var points = data.subarray(g + 10 + numberOfContours * 2 + 2 + ins);
|
|
2614
|
+
var ptsoff = 0;
|
|
2615
|
+
|
|
2616
|
+
n = 1 + ttUSHORT(data, endPtsOfContours + numberOfContours * 2 - 2);
|
|
2617
|
+
m = n + 2 * numberOfContours;
|
|
2618
|
+
|
|
2619
|
+
vertices = oalloc(m);
|
|
2620
|
+
next_move = 0;
|
|
2621
|
+
flagcount = 0;
|
|
2622
|
+
off = m - n;
|
|
2623
|
+
|
|
2624
|
+
for (i = 0; i < n; ++i) {
|
|
2625
|
+
if (flagcount == 0) {
|
|
2626
|
+
flags = points[ptsoff++];
|
|
2627
|
+
if (flags & 8) {
|
|
2628
|
+
flagcount = points[ptsoff++];
|
|
2629
|
+
}
|
|
2630
|
+
} else {
|
|
2631
|
+
--flagcount;
|
|
2632
|
+
}
|
|
2633
|
+
vertices[off + i].type = flags;
|
|
2634
|
+
}
|
|
2635
|
+
|
|
2636
|
+
x = 0;
|
|
2637
|
+
for (i = 0; i < n; ++i) {
|
|
2638
|
+
flags = vertices[off + i].type;
|
|
2639
|
+
if (flags & 2) {
|
|
2640
|
+
var dx = points[ptsoff++];
|
|
2641
|
+
x += (flags & 16) ? dx : -dx;
|
|
2642
|
+
} else {
|
|
2643
|
+
if (!(flags & 16)) {
|
|
2644
|
+
x = x + INT16(points[ptsoff] * 256 + points[ptsoff+1]);
|
|
2645
|
+
ptsoff += 2;
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
vertices[off + i].x = x;
|
|
2649
|
+
}
|
|
2650
|
+
|
|
2651
|
+
y = 0;
|
|
2652
|
+
for (i = 0; i < n; ++i) {
|
|
2653
|
+
flags = vertices[off + i].type;
|
|
2654
|
+
if (flags & 4) {
|
|
2655
|
+
var dy = points[ptsoff++];
|
|
2656
|
+
y += (flags & 32) ? dy : -dy;
|
|
2657
|
+
} else {
|
|
2658
|
+
if (!(flags & 32)) {
|
|
2659
|
+
y = y + INT16(points[ptsoff] * 256 + points[ptsoff+1]);
|
|
2660
|
+
ptsoff += 2;
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2663
|
+
vertices[off + i].y = y;
|
|
2664
|
+
}
|
|
2665
|
+
|
|
2666
|
+
var num_vertices = 0;
|
|
2667
|
+
sx = sy = cx = cy = scx = scy = 0;
|
|
2668
|
+
for (i = 0; i < n; ++i) {
|
|
2669
|
+
flags = vertices[off + i].type;
|
|
2670
|
+
x = vertices[off + i].x;
|
|
2671
|
+
y = vertices[off + i].y;
|
|
2672
|
+
|
|
2673
|
+
if (next_move == i) {
|
|
2674
|
+
if (i != 0) {
|
|
2675
|
+
num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off,
|
|
2676
|
+
sx, sy, scx, scy, cx, cy);
|
|
2677
|
+
}
|
|
2678
|
+
start_off = !(flags & 1);
|
|
2679
|
+
if (start_off) {
|
|
2680
|
+
scx = x;
|
|
2681
|
+
scy = y;
|
|
2682
|
+
if (!(vertices[off + i + 1].type & 1)) {
|
|
2683
|
+
sx = (x + vertices[off + i + 1].x) >> 1;
|
|
2684
|
+
sy = (y + vertices[off + i + 1].y) >> 1;
|
|
2685
|
+
} else {
|
|
2686
|
+
sx = vertices[off + i + 1].x;
|
|
2687
|
+
sy = vertices[off + i + 1].y;
|
|
2688
|
+
++i;
|
|
2689
|
+
}
|
|
2690
|
+
} else {
|
|
2691
|
+
sx = x;
|
|
2692
|
+
sy = y;
|
|
2693
|
+
}
|
|
2694
|
+
stbtt_setvertex(vertices[num_vertices++], STBTT_vmove, sx, sy, 0, 0);
|
|
2695
|
+
was_off = 0;
|
|
2696
|
+
next_move = 1 + ttUSHORT(data, endPtsOfContours + j * 2);
|
|
2697
|
+
++j;
|
|
2698
|
+
} else {
|
|
2699
|
+
if (!(flags & 1)) {
|
|
2700
|
+
if (was_off) {
|
|
2701
|
+
stbtt_setvertex(vertices[num_vertices++], STBTT_vcurve,
|
|
2702
|
+
(cx + x) >> 1, (cy + y) >> 1, cx, cy);
|
|
2703
|
+
}
|
|
2704
|
+
cx = x;
|
|
2705
|
+
cy = y;
|
|
2706
|
+
was_off = 1;
|
|
2707
|
+
} else {
|
|
2708
|
+
if (was_off) {
|
|
2709
|
+
stbtt_setvertex(vertices[num_vertices++], STBTT_vcurve, x, y, cx, cy);
|
|
2710
|
+
} else {
|
|
2711
|
+
stbtt_setvertex(vertices[num_vertices++], STBTT_vline, x, y, 0, 0);
|
|
2712
|
+
}
|
|
2713
|
+
was_off = 0;
|
|
2714
|
+
}
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
vertices.length = stbtt__close_shape(vertices, num_vertices, was_off, start_off,
|
|
2718
|
+
sx, sy, scx, scy, cx, cy);
|
|
2719
|
+
} else if (numberOfContours == -1) {
|
|
2720
|
+
var more = 1;
|
|
2721
|
+
var comp = g + 10;
|
|
2722
|
+
while (more) {
|
|
2723
|
+
var flags, gidx, mtx = [ 1, 0, 0, 1, 0, 0 ];
|
|
2724
|
+
|
|
2725
|
+
flags = ttSHORT(data, comp);
|
|
2726
|
+
comp += 2;
|
|
2727
|
+
gidx = ttSHORT(data, comp);
|
|
2728
|
+
comp += 2;
|
|
2729
|
+
|
|
2730
|
+
if (flags & 2) {
|
|
2731
|
+
if (flags & 1) {
|
|
2732
|
+
mtx[4] = ttSHORT(data, comp);
|
|
2733
|
+
comp += 2;
|
|
2734
|
+
mtx[5] = ttSHORT(data, comp);
|
|
2735
|
+
comp += 2;
|
|
2736
|
+
} else {
|
|
2737
|
+
mtx[4] = stbtt__buf_get8(data, comp);
|
|
2738
|
+
comp += 1;
|
|
2739
|
+
mtx[5] = stbtt__buf_get8(data, comp);
|
|
2740
|
+
comp += 1;
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2743
|
+
if (flags & (1 << 3)) {
|
|
2744
|
+
mtx[0] = mtx[3] = ttSHORT(data, comp) / 16384.0;
|
|
2745
|
+
comp += 2;
|
|
2746
|
+
mtx[1] = mtx[2] = 0;
|
|
2747
|
+
} else if (flags & (1 << 6)) {
|
|
2748
|
+
mtx[0] = ttSHORT(data, comp) / 16384.0;
|
|
2749
|
+
comp += 2;
|
|
2750
|
+
mtx[1] = mtx[2] = 0;
|
|
2751
|
+
mtx[3] = ttSHORT(data, comp) / 16384.0;
|
|
2752
|
+
comp += 2;
|
|
2753
|
+
} else if (flags & (1 << 7)) {
|
|
2754
|
+
mtx[0] = ttSHORT(data, comp) / 16384.0;
|
|
2755
|
+
comp += 2;
|
|
2756
|
+
mtx[1] = ttSHORT(data, comp) / 16384.0;
|
|
2757
|
+
comp += 2;
|
|
2758
|
+
mtx[2] = ttSHORT(data, comp) / 16384.0;
|
|
2759
|
+
comp += 2;
|
|
2760
|
+
mtx[3] = ttSHORT(data, comp) / 16384.0;
|
|
2761
|
+
comp += 2;
|
|
2762
|
+
}
|
|
2763
|
+
|
|
2764
|
+
var m = sqrt(mtx[0] * mtx[0] + mtx[1] * mtx[1]);
|
|
2765
|
+
var n = sqrt(mtx[2] * mtx[2] + mtx[3] * mtx[3]);
|
|
2766
|
+
var comp_verts = stbtt_GetGlyphShape(info, gidx);
|
|
2767
|
+
if (comp_verts.length > 0) {
|
|
2768
|
+
for (var i = 0, l = comp_verts.length; i < l; ++i) {
|
|
2769
|
+
var v = comp_verts[i], x, y;
|
|
2770
|
+
x = v.x;
|
|
2771
|
+
y = v.y;
|
|
2772
|
+
v.x = floor(m * (mtx[0] * x + mtx[2] * y + mtx[4]));
|
|
2773
|
+
v.y = floor(n * (mtx[1] * x + mtx[3] * y + mtx[5]));
|
|
2774
|
+
x = v.cx;
|
|
2775
|
+
y = v.cy;
|
|
2776
|
+
v.cx = floor(m * (mtx[0] * x + mtx[2] * y + mtx[4]));
|
|
2777
|
+
v.cy = floor(n * (mtx[1] * x + mtx[3] * y + mtx[5]));
|
|
2778
|
+
}
|
|
2779
|
+
|
|
2780
|
+
vertices = vertices.concat(comp_verts);
|
|
2781
|
+
}
|
|
2782
|
+
more = flags & (1 << 5);
|
|
2783
|
+
}
|
|
2784
|
+
}
|
|
2785
|
+
//console.log('vertices(' + vertices.length + ')');
|
|
2786
|
+
//for (var i = 0; i < vertices.length; i++) {
|
|
2787
|
+
// var pt = vertices[i];
|
|
2788
|
+
// console.log(`${i}: ${pt.x},${pt.y} / ${pt.cx},${pt.cy} / ${pt.type}`);
|
|
2789
|
+
//}
|
|
2790
|
+
|
|
2791
|
+
return vertices;
|
|
2792
|
+
}
|
|
2793
|
+
|
|
2794
|
+
//static void stbtt__track_vertex(stbtt__csctx * c, int x, int y)
|
|
2795
|
+
function stbtt__track_vertex(c, x, y) {
|
|
2796
|
+
if (x > c.max_x || !c.started) {
|
|
2797
|
+
c.max_x = x;
|
|
2798
|
+
}
|
|
2799
|
+
if (y > c.max_y || !c.started) {
|
|
2800
|
+
c.max_y = y;
|
|
2801
|
+
}
|
|
2802
|
+
if (x < c.min_x || !c.started) {
|
|
2803
|
+
c.min_x = x;
|
|
2804
|
+
}
|
|
2805
|
+
if (y < c.min_y || !c.started) {
|
|
2806
|
+
c.min_y = y;
|
|
2807
|
+
}
|
|
2808
|
+
c.started = 1;
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2811
|
+
//static void stbtt__csctx_v(stbtt__csctx * c, unsigned char type, int x, int y, int cx, int cy, int cx1, int cy1)
|
|
2812
|
+
function stbtt__csctx_v(c, type, x, y, cx, cy, cx1, cy1) {
|
|
2813
|
+
stbtt__track_vertex(c, x, y);
|
|
2814
|
+
if (type == STBTT_vcubic) {
|
|
2815
|
+
stbtt__track_vertex(c, cx, cy);
|
|
2816
|
+
stbtt__track_vertex(c, cx1, cy1);
|
|
2817
|
+
}
|
|
2818
|
+
var v = {};
|
|
2819
|
+
stbtt_setvertex(v, type, x, y, cx, cy);
|
|
2820
|
+
v.cx1 = cx1;
|
|
2821
|
+
v.cy1 = cy1;
|
|
2822
|
+
c.vertices.push(v);
|
|
2823
|
+
}
|
|
2824
|
+
|
|
2825
|
+
//static void stbtt__csctx_close_shape(stbtt__csctx * ctx)
|
|
2826
|
+
function stbtt__csctx_close_shape(ctx) {
|
|
2827
|
+
if (ctx.first_x != ctx.x || ctx.first_y != ctx.y) {
|
|
2828
|
+
stbtt__csctx_v(ctx, STBTT_vline, ctx.first_x, ctx.first_y, 0, 0, 0, 0);
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2831
|
+
|
|
2832
|
+
//static void stbtt__csctx_rmove_to(stbtt__csctx * ctx, float dx, float dy)
|
|
2833
|
+
function stbtt__csctx_rmove_to(ctx, dx, dy) {
|
|
2834
|
+
stbtt__csctx_close_shape(ctx);
|
|
2835
|
+
ctx.first_x = ctx.x = ctx.x + dx;
|
|
2836
|
+
ctx.first_y = ctx.y = ctx.y + dy;
|
|
2837
|
+
stbtt__csctx_v(ctx, STBTT_vmove, ctx.x, ctx.y, 0, 0, 0, 0);
|
|
2838
|
+
}
|
|
2839
|
+
|
|
2840
|
+
//static void stbtt__csctx_rline_to(stbtt__csctx * ctx, float dx, float dy)
|
|
2841
|
+
function stbtt__csctx_rline_to(ctx, dx, dy) {
|
|
2842
|
+
ctx.x += dx;
|
|
2843
|
+
ctx.y += dy;
|
|
2844
|
+
stbtt__csctx_v(ctx, STBTT_vline, ctx.x, ctx.y, 0, 0, 0, 0);
|
|
2845
|
+
}
|
|
2846
|
+
|
|
2847
|
+
//static void stbtt__csctx_rccurve_to(stbtt__csctx * ctx, float dx1, float dy1, float dx2,
|
|
2848
|
+
// float dy2, float dx3, float dy3)
|
|
2849
|
+
function stbtt__csctx_rccurve_to(ctx, dx1, dy1, dx2, dy2, dx3, dy3) {
|
|
2850
|
+
var cx1 = ctx.x + dx1,
|
|
2851
|
+
cy1 = ctx.y + dy1,
|
|
2852
|
+
cx2 = cx1 + dx2,
|
|
2853
|
+
cy2 = cy1 + dy2;
|
|
2854
|
+
ctx.x = cx2 + dx3;
|
|
2855
|
+
ctx.y = cy2 + dy3;
|
|
2856
|
+
stbtt__csctx_v(ctx, STBTT_vcubic, ctx.x, ctx.y, cx1, cy1, cx2, cy2);
|
|
2857
|
+
}
|
|
2858
|
+
|
|
2859
|
+
//static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n)
|
|
2860
|
+
function stbtt__get_subr(b, n) {
|
|
2861
|
+
var count = stbtt__cff_index_count(b);
|
|
2862
|
+
var bias = 107;
|
|
2863
|
+
if (count >= 33900) {
|
|
2864
|
+
bias = 32768;
|
|
2865
|
+
} else if (count >= 1240) {
|
|
2866
|
+
bias = 1131;
|
|
2867
|
+
}
|
|
2868
|
+
n += bias;
|
|
2869
|
+
if (n < 0 || n >= count) {
|
|
2870
|
+
return stbtt__null_buf();
|
|
2871
|
+
}
|
|
2872
|
+
return stbtt__cff_index_get(b, n);
|
|
2873
|
+
}
|
|
2874
|
+
|
|
2875
|
+
//static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo * info, int glyph_index)
|
|
2876
|
+
function stbtt__cid_get_glyph_subrs(info, glyph_index) {
|
|
2877
|
+
var fdselect = info.fdselect;
|
|
2878
|
+
var nranges, start, end, v, fmt, fdselector = -1, i;
|
|
2879
|
+
|
|
2880
|
+
stbtt__buf_seek(fdselect, 0);
|
|
2881
|
+
fmt = stbtt__buf_get8(fdselect);
|
|
2882
|
+
if (fmt == 0) {
|
|
2883
|
+
stbtt__buf_skip(fdselect, glyph_index);
|
|
2884
|
+
fdselector = stbtt__buf_get8(fdselect);
|
|
2885
|
+
} else if (fmt == 3) {
|
|
2886
|
+
nranges = stbtt__buf_get(fdselect, 2);
|
|
2887
|
+
start = stbtt__buf_get(fdselect, 2);
|
|
2888
|
+
for (i = 0; i < nranges; i++) {
|
|
2889
|
+
v = stbtt__buf_get8(fdselect);
|
|
2890
|
+
end = stbtt__buf_get(fdselect, 2);
|
|
2891
|
+
if (glyph_index >= start && glyph_index < end) {
|
|
2892
|
+
fdselector = v;
|
|
2893
|
+
break;
|
|
2894
|
+
}
|
|
2895
|
+
start = end;
|
|
2896
|
+
}
|
|
2897
|
+
}
|
|
2898
|
+
if (fdselector == -1) {
|
|
2899
|
+
stbtt__null_buf();
|
|
2900
|
+
}
|
|
2901
|
+
return stbtt__get_subrs(info.cff, stbtt__cff_index_get(info.fontdicts, fdselector));
|
|
2902
|
+
}
|
|
2903
|
+
|
|
2904
|
+
//static int stbtt__run_charstring(const stbtt_fontinfo * info, int glyph_index,
|
|
2905
|
+
// stbtt__csctx * c)
|
|
2906
|
+
function stbtt__run_charstring(info, glyph_index, c) {
|
|
2907
|
+
var in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0,
|
|
2908
|
+
has_subrs = 0, clear_stack,
|
|
2909
|
+
s = [], subr_stack = [], subrs = info.subrs, b, f;
|
|
2910
|
+
|
|
2911
|
+
b = stbtt__cff_index_get(info.charstrings, glyph_index);
|
|
2912
|
+
while (b.cursor < b.length) {
|
|
2913
|
+
i = 0;
|
|
2914
|
+
clear_stack = 1;
|
|
2915
|
+
b0 = stbtt__buf_get8(b);
|
|
2916
|
+
switch (b0) {
|
|
2917
|
+
case 0x13:
|
|
2918
|
+
case 0x14:
|
|
2919
|
+
if (in_header) {
|
|
2920
|
+
maskbits += (sp / 2)|0;
|
|
2921
|
+
}
|
|
2922
|
+
in_header = 0;
|
|
2923
|
+
stbtt__buf_skip(b, ((maskbits + 7) / 8)|0);
|
|
2924
|
+
break;
|
|
2925
|
+
|
|
2926
|
+
case 0x01:
|
|
2927
|
+
case 0x03:
|
|
2928
|
+
case 0x12:
|
|
2929
|
+
case 0x17:
|
|
2930
|
+
maskbits += (sp / 2)|0;
|
|
2931
|
+
break;
|
|
2932
|
+
|
|
2933
|
+
case 0x15:
|
|
2934
|
+
in_header = 0;
|
|
2935
|
+
if (sp < 2) {
|
|
2936
|
+
return 0;
|
|
2937
|
+
}
|
|
2938
|
+
stbtt__csctx_rmove_to(c, s[sp - 2], s[sp - 1]);
|
|
2939
|
+
break;
|
|
2940
|
+
case 0x04:
|
|
2941
|
+
in_header = 0;
|
|
2942
|
+
if (sp < 1) {
|
|
2943
|
+
return 0;
|
|
2944
|
+
}
|
|
2945
|
+
stbtt__csctx_rmove_to(c, 0, s[sp - 1]);
|
|
2946
|
+
break;
|
|
2947
|
+
case 0x16:
|
|
2948
|
+
in_header = 0;
|
|
2949
|
+
if (sp < 1) {
|
|
2950
|
+
return 0;
|
|
2951
|
+
}
|
|
2952
|
+
stbtt__csctx_rmove_to(c, s[sp - 1], 0);
|
|
2953
|
+
break;
|
|
2954
|
+
|
|
2955
|
+
case 0x05:
|
|
2956
|
+
if (sp < 2) {
|
|
2957
|
+
return 0;
|
|
2958
|
+
}
|
|
2959
|
+
for (; i + 1 < sp; i += 2) {
|
|
2960
|
+
stbtt__csctx_rline_to(c, s[i], s[i + 1]);
|
|
2961
|
+
}
|
|
2962
|
+
break;
|
|
2963
|
+
|
|
2964
|
+
case 0x07:
|
|
2965
|
+
if (sp < 1) {
|
|
2966
|
+
return 0;
|
|
2967
|
+
}
|
|
2968
|
+
for (;;) {
|
|
2969
|
+
if (i >= sp) {
|
|
2970
|
+
break;
|
|
2971
|
+
}
|
|
2972
|
+
stbtt__csctx_rline_to(c, 0, s[i]);
|
|
2973
|
+
i++;
|
|
2974
|
+
if (i >= sp) {
|
|
2975
|
+
break;
|
|
2976
|
+
}
|
|
2977
|
+
stbtt__csctx_rline_to(c, s[i], 0);
|
|
2978
|
+
i++;
|
|
2979
|
+
}
|
|
2980
|
+
break;
|
|
2981
|
+
case 0x06:
|
|
2982
|
+
if (sp < 1) {
|
|
2983
|
+
return 0;
|
|
2984
|
+
}
|
|
2985
|
+
for (;;) {
|
|
2986
|
+
if (i >= sp) {
|
|
2987
|
+
break;
|
|
2988
|
+
}
|
|
2989
|
+
stbtt__csctx_rline_to(c, s[i], 0);
|
|
2990
|
+
i++;
|
|
2991
|
+
if (i >= sp) {
|
|
2992
|
+
break;
|
|
2993
|
+
}
|
|
2994
|
+
stbtt__csctx_rline_to(c, 0, s[i]);
|
|
2995
|
+
i++;
|
|
2996
|
+
}
|
|
2997
|
+
break;
|
|
2998
|
+
|
|
2999
|
+
case 0x1F:
|
|
3000
|
+
if (sp < 4) {
|
|
3001
|
+
return 0;
|
|
3002
|
+
}
|
|
3003
|
+
for (;;) {
|
|
3004
|
+
if (i + 3 >= sp) {
|
|
3005
|
+
break;
|
|
3006
|
+
}
|
|
3007
|
+
stbtt__csctx_rccurve_to(c, s[i], 0, s[i + 1], s[i + 2],
|
|
3008
|
+
(sp - i == 5) ? s[i + 4] : 0.0,
|
|
3009
|
+
s[i + 3]);
|
|
3010
|
+
i += 4;
|
|
3011
|
+
if (i + 3 >= sp) {
|
|
3012
|
+
break;
|
|
3013
|
+
}
|
|
3014
|
+
stbtt__csctx_rccurve_to(c, 0, s[i], s[i + 1],
|
|
3015
|
+
s[i + 2], s[i + 3],
|
|
3016
|
+
(sp - i == 5) ? s[i + 4] : 0.0);
|
|
3017
|
+
i += 4;
|
|
3018
|
+
}
|
|
3019
|
+
break;
|
|
3020
|
+
case 0x1E:
|
|
3021
|
+
if (sp < 4) {
|
|
3022
|
+
return 0;
|
|
3023
|
+
}
|
|
3024
|
+
for (;;) {
|
|
3025
|
+
if (i + 3 >= sp) {
|
|
3026
|
+
break;
|
|
3027
|
+
}
|
|
3028
|
+
stbtt__csctx_rccurve_to(c, 0, s[i], s[i + 1],
|
|
3029
|
+
s[i + 2], s[i + 3],
|
|
3030
|
+
(sp - i == 5) ? s[i + 4] : 0.0);
|
|
3031
|
+
i += 4;
|
|
3032
|
+
if (i + 3 >= sp) {
|
|
3033
|
+
break;
|
|
3034
|
+
}
|
|
3035
|
+
stbtt__csctx_rccurve_to(c, s[i], 0, s[i + 1], s[i + 2],
|
|
3036
|
+
(sp - i == 5) ? s[i + 4] : 0.0,
|
|
3037
|
+
s[i + 3]);
|
|
3038
|
+
i += 4;
|
|
3039
|
+
}
|
|
3040
|
+
break;
|
|
3041
|
+
|
|
3042
|
+
case 0x08:
|
|
3043
|
+
if (sp < 6) {
|
|
3044
|
+
return 0;
|
|
3045
|
+
}
|
|
3046
|
+
for (; i + 5 < sp; i += 6) {
|
|
3047
|
+
stbtt__csctx_rccurve_to(c, s[i], s[i + 1],
|
|
3048
|
+
s[i + 2], s[i + 3],
|
|
3049
|
+
s[i + 4], s[i + 5]);
|
|
3050
|
+
}
|
|
3051
|
+
break;
|
|
3052
|
+
|
|
3053
|
+
case 0x18:
|
|
3054
|
+
if (sp < 8) {
|
|
3055
|
+
return 0;
|
|
3056
|
+
}
|
|
3057
|
+
for (; i + 5 < sp - 2; i += 6) {
|
|
3058
|
+
stbtt__csctx_rccurve_to(c, s[i], s[i + 1],
|
|
3059
|
+
s[i + 2], s[i + 3],
|
|
3060
|
+
s[i + 4], s[i + 5]);
|
|
3061
|
+
}
|
|
3062
|
+
if (i + 1 >= sp) {
|
|
3063
|
+
return 0;
|
|
3064
|
+
}
|
|
3065
|
+
stbtt__csctx_rline_to(c, s[i], s[i + 1]);
|
|
3066
|
+
break;
|
|
3067
|
+
|
|
3068
|
+
case 0x19:
|
|
3069
|
+
if (sp < 8) {
|
|
3070
|
+
return 0;
|
|
3071
|
+
}
|
|
3072
|
+
for (; i + 1 < sp - 6; i += 2) {
|
|
3073
|
+
stbtt__csctx_rline_to(c, s[i], s[i + 1]);
|
|
3074
|
+
}
|
|
3075
|
+
if (i + 5 >= sp) {
|
|
3076
|
+
return 0;
|
|
3077
|
+
}
|
|
3078
|
+
stbtt__csctx_rccurve_to(c, s[i], s[i + 1], s[i + 2],
|
|
3079
|
+
s[i + 3], s[i + 4], s[i + 5]);
|
|
3080
|
+
break;
|
|
3081
|
+
|
|
3082
|
+
case 0x1A:
|
|
3083
|
+
case 0x1B:
|
|
3084
|
+
if (sp < 4) {
|
|
3085
|
+
return 0;
|
|
3086
|
+
}
|
|
3087
|
+
f = 0.0;
|
|
3088
|
+
if (sp & 1) {
|
|
3089
|
+
f = s[i];
|
|
3090
|
+
i++;
|
|
3091
|
+
}
|
|
3092
|
+
for (; i + 3 < sp; i += 4) {
|
|
3093
|
+
if (b0 == 0x1B) {
|
|
3094
|
+
stbtt__csctx_rccurve_to(c, s[i], f,
|
|
3095
|
+
s[i + 1],
|
|
3096
|
+
s[i + 2],
|
|
3097
|
+
s[i + 3], 0.0);
|
|
3098
|
+
} else {
|
|
3099
|
+
stbtt__csctx_rccurve_to(c, f, s[i],
|
|
3100
|
+
s[i + 1],
|
|
3101
|
+
s[i + 2], 0.0,
|
|
3102
|
+
s[i + 3]);
|
|
3103
|
+
}
|
|
3104
|
+
f = 0.0;
|
|
3105
|
+
}
|
|
3106
|
+
break;
|
|
3107
|
+
|
|
3108
|
+
case 0x0A:
|
|
3109
|
+
if (!has_subrs) {
|
|
3110
|
+
if (info.fdselect.length) {
|
|
3111
|
+
subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
|
|
3112
|
+
}
|
|
3113
|
+
has_subrs = 1;
|
|
3114
|
+
}
|
|
3115
|
+
|
|
3116
|
+
case 0x1D:
|
|
3117
|
+
if (sp < 1) {
|
|
3118
|
+
return 0;
|
|
3119
|
+
}
|
|
3120
|
+
v = s[--sp]|0;
|
|
3121
|
+
if (subr_stack_height >= 10) {
|
|
3122
|
+
return 0;
|
|
3123
|
+
}
|
|
3124
|
+
subr_stack[subr_stack_height++] = b;
|
|
3125
|
+
b = stbtt__get_subr(b0 == 0x0A ? subrs : info.gsubrs, v);
|
|
3126
|
+
if (b.length == 0) {
|
|
3127
|
+
return 0;
|
|
3128
|
+
}
|
|
3129
|
+
b.cursor = 0;
|
|
3130
|
+
clear_stack = 0;
|
|
3131
|
+
break;
|
|
3132
|
+
|
|
3133
|
+
case 0x0B:
|
|
3134
|
+
if (subr_stack_height <= 0) {
|
|
3135
|
+
return 0;
|
|
3136
|
+
}
|
|
3137
|
+
b = subr_stack[--subr_stack_height];
|
|
3138
|
+
clear_stack = 0;
|
|
3139
|
+
break;
|
|
3140
|
+
|
|
3141
|
+
case 0x0E:
|
|
3142
|
+
stbtt__csctx_close_shape(c);
|
|
3143
|
+
return 1;
|
|
3144
|
+
|
|
3145
|
+
case 0x0C:
|
|
3146
|
+
var dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6,
|
|
3147
|
+
dx, dy, b1 = stbtt__buf_get8(b);
|
|
3148
|
+
switch (b1) {
|
|
3149
|
+
case 0x22:
|
|
3150
|
+
if (sp < 7) {
|
|
3151
|
+
return 0;
|
|
3152
|
+
}
|
|
3153
|
+
dx1 = s[0];
|
|
3154
|
+
dx2 = s[1];
|
|
3155
|
+
dy2 = s[2];
|
|
3156
|
+
dx3 = s[3];
|
|
3157
|
+
dx4 = s[4];
|
|
3158
|
+
dx5 = s[5];
|
|
3159
|
+
dx6 = s[6];
|
|
3160
|
+
stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0);
|
|
3161
|
+
stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0);
|
|
3162
|
+
break;
|
|
3163
|
+
|
|
3164
|
+
case 0x23:
|
|
3165
|
+
if (sp < 13) {
|
|
3166
|
+
return 0;
|
|
3167
|
+
}
|
|
3168
|
+
dx1 = s[0];
|
|
3169
|
+
dy1 = s[1];
|
|
3170
|
+
dx2 = s[2];
|
|
3171
|
+
dy2 = s[3];
|
|
3172
|
+
dx3 = s[4];
|
|
3173
|
+
dy3 = s[5];
|
|
3174
|
+
dx4 = s[6];
|
|
3175
|
+
dy4 = s[7];
|
|
3176
|
+
dx5 = s[8];
|
|
3177
|
+
dy5 = s[9];
|
|
3178
|
+
dx6 = s[10];
|
|
3179
|
+
dy6 = s[11];
|
|
3180
|
+
|
|
3181
|
+
stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
|
|
3182
|
+
stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
|
|
3183
|
+
break;
|
|
3184
|
+
|
|
3185
|
+
case 0x24:
|
|
3186
|
+
if (sp < 9) {
|
|
3187
|
+
return 0;
|
|
3188
|
+
}
|
|
3189
|
+
dx1 = s[0];
|
|
3190
|
+
dy1 = s[1];
|
|
3191
|
+
dx2 = s[2];
|
|
3192
|
+
dy2 = s[3];
|
|
3193
|
+
dx3 = s[4];
|
|
3194
|
+
dx4 = s[5];
|
|
3195
|
+
dx5 = s[6];
|
|
3196
|
+
dy5 = s[7];
|
|
3197
|
+
dx6 = s[8];
|
|
3198
|
+
stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0);
|
|
3199
|
+
stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1 + dy2 + dy5));
|
|
3200
|
+
break;
|
|
3201
|
+
|
|
3202
|
+
case 0x25:
|
|
3203
|
+
if (sp < 11) {
|
|
3204
|
+
return 0;
|
|
3205
|
+
}
|
|
3206
|
+
dx1 = s[0];
|
|
3207
|
+
dy1 = s[1];
|
|
3208
|
+
dx2 = s[2];
|
|
3209
|
+
dy2 = s[3];
|
|
3210
|
+
dx3 = s[4];
|
|
3211
|
+
dy3 = s[5];
|
|
3212
|
+
dx4 = s[6];
|
|
3213
|
+
dy4 = s[7];
|
|
3214
|
+
dx5 = s[8];
|
|
3215
|
+
dy5 = s[9];
|
|
3216
|
+
dx6 = dy6 = s[10];
|
|
3217
|
+
dx = dx1 + dx2 + dx3 + dx4 + dx5;
|
|
3218
|
+
dy = dy1 + dy2 + dy3 + dy4 + dy5;
|
|
3219
|
+
if (abs(dx) > abs(dy)) {
|
|
3220
|
+
dy6 = -dy;
|
|
3221
|
+
} else {
|
|
3222
|
+
dx6 = -dx;
|
|
3223
|
+
}
|
|
3224
|
+
stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
|
|
3225
|
+
stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
|
|
3226
|
+
break;
|
|
3227
|
+
|
|
3228
|
+
default:
|
|
3229
|
+
return 0;
|
|
3230
|
+
}
|
|
3231
|
+
break;
|
|
3232
|
+
|
|
3233
|
+
default:
|
|
3234
|
+
if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254)) {
|
|
3235
|
+
return 0;
|
|
3236
|
+
}
|
|
3237
|
+
if (b0 == 255) {
|
|
3238
|
+
// f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000;
|
|
3239
|
+
f = (stbtt__buf_get(b, 4)|0) / 0x10000;
|
|
3240
|
+
} else {
|
|
3241
|
+
stbtt__buf_skip(b, -1);
|
|
3242
|
+
// f = (float)(stbtt_int16)stbtt__cff_int(&b);
|
|
3243
|
+
f = ((stbtt__cff_int(b)<<16)|0)>>16;
|
|
3244
|
+
}
|
|
3245
|
+
if (sp >= 48) {
|
|
3246
|
+
return 0;
|
|
3247
|
+
}
|
|
3248
|
+
s[sp++] = f;
|
|
3249
|
+
clear_stack = 0;
|
|
3250
|
+
break;
|
|
3251
|
+
}
|
|
3252
|
+
if (clear_stack) {
|
|
3253
|
+
sp = 0;
|
|
3254
|
+
}
|
|
3255
|
+
}
|
|
3256
|
+
return 0;
|
|
3257
|
+
}
|
|
3258
|
+
|
|
3259
|
+
function stbtt__csctx_init() {
|
|
3260
|
+
return { started:0, first_x:0, first_y:0, x:0, y:0,
|
|
3261
|
+
min_x:0, max_x:0, min_y:0, max_y:0,
|
|
3262
|
+
vertices:[]
|
|
3263
|
+
};
|
|
3264
|
+
}
|
|
3265
|
+
|
|
3266
|
+
//static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo * info, int glyph_index,
|
|
3267
|
+
// stbtt_vertex ** pvertices)
|
|
3268
|
+
function stbtt__GetGlyphShapeT2(info, glyph_index) {
|
|
3269
|
+
var output_ctx = stbtt__csctx_init();
|
|
3270
|
+
if (stbtt__run_charstring(info, glyph_index, output_ctx)) {
|
|
3271
|
+
return output_ctx.vertices;
|
|
3272
|
+
}
|
|
3273
|
+
return null;
|
|
3274
|
+
}
|
|
3275
|
+
|
|
3276
|
+
//static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo * info, int glyph_index, int *x0,
|
|
3277
|
+
// int *y0, int *x1, int *y1)
|
|
3278
|
+
function stbtt__GetGlyphInfoT2(info, glyph_index, out) {
|
|
3279
|
+
var c = stbtt__csctx_init();
|
|
3280
|
+
var r = stbtt__run_charstring(info, glyph_index, c);
|
|
3281
|
+
out.x0 = r ? c.min_x : 0;
|
|
3282
|
+
out.y0 = r ? c.min_y : 0;
|
|
3283
|
+
out.x1 = r ? c.max_x : 0;
|
|
3284
|
+
out.y1 = r ? c.max_y : 0;
|
|
3285
|
+
return r && c.vertices ? c.vertices.length : 0;
|
|
3286
|
+
}
|
|
3287
|
+
|
|
3288
|
+
//extern int stbtt_GetGlyphShape(const stbtt_fontinfo * info, int glyph_index,
|
|
3289
|
+
// stbtt_vertex ** pvertices)
|
|
3290
|
+
function stbtt_GetGlyphShape(info, glyph_index) {
|
|
3291
|
+
if (!info.cff.length) {
|
|
3292
|
+
return stbtt__GetGlyphShapeTT(info, glyph_index);
|
|
3293
|
+
} else {
|
|
3294
|
+
return stbtt__GetGlyphShapeT2(info, glyph_index);
|
|
3295
|
+
}
|
|
3296
|
+
}
|
|
3297
|
+
|
|
3298
|
+
//extern void stbtt_GetGlyphHMetrics(const stbtt_fontinfo * info, int glyph_index,
|
|
3299
|
+
// int *advanceWidth, int *leftSideBearing)
|
|
3300
|
+
function stbtt_GetGlyphHMetrics(info, glyph_index) {
|
|
3301
|
+
var numOfLongHorMetrics = ttUSHORT(info.data, info.hhea + 34);
|
|
3302
|
+
if (glyph_index < numOfLongHorMetrics) {
|
|
3303
|
+
return {
|
|
3304
|
+
advanceWidth: ttSHORT(info.data, info.hmtx + 4 * glyph_index),
|
|
3305
|
+
leftSideBearing:ttSHORT(info.data, info.hmtx + 4 * glyph_index + 2)
|
|
3306
|
+
};
|
|
3307
|
+
} else {
|
|
3308
|
+
return {
|
|
3309
|
+
advanceWidth: ttSHORT(info.data, info.hmtx + 4 * (numOfLongHorMetrics - 1)),
|
|
3310
|
+
leftSideBearing:ttSHORT(info.data, info.hmtx + 4 * numOfLongHorMetrics +
|
|
3311
|
+
2 * (glyph_index - numOfLongHorMetrics))
|
|
3312
|
+
};
|
|
3313
|
+
}
|
|
3314
|
+
}
|
|
3315
|
+
|
|
3316
|
+
//extern void stbtt_GetCodepointHMetrics(const stbtt_fontinfo * info, int codepoint,
|
|
3317
|
+
// int *advanceWidth, int *leftSideBearing)
|
|
3318
|
+
function stbtt_GetCodepointHMetrics(info, codepoint) {
|
|
3319
|
+
return stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info, codepoint));
|
|
3320
|
+
}
|
|
3321
|
+
|
|
3322
|
+
//extern void stbtt_GetFontVMetrics(const stbtt_fontinfo * info, int *ascent, int *descent, int *lineGap)
|
|
3323
|
+
function stbtt_GetFontVMetrics(info) {
|
|
3324
|
+
return {
|
|
3325
|
+
ascent: ttSHORT(info.data, info.hhea + 4),
|
|
3326
|
+
descent:ttSHORT(info.data, info.hhea + 6),
|
|
3327
|
+
linegap:ttSHORT(info.data, info.hhea + 8),
|
|
3328
|
+
};
|
|
3329
|
+
}
|
|
3330
|
+
|
|
3331
|
+
//extern void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo * font, int glyph,
|
|
3332
|
+
// float scale_x, float scale_y, float shift_x, float shift_y,
|
|
3333
|
+
// int *ix0, int *iy0, int *ix1, int *iy1)
|
|
3334
|
+
function stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y, shift_x, shift_y) {
|
|
3335
|
+
var tmp = {};
|
|
3336
|
+
if (!stbtt_GetGlyphBox(font, glyph, tmp)) {
|
|
3337
|
+
return { x0:0, y0:0, x1:0, y1:0 };
|
|
3338
|
+
}
|
|
3339
|
+
return {
|
|
3340
|
+
x0:floor(tmp.x0 * scale_x + shift_x),
|
|
3341
|
+
y0:floor(-tmp.y1 * scale_y + shift_y),
|
|
3342
|
+
x1:ceil(tmp.x1 * scale_x + shift_x),
|
|
3343
|
+
y1:ceil(-tmp.y0 * scale_y + shift_y),
|
|
3344
|
+
};
|
|
3345
|
+
}
|
|
3346
|
+
|
|
3347
|
+
//extern void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo * font,
|
|
3348
|
+
// int codepoint, float scale_x, float scale_y, float shift_x,
|
|
3349
|
+
// float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
|
|
3350
|
+
function stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y, shift_x, shift_y) {
|
|
3351
|
+
return stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font, codepoint),
|
|
3352
|
+
scale_x, scale_y, shift_x, shift_y);
|
|
3353
|
+
}
|
|
3354
|
+
|
|
3355
|
+
//extern void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo * font, int codepoint, float scale_x, float scale_y,
|
|
3356
|
+
// int *ix0, int *iy0, int *ix1, int *iy1)
|
|
3357
|
+
function stbtt_GetCodepointBitmapBox(font, codepoint, scale_x, scale_y) {
|
|
3358
|
+
return stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y, 0, 0);
|
|
3359
|
+
}
|
|
3360
|
+
|
|
3361
|
+
//static stbtt__active_edge *stbtt__new_active(stbtt__hheap * hh, stbtt__edge * e, int off_x, float start_point, void *userdata)
|
|
3362
|
+
function stbtt__new_active(e, off_x, start_point) {
|
|
3363
|
+
var dxdy = (e.x1 - e.x0) / (e.y1 - e.y0);
|
|
3364
|
+
return {
|
|
3365
|
+
fdx:dxdy,
|
|
3366
|
+
fdy:dxdy != 0.0 ? (1.0 / dxdy) : 0.0,
|
|
3367
|
+
fx:(e.x0 + dxdy * (start_point - e.y0)) - (off_x|0),
|
|
3368
|
+
direction:e.invert ? 1.0 : -1.0,
|
|
3369
|
+
sy:e.y0,
|
|
3370
|
+
ey:e.y1,
|
|
3371
|
+
next:0,
|
|
3372
|
+
};
|
|
3373
|
+
}
|
|
3374
|
+
|
|
3375
|
+
//static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge * e,
|
|
3376
|
+
// float x0, float y0, float x1, float y1)
|
|
3377
|
+
function stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x1, y1) {
|
|
3378
|
+
x = x|0;
|
|
3379
|
+
if (y0 == y1) {
|
|
3380
|
+
return;
|
|
3381
|
+
}
|
|
3382
|
+
if (y0 > e.ey) {
|
|
3383
|
+
return;
|
|
3384
|
+
}
|
|
3385
|
+
if (y1 < e.sy) {
|
|
3386
|
+
return;
|
|
3387
|
+
}
|
|
3388
|
+
if (y0 < e.sy) {
|
|
3389
|
+
x0 += (x1 - x0) * (e.sy - y0) / (y1 - y0);
|
|
3390
|
+
y0 = e.sy;
|
|
3391
|
+
}
|
|
3392
|
+
if (y1 > e.ey) {
|
|
3393
|
+
x1 += (x1 - x0) * (e.ey - y1) / (y1 - y0);
|
|
3394
|
+
y1 = e.ey;
|
|
3395
|
+
}
|
|
3396
|
+
|
|
3397
|
+
if (x0 <= x && x1 <= x) {
|
|
3398
|
+
scanline[x] += e.direction * (y1 - y0);
|
|
3399
|
+
} else if (x0 >= x + 1 && x1 >= x + 1) {
|
|
3400
|
+
|
|
3401
|
+
} else {
|
|
3402
|
+
scanline[x] += e.direction * (y1 - y0) * (1 - ((x0 - x) + (x1 - x)) / 2);
|
|
3403
|
+
}
|
|
3404
|
+
}
|
|
3405
|
+
|
|
3406
|
+
//static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len,
|
|
3407
|
+
// stbtt__active_edge * e, float y_top)
|
|
3408
|
+
// The C implementation passed scanline_fill as a +1 pointer on the call, and then -1 in
|
|
3409
|
+
// places in this function. That doesn't work with array-views, so we reverse the handling.
|
|
3410
|
+
function stbtt__fill_active_edges_new(scanline, scanline_fill, len, e, y_top) {
|
|
3411
|
+
var y_bottom = y_top + 1;
|
|
3412
|
+
while (e) {
|
|
3413
|
+
if (e.fdx == 0) {
|
|
3414
|
+
var x0 = e.fx;
|
|
3415
|
+
if (x0 < len) {
|
|
3416
|
+
if (x0 >= 0) {
|
|
3417
|
+
stbtt__handle_clipped_edge(scanline, x0, e, x0, y_top, x0, y_bottom);
|
|
3418
|
+
stbtt__handle_clipped_edge(scanline_fill, x0+1, e, x0, y_top, x0, y_bottom);
|
|
3419
|
+
} else {
|
|
3420
|
+
stbtt__handle_clipped_edge(scanline_fill, 0, e, x0, y_top, x0, y_bottom);
|
|
3421
|
+
}
|
|
3422
|
+
}
|
|
3423
|
+
} else {
|
|
3424
|
+
var x0 = e.fx,
|
|
3425
|
+
dx = e.fdx,
|
|
3426
|
+
xb = x0 + dx,
|
|
3427
|
+
x_top, x_bottom,
|
|
3428
|
+
sy0, sy1,
|
|
3429
|
+
dy = e.fdy;
|
|
3430
|
+
|
|
3431
|
+
if (e.sy > y_top) {
|
|
3432
|
+
x_top = x0 + dx * (e.sy - y_top);
|
|
3433
|
+
sy0 = e.sy;
|
|
3434
|
+
} else {
|
|
3435
|
+
x_top = x0;
|
|
3436
|
+
sy0 = y_top;
|
|
3437
|
+
}
|
|
3438
|
+
if (e.ey < y_bottom) {
|
|
3439
|
+
x_bottom = x0 + dx * (e.ey - y_top);
|
|
3440
|
+
sy1 = e.ey;
|
|
3441
|
+
} else {
|
|
3442
|
+
x_bottom = xb;
|
|
3443
|
+
sy1 = y_bottom;
|
|
3444
|
+
}
|
|
3445
|
+
|
|
3446
|
+
if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {
|
|
3447
|
+
if ((x_top|0) == (x_bottom|0)) {
|
|
3448
|
+
var height = sy1 - sy0,
|
|
3449
|
+
x = x_top|0;
|
|
3450
|
+
scanline[x] += e.direction * (1 - ((x_top - x) + (x_bottom - x)) / 2) * height;
|
|
3451
|
+
scanline_fill[x+1] += e.direction * height;
|
|
3452
|
+
} else {
|
|
3453
|
+
var t, x, x1, x2, y_crossing, step, sign, area;
|
|
3454
|
+
if (x_top > x_bottom) {
|
|
3455
|
+
sy0 = y_bottom - (sy0 - y_top);
|
|
3456
|
+
sy1 = y_bottom - (sy1 - y_top);
|
|
3457
|
+
t = sy0, sy0 = sy1, sy1 = t;
|
|
3458
|
+
t = x_bottom, x_bottom = x_top, x_top = t;
|
|
3459
|
+
dx = -dx;
|
|
3460
|
+
dy = -dy;
|
|
3461
|
+
t = x0, x0 = xb, xb = t;
|
|
3462
|
+
}
|
|
3463
|
+
|
|
3464
|
+
x1 = x_top|0;
|
|
3465
|
+
x2 = x_bottom|0;
|
|
3466
|
+
y_crossing = (x1 + 1 - x0) * dy + y_top;
|
|
3467
|
+
sign = e.direction;
|
|
3468
|
+
area = sign * (y_crossing - sy0);
|
|
3469
|
+
|
|
3470
|
+
scanline[x1] += area * (1 - ((x_top - x1) + (x1 + 1 - x1)) / 2);
|
|
3471
|
+
|
|
3472
|
+
step = sign * dy;
|
|
3473
|
+
for (x = x1 + 1; x < x2; ++x) {
|
|
3474
|
+
scanline[x] += area + step / 2;
|
|
3475
|
+
area += step;
|
|
3476
|
+
}
|
|
3477
|
+
y_crossing += dy * (x2 - (x1 + 1));
|
|
3478
|
+
|
|
3479
|
+
scanline[x2] += area + sign * (1 - ((x2 - x2) + (x_bottom - x2)) / 2) *
|
|
3480
|
+
(sy1 - y_crossing);
|
|
3481
|
+
scanline_fill[x2+1] += sign * (sy1 - sy0);
|
|
3482
|
+
}
|
|
3483
|
+
} else {
|
|
3484
|
+
for (var x = 0; x < len; ++x) {
|
|
3485
|
+
var y0 = y_top,
|
|
3486
|
+
x1 = x,
|
|
3487
|
+
x2 = x + 1,
|
|
3488
|
+
x3 = xb,
|
|
3489
|
+
y3 = y_bottom,
|
|
3490
|
+
y1 = (x - x0) / dx + y_top,
|
|
3491
|
+
y2 = (x + 1 - x0) / dx + y_top;
|
|
3492
|
+
|
|
3493
|
+
if (x0 < x1 && x3 > x2) {
|
|
3494
|
+
stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x1, y1);
|
|
3495
|
+
stbtt__handle_clipped_edge(scanline, x, e, x1, y1, x2, y2);
|
|
3496
|
+
stbtt__handle_clipped_edge(scanline, x, e, x2, y2, x3, y3);
|
|
3497
|
+
} else if (x3 < x1 && x0 > x2) {
|
|
3498
|
+
stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x2, y2);
|
|
3499
|
+
stbtt__handle_clipped_edge(scanline, x, e, x2, y2, x1, y1);
|
|
3500
|
+
stbtt__handle_clipped_edge(scanline, x, e, x1, y1, x3, y3);
|
|
3501
|
+
} else if (x0 < x1 && x3 > x1) {
|
|
3502
|
+
stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x1, y1);
|
|
3503
|
+
stbtt__handle_clipped_edge(scanline, x, e, x1, y1, x3, y3);
|
|
3504
|
+
} else if (x3 < x1 && x0 > x1) {
|
|
3505
|
+
stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x1, y1);
|
|
3506
|
+
stbtt__handle_clipped_edge(scanline, x, e, x1, y1, x3, y3);
|
|
3507
|
+
} else if (x0 < x2 && x3 > x2) {
|
|
3508
|
+
stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x2, y2);
|
|
3509
|
+
stbtt__handle_clipped_edge(scanline, x, e, x2, y2, x3, y3);
|
|
3510
|
+
} else if (x3 < x2 && x0 > x2) {
|
|
3511
|
+
stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x2, y2);
|
|
3512
|
+
stbtt__handle_clipped_edge(scanline, x, e, x2, y2, x3, y3);
|
|
3513
|
+
} else {
|
|
3514
|
+
stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x3, y3);
|
|
3515
|
+
}
|
|
3516
|
+
}
|
|
3517
|
+
}
|
|
3518
|
+
}
|
|
3519
|
+
e = e.next;
|
|
3520
|
+
}
|
|
3521
|
+
}
|
|
3522
|
+
|
|
3523
|
+
//static void stbtt__rasterize_sorted_edges(stbtt__bitmap * result, stbtt__edge * e, int n,
|
|
3524
|
+
// int vsubsample, int off_x, int off_y, void *userdata)
|
|
3525
|
+
function stbtt__rasterize_sorted_edges(result, edges, nedges, vsubsample, off_x, off_y) {
|
|
3526
|
+
vsubsample |= 0, off_x |= 0, off_y |= 0;
|
|
3527
|
+
var active = null, z;
|
|
3528
|
+
var y = off_y, j = 0, i;
|
|
3529
|
+
var scanline = new Float32Array(result.w * 2 + 1);
|
|
3530
|
+
var scanline2 = scanline.subarray(result.w);
|
|
3531
|
+
var eoff = 0;
|
|
3532
|
+
|
|
3533
|
+
edges[nedges].y0 = off_y + result.h + 1;
|
|
3534
|
+
while (j < result.h) {
|
|
3535
|
+
var scan_y_top = y + 0.0,
|
|
3536
|
+
scan_y_bottom = y + 1.0,
|
|
3537
|
+
step = active;
|
|
3538
|
+
|
|
3539
|
+
// F'ing IE
|
|
3540
|
+
if (scanline.fill) { scanline.fill(0); }
|
|
3541
|
+
else { for (var $i = 0, $l = scanline.length; $i < $l; $i++) scanline[$i] = 0; }
|
|
3542
|
+
|
|
3543
|
+
while (step) {
|
|
3544
|
+
z = step;
|
|
3545
|
+
step = z.next;
|
|
3546
|
+
if (z.ey <= scan_y_top) {
|
|
3547
|
+
z.direction = 0;
|
|
3548
|
+
} else {
|
|
3549
|
+
}
|
|
3550
|
+
}
|
|
3551
|
+
|
|
3552
|
+
while (edges[eoff].y0 <= scan_y_bottom) {
|
|
3553
|
+
if (edges[eoff].y0 != edges[eoff].y1) {
|
|
3554
|
+
z = stbtt__new_active(edges[eoff], off_x, scan_y_top);
|
|
3555
|
+
z.next = active;
|
|
3556
|
+
active = z;
|
|
3557
|
+
}
|
|
3558
|
+
++eoff;
|
|
3559
|
+
}
|
|
3560
|
+
|
|
3561
|
+
if (active) {
|
|
3562
|
+
// C implementation passed scanline2+1. See function for details.
|
|
3563
|
+
stbtt__fill_active_edges_new(scanline, scanline2, result.w, active, scan_y_top);
|
|
3564
|
+
}
|
|
3565
|
+
for (var i = 0, sum = 0; i < result.w; ++i) {
|
|
3566
|
+
var k, m;
|
|
3567
|
+
sum += scanline2[i];
|
|
3568
|
+
k = scanline[i] + sum;
|
|
3569
|
+
k = abs(k) * 255 + 0.5;
|
|
3570
|
+
m = k>>>0;
|
|
3571
|
+
if (m > 255) {
|
|
3572
|
+
m = 255;
|
|
3573
|
+
}
|
|
3574
|
+
result.pixels[j * result.stride + i] = m;
|
|
3575
|
+
}
|
|
3576
|
+
|
|
3577
|
+
step = active;
|
|
3578
|
+
while (step) {
|
|
3579
|
+
z = step;
|
|
3580
|
+
z.fx += z.fdx;
|
|
3581
|
+
step = z.next;
|
|
3582
|
+
}
|
|
3583
|
+
++y;
|
|
3584
|
+
++j;
|
|
3585
|
+
}
|
|
3586
|
+
}
|
|
3587
|
+
|
|
3588
|
+
//static void stbtt__sort_edges_ins_sort(stbtt__edge * p, int n)
|
|
3589
|
+
function stbtt__sort_edges_ins_sort(p, n) {
|
|
3590
|
+
for (var i = 1; i < n; ++i) {
|
|
3591
|
+
var t = p[i], j = i;
|
|
3592
|
+
while (j > 0 && t.y0 < p[j-1].y0) {
|
|
3593
|
+
p[j] = p[j - 1];
|
|
3594
|
+
--j;
|
|
3595
|
+
}
|
|
3596
|
+
if (i != j) {
|
|
3597
|
+
p[j] = t;
|
|
3598
|
+
}
|
|
3599
|
+
}
|
|
3600
|
+
}
|
|
3601
|
+
|
|
3602
|
+
//static void stbtt__sort_edges_quicksort(stbtt__edge * p, int n)
|
|
3603
|
+
// The C implementation messed with the p pointer. JS uses an offset instead.
|
|
3604
|
+
function stbtt__sort_edges_quicksort(p, o, n) {
|
|
3605
|
+
while (n > 12) {
|
|
3606
|
+
var t, c, i, j, z,
|
|
3607
|
+
m = n >> 1,
|
|
3608
|
+
c01 = p[o].y0 < p[o+m].y0,
|
|
3609
|
+
c12 = p[o+m].y0 < p[o+n-1].y0;
|
|
3610
|
+
|
|
3611
|
+
if (c01 != c12) {
|
|
3612
|
+
c = p[o].y0 < p[o+n-11].y0;
|
|
3613
|
+
z = (c == c12) ? 0 : n - 1;
|
|
3614
|
+
t = p[o+z];
|
|
3615
|
+
p[o+z] = p[o+m];
|
|
3616
|
+
p[o+m] = t;
|
|
3617
|
+
}
|
|
3618
|
+
|
|
3619
|
+
t = p[o];
|
|
3620
|
+
p[o] = p[o+m];
|
|
3621
|
+
p[o+m] = t;
|
|
3622
|
+
|
|
3623
|
+
i = 1;
|
|
3624
|
+
j = n - 1;
|
|
3625
|
+
for (;;) {
|
|
3626
|
+
for ( ; p[o+i].y0 < p[o].y0; ++i) {
|
|
3627
|
+
}
|
|
3628
|
+
for ( ; p[o].y0 < p[o+j].y0; --j) {
|
|
3629
|
+
}
|
|
3630
|
+
if (i >= j) {
|
|
3631
|
+
break;
|
|
3632
|
+
}
|
|
3633
|
+
t = p[o+i];
|
|
3634
|
+
p[o+i] = p[o+j];
|
|
3635
|
+
p[o+j] = t;
|
|
3636
|
+
|
|
3637
|
+
++i;
|
|
3638
|
+
--j;
|
|
3639
|
+
}
|
|
3640
|
+
|
|
3641
|
+
if (j < n - i) {
|
|
3642
|
+
stbtt__sort_edges_quicksort(p, o, j);
|
|
3643
|
+
o += i;
|
|
3644
|
+
n -= i;
|
|
3645
|
+
} else {
|
|
3646
|
+
stbtt__sort_edges_quicksort(p, o + i, n - i);
|
|
3647
|
+
n = j;
|
|
3648
|
+
}
|
|
3649
|
+
}
|
|
3650
|
+
}
|
|
3651
|
+
|
|
3652
|
+
//static void stbtt__sort_edges(stbtt__edge * p, int n)
|
|
3653
|
+
function stbtt__sort_edges(p, n) {
|
|
3654
|
+
stbtt__sort_edges_quicksort(p, 0, n);
|
|
3655
|
+
stbtt__sort_edges_ins_sort(p, n);
|
|
3656
|
+
}
|
|
3657
|
+
|
|
3658
|
+
//static void stbtt__rasterize(stbtt__bitmap * result, stbtt__point * pts, int *wcount,
|
|
3659
|
+
// int windings, float scale_x, float scale_y, float shift_x,
|
|
3660
|
+
// float shift_y, int off_x, int off_y, int invert,
|
|
3661
|
+
// void *userdata)
|
|
3662
|
+
function stbtt__rasterize(result, pts, wcount, scale_x, scale_y, shift_x, shift_y, off_x, off_y, invert) {
|
|
3663
|
+
var y_scale_inv = invert ? -scale_y : scale_y,
|
|
3664
|
+
e, n, i, j, k, m,
|
|
3665
|
+
vsubsample = 1;
|
|
3666
|
+
|
|
3667
|
+
n = 0;
|
|
3668
|
+
for (i = 0; i < wcount.length; ++i) {
|
|
3669
|
+
n += wcount[i];
|
|
3670
|
+
}
|
|
3671
|
+
|
|
3672
|
+
e = oalloc(n + 1);
|
|
3673
|
+
n = 0;
|
|
3674
|
+
m = 0;
|
|
3675
|
+
for (i = 0; i < wcount.length; ++i) {
|
|
3676
|
+
var p = m;
|
|
3677
|
+
m += wcount[i];
|
|
3678
|
+
j = wcount[i] - 1;
|
|
3679
|
+
for (k = 0; k < wcount[i]; j = k++) {
|
|
3680
|
+
var a = k, b = j;
|
|
3681
|
+
if (pts[p+j].y == pts[p+k].y) {
|
|
3682
|
+
continue;
|
|
3683
|
+
}
|
|
3684
|
+
|
|
3685
|
+
e[n].invert = 0;
|
|
3686
|
+
if (invert ? pts[p+j].y > pts[p+k].y : pts[p+j].y < pts[p+k].y) {
|
|
3687
|
+
e[n].invert = 1;
|
|
3688
|
+
a = j, b = k;
|
|
3689
|
+
}
|
|
3690
|
+
e[n].x0 = pts[p+a].x * scale_x + shift_x;
|
|
3691
|
+
e[n].y0 = (pts[p+a].y * y_scale_inv + shift_y) * vsubsample;
|
|
3692
|
+
e[n].x1 = pts[p+b].x * scale_x + shift_x;
|
|
3693
|
+
e[n].y1 = (pts[p+b].y * y_scale_inv + shift_y) * vsubsample;
|
|
3694
|
+
++n;
|
|
3695
|
+
}
|
|
3696
|
+
}
|
|
3697
|
+
|
|
3698
|
+
stbtt__sort_edges(e, n);
|
|
3699
|
+
stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y);
|
|
3700
|
+
}
|
|
3701
|
+
|
|
3702
|
+
//static int stbtt__tesselate_curve(stbtt__point * points, int *num_points, float x0,
|
|
3703
|
+
// float y0, float x1, float y1, float x2, float y2,
|
|
3704
|
+
// float objspace_flatness_squared, int n)
|
|
3705
|
+
function stbtt__tesselate_curve(points, x0, y0, x1, y1, x2, y2, objspace_flatness_squared, n) {
|
|
3706
|
+
var mx = (x0 + 2 * x1 + x2) / 4,
|
|
3707
|
+
my = (y0 + 2 * y1 + y2) / 4,
|
|
3708
|
+
dx = (x0 + x2) / 2 - mx,
|
|
3709
|
+
dy = (y0 + y2) / 2 - my;
|
|
3710
|
+
if (n > 16) {
|
|
3711
|
+
return 1;
|
|
3712
|
+
}
|
|
3713
|
+
if (dx * dx + dy * dy > objspace_flatness_squared) {
|
|
3714
|
+
stbtt__tesselate_curve(points, x0, y0, (x0 + x1) / 2.0, (y0 + y1) / 2.0, mx, my,
|
|
3715
|
+
objspace_flatness_squared, n + 1);
|
|
3716
|
+
stbtt__tesselate_curve(points, mx, my, (x1 + x2) / 2.0, (y1 + y2) / 2.0, x2, y2,
|
|
3717
|
+
objspace_flatness_squared, n + 1);
|
|
3718
|
+
} else {
|
|
3719
|
+
points.push({ x:x2, y:y2 });
|
|
3720
|
+
}
|
|
3721
|
+
return 1;
|
|
3722
|
+
}
|
|
3723
|
+
|
|
3724
|
+
//static void stbtt__tesselate_cubic(stbtt__point * points, int *num_points, float x0,
|
|
3725
|
+
// float y0, float x1, float y1, float x2, float y2,
|
|
3726
|
+
// float x3, float y3, float objspace_flatness_squared, int n)
|
|
3727
|
+
function stbtt__tesselate_cubic(points, x0, y0, x1, y1, x2, y2, x3, y3, objspace_flatness_squared, n) {
|
|
3728
|
+
var dx0 = x1 - x0,
|
|
3729
|
+
dy0 = y1 - y0,
|
|
3730
|
+
dx1 = x2 - x1,
|
|
3731
|
+
dy1 = y2 - y1,
|
|
3732
|
+
dx2 = x3 - x2,
|
|
3733
|
+
dy2 = y3 - y2,
|
|
3734
|
+
dx = x3 - x0,
|
|
3735
|
+
dy = y3 - y0,
|
|
3736
|
+
longlen = sqrt(dx0 * dx0 + dy0 * dy0) +
|
|
3737
|
+
sqrt(dx1 * dx1 + dy1 * dy1) +
|
|
3738
|
+
sqrt(dx2 * dx2 + dy2 * dy2),
|
|
3739
|
+
shortlen = sqrt(dx * dx + dy * dy),
|
|
3740
|
+
flatness_squared = longlen * longlen - shortlen * shortlen;
|
|
3741
|
+
if (n > 16) {
|
|
3742
|
+
return;
|
|
3743
|
+
}
|
|
3744
|
+
|
|
3745
|
+
if (flatness_squared > objspace_flatness_squared) {
|
|
3746
|
+
var x01 = (x0 + x1) / 2,
|
|
3747
|
+
y01 = (y0 + y1) / 2,
|
|
3748
|
+
x12 = (x1 + x2) / 2,
|
|
3749
|
+
y12 = (y1 + y2) / 2,
|
|
3750
|
+
x23 = (x2 + x3) / 2,
|
|
3751
|
+
y23 = (y2 + y3) / 2,
|
|
3752
|
+
xa = (x01 + x12) / 2,
|
|
3753
|
+
ya = (y01 + y12) / 2,
|
|
3754
|
+
xb = (x12 + x23) / 2,
|
|
3755
|
+
yb = (y12 + y23) / 2,
|
|
3756
|
+
mx = (xa + xb) / 2,
|
|
3757
|
+
my = (ya + yb) / 2;
|
|
3758
|
+
|
|
3759
|
+
stbtt__tesselate_cubic(points, x0, y0, x01, y01, xa, ya, mx, my,
|
|
3760
|
+
objspace_flatness_squared, n + 1);
|
|
3761
|
+
stbtt__tesselate_cubic(points, mx, my, xb, yb, x23, y23, x3, y3,
|
|
3762
|
+
objspace_flatness_squared, n + 1);
|
|
3763
|
+
} else {
|
|
3764
|
+
points.push({ x:x3, y:y3 });
|
|
3765
|
+
}
|
|
3766
|
+
}
|
|
3767
|
+
|
|
3768
|
+
//static stbtt__point *stbtt_FlattenCurves(stbtt_vertex * vertices, int num_verts,
|
|
3769
|
+
// float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)
|
|
3770
|
+
function stbtt_FlattenCurves(vertices, objspace_flatness, contour_lengths) {
|
|
3771
|
+
var points = [],
|
|
3772
|
+
objspace_flatness_squared = objspace_flatness * objspace_flatness,
|
|
3773
|
+
n = -1, start = 0,
|
|
3774
|
+
x = 0, y = 0;
|
|
3775
|
+
for (var i = 0, nverts = vertices.length; i < nverts; ++i) {
|
|
3776
|
+
switch (vertices[i].type) {
|
|
3777
|
+
case STBTT_vmove:
|
|
3778
|
+
if (n >= 0) {
|
|
3779
|
+
contour_lengths[n] = points.length - start;
|
|
3780
|
+
}
|
|
3781
|
+
++n;
|
|
3782
|
+
start = points.length;
|
|
3783
|
+
x = vertices[i].x, y = vertices[i].y;
|
|
3784
|
+
points.push({ x:x, y:y });
|
|
3785
|
+
break;
|
|
3786
|
+
case STBTT_vline:
|
|
3787
|
+
x = vertices[i].x, y = vertices[i].y;
|
|
3788
|
+
points.push({ x:x, y:y });
|
|
3789
|
+
break;
|
|
3790
|
+
case STBTT_vcurve:
|
|
3791
|
+
stbtt__tesselate_curve(points, x, y, vertices[i].cx, vertices[i].cy,
|
|
3792
|
+
vertices[i].x, vertices[i].y, objspace_flatness_squared, 0);
|
|
3793
|
+
x = vertices[i].x, y = vertices[i].y;
|
|
3794
|
+
break;
|
|
3795
|
+
case STBTT_vcubic:
|
|
3796
|
+
stbtt__tesselate_cubic(points, x, y, vertices[i].cx, vertices[i].cy,
|
|
3797
|
+
vertices[i].cx1, vertices[i].cy1, vertices[i].x, vertices[i].y,
|
|
3798
|
+
objspace_flatness_squared, 0);
|
|
3799
|
+
x = vertices[i].x, y = vertices[i].y;
|
|
3800
|
+
break;
|
|
3801
|
+
}
|
|
3802
|
+
}
|
|
3803
|
+
contour_lengths[n] = points.length - start;
|
|
3804
|
+
|
|
3805
|
+
//console.log("--cl(" + (n+1) + '):');
|
|
3806
|
+
//for (var i = 0; i <= n; i++) {
|
|
3807
|
+
// console.log(" %d", contour_lengths[i]);
|
|
3808
|
+
//}
|
|
3809
|
+
//console.log("\n--pts(" + points.length + '):');
|
|
3810
|
+
//for (var i = 0; i < points.length; i++) {
|
|
3811
|
+
// var pt = points[i];
|
|
3812
|
+
// console.log(i + ': ' + pt.x + ',' + pt.y);
|
|
3813
|
+
//}
|
|
3814
|
+
|
|
3815
|
+
return points;
|
|
3816
|
+
}
|
|
3817
|
+
|
|
3818
|
+
//extern void stbtt_Rasterize(stbtt__bitmap * result, float flatness_in_pixels,
|
|
3819
|
+
// stbtt_vertex * vertices, int num_verts, float scale_x,
|
|
3820
|
+
// float scale_y, float shift_x, float shift_y, int x_off,
|
|
3821
|
+
// int y_off, int invert, void *userdata)
|
|
3822
|
+
function stbtt_Rasterize(result, flatness_in_pixels, vertices, scale_x, scale_y, shift_x, shift_y,
|
|
3823
|
+
x_off, y_off, invert) {
|
|
3824
|
+
x_off |= 0, y_off |= 0;
|
|
3825
|
+
var scale = scale_x > scale_y ? scale_y : scale_x,
|
|
3826
|
+
wcount = [],
|
|
3827
|
+
windings = stbtt_FlattenCurves(vertices, flatness_in_pixels / scale, wcount);
|
|
3828
|
+
if (windings) {
|
|
3829
|
+
stbtt__rasterize(result, windings, wcount, scale_x, scale_y,
|
|
3830
|
+
shift_x, shift_y, x_off, y_off, invert);
|
|
3831
|
+
}
|
|
3832
|
+
}
|
|
3833
|
+
|
|
3834
|
+
//extern void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo * info,
|
|
3835
|
+
// unsigned char *output, int out_w, int out_h,
|
|
3836
|
+
// int out_stride, float scale_x, float scale_y,
|
|
3837
|
+
// float shift_x, float shift_y, int glyph)
|
|
3838
|
+
function stbtt_MakeGlyphBitmapSubpixel(info, buffer, out_w, out_h, out_stride,
|
|
3839
|
+
scale_x, scale_y, shift_x, shift_y, glyph) {
|
|
3840
|
+
var vertices = stbtt_GetGlyphShape(info, glyph);
|
|
3841
|
+
var gbm = {};
|
|
3842
|
+
var rect = stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y);
|
|
3843
|
+
gbm.pixels = buffer;
|
|
3844
|
+
gbm.w = out_w|0;
|
|
3845
|
+
gbm.h = out_h|0;
|
|
3846
|
+
gbm.stride = out_stride|0;
|
|
3847
|
+
|
|
3848
|
+
if (gbm.w && gbm.h) {
|
|
3849
|
+
stbtt_Rasterize(gbm, 0.35, vertices, scale_x, scale_y, shift_x, shift_y, rect.x0, rect.y0, 1);
|
|
3850
|
+
}
|
|
3851
|
+
}
|
|
3852
|
+
|
|
3853
|
+
//extern void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo * info,
|
|
3854
|
+
// unsigned char *output, int out_w,
|
|
3855
|
+
// int out_h, int out_stride, float scale_x,
|
|
3856
|
+
// float scale_y, float shift_x,
|
|
3857
|
+
// float shift_y, int codepoint)
|
|
3858
|
+
function stbtt_MakeCodepointBitmapSubpixel(info, buffer, out_w, out_h, out_stride,
|
|
3859
|
+
scale_x, scale_y, shift_x, shift_y, codepoint) {
|
|
3860
|
+
stbtt_MakeGlyphBitmapSubpixel(info, buffer, out_w, out_h, out_stride,
|
|
3861
|
+
scale_x, scale_y, shift_x, shift_y,
|
|
3862
|
+
stbtt_FindGlyphIndex(info, codepoint));
|
|
3863
|
+
}
|
|
3864
|
+
|
|
3865
|
+
//extern int stbtt_InitFont(stbtt_fontinfo * info, const unsigned char *data, int offset)
|
|
3866
|
+
function stbtt_InitFont(font, data, offset) {
|
|
3867
|
+
return stbtt_InitFont_internal(font, data, offset);
|
|
3868
|
+
}
|
|
3869
|
+
|
|
3870
|
+
|
|
3871
|
+
function InitFont(data) {
|
|
3872
|
+
var font = {};
|
|
3873
|
+
if (!stbtt_InitFont_internal(font, data, 0)) {
|
|
3874
|
+
return null;
|
|
3875
|
+
}
|
|
3876
|
+
|
|
3877
|
+
var vm = stbtt_GetFontVMetrics(font);
|
|
3878
|
+
|
|
3879
|
+
font.ascent = vm.ascent;
|
|
3880
|
+
font.descent = vm.descent;
|
|
3881
|
+
font.linegap = vm.linegap;
|
|
3882
|
+
|
|
3883
|
+
return font;
|
|
3884
|
+
}
|
|
3885
|
+
|
|
3886
|
+
function GetGlyph(font, codepoint, size_x, size_y) {
|
|
3887
|
+
size_y = size_y || size_x;
|
|
3888
|
+
var scale_x = size_x / font.ascent;
|
|
3889
|
+
var scale_y = size_y / font.ascent;
|
|
3890
|
+
|
|
3891
|
+
var glyph = stbtt_FindGlyphIndex(font, codepoint);
|
|
3892
|
+
if (!glyph && codepoint) {
|
|
3893
|
+
return null;
|
|
3894
|
+
}
|
|
3895
|
+
|
|
3896
|
+
var vertices = stbtt_GetGlyphShape(font, glyph);
|
|
3897
|
+
var rect = stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y, 0, 0);
|
|
3898
|
+
var width = rect.x1 - rect.x0;
|
|
3899
|
+
var height = rect.y1 - rect.y0;
|
|
3900
|
+
var pixels = null;
|
|
3901
|
+
|
|
3902
|
+
if (width && height) {
|
|
3903
|
+
var gbm = {
|
|
3904
|
+
pixels : (pixels = new Uint8Array(width * height)),
|
|
3905
|
+
w : width,
|
|
3906
|
+
h : height,
|
|
3907
|
+
stride : width,
|
|
3908
|
+
}
|
|
3909
|
+
stbtt_Rasterize(gbm, 0.35, vertices, scale_x, scale_y, 0, 0, rect.x0, rect.y0, 1);
|
|
3910
|
+
}
|
|
3911
|
+
|
|
3912
|
+
var hmetrics = stbtt_GetGlyphHMetrics(font, glyph);
|
|
3913
|
+
return {
|
|
3914
|
+
glyph:glyph, pixels:pixels, width:width, height:height, top:-rect.y0, left:rect.x0,
|
|
3915
|
+
advance:floor(hmetrics.advanceWidth * scale_x),
|
|
3916
|
+
}
|
|
3917
|
+
}
|
|
3918
|
+
function GetPaths(font, codepoint, size_x, size_y) {
|
|
3919
|
+
size_y = size_y || size_x;
|
|
3920
|
+
var scale_x = size_x / font.ascent;
|
|
3921
|
+
var scale_y = size_y / font.ascent;
|
|
3922
|
+
|
|
3923
|
+
var glyph = stbtt_FindGlyphIndex(font, codepoint);
|
|
3924
|
+
if (!glyph && codepoint) {
|
|
3925
|
+
return null;
|
|
3926
|
+
}
|
|
3927
|
+
var vertices = stbtt_GetGlyphShape(font, glyph);
|
|
3928
|
+
var hmetrics = stbtt_GetGlyphHMetrics(font, glyph);
|
|
3929
|
+
|
|
3930
|
+
// The hmetrics just give us advance. We need ascent and descent as well.
|
|
3931
|
+
var ascent = 0;
|
|
3932
|
+
var descent = 0;
|
|
3933
|
+
|
|
3934
|
+
// Convert to SVG notation
|
|
3935
|
+
var paths = [];
|
|
3936
|
+
if (vertices) {
|
|
3937
|
+
for (var i = 0, l = vertices.length; i < l; i++) {
|
|
3938
|
+
var v = vertices[i];
|
|
3939
|
+
var path;
|
|
3940
|
+
if (v.type == STBTT_vmove) {
|
|
3941
|
+
path = { type:'M', x:v.x * scale_x, y:v.y * scale_y };
|
|
3942
|
+
} else if (v.type == STBTT_vline) {
|
|
3943
|
+
path = { type:'L', x:v.x * scale_x, y:v.y * scale_y };
|
|
3944
|
+
} else if (v.type == STBTT_vcurve) {
|
|
3945
|
+
path = { type:'Q', x:v.x * scale_x, y:v.y * scale_y,
|
|
3946
|
+
cx:v.cx * scale_x, cy:v.cy * scale_y };
|
|
3947
|
+
} else if (v.type == STBTT_vcubic) {
|
|
3948
|
+
path = { type:'C', x:v.x * scale_x, y:v.y * scale_y,
|
|
3949
|
+
cx1:v.cx * scale_x, cy1:v.cy * scale_y,
|
|
3950
|
+
cx2:v.cx1 * scale_x, cy2:v.cy1 * scale_y };
|
|
3951
|
+
} else {
|
|
3952
|
+
continue;
|
|
3953
|
+
}
|
|
3954
|
+
if (path.y > ascent) ascent = path.y;
|
|
3955
|
+
if (path.y < descent) descent = path.y;
|
|
3956
|
+
paths.push(path);
|
|
3957
|
+
}
|
|
3958
|
+
}
|
|
3959
|
+
|
|
3960
|
+
// Add the glyph metrics to the returned array.
|
|
3961
|
+
paths.advance = hmetrics.advanceWidth * scale_x;
|
|
3962
|
+
paths.ascent = ascent;
|
|
3963
|
+
paths.descent = descent;
|
|
3964
|
+
return paths;
|
|
3965
|
+
}
|
|
3966
|
+
|
|
3967
|
+
|
|
3968
|
+
// exports
|
|
3969
|
+
return {
|
|
3970
|
+
InitFont: InitFont,
|
|
3971
|
+
GetGlyph: GetGlyph,
|
|
3972
|
+
GetPaths: GetPaths,
|
|
3973
|
+
}
|
|
3974
|
+
|
|
3975
|
+
})();
|
|
3976
|
+
function toUint8Array(data) {
|
|
3977
|
+
if (typeof data == "string") {
|
|
3978
|
+
var binary = /[^A-Za-z0-9+\/=\s]/.test(data);
|
|
3979
|
+
var bstr = binary ? data : atob(data),
|
|
3980
|
+
len = bstr.length,
|
|
3981
|
+
bytes = new Uint8Array(len);
|
|
3982
|
+
for (var i = 0; i < len; i++) {
|
|
3983
|
+
bytes[i] = bstr.charCodeAt(i);
|
|
3984
|
+
}
|
|
3985
|
+
return bytes;
|
|
3986
|
+
} else if (data instanceof Uint8Array) {
|
|
3987
|
+
return data;
|
|
3988
|
+
} else if (data instanceof ArrayBuffer) {
|
|
3989
|
+
return new Uint8Array(data);
|
|
3990
|
+
}
|
|
3991
|
+
throw new ReferenceError("data must be a binary or base64 encoded string or Uint8Array");
|
|
3992
|
+
}
|
|
3993
|
+
|
|
3994
|
+
FontLib.loadFont("OCR-A", 100, 100, "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");
|
|
3995
|
+
FontLib.loadFont("OCR-B", 96, 100, "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");
|
|
3996
|
+
|
|
3997
|
+
export function datamatrix(opts,dwg) { return _ToAny(bwipp_datamatrix,opts,dwg); };
|
|
3998
|
+
export function qrcode(opts,dwg) { return _ToAny(bwipp_qrcode,opts,dwg); };
|
|
3999
|
+
export function raw(bcid, text, options) { return ToRaw(bcid, text, options)};
|
|
4000
|
+
export { ToCanvas as toCanvas, ToSVG as toSVG, Render as render, LoadFont as loadFont,
|
|
4001
|
+
DrawingCanvas as drawingCanvas, DrawingSVG as drawingSVG,
|
|
4002
|
+
BWIPJS_VERSION, BWIPP_VERSION,
|
|
4003
|
+
};
|
|
4004
|
+
export default {
|
|
4005
|
+
toCanvas:ToCanvas, toSVG:ToSVG, render:Render, raw:ToRaw,
|
|
4006
|
+
drawingCanvas:DrawingCanvas, drawingSVG:DrawingSVG,
|
|
4007
|
+
fixupOptions:FixupOptions, loadFont:LoadFont, FontLib, BWIPJS_VERSION, BWIPP_VERSION,
|
|
4008
|
+
};
|