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 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
# frozen_string_literal: true
require 'spec_helper'
require 'stringio'
require 'ttfunk/subset'
describe 'subsetting' do # rubocop: disable RSpec/DescribeClass
let(:space_char) { TTFunk::Subset::Unicode::SPACE_CHAR }
it 'consistently names font for same subsets' do
font = TTFunk::File.open(test_font('DejaVuSans'))
subset1 = TTFunk::Subset.for(font, :unicode)
subset1.use(97)
name1 = TTFunk::File.new(subset1.encode).name.strings[6]
subset2 = TTFunk::Subset.for(font, :unicode)
subset2.use(97)
name2 = TTFunk::File.new(subset2.encode).name.strings[6]
expect(name1).to eq name2
end
it 'can reconstruct an entire font' do
font = TTFunk::File.open(test_font('DejaVuSans'))
subset = TTFunk::Subset.for(font, :unicode)
font.cmap.unicode.first.code_map.each_key do |code_point|
subset.use(code_point)
end
expect { subset.encode }.to_not raise_error
end
it 'always includes the space glyph' do
font = TTFunk::File.open(test_font('DejaVuSans'))
subset = TTFunk::Subset.for(font, :unicode)
new_font = TTFunk::File.new(subset.encode)
# space should be GID 1 since it's the only glyph in the font
# (0 is always .notdef)
expect(new_font.cmap.unicode.first[space_char]).to eq(1)
end
it "explodes if the space glyph isn't included" do
font = TTFunk::File.open(test_font('DejaVuSans'))
subset = TTFunk::Subset.for(font, :unicode)
subset.instance_variable_get(:@subset).delete(space_char)
expect { subset.encode }.to raise_error(/Space glyph .* must be included/)
end
it 'changes font names for different subsets' do
font = TTFunk::File.open(test_font('DejaVuSans'))
subset1 = TTFunk::Subset.for(font, :unicode)
subset1.use(97)
name1 = TTFunk::File.new(subset1.encode).name.strings[6]
subset2 = TTFunk::Subset.for(font, :unicode)
subset2.use(97)
subset2.use(98)
name2 = TTFunk::File.new(subset2.encode).name.strings[6]
expect(name1).to_not eq name2
end
it 'calculates checksum correctly for empty table data' do
font = TTFunk::File.open(test_font('Mplus1p'))
subset1 = TTFunk::Subset.for(font, :unicode)
expect { subset1.encode }.to_not raise_error
end
it 'generates font directory with tables in ascending order' do
font = TTFunk::File.open(test_font('DejaVuSans'))
subset = TTFunk::Subset.for(font, :unicode)
subset.use(97)
directory = TTFunk::File.new(subset.encode).directory
table_tags = directory.tables.keys
expect(table_tags.sort).to eq(table_tags)
expect(table_tags.first).to be < table_tags.last
end
it 'calculates search_range, entry_selector & range_shift values' do
font = TTFunk::File.open(test_font('DejaVuSans'))
subset = TTFunk::Subset.for(font, :unicode)
subset.use(97)
subset_io = StringIO.new(subset.encode)
scaler_type, table_count = subset_io.read(6).unpack('Nn')
search_range, entry_selector, range_shift =
subset_io.read(6).unpack('nnn')
# Subset fonts include 14 tables by default.
expected_table_count = 14
# Smallest power of two less than number of tables, times 16.
expected_search_range = 8 * 16
# Log2 of max power of two smaller than number of tables.
expected_entry_selector = 3
# Range shift is defined as 16*table_count - search_range.
expected_range_shift = (16 * expected_table_count) - expected_search_range
expect(scaler_type).to eq(font.directory.scaler_type)
expect(table_count).to eq(expected_table_count)
expect(search_range).to eq(expected_search_range)
expect(entry_selector).to eq(expected_entry_selector)
expect(range_shift).to eq(expected_range_shift)
end
it 'knows which characters it includes' do
font = TTFunk::File.open(test_font('DejaVuSans'))
unicode = TTFunk::Subset.for(font, :unicode)
unicode_8bit = TTFunk::Subset.for(font, :unicode_8bit)
mac_roman = TTFunk::Subset.for(font, :mac_roman)
windows1252 = TTFunk::Subset.for(font, :windows_1252) # rubocop: disable Naming/VariableNumber
[unicode, unicode_8bit, mac_roman, windows1252].each do |subset|
expect(subset).to_not be_includes(97)
subset.use(97)
expect(subset).to be_includes(97)
end
end
it 'maps final code 0xFFFF to glyph 0 in generated type 4 cmap' do
font = TTFunk::File.open(test_font('DejaVuSans'))
subset = TTFunk::Subset.for(font, :unicode)
subset.use(97)
cmap = TTFunk::File.new(subset.encode).cmap
# Unicode subsets only contain a single format 4 cmap subtable.
expect(cmap.tables.size).to eq(1)
format04 = cmap.tables.first
expect(format04.format).to eq(4)
expect(format04.code_map[0xFFFF]).to eq(0)
end
it 'sorts records in the name table correctly' do
font = TTFunk::File.open(test_font('DejaVuSans'))
subset = TTFunk::Subset.for(font, :unicode)
subset.use(97)
name = TTFunk::File.new(subset.encode).name
records = []
name.entries.each do |entry|
records << [
entry[:platform_id],
entry[:encoding_id],
entry[:language_id],
entry[:name_id],
]
end
expect(records).to eq(records.sort)
end
end
|