prawn-core 0.5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. data/COPYING +340 -0
  2. data/LICENSE +56 -0
  3. data/README +121 -0
  4. data/Rakefile +74 -0
  5. data/data/encodings/win_ansi.txt +29 -0
  6. data/data/fonts/Action Man.dfont +0 -0
  7. data/data/fonts/Activa.ttf +0 -0
  8. data/data/fonts/Chalkboard.ttf +0 -0
  9. data/data/fonts/Courier-Bold.afm +342 -0
  10. data/data/fonts/Courier-BoldOblique.afm +342 -0
  11. data/data/fonts/Courier-Oblique.afm +342 -0
  12. data/data/fonts/Courier.afm +342 -0
  13. data/data/fonts/DejaVuSans.ttf +0 -0
  14. data/data/fonts/Dustismo_Roman.ttf +0 -0
  15. data/data/fonts/Helvetica-Bold.afm +2827 -0
  16. data/data/fonts/Helvetica-BoldOblique.afm +2827 -0
  17. data/data/fonts/Helvetica-Oblique.afm +3051 -0
  18. data/data/fonts/Helvetica.afm +3051 -0
  19. data/data/fonts/MustRead.html +19 -0
  20. data/data/fonts/Symbol.afm +213 -0
  21. data/data/fonts/Times-Bold.afm +2588 -0
  22. data/data/fonts/Times-BoldItalic.afm +2384 -0
  23. data/data/fonts/Times-Italic.afm +2667 -0
  24. data/data/fonts/Times-Roman.afm +2419 -0
  25. data/data/fonts/ZapfDingbats.afm +225 -0
  26. data/data/fonts/comicsans.ttf +0 -0
  27. data/data/fonts/gkai00mp.ttf +0 -0
  28. data/data/images/16bit.alpha +0 -0
  29. data/data/images/16bit.dat +0 -0
  30. data/data/images/16bit.png +0 -0
  31. data/data/images/arrow.png +0 -0
  32. data/data/images/arrow2.png +0 -0
  33. data/data/images/barcode_issue.png +0 -0
  34. data/data/images/dice.alpha +0 -0
  35. data/data/images/dice.dat +0 -0
  36. data/data/images/dice.png +0 -0
  37. data/data/images/dice_interlaced.png +0 -0
  38. data/data/images/fractal.jpg +0 -0
  39. data/data/images/letterhead.jpg +0 -0
  40. data/data/images/page_white_text.alpha +0 -0
  41. data/data/images/page_white_text.dat +0 -0
  42. data/data/images/page_white_text.png +0 -0
  43. data/data/images/pigs.jpg +0 -0
  44. data/data/images/rails.dat +0 -0
  45. data/data/images/rails.png +0 -0
  46. data/data/images/ruport.png +0 -0
  47. data/data/images/ruport_data.dat +0 -0
  48. data/data/images/ruport_transparent.png +0 -0
  49. data/data/images/ruport_type0.png +0 -0
  50. data/data/images/stef.jpg +0 -0
  51. data/data/images/tru256.bmp +0 -0
  52. data/data/images/web-links.dat +1 -0
  53. data/data/images/web-links.png +0 -0
  54. data/data/shift_jis_text.txt +1 -0
  55. data/examples/bounding_box/bounding_boxes.rb +44 -0
  56. data/examples/bounding_box/russian_boxes.rb +37 -0
  57. data/examples/column_box/column_box_example.rb +44 -0
  58. data/examples/general/background.rb +20 -0
  59. data/examples/general/canvas.rb +16 -0
  60. data/examples/general/measurement_units.rb +52 -0
  61. data/examples/general/metadata-info.rb +17 -0
  62. data/examples/general/multi_page_layout.rb +17 -0
  63. data/examples/general/page_geometry.rb +32 -0
  64. data/examples/graphics/basic_images.rb +24 -0
  65. data/examples/graphics/cmyk.rb +13 -0
  66. data/examples/graphics/curves.rb +12 -0
  67. data/examples/graphics/hexagon.rb +14 -0
  68. data/examples/graphics/image_fit.rb +16 -0
  69. data/examples/graphics/image_flow.rb +38 -0
  70. data/examples/graphics/image_position.rb +18 -0
  71. data/examples/graphics/line.rb +33 -0
  72. data/examples/graphics/png_types.rb +23 -0
  73. data/examples/graphics/polygons.rb +17 -0
  74. data/examples/graphics/remote_images.rb +12 -0
  75. data/examples/graphics/ruport_style_helpers.rb +20 -0
  76. data/examples/graphics/stroke_bounds.rb +21 -0
  77. data/examples/m17n/chinese_text_wrapping.rb +20 -0
  78. data/examples/m17n/euro.rb +16 -0
  79. data/examples/m17n/sjis.rb +29 -0
  80. data/examples/m17n/utf8.rb +14 -0
  81. data/examples/m17n/win_ansi_charset.rb +55 -0
  82. data/examples/text/alignment.rb +19 -0
  83. data/examples/text/dfont.rb +49 -0
  84. data/examples/text/family_based_styling.rb +25 -0
  85. data/examples/text/font_calculations.rb +92 -0
  86. data/examples/text/font_size.rb +34 -0
  87. data/examples/text/kerning.rb +31 -0
  88. data/examples/text/simple_text.rb +18 -0
  89. data/examples/text/simple_text_ttf.rb +18 -0
  90. data/examples/text/span.rb +30 -0
  91. data/examples/text/text_box.rb +26 -0
  92. data/examples/text/text_flow.rb +68 -0
  93. data/lib/prawn/compatibility.rb +38 -0
  94. data/lib/prawn/core.rb +79 -0
  95. data/lib/prawn/document.rb +399 -0
  96. data/lib/prawn/document/annotations.rb +63 -0
  97. data/lib/prawn/document/bounding_box.rb +377 -0
  98. data/lib/prawn/document/column_box.rb +89 -0
  99. data/lib/prawn/document/destinations.rb +81 -0
  100. data/lib/prawn/document/internals.rb +133 -0
  101. data/lib/prawn/document/page_geometry.rb +149 -0
  102. data/lib/prawn/document/span.rb +55 -0
  103. data/lib/prawn/document/text.rb +186 -0
  104. data/lib/prawn/document/text/box.rb +83 -0
  105. data/lib/prawn/document/text/wrapping.rb +59 -0
  106. data/lib/prawn/encoding.rb +121 -0
  107. data/lib/prawn/errors.rb +49 -0
  108. data/lib/prawn/font.rb +292 -0
  109. data/lib/prawn/font/afm.rb +202 -0
  110. data/lib/prawn/font/dfont.rb +31 -0
  111. data/lib/prawn/font/ttf.rb +327 -0
  112. data/lib/prawn/graphics.rb +257 -0
  113. data/lib/prawn/graphics/color.rb +141 -0
  114. data/lib/prawn/images.rb +339 -0
  115. data/lib/prawn/images/jpg.rb +45 -0
  116. data/lib/prawn/images/png.rb +217 -0
  117. data/lib/prawn/literal_string.rb +14 -0
  118. data/lib/prawn/measurement_extensions.rb +46 -0
  119. data/lib/prawn/measurements.rb +71 -0
  120. data/lib/prawn/name_tree.rb +165 -0
  121. data/lib/prawn/pdf_object.rb +77 -0
  122. data/lib/prawn/reference.rb +59 -0
  123. data/spec/annotations_spec.rb +90 -0
  124. data/spec/bounding_box_spec.rb +141 -0
  125. data/spec/destinations_spec.rb +15 -0
  126. data/spec/document_spec.rb +178 -0
  127. data/spec/font_spec.rb +274 -0
  128. data/spec/graphics_spec.rb +209 -0
  129. data/spec/images_spec.rb +79 -0
  130. data/spec/jpg_spec.rb +25 -0
  131. data/spec/measurement_units_spec.rb +23 -0
  132. data/spec/name_tree_spec.rb +103 -0
  133. data/spec/pdf_object_spec.rb +117 -0
  134. data/spec/png_spec.rb +236 -0
  135. data/spec/reference_spec.rb +42 -0
  136. data/spec/span_spec.rb +45 -0
  137. data/spec/spec_helper.rb +23 -0
  138. data/spec/text_box_spec.rb +83 -0
  139. data/spec/text_spec.rb +178 -0
  140. data/vendor/pdf-inspector/README +18 -0
  141. data/vendor/pdf-inspector/lib/pdf/inspector.rb +25 -0
  142. data/vendor/pdf-inspector/lib/pdf/inspector/graphics.rb +80 -0
  143. data/vendor/pdf-inspector/lib/pdf/inspector/page.rb +16 -0
  144. data/vendor/pdf-inspector/lib/pdf/inspector/text.rb +31 -0
  145. data/vendor/pdf-inspector/lib/pdf/inspector/xobject.rb +19 -0
  146. data/vendor/ttfunk/data/fonts/DejaVuSans.ttf +0 -0
  147. data/vendor/ttfunk/data/fonts/comicsans.ttf +0 -0
  148. data/vendor/ttfunk/example.rb +45 -0
  149. data/vendor/ttfunk/lib/ttfunk.rb +102 -0
  150. data/vendor/ttfunk/lib/ttfunk/directory.rb +17 -0
  151. data/vendor/ttfunk/lib/ttfunk/encoding/mac_roman.rb +88 -0
  152. data/vendor/ttfunk/lib/ttfunk/encoding/windows_1252.rb +69 -0
  153. data/vendor/ttfunk/lib/ttfunk/reader.rb +44 -0
  154. data/vendor/ttfunk/lib/ttfunk/resource_file.rb +78 -0
  155. data/vendor/ttfunk/lib/ttfunk/subset.rb +18 -0
  156. data/vendor/ttfunk/lib/ttfunk/subset/base.rb +141 -0
  157. data/vendor/ttfunk/lib/ttfunk/subset/mac_roman.rb +46 -0
  158. data/vendor/ttfunk/lib/ttfunk/subset/unicode.rb +48 -0
  159. data/vendor/ttfunk/lib/ttfunk/subset/unicode_8bit.rb +63 -0
  160. data/vendor/ttfunk/lib/ttfunk/subset/windows_1252.rb +51 -0
  161. data/vendor/ttfunk/lib/ttfunk/subset_collection.rb +72 -0
  162. data/vendor/ttfunk/lib/ttfunk/table.rb +46 -0
  163. data/vendor/ttfunk/lib/ttfunk/table/cmap.rb +34 -0
  164. data/vendor/ttfunk/lib/ttfunk/table/cmap/format00.rb +54 -0
  165. data/vendor/ttfunk/lib/ttfunk/table/cmap/format04.rb +126 -0
  166. data/vendor/ttfunk/lib/ttfunk/table/cmap/subtable.rb +79 -0
  167. data/vendor/ttfunk/lib/ttfunk/table/glyf.rb +64 -0
  168. data/vendor/ttfunk/lib/ttfunk/table/glyf/compound.rb +81 -0
  169. data/vendor/ttfunk/lib/ttfunk/table/glyf/simple.rb +37 -0
  170. data/vendor/ttfunk/lib/ttfunk/table/head.rb +44 -0
  171. data/vendor/ttfunk/lib/ttfunk/table/hhea.rb +41 -0
  172. data/vendor/ttfunk/lib/ttfunk/table/hmtx.rb +47 -0
  173. data/vendor/ttfunk/lib/ttfunk/table/kern.rb +79 -0
  174. data/vendor/ttfunk/lib/ttfunk/table/kern/format0.rb +62 -0
  175. data/vendor/ttfunk/lib/ttfunk/table/loca.rb +43 -0
  176. data/vendor/ttfunk/lib/ttfunk/table/maxp.rb +40 -0
  177. data/vendor/ttfunk/lib/ttfunk/table/name.rb +119 -0
  178. data/vendor/ttfunk/lib/ttfunk/table/os2.rb +78 -0
  179. data/vendor/ttfunk/lib/ttfunk/table/post.rb +91 -0
  180. data/vendor/ttfunk/lib/ttfunk/table/post/format10.rb +43 -0
  181. data/vendor/ttfunk/lib/ttfunk/table/post/format20.rb +35 -0
  182. data/vendor/ttfunk/lib/ttfunk/table/post/format25.rb +23 -0
  183. data/vendor/ttfunk/lib/ttfunk/table/post/format30.rb +17 -0
  184. data/vendor/ttfunk/lib/ttfunk/table/post/format40.rb +17 -0
  185. data/vendor/ttfunk/lib/ttfunk/table/simple.rb +14 -0
  186. metadata +245 -0
@@ -0,0 +1,77 @@
1
+ # encoding: utf-8
2
+ #
3
+ # pdf_object.rb : Handles Ruby to PDF object serialization
4
+ #
5
+ # Copyright April 2008, Gregory Brown. All Rights Reserved.
6
+ #
7
+ # This is free software. Please see the LICENSE and COPYING files for details.
8
+
9
+ # Top level Module
10
+ #
11
+ module Prawn
12
+
13
+ module_function
14
+
15
+ # Serializes Ruby objects to their PDF equivalents. Most primitive objects
16
+ # will work as expected, but please note that Name objects are represented
17
+ # by Ruby Symbol objects and Dictionary objects are represented by Ruby hashes
18
+ # (keyed by symbols)
19
+ #
20
+ # Examples:
21
+ #
22
+ # PdfObject(true) #=> "true"
23
+ # PdfObject(false) #=> "false"
24
+ # PdfObject(1.2124) #=> "1.2124"
25
+ # PdfObject("foo bar") #=> "(foo bar)"
26
+ # PdfObject(:Symbol) #=> "/Symbol"
27
+ # PdfObject(["foo",:bar, [1,2]]) #=> "[foo /bar [1 2]]"
28
+ #
29
+ def PdfObject(obj, in_content_stream = false)
30
+ case(obj)
31
+ when NilClass then "null"
32
+ when TrueClass then "true"
33
+ when FalseClass then "false"
34
+ when Numeric then String(obj)
35
+ when Array
36
+ "[" << obj.map { |e| PdfObject(e, in_content_stream) }.join(' ') << "]"
37
+ when Prawn::LiteralString
38
+ obj = obj.gsub(/[\\\n\(\)]/) { |m| "\\#{m}" }
39
+ "(#{obj})"
40
+ when Time
41
+ obj = obj.strftime("D:%Y%m%d%H%M%S%z").chop.chop + "'00'"
42
+ obj = obj.gsub(/[\\\n\(\)]/) { |m| "\\#{m}" }
43
+ "(#{obj})"
44
+ when String
45
+ obj = "\xFE\xFF" + obj.unpack("U*").pack("n*") unless in_content_stream
46
+ "<" << obj.unpack("H*").first << ">"
47
+ when Symbol
48
+ if (obj = obj.to_s) =~ /\s/
49
+ raise Prawn::Errors::FailedObjectConversion,
50
+ "A PDF Name cannot contain whitespace"
51
+ else
52
+ "/" << obj
53
+ end
54
+ when Hash
55
+ output = "<< "
56
+ obj.each do |k,v|
57
+ unless String === k || Symbol === k
58
+ raise Prawn::Errors::FailedObjectConversion,
59
+ "A PDF Dictionary must be keyed by names"
60
+ end
61
+ output << PdfObject(k.to_sym, in_content_stream) << " " <<
62
+ PdfObject(v, in_content_stream) << "\n"
63
+ end
64
+ output << ">>"
65
+ when Prawn::Reference
66
+ obj.to_s
67
+ when Prawn::NameTree::Node
68
+ PdfObject(obj.to_hash)
69
+ when Prawn::NameTree::Value
70
+ PdfObject(obj.name) + " " + PdfObject(obj.value)
71
+ else
72
+ raise Prawn::Errors::FailedObjectConversion,
73
+ "This object cannot be serialized to PDF"
74
+ end
75
+ end
76
+
77
+ end
@@ -0,0 +1,59 @@
1
+ # encoding: utf-8
2
+
3
+ # reference.rb : Implementation of PDF indirect objects
4
+ #
5
+ # Copyright April 2008, Gregory Brown. All Rights Reserved.
6
+ #
7
+ # This is free software. Please see the LICENSE and COPYING files for details.
8
+
9
+ require 'zlib'
10
+
11
+ module Prawn
12
+
13
+ class Reference #:nodoc:
14
+
15
+ attr_accessor :gen, :data, :offset
16
+ attr_reader :identifier, :stream
17
+
18
+ def initialize(id, data, &block)
19
+ @identifier = id
20
+ @gen = 0
21
+ @data = data
22
+ @compressed = false
23
+ @on_encode = block
24
+ end
25
+
26
+ def object
27
+ @on_encode.call(self) if @on_encode
28
+ output = "#{@identifier} #{gen} obj\n" <<
29
+ Prawn::PdfObject(data) << "\n"
30
+ if @stream
31
+ output << "stream\n" << @stream << "\nendstream\n"
32
+ end
33
+ output << "endobj\n"
34
+ end
35
+
36
+ def <<(data)
37
+ raise 'Cannot add data to a stream that is compressed' if @compressed
38
+ (@stream ||= "") << data
39
+ end
40
+
41
+ def to_s
42
+ "#{@identifier} #{gen} R"
43
+ end
44
+
45
+ def compress_stream
46
+ @stream = Zlib::Deflate.deflate(@stream)
47
+ @data[:Filter] = :FlateDecode
48
+ @data[:Length] ||= @stream.length
49
+ @compressed = true
50
+ end
51
+ end
52
+
53
+ module_function
54
+
55
+ def Reference(*args, &block) #:nodoc:
56
+ Reference.new(*args, &block)
57
+ end
58
+
59
+ end
@@ -0,0 +1,90 @@
1
+ # encoding: utf-8
2
+
3
+ require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
4
+
5
+ class PageAnnotations
6
+ attr_reader :pages
7
+
8
+ def self.parse(document)
9
+ receiver = new
10
+ PDF::Reader.string(document.render, receiver)
11
+ return receiver
12
+ end
13
+
14
+ def initialize
15
+ @pages = []
16
+ end
17
+
18
+ def begin_page(params)
19
+ @pages << params
20
+ end
21
+ end
22
+
23
+ describe "When creating annotations" do
24
+
25
+ before(:each) { create_pdf }
26
+
27
+ it "should append annotation to current page" do
28
+ @pdf.start_new_page
29
+ @pdf.annotate(:Rect => [0,0,10,10], :Subtype => :Text, :Contents => "Hello world!")
30
+ obj = PageAnnotations.parse(@pdf)
31
+ obj.pages[0][:Annots].nil?.should == true
32
+ obj.pages[1][:Annots].length.should == 1
33
+ end
34
+
35
+ it "should force :Type to be :Annot" do
36
+ opts = @pdf.annotate(:Rect => [0,0,10,10], :Subtype => :Text, :Contents => "Hello world!")
37
+ opts[:Type].should == :Annot
38
+ opts = @pdf.annotate(:Type => :Bogus, :Rect => [0,0,10,10], :Subtype => :Text, :Contents => "Hello world!")
39
+ opts[:Type].should == :Annot
40
+ end
41
+
42
+ end
43
+
44
+ describe "When creating text annotations" do
45
+
46
+ before(:each) do
47
+ @rect = [0,0,10,10]
48
+ @content = "Hello, world!"
49
+ create_pdf
50
+ end
51
+
52
+ it "should build appropriate annotation" do
53
+ opts = @pdf.text_annotation(@rect, @content)
54
+ opts[:Type].should == :Annot
55
+ opts[:Subtype].should == :Text
56
+ opts[:Rect].should == @rect
57
+ opts[:Contents].should == @content
58
+ end
59
+
60
+ it "should merge extra options" do
61
+ opts = @pdf.text_annotation(@rect, @content, :Open => true, :Subtype => :Bogus)
62
+ opts[:Subtype].should == :Text
63
+ opts[:Open].should == true
64
+ end
65
+
66
+ end
67
+
68
+ describe "When creating link annotations" do
69
+
70
+ before(:each) do
71
+ @rect = [0,0,10,10]
72
+ @dest = "home"
73
+ create_pdf
74
+ end
75
+
76
+ it "should build appropriate annotation" do
77
+ opts = @pdf.link_annotation(@rect, :Dest => @dest)
78
+ opts[:Type].should == :Annot
79
+ opts[:Subtype].should == :Link
80
+ opts[:Rect].should == @rect
81
+ opts[:Dest].should == @dest
82
+ end
83
+
84
+ it "should merge extra options" do
85
+ opts = @pdf.link_annotation(@rect, :Dest => @dest, :Subtype => :Bogus)
86
+ opts[:Subtype].should == :Link
87
+ opts[:Dest].should == @dest
88
+ end
89
+
90
+ end
@@ -0,0 +1,141 @@
1
+ # encoding: utf-8
2
+
3
+ require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
4
+
5
+ describe "A bounding box" do
6
+
7
+ before(:each) do
8
+ @x = 100
9
+ @y = 125
10
+ @width = 50
11
+ @height = 75
12
+ @box = Prawn::Document::BoundingBox.new(nil, [@x,@y], :width => @width,
13
+ :height => @height )
14
+ end
15
+
16
+ it "should have an anchor at (x, y - height)" do
17
+ @box.anchor.should == [@x,@y-@height]
18
+ end
19
+
20
+ it "should have a left boundary of 0" do
21
+ @box.left.should == 0
22
+ end
23
+
24
+ it "should have a right boundary equal to the width" do
25
+ @box.right.should == @width
26
+ end
27
+
28
+ it "should have a top boundary of height" do
29
+ @box.top.should == @height
30
+ end
31
+
32
+ it "should have a bottom boundary of 0" do
33
+ @box.bottom.should == 0
34
+ end
35
+
36
+ it "should have a top-left of [0,height]" do
37
+ @box.top_left.should == [0,@height]
38
+ end
39
+
40
+ it "should have a top-right of [width,height]" do
41
+ @box.top_right.should == [@width,@height]
42
+ end
43
+
44
+ it "should have a bottom-left of [0,0]" do
45
+ @box.bottom_left.should == [0,0]
46
+ end
47
+
48
+ it "should have a bottom-right of [width,0]" do
49
+ @box.bottom_right.should == [@width,0]
50
+ end
51
+
52
+ it "should have an absolute left boundary of x" do
53
+ @box.absolute_left.should == @x
54
+ end
55
+
56
+ it "should have an absolute right boundary of x + width" do
57
+ @box.absolute_right.should == @x + @width
58
+ end
59
+
60
+ it "should have an absolute top boundary of y" do
61
+ @box.absolute_top.should == @y
62
+ end
63
+
64
+ it "should have an absolute bottom boundary of y - height" do
65
+ @box.absolute_bottom.should == @y - @height
66
+ end
67
+
68
+ it "should have an absolute bottom-left of [x,y-height]" do
69
+ @box.absolute_bottom_left.should == [@x, @y - @height]
70
+ end
71
+
72
+ it "should have an absolute bottom-right of [x+width,y-height]" do
73
+ @box.absolute_bottom_right.should == [@x + @width , @y - @height]
74
+ end
75
+
76
+ it "should have an absolute top-left of [x,y]" do
77
+ @box.absolute_top_left.should == [@x, @y]
78
+ end
79
+
80
+ it "should have an absolute top-right of [x+width,y]" do
81
+ @box.absolute_top_right.should == [@x + @width, @y]
82
+ end
83
+
84
+
85
+ end
86
+
87
+ describe "drawing bounding boxes" do
88
+
89
+ before(:each) { create_pdf }
90
+
91
+ it "should restore the margin box when bounding box exits" do
92
+ margin_box = @pdf.bounds
93
+
94
+ @pdf.bounding_box [100,500] do
95
+ #nothing
96
+ end
97
+
98
+ @pdf.bounds.should == margin_box
99
+
100
+ end
101
+
102
+ it "should restore the parent bounding box when calls are nested" do
103
+ @pdf.bounding_box [100,500], :width => 300, :height => 300 do
104
+
105
+ @pdf.bounds.absolute_top.should == 500 + @pdf.margin_box.absolute_bottom
106
+ @pdf.bounds.absolute_left.should == 100 + @pdf.margin_box.absolute_left
107
+
108
+ parent_box = @pdf.bounds
109
+
110
+ @pdf.bounding_box [50,200], :width => 100, :height => 100 do
111
+ @pdf.bounds.absolute_top.should == 200 + parent_box.absolute_bottom
112
+ @pdf.bounds.absolute_left.should == 50 + parent_box.absolute_left
113
+ end
114
+
115
+ @pdf.bounds.absolute_top.should == 500 + @pdf.margin_box.absolute_bottom
116
+ @pdf.bounds.absolute_left.should == 100 + @pdf.margin_box.absolute_left
117
+
118
+ end
119
+ end
120
+
121
+ it "should calculate a height if none is specified" do
122
+ @pdf.bounding_box([100, 500], :width => 100) do
123
+ @pdf.text "The rain in Spain falls mainly on the plains."
124
+ end
125
+
126
+ @pdf.y.should.be.close 458.384, 0.001
127
+ end
128
+
129
+ end
130
+
131
+ describe "A canvas" do
132
+ before(:each) { create_pdf }
133
+
134
+ it "should use whatever the last set y position is" do
135
+ @pdf.canvas do
136
+ @pdf.bounding_box([100,500],:width => 200) { @pdf.move_down 50 }
137
+ end
138
+ @pdf.y.should == 450
139
+ end
140
+ end
141
+
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
4
+
5
+ describe "When creating destinations" do
6
+
7
+ before(:each) { create_pdf }
8
+
9
+ it "should add entry to Dests name tree" do
10
+ @pdf.dests.data.empty?.should == true
11
+ @pdf.add_dest "candy", "chocolate"
12
+ @pdf.dests.data.size.should == 1
13
+ end
14
+
15
+ end
@@ -0,0 +1,178 @@
1
+ # encoding: utf-8
2
+ require "tempfile"
3
+
4
+ require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
5
+
6
+ describe "The cursor" do
7
+ it "should equal pdf.y - bounds.absolute_bottom" do
8
+ pdf = Prawn::Document.new
9
+ pdf.cursor.should == pdf.bounds.top
10
+
11
+ pdf.y = 300
12
+ pdf.cursor.should == pdf.y - pdf.bounds.absolute_bottom
13
+ end
14
+ end
15
+
16
+ describe "when generating a document from a subclass" do
17
+ it "should be an instance_eval of the subclass" do
18
+ custom_document = Class.new(Prawn::Document)
19
+ custom_document.generate(Tempfile.new("generate_test").path) do |e|
20
+ e.class.should == custom_document
21
+ assert e.kind_of?(Prawn::Document)
22
+ end
23
+ end
24
+ end
25
+
26
+
27
+ describe "When creating multi-page documents" do
28
+
29
+ before(:each) { create_pdf }
30
+
31
+ it "should initialize with a single page" do
32
+ page_counter = PDF::Inspector::Page.analyze(@pdf.render)
33
+
34
+ page_counter.pages.size.should == 1
35
+ @pdf.page_count.should == 1
36
+ end
37
+
38
+ it "should provide an accurate page_count" do
39
+ 3.times { @pdf.start_new_page }
40
+ page_counter = PDF::Inspector::Page.analyze(@pdf.render)
41
+
42
+ page_counter.pages.size.should == 4
43
+ @pdf.page_count.should == 4
44
+ end
45
+
46
+ end
47
+
48
+ describe "When beginning each new page" do
49
+
50
+ describe "Background template feature" do
51
+ before(:each) do
52
+ @filename = "#{Prawn::BASEDIR}/data/images/pigs.jpg"
53
+ @pdf = Prawn::Document.new(:background => @filename)
54
+ end
55
+ it "should place a background image if it is in options block" do
56
+ output = @pdf.render
57
+ images = PDF::Inspector::XObject.analyze(output)
58
+ # there should be 2 images in the page resources
59
+ images.page_xobjects.first.size.should == 1
60
+ end
61
+ it "should place a background image if it is in options block" do
62
+ @pdf.instance_variable_defined?(:@background).should == true
63
+ @pdf.instance_variable_get(:@background).should == @filename
64
+ end
65
+ end
66
+
67
+ end
68
+
69
+ describe "When ending each page" do
70
+
71
+ it "should not compress the page content stream if compression is disabled" do
72
+
73
+ pdf = Prawn::Document.new(:compress => false)
74
+ content_stub = pdf.ref({})
75
+ content_stub.stubs(:compress_stream).returns(true)
76
+ content_stub.expects(:compress_stream).never
77
+
78
+ pdf.instance_variable_set("@page_content", content_stub)
79
+ pdf.text "Hi There" * 20
80
+ pdf.render
81
+ end
82
+
83
+ it "should compress the page content stream if compression is enabled" do
84
+
85
+ pdf = Prawn::Document.new(:compress => true)
86
+ content_stub = pdf.ref({})
87
+ content_stub.stubs(:compress_stream).returns(true)
88
+ content_stub.expects(:compress_stream).once
89
+
90
+ pdf.instance_variable_set("@page_content", content_stub)
91
+ pdf.text "Hi There" * 20
92
+ pdf.render
93
+ end
94
+
95
+ it "should result in a smaller file size when compressed" do
96
+ doc_uncompressed = Prawn::Document.new
97
+ doc_compressed = Prawn::Document.new(:compress => true)
98
+ [doc_compressed, doc_uncompressed].each do |pdf|
99
+ pdf.font "#{Prawn::BASEDIR}/data/fonts/gkai00mp.ttf"
100
+ pdf.text "更可怕的是,同质化竞争对手可以按照URL中后面这个ID来遍历" * 10
101
+ end
102
+
103
+ doc_compressed.render.length.should.be < doc_uncompressed.render.length
104
+ end
105
+
106
+ end
107
+
108
+ describe "When setting page size" do
109
+ it "should default to LETTER" do
110
+ @pdf = Prawn::Document.new
111
+ pages = PDF::Inspector::Page.analyze(@pdf.render).pages
112
+ pages.first[:size].should == Prawn::Document::PageGeometry::SIZES["LETTER"]
113
+ end
114
+
115
+ (Prawn::Document::PageGeometry::SIZES.keys - ["LETTER"]).each do |k|
116
+ it "should provide #{k} geometry" do
117
+ @pdf = Prawn::Document.new(:page_size => k)
118
+ pages = PDF::Inspector::Page.analyze(@pdf.render).pages
119
+ pages.first[:size].should == Prawn::Document::PageGeometry::SIZES[k]
120
+ end
121
+ end
122
+
123
+ it "should allow custom page size" do
124
+ @pdf = Prawn::Document.new(:page_size => [1920, 1080] )
125
+ pages = PDF::Inspector::Page.analyze(@pdf.render).pages
126
+ pages.first[:size].should == [1920, 1080]
127
+ end
128
+
129
+ end
130
+
131
+ describe "When setting page layout" do
132
+ it "should reverse coordinates for landscape" do
133
+ @pdf = Prawn::Document.new(:page_size => "A4", :page_layout => :landscape)
134
+ pages = PDF::Inspector::Page.analyze(@pdf.render).pages
135
+ pages.first[:size].should == Prawn::Document::PageGeometry::SIZES["A4"].reverse
136
+ end
137
+ end
138
+
139
+ describe "The mask() feature" do
140
+ it "should allow transactional restoration of attributes" do
141
+ @pdf = Prawn::Document.new
142
+ y, line_width = @pdf.y, @pdf.line_width
143
+ @pdf.mask(:y, :line_width) do
144
+ @pdf.y = y + 1
145
+ @pdf.line_width = line_width + 1
146
+ @pdf.y.should.not == y
147
+ @pdf.line_width.should.not == line_width
148
+ end
149
+ @pdf.y.should == y
150
+ @pdf.line_width.should == line_width
151
+ end
152
+ end
153
+
154
+ describe "The render() feature" do
155
+ if "spec".respond_to?(:encode!)
156
+ it "should return a 8 bit encoded string on a m17n aware VM" do
157
+ @pdf = Prawn::Document.new(:page_size => "A4", :page_layout => :landscape)
158
+ @pdf.line [100,100], [200,200]
159
+ str = @pdf.render
160
+ str.encoding.to_s.should == "ASCII-8BIT"
161
+ end
162
+ end
163
+ end
164
+
165
+ describe "PDF file versions" do
166
+ it "should default to 1.3" do
167
+ @pdf = Prawn::Document.new
168
+ str = @pdf.render
169
+ str[0,8].should == "%PDF-1.3"
170
+ end
171
+
172
+ it "should allow the default to be changed" do
173
+ @pdf = Prawn::Document.new
174
+ @pdf.__send__(:min_version, 1.4)
175
+ str = @pdf.render
176
+ str[0,8].should == "%PDF-1.4"
177
+ end
178
+ end