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.
- data/COPYING +340 -0
- data/HACKING +50 -0
- data/LICENSE +56 -0
- data/README +141 -0
- data/Rakefile +52 -0
- data/data/encodings/win_ansi.txt +29 -0
- data/data/fonts/Action Man.dfont +0 -0
- data/data/fonts/Activa.ttf +0 -0
- data/data/fonts/Chalkboard.ttf +0 -0
- data/data/fonts/Courier-Bold.afm +342 -0
- data/data/fonts/Courier-BoldOblique.afm +342 -0
- data/data/fonts/Courier-Oblique.afm +342 -0
- data/data/fonts/Courier.afm +342 -0
- data/data/fonts/DejaVuSans.ttf +0 -0
- data/data/fonts/Dustismo_Roman.ttf +0 -0
- data/data/fonts/Helvetica-Bold.afm +2827 -0
- data/data/fonts/Helvetica-BoldOblique.afm +2827 -0
- data/data/fonts/Helvetica-Oblique.afm +3051 -0
- data/data/fonts/Helvetica.afm +3051 -0
- data/data/fonts/MustRead.html +19 -0
- data/data/fonts/Symbol.afm +213 -0
- data/data/fonts/Times-Bold.afm +2588 -0
- data/data/fonts/Times-BoldItalic.afm +2384 -0
- data/data/fonts/Times-Italic.afm +2667 -0
- data/data/fonts/Times-Roman.afm +2419 -0
- data/data/fonts/ZapfDingbats.afm +225 -0
- data/data/fonts/comicsans.ttf +0 -0
- data/data/fonts/gkai00mp.ttf +0 -0
- data/data/images/16bit.alpha +0 -0
- data/data/images/16bit.dat +0 -0
- data/data/images/16bit.png +0 -0
- data/data/images/arrow.png +0 -0
- data/data/images/arrow2.png +0 -0
- data/data/images/barcode_issue.png +0 -0
- data/data/images/dice.alpha +0 -0
- data/data/images/dice.dat +0 -0
- data/data/images/dice.png +0 -0
- data/data/images/dice_interlaced.png +0 -0
- data/data/images/fractal.jpg +0 -0
- data/data/images/letterhead.jpg +0 -0
- data/data/images/page_white_text.alpha +0 -0
- data/data/images/page_white_text.dat +0 -0
- data/data/images/page_white_text.png +0 -0
- data/data/images/pigs.jpg +0 -0
- data/data/images/rails.dat +0 -0
- data/data/images/rails.png +0 -0
- data/data/images/ruport.png +0 -0
- data/data/images/ruport_data.dat +0 -0
- data/data/images/ruport_transparent.png +0 -0
- data/data/images/ruport_type0.png +0 -0
- data/data/images/stef.jpg +0 -0
- data/data/images/tru256.bmp +0 -0
- data/data/images/web-links.dat +1 -0
- data/data/images/web-links.png +0 -0
- data/data/pdfs/complex_template.pdf +0 -0
- data/data/pdfs/contains_ttf_font.pdf +0 -0
- data/data/pdfs/encrypted.pdf +0 -0
- data/data/pdfs/hexagon.pdf +61 -0
- data/data/pdfs/indirect_reference.pdf +86 -0
- data/data/pdfs/nested_pages.pdf +118 -0
- data/data/pdfs/resources_as_indirect_object.pdf +83 -0
- data/data/pdfs/two_hexagons.pdf +90 -0
- data/data/pdfs/version_1_6.pdf +61 -0
- data/data/shift_jis_text.txt +1 -0
- data/examples/bounding_box/bounding_boxes.rb +43 -0
- data/examples/bounding_box/indentation.rb +34 -0
- data/examples/bounding_box/russian_boxes.rb +36 -0
- data/examples/bounding_box/stretched_nesting.rb +67 -0
- data/examples/builder/simple.rb +28 -0
- data/examples/example_helper.rb +4 -0
- data/examples/general/background.rb +23 -0
- data/examples/general/canvas.rb +15 -0
- data/examples/general/context_sensitive_headers.rb +37 -0
- data/examples/general/float.rb +11 -0
- data/examples/general/margin.rb +36 -0
- data/examples/general/measurement_units.rb +51 -0
- data/examples/general/metadata-info.rb +16 -0
- data/examples/general/multi_page_layout.rb +18 -0
- data/examples/general/outlines.rb +50 -0
- data/examples/general/page_geometry.rb +31 -0
- data/examples/general/page_numbering.rb +15 -0
- data/examples/general/repeaters.rb +47 -0
- data/examples/general/stamp.rb +41 -0
- data/examples/general/templates.rb +13 -0
- data/examples/graphics/basic_images.rb +23 -0
- data/examples/graphics/chunkable.rb +38 -0
- data/examples/graphics/cmyk.rb +12 -0
- data/examples/graphics/curves.rb +11 -0
- data/examples/graphics/hexagon.rb +13 -0
- data/examples/graphics/image_fit.rb +15 -0
- data/examples/graphics/image_flow.rb +37 -0
- data/examples/graphics/image_position.rb +17 -0
- data/examples/graphics/line.rb +32 -0
- data/examples/graphics/png_types.rb +22 -0
- data/examples/graphics/polygons.rb +16 -0
- data/examples/graphics/remote_images.rb +12 -0
- data/examples/graphics/rounded_polygons.rb +19 -0
- data/examples/graphics/rounded_rectangle.rb +20 -0
- data/examples/graphics/ruport_style_helpers.rb +19 -0
- data/examples/graphics/stroke_bounds.rb +20 -0
- data/examples/graphics/stroke_cap_and_join.rb +45 -0
- data/examples/graphics/stroke_dash.rb +42 -0
- data/examples/graphics/transformations.rb +52 -0
- data/examples/graphics/transparency.rb +26 -0
- data/examples/m17n/chinese_text_wrapping.rb +17 -0
- data/examples/m17n/euro.rb +15 -0
- data/examples/m17n/sjis.rb +28 -0
- data/examples/m17n/utf8.rb +13 -0
- data/examples/m17n/win_ansi_charset.rb +54 -0
- data/examples/security/hello_foo.rb +8 -0
- data/examples/table/bill.rb +53 -0
- data/examples/table/cell.rb +12 -0
- data/examples/table/checkerboard.rb +22 -0
- data/examples/table/header.rb +14 -0
- data/examples/table/inline_format_table.rb +12 -0
- data/examples/table/multi_page_table.rb +9 -0
- data/examples/table/simple_table.rb +24 -0
- data/examples/table/subtable.rb +12 -0
- data/examples/table/widths.rb +20 -0
- data/examples/text/alignment.rb +18 -0
- data/examples/text/character_spacing.rb +12 -0
- data/examples/text/dfont.rb +48 -0
- data/examples/text/family_based_styling.rb +24 -0
- data/examples/text/font_calculations.rb +91 -0
- data/examples/text/font_size.rb +33 -0
- data/examples/text/hyphenation.rb +45 -0
- data/examples/text/indent_paragraphs.rb +22 -0
- data/examples/text/inline_format.rb +103 -0
- data/examples/text/kerning.rb +30 -0
- data/examples/text/rotated.rb +98 -0
- data/examples/text/shaped_text_box.rb +31 -0
- data/examples/text/simple_text.rb +17 -0
- data/examples/text/simple_text_ttf.rb +17 -0
- data/examples/text/text_box.rb +88 -0
- data/examples/text/text_box_returning_excess.rb +51 -0
- data/examples/text/text_flow.rb +67 -0
- data/lib/prawn.rb +27 -0
- data/lib/prawn/canvas.rb +119 -0
- data/lib/prawn/chunkable.rb +37 -0
- data/lib/prawn/compatibility.rb +51 -0
- data/lib/prawn/core.rb +85 -0
- data/lib/prawn/core/annotations.rb +61 -0
- data/lib/prawn/core/byte_string.rb +9 -0
- data/lib/prawn/core/chunk.rb +36 -0
- data/lib/prawn/core/destinations.rb +90 -0
- data/lib/prawn/core/document_state.rb +78 -0
- data/lib/prawn/core/literal_string.rb +16 -0
- data/lib/prawn/core/name_tree.rb +165 -0
- data/lib/prawn/core/object_store.rb +236 -0
- data/lib/prawn/core/page.rb +179 -0
- data/lib/prawn/core/pdf_object.rb +108 -0
- data/lib/prawn/core/reference.rb +112 -0
- data/lib/prawn/core/text.rb +140 -0
- data/lib/prawn/core/text/formatted/arranger.rb +266 -0
- data/lib/prawn/core/text/formatted/line_wrap.rb +127 -0
- data/lib/prawn/core/text/formatted/wrap.rb +112 -0
- data/lib/prawn/core/text/line_wrap.rb +209 -0
- data/lib/prawn/core/text/wrap.rb +80 -0
- data/lib/prawn/document.rb +573 -0
- data/lib/prawn/document/bounding_box.rb +425 -0
- data/lib/prawn/document/graphics_state.rb +48 -0
- data/lib/prawn/document/internals.rb +170 -0
- data/lib/prawn/document/page_geometry.rb +136 -0
- data/lib/prawn/document/snapshot.rb +87 -0
- data/lib/prawn/document_builder.rb +51 -0
- data/lib/prawn/document_builder/command.rb +38 -0
- data/lib/prawn/document_builder/constructs.rb +2 -0
- data/lib/prawn/document_builder/constructs/flowing_text_construct.rb +18 -0
- data/lib/prawn/document_builder/constructs/path_construct.rb +9 -0
- data/lib/prawn/document_builder/layout.rb +25 -0
- data/lib/prawn/document_builder/modifications.rb +2 -0
- data/lib/prawn/document_builder/modifications/layout_modification.rb +9 -0
- data/lib/prawn/document_builder/modifications/path_modification.rb +9 -0
- data/lib/prawn/encoding.rb +121 -0
- data/lib/prawn/errors.rb +94 -0
- data/lib/prawn/font.rb +341 -0
- data/lib/prawn/font/afm.rb +225 -0
- data/lib/prawn/font/dfont.rb +42 -0
- data/lib/prawn/font/ttf.rb +350 -0
- data/lib/prawn/graphics.rb +325 -0
- data/lib/prawn/graphics/cap_style.rb +38 -0
- data/lib/prawn/graphics/color.rb +205 -0
- data/lib/prawn/graphics/dash.rb +71 -0
- data/lib/prawn/graphics/join_style.rb +38 -0
- data/lib/prawn/graphics/transformation.rb +156 -0
- data/lib/prawn/graphics/transparency.rb +99 -0
- data/lib/prawn/images.rb +348 -0
- data/lib/prawn/images/jpg.rb +46 -0
- data/lib/prawn/images/png.rb +226 -0
- data/lib/prawn/measurement_extensions.rb +46 -0
- data/lib/prawn/measurements.rb +71 -0
- data/lib/prawn/outline.rb +278 -0
- data/lib/prawn/repeater.rb +129 -0
- data/lib/prawn/security.rb +262 -0
- data/lib/prawn/security/arcfour.rb +51 -0
- data/lib/prawn/stamp.rb +126 -0
- data/lib/prawn/table.rb +421 -0
- data/lib/prawn/table/accessors.rb +180 -0
- data/lib/prawn/table/cell.rb +350 -0
- data/lib/prawn/table/cell/in_table.rb +27 -0
- data/lib/prawn/table/cell/subtable.rb +65 -0
- data/lib/prawn/table/cell/text.rb +125 -0
- data/lib/prawn/text.rb +449 -0
- data/lib/prawn/text/box.rb +392 -0
- data/lib/prawn/text/formatted.rb +4 -0
- data/lib/prawn/text/formatted/box.rb +228 -0
- data/lib/prawn/text/formatted/fragment.rb +181 -0
- data/lib/prawn/text/formatted/parser.rb +213 -0
- data/spec/annotations_spec.rb +90 -0
- data/spec/bounding_box_spec.rb +190 -0
- data/spec/cell_spec.rb +348 -0
- data/spec/destinations_spec.rb +15 -0
- data/spec/document_spec.rb +473 -0
- data/spec/font_spec.rb +324 -0
- data/spec/formatted_text_arranger_spec.rb +426 -0
- data/spec/formatted_text_box_spec.rb +756 -0
- data/spec/formatted_text_fragment_spec.rb +211 -0
- data/spec/graphics_spec.rb +446 -0
- data/spec/images_spec.rb +96 -0
- data/spec/inline_formatted_text_parser_spec.rb +502 -0
- data/spec/jpg_spec.rb +25 -0
- data/spec/line_wrap_spec.rb +341 -0
- data/spec/measurement_units_spec.rb +23 -0
- data/spec/name_tree_spec.rb +112 -0
- data/spec/object_store_spec.rb +160 -0
- data/spec/outline_spec.rb +269 -0
- data/spec/pdf_object_spec.rb +170 -0
- data/spec/png_spec.rb +237 -0
- data/spec/reference_spec.rb +82 -0
- data/spec/repeater_spec.rb +96 -0
- data/spec/security_spec.rb +120 -0
- data/spec/snapshot_spec.rb +138 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/stamp_spec.rb +108 -0
- data/spec/stroke_styles_spec.rb +163 -0
- data/spec/table_spec.rb +598 -0
- data/spec/template_spec.rb +158 -0
- data/spec/text_at_spec.rb +119 -0
- data/spec/text_box_spec.rb +742 -0
- data/spec/text_spacing_spec.rb +75 -0
- data/spec/text_spec.rb +333 -0
- data/spec/text_with_inline_formatting_spec.rb +193 -0
- data/spec/transparency_spec.rb +89 -0
- 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
|