prawn 2.3.0 → 2.5.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 (203) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/prawn/document/bounding_box.rb +223 -143
  4. data/lib/prawn/document/column_box.rb +61 -26
  5. data/lib/prawn/document/internals.rb +25 -16
  6. data/lib/prawn/document/span.rb +21 -18
  7. data/lib/prawn/document.rb +273 -182
  8. data/lib/prawn/encoding.rb +2 -5
  9. data/lib/prawn/errors.rb +23 -34
  10. data/lib/prawn/font.rb +254 -139
  11. data/lib/prawn/font_metric_cache.rb +18 -16
  12. data/lib/prawn/fonts/afm.rb +99 -57
  13. data/lib/prawn/fonts/dfont.rb +7 -1
  14. data/lib/prawn/fonts/otf.rb +4 -1
  15. data/lib/prawn/fonts/to_unicode_cmap.rb +151 -0
  16. data/lib/prawn/fonts/ttc.rb +7 -2
  17. data/lib/prawn/fonts/ttf.rb +345 -107
  18. data/lib/prawn/fonts.rb +14 -0
  19. data/lib/prawn/graphics/blend_mode.rb +25 -28
  20. data/lib/prawn/graphics/cap_style.rb +9 -12
  21. data/lib/prawn/graphics/color.rb +75 -50
  22. data/lib/prawn/graphics/dash.rb +45 -42
  23. data/lib/prawn/graphics/join_style.rb +18 -12
  24. data/lib/prawn/graphics/patterns.rb +239 -110
  25. data/lib/prawn/graphics/transformation.rb +51 -44
  26. data/lib/prawn/graphics/transparency.rb +16 -40
  27. data/lib/prawn/graphics.rb +370 -260
  28. data/lib/prawn/grid.rb +219 -57
  29. data/lib/prawn/image_handler.rb +27 -10
  30. data/lib/prawn/images/image.rb +8 -10
  31. data/lib/prawn/images/jpg.rb +46 -20
  32. data/lib/prawn/images/png.rb +94 -42
  33. data/lib/prawn/images.rb +70 -81
  34. data/lib/prawn/measurement_extensions.rb +39 -8
  35. data/lib/prawn/measurements.rb +60 -5
  36. data/lib/prawn/outline.rb +120 -113
  37. data/lib/prawn/repeater.rb +52 -36
  38. data/lib/prawn/security/arcfour.rb +4 -4
  39. data/lib/prawn/security.rb +106 -98
  40. data/lib/prawn/soft_mask.rb +42 -30
  41. data/lib/prawn/stamp.rb +38 -42
  42. data/lib/prawn/text/box.rb +156 -105
  43. data/lib/prawn/text/formatted/arranger.rb +121 -41
  44. data/lib/prawn/text/formatted/box.rb +239 -163
  45. data/lib/prawn/text/formatted/fragment.rb +130 -14
  46. data/lib/prawn/text/formatted/line_wrap.rb +49 -38
  47. data/lib/prawn/text/formatted/parser.rb +116 -74
  48. data/lib/prawn/text/formatted/wrap.rb +25 -26
  49. data/lib/prawn/text/formatted.rb +75 -0
  50. data/lib/prawn/text.rb +456 -211
  51. data/lib/prawn/transformation_stack.rb +29 -10
  52. data/lib/prawn/utilities.rb +13 -13
  53. data/lib/prawn/version.rb +2 -1
  54. data/lib/prawn/view.rb +69 -54
  55. data/lib/prawn.rb +24 -18
  56. data.tar.gz.sig +0 -0
  57. metadata +55 -262
  58. metadata.gz.sig +3 -4
  59. data/.yardopts +0 -10
  60. data/Gemfile +0 -5
  61. data/Rakefile +0 -54
  62. data/manual/absolute_position.pdf +0 -0
  63. data/manual/basic_concepts/adding_pages.rb +0 -26
  64. data/manual/basic_concepts/basic_concepts.rb +0 -43
  65. data/manual/basic_concepts/creation.rb +0 -38
  66. data/manual/basic_concepts/cursor.rb +0 -32
  67. data/manual/basic_concepts/measurement.rb +0 -24
  68. data/manual/basic_concepts/origin.rb +0 -37
  69. data/manual/basic_concepts/other_cursor_helpers.rb +0 -39
  70. data/manual/basic_concepts/view.rb +0 -48
  71. data/manual/bounding_box/bounding_box.rb +0 -41
  72. data/manual/bounding_box/bounds.rb +0 -48
  73. data/manual/bounding_box/canvas.rb +0 -23
  74. data/manual/bounding_box/creation.rb +0 -22
  75. data/manual/bounding_box/indentation.rb +0 -45
  76. data/manual/bounding_box/nesting.rb +0 -52
  77. data/manual/bounding_box/russian_boxes.rb +0 -40
  78. data/manual/bounding_box/stretchy.rb +0 -29
  79. data/manual/contents.rb +0 -35
  80. data/manual/cover.rb +0 -43
  81. data/manual/document_and_page_options/background.rb +0 -25
  82. data/manual/document_and_page_options/document_and_page_options.rb +0 -34
  83. data/manual/document_and_page_options/metadata.rb +0 -25
  84. data/manual/document_and_page_options/page_margins.rb +0 -36
  85. data/manual/document_and_page_options/page_size.rb +0 -34
  86. data/manual/document_and_page_options/print_scaling.rb +0 -22
  87. data/manual/example_helper.rb +0 -8
  88. data/manual/graphics/blend_mode.rb +0 -52
  89. data/manual/graphics/circle_and_ellipse.rb +0 -21
  90. data/manual/graphics/color.rb +0 -22
  91. data/manual/graphics/common_lines.rb +0 -29
  92. data/manual/graphics/fill_and_stroke.rb +0 -41
  93. data/manual/graphics/fill_rules.rb +0 -37
  94. data/manual/graphics/gradients.rb +0 -43
  95. data/manual/graphics/graphics.rb +0 -64
  96. data/manual/graphics/helper.rb +0 -27
  97. data/manual/graphics/line_width.rb +0 -36
  98. data/manual/graphics/lines_and_curves.rb +0 -40
  99. data/manual/graphics/polygon.rb +0 -27
  100. data/manual/graphics/rectangle.rb +0 -20
  101. data/manual/graphics/rotate.rb +0 -25
  102. data/manual/graphics/scale.rb +0 -42
  103. data/manual/graphics/soft_masks.rb +0 -44
  104. data/manual/graphics/stroke_cap.rb +0 -30
  105. data/manual/graphics/stroke_dash.rb +0 -47
  106. data/manual/graphics/stroke_join.rb +0 -29
  107. data/manual/graphics/translate.rb +0 -28
  108. data/manual/graphics/transparency.rb +0 -33
  109. data/manual/how_to_read_this_manual.rb +0 -39
  110. data/manual/images/absolute_position.rb +0 -22
  111. data/manual/images/fit.rb +0 -20
  112. data/manual/images/horizontal.rb +0 -24
  113. data/manual/images/images.rb +0 -41
  114. data/manual/images/plain_image.rb +0 -17
  115. data/manual/images/scale.rb +0 -21
  116. data/manual/images/vertical.rb +0 -27
  117. data/manual/images/width_and_height.rb +0 -24
  118. data/manual/layout/boxes.rb +0 -26
  119. data/manual/layout/content.rb +0 -24
  120. data/manual/layout/layout.rb +0 -27
  121. data/manual/layout/simple_grid.rb +0 -22
  122. data/manual/outline/add_subsection_to.rb +0 -60
  123. data/manual/outline/insert_section_after.rb +0 -46
  124. data/manual/outline/outline.rb +0 -33
  125. data/manual/outline/sections_and_pages.rb +0 -66
  126. data/manual/repeatable_content/alternate_page_numbering.rb +0 -36
  127. data/manual/repeatable_content/page_numbering.rb +0 -55
  128. data/manual/repeatable_content/repeatable_content.rb +0 -35
  129. data/manual/repeatable_content/repeater.rb +0 -54
  130. data/manual/repeatable_content/stamp.rb +0 -40
  131. data/manual/security/encryption.rb +0 -28
  132. data/manual/security/permissions.rb +0 -41
  133. data/manual/security/security.rb +0 -28
  134. data/manual/table.rb +0 -16
  135. data/manual/text/alignment.rb +0 -43
  136. data/manual/text/color.rb +0 -24
  137. data/manual/text/column_box.rb +0 -30
  138. data/manual/text/fallback_fonts.rb +0 -41
  139. data/manual/text/font.rb +0 -40
  140. data/manual/text/font_size.rb +0 -44
  141. data/manual/text/font_style.rb +0 -22
  142. data/manual/text/formatted_callbacks.rb +0 -65
  143. data/manual/text/formatted_text.rb +0 -58
  144. data/manual/text/free_flowing_text.rb +0 -50
  145. data/manual/text/inline.rb +0 -40
  146. data/manual/text/kerning_and_character_spacing.rb +0 -38
  147. data/manual/text/leading.rb +0 -24
  148. data/manual/text/line_wrapping.rb +0 -60
  149. data/manual/text/paragraph_indentation.rb +0 -32
  150. data/manual/text/positioned_text.rb +0 -37
  151. data/manual/text/registering_families.rb +0 -51
  152. data/manual/text/rendering_and_color.rb +0 -36
  153. data/manual/text/right_to_left_text.rb +0 -54
  154. data/manual/text/rotation.rb +0 -47
  155. data/manual/text/single_usage.rb +0 -36
  156. data/manual/text/text.rb +0 -75
  157. data/manual/text/text_box_excess.rb +0 -35
  158. data/manual/text/text_box_extensions.rb +0 -48
  159. data/manual/text/text_box_overflow.rb +0 -49
  160. data/manual/text/utf8.rb +0 -27
  161. data/manual/text/win_ansi_charset.rb +0 -62
  162. data/prawn.gemspec +0 -57
  163. data/spec/data/curves.pdf +0 -66
  164. data/spec/extensions/encoding_helpers.rb +0 -11
  165. data/spec/prawn/document/bounding_box_spec.rb +0 -546
  166. data/spec/prawn/document/column_box_spec.rb +0 -75
  167. data/spec/prawn/document/security_spec.rb +0 -176
  168. data/spec/prawn/document_annotations_spec.rb +0 -76
  169. data/spec/prawn/document_destinations_spec.rb +0 -15
  170. data/spec/prawn/document_grid_spec.rb +0 -99
  171. data/spec/prawn/document_reference_spec.rb +0 -27
  172. data/spec/prawn/document_span_spec.rb +0 -36
  173. data/spec/prawn/document_spec.rb +0 -802
  174. data/spec/prawn/font_metric_cache_spec.rb +0 -54
  175. data/spec/prawn/font_spec.rb +0 -542
  176. data/spec/prawn/graphics/blend_mode_spec.rb +0 -63
  177. data/spec/prawn/graphics/transparency_spec.rb +0 -81
  178. data/spec/prawn/graphics_spec.rb +0 -837
  179. data/spec/prawn/graphics_stroke_styles_spec.rb +0 -229
  180. data/spec/prawn/image_handler_spec.rb +0 -53
  181. data/spec/prawn/images/jpg_spec.rb +0 -20
  182. data/spec/prawn/images/png_spec.rb +0 -283
  183. data/spec/prawn/images_spec.rb +0 -224
  184. data/spec/prawn/measurements_extensions_spec.rb +0 -24
  185. data/spec/prawn/outline_spec.rb +0 -412
  186. data/spec/prawn/repeater_spec.rb +0 -165
  187. data/spec/prawn/soft_mask_spec.rb +0 -74
  188. data/spec/prawn/stamp_spec.rb +0 -172
  189. data/spec/prawn/text/box_spec.rb +0 -1112
  190. data/spec/prawn/text/formatted/arranger_spec.rb +0 -466
  191. data/spec/prawn/text/formatted/box_spec.rb +0 -846
  192. data/spec/prawn/text/formatted/fragment_spec.rb +0 -343
  193. data/spec/prawn/text/formatted/line_wrap_spec.rb +0 -494
  194. data/spec/prawn/text/formatted/parser_spec.rb +0 -697
  195. data/spec/prawn/text_draw_text_spec.rb +0 -149
  196. data/spec/prawn/text_rendering_mode_spec.rb +0 -48
  197. data/spec/prawn/text_spacing_spec.rb +0 -95
  198. data/spec/prawn/text_spec.rb +0 -603
  199. data/spec/prawn/text_with_inline_formatting_spec.rb +0 -35
  200. data/spec/prawn/transformation_stack_spec.rb +0 -66
  201. data/spec/prawn/view_spec.rb +0 -63
  202. data/spec/prawn_manual_spec.rb +0 -35
  203. data/spec/spec_helper.rb +0 -48
@@ -1,165 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe Prawn::Repeater do
6
- it 'creates a stamp and increments Prawn::Repeater.count on initialize' do
7
- orig_count = described_class.count
8
-
9
- doc = sample_document
10
- allow(doc).to receive(:create_stamp).with("prawn_repeater(#{orig_count})")
11
-
12
- repeater(doc, :all) { :do_nothing }
13
-
14
- expect(doc).to have_received(:create_stamp)
15
- .with("prawn_repeater(#{orig_count})")
16
-
17
- expect(described_class.count).to eq(orig_count + 1)
18
- end
19
-
20
- it 'must provide an :all filter' do
21
- doc = sample_document
22
- r = repeater(doc, :all) { :do_nothing }
23
-
24
- expect((1..doc.page_count).all? { |i| r.match?(i) }).to eq true
25
- end
26
-
27
- it 'must provide an :odd filter' do
28
- doc = sample_document
29
- r = repeater(doc, :odd) { :do_nothing }
30
-
31
- odd, even = (1..doc.page_count).partition(&:odd?)
32
-
33
- expect(odd.all? { |i| r.match?(i) }).to eq true
34
- expect(even.any? { |i| r.match?(i) }).to eq false
35
- end
36
-
37
- it 'must be able to filter by an array of page numbers' do
38
- doc = sample_document
39
- r = repeater(doc, [1, 2, 7]) { :do_nothing }
40
-
41
- expect((1..10).select { |i| r.match?(i) }).to eq([1, 2, 7])
42
- end
43
-
44
- it 'must be able to filter by a range of page numbers' do
45
- doc = sample_document
46
- r = repeater(doc, 2..4) { :do_nothing }
47
-
48
- expect((1..10).select { |i| r.match?(i) }).to eq([2, 3, 4])
49
- end
50
-
51
- it 'must be able to filter by an arbitrary proc' do
52
- doc = sample_document
53
- r = repeater(doc, ->(x) { x == 1 || x % 3 == 0 })
54
-
55
- expect((1..10).select { |i| r.match?(i) }).to eq([1, 3, 6, 9])
56
- end
57
-
58
- it 'must try to run a stamp if the page number matches' do
59
- doc = sample_document
60
- allow(doc).to receive(:stamp)
61
-
62
- repeater(doc, :odd).run(3)
63
- expect(doc).to have_received(:stamp)
64
- end
65
-
66
- it 'must not try to run a stamp unless the page number matches' do
67
- doc = sample_document
68
-
69
- allow(doc).to receive(:stamp)
70
- repeater(doc, :odd).run(2)
71
- expect(doc).to_not have_received(:stamp)
72
- end
73
-
74
- it 'must not try to run a stamp if dynamic is selected' do
75
- doc = sample_document
76
-
77
- allow(doc).to receive(:stamp)
78
- (1..10).each { |p| repeater(doc, :all, true) { :do_nothing }.run(p) }
79
- expect(doc).to_not have_received(:stamp)
80
- end
81
-
82
- it 'must try to run a block if the page number matches' do
83
- doc = sample_document
84
-
85
- allow(doc).to receive(:draw_text)
86
- (1..10).each do |p|
87
- repeater(doc, [1, 2], true) { doc.draw_text 'foo' }.run(p)
88
- end
89
- expect(doc).to have_received(:draw_text).twice
90
- end
91
-
92
- it 'must not try to run a block unless the page number matches' do
93
- doc = sample_document
94
-
95
- allow(doc).to receive(:draw_text)
96
- repeater(doc, :odd, true) { doc.draw_text 'foo' }.run(2)
97
- expect(doc).to_not have_received(:draw_text)
98
- end
99
-
100
- it 'must treat any block as a closure' do
101
- doc = sample_document
102
-
103
- page = 'Page' # ensure access to ivars
104
- doc.repeat(:all, dynamic: true) do
105
- doc.draw_text "#{page} #{doc.page_number}", at: [500, 0]
106
- end
107
-
108
- text = PDF::Inspector::Text.analyze(doc.render)
109
- expect(text.strings).to eq((1..10).to_a.map { |p| "Page #{p}" })
110
- end
111
-
112
- it 'must treat any block as a closure (Document.new instance_eval form)' do
113
- doc = Prawn::Document.new(skip_page_creation: true) do
114
- 10.times { start_new_page }
115
-
116
- page = 'Page'
117
- repeat(:all, dynamic: true) do
118
- # ensure self is accessible here
119
- draw_text "#{page} #{page_number}", at: [500, 0]
120
- end
121
- end
122
-
123
- text = PDF::Inspector::Text.analyze(doc.render)
124
- expect(text.strings).to eq((1..10).to_a.map { |p| "Page #{p}" })
125
- end
126
-
127
- def sample_document
128
- doc = Prawn::Document.new(skip_page_creation: true)
129
- 10.times { |_e| doc.start_new_page }
130
- doc
131
- end
132
-
133
- def repeater(*args, &block)
134
- Prawn::Repeater.new(*args, &block)
135
- end
136
-
137
- describe 'graphic state' do
138
- let(:pdf) { create_pdf }
139
-
140
- it 'does not alter the graphic state stack color space' do
141
- starting_color_space = pdf.state.page.graphic_state.color_space.dup
142
- pdf.repeat :all do
143
- pdf.text 'Testing', size: 24, style: :bold
144
- end
145
- expect(pdf.state.page.graphic_state.color_space)
146
- .to eq(starting_color_space)
147
- end
148
-
149
- context 'with dynamic repeaters' do
150
- it 'preserves the graphic state at creation time' do
151
- pdf.repeat :all, dynamic: true do
152
- pdf.text "fill_color: #{pdf.graphic_state.fill_color}"
153
- pdf.text "cap_style: #{pdf.graphic_state.cap_style}"
154
- end
155
- pdf.fill_color '666666'
156
- pdf.cap_style :round
157
- text = PDF::Inspector::Text.analyze(pdf.render)
158
- expect(text.strings.include?('fill_color: 666666')).to eq(false)
159
- expect(text.strings.include?('fill_color: 000000')).to eq(true)
160
- expect(text.strings.include?('cap_style: round')).to eq(false)
161
- expect(text.strings.include?('cap_style: butt')).to eq(true)
162
- end
163
- end
164
- end
165
- end
@@ -1,74 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe Prawn::SoftMask do
6
- let(:pdf) { create_pdf }
7
-
8
- def make_soft_mask
9
- pdf.save_graphics_state do
10
- pdf.soft_mask do
11
- if block_given?
12
- yield
13
- else
14
- pdf.fill_color '808080'
15
- pdf.fill_rectangle [100, 100], 200, 200
16
- end
17
- end
18
-
19
- pdf.fill_color '000000'
20
- pdf.fill_rectangle [0, 0], 200, 200
21
- end
22
- end
23
-
24
- it 'has PDF version at least 1.4' do
25
- make_soft_mask
26
- str = pdf.render
27
- expect(str[0, 8]).to eq('%PDF-1.4')
28
- end
29
-
30
- it 'creates a new extended graphics state for each unique soft mask' do
31
- make_soft_mask do
32
- pdf.fill_color '808080'
33
- pdf.fill_rectangle [100, 100], 200, 200
34
- end
35
-
36
- make_soft_mask do
37
- pdf.fill_color '808080'
38
- pdf.fill_rectangle [10, 10], 200, 200
39
- end
40
-
41
- extgstates = PDF::Inspector::ExtGState.analyze(pdf.render).extgstates
42
- expect(extgstates.length).to eq(2)
43
- end
44
-
45
- it 'a new extended graphics state contains soft mask with drawing '\
46
- 'instructions' do
47
- make_soft_mask do
48
- pdf.fill_color '808080'
49
- pdf.fill_rectangle [100, 100], 200, 200
50
- end
51
-
52
- extgstate = PDF::Inspector::ExtGState.analyze(pdf.render).extgstates.first
53
- expect(extgstate[:soft_mask][:G].data).to eq(
54
- "q\n/DeviceRGB cs\n0.0 0.0 0.0 scn\n/DeviceRGB CS\n0.0 0.0 0.0 SCN\n"\
55
- "1 w\n0 J\n0 j\n[] 0 d\n/DeviceRGB cs\n0.502 0.502 0.502 scn\n"\
56
- "100.0 -100.0 200.0 200.0 re\nf\nQ\n"
57
- )
58
- end
59
-
60
- it 'does not create duplicate extended graphics states' do
61
- make_soft_mask do
62
- pdf.fill_color '808080'
63
- pdf.fill_rectangle [100, 100], 200, 200
64
- end
65
-
66
- make_soft_mask do
67
- pdf.fill_color '808080'
68
- pdf.fill_rectangle [100, 100], 200, 200
69
- end
70
-
71
- extgstates = PDF::Inspector::ExtGState.analyze(pdf.render).extgstates
72
- expect(extgstates.length).to eq(1)
73
- end
74
- end
@@ -1,172 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe Prawn::Stamp do
6
- describe 'create_stamp before any page is added' do
7
- let(:pdf) { Prawn::Document.new(skip_page_creation: true) }
8
-
9
- it 'works with the font class' do
10
- # If anything goes wrong, Prawn::Errors::NotOnPage will be raised
11
- pdf.create_stamp('my_stamp') do
12
- pdf.font.height
13
- end
14
- end
15
-
16
- it 'works with setting color' do
17
- # If anything goes wrong, Prawn::Errors::NotOnPage will be raised
18
- pdf.create_stamp('my_stamp') do
19
- pdf.fill_color = 'ff0000'
20
- end
21
- end
22
- end
23
-
24
- describe '#stamp_at' do
25
- let(:pdf) { create_pdf }
26
-
27
- it 'works' do
28
- pdf.create_stamp('MyStamp')
29
- pdf.stamp_at('MyStamp', [100, 200])
30
- # I had modified PDF::Inspector::XObject to receive the
31
- # invoke_xobject message and count the number of times it was
32
- # called, but it was only called once, so I reverted checking the
33
- # output with a regular expression
34
- expect(pdf.render).to match(%r{/Stamp1 Do.*?}m)
35
- end
36
- end
37
-
38
- describe 'Document with a stamp' do
39
- let(:pdf) { create_pdf }
40
-
41
- it 'raises NameTaken error when attempt to create stamp with '\
42
- 'same name as an existing stamp' do
43
- pdf.create_stamp('MyStamp')
44
- expect do
45
- pdf.create_stamp('MyStamp')
46
- end.to raise_error(Prawn::Errors::NameTaken)
47
- end
48
-
49
- it 'raises InvalidName error when attempt to create stamp with '\
50
- 'a blank name' do
51
- expect do
52
- pdf.create_stamp('')
53
- end.to raise_error(Prawn::Errors::InvalidName)
54
- end
55
-
56
- it 'a new XObject should be defined for each stamp created' do
57
- pdf.create_stamp('MyStamp')
58
- pdf.create_stamp('AnotherStamp')
59
- pdf.stamp('MyStamp')
60
- pdf.stamp('AnotherStamp')
61
-
62
- inspector = PDF::Inspector::XObject.analyze(pdf.render)
63
- xobjects = inspector.page_xobjects.last
64
- expect(xobjects.length).to eq(2)
65
- end
66
-
67
- it 'calling stamp with a name that does not match an existing stamp ' \
68
- 'should raise_error UndefinedObjectName' do
69
- pdf.create_stamp('MyStamp')
70
- expect do
71
- pdf.stamp('OtherStamp')
72
- end.to raise_error(Prawn::Errors::UndefinedObjectName)
73
- end
74
-
75
- it 'stamp should be drawn into the document each time stamp is called' do
76
- pdf.create_stamp('MyStamp')
77
- pdf.stamp('MyStamp')
78
- pdf.stamp('MyStamp')
79
- pdf.stamp('MyStamp')
80
- # I had modified PDF::Inspector::XObject to receive the
81
- # invoke_xobject message and count the number of times it was
82
- # called, but it was only called once, so I reverted checking the
83
- # output with a regular expression
84
- expect(pdf.render).to match(%r{(/Stamp1 Do.*?){3}}m)
85
- end
86
-
87
- it 'stamp should render clickable links' do
88
- pdf.create_stamp 'bar' do
89
- pdf.text '<b>Prawn</b> <link href="http://github.com">GitHub</link>',
90
- inline_format: true
91
- end
92
- pdf.stamp 'bar'
93
-
94
- output = pdf.render
95
- objects = output.split('endobj')
96
-
97
- objects.each do |obj|
98
- next unless %r{/Type /Page$}.match?(obj)
99
-
100
- # The page object must contain the annotation reference
101
- # to render a clickable link
102
- expect(obj).to match(%r{^/Annots \[\d \d .\]$})
103
- end
104
- end
105
-
106
- it 'resources added during stamp creation should be added to the ' \
107
- 'stamp XObject, not the page' do
108
- pdf.create_stamp('MyStamp') do
109
- pdf.transparent(0.5) { pdf.circle([100, 100], 10) }
110
- end
111
- pdf.stamp('MyStamp')
112
-
113
- # Inspector::XObject does not give information about resources, so
114
- # resorting to string matching
115
-
116
- output = pdf.render
117
- objects = output.split('endobj')
118
- objects.each do |object|
119
- if %r{/Type /Page$}.match?(object)
120
- expect(object).to_not match(%r{/ExtGState})
121
- elsif %r{/Type /XObject$}.match?(object)
122
- expect(object).to match(%r{/ExtGState})
123
- end
124
- end
125
- end
126
-
127
- it 'stamp stream should be wrapped in a graphic state' do
128
- pdf.create_stamp('MyStamp') do
129
- pdf.text "This should have a 'q' before it and a 'Q' after it"
130
- end
131
- pdf.stamp('MyStamp')
132
- stamps = PDF::Inspector::XObject.analyze(pdf.render)
133
- expect(stamps.xobject_streams[:Stamp1].data.chomp).to match(/q(.|\s)*Q\Z/)
134
- end
135
-
136
- it 'does not add to the page graphic state stack' do
137
- expect(pdf.state.page.stack.stack.size).to eq(1)
138
-
139
- pdf.create_stamp('MyStamp') do
140
- pdf.save_graphics_state
141
- pdf.save_graphics_state
142
- pdf.save_graphics_state
143
- pdf.text "This should have a 'q' before it and a 'Q' after it"
144
- pdf.restore_graphics_state
145
- end
146
- expect(pdf.state.page.stack.stack.size).to eq(1)
147
- end
148
-
149
- it 'is able to change fill and stroke colors within the stamp stream' do
150
- pdf.create_stamp('MyStamp') do
151
- pdf.fill_color(100, 100, 20, 0)
152
- pdf.stroke_color(100, 100, 20, 0)
153
- end
154
- pdf.stamp('MyStamp')
155
- stamps = PDF::Inspector::XObject.analyze(pdf.render)
156
- stamp_stream = stamps.xobject_streams[:Stamp1].data
157
- expect(stamp_stream).to include("/DeviceCMYK cs\n1.0 1.0 0.2 0.0 scn")
158
- expect(stamp_stream).to include("/DeviceCMYK CS\n1.0 1.0 0.2 0.0 SCN")
159
- end
160
-
161
- it 'saves the color space even when same as current page color space' do
162
- pdf.stroke_color(100, 100, 20, 0)
163
- pdf.create_stamp('MyStamp') do
164
- pdf.stroke_color(100, 100, 20, 0)
165
- end
166
- pdf.stamp('MyStamp')
167
- stamps = PDF::Inspector::XObject.analyze(pdf.render)
168
- stamp_stream = stamps.xobject_streams[:Stamp1].data
169
- expect(stamp_stream).to include("/DeviceCMYK CS\n1.0 1.0 0.2 0.0 SCN")
170
- end
171
- end
172
- end