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

[skrifa] floating point COLR #697

Closed
wants to merge 8 commits into from
Closed

[skrifa] floating point COLR #697

wants to merge 8 commits into from

Conversation

dfrg
Copy link
Member

@dfrg dfrg commented Nov 9, 2023

Internal interface for color outline loading in full floating point.

This copies ColrInstance & co from read-fonts to skrifa and updates it to process all values/deltas in floating point. Additionally, adds methods to ItemVariationStore to compute scalars/deltas in floating point. It's f32 all the way down.

This doesn't remove the code in read-fonts and also contains a module for printing the paint graph so it's not ready to merge.

Printing the graph for a glyph:

use skrifa::prelude::*;
use skrifa::raw::TableProvider;

let font_data = std::fs::read("/path/to/colrv1font.ttf").unwrap();
let font = FontRef::new(&font_data).unwrap();
let colr = font.colr().unwrap();
let coords = [NormalizedCoord::from_f32(-0.6021); 64];
skrifa::scale::print_color_glyph(&colr, GlyphId::new(94), LocationRef::new(&coords));

For the COLRv1 test font, glyph 94 (radial_horizontal_gradient_extend_mode_pad) with all coords set to -0.6021 loads as follows with skrifa maintaining fractional values from deltas:

freetype:

Glyph 2
    RadialGradient p0: (-202.000000,-102.000000) r0: -502.000000 p1: (98.000000,-102.000000) r1: -402.000000 extend: Pad stops: (-1.204224 3 1.000000), (-0.704224 9 1.000000), (-0.204224 0 1.000000)

skrifa:

Glyph GID_2
    RadialGradient p0: (-202.11182,-102.11182) r0: -502.11182 p1: (97.88818,-102.11182) r1: -402.11182 extend: Pad stops: (-1.2042236 3 1), (-0.70422363 9 1), (-0.20422363 0 1)

Internal interface for color outline loading in full floating point.
@drott
Copy link
Contributor

drott commented Nov 14, 2023

Thanks for this - the fact that FreeType returns rounded values is the bug in FreeType at the moment that @tursunova is in the process of fixing - so it's a bit hard to tell how war the fixed computation would be off. I am a bit concerned about the code duplication - if it's COLR related, could we perhaps shift read_fonts to do this in floats right away? I don't think we have a huge legacy there from FreeType (rather, we have bugs that we need to fix, like https://bugs.chromium.org/p/chromium/issues/detail?id=1473020

@dfrg
Copy link
Member Author

dfrg commented Nov 14, 2023

I am also curious to see how the issue will be resolved in FreeType and how big the diffs might be.

re duplication: if we go this route, my intent was to just remove this functionality from read-fonts. I think your new ColorPainter code does a better job of providing a nice semantic model of a paint graph. For people wanting low level access, that would still be available from our codegen'd types in read-fonts.

dfrg added 2 commits November 14, 2023 14:11
- remove fixed point ColrInstance code from read-fonts
- remove color paint debug printing module from skrifa
@dfrg dfrg marked this pull request as ready for review November 14, 2023 19:17
@@ -0,0 +1,653 @@
//! COLR table instance.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about putting this in skrifa/src/colr/instance.rs? Or skrifa/src/color/instance.rs - My thinking is: We're not really scaling here, mostly applying variations. And then ColorPainter can go in the same directory when it is ready.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems reasonable but the details are a bit tricky. I’m thinking forward to adding bounding box computation which will require the scaling code. As of now, the “metadata level” types don’t have any dependencies on the scale module and I find that to be a clean separation. I suppose we can maintain that by just taking a closure for computing per glyph bounding boxes. Let me put together a quick proposal for this API.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just arrived at the same question - when looking at bounding box computation. Taking transforms into account we'd arrive at implementing a full matrix transform library - which we already have in Skia. So I don't think we need to necessarily replicate that now. My approach now is a basic BoundsPainter that does mostly nothing for the fills, just keeps track of a matrix, and retrieves the tight contours of path along the way. The ingredients already exist.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#702 is a proposal for this that tries to fit it into the current design for metadata access. I see your point about the matrix library, but it seems like ColorPainter needs the struct regardless as a parameter for transform callbacks. I believe your code already has the constructors for translate/rotate/skew, so we'd really only need to add mat * mat and mat * point operators to make this work.

}

#[derive(Copy, Clone)]
enum DeltaTy {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does Ty mean Type? Is that a convention we're using. Can we spell it out? DeltaType?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, yes. Since type is a reserved word in rust, this is fairly idiomatic and I follow it by habit but I’m happy to spell it out.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -0,0 +1,6 @@
mod instance;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In line with the comment above, move this to src/colr/mod.rs?

///
/// This requires a type parameter specifying the type of target value for the
/// delta.
pub fn compute_delta_f32<T: ItemDeltaTarget>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to add some standalone file level tests for this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have a reference for correctness here so I added a sanity test to ensure that the floating point results are within a reasonable margin to the delta produced by the FT compatible computation. Specifically, it ensures that either the rounded or truncated floating point delta matches the FT compatible delta. We have to account for both because fractional accumulation can push us to either side of the 0.5 boundary in some cases.

dfrg added 2 commits November 15, 2023 12:16
- renamed DeltaTy -> DeltaType
- add sanity test for floating point delta computation
@dfrg dfrg mentioned this pull request Nov 15, 2023
dfrg added 3 commits November 28, 2023 10:41
Expose a color outline API in top level metadata rather than in the scale module.
- add version() method to ColorOutline
- remove maxp lookup and change iterator to use max glyph in COLR table
- remove glyph_id from ColorOutline and change iterator to return (GlyphId, ColorOutline) tuple
dfrg added a commit that referenced this pull request Nov 29, 2023
As requested, this is the floating point refactor extracted from #697.

* add methods to IVS to compute scalars/deltas in f32.
* move `ColrInstance` from read-fonts to a private module in skrifa and update it to produce results in f32.
@drott
Copy link
Contributor

drott commented Dec 11, 2023

Can we close this, is this superseded by #725?

@dfrg
Copy link
Member Author

dfrg commented Dec 11, 2023

Yep!

@dfrg dfrg closed this Dec 11, 2023
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