hexapdf 0.7.0 → 0.8.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 (106) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -1
  3. data/CONTRIBUTERS +1 -1
  4. data/LICENSE +3 -0
  5. data/README.md +2 -1
  6. data/Rakefile +3 -1
  7. data/VERSION +1 -1
  8. data/examples/{hello_world.rb → 001-hello_world.rb} +0 -0
  9. data/examples/{graphics.rb → 002-graphics.rb} +1 -1
  10. data/examples/{arc.rb → 003-arcs.rb} +2 -2
  11. data/examples/{optimizing.rb → 004-optimizing.rb} +0 -0
  12. data/examples/{merging.rb → 005-merging.rb} +0 -0
  13. data/examples/{standard_pdf_fonts.rb → 006-standard_pdf_fonts.rb} +0 -0
  14. data/examples/{truetype.rb → 007-truetype.rb} +0 -0
  15. data/examples/{show_char_bboxes.rb → 008-show_char_bboxes.rb} +0 -0
  16. data/examples/{text_layouter_alignment.rb → 009-text_layouter_alignment.rb} +3 -3
  17. data/examples/{text_layouter_inline_boxes.rb → 010-text_layouter_inline_boxes.rb} +7 -9
  18. data/examples/{text_layouter_line_wrapping.rb → 011-text_layouter_line_wrapping.rb} +6 -5
  19. data/examples/{text_layouter_styling.rb → 012-text_layouter_styling.rb} +6 -8
  20. data/examples/013-text_layouter_shapes.rb +176 -0
  21. data/examples/014-text_in_polygon.rb +60 -0
  22. data/examples/{boxes.rb → 015-boxes.rb} +29 -21
  23. data/examples/016-frame_automatic_box_placement.rb +90 -0
  24. data/examples/017-frame_text_flow.rb +60 -0
  25. data/lib/hexapdf/cli/command.rb +4 -3
  26. data/lib/hexapdf/cli/files.rb +1 -1
  27. data/lib/hexapdf/cli/inspect.rb +0 -1
  28. data/lib/hexapdf/cli/merge.rb +1 -1
  29. data/lib/hexapdf/cli/modify.rb +1 -1
  30. data/lib/hexapdf/configuration.rb +2 -0
  31. data/lib/hexapdf/content/canvas.rb +3 -3
  32. data/lib/hexapdf/content/graphic_object.rb +1 -0
  33. data/lib/hexapdf/content/graphic_object/geom2d.rb +132 -0
  34. data/lib/hexapdf/dictionary.rb +7 -1
  35. data/lib/hexapdf/dictionary_fields.rb +35 -83
  36. data/lib/hexapdf/document.rb +9 -5
  37. data/lib/hexapdf/document/fonts.rb +1 -1
  38. data/lib/hexapdf/encryption/standard_security_handler.rb +1 -1
  39. data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
  40. data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
  41. data/lib/hexapdf/font/cmap/writer.rb +2 -2
  42. data/lib/hexapdf/font/true_type/builder.rb +1 -1
  43. data/lib/hexapdf/font/true_type/table.rb +1 -1
  44. data/lib/hexapdf/font/true_type/table/cmap.rb +1 -1
  45. data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +3 -3
  46. data/lib/hexapdf/font/true_type/table/kern.rb +1 -1
  47. data/lib/hexapdf/font/true_type/table/post.rb +1 -1
  48. data/lib/hexapdf/font/type1/character_metrics.rb +1 -1
  49. data/lib/hexapdf/font/type1/font_metrics.rb +1 -1
  50. data/lib/hexapdf/image_loader/jpeg.rb +1 -1
  51. data/lib/hexapdf/image_loader/png.rb +2 -2
  52. data/lib/hexapdf/layout.rb +3 -0
  53. data/lib/hexapdf/layout/box.rb +64 -46
  54. data/lib/hexapdf/layout/frame.rb +348 -0
  55. data/lib/hexapdf/layout/inline_box.rb +2 -2
  56. data/lib/hexapdf/layout/line.rb +3 -3
  57. data/lib/hexapdf/layout/style.rb +81 -14
  58. data/lib/hexapdf/layout/text_box.rb +84 -0
  59. data/lib/hexapdf/layout/text_fragment.rb +8 -8
  60. data/lib/hexapdf/layout/text_layouter.rb +278 -169
  61. data/lib/hexapdf/layout/width_from_polygon.rb +246 -0
  62. data/lib/hexapdf/rectangle.rb +9 -9
  63. data/lib/hexapdf/stream.rb +2 -2
  64. data/lib/hexapdf/type.rb +1 -0
  65. data/lib/hexapdf/type/action.rb +1 -1
  66. data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
  67. data/lib/hexapdf/type/catalog.rb +1 -1
  68. data/lib/hexapdf/type/cid_font.rb +2 -1
  69. data/lib/hexapdf/type/font.rb +0 -1
  70. data/lib/hexapdf/type/font_descriptor.rb +1 -1
  71. data/lib/hexapdf/type/font_simple.rb +3 -3
  72. data/lib/hexapdf/type/font_true_type.rb +8 -0
  73. data/lib/hexapdf/type/font_type0.rb +2 -1
  74. data/lib/hexapdf/type/font_type1.rb +7 -1
  75. data/lib/hexapdf/type/font_type3.rb +61 -0
  76. data/lib/hexapdf/type/graphics_state_parameter.rb +8 -8
  77. data/lib/hexapdf/type/image.rb +10 -0
  78. data/lib/hexapdf/type/page.rb +83 -10
  79. data/lib/hexapdf/version.rb +1 -1
  80. data/test/hexapdf/common_tokenizer_tests.rb +2 -2
  81. data/test/hexapdf/content/graphic_object/test_geom2d.rb +79 -0
  82. data/test/hexapdf/encryption/test_standard_security_handler.rb +1 -1
  83. data/test/hexapdf/font/test_true_type_wrapper.rb +1 -1
  84. data/test/hexapdf/font/test_type1_wrapper.rb +1 -1
  85. data/test/hexapdf/font/true_type/table/test_cmap.rb +1 -1
  86. data/test/hexapdf/font/true_type/table/test_directory.rb +1 -1
  87. data/test/hexapdf/font/true_type/table/test_head.rb +7 -3
  88. data/test/hexapdf/layout/test_box.rb +57 -15
  89. data/test/hexapdf/layout/test_frame.rb +313 -0
  90. data/test/hexapdf/layout/test_inline_box.rb +1 -1
  91. data/test/hexapdf/layout/test_style.rb +74 -0
  92. data/test/hexapdf/layout/test_text_box.rb +77 -0
  93. data/test/hexapdf/layout/test_text_layouter.rb +220 -239
  94. data/test/hexapdf/layout/test_width_from_polygon.rb +108 -0
  95. data/test/hexapdf/test_dictionary_fields.rb +22 -26
  96. data/test/hexapdf/test_document.rb +3 -3
  97. data/test/hexapdf/test_reference.rb +1 -0
  98. data/test/hexapdf/test_writer.rb +2 -2
  99. data/test/hexapdf/type/test_font_true_type.rb +25 -0
  100. data/test/hexapdf/type/test_font_type1.rb +6 -0
  101. data/test/hexapdf/type/test_font_type3.rb +26 -0
  102. data/test/hexapdf/type/test_image.rb +10 -0
  103. data/test/hexapdf/type/test_page.rb +114 -0
  104. data/test/test_helper.rb +1 -1
  105. metadata +65 -17
  106. data/examples/text_layouter_shapes.rb +0 -170
@@ -39,7 +39,7 @@ module TestHelper
39
39
  def feeder(string, len = string.length)
40
40
  Fiber.new do
41
41
  until string.empty?
42
- Fiber.yield string.slice!(0, len).force_encoding('BINARY')
42
+ Fiber.yield(string.slice!(0, len).force_encoding('BINARY'))
43
43
  end
44
44
  end
45
45
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hexapdf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Leitner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-19 00:00:00.000000000 Z
11
+ date: 2018-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cmdparse
@@ -30,6 +30,20 @@ dependencies:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
32
  version: 3.0.3
33
+ - !ruby/object:Gem::Dependency
34
+ name: geom2d
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.1'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '0.1'
33
47
  - !ruby/object:Gem::Dependency
34
48
  name: kramdown
35
49
  requirement: !ruby/object:Gem::Requirement
@@ -50,6 +64,26 @@ dependencies:
50
64
  - - ">="
51
65
  - !ruby/object:Gem::Version
52
66
  version: 1.13.0
67
+ - !ruby/object:Gem::Dependency
68
+ name: rubocop
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '0.58'
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: 0.58.2
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '0.58'
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: 0.58.2
53
87
  description: |-
54
88
  HexaPDF is a pure Ruby library with an accompanying application for working with PDF files.
55
89
 
@@ -154,23 +188,26 @@ files:
154
188
  - data/hexapdf/cmap/V
155
189
  - data/hexapdf/encoding/glyphlist.txt
156
190
  - data/hexapdf/encoding/zapfdingbats.txt
157
- - examples/arc.rb
158
- - examples/boxes.rb
191
+ - examples/001-hello_world.rb
192
+ - examples/002-graphics.rb
193
+ - examples/003-arcs.rb
194
+ - examples/004-optimizing.rb
195
+ - examples/005-merging.rb
196
+ - examples/006-standard_pdf_fonts.rb
197
+ - examples/007-truetype.rb
198
+ - examples/008-show_char_bboxes.rb
199
+ - examples/009-text_layouter_alignment.rb
200
+ - examples/010-text_layouter_inline_boxes.rb
201
+ - examples/011-text_layouter_line_wrapping.rb
202
+ - examples/012-text_layouter_styling.rb
203
+ - examples/013-text_layouter_shapes.rb
204
+ - examples/014-text_in_polygon.rb
205
+ - examples/015-boxes.rb
206
+ - examples/016-frame_automatic_box_placement.rb
207
+ - examples/017-frame_text_flow.rb
159
208
  - examples/emoji-smile.png
160
209
  - examples/emoji-wink.png
161
- - examples/graphics.rb
162
- - examples/hello_world.rb
163
210
  - examples/machupicchu.jpg
164
- - examples/merging.rb
165
- - examples/optimizing.rb
166
- - examples/show_char_bboxes.rb
167
- - examples/standard_pdf_fonts.rb
168
- - examples/text_layouter_alignment.rb
169
- - examples/text_layouter_inline_boxes.rb
170
- - examples/text_layouter_line_wrapping.rb
171
- - examples/text_layouter_shapes.rb
172
- - examples/text_layouter_styling.rb
173
- - examples/truetype.rb
174
211
  - lib/hexapdf.rb
175
212
  - lib/hexapdf/cli.rb
176
213
  - lib/hexapdf/cli/batch.rb
@@ -189,6 +226,7 @@ files:
189
226
  - lib/hexapdf/content/graphic_object.rb
190
227
  - lib/hexapdf/content/graphic_object/arc.rb
191
228
  - lib/hexapdf/content/graphic_object/endpoint_arc.rb
229
+ - lib/hexapdf/content/graphic_object/geom2d.rb
192
230
  - lib/hexapdf/content/graphic_object/solid_arc.rb
193
231
  - lib/hexapdf/content/graphics_state.rb
194
232
  - lib/hexapdf/content/operator.rb
@@ -276,13 +314,16 @@ files:
276
314
  - lib/hexapdf/importer.rb
277
315
  - lib/hexapdf/layout.rb
278
316
  - lib/hexapdf/layout/box.rb
317
+ - lib/hexapdf/layout/frame.rb
279
318
  - lib/hexapdf/layout/inline_box.rb
280
319
  - lib/hexapdf/layout/line.rb
281
320
  - lib/hexapdf/layout/numeric_refinements.rb
282
321
  - lib/hexapdf/layout/style.rb
322
+ - lib/hexapdf/layout/text_box.rb
283
323
  - lib/hexapdf/layout/text_fragment.rb
284
324
  - lib/hexapdf/layout/text_layouter.rb
285
325
  - lib/hexapdf/layout/text_shaper.rb
326
+ - lib/hexapdf/layout/width_from_polygon.rb
286
327
  - lib/hexapdf/name_tree_node.rb
287
328
  - lib/hexapdf/number_tree_node.rb
288
329
  - lib/hexapdf/object.rb
@@ -319,6 +360,7 @@ files:
319
360
  - lib/hexapdf/type/font_true_type.rb
320
361
  - lib/hexapdf/type/font_type0.rb
321
362
  - lib/hexapdf/type/font_type1.rb
363
+ - lib/hexapdf/type/font_type3.rb
322
364
  - lib/hexapdf/type/form.rb
323
365
  - lib/hexapdf/type/graphics_state_parameter.rb
324
366
  - lib/hexapdf/type/image.rb
@@ -416,6 +458,7 @@ files:
416
458
  - test/hexapdf/content/common.rb
417
459
  - test/hexapdf/content/graphic_object/test_arc.rb
418
460
  - test/hexapdf/content/graphic_object/test_endpoint_arc.rb
461
+ - test/hexapdf/content/graphic_object/test_geom2d.rb
419
462
  - test/hexapdf/content/graphic_object/test_solid_arc.rb
420
463
  - test/hexapdf/content/test_canvas.rb
421
464
  - test/hexapdf/content/test_color_space.rb
@@ -489,12 +532,15 @@ files:
489
532
  - test/hexapdf/image_loader/test_pdf.rb
490
533
  - test/hexapdf/image_loader/test_png.rb
491
534
  - test/hexapdf/layout/test_box.rb
535
+ - test/hexapdf/layout/test_frame.rb
492
536
  - test/hexapdf/layout/test_inline_box.rb
493
537
  - test/hexapdf/layout/test_line.rb
494
538
  - test/hexapdf/layout/test_style.rb
539
+ - test/hexapdf/layout/test_text_box.rb
495
540
  - test/hexapdf/layout/test_text_fragment.rb
496
541
  - test/hexapdf/layout/test_text_layouter.rb
497
542
  - test/hexapdf/layout/test_text_shaper.rb
543
+ - test/hexapdf/layout/test_width_from_polygon.rb
498
544
  - test/hexapdf/task/test_dereference.rb
499
545
  - test/hexapdf/task/test_optimize.rb
500
546
  - test/hexapdf/test_configuration.rb
@@ -528,8 +574,10 @@ files:
528
574
  - test/hexapdf/type/test_font.rb
529
575
  - test/hexapdf/type/test_font_descriptor.rb
530
576
  - test/hexapdf/type/test_font_simple.rb
577
+ - test/hexapdf/type/test_font_true_type.rb
531
578
  - test/hexapdf/type/test_font_type0.rb
532
579
  - test/hexapdf/type/test_font_type1.rb
580
+ - test/hexapdf/type/test_font_type3.rb
533
581
  - test/hexapdf/type/test_form.rb
534
582
  - test/hexapdf/type/test_image.rb
535
583
  - test/hexapdf/type/test_info.rb
@@ -547,7 +595,7 @@ files:
547
595
  - test/hexapdf/utils/test_pdf_doc_encoding.rb
548
596
  - test/hexapdf/utils/test_sorted_tree_node.rb
549
597
  - test/test_helper.rb
550
- homepage: http://hexapdf.gettalong.org
598
+ homepage: https://hexapdf.gettalong.org
551
599
  licenses:
552
600
  - AGPL-3.0
553
601
  metadata: {}
@@ -1,170 +0,0 @@
1
- # ## Text Layouter - Shapes
2
- #
3
- # The [HexaPDF::Layout::TextLayouter] class can be used to easily lay out text,
4
- # not limiting the area to a rectangle but any shape. There is only one
5
- # restriction: In the case of arbitrary shapes the vertical alignment has to be
6
- # "top".
7
- #
8
- # Arbitrary shapes boil down to varying line widths and horizontal offsets from
9
- # left. Imagine a circle: If text is fit in a circle, the line widths start at
10
- # zero, getting larger and larger until the middle of the cirle. And then they
11
- # get smaller until zero again. The x-values of the left half circle determine
12
- # the horizontal offsets.
13
- #
14
- # Both, the line widths and the horizontal offsets can be calculated given a
15
- # certain height, and this is exactly what HexaPDF uses. If the `width` argument
16
- # to [HexaPDF::Layout::TextLayouter::new] is an object responding to #call (e.g.
17
- # a lambda), it is used for determining the line widths. And the `x_offsets`
18
- # argument can be used in a similar way for the horizontal offsets.
19
- #
20
- # This example shows text layed out in various shapes, using the above mentioned
21
- # techniques.
22
- #
23
- # Usage:
24
- # : `ruby text_layouter_shapes.rb`
25
- #
26
-
27
- require 'hexapdf'
28
-
29
- include HexaPDF::Layout
30
-
31
- doc = HexaPDF::Document.new
32
- page = doc.pages.add
33
- canvas = page.canvas
34
- canvas.font("Times", size: 10, variant: :bold)
35
- canvas.stroke_color(255, 0, 0).line_width(0.2)
36
- font = doc.fonts.add("Times")
37
-
38
- sample_text = "Lorem ipsum dolor sit amet, con\u{00AD}sectetur
39
- adipis\u{00AD}cing elit, sed do eiusmod tempor incididunt ut labore et
40
- dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
41
- ullamco laboris nisi ut aliquip ex ea commodo consequat.
42
- ".tr("\n", ' ') * 10
43
-
44
- ########################################################################
45
- # Circly things on the top
46
- radius = 100
47
- circle_top = 800
48
- half_circle_widths = lambda do |height, line_height|
49
- sum = height + line_height
50
- if sum <= radius * 2
51
- [Math.sqrt(radius**2 - (radius - height)**2),
52
- Math.sqrt([radius**2 - (radius - sum)**2, 0].max)].min
53
- else
54
- 0
55
- end
56
- end
57
- circle_widths = lambda do |height, line_height|
58
- 2 * half_circle_widths.call(height, line_height)
59
- end
60
- left_half_circle_offsets = lambda do |height, line_height|
61
- radius - half_circle_widths.call(height, line_height)
62
- end
63
-
64
- # Left: right half circle
65
- layouter = TextLayouter.create(sample_text,
66
- width: half_circle_widths,
67
- height: radius * 2,
68
- font: font)
69
- layouter.draw(canvas, 0, circle_top)
70
- canvas.circle(0, circle_top - radius, radius).stroke
71
-
72
- # Center: full circle
73
- layouter = TextLayouter.create(sample_text,
74
- width: circle_widths,
75
- x_offsets: left_half_circle_offsets,
76
- height: radius * 2,
77
- font: font,
78
- align: :justify)
79
- layouter.draw(canvas, page.box(:media).width / 2.0 - radius, circle_top)
80
- canvas.circle(page.box(:media).width / 2.0, circle_top - radius, radius).stroke
81
-
82
- # Right: left half circle
83
- layouter = TextLayouter.create(sample_text,
84
- width: half_circle_widths,
85
- x_offsets: left_half_circle_offsets,
86
- height: radius * 2,
87
- font: font,
88
- align: :right)
89
- layouter.draw(canvas, page.box(:media).width - radius, circle_top)
90
- canvas.circle(page.box(:media).width, circle_top - radius, radius).stroke
91
-
92
-
93
- ########################################################################
94
- # Pointy, diamondy things in the middle
95
-
96
- diamond_width = 100
97
- diamond_top = circle_top - 2 * radius - 50
98
- half_diamond_widths = lambda do |height, line_height|
99
- sum = height + line_height
100
- if sum < diamond_width
101
- height
102
- else
103
- [diamond_width * 2 - sum, 0].max
104
- end
105
- end
106
- full_diamond_widths = lambda do |height, line_height|
107
- 2 * half_diamond_widths.call(height, line_height)
108
- end
109
- left_half_diamond_offsets = lambda do |height, line_height|
110
- diamond_width - half_diamond_widths.call(height, line_height)
111
- end
112
-
113
- # Left: right half diamond
114
- layouter = TextLayouter.create(sample_text,
115
- width: half_diamond_widths,
116
- height: 2 * diamond_width,
117
- font: font)
118
- layouter.draw(canvas, 0, diamond_top)
119
- canvas.polyline(0, diamond_top, diamond_width, diamond_top - diamond_width,
120
- 0, diamond_top - 2 * diamond_width).stroke
121
-
122
- # Center: full diamond
123
- layouter = TextLayouter.create(sample_text,
124
- width: full_diamond_widths,
125
- x_offsets: left_half_diamond_offsets,
126
- height: 2 * diamond_width,
127
- font: font,
128
- align: :justify)
129
- left = page.box(:media).width / 2.0 - diamond_width
130
- layouter.draw(canvas, left, diamond_top)
131
- canvas.polyline(left + diamond_width, diamond_top,
132
- left + 2 * diamond_width, diamond_top - diamond_width,
133
- left + diamond_width, diamond_top - 2 * diamond_width,
134
- left, diamond_top - diamond_width).close_subpath.stroke
135
-
136
- # Right: left half diamond
137
- layouter = TextLayouter.create(sample_text,
138
- width: half_diamond_widths,
139
- x_offsets: left_half_diamond_offsets,
140
- height: 2 * diamond_width,
141
- font: font,
142
- align: :right)
143
- middle = page.box(:media).width
144
- layouter.draw(canvas, middle - diamond_width, diamond_top)
145
- canvas.polyline(middle, diamond_top,
146
- middle - diamond_width, diamond_top - diamond_width,
147
- middle, diamond_top - 2 * diamond_width).stroke
148
-
149
- ########################################################################
150
- # Sine wave thing at the bottom
151
-
152
- sine_wave_height = 200.0
153
- sine_wave_top = diamond_top - 2 * diamond_width - 50
154
- sine_wave_offsets = lambda do |height, line_height|
155
- [40 * Math.sin(2 * Math::PI * (height / sine_wave_height)),
156
- 40 * Math.sin(2 * Math::PI * (height + line_height) / sine_wave_height)].max
157
- end
158
- sine_wave_widths = lambda do |height, line_height|
159
- sine_wave_height + 100 + sine_wave_offsets.call(height, line_height) * -2
160
- end
161
- layouter = TextLayouter.create(sample_text,
162
- width: sine_wave_widths,
163
- x_offsets: sine_wave_offsets,
164
- height: sine_wave_height,
165
- font: font,
166
- align: :justify)
167
- middle = page.box(:media).width / 2.0
168
- layouter.draw(canvas, middle - (sine_wave_height + 100) / 2, sine_wave_top)
169
-
170
- doc.write("text_layouter_shapes.pdf", optimize: true)