#!/usr/bin/env ruby require 'thor' require 'digest/md5' require 'parallel' require_relative '../lib/svggvs' module SVGGVS class Cli < Thor include Thor::Actions def self.source_root ::File.expand_path('../../skel', __FILE__) end class_option :cardfile, default: 'Cardfile' desc "install [ dir ]", "Install a Cardfile and sample template" def install(dir = '.') directory '.', dir end desc "merged_file", "Write out a merged file" def merged_file context.write_merged_file end desc "svgs", "Write out individual SVG files" def svgs write_svgs end desc "pngs", "Write out individual PNG files" def pngs write_svgs ensure_tmp @exported_pngs = Parallel.map(context.individual_files.each_with_index) do |svg_file, index| target = Pathname(context.session.png_files_path % index) target.parent.mkpath system %{inkscape --export-area-page --export-png "#{target.expand_path}" --export-width #{context.session.png_export_width} --export-background="#ffffffff" "#{svg_file.expand_path}"} target end end CARDS_PER_PAGE = 9 desc "pdf", "Create PDF of card images" def pdf pngs trimmed_pngs = Parallel.map(@exported_pngs) do |png| tmp_target = tmp_target_for(png) system %{convert #{png} -gravity Center -crop #{context.session.pdf_card_size}+0+0 +repage #{tmp_target}} tmp_target end png_slices = trimmed_pngs.each_slice(CARDS_PER_PAGE) page_count = trimmed_pngs.length / CARDS_PER_PAGE placeholder = tmp_target_for("placeholder.png") system %{convert -size #{context.session.pdf_card_size} xc:white #{placeholder}} pdf_obj = SVGGVS::PDF.new(card_size: context.session.pdf_card_size) pages = Parallel.map(png_slices.each_with_index) do |files, page_index| tmp_pdf_png_target = tmp_path.join("page%05d.pdf" % page_index) tmp_pdf_target = tmp_path.join("page%05d.pdf" % page_index) files += Array.new(9 - files.length, placeholder) system %{montage -density #{context.session.pdf_dpi} -geometry +0+0 #{files.join(' ')} #{tmp_pdf_png_target}} system %{convert -density #{context.session.pdf_dpi} #{tmp_pdf_png_target} -bordercolor white -border #{SVGGVS::PDF.border_size} #{pdf_obj.generate_crop_mark_draws.join(' ')} #{tmp_pdf_target}}.tap { |o| p o } tmp_pdf_target end if context.session.card_back tmp_target = tmp_target_for(context.session.card_back) tmp_pdf_target = tmp_path.join("backs.pdf") system %{convert #{context.session.card_back} -gravity Center -crop #{context.session.pdf_card_size}+0+0 +repage #{tmp_target}} system %{montage -density #{context.session.pdf_dpi} -geometry +0+0 #{Array.new(9, tmp_target).join(' ')} #{tmp_pdf_target}} pages.length.times do |page| pages << tmp_pdf_target end end Pathname(context.session.pdf_target).parent.mkpath system "gs -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=#{context.session.pdf_target} -dBATCH #{pages.join(" ")}" end no_tasks do def tmp_target_for(file) tmp_path.join(Digest::MD5.hexdigest(file.to_s) + '.png') end def tmp_path @tmp_path ||= Pathname(".tmp") end def ensure_tmp tmp_path.rmtree if tmp_path.directory? tmp_path.mkpath end def context @context ||= SVGGVS::Context.load(options[:cardfile]) end def write_svgs context.write_individual_files end end end end SVGGVS::Cli.start