psddescriptor.coffee | |
|---|---|
class PSDDescriptor
constructor: (@file) -> | |
| Main entry point for parsing a descriptor | parse: ->
Log.debug "Parsing descriptor..."
data = {}
data.class = @parseClass()
numItems = @file.readInt()
Log.debug "Descriptor contains #{numItems} items"
for i in [0...numItems]
item = @parseKeyItem()
data[item.id] = item.value
data
parseID: ->
len = @file.readInt()
if len is 0
@file.readInt()
else
@file.readString(len)
parseClass: ->
name: @file.readUnicodeString()
id: @parseID()
parseKeyItem: ->
id: @parseID()
value: @parseItem()
parseItem: ->
type = @file.readString(4)
Log.debug "Found descriptor type: #{type}"
value = switch type
when 'bool' then @parseBoolean()
when 'type', 'GlbC' then @parseClass()
when 'Objc', 'GlbO' then @parse()
when 'doub' then @parseDouble()
when 'enum' then @parseEnum()
when 'alis' then @parseAlias()
when 'Pth ' then @parseFilePath()
when 'long' then @parseInteger()
when 'comp' then @parseLargeInteger()
when 'VlLs' then @parseList()
when 'ObAr' then @parseObjectArray()
when 'tdta' then @parseRawData()
when 'obj ' then @parseReference()
when 'TEXT' then @file.readUnicodeString()
when 'UntF' then @parseUnitDouble()
value
parseBoolean: -> @file.readBoolean()
parseDouble: -> @file.readDouble()
parseInteger: -> @file.readInt()
parseLargeInteger: -> @file.readLongLong()
parseIdentifier: -> @file.readInt()
parseIndex: -> @file.readInt()
parseOffset: -> @file.readInt()
parseProperty: -> @parseID() |
| We discard the first ID because it's the same as the key parsed from the Key/Item. | parseEnum: ->
@parseID()
@parseID() |
| File Alias This data is opaque and unique to Mac OS | parseAlias: ->
len = @file.readInt()
@file.read(len)
parseFilePath: ->
len = @file.readInt() |
| Little-endian?!? | [
sig,
pathSize,
numChars
] = @file.readf("<4s2i")
charBytes = numChars * 2
path = @file.read(charBytes)
sig: sig, path: path
parseList: ->
numItems = @file.readInt()
items = []
items.push @parseItem() for i in [0...numItems]
items
parseObjectArray: ->
numItems = @file.readInt()
klass = @parseClass()
itemsInObj = @file.readInt()
obj = []
for i in [0...numItems]
item = []
for j in [0...itemsInObj]
item.push @parseObjectArray()
obj.push item
obj
parseObjectArray: ->
id = @parseID()
type = @file.readString(4)
unitID = @file.readString()
num = @file.readInt()
values = []
values.push @file.readDouble() for i in [0...num]
values
parseRawData: ->
len = @file.readInt()
@file.read(len)
parseReference: ->
form = @file.readString(4)
klass = @parseClass()
value = switch form
when "Clss" then null
when "Enmr" then @parseEnum()
when "Idnt" then @parseIdentifier()
when "indx" then @parseIndex()
when "name" then @file.readUnicodeString()
when "rele" then @parseOffset()
when "prop" then @parseProperty()
value
parseUnitDouble: ->
unitID = @file.parseString(4)
unit = switch unitID
when "#Ang" then "Angle"
when "#Rsl" then "Density"
when "#Rlt" then "Distance"
when "#Nne" then "None"
when "#Prc" then "Percent"
when "#Pxl" then "Pixels"
when "#Mlm" then "Millimeters"
when "#Pnt" then "Points"
value = @file.readDouble()
id: unitID, unit: unit, value: value
|