ag-psd 32.0.0 → 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/03e19709 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/05135617 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/1130885f +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/226e2801 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/2a19133e +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/7ea06cea +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/932f0770 +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/c314aece +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/dc86f000 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/e03e2acd +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/f6fd8125 +0 -0
- package/CHANGELOG.md +78 -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 +357 -230
- package/dist/abr.js.map +1 -1
- package/dist/additionalInfo.d.ts +54 -2
- package/dist/additionalInfo.js +487 -306
- 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 +1937 -1115
- package/dist/descriptor.d.ts +14 -8
- package/dist/descriptor.js +202 -186
- package/dist/descriptor.js.map +1 -1
- package/dist/helpers.d.ts +1 -1
- package/dist/helpers.js +4 -2
- package/dist/helpers.js.map +1 -1
- package/dist/imageResources.d.ts +15 -3
- package/dist/imageResources.js +503 -142
- package/dist/imageResources.js.map +1 -1
- package/dist/jpeg.js +8 -8
- package/dist/jpeg.js.map +1 -1
- package/dist/psd.d.ts +148 -17
- package/dist/psd.js.map +1 -1
- package/dist/psdReader.d.ts +10 -0
- package/dist/psdReader.js +278 -166
- package/dist/psdReader.js.map +1 -1
- package/dist/psdWriter.d.ts +1 -0
- package/dist/psdWriter.js +77 -62
- package/dist/psdWriter.js.map +1 -1
- package/dist/text.js +17 -6
- package/dist/text.js.map +1 -1
- package/dist/utf8.js +0 -3
- package/dist/utf8.js.map +1 -1
- package/dist-es/abr.d.ts +11 -4
- package/dist-es/abr.js +357 -230
- package/dist-es/abr.js.map +1 -1
- package/dist-es/additionalInfo.d.ts +54 -2
- package/dist-es/additionalInfo.js +487 -306
- 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 +14 -8
- package/dist-es/descriptor.js +202 -186
- package/dist-es/descriptor.js.map +1 -1
- package/dist-es/helpers.d.ts +1 -1
- package/dist-es/helpers.js +4 -2
- package/dist-es/helpers.js.map +1 -1
- package/dist-es/imageResources.d.ts +15 -3
- package/dist-es/imageResources.js +503 -142
- package/dist-es/imageResources.js.map +1 -1
- package/dist-es/jpeg.js +8 -8
- package/dist-es/jpeg.js.map +1 -1
- package/dist-es/psd.d.ts +148 -17
- package/dist-es/psd.js.map +1 -1
- package/dist-es/psdReader.d.ts +10 -0
- package/dist-es/psdReader.js +278 -166
- package/dist-es/psdReader.js.map +1 -1
- package/dist-es/psdWriter.d.ts +1 -0
- package/dist-es/psdWriter.js +77 -62
- package/dist-es/psdWriter.js.map +1 -1
- package/dist-es/text.js +17 -6
- package/dist-es/text.js.map +1 -1
- package/dist-es/utf8.js +0 -3
- package/dist-es/utf8.js.map +1 -1
- package/package.json +2 -2
- package/src/abr.ts +375 -235
- package/src/additionalInfo.ts +663 -420
- package/src/ase.ts +66 -61
- package/src/descriptor.ts +199 -195
- package/src/helpers.ts +4 -1
- package/src/imageResources.ts +632 -168
- package/src/jpeg.ts +8 -8
- package/src/psd.ts +156 -30
- package/src/psdReader.ts +273 -172
- package/src/psdWriter.ts +95 -58
- package/src/text.ts +17 -6
- package/src/utf8.ts +0 -4
package/dist-es/descriptor.js
CHANGED
|
@@ -11,14 +11,13 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
return t;
|
|
12
12
|
};
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.
|
|
15
|
-
exports.presetKindType = exports.prjM = exports.FlMd = void 0;
|
|
14
|
+
exports.Drct = exports.WndM = exports.CntE = exports.FlCl = exports.ExtR = exports.ExtT = exports.DfsM = exports.blurType = exports.Lns = exports.MztT = exports.Chnl = exports.Dstr = exports.ZZTy = exports.Wvtp = exports.SphM = exports.RplS = exports.Cnvr = exports.UndA = exports.DspM = exports.SmBQ = exports.SmBM = exports.BlrQ = exports.BlrM = exports.strokeStyleLineAlignment = exports.strokeStyleLineJoinType = exports.strokeStyleLineCapType = exports.ESliceBGColorType = exports.ESliceOrigin = exports.ESliceVertAlign = exports.ESliceHorzAlign = exports.ESliceType = exports.FrFl = exports.FStl = exports.ClrS = exports.Clry = exports.gradientInterpolationMethodType = exports.stdTrackID = exports.animInterpStyleEnum = exports.GrdT = exports.IGSr = exports.BETE = exports.BESs = exports.bvlT = exports.BESl = exports.BlnM = exports.warpStyle = exports.Annt = exports.Ornt = exports.textGridding = exports.outputSettingsRoot = void 0;
|
|
15
|
+
exports.presetKindType = exports.prjM = exports.FlMd = exports.IntC = exports.IntE = void 0;
|
|
16
16
|
exports.setLogErrors = setLogErrors;
|
|
17
17
|
exports.readAsciiStringOrClassId = readAsciiStringOrClassId;
|
|
18
18
|
exports.writeAsciiStringOrClassId = writeAsciiStringOrClassId;
|
|
19
19
|
exports.readDescriptorStructure = readDescriptorStructure;
|
|
20
20
|
exports.writeDescriptorStructure = writeDescriptorStructure;
|
|
21
|
-
exports.createDescriptorReference = createDescriptorReference;
|
|
22
21
|
exports.pathSelectionStateToReference = pathSelectionStateToReference;
|
|
23
22
|
exports.writeClassStructure = writeClassStructure;
|
|
24
23
|
exports.readVersionAndDescriptor = readVersionAndDescriptor;
|
|
@@ -167,6 +166,7 @@ const fieldToArrayExtType = {
|
|
|
167
166
|
Clrs: makeType('', 'Clrt'),
|
|
168
167
|
Trns: makeType('', 'TrnS'),
|
|
169
168
|
keyDescriptorList: nullType,
|
|
169
|
+
keyRootDescriptorList: nullType,
|
|
170
170
|
solidFillMulti: makeType('', 'SoFi'),
|
|
171
171
|
gradientFillMulti: makeType('', 'GrFl'),
|
|
172
172
|
dropShadowMulti: makeType('', 'DrSh'),
|
|
@@ -200,17 +200,23 @@ const fieldToArrayExtType = {
|
|
|
200
200
|
};
|
|
201
201
|
const typeToField = {
|
|
202
202
|
'TEXT': [
|
|
203
|
-
'Txt ', 'printerName', 'Nm ', 'Idnt', 'blackAndWhitePresetFileName', 'LUT3DFileName',
|
|
203
|
+
'Txt ', 'printerName', 'Nm ', 'Idnt', 'blackAndWhitePresetFileName', 'LUT3DFileName', 'exportOption', 'scaleSettings',
|
|
204
|
+
'BackgroundImagePath', 'ImageSubfolderName',
|
|
204
205
|
'presetFileName', 'curvesPresetFileName', 'mixerPresetFileName', 'placed', 'description', 'reason',
|
|
205
206
|
'artboardPresetName', 'json', 'clipID', 'relPath', 'fullPath', 'mediaDescriptor', 'Msge',
|
|
206
|
-
'altTag', 'url', 'cellText', 'preset', 'KnNm', 'FPth', 'comment', 'originalPath',
|
|
207
|
+
'altTag', 'url', 'cellText', 'preset', 'KnNm', 'FPth', 'comment', 'originalPath', 'Bk ', 'pathUnicodeName',
|
|
207
208
|
],
|
|
208
209
|
'tdta': [
|
|
209
210
|
'EngineData', 'LUT3DFileData', 'indexArray', 'originalVertexArray', 'deformedVertexArray',
|
|
210
|
-
'LqMe',
|
|
211
|
+
'LqMe', 'bookKey',
|
|
211
212
|
],
|
|
212
213
|
'long': [
|
|
213
|
-
'TextIndex', 'RndS', 'Mdpn', 'Smth', 'Lctn', 'strokeStyleVersion', 'LaID', 'Vrsn', 'Cnt ',
|
|
214
|
+
'TextIndex', 'RndS', 'Mdpn', 'Smth', 'Lctn', 'strokeStyleVersion', 'LaID', 'Vrsn', 'Cnt ', 'bookID',
|
|
215
|
+
'cropRectBottom', 'cropRectLeft', 'cropRectRight', 'cropRectTop',
|
|
216
|
+
// save for web output settings
|
|
217
|
+
'Version', 'BackgroundColorBlue', 'BackgroundColorGreen', 'BackgroundColorRed', 'BackgroundColorState', 'AttributeCase', 'Encoding',
|
|
218
|
+
'DuplicateFileNameBehavior', 'ImageMapLocation', 'ImageMapType', 'Indent', 'LineEndings', 'SpacersEmptyCells',
|
|
219
|
+
'SpacersHorizontal', 'SpacersVertical', 'StylesFormat', 'TDWidthHeight', 'TagCase', 'ColorPolicy', 'MetadataPolicy',
|
|
214
220
|
'Brgh', 'Cntr', 'means', 'vibrance', 'Strt', 'bwPresetKind', 'comp', 'compID', 'originalCompID',
|
|
215
221
|
'curvesPresetKind', 'mixerPresetKind', 'uOrder', 'vOrder', 'PgNm', 'totalPages', 'Crop',
|
|
216
222
|
'numerator', 'denominator', 'frameCount', 'Annt', 'keyOriginType', 'unitValueQuadVersion',
|
|
@@ -232,7 +238,7 @@ const typeToField = {
|
|
|
232
238
|
'tableOrder', 'enableCompCore', 'enableCompCoreGPU', 'compCoreSupport', 'compCoreGPUSupport', 'Engn',
|
|
233
239
|
'enableCompCoreThreads', 'gs99', 'FrDs', 'trackID', 'animInterpStyle', 'horzAlign',
|
|
234
240
|
'vertAlign', 'bgColorType', 'shapeOperation', 'UndA', 'Wvtp', 'Drct', 'WndM', 'Edg ', 'FlCl', 'IntE',
|
|
235
|
-
'IntC', 'Cnvr', 'Fl ', 'Dstr', 'MztT', 'Lns ', 'ExtT', 'DspM', 'ExtR', 'ZZTy', 'SphM', 'SmBQ', 'placedLayerOCIOConversion', 'gradientsInterpolationMethod',
|
|
241
|
+
'IntC', 'Cnvr', 'Fl ', 'Dstr', 'MztT', 'Lns ', 'ExtT', 'DspM', 'ExtR', 'ZZTy', 'SphM', 'SmBQ', 'placedLayerOCIOConversion', 'gradientsInterpolationMethod', 'pathSymmetryMode',
|
|
236
242
|
'interpretAlpha',
|
|
237
243
|
],
|
|
238
244
|
'bool': [
|
|
@@ -249,7 +255,7 @@ const typeToField = {
|
|
|
249
255
|
'moreAccurate', 'GpuY', 'LIWy', 'Cnty', 'Lnkd', 'showAlteredVideo', 'lightingOn',
|
|
250
256
|
],
|
|
251
257
|
'doub': [
|
|
252
|
-
'warpValue', 'warpPerspective', 'warpPerspectiveOther', 'Intr', 'Wdth', 'Hght',
|
|
258
|
+
'warpValue', 'warpPerspective', 'warpPerspectiveOther', 'Intr', 'Wdth', 'Hght', 'Gmm ',
|
|
253
259
|
'strokeStyleMiterLimit', 'strokeStyleResolution', 'layerTime', 'keyOriginResolution',
|
|
254
260
|
'xx', 'xy', 'yx', 'yy', 'tx', 'ty', 'FrGA', 'frameRate', 'audioLevel', 'rotation',
|
|
255
261
|
'X ', 'Y ', 'redFloat', 'greenFloat', 'blueFloat', 'imageResolution',
|
|
@@ -263,7 +269,7 @@ const typeToField = {
|
|
|
263
269
|
'topRight', 'topLeft', 'bottomLeft', 'bottomRight', 'ClNs', 'Shrp',
|
|
264
270
|
],
|
|
265
271
|
'VlLs': [
|
|
266
|
-
'Crv ', 'Clrs', 'Mnm ', 'Mxm ', 'Trns', 'pathList', 'strokeStyleLineDashSet', 'FrLs', 'slices',
|
|
272
|
+
'Crv ', 'Clrs', 'Mnm ', 'Mxm ', 'Trns', 'pathList', 'keyRootDescriptorList', 'strokeStyleLineDashSet', 'FrLs', 'slices',
|
|
267
273
|
'LaSt', 'Trnf', 'nonAffineTransform', 'keyDescriptorList', 'guideIndeces', 'gradientFillMulti',
|
|
268
274
|
'solidFillMulti', 'frameFXMulti', 'innerShadowMulti', 'dropShadowMulti', 'FrIn', 'FSts', 'FsFr',
|
|
269
275
|
'sheetTimelineOptions', 'audioClipList', 'trackList', 'globalTrackList', 'keyList', 'audioClipList',
|
|
@@ -282,25 +288,6 @@ const channels = [
|
|
|
282
288
|
];
|
|
283
289
|
// color classes whose channel values are written as doubles ('GRYC' and 'LABC' are kept for backwards compatibility)
|
|
284
290
|
const doubleColorClasses = ['Grsc', 'LbCl', 'GRYC', 'LABC'];
|
|
285
|
-
// Hidden (non-enumerable) markers used to remember how values were stored in the file, so they can be
|
|
286
|
-
// written back the same way. They don't change the shape of the objects returned by the reader.
|
|
287
|
-
const osTypeKey = typeof Symbol !== 'undefined' ? Symbol('agPsdOSType') : '__agPsdOSType';
|
|
288
|
-
const obArInfoKey = typeof Symbol !== 'undefined' ? Symbol('agPsdObAr') : '__agPsdObAr';
|
|
289
|
-
const referenceInfoKey = typeof Symbol !== 'undefined' ? Symbol('agPsdReference') : '__agPsdReference';
|
|
290
|
-
function setHidden(target, key, value) {
|
|
291
|
-
Object.defineProperty(target, key, { value, enumerable: false, configurable: true, writable: true });
|
|
292
|
-
return target;
|
|
293
|
-
}
|
|
294
|
-
function getHidden(target, key) {
|
|
295
|
-
return (target && typeof target === 'object') ? target[key] : undefined;
|
|
296
|
-
}
|
|
297
|
-
const osTypeFamilies = {
|
|
298
|
-
UntF: 'UntF', UnFl: 'UntF',
|
|
299
|
-
Objc: 'Objc', GlbO: 'Objc',
|
|
300
|
-
type: 'type', GlbC: 'type',
|
|
301
|
-
comp: 'comp',
|
|
302
|
-
};
|
|
303
|
-
// returns the OS type the value was originally read with, if it's compatible with the type we'd write it as
|
|
304
291
|
// fallback for unknown keys, based on the type of the value
|
|
305
292
|
function guessOSType(value) {
|
|
306
293
|
if (typeof value === 'boolean')
|
|
@@ -309,26 +296,33 @@ function guessOSType(value) {
|
|
|
309
296
|
return 'doub';
|
|
310
297
|
if (Array.isArray(value))
|
|
311
298
|
return 'VlLs';
|
|
312
|
-
if (value && typeof value === 'object'
|
|
313
|
-
|
|
299
|
+
if (value && typeof value === 'object') {
|
|
300
|
+
if (typeof value._classID === 'string')
|
|
301
|
+
return 'Objc';
|
|
302
|
+
if (typeof value.classID === 'string')
|
|
303
|
+
return 'type'; // class read from 'type' or 'GlbC'
|
|
304
|
+
if (typeof value.low === 'number' && typeof value.high === 'number')
|
|
305
|
+
return 'comp';
|
|
306
|
+
if (typeof value.units === 'string' && typeof value.value === 'number')
|
|
307
|
+
return 'UntF';
|
|
308
|
+
}
|
|
314
309
|
return undefined;
|
|
315
310
|
}
|
|
316
|
-
function getRecordedOSType(value, type) {
|
|
317
|
-
const recorded = getHidden(value, osTypeKey);
|
|
318
|
-
if (!recorded)
|
|
319
|
-
return type;
|
|
320
|
-
if (!type || recorded === 'comp' || recorded === 'type' || recorded === 'GlbC')
|
|
321
|
-
return recorded;
|
|
322
|
-
return osTypeFamilies[recorded] === osTypeFamilies[type] ? recorded : type;
|
|
323
|
-
}
|
|
324
311
|
const fieldToArrayType = {
|
|
325
312
|
'Mnm ': 'long',
|
|
326
313
|
'Mxm ': 'long',
|
|
314
|
+
HtmlFileNameComponents: 'long', // save for web output settings
|
|
315
|
+
SavingFileNameComponents: 'long',
|
|
316
|
+
SliceFileNameComponents: 'long',
|
|
317
|
+
Inpt: 'long', // levels filter
|
|
318
|
+
Otpt: 'long', // levels filter
|
|
327
319
|
FrLs: 'long',
|
|
328
320
|
strokeStyleLineDashSet: 'UntF',
|
|
329
321
|
Trnf: 'doub',
|
|
330
322
|
nonAffineTransform: 'doub',
|
|
331
323
|
keyDescriptorList: 'Objc',
|
|
324
|
+
keyRootDescriptorList: 'Objc',
|
|
325
|
+
pathList: 'Objc',
|
|
332
326
|
gradientFillMulti: 'Objc',
|
|
333
327
|
solidFillMulti: 'Objc',
|
|
334
328
|
frameFXMulti: 'Objc',
|
|
@@ -419,6 +413,15 @@ function getTypeByKey(key, value, root, parent) {
|
|
|
419
413
|
else if ((key === 'Inpt' || key === 'Otpt') && parent._classID === 'HsbP') {
|
|
420
414
|
return 'enum';
|
|
421
415
|
}
|
|
416
|
+
else if ((key === 'Inpt' || key === 'Otpt') && parent._classID === 'LvlA') {
|
|
417
|
+
return 'VlLs';
|
|
418
|
+
}
|
|
419
|
+
else if (key === 'Intr' && typeof value === 'boolean') {
|
|
420
|
+
return 'bool'; // interpolation in print style
|
|
421
|
+
}
|
|
422
|
+
else if (key === 'PgPs') {
|
|
423
|
+
return 'enum';
|
|
424
|
+
}
|
|
422
425
|
else if (key === 'LghD' && parent._classID === 'oilPaint') {
|
|
423
426
|
return 'long';
|
|
424
427
|
}
|
|
@@ -431,7 +434,7 @@ function readAsciiStringOrClassId(reader) {
|
|
|
431
434
|
return (0, psdReader_1.readAsciiString)(reader, length || 4);
|
|
432
435
|
}
|
|
433
436
|
function writeAsciiStringOrClassId(writer, value) {
|
|
434
|
-
if (value.length === 4 && value !== 'warp' && value !== 'time' && value !== 'hold' && value !== 'list') {
|
|
437
|
+
if (value.length === 4 && value !== 'warp' && value !== 'time' && value !== 'hold' && value !== 'list' && value !== 'json') {
|
|
435
438
|
// write classId
|
|
436
439
|
(0, psdWriter_1.writeInt32)(writer, 0);
|
|
437
440
|
(0, psdWriter_1.writeSignature)(writer, value);
|
|
@@ -459,12 +462,20 @@ function readDescriptorStructure(reader, includeClass) {
|
|
|
459
462
|
}
|
|
460
463
|
return object;
|
|
461
464
|
}
|
|
465
|
+
exports.outputSettingsRoot = 'outputSettings';
|
|
462
466
|
function writeDescriptorStructure(writer, name, classId, value, root) {
|
|
463
467
|
if (logErrors && !classId)
|
|
464
468
|
console.log('Missing classId for: ', name, classId, value);
|
|
465
469
|
// write class structure
|
|
466
470
|
(0, psdWriter_1.writeUnicodeStringWithPadding)(writer, name);
|
|
467
|
-
|
|
471
|
+
if (root === exports.outputSettingsRoot && classId === 'null') {
|
|
472
|
+
// Photoshop writes 'null' class id as 4 character string in save for web output settings
|
|
473
|
+
(0, psdWriter_1.writeInt32)(writer, 4);
|
|
474
|
+
(0, psdWriter_1.writeSignature)(writer, classId);
|
|
475
|
+
}
|
|
476
|
+
else {
|
|
477
|
+
writeAsciiStringOrClassId(writer, classId);
|
|
478
|
+
}
|
|
468
479
|
const allKeys = Object.keys(value);
|
|
469
480
|
const keys = allKeys.filter(key => key !== '_name' && key !== '_classID' && value[key] !== undefined);
|
|
470
481
|
(0, psdWriter_1.writeUint32)(writer, keys.length);
|
|
@@ -574,12 +585,17 @@ function writeDescriptorStructure(writer, name, classId, value, root) {
|
|
|
574
585
|
else if (key === 'bounds' && root === 'quiltWarp') {
|
|
575
586
|
extType = makeType('', 'classFloatRect');
|
|
576
587
|
}
|
|
588
|
+
// guess color class from its fields (colors created by serializeColor always have _classID set)
|
|
577
589
|
if (extType && extType.classID === 'RGBC') {
|
|
578
590
|
if ('H ' in value[key])
|
|
579
591
|
extType = { classID: 'HSBC', name: '' };
|
|
580
|
-
|
|
592
|
+
else if ('Cyn ' in value[key])
|
|
593
|
+
extType = { classID: 'CMYC', name: '' };
|
|
594
|
+
else if ('Lmnc' in value[key])
|
|
595
|
+
extType = { classID: 'LbCl', name: '' };
|
|
596
|
+
else if ('Gry ' in value[key])
|
|
597
|
+
extType = { classID: 'Grsc', name: '' };
|
|
581
598
|
}
|
|
582
|
-
type = getRecordedOSType(value[key], type);
|
|
583
599
|
if (!type)
|
|
584
600
|
type = guessOSType(value[key]);
|
|
585
601
|
writeAsciiStringOrClassId(writer, key);
|
|
@@ -594,9 +610,8 @@ function readOSType(reader, type, includeClass) {
|
|
|
594
610
|
case 'obj ': // Reference
|
|
595
611
|
return readReferenceStructure(reader);
|
|
596
612
|
case 'Objc': // Descriptor
|
|
597
|
-
return readDescriptorStructure(reader, includeClass);
|
|
598
613
|
case 'GlbO': // GlobalObject same as Descriptor
|
|
599
|
-
return
|
|
614
|
+
return readDescriptorStructure(reader, includeClass);
|
|
600
615
|
case 'VlLs': { // List
|
|
601
616
|
const length = (0, psdReader_1.readInt32)(reader);
|
|
602
617
|
const items = [];
|
|
@@ -621,7 +636,7 @@ function readOSType(reader, type, includeClass) {
|
|
|
621
636
|
const value = (0, psdReader_1.readFloat32)(reader);
|
|
622
637
|
if (!unitsMap[units])
|
|
623
638
|
throw new Error(`Invalid units: ${units}`);
|
|
624
|
-
return
|
|
639
|
+
return { units: unitsMap[units], value };
|
|
625
640
|
}
|
|
626
641
|
case 'TEXT': // String
|
|
627
642
|
return (0, psdReader_1.readUnicodeString)(reader);
|
|
@@ -635,13 +650,13 @@ function readOSType(reader, type, includeClass) {
|
|
|
635
650
|
case 'comp': { // Large Integer
|
|
636
651
|
const low = (0, psdReader_1.readUint32)(reader);
|
|
637
652
|
const high = (0, psdReader_1.readUint32)(reader);
|
|
638
|
-
return
|
|
653
|
+
return { low, high };
|
|
639
654
|
}
|
|
640
655
|
case 'bool': // Boolean
|
|
641
656
|
return !!(0, psdReader_1.readUint8)(reader);
|
|
642
657
|
case 'type': // Class
|
|
643
658
|
case 'GlbC': // Class
|
|
644
|
-
return
|
|
659
|
+
return readClassStructure(reader);
|
|
645
660
|
case 'alis': { // Alias
|
|
646
661
|
const length = (0, psdReader_1.readInt32)(reader);
|
|
647
662
|
return (0, psdReader_1.readAsciiString)(reader, length);
|
|
@@ -653,21 +668,21 @@ function readOSType(reader, type, includeClass) {
|
|
|
653
668
|
case 'ObAr': { // Object array
|
|
654
669
|
(0, psdReader_1.readInt32)(reader); // version: 16
|
|
655
670
|
(0, psdReader_1.readUnicodeString)(reader); // name: ''
|
|
656
|
-
|
|
671
|
+
readAsciiStringOrClassId(reader); // classID: 'rationalPoint'
|
|
657
672
|
const length = (0, psdReader_1.readInt32)(reader);
|
|
658
673
|
const items = [];
|
|
659
674
|
for (let i = 0; i < length; i++) {
|
|
660
675
|
const type1 = readAsciiStringOrClassId(reader); // type Hrzn | Vrtc
|
|
661
|
-
|
|
662
|
-
|
|
676
|
+
(0, psdReader_1.readSignature)(reader); // UnFl
|
|
677
|
+
(0, psdReader_1.readSignature)(reader); // units ? '#Pxl'
|
|
663
678
|
const valuesCount = (0, psdReader_1.readInt32)(reader);
|
|
664
679
|
const values = [];
|
|
665
680
|
for (let j = 0; j < valuesCount; j++) {
|
|
666
681
|
values.push((0, psdReader_1.readFloat64)(reader));
|
|
667
682
|
}
|
|
668
|
-
items.push(
|
|
683
|
+
items.push({ type: type1, values });
|
|
669
684
|
}
|
|
670
|
-
return
|
|
685
|
+
return items;
|
|
671
686
|
}
|
|
672
687
|
case 'Pth ': { // File path
|
|
673
688
|
/*const length =*/ (0, psdReader_1.readInt32)(reader); // total size of all fields below
|
|
@@ -687,7 +702,7 @@ const ObArTypes = {
|
|
|
687
702
|
quiltSliceY: 'UntF',
|
|
688
703
|
};
|
|
689
704
|
function writeOSType(writer, type, value, key, extType, root) {
|
|
690
|
-
var _a
|
|
705
|
+
var _a;
|
|
691
706
|
switch (type) {
|
|
692
707
|
case 'obj ': // Reference
|
|
693
708
|
writeReferenceStructure(writer, key, value);
|
|
@@ -708,7 +723,7 @@ function writeOSType(writer, type, value, key, extType, root) {
|
|
|
708
723
|
throw new Error(`Invalid list value: ${JSON.stringify(value)}, key: ${key}`);
|
|
709
724
|
(0, psdWriter_1.writeInt32)(writer, value.length);
|
|
710
725
|
for (let i = 0; i < value.length; i++) {
|
|
711
|
-
const type = (_a =
|
|
726
|
+
const type = (_a = fieldToArrayType[key]) !== null && _a !== void 0 ? _a : guessOSType(value[i]);
|
|
712
727
|
(0, psdWriter_1.writeSignature)(writer, type || 'long');
|
|
713
728
|
writeOSType(writer, type || 'long', value[i], `${key}[]`, fieldToArrayExtType[key], root);
|
|
714
729
|
if (logErrors && !type)
|
|
@@ -782,16 +797,15 @@ function writeOSType(writer, type, value, key, extType, root) {
|
|
|
782
797
|
case 'ObAr': { // Object array
|
|
783
798
|
(0, psdWriter_1.writeInt32)(writer, 16); // version
|
|
784
799
|
(0, psdWriter_1.writeUnicodeStringWithPadding)(writer, ''); // name
|
|
785
|
-
const type =
|
|
800
|
+
const type = ObArTypes[key];
|
|
786
801
|
if (!type)
|
|
787
802
|
throw new Error(`Not implemented ObArType for: ${key}`);
|
|
788
803
|
writeAsciiStringOrClassId(writer, type);
|
|
789
804
|
(0, psdWriter_1.writeInt32)(writer, value.length);
|
|
790
805
|
for (let i = 0; i < value.length; i++) {
|
|
791
|
-
const info = getHidden(value[i], obArInfoKey);
|
|
792
806
|
writeAsciiStringOrClassId(writer, value[i].type); // Hrzn | Vrtc
|
|
793
|
-
(0, psdWriter_1.writeSignature)(writer,
|
|
794
|
-
(0, psdWriter_1.writeSignature)(writer,
|
|
807
|
+
(0, psdWriter_1.writeSignature)(writer, 'UnFl');
|
|
808
|
+
(0, psdWriter_1.writeSignature)(writer, '#Pxl');
|
|
795
809
|
(0, psdWriter_1.writeInt32)(writer, value[i].values.length);
|
|
796
810
|
for (let j = 0; j < value[i].values.length; j++) {
|
|
797
811
|
(0, psdWriter_1.writeFloat64)(writer, value[i].values[j]);
|
|
@@ -800,83 +814,60 @@ function writeOSType(writer, type, value, key, extType, root) {
|
|
|
800
814
|
break;
|
|
801
815
|
}
|
|
802
816
|
case 'Pth ': { // File path
|
|
803
|
-
const
|
|
817
|
+
const path = value.path + '\0'; // Photoshop stores trailing null character (stripped when reading)
|
|
818
|
+
const length = 4 + 4 + 4 + path.length * 2;
|
|
804
819
|
(0, psdWriter_1.writeInt32)(writer, length);
|
|
805
820
|
(0, psdWriter_1.writeSignature)(writer, value.sig);
|
|
806
821
|
(0, psdWriter_1.writeInt32LE)(writer, length);
|
|
807
|
-
(0, psdWriter_1.writeInt32LE)(writer,
|
|
808
|
-
(0, psdWriter_1.writeUnicodeStringWithoutLengthLE)(writer,
|
|
822
|
+
(0, psdWriter_1.writeInt32LE)(writer, path.length);
|
|
823
|
+
(0, psdWriter_1.writeUnicodeStringWithoutLengthLE)(writer, path);
|
|
809
824
|
break;
|
|
810
825
|
}
|
|
811
826
|
default:
|
|
812
827
|
throw new Error(`Not implemented descriptor OSType: ${type}`);
|
|
813
828
|
}
|
|
814
829
|
}
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
case 'Clss': return { name: item.name || '', classID: item.classID };
|
|
819
|
-
case 'Enmr': return `${item.typeID}.${item.enumValue}`;
|
|
820
|
-
default: return item.value;
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
function referenceItemMatches(item, value) {
|
|
824
|
-
if (!item)
|
|
825
|
-
return false;
|
|
826
|
-
const expected = referenceItemToValue(item);
|
|
827
|
-
if (expected && typeof expected === 'object') {
|
|
828
|
-
return !!value && typeof value === 'object' && value.name === expected.name && value.classID === expected.classID;
|
|
829
|
-
}
|
|
830
|
-
return expected === value;
|
|
831
|
-
}
|
|
832
|
-
// Attaches information about how each item of reference should be written (class IDs, reference types),
|
|
833
|
-
// the public value of the array stays the same (array of strings/numbers/class objects)
|
|
834
|
-
function createDescriptorReference(items) {
|
|
835
|
-
return setHidden(items.map(referenceItemToValue), referenceInfoKey, items);
|
|
830
|
+
const referenceTypes = ['prop', 'Clss', 'Enmr', 'rele', 'Idnt', 'indx', 'name'];
|
|
831
|
+
function isReferenceItem(value) {
|
|
832
|
+
return !!value && typeof value === 'object' && referenceTypes.indexOf(value.type) !== -1;
|
|
836
833
|
}
|
|
837
834
|
function readReferenceStructure(reader) {
|
|
838
835
|
const itemsCount = (0, psdReader_1.readInt32)(reader);
|
|
839
|
-
const
|
|
836
|
+
const items = [];
|
|
840
837
|
for (let i = 0; i < itemsCount; i++) {
|
|
841
838
|
const type = (0, psdReader_1.readSignature)(reader);
|
|
842
839
|
switch (type) {
|
|
843
|
-
case 'prop':
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
infos.push({ type, name, classID, keyID });
|
|
840
|
+
case 'prop': // Property
|
|
841
|
+
readClassStructure(reader);
|
|
842
|
+
items.push(readAsciiStringOrClassId(reader));
|
|
847
843
|
break;
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
const { name, classID } = readClassStructure(reader);
|
|
851
|
-
infos.push({ type, name, classID });
|
|
844
|
+
case 'Clss': // Class
|
|
845
|
+
items.push(readClassStructure(reader));
|
|
852
846
|
break;
|
|
853
|
-
}
|
|
854
847
|
case 'Enmr': { // Enumerated Reference
|
|
855
|
-
|
|
848
|
+
readClassStructure(reader);
|
|
856
849
|
const typeID = readAsciiStringOrClassId(reader);
|
|
857
850
|
const enumValue = readAsciiStringOrClassId(reader);
|
|
858
|
-
|
|
851
|
+
items.push(`${typeID}.${enumValue}`);
|
|
859
852
|
break;
|
|
860
853
|
}
|
|
861
|
-
case 'rele':
|
|
862
|
-
|
|
863
|
-
|
|
854
|
+
case 'rele': // Offset
|
|
855
|
+
readClassStructure(reader);
|
|
856
|
+
items.push((0, psdReader_1.readUint32)(reader));
|
|
864
857
|
break;
|
|
865
|
-
}
|
|
866
858
|
case 'Idnt': // Identifier
|
|
867
859
|
case 'indx': // Index
|
|
868
|
-
|
|
860
|
+
items.push((0, psdReader_1.readInt32)(reader));
|
|
869
861
|
break;
|
|
870
|
-
case 'name':
|
|
871
|
-
|
|
872
|
-
|
|
862
|
+
case 'name': // Name
|
|
863
|
+
readClassStructure(reader);
|
|
864
|
+
items.push((0, psdReader_1.readUnicodeString)(reader));
|
|
873
865
|
break;
|
|
874
|
-
}
|
|
875
866
|
default:
|
|
876
867
|
throw new Error(`Invalid descriptor reference type: ${type}`);
|
|
877
868
|
}
|
|
878
869
|
}
|
|
879
|
-
return
|
|
870
|
+
return items;
|
|
880
871
|
}
|
|
881
872
|
function guessReferenceItem(value) {
|
|
882
873
|
if (typeof value === 'string') {
|
|
@@ -884,17 +875,17 @@ function guessReferenceItem(value) {
|
|
|
884
875
|
// (values like 'My.Path' or 'Logo.v2' can't be typeID/enum value, so they are written as name references)
|
|
885
876
|
const match = /^([a-z ]{4}|[a-z]{5,})\.([a-z ]+)$/i.exec(value);
|
|
886
877
|
if (match) {
|
|
887
|
-
return { type: 'Enmr',
|
|
878
|
+
return { type: 'Enmr', _name: '', _classID: match[1], typeID: match[1], enumValue: match[2] };
|
|
888
879
|
}
|
|
889
880
|
else {
|
|
890
|
-
return { type: 'name',
|
|
881
|
+
return { type: 'name', _name: '', _classID: 'Lyr ', value };
|
|
891
882
|
}
|
|
892
883
|
}
|
|
893
884
|
else if (typeof value === 'number') {
|
|
894
885
|
return { type: 'Idnt', value };
|
|
895
886
|
}
|
|
896
887
|
else if (value && typeof value === 'object' && typeof value.classID === 'string') {
|
|
897
|
-
return { type: 'Clss',
|
|
888
|
+
return { type: 'Clss', _name: value.name || '', _classID: value.classID };
|
|
898
889
|
}
|
|
899
890
|
else {
|
|
900
891
|
throw new Error(`Invalid descriptor reference value: ${JSON.stringify(value)}`);
|
|
@@ -903,41 +894,35 @@ function guessReferenceItem(value) {
|
|
|
903
894
|
// path selection state (image resource 1088) is a reference to paths, enumerated references there use 'Path' class
|
|
904
895
|
// (name references use 'Lyr ' class, they reference layer of the vector mask)
|
|
905
896
|
function pathSelectionStateToReference(items) {
|
|
906
|
-
|
|
907
|
-
return createDescriptorReference(items.map((value, i) => {
|
|
908
|
-
if (referenceItemMatches(infos === null || infos === void 0 ? void 0 : infos[i], value))
|
|
909
|
-
return infos[i]; // keep information read from the file
|
|
897
|
+
return items.map(value => {
|
|
910
898
|
const item = guessReferenceItem(value);
|
|
911
899
|
if (item.type === 'Enmr')
|
|
912
|
-
item.
|
|
900
|
+
item._classID = 'Path';
|
|
913
901
|
return item;
|
|
914
|
-
})
|
|
902
|
+
});
|
|
915
903
|
}
|
|
916
904
|
function writeReferenceStructure(writer, _key, items) {
|
|
917
905
|
if (!Array.isArray(items))
|
|
918
906
|
throw new Error(`Invalid reference value: ${JSON.stringify(items)}, key: ${_key}`);
|
|
919
|
-
const infos = getHidden(items, referenceInfoKey);
|
|
920
907
|
(0, psdWriter_1.writeInt32)(writer, items.length);
|
|
921
|
-
for (
|
|
922
|
-
const
|
|
923
|
-
const recorded = infos === null || infos === void 0 ? void 0 : infos[i];
|
|
924
|
-
const item = referenceItemMatches(recorded, value) ? recorded : guessReferenceItem(value);
|
|
908
|
+
for (const value of items) {
|
|
909
|
+
const item = isReferenceItem(value) ? value : guessReferenceItem(value);
|
|
925
910
|
(0, psdWriter_1.writeSignature)(writer, item.type);
|
|
926
911
|
switch (item.type) {
|
|
927
912
|
case 'prop': // Property
|
|
928
|
-
writeClassStructure(writer, item.
|
|
913
|
+
writeClassStructure(writer, item._name || '', item._classID);
|
|
929
914
|
writeAsciiStringOrClassId(writer, item.keyID);
|
|
930
915
|
break;
|
|
931
916
|
case 'Clss': // Class
|
|
932
|
-
writeClassStructure(writer, item.
|
|
917
|
+
writeClassStructure(writer, item._name || '', item._classID);
|
|
933
918
|
break;
|
|
934
919
|
case 'Enmr': // Enumerated Reference
|
|
935
|
-
writeClassStructure(writer, item.
|
|
920
|
+
writeClassStructure(writer, item._name || '', item._classID);
|
|
936
921
|
writeAsciiStringOrClassId(writer, item.typeID);
|
|
937
922
|
writeAsciiStringOrClassId(writer, item.enumValue);
|
|
938
923
|
break;
|
|
939
924
|
case 'rele': // Offset
|
|
940
|
-
writeClassStructure(writer, item.
|
|
925
|
+
writeClassStructure(writer, item._name || '', item._classID);
|
|
941
926
|
(0, psdWriter_1.writeUint32)(writer, item.value);
|
|
942
927
|
break;
|
|
943
928
|
case 'Idnt': // Identifier
|
|
@@ -945,7 +930,7 @@ function writeReferenceStructure(writer, _key, items) {
|
|
|
945
930
|
(0, psdWriter_1.writeInt32)(writer, item.value);
|
|
946
931
|
break;
|
|
947
932
|
case 'name': // Name
|
|
948
|
-
writeClassStructure(writer, item.
|
|
933
|
+
writeClassStructure(writer, item._name || '', item._classID);
|
|
949
934
|
(0, psdWriter_1.writeUnicodeStringWithPadding)(writer, `${item.value}`);
|
|
950
935
|
break;
|
|
951
936
|
default:
|
|
@@ -1004,7 +989,7 @@ function parseFxObject(fx) {
|
|
|
1004
989
|
fillType: exports.FrFl.decode(fx.PntT),
|
|
1005
990
|
blendMode: exports.BlnM.decode(fx['Md ']),
|
|
1006
991
|
opacity: parsePercent(fx.Opct),
|
|
1007
|
-
size:
|
|
992
|
+
size: parseUnitsOrNumber(fx['Sz ']), // stored as number (pixels) in old versions
|
|
1008
993
|
};
|
|
1009
994
|
if (fx.present !== undefined)
|
|
1010
995
|
stroke.present = fx.present;
|
|
@@ -1109,11 +1094,11 @@ function serializeEffects(e, log, multi) {
|
|
|
1109
1094
|
}
|
|
1110
1095
|
function parseEffects(info, log) {
|
|
1111
1096
|
const effects = {};
|
|
1112
|
-
const { masterFXSwitch, DrSh, dropShadowMulti, IrSh, innerShadowMulti, OrGl, IrGl, ebbl, SoFi, solidFillMulti, patternFill, GrFl, gradientFillMulti, ChFX, FrFX, frameFXMulti, numModifyingFX } =
|
|
1097
|
+
const _a = info, { _name, _classID, 'Scl ': scale, masterFXSwitch, DrSh, dropShadowMulti, IrSh, innerShadowMulti, OrGl, IrGl, ebbl, SoFi, solidFillMulti, patternFill, GrFl, gradientFillMulti, ChFX, FrFX, frameFXMulti, numModifyingFX } = _a, rest = __rest(_a, ["_name", "_classID", 'Scl ', "masterFXSwitch", "DrSh", "dropShadowMulti", "IrSh", "innerShadowMulti", "OrGl", "IrGl", "ebbl", "SoFi", "solidFillMulti", "patternFill", "GrFl", "gradientFillMulti", "ChFX", "FrFX", "frameFXMulti", "numModifyingFX"]);
|
|
1113
1098
|
if (!masterFXSwitch)
|
|
1114
1099
|
effects.disabled = true;
|
|
1115
|
-
if (
|
|
1116
|
-
effects.scale = parsePercent(
|
|
1100
|
+
if (scale)
|
|
1101
|
+
effects.scale = parsePercent(scale);
|
|
1117
1102
|
if (DrSh)
|
|
1118
1103
|
effects.dropShadow = [parseEffectObject(DrSh, log)];
|
|
1119
1104
|
if (dropShadowMulti)
|
|
@@ -1127,7 +1112,7 @@ function parseEffects(info, log) {
|
|
|
1127
1112
|
if (IrGl)
|
|
1128
1113
|
effects.innerGlow = parseEffectObject(IrGl, log);
|
|
1129
1114
|
if (ebbl)
|
|
1130
|
-
effects.bevel = parseEffectObject(ebbl, log);
|
|
1115
|
+
effects.bevel = parseEffectObject(ebbl, log, 'bevel');
|
|
1131
1116
|
if (SoFi)
|
|
1132
1117
|
effects.solidFill = [parseEffectObject(SoFi, log)];
|
|
1133
1118
|
if (solidFillMulti)
|
|
@@ -1144,7 +1129,7 @@ function parseEffects(info, log) {
|
|
|
1144
1129
|
effects.stroke = [parseFxObject(FrFX)];
|
|
1145
1130
|
if (frameFXMulti)
|
|
1146
1131
|
effects.stroke = frameFXMulti.map(i => parseFxObject(i));
|
|
1147
|
-
if (log && Object.keys(rest).length
|
|
1132
|
+
if (log && Object.keys(rest).length)
|
|
1148
1133
|
console.log('Unhandled effect keys:', rest);
|
|
1149
1134
|
return effects;
|
|
1150
1135
|
}
|
|
@@ -1253,7 +1238,7 @@ function serializeTrackList(tracks) {
|
|
|
1253
1238
|
}
|
|
1254
1239
|
return trackList;
|
|
1255
1240
|
}
|
|
1256
|
-
function parseEffectObject(obj, reportErrors) {
|
|
1241
|
+
function parseEffectObject(obj, reportErrors, objName) {
|
|
1257
1242
|
const result = {};
|
|
1258
1243
|
for (const key of Object.keys(obj)) {
|
|
1259
1244
|
const val = obj[key];
|
|
@@ -1318,7 +1303,8 @@ function parseEffectObject(obj, reportErrors) {
|
|
|
1318
1303
|
case 'Type':
|
|
1319
1304
|
result.type = exports.GrdT.decode(val);
|
|
1320
1305
|
break;
|
|
1321
|
-
case 'gs99':
|
|
1306
|
+
case 'gs99': // gradient overlay
|
|
1307
|
+
case 'gradientsInterpolationMethod': // glows
|
|
1322
1308
|
result.interpolationMethod = exports.gradientInterpolationMethodType.decode(val);
|
|
1323
1309
|
break;
|
|
1324
1310
|
case 'Opct':
|
|
@@ -1370,18 +1356,26 @@ function parseEffectObject(obj, reportErrors) {
|
|
|
1370
1356
|
result.pattern = { name: val['Nm '], id: val.Idnt };
|
|
1371
1357
|
break;
|
|
1372
1358
|
case 'phase':
|
|
1373
|
-
result.phase =
|
|
1359
|
+
result.phase = parsePhase(val);
|
|
1374
1360
|
break;
|
|
1375
1361
|
case 'Ofst':
|
|
1376
1362
|
result.offset = { x: parsePercent(val.Hrzn), y: parsePercent(val.Vrtc) };
|
|
1377
1363
|
break;
|
|
1378
1364
|
case 'MpgS':
|
|
1379
|
-
case 'TrnS':
|
|
1380
|
-
|
|
1365
|
+
case 'TrnS': {
|
|
1366
|
+
const contour = {
|
|
1381
1367
|
name: val['Nm '],
|
|
1382
1368
|
curve: val['Crv '].map(p => ({ x: p.Hrzn, y: p.Vrtc })),
|
|
1383
1369
|
};
|
|
1370
|
+
// bevel can have both: gloss contour (TrnS) and contour of the shape (MpgS)
|
|
1371
|
+
if (objName === 'bevel' && key === 'MpgS') {
|
|
1372
|
+
result.shapeContour = contour;
|
|
1373
|
+
}
|
|
1374
|
+
else {
|
|
1375
|
+
result.contour = contour;
|
|
1376
|
+
}
|
|
1384
1377
|
break;
|
|
1378
|
+
}
|
|
1385
1379
|
case 'Grad':
|
|
1386
1380
|
result.gradient = parseGradient(val);
|
|
1387
1381
|
break;
|
|
@@ -1476,7 +1470,7 @@ function serializeEffectObject(obj, objName, reportErrors) {
|
|
|
1476
1470
|
result.Type = exports.GrdT.encode(val);
|
|
1477
1471
|
break;
|
|
1478
1472
|
case 'interpolationMethod':
|
|
1479
|
-
result
|
|
1473
|
+
result[(objName === 'outerGlow' || objName === 'innerGlow') ? 'gradientsInterpolationMethod' : 'gs99'] = exports.gradientInterpolationMethodType.encode(val);
|
|
1480
1474
|
break;
|
|
1481
1475
|
case 'opacity':
|
|
1482
1476
|
result.Opct = unitsPercent(val);
|
|
@@ -1532,15 +1526,14 @@ function serializeEffectObject(obj, objName, reportErrors) {
|
|
|
1532
1526
|
result.phase = { Hrzn: val.x, Vrtc: val.y };
|
|
1533
1527
|
break;
|
|
1534
1528
|
case 'offset':
|
|
1535
|
-
result.Ofst = { Hrzn:
|
|
1529
|
+
result.Ofst = { Hrzn: unitsPercentF(val.x), Vrtc: unitsPercentF(val.y) };
|
|
1536
1530
|
break;
|
|
1537
|
-
case 'contour':
|
|
1538
|
-
result[objName === 'satin' ? 'MpgS' : 'TrnS'] =
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1531
|
+
case 'contour':
|
|
1532
|
+
result[objName === 'satin' ? 'MpgS' : 'TrnS'] = serializeContour(val);
|
|
1533
|
+
break;
|
|
1534
|
+
case 'shapeContour':
|
|
1535
|
+
result.MpgS = serializeContour(val);
|
|
1542
1536
|
break;
|
|
1543
|
-
}
|
|
1544
1537
|
case 'gradient':
|
|
1545
1538
|
result.Grad = serializeGradient(val);
|
|
1546
1539
|
break;
|
|
@@ -1558,6 +1551,12 @@ function serializeEffectObject(obj, objName, reportErrors) {
|
|
|
1558
1551
|
}
|
|
1559
1552
|
return result;
|
|
1560
1553
|
}
|
|
1554
|
+
function serializeContour(contour) {
|
|
1555
|
+
return {
|
|
1556
|
+
'Nm ': contour.name,
|
|
1557
|
+
'Crv ': contour.curve.map(p => ({ Hrzn: p.x, Vrtc: p.y })),
|
|
1558
|
+
};
|
|
1559
|
+
}
|
|
1561
1560
|
function parseGradient(grad) {
|
|
1562
1561
|
if (grad.GrdF === 'GrdF.CstS') {
|
|
1563
1562
|
// stop locations are always in 0..4096 range, independent of smoothness (Intr)
|
|
@@ -1566,11 +1565,22 @@ function parseGradient(grad) {
|
|
|
1566
1565
|
type: 'solid',
|
|
1567
1566
|
name: grad['Nm '],
|
|
1568
1567
|
smoothness: grad.Intr / 4096,
|
|
1569
|
-
colorStops: grad.Clrs.map(s =>
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1568
|
+
colorStops: grad.Clrs.map(s => {
|
|
1569
|
+
const stop = {
|
|
1570
|
+
color: s['Clr '] ? parseColor(s['Clr ']) : { r: 0, g: 0, b: 0 },
|
|
1571
|
+
location: s.Lctn / samples,
|
|
1572
|
+
midpoint: s.Mdpn / 100,
|
|
1573
|
+
};
|
|
1574
|
+
if (s.Type) {
|
|
1575
|
+
try {
|
|
1576
|
+
const type = exports.Clry.decode(s.Type);
|
|
1577
|
+
if (type !== 'user')
|
|
1578
|
+
stop.type = type;
|
|
1579
|
+
}
|
|
1580
|
+
catch (_a) { } // unknown stop type, read as user color
|
|
1581
|
+
}
|
|
1582
|
+
return stop;
|
|
1583
|
+
}),
|
|
1574
1584
|
opacityStops: grad.Trns.map(s => ({
|
|
1575
1585
|
opacity: parsePercent(s.Opct),
|
|
1576
1586
|
location: s.Lctn / samples,
|
|
@@ -1602,18 +1612,18 @@ function serializeGradient(grad) {
|
|
|
1602
1612
|
GrdF: 'GrdF.CstS',
|
|
1603
1613
|
Intr: Math.round(((_a = grad.smoothness) !== null && _a !== void 0 ? _a : 1) * 4096),
|
|
1604
1614
|
Clrs: grad.colorStops.map(s => {
|
|
1605
|
-
var _a;
|
|
1615
|
+
var _a, _b;
|
|
1606
1616
|
return ({
|
|
1607
1617
|
'Clr ': serializeColor(s.color),
|
|
1608
|
-
Type:
|
|
1618
|
+
Type: exports.Clry.encode((_a = s.type) !== null && _a !== void 0 ? _a : 'user'),
|
|
1609
1619
|
Lctn: Math.round(s.location * samples),
|
|
1610
|
-
Mdpn: Math.round(((
|
|
1620
|
+
Mdpn: Math.round(((_b = s.midpoint) !== null && _b !== void 0 ? _b : 0.5) * 100),
|
|
1611
1621
|
});
|
|
1612
1622
|
}),
|
|
1613
1623
|
Trns: grad.opacityStops.map(s => {
|
|
1614
1624
|
var _a;
|
|
1615
1625
|
return ({
|
|
1616
|
-
Opct:
|
|
1626
|
+
Opct: unitsPercentF(s.opacity),
|
|
1617
1627
|
Lctn: Math.round(s.location * samples),
|
|
1618
1628
|
Mdpn: Math.round(((_a = s.midpoint) !== null && _a !== void 0 ? _a : 0.5) * 100),
|
|
1619
1629
|
});
|
|
@@ -1657,6 +1667,13 @@ function parseGradientContent(descriptor) {
|
|
|
1657
1667
|
}
|
|
1658
1668
|
return result;
|
|
1659
1669
|
}
|
|
1670
|
+
// phase is usually stored as plain numbers, but some files store it as unit values
|
|
1671
|
+
function parsePhase({ Hrzn, Vrtc }) {
|
|
1672
|
+
return {
|
|
1673
|
+
x: typeof Hrzn === 'number' ? Hrzn : Hrzn.value,
|
|
1674
|
+
y: typeof Vrtc === 'number' ? Vrtc : Vrtc.value,
|
|
1675
|
+
};
|
|
1676
|
+
}
|
|
1660
1677
|
function parsePatternContent(descriptor) {
|
|
1661
1678
|
const result = {
|
|
1662
1679
|
name: descriptor.Ptrn['Nm '],
|
|
@@ -1665,7 +1682,11 @@ function parsePatternContent(descriptor) {
|
|
|
1665
1682
|
if (descriptor.Lnkd !== undefined)
|
|
1666
1683
|
result.linked = descriptor.Lnkd;
|
|
1667
1684
|
if (descriptor.phase !== undefined)
|
|
1668
|
-
result.phase =
|
|
1685
|
+
result.phase = parsePhase(descriptor.phase);
|
|
1686
|
+
if (descriptor['Scl '] !== undefined)
|
|
1687
|
+
result.scale = parsePercent(descriptor['Scl ']);
|
|
1688
|
+
if (descriptor.Angl !== undefined)
|
|
1689
|
+
result.angle = parseAngle(descriptor.Angl);
|
|
1669
1690
|
return result;
|
|
1670
1691
|
}
|
|
1671
1692
|
function parseVectorContent(descriptor) {
|
|
@@ -1696,11 +1717,11 @@ function serializeGradientContent(content) {
|
|
|
1696
1717
|
if (content.align !== undefined)
|
|
1697
1718
|
result.Algn = content.align;
|
|
1698
1719
|
if (content.scale !== undefined)
|
|
1699
|
-
result['Scl '] =
|
|
1720
|
+
result['Scl '] = unitsPercentF(content.scale);
|
|
1700
1721
|
if (content.offset) {
|
|
1701
1722
|
result.Ofst = {
|
|
1702
|
-
Hrzn:
|
|
1703
|
-
Vrtc:
|
|
1723
|
+
Hrzn: unitsPercentF(content.offset.x),
|
|
1724
|
+
Vrtc: unitsPercentF(content.offset.y),
|
|
1704
1725
|
};
|
|
1705
1726
|
}
|
|
1706
1727
|
result.Grad = serializeGradient(content);
|
|
@@ -1717,6 +1738,10 @@ function serializePatternContent(content) {
|
|
|
1717
1738
|
result.Lnkd = !!content.linked;
|
|
1718
1739
|
if (content.phase !== undefined)
|
|
1719
1740
|
result.phase = { Hrzn: content.phase.x, Vrtc: content.phase.y };
|
|
1741
|
+
if (content.scale !== undefined)
|
|
1742
|
+
result['Scl '] = unitsPercentF(content.scale);
|
|
1743
|
+
if (content.angle !== undefined)
|
|
1744
|
+
result.Angl = unitsAngle(content.angle);
|
|
1720
1745
|
return result;
|
|
1721
1746
|
}
|
|
1722
1747
|
function serializeVectorContent(content) {
|
|
@@ -1732,9 +1757,9 @@ function serializeVectorContent(content) {
|
|
|
1732
1757
|
}
|
|
1733
1758
|
// Descriptor color values: HSB saturation/brightness 0..100, CMYK 0..100, Gray 0..100, Lab L 0..100, a/b -128..127
|
|
1734
1759
|
// Color values (see psd.ts): HSB 0..1, CMYK 0..255, Gray 0..255, Lab L 0..1, a/b -1..1 (same as readColor/writeColor)
|
|
1735
|
-
const colorSourceKey = typeof Symbol !== 'undefined' ? Symbol('agPsdColorSource') : '__agPsdColorSource';
|
|
1736
1760
|
const colorConversions = {
|
|
1737
1761
|
// key: [descriptor -> color, color -> descriptor]
|
|
1762
|
+
'H ': [x => x / 360, x => x * 360], // angle
|
|
1738
1763
|
Strt: [x => x / 100, x => x * 100],
|
|
1739
1764
|
Brgh: [x => x / 100, x => x * 100],
|
|
1740
1765
|
'Cyn ': [x => x * 255 / 100, x => x * 100 / 255],
|
|
@@ -1762,22 +1787,18 @@ function colorToDescriptorValue(key, value) {
|
|
|
1762
1787
|
}
|
|
1763
1788
|
return result;
|
|
1764
1789
|
}
|
|
1765
|
-
function
|
|
1766
|
-
|
|
1767
|
-
if (keys.length !== Object.keys(b).length)
|
|
1768
|
-
return false;
|
|
1769
|
-
return keys.every(key => a[key] === b[key]);
|
|
1790
|
+
function isBookColor(color) {
|
|
1791
|
+
return color._classID === 'BkCl' || 'Bk ' in color || 'bookID' in color;
|
|
1770
1792
|
}
|
|
1771
1793
|
function parseColor(color) {
|
|
1772
|
-
let result;
|
|
1773
1794
|
if ('H ' in color) {
|
|
1774
|
-
|
|
1795
|
+
return { h: parsePercentOrAngle(color['H ']), s: color.Strt / 100, b: color.Brgh / 100 };
|
|
1775
1796
|
}
|
|
1776
1797
|
else if ('Rd ' in color) {
|
|
1777
1798
|
return { r: color['Rd '], g: color['Grn '], b: color['Bl '] };
|
|
1778
1799
|
}
|
|
1779
1800
|
else if ('Cyn ' in color) {
|
|
1780
|
-
|
|
1801
|
+
return {
|
|
1781
1802
|
c: color['Cyn '] * 255 / 100,
|
|
1782
1803
|
m: color.Mgnt * 255 / 100,
|
|
1783
1804
|
y: color['Ylw '] * 255 / 100,
|
|
@@ -1785,21 +1806,22 @@ function parseColor(color) {
|
|
|
1785
1806
|
};
|
|
1786
1807
|
}
|
|
1787
1808
|
else if ('Gry ' in color) {
|
|
1788
|
-
|
|
1809
|
+
return { k: color['Gry '] * 255 / 100 };
|
|
1789
1810
|
}
|
|
1790
1811
|
else if ('Lmnc' in color) {
|
|
1791
|
-
|
|
1812
|
+
return { l: color.Lmnc / 100, a: (0, helpers_1.normalizeLabAB)(color['A ']), b: (0, helpers_1.normalizeLabAB)(color['B ']) };
|
|
1792
1813
|
}
|
|
1793
1814
|
else if ('redFloat' in color) {
|
|
1794
1815
|
return { fr: color.redFloat, fg: color.greenFloat, fb: color.blueFloat };
|
|
1795
1816
|
}
|
|
1817
|
+
else if (isBookColor(color)) {
|
|
1818
|
+
return { r: 0, g: 0, b: 0 }; // book (Pantone) colors are not supported
|
|
1819
|
+
}
|
|
1796
1820
|
else {
|
|
1797
1821
|
throw new Error('Unsupported color descriptor');
|
|
1798
1822
|
}
|
|
1799
|
-
// remember original descriptor values, so unmodified colors can be written back without conversion errors
|
|
1800
|
-
return setHidden(result, colorSourceKey, { color: Object.assign({}, result), descriptor: color });
|
|
1801
1823
|
}
|
|
1802
|
-
function
|
|
1824
|
+
function serializeColor(color) {
|
|
1803
1825
|
if (!color) {
|
|
1804
1826
|
return { _name: '', _classID: 'RGBC', 'Rd ': 0, 'Grn ': 0, 'Bl ': 0 };
|
|
1805
1827
|
}
|
|
@@ -1812,7 +1834,7 @@ function serializeColorValues(color) {
|
|
|
1812
1834
|
else if ('h' in color) {
|
|
1813
1835
|
return {
|
|
1814
1836
|
_name: '', _classID: 'HSBC',
|
|
1815
|
-
'H ': unitsAngle((color.h || 0)
|
|
1837
|
+
'H ': unitsAngle(colorToDescriptorValue('H ', color.h || 0)),
|
|
1816
1838
|
Strt: colorToDescriptorValue('Strt', color.s || 0),
|
|
1817
1839
|
Brgh: colorToDescriptorValue('Brgh', color.b || 0),
|
|
1818
1840
|
};
|
|
@@ -1841,19 +1863,6 @@ function serializeColorValues(color) {
|
|
|
1841
1863
|
throw new Error('Invalid color value');
|
|
1842
1864
|
}
|
|
1843
1865
|
}
|
|
1844
|
-
function serializeColor(color) {
|
|
1845
|
-
const result = serializeColorValues(color);
|
|
1846
|
-
const source = getHidden(color, colorSourceKey);
|
|
1847
|
-
if (source && shallowEqual(source.color, color)) {
|
|
1848
|
-
// color was not modified since it was read, use exact original values
|
|
1849
|
-
for (const key of Object.keys(result)) {
|
|
1850
|
-
if (colorConversions[key] && typeof source.descriptor[key] === 'number') {
|
|
1851
|
-
result[key] = source.descriptor[key];
|
|
1852
|
-
}
|
|
1853
|
-
}
|
|
1854
|
-
}
|
|
1855
|
-
return result;
|
|
1856
|
-
}
|
|
1857
1866
|
function parseAngle(x) {
|
|
1858
1867
|
if (x === undefined)
|
|
1859
1868
|
return 0;
|
|
@@ -1879,7 +1888,8 @@ function parsePercentOrAngle(x) {
|
|
|
1879
1888
|
}
|
|
1880
1889
|
function parseUnits({ units, value }) {
|
|
1881
1890
|
if (units !== 'Pixels' && units !== 'Millimeters' && units !== 'Points' && units !== 'None' &&
|
|
1882
|
-
units !== 'Picas' && units !== 'Inches' && units !== 'Centimeters' && units !== 'Density'
|
|
1891
|
+
units !== 'Picas' && units !== 'Inches' && units !== 'Centimeters' && units !== 'Density' &&
|
|
1892
|
+
units !== 'Distance') {
|
|
1883
1893
|
throw new Error(`Invalid units: ${JSON.stringify({ units, value })}`);
|
|
1884
1894
|
}
|
|
1885
1895
|
return { value, units };
|
|
@@ -1912,7 +1922,8 @@ function unitsValue(x, key) {
|
|
|
1912
1922
|
if (typeof value !== 'number')
|
|
1913
1923
|
throw new Error(`Invalid value in ${JSON.stringify(x)} (key: ${key})`);
|
|
1914
1924
|
if (units !== 'Pixels' && units !== 'Millimeters' && units !== 'Points' && units !== 'None' &&
|
|
1915
|
-
units !== 'Picas' && units !== 'Inches' && units !== 'Centimeters' && units !== 'Density'
|
|
1925
|
+
units !== 'Picas' && units !== 'Inches' && units !== 'Centimeters' && units !== 'Density' &&
|
|
1926
|
+
units !== 'Distance') {
|
|
1916
1927
|
throw new Error(`Invalid units in ${JSON.stringify(x)} (key: ${key})`);
|
|
1917
1928
|
}
|
|
1918
1929
|
return { units, value };
|
|
@@ -2040,6 +2051,11 @@ exports.gradientInterpolationMethodType = (0, helpers_1.createEnum)('gradientInt
|
|
|
2040
2051
|
smooth: 'Smoo',
|
|
2041
2052
|
// TODO: stripes
|
|
2042
2053
|
});
|
|
2054
|
+
exports.Clry = (0, helpers_1.createEnum)('Clry', 'user', {
|
|
2055
|
+
user: 'UsrS',
|
|
2056
|
+
foreground: 'FrgC',
|
|
2057
|
+
background: 'BckC',
|
|
2058
|
+
});
|
|
2043
2059
|
exports.ClrS = (0, helpers_1.createEnum)('ClrS', 'rgb', {
|
|
2044
2060
|
rgb: 'RGBC',
|
|
2045
2061
|
hsb: 'HSBl',
|