prawn 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. data/Rakefile +3 -1
  2. data/data/fonts/Action Man.dfont +0 -0
  3. data/examples/general/measurement_units.rb +2 -2
  4. data/examples/graphics/image_flow.rb +2 -2
  5. data/examples/graphics/stroke_bounds.rb +1 -1
  6. data/examples/m17n/win_ansi_charset.rb +3 -3
  7. data/examples/text/dfont.rb +49 -0
  8. data/examples/text/flowing_text_with_header_and_footer.rb +2 -48
  9. data/examples/text/font_calculations.rb +7 -6
  10. data/examples/text/font_size.rb +4 -4
  11. data/examples/text/text_flow.rb +1 -1
  12. data/lib/prawn.rb +6 -3
  13. data/lib/prawn/compatibility.rb +12 -17
  14. data/lib/prawn/document.rb +10 -10
  15. data/lib/prawn/document/internals.rb +8 -3
  16. data/lib/prawn/document/text.rb +39 -57
  17. data/lib/prawn/document/text/box.rb +1 -2
  18. data/lib/prawn/document/text/wrapping.rb +59 -0
  19. data/lib/prawn/errors.rb +0 -8
  20. data/lib/prawn/font.rb +192 -277
  21. data/lib/prawn/font/afm.rb +199 -0
  22. data/lib/prawn/font/dfont.rb +31 -0
  23. data/lib/prawn/font/ttf.rb +318 -0
  24. data/lib/prawn/graphics.rb +7 -2
  25. data/lib/prawn/images/png.rb +1 -1
  26. data/lib/prawn/reference.rb +7 -4
  27. data/spec/font_spec.rb +154 -61
  28. data/spec/text_spec.rb +47 -6
  29. data/vendor/pdf-inspector/lib/pdf/inspector.rb +1 -1
  30. data/vendor/ttfunk/example.rb +42 -2
  31. data/vendor/ttfunk/lib/ttfunk.rb +96 -42
  32. data/vendor/ttfunk/lib/ttfunk/directory.rb +17 -0
  33. data/vendor/ttfunk/lib/ttfunk/encoding/mac_roman.rb +88 -0
  34. data/vendor/ttfunk/lib/ttfunk/encoding/windows_1252.rb +69 -0
  35. data/vendor/ttfunk/lib/ttfunk/reader.rb +44 -0
  36. data/vendor/ttfunk/lib/ttfunk/resource_file.rb +78 -0
  37. data/vendor/ttfunk/lib/ttfunk/subset.rb +18 -0
  38. data/vendor/ttfunk/lib/ttfunk/subset/base.rb +141 -0
  39. data/vendor/ttfunk/lib/ttfunk/subset/mac_roman.rb +46 -0
  40. data/vendor/ttfunk/lib/ttfunk/subset/unicode.rb +48 -0
  41. data/vendor/ttfunk/lib/ttfunk/subset/unicode_8bit.rb +63 -0
  42. data/vendor/ttfunk/lib/ttfunk/subset/windows_1252.rb +51 -0
  43. data/vendor/ttfunk/lib/ttfunk/subset_collection.rb +72 -0
  44. data/vendor/ttfunk/lib/ttfunk/table.rb +37 -18
  45. data/vendor/ttfunk/lib/ttfunk/table/cmap.rb +24 -84
  46. data/vendor/ttfunk/lib/ttfunk/table/cmap/format00.rb +54 -0
  47. data/vendor/ttfunk/lib/ttfunk/table/cmap/format04.rb +126 -0
  48. data/vendor/ttfunk/lib/ttfunk/table/cmap/subtable.rb +79 -0
  49. data/vendor/ttfunk/lib/ttfunk/table/glyf.rb +64 -0
  50. data/vendor/ttfunk/lib/ttfunk/table/glyf/compound.rb +81 -0
  51. data/vendor/ttfunk/lib/ttfunk/table/glyf/simple.rb +37 -0
  52. data/vendor/ttfunk/lib/ttfunk/table/head.rb +38 -19
  53. data/vendor/ttfunk/lib/ttfunk/table/hhea.rb +35 -21
  54. data/vendor/ttfunk/lib/ttfunk/table/hmtx.rb +40 -13
  55. data/vendor/ttfunk/lib/ttfunk/table/kern.rb +69 -38
  56. data/vendor/ttfunk/lib/ttfunk/table/kern/format0.rb +62 -0
  57. data/vendor/ttfunk/lib/ttfunk/table/loca.rb +43 -0
  58. data/vendor/ttfunk/lib/ttfunk/table/maxp.rb +34 -11
  59. data/vendor/ttfunk/lib/ttfunk/table/name.rb +109 -42
  60. data/vendor/ttfunk/lib/ttfunk/table/os2.rb +78 -0
  61. data/vendor/ttfunk/lib/ttfunk/table/post.rb +91 -0
  62. data/vendor/ttfunk/lib/ttfunk/table/post/format10.rb +43 -0
  63. data/vendor/ttfunk/lib/ttfunk/table/post/format20.rb +35 -0
  64. data/vendor/ttfunk/lib/ttfunk/table/post/format25.rb +23 -0
  65. data/vendor/ttfunk/lib/ttfunk/table/post/format30.rb +17 -0
  66. data/vendor/ttfunk/lib/ttfunk/table/post/format40.rb +17 -0
  67. data/vendor/ttfunk/lib/ttfunk/table/simple.rb +14 -0
  68. metadata +54 -25
  69. data/examples/table/addressbook.csv +0 -6
  70. data/examples/table/cell.rb +0 -40
  71. data/examples/table/currency.csv +0 -1834
  72. data/examples/table/fancy_table.rb +0 -62
  73. data/examples/table/ruport_formatter.rb +0 -53
  74. data/examples/table/table.rb +0 -51
  75. data/examples/table/table_alignment.rb +0 -18
  76. data/examples/table/table_border_color.rb +0 -17
  77. data/examples/table/table_colspan.rb +0 -19
  78. data/examples/table/table_header_color.rb +0 -19
  79. data/examples/table/table_header_underline.rb +0 -15
  80. data/lib/prawn/document/table.rb +0 -338
  81. data/lib/prawn/font/cmap.rb +0 -59
  82. data/lib/prawn/font/metrics.rb +0 -378
  83. data/lib/prawn/font/wrapping.rb +0 -47
  84. data/lib/prawn/graphics/cell.rb +0 -264
  85. data/spec/metrics_spec.rb +0 -62
  86. data/spec/table_spec.rb +0 -179
  87. data/vendor/ttfunk/lib/ttfunk/table/directory.rb +0 -25
@@ -55,8 +55,7 @@ module Prawn
55
55
  private
56
56
 
57
57
  def fit_text_to_box
58
- text = @document.font.metrics.naive_wrap(@text,
59
- @width, @document.font.size)
58
+ text = @document.naive_wrap(@text, @width, @document.font_size)
60
59
 
61
60
  max_lines = (@height / @document.font.height).floor
62
61
 
@@ -0,0 +1,59 @@
1
+ # encoding: utf-8
2
+
3
+ # wrapping.rb : Implementation of naive text wrap
4
+ #
5
+ # Copyright May 2008, Michael Daines. All Rights Reserved.
6
+ #
7
+ # This is free software. Please see the LICENSE and COPYING files for details.
8
+ module Prawn
9
+ class Document
10
+ module Text
11
+ module Wrapping #:nodoc:
12
+ ruby_18 { $KCODE="U" }
13
+
14
+ # Gets height of text in PDF points at current font size.
15
+ # Text +:line_width+ must be specified in PDF points.
16
+ #
17
+ # If using an AFM, string *must* be encoded as WinAnsi
18
+ # (Use normalize_encoding to convert)
19
+ #
20
+ def height_of(string, line_width, size=font_size)
21
+ string = naive_wrap(string, line_width, size)
22
+ string.lines.to_a.length * font.height_at(size)
23
+ end
24
+
25
+ # TODO: Replace with TeX optimal algorithm
26
+ def naive_wrap(string, line_width, font_size, options = {})
27
+ scan_pattern = options[:mode] == :character ? /./ : /\S+|\s+/
28
+
29
+ output = ""
30
+ string.lines.each do |line|
31
+ accumulated_width = 0
32
+ segments = line.scan(scan_pattern)
33
+
34
+ segments.each do |segment|
35
+ segment_width = font.width_of(segment, :size => font_size, :kerning => options[:kerning])
36
+
37
+ if (accumulated_width + segment_width).round > line_width.round
38
+ output = "#{output.sub(/[ \t]*\n?(\n*)\z/, "\n\\1")}"
39
+
40
+ if segment =~ /\s/
41
+ accumulated_width = 0
42
+ else
43
+ output << segment
44
+ accumulated_width = segment_width
45
+ end
46
+ else
47
+ output << segment
48
+ accumulated_width += segment_width
49
+ end
50
+ end
51
+ end
52
+
53
+ output
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
data/lib/prawn/errors.rb CHANGED
@@ -36,13 +36,5 @@ module Prawn
36
36
  #
37
37
  class UnknownOption < StandardError; end
38
38
 
39
- # This error is raised when table data is malformed
40
- #
41
- class InvalidTableData < StandardError; end
42
-
43
- # This error is raised when an empty or nil table is rendered
44
- #
45
- class EmptyTable < StandardError; end
46
-
47
39
  end
48
40
  end
data/lib/prawn/font.rb CHANGED
@@ -5,358 +5,273 @@
5
5
  # Copyright May 2008, Gregory Brown / James Healy. All Rights Reserved.
6
6
  #
7
7
  # This is free software. Please see the LICENSE and COPYING files for details.
8
- require "prawn/font/wrapping"
9
- require "prawn/font/metrics"
10
- require "prawn/font/cmap"
8
+ require "prawn/font/afm"
9
+ require "prawn/font/ttf"
10
+ require "prawn/font/dfont"
11
11
 
12
- module Prawn
13
-
14
- class Document
12
+ module Prawn
13
+
14
+ class Document
15
15
  # Without arguments, this returns the currently selected font. Otherwise,
16
16
  # it sets the current font.
17
17
  #
18
18
  # The single parameter must be a string. It can be one of the 14 built-in
19
- # fonts supported by PDF, or the location of a TTF file. The BUILT_INS
19
+ # fonts supported by PDF, or the location of a TTF file. The Font::AFM::BUILT_INS
20
20
  # array specifies the valid built in font values.
21
21
  #
22
22
  # pdf.font "Times-Roman"
23
23
  # pdf.font "Chalkboard.ttf"
24
24
  #
25
- # If a ttf font is specified, the full file will be embedded in the
26
- # rendered PDF. This should be your preferred option in most cases.
27
- # It will increase the size of the resulting file, but also make it
28
- # more portable.
25
+ # If a ttf font is specified, the glyphs necessary to render your document
26
+ # will be embedded in the rendered PDF. This should be your preferred option
27
+ # in most cases. It will increase the size of the resulting file, but also
28
+ # make it more portable.
29
29
  #
30
- def font(name=nil, options={})
30
+ def font(name=nil, options={})
31
31
  return @font || font("Helvetica") if name.nil?
32
32
 
33
+ new_font = find_font(name, options)
34
+
33
35
  if block_given?
34
- original_name = font.name
35
- original_size = font.size
36
- end
37
-
38
- @font = find_font(name, options)
39
- @font.add_to_current_page
40
-
41
- @font.size = options[:size] if options[:size]
42
-
43
- if block_given?
44
- yield
45
- font(original_name, :size => original_size)
36
+ save_font do
37
+ set_font(new_font, options[:size])
38
+ yield
39
+ end
46
40
  else
47
- @font
41
+ set_font(new_font, options[:size])
48
42
  end
43
+
44
+ @font
49
45
  end
50
46
 
51
- # Looks up the given font name. Once a font has been found by that name,
52
- # it will be cached to subsequent lookups for that font will return the
53
- # same object.
47
+ # When called with no argument, returns the current font size.
48
+ # When called with a single argument but no block, sets the current font
49
+ # size. When a block is used, the font size is applied transactionally and
50
+ # is rolled back when the block exits. You may still change the font size
51
+ # within a transactional block for individual text segments, or nested calls
52
+ # to font_size.
53
+ #
54
+ # Prawn::Document.generate("font_size.pdf") do
55
+ # font_size 16
56
+ # text "At size 16"
57
+ #
58
+ # font_size(10) do
59
+ # text "At size 10"
60
+ # text "At size 6", :size => 6
61
+ # text "At size 10"
62
+ # end
63
+ #
64
+ # text "At size 16"
65
+ # end
66
+ #
67
+ # When called without an argument, this method returns the current font
68
+ # size.
69
+ #
70
+ def font_size(points=nil)
71
+ return @font_size unless points
72
+ size_before_yield = @font_size
73
+ @font_size = points
74
+ block_given? ? yield : return
75
+ @font_size = size_before_yield
76
+ end
77
+
78
+ # Sets the font directly, given an actual Font object
79
+ # and size.
80
+ def set_font(font, size=nil) # :nodoc:
81
+ @font = font
82
+ @font_size = size if size
83
+ end
84
+
85
+ # Saves the current font, and then yields. When the block
86
+ # finishes, the original font is restored.
87
+ def save_font
88
+ @font ||= find_font("Helvetica")
89
+ original_font = @font
90
+ original_size = @font_size
91
+
92
+ yield
93
+ ensure
94
+ set_font(original_font, original_size) if original_font
95
+ end
96
+
97
+ # Looks up the given font using the given criteria. Once a font has been
98
+ # found by that matches the criteria, it will be cached to subsequent lookups
99
+ # for that font will return the same object.
100
+ #--
101
+ # Challenges involved: the name alone is not sufficient to uniquely identify
102
+ # a font (think dfont suitcases that can hold multiple different fonts in a
103
+ # single file). Thus, the :name key is included in the cache key.
104
+ #
105
+ # It is further complicated, however, since fonts in some formats (like the
106
+ # dfont suitcases) can be identified either by numeric index, OR by their
107
+ # name within the suitcase, and both should hash to the same font object
108
+ # (to avoid the font being embedded multiple times). This is not yet implemented,
109
+ # which means if someone selects a font both by name, and by index, the
110
+ # font will be embedded twice. Since we do font subsetting, this double
111
+ # embedding won't be catastrophic, just annoying.
112
+ # ++
54
113
  #
55
114
  def find_font(name, options={}) #:nodoc:
56
115
  if font_families.key?(name)
57
116
  family, name = name, font_families[name][options[:style] || :normal]
117
+
118
+ if name.is_a?(Hash)
119
+ options = options.merge(name)
120
+ name = options[:file]
121
+ end
58
122
  end
59
123
 
60
- font_registry[name] ||= Font.new(name, options.merge(:for => self, :family => family))
61
- end
62
-
124
+ key = "#{name}:#{options[:font] || 0}"
125
+ font_registry[key] ||= Font.load(self, name, options.merge(:family => family))
126
+ end
127
+
63
128
  # Hash of Font objects keyed by names
64
129
  #
65
130
  def font_registry #:nodoc:
66
131
  @font_registry ||= {}
67
- end
68
-
132
+ end
133
+
69
134
  # Hash that maps font family names to their styled individual font names
70
- #
135
+ #
71
136
  # To add support for another font family, append to this hash, e.g:
72
137
  #
73
138
  # pdf.font_families.update(
74
- # "MyTrueTypeFamily" => { :bold => "foo-bold.ttf",
139
+ # "MyTrueTypeFamily" => { :bold => "foo-bold.ttf",
75
140
  # :italic => "foo-italic.ttf",
76
141
  # :bold_italic => "foo-bold-italic.ttf",
77
142
  # :normal => "foo.ttf" })
78
143
  #
79
144
  # This will then allow you to use the fonts like so:
80
145
  #
81
- # pdf.font("MyTrueTypeFamily", :style => :bold)
146
+ # pdf.font("MyTrueTypeFamily", :style => :bold)
82
147
  # pdf.text "Some bold text"
83
148
  # pdf.font("MyTrueTypeFamily")
84
149
  # pdf.text "Some normal text"
85
150
  #
86
- # This assumes that you have appropriate TTF fonts for each style you
151
+ # This assumes that you have appropriate TTF fonts for each style you
87
152
  # wish to support.
88
- #
89
- def font_families
90
- @font_families ||= Hash.new { |h,k| h[k] = {} }.merge!(
153
+ #
154
+ def font_families
155
+ @font_families ||= Hash.new { |h,k| h[k] = {} }.merge!(
91
156
  { "Courier" => { :bold => "Courier-Bold",
92
157
  :italic => "Courier-Oblique",
93
158
  :bold_italic => "Courier-BoldOblique",
94
- :normal => "Courier" },
95
-
159
+ :normal => "Courier" },
160
+
96
161
  "Times-Roman" => { :bold => "Times-Bold",
97
162
  :italic => "Times-Italic",
98
163
  :bold_italic => "Times-BoldItalic",
99
- :normal => "Times-Roman" },
100
-
164
+ :normal => "Times-Roman" },
165
+
101
166
  "Helvetica" => { :bold => "Helvetica-Bold",
102
167
  :italic => "Helvetica-Oblique",
103
168
  :bold_italic => "Helvetica-BoldOblique",
104
- :normal => "Helvetica" }
105
- })
169
+ :normal => "Helvetica" }
170
+ })
106
171
  end
107
172
  end
108
-
109
- # Provides font information and helper functions.
110
- #
173
+
174
+ # Provides font information and helper functions.
175
+ #
111
176
  class Font
112
-
113
- BUILT_INS = %w[ Courier Helvetica Times-Roman Symbol ZapfDingbats
114
- Courier-Bold Courier-Oblique Courier-BoldOblique
115
- Times-Bold Times-Italic Times-BoldItalic
116
- Helvetica-Bold Helvetica-Oblique Helvetica-BoldOblique ]
117
-
118
- DEFAULT_SIZE = 12
119
-
120
- # The font metrics object
121
- attr_reader :metrics
122
-
177
+
123
178
  # The current font name
124
179
  attr_reader :name
125
-
180
+
126
181
  # The current font family
127
182
  attr_reader :family
128
-
129
- attr_reader :identifier, :reference #:nodoc:
130
-
131
- # Sets the size of the current font:
132
- #
133
- # font.size = 16
134
- #
135
- attr_writer :size
136
-
137
- def initialize(name,options={}) #:nodoc:
138
- @name = name
139
- @family = options[:family]
140
-
141
- @metrics = Prawn::Font::Metrics[name]
142
- @document = options[:for]
143
-
144
- @document.proc_set :PDF, :Text
145
- @size = DEFAULT_SIZE
146
- @identifier = :"F#{@document.font_registry.size + 1}"
147
-
148
- @reference = nil
149
- end
150
-
151
- def inspect
152
- "Prawn::Font< #{name}: #{size} >"
183
+
184
+ # The options hash used to initialize the font
185
+ attr_reader :options
186
+
187
+ def self.load(document,name,options={})
188
+ case name
189
+ when /\.ttf$/ then TTF.new(document, name, options)
190
+ when /\.dfont$/ then DFont.new(document, name, options)
191
+ when /\.afm$/ then AFM.new(document, name, options)
192
+ else AFM.new(document, name, options)
193
+ end
153
194
  end
154
-
155
- # Sets the default font size for use within a block. Individual overrides
156
- # can be used as desired. The previous font size will be restored after the
157
- # block.
158
- #
159
- # Prawn::Document.generate("font_size.pdf") do
160
- # font.size = 16
161
- # text "At size 16"
162
- #
163
- # font.size(10) do
164
- # text "At size 10"
165
- # text "At size 6", :size => 6
166
- # text "At size 10"
167
- # end
168
- #
169
- # text "At size 16"
170
- # end
171
- #
172
- # When called without an argument, this method returns the current font
173
- # size.
174
- #
175
- def size(points=nil)
176
- return @size unless points
177
- size_before_yield = @size
178
- @size = points
179
- yield
180
- @size = size_before_yield
181
- end
182
-
183
- # Gets width of string in PDF points at current font size
184
- #
185
- # If using an AFM, string *must* be encoded as WinAnsi
186
- # (Use normalize_encoding to convert)
187
- #
188
- def width_of(string)
189
- @metrics.string_width(string,@size)
190
- end
191
-
192
- # Gets height of text in PDF points at current font size.
193
- # Text +:line_width+ must be specified in PDF points.
194
- #
195
- # If using an AFM, string *must* be encoded as WinAnsi
196
- # (Use normalize_encoding to convert)
197
- #
198
- def height_of(text,options={})
199
- @metrics.string_height( text, :font_size => @size,
200
- :line_width => options[:line_width] )
201
- end
202
-
203
- # Gets height of current font in PDF points at current font size
204
- #
205
- def height
206
- @metrics.font_height(@size)
207
- end
208
-
209
- # The height of the ascender at the current font size in PDF points
210
- #
211
- def ascender
212
- @metrics.ascender / 1000.0 * @size
213
- end
214
-
215
- # The height of the descender at the current font size in PDF points
216
- #
217
- def descender
218
- @metrics.descender / 1000.0 * @size
195
+
196
+ def initialize(document,name,options={}) #:nodoc:
197
+ @document = document
198
+ @name = name
199
+ @options = options
200
+
201
+ @family = options[:family]
202
+
203
+ @document.proc_set :PDF, :Text
204
+ @identifier = :"F#{@document.font_registry.size + 1}"
205
+
206
+ @references = {}
219
207
  end
220
-
208
+
209
+ def ascender
210
+ @ascender / 1000.0 * size
211
+ end
212
+
213
+ def descender
214
+ @descender / 1000.0 * size
215
+ end
216
+
221
217
  def line_gap
222
- @metrics.line_gap / 1000.0 * @size
218
+ @line_gap / 1000.0 * size
223
219
  end
224
-
225
- def normalize_encoding(text) # :nodoc:
226
- # check the string is encoded sanely
227
- # - UTF-8 for TTF fonts
228
- # - ISO-8859-1 for Built-In fonts
229
- if @metrics.type0?
230
- normalize_ttf_encoding(text)
231
- else
232
- normalize_builtin_encoding(text)
233
- end
220
+
221
+ def identifier_for(subset)
222
+ "#{@identifier}.#{subset}"
234
223
  end
235
-
236
- def add_to_current_page #:nodoc:
237
- embed! unless @reference
238
- @document.page_fonts.merge!(@identifier => @reference)
239
- end
240
-
241
- private
242
224
 
243
- def embed!
244
- case(name)
245
- when /\.ttf$/i
246
- embed_ttf(name)
247
- else
248
- register_builtin(name)
249
- end
225
+ def inspect
226
+ "#{self.class.name}< #{name}: #{size} >"
250
227
  end
251
228
 
252
- # built-in fonts only work with winansi encoding, so translate the string
253
- def normalize_builtin_encoding(text)
254
- enc = Prawn::Encoding::WinAnsi.new
255
- text.replace text.unpack("U*").collect { |i| enc[i] }.pack("C*")
229
+ # Returns the width of the given string using the given font. If :size is not
230
+ # specified as one of the options, the string is measured using the current
231
+ # font size. You can also pass :kerning as an option to indicate whether
232
+ # kerning should be used when measuring the width (defaults to +false+).
233
+ #
234
+ # Note that the string _must_ be encoded properly for the font being used.
235
+ # For AFM fonts, this is WinAnsi. For TTF, make sure the font is encoded as
236
+ # UTF-8. You can use the #normalize_encoding method to make sure strings
237
+ # are in an encoding appropriate for the font.
238
+ def width_of(string, options={})
239
+ raise NotImplementedError, "subclasses of Prawn::Font must implement #width_of"
256
240
  end
257
241
 
258
- def normalize_ttf_encoding(text)
259
- # TODO: if the current font is a built in one, we can't use the utf-8
260
- # string provided by the user. We should convert it to WinAnsi or
261
- # MacRoman or some such.
262
- if text.respond_to?(:encode!)
263
- # if we're running under a M17n aware VM, ensure the string provided is
264
- # UTF-8 (by converting it if necessary)
265
- begin
266
- text.encode!("UTF-8")
267
- rescue
268
- raise Prawn::Errors::IncompatibleStringEncoding, "Encoding " +
269
- "#{text.encoding} can not be transparently converted to UTF-8. " +
270
- "Please ensure the encoding of the string you are attempting " +
271
- "to use is set correctly"
272
- end
273
- else
274
- # on a non M17N aware VM, use unpack as a hackish way to verify the
275
- # string is valid utf-8. I thought it was better than loading iconv
276
- # though.
277
- begin
278
- text.unpack("U*")
279
- rescue
280
- raise Prawn::Errors::IncompatibleStringEncoding, "The string you " +
281
- "are attempting to render is not encoded in valid UTF-8."
282
- end
283
- end
242
+ # Normalizes the encoding of the string to an encoding supported by the font.
243
+ # The string is expected to be UTF-8 going in, and will be reencoded in-place
244
+ # (the argument will be modified directly). The return value is not defined.
245
+ def normalize_encoding(string)
246
+ raise NotImplementedError, "subclasses of Prawn::Font must implement #normalize_encoding"
284
247
  end
285
-
286
- def register_builtin(name)
287
- unless BUILT_INS.include?(name)
288
- raise Prawn::Errors::UnknownFont, "#{name} is not a known font."
289
- end
290
-
291
- @reference = @document.ref( :Type => :Font,
292
- :Subtype => :Type1,
293
- :BaseFont => name.to_sym,
294
- :Encoding => :WinAnsiEncoding)
295
- end
296
-
297
- def embed_ttf(file)
298
- unless File.file?(file)
299
- raise ArgumentError, "file #{file} does not exist"
300
- end
301
248
 
302
- basename = @metrics.basename
249
+ def height_at(size)
250
+ @normalized_height ||= (@ascender - @descender + @line_gap) / 1000.0
251
+ @normalized_height * size
252
+ end
303
253
 
304
- raise "Can't detect a postscript name for #{file}" if basename.nil?
254
+ # Gets height of current font in PDF points at current font size
255
+ #
256
+ def height
257
+ height_at(size)
258
+ end
305
259
 
306
- @encodings = @metrics.cmap
260
+ # Registers the given subset of the current font with the current PDF
261
+ # page. This is safe to call multiple times for a given font and subset,
262
+ # as it will only add the font the first time it is called.
263
+ #
264
+ def add_to_current_page(subset)
265
+ @references[subset] ||= register(subset)
266
+ @document.page_fonts.merge!(identifier_for(subset) => @references[subset])
267
+ end
307
268
 
308
- if @encodings.nil?
309
- raise "#{file} missing the required encoding table"
310
- end
269
+ private
311
270
 
312
- font_content = File.open(file,"rb") { |f| f.read }
313
- compressed_font = Zlib::Deflate.deflate(font_content)
314
-
315
- fontfile = @document.ref(:Length => compressed_font.size,
316
- :Length1 => font_content.size,
317
- :Filter => :FlateDecode )
318
- fontfile << compressed_font
319
-
320
- # TODO: Not sure what to do about CapHeight, as ttf2afm doesn't
321
- # pick it up. Missing proper StemV and flags
322
- #
323
- descriptor = @document.ref(:Type => :FontDescriptor,
324
- :FontName => basename,
325
- :FontFile2 => fontfile,
326
- :FontBBox => @metrics.bbox,
327
- :Flags => 32, # FIXME: additional flags
328
- :StemV => 0,
329
- :ItalicAngle => 0,
330
- :Ascent => @metrics.ascender,
331
- :Descent => @metrics.descender )
332
-
333
- descendant = @document.ref(:Type => :Font,
334
- :Subtype => :CIDFontType2, # CID, TTF
335
- :BaseFont => basename,
336
- :CIDSystemInfo => { :Registry => "Adobe",
337
- :Ordering => "Identity",
338
- :Supplement => 0 },
339
- :FontDescriptor => descriptor,
340
- :W => @metrics.glyph_widths,
341
- :CIDToGIDMap => :Identity )
342
-
343
- to_unicode_content = @metrics.to_unicode_cmap.to_s
344
- compressed_to_unicode = Zlib::Deflate.deflate(to_unicode_content)
345
-
346
- to_unicode = @document.ref(:Length => compressed_to_unicode.size,
347
- :Length1 => to_unicode_content.size,
348
- :Filter => :FlateDecode )
349
- to_unicode << compressed_to_unicode
350
-
351
- @reference = @document.ref(:Type => :Font,
352
- :Subtype => :Type0,
353
- :BaseFont => basename,
354
- :DescendantFonts => [descendant],
355
- :Encoding => :"Identity-H",
356
- :ToUnicode => to_unicode)
357
-
358
- end
271
+ def size
272
+ @document.font_size
273
+ end
359
274
 
360
275
  end
361
-
276
+
362
277
  end