combine_pdf 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 51a498d24b46760b925e4127a175868febcdb19a
|
4
|
+
data.tar.gz: 653351536fb043e14f94afc14805f488dc612c7a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c0089692cf609b368631b7e7afd59381c65403a69bfba0e27429cef04224f08074592781500b4e8ecf645ec0b422542920dd620a18e6e5fcdfaf6459d834640e
|
7
|
+
data.tar.gz: 95489bd58f7afab15904398fd9d52e3594ab44ce54f75390805c4f87073162d543a2eece82501895ed495fb78b7fe6a908140ed89dcf16fe64c1db009df19fc8
|
data/lib/combine_pdf.rb
CHANGED
@@ -45,7 +45,7 @@ require "combine_pdf/font_metrics/metrics_dictionary.rb"
|
|
45
45
|
# you can also add just odd or even pages:
|
46
46
|
# pdf = CombinePDF.new
|
47
47
|
# i = 0
|
48
|
-
# CombinePDF.new("file.pdf").pages.each do |page
|
48
|
+
# CombinePDF.new("file.pdf").pages.each do |page|
|
49
49
|
# i += 1
|
50
50
|
# pdf << page if i.even?
|
51
51
|
# end
|
@@ -129,6 +129,11 @@ module CombinePDF
|
|
129
129
|
raise TypeError, "couldn't parse and data, expecting type String" unless data.is_a? String
|
130
130
|
PDF.new( PDFParser.new(data) )
|
131
131
|
end
|
132
|
+
# makes a PDFWriter object
|
133
|
+
# ::mediabox an Array representing the size of the PDF document. defaults to: [0.0, 0.0, 612.0, 792.0]
|
134
|
+
def create_page(mediabox = [0.0, 0.0, 612.0, 792.0])
|
135
|
+
PDFWriter.new mediabox
|
136
|
+
end
|
132
137
|
end
|
133
138
|
|
134
139
|
|
@@ -25,7 +25,7 @@ module CombinePDF
|
|
25
25
|
#
|
26
26
|
# Writing on this Page is done using the textbox function.
|
27
27
|
#
|
28
|
-
# Setting the page
|
28
|
+
# Setting the page dimensions can be either at the new or using the mediabox method.
|
29
29
|
#
|
30
30
|
# the rest of the methods are for internal use.
|
31
31
|
#
|
@@ -59,25 +59,23 @@ module CombinePDF
|
|
59
59
|
self[:MediaBox]
|
60
60
|
end
|
61
61
|
# accessor (setter) for the :MediaBox element of the page
|
62
|
-
#
|
63
|
-
def mediabox=(
|
64
|
-
self[:MediaBox] =
|
62
|
+
# dimensions:: an Array consisting of four numbers (can be floats) setting the size of the media box.
|
63
|
+
def mediabox=(dimensions = [0.0, 0.0, 612.0, 792.0])
|
64
|
+
self[:MediaBox] = dimensions
|
65
65
|
end
|
66
66
|
|
67
|
-
#
|
68
|
-
#
|
69
|
-
# This function, when completed, will add a simple text box to the Page represented by the PDFWriter class.
|
67
|
+
# This method adds a simple text box to the Page represented by the PDFWriter class.
|
70
68
|
# This function takes two values:
|
71
69
|
# text:: the text to potin the box.
|
72
70
|
# properties:: a Hash of box properties.
|
73
71
|
# the symbols and values in the properties Hash could be any or all of the following:
|
74
72
|
# x:: the left position of the box.
|
75
73
|
# y:: the BUTTOM position of the box.
|
76
|
-
# length:: the length of the box.
|
77
|
-
# height:: the height of the box.
|
74
|
+
# length:: the length of the box. negative values will be computed from edge of page. defaults to 0 (end of page).
|
75
|
+
# height:: the height of the box. negative values will be computed from edge of page. defaults to 0 (end of page).
|
78
76
|
# text_align:: symbol for horizontal text alignment, can be ":center" (default), ":right", ":left"
|
79
77
|
# text_valign:: symbol for vertical text alignment, can be ":center" (default), ":top", ":buttom"
|
80
|
-
#
|
78
|
+
# font:: a Symbol representing one of the 14 standard fonts. defaults to ":Helvetica". the options are:
|
81
79
|
# - :"Times-Roman"
|
82
80
|
# - :"Times-Bold"
|
83
81
|
# - :"Times-Italic"
|
@@ -102,16 +100,15 @@ module CombinePDF
|
|
102
100
|
# border_width:: border width in PDF units. defaults to nil (none).
|
103
101
|
# box_radius:: border radius in PDF units. defaults to 0 (no corner rounding).
|
104
102
|
# opacity:: textbox opacity, a float between 0 (transparent) and 1 (opaque)
|
105
|
-
# <b>now on testing mode, defaults are different! box defaults to gray with border and rounding.</b>
|
106
103
|
def textbox(text, properties = {})
|
107
104
|
options = {
|
108
105
|
x: 0,
|
109
106
|
y: 0,
|
110
|
-
length:
|
107
|
+
length: 0,
|
111
108
|
height: -1,
|
112
109
|
text_align: :center,
|
113
110
|
text_valign: :center,
|
114
|
-
|
111
|
+
font: :Helvetica,
|
115
112
|
font_size: :fit_text,
|
116
113
|
max_font_size: nil,
|
117
114
|
font_color: [0,0,0],
|
@@ -125,12 +122,12 @@ module CombinePDF
|
|
125
122
|
}
|
126
123
|
options.update properties
|
127
124
|
# reset the length and height to meaningful values, if negative
|
128
|
-
options[:length] = mediabox[2] - options[:x] if options[:length]
|
129
|
-
options[:height] = mediabox[3] - options[:y] if options[:height]
|
125
|
+
options[:length] = mediabox[2] - options[:x] + options[:length] if options[:length] <= 0
|
126
|
+
options[:height] = mediabox[3] - options[:y] + options[:height] if options[:height] <= 0
|
130
127
|
# fit text in box, if requested
|
131
128
|
font_size = options[:font_size]
|
132
129
|
if options[:font_size] == :fit_text
|
133
|
-
font_size = self.fit_text text, options[:
|
130
|
+
font_size = self.fit_text text, options[:font], options[:length], options[:height]
|
134
131
|
font_size = options[:max_font_size] if options[:max_font_size] && font_size > options[:max_font_size]
|
135
132
|
end
|
136
133
|
|
@@ -215,7 +212,7 @@ module CombinePDF
|
|
215
212
|
x = options[:x]
|
216
213
|
y = options[:y]
|
217
214
|
|
218
|
-
text_size =
|
215
|
+
text_size = dimensions_of text, options[:font], font_size
|
219
216
|
if options[:text_align] == :center
|
220
217
|
x = (options[:length] - text_size[0])/2 + x
|
221
218
|
elsif options[:text_align] == :right
|
@@ -249,7 +246,7 @@ module CombinePDF
|
|
249
246
|
end
|
250
247
|
# format text object
|
251
248
|
text_stream << "BT\n" # the Begine Text marker
|
252
|
-
text_stream << PDFOperations._format_name_to_pdf(
|
249
|
+
text_stream << PDFOperations._format_name_to_pdf(set_font options[:font]) # Set font name
|
253
250
|
text_stream << " #{font_size} Tf\n" # set font size and add font operator
|
254
251
|
text_stream << "#{options[:font_color].join(' ')} rg\n" # sets the color state
|
255
252
|
text_stream << "#{x} #{y} Td\n" # set location for text object
|
@@ -276,7 +273,7 @@ module CombinePDF
|
|
276
273
|
end
|
277
274
|
# creates a font object and adds the font to the resources dictionary
|
278
275
|
# returns the name of the font for the content stream.
|
279
|
-
#
|
276
|
+
# font:: a Symbol of one of the 14 Type 1 fonts, known as the standard 14 fonts:
|
280
277
|
# - :"Times-Roman"
|
281
278
|
# - :"Times-Bold"
|
282
279
|
# - :"Times-Italic"
|
@@ -291,7 +288,7 @@ module CombinePDF
|
|
291
288
|
# - :"Courier-BoldOblique"
|
292
289
|
# - :Symbol
|
293
290
|
# - :ZapfDingbats
|
294
|
-
def font
|
291
|
+
def set_font(font = :Helvetica)
|
295
292
|
# refuse any other fonts that arn't basic standard fonts
|
296
293
|
allow_fonts = [ :"Times-Roman",
|
297
294
|
:"Times-Bold",
|
@@ -307,16 +304,16 @@ module CombinePDF
|
|
307
304
|
:"Courier-BoldOblique",
|
308
305
|
:Symbol,
|
309
306
|
:ZapfDingbats ]
|
310
|
-
raise "
|
307
|
+
raise "set_font(font) accepts only one of the 14 standards fonts - wrong font!" unless allow_fonts.include? font
|
311
308
|
# if the font exists, return it's name
|
312
309
|
resources[:Font] ||= {}
|
313
310
|
resources[:Font].each do |k,v|
|
314
|
-
if v.is_a?(Hash) && v[:Type] == :Font && v[:BaseFont] ==
|
311
|
+
if v.is_a?(Hash) && v[:Type] == :Font && v[:BaseFont] == font
|
315
312
|
return k
|
316
313
|
end
|
317
314
|
end
|
318
315
|
# create font object
|
319
|
-
font_object = { Type: :Font, Subtype: :Type1, BaseFont:
|
316
|
+
font_object = { Type: :Font, Subtype: :Type1, BaseFont: font}
|
320
317
|
# set a secure name for the font
|
321
318
|
name = (SecureRandom.urlsafe_base64(9)).to_sym
|
322
319
|
# add object to reasource
|
@@ -164,6 +164,12 @@ module CombinePDF
|
|
164
164
|
return object # objects that aren't Strings, Arrays or Hashes (such as Symbols and Fixnums) aren't pointers in Ruby and are always copied.
|
165
165
|
end
|
166
166
|
end
|
167
|
+
# removes id and generation number values, for better comparrison
|
168
|
+
# and avoiding object duplication
|
169
|
+
# objects:: one or more objects in a PDF file/page.
|
170
|
+
def remove_old_ids objects
|
171
|
+
_each_object(objects) {|obj| obj.delete(:indirect_reference_id); obj.delete(:indirect_generation_number)}
|
172
|
+
end
|
167
173
|
def get_refernced_object(objects_array = [], reference_hash = {})
|
168
174
|
objects_array.each do |stored_object|
|
169
175
|
return stored_object if ( stored_object.is_a?(Hash) &&
|
@@ -28,7 +28,7 @@ module CombinePDF
|
|
28
28
|
# you can also add just odd or even pages:
|
29
29
|
# pdf = CombinePDF.new
|
30
30
|
# i = 0
|
31
|
-
# CombinePDF.new("file.pdf").pages.each do |page
|
31
|
+
# CombinePDF.new("file.pdf").pages.each do |page|
|
32
32
|
# i += 1
|
33
33
|
# pdf << page if i.even?
|
34
34
|
# end
|
@@ -280,12 +280,12 @@ module CombinePDF
|
|
280
280
|
|
281
281
|
# and page numbers to the PDF
|
282
282
|
# options:: a Hash of options setting the behavior and format of the page numbers:
|
283
|
-
#
|
284
|
-
#
|
285
|
-
#
|
286
|
-
#
|
287
|
-
#
|
288
|
-
# also take all the options for PDFWriter.textbox.
|
283
|
+
# - :number_format a string representing the format for page number. defaults to ' - %d - '.
|
284
|
+
# - :number_location an Array containing the location for the page numbers, can be :top, :buttom, :top_left, :top_right, :bottom_left, :bottom_right. defaults to [:top, :buttom].
|
285
|
+
# - :start_at a Fixnum that sets the number for first page number. defaults to 1.
|
286
|
+
# - :margin_from_height a number (PDF points) for the top and buttom margins. defaults to 45.
|
287
|
+
# - :margin_from_side a number (PDF points) for the left and right margins. defaults to 15.
|
288
|
+
# the options Hash can also take all the options for PDFWriter.textbox.
|
289
289
|
# defaults to font_name: :Helvetica, font_size: 12 and no box (:border_width => 0, :box_color => nil).
|
290
290
|
def number_pages(options = {})
|
291
291
|
opt = {
|
@@ -293,7 +293,7 @@ module CombinePDF
|
|
293
293
|
number_location: [:top, :bottom],
|
294
294
|
start_at: 1,
|
295
295
|
font_size: 12,
|
296
|
-
|
296
|
+
font: :Helvetica,
|
297
297
|
margin_from_height: 45,
|
298
298
|
margin_from_side: 15
|
299
299
|
}
|
@@ -303,17 +303,17 @@ module CombinePDF
|
|
303
303
|
# create a "stamp" PDF page with the same size as the target page
|
304
304
|
mediabox = page[:MediaBox]
|
305
305
|
stamp = PDFWriter.new mediabox
|
306
|
-
# set the visible
|
306
|
+
# set the visible dimensions to the CropBox, if it exists.
|
307
307
|
cropbox = page[:CropBox]
|
308
308
|
mediabox = cropbox if cropbox
|
309
309
|
# set stamp text
|
310
310
|
text = opt[:number_format] % page_number
|
311
311
|
# compute locations for text boxes
|
312
|
-
text_dimantions = stamp.
|
312
|
+
text_dimantions = stamp.dimensions_of( text, opt[:font], opt[:font_size] )
|
313
313
|
box_width = text_dimantions[0] * 1.2
|
314
314
|
box_height = text_dimantions[1] * 2
|
315
|
-
opt[:length]
|
316
|
-
opt[:height]
|
315
|
+
opt[:length] = box_width
|
316
|
+
opt[:height] = box_height
|
317
317
|
from_height = 45
|
318
318
|
from_side = 15
|
319
319
|
page_width = mediabox[2]
|
@@ -397,12 +397,20 @@ module CombinePDF
|
|
397
397
|
object.each {|it| add_referenced(it)}
|
398
398
|
when object.is_a?(Hash)
|
399
399
|
if object[:is_reference_only] && object[:referenced_object]
|
400
|
-
|
400
|
+
found_at = @objects.find_index object[:referenced_object]
|
401
|
+
if found_at
|
402
|
+
#if the objects are equal, they might still be different objects!
|
403
|
+
# so, we need to make sure they are the same object for the pointers to effect id numbering
|
404
|
+
# and formatting operations.
|
405
|
+
object[:referenced_object] = @objects[found_at]
|
406
|
+
else @objects.include? object[:referenced_object]
|
407
|
+
#the object wasn't found - add it to the @objects array
|
401
408
|
@objects << object[:referenced_object]
|
402
409
|
object[:referenced_object].each do |k, v|
|
403
410
|
add_referenced(v) unless k == :Parent
|
404
411
|
end
|
405
412
|
end
|
413
|
+
|
406
414
|
else
|
407
415
|
object.each do |k, v|
|
408
416
|
add_referenced(v) unless k == :Parent
|
@@ -458,6 +466,9 @@ module CombinePDF
|
|
458
466
|
end
|
459
467
|
end
|
460
468
|
|
469
|
+
# when finished, remove the old numbering system and keep only pointers
|
470
|
+
PDFOperations.remove_old_ids @objects
|
471
|
+
|
461
472
|
# # Version 3
|
462
473
|
# # benchmark 1000.times was 3.568246 sec for pdf = CombinePDF.new "/Users/2Be/Desktop/מוצגים/20121002\ הודעת\ הערעור.pdf" }
|
463
474
|
# # puts Benchmark.measure { 1000.times {pdf.serialize_objects_and_references} }
|
@@ -1,17 +1,24 @@
|
|
1
1
|
module CombinePDF
|
2
2
|
class PDFWriter < Hash
|
3
|
-
# This function calculates the
|
3
|
+
# This function calculates the dimensions of a string in a PDF.
|
4
4
|
#
|
5
5
|
# UNICODE SUPPORT IS MISSING!
|
6
6
|
#
|
7
7
|
# text:: String containing the text for which the demantion box will be calculated.
|
8
|
-
#
|
8
|
+
# font:: the font name, from the 14 fonts possible. @see font
|
9
9
|
# size:: the size of the text, as it will be applied in the PDF.
|
10
|
-
def
|
11
|
-
metrics = METRICS_DICTIONARY[
|
10
|
+
def dimensions_of(text, font, size = 1000)
|
11
|
+
metrics = METRICS_DICTIONARY[font]
|
12
12
|
metrics_array = []
|
13
13
|
# the following is only good for latin text - unicode support is missing!!!!
|
14
|
-
text.each_char
|
14
|
+
text.each_char do |c|
|
15
|
+
metrics_mappings = metrics.select {|k,v| v[:charcode] == c.bytes[0].ord}
|
16
|
+
######
|
17
|
+
# need to add unicode support
|
18
|
+
# this is a lousy patch that puts the bounds of @ inside...
|
19
|
+
metrics_mappings = metrics.select {|k,v| v[:charcode] == "@".ord} if metrics_mappings.empty?
|
20
|
+
metrics_array << metrics_mappings.to_a[0][1]
|
21
|
+
end
|
15
22
|
max_width = metrics_array.map {|m| m ? m[:wx] : 0} .max
|
16
23
|
height = metrics_array.map {|m| m ? m[:boundingbox][3] : 0} .max
|
17
24
|
height = height - (metrics_array.map {|m| m ? m[:boundingbox][1] : 0} ).min
|
@@ -59,7 +66,7 @@ module CombinePDF
|
|
59
66
|
def fit_text(text, font, length, height = 10000000)
|
60
67
|
size = 100000
|
61
68
|
size_array = [size]
|
62
|
-
metrics =
|
69
|
+
metrics = dimensions_of text, font, size
|
63
70
|
if metrics[0] > length
|
64
71
|
size_array << size * length/metrics[0]
|
65
72
|
end
|