hexapdf 0.12.1 → 0.12.2

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