1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use integer_or_float::IntegerOrFloat;
mod xml;
use std::fmt::Debug;
#[cfg(feature = "glifserde")]
use serde::{Serialize, Deserialize};
use crate::error::GlifParserError;
use crate::pedantry::{FloatClass, Mend, Pedantry};
use crate::point::PointData;
use crate::string::GlifStringLenOne;
#[cfg_attr(feature = "glifserde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Derivative, PartialEq, Eq, Unwrap, IsVariant)]
#[derivative(Default(new="true"))]
pub enum AnchorType {
Mark,
#[derivative(Default)]
Base,
}
impl<S> From<S> for AnchorType where S: AsRef<str> {
fn from(s: S) -> Self {
if s.as_ref().chars().nth(0) == Some('_') {
Self::Mark
} else {
Self::Base
}
}
}
pub trait FromOption<S: Into<AnchorType>>: Default {
fn from_option(s: Option<S>) -> AnchorType {
match s {
Some(ss) => ss.into(),
None => AnchorType::default()
}
}
}
impl<S: Into<Self>> FromOption<S> for AnchorType {}
#[cfg_attr(feature = "glifserde", derive(Serialize, Deserialize))]
#[derive(Constructor, Clone, Debug, Default, PartialEq)]
pub struct Anchor<PD: PointData> {
pub x: f32,
pub y: f32,
#[cfg_attr(feature = "glifserde", serde(default))]
pub class: Option<String>,
#[cfg_attr(feature = "glifserde", serde(default))]
pub data: PD,
#[cfg_attr(feature = "glifserde", serde(default))]
pub atype: AnchorType,
}
impl<PD: PointData> Anchor<PD> {
pub fn from_glif(ga: &GlifAnchor, pedantry: Pedantry) -> Result<Self, GlifParserError> {
let (x, y) = (pedantry.level.maybe_round(ga.x, FloatClass::Anchor), pedantry.level.maybe_round(ga.y, FloatClass::Anchor));
let class = ga.class.as_ref().map(|gs|gs.to_string());
if pedantry.mend != Mend::Always && (!ga.x.holding_integer().is_ok() || !ga.y.holding_integer().is_ok()) {
return Err(GlifParserError::PedanticXmlParseError("Anchor was a float, not an integer!".to_string()))
}
let atype = AnchorType::from_option(class.as_ref());
Ok(Self {
x, y, class, atype, data: PD::default()
})
}
}
#[cfg_attr(feature = "glifserde", derive(Serialize, Deserialize))]
#[derive(Constructor, Clone, Debug, Default, PartialEq)]
pub struct GlifAnchor {
pub x: IntegerOrFloat,
pub y: IntegerOrFloat,
pub class: Option<GlifStringLenOne>,
}