Class: Fontisan::Variation::DeltaParser
- Inherits:
-
Object
- Object
- Fontisan::Variation::DeltaParser
- Defined in:
- lib/fontisan/variation/delta_parser.rb
Overview
Parses variation deltas from gvar tuple data
The gvar table stores deltas in various compression formats to minimize file size. This parser handles all delta formats and decompresses them into usable point delta arrays.
Delta Formats:
- DELTAS_ARE_ZERO: All deltas are zero (no data stored)
- DELTAS_ARE_WORDS: Deltas stored as signed 16-bit words
- DELTAS_ARE_BYTES: Deltas stored as signed 8-bit bytes
- Point number runs: Compressed sequences of affected points
Reference: OpenType specification, gvar table delta encoding
Constant Summary collapse
- DELTAS_ARE_ZERO =
Delta format flags (from tuple variation header flags)
0x80- DELTAS_ARE_WORDS =
0x40- POINTS_ARE_WORDS =
Point number flags
0x80- POINT_RUN_COUNT_MASK =
0x7F
Instance Method Summary collapse
-
#parse(data, point_count, private_points: false, shared_points: nil) ⇒ Array<Hash>
Parse delta data from tuple variation.
-
#parse_with_flags(data, point_count, flags) ⇒ Array<Hash>
Parse delta data with explicit format flag.
Instance Method Details
#parse(data, point_count, private_points: false, shared_points: nil) ⇒ Array<Hash>
Parse delta data from tuple variation
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 |
# File 'lib/fontisan/variation/delta_parser.rb', line 42 def parse(data, point_count, private_points: false, shared_points: nil) return zero_deltas(point_count) if data.nil? || data.empty? io = StringIO.new(data) io.set_encoding(Encoding::BINARY) # Parse point numbers if present points = if private_points parse_point_numbers(io) elsif shared_points shared_points else # All points affected (0...point_count).to_a end # Determine delta format from first byte (if present) format_byte = io.getbyte return zero_deltas(point_count) if format_byte.nil? io.pos -= 1 # Put byte back # Parse X deltas x_deltas = parse_delta_array(io, points.length) # Parse Y deltas y_deltas = parse_delta_array(io, points.length) # Build full delta array (zero for untouched points) build_full_deltas(points, x_deltas, y_deltas, point_count) rescue StandardError => e raise VariationDataCorruptedError.new( message: "Failed to parse delta data: #{e.}", details: { point_count: point_count, private_points: private_points, error_class: e.class.name, }, ) end |
#parse_with_flags(data, point_count, flags) ⇒ Array<Hash>
Parse delta data with explicit format flag
89 90 91 92 93 94 95 |
# File 'lib/fontisan/variation/delta_parser.rb', line 89 def parse_with_flags(data, point_count, flags) if (flags & DELTAS_ARE_ZERO).zero? parse(data, point_count) else zero_deltas(point_count) end end |