alphasights-prawn 0.10.0

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 (244) hide show
  1. data/COPYING +340 -0
  2. data/HACKING +50 -0
  3. data/LICENSE +56 -0
  4. data/README +141 -0
  5. data/Rakefile +52 -0
  6. data/data/encodings/win_ansi.txt +29 -0
  7. data/data/fonts/Action Man.dfont +0 -0
  8. data/data/fonts/Activa.ttf +0 -0
  9. data/data/fonts/Chalkboard.ttf +0 -0
  10. data/data/fonts/Courier-Bold.afm +342 -0
  11. data/data/fonts/Courier-BoldOblique.afm +342 -0
  12. data/data/fonts/Courier-Oblique.afm +342 -0
  13. data/data/fonts/Courier.afm +342 -0
  14. data/data/fonts/DejaVuSans.ttf +0 -0
  15. data/data/fonts/Dustismo_Roman.ttf +0 -0
  16. data/data/fonts/Helvetica-Bold.afm +2827 -0
  17. data/data/fonts/Helvetica-BoldOblique.afm +2827 -0
  18. data/data/fonts/Helvetica-Oblique.afm +3051 -0
  19. data/data/fonts/Helvetica.afm +3051 -0
  20. data/data/fonts/MustRead.html +19 -0
  21. data/data/fonts/Symbol.afm +213 -0
  22. data/data/fonts/Times-Bold.afm +2588 -0
  23. data/data/fonts/Times-BoldItalic.afm +2384 -0
  24. data/data/fonts/Times-Italic.afm +2667 -0
  25. data/data/fonts/Times-Roman.afm +2419 -0
  26. data/data/fonts/ZapfDingbats.afm +225 -0
  27. data/data/fonts/comicsans.ttf +0 -0
  28. data/data/fonts/gkai00mp.ttf +0 -0
  29. data/data/images/16bit.alpha +0 -0
  30. data/data/images/16bit.dat +0 -0
  31. data/data/images/16bit.png +0 -0
  32. data/data/images/arrow.png +0 -0
  33. data/data/images/arrow2.png +0 -0
  34. data/data/images/barcode_issue.png +0 -0
  35. data/data/images/dice.alpha +0 -0
  36. data/data/images/dice.dat +0 -0
  37. data/data/images/dice.png +0 -0
  38. data/data/images/dice_interlaced.png +0 -0
  39. data/data/images/fractal.jpg +0 -0
  40. data/data/images/letterhead.jpg +0 -0
  41. data/data/images/page_white_text.alpha +0 -0
  42. data/data/images/page_white_text.dat +0 -0
  43. data/data/images/page_white_text.png +0 -0
  44. data/data/images/pigs.jpg +0 -0
  45. data/data/images/rails.dat +0 -0
  46. data/data/images/rails.png +0 -0
  47. data/data/images/ruport.png +0 -0
  48. data/data/images/ruport_data.dat +0 -0
  49. data/data/images/ruport_transparent.png +0 -0
  50. data/data/images/ruport_type0.png +0 -0
  51. data/data/images/stef.jpg +0 -0
  52. data/data/images/tru256.bmp +0 -0
  53. data/data/images/web-links.dat +1 -0
  54. data/data/images/web-links.png +0 -0
  55. data/data/pdfs/complex_template.pdf +0 -0
  56. data/data/pdfs/contains_ttf_font.pdf +0 -0
  57. data/data/pdfs/encrypted.pdf +0 -0
  58. data/data/pdfs/hexagon.pdf +61 -0
  59. data/data/pdfs/indirect_reference.pdf +86 -0
  60. data/data/pdfs/nested_pages.pdf +118 -0
  61. data/data/pdfs/resources_as_indirect_object.pdf +83 -0
  62. data/data/pdfs/two_hexagons.pdf +90 -0
  63. data/data/pdfs/version_1_6.pdf +61 -0
  64. data/data/shift_jis_text.txt +1 -0
  65. data/examples/bounding_box/bounding_boxes.rb +43 -0
  66. data/examples/bounding_box/indentation.rb +34 -0
  67. data/examples/bounding_box/russian_boxes.rb +36 -0
  68. data/examples/bounding_box/stretched_nesting.rb +67 -0
  69. data/examples/builder/simple.rb +28 -0
  70. data/examples/example_helper.rb +4 -0
  71. data/examples/general/background.rb +23 -0
  72. data/examples/general/canvas.rb +15 -0
  73. data/examples/general/context_sensitive_headers.rb +37 -0
  74. data/examples/general/float.rb +11 -0
  75. data/examples/general/margin.rb +36 -0
  76. data/examples/general/measurement_units.rb +51 -0
  77. data/examples/general/metadata-info.rb +16 -0
  78. data/examples/general/multi_page_layout.rb +18 -0
  79. data/examples/general/outlines.rb +50 -0
  80. data/examples/general/page_geometry.rb +31 -0
  81. data/examples/general/page_numbering.rb +15 -0
  82. data/examples/general/repeaters.rb +47 -0
  83. data/examples/general/stamp.rb +41 -0
  84. data/examples/general/templates.rb +13 -0
  85. data/examples/graphics/basic_images.rb +23 -0
  86. data/examples/graphics/chunkable.rb +38 -0
  87. data/examples/graphics/cmyk.rb +12 -0
  88. data/examples/graphics/curves.rb +11 -0
  89. data/examples/graphics/hexagon.rb +13 -0
  90. data/examples/graphics/image_fit.rb +15 -0
  91. data/examples/graphics/image_flow.rb +37 -0
  92. data/examples/graphics/image_position.rb +17 -0
  93. data/examples/graphics/line.rb +32 -0
  94. data/examples/graphics/png_types.rb +22 -0
  95. data/examples/graphics/polygons.rb +16 -0
  96. data/examples/graphics/remote_images.rb +12 -0
  97. data/examples/graphics/rounded_polygons.rb +19 -0
  98. data/examples/graphics/rounded_rectangle.rb +20 -0
  99. data/examples/graphics/ruport_style_helpers.rb +19 -0
  100. data/examples/graphics/stroke_bounds.rb +20 -0
  101. data/examples/graphics/stroke_cap_and_join.rb +45 -0
  102. data/examples/graphics/stroke_dash.rb +42 -0
  103. data/examples/graphics/transformations.rb +52 -0
  104. data/examples/graphics/transparency.rb +26 -0
  105. data/examples/m17n/chinese_text_wrapping.rb +17 -0
  106. data/examples/m17n/euro.rb +15 -0
  107. data/examples/m17n/sjis.rb +28 -0
  108. data/examples/m17n/utf8.rb +13 -0
  109. data/examples/m17n/win_ansi_charset.rb +54 -0
  110. data/examples/security/hello_foo.rb +8 -0
  111. data/examples/table/bill.rb +53 -0
  112. data/examples/table/cell.rb +12 -0
  113. data/examples/table/checkerboard.rb +22 -0
  114. data/examples/table/header.rb +14 -0
  115. data/examples/table/inline_format_table.rb +12 -0
  116. data/examples/table/multi_page_table.rb +9 -0
  117. data/examples/table/simple_table.rb +24 -0
  118. data/examples/table/subtable.rb +12 -0
  119. data/examples/table/widths.rb +20 -0
  120. data/examples/text/alignment.rb +18 -0
  121. data/examples/text/character_spacing.rb +12 -0
  122. data/examples/text/dfont.rb +48 -0
  123. data/examples/text/family_based_styling.rb +24 -0
  124. data/examples/text/font_calculations.rb +91 -0
  125. data/examples/text/font_size.rb +33 -0
  126. data/examples/text/hyphenation.rb +45 -0
  127. data/examples/text/indent_paragraphs.rb +22 -0
  128. data/examples/text/inline_format.rb +103 -0
  129. data/examples/text/kerning.rb +30 -0
  130. data/examples/text/rotated.rb +98 -0
  131. data/examples/text/shaped_text_box.rb +31 -0
  132. data/examples/text/simple_text.rb +17 -0
  133. data/examples/text/simple_text_ttf.rb +17 -0
  134. data/examples/text/text_box.rb +88 -0
  135. data/examples/text/text_box_returning_excess.rb +51 -0
  136. data/examples/text/text_flow.rb +67 -0
  137. data/lib/prawn.rb +27 -0
  138. data/lib/prawn/canvas.rb +119 -0
  139. data/lib/prawn/chunkable.rb +37 -0
  140. data/lib/prawn/compatibility.rb +51 -0
  141. data/lib/prawn/core.rb +85 -0
  142. data/lib/prawn/core/annotations.rb +61 -0
  143. data/lib/prawn/core/byte_string.rb +9 -0
  144. data/lib/prawn/core/chunk.rb +36 -0
  145. data/lib/prawn/core/destinations.rb +90 -0
  146. data/lib/prawn/core/document_state.rb +78 -0
  147. data/lib/prawn/core/literal_string.rb +16 -0
  148. data/lib/prawn/core/name_tree.rb +165 -0
  149. data/lib/prawn/core/object_store.rb +236 -0
  150. data/lib/prawn/core/page.rb +179 -0
  151. data/lib/prawn/core/pdf_object.rb +108 -0
  152. data/lib/prawn/core/reference.rb +112 -0
  153. data/lib/prawn/core/text.rb +140 -0
  154. data/lib/prawn/core/text/formatted/arranger.rb +266 -0
  155. data/lib/prawn/core/text/formatted/line_wrap.rb +127 -0
  156. data/lib/prawn/core/text/formatted/wrap.rb +112 -0
  157. data/lib/prawn/core/text/line_wrap.rb +209 -0
  158. data/lib/prawn/core/text/wrap.rb +80 -0
  159. data/lib/prawn/document.rb +573 -0
  160. data/lib/prawn/document/bounding_box.rb +425 -0
  161. data/lib/prawn/document/graphics_state.rb +48 -0
  162. data/lib/prawn/document/internals.rb +170 -0
  163. data/lib/prawn/document/page_geometry.rb +136 -0
  164. data/lib/prawn/document/snapshot.rb +87 -0
  165. data/lib/prawn/document_builder.rb +51 -0
  166. data/lib/prawn/document_builder/command.rb +38 -0
  167. data/lib/prawn/document_builder/constructs.rb +2 -0
  168. data/lib/prawn/document_builder/constructs/flowing_text_construct.rb +18 -0
  169. data/lib/prawn/document_builder/constructs/path_construct.rb +9 -0
  170. data/lib/prawn/document_builder/layout.rb +25 -0
  171. data/lib/prawn/document_builder/modifications.rb +2 -0
  172. data/lib/prawn/document_builder/modifications/layout_modification.rb +9 -0
  173. data/lib/prawn/document_builder/modifications/path_modification.rb +9 -0
  174. data/lib/prawn/encoding.rb +121 -0
  175. data/lib/prawn/errors.rb +94 -0
  176. data/lib/prawn/font.rb +341 -0
  177. data/lib/prawn/font/afm.rb +225 -0
  178. data/lib/prawn/font/dfont.rb +42 -0
  179. data/lib/prawn/font/ttf.rb +350 -0
  180. data/lib/prawn/graphics.rb +325 -0
  181. data/lib/prawn/graphics/cap_style.rb +38 -0
  182. data/lib/prawn/graphics/color.rb +205 -0
  183. data/lib/prawn/graphics/dash.rb +71 -0
  184. data/lib/prawn/graphics/join_style.rb +38 -0
  185. data/lib/prawn/graphics/transformation.rb +156 -0
  186. data/lib/prawn/graphics/transparency.rb +99 -0
  187. data/lib/prawn/images.rb +348 -0
  188. data/lib/prawn/images/jpg.rb +46 -0
  189. data/lib/prawn/images/png.rb +226 -0
  190. data/lib/prawn/measurement_extensions.rb +46 -0
  191. data/lib/prawn/measurements.rb +71 -0
  192. data/lib/prawn/outline.rb +278 -0
  193. data/lib/prawn/repeater.rb +129 -0
  194. data/lib/prawn/security.rb +262 -0
  195. data/lib/prawn/security/arcfour.rb +51 -0
  196. data/lib/prawn/stamp.rb +126 -0
  197. data/lib/prawn/table.rb +421 -0
  198. data/lib/prawn/table/accessors.rb +180 -0
  199. data/lib/prawn/table/cell.rb +350 -0
  200. data/lib/prawn/table/cell/in_table.rb +27 -0
  201. data/lib/prawn/table/cell/subtable.rb +65 -0
  202. data/lib/prawn/table/cell/text.rb +125 -0
  203. data/lib/prawn/text.rb +449 -0
  204. data/lib/prawn/text/box.rb +392 -0
  205. data/lib/prawn/text/formatted.rb +4 -0
  206. data/lib/prawn/text/formatted/box.rb +228 -0
  207. data/lib/prawn/text/formatted/fragment.rb +181 -0
  208. data/lib/prawn/text/formatted/parser.rb +213 -0
  209. data/spec/annotations_spec.rb +90 -0
  210. data/spec/bounding_box_spec.rb +190 -0
  211. data/spec/cell_spec.rb +348 -0
  212. data/spec/destinations_spec.rb +15 -0
  213. data/spec/document_spec.rb +473 -0
  214. data/spec/font_spec.rb +324 -0
  215. data/spec/formatted_text_arranger_spec.rb +426 -0
  216. data/spec/formatted_text_box_spec.rb +756 -0
  217. data/spec/formatted_text_fragment_spec.rb +211 -0
  218. data/spec/graphics_spec.rb +446 -0
  219. data/spec/images_spec.rb +96 -0
  220. data/spec/inline_formatted_text_parser_spec.rb +502 -0
  221. data/spec/jpg_spec.rb +25 -0
  222. data/spec/line_wrap_spec.rb +341 -0
  223. data/spec/measurement_units_spec.rb +23 -0
  224. data/spec/name_tree_spec.rb +112 -0
  225. data/spec/object_store_spec.rb +160 -0
  226. data/spec/outline_spec.rb +269 -0
  227. data/spec/pdf_object_spec.rb +170 -0
  228. data/spec/png_spec.rb +237 -0
  229. data/spec/reference_spec.rb +82 -0
  230. data/spec/repeater_spec.rb +96 -0
  231. data/spec/security_spec.rb +120 -0
  232. data/spec/snapshot_spec.rb +138 -0
  233. data/spec/spec_helper.rb +26 -0
  234. data/spec/stamp_spec.rb +108 -0
  235. data/spec/stroke_styles_spec.rb +163 -0
  236. data/spec/table_spec.rb +598 -0
  237. data/spec/template_spec.rb +158 -0
  238. data/spec/text_at_spec.rb +119 -0
  239. data/spec/text_box_spec.rb +742 -0
  240. data/spec/text_spacing_spec.rb +75 -0
  241. data/spec/text_spec.rb +333 -0
  242. data/spec/text_with_inline_formatting_spec.rb +193 -0
  243. data/spec/transparency_spec.rb +89 -0
  244. metadata +331 -0
@@ -0,0 +1,112 @@
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
+ module Core
13
+
14
+ class Reference #:nodoc:
15
+
16
+ attr_accessor :gen, :data, :offset, :stream, :live, :identifier
17
+
18
+ def initialize(id, data)
19
+ @identifier = id
20
+ @gen = 0
21
+ @data = data
22
+ @compressed = false
23
+ @stream = nil
24
+ end
25
+
26
+ def object
27
+ output = "#{@identifier} #{gen} obj\n" <<
28
+ Prawn::Core::PdfObject(data) << "\n"
29
+ if @stream
30
+ output << "stream\n" << @stream << "\nendstream\n"
31
+ end
32
+ output << "endobj\n"
33
+ end
34
+
35
+ def <<(data)
36
+ raise 'Cannot add data to a stream that is compressed' if @compressed
37
+ (@stream ||= "") << data
38
+ end
39
+
40
+ def to_s
41
+ "#{@identifier} #{gen} R"
42
+ end
43
+
44
+ def compress_stream
45
+ @stream = Zlib::Deflate.deflate(@stream)
46
+ @data[:Filter] = :FlateDecode
47
+ @data[:Length] ||= @stream.length
48
+ @compressed = true
49
+ end
50
+
51
+ def compressed?
52
+ @compressed
53
+ end
54
+
55
+ # Creates a deep copy of this ref. If +share+ is provided, shares the
56
+ # given dictionary entries between the old ref and the new.
57
+ #
58
+ def deep_copy(share=[])
59
+ r = dup
60
+
61
+ if r.data.is_a?(Hash)
62
+ # Copy each entry not in +share+.
63
+ (r.data.keys - share).each do |k|
64
+ r.data[k] = Marshal.load(Marshal.dump(r.data[k]))
65
+ end
66
+ else
67
+ r.data = Marshal.load(Marshal.dump(r.data))
68
+ end
69
+
70
+ r.stream = Marshal.load(Marshal.dump(r.stream))
71
+ r
72
+ end
73
+
74
+ # Replaces the data and stream with that of other_ref. Preserves compressed
75
+ # status.
76
+ def replace(other_ref)
77
+ @data = other_ref.data
78
+ @stream = other_ref.stream
79
+ @compressed = other_ref.compressed?
80
+ end
81
+
82
+ # Marks this and all referenced objects live, recursively.
83
+ def mark_live
84
+ return if @live
85
+ @live = true
86
+ referenced_objects.each { |o| o.mark_live }
87
+ end
88
+
89
+ private
90
+
91
+ # All objects referenced by this one. Used for GC.
92
+ def referenced_objects(obj=@data)
93
+ case obj
94
+ when self.class
95
+ []
96
+ when Hash
97
+ obj.values.map{|v| [v] + referenced_objects(v) }
98
+ when Array
99
+ obj.map{|v| [v] + referenced_objects(v) }
100
+ else []
101
+ end.flatten.grep(self.class)
102
+ end
103
+
104
+ end
105
+
106
+ module_function
107
+
108
+ def Reference(*args, &block) #:nodoc:
109
+ Reference.new(*args, &block)
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,140 @@
1
+ # encoding: utf-8
2
+
3
+ # prawn/core/text.rb : Implements low level text helpers for Prawn
4
+ #
5
+ # Copyright January 2010, Daniel Nelson. All Rights Reserved.
6
+ #
7
+ # This is free software. Please see the LICENSE and COPYING files for details.
8
+
9
+ ruby_18 { $KCODE="U" }
10
+
11
+ module Prawn
12
+ module Core
13
+ module Text #:nodoc:
14
+
15
+ # These should be used as a base. Extensions may build on this list
16
+ #
17
+ VALID_OPTIONS = [:kerning, :size, :style]
18
+
19
+ attr_reader :skip_encoding
20
+
21
+ # Low level text placement method. All font and size alterations
22
+ # should already be set
23
+ #
24
+ def draw_text!(text, options)
25
+ x,y = map_to_absolute(options[:at])
26
+ add_text_content(text,x,y,options)
27
+ end
28
+
29
+ # Low level call to set the current font style and extract text options from
30
+ # an options hash. Should be called from within a save_font block
31
+ #
32
+ def process_text_options(options)
33
+ if options[:style]
34
+ raise "Bad font family" unless font.family
35
+ font(font.family, :style => options[:style])
36
+ end
37
+
38
+ # must compare against false to keep kerning on as default
39
+ unless options[:kerning] == false
40
+ options[:kerning] = font.has_kerning_data?
41
+ end
42
+
43
+ options[:size] ||= font_size
44
+ end
45
+
46
+ # Document wide setting of whether or not to use kerning with text
47
+ # Defaults to true
48
+ # Can be overridden using the :kerning text option
49
+ #
50
+ def default_kerning?
51
+ return true if @default_kerning.nil?
52
+ @default_kerning
53
+ end
54
+
55
+ def default_kerning(boolean)
56
+ @default_kerning = boolean
57
+ end
58
+
59
+ alias_method :default_kerning=, :default_kerning
60
+
61
+ # Document wide setting of leading
62
+ # Defaults to 0
63
+ # Can be overridden using the :leading text option
64
+ #
65
+ def default_leading?
66
+ return 0 if @default_leading.nil?
67
+ @default_leading
68
+ end
69
+
70
+ def default_leading(number)
71
+ @default_leading = number
72
+ end
73
+
74
+ alias_method :default_leading=, :default_leading
75
+
76
+ # Increases or decreases the space between characters.
77
+ # For horizontal text, a positive value will increase the space.
78
+ # For veritical text, a positive value will decrease the space.
79
+ #
80
+ def character_spacing(amount=nil)
81
+ return @character_spacing || 0 if amount.nil?
82
+ original_character_spacing = character_spacing
83
+ if original_character_spacing == amount
84
+ yield
85
+ else
86
+ @character_spacing = amount
87
+ add_content "\n%.3f Tc" % amount
88
+ yield
89
+ add_content "\n%.3f Tc" % original_character_spacing
90
+ @character_spacing = original_character_spacing
91
+ end
92
+ end
93
+
94
+ # Increases or decreases the space between words.
95
+ # For horizontal text, a positive value will increase the space.
96
+ # For veritical text, a positive value will decrease the space.
97
+ #
98
+ def word_spacing(amount=nil)
99
+ return @word_spacing || 0 if amount.nil?
100
+ original_word_spacing = word_spacing
101
+ if original_word_spacing == amount
102
+ yield
103
+ else
104
+ @word_spacing = amount
105
+ add_content "\n%.3f Tw" % amount
106
+ yield
107
+ add_content "\n%.3f Tw" % original_word_spacing
108
+ @word_spacing = original_word_spacing
109
+ end
110
+ end
111
+
112
+ private
113
+
114
+ def add_text_content(text, x, y, options)
115
+ chunks = font.encode_text(text,options)
116
+
117
+ add_content "\nBT"
118
+
119
+ if options[:rotate]
120
+ rad = options[:rotate].to_i * Math::PI / 180
121
+ arr = [ Math.cos(rad), Math.sin(rad), -Math.sin(rad), Math.cos(rad), x, y ]
122
+ add_content "%.3f %.3f %.3f %.3f %.3f %.3f Tm" % arr
123
+ else
124
+ add_content "#{x} #{y} Td"
125
+ end
126
+
127
+ chunks.each do |(subset, string)|
128
+ font.add_to_current_page(subset)
129
+ add_content "/#{font.identifier_for(subset)} #{font_size} Tf"
130
+
131
+ operation = options[:kerning] && string.is_a?(Array) ? "TJ" : "Tj"
132
+ add_content Prawn::Core::PdfObject(string, true) << " " << operation
133
+ end
134
+
135
+ add_content "ET\n"
136
+ end
137
+ end
138
+
139
+ end
140
+ end
@@ -0,0 +1,266 @@
1
+ # encoding: utf-8
2
+
3
+ # core/text/formatted/arranger.rb : Implements a data structure for 2-stage
4
+ # processing of lines of formatted text
5
+ #
6
+ # Copyright February 2010, Daniel Nelson. All Rights Reserved.
7
+ #
8
+ # This is free software. Please see the LICENSE and COPYING files for details.
9
+
10
+ module Prawn
11
+ module Core
12
+ module Text
13
+ module Formatted #:nodoc:
14
+
15
+ class Arranger #:nodoc:
16
+ attr_reader :max_line_height
17
+ attr_reader :max_descender
18
+ attr_reader :max_ascender
19
+
20
+ # The following present only for testing purposes
21
+ attr_reader :unconsumed
22
+ attr_reader :consumed
23
+ attr_reader :fragments
24
+ attr_reader :current_format_state
25
+
26
+ def initialize(document)
27
+ @document = document
28
+ @fragments = []
29
+ @unconsumed = []
30
+ end
31
+
32
+ def space_count
33
+ if @unfinalized_line
34
+ raise "Lines must be finalized before calling #space_count"
35
+ end
36
+ @fragments.inject(0) do |sum, fragment|
37
+ sum + fragment.text.count(" ")
38
+ end
39
+ end
40
+
41
+ def line_width
42
+ if @unfinalized_line
43
+ raise "Lines must be finalized before calling #line_width"
44
+ end
45
+ @fragments.inject(0) do |sum, fragment|
46
+ sum + fragment.width
47
+ end
48
+ end
49
+
50
+ def line
51
+ if @unfinalized_line
52
+ raise "Lines must be finalized before calling #line"
53
+ end
54
+ @fragments.collect { |fragment| fragment.text }.join("")
55
+ end
56
+
57
+ def finalize_line
58
+ @unfinalized_line = false
59
+ remove_trailing_whitespace_from_consumed
60
+ @fragments = []
61
+ @consumed.each do |hash|
62
+ text = hash[:text]
63
+ format_state = hash.dup
64
+ format_state.delete(:text)
65
+ fragment = Prawn::Text::Formatted::Fragment.new(text,
66
+ format_state,
67
+ @document)
68
+ @fragments << fragment
69
+ set_fragment_measurements(fragment)
70
+ set_line_measurement_maximums(fragment)
71
+ end
72
+ end
73
+
74
+ def format_array=(array)
75
+ initialize_line
76
+ @unconsumed = []
77
+ array.each do |hash|
78
+ hash[:text].scan(/[^\n]+|\n/) do |line|
79
+ @unconsumed << hash.merge(:text => line)
80
+ end
81
+ end
82
+ end
83
+
84
+ def initialize_line
85
+ @unfinalized_line = true
86
+ @max_line_height = 0
87
+ @max_descender = 0
88
+ @max_ascender = 0
89
+ @consumed = []
90
+ @fragments = []
91
+ end
92
+
93
+ def finished?
94
+ @unconsumed.length == 0
95
+ end
96
+
97
+ def unfinished?
98
+ @unconsumed.length > 0
99
+ end
100
+
101
+ def next_string
102
+ unless @unfinalized_line
103
+ raise "Lines must not be finalized when calling #next_string"
104
+ end
105
+ hash = @unconsumed.shift
106
+ if hash.nil?
107
+ nil
108
+ else
109
+ @consumed << hash.dup
110
+ @current_format_state = hash.dup
111
+ @current_format_state.delete(:text)
112
+ hash[:text]
113
+ end
114
+ end
115
+
116
+ def preview_next_string
117
+ hash = @unconsumed.first
118
+ if hash.nil? then nil
119
+ else hash[:text]
120
+ end
121
+ end
122
+
123
+ def apply_color_and_font_settings(fragment, &block)
124
+ if fragment.color
125
+ original_fill_color = @document.fill_color
126
+ original_stroke_color = @document.stroke_color
127
+ @document.fill_color(*fragment.color)
128
+ @document.stroke_color(*fragment.color)
129
+ apply_font_settings(fragment, &block)
130
+ @document.stroke_color = original_stroke_color
131
+ @document.fill_color = original_fill_color
132
+ else
133
+ apply_font_settings(fragment, &block)
134
+ end
135
+ end
136
+
137
+ def apply_font_settings(fragment=nil, &block)
138
+ if fragment.nil?
139
+ font = current_format_state[:font]
140
+ size = current_format_state[:size]
141
+ character_spacing = current_format_state[:character_spacing] ||
142
+ @document.character_spacing
143
+ styles = current_format_state[:styles]
144
+ font_style = font_style(styles)
145
+ else
146
+ font = fragment.font
147
+ size = fragment.size
148
+ character_spacing = fragment.character_spacing
149
+ styles = fragment.styles
150
+ font_style = font_style(styles)
151
+ end
152
+
153
+ @document.character_spacing(character_spacing) do
154
+ if font || font_style != :normal
155
+ raise "Bad font family" unless @document.font.family
156
+ @document.font(font || @document.font.family, :style => font_style) do
157
+ apply_font_size(size, styles, &block)
158
+ end
159
+ else
160
+ apply_font_size(size, styles, &block)
161
+ end
162
+ end
163
+ end
164
+
165
+ def update_last_string(printed, unprinted)
166
+ return if printed.nil?
167
+ if printed.empty?
168
+ @consumed.pop
169
+ else
170
+ @consumed.last[:text] = printed
171
+ end
172
+
173
+ unless unprinted.empty?
174
+ @unconsumed.unshift(@current_format_state.merge(:text => unprinted))
175
+ end
176
+ end
177
+
178
+ def retrieve_fragment
179
+ if @unfinalized_line
180
+ raise "Lines must be finalized before fragments can be retrieved"
181
+ end
182
+ @fragments.shift
183
+ end
184
+
185
+ def repack_unretrieved
186
+ new_unconsumed = []
187
+ while fragment = retrieve_fragment
188
+ new_unconsumed << fragment.format_state.merge(:text => fragment.text)
189
+ end
190
+ @unconsumed = new_unconsumed.concat(@unconsumed)
191
+ end
192
+
193
+ def font_style(styles)
194
+ if styles.nil?
195
+ :normal
196
+ elsif styles.include?(:bold) && styles.include?(:italic)
197
+ :bold_italic
198
+ elsif styles.include?(:bold)
199
+ :bold
200
+ elsif styles.include?(:italic)
201
+ :italic
202
+ else
203
+ :normal
204
+ end
205
+ end
206
+
207
+ private
208
+
209
+ def apply_font_size(size, styles)
210
+ if subscript?(styles) || superscript?(styles)
211
+ size = @document.font_size * 0.583
212
+ end
213
+ if size.nil?
214
+ yield
215
+ else
216
+ @document.font_size(size) { yield }
217
+ end
218
+ end
219
+
220
+ def subscript?(styles)
221
+ if styles.nil? then false
222
+ else styles.include?(:subscript)
223
+ end
224
+ end
225
+
226
+ def superscript?(styles)
227
+ if styles.nil? then false
228
+ else styles.include?(:superscript)
229
+ end
230
+ end
231
+
232
+ def remove_trailing_whitespace_from_consumed
233
+ @consumed.reverse_each do |hash|
234
+ if hash[:text] == "\n"
235
+ break
236
+ elsif hash[:text].strip.empty? && @consumed.length > 1
237
+ @consumed.pop
238
+ else
239
+ hash[:text].rstrip!
240
+ break
241
+ end
242
+ end
243
+ end
244
+
245
+ def set_fragment_measurements(fragment)
246
+ apply_font_settings(fragment) do
247
+ fragment.width = @document.width_of(fragment.text,
248
+ :kerning => @kerning)
249
+ fragment.line_height = @document.font.height
250
+ fragment.descender = @document.font.descender
251
+ fragment.ascender = @document.font.ascender
252
+ end
253
+ end
254
+
255
+ def set_line_measurement_maximums(fragment)
256
+ @max_line_height = [@max_line_height, fragment.line_height].max
257
+ @max_descender = [@max_descender, fragment.descender].max
258
+ @max_ascender = [@max_ascender, fragment.ascender].max
259
+ end
260
+
261
+ end
262
+
263
+ end
264
+ end
265
+ end
266
+ end