File: interface.rb

package info (click to toggle)
ruby-prawn-icon 3.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, sid, trixie
  • size: 3,228 kB
  • sloc: ruby: 1,370; makefile: 5
file content (239 lines) | stat: -rw-r--r-- 7,364 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# frozen_string_literal: true

# 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 and 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.configuration.font_directory}/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 <icon></icon> tags, then the output is provided
  #   to Prawn's internal formatted text parser.
  #
  class Icon
    # @deprecated Use {Prawn::Icon.configuration.font_directory} instead
    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 <icon></icon> 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 'fas-beer'
      #   pdf.icon '<icon color="0099FF">fas-user-circle</icon>',
      #   inline_format: true
      #
      def icon(key, opts = {})
        key = translate_key(key)
        make_icon(key, opts).tap { |i| i && i.render }
      end

      # Initialize a new icon object.
      #
      # == 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 <icon></icon> 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 = {})
        key = translate_key(key)
        if opts.fetch(:inline_format, false)
          inline_icon(key, opts)
        else
          Icon.new(key, self, opts)
        end
      end

      # Render formatted icon content to the document from
      # a string containing icons. Content will correctly
      # transition to a new page when necessary.
      #
      # == Parameters:
      # text::
      #   Input text to be parsed initially for <icon>
      #   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)
        formatted_text(content, opts)
      end

      # Initialize a formatted icon box from an icon-conatining
      # string. Content is not directly rendered to the document,
      # instead a +Prawn::Text::Formatted::Box+ instance is returned
      # that responds to the +render+ method.
      #
      # == Parameters:
      # text::
      #   Input text to be parsed initially for <icon>
      #   tags, then passed to Prawn's formatted text
      #   parser.
      #
      # opts::
      #   A hash of options that may be supplied to the
      #   underlying text call.
      #
      def formatted_icon_box(text, opts = {})
        parsed = Icon::Parser.format(self, text)
        content = Text::Formatted::Parser.format(parsed)
        position = opts.fetch(:at) do
          [
            opts.fetch(:x) { bounds.left },
            opts.fetch(:y) { cursor }
          ]
        end
        box_options = opts.merge(
          inline_format: true,
          document: self,
          at: position
        )
        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: 'fas', content: "\uf2b9" }
      #
      #   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('fas-coffee'), 'Cell 1'],
      #     ['Cell 2', 'Cell 3']
      #   ]
      #
      #   pdf.table(data) => (2 x 2 table)
      #
      def table_icon(key, opts = {})
        key = translate_key(key)
        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 translate_key(key)
        Compatibility.new(key: key).translate
      end

      def icon_box(content, opts = {}) # :nodoc:
        Text::Formatted::Box.new(content, opts).tap do |box|
          box.render(dry_run: true)
          self.y -= box.height
          self.y -= box.line_gap + box.leading unless opts.fetch(:final_gap, true)
        end
      end
    end

    attr_reader :set, :unicode

    def initialize(key, document, opts = {})
      @pdf     = document
      @set     = opts.fetch(: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