OpenType features: HarfBuzz Manual

## OpenType features

OpenType features enable fonts to include smart behavior, implemented as "lookup" rules stored in the GSUB and GPOS tables. The OpenType specification defines a long list of standard features that fonts can use for these behaviors; each feature has a four-character reserved name and a well-defined semantic meaning.

Some OpenType features are defined for the purpose of supporting script-specific shaping, and are automatically activated, but only when a buffer's script property is set to a script that the feature supports.

Other features are more generic and can apply to several (or any) script, and shaping engines are expected to implement them. By default, HarfBuzz activates several of these features on every text run. They include `abvm`, `blwm`, `ccmp`, `locl`, `mark`, `mkmk`, and `rlig`.

In addition, if the text direction is horizontal, HarfBuzz also applies the `calt`, `clig`, `curs`, `dist`, `kern`, `liga` and `rclt`, features.

Additionally, when HarfBuzz encounters a fraction slash (`U+2044`), it looks backward and forward for decimal digits (Unicode General Category = Nd), and enables features `numr` on the sequence before the fraction slash, `dnom` on the sequence after the fraction slash, and `frac` on the whole sequence including the fraction slash.

Some script-specific shaping models (see the section called “OpenType shaping models”) disable some of the features listed above:

- Hangul: `calt`

- Indic: `liga`

- Khmer: `liga`

If the text direction is vertical, HarfBuzz applies the `vert` feature by default.

Still other features are designed to be purely optional and left up to the application or the end user to enable or disable as desired.

You can adjust the set of features that HarfBuzz applies to a buffer by supplying an array of hb_feature_t features as the third argument to `hb_shape()`. For a simple case, let's just enable the `dlig` feature, which turns on any "discretionary" ligatures in the font:

          hb_feature_t userfeatures[1];
          userfeatures[0].tag = HB_TAG('d','l','i','g');
          userfeatures[0].value = 1;
          userfeatures[0].start = HB_FEATURE_GLOBAL_START;
          userfeatures[0].end = HB_FEATURE_GLOBAL_END;

`HB_FEATURE_GLOBAL_END` and `HB_FEATURE_GLOBAL_END` are macros we can use to indicate that the features will be applied to the entire buffer. We could also have used a literal `0` for the start and a `-1` to indicate the end of the buffer (or have selected other start and end positions, if needed).

When we pass the `userfeatures` array to `hb_shape()`, any discretionary ligature substitutions from our font that match the text in our buffer will get performed:

          hb_shape(font, buf, userfeatures, num_features);

Just like we enabled the `dlig` feature by setting its `value` to `1`, you would disable a feature by setting its `value` to `0`. Some features can take other `value` settings; be sure you read the full specification of each feature tag to understand what it does and how to control it.