@yft-design/psd-lib 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -0
- package/dist/abr.d.ts +143 -0
- package/dist/abr.js +300 -0
- package/dist/additionalInfo.d.ts +26 -0
- package/dist/additionalInfo.js +3891 -0
- package/dist/csh.d.ts +10 -0
- package/dist/csh.js +32 -0
- package/dist/descriptor.d.ts +566 -0
- package/dist/descriptor.js +1958 -0
- package/dist/effectsHelpers.d.ts +5 -0
- package/dist/effectsHelpers.js +280 -0
- package/dist/engineData.d.ts +2 -0
- package/dist/engineData.js +330 -0
- package/dist/engineData2.d.ts +2 -0
- package/dist/engineData2.js +405 -0
- package/dist/helpers.d.ts +89 -0
- package/dist/helpers.js +300 -0
- package/dist/imageResources.d.ts +17 -0
- package/dist/imageResources.js +1070 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +30 -0
- package/dist/initializeCanvas.d.ts +1 -0
- package/dist/initializeCanvas.js +21 -0
- package/dist/jpeg.d.ts +1 -0
- package/dist/jpeg.js +1017 -0
- package/dist/psd.d.ts +1822 -0
- package/dist/psd.js +7 -0
- package/dist/psdReader.d.ts +46 -0
- package/dist/psdReader.js +1188 -0
- package/dist/psdWriter.d.ts +33 -0
- package/dist/psdWriter.js +733 -0
- package/dist/text.d.ts +179 -0
- package/dist/text.js +556 -0
- package/dist/utf8.d.ts +4 -0
- package/dist/utf8.js +150 -0
- package/package.json +46 -0
|
@@ -0,0 +1,1958 @@
|
|
|
1
|
+
import { createEnum } from './helpers';
|
|
2
|
+
import { readSignature, readUnicodeString, readUint32, readUint8, readFloat64, readBytes, readAsciiString, readInt32, readFloat32, readInt32LE, readUnicodeStringWithLengthLE } from './psdReader';
|
|
3
|
+
import { writeSignature, writeBytes, writeUint32, writeFloat64, writeUint8, writeUnicodeStringWithPadding, writeInt32, writeFloat32, writeUnicodeString, writeInt32LE, writeUnicodeStringWithoutLengthLE } from './psdWriter';
|
|
4
|
+
function revMap(map) {
|
|
5
|
+
const result = {};
|
|
6
|
+
Object.keys(map).forEach(key => result[map[key]] = key);
|
|
7
|
+
return result;
|
|
8
|
+
}
|
|
9
|
+
const unitsMap = {
|
|
10
|
+
'#Ang': 'Angle',
|
|
11
|
+
'#Rsl': 'Density',
|
|
12
|
+
'#Rlt': 'Distance',
|
|
13
|
+
'#Nne': 'None',
|
|
14
|
+
'#Prc': 'Percent',
|
|
15
|
+
'#Pxl': 'Pixels',
|
|
16
|
+
'#Mlm': 'Millimeters',
|
|
17
|
+
'#Pnt': 'Points',
|
|
18
|
+
'RrPi': 'Picas',
|
|
19
|
+
'RrIn': 'Inches',
|
|
20
|
+
'RrCm': 'Centimeters',
|
|
21
|
+
};
|
|
22
|
+
const unitsMapRev = revMap(unitsMap);
|
|
23
|
+
let logErrors = false;
|
|
24
|
+
export function setLogErrors(value) {
|
|
25
|
+
logErrors = value;
|
|
26
|
+
}
|
|
27
|
+
function makeType(name, classID) {
|
|
28
|
+
return { name, classID };
|
|
29
|
+
}
|
|
30
|
+
const nullType = makeType('', 'null');
|
|
31
|
+
const USE_CHINESE = false; // Testing
|
|
32
|
+
const fieldToExtType = {
|
|
33
|
+
strokeStyleContent: makeType('', 'solidColorLayer'),
|
|
34
|
+
printProofSetup: makeType(USE_CHINESE ? '校样设置' : 'Proof Setup', 'proofSetup'),
|
|
35
|
+
Grad: makeType(USE_CHINESE ? '渐变' : 'Gradient', 'Grdn'),
|
|
36
|
+
Trnf: makeType(USE_CHINESE ? '变换' : 'Transform', 'Trnf'),
|
|
37
|
+
patternFill: makeType('', 'patternFill'),
|
|
38
|
+
ebbl: makeType('', 'ebbl'),
|
|
39
|
+
SoFi: makeType('', 'SoFi'),
|
|
40
|
+
GrFl: makeType('', 'GrFl'),
|
|
41
|
+
sdwC: makeType('', 'RGBC'),
|
|
42
|
+
hglC: makeType('', 'RGBC'),
|
|
43
|
+
'Clr ': makeType('', 'RGBC'),
|
|
44
|
+
'tintColor': makeType('', 'RGBC'),
|
|
45
|
+
Ofst: makeType('', 'Pnt '),
|
|
46
|
+
ChFX: makeType('', 'ChFX'),
|
|
47
|
+
MpgS: makeType('', 'ShpC'),
|
|
48
|
+
DrSh: makeType('', 'DrSh'),
|
|
49
|
+
IrSh: makeType('', 'IrSh'),
|
|
50
|
+
OrGl: makeType('', 'OrGl'),
|
|
51
|
+
IrGl: makeType('', 'IrGl'),
|
|
52
|
+
TrnS: makeType('', 'ShpC'),
|
|
53
|
+
Ptrn: makeType('', 'Ptrn'),
|
|
54
|
+
FrFX: makeType('', 'FrFX'),
|
|
55
|
+
phase: makeType('', 'Pnt '),
|
|
56
|
+
frameStep: nullType,
|
|
57
|
+
duration: nullType,
|
|
58
|
+
workInTime: nullType,
|
|
59
|
+
workOutTime: nullType,
|
|
60
|
+
audioClipGroupList: nullType,
|
|
61
|
+
bounds: makeType('', 'Rctn'),
|
|
62
|
+
customEnvelopeWarp: makeType('', 'customEnvelopeWarp'),
|
|
63
|
+
warp: makeType('', 'warp'),
|
|
64
|
+
'Sz ': makeType('', 'Pnt '),
|
|
65
|
+
origin: makeType('', 'Pnt '),
|
|
66
|
+
autoExpandOffset: makeType('', 'Pnt '),
|
|
67
|
+
keyOriginShapeBBox: makeType('', 'unitRect'),
|
|
68
|
+
Vrsn: nullType,
|
|
69
|
+
psVersion: nullType,
|
|
70
|
+
docDefaultNewArtboardBackgroundColor: makeType('', 'RGBC'),
|
|
71
|
+
artboardRect: makeType('', 'classFloatRect'),
|
|
72
|
+
keyOriginRRectRadii: makeType('', 'radii'),
|
|
73
|
+
keyOriginBoxCorners: nullType,
|
|
74
|
+
rectangleCornerA: makeType('', 'Pnt '),
|
|
75
|
+
rectangleCornerB: makeType('', 'Pnt '),
|
|
76
|
+
rectangleCornerC: makeType('', 'Pnt '),
|
|
77
|
+
rectangleCornerD: makeType('', 'Pnt '),
|
|
78
|
+
compInfo: nullType,
|
|
79
|
+
quiltWarp: makeType('', 'quiltWarp'),
|
|
80
|
+
generatorSettings: nullType,
|
|
81
|
+
crema: nullType,
|
|
82
|
+
FrIn: nullType,
|
|
83
|
+
blendOptions: nullType,
|
|
84
|
+
FXRf: nullType,
|
|
85
|
+
Lefx: nullType,
|
|
86
|
+
time: nullType,
|
|
87
|
+
animKey: nullType,
|
|
88
|
+
timeScope: nullType,
|
|
89
|
+
inTime: nullType,
|
|
90
|
+
outTime: nullType,
|
|
91
|
+
sheetStyle: nullType,
|
|
92
|
+
translation: nullType,
|
|
93
|
+
Skew: nullType,
|
|
94
|
+
boundingBox: makeType('', 'boundingBox'),
|
|
95
|
+
'Lnk ': makeType('', 'ExternalFileLink'),
|
|
96
|
+
frameReader: makeType('', 'FrameReader'),
|
|
97
|
+
effectParams: makeType('', 'motionTrackEffectParams'),
|
|
98
|
+
Impr: makeType('None', 'none'),
|
|
99
|
+
Anch: makeType('', 'Pnt '),
|
|
100
|
+
'Fwd ': makeType('', 'Pnt '),
|
|
101
|
+
'Bwd ': makeType('', 'Pnt '),
|
|
102
|
+
FlrC: makeType('', 'Pnt '),
|
|
103
|
+
meshBoundaryPath: makeType('', 'pathClass'),
|
|
104
|
+
filterFX: makeType('', 'filterFXStyle'),
|
|
105
|
+
Fltr: makeType('', 'rigidTransform'),
|
|
106
|
+
FrgC: makeType('', 'RGBC'),
|
|
107
|
+
BckC: makeType('', 'RGBC'),
|
|
108
|
+
sdwM: makeType('Parameters', 'adaptCorrectTones'),
|
|
109
|
+
hglM: makeType('Parameters', 'adaptCorrectTones'),
|
|
110
|
+
customShape: makeType('', 'customShape'),
|
|
111
|
+
origFXRefPoint: nullType,
|
|
112
|
+
FXRefPoint: nullType,
|
|
113
|
+
ClMg: makeType('', 'ClMg'),
|
|
114
|
+
};
|
|
115
|
+
const fieldToArrayExtType = {
|
|
116
|
+
'Crv ': makeType('', 'CrPt'),
|
|
117
|
+
Clrs: makeType('', 'Clrt'),
|
|
118
|
+
Trns: makeType('', 'TrnS'),
|
|
119
|
+
keyDescriptorList: nullType,
|
|
120
|
+
solidFillMulti: makeType('', 'SoFi'),
|
|
121
|
+
gradientFillMulti: makeType('', 'GrFl'),
|
|
122
|
+
dropShadowMulti: makeType('', 'DrSh'),
|
|
123
|
+
innerShadowMulti: makeType('', 'IrSh'),
|
|
124
|
+
frameFXMulti: makeType('', 'FrFX'),
|
|
125
|
+
FrIn: nullType,
|
|
126
|
+
FSts: nullType,
|
|
127
|
+
LaSt: nullType,
|
|
128
|
+
sheetTimelineOptions: nullType,
|
|
129
|
+
trackList: makeType('', 'animationTrack'),
|
|
130
|
+
globalTrackList: makeType('', 'animationTrack'),
|
|
131
|
+
keyList: nullType,
|
|
132
|
+
audioClipGroupList: nullType,
|
|
133
|
+
audioClipList: nullType,
|
|
134
|
+
countObjectList: makeType('', 'countObject'),
|
|
135
|
+
countGroupList: makeType('', 'countGroup'),
|
|
136
|
+
slices: makeType('', 'slice'),
|
|
137
|
+
'Pts ': makeType('', 'Pthp'),
|
|
138
|
+
SbpL: makeType('', 'SbpL'),
|
|
139
|
+
pathComponents: makeType('', 'PaCm'),
|
|
140
|
+
filterFXList: makeType('', 'filterFX'),
|
|
141
|
+
puppetShapeList: makeType('', 'puppetShape'),
|
|
142
|
+
channelDenoise: makeType('', 'channelDenoiseParams'),
|
|
143
|
+
ShrP: makeType('', 'Pnt '),
|
|
144
|
+
layerSettings: nullType,
|
|
145
|
+
list: nullType,
|
|
146
|
+
Adjs: makeType('', 'CrvA'),
|
|
147
|
+
};
|
|
148
|
+
const typeToField = {
|
|
149
|
+
'TEXT': [
|
|
150
|
+
'Txt ', 'printerName', 'Nm ', 'Idnt', 'blackAndWhitePresetFileName', 'LUT3DFileName',
|
|
151
|
+
'presetFileName', 'curvesPresetFileName', 'mixerPresetFileName', 'placed', 'description', 'reason',
|
|
152
|
+
'artboardPresetName', 'json', 'clipID', 'relPath', 'fullPath', 'mediaDescriptor', 'Msge',
|
|
153
|
+
'altTag', 'url', 'cellText', 'preset', 'KnNm', 'FPth', 'comment', 'originalPath',
|
|
154
|
+
],
|
|
155
|
+
'tdta': [
|
|
156
|
+
'EngineData', 'LUT3DFileData', 'indexArray', 'originalVertexArray', 'deformedVertexArray',
|
|
157
|
+
'LqMe',
|
|
158
|
+
],
|
|
159
|
+
'long': [
|
|
160
|
+
'TextIndex', 'RndS', 'Mdpn', 'Smth', 'Lctn', 'strokeStyleVersion', 'LaID', 'Vrsn', 'Cnt ',
|
|
161
|
+
'Brgh', 'Cntr', 'means', 'vibrance', 'Strt', 'bwPresetKind', 'comp', 'compID', 'originalCompID',
|
|
162
|
+
'curvesPresetKind', 'mixerPresetKind', 'uOrder', 'vOrder', 'PgNm', 'totalPages', 'Crop',
|
|
163
|
+
'numerator', 'denominator', 'frameCount', 'Annt', 'keyOriginType', 'unitValueQuadVersion',
|
|
164
|
+
'keyOriginIndex', 'major', 'minor', 'fix', 'docDefaultNewArtboardBackgroundType', 'artboardBackgroundType',
|
|
165
|
+
'numModifyingFX', 'deformNumRows', 'deformNumCols', 'FrID', 'FrDl', 'FsID', 'LCnt', 'AFrm', 'AFSt',
|
|
166
|
+
'numBefore', 'numAfter', 'Spcn', 'minOpacity', 'maxOpacity', 'BlnM', 'sheetID', 'gblA', 'globalAltitude',
|
|
167
|
+
'descVersion', 'frameReaderType', 'LyrI', 'zoomOrigin', 'fontSize', 'Rds ', 'sliceID',
|
|
168
|
+
'topOutset', 'leftOutset', 'bottomOutset', 'rightOutset', 'filterID', 'meshQuality',
|
|
169
|
+
'meshExpansion', 'meshRigidity', 'VrsM', 'VrsN', 'NmbG', 'WLMn', 'WLMx', 'AmMn', 'AmMx', 'SclH', 'SclV',
|
|
170
|
+
'Lvl ', 'TlNm', 'TlOf', 'FlRs', 'Thsh', 'ShrS', 'ShrE', 'FlRs', 'Vrnc', 'Strg', 'ExtS', 'ExtD',
|
|
171
|
+
'HrzS', 'VrtS', 'NmbR', 'EdgF', 'Ang1', 'Ang2', 'Ang3', 'Ang4', 'lastAppliedComp', 'capturedInfo',
|
|
172
|
+
],
|
|
173
|
+
'enum': [
|
|
174
|
+
'textGridding', 'Ornt', 'warpStyle', 'warpRotate', 'Inte', 'Bltn', 'ClrS', 'BlrQ',
|
|
175
|
+
'bvlT', 'bvlS', 'bvlD', 'Md ', 'glwS', 'GrdF', 'GlwT', 'RplS', 'BlrM', 'SmBM',
|
|
176
|
+
'strokeStyleLineCapType', 'strokeStyleLineJoinType', 'strokeStyleLineAlignment',
|
|
177
|
+
'strokeStyleBlendMode', 'PntT', 'Styl', 'lookupType', 'LUTFormat', 'dataOrder',
|
|
178
|
+
'tableOrder', 'enableCompCore', 'enableCompCoreGPU', 'compCoreSupport', 'compCoreGPUSupport', 'Engn',
|
|
179
|
+
'enableCompCoreThreads', 'gs99', 'FrDs', 'trackID', 'animInterpStyle', 'horzAlign',
|
|
180
|
+
'vertAlign', 'bgColorType', 'shapeOperation', 'UndA', 'Wvtp', 'Drct', 'WndM', 'Edg ', 'FlCl', 'IntE',
|
|
181
|
+
'IntC', 'Cnvr', 'Fl ', 'Dstr', 'MztT', 'Lns ', 'ExtT', 'DspM', 'ExtR', 'ZZTy', 'SphM', 'SmBQ', 'placedLayerOCIOConversion', 'gradientsInterpolationMethod',
|
|
182
|
+
],
|
|
183
|
+
'bool': [
|
|
184
|
+
'PstS', 'printSixteenBit', 'masterFXSwitch', 'enab', 'uglg', 'antialiasGloss',
|
|
185
|
+
'useShape', 'useTexture', 'uglg', 'antialiasGloss', 'useShape', 'Vsbl',
|
|
186
|
+
'useTexture', 'Algn', 'Rvrs', 'Dthr', 'Invr', 'VctC', 'ShTr', 'layerConceals',
|
|
187
|
+
'strokeEnabled', 'fillEnabled', 'strokeStyleScaleLock', 'strokeStyleStrokeAdjust',
|
|
188
|
+
'hardProof', 'MpBl', 'paperWhite', 'useLegacy', 'Auto', 'Lab ', 'useTint', 'keyShapeInvalidated',
|
|
189
|
+
'autoExpandEnabled', 'autoNestEnabled', 'autoPositionEnabled', 'shrinkwrapOnSaveEnabled',
|
|
190
|
+
'present', 'showInDialog', 'overprint', 'sheetDisclosed', 'lightsDisclosed', 'meshesDisclosed',
|
|
191
|
+
'materialsDisclosed', 'hasMotion', 'muted', 'Effc', 'selected', 'autoScope', 'fillCanvas',
|
|
192
|
+
'cellTextIsHTML', 'Smoo', 'Clsp', 'validAtPosition', 'rigidType', 'hasoptions', 'filterMaskEnable',
|
|
193
|
+
'filterMaskLinked', 'filterMaskExtendWithWhite', 'removeJPEGArtifact', 'Mnch', 'ExtF', 'ExtM',
|
|
194
|
+
'moreAccurate', 'GpuY', 'LIWy', 'Cnty',
|
|
195
|
+
],
|
|
196
|
+
'doub': [
|
|
197
|
+
'warpValue', 'warpPerspective', 'warpPerspectiveOther', 'Intr', 'Wdth', 'Hght',
|
|
198
|
+
'strokeStyleMiterLimit', 'strokeStyleResolution', 'layerTime', 'keyOriginResolution',
|
|
199
|
+
'xx', 'xy', 'yx', 'yy', 'tx', 'ty', 'FrGA', 'frameRate', 'audioLevel', 'rotation',
|
|
200
|
+
'X ', 'Y ', 'redFloat', 'greenFloat', 'blueFloat', 'imageResolution',
|
|
201
|
+
'PuX0', 'PuX1', 'PuX2', 'PuX3', 'PuY0', 'PuY1', 'PuY2', 'PuY3'
|
|
202
|
+
],
|
|
203
|
+
'UntF': [
|
|
204
|
+
'sdwO', 'hglO', 'lagl', 'Lald', 'srgR', 'blur', 'Sftn', 'Opct', 'Dstn', 'Angl',
|
|
205
|
+
'Ckmt', 'Nose', 'Inpr', 'ShdN', 'strokeStyleLineWidth', 'strokeStyleLineDashOffset',
|
|
206
|
+
'strokeStyleOpacity', 'H ', 'Top ', 'Left', 'Btom', 'Rght', 'Rslt',
|
|
207
|
+
'topRight', 'topLeft', 'bottomLeft', 'bottomRight', 'ClNs', 'Shrp',
|
|
208
|
+
],
|
|
209
|
+
'VlLs': [
|
|
210
|
+
'Crv ', 'Clrs', 'Mnm ', 'Mxm ', 'Trns', 'pathList', 'strokeStyleLineDashSet', 'FrLs', 'slices',
|
|
211
|
+
'LaSt', 'Trnf', 'nonAffineTransform', 'keyDescriptorList', 'guideIndeces', 'gradientFillMulti',
|
|
212
|
+
'solidFillMulti', 'frameFXMulti', 'innerShadowMulti', 'dropShadowMulti', 'FrIn', 'FSts', 'FsFr',
|
|
213
|
+
'sheetTimelineOptions', 'audioClipList', 'trackList', 'globalTrackList', 'keyList', 'audioClipList',
|
|
214
|
+
'warpValues', 'selectedPin', 'Pts ', 'SbpL', 'pathComponents', 'pinOffsets', 'posFinalPins',
|
|
215
|
+
'pinVertexIndices', 'PinP', 'PnRt', 'PnOv', 'PnDp', 'filterFXList', 'puppetShapeList', 'ShrP',
|
|
216
|
+
'channelDenoise', 'Mtrx', 'layerSettings', 'list', 'compList', 'Adjs',
|
|
217
|
+
],
|
|
218
|
+
'ObAr': ['meshPoints', 'quiltSliceX', 'quiltSliceY'],
|
|
219
|
+
'obj ': ['null', 'Chnl'],
|
|
220
|
+
'Pth ': ['DspF'],
|
|
221
|
+
};
|
|
222
|
+
const channels = [
|
|
223
|
+
'Rd ', 'Grn ', 'Bl ', 'Yllw', 'Ylw ', 'Cyn ', 'Mgnt', 'Blck', 'Gry ', 'Lmnc', 'A ', 'B ',
|
|
224
|
+
];
|
|
225
|
+
const fieldToArrayType = {
|
|
226
|
+
'Mnm ': 'long',
|
|
227
|
+
'Mxm ': 'long',
|
|
228
|
+
FrLs: 'long',
|
|
229
|
+
strokeStyleLineDashSet: 'UntF',
|
|
230
|
+
Trnf: 'doub',
|
|
231
|
+
nonAffineTransform: 'doub',
|
|
232
|
+
keyDescriptorList: 'Objc',
|
|
233
|
+
gradientFillMulti: 'Objc',
|
|
234
|
+
solidFillMulti: 'Objc',
|
|
235
|
+
frameFXMulti: 'Objc',
|
|
236
|
+
innerShadowMulti: 'Objc',
|
|
237
|
+
dropShadowMulti: 'Objc',
|
|
238
|
+
LaSt: 'Objc',
|
|
239
|
+
FrIn: 'Objc',
|
|
240
|
+
FSts: 'Objc',
|
|
241
|
+
FsFr: 'long',
|
|
242
|
+
blendOptions: 'Objc',
|
|
243
|
+
sheetTimelineOptions: 'Objc',
|
|
244
|
+
keyList: 'Objc',
|
|
245
|
+
warpValues: 'doub',
|
|
246
|
+
selectedPin: 'long',
|
|
247
|
+
'Pts ': 'Objc',
|
|
248
|
+
SbpL: 'Objc',
|
|
249
|
+
pathComponents: 'Objc',
|
|
250
|
+
pinOffsets: 'doub',
|
|
251
|
+
posFinalPins: 'doub',
|
|
252
|
+
pinVertexIndices: 'long',
|
|
253
|
+
PinP: 'doub',
|
|
254
|
+
PnRt: 'long',
|
|
255
|
+
PnOv: 'bool',
|
|
256
|
+
PnDp: 'doub',
|
|
257
|
+
filterFXList: 'Objc',
|
|
258
|
+
puppetShapeList: 'Objc',
|
|
259
|
+
ShrP: 'Objc',
|
|
260
|
+
channelDenoise: 'Objc',
|
|
261
|
+
Mtrx: 'long',
|
|
262
|
+
compList: 'long',
|
|
263
|
+
Chnl: 'enum',
|
|
264
|
+
};
|
|
265
|
+
const fieldToType = {};
|
|
266
|
+
for (const type of Object.keys(typeToField)) {
|
|
267
|
+
for (const field of typeToField[type]) {
|
|
268
|
+
fieldToType[field] = type;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
for (const field of Object.keys(fieldToExtType)) {
|
|
272
|
+
if (!fieldToType[field])
|
|
273
|
+
fieldToType[field] = 'Objc';
|
|
274
|
+
}
|
|
275
|
+
for (const field of Object.keys(fieldToArrayExtType)) {
|
|
276
|
+
fieldToArrayType[field] = 'Objc';
|
|
277
|
+
}
|
|
278
|
+
function getTypeByKey(key, value, root, parent) {
|
|
279
|
+
if (key === 'presetKind') {
|
|
280
|
+
return typeof value === 'string' ? 'enum' : 'long';
|
|
281
|
+
}
|
|
282
|
+
if (key === 'null' && root === 'slices') {
|
|
283
|
+
return 'TEXT';
|
|
284
|
+
}
|
|
285
|
+
else if (key === 'groupID') {
|
|
286
|
+
return root === 'slices' ? 'long' : 'TEXT';
|
|
287
|
+
}
|
|
288
|
+
else if (key === 'Sz ') {
|
|
289
|
+
return ('Wdth' in value) ? 'Objc' : (('units' in value) ? 'UntF' : 'doub');
|
|
290
|
+
}
|
|
291
|
+
else if (key === 'Type') {
|
|
292
|
+
return typeof value === 'string' ? 'enum' : 'long';
|
|
293
|
+
}
|
|
294
|
+
else if (key === 'AntA') {
|
|
295
|
+
return typeof value === 'string' ? 'enum' : 'bool';
|
|
296
|
+
}
|
|
297
|
+
else if ((key === 'Hrzn' || key === 'Vrtc') && (parent.Type === 'keyType.Pstn' || parent._classID === 'Ofst')) {
|
|
298
|
+
return 'long';
|
|
299
|
+
}
|
|
300
|
+
else if (key === 'Hrzn' || key === 'Vrtc' || key === 'Top ' || key === 'Left' || key === 'Btom' || key === 'Rght') {
|
|
301
|
+
if (root === 'slices')
|
|
302
|
+
return 'long';
|
|
303
|
+
return typeof value === 'number' ? 'doub' : 'UntF';
|
|
304
|
+
}
|
|
305
|
+
else if (key === 'Vrsn') {
|
|
306
|
+
return typeof value === 'number' ? 'long' : 'Objc';
|
|
307
|
+
}
|
|
308
|
+
else if (key === 'Rd ' || key === 'Grn ' || key === 'Bl ') {
|
|
309
|
+
return root === 'artd' ? 'long' : 'doub';
|
|
310
|
+
}
|
|
311
|
+
else if (key === 'Trnf') {
|
|
312
|
+
return Array.isArray(value) ? 'VlLs' : 'Objc';
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
return fieldToType[key];
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
export function readAsciiStringOrClassId(reader) {
|
|
319
|
+
const length = readInt32(reader);
|
|
320
|
+
return readAsciiString(reader, length || 4);
|
|
321
|
+
}
|
|
322
|
+
function writeAsciiStringOrClassId(writer, value) {
|
|
323
|
+
if (value.length === 4 && value !== 'warp' && value !== 'time' && value !== 'hold' && value !== 'list') {
|
|
324
|
+
// write classId
|
|
325
|
+
writeInt32(writer, 0);
|
|
326
|
+
writeSignature(writer, value);
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
// write ascii string
|
|
330
|
+
writeInt32(writer, value.length);
|
|
331
|
+
for (let i = 0; i < value.length; i++) {
|
|
332
|
+
writeUint8(writer, value.charCodeAt(i));
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
export function readDescriptorStructure(reader, includeClass) {
|
|
337
|
+
const struct = readClassStructure(reader);
|
|
338
|
+
const object = includeClass ? { _name: struct.name, _classID: struct.classID } : {};
|
|
339
|
+
// console.log('>> ', struct);
|
|
340
|
+
const itemsCount = readUint32(reader);
|
|
341
|
+
for (let i = 0; i < itemsCount; i++) {
|
|
342
|
+
const key = readAsciiStringOrClassId(reader);
|
|
343
|
+
const type = readSignature(reader);
|
|
344
|
+
// console.log(`> '${key}' '${type}'`);
|
|
345
|
+
const data = readOSType(reader, type, includeClass);
|
|
346
|
+
// if (!getTypeByKey(key, data)) console.log(`> '${key}' '${type}'`, data);
|
|
347
|
+
object[key] = data;
|
|
348
|
+
}
|
|
349
|
+
return object;
|
|
350
|
+
}
|
|
351
|
+
export function writeDescriptorStructure(writer, name, classId, value, root) {
|
|
352
|
+
if (logErrors && !classId)
|
|
353
|
+
console.log('Missing classId for: ', name, classId, value);
|
|
354
|
+
// write class structure
|
|
355
|
+
writeUnicodeStringWithPadding(writer, name);
|
|
356
|
+
writeAsciiStringOrClassId(writer, classId);
|
|
357
|
+
const keys = Object.keys(value);
|
|
358
|
+
let keyCount = keys.length;
|
|
359
|
+
if ('_name' in value)
|
|
360
|
+
keyCount--;
|
|
361
|
+
if ('_classID' in value)
|
|
362
|
+
keyCount--;
|
|
363
|
+
writeUint32(writer, keyCount);
|
|
364
|
+
for (const key of keys) {
|
|
365
|
+
if (key === '_name' || key === '_classID')
|
|
366
|
+
continue;
|
|
367
|
+
let type = getTypeByKey(key, value[key], root, value);
|
|
368
|
+
let extType = fieldToExtType[key];
|
|
369
|
+
if (key === 'bounds' && root === 'text') {
|
|
370
|
+
extType = makeType('', 'bounds');
|
|
371
|
+
}
|
|
372
|
+
else if (key === 'origin') {
|
|
373
|
+
type = root === 'slices' ? 'enum' : 'Objc';
|
|
374
|
+
}
|
|
375
|
+
else if ((key === 'Cyn ' || key === 'Mgnt' || key === 'Ylw ' || key === 'Blck') && value._classID === 'CMYC') {
|
|
376
|
+
type = 'doub';
|
|
377
|
+
}
|
|
378
|
+
else if (/^PN[a-z][a-z]$/.test(key)) {
|
|
379
|
+
type = 'TEXT';
|
|
380
|
+
}
|
|
381
|
+
else if (/^PT[a-z][a-z]$/.test(key)) {
|
|
382
|
+
type = 'long';
|
|
383
|
+
}
|
|
384
|
+
else if (/^PF[a-z][a-z]$/.test(key)) {
|
|
385
|
+
type = 'doub';
|
|
386
|
+
}
|
|
387
|
+
else if ((key === 'Rds ' || key === 'Thsh') && typeof value[key] === 'number' && value._classID === 'SmrB') {
|
|
388
|
+
type = 'doub';
|
|
389
|
+
}
|
|
390
|
+
else if (key === 'ClSz' || key === 'Rds ' || key === 'Amnt') {
|
|
391
|
+
type = typeof value[key] === 'number' ? 'long' : 'UntF';
|
|
392
|
+
}
|
|
393
|
+
else if ((key === 'sdwM' || key === 'hglM') && typeof value[key] === 'string') {
|
|
394
|
+
type = 'enum';
|
|
395
|
+
}
|
|
396
|
+
else if (key === 'blur' && typeof value[key] === 'string') {
|
|
397
|
+
type = 'enum';
|
|
398
|
+
}
|
|
399
|
+
else if (key === 'Hght' && typeof value[key] === 'number' && value._classID === 'Embs') {
|
|
400
|
+
type = 'long';
|
|
401
|
+
}
|
|
402
|
+
else if (key === 'Angl' && typeof value[key] === 'number' && (value._classID === 'Embs' || value._classID === 'smartSharpen' || value._classID === 'Twrl' || value._classID === 'MtnB')) {
|
|
403
|
+
type = 'long';
|
|
404
|
+
}
|
|
405
|
+
else if (key === 'Angl' && typeof value[key] === 'number') {
|
|
406
|
+
type = 'doub'; // ???
|
|
407
|
+
}
|
|
408
|
+
else if (key === 'bounds' && root === 'slices') {
|
|
409
|
+
type = 'Objc';
|
|
410
|
+
extType = makeType('', 'Rct1');
|
|
411
|
+
}
|
|
412
|
+
else if (key === 'Scl ') {
|
|
413
|
+
if (typeof value[key] === 'object' && 'Hrzn' in value[key]) {
|
|
414
|
+
type = 'Objc';
|
|
415
|
+
extType = nullType;
|
|
416
|
+
}
|
|
417
|
+
else if (typeof value[key] === 'number') {
|
|
418
|
+
type = 'long';
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
type = 'UntF';
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
else if (key === 'audioClipGroupList' && keys.length === 1) {
|
|
425
|
+
type = 'VlLs';
|
|
426
|
+
}
|
|
427
|
+
else if ((key === 'Strt' || key === 'Brgh') && 'H ' in value) {
|
|
428
|
+
type = 'doub';
|
|
429
|
+
}
|
|
430
|
+
else if (key === 'Wdth' && typeof value[key] === 'object') {
|
|
431
|
+
type = 'UntF';
|
|
432
|
+
}
|
|
433
|
+
else if (key === 'Ofst' && typeof value[key] === 'number') {
|
|
434
|
+
type = 'long';
|
|
435
|
+
}
|
|
436
|
+
else if (key === 'Strt' && typeof value[key] === 'object') {
|
|
437
|
+
type = 'Objc';
|
|
438
|
+
extType = nullType;
|
|
439
|
+
}
|
|
440
|
+
else if (channels.indexOf(key) !== -1) {
|
|
441
|
+
type = (classId === 'RGBC' && root !== 'artd') ? 'doub' : 'long';
|
|
442
|
+
}
|
|
443
|
+
else if (key === 'profile') {
|
|
444
|
+
type = classId === 'printOutput' ? 'TEXT' : 'tdta';
|
|
445
|
+
}
|
|
446
|
+
else if (key === 'strokeStyleContent') {
|
|
447
|
+
if (value[key]['Clr ']) {
|
|
448
|
+
extType = makeType('', 'solidColorLayer');
|
|
449
|
+
}
|
|
450
|
+
else if (value[key].Grad) {
|
|
451
|
+
extType = makeType('', 'gradientLayer');
|
|
452
|
+
}
|
|
453
|
+
else if (value[key].Ptrn) {
|
|
454
|
+
extType = makeType('', 'patternLayer');
|
|
455
|
+
}
|
|
456
|
+
else {
|
|
457
|
+
logErrors && console.log('Invalid strokeStyleContent value', value[key]);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
else if (key === 'bounds' && root === 'quiltWarp') {
|
|
461
|
+
extType = makeType('', 'classFloatRect');
|
|
462
|
+
}
|
|
463
|
+
if (extType && extType.classID === 'RGBC') {
|
|
464
|
+
if ('H ' in value[key])
|
|
465
|
+
extType = { classID: 'HSBC', name: '' };
|
|
466
|
+
// TODO: other color spaces
|
|
467
|
+
}
|
|
468
|
+
writeAsciiStringOrClassId(writer, key);
|
|
469
|
+
writeSignature(writer, type || 'long');
|
|
470
|
+
writeOSType(writer, type || 'long', value[key], key, extType, root);
|
|
471
|
+
if (logErrors && !type)
|
|
472
|
+
console.log(`Missing descriptor field type for: '${key}' in`, value);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
function readOSType(reader, type, includeClass) {
|
|
476
|
+
switch (type) {
|
|
477
|
+
case 'obj ': // Reference
|
|
478
|
+
return readReferenceStructure(reader);
|
|
479
|
+
case 'Objc': // Descriptor
|
|
480
|
+
case 'GlbO': // GlobalObject same as Descriptor
|
|
481
|
+
return readDescriptorStructure(reader, includeClass);
|
|
482
|
+
case 'VlLs': { // List
|
|
483
|
+
const length = readInt32(reader);
|
|
484
|
+
const items = [];
|
|
485
|
+
for (let i = 0; i < length; i++) {
|
|
486
|
+
const itemType = readSignature(reader);
|
|
487
|
+
// console.log(' >', itemType);
|
|
488
|
+
items.push(readOSType(reader, itemType, includeClass));
|
|
489
|
+
}
|
|
490
|
+
return items;
|
|
491
|
+
}
|
|
492
|
+
case 'doub': // Double
|
|
493
|
+
return readFloat64(reader);
|
|
494
|
+
case 'UntF': { // Unit double
|
|
495
|
+
const units = readSignature(reader);
|
|
496
|
+
const value = readFloat64(reader);
|
|
497
|
+
if (!unitsMap[units])
|
|
498
|
+
throw new Error(`Invalid units: ${units}`);
|
|
499
|
+
return { units: unitsMap[units], value };
|
|
500
|
+
}
|
|
501
|
+
case 'UnFl': { // Unit float
|
|
502
|
+
const units = readSignature(reader);
|
|
503
|
+
const value = readFloat32(reader);
|
|
504
|
+
if (!unitsMap[units])
|
|
505
|
+
throw new Error(`Invalid units: ${units}`);
|
|
506
|
+
return { units: unitsMap[units], value };
|
|
507
|
+
}
|
|
508
|
+
case 'TEXT': // String
|
|
509
|
+
return readUnicodeString(reader);
|
|
510
|
+
case 'enum': { // Enumerated
|
|
511
|
+
const enumType = readAsciiStringOrClassId(reader);
|
|
512
|
+
const value = readAsciiStringOrClassId(reader);
|
|
513
|
+
return `${enumType}.${value}`;
|
|
514
|
+
}
|
|
515
|
+
case 'long': // Integer
|
|
516
|
+
return readInt32(reader);
|
|
517
|
+
case 'comp': { // Large Integer
|
|
518
|
+
const low = readUint32(reader);
|
|
519
|
+
const high = readUint32(reader);
|
|
520
|
+
return { low, high };
|
|
521
|
+
}
|
|
522
|
+
case 'bool': // Boolean
|
|
523
|
+
return !!readUint8(reader);
|
|
524
|
+
case 'type': // Class
|
|
525
|
+
case 'GlbC': // Class
|
|
526
|
+
return readClassStructure(reader);
|
|
527
|
+
case 'alis': { // Alias
|
|
528
|
+
const length = readInt32(reader);
|
|
529
|
+
return readAsciiString(reader, length);
|
|
530
|
+
}
|
|
531
|
+
case 'tdta': { // Raw Data
|
|
532
|
+
const length = readInt32(reader);
|
|
533
|
+
return readBytes(reader, length);
|
|
534
|
+
}
|
|
535
|
+
case 'ObAr': { // Object array
|
|
536
|
+
readInt32(reader); // version: 16
|
|
537
|
+
readUnicodeString(reader); // name: ''
|
|
538
|
+
readAsciiStringOrClassId(reader); // 'rationalPoint'
|
|
539
|
+
const length = readInt32(reader);
|
|
540
|
+
const items = [];
|
|
541
|
+
for (let i = 0; i < length; i++) {
|
|
542
|
+
const type1 = readAsciiStringOrClassId(reader); // type Hrzn | Vrtc
|
|
543
|
+
readSignature(reader); // UnFl
|
|
544
|
+
readSignature(reader); // units ? '#Pxl'
|
|
545
|
+
const valuesCount = readInt32(reader);
|
|
546
|
+
const values = [];
|
|
547
|
+
for (let j = 0; j < valuesCount; j++) {
|
|
548
|
+
values.push(readFloat64(reader));
|
|
549
|
+
}
|
|
550
|
+
items.push({ type: type1, values });
|
|
551
|
+
}
|
|
552
|
+
return items;
|
|
553
|
+
}
|
|
554
|
+
case 'Pth ': { // File path
|
|
555
|
+
/*const length =*/ readInt32(reader); // total size of all fields below
|
|
556
|
+
const sig = readSignature(reader);
|
|
557
|
+
/*const pathSize =*/ readInt32LE(reader); // the same as length
|
|
558
|
+
const charsCount = readInt32LE(reader);
|
|
559
|
+
const path = readUnicodeStringWithLengthLE(reader, charsCount);
|
|
560
|
+
return { sig, path };
|
|
561
|
+
}
|
|
562
|
+
default:
|
|
563
|
+
throw new Error(`Invalid TySh descriptor OSType: ${type} at ${reader.offset.toString(16)}`);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
const ObArTypes = {
|
|
567
|
+
meshPoints: 'rationalPoint',
|
|
568
|
+
quiltSliceX: 'UntF',
|
|
569
|
+
quiltSliceY: 'UntF',
|
|
570
|
+
};
|
|
571
|
+
function writeOSType(writer, type, value, key, extType, root) {
|
|
572
|
+
switch (type) {
|
|
573
|
+
case 'obj ': // Reference
|
|
574
|
+
writeReferenceStructure(writer, key, value);
|
|
575
|
+
break;
|
|
576
|
+
case 'Objc': // Descriptor
|
|
577
|
+
case 'GlbO': { // GlobalObject same as Descriptor
|
|
578
|
+
if (typeof value !== 'object')
|
|
579
|
+
throw new Error(`Invalid struct value: ${JSON.stringify(value)}, key: ${key}`);
|
|
580
|
+
if (!extType)
|
|
581
|
+
throw new Error(`Missing ext type for: '${key}' (${JSON.stringify(value)})`);
|
|
582
|
+
const name = value._name || extType.name;
|
|
583
|
+
const classID = value._classID || extType.classID;
|
|
584
|
+
writeDescriptorStructure(writer, name, classID, value, root);
|
|
585
|
+
break;
|
|
586
|
+
}
|
|
587
|
+
case 'VlLs': // List
|
|
588
|
+
if (!Array.isArray(value))
|
|
589
|
+
throw new Error(`Invalid list value: ${JSON.stringify(value)}, key: ${key}`);
|
|
590
|
+
writeInt32(writer, value.length);
|
|
591
|
+
for (let i = 0; i < value.length; i++) {
|
|
592
|
+
const type = fieldToArrayType[key];
|
|
593
|
+
writeSignature(writer, type || 'long');
|
|
594
|
+
writeOSType(writer, type || 'long', value[i], `${key}[]`, fieldToArrayExtType[key], root);
|
|
595
|
+
if (logErrors && !type)
|
|
596
|
+
console.log(`Missing descriptor array type for: '${key}' in`, value);
|
|
597
|
+
}
|
|
598
|
+
break;
|
|
599
|
+
case 'doub': // Double
|
|
600
|
+
if (typeof value !== 'number')
|
|
601
|
+
throw new Error(`Invalid number value: ${JSON.stringify(value)}, key: ${key}`);
|
|
602
|
+
writeFloat64(writer, value);
|
|
603
|
+
break;
|
|
604
|
+
case 'UntF': // Unit double
|
|
605
|
+
if (!unitsMapRev[value.units])
|
|
606
|
+
throw new Error(`Invalid units: ${value.units} in ${key}`);
|
|
607
|
+
writeSignature(writer, unitsMapRev[value.units]);
|
|
608
|
+
writeFloat64(writer, value.value);
|
|
609
|
+
break;
|
|
610
|
+
case 'UnFl': // Unit float
|
|
611
|
+
if (!unitsMapRev[value.units])
|
|
612
|
+
throw new Error(`Invalid units: ${value.units} in ${key}`);
|
|
613
|
+
writeSignature(writer, unitsMapRev[value.units]);
|
|
614
|
+
writeFloat32(writer, value.value);
|
|
615
|
+
break;
|
|
616
|
+
case 'TEXT': // String
|
|
617
|
+
writeUnicodeStringWithPadding(writer, value);
|
|
618
|
+
break;
|
|
619
|
+
case 'enum': { // Enumerated
|
|
620
|
+
if (typeof value !== 'string')
|
|
621
|
+
throw new Error(`Invalid enum value: ${JSON.stringify(value)}, key: ${key}`);
|
|
622
|
+
const [_type, val] = value.split('.');
|
|
623
|
+
writeAsciiStringOrClassId(writer, _type);
|
|
624
|
+
writeAsciiStringOrClassId(writer, val);
|
|
625
|
+
break;
|
|
626
|
+
}
|
|
627
|
+
case 'long': // Integer
|
|
628
|
+
if (typeof value !== 'number')
|
|
629
|
+
throw new Error(`Invalid integer value: ${JSON.stringify(value)}, key: ${key}`);
|
|
630
|
+
writeInt32(writer, value);
|
|
631
|
+
break;
|
|
632
|
+
// case 'comp': // Large Integer
|
|
633
|
+
// writeLargeInteger(reader);
|
|
634
|
+
case 'bool': // Boolean
|
|
635
|
+
if (typeof value !== 'boolean')
|
|
636
|
+
throw new Error(`Invalid boolean value: ${JSON.stringify(value)}, key: ${key}`);
|
|
637
|
+
writeUint8(writer, value ? 1 : 0);
|
|
638
|
+
break;
|
|
639
|
+
// case 'type': // Class
|
|
640
|
+
// case 'GlbC': // Class
|
|
641
|
+
// writeClassStructure(reader);
|
|
642
|
+
// case 'alis': // Alias
|
|
643
|
+
// writeAliasStructure(reader);
|
|
644
|
+
case 'tdta': // Raw Data
|
|
645
|
+
writeInt32(writer, value.byteLength);
|
|
646
|
+
writeBytes(writer, value);
|
|
647
|
+
break;
|
|
648
|
+
case 'ObAr': { // Object array
|
|
649
|
+
writeInt32(writer, 16); // version
|
|
650
|
+
writeUnicodeStringWithPadding(writer, ''); // name
|
|
651
|
+
const type = ObArTypes[key];
|
|
652
|
+
if (!type)
|
|
653
|
+
throw new Error(`Not implemented ObArType for: ${key}`);
|
|
654
|
+
writeAsciiStringOrClassId(writer, type);
|
|
655
|
+
writeInt32(writer, value.length);
|
|
656
|
+
for (let i = 0; i < value.length; i++) {
|
|
657
|
+
writeAsciiStringOrClassId(writer, value[i].type); // Hrzn | Vrtc
|
|
658
|
+
writeSignature(writer, 'UnFl');
|
|
659
|
+
writeSignature(writer, '#Pxl');
|
|
660
|
+
writeInt32(writer, value[i].values.length);
|
|
661
|
+
for (let j = 0; j < value[i].values.length; j++) {
|
|
662
|
+
writeFloat64(writer, value[i].values[j]);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
break;
|
|
666
|
+
}
|
|
667
|
+
case 'Pth ': { // File path
|
|
668
|
+
const length = 4 + 4 + 4 + value.path.length * 2;
|
|
669
|
+
writeInt32(writer, length);
|
|
670
|
+
writeSignature(writer, value.sig);
|
|
671
|
+
writeInt32LE(writer, length);
|
|
672
|
+
writeInt32LE(writer, value.path.length);
|
|
673
|
+
writeUnicodeStringWithoutLengthLE(writer, value.path);
|
|
674
|
+
break;
|
|
675
|
+
}
|
|
676
|
+
default:
|
|
677
|
+
throw new Error(`Not implemented descriptor OSType: ${type}`);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
function readReferenceStructure(reader) {
|
|
681
|
+
const itemsCount = readInt32(reader);
|
|
682
|
+
const items = [];
|
|
683
|
+
for (let i = 0; i < itemsCount; i++) {
|
|
684
|
+
const type = readSignature(reader);
|
|
685
|
+
switch (type) {
|
|
686
|
+
case 'prop': { // Property
|
|
687
|
+
readClassStructure(reader);
|
|
688
|
+
const keyID = readAsciiStringOrClassId(reader);
|
|
689
|
+
items.push(keyID);
|
|
690
|
+
break;
|
|
691
|
+
}
|
|
692
|
+
case 'Clss': // Class
|
|
693
|
+
items.push(readClassStructure(reader));
|
|
694
|
+
break;
|
|
695
|
+
case 'Enmr': { // Enumerated Reference
|
|
696
|
+
readClassStructure(reader);
|
|
697
|
+
const typeID = readAsciiStringOrClassId(reader);
|
|
698
|
+
const value = readAsciiStringOrClassId(reader);
|
|
699
|
+
items.push(`${typeID}.${value}`);
|
|
700
|
+
break;
|
|
701
|
+
}
|
|
702
|
+
case 'rele': { // Offset
|
|
703
|
+
// const { name, classID } =
|
|
704
|
+
readClassStructure(reader);
|
|
705
|
+
items.push(readUint32(reader));
|
|
706
|
+
break;
|
|
707
|
+
}
|
|
708
|
+
case 'Idnt': // Identifier
|
|
709
|
+
items.push(readInt32(reader));
|
|
710
|
+
break;
|
|
711
|
+
case 'indx': // Index
|
|
712
|
+
items.push(readInt32(reader));
|
|
713
|
+
break;
|
|
714
|
+
case 'name': { // Name
|
|
715
|
+
readClassStructure(reader);
|
|
716
|
+
items.push(readUnicodeString(reader));
|
|
717
|
+
break;
|
|
718
|
+
}
|
|
719
|
+
default:
|
|
720
|
+
throw new Error(`Invalid descriptor reference type: ${type}`);
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
return items;
|
|
724
|
+
}
|
|
725
|
+
function writeReferenceStructure(writer, _key, items) {
|
|
726
|
+
writeInt32(writer, items.length);
|
|
727
|
+
for (let i = 0; i < items.length; i++) {
|
|
728
|
+
const value = items[i];
|
|
729
|
+
let type = 'unknown';
|
|
730
|
+
if (typeof value === 'string') {
|
|
731
|
+
if (/^[a-z ]+\.[a-z ]+$/i.test(value)) {
|
|
732
|
+
type = 'Enmr';
|
|
733
|
+
}
|
|
734
|
+
else {
|
|
735
|
+
type = 'name';
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
writeSignature(writer, type);
|
|
739
|
+
switch (type) {
|
|
740
|
+
// case 'prop': // Property
|
|
741
|
+
// case 'Clss': // Class
|
|
742
|
+
case 'Enmr': { // Enumerated Reference
|
|
743
|
+
const [typeID, enumValue] = value.split('.');
|
|
744
|
+
writeClassStructure(writer, '\0', typeID);
|
|
745
|
+
writeAsciiStringOrClassId(writer, typeID);
|
|
746
|
+
writeAsciiStringOrClassId(writer, enumValue);
|
|
747
|
+
break;
|
|
748
|
+
}
|
|
749
|
+
// case 'rele': // Offset
|
|
750
|
+
// case 'Idnt': // Identifier
|
|
751
|
+
// case 'indx': // Index
|
|
752
|
+
case 'name': { // Name
|
|
753
|
+
writeClassStructure(writer, '\0', 'Lyr ');
|
|
754
|
+
writeUnicodeString(writer, value + '\0');
|
|
755
|
+
break;
|
|
756
|
+
}
|
|
757
|
+
default:
|
|
758
|
+
throw new Error(`Invalid descriptor reference type: ${type}`);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
return items;
|
|
762
|
+
}
|
|
763
|
+
function readClassStructure(reader) {
|
|
764
|
+
const name = readUnicodeString(reader);
|
|
765
|
+
const classID = readAsciiStringOrClassId(reader);
|
|
766
|
+
return { name, classID };
|
|
767
|
+
}
|
|
768
|
+
function writeClassStructure(writer, name, classID) {
|
|
769
|
+
writeUnicodeString(writer, name);
|
|
770
|
+
writeAsciiStringOrClassId(writer, classID);
|
|
771
|
+
}
|
|
772
|
+
export function readVersionAndDescriptor(reader, includeClass = false) {
|
|
773
|
+
const version = readUint32(reader);
|
|
774
|
+
if (version !== 16)
|
|
775
|
+
throw new Error(`Invalid descriptor version: ${version}`);
|
|
776
|
+
const desc = readDescriptorStructure(reader, includeClass);
|
|
777
|
+
// console.log(require('util').inspect(desc, false, 99, true));
|
|
778
|
+
return desc;
|
|
779
|
+
}
|
|
780
|
+
export function writeVersionAndDescriptor(writer, name, classID, descriptor, root = '') {
|
|
781
|
+
writeUint32(writer, 16); // version
|
|
782
|
+
writeDescriptorStructure(writer, name, classID, descriptor, root);
|
|
783
|
+
}
|
|
784
|
+
export function horzVrtcToXY(hv) {
|
|
785
|
+
return { x: hv.Hrzn, y: hv.Vrtc };
|
|
786
|
+
}
|
|
787
|
+
export function xyToHorzVrtc(xy) {
|
|
788
|
+
return { Hrzn: xy.x, Vrtc: xy.y };
|
|
789
|
+
}
|
|
790
|
+
export function descBoundsToBounds(desc) {
|
|
791
|
+
return {
|
|
792
|
+
top: parseUnits(desc['Top ']),
|
|
793
|
+
left: parseUnits(desc.Left),
|
|
794
|
+
right: parseUnits(desc.Rght),
|
|
795
|
+
bottom: parseUnits(desc.Btom),
|
|
796
|
+
};
|
|
797
|
+
}
|
|
798
|
+
export function boundsToDescBounds(bounds) {
|
|
799
|
+
return {
|
|
800
|
+
Left: unitsValue(bounds.left, 'bounds.left'),
|
|
801
|
+
['Top ']: unitsValue(bounds.top, 'bounds.top'),
|
|
802
|
+
Rght: unitsValue(bounds.right, 'bounds.right'),
|
|
803
|
+
Btom: unitsValue(bounds.bottom, 'bounds.bottom'),
|
|
804
|
+
};
|
|
805
|
+
}
|
|
806
|
+
function parseFxObject(fx) {
|
|
807
|
+
const stroke = {
|
|
808
|
+
enabled: !!fx.enab,
|
|
809
|
+
position: FStl.decode(fx.Styl),
|
|
810
|
+
fillType: FrFl.decode(fx.PntT),
|
|
811
|
+
blendMode: BlnM.decode(fx['Md ']),
|
|
812
|
+
opacity: parsePercent(fx.Opct),
|
|
813
|
+
size: parseUnits(fx['Sz ']),
|
|
814
|
+
};
|
|
815
|
+
if (fx.present !== undefined)
|
|
816
|
+
stroke.present = fx.present;
|
|
817
|
+
if (fx.showInDialog !== undefined)
|
|
818
|
+
stroke.showInDialog = fx.showInDialog;
|
|
819
|
+
if (fx.overprint !== undefined)
|
|
820
|
+
stroke.overprint = fx.overprint;
|
|
821
|
+
if (fx['Clr '])
|
|
822
|
+
stroke.color = parseColor(fx['Clr ']);
|
|
823
|
+
if (fx.Grad)
|
|
824
|
+
stroke.gradient = parseGradientContent(fx);
|
|
825
|
+
if (fx.Ptrn)
|
|
826
|
+
stroke.pattern = parsePatternContent(fx);
|
|
827
|
+
return stroke;
|
|
828
|
+
}
|
|
829
|
+
function serializeFxObject(stroke) {
|
|
830
|
+
let FrFX = {};
|
|
831
|
+
FrFX.enab = !!stroke.enabled;
|
|
832
|
+
if (stroke.present !== undefined)
|
|
833
|
+
FrFX.present = !!stroke.present;
|
|
834
|
+
if (stroke.showInDialog !== undefined)
|
|
835
|
+
FrFX.showInDialog = !!stroke.showInDialog;
|
|
836
|
+
FrFX.Styl = FStl.encode(stroke.position);
|
|
837
|
+
FrFX.PntT = FrFl.encode(stroke.fillType);
|
|
838
|
+
FrFX['Md '] = BlnM.encode(stroke.blendMode);
|
|
839
|
+
FrFX.Opct = unitsPercent(stroke.opacity);
|
|
840
|
+
FrFX['Sz '] = unitsValue(stroke.size, 'size');
|
|
841
|
+
if (stroke.color)
|
|
842
|
+
FrFX['Clr '] = serializeColor(stroke.color);
|
|
843
|
+
if (stroke.gradient)
|
|
844
|
+
FrFX = { ...FrFX, ...serializeGradientContent(stroke.gradient) };
|
|
845
|
+
if (stroke.pattern)
|
|
846
|
+
FrFX = { ...FrFX, ...serializePatternContent(stroke.pattern) };
|
|
847
|
+
if (stroke.overprint !== undefined)
|
|
848
|
+
FrFX.overprint = !!stroke.overprint;
|
|
849
|
+
return FrFX;
|
|
850
|
+
}
|
|
851
|
+
export function serializeEffects(e, log, multi) {
|
|
852
|
+
const info = multi ? {
|
|
853
|
+
'Scl ': unitsPercentF(e.scale ?? 1),
|
|
854
|
+
masterFXSwitch: !e.disabled,
|
|
855
|
+
} : {
|
|
856
|
+
masterFXSwitch: !e.disabled,
|
|
857
|
+
'Scl ': unitsPercentF(e.scale ?? 1),
|
|
858
|
+
};
|
|
859
|
+
const arrayKeys = ['dropShadow', 'innerShadow', 'solidFill', 'gradientOverlay', 'stroke'];
|
|
860
|
+
for (const key of arrayKeys) {
|
|
861
|
+
if (e[key] && !Array.isArray(e[key]))
|
|
862
|
+
throw new Error(`${key} should be an array`);
|
|
863
|
+
}
|
|
864
|
+
const useMulti = (arr) => !!arr && arr.length > 1 && multi;
|
|
865
|
+
const useSingle = (arr) => !!arr && arr.length >= 1 && (!multi || arr.length === 1);
|
|
866
|
+
if (useSingle(e.dropShadow))
|
|
867
|
+
info.DrSh = serializeEffectObject(e.dropShadow[0], 'dropShadow', log);
|
|
868
|
+
if (useMulti(e.dropShadow))
|
|
869
|
+
info.dropShadowMulti = e.dropShadow.map(i => serializeEffectObject(i, 'dropShadow', log));
|
|
870
|
+
if (useSingle(e.innerShadow))
|
|
871
|
+
info.IrSh = serializeEffectObject(e.innerShadow[0], 'innerShadow', log);
|
|
872
|
+
if (useMulti(e.innerShadow))
|
|
873
|
+
info.innerShadowMulti = e.innerShadow.map(i => serializeEffectObject(i, 'innerShadow', log));
|
|
874
|
+
if (e.outerGlow)
|
|
875
|
+
info.OrGl = serializeEffectObject(e.outerGlow, 'outerGlow', log);
|
|
876
|
+
if (useMulti(e.solidFill))
|
|
877
|
+
info.solidFillMulti = e.solidFill.map(i => serializeEffectObject(i, 'solidFill', log));
|
|
878
|
+
if (useMulti(e.gradientOverlay))
|
|
879
|
+
info.gradientFillMulti = e.gradientOverlay.map(i => serializeEffectObject(i, 'gradientOverlay', log));
|
|
880
|
+
if (useMulti(e.stroke))
|
|
881
|
+
info.frameFXMulti = e.stroke.map(i => serializeFxObject(i));
|
|
882
|
+
if (e.innerGlow)
|
|
883
|
+
info.IrGl = serializeEffectObject(e.innerGlow, 'innerGlow', log);
|
|
884
|
+
if (e.bevel)
|
|
885
|
+
info.ebbl = serializeEffectObject(e.bevel, 'bevel', log);
|
|
886
|
+
if (useSingle(e.solidFill))
|
|
887
|
+
info.SoFi = serializeEffectObject(e.solidFill[0], 'solidFill', log);
|
|
888
|
+
if (e.patternOverlay)
|
|
889
|
+
info.patternFill = serializeEffectObject(e.patternOverlay, 'patternOverlay', log);
|
|
890
|
+
if (useSingle(e.gradientOverlay))
|
|
891
|
+
info.GrFl = serializeEffectObject(e.gradientOverlay[0], 'gradientOverlay', log);
|
|
892
|
+
if (e.satin)
|
|
893
|
+
info.ChFX = serializeEffectObject(e.satin, 'satin', log);
|
|
894
|
+
if (useSingle(e.stroke))
|
|
895
|
+
info.FrFX = serializeFxObject(e.stroke?.[0]);
|
|
896
|
+
if (multi) {
|
|
897
|
+
info.numModifyingFX = 0;
|
|
898
|
+
for (const key of Object.keys(e)) {
|
|
899
|
+
const value = e[key];
|
|
900
|
+
if (Array.isArray(value)) {
|
|
901
|
+
for (const effect of value) {
|
|
902
|
+
if (effect.enabled)
|
|
903
|
+
info.numModifyingFX++;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
else if (value.enabled) {
|
|
907
|
+
info.numModifyingFX++;
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
return info;
|
|
912
|
+
}
|
|
913
|
+
export function parseEffects(info, log) {
|
|
914
|
+
const effects = {};
|
|
915
|
+
const { masterFXSwitch, DrSh, dropShadowMulti, IrSh, innerShadowMulti, OrGl, IrGl, ebbl, SoFi, solidFillMulti, patternFill, GrFl, gradientFillMulti, ChFX, FrFX, frameFXMulti, numModifyingFX, ...rest } = info;
|
|
916
|
+
if (!masterFXSwitch)
|
|
917
|
+
effects.disabled = true;
|
|
918
|
+
if (info['Scl '])
|
|
919
|
+
effects.scale = parsePercent(info['Scl ']);
|
|
920
|
+
if (DrSh)
|
|
921
|
+
effects.dropShadow = [parseEffectObject(DrSh, log)];
|
|
922
|
+
if (dropShadowMulti)
|
|
923
|
+
effects.dropShadow = dropShadowMulti.map(i => parseEffectObject(i, log));
|
|
924
|
+
if (IrSh)
|
|
925
|
+
effects.innerShadow = [parseEffectObject(IrSh, log)];
|
|
926
|
+
if (innerShadowMulti)
|
|
927
|
+
effects.innerShadow = innerShadowMulti.map(i => parseEffectObject(i, log));
|
|
928
|
+
if (OrGl)
|
|
929
|
+
effects.outerGlow = parseEffectObject(OrGl, log);
|
|
930
|
+
if (IrGl)
|
|
931
|
+
effects.innerGlow = parseEffectObject(IrGl, log);
|
|
932
|
+
if (ebbl)
|
|
933
|
+
effects.bevel = parseEffectObject(ebbl, log);
|
|
934
|
+
if (SoFi)
|
|
935
|
+
effects.solidFill = [parseEffectObject(SoFi, log)];
|
|
936
|
+
if (solidFillMulti)
|
|
937
|
+
effects.solidFill = solidFillMulti.map(i => parseEffectObject(i, log));
|
|
938
|
+
if (patternFill)
|
|
939
|
+
effects.patternOverlay = parseEffectObject(patternFill, log);
|
|
940
|
+
if (GrFl)
|
|
941
|
+
effects.gradientOverlay = [parseEffectObject(GrFl, log)];
|
|
942
|
+
if (gradientFillMulti)
|
|
943
|
+
effects.gradientOverlay = gradientFillMulti.map(i => parseEffectObject(i, log));
|
|
944
|
+
if (ChFX)
|
|
945
|
+
effects.satin = parseEffectObject(ChFX, log);
|
|
946
|
+
if (FrFX)
|
|
947
|
+
effects.stroke = [parseFxObject(FrFX)];
|
|
948
|
+
if (frameFXMulti)
|
|
949
|
+
effects.stroke = frameFXMulti.map(i => parseFxObject(i));
|
|
950
|
+
if (log && Object.keys(rest).length > 1)
|
|
951
|
+
console.log('Unhandled effect keys:', rest);
|
|
952
|
+
return effects;
|
|
953
|
+
}
|
|
954
|
+
function parseKeyList(keyList, logMissingFeatures) {
|
|
955
|
+
const keys = [];
|
|
956
|
+
for (let j = 0; j < keyList.length; j++) {
|
|
957
|
+
const key = keyList[j];
|
|
958
|
+
const { time: { denominator, numerator }, selected, animKey } = key;
|
|
959
|
+
const time = { numerator, denominator };
|
|
960
|
+
const interpolation = animInterpStyleEnum.decode(key.animInterpStyle);
|
|
961
|
+
switch (animKey.Type) {
|
|
962
|
+
case 'keyType.Opct':
|
|
963
|
+
keys.push({ interpolation, time, selected, type: 'opacity', value: parsePercent(animKey.Opct) });
|
|
964
|
+
break;
|
|
965
|
+
case 'keyType.Pstn':
|
|
966
|
+
keys.push({ interpolation, time, selected, type: 'position', x: animKey.Hrzn, y: animKey.Vrtc });
|
|
967
|
+
break;
|
|
968
|
+
case 'keyType.Trnf':
|
|
969
|
+
keys.push({
|
|
970
|
+
interpolation, time, selected, type: 'transform',
|
|
971
|
+
scale: horzVrtcToXY(animKey['Scl ']), skew: horzVrtcToXY(animKey.Skew), rotation: animKey.rotation, translation: horzVrtcToXY(animKey.translation)
|
|
972
|
+
});
|
|
973
|
+
break;
|
|
974
|
+
case 'keyType.sheetStyle': {
|
|
975
|
+
const key = { interpolation, time, selected, type: 'style' };
|
|
976
|
+
if (animKey.sheetStyle.Lefx)
|
|
977
|
+
key.style = parseEffects(animKey.sheetStyle.Lefx, logMissingFeatures);
|
|
978
|
+
keys.push(key);
|
|
979
|
+
break;
|
|
980
|
+
}
|
|
981
|
+
case 'keyType.globalLighting': {
|
|
982
|
+
keys.push({
|
|
983
|
+
interpolation, time, selected, type: 'globalLighting',
|
|
984
|
+
globalAngle: animKey.gblA, globalAltitude: animKey.globalAltitude
|
|
985
|
+
});
|
|
986
|
+
break;
|
|
987
|
+
}
|
|
988
|
+
default: throw new Error(`Unsupported keyType value`);
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
return keys;
|
|
992
|
+
}
|
|
993
|
+
function serializeKeyList(keys) {
|
|
994
|
+
const keyList = [];
|
|
995
|
+
for (let j = 0; j < keys.length; j++) {
|
|
996
|
+
const key = keys[j];
|
|
997
|
+
const { time, selected = false, interpolation } = key;
|
|
998
|
+
const animInterpStyle = animInterpStyleEnum.encode(interpolation);
|
|
999
|
+
let animKey;
|
|
1000
|
+
switch (key.type) {
|
|
1001
|
+
case 'opacity':
|
|
1002
|
+
animKey = { Type: 'keyType.Opct', Opct: unitsPercent(key.value) };
|
|
1003
|
+
break;
|
|
1004
|
+
case 'position':
|
|
1005
|
+
animKey = { Type: 'keyType.Pstn', Hrzn: key.x, Vrtc: key.y };
|
|
1006
|
+
break;
|
|
1007
|
+
case 'transform':
|
|
1008
|
+
animKey = { Type: 'keyType.Trnf', 'Scl ': xyToHorzVrtc(key.scale), Skew: xyToHorzVrtc(key.skew), rotation: key.rotation, translation: xyToHorzVrtc(key.translation) };
|
|
1009
|
+
break;
|
|
1010
|
+
case 'style':
|
|
1011
|
+
animKey = { Type: 'keyType.sheetStyle', sheetStyle: { Vrsn: 1, blendOptions: {} } };
|
|
1012
|
+
if (key.style)
|
|
1013
|
+
animKey.sheetStyle = { Vrsn: 1, Lefx: serializeEffects(key.style, false, false), blendOptions: {} };
|
|
1014
|
+
break;
|
|
1015
|
+
case 'globalLighting': {
|
|
1016
|
+
animKey = { Type: 'keyType.globalLighting', gblA: key.globalAngle, globalAltitude: key.globalAltitude };
|
|
1017
|
+
break;
|
|
1018
|
+
}
|
|
1019
|
+
default: throw new Error(`Unsupported keyType value`);
|
|
1020
|
+
}
|
|
1021
|
+
keyList.push({ Vrsn: 1, animInterpStyle, time, animKey, selected });
|
|
1022
|
+
}
|
|
1023
|
+
return keyList;
|
|
1024
|
+
}
|
|
1025
|
+
export function parseTrackList(trackList, logMissingFeatures) {
|
|
1026
|
+
const tracks = [];
|
|
1027
|
+
for (let i = 0; i < trackList.length; i++) {
|
|
1028
|
+
const tr = trackList[i];
|
|
1029
|
+
const track = {
|
|
1030
|
+
type: stdTrackID.decode(tr.trackID),
|
|
1031
|
+
enabled: tr.enab,
|
|
1032
|
+
keys: parseKeyList(tr.keyList, logMissingFeatures),
|
|
1033
|
+
};
|
|
1034
|
+
if (tr.effectParams) {
|
|
1035
|
+
track.effectParams = {
|
|
1036
|
+
fillCanvas: tr.effectParams.fillCanvas,
|
|
1037
|
+
zoomOrigin: tr.effectParams.zoomOrigin,
|
|
1038
|
+
keys: parseKeyList(tr.effectParams.keyList, logMissingFeatures),
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
tracks.push(track);
|
|
1042
|
+
}
|
|
1043
|
+
return tracks;
|
|
1044
|
+
}
|
|
1045
|
+
export function serializeTrackList(tracks) {
|
|
1046
|
+
const trackList = [];
|
|
1047
|
+
for (let i = 0; i < tracks.length; i++) {
|
|
1048
|
+
const t = tracks[i];
|
|
1049
|
+
trackList.push({
|
|
1050
|
+
trackID: stdTrackID.encode(t.type),
|
|
1051
|
+
Vrsn: 1,
|
|
1052
|
+
enab: !!t.enabled,
|
|
1053
|
+
Effc: !!t.effectParams,
|
|
1054
|
+
...(t.effectParams ? {
|
|
1055
|
+
effectParams: {
|
|
1056
|
+
keyList: serializeKeyList(t.keys),
|
|
1057
|
+
fillCanvas: t.effectParams.fillCanvas,
|
|
1058
|
+
zoomOrigin: t.effectParams.zoomOrigin,
|
|
1059
|
+
}
|
|
1060
|
+
} : {}),
|
|
1061
|
+
keyList: serializeKeyList(t.keys),
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1064
|
+
return trackList;
|
|
1065
|
+
}
|
|
1066
|
+
function parseEffectObject(obj, reportErrors) {
|
|
1067
|
+
const result = {};
|
|
1068
|
+
for (const key of Object.keys(obj)) {
|
|
1069
|
+
const val = obj[key];
|
|
1070
|
+
switch (key) {
|
|
1071
|
+
case 'enab':
|
|
1072
|
+
result.enabled = !!val;
|
|
1073
|
+
break;
|
|
1074
|
+
case 'uglg':
|
|
1075
|
+
result.useGlobalLight = !!val;
|
|
1076
|
+
break;
|
|
1077
|
+
case 'AntA':
|
|
1078
|
+
result.antialiased = !!val;
|
|
1079
|
+
break;
|
|
1080
|
+
case 'Algn':
|
|
1081
|
+
result.align = !!val;
|
|
1082
|
+
break;
|
|
1083
|
+
case 'Dthr':
|
|
1084
|
+
result.dither = !!val;
|
|
1085
|
+
break;
|
|
1086
|
+
case 'Invr':
|
|
1087
|
+
result.invert = !!val;
|
|
1088
|
+
break;
|
|
1089
|
+
case 'Rvrs':
|
|
1090
|
+
result.reverse = !!val;
|
|
1091
|
+
break;
|
|
1092
|
+
case 'Clr ':
|
|
1093
|
+
result.color = parseColor(val);
|
|
1094
|
+
break;
|
|
1095
|
+
case 'hglC':
|
|
1096
|
+
result.highlightColor = parseColor(val);
|
|
1097
|
+
break;
|
|
1098
|
+
case 'sdwC':
|
|
1099
|
+
result.shadowColor = parseColor(val);
|
|
1100
|
+
break;
|
|
1101
|
+
case 'Styl':
|
|
1102
|
+
result.position = FStl.decode(val);
|
|
1103
|
+
break;
|
|
1104
|
+
case 'Md ':
|
|
1105
|
+
result.blendMode = BlnM.decode(val);
|
|
1106
|
+
break;
|
|
1107
|
+
case 'hglM':
|
|
1108
|
+
result.highlightBlendMode = BlnM.decode(val);
|
|
1109
|
+
break;
|
|
1110
|
+
case 'sdwM':
|
|
1111
|
+
result.shadowBlendMode = BlnM.decode(val);
|
|
1112
|
+
break;
|
|
1113
|
+
case 'bvlS':
|
|
1114
|
+
result.style = BESl.decode(val);
|
|
1115
|
+
break;
|
|
1116
|
+
case 'bvlD':
|
|
1117
|
+
result.direction = BESs.decode(val);
|
|
1118
|
+
break;
|
|
1119
|
+
case 'bvlT':
|
|
1120
|
+
result.technique = bvlT.decode(val);
|
|
1121
|
+
break;
|
|
1122
|
+
case 'GlwT':
|
|
1123
|
+
result.technique = BETE.decode(val);
|
|
1124
|
+
break;
|
|
1125
|
+
case 'glwS':
|
|
1126
|
+
result.source = IGSr.decode(val);
|
|
1127
|
+
break;
|
|
1128
|
+
case 'Type':
|
|
1129
|
+
result.type = GrdT.decode(val);
|
|
1130
|
+
break;
|
|
1131
|
+
case 'gs99':
|
|
1132
|
+
result.interpolationMethod = gradientInterpolationMethodType.decode(val);
|
|
1133
|
+
break;
|
|
1134
|
+
case 'Opct':
|
|
1135
|
+
result.opacity = parsePercent(val);
|
|
1136
|
+
break;
|
|
1137
|
+
case 'hglO':
|
|
1138
|
+
result.highlightOpacity = parsePercent(val);
|
|
1139
|
+
break;
|
|
1140
|
+
case 'sdwO':
|
|
1141
|
+
result.shadowOpacity = parsePercent(val);
|
|
1142
|
+
break;
|
|
1143
|
+
case 'lagl':
|
|
1144
|
+
result.angle = parseAngle(val);
|
|
1145
|
+
break;
|
|
1146
|
+
case 'Angl':
|
|
1147
|
+
result.angle = parseAngle(val);
|
|
1148
|
+
break;
|
|
1149
|
+
case 'Lald':
|
|
1150
|
+
result.altitude = parseAngle(val);
|
|
1151
|
+
break;
|
|
1152
|
+
case 'Sftn':
|
|
1153
|
+
result.soften = parseUnits(val);
|
|
1154
|
+
break;
|
|
1155
|
+
case 'srgR':
|
|
1156
|
+
result.strength = parsePercent(val);
|
|
1157
|
+
break;
|
|
1158
|
+
case 'blur':
|
|
1159
|
+
result.size = parseUnits(val);
|
|
1160
|
+
break;
|
|
1161
|
+
case 'Nose':
|
|
1162
|
+
result.noise = parsePercent(val);
|
|
1163
|
+
break;
|
|
1164
|
+
case 'Inpr':
|
|
1165
|
+
result.range = parsePercent(val);
|
|
1166
|
+
break;
|
|
1167
|
+
case 'Ckmt':
|
|
1168
|
+
result.choke = parseUnits(val);
|
|
1169
|
+
break;
|
|
1170
|
+
case 'ShdN':
|
|
1171
|
+
result.jitter = parsePercent(val);
|
|
1172
|
+
break;
|
|
1173
|
+
case 'Dstn':
|
|
1174
|
+
result.distance = parseUnits(val);
|
|
1175
|
+
break;
|
|
1176
|
+
case 'Scl ':
|
|
1177
|
+
result.scale = parsePercent(val);
|
|
1178
|
+
break;
|
|
1179
|
+
case 'Ptrn':
|
|
1180
|
+
result.pattern = { name: val['Nm '], id: val.Idnt };
|
|
1181
|
+
break;
|
|
1182
|
+
case 'phase':
|
|
1183
|
+
result.phase = { x: val.Hrzn, y: val.Vrtc };
|
|
1184
|
+
break;
|
|
1185
|
+
case 'Ofst':
|
|
1186
|
+
result.offset = { x: parsePercent(val.Hrzn), y: parsePercent(val.Vrtc) };
|
|
1187
|
+
break;
|
|
1188
|
+
case 'MpgS':
|
|
1189
|
+
case 'TrnS':
|
|
1190
|
+
result.contour = {
|
|
1191
|
+
name: val['Nm '],
|
|
1192
|
+
curve: val['Crv '].map(p => ({ x: p.Hrzn, y: p.Vrtc })),
|
|
1193
|
+
};
|
|
1194
|
+
break;
|
|
1195
|
+
case 'Grad':
|
|
1196
|
+
result.gradient = parseGradient(val);
|
|
1197
|
+
break;
|
|
1198
|
+
case 'useTexture':
|
|
1199
|
+
case 'useShape':
|
|
1200
|
+
case 'layerConceals':
|
|
1201
|
+
case 'present':
|
|
1202
|
+
case 'showInDialog':
|
|
1203
|
+
case 'antialiasGloss':
|
|
1204
|
+
result[key] = val;
|
|
1205
|
+
break;
|
|
1206
|
+
case '_name':
|
|
1207
|
+
case '_classID':
|
|
1208
|
+
break;
|
|
1209
|
+
default:
|
|
1210
|
+
reportErrors && console.log(`Invalid effect key: '${key}', value:`, val);
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
return result;
|
|
1214
|
+
}
|
|
1215
|
+
function serializeEffectObject(obj, objName, reportErrors) {
|
|
1216
|
+
const result = {
|
|
1217
|
+
enab: false,
|
|
1218
|
+
};
|
|
1219
|
+
if (objName === 'dropShadow') {
|
|
1220
|
+
result.TrnS = { 'Nm ': '', 'Crv ': [] };
|
|
1221
|
+
}
|
|
1222
|
+
for (const objKey of Object.keys(obj)) {
|
|
1223
|
+
const key = objKey;
|
|
1224
|
+
const val = obj[key];
|
|
1225
|
+
switch (key) {
|
|
1226
|
+
case 'enabled':
|
|
1227
|
+
result.enab = !!val;
|
|
1228
|
+
break;
|
|
1229
|
+
case 'useGlobalLight':
|
|
1230
|
+
result.uglg = !!val;
|
|
1231
|
+
break;
|
|
1232
|
+
case 'antialiased':
|
|
1233
|
+
result.AntA = !!val;
|
|
1234
|
+
break;
|
|
1235
|
+
case 'align':
|
|
1236
|
+
result.Algn = !!val;
|
|
1237
|
+
break;
|
|
1238
|
+
case 'dither':
|
|
1239
|
+
result.Dthr = !!val;
|
|
1240
|
+
break;
|
|
1241
|
+
case 'invert':
|
|
1242
|
+
result.Invr = !!val;
|
|
1243
|
+
break;
|
|
1244
|
+
case 'reverse':
|
|
1245
|
+
result.Rvrs = !!val;
|
|
1246
|
+
break;
|
|
1247
|
+
case 'color':
|
|
1248
|
+
result['Clr '] = serializeColor(val);
|
|
1249
|
+
break;
|
|
1250
|
+
case 'highlightColor':
|
|
1251
|
+
result.hglC = serializeColor(val);
|
|
1252
|
+
break;
|
|
1253
|
+
case 'shadowColor':
|
|
1254
|
+
result.sdwC = serializeColor(val);
|
|
1255
|
+
break;
|
|
1256
|
+
case 'position':
|
|
1257
|
+
result.Styl = FStl.encode(val);
|
|
1258
|
+
break;
|
|
1259
|
+
case 'blendMode':
|
|
1260
|
+
result['Md '] = BlnM.encode(val);
|
|
1261
|
+
break;
|
|
1262
|
+
case 'highlightBlendMode':
|
|
1263
|
+
result.hglM = BlnM.encode(val);
|
|
1264
|
+
break;
|
|
1265
|
+
case 'shadowBlendMode':
|
|
1266
|
+
result.sdwM = BlnM.encode(val);
|
|
1267
|
+
break;
|
|
1268
|
+
case 'style':
|
|
1269
|
+
result.bvlS = BESl.encode(val);
|
|
1270
|
+
break;
|
|
1271
|
+
case 'direction':
|
|
1272
|
+
result.bvlD = BESs.encode(val);
|
|
1273
|
+
break;
|
|
1274
|
+
case 'technique':
|
|
1275
|
+
if (objName === 'bevel') {
|
|
1276
|
+
result.bvlT = bvlT.encode(val);
|
|
1277
|
+
}
|
|
1278
|
+
else {
|
|
1279
|
+
result.GlwT = BETE.encode(val);
|
|
1280
|
+
}
|
|
1281
|
+
break;
|
|
1282
|
+
case 'source':
|
|
1283
|
+
result.glwS = IGSr.encode(val);
|
|
1284
|
+
break;
|
|
1285
|
+
case 'type':
|
|
1286
|
+
result.Type = GrdT.encode(val);
|
|
1287
|
+
break;
|
|
1288
|
+
case 'interpolationMethod':
|
|
1289
|
+
result.gs99 = gradientInterpolationMethodType.encode(val);
|
|
1290
|
+
break;
|
|
1291
|
+
case 'opacity':
|
|
1292
|
+
result.Opct = unitsPercent(val);
|
|
1293
|
+
break;
|
|
1294
|
+
case 'highlightOpacity':
|
|
1295
|
+
result.hglO = unitsPercent(val);
|
|
1296
|
+
break;
|
|
1297
|
+
case 'shadowOpacity':
|
|
1298
|
+
result.sdwO = unitsPercent(val);
|
|
1299
|
+
break;
|
|
1300
|
+
case 'angle':
|
|
1301
|
+
if (objName === 'gradientOverlay' || objName === 'patternFill') {
|
|
1302
|
+
result.Angl = unitsAngle(val);
|
|
1303
|
+
}
|
|
1304
|
+
else {
|
|
1305
|
+
result.lagl = unitsAngle(val);
|
|
1306
|
+
}
|
|
1307
|
+
break;
|
|
1308
|
+
case 'altitude':
|
|
1309
|
+
result.Lald = unitsAngle(val);
|
|
1310
|
+
break;
|
|
1311
|
+
case 'soften':
|
|
1312
|
+
result.Sftn = unitsValue(val, key);
|
|
1313
|
+
break;
|
|
1314
|
+
case 'strength':
|
|
1315
|
+
result.srgR = unitsPercent(val);
|
|
1316
|
+
break;
|
|
1317
|
+
case 'size':
|
|
1318
|
+
result.blur = unitsValue(val, key);
|
|
1319
|
+
break;
|
|
1320
|
+
case 'noise':
|
|
1321
|
+
result.Nose = unitsPercent(val);
|
|
1322
|
+
break;
|
|
1323
|
+
case 'range':
|
|
1324
|
+
result.Inpr = unitsPercent(val);
|
|
1325
|
+
break;
|
|
1326
|
+
case 'choke':
|
|
1327
|
+
result.Ckmt = unitsValue(val, key);
|
|
1328
|
+
break;
|
|
1329
|
+
case 'jitter':
|
|
1330
|
+
result.ShdN = unitsPercent(val);
|
|
1331
|
+
break;
|
|
1332
|
+
case 'distance':
|
|
1333
|
+
result.Dstn = unitsValue(val, key);
|
|
1334
|
+
break;
|
|
1335
|
+
case 'scale':
|
|
1336
|
+
result['Scl '] = unitsPercent(val);
|
|
1337
|
+
break;
|
|
1338
|
+
case 'pattern':
|
|
1339
|
+
result.Ptrn = { 'Nm ': val.name, Idnt: val.id };
|
|
1340
|
+
break;
|
|
1341
|
+
case 'phase':
|
|
1342
|
+
result.phase = { Hrzn: val.x, Vrtc: val.y };
|
|
1343
|
+
break;
|
|
1344
|
+
case 'offset':
|
|
1345
|
+
result.Ofst = { Hrzn: unitsPercent(val.x), Vrtc: unitsPercent(val.y) };
|
|
1346
|
+
break;
|
|
1347
|
+
case 'contour': {
|
|
1348
|
+
result[objName === 'satin' ? 'MpgS' : 'TrnS'] = {
|
|
1349
|
+
'Nm ': val.name,
|
|
1350
|
+
'Crv ': val.curve.map(p => ({ Hrzn: p.x, Vrtc: p.y })),
|
|
1351
|
+
};
|
|
1352
|
+
break;
|
|
1353
|
+
}
|
|
1354
|
+
case 'gradient':
|
|
1355
|
+
result.Grad = serializeGradient(val);
|
|
1356
|
+
break;
|
|
1357
|
+
case 'useTexture':
|
|
1358
|
+
case 'useShape':
|
|
1359
|
+
case 'layerConceals':
|
|
1360
|
+
case 'present':
|
|
1361
|
+
case 'showInDialog':
|
|
1362
|
+
case 'antialiasGloss':
|
|
1363
|
+
result[key] = val;
|
|
1364
|
+
break;
|
|
1365
|
+
default:
|
|
1366
|
+
reportErrors && console.log(`Invalid effect key: '${key}', value:`, val);
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
return result;
|
|
1370
|
+
}
|
|
1371
|
+
function parseGradient(grad) {
|
|
1372
|
+
if (grad.GrdF === 'GrdF.CstS') {
|
|
1373
|
+
const samples = grad.Intr || 4096;
|
|
1374
|
+
return {
|
|
1375
|
+
type: 'solid',
|
|
1376
|
+
name: grad['Nm '],
|
|
1377
|
+
smoothness: grad.Intr / 4096,
|
|
1378
|
+
colorStops: grad.Clrs.map(s => ({
|
|
1379
|
+
color: parseColor(s['Clr ']),
|
|
1380
|
+
location: s.Lctn / samples,
|
|
1381
|
+
midpoint: s.Mdpn / 100,
|
|
1382
|
+
})),
|
|
1383
|
+
opacityStops: grad.Trns.map(s => ({
|
|
1384
|
+
opacity: parsePercent(s.Opct),
|
|
1385
|
+
location: s.Lctn / samples,
|
|
1386
|
+
midpoint: s.Mdpn / 100,
|
|
1387
|
+
})),
|
|
1388
|
+
};
|
|
1389
|
+
}
|
|
1390
|
+
else {
|
|
1391
|
+
return {
|
|
1392
|
+
type: 'noise',
|
|
1393
|
+
name: grad['Nm '],
|
|
1394
|
+
roughness: grad.Smth / 4096,
|
|
1395
|
+
colorModel: ClrS.decode(grad.ClrS),
|
|
1396
|
+
randomSeed: grad.RndS,
|
|
1397
|
+
restrictColors: !!grad.VctC,
|
|
1398
|
+
addTransparency: !!grad.ShTr,
|
|
1399
|
+
min: grad['Mnm '].map(x => x / 100),
|
|
1400
|
+
max: grad['Mxm '].map(x => x / 100),
|
|
1401
|
+
};
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
function serializeGradient(grad) {
|
|
1405
|
+
if (grad.type === 'solid') {
|
|
1406
|
+
const samples = Math.round((grad.smoothness ?? 1) * 4096);
|
|
1407
|
+
return {
|
|
1408
|
+
'Nm ': grad.name || '',
|
|
1409
|
+
GrdF: 'GrdF.CstS',
|
|
1410
|
+
Intr: samples,
|
|
1411
|
+
Clrs: grad.colorStops.map(s => ({
|
|
1412
|
+
'Clr ': serializeColor(s.color),
|
|
1413
|
+
Type: 'Clry.UsrS',
|
|
1414
|
+
Lctn: Math.round(s.location * samples),
|
|
1415
|
+
Mdpn: Math.round((s.midpoint ?? 0.5) * 100),
|
|
1416
|
+
})),
|
|
1417
|
+
Trns: grad.opacityStops.map(s => ({
|
|
1418
|
+
Opct: unitsPercent(s.opacity),
|
|
1419
|
+
Lctn: Math.round(s.location * samples),
|
|
1420
|
+
Mdpn: Math.round((s.midpoint ?? 0.5) * 100),
|
|
1421
|
+
})),
|
|
1422
|
+
};
|
|
1423
|
+
}
|
|
1424
|
+
else {
|
|
1425
|
+
return {
|
|
1426
|
+
GrdF: 'GrdF.ClNs',
|
|
1427
|
+
'Nm ': grad.name || '',
|
|
1428
|
+
ShTr: !!grad.addTransparency,
|
|
1429
|
+
VctC: !!grad.restrictColors,
|
|
1430
|
+
ClrS: ClrS.encode(grad.colorModel),
|
|
1431
|
+
RndS: grad.randomSeed || 0,
|
|
1432
|
+
Smth: Math.round((grad.roughness ?? 1) * 4096),
|
|
1433
|
+
'Mnm ': (grad.min || [0, 0, 0, 0]).map(x => x * 100),
|
|
1434
|
+
'Mxm ': (grad.max || [1, 1, 1, 1]).map(x => x * 100),
|
|
1435
|
+
};
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
function parseGradientContent(descriptor) {
|
|
1439
|
+
const result = parseGradient(descriptor.Grad);
|
|
1440
|
+
result.style = GrdT.decode(descriptor.Type);
|
|
1441
|
+
if (descriptor.Dthr !== undefined)
|
|
1442
|
+
result.dither = descriptor.Dthr;
|
|
1443
|
+
if (descriptor.gradientsInterpolationMethod !== undefined)
|
|
1444
|
+
result.interpolationMethod = gradientInterpolationMethodType.decode(descriptor.gradientsInterpolationMethod);
|
|
1445
|
+
if (descriptor.Rvrs !== undefined)
|
|
1446
|
+
result.reverse = descriptor.Rvrs;
|
|
1447
|
+
if (descriptor.Angl !== undefined)
|
|
1448
|
+
result.angle = parseAngle(descriptor.Angl);
|
|
1449
|
+
if (descriptor['Scl '] !== undefined)
|
|
1450
|
+
result.scale = parsePercent(descriptor['Scl ']);
|
|
1451
|
+
if (descriptor.Algn !== undefined)
|
|
1452
|
+
result.align = descriptor.Algn;
|
|
1453
|
+
if (descriptor.Ofst !== undefined) {
|
|
1454
|
+
result.offset = {
|
|
1455
|
+
x: parsePercent(descriptor.Ofst.Hrzn),
|
|
1456
|
+
y: parsePercent(descriptor.Ofst.Vrtc)
|
|
1457
|
+
};
|
|
1458
|
+
}
|
|
1459
|
+
return result;
|
|
1460
|
+
}
|
|
1461
|
+
function parsePatternContent(descriptor) {
|
|
1462
|
+
const result = {
|
|
1463
|
+
name: descriptor.Ptrn['Nm '],
|
|
1464
|
+
id: descriptor.Ptrn.Idnt,
|
|
1465
|
+
};
|
|
1466
|
+
if (descriptor.Lnkd !== undefined)
|
|
1467
|
+
result.linked = descriptor.Lnkd;
|
|
1468
|
+
if (descriptor.phase !== undefined)
|
|
1469
|
+
result.phase = { x: descriptor.phase.Hrzn, y: descriptor.phase.Vrtc };
|
|
1470
|
+
return result;
|
|
1471
|
+
}
|
|
1472
|
+
export function parseVectorContent(descriptor) {
|
|
1473
|
+
if ('Grad' in descriptor) {
|
|
1474
|
+
return parseGradientContent(descriptor);
|
|
1475
|
+
}
|
|
1476
|
+
else if ('Ptrn' in descriptor) {
|
|
1477
|
+
return { type: 'pattern', ...parsePatternContent(descriptor) };
|
|
1478
|
+
}
|
|
1479
|
+
else if ('Clr ' in descriptor) {
|
|
1480
|
+
return { type: 'color', color: parseColor(descriptor['Clr ']) };
|
|
1481
|
+
}
|
|
1482
|
+
else {
|
|
1483
|
+
throw new Error('Invalid vector content');
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
function serializeGradientContent(content) {
|
|
1487
|
+
const result = {};
|
|
1488
|
+
if (content.dither !== undefined)
|
|
1489
|
+
result.Dthr = content.dither;
|
|
1490
|
+
if (content.interpolationMethod !== undefined)
|
|
1491
|
+
result.gradientsInterpolationMethod = gradientInterpolationMethodType.encode(content.interpolationMethod);
|
|
1492
|
+
if (content.reverse !== undefined)
|
|
1493
|
+
result.Rvrs = content.reverse;
|
|
1494
|
+
if (content.angle !== undefined)
|
|
1495
|
+
result.Angl = unitsAngle(content.angle);
|
|
1496
|
+
result.Type = GrdT.encode(content.style);
|
|
1497
|
+
if (content.align !== undefined)
|
|
1498
|
+
result.Algn = content.align;
|
|
1499
|
+
if (content.scale !== undefined)
|
|
1500
|
+
result['Scl '] = unitsPercent(content.scale);
|
|
1501
|
+
if (content.offset) {
|
|
1502
|
+
result.Ofst = {
|
|
1503
|
+
Hrzn: unitsPercent(content.offset.x),
|
|
1504
|
+
Vrtc: unitsPercent(content.offset.y),
|
|
1505
|
+
};
|
|
1506
|
+
}
|
|
1507
|
+
result.Grad = serializeGradient(content);
|
|
1508
|
+
return result;
|
|
1509
|
+
}
|
|
1510
|
+
function serializePatternContent(content) {
|
|
1511
|
+
const result = {
|
|
1512
|
+
Ptrn: {
|
|
1513
|
+
'Nm ': content.name || '',
|
|
1514
|
+
Idnt: content.id || '',
|
|
1515
|
+
}
|
|
1516
|
+
};
|
|
1517
|
+
if (content.linked !== undefined)
|
|
1518
|
+
result.Lnkd = !!content.linked;
|
|
1519
|
+
if (content.phase !== undefined)
|
|
1520
|
+
result.phase = { Hrzn: content.phase.x, Vrtc: content.phase.y };
|
|
1521
|
+
return result;
|
|
1522
|
+
}
|
|
1523
|
+
export function serializeVectorContent(content) {
|
|
1524
|
+
if (content.type === 'color') {
|
|
1525
|
+
return { key: 'SoCo', descriptor: { 'Clr ': serializeColor(content.color) } };
|
|
1526
|
+
}
|
|
1527
|
+
else if (content.type === 'pattern') {
|
|
1528
|
+
return { key: 'PtFl', descriptor: serializePatternContent(content) };
|
|
1529
|
+
}
|
|
1530
|
+
else {
|
|
1531
|
+
return { key: 'GdFl', descriptor: serializeGradientContent(content) };
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
export function parseColor(color) {
|
|
1535
|
+
if ('H ' in color) {
|
|
1536
|
+
return { h: parsePercentOrAngle(color['H ']), s: color.Strt, b: color.Brgh };
|
|
1537
|
+
}
|
|
1538
|
+
else if ('Rd ' in color) {
|
|
1539
|
+
return { r: color['Rd '], g: color['Grn '], b: color['Bl '] };
|
|
1540
|
+
}
|
|
1541
|
+
else if ('Cyn ' in color) {
|
|
1542
|
+
return { c: color['Cyn '], m: color.Mgnt, y: color['Ylw '], k: color.Blck };
|
|
1543
|
+
}
|
|
1544
|
+
else if ('Gry ' in color) {
|
|
1545
|
+
return { k: color['Gry '] };
|
|
1546
|
+
}
|
|
1547
|
+
else if ('Lmnc' in color) {
|
|
1548
|
+
return { l: color.Lmnc, a: color['A '], b: color['B '] };
|
|
1549
|
+
}
|
|
1550
|
+
else if ('redFloat' in color) {
|
|
1551
|
+
return { fr: color.redFloat, fg: color.greenFloat, fb: color.blueFloat };
|
|
1552
|
+
}
|
|
1553
|
+
else {
|
|
1554
|
+
throw new Error('Unsupported color descriptor');
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
export function serializeColor(color) {
|
|
1558
|
+
if (!color) {
|
|
1559
|
+
return { _name: '', _classID: 'RGBC', 'Rd ': 0, 'Grn ': 0, 'Bl ': 0 };
|
|
1560
|
+
}
|
|
1561
|
+
else if ('r' in color) {
|
|
1562
|
+
return { _name: '', _classID: 'RGBC', 'Rd ': color.r || 0, 'Grn ': color.g || 0, 'Bl ': color.b || 0 };
|
|
1563
|
+
}
|
|
1564
|
+
else if ('fr' in color) {
|
|
1565
|
+
return { _name: '', _classID: 'RGBC', redFloat: color.fr, greenFloat: color.fg, blueFloat: color.fb };
|
|
1566
|
+
}
|
|
1567
|
+
else if ('h' in color) {
|
|
1568
|
+
return { _name: '', _classID: 'HSBC', 'H ': unitsAngle(color.h * 360), Strt: color.s || 0, Brgh: color.b || 0 };
|
|
1569
|
+
}
|
|
1570
|
+
else if ('c' in color) {
|
|
1571
|
+
return { _name: '', _classID: 'CMYC', 'Cyn ': color.c || 0, Mgnt: color.m || 0, 'Ylw ': color.y || 0, Blck: color.k || 0 };
|
|
1572
|
+
}
|
|
1573
|
+
else if ('l' in color) {
|
|
1574
|
+
return { _name: '', _classID: 'LABC', Lmnc: color.l || 0, 'A ': color.a || 0, 'B ': color.b || 0 };
|
|
1575
|
+
}
|
|
1576
|
+
else if ('k' in color) {
|
|
1577
|
+
return { _name: '', _classID: 'GRYC', 'Gry ': color.k };
|
|
1578
|
+
}
|
|
1579
|
+
else {
|
|
1580
|
+
throw new Error('Invalid color value');
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
export function parseAngle(x) {
|
|
1584
|
+
if (x === undefined)
|
|
1585
|
+
return 0;
|
|
1586
|
+
if (x.units !== 'Angle')
|
|
1587
|
+
throw new Error(`Invalid units: ${x.units}`);
|
|
1588
|
+
return x.value;
|
|
1589
|
+
}
|
|
1590
|
+
export function parsePercent(x) {
|
|
1591
|
+
if (x === undefined)
|
|
1592
|
+
return 1;
|
|
1593
|
+
if (x.units !== 'Percent')
|
|
1594
|
+
throw new Error(`Invalid units: ${x.units}`);
|
|
1595
|
+
return x.value / 100;
|
|
1596
|
+
}
|
|
1597
|
+
export function parsePercentOrAngle(x) {
|
|
1598
|
+
if (x === undefined)
|
|
1599
|
+
return 1;
|
|
1600
|
+
if (x.units === 'Percent')
|
|
1601
|
+
return x.value / 100;
|
|
1602
|
+
if (x.units === 'Angle')
|
|
1603
|
+
return x.value / 360;
|
|
1604
|
+
throw new Error(`Invalid units: ${x.units}`);
|
|
1605
|
+
}
|
|
1606
|
+
export function parseUnits({ units, value }) {
|
|
1607
|
+
if (units !== 'Pixels' && units !== 'Millimeters' && units !== 'Points' && units !== 'None' &&
|
|
1608
|
+
units !== 'Picas' && units !== 'Inches' && units !== 'Centimeters' && units !== 'Density') {
|
|
1609
|
+
throw new Error(`Invalid units: ${JSON.stringify({ units, value })}`);
|
|
1610
|
+
}
|
|
1611
|
+
return { value, units };
|
|
1612
|
+
}
|
|
1613
|
+
export function parseUnitsOrNumber(value, units = 'Pixels') {
|
|
1614
|
+
if (typeof value === 'number')
|
|
1615
|
+
return { value, units };
|
|
1616
|
+
return parseUnits(value);
|
|
1617
|
+
}
|
|
1618
|
+
export function parseUnitsToNumber({ units, value }, expectedUnits) {
|
|
1619
|
+
if (units !== expectedUnits)
|
|
1620
|
+
throw new Error(`Invalid units: ${JSON.stringify({ units, value })}`);
|
|
1621
|
+
return value;
|
|
1622
|
+
}
|
|
1623
|
+
export function unitsAngle(value) {
|
|
1624
|
+
return { units: 'Angle', value: value || 0 };
|
|
1625
|
+
}
|
|
1626
|
+
export function unitsPercent(value) {
|
|
1627
|
+
return { units: 'Percent', value: Math.round((value || 0) * 100) };
|
|
1628
|
+
}
|
|
1629
|
+
export function unitsPercentF(value) {
|
|
1630
|
+
return { units: 'Percent', value: (value || 0) * 100 };
|
|
1631
|
+
}
|
|
1632
|
+
export function unitsValue(x, key) {
|
|
1633
|
+
if (x == null)
|
|
1634
|
+
return { units: 'Pixels', value: 0 };
|
|
1635
|
+
if (typeof x !== 'object')
|
|
1636
|
+
throw new Error(`Invalid value: ${JSON.stringify(x)} (key: ${key}) (should have value and units)`);
|
|
1637
|
+
const { units, value } = x;
|
|
1638
|
+
if (typeof value !== 'number')
|
|
1639
|
+
throw new Error(`Invalid value in ${JSON.stringify(x)} (key: ${key})`);
|
|
1640
|
+
if (units !== 'Pixels' && units !== 'Millimeters' && units !== 'Points' && units !== 'None' &&
|
|
1641
|
+
units !== 'Picas' && units !== 'Inches' && units !== 'Centimeters' && units !== 'Density') {
|
|
1642
|
+
throw new Error(`Invalid units in ${JSON.stringify(x)} (key: ${key})`);
|
|
1643
|
+
}
|
|
1644
|
+
return { units, value };
|
|
1645
|
+
}
|
|
1646
|
+
export function frac({ numerator, denominator }) {
|
|
1647
|
+
return { numerator, denominator };
|
|
1648
|
+
}
|
|
1649
|
+
export const textGridding = createEnum('textGridding', 'none', {
|
|
1650
|
+
none: 'None',
|
|
1651
|
+
round: 'Rnd ',
|
|
1652
|
+
});
|
|
1653
|
+
export const Ornt = createEnum('Ornt', 'horizontal', {
|
|
1654
|
+
horizontal: 'Hrzn',
|
|
1655
|
+
vertical: 'Vrtc',
|
|
1656
|
+
});
|
|
1657
|
+
export const Annt = createEnum('Annt', 'sharp', {
|
|
1658
|
+
none: 'Anno',
|
|
1659
|
+
sharp: 'antiAliasSharp',
|
|
1660
|
+
crisp: 'AnCr',
|
|
1661
|
+
strong: 'AnSt',
|
|
1662
|
+
smooth: 'AnSm',
|
|
1663
|
+
platform: 'antiAliasPlatformGray',
|
|
1664
|
+
platformLCD: 'antiAliasPlatformLCD',
|
|
1665
|
+
});
|
|
1666
|
+
export const warpStyle = createEnum('warpStyle', 'none', {
|
|
1667
|
+
none: 'warpNone',
|
|
1668
|
+
arc: 'warpArc',
|
|
1669
|
+
arcLower: 'warpArcLower',
|
|
1670
|
+
arcUpper: 'warpArcUpper',
|
|
1671
|
+
arch: 'warpArch',
|
|
1672
|
+
bulge: 'warpBulge',
|
|
1673
|
+
shellLower: 'warpShellLower',
|
|
1674
|
+
shellUpper: 'warpShellUpper',
|
|
1675
|
+
flag: 'warpFlag',
|
|
1676
|
+
wave: 'warpWave',
|
|
1677
|
+
fish: 'warpFish',
|
|
1678
|
+
rise: 'warpRise',
|
|
1679
|
+
fisheye: 'warpFisheye',
|
|
1680
|
+
inflate: 'warpInflate',
|
|
1681
|
+
squeeze: 'warpSqueeze',
|
|
1682
|
+
twist: 'warpTwist',
|
|
1683
|
+
cylinder: 'warpCylinder',
|
|
1684
|
+
custom: 'warpCustom',
|
|
1685
|
+
});
|
|
1686
|
+
export const BlnM = createEnum('BlnM', 'normal', {
|
|
1687
|
+
'normal': 'Nrml',
|
|
1688
|
+
'dissolve': 'Dslv',
|
|
1689
|
+
'darken': 'Drkn',
|
|
1690
|
+
'multiply': 'Mltp',
|
|
1691
|
+
'color burn': 'CBrn',
|
|
1692
|
+
'linear burn': 'linearBurn',
|
|
1693
|
+
'darker color': 'darkerColor',
|
|
1694
|
+
'lighten': 'Lghn',
|
|
1695
|
+
'screen': 'Scrn',
|
|
1696
|
+
'color dodge': 'CDdg',
|
|
1697
|
+
'linear dodge': 'linearDodge',
|
|
1698
|
+
'lighter color': 'lighterColor',
|
|
1699
|
+
'overlay': 'Ovrl',
|
|
1700
|
+
'soft light': 'SftL',
|
|
1701
|
+
'hard light': 'HrdL',
|
|
1702
|
+
'vivid light': 'vividLight',
|
|
1703
|
+
'linear light': 'linearLight',
|
|
1704
|
+
'pin light': 'pinLight',
|
|
1705
|
+
'hard mix': 'hardMix',
|
|
1706
|
+
'difference': 'Dfrn',
|
|
1707
|
+
'exclusion': 'Xclu',
|
|
1708
|
+
'subtract': 'blendSubtraction',
|
|
1709
|
+
'divide': 'blendDivide',
|
|
1710
|
+
'hue': 'H ',
|
|
1711
|
+
'saturation': 'Strt',
|
|
1712
|
+
'color': 'Clr ',
|
|
1713
|
+
'luminosity': 'Lmns',
|
|
1714
|
+
// used in ABR
|
|
1715
|
+
'linear height': 'linearHeight',
|
|
1716
|
+
'height': 'Hght',
|
|
1717
|
+
'subtraction': 'Sbtr', // 2nd version of subtract ?
|
|
1718
|
+
});
|
|
1719
|
+
export const BESl = createEnum('BESl', 'inner bevel', {
|
|
1720
|
+
'inner bevel': 'InrB',
|
|
1721
|
+
'outer bevel': 'OtrB',
|
|
1722
|
+
'emboss': 'Embs',
|
|
1723
|
+
'pillow emboss': 'PlEb',
|
|
1724
|
+
'stroke emboss': 'strokeEmboss',
|
|
1725
|
+
});
|
|
1726
|
+
export const bvlT = createEnum('bvlT', 'smooth', {
|
|
1727
|
+
'smooth': 'SfBL',
|
|
1728
|
+
'chisel hard': 'PrBL',
|
|
1729
|
+
'chisel soft': 'Slmt',
|
|
1730
|
+
});
|
|
1731
|
+
export const BESs = createEnum('BESs', 'up', {
|
|
1732
|
+
up: 'In ',
|
|
1733
|
+
down: 'Out ',
|
|
1734
|
+
});
|
|
1735
|
+
export const BETE = createEnum('BETE', 'softer', {
|
|
1736
|
+
softer: 'SfBL',
|
|
1737
|
+
precise: 'PrBL',
|
|
1738
|
+
});
|
|
1739
|
+
export const IGSr = createEnum('IGSr', 'edge', {
|
|
1740
|
+
edge: 'SrcE',
|
|
1741
|
+
center: 'SrcC',
|
|
1742
|
+
});
|
|
1743
|
+
export const GrdT = createEnum('GrdT', 'linear', {
|
|
1744
|
+
linear: 'Lnr ',
|
|
1745
|
+
radial: 'Rdl ',
|
|
1746
|
+
angle: 'Angl',
|
|
1747
|
+
reflected: 'Rflc',
|
|
1748
|
+
diamond: 'Dmnd',
|
|
1749
|
+
});
|
|
1750
|
+
export const animInterpStyleEnum = createEnum('animInterpStyle', 'linear', {
|
|
1751
|
+
linear: 'Lnr ',
|
|
1752
|
+
hold: 'hold',
|
|
1753
|
+
});
|
|
1754
|
+
export const stdTrackID = createEnum('stdTrackID', 'opacity', {
|
|
1755
|
+
opacity: 'opacityTrack',
|
|
1756
|
+
style: 'styleTrack',
|
|
1757
|
+
sheetTransform: 'sheetTransformTrack',
|
|
1758
|
+
sheetPosition: 'sheetPositionTrack',
|
|
1759
|
+
globalLighting: 'globalLightingTrack',
|
|
1760
|
+
});
|
|
1761
|
+
export const gradientInterpolationMethodType = createEnum('gradientInterpolationMethodType', 'perceptual', {
|
|
1762
|
+
perceptual: 'Perc',
|
|
1763
|
+
linear: 'Lnr ',
|
|
1764
|
+
classic: 'Gcls',
|
|
1765
|
+
smooth: 'Smoo',
|
|
1766
|
+
// TODO: stripes
|
|
1767
|
+
});
|
|
1768
|
+
export const ClrS = createEnum('ClrS', 'rgb', {
|
|
1769
|
+
rgb: 'RGBC',
|
|
1770
|
+
hsb: 'HSBl',
|
|
1771
|
+
lab: 'LbCl',
|
|
1772
|
+
hsl: 'HSLC',
|
|
1773
|
+
});
|
|
1774
|
+
export const FStl = createEnum('FStl', 'outside', {
|
|
1775
|
+
outside: 'OutF',
|
|
1776
|
+
center: 'CtrF',
|
|
1777
|
+
inside: 'InsF'
|
|
1778
|
+
});
|
|
1779
|
+
export const FrFl = createEnum('FrFl', 'color', {
|
|
1780
|
+
color: 'SClr',
|
|
1781
|
+
gradient: 'GrFl',
|
|
1782
|
+
pattern: 'Ptrn',
|
|
1783
|
+
});
|
|
1784
|
+
export const ESliceType = createEnum('ESliceType', 'image', {
|
|
1785
|
+
image: 'Img ',
|
|
1786
|
+
noImage: 'noImage',
|
|
1787
|
+
});
|
|
1788
|
+
export const ESliceHorzAlign = createEnum('ESliceHorzAlign', 'default', {
|
|
1789
|
+
default: 'default',
|
|
1790
|
+
});
|
|
1791
|
+
export const ESliceVertAlign = createEnum('ESliceVertAlign', 'default', {
|
|
1792
|
+
default: 'default',
|
|
1793
|
+
});
|
|
1794
|
+
export const ESliceOrigin = createEnum('ESliceOrigin', 'userGenerated', {
|
|
1795
|
+
userGenerated: 'userGenerated',
|
|
1796
|
+
autoGenerated: 'autoGenerated',
|
|
1797
|
+
layer: 'layer',
|
|
1798
|
+
});
|
|
1799
|
+
export const ESliceBGColorType = createEnum('ESliceBGColorType', 'none', {
|
|
1800
|
+
none: 'None',
|
|
1801
|
+
matte: 'matte',
|
|
1802
|
+
color: 'Clr ',
|
|
1803
|
+
});
|
|
1804
|
+
export const strokeStyleLineCapType = createEnum('strokeStyleLineCapType', 'butt', {
|
|
1805
|
+
butt: 'strokeStyleButtCap',
|
|
1806
|
+
round: 'strokeStyleRoundCap',
|
|
1807
|
+
square: 'strokeStyleSquareCap',
|
|
1808
|
+
});
|
|
1809
|
+
export const strokeStyleLineJoinType = createEnum('strokeStyleLineJoinType', 'miter', {
|
|
1810
|
+
miter: 'strokeStyleMiterJoin',
|
|
1811
|
+
round: 'strokeStyleRoundJoin',
|
|
1812
|
+
bevel: 'strokeStyleBevelJoin',
|
|
1813
|
+
});
|
|
1814
|
+
export const strokeStyleLineAlignment = createEnum('strokeStyleLineAlignment', 'inside', {
|
|
1815
|
+
inside: 'strokeStyleAlignInside',
|
|
1816
|
+
center: 'strokeStyleAlignCenter',
|
|
1817
|
+
outside: 'strokeStyleAlignOutside',
|
|
1818
|
+
});
|
|
1819
|
+
export const BlrM = createEnum('BlrM', 'ispinmage', {
|
|
1820
|
+
spin: 'Spn ',
|
|
1821
|
+
zoom: 'Zm ',
|
|
1822
|
+
});
|
|
1823
|
+
export const BlrQ = createEnum('BlrQ', 'good', {
|
|
1824
|
+
draft: 'Drft',
|
|
1825
|
+
good: 'Gd ',
|
|
1826
|
+
best: 'Bst ',
|
|
1827
|
+
});
|
|
1828
|
+
export const SmBM = createEnum('SmBM', 'normal', {
|
|
1829
|
+
normal: 'SBMN',
|
|
1830
|
+
'edge only': 'SBME',
|
|
1831
|
+
'overlay edge': 'SBMO',
|
|
1832
|
+
});
|
|
1833
|
+
export const SmBQ = createEnum('SmBQ', 'medium', {
|
|
1834
|
+
low: 'SBQL',
|
|
1835
|
+
medium: 'SBQM',
|
|
1836
|
+
high: 'SBQH',
|
|
1837
|
+
});
|
|
1838
|
+
export const DspM = createEnum('DspM', 'stretch to fit', {
|
|
1839
|
+
'stretch to fit': 'StrF',
|
|
1840
|
+
'tile': 'Tile',
|
|
1841
|
+
});
|
|
1842
|
+
export const UndA = createEnum('UndA', 'repeat edge pixels', {
|
|
1843
|
+
'wrap around': 'WrpA',
|
|
1844
|
+
'repeat edge pixels': 'RptE',
|
|
1845
|
+
});
|
|
1846
|
+
export const Cnvr = createEnum('Cnvr', 'rectangular to polar', {
|
|
1847
|
+
'rectangular to polar': 'RctP',
|
|
1848
|
+
'polar to rectangular': 'PlrR',
|
|
1849
|
+
});
|
|
1850
|
+
export const RplS = createEnum('RplS', 'medium', {
|
|
1851
|
+
small: 'Sml ',
|
|
1852
|
+
medium: 'Mdm ',
|
|
1853
|
+
large: 'Lrg ',
|
|
1854
|
+
});
|
|
1855
|
+
export const SphM = createEnum('SphM', 'normal', {
|
|
1856
|
+
'normal': 'Nrml',
|
|
1857
|
+
'horizontal only': 'HrzO',
|
|
1858
|
+
'vertical only': 'VrtO',
|
|
1859
|
+
});
|
|
1860
|
+
export const Wvtp = createEnum('Wvtp', 'sine', {
|
|
1861
|
+
sine: 'WvSn',
|
|
1862
|
+
triangle: 'WvTr',
|
|
1863
|
+
square: 'WvSq',
|
|
1864
|
+
});
|
|
1865
|
+
export const ZZTy = createEnum('ZZTy', 'pond ripples', {
|
|
1866
|
+
'around center': 'ArnC',
|
|
1867
|
+
'out from center': 'OtFr',
|
|
1868
|
+
'pond ripples': 'PndR',
|
|
1869
|
+
});
|
|
1870
|
+
export const Dstr = createEnum('Dstr', 'uniform', {
|
|
1871
|
+
uniform: 'Unfr',
|
|
1872
|
+
gaussian: 'Gsn ',
|
|
1873
|
+
});
|
|
1874
|
+
export const Chnl = createEnum('Chnl', 'composite', {
|
|
1875
|
+
red: 'Rd ',
|
|
1876
|
+
green: 'Grn ',
|
|
1877
|
+
blue: 'Bl ',
|
|
1878
|
+
composite: 'Cmps',
|
|
1879
|
+
});
|
|
1880
|
+
export const MztT = createEnum('MztT', 'fine dots', {
|
|
1881
|
+
'fine dots': 'FnDt',
|
|
1882
|
+
'medium dots': 'MdmD',
|
|
1883
|
+
'grainy dots': 'GrnD',
|
|
1884
|
+
'coarse dots': 'CrsD',
|
|
1885
|
+
'short lines': 'ShrL',
|
|
1886
|
+
'medium lines': 'MdmL',
|
|
1887
|
+
'long lines': 'LngL',
|
|
1888
|
+
'short strokes': 'ShSt',
|
|
1889
|
+
'medium strokes': 'MdmS',
|
|
1890
|
+
'long strokes': 'LngS',
|
|
1891
|
+
});
|
|
1892
|
+
export const Lns = createEnum('Lns ', '50-300mm zoom', {
|
|
1893
|
+
'50-300mm zoom': 'Zm ',
|
|
1894
|
+
'32mm prime': 'Nkn ',
|
|
1895
|
+
'105mm prime': 'Nkn1',
|
|
1896
|
+
'movie prime': 'PnVs',
|
|
1897
|
+
});
|
|
1898
|
+
export const blurType = createEnum('blurType', 'gaussian blur', {
|
|
1899
|
+
'gaussian blur': 'GsnB',
|
|
1900
|
+
'lens blur': 'lensBlur',
|
|
1901
|
+
'motion blur': 'MtnB',
|
|
1902
|
+
});
|
|
1903
|
+
export const DfsM = createEnum('DfsM', 'normal', {
|
|
1904
|
+
'normal': 'Nrml',
|
|
1905
|
+
'darken only': 'DrkO',
|
|
1906
|
+
'lighten only': 'LghO',
|
|
1907
|
+
'anisotropic': 'anisotropic',
|
|
1908
|
+
});
|
|
1909
|
+
export const ExtT = createEnum('ExtT', 'blocks', {
|
|
1910
|
+
blocks: 'Blks',
|
|
1911
|
+
pyramids: 'Pyrm',
|
|
1912
|
+
});
|
|
1913
|
+
export const ExtR = createEnum('ExtR', 'random', {
|
|
1914
|
+
random: 'Rndm',
|
|
1915
|
+
'level-based': 'LvlB',
|
|
1916
|
+
});
|
|
1917
|
+
export const FlCl = createEnum('FlCl', 'background color', {
|
|
1918
|
+
'background color': 'FlBc',
|
|
1919
|
+
'foreground color': 'FlFr',
|
|
1920
|
+
'inverse image': 'FlIn',
|
|
1921
|
+
'unaltered image': 'FlSm',
|
|
1922
|
+
});
|
|
1923
|
+
export const CntE = createEnum('CntE', 'upper', {
|
|
1924
|
+
lower: 'Lwr ',
|
|
1925
|
+
upper: 'Upr ',
|
|
1926
|
+
});
|
|
1927
|
+
export const WndM = createEnum('WndM', 'wind', {
|
|
1928
|
+
wind: 'Wnd ',
|
|
1929
|
+
blast: 'Blst',
|
|
1930
|
+
stagger: 'Stgr',
|
|
1931
|
+
});
|
|
1932
|
+
export const Drct = createEnum('Drct', 'from the right', {
|
|
1933
|
+
left: 'Left',
|
|
1934
|
+
right: 'Rght',
|
|
1935
|
+
});
|
|
1936
|
+
export const IntE = createEnum('IntE', 'odd lines', {
|
|
1937
|
+
'odd lines': 'ElmO',
|
|
1938
|
+
'even lines': 'ElmE',
|
|
1939
|
+
});
|
|
1940
|
+
export const IntC = createEnum('IntC', 'interpolation', {
|
|
1941
|
+
duplication: 'CrtD',
|
|
1942
|
+
interpolation: 'CrtI',
|
|
1943
|
+
});
|
|
1944
|
+
export const FlMd = createEnum('FlMd', 'wrap around', {
|
|
1945
|
+
'set to transparent': 'Bckg',
|
|
1946
|
+
'repeat edge pixels': 'Rpt ',
|
|
1947
|
+
'wrap around': 'Wrp ',
|
|
1948
|
+
});
|
|
1949
|
+
export const prjM = createEnum('prjM', 'fisheye', {
|
|
1950
|
+
'fisheye': 'fisP',
|
|
1951
|
+
'perspective': 'perP',
|
|
1952
|
+
'auto': 'auto',
|
|
1953
|
+
'full spherical': 'fusP',
|
|
1954
|
+
});
|
|
1955
|
+
export const presetKindType = createEnum('presetKindType', 'presetKindCustom', {
|
|
1956
|
+
custom: 'presetKindCustom',
|
|
1957
|
+
default: 'presetKindDefault',
|
|
1958
|
+
});
|