mirror of
https://github.com/wez/wezterm.git
synced 2024-12-27 15:37:29 +03:00
add rusttype rasterizer
This commit is contained in:
parent
12e2dcd181
commit
f976ca6e23
@ -1,5 +1,5 @@
|
|||||||
//! Higher level harfbuzz bindings
|
//! Higher level harfbuzz bindings
|
||||||
|
#![allow(dead_code)]
|
||||||
#[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
|
#[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
|
||||||
use freetype;
|
use freetype;
|
||||||
|
|
||||||
|
@ -110,6 +110,7 @@ impl FontConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn shape_with_harfbuzz(
|
pub fn shape_with_harfbuzz(
|
||||||
font: &mut NamedFont,
|
font: &mut NamedFont,
|
||||||
font_idx: system::FallbackIdx,
|
font_idx: system::FallbackIdx,
|
||||||
|
@ -2,20 +2,19 @@
|
|||||||
|
|
||||||
use super::hbwrap as harfbuzz;
|
use super::hbwrap as harfbuzz;
|
||||||
use config::{Config, TextStyle};
|
use config::{Config, TextStyle};
|
||||||
use failure::{self, Error};
|
use failure::Error;
|
||||||
use font::{
|
use font::{FallbackIdx, Font, FontMetrics, FontSystem, GlyphInfo, NamedFont, RasterizedGlyph};
|
||||||
shape_with_harfbuzz, FallbackIdx, Font, FontMetrics, FontSystem, GlyphInfo, NamedFont,
|
|
||||||
RasterizedGlyph,
|
|
||||||
};
|
|
||||||
use font_loader::system_fonts;
|
use font_loader::system_fonts;
|
||||||
use rusttype::{Font as RTFont, FontCollection, Scale};
|
use rusttype::{
|
||||||
use std::cell::RefCell;
|
point, Codepoint, Font as RTFont, FontCollection, PositionedGlyph, Rect, Scale, VMetrics,
|
||||||
|
};
|
||||||
|
|
||||||
struct NamedFontImpl<'a> {
|
struct NamedFontImpl<'a> {
|
||||||
collection: FontCollection<'a>,
|
_collection: FontCollection<'a>,
|
||||||
font: RTFont<'a>,
|
font: RTFont<'a>,
|
||||||
hbfont: RefCell<harfbuzz::Font>,
|
|
||||||
scale: Scale,
|
scale: Scale,
|
||||||
|
vmetrics: VMetrics,
|
||||||
|
cell_height: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type FontSystemImpl = RustTypeFonts;
|
pub type FontSystemImpl = RustTypeFonts;
|
||||||
@ -36,37 +35,75 @@ impl FontSystem for RustTypeFonts {
|
|||||||
let (data, idx) = system_fonts::get(&font_props)
|
let (data, idx) = system_fonts::get(&font_props)
|
||||||
.ok_or_else(|| format_err!("no font matching {:?}", style))?;
|
.ok_or_else(|| format_err!("no font matching {:?}", style))?;
|
||||||
eprintln!("want idx {} in bytes of len {}", idx, data.len());
|
eprintln!("want idx {} in bytes of len {}", idx, data.len());
|
||||||
let hbfont = RefCell::new(harfbuzz::Font::new_from_slice(&data, idx as u32)?);
|
|
||||||
let collection = FontCollection::from_bytes(data)?;
|
let collection = FontCollection::from_bytes(data)?;
|
||||||
let font = collection.font_at(idx as usize)?;
|
let font = collection.font_at(idx as usize)?;
|
||||||
eprintln!("made a font for {:?}", style);
|
eprintln!("made a font for {:?}", style);
|
||||||
let scale = Scale::uniform(config.font_size as f32 * 96.0 / 72.0);
|
let scale = Scale::uniform(config.font_size as f32 * 96.0 / 72.0);
|
||||||
|
let vmetrics = font.v_metrics(scale);
|
||||||
|
eprintln!("vmetrics {:?}", vmetrics);
|
||||||
|
let cell_height = f64::from(vmetrics.ascent - vmetrics.descent + vmetrics.line_gap);
|
||||||
Ok(Box::new(NamedFontImpl {
|
Ok(Box::new(NamedFontImpl {
|
||||||
collection,
|
_collection: collection,
|
||||||
hbfont,
|
cell_height,
|
||||||
font,
|
font,
|
||||||
scale,
|
scale,
|
||||||
|
vmetrics,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bounds(g: &PositionedGlyph) -> Rect<i32> {
|
||||||
|
match g.pixel_bounding_box() {
|
||||||
|
Some(bounds) => bounds,
|
||||||
|
None => rusttype::Rect {
|
||||||
|
min: point(0, 0),
|
||||||
|
max: point(0, 0),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> NamedFont for NamedFontImpl<'a> {
|
impl<'a> NamedFont for NamedFontImpl<'a> {
|
||||||
fn get_fallback(&mut self, idx: FallbackIdx) -> Result<&Font, Error> {
|
fn get_fallback(&mut self, idx: FallbackIdx) -> Result<&Font, Error> {
|
||||||
ensure!(idx == 0, "no fallback fonts available (idx={})", idx);
|
ensure!(idx == 0, "no fallback fonts available (idx={})", idx);
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
fn shape(&mut self, s: &str) -> Result<Vec<GlyphInfo>, Error> {
|
fn shape(&mut self, s: &str) -> Result<Vec<GlyphInfo>, Error> {
|
||||||
shape_with_harfbuzz(self, 0, s)
|
let mut shaped = Vec::new();
|
||||||
|
|
||||||
|
for (cluster, c) in s.chars().enumerate() {
|
||||||
|
let glyph = self.font.glyph(Codepoint(c as u32)).scaled(self.scale);
|
||||||
|
let hmetrics = glyph.h_metrics();
|
||||||
|
let glyph = glyph.positioned(point(0.0, 0.0));
|
||||||
|
|
||||||
|
if c != ' ' {
|
||||||
|
eprintln!("{} -> glyph {} {:?}", c, glyph.id().0, hmetrics);
|
||||||
|
}
|
||||||
|
|
||||||
|
shaped.push(GlyphInfo {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
text: s[cluster..cluster].to_string(),
|
||||||
|
cluster: cluster as u32,
|
||||||
|
num_cells: 1,
|
||||||
|
font_idx: 0,
|
||||||
|
glyph_pos: glyph.id().0,
|
||||||
|
x_advance: hmetrics.advance_width.into(),
|
||||||
|
x_offset: (-hmetrics.left_side_bearing).into(),
|
||||||
|
y_advance: 0.0,
|
||||||
|
y_offset: 0.0, //(-bounds.max.y).into(),
|
||||||
|
// vmetrics.descent.into(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Ok(shaped)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Font for NamedFontImpl<'a> {
|
impl<'a> Font for NamedFontImpl<'a> {
|
||||||
fn harfbuzz_shape(
|
fn harfbuzz_shape(
|
||||||
&self,
|
&self,
|
||||||
buf: &mut harfbuzz::Buffer,
|
_buf: &mut harfbuzz::Buffer,
|
||||||
features: Option<&[harfbuzz::hb_feature_t]>,
|
_features: Option<&[harfbuzz::hb_feature_t]>,
|
||||||
) {
|
) {
|
||||||
self.hbfont.borrow_mut().shape(buf, features)
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_color(&self) -> bool {
|
fn has_color(&self) -> bool {
|
||||||
@ -74,20 +111,49 @@ impl<'a> Font for NamedFontImpl<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn metrics(&self) -> FontMetrics {
|
fn metrics(&self) -> FontMetrics {
|
||||||
let vmetrics = self.font.v_metrics(self.scale);
|
|
||||||
let hmetrics = self
|
let hmetrics = self
|
||||||
.font
|
.font
|
||||||
.glyph(rusttype::Codepoint(33))
|
.glyph(Codepoint(33))
|
||||||
.scaled(self.scale)
|
.scaled(self.scale)
|
||||||
.h_metrics();
|
.h_metrics();
|
||||||
FontMetrics {
|
FontMetrics {
|
||||||
cell_height: f64::from(vmetrics.ascent - vmetrics.descent + vmetrics.line_gap),
|
cell_height: self.cell_height,
|
||||||
cell_width: hmetrics.advance_width.into(),
|
cell_width: hmetrics.advance_width.into(),
|
||||||
descender: vmetrics.descent as i16,
|
descender: self.vmetrics.descent as i16,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rasterize_glyph(&self, glyph_pos: u32) -> Result<RasterizedGlyph, Error> {
|
fn rasterize_glyph(&self, glyph_pos: u32) -> Result<RasterizedGlyph, Error> {
|
||||||
unimplemented!();
|
let g = self
|
||||||
|
.font
|
||||||
|
.glyph(rusttype::GlyphId(glyph_pos))
|
||||||
|
.scaled(self.scale)
|
||||||
|
.positioned(point(0.0, 0.0));
|
||||||
|
let bounds = bounds(&g);
|
||||||
|
let width = bounds.width() as usize;
|
||||||
|
let height = bounds.height() as usize;
|
||||||
|
let mut data = Vec::with_capacity(width * height * 4);
|
||||||
|
g.draw(|_x, _y, value| {
|
||||||
|
let v = (value * 255.0) as u8;
|
||||||
|
data.push(v); // alpha
|
||||||
|
data.push(v); // red
|
||||||
|
data.push(v); // green
|
||||||
|
data.push(v); // blue
|
||||||
|
});
|
||||||
|
eprintln!(
|
||||||
|
"rasterize_glyph {} {}x{} {} bounds {:?}",
|
||||||
|
glyph_pos, width, height, self.cell_height, bounds
|
||||||
|
);
|
||||||
|
// FIXME: there's something funky about either the bearing
|
||||||
|
// calculation here or the y_offset calculation in the
|
||||||
|
// shape function that causes the baseline to vary and
|
||||||
|
// the text look crazy.
|
||||||
|
Ok(RasterizedGlyph {
|
||||||
|
data,
|
||||||
|
height,
|
||||||
|
width,
|
||||||
|
bearing_x: bounds.min.x,
|
||||||
|
bearing_y: -bounds.min.y,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ pub struct GlyphInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GlyphInfo {
|
impl GlyphInfo {
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
text: &str,
|
text: &str,
|
||||||
font_idx: usize,
|
font_idx: usize,
|
||||||
|
Loading…
Reference in New Issue
Block a user