prawn 2.0.2 → 2.3.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 (277) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/GPLv2 +20 -21
  5. data/Gemfile +3 -9
  6. data/Rakefile +20 -23
  7. data/lib/prawn.rb +37 -49
  8. data/lib/prawn/document.rb +181 -133
  9. data/lib/prawn/document/bounding_box.rb +41 -29
  10. data/lib/prawn/document/column_box.rb +7 -7
  11. data/lib/prawn/document/internals.rb +18 -8
  12. data/lib/prawn/document/span.rb +21 -16
  13. data/lib/prawn/encoding.rb +69 -68
  14. data/lib/prawn/errors.rb +12 -7
  15. data/lib/prawn/font.rb +115 -69
  16. data/lib/prawn/font_metric_cache.rb +14 -8
  17. data/lib/prawn/{font → fonts}/afm.rb +102 -68
  18. data/lib/prawn/{font → fonts}/dfont.rb +5 -11
  19. data/lib/prawn/fonts/otf.rb +11 -0
  20. data/lib/prawn/fonts/ttc.rb +36 -0
  21. data/lib/prawn/{font → fonts}/ttf.rb +87 -68
  22. data/lib/prawn/graphics.rb +120 -80
  23. data/lib/prawn/graphics/blend_mode.rb +65 -0
  24. data/lib/prawn/graphics/cap_style.rb +3 -3
  25. data/lib/prawn/graphics/color.rb +27 -25
  26. data/lib/prawn/graphics/dash.rb +23 -11
  27. data/lib/prawn/graphics/join_style.rb +9 -3
  28. data/lib/prawn/graphics/patterns.rb +197 -67
  29. data/lib/prawn/graphics/transformation.rb +17 -8
  30. data/lib/prawn/graphics/transparency.rb +17 -13
  31. data/lib/prawn/grid.rb +48 -47
  32. data/lib/prawn/image_handler.rb +5 -5
  33. data/lib/prawn/images.rb +39 -30
  34. data/lib/prawn/images/image.rb +2 -1
  35. data/lib/prawn/images/jpg.rb +28 -22
  36. data/lib/prawn/images/png.rb +107 -66
  37. data/lib/prawn/measurement_extensions.rb +10 -9
  38. data/lib/prawn/measurements.rb +19 -15
  39. data/lib/prawn/outline.rb +97 -77
  40. data/lib/prawn/repeater.rb +14 -10
  41. data/lib/prawn/security.rb +81 -61
  42. data/lib/prawn/security/arcfour.rb +2 -2
  43. data/lib/prawn/soft_mask.rb +26 -26
  44. data/lib/prawn/stamp.rb +20 -13
  45. data/lib/prawn/text.rb +68 -52
  46. data/lib/prawn/text/box.rb +11 -8
  47. data/lib/prawn/text/formatted.rb +5 -5
  48. data/lib/prawn/text/formatted/arranger.rb +78 -49
  49. data/lib/prawn/text/formatted/box.rb +134 -100
  50. data/lib/prawn/text/formatted/fragment.rb +11 -14
  51. data/lib/prawn/text/formatted/line_wrap.rb +121 -63
  52. data/lib/prawn/text/formatted/parser.rb +139 -117
  53. data/lib/prawn/text/formatted/wrap.rb +43 -31
  54. data/lib/prawn/transformation_stack.rb +44 -0
  55. data/lib/prawn/utilities.rb +7 -22
  56. data/lib/prawn/version.rb +2 -2
  57. data/lib/prawn/view.rb +17 -7
  58. data/manual/basic_concepts/adding_pages.rb +6 -7
  59. data/manual/basic_concepts/basic_concepts.rb +31 -22
  60. data/manual/basic_concepts/creation.rb +10 -11
  61. data/manual/basic_concepts/cursor.rb +4 -5
  62. data/manual/basic_concepts/measurement.rb +6 -7
  63. data/manual/basic_concepts/origin.rb +5 -6
  64. data/manual/basic_concepts/other_cursor_helpers.rb +11 -12
  65. data/manual/basic_concepts/view.rb +22 -16
  66. data/manual/bounding_box/bounding_box.rb +29 -24
  67. data/manual/bounding_box/bounds.rb +11 -12
  68. data/manual/bounding_box/canvas.rb +4 -5
  69. data/manual/bounding_box/creation.rb +6 -7
  70. data/manual/bounding_box/indentation.rb +14 -15
  71. data/manual/bounding_box/nesting.rb +24 -17
  72. data/manual/bounding_box/russian_boxes.rb +14 -13
  73. data/manual/bounding_box/stretchy.rb +12 -13
  74. data/manual/contents.rb +28 -22
  75. data/manual/cover.rb +33 -28
  76. data/manual/document_and_page_options/background.rb +11 -13
  77. data/manual/document_and_page_options/document_and_page_options.rb +25 -20
  78. data/manual/document_and_page_options/metadata.rb +18 -16
  79. data/manual/document_and_page_options/page_margins.rb +18 -20
  80. data/manual/document_and_page_options/page_size.rb +13 -12
  81. data/manual/document_and_page_options/print_scaling.rb +17 -15
  82. data/manual/example_helper.rb +5 -4
  83. data/manual/graphics/blend_mode.rb +52 -0
  84. data/manual/graphics/circle_and_ellipse.rb +4 -5
  85. data/manual/graphics/color.rb +7 -9
  86. data/manual/graphics/common_lines.rb +7 -8
  87. data/manual/graphics/fill_and_stroke.rb +4 -5
  88. data/manual/graphics/fill_rules.rb +9 -10
  89. data/manual/graphics/gradients.rb +27 -21
  90. data/manual/graphics/graphics.rb +48 -39
  91. data/manual/graphics/helper.rb +12 -9
  92. data/manual/graphics/line_width.rb +8 -7
  93. data/manual/graphics/lines_and_curves.rb +7 -8
  94. data/manual/graphics/polygon.rb +6 -8
  95. data/manual/graphics/rectangle.rb +4 -5
  96. data/manual/graphics/rotate.rb +6 -7
  97. data/manual/graphics/scale.rb +14 -15
  98. data/manual/graphics/soft_masks.rb +4 -5
  99. data/manual/graphics/stroke_cap.rb +6 -7
  100. data/manual/graphics/stroke_dash.rb +11 -12
  101. data/manual/graphics/stroke_join.rb +5 -6
  102. data/manual/graphics/translate.rb +9 -10
  103. data/manual/graphics/transparency.rb +7 -8
  104. data/manual/how_to_read_this_manual.rb +6 -6
  105. data/manual/images/absolute_position.rb +6 -7
  106. data/manual/images/fit.rb +7 -8
  107. data/manual/images/horizontal.rb +9 -10
  108. data/manual/images/images.rb +28 -24
  109. data/manual/images/plain_image.rb +5 -6
  110. data/manual/images/scale.rb +9 -10
  111. data/manual/images/vertical.rb +13 -14
  112. data/manual/images/width_and_height.rb +10 -11
  113. data/manual/layout/boxes.rb +5 -6
  114. data/manual/layout/content.rb +7 -8
  115. data/manual/layout/layout.rb +18 -16
  116. data/manual/layout/simple_grid.rb +6 -7
  117. data/manual/outline/add_subsection_to.rb +20 -21
  118. data/manual/outline/insert_section_after.rb +15 -16
  119. data/manual/outline/outline.rb +21 -17
  120. data/manual/outline/sections_and_pages.rb +17 -18
  121. data/manual/repeatable_content/alternate_page_numbering.rb +21 -17
  122. data/manual/repeatable_content/page_numbering.rb +17 -16
  123. data/manual/repeatable_content/repeatable_content.rb +25 -19
  124. data/manual/repeatable_content/repeater.rb +14 -15
  125. data/manual/repeatable_content/stamp.rb +14 -15
  126. data/manual/security/encryption.rb +9 -10
  127. data/manual/security/permissions.rb +19 -14
  128. data/manual/security/security.rb +19 -16
  129. data/manual/table.rb +3 -3
  130. data/manual/text/alignment.rb +16 -17
  131. data/manual/text/color.rb +12 -11
  132. data/manual/text/column_box.rb +9 -10
  133. data/manual/text/fallback_fonts.rb +25 -21
  134. data/manual/text/font.rb +11 -12
  135. data/manual/text/font_size.rb +13 -14
  136. data/manual/text/font_style.rb +7 -8
  137. data/manual/text/formatted_callbacks.rb +25 -21
  138. data/manual/text/formatted_text.rb +33 -25
  139. data/manual/text/free_flowing_text.rb +20 -21
  140. data/manual/text/inline.rb +18 -19
  141. data/manual/text/kerning_and_character_spacing.rb +14 -15
  142. data/manual/text/leading.rb +7 -8
  143. data/manual/text/line_wrapping.rb +37 -18
  144. data/manual/text/paragraph_indentation.rb +13 -14
  145. data/manual/text/positioned_text.rb +15 -16
  146. data/manual/text/registering_families.rb +20 -21
  147. data/manual/text/rendering_and_color.rb +9 -10
  148. data/manual/text/right_to_left_text.rb +26 -19
  149. data/manual/text/rotation.rb +28 -23
  150. data/manual/text/single_usage.rb +8 -9
  151. data/manual/text/text.rb +57 -52
  152. data/manual/text/text_box_excess.rb +20 -17
  153. data/manual/text/text_box_extensions.rb +18 -15
  154. data/manual/text/text_box_overflow.rb +18 -19
  155. data/manual/text/utf8.rb +11 -12
  156. data/manual/text/win_ansi_charset.rb +21 -19
  157. data/prawn.gemspec +45 -33
  158. data/spec/extensions/encoding_helpers.rb +3 -3
  159. data/spec/prawn/document/bounding_box_spec.rb +546 -0
  160. data/spec/prawn/document/column_box_spec.rb +75 -0
  161. data/spec/prawn/document/security_spec.rb +176 -0
  162. data/spec/prawn/document_annotations_spec.rb +76 -0
  163. data/spec/prawn/document_destinations_spec.rb +15 -0
  164. data/spec/prawn/document_grid_spec.rb +99 -0
  165. data/spec/prawn/document_reference_spec.rb +27 -0
  166. data/spec/prawn/document_span_spec.rb +36 -0
  167. data/spec/prawn/document_spec.rb +802 -0
  168. data/spec/prawn/font_metric_cache_spec.rb +54 -0
  169. data/spec/prawn/font_spec.rb +542 -0
  170. data/spec/prawn/graphics/blend_mode_spec.rb +63 -0
  171. data/spec/prawn/graphics/transparency_spec.rb +81 -0
  172. data/spec/prawn/graphics_spec.rb +837 -0
  173. data/spec/prawn/graphics_stroke_styles_spec.rb +229 -0
  174. data/spec/prawn/image_handler_spec.rb +53 -0
  175. data/spec/prawn/images/jpg_spec.rb +20 -0
  176. data/spec/prawn/images/png_spec.rb +283 -0
  177. data/spec/prawn/images_spec.rb +224 -0
  178. data/spec/prawn/measurements_extensions_spec.rb +24 -0
  179. data/spec/prawn/outline_spec.rb +412 -0
  180. data/spec/prawn/repeater_spec.rb +165 -0
  181. data/spec/prawn/soft_mask_spec.rb +74 -0
  182. data/spec/prawn/stamp_spec.rb +172 -0
  183. data/spec/prawn/text/box_spec.rb +1112 -0
  184. data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
  185. data/spec/prawn/text/formatted/box_spec.rb +846 -0
  186. data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
  187. data/spec/prawn/text/formatted/line_wrap_spec.rb +494 -0
  188. data/spec/prawn/text/formatted/parser_spec.rb +697 -0
  189. data/spec/prawn/text_draw_text_spec.rb +149 -0
  190. data/spec/prawn/text_rendering_mode_spec.rb +48 -0
  191. data/spec/prawn/text_spacing_spec.rb +95 -0
  192. data/spec/prawn/text_spec.rb +603 -0
  193. data/spec/prawn/text_with_inline_formatting_spec.rb +35 -0
  194. data/spec/prawn/transformation_stack_spec.rb +66 -0
  195. data/spec/prawn/view_spec.rb +63 -0
  196. data/spec/prawn_manual_spec.rb +35 -0
  197. data/spec/spec_helper.rb +19 -23
  198. metadata +145 -185
  199. metadata.gz.sig +4 -0
  200. data/data/images/16bit.alpha +0 -0
  201. data/data/images/16bit.color +0 -0
  202. data/data/images/16bit.png +0 -0
  203. data/data/images/arrow.png +0 -0
  204. data/data/images/arrow2.png +0 -0
  205. data/data/images/dice.alpha +0 -0
  206. data/data/images/dice.color +0 -0
  207. data/data/images/dice.png +0 -0
  208. data/data/images/dice_interlaced.png +0 -0
  209. data/data/images/fractal.jpg +0 -0
  210. data/data/images/indexed_color.dat +0 -0
  211. data/data/images/indexed_color.png +0 -0
  212. data/data/images/letterhead.jpg +0 -0
  213. data/data/images/license.md +0 -8
  214. data/data/images/page_white_text.alpha +0 -0
  215. data/data/images/page_white_text.color +0 -0
  216. data/data/images/page_white_text.png +0 -0
  217. data/data/images/pal_bk.png +0 -0
  218. data/data/images/pigs.jpg +0 -0
  219. data/data/images/prawn.png +0 -0
  220. data/data/images/ruport.png +0 -0
  221. data/data/images/ruport_data.dat +0 -0
  222. data/data/images/ruport_transparent.png +0 -0
  223. data/data/images/ruport_type0.png +0 -0
  224. data/data/images/stef.jpg +0 -0
  225. data/data/images/tru256.bmp +0 -0
  226. data/data/images/web-links.dat +0 -1
  227. data/data/images/web-links.png +0 -0
  228. data/data/pdfs/complex_template.pdf +0 -0
  229. data/data/pdfs/contains_ttf_font.pdf +0 -0
  230. data/data/pdfs/encrypted.pdf +0 -0
  231. data/data/pdfs/form.pdf +1 -819
  232. data/data/pdfs/hexagon.pdf +0 -61
  233. data/data/pdfs/indirect_reference.pdf +0 -86
  234. data/data/pdfs/multipage_template.pdf +0 -127
  235. data/data/pdfs/nested_pages.pdf +0 -118
  236. data/data/pdfs/page_without_mediabox.pdf +0 -193
  237. data/data/pdfs/resources_as_indirect_object.pdf +0 -83
  238. data/data/pdfs/two_hexagons.pdf +0 -90
  239. data/data/pdfs/version_1_6.pdf +0 -61
  240. data/data/shift_jis_text.txt +0 -1
  241. data/spec/acceptance/png.rb +0 -24
  242. data/spec/annotations_spec.rb +0 -67
  243. data/spec/bounding_box_spec.rb +0 -501
  244. data/spec/column_box_spec.rb +0 -59
  245. data/spec/destinations_spec.rb +0 -13
  246. data/spec/document_spec.rb +0 -742
  247. data/spec/extensions/mocha.rb +0 -45
  248. data/spec/font_metric_cache_spec.rb +0 -52
  249. data/spec/font_spec.rb +0 -475
  250. data/spec/formatted_text_arranger_spec.rb +0 -423
  251. data/spec/formatted_text_box_spec.rb +0 -716
  252. data/spec/formatted_text_fragment_spec.rb +0 -299
  253. data/spec/graphics_spec.rb +0 -666
  254. data/spec/grid_spec.rb +0 -95
  255. data/spec/image_handler_spec.rb +0 -53
  256. data/spec/images_spec.rb +0 -167
  257. data/spec/inline_formatted_text_parser_spec.rb +0 -568
  258. data/spec/jpg_spec.rb +0 -23
  259. data/spec/line_wrap_spec.rb +0 -366
  260. data/spec/measurement_units_spec.rb +0 -22
  261. data/spec/outline_spec.rb +0 -409
  262. data/spec/png_spec.rb +0 -235
  263. data/spec/reference_spec.rb +0 -25
  264. data/spec/repeater_spec.rb +0 -154
  265. data/spec/security_spec.rb +0 -151
  266. data/spec/soft_mask_spec.rb +0 -78
  267. data/spec/span_spec.rb +0 -43
  268. data/spec/stamp_spec.rb +0 -179
  269. data/spec/stroke_styles_spec.rb +0 -208
  270. data/spec/text_at_spec.rb +0 -142
  271. data/spec/text_box_spec.rb +0 -1038
  272. data/spec/text_rendering_mode_spec.rb +0 -45
  273. data/spec/text_spacing_spec.rb +0 -93
  274. data/spec/text_spec.rb +0 -549
  275. data/spec/text_with_inline_formatting_spec.rb +0 -35
  276. data/spec/transparency_spec.rb +0 -91
  277. data/spec/view_spec.rb +0 -42
@@ -0,0 +1,229 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Prawn::Graphics do
6
+ let(:pdf) { create_pdf }
7
+
8
+ describe 'When stroking with default settings' do
9
+ it 'cap_style should be :butt' do
10
+ expect(pdf.cap_style).to eq(:butt)
11
+ end
12
+
13
+ it 'join_style should be :miter' do
14
+ expect(pdf.join_style).to eq(:miter)
15
+ end
16
+
17
+ it 'dashed? should be_false' do
18
+ expect(pdf).to_not be_dashed
19
+ end
20
+ end
21
+
22
+ describe 'Cap styles' do
23
+ it 'is able to use assignment operator' do
24
+ pdf.cap_style = :round
25
+ expect(pdf.cap_style).to eq(:round)
26
+ end
27
+
28
+ describe '#cap_style(:butt)' do
29
+ it 'rendered PDF should include butt style cap' do
30
+ pdf.cap_style(:butt)
31
+ cap_style = PDF::Inspector::Graphics::CapStyle.analyze(pdf.render)
32
+ .cap_style
33
+ expect(cap_style).to eq(0)
34
+ end
35
+ end
36
+
37
+ describe '#cap_style(:round)' do
38
+ it 'rendered PDF should include round style cap' do
39
+ pdf.cap_style(:round)
40
+ cap_style = PDF::Inspector::Graphics::CapStyle.analyze(pdf.render)
41
+ .cap_style
42
+ expect(cap_style).to eq(1)
43
+ end
44
+ end
45
+
46
+ describe '#cap_style(:projecting_square)' do
47
+ it 'rendered PDF should include projecting_square style cap' do
48
+ pdf.cap_style(:projecting_square)
49
+ cap_style = PDF::Inspector::Graphics::CapStyle.analyze(pdf.render)
50
+ .cap_style
51
+ expect(cap_style).to eq(2)
52
+ end
53
+ end
54
+
55
+ it 'carries the current cap style settings over to new pages' do
56
+ pdf.cap_style(:round)
57
+ pdf.start_new_page
58
+ cap_styles = PDF::Inspector::Graphics::CapStyle.analyze(pdf.render)
59
+ expect(cap_styles.cap_style_count).to eq(2)
60
+ expect(cap_styles.cap_style).to eq(1)
61
+ end
62
+ end
63
+
64
+ describe 'Join styles' do
65
+ it 'is able to use assignment operator' do
66
+ pdf.join_style = :round
67
+ expect(pdf.join_style).to eq(:round)
68
+ end
69
+
70
+ describe '#join_style(:miter)' do
71
+ it 'rendered PDF should include miter style join' do
72
+ pdf.join_style(:miter)
73
+ join_style = PDF::Inspector::Graphics::JoinStyle.analyze(pdf.render)
74
+ .join_style
75
+ expect(join_style).to eq(0)
76
+ end
77
+ end
78
+
79
+ describe '#join_style(:round)' do
80
+ it 'rendered PDF should include round style join' do
81
+ pdf.join_style(:round)
82
+ join_style = PDF::Inspector::Graphics::JoinStyle.analyze(pdf.render)
83
+ .join_style
84
+ expect(join_style).to eq(1)
85
+ end
86
+ end
87
+
88
+ describe '#join_style(:bevel)' do
89
+ it 'rendered PDF should include bevel style join' do
90
+ pdf.join_style(:bevel)
91
+ join_style = PDF::Inspector::Graphics::JoinStyle.analyze(pdf.render)
92
+ .join_style
93
+ expect(join_style).to eq(2)
94
+ end
95
+ end
96
+
97
+ it 'carries the current join style settings over to new pages' do
98
+ pdf.join_style(:round)
99
+ pdf.start_new_page
100
+ join_styles = PDF::Inspector::Graphics::JoinStyle.analyze(pdf.render)
101
+ expect(join_styles.join_style_count).to eq(2)
102
+ expect(join_styles.join_style).to eq(1)
103
+ end
104
+
105
+ context 'with invalid arguments' do
106
+ it 'raises an exception' do
107
+ expect { pdf.join_style(:mitre) }
108
+ .to raise_error(Prawn::Errors::InvalidJoinStyle)
109
+ end
110
+ end
111
+ end
112
+
113
+ describe 'Dashes' do
114
+ it 'is able to use assignment operator' do
115
+ pdf.dash = 2
116
+ expect(pdf).to be_dashed
117
+ end
118
+
119
+ describe 'setting a dash' do
120
+ it 'dashed? should be_true' do
121
+ pdf.dash(2)
122
+ expect(pdf).to be_dashed
123
+ end
124
+
125
+ it 'rendered PDF should include a stroked dash' do
126
+ pdf.dash(2)
127
+ dashes = PDF::Inspector::Graphics::Dash.analyze(pdf.render)
128
+ expect(dashes.stroke_dash).to eq([[2, 2], 0])
129
+ end
130
+ end
131
+
132
+ describe 'setting a dash by passing a single argument' do
133
+ it 'space between dashes should be the same length as the dash in the '\
134
+ 'rendered PDF' do
135
+ pdf.dash(2)
136
+ dashes = PDF::Inspector::Graphics::Dash.analyze(pdf.render)
137
+ expect(dashes.stroke_dash).to eq([[2, 2], 0])
138
+ end
139
+ end
140
+
141
+ describe 'with a space option that differs from the first argument' do
142
+ it 'space between dashes in the rendered PDF should be different length '\
143
+ 'than the length of the dash' do
144
+ pdf.dash(2, space: 3)
145
+ dashes = PDF::Inspector::Graphics::Dash.analyze(pdf.render)
146
+ expect(dashes.stroke_dash).to eq([[2, 3], 0])
147
+ end
148
+ end
149
+
150
+ describe 'with a non-zero phase option' do
151
+ it 'rendered PDF should include a non-zero phase' do
152
+ pdf.dash(2, phase: 1)
153
+ dashes = PDF::Inspector::Graphics::Dash.analyze(pdf.render)
154
+ expect(dashes.stroke_dash).to eq([[2, 2], 1])
155
+ end
156
+ end
157
+
158
+ describe 'setting a dash by using an array' do
159
+ it 'dash and spaces should be set from the array' do
160
+ pdf.dash([1, 2, 3, 4])
161
+ dashes = PDF::Inspector::Graphics::Dash.analyze(pdf.render)
162
+ expect(dashes.stroke_dash).to eq([[1, 2, 3, 4], 0])
163
+ end
164
+
165
+ it 'at least one number in the array must not be zero' do
166
+ pdf.dash([1, 0])
167
+ dashes = PDF::Inspector::Graphics::Dash.analyze(pdf.render)
168
+ expect(dashes.stroke_dash).to eq([[1, 0], 0])
169
+ end
170
+
171
+ it 'space options has to be ignored' do
172
+ pdf.dash([1, 2, 3, 4], space: 3)
173
+ dashes = PDF::Inspector::Graphics::Dash.analyze(pdf.render)
174
+ expect(dashes.stroke_dash).to eq([[1, 2, 3, 4], 0])
175
+ end
176
+
177
+ it 'phase options should be correctly used' do
178
+ pdf.dash([1, 2, 3, 4], phase: 3)
179
+ dashes = PDF::Inspector::Graphics::Dash.analyze(pdf.render)
180
+ expect(dashes.stroke_dash).to eq([[1, 2, 3, 4], 3])
181
+ end
182
+ end
183
+
184
+ describe 'clearing stroke dash' do
185
+ it 'restores solid line' do
186
+ pdf.dash(2)
187
+ pdf.undash
188
+ dashes = PDF::Inspector::Graphics::Dash.analyze(pdf.render)
189
+ expect(dashes.stroke_dash).to eq([[], 0])
190
+ end
191
+ end
192
+
193
+ it 'carries the current dash settings over to new pages' do
194
+ pdf.dash(2)
195
+ pdf.start_new_page
196
+ dashes = PDF::Inspector::Graphics::Dash.analyze(pdf.render)
197
+ expect(dashes.stroke_dash_count).to eq(2)
198
+ expect(dashes.stroke_dash).to eq([[2, 2], 0])
199
+ end
200
+
201
+ describe '#dashed?' do
202
+ it 'an initial document should not be dashed' do
203
+ expect(pdf.dashed?).to eq(false)
204
+ end
205
+
206
+ it 'returns true if any of the currently active settings are dashed' do
207
+ pdf.dash(2)
208
+ pdf.save_graphics_state
209
+ expect(pdf.dashed?).to eq(true)
210
+ end
211
+
212
+ it 'returns false if the document was most recently undashed' do
213
+ pdf.dash(2)
214
+ pdf.save_graphics_state
215
+ pdf.undash
216
+ pdf.save_graphics_state
217
+ expect(pdf.dashed?).to eq(false)
218
+ end
219
+
220
+ it 'returns true when restoring to a state that was dashed' do
221
+ pdf.dash(2)
222
+ pdf.save_graphics_state
223
+ pdf.undash
224
+ pdf.restore_graphics_state
225
+ expect(pdf.dashed?).to eq(true)
226
+ end
227
+ end
228
+ end
229
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Prawn::ImageHandler do
6
+ let(:image_handler) { described_class.new }
7
+
8
+ let(:handler_a) { instance_double('Handler A') }
9
+ let(:handler_b) { instance_double('Handler B') }
10
+
11
+ it 'finds the image handler for an image' do
12
+ allow(handler_a).to receive(:can_render?).and_return(true)
13
+
14
+ image_handler.register(handler_a)
15
+ image_handler.register(handler_b)
16
+
17
+ handler = image_handler.find('arbitrary blob')
18
+ expect(handler).to eq(handler_a)
19
+ end
20
+
21
+ it 'can prepend handlers' do
22
+ allow(handler_b).to receive(:can_render?).and_return(true)
23
+
24
+ image_handler.register(handler_a)
25
+ image_handler.register!(handler_b)
26
+
27
+ handler = image_handler.find('arbitrary blob')
28
+ expect(handler).to eq(handler_b)
29
+ end
30
+
31
+ it 'can unregister a handler' do
32
+ allow(handler_b).to receive(:can_render?).and_return(true)
33
+
34
+ image_handler.register(handler_a)
35
+ image_handler.register(handler_b)
36
+
37
+ image_handler.unregister(handler_a)
38
+
39
+ handler = image_handler.find('arbitrary blob')
40
+ expect(handler).to eq(handler_b)
41
+ end
42
+
43
+ it 'raises an error when no matching handler is found' do
44
+ allow(handler_a).to receive(:can_render?).and_return(false)
45
+ allow(handler_b).to receive(:can_render?).and_return(false)
46
+
47
+ image_handler.register(handler_a)
48
+ image_handler.register(handler_b)
49
+
50
+ expect { image_handler.find('arbitrary blob') }
51
+ .to(raise_error(Prawn::Errors::UnsupportedImageType))
52
+ end
53
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Spec'ing the PNG class. Not complete yet - still needs to check the
4
+ # contents of palette and transparency to ensure they're correct.
5
+ # Need to find files that have these sections first.
6
+
7
+ require 'spec_helper'
8
+
9
+ describe Prawn::Images::JPG do
10
+ let(:img_data) { File.binread("#{Prawn::DATADIR}/images/pigs.jpg") }
11
+
12
+ it 'reads the basic attributes correctly' do
13
+ jpg = described_class.new(img_data)
14
+
15
+ expect(jpg.width).to eq(604)
16
+ expect(jpg.height).to eq(453)
17
+ expect(jpg.bits).to eq(8)
18
+ expect(jpg.channels).to eq(3)
19
+ end
20
+ end
@@ -0,0 +1,283 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Spec'ing the PNG class. Not complete yet - still needs to check the
4
+ # contents of palette and transparency to ensure they're correct.
5
+ # Need to find files that have these sections first.
6
+ #
7
+ # see http://www.w3.org/TR/PNG/ for a detailed description of the PNG spec,
8
+ # particuarly Table 11.1 for the different color types
9
+
10
+ require 'spec_helper'
11
+
12
+ describe Prawn::Images::PNG do
13
+ describe 'When making a pdf file with png images' do
14
+ image_dir = "#{Prawn::BASEDIR}/data/images"
15
+ images = [
16
+ ['Type 0', "#{image_dir}/web-links.png"],
17
+ ['Type 0 with transparency', "#{image_dir}/ruport_type0.png"],
18
+ ['Type 2', "#{image_dir}/ruport.png"],
19
+ ['Type 2 with transparency', "#{image_dir}/arrow2.png"],
20
+ ['Type 3', "#{image_dir}/indexed_color.png"],
21
+ ['Type 3 with transparency', "#{image_dir}/indexed_transparency.png"],
22
+ ['Type 4', "#{image_dir}/page_white_text.png"],
23
+ ['Type 6', "#{image_dir}/dice.png"],
24
+ ['Type 6 in 16bit', "#{image_dir}/16bit.png"]
25
+ ]
26
+
27
+ images.each do |header, file|
28
+ describe "and the image is #{header}" do
29
+ it 'does not error' do
30
+ expect do
31
+ Prawn::Document.generate("#{header}.pdf", page_size: 'A5') do
32
+ fill_color '00FF00'
33
+
34
+ fill_rectangle bounds.top_left, bounds.width, bounds.height
35
+ text header
36
+
37
+ image file, at: [50, 450]
38
+ end
39
+ end.to_not raise_error
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ describe 'When reading a greyscale PNG file (color type 0)' do
46
+ let(:data_filename) { "#{Prawn::DATADIR}/images/web-links.dat" }
47
+ let(:img_data) { File.binread("#{Prawn::DATADIR}/images/web-links.png") }
48
+
49
+ it 'reads the attributes from the header chunk correctly' do
50
+ png = described_class.new(img_data)
51
+
52
+ expect(png.width).to eq(21)
53
+ expect(png.height).to eq(14)
54
+ expect(png.bits).to eq(8)
55
+ expect(png.color_type).to eq(0)
56
+ expect(png.compression_method).to eq(0)
57
+ expect(png.filter_method).to eq(0)
58
+ expect(png.interlace_method).to eq(0)
59
+ end
60
+
61
+ it 'reads the image data chunk correctly' do
62
+ png = described_class.new(img_data)
63
+ data = Zlib::Inflate.inflate(File.binread(data_filename))
64
+ expect(png.img_data).to eq(data)
65
+ end
66
+ end
67
+
68
+ describe 'When reading a greyscale PNG with transparency (color type 0)' do
69
+ let(:img_data) { File.binread("#{Prawn::DATADIR}/images/ruport_type0.png") }
70
+
71
+ # In a greyscale type 0 PNG image, the tRNS chunk should contain a single
72
+ # value that indicates the color that should be interpreted as transparent.
73
+ #
74
+ # http://www.w3.org/TR/PNG/#11tRNS
75
+ it 'reads the tRNS chunk correctly' do
76
+ png = described_class.new(img_data)
77
+ expect(png.transparency[:grayscale]).to eq(255)
78
+ end
79
+ end
80
+
81
+ describe 'When reading an RGB PNG file (color type 2)' do
82
+ let(:data_filename) { "#{Prawn::DATADIR}/images/ruport_data.dat" }
83
+ let(:img_data) { File.binread("#{Prawn::DATADIR}/images/ruport.png") }
84
+
85
+ it 'reads the attributes from the header chunk correctly' do
86
+ png = described_class.new(img_data)
87
+
88
+ expect(png.width).to eq(258)
89
+ expect(png.height).to eq(105)
90
+ expect(png.bits).to eq(8)
91
+ expect(png.color_type).to eq(2)
92
+ expect(png.compression_method).to eq(0)
93
+ expect(png.filter_method).to eq(0)
94
+ expect(png.interlace_method).to eq(0)
95
+ end
96
+
97
+ it 'reads the image data chunk correctly' do
98
+ png = described_class.new(img_data)
99
+ data = Zlib::Inflate.inflate(File.binread(data_filename))
100
+ expect(png.img_data).to eq(data)
101
+ end
102
+ end
103
+
104
+ describe 'When reading an RGB PNG file with transparency (color type 2)' do
105
+ let(:img_data) { File.binread("#{Prawn::DATADIR}/images/arrow2.png") }
106
+
107
+ # In a RGB type 2 PNG image, the tRNS chunk should contain a single RGB
108
+ # value that indicates the color that should be interpreted as transparent.
109
+ # In this case it's green.
110
+ #
111
+ # http://www.w3.org/TR/PNG/#11tRNS
112
+ it 'reads the tRNS chunk correctly' do
113
+ png = described_class.new(img_data)
114
+ expect(png.transparency[:rgb]).to eq([0, 255, 0])
115
+ end
116
+ end
117
+
118
+ describe 'When reading an indexed color PNG file with transparency '\
119
+ '(color type 3)' do
120
+ let(:filename) { "#{Prawn::DATADIR}/images/indexed_transparency.png" }
121
+ let(:color_filename) do
122
+ "#{Prawn::DATADIR}/images/indexed_transparency_color.dat"
123
+ end
124
+ let(:transparency_filename) do
125
+ "#{Prawn::DATADIR}/images/indexed_transparency_alpha.dat"
126
+ end
127
+ let(:img_data) { File.binread(filename) }
128
+ let(:png) { described_class.new(img_data) }
129
+
130
+ it 'reads the attributes from the header chunk correctly' do
131
+ expect(png.width).to eq(200)
132
+ expect(png.height).to eq(200)
133
+ expect(png.bits).to eq(8)
134
+ expect(png.color_type).to eq(3)
135
+ expect(png.compression_method).to eq(0)
136
+ expect(png.filter_method).to eq(0)
137
+ expect(png.interlace_method).to eq(0)
138
+ end
139
+
140
+ it 'reads the image data correctly' do
141
+ data = Zlib::Inflate.inflate(File.binread(color_filename))
142
+ expect(png.img_data).to eq(data)
143
+ end
144
+
145
+ it 'reads the image transparency correctly' do
146
+ png.split_alpha_channel!
147
+
148
+ data = Zlib::Inflate.inflate(File.binread(transparency_filename))
149
+ expect(png.alpha_channel).to eq(data)
150
+ end
151
+ end
152
+
153
+ describe 'When reading an indexed color PNG file (color type 3)' do
154
+ let(:data_filename) { "#{Prawn::DATADIR}/images/indexed_color.dat" }
155
+ let(:img_data) do
156
+ File.binread("#{Prawn::DATADIR}/images/indexed_color.png")
157
+ end
158
+
159
+ it 'reads the attributes from the header chunk correctly' do
160
+ png = described_class.new(img_data)
161
+
162
+ expect(png.width).to eq(150)
163
+ expect(png.height).to eq(200)
164
+ expect(png.bits).to eq(8)
165
+ expect(png.color_type).to eq(3)
166
+ expect(png.compression_method).to eq(0)
167
+ expect(png.filter_method).to eq(0)
168
+ expect(png.interlace_method).to eq(0)
169
+ end
170
+
171
+ it 'reads the image data chunk correctly' do
172
+ png = described_class.new(img_data)
173
+ data = Zlib::Inflate.inflate(File.binread(data_filename))
174
+ expect(png.img_data).to eq(data)
175
+ end
176
+ end
177
+
178
+ describe 'When reading a greyscale+alpha PNG file (color type 4)' do
179
+ let(:color_data_filename) do
180
+ "#{Prawn::DATADIR}/images/page_white_text.color"
181
+ end
182
+ let(:alpha_data_filename) do
183
+ "#{Prawn::DATADIR}/images/page_white_text.alpha"
184
+ end
185
+ let(:img_data) do
186
+ File.binread("#{Prawn::DATADIR}/images/page_white_text.png")
187
+ end
188
+
189
+ it 'reads the attributes from the header chunk correctly' do
190
+ png = described_class.new(img_data)
191
+
192
+ expect(png.width).to eq(16)
193
+ expect(png.height).to eq(16)
194
+ expect(png.bits).to eq(8)
195
+ expect(png.color_type).to eq(4)
196
+ expect(png.compression_method).to eq(0)
197
+ expect(png.filter_method).to eq(0)
198
+ expect(png.interlace_method).to eq(0)
199
+ end
200
+
201
+ it 'correctly returns the raw image data (with no alpha channel) from '\
202
+ 'the image data chunk' do
203
+ png = described_class.new(img_data)
204
+ png.split_alpha_channel!
205
+ data = File.binread(color_data_filename)
206
+ expect(png.img_data).to eq(data)
207
+ end
208
+
209
+ it 'correctly extracts the alpha channel data from the image data chunk' do
210
+ png = described_class.new(img_data)
211
+ png.split_alpha_channel!
212
+ data = File.binread(alpha_data_filename)
213
+ expect(png.alpha_channel).to eq(data)
214
+ end
215
+ end
216
+
217
+ describe 'When reading an RGB+alpha PNG file (color type 6)' do
218
+ let(:color_data_filename) { "#{Prawn::DATADIR}/images/dice.color" }
219
+ let(:alpha_data_filename) { "#{Prawn::DATADIR}/images/dice.alpha" }
220
+ let(:img_data) { File.binread("#{Prawn::DATADIR}/images/dice.png") }
221
+
222
+ it 'reads the attributes from the header chunk correctly' do
223
+ png = described_class.new(img_data)
224
+
225
+ expect(png.width).to eq(320)
226
+ expect(png.height).to eq(240)
227
+ expect(png.bits).to eq(8)
228
+ expect(png.color_type).to eq(6)
229
+ expect(png.compression_method).to eq(0)
230
+ expect(png.filter_method).to eq(0)
231
+ expect(png.interlace_method).to eq(0)
232
+ end
233
+
234
+ it 'correctly returns the raw image data (with no alpha channel) from '\
235
+ 'the image data chunk' do
236
+ png = described_class.new(img_data)
237
+ png.split_alpha_channel!
238
+ data = File.binread(color_data_filename)
239
+ expect(png.img_data).to eq(data)
240
+ end
241
+
242
+ it 'correctly extracts the alpha channel data from the image data chunk' do
243
+ png = described_class.new(img_data)
244
+ png.split_alpha_channel!
245
+ data = File.binread(alpha_data_filename)
246
+ expect(png.alpha_channel).to eq(data)
247
+ end
248
+ end
249
+
250
+ describe 'When reading a 16bit RGB+alpha PNG file (color type 6)' do
251
+ let(:color_data_filename) { "#{Prawn::DATADIR}/images/16bit.color" }
252
+ # alpha channel truncated to 8-bit
253
+ let(:alpha_data_filename) { "#{Prawn::DATADIR}/images/16bit.alpha" }
254
+ let(:img_data) { File.binread("#{Prawn::DATADIR}/images/16bit.png") }
255
+
256
+ it 'reads the attributes from the header chunk correctly' do
257
+ png = described_class.new(img_data)
258
+
259
+ expect(png.width).to eq(32)
260
+ expect(png.height).to eq(32)
261
+ expect(png.bits).to eq(16)
262
+ expect(png.color_type).to eq(6)
263
+ expect(png.compression_method).to eq(0)
264
+ expect(png.filter_method).to eq(0)
265
+ expect(png.interlace_method).to eq(0)
266
+ end
267
+
268
+ it 'correctly returns the raw image data (with no alpha channel) from '\
269
+ 'the image data chunk' do
270
+ png = described_class.new(img_data)
271
+ png.split_alpha_channel!
272
+ data = File.binread(color_data_filename)
273
+ expect(png.img_data).to eq(data)
274
+ end
275
+
276
+ it 'correctly extracts the alpha channel data from the image data chunk' do
277
+ png = described_class.new(img_data)
278
+ png.split_alpha_channel!
279
+ data = File.binread(alpha_data_filename)
280
+ expect(png.alpha_channel).to eq(data)
281
+ end
282
+ end
283
+ end