Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "Fix maxp table" #104

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 16 additions & 140 deletions lib/ttfunk/table/maxp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,151 +76,27 @@ class Maxp < Table
# @return [Integer]
attr_reader :max_component_depth

class << self
# Encode table.
#
# @param maxp [TTFunk::Table::Maxp]
# @param new2old_glyph [Hash{Integer => Integer}] keys are new glyph IDs, values
# are old glyph IDs.
# @return [String]
def encode(maxp, new2old_glyph)
''.b.tap do |table|
num_glyphs = new2old_glyph.length
table << [maxp.version, num_glyphs].pack('Nn')

if maxp.version == 0x10000
stats = stats_for(maxp, glyphs_from_ids(maxp, new2old_glyph.values))

table << [
stats[:max_points],
stats[:max_contours],
stats[:max_component_points],
stats[:max_component_contours],
# these all come from the fpgm and cvt tables, which
# we don't support at the moment
maxp.max_zones,
maxp.max_twilight_points,
maxp.max_storage,
maxp.max_function_defs,
maxp.max_instruction_defs,
maxp.max_stack_elements,
stats[:max_size_of_instructions],
stats[:max_component_elements],
stats[:max_component_depth],
].pack('n*')
end
end
end

private

def glyphs_from_ids(maxp, glyph_ids)
glyph_ids.each_with_object([]) do |glyph_id, ret|
if (glyph = maxp.file.glyph_outlines.for(glyph_id))
ret << glyph
end
end
end

def stats_for(maxp, glyphs)
stats_for_simple(maxp, glyphs)
.merge(stats_for_compound(maxp, glyphs))
.transform_values { |agg| agg.value_or(0) }
end

def stats_for_simple(_maxp, glyphs)
max_component_elements = Max.new
max_points = Max.new
max_contours = Max.new
max_size_of_instructions = Max.new

glyphs.each do |glyph|
if glyph.compound?
max_component_elements << glyph.glyph_ids.size
else
max_points << glyph.end_point_of_last_contour
max_contours << glyph.number_of_contours
max_size_of_instructions << glyph.instruction_length
end
end

{
max_component_elements: max_component_elements,
max_points: max_points,
max_contours: max_contours,
max_size_of_instructions: max_size_of_instructions,
}
end

def stats_for_compound(maxp, glyphs)
max_component_points = Max.new
max_component_depth = Max.new
max_component_contours = Max.new

glyphs.each do |glyph|
next unless glyph.compound?

stats = totals_for_compound(maxp, [glyph], 0)
max_component_points << stats[:total_points]
max_component_depth << stats[:max_depth]
max_component_contours << stats[:total_contours]
end

{
max_component_points: max_component_points,
max_component_depth: max_component_depth,
max_component_contours: max_component_contours,
}
end

def totals_for_compound(maxp, glyphs, depth)
total_points = Sum.new
total_contours = Sum.new
max_depth = Max.new(depth)

glyphs.each do |glyph|
if glyph.compound?
stats = totals_for_compound(maxp, glyphs_from_ids(maxp, glyph.glyph_ids), depth + 1)

total_points << stats[:total_points]
total_contours << stats[:total_contours]
max_depth << stats[:max_depth]
else
stats = stats_for_simple(maxp, [glyph])
total_points << stats[:max_points]
total_contours << stats[:max_contours]
end
end

{
total_points: total_points,
total_contours: total_contours,
max_depth: max_depth,
}
end
# Encode table.
#
# @param maxp [TTFunk::Table::Maxp]
# @param mapping [Hash{Integer => Integer}] keys are new glyph IDs, values
# are old glyph IDs.
# @return [String]
def self.encode(maxp, mapping)
num_glyphs = mapping.length
raw = maxp.raw
raw[4, 2] = [num_glyphs].pack('n')
raw
end

private

def parse!
@version, @num_glyphs = read(6, 'Nn')

if @version == 0x10000
@max_points, @max_contours, @max_component_points,
@max_component_contours, @max_zones, @max_twilight_points,
@max_storage, @max_function_defs, @max_instruction_defs,
@max_stack_elements, @max_size_of_instructions,
@max_component_elements = read(24, 'n*')

# a number of fonts omit these last two bytes for some reason,
# so we have to supply a default here to prevent nils
@max_component_depth =
if length == MAX_V1_TABLE_LENGTH
read(2, 'n').first
else
DEFAULT_MAX_COMPONENT_DEPTH
end
end
@version, @num_glyphs, @max_points, @max_contours,
@max_component_points, @max_component_contours, @max_zones,
@max_twilight_points, @max_storage, @max_function_defs,
@max_instruction_defs, @max_stack_elements, @max_size_of_instructions,
@max_component_elements, @max_component_depth = read(length, 'Nn*')
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/ttfunk/ttf_encoder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@

# verified via the Font-Validator tool at:
# https://github.com/HinTak/Font-Validator
expect(checksum).to eq(0xEEAE9DCF)
expect(checksum).to eq(0xEE3A9625)
end
end
end