use std::path;
use crate::anchor::Anchor;
use crate::component::GlifComponents;
use crate::error::GlifParserError;
use crate::guideline::Guideline;
#[cfg(feature = "glifimage")]
use crate::image::GlifImage;
use crate::point::PointData;
use crate::outline::Outline;
mod conv;
mod lib;
pub use lib::Lib;
mod read;
pub use self::read::read_ufo_glif as read;
pub use self::read::read_ufo_glif_pedantic as read_pedantic;
pub use self::read::read_ufo_glif_from_filename as read_from_filename;
pub use self::read::read_ufo_glif_from_filename_pedantic as read_from_filename_pedantic;
mod write;
pub use self::write::write_ufo_glif as write;
pub use self::write::write_ufo_glif_to_filename as write_to_filename;
#[cfg(feature = "mfek")]
pub mod mfek;
pub mod xml;
pub use self::{read::FromXML, write::IntoXML, xml::XMLConversion};
#[cfg(feature = "glifserde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "mfek")]
pub use mfek::*;
#[cfg_attr(feature = "glifserde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Glif<PD: PointData> {
pub outline: Option<Outline<PD>>,
pub anchors: Vec<Anchor<PD>>,
pub components: GlifComponents,
pub guidelines: Vec<Guideline<PD>>,
#[cfg(feature = "glifimage")]
pub images: Vec<GlifImage>,
pub width: Option<u64>,
pub unicode: Vec<char>,
pub name: String,
pub note: Option<String>,
#[cfg_attr(feature = "glifserde", serde(skip_serializing, skip_deserializing))]
pub filename: Option<path::PathBuf>,
pub lib: Lib,
}
impl<PD: PointData> Glif<PD> {
pub fn new() -> Self {
Self::default()
}
pub fn name_to_filename(&self) -> String {
name_to_filename(&self.name, true)
}
pub fn filename_is_sane(&self) -> Result<bool, GlifParserError> {
match &self.filename {
Some(gfn) => {
let gfn_fn = match gfn.file_name() {
Some(gfn_fn) => gfn_fn,
None => { return Err(GlifParserError::GlifFilenameInsane("Glif file name is directory".to_string())) }
};
Ok(self.name_to_filename() == gfn_fn.to_str().ok_or(GlifParserError::GlifFilenameInsane("Glif file name has unknown encoding".to_string()))?)
}
None => Err(GlifParserError::GlifFilenameInsane("Glif file name is not set".to_string()))
}
}
}
pub trait GlifLike {
fn name(&self) -> &String;
fn filename(&self) -> &Option<path::PathBuf>;
}
impl<PD: PointData> GlifLike for Glif<PD> {
fn name(&self) -> &String {
&self.name
}
fn filename(&self) -> &Option<path::PathBuf> {
&self.filename
}
}
#[inline]
pub fn name_to_filename(name: &str, append_extension: bool) -> String {
let mut ret = String::new();
let chars: Vec<char> = name.chars().collect();
for c in chars {
ret.push(c);
if ('A'..'Z').contains(&c) {
ret.push('_');
}
}
if append_extension {
ret.push_str(".glif");
}
ret
}