From 23b606a17d504bd5ccb6c9c27dc1f03df9c4715d Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Sat, 18 Jan 2025 01:21:09 +0000 Subject: [PATCH] First pass at defining an updated encoder configuration scheme that does not rely on IFTB. --- ift/encoder/encoder_config.proto | 171 +++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 ift/encoder/encoder_config.proto diff --git a/ift/encoder/encoder_config.proto b/ift/encoder/encoder_config.proto new file mode 100644 index 0000000..1d8e334 --- /dev/null +++ b/ift/encoder/encoder_config.proto @@ -0,0 +1,171 @@ +edition = "2023"; + +// This message is used to configure an IFT encoder to generate and IFT encoding of some input font. +// +// The produced encoding will be a "mixed mode" encoding that makes use of both table keyed (https://w3c.github.io/IFT/Overview.html#table-keyed) +// patches to extend non-glyph data (everything other than glyf, gvar, CFF, and CFF2) and glyph keyed patches +// to extend the glyph data tables (glyf, gvar, CFF, CFF2). +// +// The configuration has two distinct parts, the first "Glyph Data Extension Configuration" section +// configures how the font will be split into a set of glyph keyed patches. The generated encoding will +// contain one glyph keyed patch per specified glyph segment and unique configuration of the design space +// reachable via the non glyph table keyed patches. +// +// By default each glyph segment will be reachable by matching any code points that map to any glyph in that +// segment. However, this default mapping can be overriden use the glyph_patch_dependecies map to specify a +// set of glyph segments and features that when matched will trigger that glyph segment. For example if there +// were three input segments (1, 2, 3) where segment 1 contained the f glyph, segment 2 contained the i glyph +// and segment 3 contains the fi ligature glyph then segment 3 should be configured to be dependent on +// segments 1 and 2 which would result in segment 3 to only be selected by the client if segments 1 and 2 +// were also selected. +// +// The second section of the configuration is the "Non Glyph Extension Configuration" which describes how to +// segment the data in all non-glyph tables (everything but glyf, gvar, CFF, and CFF2). These tables will be +// extended by table keyed patches. Since table keyed patches are invalidating +// (see: https://w3c.github.io/IFT/Overview.html#font-patch-invalidations) a graph of patches will be +// produced such that the font can be extended to include data for any of the specified segments. +// +// In the simplest case a graph is generated by the following process: +// - each node will contain one patch per code point, feature, and design space segment that has not yet +// been included. Where each patch will extend the font to add data only for the associated segment. +// +// Additional controls are provided which can modify how the graph is formed. For example to reduce +// potential client round trips or reduce the number of patches in the graph. The following options are +// provided: +// +// - jump_ahead: defaults to 1, normally each node would contain one patch per outstanding segment. If +// jump ahead is greater than 1 then additional patches will be included at each node which +// simultaneously extends the font to all combinations of 2 through jump_ahead segments. For +// example if a node has three segments a, b, and c and jump ahead is set to 2 then the node +// will include patches for a, b, c, a+b, a+c, and b+c. +// +// - max_depth: max depth limits the depth of the produced graph. In the second last level of the graph all +// nodes will contain only a single patch which adds all remaining segments. This setting is +// useful to limit the total size of the graph. +// +// - include_all_segment_patches: if true in the generated table keyed patch graph every node (in addition +// to the usual patches) will have a patch available which adds all remaining +// segments to the font. This makes it possible for the client to reach any +// combination of coverage in at most one round trip from any intermediate +// (or initial) state. +message EncoderConfig { + + // TODO validation criteria for the configuration: + // - check that fully expanded font meets closure requirement. + // TODO mechanism to specify uvs to glyph patch deps. + + // ### Glyph Data Extension Configuration ### + + // A list of segments. In the generated encoding there will be one glyph keyed patch (containing all + // data for all of the glyphs in the segment) per segment and unique design space configuration. + // + // The key of the mapping is an integer id which other parts of the configuration can use to reference + // the segment. + map glyph_segments = 1; + + // Encodes a depencies between other glyph patches and layout features. + // + // An entry in this map implies that the patch mapping entry for the glyph patch identified by the key + // will be set up such that it will only be matched for loading iff: + // - All of GlyphPatchDependency.required_patches are matched, AND + // - All of GlyphPatchDependency.required_features are matched. + map glyph_patch_dependencies = 2; + + // ### Non Glyph Extension Configuration ### + + // For table keyed patches the patch graph will include patches that can add up to this many + // segments in a single patch. Defaults to 1. + uint32 jump_ahead = 3; + + // For table keyed patches the patch graph will be at most this many levels deep, or in other + // words at most max depth round trips will ever be needed to reach any content in the font. + // + // This is implemented in the graph by having the nodes in the second last level contain + // only a single patch which adds everything remaining. + // + // Defaults to unlimited depth. + uint32 max_depth = 4; + + // In the generated table keyed patch graph every node (in addition to the usual patches) will + // have a patch available which adds everything remaining to the font. This makes it possible + // for the client to reach any combination of coverage in at most one round trip from any + // intermediate (or initial) state. + bool include_all_segment_patches = 5; + + // The initial_* fields defines all of the data that the initial IFT font will include. If these are all + // left empty then the initial font will be a desiccated font which contains the minimum possible amount of + // data. + // + // Any glyph patches listed in initial_glyph_patches will be added to the initial font and patch files will + // not be generated for them. Glyph dependencies will be automatically updated to reflect the inclusion of + // these patches in the initial font. Any glyph patches whose dependencies are satisfied as a result will + // also be included in the initial font (this is done recursively). + Codepoints initial_codepoints = 6; + GlyphPatches initial_glyph_patches = 7; + Features initial_features = 8; + DesignSpace initial_design_space = 9; + + // Groups of codepoints which the non glyph data in the font can be extended in a single + // jump. These can be specified as either groups of codepoints + // (via non_glyph_codepoint_segmentation), or by grouping together glyph keyed patches defined + // above (via glyph_patch_groupings). + repeated Codepoints non_glyph_codepoint_segmentation = 10; + + // An alternative way to specify codepoint segmentations. One segment will be formed from + // the union of all of the codepoints associated with each referenced glyph patch. Glyph + // patches are defined above. This field can be used in addition to non_glyph_codepoint_segmentation. + repeated GlyphPatches glyph_patch_groupings = 11; + + // Groups of open type layout features which the non glyph data in the font can be extended + // for in a single jump. + // + // Note: all segments (codepoints, features, design space) implicitly include the features + // in the "default feature list" (https://w3c.github.io/IFT/Overview.html#feature-tag-list) + // so this segmentation should be used to provide optional access to features not already + // on that list. + repeated Features non_glyph_feature_segmentation = 12; + + // Parts of the fonts overall design space which the non glyph data in the font can be extended + // for in a single jump. + repeated DesignSpace non_glyph_design_space_segmentation = 13; + + // ### Glyph and Non Glyph Configuration ### + + // If true, the for each of glyph, codepoint, feature, and design space segmentations an additional segment + // will be automatically added (if needed) which includes anything not covered by the specified segments + // + // Note: this applies to both the glyph and non-glyph segmentations. + // + // Setting this ensures that all data in the original font is always reachable. + bool add_everything_else_segments = 14; +} + +message GlyphPatchDependency { + GlyphPatches required_patches = 1; + Features required_features = 2; +} + +// A list of glyph patch ids +message GlyphPatches { + repeated uint32 values = 1; +} + +// A list of glyph ids +message Glyphs { + repeated uint32 values = 1; +} + +// A list of unicode code points. +message Codepoints { + repeated uint32 values = 1; +} + +// A list of open type layout feature tags. +message Features { + repeated string values = 1; +} + +// A variable font design space. +message DesignSpace { + // TODO +} \ No newline at end of file