1
0
Fork 0
mirror of https://github.com/alacritty/alacritty.git synced 2024-11-25 14:05:41 -05:00

Update glyph cache on DPI change

When the DPI is changed, the glyph cache is now properly updated to
make use of the correct font size again.

This solves an issue where alacritty would be moved to a different
monitor and then part of the text would be rendered offscreen with
selection breaking.
This commit is contained in:
Christian Duerr 2018-07-13 21:33:57 +02:00 committed by Matt Keeler
parent c772ef3c2b
commit 563f96aa32
11 changed files with 59 additions and 57 deletions

View file

@ -93,12 +93,6 @@ font:
x: 0 x: 0
y: 0 y: 0
# Scale the font size based on the monitor's DPI. This will lead to bigger text on HiDPI
# screens and make reading text a little easier.
# On X11 it is possible to change the DPI for each instance of alacritty by using
# `WINIT_HIDPI_FACTOR=1.0 alacritty` to scale the font.
scale_with_dpi: true
# OS X only: use thin stroke font rendering. Thin strokes are suitable # OS X only: use thin stroke font rendering. Thin strokes are suitable
# for retina displays, but for non-retina you probably want this set to # for retina displays, but for non-retina you probably want this set to
# false. # false.

View file

@ -73,10 +73,6 @@ font:
x: 0 x: 0
y: 0 y: 0
# Scale the font size based on the monitor's DPI. This will lead to bigger text on HiDPI
# screens and make reading text a little easier.
scale_with_dpi: true
# OS X only: use thin stroke font rendering. Thin strokes are suitable # OS X only: use thin stroke font rendering. Thin strokes are suitable
# for retina displays, but for non-retina you probably want this set to # for retina displays, but for non-retina you probably want this set to
# false. # false.

View file

@ -183,6 +183,10 @@ impl ::Rasterize for Rasterizer {
Err(Error::MissingGlyph(glyph.c)) Err(Error::MissingGlyph(glyph.c))
}) })
} }
fn update_dpr(&mut self, device_pixel_ratio: f32) {
self.device_pixel_ratio = device_pixel_ratio;
}
} }
impl Rasterizer { impl Rasterizer {

View file

@ -106,6 +106,9 @@ impl ::Rasterize for FreeTypeRasterizer {
self.get_rendered_glyph(glyph_key) self.get_rendered_glyph(glyph_key)
} }
fn update_dpr(&mut self, device_pixel_ratio: f32) {
self.device_pixel_ratio = device_pixel_ratio;
}
} }
pub trait IntoFontconfigType { pub trait IntoFontconfigType {

View file

@ -348,4 +348,7 @@ pub trait Rasterize {
/// Rasterize the glyph described by `GlyphKey`. /// Rasterize the glyph described by `GlyphKey`.
fn get_glyph(&mut self, GlyphKey) -> Result<RasterizedGlyph, Self::Err>; fn get_glyph(&mut self, GlyphKey) -> Result<RasterizedGlyph, Self::Err>;
/// Update the Rasterizer's DPI factor
fn update_dpr(&mut self, device_pixel_ratio: f32);
} }

View file

@ -1585,8 +1585,18 @@ pub struct Font {
#[serde(default="true_bool", deserialize_with = "default_true_bool")] #[serde(default="true_bool", deserialize_with = "default_true_bool")]
use_thin_strokes: bool, use_thin_strokes: bool,
#[serde(default="true_bool", deserialize_with = "default_true_bool")] // TODO: Deprecated
scale_with_dpi: bool, #[serde(default, deserialize_with = "deserialize_scale_with_dpi")]
scale_with_dpi: Option<()>,
}
fn deserialize_scale_with_dpi<'a, D>(_deserializer: D) -> ::std::result::Result<Option<()>, D::Error>
where D: de::Deserializer<'a>
{
panic!(
"The `scale_with_dpi` field has been deprecated, \
on X11 the WINIT_HIDPI_FACTOR environment variable can be used instead."
);
} }
fn default_bold_desc() -> FontDescription { fn default_bold_desc() -> FontDescription {
@ -1639,11 +1649,6 @@ impl Font {
.. self .. self
} }
} }
/// Check whether dpi should be applied
pub fn scale_with_dpi(&self) -> bool {
self.scale_with_dpi
}
} }
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
@ -1655,7 +1660,7 @@ impl Default for Font {
italic: FontDescription::new_with_family("Menlo"), italic: FontDescription::new_with_family("Menlo"),
size: Size::new(11.0), size: Size::new(11.0),
use_thin_strokes: true, use_thin_strokes: true,
scale_with_dpi: true, scale_with_dpi: None,
glyph_offset: Default::default(), glyph_offset: Default::default(),
offset: Default::default(), offset: Default::default(),
} }
@ -1671,7 +1676,7 @@ impl Default for Font {
italic: FontDescription::new_with_family("monospace"), italic: FontDescription::new_with_family("monospace"),
size: Size::new(11.0), size: Size::new(11.0),
use_thin_strokes: false, use_thin_strokes: false,
scale_with_dpi: true, scale_with_dpi: None,
glyph_offset: Default::default(), glyph_offset: Default::default(),
offset: Default::default(), offset: Default::default(),
} }

View file

@ -140,23 +140,18 @@ impl Display {
// Create the window where Alacritty will be displayed // Create the window where Alacritty will be displayed
let mut window = Window::new(&options, config.window())?; let mut window = Window::new(&options, config.window())?;
let dpi_factor = if config.font().scale_with_dpi() { let dpr = window.hidpi_factor();
window.hidpi_factor() info!("device_pixel_ratio: {}", dpr);
} else {
1.0
};
// get window properties for initializing the other subsystems // get window properties for initializing the other subsystems
let mut viewport_size = window.inner_size_pixels() let mut viewport_size = window.inner_size_pixels()
.expect("glutin returns window size").to_physical(dpi_factor); .expect("glutin returns window size").to_physical(dpr);
info!("device_pixel_ratio: {}", dpi_factor);
// Create renderer // Create renderer
let mut renderer = QuadRenderer::new(config, viewport_size)?; let mut renderer = QuadRenderer::new(config, viewport_size)?;
let (glyph_cache, cell_width, cell_height) = let (glyph_cache, cell_width, cell_height) =
Self::new_glyph_cache(dpi_factor, &mut renderer, config)?; Self::new_glyph_cache(dpr, &mut renderer, config)?;
let dimensions = options.dimensions() let dimensions = options.dimensions()
@ -171,7 +166,7 @@ impl Display {
(width + 2 * u32::from(config.padding().x)) as f64, (width + 2 * u32::from(config.padding().x)) as f64,
(height + 2 * u32::from(config.padding().y)) as f64); (height + 2 * u32::from(config.padding().y)) as f64);
window.set_inner_size(new_viewport_size.to_logical(dpi_factor)); window.set_inner_size(new_viewport_size.to_logical(dpr));
renderer.resize(new_viewport_size); renderer.resize(new_viewport_size);
viewport_size = new_viewport_size; viewport_size = new_viewport_size;
} }
@ -179,7 +174,7 @@ impl Display {
info!("Cell Size: ({} x {})", cell_width, cell_height); info!("Cell Size: ({} x {})", cell_width, cell_height);
let size_info = SizeInfo { let size_info = SizeInfo {
dpi_factor, dpr,
width: viewport_size.width as f32, width: viewport_size.width as f32,
height: viewport_size.height as f32, height: viewport_size.height as f32,
cell_width: cell_width as f32, cell_width: cell_width as f32,
@ -217,11 +212,11 @@ impl Display {
}) })
} }
fn new_glyph_cache(dpi_factor: f64, renderer: &mut QuadRenderer, config: &Config) fn new_glyph_cache(dpr: f64, renderer: &mut QuadRenderer, config: &Config)
-> Result<(GlyphCache, f32, f32), Error> -> Result<(GlyphCache, f32, f32), Error>
{ {
let font = config.font().clone(); let font = config.font().clone();
let rasterizer = font::Rasterizer::new(dpi_factor as f32, config.use_thin_strokes())?; let rasterizer = font::Rasterizer::new(dpr as f32, config.use_thin_strokes())?;
// Initialize glyph cache // Initialize glyph cache
let glyph_cache = { let glyph_cache = {
@ -255,10 +250,11 @@ impl Display {
} }
pub fn update_glyph_cache(&mut self, config: &Config) { pub fn update_glyph_cache(&mut self, config: &Config) {
let dpr = self.size_info.dpr;
let cache = &mut self.glyph_cache; let cache = &mut self.glyph_cache;
let size = self.font_size; let size = self.font_size;
self.renderer.with_loader(|mut api| { self.renderer.with_loader(|mut api| {
let _ = cache.update_font_size(config.font(), size, &mut api); let _ = cache.update_font_size(config.font(), size, dpr, &mut api);
}); });
let metrics = cache.font_metrics(); let metrics = cache.font_metrics();
@ -292,19 +288,14 @@ impl Display {
// Resize events are emitted via glutin/winit with logical sizes // Resize events are emitted via glutin/winit with logical sizes
// However the terminal, window and renderer use physical sizes // However the terminal, window and renderer use physical sizes
// so a conversion must be done here // so a conversion must be done here
new_size = Some(sz.to_physical(self.window.hidpi_factor())); new_size = Some(sz.to_physical(self.size_info.dpr));
} }
let dpi_factor = if config.font().scale_with_dpi() { // Font size/DPI factor modification detected
self.window.hidpi_factor() let dpr = self.window.hidpi_factor();
} else { if terminal.font_size != self.font_size || dpr != self.size_info.dpr {
1.0
};
// Font size modification detected
if terminal.font_size != self.font_size || dpi_factor != self.size_info.dpi_factor {
self.size_info.dpi_factor = dpi_factor;
self.font_size = terminal.font_size; self.font_size = terminal.font_size;
self.size_info.dpr = dpr;
self.update_glyph_cache(config); self.update_glyph_cache(config);
if new_size == None { if new_size == None {

View file

@ -339,7 +339,7 @@ impl<N: Notify> Processor<N> {
} }
}, },
CursorMoved { position: lpos, modifiers, .. } => { CursorMoved { position: lpos, modifiers, .. } => {
let (x, y) = lpos.to_physical(processor.ctx.size_info.dpi_factor).into(); let (x, y) = lpos.to_physical(processor.ctx.size_info.dpr).into();
let x: i32 = limit(x, 0, processor.ctx.size_info.width as i32); let x: i32 = limit(x, 0, processor.ctx.size_info.width as i32);
let y: i32 = limit(y, 0, processor.ctx.size_info.height as i32); let y: i32 = limit(y, 0, processor.ctx.size_info.height as i32);
@ -374,7 +374,8 @@ impl<N: Notify> Processor<N> {
use input::ActionContext; use input::ActionContext;
let path: String = path.to_string_lossy().into(); let path: String = path.to_string_lossy().into();
processor.ctx.write_to_pty(path.into_bytes()); processor.ctx.write_to_pty(path.into_bytes());
} },
HiDpiFactorChanged(_) => self.terminal.dirty = true,
_ => (), _ => (),
} }
}, },

View file

@ -735,7 +735,7 @@ mod tests {
cell_height: 3.0, cell_height: 3.0,
padding_x: 0.0, padding_x: 0.0,
padding_y: 0.0, padding_y: 0.0,
dpi_factor: 1.0, dpr: 1.0,
}; };
let mut terminal = Term::new(&config, size); let mut terminal = Term::new(&config, size);

View file

@ -294,19 +294,24 @@ impl GlyphCache {
&mut self, &mut self,
font: &config::Font, font: &config::Font,
size: font::Size, size: font::Size,
dpr: f64,
loader: &mut L loader: &mut L
) -> Result<(), font::Error> { ) -> Result<(), font::Error> {
// Clear currently cached data in both GL and the registry // Clear currently cached data in both GL and the registry
loader.clear(); loader.clear();
self.cache = HashMap::default(); self.cache = HashMap::default();
// Update dpi scaling
self.rasterizer.update_dpr(dpr as f32);
// Recompute font keys // Recompute font keys
let font = font.to_owned().with_size(size); let font = font.to_owned().with_size(size);
info!("Font size changed: {:?}", font.size);
let (regular, bold, italic) = Self::compute_font_keys(&font, &mut self.rasterizer)?; let (regular, bold, italic) = Self::compute_font_keys(&font, &mut self.rasterizer)?;
self.rasterizer.get_glyph(GlyphKey { font_key: regular, c: 'm', size: font.size() })?; self.rasterizer.get_glyph(GlyphKey { font_key: regular, c: 'm', size: font.size() })?;
let metrics = self.rasterizer.metrics(regular)?; let metrics = self.rasterizer.metrics(regular)?;
info!("Font size changed: {:?} [DPR: {}]", font.size, dpr);
self.font_size = font.size; self.font_size = font.size;
self.font_key = regular; self.font_key = regular;
self.bold_key = bold; self.bold_key = bold;
@ -715,7 +720,7 @@ impl QuadRenderer {
pub fn resize(&mut self, size: PhysicalSize) { pub fn resize(&mut self, size: PhysicalSize) {
let (width, height) : (u32, u32) = size.into(); let (width, height) : (u32, u32) = size.into();
let padding_x = i32::from(self.program.padding_x); let padding_x = i32::from(self.program.padding_x);
let padding_y = i32::from(self.program.padding_y); let padding_y = i32::from(self.program.padding_y);
@ -1019,7 +1024,7 @@ impl ShaderProgram {
}; };
shader.update_projection(size.width as f32, size.height as f32); shader.update_projection(size.width as f32, size.height as f32);
shader.deactivate(); shader.deactivate();
Ok(shader) Ok(shader)

View file

@ -758,7 +758,7 @@ pub struct SizeInfo {
/// DPI factor of the current window /// DPI factor of the current window
#[serde(default)] #[serde(default)]
pub dpi_factor: f64, pub dpr: f64,
} }
impl SizeInfo { impl SizeInfo {
@ -1972,7 +1972,7 @@ mod tests {
cell_height: 3.0, cell_height: 3.0,
padding_x: 0.0, padding_x: 0.0,
padding_y: 0.0, padding_y: 0.0,
dpi_factor: 1.0, dpr: 1.0,
}; };
let mut term = Term::new(&Default::default(), size); let mut term = Term::new(&Default::default(), size);
let mut grid: Grid<Cell> = Grid::new(Line(3), Column(5), &Cell::default()); let mut grid: Grid<Cell> = Grid::new(Line(3), Column(5), &Cell::default());
@ -2016,7 +2016,7 @@ mod tests {
cell_height: 3.0, cell_height: 3.0,
padding_x: 0.0, padding_x: 0.0,
padding_y: 0.0, padding_y: 0.0,
dpi_factor: 1.0, dpr: 1.0,
}; };
let mut term = Term::new(&Default::default(), size); let mut term = Term::new(&Default::default(), size);
let mut grid: Grid<Cell> = Grid::new(Line(1), Column(5), &Cell::default()); let mut grid: Grid<Cell> = Grid::new(Line(1), Column(5), &Cell::default());
@ -2060,7 +2060,7 @@ mod tests {
cell_height: 3.0, cell_height: 3.0,
padding_x: 0.0, padding_x: 0.0,
padding_y: 0.0, padding_y: 0.0,
dpi_factor: 1.0, dpr: 1.0,
}; };
let mut term = Term::new(&Default::default(), size); let mut term = Term::new(&Default::default(), size);
let cursor = Point::new(Line(0), Column(0)); let cursor = Point::new(Line(0), Column(0));
@ -2079,7 +2079,7 @@ mod tests {
cell_height: 3.0, cell_height: 3.0,
padding_x: 0.0, padding_x: 0.0,
padding_y: 0.0, padding_y: 0.0,
dpi_factor: 1.0, dpr: 1.0,
}; };
let config: Config = Default::default(); let config: Config = Default::default();
let mut term: Term = Term::new(&config, size); let mut term: Term = Term::new(&config, size);
@ -2108,7 +2108,7 @@ mod tests {
cell_height: 3.0, cell_height: 3.0,
padding_x: 0.0, padding_x: 0.0,
padding_y: 0.0, padding_y: 0.0,
dpi_factor: 1.0, dpr: 1.0,
}; };
let config: Config = Default::default(); let config: Config = Default::default();
let mut term: Term = Term::new(&config, size); let mut term: Term = Term::new(&config, size);
@ -2128,7 +2128,7 @@ mod tests {
cell_height: 3.0, cell_height: 3.0,
padding_x: 0.0, padding_x: 0.0,
padding_y: 0.0, padding_y: 0.0,
dpi_factor: 1.0, dpr: 1.0,
}; };
let config: Config = Default::default(); let config: Config = Default::default();
let mut term: Term = Term::new(&config, size); let mut term: Term = Term::new(&config, size);