mirror of
https://github.com/storytold/cadcraft.git
synced 2026-10-26 03:46:53 -06:00
Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e094c2f92 | ||
|
|
dd802e0956 | ||
|
|
f4485bbee7 | ||
|
|
97d570c421 | ||
|
|
1b6861698c | ||
|
|
f24af47ffb | ||
|
|
055b06a2f4 | ||
|
|
660a7881d1 | ||
|
|
3d8301b965 | ||
|
|
cb8b1709e9 | ||
|
|
66ecce06f5 |
@@ -120,7 +120,7 @@ fn style(s: &Session) -> String {
|
||||
s.doc().map(|d| d.header.str("DIMSTYLE", "Standard")).unwrap_or_else(|_| "Standard".into())
|
||||
}
|
||||
|
||||
fn dim(s: &Session, kind: DimKind, defpt: Vec2, p13: Vec2, p14: Vec2, p15: Vec2, p16: Vec2, text: &str) -> EntityKind {
|
||||
fn dim(s: &Session, kind: DimKind, defpt: Vec2, p13: Vec2, p14: Vec2, p15: Vec2, text: &str) -> EntityKind {
|
||||
EntityKind::Dimension(Dimension {
|
||||
kind,
|
||||
defpt: v3(defpt),
|
||||
@@ -128,7 +128,7 @@ fn dim(s: &Session, kind: DimKind, defpt: Vec2, p13: Vec2, p14: Vec2, p15: Vec2,
|
||||
p13: v3(p13),
|
||||
p14: v3(p14),
|
||||
p15: v3(p15),
|
||||
p16: v3(p16),
|
||||
p16: v3(Vec2::ZERO),
|
||||
text: text.into(),
|
||||
style: style(s),
|
||||
measurement: 0.0,
|
||||
@@ -205,7 +205,10 @@ fn angular_from_lines(s: &Session, h1: Handle, h2: Handle, at: Vec2) -> Option<E
|
||||
// The picked leg end goes last in each pair, so the renderer measures between p14 and p15.
|
||||
let (o1, t1) = if s1 == AssocSnap::Start { (a2, AssocSnap::End) } else { (a1, AssocSnap::Start) };
|
||||
let (o2, t2) = if s2 == AssocSnap::Start { (b2, AssocSnap::End) } else { (b1, AssocSnap::Start) };
|
||||
let k = dim(s, DimKind::Angular, o2, o1, p1, p2, at, "");
|
||||
let mut k = dim(s, DimKind::Angular, o2, o1, p1, p2, "");
|
||||
if let EntityKind::Dimension(d) = &mut k {
|
||||
d.p16 = v3(at);
|
||||
}
|
||||
let mut assoc = Vec::new();
|
||||
if assoc_enabled(s) {
|
||||
assoc = vec![
|
||||
@@ -225,7 +228,7 @@ fn run_linear(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
};
|
||||
let at = point_req("dimlinear", p, "at")?;
|
||||
let rot = p.get("rotation").and_then(Value::as_f64).map(f64::to_radians);
|
||||
let k = dim(s, linear_kind(a, b, at, rot, false), at, a, b, Vec2::ZERO, Vec2::ZERO, str_param(p, "text").unwrap_or(""));
|
||||
let k = dim(s, linear_kind(a, b, at, rot, false), at, a, b, Vec2::ZERO, str_param(p, "text").unwrap_or(""));
|
||||
Ok(json!({ "handle": add_dim(s, k)?.hex() }))
|
||||
}
|
||||
|
||||
@@ -233,7 +236,7 @@ fn run_aligned(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let a = point_req("dimaligned", p, "p1")?;
|
||||
let b = point_req("dimaligned", p, "p2")?;
|
||||
let at = point_req("dimaligned", p, "at")?;
|
||||
let k = dim(s, DimKind::Aligned, at, a, b, Vec2::ZERO, Vec2::ZERO, str_param(p, "text").unwrap_or(""));
|
||||
let k = dim(s, DimKind::Aligned, at, a, b, Vec2::ZERO, str_param(p, "text").unwrap_or(""));
|
||||
Ok(json!({ "handle": add_dim(s, k)?.hex() }))
|
||||
}
|
||||
|
||||
@@ -261,9 +264,9 @@ fn radial(s: &mut Session, p: &Value, diameter: bool) -> Result<Value> {
|
||||
return Err(bad(id, "`point` must differ from `center`"));
|
||||
}
|
||||
let k = if diameter {
|
||||
dim(s, DimKind::Diameter, c + (c - pt), Vec2::ZERO, Vec2::ZERO, pt, Vec2::ZERO, "")
|
||||
dim(s, DimKind::Diameter, c + (c - pt), Vec2::ZERO, Vec2::ZERO, pt, "")
|
||||
} else {
|
||||
dim(s, DimKind::Radius, c, Vec2::ZERO, Vec2::ZERO, pt, Vec2::ZERO, "")
|
||||
dim(s, DimKind::Radius, c, Vec2::ZERO, Vec2::ZERO, pt, "")
|
||||
};
|
||||
let k = match at {
|
||||
Some(at) => text_at(k, at),
|
||||
@@ -308,7 +311,7 @@ fn run_angular(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
_ => return Err(bad("dimangular", "object is not an arc")),
|
||||
};
|
||||
let g = cadcraft_geom::Arc::new(a.center.xy(), a.radius, a.start, a.end);
|
||||
let k = dim(s, DimKind::Angular3P, at, g.start_point(), g.end_point(), g.center, Vec2::ZERO, "");
|
||||
let k = dim(s, DimKind::Angular3P, at, g.start_point(), g.end_point(), g.center, "");
|
||||
return Ok(json!({ "handle": add_dim(s, k)?.hex() }));
|
||||
}
|
||||
let v = point_req("dimangular", p, "vertex")?;
|
||||
@@ -318,7 +321,7 @@ fn run_angular(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
if v.near(a, 1e-12) || v.near(b, 1e-12) {
|
||||
return Err(bad("dimangular", "`p1` and `p2` must differ from `vertex`"));
|
||||
}
|
||||
let k = dim(s, DimKind::Angular3P, at, a, b, v, Vec2::ZERO, "");
|
||||
let k = dim(s, DimKind::Angular3P, at, a, b, v, "");
|
||||
Ok(json!({ "handle": add_dim(s, k)?.hex() }))
|
||||
}
|
||||
|
||||
@@ -330,7 +333,7 @@ fn run_arclen(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
_ => return Err(bad("dimarc", "object is not an arc")),
|
||||
};
|
||||
let ga = cadcraft_geom::Arc::new(a.center.xy(), a.radius, a.start, a.end);
|
||||
let k = dim(s, DimKind::ArcLength, at, ga.start_point(), ga.end_point(), ga.center, Vec2::ZERO, "");
|
||||
let k = dim(s, DimKind::ArcLength, at, ga.start_point(), ga.end_point(), ga.center, "");
|
||||
Ok(json!({ "handle": add_dim(s, k)?.hex() }))
|
||||
}
|
||||
|
||||
@@ -338,7 +341,7 @@ fn run_ordinate(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let f = point_req("dimordinate", p, "feature")?;
|
||||
let l = point_req("dimordinate", p, "leader")?;
|
||||
let xtype = p.get("xtype").and_then(Value::as_bool).unwrap_or((l - f).y.abs() > (l - f).x.abs());
|
||||
let k = dim(s, DimKind::Ordinate { x_type: xtype }, Vec2::ZERO, f, l, Vec2::ZERO, Vec2::ZERO, "");
|
||||
let k = dim(s, DimKind::Ordinate { x_type: xtype }, Vec2::ZERO, f, l, Vec2::ZERO, "");
|
||||
Ok(json!({ "handle": add_dim(s, k)?.hex() }))
|
||||
}
|
||||
|
||||
@@ -1060,7 +1063,7 @@ impl Interactive for LinearM {
|
||||
}
|
||||
(_, Input::Point(at)) => {
|
||||
let (Some(&a), Some(&b)) = (self.pts.first(), self.pts.get(1)) else { return Ok(Step::Continue) };
|
||||
let k = self.text.apply(dim(s, linear_kind(a, b, at, self.rotation, self.aligned), at, a, b, Vec2::ZERO, Vec2::ZERO, ""));
|
||||
let k = self.text.apply(dim(s, linear_kind(a, b, at, self.rotation, self.aligned), at, a, b, Vec2::ZERO, ""));
|
||||
add_dim(s, k)?;
|
||||
if let Some(EntityKind::Dimension(d)) = s.last_dim.and_then(|h| s.doc().ok()?.entity(h).map(|e| e.kind.clone())) {
|
||||
let st = s.doc()?.dim_style(&d.style).cloned().unwrap_or_default();
|
||||
@@ -1087,7 +1090,7 @@ impl Interactive for LinearM {
|
||||
fn preview(&self, s: &Session, c: Vec2) -> Vec<EntityKind> {
|
||||
match self.pts.as_slice() {
|
||||
[a] => vec![super::helpers::line(*a, c)],
|
||||
[a, b] => vec![self.text.apply(dim(s, linear_kind(*a, *b, c, self.rotation, self.aligned), c, *a, *b, Vec2::ZERO, Vec2::ZERO, ""))],
|
||||
[a, b] => vec![self.text.apply(dim(s, linear_kind(*a, *b, c, self.rotation, self.aligned), c, *a, *b, Vec2::ZERO, ""))],
|
||||
_ => Vec::new(),
|
||||
}
|
||||
}
|
||||
@@ -1106,9 +1109,9 @@ impl RadialM {
|
||||
fn kind(&self, s: &Session, c: Vec2, r: f64, at: Vec2) -> EntityKind {
|
||||
let pt = c + (at - c).normalized() * r;
|
||||
let k = self.text.apply(if self.diameter {
|
||||
dim(s, DimKind::Diameter, c + (c - pt), Vec2::ZERO, Vec2::ZERO, pt, Vec2::ZERO, "")
|
||||
dim(s, DimKind::Diameter, c + (c - pt), Vec2::ZERO, Vec2::ZERO, pt, "")
|
||||
} else {
|
||||
dim(s, DimKind::Radius, c, Vec2::ZERO, Vec2::ZERO, pt, Vec2::ZERO, "")
|
||||
dim(s, DimKind::Radius, c, Vec2::ZERO, Vec2::ZERO, pt, "")
|
||||
});
|
||||
text_at(k, at)
|
||||
}
|
||||
@@ -1241,7 +1244,7 @@ impl Interactive for AngularM {
|
||||
([h1, h2], None) => angular_from_lines(s, *h1, *h2, at),
|
||||
_ => None,
|
||||
};
|
||||
let k = k.unwrap_or_else(|| dim(s, DimKind::Angular3P, at, a, b, v, Vec2::ZERO, ""));
|
||||
let k = k.unwrap_or_else(|| dim(s, DimKind::Angular3P, at, a, b, v, ""));
|
||||
add_dim(s, self.text.apply(k))?;
|
||||
Ok(Step::Done)
|
||||
}
|
||||
@@ -1307,9 +1310,7 @@ impl Interactive for AngularM {
|
||||
}
|
||||
}
|
||||
fn preview(&self, s: &Session, c: Vec2) -> Vec<EntityKind> {
|
||||
self.geometry()
|
||||
.map(|(v, a, b)| vec![self.text.apply(dim(s, DimKind::Angular3P, self.located(v, c), a, b, v, Vec2::ZERO, ""))])
|
||||
.unwrap_or_default()
|
||||
self.geometry().map(|(v, a, b)| vec![self.text.apply(dim(s, DimKind::Angular3P, self.located(v, c), a, b, v, ""))]).unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1385,7 +1386,7 @@ impl Interactive for ArcLenM {
|
||||
Ok(Step::Continue)
|
||||
}
|
||||
(Some(g), Input::Point(at)) => {
|
||||
add_dim(s, self.text.apply(dim(s, DimKind::ArcLength, at, g.start_point(), g.end_point(), g.center, Vec2::ZERO, "")))?;
|
||||
add_dim(s, self.text.apply(dim(s, DimKind::ArcLength, at, g.start_point(), g.end_point(), g.center, "")))?;
|
||||
Ok(Step::Done)
|
||||
}
|
||||
(Some(_), Input::Keyword(k)) => {
|
||||
@@ -1404,9 +1405,7 @@ impl Interactive for ArcLenM {
|
||||
if self.partial.is_some() {
|
||||
return Vec::new();
|
||||
}
|
||||
self.arc
|
||||
.map(|g| vec![self.text.apply(dim(s, DimKind::ArcLength, c, g.start_point(), g.end_point(), g.center, Vec2::ZERO, ""))])
|
||||
.unwrap_or_default()
|
||||
self.arc.map(|g| vec![self.text.apply(dim(s, DimKind::ArcLength, c, g.start_point(), g.end_point(), g.center, ""))]).unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1421,7 +1420,7 @@ struct OrdinateM {
|
||||
impl OrdinateM {
|
||||
fn kind(&self, s: &Session, f: Vec2, l: Vec2) -> EntityKind {
|
||||
let x = self.xtype.unwrap_or((l - f).y.abs() > (l - f).x.abs());
|
||||
self.text.apply(dim(s, DimKind::Ordinate { x_type: x }, Vec2::ZERO, f, l, Vec2::ZERO, Vec2::ZERO, ""))
|
||||
self.text.apply(dim(s, DimKind::Ordinate { x_type: x }, Vec2::ZERO, f, l, Vec2::ZERO, ""))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -283,7 +283,7 @@ fn jogged_kind(s: &Session, c: Vec2, r: f64, center: Vec2, at: Vec2, jog: Option
|
||||
}
|
||||
let tip = c + dir * r;
|
||||
let jog = jog.unwrap_or_else(|| center.mid(tip));
|
||||
let mut k = dim(s, DimKind::Radius, c, Vec2::ZERO, Vec2::ZERO, tip, Vec2::ZERO, text);
|
||||
let mut k = dim(s, DimKind::Radius, c, Vec2::ZERO, Vec2::ZERO, tip, text);
|
||||
if let EntityKind::Dimension(dm) = &mut k {
|
||||
dm.marks.jogged = Some(JoggedRadius { center: v3(center), jog: v3(jog) });
|
||||
if at.dist(c) > r + 1e-9 {
|
||||
|
||||
@@ -96,9 +96,9 @@ fn plan(
|
||||
let dir = if dir == Vec2::ZERO || !dir.is_finite() { Vec2::from_angle(std::f64::consts::FRAC_PI_4) } else { dir };
|
||||
let p = *c + dir * *r;
|
||||
out.push(if mode == Mode::Diameter {
|
||||
dim(s, DimKind::Diameter, *c - dir * *r, Vec2::ZERO, Vec2::ZERO, p, Vec2::ZERO, "")
|
||||
dim(s, DimKind::Diameter, *c - dir * *r, Vec2::ZERO, Vec2::ZERO, p, "")
|
||||
} else {
|
||||
dim(s, DimKind::Radius, *c, Vec2::ZERO, Vec2::ZERO, p, Vec2::ZERO, "")
|
||||
dim(s, DimKind::Radius, *c, Vec2::ZERO, Vec2::ZERO, p, "")
|
||||
});
|
||||
}
|
||||
if out.is_empty() {
|
||||
@@ -131,7 +131,7 @@ fn plan(
|
||||
.iter()
|
||||
.map(|p| {
|
||||
let end = if vertical { Vec2::new(at.x, p.y) } else { Vec2::new(p.x, at.y) };
|
||||
dim(s, DimKind::Ordinate { x_type: !vertical }, origin, *p, end, Vec2::ZERO, Vec2::ZERO, "")
|
||||
dim(s, DimKind::Ordinate { x_type: !vertical }, origin, *p, end, Vec2::ZERO, "")
|
||||
})
|
||||
.collect());
|
||||
}
|
||||
@@ -147,8 +147,7 @@ fn plan(
|
||||
let mid = bounds.center();
|
||||
let out_dir =
|
||||
if vertical { Vec2::new(if at.x >= mid.x { 1.0 } else { -1.0 }, 0.0) } else { Vec2::new(0.0, if at.y >= mid.y { 1.0 } else { -1.0 }) };
|
||||
let lin =
|
||||
|a: Vec2, b: Vec2, k: usize| dim(s, DimKind::Linear { rotation: rot }, at + out_dir * (step * k as f64), a, b, Vec2::ZERO, Vec2::ZERO, "");
|
||||
let lin = |a: Vec2, b: Vec2, k: usize| dim(s, DimKind::Linear { rotation: rot }, at + out_dir * (step * k as f64), a, b, Vec2::ZERO, "");
|
||||
Ok(match mode {
|
||||
Mode::Baseline => {
|
||||
// From the datum (the point nearest it, by default the first) to every other point.
|
||||
|
||||
@@ -16,7 +16,8 @@ use serde_json::{Value, json};
|
||||
|
||||
use super::super::helpers::v3;
|
||||
use super::super::machines::{SelOutcome, SelectPhase, number};
|
||||
use super::super::*;
|
||||
use super::super::{CommandSpec, bad, bool_or, point_param, targets};
|
||||
|
||||
use super::{KEYWORDS, angle, check_size, count, fmt, nesting, other, yes, yes_no};
|
||||
use crate::{Accept, Input, Interactive, Prompt, Result, Session, Step};
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@ use std::sync::Arc;
|
||||
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::*;
|
||||
use super::{CommandSpec, bad, bool_or, file, str_param};
|
||||
|
||||
use super::always;
|
||||
use crate::{Accept, Input, Interactive, Prompt, Result, Session, Step};
|
||||
|
||||
pub fn specs() -> Vec<CommandSpec> {
|
||||
|
||||
@@ -12,7 +12,9 @@ use serde_json::{Value, json};
|
||||
|
||||
use super::helpers::v3;
|
||||
use super::machines::{SelOutcome, SelectPhase, number};
|
||||
use super::*;
|
||||
use super::{CommandSpec, bad, bool_or, f64_or, find_command, ok, point_param, point_req, point_value, str_param, targets};
|
||||
|
||||
use super::has_doc;
|
||||
use crate::{Accept, EngineError, Input, Interactive, Prompt, Result, Session, Step};
|
||||
|
||||
mod attedit;
|
||||
|
||||
@@ -14,7 +14,8 @@ use cadcraft_geom::{Line, Vec2};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::machines::{SelOutcome, SelectPhase};
|
||||
use super::*;
|
||||
use super::{CommandSpec, bad, bool_or, f64_or, point_value, str_param, targets};
|
||||
|
||||
use crate::{Accept, EngineError, Input, Interactive, Prompt, Result, Session, Step};
|
||||
|
||||
macro_rules! gc {
|
||||
|
||||
@@ -5,10 +5,15 @@ use cadcraft_doc::{EntityKind, HAlign, MText, Point, RayLine, Text, VAlign};
|
||||
use cadcraft_geom::{Arc, Circle, Ellipse, PolyVertex, Polyline, Spline, Vec2, arc_to_bulge, bulge_to_arc};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::helpers::*;
|
||||
use super::helpers::{arc, circle, line, lwpoly, polygon_from_edge, polygon_typed_radius_point, polygon_vertices, v3};
|
||||
|
||||
use super::machines::number;
|
||||
use super::pline_opts::{Outcome, PlineAsk};
|
||||
use super::*;
|
||||
use super::{
|
||||
CommandSpec, bad, bool_or, distinct_points, f64_or, f64_req, find_command, point_param, point_req, point_value, points_param, size_param,
|
||||
str_param,
|
||||
};
|
||||
|
||||
use crate::{Accept, Input, Interactive, Prompt, Result, Session, Step, snap};
|
||||
|
||||
/// Every draw command's spec: JSON parameters, menu path, aliases and the interactive prompt
|
||||
|
||||
@@ -7,9 +7,11 @@ use cadcraft_geom::{Arc, Circle, Ellipse, Line, PolyVertex, Polyline, Spline, TA
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::curves::{self, Chain, MAX_GEN, TanObj};
|
||||
use super::helpers::*;
|
||||
use super::helpers::{arc, circle, line, lwpoly, rect_vertices, rect_with_corners, v3};
|
||||
|
||||
use super::machines::number;
|
||||
use super::*;
|
||||
use super::{CommandSpec, bad, bool_or, f64_or, f64_req, point_param, point_req, point_value, points_param, size_param, str_param, targets};
|
||||
|
||||
use crate::{Accept, EngineError, Input, Interactive, Prompt, Result, Session, Step};
|
||||
|
||||
pub(crate) mod breakline;
|
||||
@@ -1572,7 +1574,7 @@ impl Interactive for XlineM2 {
|
||||
// RECTANG with Area / Dimensions / Rotation / Width / Elevation / Thickness
|
||||
// =====================================================================================
|
||||
|
||||
fn rect_kind(first: Vec2, w: f64, h: f64, rot: f64, fillet: f64, chamfer: (f64, f64), width: f64, elevation: f64) -> EntityKind {
|
||||
fn rect_kind(first: Vec2, (w, h): (f64, f64), rot: f64, fillet: f64, chamfer: (f64, f64), width: f64, elevation: f64) -> EntityKind {
|
||||
let local = rect_with_corners(Vec2::ZERO, Vec2::new(w, h), fillet, chamfer);
|
||||
let vs = local.into_iter().map(|v| PolyVertex { p: first + v.p.rotate(rot), ..v }).collect();
|
||||
let mut k = lwpoly(vs, true);
|
||||
@@ -1631,7 +1633,7 @@ pub(crate) fn run_rectang2(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
return Err(bad("rectang", "rectangle has no area"));
|
||||
}
|
||||
let first = if centered { a - Vec2::new(w / 2.0, h / 2.0).rotate(rot) } else { a };
|
||||
let k = rect_kind(first, w, h, rot, fillet, ch, width, f64_or(p, "elevation", 0.0));
|
||||
let k = rect_kind(first, (w, h), rot, fillet, ch, width, f64_or(p, "elevation", 0.0));
|
||||
let hd = s.add_entity(k)?;
|
||||
// A rectangle has its own thickness option and does not take THICKNESS.
|
||||
let th = f64_or(p, "thickness", 0.0);
|
||||
@@ -1683,7 +1685,8 @@ impl RectM2 {
|
||||
return Err(other("The rectangle has no area."));
|
||||
}
|
||||
let first = self.origin(w, h).unwrap_or(a);
|
||||
let hd = s.add_entity(rect_kind(first, w, h, self.rotation, self.fillet, self.chamfer, self.width, self.elevation))?;
|
||||
let hd = s.add_entity(rect_kind(first, (w, h), self.rotation, self.fillet, self.chamfer, self.width, self.elevation))?;
|
||||
// A rectangle has its own thickness option and does not take THICKNESS.
|
||||
let t = self.thickness;
|
||||
s.doc_mut()?.modify_entity(hd, |e| e.common.thickness = t)?;
|
||||
Ok(Step::Done)
|
||||
@@ -1861,7 +1864,7 @@ impl Interactive for RectM2 {
|
||||
}
|
||||
match self.other_corner(c).and_then(|(w, h)| self.origin(w, h).map(|a| (a, w, h))) {
|
||||
Some((a, w, h)) if w.abs() > 1e-12 && h.abs() > 1e-12 => {
|
||||
vec![rect_kind(a, w, h, self.rotation, self.fillet, self.chamfer, self.width, self.elevation)]
|
||||
vec![rect_kind(a, (w, h), self.rotation, self.fillet, self.chamfer, self.width, self.elevation)]
|
||||
}
|
||||
_ => Vec::new(),
|
||||
}
|
||||
|
||||
@@ -9,10 +9,11 @@ use cadcraft_doc::{Drawing, EntityKind};
|
||||
use cadcraft_geom::{PolyVertex, Vec2};
|
||||
use serde_json::Value;
|
||||
|
||||
use super::super::machines::number;
|
||||
use super::added;
|
||||
use super::curves::MAX_GEN;
|
||||
use super::machines::number;
|
||||
use super::*;
|
||||
use super::{CommandSpec, line, lwpoly, point_param, point_req, size_param, str_param};
|
||||
|
||||
use crate::cmd::modify2::as_lwpoly;
|
||||
use crate::{Accept, EngineError, Input, Interactive, Prompt, Result, Session, Step};
|
||||
|
||||
|
||||
@@ -9,9 +9,11 @@ use cadcraft_doc::{
|
||||
use cadcraft_geom::{Line, Vec2, line_line_infinite};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::super::machines::number;
|
||||
use super::super::{distinct_points, ok};
|
||||
use super::curves::{self, MAX_GEN};
|
||||
use super::machines::number;
|
||||
use super::*;
|
||||
use super::{CommandSpec, bad, bool_or, f64_or, point_req, points_param, str_param};
|
||||
|
||||
use crate::{Accept, EngineError, Input, Interactive, Prompt, Result, Session, Step};
|
||||
|
||||
pub fn specs() -> Vec<CommandSpec> {
|
||||
|
||||
@@ -8,7 +8,8 @@ use cadcraft_doc::{EntityKind, Handle};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::machines::{SelOutcome, SelectPhase, SelectRun};
|
||||
use super::*;
|
||||
use super::{CommandSpec, EngineError, bad, ok, targets};
|
||||
|
||||
use crate::{Accept, Input, Interactive, Prompt, Result, Session, Step};
|
||||
|
||||
pub fn specs() -> Vec<CommandSpec> {
|
||||
|
||||
@@ -5,7 +5,8 @@ use cadcraft_geom::{Bounds2, Mat3, Vec2};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::machines::{SelOutcome, SelectPhase, SelectRun};
|
||||
use super::*;
|
||||
use super::{CommandSpec, EngineError, bad, bool_or, clipboard, f64_or, has_selection, point_param, point_req, points_param, str_param, targets};
|
||||
|
||||
use crate::undoctl::Control;
|
||||
use crate::{Accept, Input, Interactive, Prompt, Result, Session, Step};
|
||||
|
||||
|
||||
@@ -18,7 +18,8 @@ use cadcraft_render::raster::{RasterOptions, View};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::file::{base64_decode, base64_encode, io};
|
||||
use super::*;
|
||||
use super::{CommandSpec, bad, point_value, str_param};
|
||||
|
||||
use crate::{EngineError, Result, Session};
|
||||
|
||||
/// Formats EXPORT writes (the io layer picks the writer from the extension).
|
||||
@@ -557,7 +558,10 @@ mod tests {
|
||||
use cadcraft_geom::Vec3;
|
||||
|
||||
use super::super::file::{IoHooks, set_io};
|
||||
|
||||
use super::super::resolve_alias;
|
||||
use super::*;
|
||||
use serde_json::json;
|
||||
|
||||
static DELIVERED: std::sync::Mutex<Vec<(String, String, usize)>> = std::sync::Mutex::new(Vec::new());
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@ use cadcraft_doc::Drawing;
|
||||
pub use cadcraft_dxf::Version;
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::*;
|
||||
use super::{CommandSpec, EngineError, Interactive, always, bad, bool_or, find_command, ok, str_param};
|
||||
|
||||
use crate::{Accept, Input, Prompt, Result, Session, Step};
|
||||
|
||||
/// The rules the Command Aliases dialog checks before it sends an alias to ALIASEDIT.
|
||||
@@ -731,6 +732,7 @@ mod tests {
|
||||
#[cfg(test)]
|
||||
mod pr193_tests {
|
||||
use super::*;
|
||||
use crate::Session;
|
||||
|
||||
#[test]
|
||||
fn failed_store_keeps_unsaved_changes_and_delivered_save_clears_them() {
|
||||
|
||||
@@ -11,7 +11,8 @@ use cadcraft_geom::{Line, Vec2, line_line, point_in_polygon};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::super::machines::{SelOutcome, SelectPhase, SelectRun};
|
||||
use super::super::*;
|
||||
use super::super::{CommandSpec, bad, targets};
|
||||
|
||||
use super::SelfCheck;
|
||||
use crate::{EngineError, Input, Interactive, Prompt, Result, Session, Step};
|
||||
|
||||
|
||||
@@ -6,7 +6,9 @@ use cadcraft_doc::{Entity, EntityKind};
|
||||
use cadcraft_geom::{Bounds2, Polyline, Vec2, intersect_segments};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::super::*;
|
||||
use super::super::bad;
|
||||
|
||||
use super::super::point_value;
|
||||
use super::{SelfCheck, area_of, object_area};
|
||||
use crate::{Result, Session};
|
||||
|
||||
|
||||
@@ -8,8 +8,9 @@ use std::collections::{HashMap, HashSet};
|
||||
use cadcraft_doc::{Drawing, Entity, EntityKind};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::super::bad;
|
||||
use super::super::blocks::purge;
|
||||
use super::super::*;
|
||||
|
||||
use crate::{Result, Session};
|
||||
|
||||
const CMD: &str = "usage";
|
||||
@@ -280,11 +281,9 @@ impl Unused {
|
||||
fn item_json(
|
||||
c: Category,
|
||||
name: &str,
|
||||
entities: usize,
|
||||
block_entities: usize,
|
||||
(entities, block_entities): (usize, usize),
|
||||
references: usize,
|
||||
used: bool,
|
||||
empty: bool,
|
||||
(used, empty): (bool, bool),
|
||||
current: Option<bool>,
|
||||
unused: &Unused,
|
||||
) -> Value {
|
||||
@@ -314,13 +313,13 @@ fn items(scan: &Scan, unused: &Unused, d: &Drawing) -> Vec<Value> {
|
||||
let (e, b) = scan.layers.get(&l.name.to_ascii_lowercase()).copied().unwrap_or_default();
|
||||
let uses = e.saturating_add(b);
|
||||
let cur = l.name.eq_ignore_ascii_case(¤t_layer);
|
||||
out.push(item_json(Category::Layer, &l.name, e, b, 0, uses > 0, uses == 0, Some(cur), unused));
|
||||
out.push(item_json(Category::Layer, &l.name, (e, b), 0, (uses > 0, uses == 0), Some(cur), unused));
|
||||
}
|
||||
for b in d.blocks.values() {
|
||||
let (e, n) = scan.blocks.get(&b.name.to_ascii_lowercase()).copied().unwrap_or_default();
|
||||
// A definition is used when a reference to it is reachable, as PURGE counts it.
|
||||
let used = scan.used_blocks.contains(&b.name.to_ascii_uppercase());
|
||||
out.push(item_json(Category::Block, &b.name, e, n, 0, used, e.saturating_add(n) == 0, None, unused));
|
||||
out.push(item_json(Category::Block, &b.name, (e, n), 0, (used, e.saturating_add(n) == 0), None, unused));
|
||||
}
|
||||
let current_style = d.header.str("TEXTSTYLE", "Standard");
|
||||
for t in &d.text_styles {
|
||||
@@ -328,7 +327,7 @@ fn items(scan: &Scan, unused: &Unused, d: &Drawing) -> Vec<Value> {
|
||||
let r = scan.style_refs.get(&t.name.to_ascii_lowercase()).copied().unwrap_or(0);
|
||||
let uses = e.saturating_add(b).saturating_add(r);
|
||||
let cur = t.name.eq_ignore_ascii_case(¤t_style);
|
||||
out.push(item_json(Category::TextStyle, &t.name, e, b, r, uses > 0, uses == 0, Some(cur), unused));
|
||||
out.push(item_json(Category::TextStyle, &t.name, (e, b), r, (uses > 0, uses == 0), Some(cur), unused));
|
||||
}
|
||||
let current_linetype = d.header.str("CELTYPE", "ByLayer");
|
||||
for t in &d.linetypes {
|
||||
@@ -336,7 +335,7 @@ fn items(scan: &Scan, unused: &Unused, d: &Drawing) -> Vec<Value> {
|
||||
let r = scan.linetype_refs.get(&t.name.to_ascii_lowercase()).copied().unwrap_or(0);
|
||||
let uses = e.saturating_add(b).saturating_add(r);
|
||||
let cur = t.name.eq_ignore_ascii_case(¤t_linetype);
|
||||
out.push(item_json(Category::Linetype, &t.name, e, b, r, uses > 0, uses == 0, Some(cur), unused));
|
||||
out.push(item_json(Category::Linetype, &t.name, (e, b), r, (uses > 0, uses == 0), Some(cur), unused));
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@ use cadcraft_doc::{Layer, Lineweight};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::machines::SelectRun;
|
||||
use super::*;
|
||||
use super::{CommandSpec, bad, bool_or, ok, str_param, targets};
|
||||
|
||||
use crate::{Result, Session};
|
||||
|
||||
pub fn specs() -> Vec<CommandSpec> {
|
||||
|
||||
@@ -10,6 +10,7 @@ use serde_json::{Value, json};
|
||||
|
||||
use super::file::{base64_encode, io};
|
||||
use super::*;
|
||||
|
||||
use crate::{Accept, Input, Interactive, Prompt, Result, Session, Step};
|
||||
use viewports::MviewM;
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
use cadcraft_doc::{Drawing, PlotStyle, PlotStyleKind, PlotStyleTable};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::*;
|
||||
use super::super::targets;
|
||||
use super::{CommandSpec, Result, Session, bad, str_param};
|
||||
|
||||
pub fn specs() -> Vec<CommandSpec> {
|
||||
vec![
|
||||
|
||||
@@ -9,7 +9,8 @@ use serde_json::{Value, json};
|
||||
|
||||
use super::helpers::v3;
|
||||
use super::machines::{SelOutcome, SelectPhase};
|
||||
use super::*;
|
||||
use super::{CommandSpec, bad, point_req, points_param, str_param, targets};
|
||||
|
||||
use crate::{Accept, Input, Interactive, Prompt, Result, Session, Step};
|
||||
|
||||
/// Most arrowheads added by one call, and most multileaders aligned / collected by one call.
|
||||
|
||||
@@ -7,10 +7,12 @@ use cadcraft_geom::{
|
||||
};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::helpers::*;
|
||||
use super::helpers::{arc, circle, line, lwpoly, v3};
|
||||
|
||||
use super::machines::{SelOutcome, SelectPhase, number};
|
||||
use super::trimextend::{self, TrimM};
|
||||
use super::*;
|
||||
use super::{CommandSpec, bad, bool_or, f64_or, f64_req, point_param, point_req, points_param, str_param, targets};
|
||||
|
||||
use crate::select::{SelectKind, SelectMode};
|
||||
use crate::{Accept, EngineError, Input, Interactive, Prompt, Result, Session, Step};
|
||||
|
||||
|
||||
@@ -9,9 +9,11 @@ use cadcraft_geom::{
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::curves::{self, Chain, MAX_GEN, TanObj};
|
||||
use super::helpers::*;
|
||||
use super::helpers::{arc, line, lwpoly, v3};
|
||||
|
||||
use super::machines::{SelOutcome, SelectPhase, number};
|
||||
use super::*;
|
||||
use super::{CommandSpec, bad, bool_or, f64_or, f64_req, point_param, point_req, str_param, targets};
|
||||
|
||||
use crate::{Accept, EngineError, Input, Interactive, Prompt, Result, Session, Step};
|
||||
|
||||
mod curve_edits;
|
||||
|
||||
@@ -80,8 +80,7 @@ fn same_polyline(
|
||||
s: &mut Session,
|
||||
h: Handle,
|
||||
pl: &LwPolyline,
|
||||
p1: Vec2,
|
||||
p2: Vec2,
|
||||
(p1, p2): (Vec2, Vec2),
|
||||
r: f64,
|
||||
chamfer: Option<ChamferDistances>,
|
||||
trim: bool,
|
||||
@@ -223,7 +222,7 @@ pub(crate) fn fillet_pline(
|
||||
_ => None,
|
||||
};
|
||||
let made = match (&e1.kind, &e2.kind) {
|
||||
(EntityKind::LwPolyline(pl), _) if h1 == h2 => same_polyline(s, h1, pl, p1, p2, r, chamfer, trim)?,
|
||||
(EntityKind::LwPolyline(pl), _) if h1 == h2 => same_polyline(s, h1, pl, (p1, p2), r, chamfer, trim)?,
|
||||
(EntityKind::LwPolyline(pl), k) if as_line(k).is_some() => {
|
||||
let ln = as_line(k).ok_or_else(|| other("Select a line."))?;
|
||||
polyline_and_line(s, (h1, pl, p1), (h2, ln, p2), true, r, chamfer, trim)?
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
//! PEDIT Edit vertex: Break and Straighten between two marked vertices, Tangent directions
|
||||
//! that Fit honours, and Regen.
|
||||
|
||||
use super::*;
|
||||
use super::super::point_value;
|
||||
use super::{
|
||||
EntityKind, Handle, Input, LwPolyline, PPhase, PeditM, PolyVertex, Result, Session, Value, Vec2, bad, curves, json, other, push_entity, set_kind,
|
||||
};
|
||||
|
||||
fn ordered(pl: &LwPolyline, i: usize, j: usize) -> Result<(usize, usize)> {
|
||||
let n = pl.vertices.len();
|
||||
|
||||
@@ -6,7 +6,11 @@
|
||||
//! parametrisation, end tangents and fit tolerance. Control-point edits change the curve
|
||||
//! directly and drop the fit data, as the curve no longer follows it.
|
||||
|
||||
use super::*;
|
||||
use super::super::{point_value, points_param};
|
||||
use super::{
|
||||
Accept, Entity, EntityKind, Handle, Input, Interactive, LwPolyline, MAX_GEN, PolyVertex, Prompt, Result, SelOutcome, SelectPhase, Session, Space,
|
||||
Spline, Step, Value, Vec2, bad, bool_or, curves, f64_req, json, line, number, other, point_req, set_kind, str_param, targets,
|
||||
};
|
||||
|
||||
/// The spline after a JSON SPLINEDIT option (`option` plus that option's parameters).
|
||||
pub(super) fn run_splinedit(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
|
||||
@@ -9,7 +9,8 @@ use cadcraft_doc::{Drawing, Entity, EntityKind, Handle};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::machines::{SelOutcome, SelectPhase, SelectRun};
|
||||
use super::*;
|
||||
use super::{CommandSpec, bad, targets};
|
||||
|
||||
use crate::{Accept, Input, Interactive, Prompt, Result, Session, Step};
|
||||
|
||||
/// Most objects one call looks at (a hostile drawing can be huge).
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::*;
|
||||
use super::{CommandSpec, always, bad, point_param, str_param};
|
||||
|
||||
use crate::{Accept, Input, Interactive, Prompt, Result, Session, Step};
|
||||
|
||||
pub(super) mod iso;
|
||||
|
||||
@@ -12,7 +12,8 @@ use cadcraft_geom::Vec2;
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::helpers::v3;
|
||||
use super::*;
|
||||
use super::{CommandSpec, bad, point_req, size_param, str_param};
|
||||
|
||||
use crate::{Accept, Input, Interactive, Prompt, Result, Session, Step};
|
||||
|
||||
/// Caps for hostile parameters.
|
||||
|
||||
@@ -5,7 +5,8 @@ use cadcraft_geom::{PolyVertex, Vec2};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::helpers::{line, lwpoly, v3};
|
||||
use super::*;
|
||||
use super::{CommandSpec, bad, bool_or, f64_or, point_req, str_param};
|
||||
|
||||
use crate::{Accept, Input, Interactive, Prompt, Result, Session, Step};
|
||||
|
||||
pub fn specs() -> Vec<CommandSpec> {
|
||||
|
||||
@@ -4,7 +4,8 @@ use cadcraft_doc::{EntityKind, Handle};
|
||||
use cadcraft_geom::{Segment, Vec2};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::*;
|
||||
use super::{CommandSpec, always, bad, bool_or, point_param, points_param, str_param, targets};
|
||||
|
||||
use crate::{Accept, Input, Interactive, Prompt, Result, Session, Step};
|
||||
|
||||
pub fn specs() -> Vec<CommandSpec> {
|
||||
|
||||
@@ -6,7 +6,8 @@ use cadcraft_geom::{Bounds2, Vec2};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::machines::{SelectRun, number};
|
||||
use super::*;
|
||||
use super::{CommandSpec, bad, bool_or, f64_or, f64_req, ok, point_param, point_req, str_param, targets};
|
||||
|
||||
use crate::{Accept, Input, Interactive, Prompt, Result, Session, Step, View};
|
||||
|
||||
mod named_views;
|
||||
|
||||
+11
-11
@@ -2373,7 +2373,7 @@ fn tags_for(d: &Drawing, version: Version, target: Version) -> Vec<Tag> {
|
||||
// ---------------- BLOCKS ----------------
|
||||
w.s(0, "SECTION");
|
||||
w.s(2, "BLOCKS");
|
||||
let block = |w: &mut W, name: &str, desc: &str, brh: &str, base: Vec3, flags: i64, ents: &mut dyn Iterator<Item = &Entity>, paper: bool| {
|
||||
let block = |w: &mut W, (name, desc): (&str, &str), brh: &str, base: Vec3, flags: i64, ents: &mut dyn Iterator<Item = &Entity>, paper: bool| {
|
||||
let bh = w.h();
|
||||
w.s(0, "BLOCK");
|
||||
w.s(5, bh);
|
||||
@@ -2406,16 +2406,16 @@ fn tags_for(d: &Drawing, version: Version, target: Version) -> Vec<Tag> {
|
||||
w.s(8, "0");
|
||||
w.s(100, "AcDbBlockEnd");
|
||||
};
|
||||
block(&mut w, "*Model_Space", "", &ms_br, Vec3::ZERO, 0, &mut std::iter::empty(), false);
|
||||
block(&mut w, ("*Model_Space", ""), &ms_br, Vec3::ZERO, 0, &mut std::iter::empty(), false);
|
||||
for (i, (n, h, l)) in ps_brs.iter().enumerate() {
|
||||
if i == 0 {
|
||||
block(&mut w, n, "", h, Vec3::ZERO, 0, &mut std::iter::empty(), true);
|
||||
block(&mut w, (n, ""), h, Vec3::ZERO, 0, &mut std::iter::empty(), true);
|
||||
} else {
|
||||
block(&mut w, n, "", h, Vec3::ZERO, 0, &mut sheet_first(l).into_iter(), true);
|
||||
block(&mut w, (n, ""), h, Vec3::ZERO, 0, &mut sheet_first(l).into_iter(), true);
|
||||
}
|
||||
}
|
||||
for (n, h, b) in &user_blocks {
|
||||
block(&mut w, n, &b.description, h, b.base, if b.anonymous { 1 } else { 0 }, &mut b.entities.iter().map(|e| e.as_ref()), false);
|
||||
block(&mut w, (n, &b.description), h, b.base, if b.anonymous { 1 } else { 0 }, &mut b.entities.iter().map(|e| e.as_ref()), false);
|
||||
}
|
||||
// Generated geometry entities (dimension, arrowhead and table blocks) need handles.
|
||||
for (_, _, ents) in dim_defs.iter_mut().chain(arrow_defs.iter_mut()).chain(table_defs.iter_mut()) {
|
||||
@@ -2425,13 +2425,13 @@ fn tags_for(d: &Drawing, version: Version, target: Version) -> Vec<Tag> {
|
||||
}
|
||||
}
|
||||
for (n, h, ents) in &dim_defs {
|
||||
block(&mut w, n, "", h, Vec3::ZERO, 1, &mut ents.iter(), false);
|
||||
block(&mut w, (n, ""), h, Vec3::ZERO, 1, &mut ents.iter(), false);
|
||||
}
|
||||
for (n, h, ents) in &arrow_defs {
|
||||
block(&mut w, n, "", h, Vec3::ZERO, 0, &mut ents.iter(), false);
|
||||
block(&mut w, (n, ""), h, Vec3::ZERO, 0, &mut ents.iter(), false);
|
||||
}
|
||||
for (n, h, ents) in &table_defs {
|
||||
block(&mut w, n, "", h, Vec3::ZERO, 1, &mut ents.iter(), false);
|
||||
block(&mut w, (n, ""), h, Vec3::ZERO, 1, &mut ents.iter(), false);
|
||||
}
|
||||
w.s(0, "ENDSEC");
|
||||
|
||||
@@ -2612,7 +2612,7 @@ fn tags_for(d: &Drawing, version: Version, target: Version) -> Vec<Tag> {
|
||||
w.s(3, &l.name);
|
||||
w.s(350, layout_handles.get(i).cloned().unwrap_or_default());
|
||||
}
|
||||
let layout_obj = |w: &mut W, h: &str, name: &str, tab: i64, brh: &str, flags: i64, page: &PageSetup, view: Option<(Vec2, f64)>| {
|
||||
let layout_obj = |w: &mut W, h: &str, (name, tab): (&str, i64), brh: &str, flags: i64, page: &PageSetup, view: Option<(Vec2, f64)>| {
|
||||
// Plot scale: a standard scale when fitting or 1:1, otherwise custom (142 paper units
|
||||
// per 143 drawing units).
|
||||
let scale = if page.scale.is_finite() && page.scale > 0.0 { page.scale } else { 1.0 };
|
||||
@@ -2697,10 +2697,10 @@ fn tags_for(d: &Drawing, version: Version, target: Version) -> Vec<Tag> {
|
||||
// plot type 5, "Layout information" (DXF Reference, PLOTSETTINGS group 74), which means
|
||||
// nothing for model space: another program's Plot dialog then shows no plot area or scale.
|
||||
let model_page = PageSetup { plot_area: "extents".into(), scale_to_fit: true, ..PageSetup::default() };
|
||||
layout_obj(&mut w, &model_layout, "Model", 0, &ms_br, 1, &model_page, None);
|
||||
layout_obj(&mut w, &model_layout, ("Model", 0), &ms_br, 1, &model_page, None);
|
||||
for (i, (_, brh, l)) in ps_brs.iter().enumerate() {
|
||||
let h = layout_handles.get(i).cloned().unwrap_or_default();
|
||||
layout_obj(&mut w, &h, &l.name, i64::from(l.tab_order.max(1)), brh, 1, &l.page, l.view);
|
||||
layout_obj(&mut w, &h, (&l.name, i64::from(l.tab_order.max(1))), brh, 1, &l.page, l.view);
|
||||
}
|
||||
// Raster image definitions.
|
||||
w.t.extend(crate::dxf_image::objects(&cx.images, &root_dict));
|
||||
|
||||
+14
-14
@@ -165,7 +165,7 @@ fn style(d: &mut Drawing, name: &str, font: &str) {
|
||||
d.text_styles.push(TextStyle { name: name.into(), font: font.into(), ..TextStyle::default() });
|
||||
}
|
||||
|
||||
fn text(d: &mut Drawing, space: &Space, style: &str, at: (f64, f64), value: &str, rotation: f64, width_factor: f64, oblique: f64) {
|
||||
fn text(d: &mut Drawing, space: &Space, style: &str, at: (f64, f64), value: &str, (rotation, width_factor, oblique): (f64, f64, f64)) {
|
||||
let t = Text {
|
||||
insert: Vec3::new(at.0, at.1, 0.0),
|
||||
align_pt: None,
|
||||
@@ -225,7 +225,7 @@ fn font_files(doc: &Doc) -> usize {
|
||||
#[test]
|
||||
fn truetype_text_is_embedded_as_text() {
|
||||
let mut d = drawing();
|
||||
text(&mut d, &Space::Model, "Real", (0.0, 0.0), "ABBA", 0.0, 1.0, 0.0);
|
||||
text(&mut d, &Space::Model, "Real", (0.0, 0.0), "ABBA", (0.0, 1.0, 0.0));
|
||||
let doc = pdf(&d, &Space::Model, json!({}));
|
||||
let page = &doc.pages[0];
|
||||
// A Type0 font over a CIDFontType2 subset with a ToUnicode map.
|
||||
@@ -260,7 +260,7 @@ fn truetype_text_is_embedded_as_text() {
|
||||
#[test]
|
||||
fn the_subset_is_a_valid_truetype_font() {
|
||||
let mut d = drawing();
|
||||
text(&mut d, &Space::Model, "Real", (0.0, 0.0), "A", 0.0, 1.0, 0.0);
|
||||
text(&mut d, &Space::Model, "Real", (0.0, 0.0), "A", (0.0, 1.0, 0.0));
|
||||
let doc = pdf(&d, &Space::Model, json!({}));
|
||||
let file = doc.pages[0].fonts[0].font_file.clone().expect("an embedded font file");
|
||||
let face = cadcraft_fonts::ttf::Face::new(std::sync::Arc::new(file.clone()), 0).expect("the subset parses");
|
||||
@@ -273,9 +273,9 @@ fn the_subset_is_a_valid_truetype_font() {
|
||||
fn rotation_width_factor_and_obliquing_go_into_the_text_matrix() {
|
||||
let mut d = drawing();
|
||||
let quarter = std::f64::consts::FRAC_PI_2;
|
||||
text(&mut d, &Space::Model, "Real", (0.0, 0.0), "A", quarter, 1.0, 0.0);
|
||||
text(&mut d, &Space::Model, "Real", (0.0, 50.0), "A", 0.0, 2.0, 0.0);
|
||||
text(&mut d, &Space::Model, "Real", (0.0, 100.0), "A", 0.0, 1.0, 15f64.to_radians());
|
||||
text(&mut d, &Space::Model, "Real", (0.0, 0.0), "A", (quarter, 1.0, 0.0));
|
||||
text(&mut d, &Space::Model, "Real", (0.0, 50.0), "A", (0.0, 2.0, 0.0));
|
||||
text(&mut d, &Space::Model, "Real", (0.0, 100.0), "A", (0.0, 1.0, 15f64.to_radians()));
|
||||
let m = matrices(&pdf(&d, &Space::Model, json!({})));
|
||||
assert_eq!(m.len(), 3, "{m:?}");
|
||||
// Rotated a quarter turn: the baseline points up, "up" points left.
|
||||
@@ -294,7 +294,7 @@ fn rotation_width_factor_and_obliquing_go_into_the_text_matrix() {
|
||||
#[test]
|
||||
fn a_font_the_writer_cannot_subset_plots_as_outlines() {
|
||||
let mut d = drawing();
|
||||
text(&mut d, &Space::Model, "Short", (0.0, 0.0), "AB", 0.0, 1.0, 0.0);
|
||||
text(&mut d, &Space::Model, "Short", (0.0, 0.0), "AB", (0.0, 1.0, 0.0));
|
||||
let p = pdf(&d, &Space::Model, json!({}));
|
||||
assert!(font_files(&p) == 0 && pdf_read::count(p.content(), "BT") == 0 && fills(&p) > 0, "outlines: {}", p.content());
|
||||
}
|
||||
@@ -302,16 +302,16 @@ fn a_font_the_writer_cannot_subset_plots_as_outlines() {
|
||||
#[test]
|
||||
fn fonts_that_forbid_embedding_and_the_geometry_option_draw_outlines() {
|
||||
let mut d = drawing();
|
||||
text(&mut d, &Space::Model, "Locked", (0.0, 0.0), "AB", 0.0, 1.0, 0.0);
|
||||
text(&mut d, &Space::Model, "Locked", (0.0, 0.0), "AB", (0.0, 1.0, 0.0));
|
||||
let p = pdf(&d, &Space::Model, json!({}));
|
||||
assert!(font_files(&p) == 0 && pdf_read::count(p.content(), "BT") == 0 && fills(&p) > 0, "restricted licence: outlines");
|
||||
let mut d = drawing();
|
||||
text(&mut d, &Space::Model, "Real", (0.0, 0.0), "AB", 0.0, 1.0, 0.0);
|
||||
text(&mut d, &Space::Model, "Real", (0.0, 0.0), "AB", (0.0, 1.0, 0.0));
|
||||
let p = pdf(&d, &Space::Model, json!({"text": "geometry"}));
|
||||
assert!(font_files(&p) == 0 && pdf_read::count(p.content(), "BT") == 0 && fills(&p) > 0, "text as geometry");
|
||||
// The stroke font is always geometry.
|
||||
let mut d = drawing();
|
||||
text(&mut d, &Space::Model, "Standard", (0.0, 0.0), "AB", 0.0, 1.0, 0.0);
|
||||
text(&mut d, &Space::Model, "Standard", (0.0, 0.0), "AB", (0.0, 1.0, 0.0));
|
||||
let p = pdf(&d, &Space::Model, json!({}));
|
||||
assert!(pdf_read::count(p.content(), "BT") == 0 && pdf_read::count(p.content(), "S") > 0);
|
||||
}
|
||||
@@ -321,8 +321,8 @@ fn text_seen_through_a_viewport_and_on_layers() {
|
||||
let mut d = drawing();
|
||||
let paper = Space::Paper("Layout1".into());
|
||||
// Model: one word well inside the viewport, one cut by its right edge.
|
||||
text(&mut d, &Space::Model, "Real", (0.0, 0.0), "AB", 0.0, 1.0, 0.0);
|
||||
text(&mut d, &Space::Model, "Real", (88.0, 0.0), "BA", 0.0, 1.0, 0.0);
|
||||
text(&mut d, &Space::Model, "Real", (0.0, 0.0), "AB", (0.0, 1.0, 0.0));
|
||||
text(&mut d, &Space::Model, "Real", (88.0, 0.0), "BA", (0.0, 1.0, 0.0));
|
||||
let vp = Viewport {
|
||||
center: Vec3::new(150.0, 100.0, 0.0),
|
||||
width: 100.0,
|
||||
@@ -337,7 +337,7 @@ fn text_seen_through_a_viewport_and_on_layers() {
|
||||
on: true,
|
||||
};
|
||||
d.add(&paper, Common::default(), EntityKind::Viewport(vp)).unwrap();
|
||||
text(&mut d, &paper, "Real", (20.0, 20.0), "B", 0.0, 1.0, 0.0);
|
||||
text(&mut d, &paper, "Real", (20.0, 20.0), "B", (0.0, 1.0, 0.0));
|
||||
let p = pdf(&d, &paper, json!({}));
|
||||
// "AB" inside, the paper-space "B", and the glyph of "BA" left of the edge: real text. The
|
||||
// glyph the edge cuts stays a (clipped) outline.
|
||||
@@ -353,7 +353,7 @@ fn text_seen_through_a_viewport_and_on_layers() {
|
||||
#[test]
|
||||
fn text_sits_in_its_layers_marked_content() {
|
||||
let mut d = drawing();
|
||||
text(&mut d, &Space::Model, "Real", (0.0, 0.0), "AB", 0.0, 1.0, 0.0);
|
||||
text(&mut d, &Space::Model, "Real", (0.0, 0.0), "AB", (0.0, 1.0, 0.0));
|
||||
let p = pdf(&d, &Space::Model, json!({}));
|
||||
let ops = pdf_read::ops(p.content());
|
||||
let first_bt = ops.iter().position(|o| o.op == "BT").unwrap();
|
||||
|
||||
@@ -528,14 +528,14 @@ impl Family<'_> {
|
||||
if solid_line {
|
||||
out.push(vec![self.to_world(Vec2::new(x0, y)), self.to_world(Vec2::new(x1, y))]);
|
||||
} else {
|
||||
self.dash(x0, x1, y, offset, pat_len, out, work);
|
||||
self.dash((x0, x1), y, offset, pat_len, out, work);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The dashes and dots of the span `x0..x1` of the line at `y`, phase anchored at x = `offset`.
|
||||
fn dash(&self, x0: f64, x1: f64, y: f64, offset: f64, pat_len: f64, out: &mut Vec<Vec<Vec2>>, work: &mut u64) {
|
||||
fn dash(&self, (x0, x1): (f64, f64), y: f64, offset: f64, pat_len: f64, out: &mut Vec<Vec<Vec2>>, work: &mut u64) {
|
||||
let start_rep = ((x0 - offset) / pat_len).floor();
|
||||
let mut x = offset + start_rep * pat_len;
|
||||
let mut guard = 0;
|
||||
|
||||
Reference in New Issue
Block a user