mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-13 21:17:48 +00:00
HP-GL export: an HP-GL plot past 16-bit coordinates gets a warning
Coordinates outside -32,768 to 32,767 plotter units (about 82 cm from the origin) are written as they are, with a warning that older devices may not read them. HP-GL/2 plots are not checked against this range.
This commit is contained in:
@@ -15,6 +15,8 @@
|
||||
//! Coordinates are plotter units (1016 to the inch, y up) from the region's bottom-left corner or
|
||||
//! its center, rounded to whole units. Art past ±8,388,607 units (2²³ − 1, the smallest range
|
||||
//! the HP-GL/2 reference asks a device to take for encoded polylines) from the origin is cut off.
|
||||
//! An HP-GL plot with a coordinate outside −32,768 to 32,767 (16-bit numbers, the range older
|
||||
//! devices read) gets a warning; HP-GL/2's encoded polylines take the wider range.
|
||||
//! The pens are drawn in turn (pen 1's paths, then pen 2's), each in paint order or, with
|
||||
//! `sort`, each next path the one that starts nearest where the pen stopped.
|
||||
//!
|
||||
@@ -39,6 +41,8 @@ use clip::Region;
|
||||
const PLU_PER_PT: f64 = 1016.0 / 72.0;
|
||||
/// The largest coordinate written, plotter units.
|
||||
pub const MAX_COORD: i64 = (1 << 23) - 1;
|
||||
/// The coordinates an HP-GL plot keeps to without a warning: 16-bit numbers, plotter units.
|
||||
const CLASSIC_RANGE: std::ops::RangeInclusive<i64> = -32_768..=32_767;
|
||||
/// The curve tolerance a path is flattened to by default, points.
|
||||
pub const DEFAULT_TOLERANCE: f64 = 0.1;
|
||||
/// The smallest and largest curve tolerance, points.
|
||||
@@ -67,6 +71,7 @@ const TOO_MANY_POINTS: &str = "the export is too large: the art past its first 1
|
||||
const CLIP_WORK: &str = "clipping masks are too complex to apply in full: the art past that point is drawn whole";
|
||||
const MASK_POINTS: &str = "clipping masks past 10 million points together are left out: the art they clip is drawn unclipped by them";
|
||||
const OUT_OF_RANGE: &str = "art past 8,388,607 plotter units (about 210 m) from the origin is cut off";
|
||||
const PAST_CLASSIC_RANGE: &str = "the plot has coordinates past 32,767 plotter units (about 82 cm) from the origin, which older HP-GL devices may not read: HP-GL/2 takes a wider range";
|
||||
const MANY_COLORS: &str = "the art has more than 255 colors: the colors past those draw with the pen of the nearest color";
|
||||
const UNSORTED: &str = "the plot has too many paths to sort in full: the rest are drawn in paint order";
|
||||
const TOO_DEEP: &str = "symbols, blends, envelopes and repeats nested more than 8 deep were left out";
|
||||
@@ -261,6 +266,9 @@ pub fn export_regions(doc: &Document, opts: &HpglOptions, regions: &[Rect]) -> R
|
||||
}
|
||||
}
|
||||
}
|
||||
if opts.version == Version::Hpgl && by_pen.iter().flatten().flatten().any(|(x, y)| !CLASSIC_RANGE.contains(x) || !CLASSIC_RANGE.contains(y)) {
|
||||
warn(&mut warnings, PAST_CLASSIC_RANGE);
|
||||
}
|
||||
let bytes = match opts.version {
|
||||
Version::Hpgl => plain(&by_pen),
|
||||
Version::Hpgl2 => encoded(&by_pen, &pens),
|
||||
|
||||
@@ -454,6 +454,27 @@ fn art_past_the_plotter_range_is_cut_off() {
|
||||
assert_eq!(text(&out), "IN;PU;SP1;PU0,706;PD141,706;PU;SP0;");
|
||||
}
|
||||
|
||||
/// HP-GL past 16-bit coordinates is written as it is, with a warning; HP-GL/2 gets none.
|
||||
#[test]
|
||||
fn hpgl_past_16_bit_coordinates_warns() {
|
||||
let region = Rect::new(-2400.0, 0.0, 2400.0, 100.0);
|
||||
// Past 32,767 from the bottom-left corner, within the range from the center.
|
||||
let d = doc_with(|d| vec![stroked(d, line((-2000.0, 50.0), (2000.0, 50.0)), Color::BLACK)]);
|
||||
let out = plot(&d, &HpglOptions { region, ..HpglOptions::default() });
|
||||
assert_eq!(out.warnings, [PAST_CLASSIC_RANGE]);
|
||||
assert_eq!(text(&out), "IN;PU;SP1;PU5644,706;PD62089,706;PU;SP0;");
|
||||
let out = plot(&d, &HpglOptions { region, origin: Origin::Center, ..HpglOptions::default() });
|
||||
assert!(out.warnings.is_empty(), "{:?}", out.warnings);
|
||||
assert_eq!(text(&out), "IN;PU;SP1;PU-28222,0;PD28222,0;PU;SP0;");
|
||||
// Past −32,768 and 32,767 from the center.
|
||||
let d = doc_with(|d| vec![stroked(d, line((-2400.0, 50.0), (2400.0, 50.0)), Color::BLACK)]);
|
||||
let out = plot(&d, &HpglOptions { region, origin: Origin::Center, ..HpglOptions::default() });
|
||||
assert_eq!(out.warnings, [PAST_CLASSIC_RANGE]);
|
||||
assert_eq!(text(&out), "IN;PU;SP1;PU-33867,0;PD33867,0;PU;SP0;");
|
||||
let out = plot(&d, &HpglOptions { region, origin: Origin::Center, version: Version::Hpgl2, ..HpglOptions::default() });
|
||||
assert!(out.warnings.is_empty(), "{:?}", out.warnings);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_plot_stops_at_its_point_budget() {
|
||||
let d = doc_with(|d| (0..MAX_POINTS / 4).map(|i| stroked(d, rect(1.0, 1.0, 2.0 + (i % 50) as f64, 3.0), Color::BLACK)).collect());
|
||||
|
||||
@@ -22,7 +22,7 @@ pub(super) const OPTIONS: &[FormatOption] = &[
|
||||
name: "hpglVersion",
|
||||
ty: "string",
|
||||
default: "\"hpgl\"",
|
||||
description: "hpgl (IN, SP, PU and PD only) or hpgl2 (also the pens' colors, NP and PC, and each pen's paths as one encoded polyline, PE)",
|
||||
description: "hpgl (IN, SP, PU and PD only; a coordinate outside -32,768 to 32,767 gets a warning) or hpgl2 (also the pens' colors, NP and PC, and each pen's paths as one encoded polyline, PE)",
|
||||
},
|
||||
FormatOption {
|
||||
name: "curveTolerance",
|
||||
|
||||
+5
-3
@@ -6419,10 +6419,12 @@ are VectorCraft's own.
|
||||
|
||||
`hpglVersion: "hpgl"` (the default) writes `IN;`, then for each pen `PU;SP<n>;` and each path `PUx,y;PDx,y,…;`, and
|
||||
ends with `PU;SP0;`. `"hpgl2"` also writes the palette (`NP` and a `PC` color for each pen) and draws each pen's
|
||||
paths as one encoded polyline (`PE`, base 64), which takes fewer bytes than the same moves as text. `warnings` names
|
||||
paths as one encoded polyline (`PE`, base 64), which takes fewer bytes than the same moves as text. An `"hpgl"` plot
|
||||
with a coordinate outside −32,768 to 32,767 units (about 82 cm from the origin, the range of 16-bit numbers) is written
|
||||
as it is, with a warning that older devices may not read it; this check is VectorCraft's own. `warnings` names
|
||||
type drawn as outlines, inline graphics in type (left out), placed images, opacity masks, raster effects, stroke
|
||||
looks that are not drawn, art past the plotter's range, colors past 255 pens, and the limits on points, clipping
|
||||
work, symbols, live art, nesting depth and sorting.
|
||||
looks that are not drawn, art past the plotter's range, HP-GL coordinates past 16-bit numbers, colors past 255 pens,
|
||||
and the limits on points, clipping work, symbols, live art, nesting depth and sorting.
|
||||
|
||||
```json
|
||||
{"name":"export","arguments":{"path":"/tmp/decal.plt","format":"hpgl"}}
|
||||
|
||||
Reference in New Issue
Block a user