1use crate as pdf;
2use crate::object::*;
3use crate::error::*;
4use itertools::izip;
5use datasize::DataSize;
6
7#[derive(Object, Debug, Clone, ObjectWrite)]
8struct RawFunction {
9 #[pdf(key="FunctionType")]
10 function_type: u32,
11
12 #[pdf(key="Domain")]
13 domain: Vec<f32>,
14
15 #[pdf(key="Range")]
16 range: Option<Vec<f32>>,
17
18 #[pdf(key="Size")]
19 size: Option<Vec<u32>>,
20
21 #[pdf(key="BitsPerSample")]
22 _bits_per_sample: Option<u32>,
23
24 #[pdf(key="Order", default="1")]
25 order: u32,
26
27 #[pdf(key="Encode")]
28 encode: Option<Vec<f32>>,
29
30 #[pdf(key="Decode")]
31 decode: Option<Vec<f32>>,
32
33 #[pdf(other)]
34 other: Dictionary
35}
36
37#[derive(Object, Debug, Clone)]
38struct Function2 {
39 #[pdf(key="C0")]
40 c0: Option<Vec<f32>>,
41
42 #[pdf(key="C1")]
43 c1: Option<Vec<f32>>,
44
45 #[pdf(key="N")]
46 exponent: f32,
47}
48
49#[derive(Debug, Clone, DataSize)]
50pub enum Function {
51 Sampled(SampledFunction),
52 Interpolated(Vec<InterpolatedFunctionDim>),
53 Stiching,
54 Calculator,
55 PostScript { func: PsFunc, domain: Vec<f32>, range: Vec<f32> },
56}
57impl Function {
58 pub fn apply(&self, x: &[f32], out: &mut [f32]) -> Result<()> {
59 match *self {
60 Function::Sampled(ref func) => {
61 func.apply(x, out)
62 }
63 Function::Interpolated(ref parts) => {
64 if parts.len() != out.len() {
65 bail!("incorrect output length: expected {}, found {}.", parts.len(), out.len())
66 }
67 for (f, y) in parts.iter().zip(out) {
68 *y = f.apply(x[0]);
69 }
70 Ok(())
71 }
72 Function::PostScript { ref func, .. } => func.exec(x, out),
73 _ => bail!("unimplemted function {:?}", self)
74 }
75 }
76 pub fn input_dim(&self) -> usize {
77 match *self {
78 Function::PostScript { ref domain, .. } => domain.len() / 2,
79 Function::Sampled(ref f) => f.input.len(),
80 _ => panic!()
81 }
82 }
83 pub fn output_dim(&self) -> usize {
84 match *self {
85 Function::PostScript { ref range, .. } => range.len() / 2,
86 Function::Sampled(ref f) => f.output.len(),
87 _ => panic!()
88 }
89 }
90}
91impl FromDict for Function {
92 fn from_dict(dict: Dictionary, resolve: &impl Resolve) -> Result<Self> {
93 use std::f32::INFINITY;
94 let raw = RawFunction::from_dict(dict, resolve)?;
95 match raw.function_type {
96 2 => {
97 let f2 = Function2::from_dict(raw.other, resolve)?;
98
99 let n_dim = match (raw.range.as_ref(), f2.c0.as_ref(), f2.c1.as_ref()) {
100 (Some(range), _, _) => range.len() / 2,
101 (_, Some(c0), _) => c0.len(),
102 (_, _, Some(c1)) => c1.len(),
103 _ => bail!("unknown dimensions")
104 };
105 let mut parts = Vec::with_capacity(n_dim);
106 let input_range = (raw.domain[0], raw.domain[1]);
107 for dim in 0 .. n_dim {
108 let output_range = (
109 raw.range.as_ref().and_then(|r| r.get(2*dim).cloned()).unwrap_or(-INFINITY),
110 raw.range.as_ref().and_then(|r| r.get(2*dim+1).cloned()).unwrap_or(INFINITY)
111 );
112 let c0 = f2.c0.as_ref().and_then(|c0| c0.get(dim).cloned()).unwrap_or(0.0);
113 let c1 = f2.c1.as_ref().and_then(|c1| c1.get(dim).cloned()).unwrap_or(1.0);
114 let exponent = f2.exponent;
115 parts.push(InterpolatedFunctionDim {
116 input_range, output_range, c0, c1, exponent
117 });
118 }
119 Ok(Function::Interpolated(parts))
120 },
121 i => {
122 dbg!(raw);
123 bail!("unsupported function type {}", i)
124 }
125 }
126 }
127}
128impl Object for Function {
129 fn from_primitive(p: Primitive, resolve: &impl Resolve) -> Result<Self> {
130 match p {
131 Primitive::Dictionary(dict) => Self::from_dict(dict, resolve),
132 Primitive::Stream(s) => {
133 let stream = Stream::<RawFunction>::from_stream(s, resolve)?;
134 let data = stream.data(resolve)?;
135 match stream.info.function_type {
136 4 => {
137 let s = std::str::from_utf8(&data)?;
138 let func = PsFunc::parse(s)?;
139 let info = stream.info.info;
140 Ok(Function::PostScript { func, domain: info.domain, range: info.range.unwrap() })
141 },
142 0 => {
143 let info = stream.info.info;
144 let order = match info.order {
145 1 => Interpolation::Linear,
146 3 => Interpolation::Cubic,
147 n => bail!("Invalid interpolation order {}", n),
148 };
149
150 let size = try_opt!(info.size);
151 let range = try_opt!(info.range);
152 let encode = info.encode.unwrap_or_else(|| size.iter().flat_map(|&n| [0.0, (n-1) as f32]).collect());
153 let decode = info.decode.unwrap_or_else(|| range.clone());
154
155 Ok(Function::Sampled(SampledFunction {
156 input: izip!(info.domain.chunks_exact(2), encode.chunks_exact(2), size.iter()).map(|(c, e, &s)| {
157 SampledFunctionInput {
158 domain: (c[0], c[1]),
159 encode_offset: e[0],
160 encode_scale: e[1],
161 size: s as usize,
162 }
163 }).collect(),
164 output: decode.chunks_exact(2).map(|c| SampledFunctionOutput {
165 offset: c[0],
166 scale: (c[1] - c[0]) / 255.,
167 }).collect(),
168 data,
169 order,
170 range,
171 }))
172 }
173 ref p => bail!("found a function stream with type {:?}", p)
174 }
175 },
176 Primitive::Reference(r) => Self::from_primitive(resolve.resolve(r)?, resolve),
177 _ => bail!("double indirection")
178 }
179 }
180}
181impl ObjectWrite for Function {
182 fn to_primitive(&self, update: &mut impl Updater) -> Result<Primitive> {
183 unimplemented!()
184 }
206}
207impl DeepClone for Function {
208 fn deep_clone(&self, cloner: &mut impl Cloner) -> Result<Self> {
209 Ok(self.clone())
210 }
211}
212
213#[derive(Debug, Clone, DataSize)]
214struct SampledFunctionInput {
215 domain: (f32, f32),
216 encode_offset: f32,
217 encode_scale: f32,
218 size: usize,
219}
220impl SampledFunctionInput {
221 fn map(&self, x: f32) -> (usize, usize, f32) {
222 let x = x.clamp(self.domain.0, self.domain.1);
223 let y = x.mul_add(self.encode_scale, self.encode_offset);
224 (y.floor() as usize, self.size, y.fract())
225 }
226}
227
228#[derive(Debug, Clone, DataSize)]
229struct SampledFunctionOutput {
230 offset: f32,
231 scale: f32
232}
233impl SampledFunctionOutput {
234 fn map(&self, x: f32) -> f32 {
235 x.mul_add(self.scale, self.offset)
236 }
237}
238
239#[derive(Debug, Clone, DataSize)]
240enum Interpolation {
241 Linear,
242 #[allow(dead_code)] Cubic,
244}
245
246#[derive(Debug, Clone, DataSize)]
247pub struct SampledFunction {
248 input: Vec<SampledFunctionInput>,
249 output: Vec<SampledFunctionOutput>,
250 data: Arc<[u8]>,
251 order: Interpolation,
252 range: Vec<f32>,
253}
254impl SampledFunction {
255 fn apply(&self, x: &[f32], out: &mut [f32]) -> Result<()> {
256 if x.len() != self.input.len() {
257 bail!("input dimension mismatch {} != {}", x.len(), self.input.len());
258 }
259 let n_out = out.len();
260 if out.len() * 2 != self.range.len() {
261 bail!("output dimension mismatch 2 * {} != {}", out.len(), self.range.len())
262 }
263 match x.len() {
264 1 => {
265 match self.order {
266 Interpolation::Linear => {
267 let (i, _, s) = self.input[0].map(x[0]);
268 let idx = i * n_out;
269
270 for (o, &a) in out.iter_mut().zip(&self.data[idx..]) {
271 *o = a as f32 * (1. - s);
272 }
273 for (o, &b) in out.iter_mut().zip(&self.data[idx + n_out..]) {
274 *o += b as f32 * s;
275 }
276 }
277 _ => unimplemented!()
278 }
279 }
280 2 => match self.order {
281 Interpolation::Linear => {
282 let (i0, s0, f0) = self.input[0].map(x[0]);
283 let (i1, _, f1) = self.input[1].map(x[1]);
284 let (j0, j1) = (i0+1, i1+1);
285 let (g0, g1) = (1. - f0, 1. - f1);
286
287 out.fill(0.0);
288 let mut add = |i0, i1, f| {
289 let idx = (i0 + s0 * i1) * n_out;
290
291 if let Some(part) = self.data.get(idx .. idx+n_out) {
292 for (o, &b) in out.iter_mut().zip(part) {
293 *o += f * b as f32;
294 }
295 }
296 };
297
298 add(i0, i1, g0 * g1);
299 add(j0, i1, f0 * g1);
300 add(i0, j1, g0 * f1);
301 add(j0, j1, f0 * f1);
302 }
303 _ => unimplemented!()
304 }
305 3 => match self.order {
306 Interpolation::Linear => {
307 let (i0, s0, f0) = self.input[0].map(x[0]);
308 let (i1, s1, f1) = self.input[1].map(x[1]);
309 let (i2, _, f2) = self.input[2].map(x[2]);
310 let (j0, j1, j2) = (i0+1, i1+1, i2+1);
311 let (g0, g1, g2) = (1. - f0, 1. - f1, 1. - f2);
312
313 out.fill(0.0);
314 let mut add = |i0, i1, i2, f| {
315 let idx = (i0 + s0 * (i1 + s1 * i2)) * n_out;
316
317 if let Some(part) = self.data.get(idx .. idx+n_out) {
318 for (o, &b) in out.iter_mut().zip(part) {
319 *o += f * b as f32;
320 }
321 }
322 };
323
324 add(i0, i1, i2, g0 * g1 * g2);
325 add(j0, i1, i2, f0 * g1 * g2);
326 add(i0, j1, i2, g0 * f1 * g2);
327 add(j0, j1, i2, f0 * f1 * g2);
328
329 add(i0, i1, j2, g0 * g1 * f2);
330 add(j0, i1, j2, f0 * g1 * f2);
331 add(i0, j1, j2, g0 * f1 * f2);
332 add(j0, j1, j2, f0 * f1 * f2);
333 }
334 _ => unimplemented!()
335 }
336 n => bail!("Order {}", n)
337 }
338 for (o, y) in self.output.iter().zip(out.iter_mut()) {
339 *y = o.map(*y);
340 }
341 Ok(())
342 }
343}
344
345
346#[derive(Debug, Clone, DataSize)]
347pub struct InterpolatedFunctionDim {
348 pub input_range: (f32, f32),
349 pub output_range: (f32, f32),
350 pub c0: f32,
351 pub c1: f32,
352 pub exponent: f32,
353}
354impl InterpolatedFunctionDim {
355 pub fn apply(&self, x: f32) -> f32 {
356 let y = self.c0 + x.powf(self.exponent) * (self.c1 - self.c0);
357 let (y0, y1) = self.output_range;
358 y.min(y1).max(y0)
359 }
360}
361
362#[derive(Debug)]
363pub enum PostScriptError {
364 StackUnderflow,
365 IncorrectStackSize
366}
367#[derive(Debug, Clone, DataSize)]
368pub struct PsFunc {
369 pub ops: Vec<PsOp>
370}
371
372macro_rules! op {
373 ($stack:ident; $($v:ident),* => $($e:expr),*) => ( {
374 $(let $v = $stack.pop().ok_or(PostScriptError::StackUnderflow)?;)*
375 $($stack.push($e);)*
376 } )
377}
378
379impl PsFunc {
380 fn exec_inner(&self, stack: &mut Vec<f32>) -> Result<(), PostScriptError> {
381 for &op in &self.ops {
382 match op {
383 PsOp::Int(i) => stack.push(i as f32),
384 PsOp::Value(v) => stack.push(v),
385 PsOp::Dup => op!(stack; v => v, v),
386 PsOp::Exch => op!(stack; b, a => b, a),
387 PsOp::Add => op!(stack; b, a => a + b),
388 PsOp::Sub => op!(stack; b, a => a - b),
389 PsOp::Mul => op!(stack; b, a => a * b),
390 PsOp::Abs => op!(stack; a => a.abs()),
391 PsOp::Roll => {
392 let j = stack.pop().ok_or(PostScriptError::StackUnderflow)? as isize;
393 let n = stack.pop().ok_or(PostScriptError::StackUnderflow)? as usize;
394 let start = stack.len() - n;
395 let slice = &mut stack[start..];
396 if j > 0 {
397 slice.rotate_right(j as usize);
398 } else {
399 slice.rotate_left(-j as usize);
400 }
401 }
402 PsOp::Index => {
403 let n = stack.pop().ok_or(PostScriptError::StackUnderflow)? as usize;
404 if n >= stack.len() { return Err(PostScriptError::StackUnderflow); }
405 let val = stack[stack.len() - n - 1];
406 stack.push(val);
407 }
408 PsOp::Cvr => {}
409 PsOp::Pop => {
410 stack.pop().ok_or(PostScriptError::StackUnderflow)?;
411 }
412 }
413 }
414 Ok(())
415 }
416 pub fn exec(&self, input: &[f32], output: &mut [f32]) -> Result<()> {
417 let mut stack = Vec::with_capacity(10);
418 stack.extend_from_slice(input);
419 match self.exec_inner(&mut stack) {
420 Ok(()) => {},
421 Err(_) => return Err(PdfError::PostScriptExec)
422 }
423 if output.len() != stack.len() {
424 bail!("incorrect output length: expected {}, found {}.", stack.len(), output.len())
425 }
426 output.copy_from_slice(&stack);
427 Ok(())
428 }
429 pub fn parse(s: &str) -> Result<Self, PdfError> {
430 let start = s.find('{').ok_or(PdfError::PostScriptParse)?;
431 let end = s.rfind('}').ok_or(PdfError::PostScriptParse)?;
432
433 let ops: Result<Vec<_>, _> = s[start + 1 .. end].split_ascii_whitespace().map(PsOp::parse).collect();
434 Ok(PsFunc { ops: ops? })
435 }
436}
437
438#[derive(Copy, Clone, Debug, DataSize)]
439pub enum PsOp {
440 Int(i32),
441 Value(f32),
442 Add,
443 Sub,
444 Abs,
445 Mul,
446 Dup,
447 Exch,
448 Roll,
449 Index,
450 Cvr,
451 Pop,
452}
453impl PsOp {
454 pub fn parse(s: &str) -> Result<Self> {
455 if let Ok(i) = s.parse::<i32>() {
456 Ok(PsOp::Int(i))
457 } else if let Ok(f) = s.parse::<f32>() {
458 Ok(PsOp::Value(f))
459 } else {
460 Ok(match s {
461 "add" => PsOp::Add,
462 "sub" => PsOp::Sub,
463 "abs" => PsOp::Abs,
464 "mul" => PsOp::Mul,
465 "dup" => PsOp::Dup,
466 "exch" => PsOp::Exch,
467 "roll" => PsOp::Roll,
468 "index" => PsOp::Index,
469 "cvr" => PsOp::Cvr,
470 "pop" => PsOp::Pop,
471 _ => {
472 bail!("unimplemented op {}", s);
473 }
474 })
475 }
476 }
477}