diff options
Diffstat (limited to 'src/config/font.rs')
-rw-r--r-- | src/config/font.rs | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/src/config/font.rs b/src/config/font.rs new file mode 100644 index 00000000..2d3ae310 --- /dev/null +++ b/src/config/font.rs @@ -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) + }, + } +} |