class Inkmake::InkFile
Constants
- AREA_NAME_RE
@name
- AREA_SPEC_RE
@x:y:w:h
- DEST_RE
(prefix)(suffix)
- DPI_RE
180dpi
- DefaultVariants
- EXT_RE
ext to format, supported inkscape output formats
- FORMAT_RE
supported inkscape output formats
- RES_RE
123x123, 12.3cm*12.3cm
- ROTATE_RE
right, left, upsidedown
- Rotations
- SCALE_RE
*123, *1.23
- SHOWHIDE_RE
show/hide layer or id, “+Layer 1”, +#id, -*
- SVG_RE
test.svg, test.SVG
Attributes
out_path[R]
svg_path[R]
Public Class Methods
new(file, opts)
click to toggle source
# File lib/inkmake.rb, line 432 def initialize(file, opts) @file = file @images = [] @force = opts[:force] svg_path = nil out_path = nil File.read(file).lines.each_with_index do |line, index| line.strip! next if line.empty? or line.start_with? "#" begin case line when /^svg:(.*)/i then svg_path = File.expand_path($1.strip, File.dirname(file)) when /^out:(.*)/i then out_path = File.expand_path($1.strip, File.dirname(file)) else @images << InkImage.new(self, parse_line(line)) end rescue SyntaxError => e puts "#{file}:#{index+1}: #{e.message}" exit end end # order is: argument, config in inkfile, inkfile directory @svg_path = opts[:svg_path] || svg_path || File.dirname(file) @out_path = opts[:out_path] || out_path || File.dirname(file) end
Public Instance Methods
parse_line(line)
click to toggle source
# File lib/inkmake.rb, line 470 def parse_line(line) cols = nil begin cols = parse_split_line(line) rescue CSV::MalformedCSVError => e raise SyntaxError, e.message end raise SyntaxError, "Invalid number of columns" if cols.count < 1 if not DEST_RE.match(cols[0]) raise SyntaxError, "Invalid destination format \"#{cols[0]}\"" end opts = {} opts[:prefix] = $1 variants = $2 opts[:suffix] = $3 opts[:format] = $1.downcase if EXT_RE.match(opts[:prefix] + opts[:suffix]) cols[1..-1].each do |col| case col when RES_RE then opts[:res] = InkscapeResolution.new($1, $2, "px") when SVG_RE then opts[:svg] = col when AREA_SPEC_RE then opts[:area] = [$1.to_f, $2.to_f, $3.to_f, $4.to_f] when AREA_NAME_RE then opts[:area] = $1 when /^drawing$/ then opts[:area] = :drawing when FORMAT_RE then opts[:format] = $1.downcase when ROTATE_RE then opts[:rotate] = Rotations[$1] when SCALE_RE then opts[:scale] = $1.to_f when DPI_RE then opts[:dpi] = $1.to_f when SHOWHIDE_RE op = $1 == "+" ? :show : :hide if $2.start_with? "#" type = :id name= $2[1..-1] else type = :layer name = $2 == "*" ? :all : $2 end (opts[:showhide] ||= []).push({:op => op, :type => type, :name => name}) else raise SyntaxError, "Unknown column \"#{col}\"" end end if not opts[:format] raise SyntaxError, "Unknown or no output format could be determined" end variants = (variants.split("|") if variants) || [] opts[:variants] = variants.collect do |variant| name, options = variant.split("=", 2) if options options = Hash[ options.split(",").map do |option| case option when ROTATE_RE then [:rotate, Rotations[$1]] when RES_RE then [:res, InkscapeResolution.new($1, $2, "px")] when SCALE_RE then [:scale, $1.to_f] when DPI_RE then [:dpi, $1.to_f] else raise SyntaxError, "Invalid variant option \"#{option}\"" end end ] else options = DefaultVariants[name] raise SyntaxError, "Invalid default variant \"#{name}\"" if not options end [name, options] end opts end
parse_split_line(line)
click to toggle source
# File lib/inkmake.rb, line 460 def parse_split_line(line) # changed CSV API in ruby 1.9 # - [nil] to remove empty fields if RUBY_VERSION.start_with? "1.8" CSV::parse_line(line, fs = " ") - [nil] else CSV::parse_line(line, **{:col_sep => " "}) - [nil] end end
process()
click to toggle source
# File lib/inkmake.rb, line 588 def process variants = variants_to_generate if variants.empty? return false end idfilemap = {} InkscapeRemote.new do |inkscape| variants.each do |variant| if not File.exists? variant.image.svg_path raise ProcessError, "Source SVG file #{variant.image.svg_path} does not exist" end out_res = nil # order: 200x200, @id/area, svg res if variant.image.res out_res = variant.image.res elsif variant.image.area == :drawing res = inkscape.drawing_area(variant.image.svg_path) out_res = InkscapeResolution.new(res[2], res[3], "uu") elsif variant.image.area if variant.image.area.kind_of? String if not idfilemap.has_key? variant.image.svg_path idfilemap[variant.image.svg_path] = inkscape.ids(variant.image.svg_path) end if not idfilemap[variant.image.svg_path].has_key? variant.image.area raise ProcessError, "Unknown id \"#{variant.image.area}\" in file #{variant.image.svg_path} when exporting #{variant.out_path}" end res = idfilemap[variant.image.svg_path][variant.image.area] out_res = InkscapeResolution.new(res[2], res[3], "uu") else a = variant.image.area # x0:y0:x1:y1 out_res = InkscapeResolution.new(a[2]-a[0], a[3]-a[1], "uu") end else out_res = variant.image.svg_res end scale = variant.options[:scale] if scale out_res = out_res.scale(scale) end out_res = variant.options[:res] if variant.options[:res] rotate = (variant.image.format == "png" and variant.options[:rotate]) FileUtils.mkdir_p File.dirname(variant.out_path) svg_path = variant.image.svg_path if variant.image.showhide svg_path = variant.image.svg_showhide_file.path end res = inkscape.export({ :svg_path => svg_path, :out_path => variant.out_path, :res => out_res, :dpi => variant.options[:dpi], :format => variant.image.format, :area => variant.image.area, :rotate_scale_hack => rotate }) if rotate tmp, width, height = temp_rotate_svg(variant.out_path, rotate, res[0].to_i, res[1].to_i) res = inkscape.export({ :svg_path => tmp.path, :out_path => variant.out_path, :res => InkscapeResolution.new(width / 2, height / 2, "px"), :format => variant.image.format }) tmp.close! end rel_path = Pathname.new(variant.out_path).relative_path_from(Pathname.new(Dir.pwd)) if variant.image.format == "png" puts "#{rel_path} #{res[0]}x#{res[1]}" else puts rel_path end end end return true end
temp_rotate_svg(path, degrees, width, height)
click to toggle source
# File lib/inkmake.rb, line 565 def temp_rotate_svg(path, degrees, width, height) if degrees != 180 out_width, out_height = height, width else out_width, out_height = width, height end file_href = "file://#{path}" svg = "<?xml version=\"1.0\"?>" + "<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"#{out_width}\" height=\"#{out_height}\">" + "<g>" + "<image transform=\"translate(#{out_width/2} #{out_height/2}) rotate(#{degrees})\"" + " width=\"#{width}\" height=\"#{height}\" x=\"#{-width/2}\" y=\"#{-height/2}\"" + " xlink:href=#{file_href.encode(:xml => :attr)} />" + "</g>" + "</svg>" f = Tempfile.new(["inkmake", ".svg"]) f.write(svg) f.flush f.seek(0) [f, out_width, out_height] end
variants_to_generate()
click to toggle source
# File lib/inkmake.rb, line 546 def variants_to_generate l = [] @images.each do |image| image.variants.each do |variant| next if not @force and File.exists? variant.out_path and File.mtime(variant.out_path) > File.mtime(image.svg_path) and File.mtime(variant.out_path) > File.mtime(@file) if variant.out_path == image.svg_path raise ProcessError, "Avoiding overwriting source SVG file #{image.svg_path}" end l << variant end end l end