ag-psd 31.0.3 → 33.0.0
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/.v8-cache/v24.7.0-x64-ef5a0af0/00d0e0b4 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/03e19709 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/05135617 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/0cc76730 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/1130885f +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/20729831 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/214a593b +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/226e2801 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/25f8b84a +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/27518289 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/2a19133e +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/330ef2d9 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/37ff16b8 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/3f72a97c +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/4511bacf +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/68416cb2 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/71df9cb3 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/75efccd4 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/762f9305 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/7bcfc50a +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/7ea06cea +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/825e9a05 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/87372817 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/87cf2209 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/891a7c73 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/8b68a3a2 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/932f0770 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/a1d12a93 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/a7e80865 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/ac317c9c +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/acc36e66 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/b3c2fab7 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/b8569d6b +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/b8b073c4 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/bb489c89 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/c0b789d2 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/c314aece +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/c46725e1 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/c794cb34 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/cd4ae980 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/cfc49f4f +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/cff9434a +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/d02dd6f7 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/dc86f000 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/e03e2acd +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/e6735171 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/e6745c2b +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/e6b99945 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/eeeebdfe +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/f5417276 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/f6fd8125 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/f74d3518 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/f886deac +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/fd0a2987 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/fe349423 +0 -0
- package/CHANGELOG.md +107 -0
- package/LICENSE +5 -0
- package/README.md +3 -6
- package/README_PSD.md +242 -81
- package/dist/abr.d.ts +11 -4
- package/dist/abr.js +363 -229
- package/dist/abr.js.map +1 -1
- package/dist/additionalInfo.d.ts +56 -2
- package/dist/additionalInfo.js +600 -364
- package/dist/additionalInfo.js.map +1 -1
- package/dist/ase.d.ts +6 -1
- package/dist/ase.js +61 -61
- package/dist/ase.js.map +1 -1
- package/dist/bundle.js +3096 -1541
- package/dist/descriptor.d.ts +25 -6
- package/dist/descriptor.js +380 -135
- package/dist/descriptor.js.map +1 -1
- package/dist/effectsHelpers.js +12 -12
- package/dist/effectsHelpers.js.map +1 -1
- package/dist/engineData.d.ts +3 -1
- package/dist/engineData.js +34 -13
- package/dist/engineData.js.map +1 -1
- package/dist/engineData2.js +50 -21
- package/dist/engineData2.js.map +1 -1
- package/dist/helpers.d.ts +6 -3
- package/dist/helpers.js +22 -6
- package/dist/helpers.js.map +1 -1
- package/dist/imageResources.d.ts +15 -3
- package/dist/imageResources.js +529 -144
- package/dist/imageResources.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/jpeg.js +30 -10
- package/dist/jpeg.js.map +1 -1
- package/dist/psd.d.ts +154 -18
- package/dist/psd.js.map +1 -1
- package/dist/psdReader.d.ts +12 -2
- package/dist/psdReader.js +720 -421
- package/dist/psdReader.js.map +1 -1
- package/dist/psdWriter.d.ts +3 -0
- package/dist/psdWriter.js +167 -130
- package/dist/psdWriter.js.map +1 -1
- package/dist/text.js +143 -29
- package/dist/text.js.map +1 -1
- package/dist/utf8.js +36 -18
- package/dist/utf8.js.map +1 -1
- package/dist-es/abr.d.ts +11 -4
- package/dist-es/abr.js +363 -229
- package/dist-es/abr.js.map +1 -1
- package/dist-es/additionalInfo.d.ts +56 -2
- package/dist-es/additionalInfo.js +600 -364
- package/dist-es/additionalInfo.js.map +1 -1
- package/dist-es/ase.d.ts +6 -1
- package/dist-es/ase.js +61 -61
- package/dist-es/ase.js.map +1 -1
- package/dist-es/descriptor.d.ts +25 -6
- package/dist-es/descriptor.js +380 -135
- package/dist-es/descriptor.js.map +1 -1
- package/dist-es/effectsHelpers.js +12 -12
- package/dist-es/effectsHelpers.js.map +1 -1
- package/dist-es/engineData.d.ts +3 -1
- package/dist-es/engineData.js +34 -13
- package/dist-es/engineData.js.map +1 -1
- package/dist-es/engineData2.js +50 -21
- package/dist-es/engineData2.js.map +1 -1
- package/dist-es/helpers.d.ts +6 -3
- package/dist-es/helpers.js +22 -6
- package/dist-es/helpers.js.map +1 -1
- package/dist-es/imageResources.d.ts +15 -3
- package/dist-es/imageResources.js +529 -144
- package/dist-es/imageResources.js.map +1 -1
- package/dist-es/index.js +1 -0
- package/dist-es/index.js.map +1 -1
- package/dist-es/jpeg.js +30 -10
- package/dist-es/jpeg.js.map +1 -1
- package/dist-es/psd.d.ts +154 -18
- package/dist-es/psd.js.map +1 -1
- package/dist-es/psdReader.d.ts +12 -2
- package/dist-es/psdReader.js +720 -421
- package/dist-es/psdReader.js.map +1 -1
- package/dist-es/psdWriter.d.ts +3 -0
- package/dist-es/psdWriter.js +167 -130
- package/dist-es/psdWriter.js.map +1 -1
- package/dist-es/text.js +143 -29
- package/dist-es/text.js.map +1 -1
- package/dist-es/utf8.js +36 -18
- package/dist-es/utf8.js.map +1 -1
- package/package.json +2 -2
- package/src/abr.ts +380 -232
- package/src/additionalInfo.ts +781 -477
- package/src/ase.ts +66 -61
- package/src/descriptor.ts +386 -142
- package/src/effectsHelpers.ts +9 -9
- package/src/engineData.ts +36 -13
- package/src/engineData2.ts +468 -432
- package/src/helpers.ts +23 -5
- package/src/imageResources.ts +658 -167
- package/src/index.ts +1 -0
- package/src/jpeg.ts +27 -12
- package/src/psd.ts +158 -30
- package/src/psdReader.ts +732 -414
- package/src/psdWriter.ts +186 -132
- package/src/text.ts +139 -18
- package/src/utf8.ts +35 -21
package/src/text.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { TextStyle, LayerTextData, ParagraphStyle, Font, AntiAlias, TextGridInfo, Justification, Color, TextPath } from './psd';
|
|
2
|
+
import { clamp } from './helpers';
|
|
2
3
|
|
|
3
4
|
interface Adjustments {
|
|
4
5
|
Axis: number[];
|
|
@@ -273,7 +274,16 @@ const styleKeys: (keyof TextStyle)[] = [
|
|
|
273
274
|
'kashida', 'diacriticPos',
|
|
274
275
|
];
|
|
275
276
|
|
|
276
|
-
const antialias: AntiAlias[] = [
|
|
277
|
+
const antialias: (AntiAlias | undefined)[] = [
|
|
278
|
+
'none', // 0
|
|
279
|
+
'crisp', // 1
|
|
280
|
+
'strong', // 2
|
|
281
|
+
'smooth', // 3
|
|
282
|
+
'sharp', // 4
|
|
283
|
+
undefined, // 5 - unknown
|
|
284
|
+
'platformLCD', // 6
|
|
285
|
+
'platform', // 7
|
|
286
|
+
];
|
|
277
287
|
const justification: Justification[] = [
|
|
278
288
|
'left', // 0
|
|
279
289
|
'right', // 1
|
|
@@ -300,13 +310,43 @@ function decodeColor(color: TypeValues): Color {
|
|
|
300
310
|
}
|
|
301
311
|
}
|
|
302
312
|
|
|
313
|
+
// h, s, b in 0..1 range, returns r, g, b in 0..1 range
|
|
314
|
+
function hsbToRgb(h: number, s: number, v: number): [number, number, number] {
|
|
315
|
+
h = clamp(h || 0, 0, 1);
|
|
316
|
+
s = clamp(s || 0, 0, 1);
|
|
317
|
+
v = clamp(v || 0, 0, 1);
|
|
318
|
+
|
|
319
|
+
const h6 = (h * 6) % 6;
|
|
320
|
+
const i = Math.floor(h6);
|
|
321
|
+
const f = h6 - i;
|
|
322
|
+
const p = v * (1 - s);
|
|
323
|
+
const q = v * (1 - s * f);
|
|
324
|
+
const t = v * (1 - s * (1 - f));
|
|
325
|
+
|
|
326
|
+
switch (i) {
|
|
327
|
+
case 0: return [v, t, p];
|
|
328
|
+
case 1: return [q, v, p];
|
|
329
|
+
case 2: return [p, v, t];
|
|
330
|
+
case 3: return [p, q, v];
|
|
331
|
+
case 4: return [t, p, v];
|
|
332
|
+
default: return [v, p, q];
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
303
336
|
function encodeColor(color: Color | undefined): TypeValues {
|
|
304
337
|
if (!color) {
|
|
305
338
|
return { Type: 1, Values: [0, 0, 0, 0] };
|
|
306
339
|
} else if ('r' in color) {
|
|
307
340
|
return { Type: 1, Values: ['a' in color ? color.a / 255 : 1, color.r / 255, color.g / 255, color.b / 255] };
|
|
341
|
+
} else if ('fr' in color) {
|
|
342
|
+
return { Type: 1, Values: [1, clamp(color.fr || 0, 0, 1), clamp(color.fg || 0, 0, 1), clamp(color.fb || 0, 0, 1)] };
|
|
343
|
+
} else if ('h' in color) {
|
|
344
|
+
const [r, g, b] = hsbToRgb(color.h, color.s, color.b);
|
|
345
|
+
return { Type: 1, Values: [1, r, g, b] };
|
|
308
346
|
} else if ('c' in color) {
|
|
309
347
|
return { Type: 2, Values: [1, color.c / 255, color.m / 255, color.y / 255, color.k / 255] };
|
|
348
|
+
} else if ('l' in color) {
|
|
349
|
+
throw new Error('LAB colors are not supported in text layers, use RGB, CMYK or grayscale color instead');
|
|
310
350
|
} else if ('k' in color) {
|
|
311
351
|
return { Type: 0, Values: [1, color.k / 255] };
|
|
312
352
|
} else {
|
|
@@ -329,8 +369,9 @@ function objectsEqual(a: any, b: any) {
|
|
|
329
369
|
}
|
|
330
370
|
|
|
331
371
|
function findOrAddFont(fonts: Font[], font: Font) {
|
|
372
|
+
// Photoshop writes separate entries for the same font with different synthetic (faux bold/italic) styles
|
|
332
373
|
for (let i = 0; i < fonts.length; i++) {
|
|
333
|
-
if (fonts[i].name === font.name) return i;
|
|
374
|
+
if (fonts[i].name === font.name && (fonts[i].synthetic || 0) === (font.synthetic || 0)) return i;
|
|
334
375
|
}
|
|
335
376
|
|
|
336
377
|
fonts.push(font);
|
|
@@ -346,9 +387,10 @@ function decodeObject(obj: any, keys: string[], fonts: Font[]) {
|
|
|
346
387
|
if (obj[Key] === undefined) continue;
|
|
347
388
|
|
|
348
389
|
if (key === 'justification') {
|
|
349
|
-
result[key] = justification[obj[Key]];
|
|
390
|
+
result[key] = justification[obj[Key]] ?? 'left';
|
|
350
391
|
} else if (key === 'font') {
|
|
351
|
-
|
|
392
|
+
const font = fonts[obj[Key]];
|
|
393
|
+
if (font) result[key] = font; // invalid font index, leave the font unset so it falls back to default
|
|
352
394
|
} else if (key === 'fillColor' || key === 'strokeColor') {
|
|
353
395
|
result[key] = decodeColor(obj[Key]);
|
|
354
396
|
} else {
|
|
@@ -368,7 +410,7 @@ function encodeObject(obj: any, keys: string[], fonts: Font[]) {
|
|
|
368
410
|
if (obj[key] === undefined) continue;
|
|
369
411
|
|
|
370
412
|
if (key === 'justification') {
|
|
371
|
-
result[Key] = justification.indexOf(obj[key] ?? 'left');
|
|
413
|
+
result[Key] = Math.max(0, justification.indexOf(obj[key] ?? 'left')); // default to 'left' for unknown values
|
|
372
414
|
} else if (key === 'font') {
|
|
373
415
|
result[Key] = findOrAddFont(fonts, obj[key]);
|
|
374
416
|
} else if (key === 'fillColor' || key === 'strokeColor') {
|
|
@@ -443,6 +485,39 @@ function deduplicateValues<T>(base: T, runs: { style: T; }[], keys: (keyof T)[])
|
|
|
443
485
|
}
|
|
444
486
|
}
|
|
445
487
|
|
|
488
|
+
function isDefaultGridColor(color: Color | undefined) {
|
|
489
|
+
// Photoshop writes default grid colors as blue with 0 alpha, ignore alpha when comparing
|
|
490
|
+
return !!color && 'r' in color && color.r === 0 && color.g === 0 && color.b === 255;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
function decodeGridColor(color: TypeValues | undefined, defaultColor: Color): Color {
|
|
494
|
+
try {
|
|
495
|
+
return color ? decodeColor(color) : defaultColor;
|
|
496
|
+
} catch {
|
|
497
|
+
return defaultColor; // don't fail whole text layer because of invalid grid color
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
function decodeGridInfo(grid: EngineData['EngineDict']['GridInfo'] | undefined): TextGridInfo | undefined {
|
|
502
|
+
if (!grid || typeof grid !== 'object') return undefined;
|
|
503
|
+
|
|
504
|
+
const result: TextGridInfo = {
|
|
505
|
+
isOn: !!grid.GridIsOn,
|
|
506
|
+
show: !!grid.ShowGrid,
|
|
507
|
+
size: grid.GridSize ?? defaultGridInfo.size,
|
|
508
|
+
leading: grid.GridLeading ?? defaultGridInfo.leading,
|
|
509
|
+
color: decodeGridColor(grid.GridColor, defaultGridInfo.color!),
|
|
510
|
+
leadingFillColor: decodeGridColor(grid.GridLeadingFillColor, defaultGridInfo.leadingFillColor!),
|
|
511
|
+
alignLineHeightToGridFlags: !!grid.AlignLineHeightToGridFlags,
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
const isDefault = !result.isOn && !result.show && result.size === defaultGridInfo.size &&
|
|
515
|
+
result.leading === defaultGridInfo.leading && !result.alignLineHeightToGridFlags &&
|
|
516
|
+
isDefaultGridColor(result.color) && isDefaultGridColor(result.leadingFillColor);
|
|
517
|
+
|
|
518
|
+
return isDefault ? undefined : result;
|
|
519
|
+
}
|
|
520
|
+
|
|
446
521
|
export function decodeEngineData(engineData: EngineData) {
|
|
447
522
|
// console.log('engineData', require('util').inspect(engineData, false, 99, true));
|
|
448
523
|
const engineDict = engineData.EngineDict;
|
|
@@ -458,9 +533,11 @@ export function decodeEngineData(engineData: EngineData) {
|
|
|
458
533
|
let text = engineDict.Editor.Text.replace(/\r/g, '\n');
|
|
459
534
|
let removedCharacters = 0;
|
|
460
535
|
|
|
461
|
-
|
|
536
|
+
// Photoshop always appends exactly one trailing \r (and encoder adds one back), any additional
|
|
537
|
+
// trailing new lines are empty paragraphs that are part of the text
|
|
538
|
+
if (/\n$/.test(text)) {
|
|
462
539
|
text = text.substring(0, text.length - 1);
|
|
463
|
-
removedCharacters
|
|
540
|
+
removedCharacters = 1;
|
|
464
541
|
}
|
|
465
542
|
|
|
466
543
|
const result: LayerTextData = {
|
|
@@ -484,6 +561,11 @@ export function decodeEngineData(engineData: EngineData) {
|
|
|
484
561
|
if (photoshop.BoxBounds) result.boxBounds = photoshop.BoxBounds;
|
|
485
562
|
}
|
|
486
563
|
|
|
564
|
+
// grid info (only included when it differs from defaults, to avoid noise in common case)
|
|
565
|
+
|
|
566
|
+
const gridInfo = decodeGridInfo(engineDict.GridInfo);
|
|
567
|
+
if (gridInfo) result.gridInfo = gridInfo;
|
|
568
|
+
|
|
487
569
|
// paragraph style
|
|
488
570
|
|
|
489
571
|
// const theNormalParagraphSheet = resourceDict.TheNormalParagraphSheet;
|
|
@@ -506,7 +588,8 @@ export function decodeEngineData(engineData: EngineData) {
|
|
|
506
588
|
}
|
|
507
589
|
|
|
508
590
|
for (let counter = removedCharacters; result.paragraphStyleRuns.length && counter > 0; counter--) {
|
|
509
|
-
|
|
591
|
+
// keep 0 length run if it's for empty last paragraph, otherwise we lose its style
|
|
592
|
+
if (--result.paragraphStyleRuns[result.paragraphStyleRuns.length - 1].length === 0 && result.paragraphStyleRuns.length === 1) {
|
|
510
593
|
result.paragraphStyleRuns.pop();
|
|
511
594
|
}
|
|
512
595
|
}
|
|
@@ -522,13 +605,18 @@ export function decodeEngineData(engineData: EngineData) {
|
|
|
522
605
|
// const styleSheetData = styleSheetSet[theNormalStyleSheet].StyleSheetData;
|
|
523
606
|
const styleRun = engineDict.StyleRun;
|
|
524
607
|
|
|
608
|
+
// style runs without a font use the font of the normal style sheet
|
|
609
|
+
const normalStyleSheet = resourceDict.StyleSheetSet?.[resourceDict.TheNormalStyleSheet ?? 0]?.StyleSheetData;
|
|
610
|
+
const normalFontIndex = normalStyleSheet?.Font;
|
|
611
|
+
const normalFont = (normalFontIndex !== undefined ? fonts[normalFontIndex] : undefined) ?? fonts[0];
|
|
612
|
+
|
|
525
613
|
result.style = {}; // decodeStyle(styleSheetData, fonts);
|
|
526
614
|
result.styleRuns = [];
|
|
527
615
|
|
|
528
616
|
for (let i = 0; i < styleRun.RunArray.length; i++) {
|
|
529
617
|
const length = styleRun.RunLengthArray[i];
|
|
530
618
|
const style = decodeStyle(styleRun.RunArray[i].StyleSheet.StyleSheetData, fonts);
|
|
531
|
-
if (!style.font) style.font =
|
|
619
|
+
if (!style.font && normalFont) style.font = normalFont;
|
|
532
620
|
result.styleRuns.push({ length, style });
|
|
533
621
|
}
|
|
534
622
|
|
|
@@ -545,8 +633,38 @@ export function decodeEngineData(engineData: EngineData) {
|
|
|
545
633
|
return result;
|
|
546
634
|
}
|
|
547
635
|
|
|
636
|
+
// Adjusts run lengths (specified in terms of the original text) for characters removed from the text
|
|
637
|
+
// (\r characters of \r\n pairs that are collapsed into single \r)
|
|
638
|
+
function adjustRunLengths<T extends { length: number; }>(runs: T[] | undefined, removed: number[]): T[] | undefined {
|
|
639
|
+
if (!runs || !removed.length) return runs;
|
|
640
|
+
|
|
641
|
+
let start = 0;
|
|
642
|
+
let removedIndex = 0;
|
|
643
|
+
|
|
644
|
+
return runs.map(run => {
|
|
645
|
+
const length = Math.max(0, run.length || 0);
|
|
646
|
+
const end = start + length;
|
|
647
|
+
let count = 0;
|
|
648
|
+
|
|
649
|
+
while (removedIndex < removed.length && removed[removedIndex] < end) {
|
|
650
|
+
if (removed[removedIndex] >= start) count++;
|
|
651
|
+
removedIndex++;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
start = end;
|
|
655
|
+
return { ...run, length: length - count };
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
|
|
548
659
|
export function encodeEngineData(data: LayerTextData) {
|
|
549
|
-
const
|
|
660
|
+
const sourceText = data.text || '';
|
|
661
|
+
const removedIndices: number[] = []; // indices of \r characters removed from \r\n pairs
|
|
662
|
+
|
|
663
|
+
for (let i = 0; i < sourceText.length - 1; i++) {
|
|
664
|
+
if (sourceText.charCodeAt(i) === 13 && sourceText.charCodeAt(i + 1) === 10) removedIndices.push(i);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
const text = `${sourceText.replace(/\r?\n/g, '\r')}\r`;
|
|
550
668
|
|
|
551
669
|
const fonts: Font[] = [
|
|
552
670
|
{ name: 'AdobeInvisFont', script: 0, type: 0, synthetic: 0 },
|
|
@@ -555,7 +673,7 @@ export function encodeEngineData(data: LayerTextData) {
|
|
|
555
673
|
const defFont = data.style?.font || data.styleRuns?.find(s => s.style.font)?.style.font || defaultFont;
|
|
556
674
|
const paragraphRunArray: ParagraphRun[] = [];
|
|
557
675
|
const paragraphRunLengthArray: number[] = [];
|
|
558
|
-
const paragraphRuns = data.paragraphStyleRuns;
|
|
676
|
+
const paragraphRuns = adjustRunLengths(data.paragraphStyleRuns, removedIndices);
|
|
559
677
|
|
|
560
678
|
if (paragraphRuns && paragraphRuns.length) {
|
|
561
679
|
let leftLength = text.length;
|
|
@@ -564,14 +682,14 @@ export function encodeEngineData(data: LayerTextData) {
|
|
|
564
682
|
let runLength = Math.min(run.length, leftLength);
|
|
565
683
|
leftLength -= runLength;
|
|
566
684
|
|
|
567
|
-
if (
|
|
568
|
-
|
|
569
|
-
// extend last run if it's only for trailing \r
|
|
685
|
+
// extend last run if it's only for trailing \r (last run has 0 length if it's for empty last paragraph)
|
|
570
686
|
if (leftLength === 1 && run === paragraphRuns[paragraphRuns.length - 1]) {
|
|
571
687
|
runLength++;
|
|
572
688
|
leftLength--;
|
|
573
689
|
}
|
|
574
690
|
|
|
691
|
+
if (!runLength) continue; // ignore 0 size runs
|
|
692
|
+
|
|
575
693
|
paragraphRunLengthArray.push(runLength);
|
|
576
694
|
paragraphRunArray.push({
|
|
577
695
|
ParagraphSheet: {
|
|
@@ -609,7 +727,9 @@ export function encodeEngineData(data: LayerTextData) {
|
|
|
609
727
|
}
|
|
610
728
|
|
|
611
729
|
const styleSheetData = encodeStyle({ ...defaultStyle, font: defFont }, fonts);
|
|
612
|
-
const styleRuns = data.styleRuns
|
|
730
|
+
const styleRuns = data.styleRuns?.length ?
|
|
731
|
+
adjustRunLengths(data.styleRuns, removedIndices)! :
|
|
732
|
+
[{ length: text.length, style: data.style || {} }];
|
|
613
733
|
const styleRunArray: StyleRun[] = [];
|
|
614
734
|
const styleRunLengthArray: number[] = [];
|
|
615
735
|
|
|
@@ -642,7 +762,7 @@ export function encodeEngineData(data: LayerTextData) {
|
|
|
642
762
|
}
|
|
643
763
|
|
|
644
764
|
// add extra run to the end if existing ones didn't fill it up
|
|
645
|
-
if (leftLength
|
|
765
|
+
if (leftLength) {
|
|
646
766
|
styleRunLengthArray.push(leftLength);
|
|
647
767
|
styleRunArray.push({
|
|
648
768
|
StyleSheet: {
|
|
@@ -657,6 +777,7 @@ export function encodeEngineData(data: LayerTextData) {
|
|
|
657
777
|
}
|
|
658
778
|
|
|
659
779
|
const gridInfo = { ...defaultGridInfo, ...data.gridInfo };
|
|
780
|
+
const antiAliasIndex = antialias.indexOf(data.antiAlias ?? 'sharp');
|
|
660
781
|
const WritingDirection = data.orientation === 'vertical' ? 2 : 0;
|
|
661
782
|
const Procession = data.orientation === 'vertical' ? 1 : 0;
|
|
662
783
|
const ShapeType = data.shapeType === 'box' ? 1 : 0;
|
|
@@ -753,10 +874,10 @@ export function encodeEngineData(data: LayerTextData) {
|
|
|
753
874
|
GridSize: gridInfo.size ?? 18,
|
|
754
875
|
GridLeading: gridInfo.leading ?? 22,
|
|
755
876
|
GridColor: encodeColor(gridInfo.color),
|
|
756
|
-
GridLeadingFillColor: encodeColor(gridInfo.
|
|
877
|
+
GridLeadingFillColor: encodeColor(gridInfo.leadingFillColor),
|
|
757
878
|
AlignLineHeightToGridFlags: !!gridInfo.alignLineHeightToGridFlags,
|
|
758
879
|
},
|
|
759
|
-
AntiAlias: antialias.indexOf(
|
|
880
|
+
AntiAlias: antiAliasIndex === -1 ? antialias.indexOf('sharp') : antiAliasIndex,
|
|
760
881
|
UseFractionalGlyphWidths: data.useFractionalGlyphWidths ?? true,
|
|
761
882
|
Rendered: {
|
|
762
883
|
Version: 1,
|
package/src/utf8.ts
CHANGED
|
@@ -10,36 +10,48 @@ function charLengthInBytes(code: number): number {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
//
|
|
13
|
+
// Returns scalar value at index `i` (combining surrogate pairs), replacing unpaired surrogates with U+FFFD,
|
|
14
14
|
// matching how TextEncoder converts a string to a sequence of Unicode scalar values.
|
|
15
|
-
|
|
15
|
+
// Values above 0xffff always take 2 UTF-16 code units.
|
|
16
|
+
function codePointAt(value: string, i: number): number {
|
|
16
17
|
const code = value.charCodeAt(i);
|
|
17
18
|
|
|
19
|
+
if (code < 0xd800 || code > 0xdfff) return code;
|
|
20
|
+
|
|
18
21
|
// high surrogate
|
|
19
|
-
if (code
|
|
22
|
+
if (code <= 0xdbff && (i + 1) < value.length) {
|
|
20
23
|
const extra = value.charCodeAt(i + 1);
|
|
21
24
|
|
|
22
25
|
// low surrogate
|
|
23
26
|
if (extra >= 0xdc00 && extra <= 0xdfff) {
|
|
24
|
-
return
|
|
27
|
+
return ((code & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000;
|
|
25
28
|
}
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
// unpaired surrogate (lone high or lone low)
|
|
29
|
-
|
|
30
|
-
return { code: 0xfffd, size: 1 };
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return { code, size: 1 };
|
|
32
|
+
return 0xfffd;
|
|
34
33
|
}
|
|
35
34
|
|
|
36
35
|
export function stringLengthInBytes(value: string): number {
|
|
37
36
|
let result = 0;
|
|
38
37
|
|
|
39
|
-
for (let i = 0; i < value.length;) {
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
for (let i = 0; i < value.length; i++) {
|
|
39
|
+
const code = value.charCodeAt(i);
|
|
40
|
+
|
|
41
|
+
if (code < 0x80) {
|
|
42
|
+
result += 1;
|
|
43
|
+
} else if (code < 0x800) {
|
|
44
|
+
result += 2;
|
|
45
|
+
} else {
|
|
46
|
+
const scalar = codePointAt(value, i);
|
|
47
|
+
|
|
48
|
+
if (scalar > 0xffff) {
|
|
49
|
+
result += 4;
|
|
50
|
+
i++;
|
|
51
|
+
} else {
|
|
52
|
+
result += 3;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
43
55
|
}
|
|
44
56
|
|
|
45
57
|
return result;
|
|
@@ -73,10 +85,16 @@ function writeCharacter(buffer: Uint8Array | Buffer, offset: number, code: numbe
|
|
|
73
85
|
}
|
|
74
86
|
|
|
75
87
|
export function encodeStringTo(buffer: Uint8Array | Buffer, offset: number, value: string): number {
|
|
76
|
-
for (let i = 0; i < value.length;) {
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
88
|
+
for (let i = 0; i < value.length; i++) {
|
|
89
|
+
const code = value.charCodeAt(i);
|
|
90
|
+
|
|
91
|
+
if (code < 0x80) {
|
|
92
|
+
buffer[offset++] = code;
|
|
93
|
+
} else {
|
|
94
|
+
const scalar = codePointAt(value, i);
|
|
95
|
+
if (scalar > 0xffff) i++;
|
|
96
|
+
offset += writeCharacter(buffer, offset, scalar);
|
|
97
|
+
}
|
|
80
98
|
}
|
|
81
99
|
|
|
82
100
|
return offset;
|
|
@@ -95,10 +113,6 @@ export function encodeString(value: string): Uint8Array {
|
|
|
95
113
|
// UTF-8 decoder implementing the WHATWG Encoding Standard's non-fatal error handling,
|
|
96
114
|
// so malformed byte sequences are replaced with U+FFFD instead of throwing, matching TextDecoder.
|
|
97
115
|
export function decodeString(value: Uint8Array): string {
|
|
98
|
-
if (value.byteLength > 1000 && typeof TextDecoder !== 'undefined') {
|
|
99
|
-
return (new TextDecoder()).decode(value);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
116
|
const result: string[] = [];
|
|
103
117
|
|
|
104
118
|
function pushCodePoint(code: number) {
|