mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-07 12:13:19 +00:00
Merge pull request #6002 from mockydevs/fix/eps-cvi-radix
EPS import: cvi and cvr read radix numbers (eps2write spot colours with spaces)
This commit is contained in:
@@ -12,7 +12,7 @@ use vectorcraft_geom::Affine;
|
||||
|
||||
use super::data::Stream;
|
||||
use super::graphics::{GState, Out};
|
||||
use super::lex::{IMMEDIATE, Lexer};
|
||||
use super::lex::{IMMEDIATE, Lexer, number};
|
||||
use super::obj::{Dict, DictRef, Key, Obj, Op, PsError, Res, Shared, ps_err};
|
||||
|
||||
/// Most operations one file may run.
|
||||
@@ -775,7 +775,7 @@ impl<'a> Interp<'a> {
|
||||
},
|
||||
Cvi => {
|
||||
let v = match self.pop()? {
|
||||
Obj::Str(s) => String::from_utf8_lossy(&s.borrow()).trim().parse::<f64>().map_err(|_| PsError::Ps("typecheck", String::new()))?,
|
||||
Obj::Str(s) => string_number(&s.borrow())?,
|
||||
o => o.as_num().ok_or(PsError::Ps("typecheck", String::new()))?,
|
||||
};
|
||||
if !(v.is_finite() && v.abs() < 9e15) {
|
||||
@@ -785,7 +785,7 @@ impl<'a> Interp<'a> {
|
||||
}
|
||||
Cvr => {
|
||||
let v = match self.pop()? {
|
||||
Obj::Str(s) => String::from_utf8_lossy(&s.borrow()).trim().parse::<f64>().map_err(|_| PsError::Ps("typecheck", String::new()))?,
|
||||
Obj::Str(s) => string_number(&s.borrow())?,
|
||||
o => o.as_num().ok_or(PsError::Ps("typecheck", String::new()))?,
|
||||
};
|
||||
self.push_num(v)?;
|
||||
@@ -1471,6 +1471,17 @@ impl<'a> Interp<'a> {
|
||||
}
|
||||
|
||||
/// An array or string index.
|
||||
/// The number a string holds by the PostScript syntax (`cvi`, `cvr`: PLRM 3rd ed., chapter 8),
|
||||
/// radix numbers such as `16#20` included.
|
||||
fn string_number(s: &[u8]) -> Res<f64> {
|
||||
let text = String::from_utf8_lossy(s);
|
||||
match number(text.trim_matches(|c: char| c.is_ascii_whitespace() || c == '\0')) {
|
||||
Some(Obj::Int(i)) => Ok(i as f64),
|
||||
Some(Obj::Real(r)) => Ok(r),
|
||||
_ => ps_err("typecheck", ""),
|
||||
}
|
||||
}
|
||||
|
||||
fn index(k: &Obj) -> Res<usize> {
|
||||
match *k {
|
||||
Obj::Int(i) if i >= 0 => Ok(i as usize),
|
||||
|
||||
@@ -276,7 +276,7 @@ pub(crate) fn hex_decode(body: &[u8]) -> Option<Vec<u8>> {
|
||||
}
|
||||
|
||||
/// A number token (`12`, `-3.5`, `.5`, `1e-3`, `16#ff`), or `None`.
|
||||
fn number(w: &str) -> Option<Obj> {
|
||||
pub(crate) fn number(w: &str) -> Option<Obj> {
|
||||
let first = w.bytes().next()?;
|
||||
if !(first.is_ascii_digit() || matches!(first, b'+' | b'-' | b'.')) {
|
||||
return None;
|
||||
|
||||
@@ -1022,6 +1022,18 @@ fn known_answers_false_for_keys_no_dictionary_holds() {
|
||||
check("{ 1 dict null known } stopped");
|
||||
}
|
||||
|
||||
/// `cvi` and `cvr` read a string as the PostScript syntax reads a number (PLRM 3rd ed., chapter
|
||||
/// 8), radix numbers included: prologs turn a name's `#20` escape back into its character with
|
||||
/// `(16#20) cvi`.
|
||||
#[test]
|
||||
fn cvi_and_cvr_read_radix_numbers() {
|
||||
check("(16#20) cvi 32 eq (8#17) cvi 15 eq and ( 2#101 ) cvi 5 eq and (36#Z) cvi 35 eq and");
|
||||
check("(16#ff) cvr 255 eq (3.7) cvi 3 eq and (-2.5e1) cvr -25 eq and (12) cvr 12 eq and");
|
||||
check("{ (16#zz) cvi } stopped { (inf) cvr } stopped and { (16#-1) cvi } stopped and { () cvi } stopped and");
|
||||
// A name's escapes, as a prolog undoes them for a spot colour named `PANTONE 300 C`.
|
||||
check("(PANTONE#20300) dup 7 3 getinterval (16#--) dup 3 4 -1 roll 1 2 getinterval putinterval cvi 32 eq exch pop");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dictstack_and_internaldict_answer() {
|
||||
check("10 array dictstack length countdictstack eq");
|
||||
|
||||
Reference in New Issue
Block a user