combine_pdf 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 169d63fc09f86f09a633e199582c65212fbcd158
4
- data.tar.gz: 6f5d94234603827a33100c77e4b66ac41492c60c
3
+ metadata.gz: 91a403f449ba29c772a9e6d12e114e0271129ecb
4
+ data.tar.gz: 9b94530e869fe1a5936706305c2407eeeb9f35a7
5
5
  SHA512:
6
- metadata.gz: ffb49820460e29f7d6d857fe6f66af7a9b0f97edae28a2ab1caa814eb5e84d521f91b76e091b2b33fe36f716684253a30fc51cc777e8696c5ee09ed21ebae0ae
7
- data.tar.gz: fb6e175436280fd64499684151f29c7cf9254ca21be6a0052e42f80c6d29ede70ed982afbf7aef07fd31cbcf88c460f9eb1a84bea3f363a74ac78d3bb5bc44e2
6
+ metadata.gz: ce4a31ce78d6ff246f51ced6567b73fb5b5905cfbcf43fa2d980996d16e66570e1777a350cec53527d5772eae07be8dfc768f7b68811505428e4788cb55e195f
7
+ data.tar.gz: 9fc48d3e72643e48b179ceb01d755fc928585b5d911f53bc83fa96f41c87353c46a517966c9c094ff0e116dcb95010d7aced07cb3aafe1a12ea8d0c1b21da2bd
@@ -37,9 +37,12 @@ require "combine_pdf/font_metrics/metrics_dictionary.rb"
37
37
  # == Combine / Merge
38
38
  # To combine PDF files (or data):
39
39
  # pdf = CombinePDF.new
40
- # pdf << CombinePDF.new "file1.pdf" # one way to combine, very fast.
40
+ # pdf << CombinePDF.new("file1.pdf") # one way to combine, very fast.
41
41
  # CombinePDF.new("file2.pdf").pages.each {|page| pdf << page} # different way to combine, slower.
42
42
  # pdf.save "combined.pdf"
43
+ #
44
+ # Or, you can do it all in one line:
45
+ # ( CombinePDF.new("file1.pdf") << CombinePDF.new("file2.pdf") << CombinePDF.new("file3.pdf") ).save "combined.pdf"
43
46
  # == Stamp / Watermark
44
47
  # <b>has issues with specific PDF files - please see the issues</b>: https://github.com/boazsegev/combine_pdf/issues/2
45
48
  # To combine PDF files (or data), first create the stamp from a PDF file:
@@ -50,6 +53,10 @@ require "combine_pdf/font_metrics/metrics_dictionary.rb"
50
53
  # pdf.pages.each {|page| page << stamp_page}
51
54
  # Notice the << operator is on a page and not a PDF object. The << operator acts differently on PDF objects and on Pages.
52
55
  #
56
+ # The << operator defaults to secure injection by renaming references to avoid conflics. For overlaying pages using compressed data that might not be editable (due to limited filter support), you can use:
57
+ # pdf.pages(nil, false).each {|page| page << stamp_page}
58
+ #
59
+ #
53
60
  # Notice that page objects are Hash class objects and the << operator was added to the Page instances without altering the class.
54
61
  #
55
62
  # == Decryption & Filters
@@ -15,7 +15,7 @@ module CombinePDF
15
15
  #
16
16
  # <b>This doesn't work yet!</b>
17
17
  #
18
- # and alsom, for even when it will work, UNICODE SUPPORT IS MISSING!
18
+ # and also, even when it will work, UNICODE SUPPORT IS MISSING!
19
19
  #
20
20
  # in the future I wish to make a simple PDF page writer, that has only one functions - the text box.
21
21
  # Once the simple writer is ready (creates a text box in a self contained Page element),
@@ -26,7 +26,9 @@ module CombinePDF
26
26
  #
27
27
  # Writing on this Page is done using the text_box function.
28
28
  #
29
- # the rest of the functions are for internal use.
29
+ # Setting the page dimentions can be either at the new or using the media_box method.
30
+ #
31
+ # the rest of the methods are for internal use.
30
32
  #
31
33
  # Once the Page is completed (the last text box was added),
32
34
  # we can insert the page to a CombinePDF object.
@@ -53,16 +55,6 @@ module CombinePDF
53
55
  self[:Contents] = { is_reference_only: true , referenced_object: {indirect_reference_id: 0, raw_stream_content: ""} }
54
56
  self[:MediaBox] = media_box
55
57
  end
56
-
57
- # accessor (getter) for the :Resources element of the page
58
- def resources
59
- self[:Resources]
60
- end
61
- # accessor (getter) for the stream in the :Contents element of the page
62
- # after getting the string object, you can operate on it but not replace it (use << or other String methods).
63
- def contents
64
- self[:Contents][:referenced_object][:raw_stream_content]
65
- end
66
58
  # accessor (getter) for the :MediaBox element of the page
67
59
  def media_box
68
60
  self[:MediaBox]
@@ -72,73 +64,6 @@ module CombinePDF
72
64
  def media_box=(dimentions = [0.0, 0.0, 612.0, 792.0])
73
65
  self[:MediaBox] = dimentions
74
66
  end
75
- # creates a font object and adds the font to the resources dictionary
76
- # returns the name of the font for the content stream.
77
- # font_name:: a Symbol of one of the 14 Type 1 fonts, known as the standard 14 fonts:
78
- # - :"Times-Roman"
79
- # - :"Times-Bold"
80
- # - :"Times-Italic"
81
- # - :"Times-BoldItalic"
82
- # - :Helvetica
83
- # - :"Helvetica-Bold"
84
- # - :"Helvetica-BoldOblique"
85
- # - :"Helvetica- Oblique"
86
- # - :Courier
87
- # - :"Courier-Bold"
88
- # - :"Courier-Oblique"
89
- # - :"Courier-BoldOblique"
90
- # - :Symbol
91
- # - :ZapfDingbats
92
- def font(font_name = :Helvetica)
93
- # refuse any other fonts that arn't basic standard fonts
94
- allow_fonts = [ :"Times-Roman",
95
- :"Times-Bold",
96
- :"Times-Italic",
97
- :"Times-BoldItalic",
98
- :Helvetica,
99
- :"Helvetica-Bold",
100
- :"Helvetica-BoldOblique",
101
- :"Helvetica-Oblique",
102
- :Courier,
103
- :"Courier-Bold",
104
- :"Courier-Oblique",
105
- :"Courier-BoldOblique",
106
- :Symbol,
107
- :ZapfDingbats ]
108
- raise "add_font(font_name) accepts only one of the 14 standards fonts - wrong font_name!" unless allow_fonts.include? font_name
109
- # if the font exists, return it's name
110
- resources[:Font] ||= {}
111
- resources[:Font].each do |k,v|
112
- if v.is_a?(Hash) && v[:Type] == :Font && v[:BaseFont] == font_name
113
- return k
114
- end
115
- end
116
- # create font object
117
- font_object = { Type: :Font, Subtype: :Type1, BaseFont: font_name}
118
- # set a secure name for the font
119
- name = (SecureRandom.urlsafe_base64(9)).to_sym
120
- # add object to reasource
121
- resources[:Font][name] = font_object
122
- #return name
123
- name
124
- end
125
- def graphic_state(graphic_state_dictionary = {})
126
- # if the graphic state exists, return it's name
127
- resources[:ExtGState] ||= {}
128
- resources[:ExtGState].each do |k,v|
129
- if v.is_a?(Hash) && v == graphic_state_dictionary
130
- return k
131
- end
132
- end
133
- # set graphic state type
134
- graphic_state_dictionary[:Type] = :ExtGState
135
- # set a secure name for the graphic state
136
- name = (SecureRandom.urlsafe_base64(9)).to_sym
137
- # add object to reasource
138
- resources[:ExtGState][name] = graphic_state_dictionary
139
- #return name
140
- name
141
- end
142
67
 
143
68
  # <b>INCOMPLETE</b>
144
69
  #
@@ -226,6 +151,84 @@ module CombinePDF
226
151
  self
227
152
  end
228
153
 
154
+ protected
155
+
156
+ # accessor (getter) for the :Resources element of the page
157
+ def resources
158
+ self[:Resources]
159
+ end
160
+ # accessor (getter) for the stream in the :Contents element of the page
161
+ # after getting the string object, you can operate on it but not replace it (use << or other String methods).
162
+ def contents
163
+ self[:Contents][:referenced_object][:raw_stream_content]
164
+ end
165
+ # creates a font object and adds the font to the resources dictionary
166
+ # returns the name of the font for the content stream.
167
+ # font_name:: a Symbol of one of the 14 Type 1 fonts, known as the standard 14 fonts:
168
+ # - :"Times-Roman"
169
+ # - :"Times-Bold"
170
+ # - :"Times-Italic"
171
+ # - :"Times-BoldItalic"
172
+ # - :Helvetica
173
+ # - :"Helvetica-Bold"
174
+ # - :"Helvetica-BoldOblique"
175
+ # - :"Helvetica- Oblique"
176
+ # - :Courier
177
+ # - :"Courier-Bold"
178
+ # - :"Courier-Oblique"
179
+ # - :"Courier-BoldOblique"
180
+ # - :Symbol
181
+ # - :ZapfDingbats
182
+ def font(font_name = :Helvetica)
183
+ # refuse any other fonts that arn't basic standard fonts
184
+ allow_fonts = [ :"Times-Roman",
185
+ :"Times-Bold",
186
+ :"Times-Italic",
187
+ :"Times-BoldItalic",
188
+ :Helvetica,
189
+ :"Helvetica-Bold",
190
+ :"Helvetica-BoldOblique",
191
+ :"Helvetica-Oblique",
192
+ :Courier,
193
+ :"Courier-Bold",
194
+ :"Courier-Oblique",
195
+ :"Courier-BoldOblique",
196
+ :Symbol,
197
+ :ZapfDingbats ]
198
+ raise "add_font(font_name) accepts only one of the 14 standards fonts - wrong font_name!" unless allow_fonts.include? font_name
199
+ # if the font exists, return it's name
200
+ resources[:Font] ||= {}
201
+ resources[:Font].each do |k,v|
202
+ if v.is_a?(Hash) && v[:Type] == :Font && v[:BaseFont] == font_name
203
+ return k
204
+ end
205
+ end
206
+ # create font object
207
+ font_object = { Type: :Font, Subtype: :Type1, BaseFont: font_name}
208
+ # set a secure name for the font
209
+ name = (SecureRandom.urlsafe_base64(9)).to_sym
210
+ # add object to reasource
211
+ resources[:Font][name] = font_object
212
+ #return name
213
+ name
214
+ end
215
+ def graphic_state(graphic_state_dictionary = {})
216
+ # if the graphic state exists, return it's name
217
+ resources[:ExtGState] ||= {}
218
+ resources[:ExtGState].each do |k,v|
219
+ if v.is_a?(Hash) && v == graphic_state_dictionary
220
+ return k
221
+ end
222
+ end
223
+ # set graphic state type
224
+ graphic_state_dictionary[:Type] = :ExtGState
225
+ # set a secure name for the graphic state
226
+ name = (SecureRandom.urlsafe_base64(9)).to_sym
227
+ # add object to reasource
228
+ resources[:ExtGState][name] = graphic_state_dictionary
229
+ #return name
230
+ name
231
+ end
229
232
  end
230
233
 
231
234
  end
@@ -10,29 +10,26 @@
10
10
 
11
11
  module CombinePDF
12
12
 
13
- ########################################################
14
- ## This is the Parser class.
15
- ## It takes PDF data and parses it, returning an array
16
- ## of data.
17
- ## That array can be used to initialize a PDF object.
18
- ## The Parser class doesn't involve itself with the
19
- ## file version.
20
- ########################################################
21
13
 
14
+ #######################################################
22
15
  #@private
23
16
  #:nodoc: all
17
+ # This is the Parser class.
18
+ #
19
+ # It takes PDF data and parses it.
20
+ #
21
+ # The information is then used to initialize a PDF object.
22
+ #######################################################
24
23
  class PDFParser
25
- # LITERAL_STRING_REPLACEMENT_HASH = {
26
- # 110 => 10, # "\\n".bytes = [92, 110] "\n".ord = 10
27
- # 114 => 13, #r
28
- # 116 => 9, #t
29
- # 98 => 8, #b
30
- # 102 => 255, #f
31
- # 40 => 40, #(
32
- # 41 => 41, #)
33
- # 92 => 92 #\
34
- # }
35
- attr_reader :parsed, :version, :info_object, :root_object
24
+
25
+ # the array containing all the parsed data (PDF Objects)
26
+ attr_reader :parsed
27
+ # a Float representing the PDF version of the data parsed (if exists).
28
+ attr_reader :version
29
+ # the info and root objects, as found (if found) in the PDF file.
30
+ #
31
+ # they are mainly to used to know if the file is (was) encrypted and to get more details.
32
+ attr_reader :info_object, :root_object
36
33
  def initialize (string)
37
34
  raise TypeError, "couldn't parse and data, expecting type String" unless string.is_a? String
38
35
  @string_to_parse = string.force_encoding(Encoding::ASCII_8BIT)
@@ -46,6 +43,7 @@ module CombinePDF
46
43
  @scanner = nil
47
44
  end
48
45
 
46
+ # parse the data in the parser (set in the initialize / new method)
49
47
  def parse
50
48
  return @parsed unless @parsed.empty?
51
49
  @scanner = StringScanner.new @string_to_parse
@@ -38,13 +38,13 @@ module CombinePDF
38
38
  # use, for example:
39
39
  # pdf.info[:Title] = "title"
40
40
  attr_reader :info
41
- # sets the string output format (PDF files store strings in to type of formats).
41
+ # gets/sets the string output format (PDF files store strings in to type of formats).
42
42
  #
43
43
  # Accepts:
44
44
  # - :literal
45
45
  # - :hex
46
46
  attr_accessor :string_output
47
- # A Float attrinute, setting and returning the PDF version of the file (1.1-1.7).
47
+ # set/get the PDF version of the file (1.1-1.7) - shuold be type Float.
48
48
  attr_accessor :version
49
49
  def initialize (*args)
50
50
  # default before setting
@@ -139,8 +139,18 @@ module CombinePDF
139
139
  # This method also adds the << operator to each page instance, so that content can be
140
140
  # injected to the pages, as described above.
141
141
  #
142
+ # if the secure_injection is false, then the << operator will not alter the any of the information added to the page.
143
+ # this might cause conflicts in the added content, but is available for situations in which
144
+ # the content added is compressed using unsupported filters or options.
145
+ #
146
+ # the default is for the << operator to attempt a secure copy, by attempting to rename the content references and avoiding conflicts.
147
+ # because of not all PDF files are created equal (some might have formating errors or differences), it is imposiible to learn if the attempt wa successful.
148
+ #
142
149
  # (page objects are Hash class objects. the << operator is added to the specific instances without changing the class)
143
- def pages(catalogs = nil)
150
+ #
151
+ # catalogs:: a catalog, or an Array of catalog objects. defaults to the existing catalog.
152
+ # secure_injection:: a boolean (true / false) controling the behavior of the << operator.
153
+ def pages(catalogs = nil, secure_injection = true)
144
154
  page_list = []
145
155
  if catalogs == nil
146
156
  catalogs = @objects.select {|obj| obj.is_a?(Hash) && obj[:Type] == :Catalog}
@@ -161,11 +171,20 @@ module CombinePDF
161
171
  case catalogs[:Type]
162
172
  when :Page
163
173
  holder = self
164
- catalogs.define_singleton_method("<<".to_sym) do |obj|
165
- obj = PDFOperations.copy_and_secure_for_injection obj
166
- PDFOperations.inject_to_page self, obj
167
- holder.add_referenced self # add new referenced objects
168
- self
174
+ if secure_injection
175
+ catalogs.define_singleton_method("<<".to_sym) do |obj|
176
+ obj = PDFOperations.copy_and_secure_for_injection obj
177
+ PDFOperations.inject_to_page self, obj
178
+ holder.add_referenced self # add new referenced objects
179
+ self
180
+ end
181
+ else
182
+ catalogs.define_singleton_method("<<".to_sym) do |obj|
183
+ obj = PDFOperations.create_deep_copy obj
184
+ PDFOperations.inject_to_page self, obj
185
+ holder.add_referenced self # add new referenced objects
186
+ self
187
+ end
169
188
  end
170
189
  page_list << catalogs
171
190
  when :Pages
@@ -222,30 +241,62 @@ module CombinePDF
222
241
  end
223
242
 
224
243
  # get the title for the pdf
225
- # The title is stored in the information dictionary and isn't requited
244
+ # The title is stored in the information dictionary and isn't required
226
245
  def title
227
246
  return @info[:Title]
228
247
  end
229
248
  # set the title for the pdf
230
- # The title is stored in the information dictionary and isn't requited
249
+ # The title is stored in the information dictionary and isn't required
231
250
  # new_title:: a string that is the new author value.
232
251
  def title=(new_title = nil)
233
252
  @info[:Title] = new_title
234
253
  end
235
- # get the author value for the pdf
236
- # The author is stored in the information dictionary and isn't requited
254
+ # get the author value for the pdf.
255
+ # The author is stored in the information dictionary and isn't required
237
256
  def author
238
257
  return @info[:Author]
239
258
  end
240
- # set the author for the pdf
241
- # The author is stored in the information dictionary and isn't requited
259
+ # set the author value for the pdf.
260
+ # The author is stored in the information dictionary and isn't required
261
+ #
242
262
  # new_title:: a string that is the new author value.
243
263
  def author=(new_author = nil)
244
264
  @info[:Author] = new_author
245
265
  end
246
266
  end
247
267
  class PDF #:nodoc: all
248
-
268
+ # @private
269
+ # Some PDF objects contain references to other PDF objects.
270
+ #
271
+ # this function adds the references contained in "object", but DOESN'T add the object itself.
272
+ #
273
+ # this is used for internal operations, such as injectng data using the << operator.
274
+ def add_referenced(object)
275
+ # add references but not root
276
+ case
277
+ when object.is_a?(Array)
278
+ object.each {|it| add_referenced(it)}
279
+ when object.is_a?(Hash)
280
+ if object[:is_reference_only] && object[:referenced_object]
281
+ unless @objects.include? object[:referenced_object]
282
+ @objects << object[:referenced_object]
283
+ object[:referenced_object].each do |k, v|
284
+ add_referenced(v) unless k == :Parent
285
+ end
286
+ end
287
+ else
288
+ object.each do |k, v|
289
+ add_referenced(v) unless k == :Parent
290
+ end
291
+ end
292
+ end
293
+ end
294
+ # @private
295
+ # run block of code on evey object (Hash)
296
+ def each_object(&block)
297
+ PDFOperations._each_object(@objects, &block)
298
+ end
299
+ protected
249
300
  # @private
250
301
  # this function returns all the Page objects - regardless of order and even if not cataloged
251
302
  # could be used for finding "lost" pages... but actually rather useless.
@@ -339,31 +390,8 @@ module CombinePDF
339
390
  end
340
391
  end
341
392
 
342
- # @private
343
- def add_referenced(object)
344
- # add references but not root
345
- case
346
- when object.is_a?(Array)
347
- object.each {|it| add_referenced(it)}
348
- when object.is_a?(Hash)
349
- if object[:is_reference_only] && object[:referenced_object]
350
- unless @objects.include? object[:referenced_object]
351
- @objects << object[:referenced_object]
352
- object[:referenced_object].each do |k, v|
353
- add_referenced(v) unless k == :Parent
354
- end
355
- end
356
- else
357
- object.each do |k, v|
358
- add_referenced(v) unless k == :Parent
359
- end
360
- end
361
- end
362
- end
363
393
  # @private
364
394
  def rebuild_catalog(*with_pages)
365
- ##########################
366
- ## Test-Run - How is that done?
367
395
  warn "Re-Building Catalog"
368
396
 
369
397
  # # build page list v.1 Slow but WORKS
@@ -373,7 +401,7 @@ module CombinePDF
373
401
  # page_list = []
374
402
  # PDFOperations._each_object(old_catalogs,false) { |p| page_list << p if p.is_a?(Hash) && p[:Type] == :Page }
375
403
 
376
- # build page list v.2
404
+ # build page list v.2 faster, better, and works
377
405
  # Benchmark testing value: 0.215114
378
406
  page_list = pages
379
407
 
@@ -458,12 +486,6 @@ module CombinePDF
458
486
  # rebuild stream lengths?
459
487
  end
460
488
 
461
- # @private
462
- # run block of code on evey object (Hash)
463
- def each_object(&block)
464
- PDFOperations._each_object(@objects, &block)
465
- end
466
-
467
489
  # @private
468
490
  # the function rerturns true if the reference belongs to the object
469
491
  def compare_reference_values(obj, ref)
@@ -1,5 +1,6 @@
1
1
  module CombinePDF
2
2
  class PDFWriter < Hash
3
+ protected
3
4
  # with thanks to Jan Krutisch, the creator of the afm gem.
4
5
  COURIER_BOLD_METRICS =
5
6
  {"space"=>{:charcode=>32,
@@ -1,5 +1,6 @@
1
1
  module CombinePDF
2
2
  class PDFWriter < Hash
3
+ protected
3
4
  # with thanks to Jan Krutisch, the creator of the afm gem.
4
5
  COURIER_BOLDOBLIQUE_METRICS =
5
6
  {"space"=>{:charcode=>32,
@@ -1,5 +1,6 @@
1
1
  module CombinePDF
2
2
  class PDFWriter < Hash
3
+ protected
3
4
  # with thanks to Jan Krutisch, the creator of the afm gem.
4
5
  COURIER_OBLIQUE_METRICS =
5
6
  {"space"=>{:charcode=>32,
@@ -1,5 +1,6 @@
1
1
  module CombinePDF
2
2
  class PDFWriter < Hash
3
+ protected
3
4
  # with thanks to Jan Krutisch, the creator of the afm gem.
4
5
  COURIER_METRICS =
5
6
  {"space"=>{:charcode=>32,
@@ -1,5 +1,6 @@
1
1
  module CombinePDF
2
2
  class PDFWriter < Hash
3
+ protected
3
4
  # with thanks to Jan Krutisch, the creator of the afm gem.
4
5
  HELVETICA_BOLD_METRICS =
5
6
  {"space"=>{:charcode=>32,
@@ -1,5 +1,6 @@
1
1
  module CombinePDF
2
2
  class PDFWriter < Hash
3
+ protected
3
4
  # with thanks to Jan Krutisch, the creator of the afm gem.
4
5
  HELVETICA_BOLDOBLIQUE_METRICS =
5
6
  {"space"=>{:charcode=>32,
@@ -1,5 +1,6 @@
1
1
  module CombinePDF
2
2
  class PDFWriter < Hash
3
+ protected
3
4
  # with thanks to Jan Krutisch, the creator of the afm gem.
4
5
  HELVETICA_OBLIQUE_METRICS =
5
6
  {"space"=>{:charcode=>32,
@@ -1,5 +1,6 @@
1
1
  module CombinePDF
2
2
  class PDFWriter < Hash
3
+ protected
3
4
  # with thanks to Jan Krutisch, the creator of the afm gem.
4
5
  HELVETICA_METRICS =
5
6
  {"space"=>{:charcode=>32,
@@ -1,5 +1,6 @@
1
1
  module CombinePDF
2
2
  class PDFWriter < Hash
3
+ protected
3
4
  METRICS_DICTIONARY = {
4
5
  :"Times-Roman" => TIMES_ROMAN_METRICS,
5
6
  :"Times-Bold" => TIMES_BOLD_METRICS,
@@ -1,5 +1,6 @@
1
1
  module CombinePDF
2
2
  class PDFWriter < Hash
3
+ protected
3
4
  # with thanks to Jan Krutisch, the creator of the afm gem.
4
5
  SYMBOL_METRICS =
5
6
  {"space"=>{:charcode=>32,
@@ -1,5 +1,6 @@
1
1
  module CombinePDF
2
2
  class PDFWriter < Hash
3
+ protected
3
4
  # with thanks to Jan Krutisch, the creator of the afm gem.
4
5
  TIMES_BOLD_METRICS =
5
6
  {"space"=>{:charcode=>32,
@@ -1,5 +1,6 @@
1
1
  module CombinePDF
2
2
  class PDFWriter < Hash
3
+ protected
3
4
  # with thanks to Jan Krutisch, the creator of the afm gem.
4
5
  TIMES_BOLDITALIC_METRICS =
5
6
  {"space"=>{:charcode=>32,
@@ -1,5 +1,6 @@
1
1
  module CombinePDF
2
2
  class PDFWriter < Hash
3
+ protected
3
4
  # with thanks to Jan Krutisch, the creator of the afm gem.
4
5
  TIMES_ITALIC_METRICS =
5
6
  {"space"=>{:charcode=>32,
@@ -1,5 +1,6 @@
1
1
  module CombinePDF
2
2
  class PDFWriter < Hash
3
+ protected
3
4
  # with thanks to Jan Krutisch, the creator of the afm gem.
4
5
  TIMES_ROMAN_METRICS =
5
6
  {"space"=>{:charcode=>32,
@@ -1,5 +1,6 @@
1
1
  module CombinePDF
2
2
  class PDFWriter < Hash
3
+ protected
3
4
  # with thanks to Jan Krutisch, the creator of the afm gem.
4
5
  ZAPFDINGBATS_METRICS =
5
6
  {"space"=>{:charcode=>32,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: combine_pdf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev