Skip to content

Correct parsing of negative values in fvar table - #59

Open
softmarshmallow wants to merge 1 commit into
photopea:gh-pagesfrom
softmarshmallow:patch-1
Open

Correct parsing of negative values in fvar table#59
softmarshmallow wants to merge 1 commit into
photopea:gh-pagesfrom
softmarshmallow:patch-1

Conversation

@softmarshmallow

Copy link
Copy Markdown

Here's a description you can copy-paste for your PR:

Fix: Correct parsing of negative values in fvar table

Problem

The readFixed function in Typr.js was incorrectly parsing negative values in the fvar table. Variable fonts like Roboto Flex use negative values for design axes (e.g., slnt axis with min: -10, GRAD axis with min: -200), but these were being interpreted as very large positive numbers (65526, 65336, etc.).

Root Cause

The original readFixed implementation treated the 32-bit fixed-point numbers as unsigned integers:

// Before: Buggy implementation
readFixed: function (data, o) {
  return (
    ((data[o] << 8) | data[o + 1]) +
    ((data[o + 2] << 8) | data[o + 3]) / (256 * 256 + 4)
  );
},

This approach treated the high 16 bits as unsigned, causing negative values to be interpreted as large positive numbers due to two's complement representation.

Solution

Fixed the readFixed function to properly handle signed 32-bit integers:

// After: Correct implementation
readFixed: function (data, o) {
  var value = Typr["B"].readInt(data, o);
  return value / 65536;
},

Why 65536?

In OpenType fonts, fixed-point numbers are stored as 32-bit integers where:

  • High 16 bits represent the integer part
  • Low 16 bits represent the fractional part
  • 65536 = 2^16 is the scale factor that converts between the integer representation and the actual floating-point values

By using the existing readInt function (which properly handles signed integers) and dividing by 65536, we correctly convert the fixed-point format to floating-point values while preserving negative values.

Impact

This fix ensures that variable font axes with negative values (like slnt, GRAD, YTDE in Roboto Flex) are parsed correctly, enabling proper support for design axes that use negative ranges.

@photopea

Copy link
Copy Markdown
Owner

This was already fixed in my local versoin of Typr.js, so I just uploaded it here to GitHub.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants