linebender / linebender/parley

Custom Font Collection

Open
#622 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
736
Forks
120
Avg merge
1d 3h
Merged PRs (30d)
53

Description

Motivation

I am trying to render user text in arbitrary language. The app should work in both desktop and wasm.

Most languages are covered by Noto Sans CJK(5MB) + Noto Sans non-CJK megamerge (5MB), which is fine for desktop but not in web. 10MB is too bad for page load time. In Firefox, wasm cannot access the local font, so having required fonts pre-installed doesn't help.

One solution is to split the font into many smaller chunks like Google fonts api does.

Google CDN serves Noto Sans JP in 100+ chunks:
https://unpkg.com/@fontsource/noto-sans-jp@4.5.5/unicode.json

Automatic css generation for given weights / family / styles:
https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;700&family=Noto+Sans+JP:wght@400;700&display=swap

@font-face {
  font-family: 'Noto Sans JP';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/notosansjp/v56/-F62fjtqLzI2JPCgQBnw7HFow2oe2EcP5pp0erwTqsSWs9Jezazjcb4.114.woff2) format('woff2');
  unicode-range: U+3e, U+3005, U+4e0d, U+4e88, U+4ecb, U+4ee3, U+4ef6, U+4fdd, U+4fe1, U+500b, U+50cf, U+5186, U+5316, U+53d7, U+540c, U+544a, U+54e1, U+5728, U+58f2, U+5973, U+5b89, U+5c71, U+5e02, U+5e97, U+5f15, U+5fc3, U+5fdc, U+601d, U+611b, U+611f, U+671f, U+6728, U+6765, U+683c, U+6b21, U+6ce8, U+6d3b, U+6d77, U+7530, U+7740, U+7acb, U+7d50, U+826f, U+8f09, U+8fbc, U+9001, U+9053, U+91ce, U+9762, U+98df;
}
@font-face {
  font-family: 'Noto Sans JP';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/notosansjp/v56/-F62fjtqLzI2JPCgQBnw7HFow2oe2EcP5pp0erwTqsSWs9Jezazjcb4.115.woff2) format('woff2');
  unicode-range: U+7c, U+3080, U+4ee5, U+5148, U+516c, U+521d, U+5225, U+529b, U+52a0, U+53ef, U+56de, U+56fd, U+5909, U+591a, U+5b66, U+5b9f, U+5bb6, U+5bfe, U+5e73, U+5e83, U+5ea6, U+5f53, U+6027, U+610f, U+6210, U+6240, U+660e, U+66f4, U+66f8, U+6709, U+6771, U+697d, U+69d8, U+6a5f, U+6c34, U+6cbb, U+73fe, U+756a, U+7684, U+771f, U+793a, U+7f8e, U+898f, U+8a2d, U+8a71, U+8fd1, U+9078, U+9577, U+96fb, U+ff5e;
}

Each chunk is 1KB~50KB which is suitable for web.

Feature Request

In parley/fontique we need

  • faster font lookup mechanism than naively iterating FontStack or fallback list (There are 100+ Noto Sans family, and 700+ chunks in total)
  • priority between fallback fonts
  // fontique-0.8.0/src/collection/query.rs
  for family in self.state.families.iter_mut()
      .chain(self.state.fallback_families.iter_mut()) {
      // ... probe best-match + default font, callback ...
  }

The definition of best-match also can get complex. I suggest to make Collection customizable with user-provided implementation.

struct MyFontCollection {
  // sorted, non-overlapping ranges for binary-search
  coverage: Vec<UnicodeRange, ChunkIndex>,
  chunks: Vec<Font>,
}

impl parley::SomeTrait for MyFontCollection {
  ..
}

impl MyFontCollection {
  async fn ensure(&mut self, text: .., lang: ..) {
    // 1. check local font
    // 2. load fonts via network
  }
}

font_context.collection = Arc::new(MyFontCollection::default());
font_context.collection.ensure("abc").await; // load some chunks of Noto Sans
font_context.collection.ensure("가나다").await; // load some chunks of Noto Sans CJK

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading fontique-0.8.0/src/collection/query.rs and tracing how Collection searches families and fallback families. Clarify the requirements for customizable collection lookup, fallback priority, and loading font chunks for desktop and wasm; done means an agreed design that addresses the proposed use cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust, wasm
Domain
desktop, web-dev
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.