Skip to content

Commit 6c9db1b

Browse files
authored
[CWS] Support for remove_internal/external options (#12)
* [CWS] Support for remove_internal/external options Used for closed paths. Don't merge until MFEK/math.rlib#8 is merged. * rustfmt
1 parent f5cc602 commit 6c9db1b

2 files changed

Lines changed: 93 additions & 41 deletions

File tree

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,7 @@ FONTFORGE := $(if $(FONTFORGE),"fontforge","")
99
.PHONY: all
1010
all:
1111
cargo build $(DEBUGARGS) --features $(FONTFORGE)
12+
13+
.PHONY: fmt
14+
fmt:
15+
find src -type f -iname '*.rs' | parallel --bar RUST_LOG=error rustfmt {}

src/constant_width_stroke.rs

Lines changed: 89 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,77 @@ pub fn clap_app() -> clap::App<'static, 'static> {
5656
.help(r#"<f64> Constant stroke width."#)
5757
.validator(super::arg_validator_positive_f64)
5858
.required(true))
59+
.arg(Arg::with_name("remove-internal")
60+
.long("remove-internal")
61+
.short("I")
62+
.takes_value(false)
63+
.help(r#"Remove internal contour"#))
64+
.arg(Arg::with_name("remove-external")
65+
.long("remove-external")
66+
.short("E")
67+
.takes_value(false)
68+
.help(r#"Remove external contour"#))
69+
}
70+
71+
#[derive(Debug)]
72+
struct CWSSettings {
73+
vws_settings: VWSSettings,
74+
width: f64,
75+
jointype: JoinType,
76+
startcap: CapType,
77+
endcap: CapType,
78+
remove_internal: bool,
79+
remove_external: bool,
80+
}
81+
82+
fn constant_width_stroke(
83+
path: &glifparser::Glif<Option<PointData>>,
84+
settings: &CWSSettings,
85+
) -> Outline<Option<PointData>> {
86+
let vws_contour = VWSContour {
87+
id: 0,
88+
join_type: settings.jointype,
89+
cap_start_type: settings.startcap,
90+
cap_end_type: settings.endcap,
91+
handles: vec![], // to be populated based on number of points
92+
remove_internal: settings.remove_internal,
93+
remove_external: settings.remove_external,
94+
};
95+
96+
// convert our path and pattern to piecewise collections of beziers
97+
let piece_path = Piecewise::from(path.outline.as_ref().unwrap());
98+
let mut output_outline: Outline<Option<PointData>> = Vec::new();
99+
100+
let mut vws_contours = vec![vws_contour; path.outline.as_ref().unwrap().len()];
101+
102+
let vws_handle = VWSHandle {
103+
left_offset: settings.width / 2.0,
104+
right_offset: settings.width / 2.0,
105+
tangent_offset: 0.0,
106+
interpolation: InterpolationType::Linear,
107+
};
108+
109+
for outline in path.outline.as_ref() {
110+
for (cidx, contour) in outline.iter().enumerate() {
111+
let pointiter = contour.iter().enumerate();
112+
113+
for (_, _) in pointiter {
114+
vws_contours[cidx].handles.push(vws_handle);
115+
}
116+
vws_contours[cidx].handles.push(vws_handle);
117+
}
118+
}
119+
120+
let iter = piece_path.segs.iter().enumerate();
121+
for (i, pwpath_contour) in iter {
122+
let vws_contour = &vws_contours[i];
123+
124+
let results = variable_width_stroke(&pwpath_contour, &vws_contour, &settings.vws_settings);
125+
for result_contour in results.segs {
126+
output_outline.push(result_contour.to_contour());
127+
}
128+
}
129+
output_outline
59130
}
60131

61132
// Constant width stroking is really just a special case of variable width stroking. So, we take
@@ -96,60 +167,36 @@ pub fn cws_cli(matches: &clap::ArgMatches) {
96167
let startcap = str_to_cap(matches.value_of("startcap").unwrap());
97168
let endcap = str_to_cap(matches.value_of("endcap").unwrap());
98169
let jointype = str_to_jointype(matches.value_of("jointype").unwrap());
170+
let remove_internal = matches.is_present("remove-internal");
171+
let remove_external = matches.is_present("remove-external");
99172

100173
let width: f64 = matches.value_of("width").unwrap().parse().unwrap();
101174
let path: glifparser::Glif<Option<PointData>> =
102175
glifparser::read_ufo_glif(&fs::read_to_string(input_file).expect("Failed to read file!"));
103176

104-
let vws_contour = VWSContour {
105-
id: 0,
106-
join_type: jointype,
107-
cap_start_type: startcap,
108-
cap_end_type: endcap,
109-
handles: vec![], // to be populated based on number of points
110-
};
111-
112-
let settings = VWSSettings {
177+
let vws_settings = VWSSettings {
113178
cap_custom_end: custom_cap_if_requested(endcap, matches.value_of("endcap").unwrap()),
114179
cap_custom_start: custom_cap_if_requested(startcap, matches.value_of("startcap").unwrap()),
115180
};
116181

117-
// convert our path and pattern to piecewise collections of beziers
118-
let piece_path = Piecewise::from(path.outline.as_ref().unwrap());
119-
let mut output_outline: Outline<Option<PointData>> = Vec::new();
120-
121-
let mut vws_contours = vec![vws_contour; path.outline.as_ref().unwrap().len()];
122-
123-
let vws_handle = VWSHandle {
124-
left_offset: width / 2.0,
125-
right_offset: width / 2.0,
126-
tangent_offset: 0.0,
127-
interpolation: InterpolationType::Linear,
182+
let cws_settings = CWSSettings {
183+
vws_settings: vws_settings,
184+
width: width,
185+
startcap: startcap,
186+
endcap: endcap,
187+
jointype: jointype,
188+
remove_internal: remove_internal,
189+
remove_external: remove_external,
128190
};
129191

130-
for outline in path.outline.as_ref() {
131-
for (cidx, contour) in outline.iter().enumerate() {
132-
let pointiter = contour.iter().enumerate();
133-
134-
for (_, _) in pointiter {
135-
vws_contours[cidx].handles.push(vws_handle);
136-
}
137-
vws_contours[cidx].handles.push(vws_handle);
138-
}
139-
}
140-
141-
let iter = piece_path.segs.iter().enumerate();
142-
for (i, pwpath_contour) in iter {
143-
let vws_contour = &vws_contours[i];
144-
145-
let results = variable_width_stroke(&pwpath_contour, &vws_contour, &settings);
146-
for result_contour in results.segs {
147-
output_outline.push(result_contour.to_contour());
148-
}
149-
}
192+
let output_outline = path
193+
.outline
194+
.as_ref()
195+
.map(|_| Some(constant_width_stroke(&path, &cws_settings)))
196+
.unwrap_or_else(|| None);
150197

151198
let out = Glif {
152-
outline: Some(output_outline),
199+
outline: output_outline,
153200
order: path.order,
154201
anchors: path.anchors.clone(),
155202
width: path.width,
@@ -158,6 +205,7 @@ pub fn cws_cli(matches: &clap::ArgMatches) {
158205
format: 2,
159206
lib: None,
160207
};
208+
161209
let glifstring = glifparser::write_ufo_glif(&out);
162210
fs::write(output_file, glifstring).expect("Unable to write file");
163211
}

0 commit comments

Comments
 (0)