Gaps in the HarfRust C FFI and how to fill them
- Dominant language
- Rust
- Stars
- 301
- Forks
- 26
- Avg merge
- 10h 11m
- Merged PRs (30d)
- 43
Description
# Chromium's remaining gaps in the C API
## Assessment
Diffing the `hb_` names Chromium calls against the ones `harfrust-capi`
maps, as of `399dcb3` on `c-api`:
| | |
| --- | --- |
| distinct `hb_` functions Chromium calls | 87 |
| names mapped in `hr-hb.h` | 195 |
| of Chromium's, not yet mapped | 42 |
| of those, actually needed | 33 |
| already tracked in #466 and #467 | 7 |
| untracked and needed | 26 |
The structural pieces are already there, which is the hard part:
`hb_font_create_sub_font`, `hb_font_get_parent`, `hb_face_create_for_tables`,
`hb_shape_full`, `hb_font_set_ptem` and `hb_glyph_info_get_glyph_flags` all
map. Blink builds its shaping font as a sub-font over a Skia-backed face and
overrides the metrics funcs, and nothing in that shape is blocked.
What is missing falls into three groups.
## 1. Buffer input encodings — blocking
The branch has `add`, `add_codepoints`, `add_utf32` and `add_utf8`. Chromium
uses none of those. Its strings are UTF-16 or Latin-1 and it never hands
HarfBuzz UTF-8:
| function | call sites |
| --- | --- |
| `hb_buffer_add_utf16` | `harfbuzz_shaper.cc:1189`, `render_text_harfbuzz.cc:1456` |
| `hb_buffer_add_latin1` | `harfbuzz_shaper.cc:1183` |
Both take an `item_offset` and `item_length` within a longer buffer, so the
pre- and post-context that shaping depends on comes along with them. Without
these two, Chromium cannot feed text at all, so they gate everything else
here.
## 2. Font funcs and sub-font delegation
Chromium installs nine font funcs; five map today. Blink overrides metrics so
that advances and extents come from Skia — hinted and subpixel-aware, and
matching what it will actually rasterize — so these are not optional
niceties.
| function | who installs it |
| --- | --- |
| `hb_font_funcs_set_glyph_h_advances_func` | Blink, the batched path |
| `hb_font_funcs_set_glyph_h_kerning_func` | ui/gfx |
| `hb_font_funcs_set_glyph_h_origin_func` | ui/gfx |
| `hb_font_funcs_set_glyph_v_kerning_func` | ui/gfx |
Three more belong with them:
- `hb_font_get_glyph` — Blink's nominal and variation glyph callbacks
re-enter HarfBuzz as `hb_font_get_glyph(hb_font_get_parent(font), …)`
(`harfbuzz_face.cc:182`). `hb_font_get_parent` already maps; this does not.
- `hb_ot_font_set_funcs` — applied to the parent font before the sub-font is
made (`harfbuzz_face.cc:574`).
- `hb_face_count` — validates the TTC index before `hb_face_create`
(`harfbuzz_face_from_typeface.cc:38`).
## 3. Layout table introspection — untracked
There are currently no `hb_ot_*` functions in the branch, which matches the
README's stated scope. Everything Chromium reaches through
`hb_font_get_face()` on its shaping font lands here.
**Whether a space takes part in kerning or ligatures**
(`HarfBuzzFace::HasSpaceInLigaturesOrKerning`, which decides whether text can
be cached word by word):
- `hb_ot_layout_has_substitution`, `hb_ot_layout_has_positioning`
- `hb_ot_layout_table_get_lookup_count`
- `hb_ot_layout_lookup_collect_glyphs`
- `hb_set_create`, `hb_set_clear`, `hb_set_has`
Note the sub-dependency: `collect_glyphs` returns its results in an
`hb_set_t`, and the README says `hb_set` has no mapping. Some form of set
has to be exposed before this one can be.
**Small-caps support probing** (`OpenTypeCapsSupport`, which decides between
real small caps and synthesis):
- `hb_ot_layout_table_select_script`, `hb_ot_layout_language_find_feature`
- `hb_aat_layout_get_feature_types`,
`hb_aat_layout_feature_type_get_selector_infos`
**Feature enumeration** (`OpenTypeFeatures`):
- `hb_ot_layout_table_get_feature_tags`
**Tag conversion**:
- `hb_ot_tag_to_language` (`harfbuzz_shaper.cc:869`)
- `hb_ot_tags_from_script_and_language` (`caps_support_mpl.cc:34`)
## Already tracked
- `hb_ot_math_*`, six functions — #466
- `hb_ot_layout_get_baseline` — #467
Both now have a `read-fonts` reading layer to build on.
## Not needed
Nine of the 42 can be ignored. They are real Chromium calls, but not on a
shaping font: each builds its own `hb_face_t` straight from font bytes.
- `hb_ot_var_get_axis_count`, `hb_ot_var_get_axis_infos`,
`hb_ot_name_get_utf16` — `variable_axes_names.cc`, face from raw `SkData`
- `hb_ot_color_has_palettes`, `hb_ot_color_palette_get_count`,
`_get_flags`, `_get_colors`, `hb_color_get_red`/`green`/`blue`/`alpha` —
`open_type_cpal_lookup.cc`, likewise
`hb_aat_layout_has_substitution` also appears in the diff but is only
mentioned in a TODO comment (`open_type_caps_support.cc:154`); it is never
called.
## Suggested order
1. **Buffer encodings.** Cheap, self-contained, and nothing else can be
exercised against Chromium until they exist.
2. **Font funcs and delegation.** Completes the sub-font arrangement Blink
relies on, and makes the metrics agree with the renderer.
3. **`hb_set`, then the space-in-lookups group.** The set type is the
gating decision; the rest follows once it exists.
4. **Caps support and feature enumeration.** Independent of the above and of
each other.
5. **Tag conversion.** Small, and can land any time.
#466 and #467 are independent of all of this and can proceed in parallel.
## Method
Reproducible against any checkout:
```sh
# what Chromium calls, from a sparse checkout of
# third_party/blink/renderer/platform/fonts and ui/gfx
grep -rhoE '\bhb_[a-z0-9_]+' --include=*.cc --include=*.h |
sort -u > chrome.txt
# what the C API maps
grep -oE '^#define (hb_[a-z0-9_]+)' harfrust-capi/include/hr-hb.h |
awk '{print $2}' | sort -u > capi.txt
comm -23 chrome.txt capi.txt
```
Collect bare identifiers, not just `name(` — Chromium passes
`hb_ot_math_get_glyph_variants` as a function pointer, and a paren-anchored
pattern misses it. The raw diff needs the filtering above: it includes names
that appear only in comments, and names called on faces built outside the
shaping path.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by running the issue's grep and comm commands to compare Chromium calls with harfrust-capi/include/hr-hb.h. Read the listed Chromium entry points, including harfbuzz_shaper.cc, harfrust_face.cc, and the font layout callers, then implement the missing groups in the suggested order. Done means the required shaping-path functions are mapped and the independent, raw-face-only calls remain excluded.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, rust
- Domain
- api, backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100