# encoding: utf-8 # # interface.rb: Prawn extension module and logic. # # Copyright October 2016, Jesse Doyle. All rights reserved. # # This is free software. Please see the LICENSE and COPYING files for details. module Prawn # Easy icon font usage within Prawn. Currently # supported icon fonts include: FontAwesome, # Zurb Foundicons, GitHub Octicons, as well as # PaymentFont. # # = Icon Keys # # Icon keys must be supplied to most +Prawn::Icon+ # methods. Keys map directly to a unicode character # within the font that produces a given icon. As a # rule, included icon keys should match the keys from # the font provider. The icon key mapping is specified # in the font's +legend_file+, which is a +YAML+ file # located in Prawn::Icon::Base::FONTDIR/font/font.yml. # # Prawn::Icon:: # Houses the methods and interfaces necessary for # rendering icons to the Prawn::Document. # # Prawn::Icon::FontData:: # Used to store various information about an icon font, # including the key-to-unicode mapping information. # Also houses methods to cache and lazily load the # requested font data on a document basis. # # Prawn::Icon::Parser:: # Used to initially parse icons that are used with the # inline_format: true option. The input string is parsed # once for tags, then the output is provided # to Prawn's internal formatted text parser. # class Icon FONTDIR = Icon::Base::FONTDIR module Interface # Set up and draw an icon on this document. This # method operates much like +Prawn::Text::Box+. # # == Parameters: # key:: # Contains the key to a particular icon within # a font family. If :inline_format is true, # then key may contain formatted text marked # with tags and any tag supported # by Prawn's parser. # # opts:: # A hash of options that may be supplied to # the underlying +text+ method call. # # == Examples: # pdf.icon 'fa-beer' # pdf.icon 'fa-arrows', # inline_format: true # def icon(key, opts = {}) make_icon(key, opts).tap(&:render) end # Initialize a new icon object, but do # not render it to the document. # # == Parameters: # key:: # Contains the key to a particular icon within # a font family. If :inline_format is true, # then key may contain formatted text marked # with tags and any tag supported # by Prawn's parser. # # opts:: # A hash of options that may be supplied to # the underlying text method call. # def make_icon(key, opts = {}) if opts[:inline_format] inline_icon(key, opts) else Icon.new(key, self, opts) end end # Initialize a new formatted text box containing # icon information, but don't render it to the # document. # # == Parameters: # text:: # Input text to be parsed initially for # tags, then passed to Prawn's formatted text # parser. # # opts:: # A hash of options that may be supplied to the # underlying text call. # def inline_icon(text, opts = {}) parsed = Icon::Parser.format(self, text) content = Text::Formatted::Parser.format(parsed) box_options = opts.merge( inline_format: true, document: self, at: [bounds.left, cursor] ) icon_box(content, box_options) end # Initialize a new Prawn::Icon, but don't render # the icon to a document. Intended to be used as # an entry of a data array when combined with # Prawn::Table. # # == Parameters: # key:: # Contains the key to a particular icon within # a font family. The key may contain a string # with format tags if +inline_format: true+ in # the +opts+ hash. # # opts:: # A hash of options that may be supplied to the # underlying text call. # # == Returns: # A Hash containing +font+ and +content+ keys # that match the data necessary for the # specified icon. # # eg. { font: 'fa', content: '\uf047' } # # Note that the +font+ key will not be set # if +inline_format: true+. # # == Examples: # require 'prawn/table' # # data = [ # # Explicit brackets must be used here # [pdf.table_icon('fa-arrows'), 'Cell 1'], # ['Cell 2', 'Cell 3'] # ] # # pdf.table(data) => (2 x 2 table) # def table_icon(key, opts = {}) if opts[:inline_format] content = Icon::Parser.format(self, key) opts.merge(content: content) else make_icon(key, opts).format_hash end end private def icon_box(content, opts = {}) # :nodoc: Text::Formatted::Box.new(content, opts).tap do |box| box.render(dry_run: true) self.y -= box.height unless opts.fetch(:final_gap, true) self.y -= box.line_gap + box.leading end end end end attr_reader :set, :unicode def initialize(key, document, opts = {}) @pdf = document @set = opts[:set] || FontData.specifier_from_key(key) @data = FontData.load(document, @set) @key = strip_specifier_from_key(key) @unicode = @data.unicode(@key) @options = opts end def format_hash base = { font: @set.to_s, content: @unicode } opts = @options.dup # Prawn::Table renames :color to :text_color opts[:text_color] = opts.delete(:color) base.merge(opts) end def render @pdf.font(@data.path) do @pdf.text @unicode, @options end end private def strip_specifier_from_key(key) # :nodoc: reg = Regexp.new "#{@data.specifier}-" key.sub(reg, '') # Only one specifier end end end