use std::collections::BTreeMap;
use crate::{
common::{InstanceFactors, SmartComponentSetting},
serde::{
anything_to_bool, bool_true, deserialize_comma_hexstring, deserialize_commify, is_default,
is_false, is_scale_unit, is_true, scale_unit, serialize_comma_hexstring, serialize_commify,
},
};
use openstep_plist::Dictionary;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use crate::{
common::{
Color, CustomParameter, Feature, FeatureClass, FeaturePrefix, Kerning, NodeType,
Orientation, Version,
},
serde::{is_one_hundred, one_hundred},
};
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
pub struct Glyphs2 {
#[serde(
rename = ".appVersion",
default,
skip_serializing_if = "String::is_empty"
)]
pub app_version: String,
#[serde(
rename = "DisplayStrings",
skip_serializing_if = "Vec::is_empty",
default
)]
pub display_strings: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub classes: Vec<FeatureClass>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub copyright: Option<String>,
#[serde(
default,
rename = "customParameters",
skip_serializing_if = "Vec::is_empty"
)]
pub custom_parameters: Vec<CustomParameter>,
#[serde(default, skip_serializing_if = "String::is_empty")]
pub date: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub designer: Option<String>,
#[serde(
default,
rename = "designerURL",
skip_serializing_if = "Option::is_none"
)]
pub designer_url: Option<String>,
#[serde(
default,
skip_serializing_if = "is_default",
rename = "disablesAutomaticAlignment"
)]
pub disables_automatic_alignment: bool,
#[serde(
default,
skip_serializing_if = "is_default",
rename = "disablesNiceNames"
)]
pub disables_nice_names: bool,
#[serde(rename = "familyName")]
pub family_name: String,
#[serde(
default,
rename = "featurePrefixes",
skip_serializing_if = "Vec::is_empty"
)]
pub feature_prefixes: Vec<FeaturePrefix>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub features: Vec<Feature>,
#[serde(rename = "fontMaster", skip_serializing_if = "Vec::is_empty", default)]
pub masters: Vec<Master>,
#[serde(default)]
pub glyphs: Vec<Glyph>,
#[serde(rename = "gridLength", skip_serializing_if = "Option::is_none")]
pub grid_length: Option<i32>,
#[serde(rename = "gridSubDivision", skip_serializing_if = "Option::is_none")]
pub grid_sub_division: Option<i32>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub instances: Vec<Instance>,
#[serde(
rename = "keepAlternatesTogether",
default,
skip_serializing_if = "is_default"
)]
pub keep_alternates_together: bool,
#[serde(default, skip_serializing_if = "Kerning::is_empty")]
pub kerning: Kerning,
#[serde(
rename = "vertKerning",
default,
skip_serializing_if = "Kerning::is_empty"
)]
pub kerning_vertical: Kerning,
#[serde(rename = "keyboardIncrement", skip_serializing_if = "Option::is_none")]
pub keyboard_increment: Option<f32>,
#[serde(
rename = "keyboardIncrementBig",
skip_serializing_if = "Option::is_none"
)]
pub keyboard_increment_big: Option<f32>,
#[serde(
rename = "keyboardIncrementHuge",
skip_serializing_if = "Option::is_none"
)]
pub keyboard_increment_huge: Option<f32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub manufacturer: Option<String>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
rename = "manufacturerURL"
)]
pub manufacturer_url: Option<String>,
#[serde(rename = "unitsPerEm")]
pub units_per_em: i32,
#[serde(rename = "userData", default, skip_serializing_if = "is_default")]
pub user_data: Dictionary,
#[serde(flatten, default, skip_serializing_if = "is_default")]
pub version: Version,
}
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
pub struct Master {
#[serde(
rename = "alignmentZones",
skip_serializing_if = "Vec::is_empty",
default
)]
pub alignment_zones: Vec<AlignmentZone>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ascender: Option<f32>,
#[serde(rename = "capHeight", default, skip_serializing_if = "Option::is_none")]
pub cap_height: Option<f32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub custom: Option<String>,
#[serde(default, skip_serializing_if = "is_default", rename = "customValue")]
pub custom_value: i32,
#[serde(default, skip_serializing_if = "is_default", rename = "customValue1")]
pub custom_value_1: i32,
#[serde(default, skip_serializing_if = "is_default", rename = "customValue2")]
pub custom_value_2: i32,
#[serde(default, skip_serializing_if = "is_default", rename = "customValue3")]
pub custom_value_3: i32,
#[serde(
rename = "customParameters",
default,
skip_serializing_if = "Vec::is_empty"
)]
pub custom_parameters: Vec<CustomParameter>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub descender: Option<f32>,
#[serde(rename = "guideLines", default, skip_serializing_if = "Vec::is_empty")]
pub guides: Vec<Guide>,
#[serde(
default,
skip_serializing_if = "Vec::is_empty",
rename = "horizontalStems"
)]
pub horizontal_stems: Vec<i32>,
#[serde(rename = "iconName", default, skip_serializing_if = "String::is_empty")]
pub icon_name: String,
pub id: String,
#[serde(default, skip_serializing_if = "is_default", rename = "italicAngle")]
pub italic_angle: f32,
#[serde(default, skip_serializing_if = "String::is_empty")]
pub name: String,
#[serde(rename = "userData", default, skip_serializing_if = "is_default")]
pub user_data: Dictionary,
#[serde(
rename = "verticalStems",
default,
skip_serializing_if = "Vec::is_empty"
)]
pub vertical_stems: Vec<i32>,
#[serde(default, skip_serializing_if = "is_default")]
pub visible: bool,
#[serde(default, skip_serializing_if = "String::is_empty")]
pub weight: String,
#[serde(
default = "one_hundred",
skip_serializing_if = "is_one_hundred",
rename = "weightValue"
)]
pub weight_value: i32,
#[serde(default, skip_serializing_if = "String::is_empty")]
pub width: String,
#[serde(
default = "one_hundred",
skip_serializing_if = "is_one_hundred",
rename = "widthValue"
)]
pub width_value: i32,
#[serde(default, rename = "xHeight", skip_serializing_if = "Option::is_none")]
pub x_height: Option<f32>,
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct AlignmentZone {
pub position: f32,
pub overshoot: f32,
}
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
pub struct Instance {
#[serde(
rename = "customParameters",
default,
skip_serializing_if = "Vec::is_empty"
)]
pub custom_parameters: Vec<CustomParameter>,
#[serde(default = "bool_true", skip_serializing_if = "is_true")]
pub exports: bool,
#[serde(
default,
skip_serializing_if = "is_default",
rename = "interpolationCustom"
)]
pub custom_value: f32,
#[serde(
default,
skip_serializing_if = "is_default",
rename = "interpolationCustom1"
)]
pub custom_value_1: f32,
#[serde(
default,
skip_serializing_if = "is_default",
rename = "interpolationCustom2"
)]
pub custom_value_2: f32,
#[serde(
default,
skip_serializing_if = "is_default",
rename = "interpolationCustom3"
)]
pub custom_value_3: f32,
#[serde(
default,
skip_serializing_if = "is_default",
rename = "interpolationWeight"
)]
pub weight_value: f32,
#[serde(
default,
skip_serializing_if = "is_default",
rename = "interpolationWidth"
)]
pub width_value: f32,
#[serde(
default,
skip_serializing_if = "BTreeMap::is_empty",
rename = "instanceInterpolations"
)]
pub instance_interpolations: BTreeMap<String, InstanceFactors>,
#[serde(default, rename = "isBold", skip_serializing_if = "is_false")]
pub is_bold: bool,
#[serde(default, rename = "isItalic", skip_serializing_if = "is_false")]
pub is_italic: bool,
#[serde(default, rename = "linkStyle", skip_serializing_if = "Option::is_none")]
pub link_style: Option<String>,
#[serde(
default,
rename = "manualInterpolation",
skip_serializing_if = "is_false"
)]
pub manual_interpolation: bool,
pub name: String,
#[serde(default, rename = "userData", skip_serializing_if = "is_default")]
pub user_data: Dictionary,
#[serde(
default,
rename = "weightClass",
skip_serializing_if = "Option::is_none"
)]
pub weight_class: Option<String>,
#[serde(
default,
rename = "widthClass",
skip_serializing_if = "Option::is_none"
)]
pub width_class: Option<String>,
}
#[serde_as]
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
pub struct Glyph {
#[serde(rename = "bottomKerningGroup", skip_serializing_if = "is_default")]
pub kern_bottom: Option<String>,
#[serde(
default,
skip_serializing_if = "is_default",
rename = "bottomMetricsKey"
)]
pub metric_bottom: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub category: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub color: Option<Color>,
#[serde(default = "bool_true", skip_serializing_if = "is_true")]
pub export: bool,
#[serde(rename = "glyphname")]
pub name: String,
#[serde(rename = "lastChange", skip_serializing_if = "is_default")]
pub last_change: Option<String>,
pub layers: Vec<Layer>,
#[serde(rename = "leftKerningGroup", skip_serializing_if = "is_default")]
pub kern_left: Option<String>,
#[serde(default, skip_serializing_if = "is_default", rename = "leftMetricsKey")]
pub metric_left: Option<String>,
#[serde(
default,
skip_serializing_if = "is_default",
deserialize_with = "anything_to_bool"
)]
pub locked: bool,
#[serde(default, skip_serializing_if = "is_default")]
pub note: String,
#[serde(
default,
skip_serializing_if = "Vec::is_empty",
rename = "partsSettings"
)]
pub smart_component_settings: Vec<SmartComponentSetting>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub production: Option<String>,
#[serde(rename = "rightKerningGroup", skip_serializing_if = "is_default")]
pub kern_right: Option<String>,
#[serde(
default,
skip_serializing_if = "is_default",
rename = "rightMetricsKey"
)]
pub metric_right: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub script: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub subcategory: Option<String>,
#[serde(rename = "topKerningGroup", skip_serializing_if = "is_default")]
pub kern_top: Option<String>,
#[serde(default, skip_serializing_if = "is_default", rename = "topMetricsKey")]
pub metric_top: Option<String>,
#[serde(
default,
deserialize_with = "deserialize_comma_hexstring",
serialize_with = "serialize_comma_hexstring",
skip_serializing_if = "Vec::is_empty",
alias = "unicodes"
)]
pub unicode: Vec<u32>,
#[serde(rename = "userData", default, skip_serializing_if = "is_default")]
pub user_data: Dictionary,
#[serde(
default,
skip_serializing_if = "is_default",
rename = "vertWidthMetricsKey"
)]
pub metric_vert_width: Option<String>,
#[serde(
default,
skip_serializing_if = "is_default",
rename = "widthMetricsKey"
)]
pub metric_width: Option<String>,
}
#[serde_as]
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
pub struct Layer {
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub anchors: Vec<Anchor>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub annotations: Vec<Dictionary>,
#[serde(
rename = "associatedMasterId",
default,
skip_serializing_if = "is_default"
)]
pub associated_master_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub background: Option<Box<Layer>>,
#[serde(
rename = "backgroundImage",
default,
skip_serializing_if = "Option::is_none"
)]
pub background_image: Option<BackgroundImage>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub color: Option<ColorLabel>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub components: Vec<Component>,
#[serde(default, skip_serializing_if = "Vec::is_empty", rename = "guideLines")]
pub guides: Vec<Guide>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub hints: Vec<Hint>,
#[serde(rename = "layerId", default, skip_serializing_if = "String::is_empty")]
pub layer_id: String,
#[serde(rename = "leftMetricsKey", default, skip_serializing_if = "is_default")]
pub metric_left: Option<String>,
#[serde(
rename = "rightMetricsKey",
default,
skip_serializing_if = "is_default"
)]
pub metric_right: Option<String>,
#[serde(
rename = "widthMetricsKey",
default,
skip_serializing_if = "is_default"
)]
pub metric_width: Option<String>,
#[serde(default, skip_serializing_if = "is_default")]
pub name: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub paths: Vec<Path>,
#[serde(rename = "userData", default, skip_serializing_if = "is_default")]
pub user_data: Dictionary,
#[serde(rename = "vertWidth", default, skip_serializing_if = "is_default")]
pub vert_width: Option<f32>,
#[serde(default, skip_serializing_if = "is_default")]
pub width: f32,
#[serde(default = "bool_true", skip_serializing_if = "is_true")]
pub visible: bool,
}
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
pub struct Anchor {
pub name: String,
#[serde(
serialize_with = "serialize_commify",
deserialize_with = "deserialize_commify"
)]
pub position: (f32, f32),
}
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
pub struct BackgroundImage {
#[serde(default)]
pub crop: CropRect,
#[serde(rename = "imagePath", default)]
pub image_path: String,
#[serde(
default,
skip_serializing_if = "is_false",
deserialize_with = "anything_to_bool"
)]
pub locked: bool,
pub transform: Transform,
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Transform {
pub m11: f32,
pub m12: f32,
pub m21: f32,
pub m22: f32,
pub t_x: f32,
pub t_y: f32,
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct CropRect {
pub top: i32,
pub left: i32,
pub bottom: i32,
pub right: i32,
}
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
pub struct Component {
#[serde(default, skip_serializing_if = "is_default")]
pub alignment: i8,
#[serde(default, skip_serializing_if = "is_default")]
pub anchor: Option<String>,
#[serde(
default,
skip_serializing_if = "is_false",
deserialize_with = "anything_to_bool"
)]
pub locked: bool,
#[serde(rename = "piece", default, skip_serializing_if = "is_default")]
pub smart_component_location: BTreeMap<String, f32>,
#[serde(rename = "name")]
pub component_glyph: String,
#[serde(default, skip_serializing_if = "is_default")]
pub transform: Transform,
#[serde(
default,
skip_serializing_if = "is_default",
rename = "disableAlignment"
)]
pub disable_alignment: bool,
#[serde(rename = "userData", default, skip_serializing_if = "is_default")]
pub user_data: Dictionary,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct Guide {
#[serde(default, skip_serializing_if = "is_default")]
pub alignment: Orientation,
#[serde(default, skip_serializing_if = "is_default")]
pub angle: f32,
#[serde(default, skip_serializing_if = "is_default")]
pub filter: String,
#[serde(default, skip_serializing_if = "is_default")]
pub grid: f32,
#[serde(default, skip_serializing_if = "is_default")]
pub length: f32,
#[serde(
default,
skip_serializing_if = "is_false",
deserialize_with = "anything_to_bool",
rename = "lockAngle"
)]
pub lock_angle: bool,
#[serde(
default,
skip_serializing_if = "is_false",
deserialize_with = "anything_to_bool"
)]
pub locked: bool,
#[serde(default, skip_serializing_if = "is_default")]
pub name: String,
#[serde(
default,
skip_serializing_if = "is_default",
rename = "showMeasurement"
)]
pub show_measurement: bool,
#[serde(
rename = "position",
serialize_with = "serialize_commify",
deserialize_with = "deserialize_commify"
)]
pub pos: (f32, f32),
#[serde(
default = "scale_unit",
serialize_with = "serialize_commify",
deserialize_with = "deserialize_commify",
skip_serializing_if = "is_scale_unit"
)]
pub scale: (f32, f32),
#[serde(rename = "userData", default, skip_serializing_if = "is_default")]
pub user_data: Dictionary,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct Hint {
#[serde(default, skip_serializing_if = "is_default")]
pub horizontal: bool,
#[serde(default, rename = "type")]
pub type_: String,
#[serde(default, skip_serializing_if = "is_default")]
pub name: String,
#[serde(
default,
skip_serializing_if = "is_default",
serialize_with = "serialize_commify",
deserialize_with = "deserialize_commify"
)]
pub origin: (f32, f32),
#[serde(default, skip_serializing_if = "is_default")]
pub target: HintTarget,
#[serde(
default,
skip_serializing_if = "is_default",
serialize_with = "serialize_commify",
deserialize_with = "deserialize_commify"
)]
pub other1: (f32, f32),
#[serde(
default,
skip_serializing_if = "is_default",
serialize_with = "serialize_commify",
deserialize_with = "deserialize_commify"
)]
pub other2: (f32, f32),
#[serde(
default,
skip_serializing_if = "is_default",
serialize_with = "serialize_commify",
deserialize_with = "deserialize_commify"
)]
pub scale: (f32, f32),
#[serde(default, skip_serializing_if = "is_default")]
pub stem: bool,
#[serde(default, skip_serializing_if = "is_default")]
pub options: i8,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
#[serde(untagged)]
pub enum HintTarget {
#[serde(
serialize_with = "serialize_commify",
deserialize_with = "deserialize_commify"
)]
Position((f32, f32)),
Label(String),
}
impl Default for HintTarget {
fn default() -> Self {
HintTarget::Position((0.0, 0.0))
}
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct Path {
#[serde(default, skip_serializing_if = "is_false")]
pub closed: bool,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub nodes: Vec<Node>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Node {
pub x: f32,
pub y: f32,
pub node_type: NodeType,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
#[serde(untagged)]
pub enum ColorLabel {
IntColor(u16),
ArrayColor(Color),
}