razrfalcon / fontdb Goto Github PK
View Code? Open in Web Editor NEWA simple, in-memory font database with CSS-like queries.
License: MIT License
A simple, in-memory font database with CSS-like queries.
License: MIT License
Hi,
I'm filing this issue as a API feature request and question. If concluded to be reasonable, I'd be more than happy to do submit an implementation, but I'm unclear about the best API for the use-case:
I'm using fontdb with the memmap feature enabled, on a file system on macOS, Linux and Windows. Initially loading/scanning the system fonts works great with load_system_fonts
. Later, when I decide to pick a particular font and fontdb returns the Face ID, the with_face_data
API allows accessing the data temporarily.
When rendering text then, I'm using ttf_parser and rustybuzz (indirectly via femtovg) and that works great. But whenever rendering text, there is a chance of encountering uncached glyphs or (more likely) access to the opentype tables, etc. is required for use with rustybuzz. With the current fontdb API that means that either every time a new temporary file mapping needs to be created/destroyed (with_face_data
) or the entire font data needs to be duplicated in memory (copied into a Vec<u8>
).
I'd like to figure out what the right API would be for fontdb to offer a way to make fontdb persist a file mapping for a given face id, in a way that for example fontdb could return for example an Arc<dyn AsRef<[u8]>>
(or basically an Arc
with the traits that memmap2::Mmap
implements).
I thought of a function like fn shared_face_source(&mut self, id: ID) -> Option<(Arc<dyn AsRef<[u8]>>, u32>)
, but I think implementation wise that wouldn't fit well with the existing Vec<FaceInfo>
or more specifically the public Source
enum. While that could in theory hold something like a SharedBinary(Box<dyn AsRef<[u8]>>)
variant, it doesn't work in practice because Source
also implements Clone
.
So I'm curious: Is this a feature that you'd be willing to generally accept?
If yes, can you think of a way to implement this without breaking API compatibility?
If API compatibility is okay to break, what API would be acceptable?
Any input would be greatly appreciated - and as said: I'd be happy to get my hands dirty on an implementation.
std::fs::read_dir
is pretty slow and allocates a lot.
This lib includes fn set_serif_family
etc. but has no default assignments, which may be useful in lieu of a full fontconfig
implementation.
Font-kit does do this, here.
P.S. close as "out of scope" if you like; this isn't clear from the README.
Database::load_system_fonts
use predefined paths but it's a bit limited
some distros like NixOS don't use that path and users may configure their own fonts to other custom path
but I think you don't prefer have a native fontconfig dependency (me neither)
However, I recently make fontconfig-parser it's not perfect but it can parse dir
and include
and that's enough to get all font paths here is list all installed fonts example
I'll send PR if you like this
While this is issue is being discussed on lapce/lapce#2748 ,
could we have some opinion on fontdb-0.14.1 used in https://github.com/lapce/lapce 0.3.1 about the error, "no default font found"
Same problem was found on some linux distros, but we can find a way of fixing it on FreeBSD.
Any help is welcome,
Thanks
(Typst user here, no experience with Rust)
Typst 0.9 uses now fontdb, but still doesn't find all the fonts on my linux box.
strace -f typst fonts
openat(AT_FDCWD, "/etc/fonts/fonts.conf", O_RDONLY|O_CLOEXEC) = 3
statx(3, "", AT_STATX_SYNC_AS_STAT|AT_EMPTY_PATH, STATX_ALL, {stx_mask=STATX_ALL|STATX_MNT_ID, stx_attributes=0, stx_mode=S_IFREG|0644, stx_size=2940, ...}) = 0
read(3, "<?xml version=\"1.0\"?>\n<!DOCTYPE "..., 2940) = 2940
read(3, "", 32) = 0
close(3) = 0
statx(AT_FDCWD, "conf.d", AT_STATX_SYNC_AS_STAT, STATX_ALL, 0x7fff2d98bb80) = -1 ENOENT (No such file or directory)
#ls /etc/fonts/conf.d/
10-hinting-slight.conf
10-scale-bitmap-fonts.conf
10-yes-antialias.conf
11-lcdfilter-default.conf
20-unhint-small-dejavu-lgc-sans-mono.conf
20-unhint-small-dejavu-lgc-sans.conf
20-unhint-small-dejavu-lgc-serif.conf
20-unhint-small-dejavu-sans-mono.conf
20-unhint-small-dejavu-sans.conf
...
It seems to me that the
<include ignore_missing="yes">conf.d</include>
line of /etc/fonts/fonts.conf
is not interpreted in the right way, i.e., relative to the dir where fonts.conf
is.
The same happens with `$HOME/.config/fontconfig/{fonts.conf,conf.d/}
I'm using fontdb with egui crate, it's FontDefinitions
need a string key to store font face data, I think the ID
type is a prefect unique identifier for font face, but for now, because the internal u32
is private, the only way I can convert it to a string is using the Debug
trait(format!("{id:?}")
). it works well, but kind of weird……
So can we add a ToString
or Display
impl for ID
? With some document like:
We only promise that unequal IDs don't output the same string, but does not make any guarantees about the format/content of output string.
or something like this, to guarantee non-breaking changes when modifying the internal implementation.
This may be do to my own misunderstanding of fonts / this particular font, but preliminary investigation seems to suggest that fontdb ignores variable fonts (or at least, only takes a look at one variation).
https://fonts.google.com/specimen/Raleway specifically Raleway-VariableFont_wght.ttf
It looks like this only gets detected as "Raleway Thin" whereas ExtraLight, Light etc seem to be missing completely, causing the query
functionality to skip over all of those.
When running my app, I found strange is_file
in flamegraph(look at the right side of flamegraph)
Path.is_file() - get file metadata from disk which is slow and redundant, because DirEntry already read if this is file or not
Entire function load_system_fonts
takes 7.46% time of running app and is_file
0.91%, so changing this code will give free 12% performance boost.
The only thing that needs to be changed is to change from - https://github.com/RazrFalcon/fontdb/blob/c3274d016cad92fac744d76a91e4554fe51c5745/src/lib.rs#L315C2-L318
let path = entry.path();
if path.is_file() {
} else if path.is_dir() {
}
into
let file_type = entry.file_type();
if file_type.is_file() {
} else if file_type.is_dir() {
}
I think it's worth considering enabling the fontconfig
feature be enabled by default. Without the fontconfig
feature enabled, fontdb
is unable to discover system fonts on NixOS (#20). Enabling the fontconfig
feature by default would make dependents easier to work with on NixOS, and would prevent opening an issue to enable the feature for each dependent that wishes to support NixOS (see pop-os/cosmic-text#167).
As an alternative to enabling the fontconfig
feature by default, a note could be added to README.md
to inform users that enabling the feature is more portable.
Any thoughts on this?
Hello there
I'm using this API to load a local font:
.load_font_file("./font/UbuntuMono-Regular.ttf")
.unwrap();
But I don't know how to get its ID, I want to check its family name etc. Does it make sense to let this function return the ID?
We need like 1% of it's features and we can greatly improve performance by parsing only the necessary data.
I'm currently looking to somewhat replicating the font lookup a browser does, and I stumbled upon this crate. However it seems to only be able to match against the family name rather than the full name. Is this something that you would consider adding, or that I could do a Pull Request for?
My issue: Browsers allow you to provide a custom name for a font file and even do not expose the default provided by the file content font. So for something that mimics browser or rendering CSS it will be required to override the font family name when loading specific file.
It would be great to have an API to provide the custom family name for the font face.
In the CSS Fonts Module Level 3 spec (see https://www.w3.org/TR/2018/REC-css-fonts-3-20180920/#font-family-casing), case-insensitive, folding matching of font family names is required. Currently, font family names in fontdb are matched by string equality.
For example, "FOO sans" does not match "Foo Sans" and "massanzug serif" does not match "Maßanzug Serif" (examples from query tests, see draft PR for query logic rewrite).
Using standard DejaVu system fonts:
$ fc-list
...
/usr/share/fonts/dejavu/DejaVuSans-Oblique.ttf: DejaVu Sans:style=Oblique
Properties detected by fontdb
:
name | family | style | weight | stretch | monospace | path | index |
---|---|---|---|---|---|---|---|
DejaVuSans-Oblique | DejaVu Sans | Italic | Weight(400) | Normal | FALSE | /usr/share/fonts/dejavu/DejaVuSans-Oblique.ttf | 0 |
For long running apps this is not an issue, but for small CLI tools (like resvg) loading all system fonts is way too slow.
Meaning we have to be able to dump the database to a file and then load it back.
To do so, we have to figure out:
This is a tracking issue for the bug described in #40, opened since the mentioned PR was auto-closed.
A patch on top of v0.11.2 is available at #40 (comment).
Alternatively, a refactoring/rewrite of the querying logic is being considered, for which a separate PR will be opened once it's ready.
Currently, fontdb
takes the first Family entry in the name
table as a font family name. We should prefer English.
I hope that this is to some extent in scope of fontdb, feel free to close otherwise.
The default families in fontdb are coded to Arial, etc. as documented. It would be nice if fontdb, when the fontconfig feature is enabled, would read and interpret the settings from fontconfig to determine the fonts that alias "Sans Serif, "Serif", "Cursive", etc.
Have to find a way to get a user dir without winapi...
When adding a FaceInfo entry to the database using Database::push_face_info, the corresponding FaceInfo ID is auto-generated.
It would be useful, especially for testing, to return that auto-generated ID from push_face_info, to be able to reliably identify the newly inserted entry.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.