use std::ops::Range;
use crate::color::rgb;
use crate::geom::Transform;
use crate::surface::Surface;
use crate::text::Font;
#[cfg(feature = "raster-images")]
pub(crate) mod bitmap;
pub(crate) mod colr;
pub(crate) mod outline;
pub(crate) mod svg;
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]
pub struct GlyphId(u32);
impl GlyphId {
pub fn new(id: u32) -> Self {
Self(id)
}
pub fn to_u32(&self) -> u32 {
self.0
}
pub(crate) fn to_skrifa(self) -> skrifa::GlyphId {
skrifa::GlyphId::new(self.0)
}
}
pub(crate) fn draw_color_glyph(
font: Font,
context_color: rgb::Color,
glyph: GlyphId,
base_transform: Transform,
surface: &mut Surface,
) -> Option<()> {
surface.push_transform(&base_transform);
surface.push_transform(&Transform::from_scale(1.0, -1.0));
let drawn = colr::draw_glyph(font.clone(), context_color, glyph, surface)
.or_else(|| svg::draw_glyph(font.clone(), context_color, glyph, surface))
.or_else(|| {
#[cfg(feature = "raster-images")]
let res = bitmap::draw_glyph(font.clone(), glyph, surface);
#[cfg(not(feature = "raster-images"))]
let res = None;
res
});
surface.pop();
surface.pop();
drawn
}
pub(crate) fn should_outline(font: &Font, glyph: GlyphId) -> bool {
let has_svg = svg::has_svg_data(font, glyph);
let has_colr = colr::has_colr_data(font, glyph);
#[cfg(feature = "raster-images")]
let has_bitmap = bitmap::has_bitmap_data(font, glyph);
#[cfg(not(feature = "raster-images"))]
let has_bitmap = false;
font.font_info().can_be_cid_font() && !has_svg && !has_colr && !has_bitmap
}
pub(crate) fn draw_glyph(
font: Font,
context_color: rgb::Color,
glyph: GlyphId,
base_transform: Transform,
surface: &mut Surface,
) -> Option<()> {
draw_color_glyph(font.clone(), context_color, glyph, base_transform, surface)
.or_else(|| outline::draw_glyph(font, glyph, base_transform, surface))
}
pub trait Glyph {
fn glyph_id(&self) -> GlyphId;
fn text_range(&self) -> Range<usize>;
fn x_advance(&self, size: f32) -> f32;
fn x_offset(&self, size: f32) -> f32;
fn y_offset(&self, size: f32) -> f32;
fn y_advance(&self, size: f32) -> f32;
fn location(&self) -> Option<crate::surface::Location>;
}
#[derive(Debug, Clone)]
pub struct KrillaGlyph {
pub glyph_id: GlyphId,
pub text_range: Range<usize>,
pub x_advance: f32,
pub x_offset: f32,
pub y_offset: f32,
pub y_advance: f32,
pub location: Option<crate::surface::Location>,
}
impl Glyph for KrillaGlyph {
fn glyph_id(&self) -> GlyphId {
self.glyph_id
}
fn text_range(&self) -> Range<usize> {
self.text_range.clone()
}
fn x_advance(&self, size: f32) -> f32 {
self.x_advance * size
}
fn x_offset(&self, size: f32) -> f32 {
self.x_offset * size
}
fn y_offset(&self, size: f32) -> f32 {
self.y_offset * size
}
fn y_advance(&self, size: f32) -> f32 {
self.y_advance * size
}
fn location(&self) -> Option<crate::surface::Location> {
self.location
}
}
impl KrillaGlyph {
pub fn new(
glyph_id: GlyphId,
x_advance: f32,
x_offset: f32,
y_offset: f32,
y_advance: f32,
range: Range<usize>,
location: Option<crate::surface::Location>,
) -> Self {
Self {
glyph_id,
x_advance,
x_offset,
y_offset,
y_advance,
text_range: range,
location,
}
}
}
#[derive(Clone, Copy)]
pub(crate) enum PDFGlyph {
Type3(u8),
Cid(u16),
}
impl PDFGlyph {
#[inline(always)]
pub(crate) fn encode_into(&self, slice: &mut Vec<u8>) {
match self {
PDFGlyph::Type3(cg) => slice.push(*cg),
PDFGlyph::Cid(cid) => {
slice.push((cid >> 8) as u8);
slice.push((cid & 0xff) as u8);
}
}
}
}