lib/libis/format/converter/pdf_converter.rb in libis-format-1.3.5 vs lib/libis/format/converter/pdf_converter.rb in libis-format-2.0.0

- old
+ new

@@ -1,268 +1,120 @@ -# frozen_string_literal: true +# encoding: utf-8 require_relative 'base' require 'libis/tools/extend/hash' -require 'libis/format/tool/pdf_tool' +require 'libis/format/tool/pdf_copy' require 'libis/format/tool/pdf_to_pdfa' -require 'libis/format/tool/pdfa_validator' require 'libis/format/tool/pdf_optimizer' module Libis module Format module Converter + + # noinspection DuplicatedCode class PdfConverter < Libis::Format::Converter::Base + def self.input_types [:PDF] end def self.output_types(format = nil) - return [] unless input_types.include?(format) - - %i[PDF PDFA] + return [] unless input_types.include?(format) if format + [:PDF, :PDFA] end - def pdf_convert(_) - # force usage of this converter + def title(v) + @options[:title] = v.blank? ? nil : v end - # Set metadata for Pdf file - # - # valid metadata keys are): - # - title - # - author - # - creator - # - keywords - # - subject - # - # @param [Hash] values list of metadata values to set - def metadata(values = {}) - values.key_strings_to_symbols! - values.each do |k, v| - next unless %i[title author creator keywords subject].include?(k) - (@options[:metadata] ||= {})[k] = v - end + def author(v) + @options[:author] = v.blank? ? nil : v end - # Select a partial list of pages - # @param [String] selection as described in com.itextpdf.text.pdf.SequenceList: [!][o][odd][e][even]start-end - def range(selection) - @options[:select] = {range: [selection].flatten.compact.join(',')} + def creator(v) + @options[:creator] = v.blank? ? nil : v end - # Create or use a watermark image. - # - # The watermark options are (use symbols): - # - text: text to create a watermark from - # - file: watermark image to use - # - image: same as above - # - rotation: rotation of the watermark text (in degrees; integer number) - # - size: font size of the watermark text - # - opacity: opacity of the watermark (fraction 0.0 - 1.0) - # - gap: size of the gap between watermark instances. Integer value is absolute size in points (1/72 inch). - # Fractions are percentage of widht/height. - # If both options are given, the file will be used as-is if it exists and is a valid image file. Otherwise the - # file will be created or overwritten with a newly created watermark image. - # - # The created watermark file will be a PNG image with transparent background containing the supplied text - # slanted by 30 degrees counter-clockwise. - # - # @param [Hash] options Hash of options for watermark creation. - def watermark(options = {}) - options.key_strings_to_symbols! - if options[:file] || options[:image] - watermark_image(options) - elsif options[:text] - watermark_text(options) - elsif options[:banner] - watermark_banner(options) - end + def keywords(v) + @options[:keywords] = v.blank? ? nil : v end - def watermark_image(options = {}) - options.key_strings_to_symbols! - @options[:watermark] = {command: 'image'} - @options[:watermark][:data] = options[:file] || options[:image] - @options[:watermark][:opacity] = options[:opacity] || '0.3' - + def subject(v) + @options[:subject] = v.blank? ? nil : v end - def watermark_text(options = {}) - options.key_strings_to_symbols! - @options[:watermark] = {command: 'text'} - @options[:watermark][:data] = (options[:text] || '© LIBIS').split('\n') - @options[:watermark][:rotation] = options[:rotation] if options[:rotation] - @options[:watermark][:size] = options[:size] if options[:size] - @options[:watermark][:gap] = options[:gap] if options[:gap].to_s =~ /^\s*\d+\s*$/ - @options[:watermark][:padding] = options[:gap] if options[:gap].to_s =~ /^\s*(0+\.\d+|1\.0+)\s*$/ - @options[:watermark][:padding] = options[:padding] if options[:padding] - @options[:watermark][:opacity] = options[:opacity] || '0.3' + # Select a partial list of pages + # @param [String] selection as described in com.itextpdf.text.pdf.SequenceList: [!][o][odd][e][even]start-end + def range(selection) + @options[:ranges] = selection.blank? ? nil : selection end - # Create a vertical banner to the right side of each page - # - # The banner options are: - # - banner: text to put in the banner - # - add_filename: append filename to the text (use any value to enable) - # - fontsize: size of the font (in points) - # - width: width of the banner - # - (background|text)_color_(red|green|blue): color components of background and text - def watermark_banner(options = {}) - options.key_strings_to_symbols! - @options[:watermark] = {command: 'banner'} - @options[:watermark][:data] = (options[:banner] || '© LIBIS') - @options[:watermark][:add_filename] = !!options[:add_filename] - @options[:watermark][:size] = options[:fontsize] if options[:fontsize] - @options[:watermark][:width] = options[:width] if options[:width] - @options[:watermark][:background_red] = options[:background_color_red] if options[:background_color_red] - @options[:watermark][:background_green] = options[:background_color_green] if options[:background_color_green] - @options[:watermark][:background_blue] = options[:background_color_blue] if options[:background_color_blue] - @options[:watermark][:text_red] = options[:text_color_red] if options[:text_color_red] - @options[:watermark][:text_green] = options[:text_color_green] if options[:text_color_green] - @options[:watermark][:text_blue] = options[:text_color_blue] if options[:text_color_blue] - end - - # Optimize the PDF - # - # This reduces the graphics quality to a level in order to limit file size. This option relies on the - # presence of ghostscript and takes one argument: the quality level. It should be one of: - # - # - 0 : lowest quality (Acrobat Distiller 'Screen Optimized' equivalent) - # - 1 : medium quality (Acrobat Distiller 'eBook' equivalent) - # - 2 : good quality (Acrobat Distiller 'Default' equivalent) - # - 3 : high quality (Acrobat Distiller 'Print Optimized' equivalent) - # - 4 : highest quality (Acrobat Distiller 'Prepress Optimized' equivalent) - # - # Note that the optimization is intended to be used with PDF's containing high-resolution images. - # - # @param [Integer] setting quality setting. [0-4] - def optimize(setting = 1) - @options[:optimize] = %w[screen ebook default printer prepress][setting] if (0..4).include?(setting) - end - def convert(source, target, format, opts = {}) super result = nil unless @options.empty? result = convert_pdf(source, target) + return nil unless result source = result end - if source && (quality = @options.delete(:optimize)) - result = optimize_pdf(source, target, quality) - source = result - end - - if source && (format == :PDFA) + if format == :PDFA and source result = pdf_to_pdfa(source, target) end - { - files: [result], - converter: self.class.name - } - end + result - protected - - def optimize_pdf(source, target, quality) - using_temp(target) do |tmpname| - result = Libis::Format::Tool::PdfOptimizer.run(source, tmpname, quality) - unless result[:err].empty? - error("Pdf optimization encountered errors:\n%s", (result[:err] + result[:out]).join("\n")) - return nil - end - tmpname - end end + OPTIONS_TABLE = { + title: 'md_title', + author: 'md_author', + creator: 'md_creator', + keywords: 'md_keywords', + subject: 'md_subject' + } + def convert_pdf(source, target) - result = source - result = add_watermark(result, target, @options[:watermark]) if @options[:watermark] - result = add_metadata(result, target, @options[:metadata]) if @options[:metadata] - result = select_range(result, target, @options[:select]) if @options[:select] - return result - end - def options_to_args(options) - options.map do |k, v| - key = "--#{k.to_s.tr_s('_', '-')}" - value = v - case value - when TrueClass - value = nil - when FalseClass - value = key = nil - when Array - value = value.map(&:to_s) - else - value = v.to_s - end - [key, value] - end.flatten.compact - end - - def add_watermark(source, target, options) - command = options.delete(:command) - data = [options.delete(:data)].flatten.compact - args = data + options_to_args(options) - using_temp(target) do |tmpname| - result = Libis::Format::Tool::PdfTool.run(['watermark', command], source, tmpname, *args) + result = Libis::Format::Tool::PdfCopy.run( + source, tmpname, + @options.map {|k, v| + if v.nil? + nil + else + k = OPTIONS_TABLE[k] || k + ["--#{k}", (v.is_a?(Array) ? v : v.to_s)] + end}.compact.flatten + ) unless result[:err].empty? - error("Pdf watermarking encountered errors:\n%s", result[:err].join(join("\n"))) - return nil + error("Pdf conversion encountered errors:\n%s", result[:err].join(join("\n"))) + next nil end tmpname end - end - def add_metadata(source, target, options) - args = options_to_args(options) - - using_temp(target) do |tmpname| - result = Libis::Format::Tool::PdfTool.run('metadata', source, tmpname, *args) - unless result[:err].empty? - error("Pdf metadata encountered errors:\n%s", result[:err].join(join("\n"))) - return nil - end - tmpname - end end - def select_range(source, target, options) - args = options_to_args(options) + def pdf_to_pdfa(source, target) using_temp(target) do |tmpname| - result = Libis::Format::Tool::PdfTool.run('select', source, tmpname, *args) - unless result[:err].empty? - error("Pdf select encountered errors:\n%s", result[:err].join(join("\n"))) - return nil - end - tmpname - end - end - - def pdf_to_pdfa(source, target) - using_temp(target) do |tmpname| result = Libis::Format::Tool::PdfToPdfa.run source, tmpname - - unless result[:status].zero? - error("Pdf/A conversion encountered errors:\n%s", (result[:out] + result[:err]).join("\n")) - return nil + if result[:status] != 0 + error("Pdf/A conversion encountered errors:\n%s", result[:err].join("\n")) + next nil else - r = Libis::Format::Tool::PdfaValidator.run tmpname - if r[:status] != 0 - error "Pdf/A file failed to validate with following errors:\n%s", (r[:err] || r[:out] || []).join("\n") - return nil - end + warn("Pdf/A conversion warnings:\n%s", result[:err].join("\n")) unless result[:err].empty? end tmpname end + end + end + end end end