@flowaccount/pdfmake 1.0.4-staging.0 → 1.0.4-staging.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowaccount/pdfmake",
3
- "version": "1.0.4-staging.0",
3
+ "version": "1.0.4-staging.2",
4
4
  "description": "Client/server side PDF printing in pure JavaScript",
5
5
  "main": "src/printer.js",
6
6
  "browser": "build/pdfmake.js",
@@ -266,7 +266,7 @@ PageElementWriter.prototype.moveToNextPage = function (pageOrientation) {
266
266
  this.writer.tracker.emit('pageChanged', {
267
267
  prevPage: nextPage.prevPage,
268
268
  prevY: nextPage.prevY,
269
- y: nextPage.y
269
+ y: this.writer.context.y
270
270
  });
271
271
  };
272
272
 
package/src/textTools.js CHANGED
@@ -1,22 +1,17 @@
1
+ /* jslint node: true */
1
2
  'use strict';
2
3
 
3
- var isString = require('./helpers').isString;
4
- var isNumber = require('./helpers').isNumber;
5
- var isObject = require('./helpers').isObject;
6
- var isArray = require('./helpers').isArray;
7
- var isUndefined = require('./helpers').isUndefined;
8
4
  var LineBreaker = require('@foliojs-fork/linebreak');
9
- var Tokenizer = require('@flowaccount/node-icu-tokenizer');
10
- var fontkit = require('fontkit');
5
+ const Tokenizer = require('@flowaccount/node-icu-tokenizer');
6
+ const fontkit = require('fontkit');
11
7
 
12
8
  var LEADING = /^(\s)+/g;
13
9
  var TRAILING = /(\s)+$/g;
14
10
 
15
- var fontCacheName = '';
16
- var fontCache = null;
17
- var fontSubstituteCache = {};
18
- var defaultFont = 'Roboto';
19
-
11
+ var fontCacheName_new = '';
12
+ var fontCache_new = {};
13
+ var fontSubstituteCache = [];
14
+ var defaultFont = '';
20
15
  /**
21
16
  * Creates an instance of TextTools - text measurement utility
22
17
  *
@@ -36,10 +31,57 @@ function TextTools(fontProvider) {
36
31
  * @return {Object} collection of inlines, minWidth, maxWidth
37
32
  */
38
33
  TextTools.prototype.buildInlines = function (textArray, styleContextStack) {
39
- primeFontCaches.call(this, styleContextStack);
40
34
 
41
- var measured = measure(this.fontProvider, textArray, styleContextStack);
42
35
 
36
+ defaultFont = (styleContextStack && styleContextStack.getProperty('font')) || 'Roboto';
37
+ // if(!fontCacheName_new)
38
+ // {
39
+ fontCacheName_new = defaultFont;
40
+ // Only open font files if fonts exist and provider has fonts property
41
+ if (this.fontProvider.fonts && this.fontProvider.fonts[fontCacheName_new] && this.fontProvider.fonts[fontCacheName_new].normal) {
42
+ try {
43
+ fontCache_new = fontkit.openSync(this.fontProvider.fonts[fontCacheName_new].normal);
44
+ } catch (e) {
45
+ // Font file doesn't exist (likely in tests), provide mock methods
46
+ fontCache_new = {
47
+ glyphsForString: function(text) {
48
+ // Return mock glyphs - all valid (id > 0)
49
+ return text.split('').map(function(char, i) {
50
+ return { id: i + 1, char: char };
51
+ });
52
+ }
53
+ };
54
+ }
55
+ }
56
+ //}
57
+ //var fcount = 0;
58
+ if (this.fontProvider.fonts) {
59
+ for(let fontItem in this.fontProvider.fonts) {
60
+ if(fontCacheName_new != fontItem) {
61
+ if(!fontSubstituteCache[fontItem])
62
+ {
63
+ try {
64
+ var fontObj = fontkit.openSync(this.fontProvider.fonts[fontItem].normal);
65
+ fontSubstituteCache[fontItem] = { "Name" : fontItem, "FontObj" : fontObj };
66
+ } catch (e) {
67
+ // Font file doesn't exist (likely in tests), provide mock font object
68
+ fontSubstituteCache[fontItem] = {
69
+ "Name" : fontItem,
70
+ "FontObj" : {
71
+ glyphsForString: function(text) {
72
+ // Return mock glyphs - all valid (id > 0)
73
+ return text.split('').map(function(char, i) {
74
+ return { id: i + 1, char: char };
75
+ });
76
+ }
77
+ }
78
+ };
79
+ }
80
+ }
81
+ }
82
+ }
83
+ }
84
+ var measured = measure(this.fontProvider, textArray, styleContextStack);
43
85
  var minWidth = 0,
44
86
  maxWidth = 0,
45
87
  currentLineWidth;
@@ -48,7 +90,7 @@ TextTools.prototype.buildInlines = function (textArray, styleContextStack) {
48
90
  minWidth = Math.max(minWidth, inline.width - inline.leadingCut - inline.trailingCut);
49
91
 
50
92
  if (!currentLineWidth) {
51
- currentLineWidth = { width: 0, leadingCut: inline.leadingCut, trailingCut: 0 };
93
+ currentLineWidth = {width: 0, leadingCut: inline.leadingCut, trailingCut: 0};
52
94
  }
53
95
 
54
96
  currentLineWidth.width += inline.width;
@@ -83,12 +125,11 @@ TextTools.prototype.buildInlines = function (textArray, styleContextStack) {
83
125
  * @return {Object} size of the specified string
84
126
  */
85
127
  TextTools.prototype.sizeOfString = function (text, styleContextStack) {
86
- text = text ? text.toString().replace(/\t/g, ' ') : '';
128
+ text = text ? text.toString().replace('\t', ' ') : '';
87
129
 
88
130
  //TODO: refactor - extract from measure
89
131
  var fontName = getStyleProperty({}, styleContextStack, 'font', 'Roboto');
90
132
  var fontSize = getStyleProperty({}, styleContextStack, 'fontSize', 12);
91
- var fontFeatures = getStyleProperty({}, styleContextStack, 'fontFeatures', null);
92
133
  var bold = getStyleProperty({}, styleContextStack, 'bold', false);
93
134
  var italics = getStyleProperty({}, styleContextStack, 'italics', false);
94
135
  var lineHeight = getStyleProperty({}, styleContextStack, 'lineHeight', 1);
@@ -97,7 +138,7 @@ TextTools.prototype.sizeOfString = function (text, styleContextStack) {
97
138
  var font = this.fontProvider.provideFont(fontName, bold, italics);
98
139
 
99
140
  return {
100
- width: widthOfString(text, font, fontSize, characterSpacing, fontFeatures),
141
+ width: widthOfString(text, font, fontSize, characterSpacing),
101
142
  height: font.lineHeight(fontSize) * lineHeight,
102
143
  fontSize: fontSize,
103
144
  lineHeight: lineHeight,
@@ -106,26 +147,31 @@ TextTools.prototype.sizeOfString = function (text, styleContextStack) {
106
147
  };
107
148
  };
108
149
 
109
- /**
110
- * Returns size of the specified rotated string (without breaking it) using the current style
111
- *
112
- * @param {string} text text to be measured
113
- * @param {number} angle
114
- * @param {object} styleContextStack current style stack
115
- * @returns {object} size of the specified string
116
- */
117
- TextTools.prototype.sizeOfRotatedText = function (text, angle, styleContextStack) {
118
- var angleRad = angle * Math.PI / -180;
119
- var size = this.sizeOfString(text, styleContextStack);
120
- return {
121
- width: Math.abs(size.height * Math.sin(angleRad)) + Math.abs(size.width * Math.cos(angleRad)),
122
- height: Math.abs(size.width * Math.sin(angleRad)) + Math.abs(size.height * Math.cos(angleRad))
123
- };
150
+ TextTools.prototype.widthOfString = function (text, font, fontSize, characterSpacing) {
151
+ return widthOfString(text, font, fontSize, characterSpacing);
124
152
  };
125
153
 
126
- TextTools.prototype.widthOfString = function (text, font, fontSize, characterSpacing, fontFeatures) {
127
- return widthOfString(text, font, fontSize, characterSpacing, fontFeatures);
128
- };
154
+ function tokenizerWords(word) {
155
+
156
+ var regex = / /;
157
+ word = word.replace(regex, "[BLANK]");
158
+
159
+ var tokenizer = new Tokenizer().tokenize(word, { ignoreWhitespaceTokens:false });
160
+ for(var tItem in tokenizer){
161
+ if(tItem < tokenizer.length){
162
+ var numIndex = parseInt(tItem);
163
+ if(tokenizer[numIndex].token == '[' && tokenizer[numIndex + 1].token == 'BLANK' && tokenizer[numIndex + 2].token == ']') {
164
+ tokenizer[numIndex].token = ' ';
165
+ tokenizer[numIndex + 1].del = true;
166
+ tokenizer[numIndex + 2].del = true;
167
+ }
168
+
169
+ } else {
170
+ break;
171
+ }
172
+ }
173
+ return tokenizer;
174
+ }
129
175
 
130
176
  function splitWords(text, noWrap) {
131
177
  var results = [];
@@ -133,86 +179,58 @@ function splitWords(text, noWrap) {
133
179
  text = text.replace(/\t/g, ' ');
134
180
  text = text.replace(/\r/g, '');
135
181
 
136
- // Remove all invisible/hidden Unicode characters that can cause font rendering issues
137
- // This includes: zero-width spaces, directional marks, line/paragraph separators, and other control characters
138
- // See CLAUDE.md "Hidden Unicode Characters & Font Rendering Issues" for full list
139
- text = text.replace(/[\u200B-\u200D\uFEFF\u200E\u200F\u202A-\u202E\u2028\u2029\u180E\u2060-\u2064\u206A-\u206F]/g, '');
182
+ // Remove Hidden Unicode
183
+ text = text.replace(/[\u200D\uFEFF\u200E\u200F\u202A-\u202E\u2028\u2029\u180E\u2060-\u2064\u206A-\u206F]/g, '');
140
184
 
141
185
  if (noWrap) {
142
- results.push({ text: text });
186
+ results.push({text: text});
143
187
  return results;
144
- }
188
+ }
145
189
 
146
- var breaker = new LineBreaker(text);
147
- var last = 0;
148
- var bk;
190
+ var breaker = new LineBreaker(text);
191
+ var last = 0;
192
+ var bk;
149
193
 
150
- while ((bk = breaker.nextBreak())) {
151
- var word = text.slice(last, bk.position);
152
- var isLineEnd = bk.required || /\r?\n$|\r$/.test(word);
153
- var trimmed = word.trim();
154
- var useTokenizer = !exceptTokenizer(trimmed) && needsTokenizer(trimmed);
194
+ while (bk = breaker.nextBreak()) {
195
+ var word = text.slice(last, bk.position);
155
196
 
156
- if (!useTokenizer) {
157
- var output = word;
158
- if (isLineEnd) {
159
- output = output.replace(/\r?\n$|\r$/, '');
160
- }
161
- results.push({ text: output, lineEnd: isLineEnd });
162
- } else {
163
- var tokenWord = tokenizerWords(word);
164
- for (var tIndex = 0; tIndex < tokenWord.length; tIndex++) {
165
- var token = tokenWord[tIndex];
166
- if (!token || token.del) {
167
- continue;
197
+ if(exceptTokenizer(word.trim()))
198
+ {
199
+ results.push({text: word, lineEnd: (bk.required || word.match(/\r?\n$|\r$/))});
168
200
  }
169
-
170
- var tokenText = token.token;
171
- var tokenResult = { text: tokenText };
172
-
173
- if (tokenText === '\n') {
174
- tokenResult.lineEnd = true;
175
- tokenResult.text = '';
176
- } else if (isLineEnd && tIndex === tokenWord.length - 1) {
177
- tokenResult.text = tokenText.replace(/\r?\n$|\r$/, '');
178
- tokenResult.lineEnd = true;
201
+ else if (bk.required || word.match(/\r?\n$|\r$/)) {
202
+ //word = word.replace(/\r?\n$|\r$/, '');
203
+
204
+ var tokenWord = tokenizerWords(word);
205
+ for (var tIndex in tokenWord) {
206
+ if (!tokenWord[tIndex].del) {
207
+ if (tIndex < tokenWord.length - 1 && tokenWord[tIndex].token != '\n') {
208
+ results.push({ text: tokenWord[tIndex].token });
209
+ } else {
210
+ results.push({ text: tokenWord[tIndex].token, lineEnd: true });
211
+ }
212
+ }
213
+ }
214
+ } else {
215
+ var tokenWord = tokenizerWords(word);
216
+ for (var tIndex in tokenWord) {
217
+ if (!tokenWord[tIndex].del) {
218
+ results.push({ text: tokenWord[tIndex].token });
219
+ }
220
+ }
179
221
  }
180
222
 
181
- results.push(tokenResult);
223
+ last = bk.position;
182
224
  }
183
- }
184
-
185
- last = bk.position;
186
- }
187
-
188
225
  return results;
189
226
  }
190
227
 
191
- function tokenizerWords(word) {
192
- var regex = / /;
193
- word = word.replace(regex, '[BLANK]');
194
-
195
- var tokenizer = new Tokenizer().tokenize(word, { ignoreWhitespaceTokens: false });
196
-
197
- for (var i = 0; i < tokenizer.length; i++) {
198
- if (tokenizer[i] && tokenizer[i].token === '[' &&
199
- tokenizer[i + 1] && tokenizer[i + 1].token === 'BLANK' &&
200
- tokenizer[i + 2] && tokenizer[i + 2].token === ']') {
201
- tokenizer[i].token = ' ';
202
- tokenizer[i + 1].del = true;
203
- tokenizer[i + 2].del = true;
204
- }
205
- }
206
-
207
- return tokenizer;
208
- }
209
-
210
228
  function copyStyle(source, destination) {
211
229
  destination = destination || {};
212
230
  source = source || {}; //TODO: default style
213
231
 
214
232
  for (var key in source) {
215
- if (key !== 'text' && Object.prototype.hasOwnProperty.call(source, key)) {
233
+ if (key != 'text' && source.hasOwnProperty(key)) {
216
234
  destination[key] = source[key];
217
235
  }
218
236
  }
@@ -221,69 +239,26 @@ function copyStyle(source, destination) {
221
239
  }
222
240
 
223
241
  function normalizeTextArray(array, styleContextStack) {
224
- function flatten(target) {
225
- return target.reduce(function (prev, cur) {
226
- var current = isObject(cur) && isArray(cur.text) ? flatten(cur.text) : cur;
227
- var more = [].concat(current).some(Array.isArray);
228
- return prev.concat(more ? flatten(current) : current);
229
- }, []);
230
- }
231
-
232
- function getOneWord(index, words, noWrap) {
233
- if (isUndefined(words[index])) {
234
- return null;
235
- }
236
-
237
- if (words[index].lineEnd) {
238
- return null;
239
- }
240
-
241
- var word = words[index].text;
242
-
243
- if (noWrap) {
244
- var tmpWords = splitWords(normalizeString(word), false);
245
- if (isUndefined(tmpWords[tmpWords.length - 1])) {
246
- return null;
247
- }
248
- word = tmpWords[tmpWords.length - 1].text;
249
- }
250
-
251
- return word;
252
- }
253
-
254
242
  var results = [];
255
243
 
256
- if (!isArray(array)) {
244
+ if (!Array.isArray(array)) {
257
245
  array = [array];
258
246
  }
259
247
 
260
- array = flatten(array);
261
-
262
- var lastWord = null;
263
248
  for (var i = 0, l = array.length; i < l; i++) {
264
249
  var item = array[i];
265
250
  var style = null;
266
251
  var words;
267
252
 
268
253
  var noWrap = getStyleProperty(item || {}, styleContextStack, 'noWrap', false);
269
- if (isObject(item)) {
270
- if (item._textRef && item._textRef._textNodeRef && item._textRef._textNodeRef.text) {
271
- item.text = item._textRef._textNodeRef.text;
272
- }
254
+
255
+ if (item !== null && (typeof item === 'object' || item instanceof Object)) {
273
256
  words = splitWords(normalizeString(item.text), noWrap);
274
257
  style = copyStyle(item);
275
258
  } else {
276
259
  words = splitWords(normalizeString(item), noWrap);
277
260
  }
278
261
 
279
- if (lastWord && words.length) {
280
- var firstWord = getOneWord(0, words, noWrap);
281
- var wrapWords = splitWords(normalizeString(lastWord + firstWord), false);
282
- if (wrapWords.length === 1) {
283
- results[results.length - 1].noNewLine = true;
284
- }
285
- }
286
-
287
262
  for (var i2 = 0, l2 = words.length; i2 < l2; i2++) {
288
263
  var result = {
289
264
  text: words[i2].text
@@ -293,32 +268,29 @@ function normalizeTextArray(array, styleContextStack) {
293
268
  result.lineEnd = true;
294
269
  }
295
270
 
296
- // Preserve leading spaces for words that come after a line break (not the first word)
297
- // This fixes the issue where spaces at the beginning of new lines are removed
298
- if (i2 > 0 && words[i2 - 1].lineEnd) {
299
- result.preserveLeadingSpaces = true;
300
- }
301
-
302
271
  copyStyle(style, result);
303
272
  results.push(result);
304
- }
305
-
306
- lastWord = null;
307
- if (i + 1 < l) {
308
- lastWord = getOneWord(words.length - 1, words, noWrap);
309
- }
273
+ }
310
274
  }
311
-
312
275
  return results;
313
276
  }
314
277
 
315
278
  function normalizeString(value) {
316
279
  if (value === undefined || value === null) {
317
280
  return '';
318
- } else if (isNumber(value)) {
281
+ } else if (typeof value === 'number') {
319
282
  return value.toString();
320
- } else if (isString(value)) {
283
+ } else if (typeof value === 'string' || value instanceof String) {
321
284
  return value;
285
+ } else if (Array.isArray(value)) {
286
+ // Handle arrays - extract text from first element if it exists
287
+ if (value.length > 0) {
288
+ return normalizeString(value[0]);
289
+ }
290
+ return '';
291
+ } else if (typeof value === 'object' && value.text !== undefined) {
292
+ // Recursively extract nested text property (handles { text: { text: 'hello' } })
293
+ return normalizeString(value.text);
322
294
  } else {
323
295
  return value.toString();
324
296
  }
@@ -327,18 +299,22 @@ function normalizeString(value) {
327
299
  function getStyleProperty(item, styleContextStack, property, defaultValue) {
328
300
  var value;
329
301
 
330
- if (item && item[property] !== undefined && item[property] !== null) {
302
+ if (item[property] !== undefined && item[property] !== null) {
331
303
  // item defines this property
332
304
  return item[property];
333
305
  }
334
306
 
335
- if (!styleContextStack || typeof styleContextStack.auto !== 'function') {
307
+ if (!styleContextStack) {
336
308
  return defaultValue;
337
309
  }
338
310
 
339
- styleContextStack.auto(item, function () {
311
+ if (styleContextStack.auto && typeof styleContextStack.auto === 'function') {
312
+ styleContextStack.auto(item, function () {
313
+ value = styleContextStack.getProperty(property);
314
+ });
315
+ } else if (styleContextStack.getProperty && typeof styleContextStack.getProperty === 'function') {
340
316
  value = styleContextStack.getProperty(property);
341
- });
317
+ }
342
318
 
343
319
  if (value !== null && value !== undefined) {
344
320
  return value;
@@ -347,9 +323,38 @@ function getStyleProperty(item, styleContextStack, property, defaultValue) {
347
323
  }
348
324
  }
349
325
 
326
+ function getFontCompaitible(item, fontProvider, styleContextStack) {
327
+ // Guard against missing or non-string text
328
+ if (!item.text || typeof item.text !== 'string') {
329
+ return defaultFont;
330
+ }
331
+
332
+ if(fontCacheName_new && fontCache_new && typeof fontCache_new.glyphsForString === 'function') {
333
+ var glyphList = fontCache_new.glyphsForString(item.text);
334
+ if(glyphList.filter(function(x) {return x.id <= 0;}).length == 0) {
335
+ return fontCacheName_new;
336
+ }
337
+ }
338
+ for(let count in fontSubstituteCache) {
339
+ var fontItem = fontSubstituteCache[count];
340
+ if(fontCacheName_new != fontItem.Name) {
341
+ var glyphList = fontItem.FontObj.glyphsForString(item.text);
342
+ if(glyphList.filter(function(x) {return x.id <= 0;}).length == 0) {
343
+ return fontItem.Name;
344
+ }
345
+ }
346
+ }
347
+ return defaultFont;
348
+ }
349
+
350
350
  function measure(fontProvider, textArray, styleContextStack) {
351
351
  var normalized = normalizeTextArray(textArray, styleContextStack);
352
352
 
353
+ // Filter out items without valid text (empty objects, etc.)
354
+ normalized = normalized.filter(function(item) {
355
+ return item.text && typeof item.text === 'string';
356
+ });
357
+
353
358
  if (normalized.length) {
354
359
  var leadingIndent = getStyleProperty(normalized[0], styleContextStack, 'leadingIndent', 0);
355
360
 
@@ -358,11 +363,10 @@ function measure(fontProvider, textArray, styleContextStack) {
358
363
  normalized[0].leadingIndent = leadingIndent;
359
364
  }
360
365
  }
361
-
362
366
  normalized.forEach(function (item) {
363
- var fontName = getFontCompaitible(item);
367
+
368
+ var fontName = getFontCompaitible(item, fontProvider, styleContextStack);//getStyleProperty(item, styleContextStack, 'font', 'Roboto');
364
369
  var fontSize = getStyleProperty(item, styleContextStack, 'fontSize', 12);
365
- var fontFeatures = getStyleProperty(item, styleContextStack, 'fontFeatures', null);
366
370
  var bold = getStyleProperty(item, styleContextStack, 'bold', false);
367
371
  var italics = getStyleProperty(item, styleContextStack, 'italics', false);
368
372
  var color = getStyleProperty(item, styleContextStack, 'color', 'black');
@@ -374,44 +378,34 @@ function measure(fontProvider, textArray, styleContextStack) {
374
378
  var characterSpacing = getStyleProperty(item, styleContextStack, 'characterSpacing', 0);
375
379
  var link = getStyleProperty(item, styleContextStack, 'link', null);
376
380
  var linkToPage = getStyleProperty(item, styleContextStack, 'linkToPage', null);
377
- var linkToDestination = getStyleProperty(item, styleContextStack, 'linkToDestination', null);
378
381
  var noWrap = getStyleProperty(item, styleContextStack, 'noWrap', null);
379
382
  var preserveLeadingSpaces = getStyleProperty(item, styleContextStack, 'preserveLeadingSpaces', false);
380
- var preserveTrailingSpaces = getStyleProperty(item, styleContextStack, 'preserveTrailingSpaces', false);
381
- var opacity = getStyleProperty(item, styleContextStack, 'opacity', 1);
382
- var sup = getStyleProperty(item, styleContextStack, 'sup', false);
383
- var sub = getStyleProperty(item, styleContextStack, 'sub', false);
384
-
385
- if ((sup || sub) && item.fontSize === undefined) {
386
- // font size reduction taken from here: https://en.wikipedia.org/wiki/Subscript_and_superscript#Desktop_publishing
387
- fontSize *= 0.58;
388
- }
389
383
 
390
384
  var font = fontProvider.provideFont(fontName, bold, italics);
391
385
 
392
- item.width = widthOfString(item.text, font, fontSize, characterSpacing, fontFeatures);
386
+ item.width = widthOfString(item.text, font, fontSize, characterSpacing);
393
387
  item.height = font.lineHeight(fontSize) * lineHeight;
394
388
 
389
+ var leadingSpaces = item.text.match(LEADING);
390
+
395
391
  if (!item.leadingCut) {
396
392
  item.leadingCut = 0;
397
393
  }
398
394
 
399
- var leadingSpaces;
400
- if (!preserveLeadingSpaces && (leadingSpaces = item.text.match(LEADING))) {
401
- item.leadingCut += widthOfString(leadingSpaces[0], font, fontSize, characterSpacing, fontFeatures);
395
+ if (leadingSpaces && !preserveLeadingSpaces) {
396
+ item.leadingCut += widthOfString(leadingSpaces[0], font, fontSize, characterSpacing);
402
397
  }
403
398
 
404
- var trailingSpaces;
405
- if (!preserveTrailingSpaces && (trailingSpaces = item.text.match(TRAILING))) {
406
- item.trailingCut = widthOfString(trailingSpaces[0], font, fontSize, characterSpacing, fontFeatures);
407
- } else if (item.trailingCut === undefined) {
399
+ var trailingSpaces = item.text.match(TRAILING);
400
+ if (trailingSpaces) {
401
+ item.trailingCut = widthOfString(trailingSpaces[0], font, fontSize, characterSpacing);
402
+ } else {
408
403
  item.trailingCut = 0;
409
404
  }
410
405
 
411
406
  item.alignment = getStyleProperty(item, styleContextStack, 'alignment', 'left');
412
407
  item.font = font;
413
408
  item.fontSize = fontSize;
414
- item.fontFeatures = fontFeatures;
415
409
  item.characterSpacing = characterSpacing;
416
410
  item.color = color;
417
411
  item.decoration = decoration;
@@ -420,18 +414,14 @@ function measure(fontProvider, textArray, styleContextStack) {
420
414
  item.background = background;
421
415
  item.link = link;
422
416
  item.linkToPage = linkToPage;
423
- item.linkToDestination = linkToDestination;
424
417
  item.noWrap = noWrap;
425
- item.opacity = opacity;
426
- item.sup = sup;
427
- item.sub = sub;
428
418
  });
429
419
 
430
420
  return normalized;
431
421
  }
432
422
 
433
- function widthOfString(text, font, fontSize, characterSpacing, fontFeatures) {
434
- return font.widthOfString(text, fontSize, fontFeatures) + ((characterSpacing || 0) * (text.length - 1));
423
+ function widthOfString(text, font, fontSize, characterSpacing) {
424
+ return font.widthOfString(text, fontSize) + ((characterSpacing || 0) * (text.length - 1));
435
425
  }
436
426
 
437
427
  function exceptTokenizer(word) {
@@ -449,106 +439,4 @@ function exceptTokenizer(word) {
449
439
  return listExceptWord.indexOf(word) > -1;
450
440
  }
451
441
 
452
- function needsTokenizer(word) {
453
- if (!word) {
454
- return false;
455
- }
456
-
457
- return /[\u0E00-\u0E7F]/.test(word);
458
- }
459
-
460
- function primeFontCaches(styleContextStack) {
461
- if (styleContextStack && typeof styleContextStack.getProperty === 'function') {
462
- var stackFont = styleContextStack.getProperty('font');
463
- if (stackFont) {
464
- defaultFont = stackFont;
465
- }
466
- }
467
-
468
- if (!defaultFont) {
469
- defaultFont = 'Roboto';
470
- }
471
-
472
- if (!this.fontProvider || !this.fontProvider.fonts) {
473
- return;
474
- }
475
-
476
- if (defaultFont && fontCacheName !== defaultFont) {
477
- var defaultFontDef = this.fontProvider.fonts[defaultFont];
478
- var primaryFont = safeOpenFont(defaultFontDef && defaultFontDef.normal);
479
-
480
- if (primaryFont) {
481
- fontCacheName = defaultFont;
482
- fontCache = primaryFont;
483
- } else {
484
- fontCacheName = '';
485
- fontCache = null;
486
- }
487
- }
488
-
489
- for (var fontItem in this.fontProvider.fonts) {
490
- if (!Object.prototype.hasOwnProperty.call(this.fontProvider.fonts, fontItem)) {
491
- continue;
492
- }
493
-
494
- if (fontItem === fontCacheName) {
495
- continue;
496
- }
497
-
498
- if (!fontSubstituteCache[fontItem]) {
499
- var substitute = safeOpenFont(this.fontProvider.fonts[fontItem].normal);
500
- if (substitute) {
501
- fontSubstituteCache[fontItem] = { Name: fontItem, FontObj: substitute };
502
- }
503
- }
504
- }
505
- }
506
-
507
- function getFontCompaitible(item) {
508
- var text = item.text || '';
509
-
510
- if (fontCacheName && fontCache && !hasMissingGlyphs(fontCache.glyphsForString(text))) {
511
- return fontCacheName;
512
- }
513
-
514
- for (var key in fontSubstituteCache) {
515
- if (!Object.prototype.hasOwnProperty.call(fontSubstituteCache, key)) {
516
- continue;
517
- }
518
-
519
- var fontItem = fontSubstituteCache[key];
520
- if (!fontItem || !fontItem.FontObj || fontItem.Name === fontCacheName) {
521
- continue;
522
- }
523
-
524
- if (!hasMissingGlyphs(fontItem.FontObj.glyphsForString(text))) {
525
- return fontItem.Name;
526
- }
527
- }
528
-
529
- return defaultFont || 'Roboto';
530
- }
531
-
532
- function hasMissingGlyphs(glyphList) {
533
- for (var i = 0; i < glyphList.length; i++) {
534
- if (!glyphList[i] || glyphList[i].id <= 0) {
535
- return true;
536
- }
537
- }
538
- return false;
539
- }
540
-
541
- function safeOpenFont(path) {
542
- if (!path) {
543
- return null;
544
- }
545
-
546
- try {
547
- return fontkit.openSync(path);
548
- } catch (error) {
549
- void error;
550
- return null;
551
- }
552
- }
553
-
554
442
  module.exports = TextTools;