hexapdf 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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)