#![deny(clippy::all, clippy::if_not_else, clippy::enum_glob_use, clippy::wrong_pub_self_convention)]
use std::fmt;
use std::ops::{Add, Mul};
use std::sync::atomic::{AtomicUsize, Ordering};
#[cfg(not(any(target_os = "macos", windows)))]
pub mod ft;
#[cfg(not(any(target_os = "macos", windows)))]
pub use ft::{Error, FreeTypeRasterizer as Rasterizer};
#[cfg(windows)]
pub mod directwrite;
#[cfg(windows)]
pub use directwrite::{DirectWriteRasterizer as Rasterizer, Error};
#[cfg(target_os = "macos")]
mod darwin;
#[cfg(target_os = "macos")]
pub use darwin::*;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct FontDesc {
name: String,
style: Style,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Slant {
Normal,
Italic,
Oblique,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Weight {
Normal,
Bold,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Style {
Specific(String),
Description { slant: Slant, weight: Weight },
}
impl fmt::Display for Style {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Style::Specific(ref s) => f.write_str(&s),
Style::Description { slant, weight } => {
write!(f, "slant={:?}, weight={:?}", slant, weight)
},
}
}
}
impl FontDesc {
pub fn new<S>(name: S, style: Style) -> FontDesc
where
S: Into<String>,
{
FontDesc { name: name.into(), style }
}
}
impl fmt::Display for FontDesc {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} - {}", self.name, self.style)
}
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct FontKey {
token: u32,
}
impl FontKey {
pub fn next() -> FontKey {
static TOKEN: AtomicUsize = AtomicUsize::new(0);
FontKey { token: TOKEN.fetch_add(1, Ordering::SeqCst) as _ }
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct GlyphKey {
pub c: char,
pub font_key: FontKey,
pub size: Size,
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Size(i16);
impl Size {
pub fn new(size: f32) -> Size {
Size((size * Size::factor()) as i16)
}
#[inline]
pub fn factor() -> f32 {
2.0
}
pub fn as_f32_pts(self) -> f32 {
f32::from(self.0) / Size::factor()
}
}
impl<T: Into<Size>> Add<T> for Size {
type Output = Size;
fn add(self, other: T) -> Size {
Size(self.0.saturating_add(other.into().0))
}
}
impl<T: Into<Size>> Mul<T> for Size {
type Output = Size;
fn mul(self, other: T) -> Size {
Size(self.0 * other.into().0)
}
}
impl From<f32> for Size {
fn from(float: f32) -> Size {
Size::new(float)
}
}
#[derive(Clone)]
pub struct RasterizedGlyph {
pub c: char,
pub width: i32,
pub height: i32,
pub top: i32,
pub left: i32,
pub buf: BitmapBuffer,
}
#[derive(Clone, Debug)]
pub enum BitmapBuffer {
RGB(Vec<u8>),
RGBA(Vec<u8>),
}
impl Default for RasterizedGlyph {
fn default() -> RasterizedGlyph {
RasterizedGlyph {
c: ' ',
width: 0,
height: 0,
top: 0,
left: 0,
buf: BitmapBuffer::RGB(Vec::new()),
}
}
}
impl fmt::Debug for RasterizedGlyph {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("RasterizedGlyph")
.field("c", &self.c)
.field("width", &self.width)
.field("height", &self.height)
.field("top", &self.top)
.field("left", &self.left)
.field("buf", &self.buf)
.finish()
}
}
#[derive(Copy, Clone)]
pub struct Metrics {
pub average_advance: f64,
pub line_height: f64,
pub descent: f32,
pub underline_position: f32,
pub underline_thickness: f32,
pub strikeout_position: f32,
pub strikeout_thickness: f32,
}
pub trait Rasterize {
type Err: ::std::error::Error + Send + Sync + 'static;
fn new(device_pixel_ratio: f32, use_thin_strokes: bool) -> Result<Self, Self::Err>
where
Self: Sized;
fn metrics(&self, _: FontKey, _: Size) -> Result<Metrics, Self::Err>;
fn load_font(&mut self, _: &FontDesc, _: Size) -> Result<FontKey, Self::Err>;
fn get_glyph(&mut self, _: GlyphKey) -> Result<RasterizedGlyph, Self::Err>;
fn update_dpr(&mut self, device_pixel_ratio: f32);
}