Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
skef committed Oct 14, 2024
1 parent d72581d commit 44e36cd
Show file tree
Hide file tree
Showing 8 changed files with 6,356 additions and 2 deletions.
1,285 changes: 1,285 additions & 0 deletions Grammar_Diff.html

Large diffs are not rendered by default.

4,454 changes: 4,454 additions & 0 deletions OpenTypeFeatureFileSpecification_diff.html

Large diffs are not rendered by default.

99 changes: 97 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,97 @@
# feature_file_change_review
Public review of tentative changes to the Adobe OpenType Feature File Format Specification
# OpenType Feature File Specification Additions for Variable Values: Public Review

The Adobe Type Team has been working to extend the OpenType Feature File
Specification to add direct support for variable fonts. These additions will
provide a new workflow in which a single feature file can be applied to an
already-variable "base" font, producing a full OpenType font with layout
features (and other additional tables). Compared with the currently predominant
"merging" workflow, this new syntax makes it easier to reference designspace
locations in kerning or other values that are not associated with a given
master, eliminates the ambiguity of 0 values in a master font, and provides
other advantages.

We are introducing these specification changes in two stages:

* Stage 1, which is now ready for public review, adds support for variable
values.
* Stage 2, which should be ready in the first half of 2025, will add support
for feature variations (such as swapping one glyph for another based on axis
range conditions).

Supporting these changes in our AFDKO toolset has required an extensive
modernization of much of its lower-level implementation, which is one reason
this project has taken longer than expected. However, the feature file syntax
is also used in many tools not built or provided by Adobe. We have no control
over whether our proposals are adopted by other toolsets, of course, but we
have tried to take the wider needs of the font development community into
account in developing these extensions. It is our hope that feature files will
continue to be more or less portable between different font development
toolchains.

This specification review provides an opportunity for the Adobe type team to
answer questions about our choices, and if necessary to make adjustments to the
specification so that it is adopted as widely as possible.

Adobe is now accepting comments on the stage 1 work via this GitHub repository.
Start a [Discussion](/adobe-type-tools/feature_file_change_review/discussions)
about whatever you would like to clarify, or add an
[Issue](/adobe-type-tools/feature_file_change_review/issues) to raise the
possibility of adding to or changing the specification. (As always, it is
good practice to look through the lists of existing discussions and
issues to avoid duplication.)

The review period for stage 1 ends on January 15th 2025.

The documentation provided includes:

* A [style guide](https://adobe-type-tools.github.io/feature_file_change_review/Variable_Feature_Style_Guide.md).
(This is probably the best place to start.)
* A [revised specification](https://adobe-type-tools.github.io/feature_file_change_review/OpenTypeFeatureFileSpecification_diff.html) marked
with the differences from the previous version.
* An annotated ANTLR 4 format [grammar](https://adobe-type-tools.github.io/feature_file_change_review/Grammar_Diff.html).
* A short list of [ideas that were rejected](https://adobe-type-tools.github.io/feature_file_change_review/rejected_ideas.md).

In addition to this documentation we are providing an [example
repository](https://github.com/adobe-fonts/vffirst-source-serif) with
the sources for the Source Serif 4 Variable roman font reorganized to use the
new workflow. It explains how to install a beta version of AFDKO that builds
these sources, and how the feature files can be modified to experiment with
additional aspects of the grammar. (Note that this beta version of our toolset
is only partially tested and should not be used to attempt to build
production-quality fonts.)

## Who should review?

Anyone is free to comment on and ask questions about the changes to the
specification, but here is some guidance on whether and how you might want to
participate:

* If you are only vaguely familiar with feature files, perhaps because you use
a font editor that produces and compiles them for you "under the hood", you
can probably trust that the developer of your editor will be reviewing these
changes on your behalf.
* If you author your own feature files but your use of them is fairly routine,
you might read through the style guide to understand the new functionality,
and reference parts of the revised specification if you have further
questions.
* If you make or have made extensive use of feature files to create fonts with
unusual layout features or other characteristics, we recommend reviewing the
style guide and specification to judge if you will be able to do what you
need to and if there are aspects of the process that might be improved.
* If you develop a tool that creates, processes, or consumes feature files, we
recommend reviewing the proposed changes—including the ANTLR grammar—with an
eye toward adopting the extended grammar in the future, and perhaps to
engage with your community of users about it. If there are obstacles to that
adoption, please raise them in issues or discussions in the review
repository and we will try to work with you.

## A note about the scope and role of feature files in font development

In reading the proposals you will notice that there is more than one way of
specifying a variable metric or anchor, and several optional features such as
named designspace locations. This flexibility is intentional, and reflects the
role of feature files as a "fallback" mechanism for less common layout needs
that may not be supported by an interactive font development system. The goal
of the specification has been, and continues to be, to provide almost all of
the functionality of the OpenType shaping tables in a form that can be authored
and reviewed by font designers and engineers.
262 changes: 262 additions & 0 deletions Variable_Feature_Style_Guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
# Style guide for variable font-specific features

## Introduction

As of version 1.27, the [OpenType Feature File
Specification](./OpenTypeFeatureFileSpecification.md) includes new syntax for
direct encoding of variable values in a variable font. Prior to this revision
the creation of a variable font using AFDKO (and most other font development
toolkits) has started with the generation of a number of relatively complete
"static" fonts, each with its own feature file hierarchy. Those static fonts
would then be merged to form a variable font.

This construction method (which is still supported) has the advantage of
continuity with pre-variable-font methods of producing font families from a
smaller set of interpolable masters. However, it also has some drawbacks. One
is that it limits the designer to locations in designspace that correspond to
one of the static input fonts. This can be somewhat mitigated by the use of
"sparse" masters, but these can be cumbersome to create and the rules for how
sparse masters are merged can get complicated. Each additional master will also
typically add a number of font-level values that may not be wanted.

Another drawback is the need to maintain multiple feature file hierarchies
with carefully synchronized data, so that the GSUB, GPOS, and GDEF tables
in the static input fonts can be merged.

The additions to the feature file syntax discussed in this style guide provide
an alternative, "variable-first" development process. The first step of this
process also involves merging static "fonts" into a variable "font", but these
fonts are "minimal" in that they just contain glyph-level data and a few
general parameters like ascent, descent, and em-height. (The need for such
intermediate fonts may be optimized out of future versions of AFDKO.) Features
and other parameters are then specified in a single, font-wide feature file
hierarchy. The content of that hierarchy is then added to the minimal font to
produce a complete OpenType variable font.

The actual process of creating a variable font in this new way is documented
elsewhere, and will anyway likely change somewhat in the first few years after
these syntax changes have been introduced. The detailed descriptions of each
addition are documented, and will continue to be documented, in the
specification linked above. This document provides a basic introduction to them
along with advice about how to choose between expressions when alternatives are
available.

**Note:** As of this draft the additional support for variable values (kerning,
anchors, etc) is tentatively complete and being prepared for general community
review. Other planned additions to support "Feature Variations" (such as
substitutions that are limited to certain axis ranges) have not yet been
specified or implemented. This document will be updated as the specification,
implementation, reviewing, and finalizing continues.)

## The basics of a single variable value

Generally speaking, a variable value consists of a set of designspace locations
paired with values. In a merging workflow the location is assigned to a source
master in a designspace file and the value is some value in the master, such as
the *x* coordinate of a point on a glyph, a kerning value, or the TypoAscender
value in the OS/2 table.

The added syntax allows a variable value to be declared all at once, often in a
context where a single number would be written when building a static font. The
second part of a pair—the value—will typically just be a number (and therefore
does not need much explanation). Locations are more complicated, and the best
way of specifying a location may depend on a font designer's process.

### Designspace locations and unit suffixes

A designspace location is itself a set of pairs, each consisting of an axis
specifier—almost always a three- or four-letter "tag"—and a position on that
axis. There are scales for specifying an axis position, each with its own
"unit letter":

* Design units (`d`): These are units chosen by the designer and typically
specified in a designspace file. Each axis will have a minimum, maximum,
and default value in these units.
* User units (`u`): These are the units presented to a user when adjusting the
axis. A designspace file maps between design units and user units. If there
is no mapping for an axis, the user units are treated as the same as the
design units. Some standardized axes, such as `wght`, have standardized
axis values, others do not. As with design units there will always be a
minimum, maximum, and default for each axis.
* Normalized units (`n`): Normalized units are in a range from a minimum of -1
to a maximum of 1 inclusive, with a default of 0. They have a precision of
F2dot14 (14 bits for the fractional part of the number). Most OpenType
tables that store axis positions use normalized values (the exception being
the `fvar` table, which stores user values).

Which scale is best to use depends on how a font is being designed, and more
particularly on what a designer takes the axis location they are specifying to
correspond to. That said, the designers we have talked to say that design units
are typically both the most intuitive and the most stable measure for
specifying axis locations.

A full designspace location is a comma-separated list of axis tag, axis value
pairs separated by an equals sign (`=`). Each axis value must have a unit. For
example, in a variable font with a `wght` axis and an `opsz` axis, this would
fully specify a location:

```fea
wght=1000d, opsz=0n
```

(Note that `0n` always represents the default location of an axis, just as
`-1n` always represents the minimum and `1n` always represents the maximum.)

There is one extra "trick" with axis position specifiers: When the unit letter
is followed by a plus sign (`+`) like this:

```fea
wght=600d+, opsz=0n+
```

the axis position specified will be the minimum F2dot14 increment above the
position specified with the number and unit. This makes it easier to specify
locations that are "right next to each other". Following the unit letter with a
minus sign/hyphen (`-`) similarly yields the minimum F2dot14 decremented
position.

### Named locations

The `locationDef` keyword can be used to give a name to a location. For example,
this statement gives the name `@DisplayBlack` to a weight of 1000 and an optical
size of 60 (both in design units):

```fea
locationDef wght=1000d, opsz=60d @DisplayBlack;
```

Note that all named locations must start with an at-sign (`@`) in both the
definition and wherever it is used.

We strongly encourage the use of named locations in feature files, for these
reasons:

* For typical variable fonts only a small number (typically less than 30) of
locations are used in specifying variable values. Even fonts playing "tricks"
will typically only use a few extra locations in a given case. So it will
generally not be a burden to give each location a name. (Or, failing that,
to give each "primary" location a name.)
* If the designspace of a font changes during development, named locations
mean that only a small number of lines in the feature file need to change.
* Location literals are comma-separated lists of tag, value pairs, and
variable values are whitespace-separated lists of location, value pairs.
This means that even with careful formatting a variable value specified
using location literals can be difficult to read and understand, while
variable values specified with named locations will be shorter and easier to
read.
* Named locations are likely to decrease the time it takes to parse a feature
file compared with repeated location literals (although this may only be a
factor for very large files).

The particular choice of names is up to the designer. Abbreviated instance
names, as in the above example, are one possibility. Another is the use of "m",
"d", and "M" for minimum, default, and maximum for each axis, so for example:

```fea
locationDef wght=0d, opsz=60d @mM
```

as these yield short and distinctive names for the middle and "corners" of the
designspace.

Most of the subsequent examples will use named locations.

### "Single" variable values

In most contexts of a feature file where a single number is specified in a
non-variable font, and where a variable value is now permitted, one can now
supply a "single" variable value. A variable value is specified as a set of
whitespace-separated location, value pairs enclosed in parentheses, where the
location and the value are separated by a colon. For example (for a font with
one `wght` axis):

```fea
(50 wght=0:47 wght=1000:54)
```

or this example using named locations:

```fea
(50 @mm:47 @mM:48 @Mm:54 @MM:51)
```

Note that when the location and colon are *omitted* from a pair, the value will
treated as that of the *default location* of the variable font.

This syntax is used in almost all places where a variable value can be
specified other than a "metric" and an anchor, and can optionally be used in
those contexts as well.

## Kerning metrics

A valid kerning metric can consist of either one or four values. When
specifying one value a single variable value is appropriate. When specifying
four values there are two choices of syntax. One choice is to treat any or all
of the four values as a single variable value:

```fea
valueRecordDef <0 0 (20 @ExtraLight:30 @ExtraBlack:10) 0> KERN_A;
```

With the other syntax, the ordering of the parentheses and brackets is
reversed, so that each distinct location is used once in the metric:

```fea
valueRecordDef (<-80 0 -160 0> wght=200u:<-80 0 -140 0> @ExtraBlack:<-80 0 -180 0>) KERN_B;
```

The first syntax is easier when:

* Not all of the metrics are variable, or
* Different metrics use different locations

And the second syntax is easier when all metrics use the same locations.

## Anchors

Anchor specifiers provide two analogous choices. Either some or all of the two
position values can be variable

```fea
<anchor (120 @ExtraLight:115 @ExtraBlack:125) (-20 @ExtraLight:-10 @ExtraBlack:-30)>
```

or there can be a single parenthetical with internal angle brackets containing two
values:

```fea
<anchor (<120 20> @ExtraLight:<115 -10> @ExtraBlack:<125 -30>)>
```

As with variable metrics, the first syntax is easier when:

* Only one of the positions is variable, or
* Different positions use different locations

And the second syntax is easier when both positions use the same locations.

## Recommended practices for generated files

In typical development workflows at least some feature files are
auto-generated. This is most common for pair kerning values and mark features,
because those are often available in font source files. In many cases an
auto-generated feature file will never need to be inspected. However, not every
toolchain is perfect and sometimes it is necessary to verify that the contents
of a generated file match the sources and/or match the tables of the compiled
font. It is therefore best to try to make such files at least somewhat legible.

Our primary recommendation for readable files is to use named locations.
Ideally the designer should be able to control or influence the choice of
names. A variable value specified with named locations easily recognized by the
designer are far easier to read than the alternatives.

Beyond that, when a value has more locations and values than fit on a typical
line (say 80 or 100 characters), putting some thought into formatting can be
very helpful. This can be as simple as adding a newline and some spaces for
basic alignment, as in:

```fea
pos at underscore (@CEL:-40 @CR:-40 @CBl:-70 @TEL:-80 -80 @TBl:-80 @DEL:-80
@DR:-80 @DBl:-80);
```
Loading

0 comments on commit 44e36cd

Please sign in to comment.