lib/combine_pdf.rb in combine_pdf-0.0.11 vs lib/combine_pdf.rb in combine_pdf-0.0.12
- old
+ new
@@ -31,35 +31,52 @@
# This is a pure ruby library to merge PDF files.
+#
# In the future, this library will also allow stamping and watermarking PDFs (it allows this now, only with some issues).
#
# PDF objects can be used to combine or to inject data.
+#
+# here is the most basic application for the library, a one-liner that combines the PDF files and saves them:
+# (CombinePDF.new("file1.pdf") << CombinePDF.new("file2.pdf") << CombinePDF.new("file3.pdf")).save("combined.pdf")
+#
+# == Loading PDF data
+# Loading PDF data can be done from file system or directly from the memory.
+#
+# Loading data from a file is easy:
+# pdf = CombinePDF.new("file.pdf")
+# you can also parse PDF files from memory:
+# pdf_data = IO.read 'file.pdf' # for this demo, load a file to memory
+# pdf = CombinePDF.parse(pdf_data)
+# Loading from the memory is especially effective for importing PDF data recieved through the internet or from a different authoring library such as Prawn.
+#
# == Combine/Merge PDF files or Pages
# To combine PDF files (or data):
# pdf = CombinePDF.new
-# pdf << CombinePDF.new("file1.pdf") # one way to combine, very fast.
+# pdf << CombinePDF.new("file1.pdf")
# pdf << CombinePDF.new("file2.pdf")
# pdf.save "combined.pdf"
-# or even a one liner:
-# (CombinePDF.new("file1.pdf") << CombinePDF.new("file2.pdf") << CombinePDF.new("file3.pdf")).save("combined.pdf")
-# you can also add just odd or even pages:
+# as demonstrated above, these can be chained for into a one-liner.
+#
+# you can also only selected pages.
+#
+# in this example, only even pages will be added:
# pdf = CombinePDF.new
# i = 0
# CombinePDF.new("file.pdf").pages.each do |page|
# i += 1
# pdf << page if i.even?
# end
# pdf.save "even_pages.pdf"
-# notice that adding all the pages one by one is slower then adding the whole file.
+# notice that adding the whole file is faster then adding each page seperately.
# == Add content to existing pages (Stamp / Watermark)
# To add content to existing PDF pages, first import the new content from an existing PDF file.
# after that, add the content to each of the pages in your existing PDF.
#
-# in this example, we will add a company logo to each page:
+# in this example, a company logo will be stamped over each page:
# company_logo = CombinePDF.new("company_logo.pdf").pages[0]
# pdf = CombinePDF.new "content_file.pdf"
# pdf.pages.each {|page| page << company_logo} # notice the << operator is on a page and not a PDF object.
# pdf.save "content_with_logo.pdf"
# Notice the << operator is on a page and not a PDF object. The << operator acts differently on PDF objects and on Pages.
@@ -75,21 +92,45 @@
# pdf = CombinePDF.new "file_to_number.pdf"
# pdf.number_pages
# pdf.save "file_with_numbering.pdf"
#
# numbering can be done with many different options, with different formating, with or without a box object, and even with opacity values.
+# == Writing Content
+# page numbering actually adds content using the PDFWriter object (a very basic writer).
#
-# == Loading PDF data
-# Loading PDF data can be done from file system or directly from the memory.
+# in this example, all the PDF pages will be stamped, along the top, with a red box, with blue text, stating "Draft, page #".
+# here is the easy way (we can even use "number_pages" without page numbers, if we wish):
+# pdf = CombinePDF.new "file_to_stamp.pdf"
+# pdf.number_pages number_format: " - Draft, page %d - ", number_location: [:top], font_color: [0,0,1], box_color: [0.4,0,0], opacity: 0.75, font_size:16
+# pdf.save "draft.pdf"
#
-# Loading data from a file is easy:
-# pdf = CombinePDF.new("file.pdf")
-# you can also parse PDF files from memory:
-# pdf_data = IO.read 'file.pdf' # for this demo, load a file to memory
-# pdf = CombinePDF.parse(pdf_data)
-# Loading from the memory is especially effective for importing PDF data recieved through the internet or from a different authoring library such as Prawn.
+# for demntration, it will now be coded the hard way, just so we can play more directly with some of the data.
#
+# pdf = CombinePDF.new "file_to_stamp.pdf"
+# ipage_number = 1
+# pdf.pages.each do |page|
+# # create a "stamp" PDF page with the same size as the target page
+# # we will do this because we will use this to center the box in the page
+# mediabox = page[:MediaBox]
+# # CombinePDF is pointer based...
+# # so you can add the stamp to the page and still continue to edit it's content!
+# stamp = PDFWriter.new mediabox
+# page << stamp
+# # set the visible dimensions to the CropBox, if it exists.
+# cropbox = page[:CropBox]
+# mediabox = cropbox if cropbox
+# # set stamp text
+# text = " Draft (page %d) " % page_number
+# # write the textbox
+# stamp.textbox text, x: mediabox[0]+30, y: mediabox[1]+30, width: mediabox[2]-mediabox[0]-60, height: mediabox[3]-mediabox[1]-60, font_color: [0,0,1], font_size: :fit_text, box_color: [0.4,0,0], opacity: 0.5
+# end
+# pdf.save "draft.pdf"
+#
+#
+# font support for the writer is still in the works and is extreamly limited.
+# at the moment it is best to limit the fonts to the 14 standard latin fonts (no unicode).
+#
# == Decryption & Filters
#
# Some PDF files are encrypted and some are compressed (the use of filters)...
#
# There is very little support for encrypted files and very very basic and limited support for compressed files.
@@ -130,12 +171,49 @@
def parse(data)
raise TypeError, "couldn't parse and data, expecting type String" unless data.is_a? String
PDF.new( PDFParser.new(data) )
end
# makes a PDFWriter object
+ #
+ # PDFWriter objects reresent an empty page and have the method "textbox"
+ # that adds content to that page.
+ #
+ # PDFWriter objects are used internally for numbering pages (by creating a PDF page
+ # with the page number and "stamping" it over the existing page).
+ #
# ::mediabox an Array representing the size of the PDF document. defaults to: [0.0, 0.0, 612.0, 792.0]
+ #
+ # if the page is PDFWriter object as a stamp, the final size will be that of the original page.
def create_page(mediabox = [0.0, 0.0, 612.0, 792.0])
PDFWriter.new mediabox
+ end
+
+ # adds a correctly formatted font object to the font library.
+ #
+ # registered fonts will remain in the library and will only be embeded in
+ # PDF objects when they are used by PDFWriter objects (for example, for numbering pages).
+ #
+ # this function enables plug-ins to expend the font functionality of CombinePDF.
+ #
+ # font_name:: a Symbol with the name of the font. if the fonts exists in the library, it will be overwritten!
+ # font_metrics:: a Hash of font metrics, of the format char => {wx: char_width, boundingbox: [left_x, buttom_y, right_x, top_y]} where char == character itself (i.e. " " for space). The Hash should contain a special value :missing for the metrics of missing characters. an optional :wy might be supported in the future, for up to down fonts.
+ # font_pdf_object:: a Hash in the internal format recognized by CombinePDF, that represents the font object.
+ # font_cmap:: a CMap dictionary Hash) which maps unicode characters to the hex CID for the font (i.e. {"a" => "61", "z" => "7a" }).
+ def register_font(font_name, font_metrics, font_pdf_object, font_cmap = nil)
+ Fonts.register_font font_name, font_metrics, font_pdf_object, font_cmap
+ end
+
+ # adds an existing font (from any PDF Object) to the font library.
+ #
+ # returns the font on success or false on failure.
+ #
+ # VERY LIMITTED SUPPORT:
+ # - at the moment it only imports Type0 fonts.
+ # - also, to extract the Hash of the actual font object you were looking for, is not a trivial matter. I do it on the console.
+ # font_name:: a Symbol with the name of the font registry. if the fonts exists in the library, it will be overwritten!
+ # font_object:: a Hash in the internal format recognized by CombinePDF, that represents the font object.
+ def register_font_from_pdf_object font_name, font_object
+ Fonts.register_font_from_pdf_object font_name, font_object
end
end