@muhammara/native-core 7.0.0-beta.3 → 7.0.0-rc.1
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/README.md +57 -7
- package/THIRD_PARTY_NOTICES.md +39 -0
- package/index.js +120 -1
- package/lib/PDFRStreamForBuffer.js +52 -7
- package/lib/PDFRStreamForFile.js +56 -7
- package/lib/PDFStreamForResponse.js +22 -5
- package/lib/PDFWStreamForBuffer.js +49 -10
- package/lib/PDFWStreamForFile.js +26 -5
- package/lib/Recipe.js +86 -30
- package/lib/content-stream.js +503 -0
- package/lib/css-colors.js +149 -0
- package/lib/font-text.js +1461 -0
- package/lib/glyph-list.js +1127 -0
- package/lib/recipe/annotation.js +482 -105
- package/lib/recipe/appendPage.js +8 -1
- package/lib/recipe/colors.js +132 -35
- package/lib/recipe/coordinate.js +82 -16
- package/lib/recipe/encrypt.js +32 -13
- package/lib/recipe/font.js +70 -25
- package/lib/recipe/graphics-state.js +3 -2
- package/lib/recipe/htmlToTextObjects.js +154 -21
- package/lib/recipe/image.js +34 -9
- package/lib/recipe/info.js +93 -22
- package/lib/recipe/insertPage.js +12 -3
- package/lib/recipe/overlay.js +4 -2
- package/lib/recipe/page-references.js +436 -0
- package/lib/recipe/page.js +379 -275
- package/lib/recipe/parameters.js +11 -2
- package/lib/recipe/replaceText.js +464 -30
- package/lib/recipe/shapes.js +418 -45
- package/lib/recipe/split.js +6 -2
- package/lib/recipe/table.js +260 -173
- package/lib/recipe/text.helper.js +176 -10
- package/lib/recipe/text.js +420 -115
- package/lib/recipe/utils.js +66 -3
- package/lib/recipe/vector-line.js +101 -39
- package/lib/recipe/vector-polygon.js +18 -6
- package/lib/recipe/vector.helper.js +150 -13
- package/lib/recipe/vector.js +150 -53
- package/lib/recipe/xObjectForm.js +73 -10
- package/lib/recipe-constants.js +373 -0
- package/muhammara.d.ts +3487 -152
- package/package.json +1 -1
|
@@ -1,11 +1,29 @@
|
|
|
1
|
+
var { cloneOptions, resolveFontSize } = require("./utils");
|
|
2
|
+
var { HorizontalAlign, VerticalAlign } = require("../recipe-constants");
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The width character spacing adds between the characters of a text.
|
|
6
|
+
* @private
|
|
7
|
+
* @param {string} text - The text.
|
|
8
|
+
* @param {number} charSpace - The spacing added after each character but the last.
|
|
9
|
+
* @returns {number} The added width.
|
|
10
|
+
*/
|
|
1
11
|
const charSpacing = function charSpacing(text, charSpace) {
|
|
2
|
-
|
|
3
|
-
return
|
|
12
|
+
var characterCount = Array.from(String(text)).length;
|
|
13
|
+
return characterCount ? (characterCount - 1) * charSpace : 0;
|
|
4
14
|
};
|
|
5
15
|
|
|
6
16
|
// Have to set up word as a constant, then export it below
|
|
7
17
|
// so that Line can see it. Otherwise, an error is thrown.
|
|
8
18
|
|
|
19
|
+
/**
|
|
20
|
+
* A word used by Recipe text layout.
|
|
21
|
+
* @name Word
|
|
22
|
+
* @class
|
|
23
|
+
* @memberof Recipe#
|
|
24
|
+
* @param {string} word - The word, a single space measured as "o".
|
|
25
|
+
* @param {Object} pathOptions - The resolved text options: font, size and charSpace.
|
|
26
|
+
*/
|
|
9
27
|
const Word = class Word {
|
|
10
28
|
constructor(word, pathOptions) {
|
|
11
29
|
this._value = word;
|
|
@@ -14,10 +32,17 @@ const Word = class Word {
|
|
|
14
32
|
this._text = word === " " ? "o" : word; // allows space to get an actual dimension
|
|
15
33
|
}
|
|
16
34
|
|
|
35
|
+
/**
|
|
36
|
+
* @returns {string} The word text.
|
|
37
|
+
*/
|
|
17
38
|
get value() {
|
|
18
39
|
return this._value;
|
|
19
40
|
}
|
|
20
41
|
|
|
42
|
+
/**
|
|
43
|
+
* The measured text box, including character spacing; cached.
|
|
44
|
+
* @returns {Object} xMin, yMin, xMax, yMax, width and height.
|
|
45
|
+
*/
|
|
21
46
|
get dimensions() {
|
|
22
47
|
if (this._dimensions) {
|
|
23
48
|
return this._dimensions;
|
|
@@ -30,14 +55,26 @@ const Word = class Word {
|
|
|
30
55
|
return this._dimensions;
|
|
31
56
|
}
|
|
32
57
|
|
|
58
|
+
/**
|
|
59
|
+
* @returns {boolean} Whether this is the last word of its line.
|
|
60
|
+
*/
|
|
33
61
|
get last() {
|
|
34
62
|
return this._last;
|
|
35
63
|
}
|
|
36
64
|
|
|
65
|
+
/**
|
|
66
|
+
* @returns {number} The width character spacing adds to the word.
|
|
67
|
+
*/
|
|
37
68
|
get charSpacing() {
|
|
38
69
|
return charSpacing(this._text, this._pathOptions.charSpace);
|
|
39
70
|
}
|
|
40
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Mark the word as the last of its line, trimming trailing space and
|
|
74
|
+
* measuring it again.
|
|
75
|
+
* @param {boolean} [value=true] - Whether the word is last.
|
|
76
|
+
* @returns {void}
|
|
77
|
+
*/
|
|
41
78
|
lastWord(value = true) {
|
|
42
79
|
// indicate last word in line (for justification)
|
|
43
80
|
this._last = value;
|
|
@@ -73,9 +110,19 @@ exports.Word = Word; // ... now export Word to the rest of the library.
|
|
|
73
110
|
* @param {number} size - The font size.
|
|
74
111
|
* @param {Object} pathOptions - The resolved text options.
|
|
75
112
|
*/
|
|
113
|
+
// The width of a line without a text box. No text reaches it, so such a line
|
|
114
|
+
// accepts every word without measuring.
|
|
115
|
+
const UNBOUNDED_LINE_WIDTH = 999999999;
|
|
116
|
+
|
|
76
117
|
exports.Line = class Line {
|
|
118
|
+
/**
|
|
119
|
+
* @param {number} [width] - The available width; unlimited when omitted.
|
|
120
|
+
* @param {number} [height] - A fixed line height.
|
|
121
|
+
* @param {number} [size] - The font size; defaults to the text options size.
|
|
122
|
+
* @param {Object} pathOptions - The resolved text options.
|
|
123
|
+
*/
|
|
77
124
|
constructor(width, height, size, pathOptions) {
|
|
78
|
-
this._width = width ||
|
|
125
|
+
this._width = width || UNBOUNDED_LINE_WIDTH;
|
|
79
126
|
this._height = height;
|
|
80
127
|
this._pathOptions = pathOptions;
|
|
81
128
|
this.size = size || pathOptions.size;
|
|
@@ -83,41 +130,75 @@ exports.Line = class Line {
|
|
|
83
130
|
this.wordObjects = [];
|
|
84
131
|
}
|
|
85
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Replace the line ID; falsy values are ignored.
|
|
135
|
+
* @param {number} id - The new ID.
|
|
136
|
+
*/
|
|
86
137
|
set lineID(id) {
|
|
87
138
|
if (id) {
|
|
88
139
|
this._lineID = id;
|
|
89
140
|
}
|
|
90
141
|
}
|
|
91
142
|
|
|
143
|
+
/**
|
|
144
|
+
* @returns {number} The line ID, grouping objects laid out on one line.
|
|
145
|
+
*/
|
|
92
146
|
get lineID() {
|
|
93
147
|
return this._lineID;
|
|
94
148
|
}
|
|
95
149
|
|
|
150
|
+
/**
|
|
151
|
+
* @param {Word} wordObject - The word to append.
|
|
152
|
+
* @returns {void}
|
|
153
|
+
*/
|
|
96
154
|
addWord(wordObject) {
|
|
97
155
|
this.wordObjects.push(wordObject);
|
|
98
156
|
}
|
|
99
157
|
|
|
158
|
+
/**
|
|
159
|
+
* Append leading spaces.
|
|
160
|
+
* @param {number} amount - The number of spaces.
|
|
161
|
+
* @returns {void}
|
|
162
|
+
*/
|
|
100
163
|
indent(amount) {
|
|
101
164
|
for (let i = 0; i < amount; i++) {
|
|
102
165
|
this.addWord(new Word(" ", this._pathOptions));
|
|
103
166
|
}
|
|
104
167
|
}
|
|
105
168
|
|
|
169
|
+
/**
|
|
170
|
+
* Mark the final word as the last of the line.
|
|
171
|
+
* @returns {void}
|
|
172
|
+
*/
|
|
106
173
|
markLastWord() {
|
|
107
174
|
if (this.wordObjects.length > 0) {
|
|
108
175
|
this.wordObjects[this.wordObjects.length - 1].lastWord();
|
|
109
176
|
}
|
|
110
177
|
}
|
|
111
178
|
|
|
179
|
+
/**
|
|
180
|
+
* @returns {Word|undefined} The final word, or undefined for an empty line.
|
|
181
|
+
*/
|
|
112
182
|
get lastWord() {
|
|
113
183
|
return this.wordObjects[this.wordObjects.length - 1];
|
|
114
184
|
}
|
|
115
185
|
|
|
186
|
+
/**
|
|
187
|
+
* @param {string} text - The text.
|
|
188
|
+
* @returns {number} The width character spacing adds to the text.
|
|
189
|
+
*/
|
|
116
190
|
charSpacing(text) {
|
|
117
191
|
return charSpacing(text, this._pathOptions.charSpace);
|
|
118
192
|
}
|
|
119
193
|
|
|
194
|
+
/**
|
|
195
|
+
* @param {Word} wordObject - The word to test.
|
|
196
|
+
* @returns {boolean} Whether the line still fits its width with the word appended.
|
|
197
|
+
*/
|
|
120
198
|
canFit(wordObject) {
|
|
199
|
+
// Measuring the whole line for every word is quadratic in its length, and
|
|
200
|
+
// a line without a text box never wraps.
|
|
201
|
+
if (this._width >= UNBOUNDED_LINE_WIDTH) return true;
|
|
121
202
|
const tempValue = this.value + wordObject.value;
|
|
122
203
|
const toWidth =
|
|
123
204
|
this._pathOptions.font.calculateTextDimensions(tempValue, this.size)
|
|
@@ -125,6 +206,11 @@ exports.Line = class Line {
|
|
|
125
206
|
return toWidth <= this.width;
|
|
126
207
|
}
|
|
127
208
|
|
|
209
|
+
/**
|
|
210
|
+
* Replace the final word and mark the new one as last.
|
|
211
|
+
* @param {Word|string} wordObject - The replacement word.
|
|
212
|
+
* @returns {void}
|
|
213
|
+
*/
|
|
128
214
|
replaceLastWord(wordObject) {
|
|
129
215
|
if (typeof wordObject === "string") {
|
|
130
216
|
wordObject = new Word(wordObject, this._pathOptions);
|
|
@@ -134,14 +220,23 @@ exports.Line = class Line {
|
|
|
134
220
|
wordObject.lastWord();
|
|
135
221
|
}
|
|
136
222
|
|
|
223
|
+
/**
|
|
224
|
+
* @returns {Word[]} The words of the line.
|
|
225
|
+
*/
|
|
137
226
|
get words() {
|
|
138
227
|
return this.wordObjects;
|
|
139
228
|
}
|
|
140
229
|
|
|
230
|
+
/**
|
|
231
|
+
* @returns {number} The width of one space, measured as "o".
|
|
232
|
+
*/
|
|
141
233
|
get spaceWidth() {
|
|
142
234
|
return this._pathOptions.font.calculateTextDimensions("o", this.size).width;
|
|
143
235
|
}
|
|
144
236
|
|
|
237
|
+
/**
|
|
238
|
+
* @returns {string} The text of the line.
|
|
239
|
+
*/
|
|
145
240
|
get value() {
|
|
146
241
|
const value = this.wordObjects.reduce((string, word) => {
|
|
147
242
|
string += word.value;
|
|
@@ -150,6 +245,9 @@ exports.Line = class Line {
|
|
|
150
245
|
return value;
|
|
151
246
|
}
|
|
152
247
|
|
|
248
|
+
/**
|
|
249
|
+
* @returns {number} The measured width of the line text.
|
|
250
|
+
*/
|
|
153
251
|
get currentWidth() {
|
|
154
252
|
return (
|
|
155
253
|
this._pathOptions.font.calculateTextDimensions(this.value, this.size)
|
|
@@ -157,6 +255,9 @@ exports.Line = class Line {
|
|
|
157
255
|
);
|
|
158
256
|
}
|
|
159
257
|
|
|
258
|
+
/**
|
|
259
|
+
* @returns {number} The sum of the measured word widths.
|
|
260
|
+
*/
|
|
160
261
|
get textWidth() {
|
|
161
262
|
return this.wordObjects.reduce((width, word) => {
|
|
162
263
|
width += word.dimensions.xMax;
|
|
@@ -164,11 +265,17 @@ exports.Line = class Line {
|
|
|
164
265
|
}, 0);
|
|
165
266
|
}
|
|
166
267
|
|
|
268
|
+
/**
|
|
269
|
+
* @returns {number} The available width.
|
|
270
|
+
*/
|
|
167
271
|
get width() {
|
|
168
272
|
return this._width;
|
|
169
273
|
}
|
|
170
274
|
|
|
171
275
|
// dynamic adjust height based on word height?
|
|
276
|
+
/**
|
|
277
|
+
* @returns {number} The fixed height, or the measured text height plus 20.
|
|
278
|
+
*/
|
|
172
279
|
get height() {
|
|
173
280
|
if (this._height) {
|
|
174
281
|
return this._height;
|
|
@@ -185,6 +292,12 @@ exports.Line = class Line {
|
|
|
185
292
|
* Get the offset for a text box.
|
|
186
293
|
* @private
|
|
187
294
|
* @todo handle page margin and padding
|
|
295
|
+
* @param {Object} textBox - The laid-out text box: width, height, textHeight,
|
|
296
|
+
* firstLineHeight and isSimpleText.
|
|
297
|
+
* @param {Object} [options] - The text options.
|
|
298
|
+
* @param {string} [options.align] - A `Recipe.HorizontalAlign` value,
|
|
299
|
+
* optionally followed by a space and a `Recipe.VerticalAlign` value.
|
|
300
|
+
* @returns {{offsetX: number, offsetY: number}} The offset from the placement point.
|
|
188
301
|
*/
|
|
189
302
|
exports._getTextBoxOffset = function _getTextBoxOffset(textBox, options = {}) {
|
|
190
303
|
let offsetX = 0;
|
|
@@ -194,10 +307,10 @@ exports._getTextBoxOffset = function _getTextBoxOffset(textBox, options = {}) {
|
|
|
194
307
|
const alignments = options.align.split(" ");
|
|
195
308
|
if (alignments[0]) {
|
|
196
309
|
switch (alignments[0]) {
|
|
197
|
-
case
|
|
310
|
+
case HorizontalAlign.CENTER:
|
|
198
311
|
offsetX = (-1 * width) / 2;
|
|
199
312
|
break;
|
|
200
|
-
case
|
|
313
|
+
case HorizontalAlign.RIGHT:
|
|
201
314
|
offsetX = -width;
|
|
202
315
|
break;
|
|
203
316
|
default:
|
|
@@ -206,12 +319,12 @@ exports._getTextBoxOffset = function _getTextBoxOffset(textBox, options = {}) {
|
|
|
206
319
|
if (alignments[1]) {
|
|
207
320
|
height = height || textHeight;
|
|
208
321
|
switch (alignments[1]) {
|
|
209
|
-
case
|
|
322
|
+
case VerticalAlign.CENTER:
|
|
210
323
|
offsetY = textBox.isSimpleText
|
|
211
324
|
? -textBox.firstLineHeight / 2
|
|
212
325
|
: height / 2 + offsetY;
|
|
213
326
|
break;
|
|
214
|
-
case
|
|
327
|
+
case VerticalAlign.BOTTOM:
|
|
215
328
|
offsetY = height + offsetY;
|
|
216
329
|
break;
|
|
217
330
|
default:
|
|
@@ -235,9 +348,14 @@ exports._getTextBoxOffset = function _getTextBoxOffset(textBox, options = {}) {
|
|
|
235
348
|
* @param {string} [options.font='helvetica'] - name of font from which measurements are to be taken
|
|
236
349
|
* @param {number} [options.size=14] - size of font to be used in taking measurements
|
|
237
350
|
* @param {number} [options.charSpace=0] - character spacing being applied to the given text.
|
|
351
|
+
* @param {boolean} [options.bold] - Measure with the bold style of the font.
|
|
352
|
+
* @param {boolean} [options.italic] - Measure with the italic style of the font.
|
|
238
353
|
* @returns {Object} measurement components of given text: width, height, xMin, xMax, yMin, yMax
|
|
354
|
+
* @throws {Error} If the font file cannot be loaded.
|
|
239
355
|
*/
|
|
240
356
|
exports.textDimensions = function textDimensions(text, options = {}) {
|
|
357
|
+
// null options act like omitted options.
|
|
358
|
+
if (options === null) options = {};
|
|
241
359
|
const font = this._getFont(options);
|
|
242
360
|
let dimensions = {};
|
|
243
361
|
let charSpaces = 0;
|
|
@@ -246,7 +364,7 @@ exports.textDimensions = function textDimensions(text, options = {}) {
|
|
|
246
364
|
if (options.charSpace) {
|
|
247
365
|
charSpaces = charSpacing(text, options.charSpace);
|
|
248
366
|
}
|
|
249
|
-
const fontSize = options
|
|
367
|
+
const fontSize = resolveFontSize(options, this.current.defaultFontSize);
|
|
250
368
|
dimensions = font.calculateTextDimensions(text, fontSize);
|
|
251
369
|
dimensions.xMax += charSpaces;
|
|
252
370
|
}
|
|
@@ -268,6 +386,15 @@ exports.textDimensions = function textDimensions(text, options = {}) {
|
|
|
268
386
|
* @param {Object} [options] - The column options.
|
|
269
387
|
*/
|
|
270
388
|
exports.Column = class Column {
|
|
389
|
+
/**
|
|
390
|
+
* @param {number} x - The x coordinate.
|
|
391
|
+
* @param {number} y - The y coordinate.
|
|
392
|
+
* @param {number} width - The column width.
|
|
393
|
+
* @param {number} [height] - The column height; unlimited when omitted.
|
|
394
|
+
* @param {string} [text=''] - The column heading; defaults to the field.
|
|
395
|
+
* @param {string} [field=''] - The associated data field.
|
|
396
|
+
* @param {Object} [options] - The column options; `cell` becomes the text box.
|
|
397
|
+
*/
|
|
271
398
|
constructor(x, y, width, height, text = "", field = "", options = {}) {
|
|
272
399
|
this._x = x;
|
|
273
400
|
this._y = y;
|
|
@@ -276,7 +403,7 @@ exports.Column = class Column {
|
|
|
276
403
|
this._field = field; // associated data field
|
|
277
404
|
this._text = text || field; // for column title
|
|
278
405
|
this._gap = 0;
|
|
279
|
-
this._options =
|
|
406
|
+
this._options = cloneOptions(options);
|
|
280
407
|
|
|
281
408
|
this._options.textBox = this._options.cell;
|
|
282
409
|
|
|
@@ -292,7 +419,10 @@ exports.Column = class Column {
|
|
|
292
419
|
if (!this._options.header || typeof this._options.header === "boolean") {
|
|
293
420
|
this._options.header = {
|
|
294
421
|
bold: true,
|
|
295
|
-
textBox: {
|
|
422
|
+
textBox: {
|
|
423
|
+
padding: 2,
|
|
424
|
+
textAlign: `${HorizontalAlign.CENTER} ${VerticalAlign.CENTER}`,
|
|
425
|
+
},
|
|
296
426
|
};
|
|
297
427
|
}
|
|
298
428
|
|
|
@@ -301,39 +431,75 @@ exports.Column = class Column {
|
|
|
301
431
|
}
|
|
302
432
|
}
|
|
303
433
|
|
|
434
|
+
/**
|
|
435
|
+
* @returns {number} The column width.
|
|
436
|
+
*/
|
|
304
437
|
get width() {
|
|
305
438
|
return this._width;
|
|
306
439
|
}
|
|
440
|
+
/**
|
|
441
|
+
* @returns {number} The column height.
|
|
442
|
+
*/
|
|
307
443
|
get height() {
|
|
308
444
|
return this._height;
|
|
309
445
|
}
|
|
446
|
+
/**
|
|
447
|
+
* @returns {number} The column x coordinate.
|
|
448
|
+
*/
|
|
310
449
|
get x() {
|
|
311
450
|
return this._x;
|
|
312
451
|
}
|
|
452
|
+
/**
|
|
453
|
+
* @param {number} x - The new x coordinate.
|
|
454
|
+
*/
|
|
313
455
|
set x(x) {
|
|
314
456
|
this._x = x;
|
|
315
457
|
}
|
|
458
|
+
/**
|
|
459
|
+
* @returns {number} The column y coordinate.
|
|
460
|
+
*/
|
|
316
461
|
get y() {
|
|
317
462
|
return this._y;
|
|
318
463
|
}
|
|
464
|
+
/**
|
|
465
|
+
* @returns {number[]} The column [x, y] position.
|
|
466
|
+
*/
|
|
319
467
|
get position() {
|
|
320
468
|
return [this._x, this._y];
|
|
321
469
|
}
|
|
470
|
+
/**
|
|
471
|
+
* @param {number[]} pos - The new [x, y] position.
|
|
472
|
+
*/
|
|
322
473
|
set position(pos) {
|
|
323
474
|
[this._x, this._y] = pos;
|
|
324
475
|
}
|
|
476
|
+
/**
|
|
477
|
+
* @returns {number} The gap after the column.
|
|
478
|
+
*/
|
|
325
479
|
get gap() {
|
|
326
480
|
return this._gap;
|
|
327
481
|
}
|
|
482
|
+
/**
|
|
483
|
+
* @param {number} gap - The new gap after the column.
|
|
484
|
+
*/
|
|
328
485
|
set gap(gap) {
|
|
329
486
|
this._gap = gap;
|
|
330
487
|
}
|
|
488
|
+
/**
|
|
489
|
+
* @returns {string} The associated data field.
|
|
490
|
+
*/
|
|
331
491
|
get field() {
|
|
332
492
|
return this._field;
|
|
333
493
|
}
|
|
494
|
+
/**
|
|
495
|
+
* @returns {string} The column heading.
|
|
496
|
+
*/
|
|
334
497
|
get text() {
|
|
335
498
|
return this._text;
|
|
336
499
|
}
|
|
500
|
+
/**
|
|
501
|
+
* @returns {Object} The column text options.
|
|
502
|
+
*/
|
|
337
503
|
get options() {
|
|
338
504
|
return this._options;
|
|
339
505
|
}
|