Class: Idml::Render::PdfWriter
- Inherits:
-
Object
- Object
- Idml::Render::PdfWriter
- Defined in:
- lib/idml/render/pdf_writer.rb
Overview
Minimal PDF file writer. Assembles content-stream strings into a valid PDF with page tree, font resources, image XObjects, embedded TrueType fonts, cross-reference table, and trailer.
Instance Method Summary collapse
-
#add_bookmark(title, page_index) ⇒ Object
Add a bookmark (outline entry) pointing to a page.
-
#add_image(data:) ⇒ Object
Auto-detect format and register the image.
- #add_image_object(data:, width:, height:, colorspace:, filter:) ⇒ Object
-
#add_jpeg_image(data:, width:, height:, colorspace: :DeviceRGB) ⇒ Object
Register a JPEG image as a PDF image XObject (DCTDecode).
- #add_page(width:, height:, content:, fonts: {}, xobjects: []) ⇒ Object
-
#add_png_image(data:, width:, height:, colorspace: :DeviceRGB) ⇒ Object
Register a PNG image as a PDF image XObject (FlateDecode with PNG predictor).
- #image_colorspace(data, format) ⇒ Object
- #image_dimensions(data, format) ⇒ Object
-
#initialize ⇒ PdfWriter
constructor
A new instance of PdfWriter.
- #png_decode_parms(width, colorspace) ⇒ Object
-
#register_embedded_font(metrics:, data:) ⇒ Object
Register a TrueType font for embedding (FontFile2).
- #register_format_image(data, format, dims, cs) ⇒ Object
-
#set_info(hash) ⇒ Object
Set PDF metadata (Title, Author, Subject, etc.).
-
#set_output_intent(profile_data) ⇒ Object
Set OutputIntent with an ICC profile.
-
#set_xmp(xml) ⇒ Object
Set XMP metadata packet (XML string).
- #write(path) ⇒ Object
Constructor Details
#initialize ⇒ PdfWriter
Returns a new instance of PdfWriter.
14 15 16 17 18 19 20 21 22 23 |
# File 'lib/idml/render/pdf_writer.rb', line 14 def initialize @pages = [] @images = {} @embedded_fonts = {} @info = {} @next_id = 1 @catalog_id = alloc_id @pages_id = alloc_id @info_id = alloc_id end |
Instance Method Details
#add_bookmark(title, page_index) ⇒ Object
Add a bookmark (outline entry) pointing to a page. title: display text; page_index: 0-based page index.
144 145 146 147 |
# File 'lib/idml/render/pdf_writer.rb', line 144 def add_bookmark(title, page_index) @outlines ||= [] @outlines << { title: title, page_index: page_index } end |
#add_image(data:) ⇒ Object
Auto-detect format and register the image.
64 65 66 67 68 69 70 71 72 73 |
# File 'lib/idml/render/pdf_writer.rb', line 64 def add_image(data:) format = Render::Image.detect_format(data) return nil unless format dims = image_dimensions(data, format) return nil unless dims cs = image_colorspace(data, format) || :DeviceRGB register_format_image(data, format, dims, cs) end |
#add_image_object(data:, width:, height:, colorspace:, filter:) ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/idml/render/pdf_writer.rb', line 102 def add_image_object(data:, width:, height:, colorspace:, filter:) name = "Im#{@images.length + 1}" id = alloc_id @images[name] = { id: id, data: data.dup.force_encoding("ASCII-8BIT"), width: width, height: height, colorspace: colorspace, filter: filter, } name end |
#add_jpeg_image(data:, width:, height:, colorspace: :DeviceRGB) ⇒ Object
Register a JPEG image as a PDF image XObject (DCTDecode). Returns the XObject name to use in content streams (e.g. "Im1").
45 46 47 48 |
# File 'lib/idml/render/pdf_writer.rb', line 45 def add_jpeg_image(data:, width:, height:, colorspace: :DeviceRGB) add_image_object(data: data, width: width, height: height, colorspace: colorspace, filter: :DCTDecode) end |
#add_page(width:, height:, content:, fonts: {}, xobjects: []) ⇒ Object
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/idml/render/pdf_writer.rb', line 25 def add_page(width:, height:, content:, fonts: {}, xobjects: []) font_objs = build_fonts(fonts) xobject_objs = build_xobjects(xobjects) content_id = alloc_id page_id = alloc_id @pages << { id: page_id, width: width, height: height, content_id: content_id, content: content, font_objs: font_objs, xobject_objs: xobject_objs, } page_id end |
#add_png_image(data:, width:, height:, colorspace: :DeviceRGB) ⇒ Object
Register a PNG image as a PDF image XObject (FlateDecode with PNG predictor). The IDAT chunk data is embedded directly; the PDF viewer handles decompression and unfiltering.
53 54 55 56 57 58 59 60 61 |
# File 'lib/idml/render/pdf_writer.rb', line 53 def add_png_image(data:, width:, height:, colorspace: :DeviceRGB) idat = Render::Image.png_idat_data(data) return nil unless idat name = add_image_object(data: idat, width: width, height: height, colorspace: colorspace, filter: :FlateDecode) @images[name][:decode_parms] = png_decode_parms(width, colorspace) name end |
#image_colorspace(data, format) ⇒ Object
83 84 85 86 87 88 89 |
# File 'lib/idml/render/pdf_writer.rb', line 83 def image_colorspace(data, format) if format == :png Render::Image.png_colorspace(data) else Render::Image.jpeg_colorspace(data) end end |
#image_dimensions(data, format) ⇒ Object
75 76 77 78 79 80 81 |
# File 'lib/idml/render/pdf_writer.rb', line 75 def image_dimensions(data, format) if format == :png Render::Image.png_dimensions(data) else Render::Image.jpeg_dimensions(data) end end |
#png_decode_parms(width, colorspace) ⇒ Object
116 117 118 119 |
# File 'lib/idml/render/pdf_writer.rb', line 116 def png_decode_parms(width, colorspace) colors = colorspace == :DeviceGray ? 1 : 3 "<< /Predictor 15 /Columns #{width} /Colors #{colors} /BitsPerComponent 8 >>" end |
#register_embedded_font(metrics:, data:) ⇒ Object
Register a TrueType font for embedding (FontFile2). Returns the PostScript name to use as the value in add_page's fonts hash.
123 124 125 126 127 128 129 130 |
# File 'lib/idml/render/pdf_writer.rb', line 123 def (metrics:, data:) ps_name = metrics.postscript_name @embedded_fonts[ps_name] = { metrics: metrics, data: data.dup.force_encoding("ASCII-8BIT"), } ps_name end |
#register_format_image(data, format, dims, cs) ⇒ Object
91 92 93 94 95 96 97 98 99 100 |
# File 'lib/idml/render/pdf_writer.rb', line 91 def register_format_image(data, format, dims, cs) case format when :jpeg add_jpeg_image(data: data, width: dims[0], height: dims[1], colorspace: cs) when :png add_png_image(data: data, width: dims[0], height: dims[1], colorspace: cs) end end |
#set_info(hash) ⇒ Object
Set PDF metadata (Title, Author, Subject, etc.). Values should be strings; keys are PDF Info dictionary keys.
138 139 140 |
# File 'lib/idml/render/pdf_writer.rb', line 138 def set_info(hash) @info.merge!(hash) end |
#set_output_intent(profile_data) ⇒ Object
Set OutputIntent with an ICC profile. Required for PDF/A. profile_data: binary ICC profile data.
157 158 159 |
# File 'lib/idml/render/pdf_writer.rb', line 157 def set_output_intent(profile_data) @icc_profile = profile_data end |
#set_xmp(xml) ⇒ Object
Set XMP metadata packet (XML string). Embedded as a stream object referenced from the Catalog.
151 152 153 |
# File 'lib/idml/render/pdf_writer.rb', line 151 def set_xmp(xml) @xmp = xml end |
#write(path) ⇒ Object
132 133 134 |
# File 'lib/idml/render/pdf_writer.rb', line 132 def write(path) File.binwrite(path, build_pdf) end |