servo / font-kit Goto Github PK
View Code? Open in Web Editor NEWA cross-platform font loading library written in Rust
License: Apache License 2.0
A cross-platform font loading library written in Rust
License: Apache License 2.0
Currently, fonts for sans/serif/monospace/fantasy/etc. are hardcoded for Win and Mac. And there are only one font for each type.
The problem is that it doesn't guarantee that this font is present. For example, a default Win10 contains the Impact font, but the one used by TravisCI - doesn't.
Here is the list of font families available in a Travis instance:
Not sure with one we can use as fantasy. Maybe Ink Free?
There may be more cases to reproduce this, but this is easily repeatable:
thread 'main' panicked at 'index 89 out of range for slice of length 88', src/libcore/slice/mod.rs:2349:5
stack backtrace:
0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
1: std::sys_common::backtrace::_print
at src/libstd/sys_common/backtrace.rs:71
2: std::panicking::default_hook::{{closure}}
at src/libstd/sys_common/backtrace.rs:59
at src/libstd/panicking.rs:210
3: std::panicking::default_hook
at src/libstd/panicking.rs:225
4: std::panicking::rust_panic_with_hook
at src/libstd/panicking.rs:488
5: std::panicking::continue_panic_fmt
at src/libstd/panicking.rs:395
6: rust_begin_unwind
at src/libstd/panicking.rs:322
7: core::panicking::panic_fmt
at src/libcore/panicking.rs:95
8: core::slice::slice_index_len_fail
at src/libcore/slice/mod.rs:2349
9: <core::ops::range::Range<usize> as core::slice::SliceIndex<[T]>>::index
at /rustc/96d1334e567237b1507cd277938e7ae2de75ff51/src/libcore/slice/mod.rs:2514
10: core::slice::<impl core::ops::index::Index<I> for [T]>::index
at /rustc/96d1334e567237b1507cd277938e7ae2de75ff51/src/libcore/slice/mod.rs:2331
11: font_kit::canvas::Canvas::blit_from_with
at /home/zac/projects/font-kit/src/canvas.rs:153
12: font_kit::canvas::Canvas::blit_from
at /home/zac/projects/font-kit/src/canvas.rs:89
13: font_kit::loaders::freetype::Font::rasterize_glyph
at /home/zac/projects/font-kit/src/loaders/freetype.rs:754
14: <font::fontkit::FontKitRasterizer as font::Rasterize>::get_glyph
at font/src/fontkit/mod.rs:144
15: alacritty::renderer::GlyphCache::get::{{closure}}
at src/renderer/mod.rs:276
16: <std::collections::hash::map::Entry<'a, K, V>>::or_insert_with
at /rustc/96d1334e567237b1507cd277938e7ae2de75ff51/src/libstd/collections/hash/map.rs:2695
17: alacritty::renderer::GlyphCache::get
at src/renderer/mod.rs:273
18: alacritty::renderer::GlyphCache::load_glyphs_for_font
at src/renderer/mod.rs:204
19: alacritty::renderer::GlyphCache::new
at src/renderer/mod.rs:195
20: alacritty::display::Display::new_glyph_cache::{{closure}}
at src/display.rs:250
21: alacritty::renderer::QuadRenderer::with_loader
at src/renderer/mod.rs:713
22: alacritty::display::Display::new_glyph_cache
at src/display.rs:250
23: alacritty::display::Display::new
at src/display.rs:156
24: alacritty::run
at src/main.rs:127
25: alacritty::main
at src/main.rs:79
26: std::rt::lang_start::{{closure}}
at /rustc/96d1334e567237b1507cd277938e7ae2de75ff51/src/libstd/rt.rs:74
27: std::panicking::try::do_call
at src/libstd/rt.rs:59
at src/libstd/panicking.rs:307
28: __rust_maybe_catch_panic
at src/libpanic_unwind/lib.rs:102
29: std::rt::lang_start_internal
at src/libstd/panicking.rs:286
at src/libstd/panic.rs:398
at src/libstd/rt.rs:58
30: std::rt::lang_start
at /rustc/96d1334e567237b1507cd277938e7ae2de75ff51/src/libstd/rt.rs:74
31: main
32: __libc_start_main
33: _start
Logging values in the loop:
Start 0 width 3 bytes 3 len 88
Start 8 width 3 bytes 3 len 88
Start 16 width 3 bytes 3 len 88
Start 24 width 3 bytes 3 len 88
Start 32 width 3 bytes 3 len 88
Start 40 width 3 bytes 3 len 88
Start 48 width 3 bytes 3 len 88
Start 56 width 3 bytes 3 len 88
Start 64 width 3 bytes 3 len 88
Start 72 width 3 bytes 3 len 88
Start 80 width 3 bytes 3 len 88
<panic 89 out of range>
All calls to raster_bounds
after the first rasterize_glyph
return very small bounds like 1x1. See this gist for reproduction (it's just the render-glyph
example with the raster_bounds
and rasterize_glyph
parts repeated.
https://gist.github.com/wezm/cecc28f3446d73dc2ee3a1822fd15f89
Reproduced with multiple fonts on the following platforms with font-kit 159c016:
use font_kit::source::SystemSource;
use font_kit::properties::*;
use font_kit::family_name::FamilyName;
SystemSource::new().select_best_match(&[FamilyName::Serif], &Properties::default()).unwrap()
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: NotFound', libcore/result.rs:1009:5
Is it possible to add the Canvas from font-kit to to the Display List Builder, and how would I go about doing that?
My question has been spurred on by servo/webrender#3222 and looking to see it this could have any positive effect on RAM consumption.
Like fc-list
.
~> fc-match fantasy
impact.ttf: "Impact" "Regular"
But font-kit returns Arial for some reasons.
Any type of shaping will require access to OpenType table data.
I think the model of what we need is getTableData from SkTypeface. This signature allocates and copies, but the alternative is to have more complex lifetime invariants.
For CoreText, the underlying function is CTFontCopyTable, which appears to be misnamed, as it seems to return a CFDataRef
. It might be possible to use that to avoid copying. But that would require designing appropriate types; if the data reference were an associated type, it would make Font
not object-safe, which I think is undesirable.
I may be able to work around this, possibly for a while, by using copy_font_data
and using HarfBuzz-provided functions for table access, so I'm not sure how urgent this is.
The font loader should have an "Id" type that efficiently impl's PartialEq and Hash, that is guaranteed (with reasonably high confidence) to be equal when the fonts are equal. Such an Id is necessary for caching of any resource associated with a font (rendered glyphs, HarfBuzz font and face objects, table data, coverage bitmaps). Currently font-kit tends to use PostScript name for this purpose, but it's easy to see how this might fail uniqueness (for example, when a web font stack contains a different version of a font already present in the system). It should also be cheap to compute, because we will need it for every typeface that comes back from a fallback query.
Skia's SkTypeface has a uniqueID
method. Its implementation largely rests on using a cache - when going from a native font object (for example, a DirectWrite font) to an SkTypeface, there's a comparison procedure to compare equality with existing fonts in the cache. An example for DirectWrite shows a fairly complex set of heuristics - it starts with pointer equality and other checks based on the way the font is loaded, then compares a bunch of name strings.
I'm not at all convinced font-kit should be based on a cache the way Skia does it, but it might be useful as a reference.
In any case, we should export the type, then implementations can refine the tactics to compare equality efficiently and reliably, without breaking client code - for example, an initial implementation can be based on PostScript name. This is one reason I agree with @pcwalton it should be a type and not a small integer. Another reason is so the Debug formatting is informative.
Because of a missing implementation for blit_from A8 -> Rgb24
in src/canvas.rs
.
Workaround is to specify an AA type which matches the canvas format, e.g. SubpixelAa
for Rgb24
.
Hello.
WHile trying to build amethyst for a few tests, I ended up having compilation errors on font-kit. Looks like many types are mismatching on this device. I'll be attaching a log as a file as it takes quite a bit of vertical space.
Here's my current rust compiler toolchains
installed toolchains
--------------------
stable-armv7-unknown-linux-gnueabihf
nightly-armv7-unknown-linux-gnueabihf
active toolchain
----------------
stable-armv7-unknown-linux-gnueabihf (default)
rustc 1.29.2 (17a9dc751 2018-10-05)
Thank you and have a nice day.
cargo test
fails with rust 1.33.0 (2aa4c46cf 2019-02-28), on Ubuntu Linux x86_64 18.04.2, although both examples (list-fonts and render-glyph) work fine:
$ RUST_BACKTRACE=1 cargo test --release
Finished release [optimized] target(s) in 0.10s
Running target/release/deps/font_kit-1114c272e27097b8
running 30 tests
test test::analyze_file ... ok
test loaders::freetype::test::get_pcf_postscript_name ... ok
test test::get_empty_glyph_outline ... ok
test test::analyze_bytes ... ok
test test::fail_to_lookup_font_by_postscript_name ... ok
test test::get_font_data ... ok
test test::get_font_metrics ... ok
test test::get_font_full_name ... ok
test test::get_glyph_count ... ok
test test::get_font_properties ... ok
test test::get_fully_hinted_glyph_outline ... ok
test test::get_glyph_outline_eb_garamond_exclam ... ok
test test::get_glyph_outline_inconsolata_J ... ok
test test::get_glyph_advance_and_origin ... ok
test test::get_glyph_for_char ... ok
test test::load_font_from_file ... ok
test test::load_font_from_memory ... ok
test test::load_fonts_from_opentype_collection ... ok
test test::get_glyph_typographic_bounds ... ok
test test::lookup_all_fonts_in_a_family_in_system_font_directories ... ignored
test test::get_glyph_outline ... ok
test test::get_vertically_hinted_glyph_outline ... ok
test test::lookup_font_by_postscript_name ... ok
test test::lookup_all_fonts_in_a_family ... FAILED
test test::lookup_single_bold_font ... FAILED
test test::lookup_single_italic_font ... FAILED
test test::lookup_single_regular_font ... ok
test test::rasterize_glyph_with_full_hinting ... ok
test test::rasterize_glyph_with_grayscale_aa ... ok
test test::rasterize_glyph_bilevel ... ok
failures:
---- test::lookup_all_fonts_in_a_family stdout ----
thread 'test::lookup_all_fonts_in_a_family' panicked at 'assertion failed: family.fonts().len() > 2', src/test.rs:96:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:39
1: std::sys_common::backtrace::_print
at src/libstd/sys_common/backtrace.rs:70
2: std::panicking::default_hook::{{closure}}
at src/libstd/sys_common/backtrace.rs:58
at src/libstd/panicking.rs:200
3: std::panicking::default_hook
at src/libstd/panicking.rs:209
4: std::panicking::rust_panic_with_hook
at src/libstd/panicking.rs:478
5: std::panicking::begin_panic
6: font_kit::test::lookup_all_fonts_in_a_family
7: <F as alloc::boxed::FnBox<A>>::call_box
at src/libtest/lib.rs:1475
at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libcore/ops/function.rs:231
at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/liballoc/boxed.rs:734
8: __rust_maybe_catch_panic
at src/libpanic_unwind/lib.rs:92
9: test::run_test::run_test_inner::{{closure}}
at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libstd/panicking.rs:276
at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libstd/panic.rs:388
at src/libtest/lib.rs:1430
---- test::lookup_single_bold_font stdout ----
thread 'test::lookup_single_bold_font' panicked at 'assertion failed: `(left == right)`
left: `"DejaVuSans"`,
right: `"DejaVuSans-Bold"`', src/test.rs:80:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:39
1: std::sys_common::backtrace::_print
at src/libstd/sys_common/backtrace.rs:70
2: std::panicking::default_hook::{{closure}}
at src/libstd/sys_common/backtrace.rs:58
at src/libstd/panicking.rs:200
3: std::panicking::default_hook
at src/libstd/panicking.rs:209
4: std::panicking::rust_panic_with_hook
at src/libstd/panicking.rs:478
5: std::panicking::continue_panic_fmt
at src/libstd/panicking.rs:385
6: std::panicking::begin_panic_fmt
at src/libstd/panicking.rs:340
7: font_kit::test::lookup_single_bold_font
8: <F as alloc::boxed::FnBox<A>>::call_box
at src/libtest/lib.rs:1475
at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libcore/ops/function.rs:231
at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/liballoc/boxed.rs:734
9: __rust_maybe_catch_panic
at src/libpanic_unwind/lib.rs:92
10: test::run_test::run_test_inner::{{closure}}
at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libstd/panicking.rs:276
at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libstd/panic.rs:388
at src/libtest/lib.rs:1430
---- test::lookup_single_italic_font stdout ----
thread 'test::lookup_single_italic_font' panicked at 'assertion failed: `(left == right)`
left: `"DejaVuSans"`,
right: `"DejaVuSans-Oblique"`', src/test.rs:90:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:39
1: std::sys_common::backtrace::_print
at src/libstd/sys_common/backtrace.rs:70
2: std::panicking::default_hook::{{closure}}
at src/libstd/sys_common/backtrace.rs:58
at src/libstd/panicking.rs:200
3: std::panicking::default_hook
at src/libstd/panicking.rs:209
4: std::panicking::rust_panic_with_hook
at src/libstd/panicking.rs:478
5: std::panicking::continue_panic_fmt
at src/libstd/panicking.rs:385
6: std::panicking::begin_panic_fmt
at src/libstd/panicking.rs:340
7: font_kit::test::lookup_single_italic_font
8: <F as alloc::boxed::FnBox<A>>::call_box
at src/libtest/lib.rs:1475
at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libcore/ops/function.rs:231
at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/liballoc/boxed.rs:734
9: __rust_maybe_catch_panic
at src/libpanic_unwind/lib.rs:92
10: test::run_test::run_test_inner::{{closure}}
at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libstd/panicking.rs:276
at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libstd/panic.rs:388
at src/libtest/lib.rs:1430
failures:
test::lookup_all_fonts_in_a_family
test::lookup_single_bold_font
test::lookup_single_italic_font
test result: FAILED. 26 passed; 3 failed; 1 ignored; 0 measured; 0 filtered out
error: test failed, to rerun pass '--lib'
Looks like a rendering canvas doesn't have an enough space.
>cargo run --example render-glyph -- ArialMT { 32
Finished dev [unoptimized + debuginfo] target(s) in 0.10s
Running `target\debug\examples\render-glyph.exe ArialMT { 32`
glyph 94:
▓▓██████
██████████
▒▒████▒▒
▓▓██▓▓
▓▓██▓▓
▓▓██▓▓
▓▓██▓▓
▓▓██▓▓
▓▓██▓▓
████▓▓
████▒▒
▒▒████▒▒
▒▒████▓▓
░░████████
░░████▒▒
░░████████
▒▒████▓▓
▒▒████▒▒
░░████▒▒
████▓▓
▓▓██▓▓
▓▓██▓▓
▓▓██▓▓
Works correctly on Linux. Not sure about macOS.
@pcwalton I'm not familiar with dwrite. Can you take a look?
So we can check which languages/scripts can be handled by this font.
This is very useful for the font fallback resolution, when we need to find a font that can be used to write a specified text.
Servo would like to implement CSS on top of font-kit. The spec (relevant bits below):
Source::select_family_by_name
looks like the appropriate API for looking up system fonts matching a given family name string. Some research is needed, to figure out whether the underlying APIs (fontconfig/CoreText/DirectWrite) of the respective default Source
for each supported platform behaves as CSS requires on these two points, or if can be configured to do so.
An alternative could be to enumerate all available fonts and their family names, and maintain a Rust (hash?) map where keys are normalized with default case fold. But I suspect this would have significant startup cost.
https://drafts.csswg.org/css-fonts/#font-family-casing
User agents must match these names case insensitively, using the "Default Caseless Matching" algorithm outlined in the Unicode specification [UNICODE]. This algorithm is detailed in section 3.13 entitled "Default Case Algorithms". Specifically, the algorithm must be applied without normalizing the strings involved and without applying any language-specific tailorings. The case folding method specified by this algorithm uses the case mappings with status field ‘C’ or ‘F’ in the CaseFolding.txt file of the Unicode Character Database [UNICODE].
[…]
Implementors should take care to verify that a given caseless string comparison implementation uses this precise algorithm and not assume that a given platform string matching routine follows it, as many of these have locale-specific behavior or use some level of string normalization [UAX15].
https://drafts.csswg.org/css-fonts/#font-style-matching
On systems containing fonts with multiple localized font family names, user agents must match any of these names independent of the underlying system locale or platform API used.
https://drafts.csswg.org/css-fonts/#family-name-value
Some font formats allow fonts to carry multiple localizations of the family name. User agents must recognize and correctly match all of these names independent of the underlying platform localization, system API used or document encoding:
The origin
argument translates the glyph in the CoreText loader but not the freetype one. In addition, the default seems to be the top-left alignment in freetype, but bottom-left in CoreText.
We're experiencing some strange issues when using fontkit and the Google font "Roboto-Thin"
When working with this font locally(localhost - http), everything works fine, but once we deploy our app to a production server(https), i.e. minimize, package(zip) and upload, the letter "a" in the Roboto-Thin font is gone.
I have done some console.log of the Fontkit.font object returned from this font. The letter "a" has acii code 97. If I understand the fontkit.font properly, I can see that characterSet entry 68 refers to 97. Then, when I look into the _glyphs array, I can see that the entry 68 has codePoints set to [97] on my localhost. However, on the https production server, the same _glyphs entry has codePoints set to an empty array(codePoints: []). I assume this is the reason why we can't see the letter "a" there.
In summary:
It's a very strange problem. Have you experienced this before, and do you have any tip on what the cause could be?
Thanks
Alf
AFAIU, this code returns only half of the char
.
The build breaks on Windows because dwrote published a patch version yesterday that changed an API signature. This issue is more for general information. I've asked them to yank it and republish under 0.6.
Servo would like to implement CSS on top of font-kit. This includes:
https://drafts.csswg.org/css-fonts/#font-matching-algorithm
A font is considered to support a given character if (1) the character is contained in the font's character map and (2) if required by the containing script, shaping information is available for that character.
Some legacy fonts may include a given character in the character map but lack the shaping information (e.g. OpenType layout tables or Graphite tables) necessary for correctly rendering text runs containing that character.
I think font.glyph_for_char(c).is_some()
implements (1). But how can (2) be achieved? I’m not quite sure what it means excatly, and I don’t see an obvious API in HarfBuzz either.
Clearly one of the trickier aspects to integrating with a text layout system is script aware fallback. Issue #28 is one way, provide metadata. The problem is, it's not really supported by platform text libraries.
What is supported, and used by most web browsers, is an API for choosing a fallback font based on a Unicode code point and other data, generally locale preferences. In CoreText, that's the not-well-documented CTFontCopyDefaultCascadeListForLanguages. In DirectWrite, it's IDWriteFontFallback with IDWriteTextAnalysisSource. In discussions with @pcwalton and further thought, I think the best thing to do is to implement an abstraction for those API's in font-kit.
This will change and increase the API surface of font-kit quite a bit. In particular, we need to adopt a locale representation, and have code to plumb that to platform API calls. I suggest we use fluent-locale-rs, as this has promise to be a standard across the Rust ecosystem.
Discussion is welcome, as is an offer to implement the functionality. However, I'm also quite willing to do it myself, especially as I expect this to interact with the design of the rest of skribo, including its API.
---- test::select_family_by_name_arial stdout ----
thread 'test::select_family_by_name_arial' panicked at 'assertion failed: `(left == right)`
left: `14`,
right: `8`', tests\select_font.rs:116:9
stack backtrace:
0: backtrace::backtrace::trace_unsynchronized
at C:\Program Files\Rust\.cargo\registry\src\github.com-1ecc6299db9ec823\backtrace-0.3.29\src\backtrace\mod.rs:66
1: std::sys_common::backtrace::_print
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libstd\sys_common\backtrace.rs:47
2: std::sys_common::backtrace::print
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libstd\sys_common\backtrace.rs:36
3: std::panicking::default_hook::{{closure}}
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libstd\panicking.rs:200
4: std::panicking::default_hook
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libstd\panicking.rs:211
5: std::panicking::rust_panic_with_hook
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libstd\panicking.rs:477
6: std::panicking::continue_panic_fmt
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libstd\panicking.rs:384
7: std::panicking::begin_panic_fmt
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libstd\panicking.rs:339
8: select_font::test::select_family_by_name_arial
at .\tests\select_font.rs:116
9: select_font::test::select_family_by_name_arial::{{closure}}
at .\tests\select_font.rs:114
10: core::ops::function::FnOnce::call_once<closure,()>
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\src\libcore\ops\function.rs:231
11: alloc::boxed::{{impl}}::call_once<(),FnOnce<()>>
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\src\liballoc\boxed.rs:766
12: panic_unwind::__rust_maybe_catch_panic
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libpanic_unwind\lib.rs:82
13: std::panicking::try
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\src\libstd\panicking.rs:275
14: std::panic::catch_unwind
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\src\libstd\panic.rs:394
15: test::run_test::run_test_inner::{{closure}}
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libtest\lib.rs:1466
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
failures:
test::select_family_by_name_arial
test result: FAILED. 8 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
error: test failed, to rerun pass '--test select_font'
CoreGraphics uses a bottom left origin. This shouldn't be exposed to the user.
Fontconfig's Source
checks that families list isn't empty, but other implementations aren't. I think this should be unified. But not sure in what way.
I would like to get bbox for glyphs of font as described at https://www.freetype.org/freetype2/docs/glyphs/glyphs-3.html#section-2
Is there any way to do it?
How to retrieve a colored emoji from a font?
We have Loader::outline
, but for emojis we have to return an SVG? I have no idea how this is implemented in existing software...
servo-fontconfig
is pretty heavy (as a build dependency), since it uses bundled C sources:
So to build font-kit on Linux we have to download ~4MiB of useless code, because it will use system libraries anyway.
There are no alternatives for now, but it's still a problem, imho.
extern crate font_kit;
fn main() {
let names = vec![font_kit::family_name::FamilyName::Title("Arial".to_string())];
let properties = font_kit::properties::Properties {
style: font_kit::properties::Style::Normal,
weight: font_kit::properties::Weight::BOLD,
stretch: font_kit::properties::Stretch::NORMAL,
};
let handle = font_kit::source::SystemSource::new().select_best_match(&names, &properties).unwrap();
println!("{:?}", handle); // Path { path: "/usr/share/fonts/corefonts/arial.ttf", font_index: 0 }
}
~> fc-match 'Arial :weight=700' --format="%{file}\n"
/usr/share/fonts/corefonts/arialbd.ttf
At least on CoreText (haven't tested the other loaders), the glyph_for_char method returns Some(0)
instead of None
for codepoints missing from the cmap.
I'm not sure this will be my primary method for determining script coverage for itemization, but I figured I'd record it as something that should be fixed.
Will this library support RTL languages?
The substitutions happen one character at a time in this library, so I'm not sure how this could be achieved. Yet getting the correct glyphs is important for languages that have joining characters.
Motivation: alacritty/alacritty#957
Freetype/Fontconfig: ?
Can't be done until cocoa, core-foundation, core-graphics, and core-text are published to crates.io. Also dwrote-rs needs the additions to be merged.
This is actually an architectural question about whether layout based on font-kit should be sensitive to font-size or whether layout should be considered scale-invariant and scaling should strictly be a rendering question.
In any case, the advance
method on Font
only gives access to font-unit advance, without any way to access the hdmx
table.
The point_size
argument to rasterize_glyph
(and raster_bounds
) is a scalar, but in general we might need an affine transform (to apply fake-italic). If we used a full 3x2 affine, this would also subsume the origin
argument.
Is there a way to get a suggested baseline from Metrics? Right now I'm just using:
(fontsize-in-px / (ascent + descent)) * ascent
I don't see anything wrong with using what I have but just wondering if that is the correct approach.
Might be Windows-specific.
Minimal repro:
let font = SystemSource::new().select_by_postscript_name("ArialMT")
.unwrap()
.load()
.unwrap();
let glyph_id = font.glyph_for_char(' ').unwrap();
font.rasterize_glyph(
&mut canvas,
glyph_id,
font_size,
&Point2D::zero(),
HintingOptions::Vertical(font_size),
RasterizationOptions::GrayscaleAa
); // <--- Panic
Here's the backtrace:
thread 'main' panicked at 'assertion failed: hr == 0', C:\Users\foobar\.cargo\registry\src\github.com-1ecc6299db9ec823\dwrote-0.5.1\src\glyph_run_analysis.rs:72:13
stack backtrace:
0: std::sys::windows::backtrace::set_frames
at C:\projects\rust\src\libstd\sys\windows\backtrace\mod.rs:104
1: std::sys::windows::backtrace::set_frames
at C:\projects\rust\src\libstd\sys\windows\backtrace\mod.rs:104
2: std::sys_common::backtrace::_print
at C:\projects\rust\src\libstd\sys_common\backtrace.rs:71
3: std::sys_common::backtrace::_print
at C:\projects\rust\src\libstd\sys_common\backtrace.rs:71
4: std::panicking::default_hook::{{closure}}
at C:\projects\rust\src\libstd\panicking.rs:211
5: std::panicking::default_hook
at C:\projects\rust\src\libstd\panicking.rs:227
6: std::panicking::rust_panic_with_hook
at C:\projects\rust\src\libstd\panicking.rs:475
7: std::panicking::begin_panic<str*>
at C:\projects\rust\src\libstd\panicking.rs:409
8: dwrote::glyph_run_analysis::GlyphRunAnalysis::create_alpha_texture
at C:\Users\foobar\.cargo\registry\src\github.com-1ecc6299db9ec823\dwrote-0.5.1\src\glyph_run_analysis.rs:72
9: font_kit::loaders::directwrite::Font::rasterize_glyph
at C:\Users\foobar\.cargo\registry\src\github.com-1ecc6299db9ec823\font-kit-0.1.0\src\loaders\directwrite.rs:399
10: foobar::main
at .\src\main.rs:288
11: std::rt::lang_start::{{closure}}<()>
at C:\projects\rust\src\libstd\rt.rs:74
12: std::rt::lang_start_internal::{{closure}}
at C:\projects\rust\src\libstd\rt.rs:59
13: std::rt::lang_start_internal::{{closure}}
at C:\projects\rust\src\libstd\rt.rs:59
14: panic_unwind::__rust_maybe_catch_panic
at C:\projects\rust\src\libpanic_unwind\lib.rs:105
15: std::panicking::try
at C:\projects\rust\src\libstd\panicking.rs:289
16: std::panicking::try
at C:\projects\rust\src\libstd\panicking.rs:289
17: std::panicking::try
at C:\projects\rust\src\libstd\panicking.rs:289
18: std::rt::lang_start<()>
at C:\projects\rust\src\libstd\rt.rs:74
19: main
20: invoke_main
at f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:74
21: invoke_main
at f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:74
22: BaseThreadInitThunk
23: RtlUserThreadStart
error: process didn't exit successfully: `target\debug\foobar.exe` (exit code: 101)
Currently, when rendering a glyph on Linux using the FreeType renderer and RasterizationOptions::SubpixelAa
there is no LCD filtering.
It looks like this, with very noticeable color fringing:
To enable filtering with FreeType FT_Library_SetLcdFilter
should be set, but I don't know how that would work on other platforms.
The easiest solution would be to keep it transparent to the user and always use FT_LCD_FILTER_DEFAULT
with FreeType. I could try to make a pull request for that if this solution works for you.
On 32 bit linux with libfreetype6-dev 2.6.1-0.1ubuntu2.3
.
I am getting this error when compiling this library (as a dependency):
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:130:39
|
130 | font_data.len() as i64,
| ^^^^^^^^^^^^^^^^^^^^^^ expected i32, found i64
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:157:39
|
157 | mmap.len() as i64,
| ^^^^^^^^^^^^^^^^^ expected i32, found i64
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:194:61
|
194 | font_data.len() as u64,
| ^^^^^^^^^^^^^^^^^^^^^^ expected u32, found u64
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:196:61
|
196 | CHUNK_SIZE as u64);
| ^^^^^^^^^^^^^^^^^ expected u32, found u64
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:197:25
|
197 | if n_read < CHUNK_SIZE as u64 {
| ^^^^^^^^^^^^^^^^^ expected u32, found u64
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:219:39
|
219 | font_data.len() as i64,
| ^^^^^^^^^^^^^^^^^^^^^^ expected i32, found i64
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:243:39
|
243 | mmap.len() as i64,
| ^^^^^^^^^^^^^^^^^ expected i32, found i64
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:325:48
|
325 | (*self.freetype_face).face_flags & (FT_FACE_FLAG_FIXED_WIDTH as i64) != 0
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found i64
error[E0277]: no implementation for `i32 & i64`
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:325:46
|
325 | (*self.freetype_face).face_flags & (FT_FACE_FLAG_FIXED_WIDTH as i64) != 0
| ^ no implementation for `i32 & i64`
|
= help: the trait `std::ops::BitAnd<i64>` is not implemented for `i32`
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:337:59
|
337 | _ if ((*self.freetype_face).style_flags & (FT_STYLE_FLAG_ITALIC) as i64) != 0 => {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found i64
error[E0277]: no implementation for `i32 & i64`
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:337:57
|
337 | _ if ((*self.freetype_face).style_flags & (FT_STYLE_FLAG_ITALIC) as i64) != 0 => {
| ^ no implementation for `i32 & i64`
|
= help: the trait `std::ops::BitAnd<i64>` is not implemented for `i32`
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:401:45
|
401 | f32_to_ft_fixed_26_6(size),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found i64
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:523:72
|
523 | let mut point_position = Point2D::new(ft_fixed_26_6_to_f32(point_position.x),
| ^^^^^^^^^^^^^^^^ expected i64, found i32
help: you can cast an `i32` to `i64`, which will sign-extend the source value
|
523 | let mut point_position = Point2D::new(ft_fixed_26_6_to_f32(point_position.x.into()),
| ^^^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:524:72
|
524 | ft_fixed_26_6_to_f32(point_position.y));
| ^^^^^^^^^^^^^^^^ expected i64, found i32
help: you can cast an `i32` to `i64`, which will sign-extend the source value
|
524 | ft_fixed_26_6_to_f32(point_position.y.into()));
| ^^^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:543:60
|
543 | Ok(Rect::new(Point2D::new(ft_fixed_26_6_to_f32(metrics.horiBearingX),
| ^^^^^^^^^^^^^^^^^^^^ expected i64, found i32
help: you can cast an `i32` to `i64`, which will sign-extend the source value
|
543 | Ok(Rect::new(Point2D::new(ft_fixed_26_6_to_f32(metrics.horiBearingX.into()),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:544:60
|
544 | ft_fixed_26_6_to_f32(metrics.horiBearingY - metrics.height)),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i64, found i32
help: you can cast an `i32` to `i64`, which will sign-extend the source value
|
544 | ft_fixed_26_6_to_f32((metrics.horiBearingY - metrics.height).into())),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:545:59
|
545 | Size2D::new(ft_fixed_26_6_to_f32(metrics.width),
| ^^^^^^^^^^^^^ expected i64, found i32
help: you can cast an `i32` to `i64`, which will sign-extend the source value
|
545 | Size2D::new(ft_fixed_26_6_to_f32(metrics.width.into()),
| ^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:546:59
|
546 | ft_fixed_26_6_to_f32(metrics.height))))
| ^^^^^^^^^^^^^^ expected i64, found i32
help: you can cast an `i32` to `i64`, which will sign-extend the source value
|
546 | ft_fixed_26_6_to_f32(metrics.height.into()))))
| ^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:561:51
|
561 | Ok(Vector2D::new(ft_fixed_26_6_to_f32(advance.x), ft_fixed_26_6_to_f32(advance.y)))
| ^^^^^^^^^ expected i64, found i32
help: you can cast an `i32` to `i64`, which will sign-extend the source value
|
561 | Ok(Vector2D::new(ft_fixed_26_6_to_f32(advance.x.into()), ft_fixed_26_6_to_f32(advance.y)))
| ^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:561:84
|
561 | Ok(Vector2D::new(ft_fixed_26_6_to_f32(advance.x), ft_fixed_26_6_to_f32(advance.y)))
| ^^^^^^^^^ expected i64, found i32
help: you can cast an `i32` to `i64`, which will sign-extend the source value
|
561 | Ok(Vector2D::new(ft_fixed_26_6_to_f32(advance.x), ft_fixed_26_6_to_f32(advance.y.into())))
| ^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:628:41
|
628 | buffer.len() as i64) == 0 {
| ^^^^^^^^^^^^^^^^^^^ expected i32, found i64
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:716:20
|
716 | x: f32_to_ft_fixed_26_6(origin.x),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found i64
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:717:20
|
717 | y: f32_to_ft_fixed_26_6(origin.y),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found i64
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:722:41
|
722 | f32_to_ft_fixed_26_6(point_size),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found i64
error[E0308]: mismatched types
--> /home/matias/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.1.0/src/loaders/freetype.rs:981:43
|
981 | assert_eq!(FT_Set_Char_Size(face, ((*face).units_per_EM as i64) << 6, 0, 0, 0), 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found i64
I'm looking for a Source
method that will return a list of fonts that contain a specified character. I've tried to implement this via Loader::glyph_for_char
, but it's extremely slow. On my machine (Linux), with 212 font families, it takes up to 3 seconds to find a right font.
On the other hand, fontconfig can do this instantly:
> fc-list ":charset=672c"
/usr/share/fonts/droid/DroidSansFallback.ttf: Droid Sans Fallback:style=Regular
/usr/share/fonts/droid/DroidSansFallbackLegacy.ttf: Droid Sans Fallback:style=Regular
/usr/share/fonts/droid/DroidSansJapanese.ttf: Droid Sans Japanese:style=Regular
It takes no time at all. I don't know does it uses a cache or parses only font headers or else.
The problem is to find similar methods for Windows and Mac. And I'm not familiar with their API. @raphlinus do you have any suggestions?
I found GetFontUnicodeRanges
and ScriptGetCMap
, but I'm not sure how good they are. Also, both of them are not from DirectWrite.
Qt uses EnumFontFamiliesEx
.
The following program persistenly increases its memory usage.
use font_kit::source::SystemSource;
fn main() {
loop { SystemSource::new(); }
}
System details:
OS: Windows 10 1903
rustc 1.38.0-nightly (69656fa4c 2019-07-13)
How to reproduce:
repo: https://github.com/Aloxaf/silicon
Command: cargo run -- some_rust_source.rs -o test.png
Error:
thread 'main' panicked at 'this will panic.: PlatformError', src\libcore\result.rs:1051:5
BackTrace:
stack backtrace:
0: backtrace::backtrace::trace_unsynchronized
at C:\Program Files\Rust\.cargo\registry\src\github.com-1ecc6299db9ec823\backtrace-0.3.29\src\backtrace\mod.rs:66
1: std::sys_common::backtrace::_print
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libstd\sys_common\backtrace.rs:47
2: std::sys_common::backtrace::print
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libstd\sys_common\backtrace.rs:36
3: std::panicking::default_hook::{{closure}}
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libstd\panicking.rs:200
4: std::panicking::default_hook
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libstd\panicking.rs:214
5: std::panicking::rust_panic_with_hook
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libstd\panicking.rs:477
6: std::panicking::continue_panic_fmt
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libstd\panicking.rs:384
7: std::panicking::rust_begin_panic
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libstd\panicking.rs:311
8: core::panicking::panic_fmt
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libcore\panicking.rs:85
9: core::result::unwrap_failed<font_kit::error::GlyphLoadingError>
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\src\libcore\macros.rs:18
10: core::result::Result<(), font_kit::error::GlyphLoadingError>::expect<(),font_kit::error::GlyphLoadingError>
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\src\libcore\result.rs:879
11: silicon::font::PositionedGlyph::draw<closure>
at .\src\font.rs:286
12: silicon::font::FontCollection::draw_text_mut<image::dynimage::DynamicImage>
at .\src\font.rs:253
13: silicon::formatter::ImageFormatter::draw_line_number
at .\src\formatter.rs:177
14: silicon::formatter::ImageFormatter::format
at .\src\formatter.rs:230
15: silicon::run
at .\src\main.rs:48
16: silicon::main
at .\src\main.rs:76
17: std::rt::lang_start::{{closure}}<()>
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\src\libstd\rt.rs:64
18: std::rt::lang_start_internal::{{closure}}
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libstd\rt.rs:49
19: std::panicking::try::do_call<closure,i32>
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libstd\panicking.rs:296
20: panic_unwind::__rust_maybe_catch_panic
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libpanic_unwind\lib.rs:82
21: std::panicking::try
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libstd\panicking.rs:275
22: std::panic::catch_unwind
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libstd\panic.rs:394
23: std::rt::lang_start_internal
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\/src\libstd\rt.rs:48
24: std::rt::lang_start<()>
at /rustc/69656fa4cbafc378fd63f9186d93b0df3cdd9320\src\libstd\rt.rs:64
25: main
26: invoke_main
at d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
27: __scrt_common_main_seh
at d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
28: BaseThreadInitThunk
29: RtlUserThreadStart
error: process didn't exit successfully: `target\debug\silicon.exe main.rs -o test.png` (exit code: 101)
I identified the following in src\font.rs:286
as the problem:
self.font
.rasterize_glyph(
&mut canvas,
self.id,
self.size,
&FontTransform::identity(),
&origin,
HintingOptions::None,
RasterizationOptions::GrayscaleAa,
)
.expect("this will panic.");
The glyph rasterization using the DirectWrite loader seems to cut off the glyph on the right edge of the canvas. FreeType seems to work correctly but I run into the #14 issue and only the first glyph rasterized works.
Forcibly increasing the raster bound size in the render-glyph example seems to give the correct results.
Output of render-glyph example:
d:/projects/font-kit $ cargo run --example render-glyph -- "Calibri" "H" 24
Finished dev [unoptimized + debuginfo] target(s) in 0.21s
Running `target\debug\examples\render-glyph.exe` Calibri H 24
glyph 44:
████ ██
████ ██
████ ██
████ ██
████ ██
████ ██
████████████████████
████████████████████
████ ██
████ ██
████ ██
████ ██
████ ██
████ ██
████ ██
d:/projects/font-kit $ cargo run --example render-glyph -- "Calibri" "e" 24
Finished dev [unoptimized + debuginfo] target(s) in 0.19s
Running `target\debug\examples\render-glyph.exe` Calibri e 24
glyph 286:
░░████████▒▒
▒▒████████████▓▓
░░████ ▓▓██
▓▓██░░ ░░██
▓▓████████████████
▓▓████████████████
▓▓██░░
▓▓██▒▒
▒▒████▒▒ ██
▓▓██████████████
▒▒██████████░░
d:/projects/font-kit $ cargo run --features loader-freetype-default --example render-glyph -- "Calibri" "e" 24
Finished dev [unoptimized + debuginfo] target(s) in 5.50s
Running `target\debug\examples\render-glyph.exe Calibri e 24`
glyph 286:
░░░░▒▒░░░░
░░▒▒▓▓██████▓▓░░
░░▓▓██▓▓░░░░▒▒▓▓▓▓░░
░░██▓▓ ▒▒██▒▒
▓▓██░░ ░░██▓▓
▓▓██▒▒▒▒▒▒▒▒▒▒▓▓██▓▓
▓▓██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒
▓▓██░░
▓▓██▒▒
▒▒██▓▓░░ ░░░░
░░▓▓██▓▓▒▒▒▒▒▒▒▒▓▓░░
░░▒▒▓▓██████▓▓▒▒░░
░░░░░░░░░░
d:/projects/font-kit $ cargo run --features loader-freetype-default --example render-glyph -- "Calibri" "H" 24
Finished dev [unoptimized + debuginfo] target(s) in 0.18s
Running `target\debug\examples\render-glyph.exe Calibri H 24`
glyph 44:
░░░░ ░░░░
▓▓██░░ ░░██▓▓
▓▓██░░ ░░██▓▓
▓▓██░░ ░░██▓▓
▓▓██░░ ░░██▓▓
▓▓██░░ ░░██▓▓
▓▓██░░ ░░██▓▓
▓▓██▓▓▓▓▓▓▓▓▓▓▓▓▓▓██▓▓
▓▓██▓▓▓▓▓▓▓▓▓▓▓▓▓▓██▓▓
▓▓██░░ ░░██▓▓
▓▓██░░ ░░██▓▓
▓▓██░░ ░░██▓▓
▓▓██░░ ░░██▓▓
▓▓██░░ ░░██▓▓
▓▓██░░ ░░██▓▓
▓▓▓▓░░ ░░▓▓▓▓
░░░░ ░░░░
d:/projects/font-kit $ cargo run --example render-glyph -- "Calibri" "H" 24
Compiling font-kit v0.1.0 (D:\projects\font-kit)
Finished dev [unoptimized + debuginfo] target(s) in 1.70s
Running `target\debug\examples\render-glyph.exe Calibri H 24`
glyph 44:
████ ████
████ ████
████ ████
████ ████
████ ████
████ ████
██████████████████████
██████████████████████
████ ████
████ ████
████ ████
████ ████
████ ████
████ ████
████ ████
d:/projects/font-kit $ cargo run --example render-glyph -- "Calibri" "e" 24
Finished dev [unoptimized + debuginfo] target(s) in 0.18s
Running `target\debug\examples\render-glyph.exe Calibri e 24`
glyph 286:
░░████████▒▒
▒▒████████████▓▓
░░████ ▓▓██▒▒
▓▓██░░ ░░██▓▓
▓▓████████████████▓▓
▓▓████████████████▓▓
▓▓██░░
▓▓██▒▒
▒▒████▒▒ ██▒▒
▓▓██████████████▒▒
▒▒██████████░░
Compiling font-kit v0.1.0 (/shareddata/share/Prog/Rust/font-kit)
Finished dev [unoptimized + debuginfo] target(s) in 34.28s
Running `target/debug/examples/list-fonts`
Loading fonts… 242 / 248 [====================================================================================>--] 97.58 % 142.13/s 0s zsh: segmentation fault (core dumped) cargo run --example list-fonts
It would be nice, if you could add me as a collaborator to this project. At least temporarily.
Currently, I'm trying to maintain my own fork, but it's troublesome, since there are a lot of changes/fixes and most of them are depending on each other. And the patches review process is pretty slow at the moment.
The current fantasy-style font for Windows is hardcoded as Papyrus, but there are no such font. At least on a default Win10 machine.
It creates a memory-mapped buffer from a file, and this file can be modified by any other process on the computer or even another thread in the same executable, but it isn't marked unsafe.
This is exactly why Mmap::map
itself is unsafe.
extern crate font_kit;
fn main() {
let names = vec![
font_kit::family_name::FamilyName::Title("Invalid".to_string()),
font_kit::family_name::FamilyName::Title("Times New Roman".to_string()),
];
let properties = font_kit::properties::Properties::default();
let handle = font_kit::source::SystemSource::new().select_best_match(&names, &properties).unwrap();
println!("{:?}", handle);
}
Prints: Path { path: "/usr/share/fonts/corefonts/arial.ttf", font_index: 0 }
Works correctly on Windows. Didn't tested on macOS.
WebRender and Raqote don't need any of the font matching/searching code so it would be nice to have a separate font rendering crate.
There are font families like MS Shell Dlg 2
which will not be resolved at the moment:
> cargo run --example match-font -- "MS Shell Dlg 2"
Error: NotFound
I'm not sure if it's possible to resolve them via winapi, but they are defined here: Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes\
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.