Mirror of https://gitlab.redox-os.org/redox-os/rusttype

Overview

RustType

crates.io docs.rs

RustType is a pure Rust alternative to libraries like FreeType.

The current capabilities of RustType:

  • Reading OpenType formatted fonts and font collections. This includes *.ttf as well as *.otf font files.
  • Retrieving glyph shapes and commonly used properties for a font and its glyphs.
  • Laying out glyphs horizontally using horizontal and vertical metrics, and glyph-pair-specific kerning.
  • Rasterising glyphs with sub-pixel positioning using an accurate analytical algorithm (not based on sampling).
  • Managing a font cache on the GPU with the gpu_cache module. This keeps recently used glyph renderings in a dynamic cache in GPU memory to minimise texture uploads per-frame. It also allows you keep the draw call count for text very low, as all glyphs are kept in one GPU texture.

Notable things that RustType does not support yet:

  • Font hinting.
  • Ligatures of any kind.
  • Some less common TrueType sub-formats.
  • Right-to-left and vertical text layout.

Testing & examples

Heavier examples, tests & benchmarks are in the ./dev directory. This avoids dev-dependency feature bleed.

Run all tests with cargo test --all --all-features.

Run examples with cargo run --example <NAME> -p dev

Getting Started

To hit the ground running with RustType, look at dev/examples/ascii.rs supplied with the crate. It demonstrates loading a font file, rasterising an arbitrary string, and displaying the result as ASCII art. If you prefer to just look at the documentation, the entry point for loading fonts is Font, from which you can access individual fonts, then their glyphs.

Future Plans

The initial motivation for the project was to provide easy-to-use font rendering for games. There are numerous avenues for improving RustType. Ideas:

  • Support for some common forms of ligatures.
  • And, eventually, support for embedded right-to-left Unicode text.

If you think you could help with achieving any of these goals, feel free to open a tracking issue for discussing them.

Minimum supported rust compiler

This crate is maintained with latest stable rust.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

See Also

  • glyph_brush - can cache vertex generation & provides more complex layouts.
Comments
  • Add a simple new `image` example

    Add a simple new `image` example

    Hi, personally, I found the simple example to be a little too complicated for my tastes (and rendering to a terminal was a bit wierd), so I went and created this simple example that renders out to an png image using the image crate.

    This is the image this example produces: image_example

    Feedback welcome!

    opened by expenses 8
  • Add `rusttype::Error`, for `FontCollection` and `Font` operations.

    Add `rusttype::Error`, for `FontCollection` and `Font` operations.

    This is part of the work for issue #84, making rusttype handle errors in a more rustic fashion.

    • Introduce rusttype::Error, which implements std::error::Error, Debug and Display, and can be converted to std::io::Error.
    • Introduce rusttype::Result.
    • Use Result to report failure in FontCollection, Font, and associated iterators.
    opened by jimblandy 6
  • Replace CodepointOrGlyphId enum with IntoGlyphId trait.

    Replace CodepointOrGlyphId enum with IntoGlyphId trait.

    This implements the change proposed in #89. I've tested it against the ten most-downloaded crates that depend on rusttype (listed below), and none of them required source code changes.

    Lattice
    conrod
    font-atlas
    gfx-glyph
    ggez
    imageproc
    orbfont
    piston2d-graphics --features=glyph_cache_rusttype
    radiant-rs
    waterfall
    
    opened by jimblandy 6
  • Fix font.glyph lifetimes allow proxy glyphs in cache

    Fix font.glyph lifetimes allow proxy glyphs in cache

    One thing I noticed about Cache::queue_glyph was that it called glyph.standalone() for each queued glyph to convert it to a 'static lifetime. I wondered why this was necessary, and when it wasn't if the performance would be improved.

    Allowing the cache's queue to take glyphs with a generic lifetime is fairly simple, but I had to stare at the error messages for a while to work out why it wasn't working. There was a signature error in Font::glyph:

    Before

    impl<'a> Font<'a> {
        pub fn glyph<C: Into<CodepointOrGlyphId>>(&self, id: C) -> Option<Glyph> {...}
    }
    

    After

    impl<'a> Font<'a> {
        pub fn glyph<C: Into<CodepointOrGlyphId>>(&self, id: C) -> Option<Glyph<'a>> {...}
    }
    

    Spot the difference? Before the signature means the Glyph takes the lifetime of the reference to the font, rather than the lifetime of the font data. This was compounded by the fact a reference to the font was used in the GlyphInner struct. This isn't necessary, as Font is a cheap-clone type anyway (a reference, or an Arc).

    With this change we can see another small improvement to cache performance, in addition to the optimisation earlier today:

    name                                                    control.stdout ns/iter  change.stdout ns/iter  diff ns/iter  diff %  speedup 
    gpu_cache::cache_bench_tests::cache_bench_tolerance_1   3,048,049               2,878,432                  -169,617  -5.56%   x 1.06 
    gpu_cache::cache_bench_tests::cache_bench_tolerance_p1  5,288,473               5,067,874                  -220,599  -4.17%   x 1.04 
    

    Moreover, this has a larger affect downstream. In my crate gfx_glyph I'm seeing 15-24% reduction in cache interaction latency after all standalone() calls are removed (allowed by this patch).

    The change from Cache -> Cache<'font> means this isn't totally backward compatible though, so should be part of the next version, ie 0.3.

    opened by alexheretic 6
  • Make `gpu_cache` optional

    Make `gpu_cache` optional

    I think gpu_cache module and related features should be optional, so how is it to use "feature" feature? ~~This change will help solve also #12, by not turning on the gpu_cache feature on Redox os.~~ The feature is (currently) disabled by default, but can be enabled by building with cargo build --features="gpu_cache", and gpu_cache example can run by cargo run --example=gpu_cache --features="gpu_cache". (See http://doc.crates.io/manifest.html#the-features-section )

    opened by lo48576 6
  • GpuCache: Constant time hash lookups of matching glyph texures

    GpuCache: Constant time hash lookups of matching glyph texures

    I had a thought after the last optimisation of the glyph search: Instead of storing the info of the glyphs we cache and searching through what we have, we could have a function that produces some hashable data such that 2 matching glyphs produce the same hash. In this way we could then lookup glyphs in constant time.

    tldr: You can, and it's way faster.

    Implementation

    I've implemented this idea by instead of keying the cache by the exact scale & offset of the glyphs, using lossy integer scales & offsets. These integers are attained by dividing the actual values by the scale_tolerance or position_tolerance as applicable then rounding into integers.

    So with scale_tolerance = 0.2 glyph with scale 10.0, matches glyph with scale 10.09 as the lossy scale_over_tolerance is 50 for both. The matching bracket is (9.9, 10.1).

    This is a little different to before where you add a glyph with scale 10.33 and it would become a match for anything within the tolerance, ie (10.23, 10.43) for default 0.1 tolerance. The lossy approach the bracket already conceptually exists, so the glyph with scale 10.33 becomes a match for anything in it's bracket (10.25, 10.35).

    Impacts

    The old approach meant that you could have glyphs next to each other but in the worst case rendered with textures up to 2 times the scale/position tolerance away from the ideal. The new approach means the absolute maximum error is equal to the tolerance, but you can now have glyphs close to each other but requiring a texture each as they lie in adjacent brackets.

    So different usages could see size requirements go up, but may be able to simply relax their tolerances if previously they were seeing the worst case.

    Other than subtle changes to tolerance meaning the API is mostly unaffected, that is except gpu_cache::Cache::set_scale_tolerance & gpu_cache::Cache::set_position_tolerance which are now deprecated. These method invalidate the cache as they're moving our hashing goalposts. They function equivalently to recreating the Cache. It looks like no-one is using them anyway (crates.io/github quick search).

    Because of this we should probably bump to 0.6, even though all 0.5 code should still compile.

    Performance

    All this yields a large performance improvement compared with 0.5.2 (using b4ad64e6bef85087b9e82b9375920f2d76820890 to test which has the latest bench code). The moving text benchmark goes from 4.1ms -> 1.5ms frame latency. General performance is 1.6× to 3× faster. First run performance looks about the same, though maybe the change has just got the benchmark scenario generating more glyph textures than before as discussed above.

    name                                                         control ns/iter  change ns/iter  diff ns/iter   diff %  speedup 
    gpu_cache::cache_bench_tests::bench_high_position_tolerance  1,813,760        1,113,060           -700,700  -38.63%   x 1.63 
    gpu_cache::cache_bench_tests::bench_moving_text              4,086,238        1,456,736         -2,629,502  -64.35%   x 2.81 
    gpu_cache::cache_bench_tests::bench_multi_font               3,628,038        1,309,421         -2,318,617  -63.91%   x 2.77 
    gpu_cache::cache_bench_tests::bench_multi_font_population    12,649,773       12,160,079          -489,694   -3.87%   x 1.04 
    gpu_cache::cache_bench_tests::bench_single_font              3,799,776        1,255,568         -2,544,208  -66.96%   x 3.03
    

    Code Changes

    The code is overall reduced. BTreeMap search logic was a big part of the old code, and now is totally gone. I also removed the very short lived use of rayon, as with the new data structures it didn't yield a significant benefit.

    opened by alexheretic 5
  • Make `Font::glyph` return `Glyph`, not `Option<Glyph>`.

    Make `Font::glyph` return `Glyph`, not `Option`.

    This patch implements the change suggested in issue #96. The impact on downstream crates is described in that issue.

    This change would require a version bump.

    opened by jimblandy 5
  • Fix GlyphNotCached when match is not adjacent to order

    Fix GlyphNotCached when match is not adjacent to order

    As mentioned in #39 this PR adds a new solution to #52. I've also added two benchmarks which highlight the issue and server to avoid performance regression / encourage improvement in the future.

    As in #39 I decided to simply solve the failure to find a glyph in the cache will worst-case full traversal. However, I went for a middle out style which is quite similar to the original check-adjacent algorithm.

    My method starts from the same place according to BTreeMap ordering, but keeps searching outwards until it finds a left and/or right match instead of stopping after the first two. It'll search this way until it finds at least one match or exhausts the entire cache. After that it works on the 0/1/2 matches in exactly the same way as current code.

    In summary it fixes the bug and performs the same way as the current algorithm in all the cases the current algorithm actually works. So while it may still not be the perfect algorithm it seems to definitely be an improvement.

    rusttype version | position tolerance | benchmark --- | --- | --- 0.2.1 master | 1.0 | 3,623,762 ns/iter (+/- 49,103) 0.2.1 master | 0.1 | failed PR39-code | 1.0 | 8,378,997 ns/iter (+/- 176,811) PR39-code | 0.1 | 123,299,414 ns/iter (+/- 804,216) this PR | 1.0 | 3,579,136 ns/iter (+/- 54,938) this PR | 0.1 | 63,443,258 ns/iter (+/- 521,366)

    Fixes #52 This will also address #39, and all current dependency update PRs.

    Note: I took the liberty of adding a note about the benchmark to the readme. Feel free to remove if this isn't desired.

    opened by alexheretic 5
  • Better support for unscaled glyphs (fixes #45)

    Better support for unscaled glyphs (fixes #45)

    This commit should fix issues I had with reading the raw metrics from a font (for PDF purposes, you have to deal with unscaled fonts). There was previously no way to:

    • Get the raw width of a glyph in unscaled units
    • Get the ascender / descender of an unscaled font

    This is needed because in PDF, fonts are scaled when text is written, not when the font is embedded. So I need access to the raw metrics.

    The documentation is simply what I could derive from the naming, not sure if absolutely correct.

    This would close https://github.com/dylanede/rusttype/issues/45

    opened by fschutt 4
  • Attempt at fixing rasterize returning negative values

    Attempt at fixing rasterize returning negative values

    The change here is simply to call .abs() on values before sending them to output. It doesn't seem like having negative values is ever what any consumer expects or is prepared to handle.

    I'm not at all sure this is the best solution for what's happening, but it does fix the bug I was having.

    See #37 for the issue this is addressing.

    If anyone can think of a better solution for this, or a way to fix the underlying algorithm rather than just laying an absolute value on top of it, that would be greatly appreciated! This is a hacky fix from someone who doesn't know much low-level graphics programming.

    opened by daboross 4
  • Prevent GlyphNotCached due to ordering issues

    Prevent GlyphNotCached due to ordering issues

    The BTreeMap ordering in gpu_cache doesn't really work, since it's a one-dimensional ordering across a two-dimensional space. It's possible for adjacent glyphs in the map to not be considered "matches" (because their scale is the same but their position is not within the position tolerance), while matches further away in the map do match.

    This PR changes rect_for and cache_queued to check every glyph already in all_glyphs for similarity, rather than only the ones adjacent to it in the BTreeMap. This comes with a very minor performance hit, but luckily helps simplify some code. I think that this was the only place where the ordering aspect of the BTreeMap was actually being used, so you could likely convert to a HashMap to gain a tiny bit of performance back.

    There's also an additional fix that prevents changes to the oldest_in_use_row from moving it forward in the LRU, since that could make it "more recent" than other currently-in-use rows.

    I've also tested this branch against my game, where it's fixed a noticeable bug that causes various characters to occasionally not show up (due to GlyphNotCached).

    (P.S. Huge thanks for the library! I'm shipping my game in the next few weeks, and rusttype has been perfect for my font rendering needs.)

    opened by michaelfairley 4
  • Update image.rs

    Update image.rs

    fix error

    warning: use of deprecated associated function `image::DynamicImage::to_rgba`: replaced by `to_rgba8`
      --> dev/examples/image.rs:41:84
       |
    41 |     let mut image = DynamicImage::new_rgba8(glyphs_width + 40, glyphs_height + 40).to_rgba();
       |                                                                                    ^^^^^^^
       |
       = note: `#[warn(deprecated)]` on by default
    
    warning: 1 warning emitted
    
    
    opened by llgoer 0
Owner
Redox OS
A Rust Operating System
Redox OS
Mirror of https://gitlab.redox-os.org/redox-os/ion

Introduction Ion is a modern system shell that features a simple, yet powerful, syntax. It is written entirely in Rust, which greatly increases the ov

Redox OS 1.3k Jan 4, 2023
Mirror of https://gitlab.redox-os.org/redox-os/termion

Documentation Examples Changelog Tutorial Termion is a pure Rust, bindless library for low-level handling, manipulating and reading information about

Redox OS 1.9k Dec 31, 2022
This project now lives on in a rewrite at https://gitlab.redox-os.org/redox-os/parallel

MIT/Rust Parallel: A Command-line CPU Load Balancer Written in Rust This is an attempt at recreating the functionality of GNU Parallel, a work-stealer

Michael Murphy 1.2k Nov 20, 2022
Mirror of https://gitlab.com/mmstick/tv-renamer

Build Status: Features Written safely in the Rust programming language Features both a command-line and GTK3 interface Support for Templates to define

Michael Murphy 143 Sep 24, 2022
This is a mirror of https://gitlab.com/pcasotti/plate

plate Rust library for writing simpler Vulkan code Installation Add the library to your Cargo.toml file: [dependencies] plate = "0.5" Example Example

Pedro Casotti 15 Sep 10, 2022
Provision your authorized_keys via HTTPS/GitHub/GitLab

Keyps Key Provisioning Service Provision authorized_keys from HTTPS/GitHub/GitLab and automatically keep them up to date. Motivation Problem Provision

Samuel Rounce 6 Apr 27, 2023
Federated blogging application, thanks to ActivityPub (now on https://git.joinplu.me/ — this is just a mirror)

Plume Website — Documentation — Contribute — Instances list Plume is a federated blogging engine, based on ActivityPub. It is written in Rust, with th

Plume 1.9k Jan 8, 2023
Rust wrapper for gphoto2 (mirror of https://git.maxicarlos.de/maxicarlos08/gphoto2-rs)

GPhoto2-rs Rust bindings to libgphoto2 What about gphoto-rs? I know about the other crate (gphoto and gphoto2-sys which was created by @dcuddeback, bu

Maxicarlos08 14 Dec 29, 2022
A fast static site generator in a single binary with everything built-in. https://www.getzola.org

zola (né Gutenberg) A fast static site generator in a single binary with everything built-in. Documentation is available on its site or in the docs/co

Zola 10.1k Jan 5, 2023
A fast static site generator in a single binary with everything built-in. https://www.getzola.org

zola (né Gutenberg) A fast static site generator in a single binary with everything built-in. Documentation is available on its site or in the docs/co

Zola 10.1k Jan 10, 2023
A library for extracting #[no_mangle] pub extern "C" functions (https://docs.rust-embedded.org/book/interoperability/rust-with-c.html#no_mangle)

A library for extracting #[no_mangle] pub extern "C" functions In order to expose a function with C binary interface for interoperability with other p

Dmitrii - Demenev 0 Feb 17, 2022
Cassandra DB native client written in Rust language. Find 1.x versions on https://github.com/AlexPikalov/cdrs/tree/v.1.x Looking for an async version? - Check WIP https://github.com/AlexPikalov/cdrs-async

CDRS CDRS is looking for maintainers CDRS is Apache Cassandra driver written in pure Rust. ?? Looking for an async version? async-std https://github.c

Alex Pikalov 338 Jan 1, 2023
Basic vim-like editor for Redox-OS

red red is an editor based on vim written in Rust. Goal of this project is to provide a basic command-line editor, much like nano. Targeted for Redox.

null 1 Mar 5, 2022
A CLI command to parse kustomize build result and notify it to GitLab

ksnotify A CLI command to parse kustomize build result and notify it to GitLab Caution This repository is under development status. What ksnotify does

null 7 Jan 2, 2023
GitLab Deploy is used for deploying software projects to multiple hosts during different phases.

GitLab Deploy is used for deploying software projects to multiple hosts during different phases. This program should be run on Linux.

Magic Len (Ron Li) 1 Nov 22, 2021
Retrieving SSH and GPS keys from GitHub and GitLab

Dormarch Retrieving SSH and GPS keys from GitHub and GitLab Usage After having installed Dormarch, you can see all the options with dormarch -h. To re

Riccardo Padovani 2 Dec 24, 2021
Everyday-use client-side map-aware Arch Linux mirror ranking tool

Rate Arch Mirrors This is a tool, which fetches mirrors, skips outdated/syncing Arch Linux mirrors, then uses info about submarine cables and internet

Nikita Almakov 196 Jan 2, 2023
memflow based dxgi screen mirror prototype

memflow-mirror work in progress framebuffer mirror based on memflow. Installation Compile the guest-agent on Windows with: cargo build --release --bin

null 21 May 9, 2022
Check the reproducibility status of your Arch Linux packages (read-only mirror)

arch-repro-status A CLI tool for querying the reproducibility status of the Arch Linux packages using data from a rebuilderd instance such as reproduc

Arch Linux 12 Nov 16, 2022
A library that creates a terminal-like window with feature-packed drawing of text and easy input handling. MIRROR.

BearLibTerminal provides a pseudoterminal window with a grid of character cells and a simple yet powerful API for flexible textual output and uncompli

Tommy Ettinger 43 Oct 31, 2022