File: dict_spec.rb

package info (click to toggle)
ruby-ttfunk 1.8.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 18,472 kB
  • sloc: ruby: 7,954; makefile: 7
file content (109 lines) | stat: -rw-r--r-- 3,406 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# frozen_string_literal: true

require 'spec_helper'
require 'ttfunk/table/cff/dict'

RSpec.describe TTFunk::Table::Cff::Dict do
  test_cases = {
    # negative 1-byte int, positive 1-byte int, operator 5
    [0x6B, 0xF0, 0x05] => { 5 => [-32, 101] },

    # positive 2-byte ints, operator 6
    [0xF7, 0x02, 0xF8, 0x7B, 0xFA, 0x94, 0x06] => { 6 => [110, 487, 1024] },

    # negative 2-byte ints, operator 7
    [0xFB, 0x02, 0xFC, 0x7B, 0xFE, 0x94, 0x07] => { 7 => [-110, -487, -1024] },

    # negative 3-byte int, positive 3-byte int, operator 8
    [0x1C, 0x84, 0xB8, 0x1C, 0x76, 0x15, 0x08] => { 8 => [-31_560, 30_229] },

    # negative 4-byte int, positive 4-byte int, operator 9
    [0x1D, 0xBC, 0x92, 0x6A, 0xE8, 0x1D, 0x55, 0x4F, 0x3A, 0xD4, 0x09] => {
      9 => [-1_131_255_064, 1_431_255_764],
    },

    # negative float with no exponent, operator 10
    [0x1E, 0xE2, 0xA2, 0x5F, 0x0A] => { 10 => [-2.25] },

    # positive float with no exponent, operator 10
    [0x1E, 0x2A, 0x25, 0xFF, 0x0A] => { 10 => [2.25] },

    # positive float with negative exponent, operator 11
    [0x1E, 0x0A, 0x14, 0x05, 0x41, 0xC3, 0xFF, 0x0B] => {
      11 => [TTFunk::SciForm.new(0.140541, -3)],
    },

    # positive float with positive exponent, operator 11
    [0x1E, 0x0A, 0x14, 0x05, 0x41, 0xB3, 0xFF, 0x0B] => {
      11 => [TTFunk::SciForm.new(0.140541, 3)],
    },

    # Float with a missing exponent, operator 1
    [0x1E, 0x0A, 0x1F, 0x01] => { 1 => [TTFunk::SciForm.new(0.1, 0)] },
  }

  test_cases.each_with_index do |(bytes, decoded_values), idx|
    context "with example #{idx}" do
      subject(:dict) do
        io = StringIO.new(bytes.pack('C*'))
        described_class.new(TestFile.new(io), 0, bytes.length)
      end

      it 'parses correctly' do
        decoded_values.each do |operand, operators|
          expect(dict[operand]).to eq(operators)
        end
      end

      it 'encodes correctly' do
        expect(dict.encode.bytes).to eq(bytes)
      end
    end
  end

  it 'raises an error if an invalid operand is supplied' do
    # this is the invalid sci form operand "0." followed by the operator 5
    data = [0x1E, 0x0A, 0xFF, 0x05]
    file = TestFile.new(StringIO.new(data.pack('C*')))

    expect { described_class.new(file, 0, data.length) }.to raise_error(described_class::InvalidOperandError)
  end

  it 'raises an error if too many operands are supplied' do
    data = [0x6B] * (described_class::MAX_OPERANDS + 1)
    data << 0x05 # operator
    file = TestFile.new(StringIO.new(data.pack('C*')))

    expect { described_class.new(file, 0, data.length) }.to raise_error(described_class::TooManyOperandsError)
  end

  it 'allows addition of entries' do
    dict = described_class.new(TestFile.new(StringIO.new('')), 0, 0)

    dict[1] = 42
    dict[1201] = [43, 44]

    expect(dict.encode).to eq("\xB5\x01\xb6\xb7\x0c\x01".b)
  end

  it 'allows replacement of entries' do
    dict = described_class.new(TestFile.new(StringIO.new("\xB5\x01\xb6\xb7\x0c\x01".b)), 0, 6)

    dict[1] = 0

    expect(dict.encode).to eq("\x8b\x01\xb6\xb7\x0c\x01".b)
  end

  it 'uses a stable encoding order' do
    dict1 = described_class.new(TestFile.new(StringIO.new('')), 0, 0)
    dict2 = described_class.new(TestFile.new(StringIO.new('')), 0, 0)

    dict1[1] = 1
    dict1[2] = 2

    dict2[2] = 2
    dict2[1] = 1

    expect(dict1.encode).to eq(dict2.encode)
  end
end