mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-18 13:55:23 -05:00
WIP
This commit is contained in:
parent
2466f81d5e
commit
038899c5b3
4 changed files with 283 additions and 280 deletions
212
src/config/font.rs
Normal file
212
src/config/font.rs
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
use serde_yaml;
|
||||||
|
use serde::{de, Deserialize};
|
||||||
|
|
||||||
|
use config::{Delta, failure_default};
|
||||||
|
use font::{Size, FontKey, Slant};
|
||||||
|
|
||||||
|
// Global and local font configuration
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct FontConfiguration {
|
||||||
|
#[serde(default, deserialize_with="failure_default")]
|
||||||
|
options: GlobalOptions,
|
||||||
|
#[serde(default, deserialize_with="deserialize_font_collection")]
|
||||||
|
fonts: Vec<Font>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FontConfiguration {
|
||||||
|
pub fn font_by_char(&self, c: char, weight: Slant) -> FontKey {
|
||||||
|
for font in fonts {
|
||||||
|
let options = font.options();
|
||||||
|
|
||||||
|
// Skip font if font slant does not match requested slant
|
||||||
|
if options.unwrap_or(self.options as Options).style.unwrap_or(self.options.style) != weight {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let is_match = match options {
|
||||||
|
Some(options) => {
|
||||||
|
for range in options.ranges {
|
||||||
|
if range.start < c && range.end > c {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
true
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if is_match {
|
||||||
|
// TODO: Check if this font contains the char
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FontConfiguration {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
fonts: vec!(Font::default()),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Information about a font
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct Font {
|
||||||
|
family: String,
|
||||||
|
#[serde(deserialize_with="failure_default")]
|
||||||
|
options: Option<Options>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default font config in case of failure or missing config
|
||||||
|
impl Default for Font {
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
fn default() -> Self {
|
||||||
|
Font {
|
||||||
|
family: "Menlo".into(),
|
||||||
|
options: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
fn default() -> Self {
|
||||||
|
Font {
|
||||||
|
family: "monospace".into(),
|
||||||
|
options: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Options for a font
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct Options {
|
||||||
|
#[serde(deserialize_with="deserialize_size")]
|
||||||
|
size: Option<Size>,
|
||||||
|
#[serde(deserialize_with="failure_default")]
|
||||||
|
thin_strokes: Option<bool>,
|
||||||
|
#[serde(deserialize_with="failure_default")]
|
||||||
|
antialias: Option<AntiAlias>,
|
||||||
|
#[serde(deserialize_with="failure_default")]
|
||||||
|
hinting: Option<bool>,
|
||||||
|
#[serde(deserialize_with="failure_default")]
|
||||||
|
style: Option<String>,
|
||||||
|
#[serde(deserialize_with="failure_default")]
|
||||||
|
offset: Option<Delta>,
|
||||||
|
#[serde(deserialize_with="failure_default")]
|
||||||
|
ranges: Vec<FontRange>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Options {
|
||||||
|
fn default() -> Self {
|
||||||
|
Options {
|
||||||
|
size: None,
|
||||||
|
thin_strokes: None,
|
||||||
|
antialias: None,
|
||||||
|
hinting: None,
|
||||||
|
style: None,
|
||||||
|
offset: None,
|
||||||
|
ranges: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct GlobalOptions(Options);
|
||||||
|
impl Default for GlobalOptions {
|
||||||
|
fn default() -> Self {
|
||||||
|
GlobalOptions(Options {
|
||||||
|
size: Some(Size::new(12.0)),
|
||||||
|
thin_strokes: Some(true),
|
||||||
|
antialias: Some(AntiAlias::LCD),
|
||||||
|
hinting: Some(true),
|
||||||
|
style: Some("normal".into()),
|
||||||
|
offset: Some(Delta::default()),
|
||||||
|
ranges: Vec::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AntiAliasing settings for fonts
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub enum AntiAlias {
|
||||||
|
LCD,
|
||||||
|
LCDV,
|
||||||
|
GRAY,
|
||||||
|
DISABLED,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Range for which a specific font should be used
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct FontRange {
|
||||||
|
#[serde(deserialize_with="failure_default")]
|
||||||
|
start: char,
|
||||||
|
#[serde(deserialize_with="failure_default")]
|
||||||
|
end: char,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deserialize the font vector
|
||||||
|
fn deserialize_font_collection<'a, D>(deserializer: D)
|
||||||
|
-> ::std::result::Result<Vec<Font>, D::Error>
|
||||||
|
where D: de::Deserializer<'a>,
|
||||||
|
{
|
||||||
|
// Deserialize vector as generic yaml value
|
||||||
|
let mut value = match serde_yaml::Value::deserialize(deserializer) {
|
||||||
|
Ok(value) => value,
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("problem with config: {}; Using default fonts", err);
|
||||||
|
return Ok(vec!(Font::default()));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get value as sequence
|
||||||
|
let sequence = match value.as_sequence_mut() {
|
||||||
|
Some(sequence) => sequence,
|
||||||
|
None => return Ok(vec!(Font::default())),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Deserialize each element in the sequence
|
||||||
|
let mut font_collection = Vec::new();
|
||||||
|
for i in 0..sequence.len() {
|
||||||
|
match Font::deserialize(sequence.remove(i)) {
|
||||||
|
Ok(font) => font_collection.push(font),
|
||||||
|
// TODO: Print line or something like that?
|
||||||
|
Err(err) => eprintln!("problem with config: Malformed font; Skipping"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return defaults if collection contains no font
|
||||||
|
if font_collection.is_empty() {
|
||||||
|
Ok(vec!(Font::default()))
|
||||||
|
} else {
|
||||||
|
Ok(font_collection)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deserialize font size
|
||||||
|
fn deserialize_size<'a, D>(deserializer: D)
|
||||||
|
-> ::std::result::Result<Option<Size>, D::Error>
|
||||||
|
where D: de::Deserializer<'a>,
|
||||||
|
{
|
||||||
|
match f32::deserialize(deserializer) {
|
||||||
|
Ok(value) => Ok(Some(Size::new(value))),
|
||||||
|
_ => {
|
||||||
|
Ok(None)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,8 @@
|
||||||
//! Alacritty reads from a config file at startup to determine various runtime
|
//! Alacritty reads from a config file at startup to determine various runtime
|
||||||
//! parameters including font family and style, font size, etc. In the future,
|
//! parameters including font family and style, font size, etc. In the future,
|
||||||
//! the config file will also hold user and platform specific keybindings.
|
//! the config file will also hold user and platform specific keybindings.
|
||||||
|
pub mod font;
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::{env, fmt};
|
use std::{env, fmt};
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
|
@ -14,15 +16,15 @@ use std::time::Duration;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use ::Rgb;
|
use ::Rgb;
|
||||||
use font::Size;
|
|
||||||
use serde_yaml;
|
use serde_yaml;
|
||||||
use serde::{self, de, Deserialize};
|
use serde::{de, Deserialize};
|
||||||
use serde::de::Error as SerdeError;
|
use serde::de::Error as SerdeError;
|
||||||
use serde::de::{Visitor, MapAccess, Unexpected};
|
use serde::de::{Visitor, MapAccess, Unexpected};
|
||||||
use notify::{Watcher, watcher, DebouncedEvent, RecursiveMode};
|
use notify::{Watcher, watcher, DebouncedEvent, RecursiveMode};
|
||||||
|
|
||||||
use glutin::ModifiersState;
|
use glutin::ModifiersState;
|
||||||
|
|
||||||
|
use self::font::FontConfiguration;
|
||||||
use input::{Action, Binding, MouseBinding, KeyBinding};
|
use input::{Action, Binding, MouseBinding, KeyBinding};
|
||||||
use index::{Line, Column};
|
use index::{Line, Column};
|
||||||
use ansi::CursorStyle;
|
use ansi::CursorStyle;
|
||||||
|
@ -326,7 +328,7 @@ pub struct Config {
|
||||||
|
|
||||||
/// Font configuration
|
/// Font configuration
|
||||||
#[serde(default, deserialize_with = "failure_default")]
|
#[serde(default, deserialize_with = "failure_default")]
|
||||||
font: Font,
|
font: FontConfiguration,
|
||||||
|
|
||||||
/// Should show render timer
|
/// Should show render timer
|
||||||
#[serde(default, deserialize_with = "failure_default")]
|
#[serde(default, deserialize_with = "failure_default")]
|
||||||
|
@ -453,7 +455,7 @@ fn default_true_bool<'a, D>(deserializer: D) -> ::std::result::Result<bool, D::E
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn failure_default<'a, D, T>(deserializer: D)
|
pub fn failure_default<'a, D, T>(deserializer: D)
|
||||||
-> ::std::result::Result<T, D::Error>
|
-> ::std::result::Result<T, D::Error>
|
||||||
where D: de::Deserializer<'a>,
|
where D: de::Deserializer<'a>,
|
||||||
T: Deserialize<'a> + Default
|
T: Deserialize<'a> + Default
|
||||||
|
@ -467,10 +469,8 @@ fn failure_default<'a, D, T>(deserializer: D)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os="macos"))]
|
static DEFAULT_ALACRITTY_CONFIG: &'static str =
|
||||||
static DEFAULT_ALACRITTY_CONFIG: &'static str = include_str!("../alacritty.yml");
|
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/alacritty.yml"));
|
||||||
#[cfg(target_os="macos")]
|
|
||||||
static DEFAULT_ALACRITTY_CONFIG: &'static str = include_str!("../alacritty_macos.yml");
|
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
@ -1295,12 +1295,6 @@ impl Config {
|
||||||
self.draw_bold_text_with_bright_colors
|
self.draw_bold_text_with_bright_colors
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get font config
|
|
||||||
#[inline]
|
|
||||||
pub fn font(&self) -> &Font {
|
|
||||||
&self.font
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get window dimensions
|
/// Get window dimensions
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn dimensions(&self) -> Dimensions {
|
pub fn dimensions(&self) -> Dimensions {
|
||||||
|
@ -1325,11 +1319,6 @@ impl Config {
|
||||||
self.render_timer
|
self.render_timer
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn use_thin_strokes(&self) -> bool {
|
|
||||||
self.font.use_thin_strokes
|
|
||||||
}
|
|
||||||
|
|
||||||
/// show cursor as inverted
|
/// show cursor as inverted
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn custom_cursor_colors(&self) -> bool {
|
pub fn custom_cursor_colors(&self) -> bool {
|
||||||
|
@ -1464,173 +1453,6 @@ impl Default for Delta {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait DeserializeSize : Sized {
|
|
||||||
fn deserialize<'a, D>(D) -> ::std::result::Result<Self, D::Error>
|
|
||||||
where D: serde::de::Deserializer<'a>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DeserializeSize for Size {
|
|
||||||
fn deserialize<'a, D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
|
|
||||||
where D: serde::de::Deserializer<'a>
|
|
||||||
{
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
|
|
||||||
struct NumVisitor<__D> {
|
|
||||||
_marker: PhantomData<__D>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, __D> Visitor<'a> for NumVisitor<__D>
|
|
||||||
where __D: serde::de::Deserializer<'a>
|
|
||||||
{
|
|
||||||
type Value = f64;
|
|
||||||
|
|
||||||
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
f.write_str("f64 or u64")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_f64<E>(self, value: f64) -> ::std::result::Result<Self::Value, E>
|
|
||||||
where E: ::serde::de::Error
|
|
||||||
{
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_u64<E>(self, value: u64) -> ::std::result::Result<Self::Value, E>
|
|
||||||
where E: ::serde::de::Error
|
|
||||||
{
|
|
||||||
Ok(value as f64)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let size = deserializer
|
|
||||||
.deserialize_any(NumVisitor::<D>{ _marker: PhantomData })
|
|
||||||
.map(|v| Size::new(v as _));
|
|
||||||
|
|
||||||
// Use font size 12 as fallback
|
|
||||||
match size {
|
|
||||||
Ok(size) => Ok(size),
|
|
||||||
Err(err) => {
|
|
||||||
eprintln!("problem with config: {}; Using size 12", err);
|
|
||||||
Ok(Size::new(12.))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Font config
|
|
||||||
///
|
|
||||||
/// Defaults are provided at the level of this struct per platform, but not per
|
|
||||||
/// field in this struct. It might be nice in the future to have defaults for
|
|
||||||
/// each value independently. Alternatively, maybe erroring when the user
|
|
||||||
/// doesn't provide complete config is Ok.
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
|
||||||
pub struct Font {
|
|
||||||
/// Font family
|
|
||||||
pub normal: FontDescription,
|
|
||||||
|
|
||||||
#[serde(default="default_italic_desc")]
|
|
||||||
pub italic: FontDescription,
|
|
||||||
|
|
||||||
#[serde(default="default_bold_desc")]
|
|
||||||
pub bold: FontDescription,
|
|
||||||
|
|
||||||
// Font size in points
|
|
||||||
#[serde(deserialize_with="DeserializeSize::deserialize")]
|
|
||||||
pub size: Size,
|
|
||||||
|
|
||||||
/// Extra spacing per character
|
|
||||||
#[serde(default, deserialize_with = "failure_default")]
|
|
||||||
offset: Delta,
|
|
||||||
|
|
||||||
/// Glyph offset within character cell
|
|
||||||
#[serde(default, deserialize_with = "failure_default")]
|
|
||||||
glyph_offset: Delta,
|
|
||||||
|
|
||||||
#[serde(default="true_bool", deserialize_with = "default_true_bool")]
|
|
||||||
use_thin_strokes: bool
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_bold_desc() -> FontDescription {
|
|
||||||
Font::default().bold
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_italic_desc() -> FontDescription {
|
|
||||||
Font::default().italic
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Description of a single font
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
|
||||||
pub struct FontDescription {
|
|
||||||
pub family: String,
|
|
||||||
pub style: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FontDescription {
|
|
||||||
fn new_with_family<S: Into<String>>(family: S) -> FontDescription {
|
|
||||||
FontDescription {
|
|
||||||
family: family.into(),
|
|
||||||
style: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Font {
|
|
||||||
/// Get the font size in points
|
|
||||||
#[inline]
|
|
||||||
pub fn size(&self) -> Size {
|
|
||||||
self.size
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get offsets to font metrics
|
|
||||||
#[inline]
|
|
||||||
pub fn offset(&self) -> &Delta {
|
|
||||||
&self.offset
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get cell offsets for glyphs
|
|
||||||
#[inline]
|
|
||||||
pub fn glyph_offset(&self) -> &Delta {
|
|
||||||
&self.glyph_offset
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a font clone with a size modification
|
|
||||||
pub fn with_size(self, size: Size) -> Font {
|
|
||||||
Font {
|
|
||||||
size,
|
|
||||||
.. self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
impl Default for Font {
|
|
||||||
fn default() -> Font {
|
|
||||||
Font {
|
|
||||||
normal: FontDescription::new_with_family("Menlo"),
|
|
||||||
bold: FontDescription::new_with_family("Menlo"),
|
|
||||||
italic: FontDescription::new_with_family("Menlo"),
|
|
||||||
size: Size::new(11.0),
|
|
||||||
use_thin_strokes: true,
|
|
||||||
offset: Default::default(),
|
|
||||||
glyph_offset: Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux",target_os = "freebsd"))]
|
|
||||||
impl Default for Font {
|
|
||||||
fn default() -> Font {
|
|
||||||
Font {
|
|
||||||
normal: FontDescription::new_with_family("monospace"),
|
|
||||||
bold: FontDescription::new_with_family("monospace"),
|
|
||||||
italic: FontDescription::new_with_family("monospace"),
|
|
||||||
size: Size::new(11.0),
|
|
||||||
use_thin_strokes: false,
|
|
||||||
offset: Default::default(),
|
|
||||||
glyph_offset: Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Monitor {
|
pub struct Monitor {
|
||||||
_thread: ::std::thread::JoinHandle<()>,
|
_thread: ::std::thread::JoinHandle<()>,
|
||||||
rx: mpsc::Receiver<Config>,
|
rx: mpsc::Receiver<Config>,
|
43
src/font.rs
Normal file
43
src/font.rs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
use config::Delta;
|
||||||
|
use font::Size;
|
||||||
|
|
||||||
|
struct Font {
|
||||||
|
family: String,
|
||||||
|
options: Option<Options>,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AntiAlias {
|
||||||
|
LCD,
|
||||||
|
LCDV,
|
||||||
|
GRAY,
|
||||||
|
// TODO: Maybe change the name so it's not confused with Rust's None?
|
||||||
|
NONE,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Options {
|
||||||
|
size: Option<Size>,
|
||||||
|
thin_strokes: Option<bool>,
|
||||||
|
antialias: Option<AntiAlias>,
|
||||||
|
hinting: Option<bool>,
|
||||||
|
style: Option<String>,
|
||||||
|
offset: Option<Delta>,
|
||||||
|
range: Option<FontRange>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FontRange {
|
||||||
|
start: char,
|
||||||
|
end: char,
|
||||||
|
}
|
|
@ -30,6 +30,7 @@ use index::{Line, Column, RangeInclusive};
|
||||||
use notify::{Watcher, watcher, RecursiveMode, DebouncedEvent};
|
use notify::{Watcher, watcher, RecursiveMode, DebouncedEvent};
|
||||||
|
|
||||||
use config::{self, Config, Delta};
|
use config::{self, Config, Delta};
|
||||||
|
use config::font::FontConfiguration;
|
||||||
use term::{self, cell, RenderableCell};
|
use term::{self, cell, RenderableCell};
|
||||||
use window::{Size, Pixels};
|
use window::{Size, Pixels};
|
||||||
|
|
||||||
|
@ -152,124 +153,47 @@ pub struct GlyphCache {
|
||||||
/// Rasterizer for loading new glyphs
|
/// Rasterizer for loading new glyphs
|
||||||
rasterizer: Rasterizer,
|
rasterizer: Rasterizer,
|
||||||
|
|
||||||
/// regular font
|
/// Font configuration with all fonts
|
||||||
font_key: FontKey,
|
font_config: FontConfiguration,
|
||||||
|
|
||||||
/// italic font
|
|
||||||
italic_key: FontKey,
|
|
||||||
|
|
||||||
/// bold font
|
|
||||||
bold_key: FontKey,
|
|
||||||
|
|
||||||
/// font size
|
|
||||||
font_size: font::Size,
|
|
||||||
|
|
||||||
/// glyph offset
|
|
||||||
glyph_offset: Delta,
|
|
||||||
|
|
||||||
|
/// Font metrics like glyph width/height
|
||||||
metrics: ::font::Metrics,
|
metrics: ::font::Metrics,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlyphCache {
|
impl GlyphCache {
|
||||||
pub fn new<L>(
|
pub fn new<L>(
|
||||||
mut rasterizer: Rasterizer,
|
mut rasterizer: Rasterizer,
|
||||||
font: &config::Font,
|
font_config: FontConfiguration,
|
||||||
loader: &mut L
|
loader: &mut L
|
||||||
) -> Result<GlyphCache, font::Error>
|
) -> Result<GlyphCache, font::Error>
|
||||||
where L: LoadGlyph
|
where L: LoadGlyph
|
||||||
{
|
{
|
||||||
let (regular, bold, italic) = Self::compute_font_keys(font, &mut rasterizer)?;
|
|
||||||
|
|
||||||
// Need to load at least one glyph for the face before calling metrics.
|
// Need to load at least one glyph for the face before calling metrics.
|
||||||
// The glyph requested here ('m' at the time of writing) has no special
|
// The glyph requested here ('0' at the time of writing) has no special
|
||||||
// meaning.
|
// meaning.
|
||||||
rasterizer.get_glyph(&GlyphKey { font_key: regular, c: 'm', size: font.size() })?;
|
let primary_font = font_config.font_by_char('0');
|
||||||
|
rasterizer.get_glyph(&GlyphKey { font_key: primary_font, c: '0', size: primary_font.size() })?;
|
||||||
let metrics = rasterizer.metrics(regular)?;
|
let metrics = rasterizer.metrics(regular)?;
|
||||||
|
|
||||||
let mut cache = GlyphCache {
|
let mut cache = GlyphCache {
|
||||||
cache: HashMap::default(),
|
cache: HashMap::default(),
|
||||||
rasterizer: rasterizer,
|
metrics,
|
||||||
font_size: font.size(),
|
rasterizer,
|
||||||
font_key: regular,
|
font_config,
|
||||||
bold_key: bold,
|
|
||||||
italic_key: italic,
|
|
||||||
glyph_offset: *font.glyph_offset(),
|
|
||||||
metrics: metrics
|
|
||||||
};
|
};
|
||||||
|
|
||||||
cache.load_glyphs_for_font(regular, loader);
|
// TODO: Load set of standard glyphs
|
||||||
cache.load_glyphs_for_font(bold, loader);
|
// cache.load_glyphs_for_font(regular, loader);
|
||||||
cache.load_glyphs_for_font(italic, loader);
|
// cache.load_glyphs_for_font(bold, loader);
|
||||||
|
// cache.load_glyphs_for_font(italic, loader);
|
||||||
|
|
||||||
Ok(cache)
|
Ok(cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_glyphs_for_font<L: LoadGlyph>(
|
|
||||||
&mut self,
|
|
||||||
font: FontKey,
|
|
||||||
loader: &mut L,
|
|
||||||
) {
|
|
||||||
let size = self.font_size;
|
|
||||||
for i in RangeInclusive::new(32u8, 128u8) {
|
|
||||||
self.get(&GlyphKey {
|
|
||||||
font_key: font,
|
|
||||||
c: i as char,
|
|
||||||
size: size
|
|
||||||
}, loader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computes font keys for (Regular, Bold, Italic)
|
|
||||||
fn compute_font_keys(
|
|
||||||
font: &config::Font,
|
|
||||||
rasterizer: &mut Rasterizer
|
|
||||||
) -> Result<(FontKey, FontKey, FontKey), font::Error> {
|
|
||||||
let size = font.size();
|
|
||||||
|
|
||||||
// Load regular font
|
|
||||||
let regular_desc = Self::make_desc(&font.normal, font::Slant::Normal, font::Weight::Normal);
|
|
||||||
|
|
||||||
let regular = rasterizer
|
|
||||||
.load_font(®ular_desc, size)?;
|
|
||||||
|
|
||||||
// helper to load a description if it is not the regular_desc
|
|
||||||
let mut load_or_regular = |desc:FontDesc| {
|
|
||||||
if desc == regular_desc {
|
|
||||||
regular
|
|
||||||
} else {
|
|
||||||
rasterizer.load_font(&desc, size).unwrap_or_else(|_| regular)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Load bold font
|
|
||||||
let bold_desc = Self::make_desc(&font.bold, font::Slant::Normal, font::Weight::Bold);
|
|
||||||
|
|
||||||
let bold = load_or_regular(bold_desc);
|
|
||||||
|
|
||||||
// Load italic font
|
|
||||||
let italic_desc = Self::make_desc(&font.italic, font::Slant::Italic, font::Weight::Normal);
|
|
||||||
|
|
||||||
let italic = load_or_regular(italic_desc);
|
|
||||||
|
|
||||||
Ok((regular, bold, italic))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_desc(
|
|
||||||
desc: &config::FontDescription,
|
|
||||||
slant: font::Slant,
|
|
||||||
weight: font::Weight,
|
|
||||||
) -> FontDesc {
|
|
||||||
let style = if let Some(ref spec) = desc.style {
|
|
||||||
font::Style::Specific(spec.to_owned())
|
|
||||||
} else {
|
|
||||||
font::Style::Description {slant:slant, weight:weight}
|
|
||||||
};
|
|
||||||
FontDesc::new(&desc.family[..], style)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn font_metrics(&self) -> font::Metrics {
|
pub fn font_metrics(&self) -> font::Metrics {
|
||||||
|
let primary_font = self.font_config.font_by_char('0');
|
||||||
self.rasterizer
|
self.rasterizer
|
||||||
.metrics(self.font_key)
|
.metrics(primary_font)
|
||||||
.expect("metrics load since font is loaded at glyph cache creation")
|
.expect("metrics load since font is loaded at glyph cache creation")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,9 +216,11 @@ impl GlyphCache {
|
||||||
loader.load_glyph(&rasterized)
|
loader.load_glyph(&rasterized)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
pub fn update_font_size<L: LoadGlyph>(
|
pub fn update_font_size<L: LoadGlyph>(
|
||||||
&mut self,
|
&mut self,
|
||||||
font: &config::Font,
|
font: &FontConfiguration,
|
||||||
size: font::Size,
|
size: font::Size,
|
||||||
loader: &mut L
|
loader: &mut L
|
||||||
) -> Result<(), font::Error> {
|
) -> Result<(), font::Error> {
|
||||||
|
|
Loading…
Reference in a new issue