hexapdf 0.11.4 → 0.11.5

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: '0907516ec3eaf3e982a0380bab72ea8923ea18ed3213b426061572913c2c426e'
4
- data.tar.gz: 6541fdd61bfc2000a3bd77e8aa8ebf046e14c56a87d856bace5f89c586042f42
3
+ metadata.gz: 245de775fa069ad91f2fe9f5e72610df40211e8b15a92b376cdf217c63b877fe
4
+ data.tar.gz: 34891827479def7d0efd506c9cd62f10abced99b8e694e39bc0dd06b1fa88bfe
5
5
  SHA512:
6
- metadata.gz: 76a46bb08612f035c0e1159c1644797ecb949933ea73451d4f2e3bb128f5db3fd240bb759ec750ab42469c378b3fc36ec8ff466a6c39682a166b606dca5e7ca1
7
- data.tar.gz: 1368b225b5d638c8cfc36057d983126746df3333e73f2b88d50238c51bdef095de275b9c872653b5c78a3009dbf60d71a7cd0ae7f9e231e6966c590e831de834
6
+ metadata.gz: 0c8bedff161a8aa756d6ffc426c89554e82537198692250a78f0eaad36fa896767681bda681d43bdcd5237f3eba91d25679499bbbe56ff525a16813c06187636
7
+ data.tar.gz: 35f82390333d2110c7ccb3059c93914e7ab03bbcd986c0ca7da1d3425c5a2c619aa42513da15d218423917e01f696b7b4e156f00b1997007c9feb637ae921d20
@@ -1,3 +1,20 @@
1
+ ## 0.11.5 - 2020-01-27
2
+
3
+ ### Changed
4
+
5
+ * [HexaPDF::Font::TrueType::Table::CmapSubtable] to lazily parse the subtable
6
+ * [HexaPDF::Font::TrueType::Table::Hmtx] to lazily parse the width data
7
+ * CLI command `hexapdf image2pdf` to use the last argument as output file
8
+ instead of the first (same order as `merge`)
9
+ * Automatically require the HexaPDF C extension if it is installed
10
+
11
+ ### Fixed
12
+
13
+ * Wrong line length calculation for variable width layouting when a text box is
14
+ too wide and needs to be broken into parts
15
+ * CLI command `hexapdf image2pdf` so that treating a PDF as image works
16
+
17
+
1
18
  ## 0.11.4 - 2019-12-28
2
19
 
3
20
  ### Fixed
@@ -1,5 +1,5 @@
1
1
  Count Name
2
2
  ======= ====
3
- 1097 Thomas Leitner <t_leitner@gmx.at>
3
+ 1104 Thomas Leitner <t_leitner@gmx.at>
4
4
  1 Stanislav (Stas) Katkov <sk@skylup.com>
5
5
  1 Daniel Kraus <bovender@bovender.de>
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.11.4
1
+ 0.11.5
@@ -99,15 +99,15 @@ module HexaPDF
99
99
  @margins = [0, 0, 0, 0]
100
100
  end
101
101
 
102
- def execute(out_file, *images) #:nodoc:
102
+ def execute(*images, out_file) #:nodoc:
103
103
  maybe_raise_on_existing_file(out_file)
104
104
 
105
105
  out = HexaPDF::Document.new
106
106
 
107
107
  images.each do |image_file|
108
108
  image = out.images.add(image_file)
109
- iw = image.info.width.to_f
110
- ih = image.info.height.to_f
109
+ iw = image.width.to_f
110
+ ih = image.height.to_f
111
111
  if @scale != :fit
112
112
  iw *= 72 / @scale
113
113
  ih *= 72 / @scale
@@ -52,6 +52,11 @@ require 'hexapdf/image_loader'
52
52
  require 'hexapdf/font_loader'
53
53
  require 'hexapdf/layout'
54
54
 
55
+ begin
56
+ require 'hexapdf/cext'
57
+ rescue LoadError
58
+ end
59
+
55
60
  # == HexaPDF API Documentation
56
61
  #
57
62
  # Here are some pointers to more in depth information:
@@ -73,9 +73,14 @@ module HexaPDF
73
73
  attr_accessor :language
74
74
 
75
75
  # The complete code map.
76
+ #
77
+ # Is only fully initialized for existing fonts when a mapping is first accessed via #[].
76
78
  attr_accessor :code_map
77
79
 
78
80
  # The complete gid map.
81
+ #
82
+ # Is only fully initialized for existing fonts when a mapping is first accessed via
83
+ # #gid_to_code.
79
84
  attr_accessor :gid_map
80
85
 
81
86
  # Creates a new subtable.
@@ -127,7 +132,22 @@ module HexaPDF
127
132
  elsif [0, 2, 4, 6].include?(@format)
128
133
  length, @language = io.read(4).unpack('n2')
129
134
  end
130
- supported = true
135
+
136
+ return false unless [0, 2, 4, 6, 10, 12].include?(@format)
137
+ offset = io.pos
138
+ @code_map = lambda do |code|
139
+ parse_mapping(io, offset, length)
140
+ @code_map[code]
141
+ end
142
+ @gid_map = lambda do |gid|
143
+ parse_mapping(io, offset, length)
144
+ @gid_map[gid]
145
+ end
146
+ true
147
+ end
148
+
149
+ def parse_mapping(io, offset, length)
150
+ io.pos = offset
131
151
  @code_map, @gid_map = case @format
132
152
  when 0 then Format0.parse(io, length)
133
153
  when 2 then Format2.parse(io, length)
@@ -135,12 +155,9 @@ module HexaPDF
135
155
  when 6 then Format6.parse(io, length)
136
156
  when 10 then Format10.parse(io, length)
137
157
  when 12 then Format12.parse(io, length)
138
- else
139
- supported = false
140
- [{}, {}]
141
158
  end
142
- supported
143
159
  end
160
+ private :parse_mapping
144
161
 
145
162
  def inspect #:nodoc:
146
163
  "#<#{self.class.name} (#{platform_id}, #{encoding_id}, #{language}, " \
@@ -51,7 +51,7 @@ module HexaPDF
51
51
  # the :left_side_bearing.
52
52
  Metric = Struct.new(:advance_width, :left_side_bearing)
53
53
 
54
- # An array of Metric objects, one for each glyph in the font.
54
+ # A hash of glyph ID to Metric objects mapping.
55
55
  attr_accessor :horizontal_metrics
56
56
 
57
57
  # Returns the Metric object for the give glyph ID.
@@ -63,10 +63,20 @@ module HexaPDF
63
63
 
64
64
  def parse_table #:nodoc:
65
65
  nr_entries = font[:hhea].num_of_long_hor_metrics
66
- @horizontal_metrics = Array.new(nr_entries) { Metric.new(*read_formatted(4, 'ns>')) }
67
- last_advance_width = @horizontal_metrics[-1].advance_width
68
- read_formatted(directory_entry.length - 4 * nr_entries, 's>*').map do |lsb|
69
- @horizontal_metrics << Metric.new(last_advance_width, lsb)
66
+ max_id = nr_entries + (directory_entry.length - 4 * nr_entries) / 2
67
+ @horizontal_metrics = Hash.new do |hash, glyph_id|
68
+ return nil if glyph_id >= max_id
69
+ if glyph_id >= nr_entries
70
+ with_io_pos(directory_entry.offset + 4 * nr_entries + (glyph_id - nr_entries) * 2) do
71
+ hash[glyph_id] = Metric.new(@horizontal_metrics[nr_entries - 1].advance_width,
72
+ *read_formatted(2, 's>'))
73
+ end
74
+ else
75
+ with_io_pos(directory_entry.offset + 4 * glyph_id) do
76
+ hash[glyph_id] = Metric.new(*read_formatted(4, 'ns>'))
77
+ end
78
+ end
79
+ hash[glyph_id]
70
80
  end
71
81
  end
72
82
 
@@ -751,6 +751,7 @@ module HexaPDF
751
751
 
752
752
  while true
753
753
  too_wide_box = nil
754
+ line_height = 0
754
755
 
755
756
  rest = style.text_line_wrapping_algorithm.call(rest, width_block) do |line, item|
756
757
  # make sure empty lines broken by mandatory paragraph breaks are not empty
@@ -37,6 +37,6 @@
37
37
  module HexaPDF
38
38
 
39
39
  # The version of HexaPDF.
40
- VERSION = '0.11.4'
40
+ VERSION = '0.11.5'
41
41
 
42
42
  end
@@ -43,14 +43,14 @@ describe HexaPDF::Font::TrueType::Table::CmapSubtable do
43
43
 
44
44
  it "works for format 0" do
45
45
  t = table([0, 262, 0].pack('n3') + [255].pack('C*') + (0..254).to_a.pack('C*'))
46
+ assert_equal(0, t.gid_to_code(255))
47
+ assert_equal(234, t.gid_to_code(233))
48
+
46
49
  assert_equal(255, t[0])
47
50
  assert_equal(233, t[234])
48
51
  assert_nil(t[256])
49
52
 
50
- assert_equal(0, t.gid_to_code(255))
51
- assert_equal(234, t.gid_to_code(233))
52
-
53
- assert_raises(HexaPDF::Error) { table([0, 20, 0].pack('n3') + "a" * 20) }
53
+ assert_raises(HexaPDF::Error) { table([0, 20, 0].pack('n3') + "a" * 20)[0] }
54
54
  end
55
55
 
56
56
  it "works for format 2" do
@@ -5,7 +5,7 @@ require_relative 'common'
5
5
  require 'hexapdf/font/true_type/table/hhea'
6
6
  require 'hexapdf/font/true_type/table/hmtx'
7
7
 
8
- describe HexaPDF::Font::TrueType::Table::Hhea do
8
+ describe HexaPDF::Font::TrueType::Table::Hmtx do
9
9
  before do
10
10
  data = [1, -2, 3, -4, 5, -6].pack('ns>ns>s>2')
11
11
  set_up_stub_true_type_font(data)
@@ -17,14 +17,14 @@ describe HexaPDF::Font::TrueType::Table::Hhea do
17
17
  describe "initialize" do
18
18
  it "reads the data from the associated file" do
19
19
  table = create_table(:Hmtx)
20
- assert_equal(1, table[0].advance_width)
21
- assert_equal(-2, table[0].left_side_bearing)
22
- assert_equal(3, table[1].advance_width)
23
- assert_equal(-4, table[1].left_side_bearing)
24
20
  assert_equal(3, table[2].advance_width)
25
21
  assert_equal(5, table[2].left_side_bearing)
26
22
  assert_equal(3, table[3].advance_width)
27
23
  assert_equal(-6, table[3].left_side_bearing)
24
+ assert_equal(1, table[0].advance_width)
25
+ assert_equal(-2, table[0].left_side_bearing)
26
+ assert_equal(3, table[1].advance_width)
27
+ assert_equal(-4, table[1].left_side_bearing)
28
28
  end
29
29
  end
30
30
  end
@@ -556,18 +556,37 @@ describe HexaPDF::Layout::TextLayouter do
556
556
  end
557
557
  end
558
558
 
559
- it "breaks a text fragment into parts if it is wider than the available width" do
560
- str = " Thisisaverylongstring"
561
- frag = HexaPDF::Layout::TextFragment.create(str, font: @font)
562
- result = @layouter.fit([frag], 20, 100)
563
- assert(result.remaining_items.empty?)
564
- assert_equal(:success, result.status)
565
- assert_equal(str.strip.length, result.lines.sum {|l| l.items.sum {|i| i.items.count } })
566
- assert_equal(45, result.height)
559
+ describe "breaks a text fragment into parts if it is wider than the available width" do
560
+ before do
561
+ @str = " This is averylongstring"
562
+ @frag = HexaPDF::Layout::TextFragment.create(@str, font: @font)
563
+ end
567
564
 
568
- result = @layouter.fit([frag], 1, 100)
569
- assert_equal(str.strip.length, result.remaining_items.count)
570
- assert_equal(:box_too_wide, result.status)
565
+ it "works with fixed width" do
566
+ result = @layouter.fit([@frag], 20, 100)
567
+ assert(result.remaining_items.empty?)
568
+ assert_equal(:success, result.status)
569
+ assert_equal(@str.delete(" ").length, result.lines.sum {|l| l.items.sum {|i| i.items.count } })
570
+ assert_equal(54, result.height)
571
+
572
+ result = @layouter.fit([@frag], 1, 100)
573
+ assert_equal(8, result.remaining_items.count)
574
+ assert_equal(:box_too_wide, result.status)
575
+ end
576
+
577
+ it "works with variable width" do
578
+ width_block = lambda do |height, line_height|
579
+ # 'averylongstring' would fit when only considering height but not height + line_height
580
+ if height + line_height < 15
581
+ 63
582
+ else
583
+ 10
584
+ end
585
+ end
586
+ result = @layouter.fit([@frag], width_block, 30)
587
+ assert_equal(:height, result.status)
588
+ assert_equal([26.95, 9.44, 7.77], result.lines.map {|l| l.width.round(3) })
589
+ end
571
590
  end
572
591
 
573
592
  describe "horizontal alignment" do
@@ -40,7 +40,7 @@ describe HexaPDF::Writer do
40
40
  219
41
41
  %%EOF
42
42
  3 0 obj
43
- <</Producer(HexaPDF version 0.11.4)>>
43
+ <</Producer(HexaPDF version 0.11.5)>>
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.11.4)>>
75
+ <</Producer(HexaPDF version 0.11.5)>>
76
76
  endobj
77
77
  2 0 obj
78
78
  <</Length 10>>stream
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.11.4
4
+ version: 0.11.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Leitner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-28 00:00:00.000000000 Z
11
+ date: 2020-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cmdparse
@@ -637,7 +637,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
637
637
  - !ruby/object:Gem::Version
638
638
  version: '0'
639
639
  requirements: []
640
- rubygems_version: 3.0.3
640
+ rubygems_version: 3.1.2
641
641
  signing_key:
642
642
  specification_version: 4
643
643
  summary: HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby