Class: Fontisan::Collection::TableDeduplicator
- Inherits:
-
Object
- Object
- Fontisan::Collection::TableDeduplicator
- Defined in:
- lib/fontisan/collection/table_deduplicator.rb
Overview
TableDeduplicator deduplicates identical tables across fonts
Single responsibility: Group identical tables and create a canonical mapping for shared table references. Ensures that each unique table content is stored only once in the collection.
Constant Summary collapse
- VARIATION_SHAREABLE_TABLES =
Tables that can be shared in variable font collections if identical
%w[fvar avar STAT HVAR VVAR MVAR].freeze
- VARIATION_FONT_SPECIFIC_TABLES =
Tables that must remain font-specific in variable fonts
%w[gvar CFF2].freeze
Instance Attribute Summary collapse
-
#canonical_tables ⇒ Hash<String, Hash>
readonly
Canonical tables (unique table data).
-
#sharing_map ⇒ Hash<Integer, Hash<String, Hash>>
readonly
Sharing map (font -> table -> canonical reference).
Instance Method Summary collapse
-
#build_sharing_map ⇒ Hash<Integer, Hash<String, Hash>>
Build sharing map for all fonts.
-
#canonical_table_data(tag, canonical_id) ⇒ String?
Get canonical table data for a specific table.
-
#canonical_tables_for_tag(tag) ⇒ Hash<String, Hash>?
Get all canonical tables for a specific tag.
-
#initialize(fonts) ⇒ TableDeduplicator
constructor
Initialize deduplicator with fonts.
-
#statistics ⇒ Hash
Get sharing statistics.
Constructor Details
#initialize(fonts) ⇒ TableDeduplicator
Initialize deduplicator with fonts
36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/fontisan/collection/table_deduplicator.rb', line 36 def initialize(fonts) if fonts.nil? || fonts.empty? raise ArgumentError, "fonts cannot be nil or empty" end raise ArgumentError, "fonts must be an array" unless fonts.is_a?(Array) @fonts = fonts @canonical_tables = {} @sharing_map = {} @checksum_to_canonical = {} end |
Instance Attribute Details
#canonical_tables ⇒ Hash<String, Hash> (readonly)
Canonical tables (unique table data)
26 27 28 |
# File 'lib/fontisan/collection/table_deduplicator.rb', line 26 def canonical_tables @canonical_tables end |
#sharing_map ⇒ Hash<Integer, Hash<String, Hash>> (readonly)
Sharing map (font -> table -> canonical reference)
30 31 32 |
# File 'lib/fontisan/collection/table_deduplicator.rb', line 30 def sharing_map @sharing_map end |
Instance Method Details
#build_sharing_map ⇒ Hash<Integer, Hash<String, Hash>>
Build sharing map for all fonts
Creates a map structure that indicates which canonical table each font should reference for each table tag. This enables efficient table sharing in the final collection.
67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/fontisan/collection/table_deduplicator.rb', line 67 def build_sharing_map # First pass: collect all unique tables collect_canonical_tables # Handle variable font table deduplication deduplicate_variation_tables if has_variable_fonts? # Second pass: build sharing map for each font build_font_sharing_references @sharing_map end |
#canonical_table_data(tag, canonical_id) ⇒ String?
Get canonical table data for a specific table
85 86 87 |
# File 'lib/fontisan/collection/table_deduplicator.rb', line 85 def canonical_table_data(tag, canonical_id) @canonical_tables.dig(tag, canonical_id, :data) end |
#canonical_tables_for_tag(tag) ⇒ Hash<String, Hash>?
Get all canonical tables for a specific tag
93 94 95 |
# File 'lib/fontisan/collection/table_deduplicator.rb', line 93 def canonical_tables_for_tag(tag) @canonical_tables[tag] end |
#statistics ⇒ Hash
Get sharing statistics
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/fontisan/collection/table_deduplicator.rb', line 100 def statistics total_tables = 0 shared_tables = 0 unique_tables = 0 @sharing_map.each_value do |tables| tables.each_value do |info| total_tables += 1 if info[:shared] shared_tables += 1 else unique_tables += 1 end end end { total_tables: total_tables, shared_tables: shared_tables, unique_tables: unique_tables, sharing_percentage: total_tables.positive? ? (shared_tables.to_f / total_tables * 100).round(2) : 0.0, canonical_count: @canonical_tables.values.sum(&:size), } end |