1use super::*;
2
3#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
5enum FunctionType {
6 Sampled,
8 Exponential,
10 Stitching,
12 PostScript,
14}
15
16impl FunctionType {
17 pub(crate) fn to_int(self) -> i32 {
18 match self {
19 Self::Sampled => 0,
20 Self::Exponential => 2,
21 Self::Stitching => 3,
22 Self::PostScript => 4,
23 }
24 }
25}
26
27macro_rules! common_func_methods {
28 () => {
29 pub fn domain(&mut self, domain: impl IntoIterator<Item = f32>) -> &mut Self {
32 self.insert(Name(b"Domain")).array().items(domain);
33 self
34 }
35
36 pub fn range(&mut self, range: impl IntoIterator<Item = f32>) -> &mut Self {
40 self.insert(Name(b"Range")).array().items(range);
41 self
42 }
43 };
44}
45
46pub struct SampledFunction<'a> {
50 stream: Stream<'a>,
51}
52
53impl<'a> SampledFunction<'a> {
54 pub(crate) fn start(mut stream: Stream<'a>) -> Self {
56 stream.pair(Name(b"FunctionType"), FunctionType::Sampled.to_int());
57 Self { stream }
58 }
59
60 common_func_methods!();
61
62 pub fn size(&mut self, size: impl IntoIterator<Item = i32>) -> &mut Self {
66 self.insert(Name(b"Size")).array().items(size);
67 self
68 }
69
70 pub fn bits_per_sample(&mut self, bits: i32) -> &mut Self {
74 self.pair(Name(b"BitsPerSample"), bits);
75 self
76 }
77
78 pub fn order(&mut self, order: InterpolationOrder) -> &mut Self {
82 self.pair(Name(b"Order"), order.to_int());
83 self
84 }
85
86 pub fn encode(&mut self, encode: impl IntoIterator<Item = f32>) -> &mut Self {
90 self.insert(Name(b"Encode")).array().items(encode);
91 self
92 }
93
94 pub fn decode(&mut self, decode: impl IntoIterator<Item = f32>) -> &mut Self {
98 self.insert(Name(b"Decode")).array().items(decode);
99 self
100 }
101}
102
103deref!('a, SampledFunction<'a> => Stream<'a>, stream);
104
105#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash)]
108pub enum InterpolationOrder {
109 #[default]
111 Linear,
112 Cubic,
114}
115
116impl InterpolationOrder {
117 pub(crate) fn to_int(self) -> i32 {
118 match self {
119 Self::Linear => 1,
120 Self::Cubic => 3,
121 }
122 }
123}
124
125pub struct ExponentialFunction<'a> {
133 dict: Dict<'a>,
134}
135
136writer!(ExponentialFunction: |obj| {
137 let mut dict = obj.dict();
138 dict.pair(Name(b"FunctionType"), FunctionType::Exponential.to_int());
139 Self { dict }
140});
141
142impl ExponentialFunction<'_> {
143 common_func_methods!();
144
145 pub fn c0(&mut self, c0: impl IntoIterator<Item = f32>) -> &mut Self {
149 self.insert(Name(b"C0")).array().items(c0);
150 self
151 }
152
153 pub fn c1(&mut self, c1: impl IntoIterator<Item = f32>) -> &mut Self {
157 self.insert(Name(b"C1")).array().items(c1);
158 self
159 }
160
161 pub fn n(&mut self, n: f32) -> &mut Self {
165 self.pair(Name(b"N"), n);
166 self
167 }
168}
169
170deref!('a, ExponentialFunction<'a> => Dict<'a>, dict);
171
172pub struct StitchingFunction<'a> {
180 dict: Dict<'a>,
181}
182
183writer!(StitchingFunction: |obj| {
184 let mut dict = obj.dict();
185 dict.pair(Name(b"FunctionType"), FunctionType::Stitching.to_int());
186 Self { dict }
187});
188
189impl StitchingFunction<'_> {
190 common_func_methods!();
191
192 pub fn functions(&mut self, functions: impl IntoIterator<Item = Ref>) -> &mut Self {
196 self.insert(Name(b"Functions")).array().items(functions);
197 self
198 }
199
200 pub fn bounds(&mut self, bounds: impl IntoIterator<Item = f32>) -> &mut Self {
205 self.insert(Name(b"Bounds")).array().items(bounds);
206 self
207 }
208
209 pub fn encode(&mut self, encode: impl IntoIterator<Item = f32>) -> &mut Self {
214 self.insert(Name(b"Encode")).array().items(encode);
215 self
216 }
217}
218
219deref!('a, StitchingFunction<'a> => Dict<'a>, dict);
220
221pub struct PostScriptFunction<'a> {
225 stream: Stream<'a>,
226}
227
228impl<'a> PostScriptFunction<'a> {
229 pub(crate) fn start(mut stream: Stream<'a>) -> Self {
231 stream.pair(Name(b"FunctionType"), FunctionType::PostScript.to_int());
232 Self { stream }
233 }
234
235 common_func_methods!();
236}
237
238deref!('a, PostScriptFunction<'a> => Stream<'a>, stream);
239
240#[derive(Debug, Copy, Clone, PartialEq)]
242pub enum PostScriptOp<'a> {
243 Real(f32),
245 Integer(i32),
247
248 Abs,
250 Add,
252 Atan,
254 Ceiling,
256 Cos,
258 Cvi,
260 Cvr,
262 Div,
264 Exp,
266 Floor,
268 Idiv,
270 Ln,
272 Log,
274 Mod,
276 Mul,
278 Neg,
280 Round,
282 Sin,
284 Sqrt,
286 Sub,
288 Truncate,
290
291 And,
293 Bitshift,
295 Eq,
297 False,
299 Ge,
301 Gt,
303 Le,
305 Lt,
307 Ne,
309 Not,
311 Or,
313 True,
315 Xor,
317
318 If(&'a [Self]),
320 IfElse(&'a [Self], &'a [Self]),
322
323 Copy,
325 Dup,
327 Exch,
329 Index,
331 Pop,
333 Roll,
335}
336
337impl PostScriptOp<'_> {
338 pub fn encode(ops: &[Self]) -> Buf {
340 let mut buf = Buf::new();
341 Self::write_slice(ops, &mut buf);
342 buf
343 }
344
345 fn write_slice(ops: &[Self], buf: &mut Buf) {
346 buf.push(b'{');
347 if ops.len() > 1 {
348 buf.push(b' ');
349 }
350 for op in ops {
351 op.write(buf);
352 buf.push(b' ');
353 }
354 if ops.len() == 1 {
355 buf.inner.pop();
356 }
357 buf.push(b'}');
358 }
359
360 fn write(&self, buf: &mut Buf) {
361 match *self {
362 Self::Real(r) => buf.push_decimal(r),
363 Self::Integer(i) => buf.push_val(i),
364 Self::If(ops) => {
365 Self::write_slice(ops, buf);
366 buf.push(b' ');
367 buf.extend(self.operator());
368 }
369 Self::IfElse(ops1, ops2) => {
370 Self::write_slice(ops1, buf);
371 buf.push(b' ');
372 Self::write_slice(ops2, buf);
373 buf.push(b' ');
374 buf.extend(self.operator());
375 }
376 _ => buf.extend(self.operator()),
377 }
378 }
379
380 fn operator(&self) -> &'static [u8] {
381 match self {
382 Self::Real(_) | Self::Integer(_) => b"",
383 Self::Abs => b"abs",
384 Self::Add => b"add",
385 Self::Atan => b"atan",
386 Self::Ceiling => b"ceiling",
387 Self::Cos => b"cos",
388 Self::Cvi => b"cvi",
389 Self::Cvr => b"cvr",
390 Self::Div => b"div",
391 Self::Exp => b"exp",
392 Self::Floor => b"floor",
393 Self::Idiv => b"idiv",
394 Self::Ln => b"ln",
395 Self::Log => b"log",
396 Self::Mod => b"mod",
397 Self::Mul => b"mul",
398 Self::Neg => b"neg",
399 Self::Round => b"round",
400 Self::Sin => b"sin",
401 Self::Sqrt => b"sqrt",
402 Self::Sub => b"sub",
403 Self::Truncate => b"truncate",
404 Self::And => b"and",
405 Self::Bitshift => b"bitshift",
406 Self::Eq => b"eq",
407 Self::False => b"false",
408 Self::Ge => b"ge",
409 Self::Gt => b"gt",
410 Self::Le => b"le",
411 Self::Lt => b"lt",
412 Self::Ne => b"ne",
413 Self::Not => b"not",
414 Self::Or => b"or",
415 Self::True => b"true",
416 Self::Xor => b"xor",
417 Self::If(_) => b"if",
418 Self::IfElse(_, _) => b"ifelse",
419 Self::Copy => b"copy",
420 Self::Dup => b"dup",
421 Self::Exch => b"exch",
422 Self::Index => b"index",
423 Self::Pop => b"pop",
424 Self::Roll => b"roll",
425 }
426 }
427}
428
429#[cfg(test)]
430mod tests {
431 use super::*;
432
433 #[test]
434 fn test_post_script_encoding() {
435 use PostScriptOp::*;
436
437 let ops = [
438 Real(3.0),
439 Real(2.0),
440 Mul,
441 Exch,
442 Dup,
443 Real(0.0),
444 Ge,
445 IfElse(&[Real(1.0), Add], &[Neg]),
446 Add,
447 ];
448
449 assert_eq!(
450 PostScriptOp::encode(&ops).as_slice(),
451 b"{ 3.0 2.0 mul exch dup 0.0 ge { 1.0 add } {neg} ifelse add }"
452 );
453 }
454}