mipmip
7/11/2013 - 12:32 PM

indesign color functions

indesign color functions

class  CInddexport
  	require 'rubygems'
		require 'appscript' 
		include Appscript
		
	def initialize(filePath, outputPath, test = false)
		@filePath = filePath 
		@outputPath = outputPath 
		@idApp = (test == true) ? app('Adobe InDesign CS3') : app('InDesignServer')
	end
	
	# public functions	
	def openDoc
		@idDoc = @idApp.open(MacTypes::FileURL.path(@filePath).hfs_path)
	end
	
	def closeDoc
		@idDoc.close(:saving => :no)
	end
	
	def getDocArray
		document = Hash.new
		
		breakGroups
		
		#FIXME add information about books, spreads, position pages on spread, etc to array
		document[:layerGroups] = getLayerGroups()
		#document[:preview] = 'test'
		
		return document
	end
	
	def getPreview
		docArray = getDocArray

		return docArray[:preview]
	end
	
	# private functions
	
	def getLayerGroups
		layerGroups = Hash.new{|hash, key| hash[key] = Array.new}
		layers = getLayers
		lastLayer = ''
		
		layers.each do |layer|
			layerId = layer[:name].to_s[0, 2]
			if(lastLayer == layerId || layerId == 'xx' || layerId == 'XX') 
				@idApp.set(@idDoc.layers[its.id_.eq(layer[:layerID])].visible, :to => false)
			else
				@idApp.set(@idDoc.layers[its.id_.eq(layer[:layerID])].visible, :to => true)
			end
			lastLayer = layerId
			layerGroups[layerId.to_i] << layer
		end
		
		return layerGroups
	end
	
	def getCurrentLayerGroup(currLayer)
		layerCount = 0
		
		@idDoc.layers.get.each do |layer|
			if(layer.name.get.to_s[0, 2] == currLayer) then  layerCount += 1 end
		end

		return layerCount
	end
	
	def getLayers
		layerArray = Array.new
		i = 0
		
		@idDoc.layers.get.each do |layer|
			layerProps = Hash.new{|hash, key| hash[key] = Array.new}
			
			layerProps[:layerID] = layer.id_.get
			layerProps[:name] = layer.name.get.to_s
			layerProps[:zindex] = @idDoc.layers.get.length-i
			layerProps[:layerChilds] << getChilds(layer)
			
			layerArray << layerProps
			
			i = i+1
		end
		puts MacTypes::FileURL.path(@outputPath+'sourcedoc.eps').hfs_path
		@idApp.export(@idDoc, :format => :EPS_type, :to => MacTypes::FileURL.path(@outputPath+'sourcedoc.eps').hfs_path, :showing_options => false)
	
		return layerArray
	end
	
	def getChilds(layer)
		childs = Array.new
		#FIXME add support for tables
		
		layer.page_items.get.each do |child|			
			#FIXME add support for ovals, polygons, and graphic lines
			
			childProps = Hash.new{|hash, key| hash[key] = Array.new}
			geom =  child.geometric_bounds.get
			
			childProps[:objectID] = child.id_.get
			childProps[:name] = child.get.to_s
			childProps[:x] = geom[1]
			childProps[:y] = geom[0]
			childProps[:w] = geom[3].to_f-geom[1].to_f
			childProps[:h] = geom[2].to_f-geom[0].to_f
			childProps[:label] = child.label.get.to_s
			childProps[:isStatic] = getStatic(child.label.get.to_s)
			childProps[:type] = getType(child)
			childProps[:inGroup] = (getCurrentLayerGroup(layer.name.get.to_s[0, 2]) > 1) ? true : false
			childProps[:group] = layer.name.get.to_s[0, 2]
			childProps[:content] = 'content'
			#FIXME indesign/appscript gives very 'special' output in case of Pantone colors - ignore for now
			childProps[:background] = 'unknown'  #getBackGroundColor(child)  
			childs << childProps 
		end
		
		return childs
		
	end
	
	def breakGroups
		groups = @idDoc.groups.get
		
		groups.each do |group|
			group.ungroup
		end
		
		if (@idDoc.groups.get.length > 0) then breakGroups	end	
	end
	
	def getStatic(label)
		# pTextInput & pMergeField = plain text, rTextInput & rMergeField = rich text, mergeTextField need to have a label after the underscore
		types = ['textInput', 'imageInput', 'colorInput', 'mergeTextField_', 'mergeImgField'] 
		isStatic = true
		
		types.each do |type|
			if type.to_s == label || type.to_s[0,15] == label
				isStatic = false
				break 
			else
				isStatic = true
			end
		end
		
		return isStatic
	end
	
	def getType(child)
		#FIXME add support for ovals, polygons, and graphic lines
		if(child.class_.get.to_s == 'rectangle')
			#FIXME add support for multiple images in rectangles
			type = (child.graphics.get.length == 1) ? child.graphics.class_.get.to_s : 'rectangle'
		elsif(child.class_.get.to_s == 'text_frame')
			type = 'text'
		else 
			type = 'undefined'
		end
	
		return type
	end
	
	def getBackGroundColor(child)
		#FIXME possibly Indesign supports multiple color spaces, for now, presume it's always CMYK
			if(child.fill_color.class_.get.to_s == 'color')
				
				puts child.fill_color.space.get
				return getCMYKtoHeX(child.fill_color.color_value.get.to_s)
			else
				return 'none'
			end
	end
	
	def getCMYKtoHeX(cmyk)
		#FIXME somehow this seems not as accurate as the ActionScript equivalent
		colorArr = cmyk.split('.')
		puts cmyk
		c = stripLeadingZero(colorArr[0]).to_f/100
		m = stripLeadingZero(colorArr[1]).to_f/100
		y = stripLeadingZero(colorArr[2]).to_f/100
		k = stripLeadingZero(colorArr[3]).to_f/100
		
		#the adobe approach
		ra = (1.0 - min(1.0, c + k))*255
		ga = (1.0 - min(1.0, m + k))*255
		ba = (1.0 - min(1.0, y + k))*255
		
		#a custom interpretation
		rc = (1.0 - (c * (1.0 - k) + k))*255
		gc = (1.0 - (m * (1.0 - k) + k))*255
		bc = (1.0 - (y * (1.0 - k) + k))*255
		
		#another approach
		ro = ((1.0 - k + c)*(k - 1.0))*255
		go = ((1.0 - k + m)*(k - 1.0))*255
		bo = ((1.0 - k + y)*(k - 1.0))*255
		
		#return '#' + toHex(r) + toHex(g) + toHex(b)
	end
	
	def stripLeadingZero(string)
		if (string[0,1] == '0' && string.length > 1) 
			return stripLeadingZero(string[1..-1])
		else
			return string
		end	
	end
	
	def toHex(color)
		if(color < 0) then color = 0 end
		return color.round.to_s(16)
	end
	

	def min(a,b)
		return a <= b ? a : b
	end
end

class CDebug
	require 'YAML'

	def debugArray(arr)
		puts YAML::dump(arr)
	end
end

class XMLParser
	require 'XmlSimple'
	
	def initialize
    end
	
	def convertXML(arr)
		return	XmlSimple.xml_out(arr)
	end
end 
	

indd = CInddexport.new('/Users/server/Desktop/sourcedoc.indd','/Users/server/Desktop/test/', true)
debug = CDebug.new()
xml = XMLParser.new()

indd.openDoc
#indd.getDocArray
debug.debugArray(indd.getDocArray)
#debug.debugArray(xml.convertXML(indd.getDocArray))
#indd.closeDoc