From 8895738454a3f0789f0979663360fd69ae05da49 Mon Sep 17 00:00:00 2001 From: Thomas Leitner Date: Tue, 5 Nov 2024 10:03:12 +0100 Subject: [PATCH] Fix performance regression when encoding char codes for TrueType fonts The recent change for supporting multiple codepoint referencing the same glyph lead to a performance regression because the char codes 13, 40, 41 and 92 were used again. --- CHANGELOG.md | 1 + lib/hexapdf/font/true_type_wrapper.rb | 5 +++++ test/hexapdf/font/test_true_type_wrapper.rb | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ca9f152..2b884e4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Checksum calculation for TrueType tables * Automatic wrapping of dictionary entry /CIDToGIDMap for CID fonts +* Performance regression when encoding char codes for TrueType fonts ## 1.0.1 - 2024-11-04 diff --git a/lib/hexapdf/font/true_type_wrapper.rb b/lib/hexapdf/font/true_type_wrapper.rb index df0cfeab..7b73bee1 100644 --- a/lib/hexapdf/font/true_type_wrapper.rb +++ b/lib/hexapdf/font/true_type_wrapper.rb @@ -239,6 +239,11 @@ def encode(glyph) raise HexaPDF::MissingGlyphError.new(glyph) if glyph.kind_of?(InvalidGlyph) @subsetter.use_glyph(glyph.id) if @subsetter @last_char_code += 1 + # Handle codes for ASCII characters \r (13), (, ) (40, 41) and \ (92) specially so that + # they never appear in the output (PDF serialization would need to escape them) + if @last_char_code == 13 || @last_char_code == 40 || @last_char_code == 92 + @last_char_code += (@last_char_code == 40 ? 2 : 1) + end [[@last_char_code].pack('n'), @last_char_code] end)[0] end diff --git a/test/hexapdf/font/test_true_type_wrapper.rb b/test/hexapdf/font/test_true_type_wrapper.rb index 60de396e..9d19904f 100644 --- a/test/hexapdf/font/test_true_type_wrapper.rb +++ b/test/hexapdf/font/test_true_type_wrapper.rb @@ -119,6 +119,11 @@ assert_equal([3].pack('n'), code) end + it "doesn't use char codes 13, 40, 41 and 92 because they would need to be escaped" do + codes = 1.upto(93).map {|i| @font_wrapper.encode(@font_wrapper.glyph(i)) }.join + assert_equal([1..12, 14..39, 42..91, 93..97].flat_map(&:to_a).pack('n*'), codes) + end + it "raises an error if an InvalidGlyph is encoded" do exp = assert_raises(HexaPDF::MissingGlyphError) do @font_wrapper.encode(@font_wrapper.decode_utf8("รถ").first)