Module: Fontisan::Woff2::TripletCodec
- Defined in:
- lib/fontisan/woff2/triplet_codec.rb
Overview
Variable-length coordinate codec for the WOFF2 glyf transform.
Per WOFF2 spec section 5.2, each (dx, dy, on_curve) point is encoded as one flag byte plus 1-4 payload bytes ("triplets"). The flag byte's high bit is the on-curve flag; the low 7 bits select one of 128 encoding variants. Variants are chosen by coordinate magnitude so small deltas cost 1-2 bytes and only very large deltas cost 4.
Reference: WOFF2 spec section 5.2 (triplet encoding table).
Constant Summary collapse
- ON_CURVE_BIT =
0x00- OFF_CURVE_BIT =
0x80
Class Method Summary collapse
-
.decode(flag, payload) ⇒ Array(Integer, Integer, Boolean)
Decode one triplet given the flag byte and a cursor over payload bytes.
-
.encode(dx, dy, on_curve:) ⇒ Array(Integer, Array<Integer>)
Encode a single (dx, dy) delta with the given on-curve flag.
Class Method Details
.decode(flag, payload) ⇒ Array(Integer, Integer, Boolean)
Decode one triplet given the flag byte and a cursor over payload bytes.
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/fontisan/woff2/triplet_codec.rb', line 52 def self.decode(flag, payload) on_curve = (flag & OFF_CURVE_BIT).zero? idx = flag & 0x7F dx, dy = if idx < 10 decode_y_only(idx, payload) elsif idx < 20 decode_x_only(idx, payload) elsif idx < 84 decode_nibble_pair(idx, payload) elsif idx < 120 decode_byte_pair(idx, payload) elsif idx < 124 decode_12_bit_pair(idx, payload) else decode_16_bit_pair(idx, payload) end [dx, dy, on_curve] end |
.encode(dx, dy, on_curve:) ⇒ Array(Integer, Array<Integer>)
Encode a single (dx, dy) delta with the given on-curve flag.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/fontisan/woff2/triplet_codec.rb', line 24 def self.encode(dx, dy, on_curve:) on_curve_bit = on_curve ? ON_CURVE_BIT : OFF_CURVE_BIT abs_x = dx.abs abs_y = dy.abs x_sign_bit = dx.negative? ? 0 : 1 y_sign_bit = dy.negative? ? 0 : 1 xy_sign_bits = x_sign_bit + (2 * y_sign_bit) if dx.zero? && abs_y < 1280 encode_y_only(on_curve_bit, abs_y, y_sign_bit) elsif dy.zero? && abs_x < 1280 encode_x_only(on_curve_bit, abs_x, x_sign_bit) elsif abs_x < 65 && abs_y < 65 encode_nibble_pair(on_curve_bit, abs_x, abs_y, xy_sign_bits) elsif abs_x < 769 && abs_y < 769 encode_byte_pair(on_curve_bit, abs_x, abs_y, xy_sign_bits) elsif abs_x < 4096 && abs_y < 4096 encode_12_bit_pair(on_curve_bit, abs_x, abs_y, xy_sign_bits) else encode_16_bit_pair(on_curve_bit, abs_x, abs_y, xy_sign_bits) end end |