summaryrefslogtreecommitdiffstats
path: root/font
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2016-08-12 13:38:41 -0500
committerJoe Wilm <joe@jwilm.com>2016-08-12 19:30:14 -0500
commitb70394170c0fa9cd4e4be8150121a698a426a069 (patch)
tree41d84240a4e58df201fbd7f4f984c3814c7cb055 /font
parent874719580ce3e12f09d01a9a53c5e64205ef5b5d (diff)
Support bold/italic font rendering on macOS
This patch adds support for rendering italic fonts and bold fonts. The `font` crate has a couple of new paradigms to support this: font keys and glyph keys. `FontKey` is a lightweight (4 byte) identifier for a font loaded out of the rasterizer. This replaces `FontDesc` for rasterizing glyphs from a loaded font. `FontDesc` had the problem that it contained two strings, and the glyph cache needs to store a copy of the font key for every loaded glyph. `GlyphKey` is now passed to the glyph rasterization method instead of a simple `char`. `GlyphKey` contains information including font, size, and the character. The rasterizer APIs do not define what happens when loading the same font from a `FontDesc` more than once. It is assumed that the application will track the resulting `FontKey` instead of asking the font to be loaded multiple times.
Diffstat (limited to 'font')
-rw-r--r--font/src/darwin/mod.rs60
-rw-r--r--font/src/lib.rs52
2 files changed, 93 insertions, 19 deletions
diff --git a/font/src/darwin/mod.rs b/font/src/darwin/mod.rs
index 31eb1292..4db8dad1 100644
--- a/font/src/darwin/mod.rs
+++ b/font/src/darwin/mod.rs
@@ -43,7 +43,7 @@ use euclid::point::Point2D;
use euclid::rect::Rect;
use euclid::size::Size2D;
-use super::{FontDesc, RasterizedGlyph, Metrics};
+use super::{FontDesc, RasterizedGlyph, Metrics, FontKey, GlyphKey};
pub mod cg_color;
use self::cg_color::{CGColorRef, CGColor};
@@ -52,6 +52,10 @@ pub mod byte_order;
use self::byte_order::kCGBitmapByteOrder32Host;
use self::byte_order::extract_rgb;
+use super::Size;
+
+static FONT_LOAD_ERROR: &'static str = "font specified by FontKey has been loaded";
+
/// Font descriptor
///
/// The descriptor provides data about a font and supports creating a font.
@@ -70,7 +74,7 @@ pub struct Descriptor {
///
/// Given a fontdesc, can rasterize fonts.
pub struct Rasterizer {
- fonts: HashMap<FontDesc, Font>,
+ fonts: HashMap<FontKey, Font>,
device_pixel_ratio: f32,
}
@@ -83,22 +87,35 @@ impl Rasterizer {
}
}
- pub fn metrics(&mut self, desc: &FontDesc, size: f32) -> Metrics {
- let scaled_size = self.device_pixel_ratio * size;
- self.get_font(desc, scaled_size).unwrap().metrics()
+ /// Get metrics for font specified by FontKey
+ ///
+ /// # Panics
+ ///
+ /// If FontKey was not generated by `load_font`, this method will panic.
+ pub fn metrics(&self, key: FontKey, _size: Size) -> Metrics {
+ // NOTE size is not needed here since the font loaded already contains
+ // it. It's part of the API due to platform differences.
+ let font = self.fonts.get(&key).expect(FONT_LOAD_ERROR);
+ font.metrics()
}
- fn get_font(&mut self, desc: &FontDesc, size: f32) -> Option<Font> {
- if let Some(font) = self.fonts.get(desc) {
- return Some(font.clone());
- }
+ pub fn load_font(&mut self, desc: &FontDesc, size: Size) -> Option<FontKey> {
+ self.get_font(desc, size)
+ .map(|font| {
+ let key = FontKey::next();
+ self.fonts.insert(key, font);
+ key
+ })
+ }
+
+ fn get_font(&mut self, desc: &FontDesc, size: Size) -> Option<Font> {
let descriptors = descriptors_for_family(&desc.name[..]);
for descriptor in descriptors {
if descriptor.style_name == desc.style {
// Found the font we want
- let font = descriptor.to_font(size as _);
- self.fonts.insert(desc.to_owned(), font.clone());
+ let scaled_size = size.as_f32_pts() as f64 * self.device_pixel_ratio as f64;
+ let font = descriptor.to_font(scaled_size);
return Some(font);
}
}
@@ -106,11 +123,18 @@ impl Rasterizer {
None
}
- pub fn get_glyph(&mut self, desc: &FontDesc, size: f32, c: char) -> RasterizedGlyph {
- let scaled_size = self.device_pixel_ratio * size;
- let glyph = self.get_font(desc, scaled_size).unwrap().get_glyph(c, scaled_size as _);
-
- glyph
+ /// Get rasterized glyph for given glyph key
+ ///
+ /// # Panics
+ ///
+ /// Panics if the FontKey specified in GlyphKey was not generated from `load_font`
+ pub fn get_glyph(&mut self, glyph: &GlyphKey) -> RasterizedGlyph {
+ let scaled_size = self.device_pixel_ratio * glyph.size.as_f32_pts();
+
+ self.fonts
+ .get(&glyph.font_key)
+ .expect(FONT_LOAD_ERROR)
+ .get_glyph(glyph.c, scaled_size as _)
}
}
@@ -181,8 +205,8 @@ pub fn descriptors_for_family(family: &str) -> Vec<Descriptor> {
impl Descriptor {
/// Create a Font from this descriptor
- pub fn to_font(&self, pt_size: f64) -> Font {
- let ct_font = ct_new_from_descriptor(&self.ct_descriptor, pt_size);
+ pub fn to_font(&self, size: f64) -> Font {
+ let ct_font = ct_new_from_descriptor(&self.ct_descriptor, size);
let cg_font = ct_font.copy_to_CGFont();
Font {
ct_font: ct_font,
diff --git a/font/src/lib.rs b/font/src/lib.rs
index a42020d8..74563b1a 100644
--- a/font/src/lib.rs
+++ b/font/src/lib.rs
@@ -19,6 +19,7 @@
//!
//! CoreText is used on Mac OS.
//! FreeType is used on everything that's not Mac OS.
+#![feature(integer_atomics)]
#[cfg(not(target_os = "macos"))]
extern crate fontconfig;
@@ -38,6 +39,7 @@ extern crate euclid;
extern crate libc;
use std::fmt;
+use std::sync::atomic::{AtomicU32, ATOMIC_U32_INIT, Ordering};
// If target isn't macos, reexport everything from ft
#[cfg(not(target_os = "macos"))]
@@ -51,7 +53,7 @@ mod darwin;
#[cfg(target_os = "macos")]
pub use darwin::*;
-#[derive(Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct FontDesc {
name: String,
style: String,
@@ -68,6 +70,54 @@ impl FontDesc {
}
}
+/// Identifier for a Font for use in maps/etc
+#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
+pub struct FontKey {
+ token: u32,
+}
+
+impl FontKey {
+ /// Get next font key for given size
+ ///
+ /// The generated key will be globally unique
+ pub fn next() -> FontKey {
+ static TOKEN: AtomicU32 = ATOMIC_U32_INIT;
+
+ FontKey {
+ token: TOKEN.fetch_add(1, Ordering::SeqCst),
+ }
+ }
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub struct GlyphKey {
+ pub c: char,
+ pub font_key: FontKey,
+ pub size: Size,
+}
+
+/// Font size stored as integer
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct Size(i32);
+
+impl Size {
+ /// Scale factor between font "Size" type and point size
+ #[inline]
+ pub fn factor() -> f32 {
+ 2.0
+ }
+
+ /// Create a new `Size` from a f32 size in points
+ pub fn new(size: f32) -> Size {
+ Size((size * Size::factor()) as i32)
+ }
+
+ /// Get the f32 size in points
+ pub fn as_f32_pts(self) -> f32 {
+ self.0 as f32 / Size::factor()
+ }
+}
+
pub struct RasterizedGlyph {
pub c: char,
pub width: i32,