Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cross-platform font selection engine #4901

Closed
kmcallister opened this issue Feb 12, 2015 · 18 comments
Closed

Cross-platform font selection engine #4901

kmcallister opened this issue Feb 12, 2015 · 18 comments

Comments

@kmcallister
Copy link
Contributor

@kmcallister kmcallister commented Feb 12, 2015

See discussion on #1908.

@cybergeek94:

Sounds like a new library project: cross-platform font querying using native APIs.

@nattokirai:

Yeah, the level of support for various things related to fonts needed by a modern web browser varies across platforms. In general, you'll need to maintain some sort of font lookup interface and fill in what's needed on a per-platform basis. OSX and DirectWrite are fairly easy, fontconfig and Android are relatively painful. Gecko uses platform API's to maintain a list of font families available and fills in data for a given family when it's actually used. Font style matching really needs to be done by servo code and not punted to platform-level API's which have their own rules for style matching.

Key features of a font system interface:

  • lookup a font family name
  • enumerate styles within a single family
  • select a given face within a family based on CSS font properties (i.e. weight/width/slant)
  • activate a font from data (with required sanitation such as OTS)
  • lookup individual font faces via a fullname or Postscript name

For browsers you'll also need:

  • system font fallback, the ability to find a font for a given character
  • mappings of generics based on language/script (e.g. sans-serif for Arabic and Japanese are not the same font)
  • ability to read (and cache) font metrics and font table data

See also #3369, #3030, #1677, #249, #190, #186, and many others.

cc @Manishearth, @jdm

@Yoric
Copy link
Contributor

@Yoric Yoric commented Oct 4, 2015

@kmcallister, is this still useful? If so, I might try and look at it, at least for some platforms.

Also, is there any kind of consensus for an API?

@Manishearth
Copy link
Member

@Manishearth Manishearth commented Oct 4, 2015

cc @vvuk

@Yoric
Copy link
Contributor

@Yoric Yoric commented Oct 4, 2015

If fontconfig-rs has an acceptable API, I can work on making it cross-platform.

@nattokirai
Copy link

@nattokirai nattokirai commented Oct 5, 2015

Fontconfig is not an API that you want to base anything on. It is basically a "pick a font" API that doesn't, by intention, cover all the font services needed by a browser engine. A cross-platform API needs to integrate appropriately with underlying system font services, which means doing more work for older platforms (e.g. XP, Linux) and less for more modern ones (DirectWrite, CoreText).

@Yoric
Copy link
Contributor

@Yoric Yoric commented Oct 5, 2015

As I have little-to-no knowledge in (cross-platform) font management, any suggestion of a nice API would be very useful. Should I try to ape CoreText (actually, did you mean CoreText or Apple Type Services?) or DirectWrite, for instance?

@abonander
Copy link

@abonander abonander commented Oct 5, 2015

cc @retep998 for status on DirectWrite bindings in winapi, I can't seem to find them. The DirectWrite API is C++/COM so it might be a little more involved to call into.

Servo actually already has CoreText bindings. I don't know how useful they are though.

Edit: looks like the DirectWrite bindings have yet to be filled out: https://crates.io/crates/dwrite-sys

@vvuk
Copy link
Contributor

@vvuk vvuk commented Oct 5, 2015

DWrite is COM; as far as I can tell, the winapi bindings are complete for it (despite the docs saying otherwise). The only public entry point is via the DWriteCreateFactory factory getter, everything else is done through interface structs. e.g. https://github.com/retep998/winapi-rs/blob/master/src/dwrite.rs

For an API for this, I would suggest looking at what Gecko does -- gfxPlatformFontList/gfxFont and friends. It's been fairly recently designed and is pretty clean, though is support for lots of things that servo may not want to deal with right away. It would also give you an idea of how it maps to the various platforms.

@Yoric
Copy link
Contributor

@Yoric Yoric commented Oct 5, 2015

Would it be best to implement this as a separate lib?

@abonander
Copy link

@abonander abonander commented Oct 5, 2015

Definitely. Cross-platform font selection isn't just a problem for browser engines. It would be really beneficial if it were reusable for other projects.

@Yoric
Copy link
Contributor

@Yoric Yoric commented Oct 5, 2015

The initial description of the issue didn't mention actual rendering. Is that still true?

@nattokirai
Copy link

@nattokirai nattokirai commented Oct 6, 2015

Font management, shaping and rendering are really three separate pieces that are pretty distinct, especially the rendering part. I would keep rendering separate.

Note that you really need more than just "font selection", you need a way of managing font resources efficiently.

@retep998
Copy link

@retep998 retep998 commented Oct 6, 2015

Do note that on Windows, DirectWrite handles all aspects of dealing with fonts including management shaping and rendering.

I'm currently polishing up the dwrite bindings so I can bump them on crates.io soon.

@nattokirai
Copy link

@nattokirai nattokirai commented Oct 6, 2015

Gecko uses harfbuzz for shaping on all platforms with the exception of Apple-flavored TrueType fonts which require CoreText shaping. Using DirectWrite to do shaping will work just fine but you may not end up with consistent results across platforms and you increase your per-platform testing requirements.

@Yoric
Copy link
Contributor

@Yoric Yoric commented Oct 13, 2015

I'm currently working on #7029, so I may not have time to get started on this before a few weeks.

@flacerdk
Copy link
Contributor

@flacerdk flacerdk commented Oct 2, 2016

@Yoric: Are you currently working on this? Or is anyone else? I've been looking into how to improve font selection on Linux (see e.g. #12944), but I figured an ideal solution would likely involve something like this. I'd volunteer myself, but testing on Windows and OS X would be very time-consuming for me. I'd be willing to look into handling Fontconfig, though.

@Yoric
Copy link
Contributor

@Yoric Yoric commented Oct 2, 2016

Sorry about that, I've been asked to work on other stuff and I forgot to mention it. So, anyone, feel free to pick this up.

@shinglyu shinglyu mentioned this issue Aug 23, 2017
1 of 6 tasks complete
bors-servo added a commit that referenced this issue Feb 22, 2018
 Lazy load fonts in a FontGroup

The first commit message explains this so I'll just copy it here:

---

This is a step towards fixing #17267. To fix that, we need to be able to
try various different fallback fonts in turn, which would become
unweildy with the prior eager-loading strategy.

Prior to this change, FontGroup loaded up all Font instances, including
the fallback font, before any of them were checked for the presence of
the glyphs we're trying to render.

So for the following CSS:

    font-family: Helvetica, Arial;

The FontGroup would contain a Font instance for Helvetica, and a Font
instance for Arial, and a Font instance for the fallback font.

It may be that Helvetica contains glyphs for every character in the
document, and therefore Arial and the fallback font are not needed at
all.

This change makes the strategy lazy, so that we'll only create a Font
for Arial if we cannot find a glyph within Helvetica. I've also
substantially refactored the existing code in the process and added
some documentation along the way.

---

I've added some tests in the second commit, but it required quite a bit of gymnastics to make it possible to write such a test. I'm not sure if the added complexity to the production code is worth it?

On the other hand, having this infrastructure in place may be useful for testing future changes in this area, and also possibly brings us a step closer to extracting a library as discussed in #4901. (What I mean by that is: it reduces coupling between `FontCacheThread` and `FontContext` -- the latter would have a place in such a library, the former wouldn't.)

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/20021)
<!-- Reviewable:end -->
bors-servo added a commit that referenced this issue Feb 22, 2018
 Lazy load fonts in a FontGroup

The first commit message explains this so I'll just copy it here:

---

This is a step towards fixing #17267. To fix that, we need to be able to
try various different fallback fonts in turn, which would become
unweildy with the prior eager-loading strategy.

Prior to this change, FontGroup loaded up all Font instances, including
the fallback font, before any of them were checked for the presence of
the glyphs we're trying to render.

So for the following CSS:

    font-family: Helvetica, Arial;

The FontGroup would contain a Font instance for Helvetica, and a Font
instance for Arial, and a Font instance for the fallback font.

It may be that Helvetica contains glyphs for every character in the
document, and therefore Arial and the fallback font are not needed at
all.

This change makes the strategy lazy, so that we'll only create a Font
for Arial if we cannot find a glyph within Helvetica. I've also
substantially refactored the existing code in the process and added
some documentation along the way.

---

I've added some tests in the second commit, but it required quite a bit of gymnastics to make it possible to write such a test. I'm not sure if the added complexity to the production code is worth it?

On the other hand, having this infrastructure in place may be useful for testing future changes in this area, and also possibly brings us a step closer to extracting a library as discussed in #4901. (What I mean by that is: it reduces coupling between `FontCacheThread` and `FontContext` -- the latter would have a place in such a library, the former wouldn't.)

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/20021)
<!-- Reviewable:end -->
@atouchet
Copy link
Contributor

@atouchet atouchet commented May 8, 2020

Does font-kit take care of this?

@jdm
Copy link
Member

@jdm jdm commented May 8, 2020

It takes care of some of it. I don't see a good reason for this issue to remain open, though, since we have many of the requirements implemented in Servo.

@jdm jdm closed this May 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
10 participants
You can’t perform that action at this time.