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

More advanced text shaping #47

Draft
wants to merge 1 commit into
base: stable
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
48 changes: 15 additions & 33 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# Copyright © 2018-2022 The Fonterator Contributors.
#
# Licensed under any of:
# - Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
# - MIT License (https://mit-license.org/)
# - Boost Software License, Version 1.0 (https://www.boost.org/LICENSE_1_0.txt)
# At your choosing (See accompanying files LICENSE_APACHE_2_0.txt,
# LICENSE_MIT.txt and LICENSE_BOOST_1_0.txt).
#
# Licensed under any of:
# - Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
# - Boost Software License, Version 1.0 (https://www.boost.org/LICENSE_1_0.txt)
# - MIT License (https://mit-license.org/)
# At your choosing (See accompanying files LICENSE_APACHE_2_0.txt,
# LICENSE_BOOST_1_0.txt, and LICENSE_MIT.txt).

[package]
name = "fonterator"
version = "0.9.0"
license = "Apache-2.0 OR Zlib"
license = "Apache-2.0 OR BSL-1.0 OR MIT"

description = "Load fonts as vector graphics in pure Rust with advanced text layout."
repository = "https://github.com/ardaku/fonterator"
Expand All @@ -20,7 +20,7 @@ include = ["Cargo.toml", "README.md", "LICENSE-ZLIB", "LICENSE-APACHE", "src/*"]
categories = ["gui", "rendering"]
keywords = ["font", "truetype", "opentype", "ttf", "otf"]
readme = "README.md"
edition = "2018"
edition = "2021"

[dependencies]
footile = "0.7" # For vector path operations
Expand All @@ -29,6 +29,10 @@ rustybuzz = "0.5" # For text shaping
ttf-parser = "0.15" # For reading TTF/OTF files
unicode-script = "0.5" # For calculating text direction.

[dependencies.zip]
version = "0.6"
optional = true

[dev-dependencies]
svg = "0.12"
png_pong = "0.8"
Expand All @@ -38,28 +42,6 @@ pix = "0.13"
all-features = true
default-target = "x86_64-unknown-linux-gnu"

[[example]]
name = "directions"
path = "examples/directions.rs"
required-features = ["monospace-font"]

[[example]]
name = "image"
path = "examples/image.rs"
required-features = ["monospace-font"]

[[example]]
name = "main"
path = "examples/main.rs"
required-features = ["monospace-font"]

[[example]]
name = "raster"
path = "examples/raster.rs"
required-features = ["monospace-font"]

[features]
default = []
docs-rs = []
monospace-font = []
normal-font = []
default = ["quantii-sans"]
quantii-sans = ["dep:zip"]
5 changes: 5 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//! build.rs for downloading fonts

fn main() {

}
4 changes: 2 additions & 2 deletions examples/directions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

use fonterator as font; // For parsing font file.
use footile::{FillRule, Plotter}; // For rendering font text.
use pointy::Transform;
use pix::matte::Matte8;
use pix::ops::SrcOver;
use pix::rgb::{Rgba8p, SRgba8};
use pix::Raster;
use png_pong::{Encoder, PngRaster}; // For saving PNG
use png_pong::{Encoder, PngRaster};
use pointy::Transform; // For saving PNG

const FONT_SIZE: f32 = 32.0;

Expand Down
2 changes: 1 addition & 1 deletion examples/image.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use footile::{PathOp};
use footile::PathOp;
use svg::{
node::element::{path::Data, Group, Path, Style},
Document, Node,
Expand Down
4 changes: 2 additions & 2 deletions examples/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use footile::{FillRule, Plotter};
use pointy::Transform;
use pix::matte::Matte8;
use pix::ops::SrcOver;
use pix::rgb::{Rgba8p, SRgba8};
use pix::Raster;
use png_pong::{Encoder, PngRaster}; // For saving PNG
use png_pong::{Encoder, PngRaster};
use pointy::Transform; // For saving PNG

fn main() {
// Load the default FontGroup (font and fallbacks).
Expand Down
4 changes: 2 additions & 2 deletions examples/raster.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use footile::{FillRule, Plotter};
use pointy::Transform;
use pix::matte::Matte8;
use pix::ops::SrcOver;
use pix::rgb::{Rgba8p, SRgba8};
use pix::Raster;
use png_pong::{Encoder, PngRaster}; // For saving PNG
use png_pong::{Encoder, PngRaster};
use pointy::Transform; // For saving PNG

const FONT_SIZE: f32 = 200.0;

Expand Down
46 changes: 0 additions & 46 deletions src/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -512,49 +512,3 @@ impl Iterator for TextPathIterator<'_, '_> {
}
}*/
}

/// Get a monospace font. Requires feature = "monospace-font", enabled by default.
#[cfg(feature = "monospace-font")]
pub fn monospace_font() -> Font<'static> {
const FONTA: &[u8] = include_bytes!("font/dejavu/SansMono.ttf");
const FONTB: &[u8] = include_bytes!("font/noto/SansDevanagari.ttf");
const FONTC: &[u8] = include_bytes!("font/noto/SansHebrew.ttf");
const FONTD: &[u8] = include_bytes!("font/droid/SansFallback.ttf");

Font::new()
.push(FONTA)
.unwrap()
.push(FONTB)
.unwrap()
.push(FONTC)
.unwrap()
.push(FONTD)
.unwrap()
}

/// Get a normal font. Requires feature = "normal-font".
#[cfg(feature = "normal-font")]
pub fn normal_font() -> Font<'static> {
const FONTA: &[u8] = include_bytes!("font/dejavu/Sans.ttf");
const FONTB: &[u8] = include_bytes!("font/noto/SansDevanagari.ttf");
const FONTC: &[u8] = include_bytes!("font/noto/SansHebrew.ttf");
const FONTD: &[u8] = include_bytes!("font/droid/SansFallback.ttf");

Font::new()
.push(FONTA)
.unwrap()
.push(FONTB)
.unwrap()
.push(FONTC)
.unwrap()
.push(FONTD)
.unwrap()
}

#[cfg(any(feature = "monospace-font", feature = "normal-font"))]
/// Get a text string of the licenses that must be included in a binary program
/// for using the font. Requires either feature = "monospace-font" or feature
/// = "normal-font"
pub fn licenses() -> &'static str {
include_str!("bin-licenses.txt")
}
16 changes: 8 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
//
// Licensed under any of:
// - Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
// - MIT License (https://mit-license.org/)
// - Boost Software License, Version 1.0 (https://www.boost.org/LICENSE_1_0.txt)
// At your choosing (See accompanying files LICENSE_APACHE_2_0.txt,
// LICENSE_MIT.txt and LICENSE_BOOST_1_0.txt).
//! TODO: Top-level Documentation.
// - MIT License (https://mit-license.org/)
// At your choosing (See accompanying files LICENSE_APACHE_2_0.txt,
// LICENSE_BOOST_1_0.txt, and LICENSE_MIT.txt).
//! Render text with TTF fonts using footile.

#![doc(
html_logo_url = "https://ardaku.github.io/mm/logo.svg",
Expand All @@ -30,9 +30,9 @@
variant_size_differences
)]

mod direction;
mod font;
mod shape;
// mod direction;
// mod font;
mod render;
mod shape;

pub use font::*;
pub use shape::Font;
82 changes: 81 additions & 1 deletion src/render.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,88 @@
// Copyright © 2018-2022 The Fonterator Contributors.
//
// Licensed under any of:
// - Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
// - Boost Software License, Version 1.0 (https://www.boost.org/LICENSE_1_0.txt)
// - MIT License (https://mit-license.org/)
// At your choosing (See accompanying files LICENSE_APACHE_2_0.txt,
// LICENSE_BOOST_1_0.txt, and LICENSE_MIT.txt).
//! Rendering TTF glyphs with footile

use footile::PathOp;
use pointy::Pt;
use rustybuzz::Face;
use ttf_parser::{GlyphId, OutlineBuilder};

struct Outliner<'a> {
// Path to write out to.
path: &'a mut Vec<PathOp>,
// Scale to 1.0 = 1 em
scale: f32,
// Where to draw the glyph X
glyph_x: f32,
// Where to draw the glyph Y
glyph_y: f32,
}

impl OutlineBuilder for Outliner<'_> {
fn move_to(&mut self, x: f32, y: f32) {
let x = x + self.glyph_x;
let y = y + self.glyph_y;
self.path
.push(PathOp::Move(Pt::new(x * self.scale, y * self.scale)));
}

fn line_to(&mut self, x: f32, y: f32) {
let x = x + self.glyph_x;
let y = y + self.glyph_y;
self.path
.push(PathOp::Line(Pt::new(x * self.scale, y * self.scale)));
}

fn quad_to(&mut self, x1: f32, y1: f32, x: f32, y: f32) {
let x1 = x1 + self.glyph_x;
let y1 = y1 + self.glyph_y;
let x = x + self.glyph_x;
let y = y + self.glyph_y;
self.path.push(PathOp::Quad(
Pt::new(x1 * self.scale, y1 * self.scale),
Pt::new(x * self.scale, y * self.scale),
));
}

fn curve_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32) {
let x1 = x1 + self.glyph_x;
let y1 = y1 + self.glyph_y;
let x2 = x2 + self.glyph_x;
let y2 = y2 + self.glyph_y;
let x = x + self.glyph_x;
let y = y + self.glyph_y;
self.path.push(PathOp::Cubic(
Pt::new(x1 * self.scale, y1 * self.scale),
Pt::new(x2 * self.scale, y2 * self.scale),
Pt::new(x * self.scale, y * self.scale),
));
}

fn close(&mut self) {
self.path.push(PathOp::Close());
}
}

/// Build a path
pub(crate) fn build_path(path_buffer: &mut Vec<PathOp>, face: &Face<'_>, glyph_x: f32, glyph_y: f32, glyph_id: u16) {
pub(crate) fn build_path(
path: &mut Vec<PathOp>,
face: &Face<'_>,
glyph_x: f32,
glyph_y: f32,
glyph_id: u16,
scale: f32,
) {
let mut outliner = Outliner {
path,
scale,
glyph_x,
glyph_y,
};
face.outline_glyph(GlyphId(glyph_id), &mut outliner);
}
Loading