combine_pdf 0.1.1 → 0.1.2

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: 1415b642f2d84f101f6f444d16191faa35d3a6b9
4
- data.tar.gz: aa872079b6576afd266bcb2b628772e80e33b9b8
3
+ metadata.gz: c5d50f2ddbf6142442857b65ec46d9565ae774e2
4
+ data.tar.gz: caaa8ac30c72919c54d28d21a4d30979a40ff41e
5
5
  SHA512:
6
- metadata.gz: 78ada1b24bc160cc492b272dd31a1115a76dd217baebbac78fc259a077720427c837c053c5fe54cdfab6f84629142a45275629a714f693a6e8416bf47cb3bfa7
7
- data.tar.gz: 03ced7106be2f831f5dc51df810d810f1f8b1828f8d6364800eb4d248764d30a6e67281b5d34d40fdbe5581673e9da1bed7a494f094e4a7ef4d6550c6e2984f2
6
+ metadata.gz: 0814bd7cfdfbd06d58506dc83f2160099bb6741c60625279850b6d8f525fa970228ce99425223a54998136cecff3593e1530bd0e77f5071d931a173bc26128ff
7
+ data.tar.gz: 88230912c86e10a0949c63c0a10b358da411a96a615860bd8c62985c2c62ff4d98a05b0fb5982e9f6fab7a6fb3cd8d049254660d6c1c449e84c5922783cf7552
data/lib/combine_pdf.rb CHANGED
@@ -184,6 +184,114 @@ module CombinePDF
184
184
  PDFWriter.new mediabox
185
185
  end
186
186
 
187
+ # makes a PDF object containing a table
188
+ #
189
+ # all the pages in this PDF object are PDFWriter objects and are
190
+ # writable using the texbox function (should you wish to add a title, or more info)
191
+ #
192
+ # the main intended use of this method is to create indexes (a table of contents) for merged data.
193
+ #
194
+ # example:
195
+ # pdf = CombinePDF.new_table headers: ["header 1", "another header"], table_data: [ ["this is one row", "with two columns"] , ["this is another row", "also two columns", "the third will be ignored"] ]
196
+ # pdf.save "table_file.pdf"
197
+ #
198
+ # accepts a Hash with any of the following keys as well as any of the PDFWriter#textbox options:
199
+ # headers:: an Array of strings with the headers (will be repeated every page).
200
+ # table_data:: as Array of Arrays, each containing a string for each column. the first row sets the number of columns. extra columns will be ignored.
201
+ # font:: a registered or standard font name (see PDFWriter). defaults to nil (:Helvetica).
202
+ # header_font:: a registered or standard font name for the headers (see PDFWriter). defaults to nil (the font for all the table rows).
203
+ # max_font_size:: the maximum font size. if the string doesn't fit, it will be resized. defaults to 14.
204
+ # column_widths:: an array of relative column widths ([1,2] will display only the first two columns, the second twice as big as the first). defaults to nil (even widths).
205
+ # header_color:: the header color. defaults to [0.8, 0.8, 0.8] (light gray).
206
+ # main_color:: main row color. defaults to nil (transparent / white).
207
+ # alternate_color: alternate row color. defaults to [0.95, 0.95, 0.95] (very light gray).
208
+ # font_color: font color. defaults to [0,0,0] (black).
209
+ # border_color: border color. defaults to [0,0,0] (black).
210
+ # border_width: border width in PDF units. defaults to 1.
211
+ # header_align: the header text alignment within each column (:right, :left, :center). defaults to :center.
212
+ # row_align:: the row text alignment within each column. defaults to :left (:right for RTL table).
213
+ # direction: the table's writing direction (:ltr or :rtl). this reffers to the direction of the columns and doesn't effect text (rtl text is automatically recognized). defaults to :ltr.
214
+ # rows_per_page: the number of rows per page, INCLUDING the header row. deafults to 25.
215
+ # page_size: the size of the page in PDF points. defaults to [0, 0, 595.3, 841.9] (A4).
216
+ def new_table (options = {})
217
+ defaults = {
218
+ headers: nil,
219
+ table_data: [[]],
220
+ font: nil,
221
+ header_font: nil,
222
+ max_font_size: 14,
223
+ column_widths: nil,
224
+ header_color: [0.8, 0.8, 0.8],
225
+ main_color: nil,
226
+ alternate_color: [0.95, 0.95, 0.95],
227
+ font_color: [0,0,0],
228
+ border_color: [0,0,0],
229
+ border_width: 1,
230
+ header_align: :center,
231
+ row_align: nil,
232
+ direction: :ltr,
233
+ rows_per_page: 25,
234
+ page_size: [0, 0, 595.3, 841.9] #A4
235
+ }
236
+ options = defaults.merge options
237
+ options[:header_font] = options[:font] unless options[:header_font]
238
+ options[:row_align] ||= ( (options[:direction] == :rtl) ? :right : :left )
239
+ # assert table_data is an array of arrays
240
+ return false unless (options[:table_data].select {|r| !r.is_a?(Array) }).empty?
241
+ # compute sizes
242
+ page_size = options[:page_size]
243
+ top = page_size[3] * 0.9
244
+ height = page_size[3] * 0.8 / options[:rows_per_page]
245
+ from_side = page_size[2] * 0.1
246
+ width = page_size[2] * 0.8
247
+ columns = options[:table_data][0].length
248
+ column_widths = []
249
+ columns.times {|i| column_widths << (width/columns) }
250
+ if options[:column_widths]
251
+ scale = 0
252
+ options[:column_widths].each {|w| scale += w}
253
+ column_widths = []
254
+ options[:column_widths].each { |w| column_widths << (width*w/scale) }
255
+ end
256
+ column_widths = column_widths.reverse if options[:direction] == :rtl
257
+ # set pdf object and start writing the data
258
+ table = PDF.new()
259
+ page = nil
260
+ rows_per_page = options[:rows_per_page]
261
+ row_number = rows_per_page + 1
262
+
263
+ options[:table_data].each do |row_data|
264
+ if row_number > rows_per_page
265
+ page = create_page page_size
266
+ table << page
267
+ row_number = 1
268
+ # add headers
269
+ if options[:headers]
270
+ x = from_side
271
+ headers = options[:headers]
272
+ headers = headers.reverse if options[:direction] == :rtl
273
+ column_widths.each_index do |i|
274
+ text = headers[i].to_s
275
+ page.textbox text, {x: x, y: (top - (height*row_number)), width: column_widths[i], height: height, box_color: options[:header_color], text_align: options[:header_align] }.merge(options).merge({font: options[:header_font]})
276
+ x += column_widths[i]
277
+ end
278
+ row_number += 1
279
+ end
280
+ end
281
+ x = from_side
282
+ row_data = row_data.reverse if options[:direction] == :rtl
283
+ column_widths.each_index do |i|
284
+ text = row_data[i].to_s
285
+ box_color = options[:main_color]
286
+ box_color = options[:alternate_color] if options[:alternate_color] && row_number.odd?
287
+ page.textbox text, {x: x, y: (top - (height*row_number)), width: column_widths[i], height: height, box_color: box_color, text_align: options[:row_align]}.merge(options)
288
+ x += column_widths[i]
289
+ end
290
+ row_number += 1
291
+ end
292
+ table
293
+ end
294
+
187
295
  # adds a correctly formatted font object to the font library.
188
296
  #
189
297
  # registered fonts will remain in the library and will only be embeded in
@@ -72,6 +72,7 @@ module CombinePDF
72
72
  # height:: the height of the box. negative values will be computed from edge of page. defaults to 0 (end of page).
73
73
  # text_align:: symbol for horizontal text alignment, can be ":center" (default), ":right", ":left"
74
74
  # text_valign:: symbol for vertical text alignment, can be ":center" (default), ":top", ":buttom"
75
+ # text_padding:: a Float between 0 and 1, setting the padding for the text. defaults to 0.05 (5%).
75
76
  # font:: a registered font name or an Array of names. defaults to ":Helvetica". The 14 standard fonts names are:
76
77
  # - :"Times-Roman"
77
78
  # - :"Times-Bold"
@@ -105,6 +106,7 @@ module CombinePDF
105
106
  height: -1,
106
107
  text_align: :center,
107
108
  text_valign: :center,
109
+ text_padding: 0.1,
108
110
  font: nil,
109
111
  font_size: :fit_text,
110
112
  max_font_size: nil,
@@ -122,6 +124,9 @@ module CombinePDF
122
124
  options[:width] = mediabox[2] - options[:x] + options[:width] if options[:width] <= 0
123
125
  options[:height] = mediabox[3] - options[:y] + options[:height] if options[:height] <= 0
124
126
 
127
+ # reset the padding value
128
+ options[:text_padding] = 0 if options[:text_padding].to_f >= 1
129
+
125
130
  # create box stream
126
131
  box_stream = ""
127
132
  # set graphic state for box
@@ -199,29 +204,29 @@ module CombinePDF
199
204
  text_stream = ""
200
205
  if text.to_s != "" && options[:font_size] != 0 && (options[:font_color] || options[:stroke_color])
201
206
  # compute x and y position for text
202
- x = options[:x]
203
- y = options[:y]
207
+ x = options[:x] + (options[:width]*options[:text_padding])
208
+ y = options[:y] + (options[:height]*options[:text_padding])
204
209
 
205
210
  # set the fonts (fonts array, with :Helvetica as fallback).
206
211
  fonts = [*options[:font], :Helvetica]
207
212
  # fit text in box, if requested
208
213
  font_size = options[:font_size]
209
214
  if options[:font_size] == :fit_text
210
- font_size = self.fit_text text, fonts, options[:width], options[:height]
215
+ font_size = self.fit_text text, fonts, (options[:width]*(1-options[:text_padding])), (options[:height]*(1-options[:text_padding]))
211
216
  font_size = options[:max_font_size] if options[:max_font_size] && font_size > options[:max_font_size]
212
217
  end
213
218
 
214
219
  text_size = dimensions_of text, fonts, font_size
215
220
 
216
221
  if options[:text_align] == :center
217
- x = (options[:width] - text_size[0])/2 + x
222
+ x = ( ( options[:width]*(1-(2*options[:text_padding])) ) - text_size[0] )/2 + x
218
223
  elsif options[:text_align] == :right
219
- x = (options[:width] - text_size[0]) + x
224
+ x = ( ( options[:width]*(1-(1.5*options[:text_padding])) ) - text_size[0] ) + x
220
225
  end
221
226
  if options[:text_valign] == :center
222
- y = (options[:height] - text_size[1])/2 + y
227
+ y = ( ( options[:height]*(1-(2*options[:text_padding])) ) - text_size[1] )/2 + y
223
228
  elsif options[:text_valign] == :top
224
- y = (options[:height] - text_size[1]) + y
229
+ y = ( options[:height]*(1-(1.5*options[:text_padding])) ) - text_size[1] + y
225
230
  end
226
231
 
227
232
  # set graphic state for text
@@ -217,7 +217,11 @@ module CombinePDF
217
217
  old_widths = font_object[:DescendantFonts]
218
218
  old_widths = old_widths[:referenced_object][:indirect_without_dictionary] if old_widths[:is_reference_only]
219
219
  old_widths = old_widths[0][:referenced_object]
220
- avarage_bbox = [0, 0, 0, 0] # data is missing for full box metrics, just ignore
220
+ avrg_height = 360
221
+ avrg_height = old_widths[:XHeight] if old_widths[:XHeight]
222
+ avrg_height = (avrg_height + old_widths[:CapHeight])/2 if old_widths[:CapHeight]
223
+ avrg_width = old_widths[:AvgWidth] || 0
224
+ avarage_bbox = [0, 0, avrg_width, avrg_height] # data is missing for full box metrics, just ignore
221
225
  end
222
226
 
223
227
  # compute the metrics values using the appropiate system (TrueType vs. Type0 fonts)
@@ -87,17 +87,32 @@ module CombinePDF
87
87
  @info = {}
88
88
  if args[0].is_a? PDFParser
89
89
  @objects = args[0].parse
90
+ # connecting references with original objects
91
+ serialize_objects_and_references
92
+ # make sure there is only one Catalog (the latest Catalog)
93
+ if args[0].root_object[:Root]
94
+ @objects.delete_if {|obj| obj[:Type] == :Catalog}
95
+ @objects << args[0].root_object[:Root]
96
+ else
97
+ last_calalog = (@objects.select {|obj| obj[:Type] == :Catalog}).last
98
+ unless last_calalog.nil?
99
+ @objects.delete_if {|obj| obj[:Type] == :Catalog}
100
+ @objects << last_calalog
101
+ end
102
+ end
90
103
  @version = args[0].version if args[0].version.is_a? Float
91
104
  @info = args[0].info_object || {}
92
105
  elsif args[0].is_a? Array
93
106
  # object initialization
94
107
  @objects = args[0]
95
108
  @version = args[1] if args[1].is_a? Float
109
+ # connecting references with original objects
110
+ serialize_objects_and_references
96
111
  elsif args[0].is_a? Hash
97
112
  @objects = args
113
+ # connecting references with original objects
114
+ serialize_objects_and_references
98
115
  end
99
- # connecting references with original objects
100
- serialize_objects_and_references
101
116
  # general globals
102
117
  @string_output = :literal
103
118
  @need_to_rebuild_resources = false
@@ -224,6 +239,10 @@ module CombinePDF
224
239
  self
225
240
  end
226
241
  end
242
+ catalogs[:MediaBox] ||= catalogs[:Parent][:referenced_object][:MediaBox] if catalogs[:Parent].is_a?(Hash) && catalogs[:Parent][:referenced_object].is_a?(Hash) && catalogs[:Parent][:referenced_object][:MediaBox]
243
+ catalogs[:CropBox] ||= catalogs[:Parent][:referenced_object][:CropBox] if catalogs[:CropBox].is_a?(Hash) && catalogs[:CropBox][:referenced_object].is_a?(Hash) && catalogs[:Parent][:referenced_object][:CropBox]
244
+ catalogs[:MediaBox] = catalogs[:MediaBox][:referenced_object][:indirect_without_dictionary] if catalogs[:MediaBox].is_a?(Hash) && catalogs[:MediaBox][:referenced_object].is_a?(Hash) && catalogs[:MediaBox][:referenced_object][:indirect_without_dictionary]
245
+ catalogs[:CropBox] = catalogs[:CropBox][:referenced_object][:indirect_without_dictionary] if catalogs[:CropBox].is_a?(Hash) && catalogs[:CropBox][:referenced_object].is_a?(Hash) && catalogs[:CropBox][:referenced_object][:indirect_without_dictionary]
227
246
  page_list << catalogs
228
247
  when :Pages
229
248
  page_list.push *(pages(catalogs[:Kids])) unless catalogs[:Kids].nil?
@@ -330,11 +349,8 @@ module CombinePDF
330
349
  page_number = opt[:start_at]
331
350
  pages.each do |page|
332
351
  # create a "stamp" PDF page with the same size as the target page
333
- mediabox = page[:MediaBox]
352
+ mediabox = page[:CropBox] || page[:MediaBox] || [0, 0, 595.3, 841.9]
334
353
  stamp = PDFWriter.new mediabox
335
- # set the visible dimensions to the CropBox, if it exists.
336
- cropbox = page[:CropBox]
337
- mediabox = cropbox if cropbox
338
354
  # set stamp text
339
355
  text = opt[:number_format] % page_number
340
356
  # compute locations for text boxes
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.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-09-13 00:00:00.000000000 Z
12
+ date: 2014-09-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ruby-rc4