Module: Prawn::Core

Included in:
Document::Security
Defined in:
lib/prawn/security.rb,
lib/prawn/core/page.rb,
lib/prawn/core/text.rb,
lib/prawn/core/name_tree.rb,
lib/prawn/core/reference.rb,
lib/prawn/core/pdf_object.rb,
lib/prawn/core/annotations.rb,
lib/prawn/core/byte_string.rb,
lib/prawn/core/destinations.rb,
lib/prawn/core/object_store.rb,
lib/prawn/core/document_state.rb,
lib/prawn/core/literal_string.rb,
lib/prawn/document/graphics_state.rb,
lib/prawn/core/text/formatted/wrap.rb,
lib/prawn/core/text/formatted/arranger.rb,
lib/prawn/core/text/formatted/line_wrap.rb

Overview

:nodoc:

Defined Under Namespace

Modules: Annotations, Destinations, NameTree, Text Classes: ByteString, DocumentState, LiteralString, ObjectStore, Page, Reference

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.EncryptedPdfObject(obj, key, id, gen, in_content_stream = false) ⇒ Object

Like PdfObject, but returns an encrypted result if required. For direct objects, requires the object identifier and generation number from the indirect object referencing obj.



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/prawn/security.rb', line 208

def EncryptedPdfObject(obj, key, id, gen, in_content_stream=false)
  case obj
  when Array
    "[" << obj.map { |e|
        EncryptedPdfObject(e, key, id, gen, in_content_stream)
    }.join(' ') << "]"
  when LiteralString
    # FIXME: encrypted?
    obj = obj.gsub(/[\\\n\(\)]/) { |m| "\\#{m}" }
    "(#{obj})"
  when Time
    # FIXME: encrypted?
    obj = obj.strftime("D:%Y%m%d%H%M%S%z").chop.chop + "'00'"
    obj = obj.gsub(/[\\\n\(\)]/) { |m| "\\#{m}" }
    "(#{obj})"
  when String
    PdfObject(
      ByteString.new(
        Document::Security.encrypt_string(obj, key, id, gen)),
      in_content_stream)
  when Hash
    output = "<< "
    obj.each do |k,v|
      unless String === k || Symbol === k
        raise Prawn::Errors::FailedObjectConversion,
          "A PDF Dictionary must be keyed by names"
      end
      output << PdfObject(k.to_sym, in_content_stream) << " " <<
                EncryptedPdfObject(v, key, id, gen, in_content_stream) << "\n"
    end
    output << ">>"
  when NameTree::Value
    PdfObject(obj.name) + " " +
      EncryptedPdfObject(obj.value, key, id, gen, in_content_stream)
  when Prawn::OutlineRoot, Prawn::OutlineItem
    EncryptedPdfObject(obj.to_hash, key, id, gen, in_content_stream)
  else # delegate back to PdfObject
    PdfObject(obj, in_content_stream)
  end
end

.PdfObject(obj, in_content_stream = false) ⇒ Object

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:

   PdfObject(true)      #=> "true"
   PdfObject(false)     #=> "false" 
   PdfObject(1.2124)    #=> "1.2124"
   PdfObject("foo bar") #=> "(foo bar)"  
   PdfObject(:Symbol)   #=> "/Symbol"
   PdfObject(["foo",:bar, [1,2]]) #=> "[foo /bar [1 2]]"


66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/prawn/core/pdf_object.rb', line 66

def PdfObject(obj, in_content_stream = false)
  case(obj)        
  when NilClass   then "null" 
  when TrueClass  then "true"
  when FalseClass then "false"
  when Numeric
    if (str = String(obj)) =~ /e/i
      # scientific notation is not supported in PDF
      sprintf("%.16f", obj).gsub(/\.?0+\z/, "")
    else
      str
    end
  when Array
    "[" << obj.map { |e| PdfObject(e, in_content_stream) }.join(' ') << "]"
  when Prawn::Core::LiteralString
    obj = obj.gsub(/[\\\n\r\t\b\f\(\)]/n) { |m| "\\#{m}" }
    "(#{obj})"
  when Time
    obj = obj.strftime("D:%Y%m%d%H%M%S%z").chop.chop + "'00'"
    obj = obj.gsub(/[\\\n\r\t\b\f\(\)]/n) { |m| "\\#{m}" }
    "(#{obj})"
  when Prawn::Core::ByteString
    "<" << obj.unpack("H*").first << ">"
  when String
    obj = utf8_to_utf16(obj) unless in_content_stream
    "<" << string_to_hex(obj) << ">"
   when Symbol                                                         
     "/" + obj.to_s.unpack("C*").map { |n|
      if n < 33 || n > 126 || [35,40,41,47,60,62].include?(n)
        "#" + n.to_s(16).upcase
      else
        [n].pack("C*")
      end
     }.join
  when Hash           
    output = "<< "
    obj.each do |k,v|  
      unless String === k || Symbol === k
        raise Prawn::Errors::FailedObjectConversion, 
          "A PDF Dictionary must be keyed by names"
      end                          
      output << PdfObject(k.to_sym, in_content_stream) << " " << 
                PdfObject(v, in_content_stream) << "\n"
    end  
    output << ">>"  
  when Prawn::Core::Reference
    obj.to_s      
  when Prawn::Core::NameTree::Node
    PdfObject(obj.to_hash)
  when Prawn::Core::NameTree::Value
    PdfObject(obj.name) + " " + PdfObject(obj.value)
  when Prawn::OutlineRoot, Prawn::OutlineItem
    PdfObject(obj.to_hash)
  else
    raise Prawn::Errors::FailedObjectConversion, 
      "This object cannot be serialized to PDF (#{obj.inspect})"
  end     
end

.Reference(*args, &block) ⇒ Object

:nodoc:



111
112
113
# File 'lib/prawn/core/reference.rb', line 111

def Reference(*args, &block) #:nodoc:
  Reference.new(*args, &block)
end

Instance Method Details

#string_to_hex(str) ⇒ Object

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



25
26
27
# File 'lib/prawn/core/pdf_object.rb', line 25

def string_to_hex(str)
  str.unpack("H*").first.force_encoding("ascii")
end

#utf8_to_utf16(str) ⇒ Object

Ruby 1.8



18
19
20
# File 'lib/prawn/core/pdf_object.rb', line 18

def utf8_to_utf16(str)
  utf16 = "\xFE\xFF".force_encoding("UTF-16BE") + str.encode("UTF-16BE")
end