Skip to content

Commit

Permalink
pdf: support for the save option :eol
Browse files Browse the repository at this point in the history
It is now possible to pass a specific newline token to PDF#save.
Origami used to use a constant CRLF token. The new default value is $/,
which is the newline value of the system.
  • Loading branch information
Guillaume Delugré committed Oct 15, 2017
1 parent 863856a commit 98ea557
Show file tree
Hide file tree
Showing 18 changed files with 97 additions and 81 deletions.
8 changes: 4 additions & 4 deletions lib/origami/array.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,21 +107,21 @@ def to_a

alias each_value each

def to_s #:nodoc:
def to_s(eol: $/) #:nodoc:
content = TOKENS.first.dup
content << self.map {|entry|
entry = entry.to_o

case entry
when Dictionary # Do not indent dictionaries inside of arrays.
entry.to_s(indent: 0)
entry.to_s(indent: 0, eol: eol)
else
entry.to_s
entry.to_s(eol: eol)
end
}.join(' ')
content << TOKENS.last

super(content)
super(content, eol: eol)
end

def +(other)
Expand Down
4 changes: 2 additions & 2 deletions lib/origami/boolean.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ def initialize(value)
@value = (value == true)
end

def to_s #:nodoc:
super(@value.to_s)
def to_s(eol: $/) #:nodoc:
super(@value.to_s, eol: eol)
end

def self.parse(stream, _parser = nil) #:nodoc:
Expand Down
33 changes: 18 additions & 15 deletions lib/origami/dictionary.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,25 +101,28 @@ def self.parse(stream, parser = nil) #:nodoc:
dict
end

def to_s(indent: 1, tab: "\t") #:nodoc:
if indent > 0
content = TOKENS.first + EOL
self.each_pair do |key,value|
content << tab * indent << key.to_s << ' '
content << (value.is_a?(Dictionary) ? value.to_s(indent: indent+1) : value.to_s)
content << EOL
def to_s(indent: 1, tab: "\t", eol: $/) #:nodoc:
nl = eol
tab, nl = '', '' if indent == 0

content = TOKENS.first + nl
self.each_pair do |key,value|
content << "#{tab * indent}#{key} "

content <<
if value.is_a?(Dictionary)
value.to_s(eol: eol, indent: (indent == 0) ? 0 : indent + 1)
else
value.to_s(eol: eol)
end

content << tab * (indent - 1) << TOKENS.last
else
content = TOKENS.first.dup
self.each_pair do |key,value|
content << "#{key} #{value.is_a?(Dictionary) ? value.to_s(indent: 0) : value.to_s}"
end
content << TOKENS.last
content << nl
end

super(content)
content << tab * (indent - 1) if indent > 0
content << TOKENS.last

super(content, eol: eol)
end

#
Expand Down
4 changes: 2 additions & 2 deletions lib/origami/extensions/fdf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ def self.parse(stream) #:nodoc:
FDF::Header.new(maj, min)
end

def to_s
"%FDF-#{@major_version}.#{@minor_version}".b + EOL
def to_s(eol: $/)
"%FDF-#{@major_version}.#{@minor_version}".b + eol
end

def to_sym #:nodoc:
Expand Down
4 changes: 2 additions & 2 deletions lib/origami/extensions/ppklite.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ def self.parse(stream) #:nodoc:
#
# Outputs self into PDF code.
#
def to_s
"%PPKLITE-#{@major_version}.#{@minor_version}".b + EOL
def to_s(eol: $/)
"%PPKLITE-#{@major_version}.#{@minor_version}".b + eol
end

def to_sym #:nodoc:
Expand Down
5 changes: 2 additions & 3 deletions lib/origami/header.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ def self.parse(stream) #:nodoc:
#
# Outputs self into PDF code.
#
def to_s
"%PDF-#{@major_version}.#{@minor_version}".b + EOL
def to_s(eol: $/)
"%PDF-#{@major_version}.#{@minor_version}".b + eol
end

def to_sym #:nodoc:
Expand All @@ -73,5 +73,4 @@ def to_f #:nodoc:
end
end
end

end
4 changes: 2 additions & 2 deletions lib/origami/name.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ def hash #:nodoc:
@value.hash
end

def to_s #:nodoc:
super(TOKENS.first + Name.expand(@value))
def to_s(eol: $/) #:nodoc:
super(TOKENS.first + Name.expand(@value), eol: eol)
end

def self.parse(stream, _parser = nil) #:nodoc:
Expand Down
4 changes: 2 additions & 2 deletions lib/origami/null.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ def value
nil
end

def to_s #:nodoc:
super(TOKENS.first)
def to_s(eol: $/) #:nodoc:
super(TOKENS.first, eol: eol)
end
end

Expand Down
12 changes: 6 additions & 6 deletions lib/origami/numeric.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,6 @@ def abs
def **(val)
self.class.new(self.value ** val)
end

def to_s
super(self.value.to_s)
end
end

#
Expand Down Expand Up @@ -126,6 +122,10 @@ def self.parse(stream, _parser = nil) #:nodoc:
int
end

def to_s(eol: $/) #:nodoc:
super(self.value.to_s, eol: eol)
end

alias value to_i
end

Expand Down Expand Up @@ -173,8 +173,8 @@ def self.parse(stream, _parser = nil) #:nodoc:

alias value to_f

def to_s
sprintf("%f", self).sub(/\.0*$|(\.\d*[^0])0*$/, '\1')
def to_s(eol: $/) #:nodoc:
super(sprintf("%f", self).sub(/\.0*$|(\.\d*[^0])0*$/, '\1'), eol: eol)
end
end

Expand Down
10 changes: 5 additions & 5 deletions lib/origami/obfuscation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def self.junk_comment(max_size = 15)
byte = rand(256).chr until (not byte.nil? and byte != "\n" and byte != "\r"); byte
}.join

"%#{junk_comment}#{EOL}"
"%#{junk_comment}#{$/}"
end

def self.junk_object(type = nil)
Expand Down Expand Up @@ -221,9 +221,9 @@ def to_obfuscated_str
content = ""

content << @dictionary.to_obfuscated_str
content << "stream" + EOL
content << "stream" + $/
content << self.encoded_data
content << EOL << TOKENS.last
content << $/ << TOKENS.last

super(content)
end
Expand All @@ -233,10 +233,10 @@ class Trailer
def to_obfuscated_str
content = ""
if self.dictionary?
content << TOKENS.first << EOL << @dictionary.to_obfuscated_str << EOL
content << TOKENS.first << $/ << @dictionary.to_obfuscated_str << $/
end

content << XREF_TOKEN << EOL << @startxref.to_s << EOL << TOKENS.last << EOL
content << XREF_TOKEN << $/ << @startxref.to_s << $/ << TOKENS.last << $/

content
end
Expand Down
7 changes: 3 additions & 4 deletions lib/origami/object.rb
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,6 @@ def initialize(msg,obj)

WHITESPACES = "([ \\f\\t\\r\\n\\0]|%[^\\n\\r]*(\\r\\n|\\r|\\n))*" #:nodoc:
WHITECHARS_NORET = "[ \\f\\t\\0]*" #:nodoc:
EOL = "\r\n" #:nodoc:
WHITECHARS = "[ \\f\\t\\r\\n\\0]*" #:nodoc:
REGEXP_WHITESPACES = Regexp.new(WHITESPACES) #:nodoc:

Expand Down Expand Up @@ -674,11 +673,11 @@ def type
# Outputs this object into PDF code.
# _data_:: The object data.
#
def to_s(data)
def to_s(data, eol: $/)
content = ""
content << "#{no} #{generation} #{TOKENS.first}" << EOL if indirect? and numbered?
content << "#{no} #{generation} #{TOKENS.first}" << eol if indirect? and numbered?
content << data
content << EOL << TOKENS.last << EOL if indirect? and numbered?
content << eol << TOKENS.last << eol if indirect? and numbered?

content.force_encoding('binary')
end
Expand Down
29 changes: 22 additions & 7 deletions lib/origami/pdf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,7 @@ def output(params = {})

options =
{
eol: $/,
rebuild_xrefs: true,
noindent: false,
obfuscate: false,
Expand All @@ -797,14 +798,21 @@ def output(params = {})
}
options.update(params)

options[:up_to_revision] = @revisions.size if options[:up_to_revision] > @revisions.size
# Ensures we are using a valid EOL delimiter.
assert_valid_eol(options[:eol])

# Do not emit more revisions than present in the document.
options[:up_to_revision] = [ @revisions.size, options[:up_to_revision] ].min

# Reset to default params if no xrefs are chosen (hybrid files not supported yet)
if options[:use_xrefstm] == options[:use_xreftable]
options[:use_xrefstm] = has_objstm
options[:use_xreftable] = (not has_objstm)
end

# Indent level for objects.
indent = (options[:noindent] == true ? 0 : 1)

# Get trailer dictionary
trailer_dict = self.trailer.dictionary

Expand All @@ -813,7 +821,7 @@ def output(params = {})

# Header
bin = ""
bin << @header.to_s
bin << @header.to_s(eol: options[:eol])

# For each revision
@revisions[0, options[:up_to_revision]].each do |rev|
Expand Down Expand Up @@ -923,10 +931,10 @@ def output(params = {})
end

# Output object code
if (obj.is_a?(Dictionary) or obj.is_a?(Stream)) and options[:noindent]
bin << obj.to_s(indent: 0)
if (obj.is_a?(Dictionary) or obj.is_a?(Stream))
bin << obj.to_s(eol: options[:eol], indent: indent)
else
bin << obj.to_s
bin << obj.to_s(eol: options[:eol])
end
end
end # end each object
Expand Down Expand Up @@ -955,14 +963,21 @@ def output(params = {})
end

# Trailer
bin << rev.xreftable.to_s if options[:use_xreftable] == true
bin << (options[:obfuscate] == true ? rev.trailer.to_obfuscated_str : rev.trailer.to_s)
bin << rev.xreftable.to_s(eol: options[:eol]) if options[:use_xreftable] == true
bin << (options[:obfuscate] == true ? rev.trailer.to_obfuscated_str : rev.trailer.to_s(eol: options[:eol], indent: indent))

end # end each revision

bin
end

def assert_valid_eol(d)
allowed = [ "\n", "\r", "\r\n" ]
unless allowed.include?(d)
raise ArgumentError, "Invalid EOL delimiter #{d.inspect}, allowed: #{allowed.inspect}"
end
end

#
# Instanciates basic structures required for a valid PDF file.
#
Expand Down
4 changes: 2 additions & 2 deletions lib/origami/reference.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ def to_a
[@refno, @refgen]
end

def to_s #:nodoc:
super("#{@refno} #{@refgen} R")
def to_s(eol: $/) #:nodoc:
super("#{@refno} #{@refgen} R", eol: eol)
end

#
Expand Down
14 changes: 7 additions & 7 deletions lib/origami/signature.rb
Original file line number Diff line number Diff line change
Expand Up @@ -486,16 +486,16 @@ def pre_build #:nodoc:
super
end

def to_s(indent: 1, tab: "\t") #:nodoc:
def to_s(indent: 1, tab: "\t", eol: $/) #:nodoc:

# Must be deterministic.
indent, tab = 1, "\t"
indent, tab, eol = 1, "\t", $/

content = TOKENS.first + EOL
content = TOKENS.first + eol

self.to_a.sort_by{ |key, _| key }.reverse.each do |key, value|
content << tab * indent << key.to_s << " "
content << (value.is_a?(Dictionary) ? value.to_s(indent: indent + 1) : value.to_s) << EOL
content << (value.is_a?(Dictionary) ? value.to_s(indent: indent + 1) : value.to_s) << eol
end

content << tab * (indent - 1) << TOKENS.last
Expand All @@ -516,8 +516,8 @@ def ranges
end

def signature_offset #:nodoc:
indent, tab = 1, "\t"
content = "#{no} #{generation} obj" + EOL + TOKENS.first + EOL
indent, tab, eol = 1, "\t", $/
content = "#{no} #{generation} obj" + eol + TOKENS.first + eol

self.to_a.sort_by{ |key, _| key }.reverse.each do |key, value|
if key == :Contents
Expand All @@ -526,7 +526,7 @@ def signature_offset #:nodoc:
return content.size
else
content << tab * indent + key.to_s << " "
content << (value.is_a?(Dictionary) ? value.to_s(indent: indent + 1) : value.to_s) << EOL
content << (value.is_a?(Dictionary) ? value.to_s(indent: indent + 1) : value.to_s) << eol
end
end

Expand Down
8 changes: 4 additions & 4 deletions lib/origami/stream.rb
Original file line number Diff line number Diff line change
Expand Up @@ -333,15 +333,15 @@ def encode!
self
end

def to_s(indent: 1, tab: "\t") #:nodoc:
def to_s(indent: 1, tab: "\t", eol: $/) #:nodoc:
content = ""

content << @dictionary.to_s(indent: indent, tab: tab)
content << "stream" + EOL
content << "stream" + eol
content << self.encoded_data
content << EOL << TOKENS.last
content << eol << TOKENS.last

super(content)
super(content, eol: eol)
end

def [](key) #:nodoc:
Expand Down
Loading

0 comments on commit 98ea557

Please sign in to comment.