Module: PDF::Core
- Defined in:
- lib/pdf/core.rb,
lib/pdf/core/page.rb,
lib/pdf/core/text.rb,
lib/pdf/core/utils.rb,
lib/pdf/core/stream.rb,
lib/pdf/core/filters.rb,
lib/pdf/core/renderer.rb,
lib/pdf/core/name_tree.rb,
lib/pdf/core/reference.rb,
lib/pdf/core/pdf_object.rb,
lib/pdf/core/annotations.rb,
lib/pdf/core/byte_string.rb,
lib/pdf/core/filter_list.rb,
lib/pdf/core/destinations.rb,
lib/pdf/core/object_store.rb,
lib/pdf/core/outline_item.rb,
lib/pdf/core/outline_root.rb,
lib/pdf/core/page_geometry.rb,
lib/pdf/core/document_state.rb,
lib/pdf/core/graphics_state.rb,
lib/pdf/core/literal_string.rb
Overview
PDF::Core is concerned with low-level PDF functions such as serialization, content streams and such.
It’s extracted from Prawn but at the moment is not entirely independent.
Defined Under Namespace
Modules: Annotations, Destinations, Errors, Filters, NameTree, PageGeometry, Text, Utils Classes: ByteString, DocumentState, FilterList, GraphicState, GraphicStateStack, LiteralString, ObjectStore, OutlineItem, OutlineRoot, Page, Reference, Renderer, Stream
Constant Summary collapse
- ESCAPED_NAME_CHARACTERS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Characters to escape in name objects
(1..32).to_a + [35, 40, 41, 47, 60, 62] + (127..255).to_a
- STRING_ESCAPE_MAP =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
How to escape special characters in literal strings
{ '(' => '\(', ')' => '\)', '\\' => '\\\\', "\r" => '\r' }.freeze
Class Method Summary collapse
-
.pdf_object(obj, in_content_stream = false) ⇒ String
Serializes Ruby objects to their PDF equivalents.
-
.real(num) ⇒ String
Serializes floating number into a string.
-
.real_params(array) ⇒ String
Serializes a n array of numbers.
-
.string_to_hex(str) ⇒ String
Encodes any string into a hex representation.
-
.utf8_to_utf16(str) ⇒ String
private
Converts string to UTF-16BE encoding as expected by PDF.
Class Method Details
.pdf_object(obj, in_content_stream = false) ⇒ String
Serializes Ruby objects to their PDF equivalents. Most primitive objects will work as expected, but please note that Name objects are represented by Ruby Symbol objects and Dictionary objects are represented by Ruby hashes (keyed by symbols)
Examples:
pdf_object(true) #=> "true"
pdf_object(false) #=> "false"
pdf_object(1.2124) #=> "1.2124"
pdf_object('foo bar') #=> "(foo bar)"
pdf_object(:Symbol) #=> "/Symbol"
pdf_object(['foo',:bar, [1,2]]) #=> "[foo /bar [1 2]]"
Source Code
77 | def pdf_object(obj, in_content_stream = false) |
78 | case obj |
79 | when NilClass then 'null' |
80 | when TrueClass then 'true' |
81 | when FalseClass then 'false' |
82 | when Numeric |
83 | num_string = obj.is_a?(Integer) ? String(obj) : real(obj) |
84 | |
85 | # Truncate trailing fraction zeroes
|
86 | num_string.sub!(/(\d*)((\.0*$)|(\.0*[1-9]*)0*$)/, '\1\4') |
87 | num_string
|
88 | when Array |
89 | "[#{obj.map { |e| pdf_object(e, in_content_stream) }.join(' ')}]" |
90 | when PDF::Core::LiteralString |
91 | obj = obj.gsub(/[\\\r()]/, STRING_ESCAPE_MAP) |
92 | "(#{obj})" |
93 | when Time |
94 | obj = "#{obj.strftime('D:%Y%m%d%H%M%S%z').chop.chop}'00'" |
95 | obj = obj.gsub(/[\\\r()]/, STRING_ESCAPE_MAP) |
96 | "(#{obj})" |
97 | when PDF::Core::ByteString |
98 | "<#{obj.unpack1('H*')}>" |
99 | when String |
100 | obj = utf8_to_utf16(obj) unless in_content_stream |
101 | "<#{string_to_hex(obj)}>" |
102 | when Symbol |
103 | (@symbol_str_cache ||= {})[obj] ||= (+'/') << obj.to_s.unpack('C*').map { |n| |
104 | if ESCAPED_NAME_CHARACTERS.include?(n) |
105 | "##{n.to_s(16).upcase}" |
106 | else
|
107 | n.chr |
108 | end
|
109 | }.join |
110 | when ::Hash |
111 | output = +'<< ' |
112 | obj
|
113 | .sort_by { |k, _v| k.to_s } |
114 | .each do |(k, v)| |
115 | unless k.is_a?(String) || k.is_a?(Symbol) |
116 | raise PDF::Core::Errors::FailedObjectConversion, |
117 | 'A PDF Dictionary must be keyed by names'
|
118 | end
|
119 | output << pdf_object(k.to_sym, in_content_stream) << ' ' << |
120 | pdf_object(v, in_content_stream) << "\n" |
121 | end
|
122 | output << '>>' |
123 | when PDF::Core::Reference |
124 | obj.to_s |
125 | when PDF::Core::NameTree::Node, PDF::Core::OutlineRoot, PDF::Core::OutlineItem |
126 | pdf_object(obj.to_hash) |
127 | when PDF::Core::NameTree::Value |
128 | "#{pdf_object(obj.name)} #{pdf_object(obj.value)}" |
129 | else
|
130 | raise PDF::Core::Errors::FailedObjectConversion, |
131 | "This object cannot be serialized to PDF (#{obj.inspect})" |
132 | end
|
133 | end
|
.real(num) ⇒ String
Serializes floating number into a string
Source Code
11 | def real(num) |
12 | result = format('%.5f', num) |
13 | result.sub!(/((?<!\.)0)+\z/, '') |
14 | result
|
15 | end
|
.real_params(array) ⇒ String
Serializes a n array of numbers. This is specifically for use in PDF content streams.
Source Code
22 | def real_params(array) |
23 | array.map { |e| real(e) }.join(' ') |
24 | end
|
.string_to_hex(str) ⇒ String
Encodes any string into a hex representation. The result is a string with only 0-9 and a-f characters. That result is valid ASCII so tag it as such to account for behaviour of different ruby VMs.
Source Code
42 | def string_to_hex(str) |
43 | str.unpack1('H*').force_encoding(::Encoding::US_ASCII) |
44 | end
|
.utf8_to_utf16(str) ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Converts string to UTF-16BE encoding as expected by PDF.
Source Code
31 | def utf8_to_utf16(str) |
32 | (+"\xFE\xFF").force_encoding(::Encoding::UTF_16BE) << |
33 | str.encode(::Encoding::UTF_16BE) |
34 | end
|