mirror of
https://github.com/wez/wezterm.git
synced 2024-09-11 14:25:57 +03:00
parent
c37ee01222
commit
0519b5499a
@ -24,7 +24,7 @@ As features stabilize some brief notes about them will accumulate here.
|
||||
* Fixed: errors loading custom color schemes are now logged to the error log [#794](https://github.com/wez/wezterm/issues/794)
|
||||
* Fixed: OSC 7 (current working directory) now works with paths that contain spaces and other special characters. Thanks to [@Arvedui](https://github.com/Arvedui)! [#799](https://github.com/wez/wezterm/pull/799)
|
||||
* Changed: the homebrew tap is now a Cask that installs to the /Applications directory on macOS. Thanks to [@laggardkernel](https://github.com/laggardkernel)!
|
||||
* New: bold and/or italics are now synthesized for fonts when the matching font is not actually italic or doesn't match the requested weight. Synthesized italics only apply to scalable fonts. [#815](https://github.com/wez/wezterm/issues/815)
|
||||
* New: bold and/or italics are now synthesized for fonts when the matching font is not actually italic or doesn't match the requested weight. [#815](https://github.com/wez/wezterm/issues/815)
|
||||
|
||||
### 20210502-154244-3f7122cb
|
||||
|
||||
|
@ -2,7 +2,7 @@ use crate::parser::ParsedFont;
|
||||
use crate::rasterizer::FontRasterizer;
|
||||
use crate::units::*;
|
||||
use crate::{ftwrap, RasterizedGlyph};
|
||||
use ::freetype::{FT_GlyphSlotRec_, FT_Matrix};
|
||||
use ::freetype::{FT_GlyphSlotRec_, FT_Glyph_Format, FT_Matrix};
|
||||
use anyhow::bail;
|
||||
use std::cell::RefCell;
|
||||
use std::mem;
|
||||
@ -14,6 +14,7 @@ pub struct FreeTypeRasterizer {
|
||||
face: RefCell<ftwrap::Face>,
|
||||
_lib: ftwrap::Library,
|
||||
synthesize_bold: bool,
|
||||
synthesize_italic: bool,
|
||||
}
|
||||
|
||||
impl FontRasterizer for FreeTypeRasterizer {
|
||||
@ -53,7 +54,14 @@ impl FontRasterizer for FreeTypeRasterizer {
|
||||
ftwrap::FT_Pixel_Mode::FT_PIXEL_MODE_MONO => self.rasterize_mono(pitch, ft_glyph, data),
|
||||
mode => bail!("unhandled pixel mode: {:?}", mode),
|
||||
};
|
||||
Ok(glyph)
|
||||
|
||||
let slot = unsafe { &mut *(*face.face).glyph };
|
||||
if self.synthesize_italic && slot.format == FT_Glyph_Format::FT_GLYPH_FORMAT_BITMAP {
|
||||
// The source was and thus the italic transform did nothing
|
||||
Ok(glyph.skew())
|
||||
} else {
|
||||
Ok(glyph)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -313,6 +321,7 @@ impl FreeTypeRasterizer {
|
||||
face: RefCell::new(face),
|
||||
has_color,
|
||||
synthesize_bold: parsed.synthesize_bold,
|
||||
synthesize_italic: parsed.synthesize_italic,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,65 @@ pub struct RasterizedGlyph {
|
||||
pub has_color: bool,
|
||||
}
|
||||
|
||||
impl RasterizedGlyph {
|
||||
/// Computes a skewed version of this glyph to produce a synthesized oblique variant
|
||||
pub fn skew(&self) -> Self {
|
||||
// This function is derived from code which is subject to the terms of the
|
||||
// Mozilla Public License, v. 2.0. http://mozilla.org/MPL/2.0/
|
||||
|
||||
let factor = 0.2f64; // Skew factor
|
||||
let stride = self.width * 4;
|
||||
|
||||
// Calculate the skewed horizontal offsets of the bottom and top of the glyph.
|
||||
let bottom = self.bearing_y.get().round() as f64 - self.height as f64;
|
||||
let skew_min = ((bottom + 0.5) * factor).floor();
|
||||
let skew_max = ((self.bearing_y.get() as f64 - 0.5) * factor).ceil();
|
||||
|
||||
// Allocate enough extra width for the min/max skew offsets.
|
||||
let skew_width = self.width + (skew_max - skew_min) as usize;
|
||||
let mut skew_buffer = vec![0u8; skew_width * self.height * 4];
|
||||
for y in 0..self.height {
|
||||
// Calculate a skew offset at the vertical center of the current row.
|
||||
let offset = (self.bearing_y.get() - y as f64 - 0.5) * factor - skew_min;
|
||||
// Get a blend factor in 0..256 constant across all pixels in the row.
|
||||
let blend = (offset.fract() * 256.0) as u32;
|
||||
let src_row = y * stride;
|
||||
let dest_row = (y * skew_width + offset.floor() as usize) * 4;
|
||||
let mut prev_px = [0u32; 4];
|
||||
for (src, dest) in self.data[src_row..src_row + stride]
|
||||
.chunks(4)
|
||||
.zip(skew_buffer[dest_row..dest_row + stride].chunks_mut(4))
|
||||
{
|
||||
let px = [src[0] as u32, src[1] as u32, src[2] as u32, src[3] as u32];
|
||||
// Blend current pixel with previous pixel based on blend factor.
|
||||
let next_px = [px[0] * blend, px[1] * blend, px[2] * blend, px[3] * blend];
|
||||
dest[0] = ((((px[0] << 8) - next_px[0]) + prev_px[0] + 128) >> 8) as u8;
|
||||
dest[1] = ((((px[1] << 8) - next_px[1]) + prev_px[1] + 128) >> 8) as u8;
|
||||
dest[2] = ((((px[2] << 8) - next_px[2]) + prev_px[2] + 128) >> 8) as u8;
|
||||
dest[3] = ((((px[3] << 8) - next_px[3]) + prev_px[3] + 128) >> 8) as u8;
|
||||
// Save the remainder for blending onto the next pixel.
|
||||
prev_px = next_px;
|
||||
}
|
||||
// If the skew misaligns the final pixel, write out the remainder.
|
||||
if blend > 0 {
|
||||
let dest = &mut skew_buffer[dest_row + stride..dest_row + stride + 4];
|
||||
dest[0] = ((prev_px[0] + 128) >> 8) as u8;
|
||||
dest[1] = ((prev_px[1] + 128) >> 8) as u8;
|
||||
dest[2] = ((prev_px[2] + 128) >> 8) as u8;
|
||||
dest[3] = ((prev_px[3] + 128) >> 8) as u8;
|
||||
}
|
||||
}
|
||||
Self {
|
||||
data: skew_buffer,
|
||||
height: self.height,
|
||||
width: skew_width,
|
||||
bearing_x: self.bearing_x + PixelLength::new(skew_min),
|
||||
bearing_y: self.bearing_y,
|
||||
has_color: self.has_color,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Rasterizes the specified glyph index in the associated font
|
||||
/// and returns the generated bitmap
|
||||
pub trait FontRasterizer {
|
||||
|
Loading…
Reference in New Issue
Block a user