hexapdf 0.12.1 → 0.12.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a0354d0b129396ae7c479e806b3115f0be7a7f7d74d47df13f9ad82e5f93df50
4
- data.tar.gz: 15f8a80efbffea1724ffdd54bc2f204816def3980ba59986336b742eed3ce6b3
3
+ metadata.gz: d95e6e2abba7581aab78e449bf860c3955170d4c266850373296300495236c44
4
+ data.tar.gz: '0950af72d8864e98a70367ee28bdf09bc09aa83cace38933aa613bc8d476263d'
5
5
  SHA512:
6
- metadata.gz: dc132b215e6d6bd2ab6684e269c559e1d55301403c2c035e32eb7fc213572b86e993f1307c219f6e0aec6bbd8da36ab6d10146c82b89e52f68ca5c90949ef819
7
- data.tar.gz: 9bd6252238d418844de0d9e08250dc6b7d8a620fc1e4f232bea6870986764ced86dadc0e4794512ae6abc347a6cf95569b5af7ff35c54833d57b2c2513a0d987
6
+ metadata.gz: c3c4ad1073d3ea9b820dc129348cf2d571159ea129aa65a10546552ae52e19cf29d74a4716e3fcefac10b34f9d2ad7e833bb90355c81564a152c853e0a406ea4
7
+ data.tar.gz: 637e17817d1aa8eb3b75035aa5d654f5bdbd7b531fb16776da49945c5100ab0705ab7d59b300f192b865d75ded43edae48d2f15541c2a93edbdedba9318f896a
@@ -1,3 +1,13 @@
1
+ ## 0.12.2 - 2020-08-17
2
+
3
+ ### Fixed
4
+
5
+ - Wrong origin for page canvases when bottom left corner of media box doesn't
6
+ coincide with origin of coordinate system
7
+ - Wrong origin for Form XObject canvas when bottom left corner of bounding box
8
+ doesn't coincide with origin of coordinate system
9
+
10
+
1
11
  ## 0.12.1 - 2020-08-16
2
12
 
3
13
  ### Added
@@ -126,13 +126,22 @@ module HexaPDF
126
126
  # The canvas object is cached once it is created so that its graphics state is correctly
127
127
  # retained without the need for parsing its contents.
128
128
  #
129
+ # If the bounding box of the form XObject doesn't have its origin at (0, 0), the canvas origin
130
+ # is translated into the bottom left corner so that this detail doesn't matter when using the
131
+ # canvas. This means that the canvas' origin is always at the bottom left corner of the
132
+ # bounding box.
133
+ #
129
134
  # *Note* that a canvas can only be retrieved for initially empty form XObjects!
130
135
  def canvas
131
136
  document.cache(@data, :canvas) do
132
137
  unless stream.empty?
133
138
  raise HexaPDF::Error, "Cannot create a canvas for a form XObjects with contents"
134
139
  end
140
+
135
141
  canvas = Content::Canvas.new(self)
142
+ if box.left != 0 || box.bottom != 0
143
+ canvas.save_graphics_state.translate(box.left, box.bottom)
144
+ end
136
145
  self.stream = canvas.stream_data
137
146
  set_filter(:FlateDecode)
138
147
  canvas
@@ -358,6 +358,11 @@ module HexaPDF
358
358
  # The canvas object is cached once it is created so that its graphics state is correctly
359
359
  # retained without the need for parsing its contents.
360
360
  #
361
+ # If the media box of the page doesn't have its origin at (0, 0), the canvas origin is
362
+ # translated into the bottom left corner so that this detail doesn't matter when using the
363
+ # canvas. This means that the canvas' origin is always at the bottom left corner of the media
364
+ # box.
365
+ #
361
366
  # type::
362
367
  # Can either be
363
368
  # * :page for getting the canvas for the page itself (only valid for initially empty pages)
@@ -374,16 +379,25 @@ module HexaPDF
374
379
  raise HexaPDF::Error, "Cannot get the canvas for a page with contents"
375
380
  end
376
381
 
382
+ create_canvas = lambda do
383
+ Content::Canvas.new(self).tap do |canvas|
384
+ media_box = box(:media)
385
+ if media_box.left != 0 || media_box.bottom != 0
386
+ canvas.translate(media_box.left, media_box.bottom)
387
+ end
388
+ end
389
+ end
390
+
377
391
  contents = self[:Contents]
378
392
  if contents.nil?
379
- page_canvas = document.cache(@data, :page_canvas, Content::Canvas.new(self))
393
+ page_canvas = document.cache(@data, :page_canvas, create_canvas.call)
380
394
  self[:Contents] = document.add({Filter: :FlateDecode},
381
395
  stream: page_canvas.stream_data)
382
396
  end
383
397
 
384
398
  if type == :overlay || type == :underlay
385
- underlay_canvas = document.cache(@data, :underlay_canvas, Content::Canvas.new(self))
386
- overlay_canvas = document.cache(@data, :overlay_canvas, Content::Canvas.new(self))
399
+ underlay_canvas = document.cache(@data, :underlay_canvas, create_canvas.call)
400
+ overlay_canvas = document.cache(@data, :overlay_canvas, create_canvas.call)
387
401
 
388
402
  stream = HexaPDF::StreamData.new do
389
403
  Fiber.yield(" q ")
@@ -396,11 +410,12 @@ module HexaPDF
396
410
  underlay = document.add({Filter: :FlateDecode}, stream: stream)
397
411
 
398
412
  stream = HexaPDF::StreamData.new do
399
- Fiber.yield(" Q ")
413
+ Fiber.yield(" Q q ")
400
414
  fiber = overlay_canvas.stream_data.fiber
401
415
  while fiber.alive? && (data = fiber.resume)
402
416
  Fiber.yield(data)
403
417
  end
418
+ " Q "
404
419
  end
405
420
  overlay = document.add({Filter: :FlateDecode}, stream: stream)
406
421
 
@@ -37,6 +37,6 @@
37
37
  module HexaPDF
38
38
 
39
39
  # The version of HexaPDF.
40
- VERSION = '0.12.1'
40
+ VERSION = '0.12.2'
41
41
 
42
42
  end
@@ -537,7 +537,7 @@ describe HexaPDF::Layout::Style::LinkLayer do
537
537
  end
538
538
 
539
539
  it "does nothing if the context is not a page object" do
540
- @canvas = HexaPDF::Document.new.add({Type: :XObject, Subtype: :Form}).canvas
540
+ @canvas = HexaPDF::Document.new.add({Type: :XObject, Subtype: :Form, BBox: [0, 0, 1, 1]}).canvas
541
541
  assert_nil(call_link(dest: true))
542
542
  end
543
543
 
@@ -40,7 +40,7 @@ describe HexaPDF::Writer do
40
40
  219
41
41
  %%EOF
42
42
  3 0 obj
43
- <</Producer(HexaPDF version 0.12.1)>>
43
+ <</Producer(HexaPDF version 0.12.2)>>
44
44
  endobj
45
45
  xref
46
46
  3 1
@@ -72,7 +72,7 @@ describe HexaPDF::Writer do
72
72
  141
73
73
  %%EOF
74
74
  6 0 obj
75
- <</Producer(HexaPDF version 0.12.1)>>
75
+ <</Producer(HexaPDF version 0.12.2)>>
76
76
  endobj
77
77
  2 0 obj
78
78
  <</Length 10>>stream
@@ -82,9 +82,27 @@ describe HexaPDF::Type::Form do
82
82
  end
83
83
 
84
84
  describe "canvas" do
85
+ # Asserts that the form's contents contains the operators.
86
+ def assert_operators(form, operators)
87
+ processor = TestHelper::OperatorRecorder.new
88
+ form.process_contents(processor)
89
+ assert_equal(operators, processor.recorded_ops)
90
+ end
91
+
85
92
  it "always returns the same Canvas instance" do
93
+ @form[:BBox] = [0, 0, 100, 100]
86
94
  canvas = @form.canvas
87
95
  assert_same(canvas, @form.canvas)
96
+ assert_operators(@form, [])
97
+ end
98
+
99
+ it "always moves the origin to the bottom left corner of the bounding box" do
100
+ @form[:BBox] = [-10, -5, 100, 300]
101
+ @form.canvas.line_width = 5
102
+ assert_operators(@form, [[:save_graphics_state],
103
+ [:concatenate_matrix, [1, 0, 0, 1, -10, -5]],
104
+ [:set_line_width, [5]],
105
+ [:restore_graphics_state]])
88
106
  end
89
107
 
90
108
  it "fails if the form XObject already has data" do
@@ -331,31 +331,36 @@ describe HexaPDF::Type::Page do
331
331
  @page.canvas(type: :overlay).line_width = 5
332
332
  assert_operators(@page, [[:save_graphics_state], [:restore_graphics_state],
333
333
  [:save_graphics_state], [:set_line_width, [10]],
334
- [:restore_graphics_state], [:set_line_width, [5]]])
334
+ [:restore_graphics_state], [:save_graphics_state],
335
+ [:set_line_width, [5]], [:restore_graphics_state]])
335
336
 
336
337
  @page.canvas(type: :underlay).line_width = 2
337
338
  assert_operators(@page, [[:save_graphics_state], [:set_line_width, [2]],
338
339
  [:restore_graphics_state], [:save_graphics_state],
339
340
  [:set_line_width, [10]],
340
- [:restore_graphics_state], [:set_line_width, [5]]])
341
+ [:restore_graphics_state], [:save_graphics_state],
342
+ [:set_line_width, [5]], [:restore_graphics_state]])
341
343
  end
342
344
 
343
345
  it "works correctly if invoked on an empty page, using type :underlay in first invocation" do
344
346
  @page.canvas(type: :underlay).line_width = 2
345
347
  assert_operators(@page, [[:save_graphics_state], [:set_line_width, [2]],
348
+ [:restore_graphics_state], [:save_graphics_state],
346
349
  [:restore_graphics_state], [:save_graphics_state],
347
350
  [:restore_graphics_state]])
348
351
 
349
352
  @page.canvas.line_width = 10
350
353
  assert_operators(@page, [[:save_graphics_state], [:set_line_width, [2]],
351
354
  [:restore_graphics_state], [:save_graphics_state],
352
- [:set_line_width, [10]], [:restore_graphics_state]])
355
+ [:set_line_width, [10]], [:restore_graphics_state],
356
+ [:save_graphics_state], [:restore_graphics_state]])
353
357
 
354
358
  @page.canvas(type: :overlay).line_width = 5
355
359
  assert_operators(@page, [[:save_graphics_state], [:set_line_width, [2]],
356
360
  [:restore_graphics_state], [:save_graphics_state],
357
361
  [:set_line_width, [10]],
358
- [:restore_graphics_state], [:set_line_width, [5]]])
362
+ [:restore_graphics_state], [:save_graphics_state],
363
+ [:set_line_width, [5]], [:restore_graphics_state]])
359
364
  end
360
365
 
361
366
  it "works correctly if invoked on a page with existing contents" do
@@ -364,13 +369,39 @@ describe HexaPDF::Type::Page do
364
369
  @page.canvas(type: :overlay).line_width = 5
365
370
  assert_operators(@page, [[:save_graphics_state], [:restore_graphics_state],
366
371
  [:save_graphics_state], [:set_line_width, [10]],
367
- [:restore_graphics_state], [:set_line_width, [5]]])
372
+ [:restore_graphics_state],
373
+ [:save_graphics_state], [:set_line_width, [5]],
374
+ [:restore_graphics_state]])
368
375
 
369
376
  @page.canvas(type: :underlay).line_width = 2
370
377
  assert_operators(@page, [[:save_graphics_state], [:set_line_width, [2]],
371
378
  [:restore_graphics_state], [:save_graphics_state],
372
379
  [:set_line_width, [10]],
373
- [:restore_graphics_state], [:set_line_width, [5]]])
380
+ [:restore_graphics_state],
381
+ [:save_graphics_state], [:set_line_width, [5]],
382
+ [:restore_graphics_state]])
383
+ end
384
+
385
+ it "works correctly if the page has its origin not at (0,0)" do
386
+ @page.box(:media, [-10, -5, 100, 300])
387
+ @page.canvas(type: :underlay).line_width = 2
388
+ @page.canvas(type: :page).line_width = 2
389
+ @page.canvas(type: :overlay).line_width = 2
390
+
391
+ assert_operators(@page, [[:save_graphics_state],
392
+ [:concatenate_matrix, [1, 0, 0, 1, -10, -5]],
393
+ [:set_line_width, [2]],
394
+ [:restore_graphics_state],
395
+
396
+ [:save_graphics_state],
397
+ [:concatenate_matrix, [1, 0, 0, 1, -10, -5]],
398
+ [:set_line_width, [2]],
399
+ [:restore_graphics_state],
400
+
401
+ [:save_graphics_state],
402
+ [:concatenate_matrix, [1, 0, 0, 1, -10, -5]],
403
+ [:set_line_width, [2]],
404
+ [:restore_graphics_state]])
374
405
  end
375
406
 
376
407
  it "fails if the page canvas is requested for a page with existing contents" do
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.12.1
4
+ version: 0.12.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Leitner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-16 00:00:00.000000000 Z
11
+ date: 2020-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cmdparse
@@ -653,7 +653,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
653
653
  - !ruby/object:Gem::Version
654
654
  version: '0'
655
655
  requirements: []
656
- rubygems_version: 3.1.2
656
+ rubyforge_project:
657
+ rubygems_version: 2.7.6.2
657
658
  signing_key:
658
659
  specification_version: 4
659
660
  summary: HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby