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

Add font support #581

Merged
merged 28 commits into from
Apr 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d9b069f
WIP
ryanisaacg Feb 17, 2020
710616a
Font rendering almost works
ryanisaacg Feb 23, 2020
1558f65
Update elefont to add spaces between characters
ryanisaacg Feb 23, 2020
8ffc935
Clear out the cache texture before rendering text
ryanisaacg Feb 23, 2020
9492b91
Remove unused import
ryanisaacg Feb 24, 2020
3d932c2
Use a version of golem from crates.io
ryanisaacg Feb 24, 2020
4b9b486
Refactor the actual layout code into Font
ryanisaacg Mar 2, 2020
f9a3582
Write a method to find the extents of rendered text
ryanisaacg Mar 2, 2020
e7d49c2
Add the ability to clamp the width fonts can draw
ryanisaacg Mar 2, 2020
87ae87b
Fmt pass
ryanisaacg Mar 4, 2020
79d73a1
Remove VecDeque import
ryanisaacg Mar 4, 2020
20d6dbb
Merge remote-tracking branch 'origin/master' into add-font-support
ryanisaacg Mar 4, 2020
7fa8bc0
Clippy
ryanisaacg Mar 4, 2020
e1440a6
Clippy
ryanisaacg Mar 4, 2020
dd84f7d
Fix example
ryanisaacg Mar 4, 2020
f5e7047
Update to the released version of elefont
ryanisaacg Apr 11, 2020
2ad394c
Refactor the font API
ryanisaacg Apr 11, 2020
9b56dcf
Fmt pass
ryanisaacg Apr 11, 2020
1d72752
Remove the draw_text method
ryanisaacg Apr 11, 2020
e9ca6e1
Include the image in the LayoutGlyph
ryanisaacg Apr 11, 2020
17e2247
Resolve the issue of cache space
ryanisaacg Apr 11, 2020
351aa0e
Add documentation to the font module
ryanisaacg Apr 11, 2020
430b98c
Merge branch 'master' into add-font-support
ryanisaacg Apr 14, 2020
30224f8
Add FontError
ryanisaacg Apr 14, 2020
945db5b
Changelog
ryanisaacg Apr 14, 2020
80c08e5
Fmt
ryanisaacg Apr 14, 2020
2358713
Rename the text example
ryanisaacg Apr 16, 2020
61a985e
Docs update
ryanisaacg Apr 16, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
- Add `exhaust` and `reset` function to timer so they can be used for more than just an update cycle
- `lifecycle::run` can now accept any kind of Error.
- Add `into_raw_context` on Graphics, to allow lower-level graphics programming
- Add font support!
- `VectorFont` allows you to load TTF files via rusttype
- `FontRenderer` allows you to draw glyphs to the screen

## v0.4.0-alpha0.3
- Update `golem` to `v0.1.1` to fix non-power-of-2 textures
Expand Down
10 changes: 7 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,33 @@ edition = "2018"

[features]
# complex_shapes, fonts, gamepads, sounds
default = ["easy-log", "event-cache", "gamepad", "saving"]
default = ["easy-log", "event-cache", "font", "gamepad", "saving", "ttf"]

easy-log = ["simple_logger", "web_logger"]
event-cache = ["blinds/event-cache"]
font = ["elefont"]
gamepad = ["blinds/gamepad"]
saving = ["gestalt"]
stdweb = ["gestalt/stdweb", "platter/stdweb", "blinds/stdweb", "golem/stdweb","instant/stdweb"]
web-sys = ["gestalt/web-sys", "platter/web-sys", "blinds/web-sys", "golem/web-sys","instant/web-sys"]
ttf = ["elefont/rusttype", "rusttype"]

[badges]

maintenance = { status = "actively-developed" }

[dependencies]
blinds = { version = "0.1.0", default-features = false, features = ["gl"] }
bytemuck = "1.0"
elefont = { version = "0.1.3", features = ["rusttype", "unicode-normalization"], optional = true }
gestalt = { version = "0.1", optional = true }
golem = { version = "0.1.3", features = ["std"] }
image = { version = "0.22", default-features = false, features = ["png_codec", "jpeg"] }
instant = "0.1.2"
log = "0.4"
mint = "0.5.3"
platter = "0.1"
blinds = { version = "0.1.0", default-features = false, features = ["gl"] }
instant = "0.1.2"
rusttype = { version = "0.8.2", optional = true }

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
simple_logger = { version = "1.4", optional = true }
Expand Down
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ A simple 2D game framework written in pure Rust, for both the Web and Desktop

## Alpha Notice

This version of Quicksilver is currently in a very early alpha! There are still planned changes
to the API, some of them breaking. Additionally, major features (like audio support or text, for
example) are entirely missing. Use at your own risk! Feedback on alpha-related bugs or the API
changes from the 0.3.x API to the new API would be appreciated.
This version of Quicksilver is currently working its way through alpha! There is still work to do
on the API and on bugfixes, as well as waiting on an upstream library for audio support.
Please feel free to use this version and **provide feedback!** If you run into bugs or want to
give feedback on API decisions, please open an issue.

## A quick example

Expand Down Expand Up @@ -127,8 +127,8 @@ favorite browser to the port it provides.
#### wasm-bindgen support

Quicksilver has recently gained experimental support for `wasm-bindgen`, under the `web-sys`
feature. The workflow is not currently documented here, but it should be the same as any other
library.
feature. The workflow is not currently documented here, but it should be the same as using any other
library with `wasm-bindgen`.

## Optional Features

Expand All @@ -141,6 +141,7 @@ The optional features available are:
[web_logger](https://github.com/yewstack/web_logger))
- gamepad event generation (via [gilrs](https://gitlab.com/gilrs-project/gilrs))
- saving (via [gestalt](https://github.com/ryanisaacg/gestalt))
- font rendering (via [elefont](https://github.com/ryanisaacg/elefont)) and TTF parsing (via [rusttype](https://gitlab.redox-os.org/redox-os/rusttype))

Each are enabled by default, but you can
[specify which features](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#choosing-features)
Expand Down
38 changes: 38 additions & 0 deletions examples/07_text.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Example 7: Text
// Write some text on the screen
use quicksilver::{
geom::Vector,
graphics::{Color, Graphics, VectorFont},
lifecycle::{run, EventStream, Settings, Window},
Result,
};

fn main() {
run(
Settings {
size: Vector::new(800.0, 600.0).into(),
title: "Font Example",
..Settings::default()
},
app,
);
}

async fn app(window: Window, mut gfx: Graphics, mut events: EventStream) -> Result<()> {
// Load the Font, just like loading any other asset
let ttf = VectorFont::load("font.ttf").await?;
let mut font = ttf.to_renderer(&gfx, 72.0)?;
gfx.clear(Color::WHITE);
// Use the font rendering API to draw some text
font.draw(
&mut gfx,
"Hello world!\nHello Quicksilver!",
Color::BLACK,
Vector::new(100.0, 100.0),
)?;
gfx.present(&window)?;

loop {
while let Some(_) = events.next_event().await {}
}
}
32 changes: 32 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,24 @@ pub enum QuicksilverError {
SurfaceImageError,
/// A surface operation was attempted with no image bound to the surface
NoSurfaceImageBound,
#[cfg(feature = "font")]
FontError(FontError),
}

#[cfg(feature = "font")]
#[derive(Debug)]
pub enum FontError {
/// A non-renderable glyph was passed to a font rendering function
///
/// Generally this means the glyph was not included in the font, e.g. passing a non-ASCII
/// character to an ASCII-only font
NonRenderableGlyph(elefont::Glyph),
/// The string passed to the font (at the given size) is too large to render
///
/// Because glyphs are cached on the GPU, a given character or word may be too large to render.
/// This is unlikely to be an issue for most applications, but if a character is rendered at a
/// size larger than 2048x2048, this error may occur.
StringTooLarge,
}

impl From<ImageError> for QuicksilverError {
Expand All @@ -42,6 +60,13 @@ impl From<GolemError> for QuicksilverError {
}
}

#[cfg(feature = "font")]
impl From<FontError> for QuicksilverError {
fn from(err: FontError) -> QuicksilverError {
QuicksilverError::FontError(err)
}
}

impl Display for QuicksilverError {
fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
match self {
Expand All @@ -56,6 +81,13 @@ impl Display for QuicksilverError {
fmt,
"A surface operation was attempted with no image bound to the surface"
),
QuicksilverError::FontError(FontError::NonRenderableGlyph(g)) => {
write!(fmt, "This glyph cannot be rendered: {:?}", g)
}
QuicksilverError::FontError(FontError::StringTooLarge) => write!(
fmt,
"A word or glyph passed to a font was too large to render."
),
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ use crate::QuicksilverError;

mod circle_points;
mod color;
#[cfg(feature = "font")]
mod font;
mod image;
mod mesh;
mod surface;
mod vertex;

pub use self::color::Color;
#[cfg(feature = "font")]
pub use self::font::{FontRenderer, LayoutGlyph, VectorFont};
pub use self::image::Image;
pub use self::mesh::Mesh;
pub use self::surface::Surface;
Expand Down
Loading