1#![allow(clippy::needless_range_loop)]
4
5use crate::CacheKey;
6use crate::cache::Cache;
7use crate::color::{ColorComponents, ColorSpace};
8use crate::util::{FloatExt, PointExt};
9use hayro_syntax::bit_reader::{BitReader, BitSize};
10use hayro_syntax::function::{Function, Values, interpolate};
11use hayro_syntax::object::Array;
12use hayro_syntax::object::Dict;
13use hayro_syntax::object::Object;
14use hayro_syntax::object::Rect;
15use hayro_syntax::object::Stream;
16use hayro_syntax::object::dict::keys::{
17 BACKGROUND, BBOX, BITS_PER_COMPONENT, BITS_PER_COORDINATE, BITS_PER_FLAG, COLORSPACE, COORDS,
18 DECODE, DOMAIN, EXTEND, FUNCTION, MATRIX, SHADING_TYPE, VERTICES_PER_ROW,
19};
20use kurbo::{Affine, BezPath, CubicBez, ParamCurve, Point, Shape};
21use log::warn;
22use smallvec::{SmallVec, smallvec};
23use std::sync::Arc;
24#[derive(Debug, Clone)]
28pub enum ShadingFunction {
29 Single(Function),
31 Multiple(SmallVec<[Function; 4]>),
33}
34
35impl ShadingFunction {
36 pub fn eval(&self, input: &Values) -> Option<Values> {
38 match self {
39 ShadingFunction::Single(s) => s.eval(input.clone()),
40 ShadingFunction::Multiple(m) => {
41 let mut out = smallvec![];
44
45 for func in m {
46 out.push(*func.eval(input.clone())?.first()?);
47 }
48
49 Some(out)
50 }
51 }
52 }
53}
54
55#[derive(Debug)]
57pub enum ShadingType {
58 FunctionBased {
60 domain: [f32; 4],
62 matrix: Affine,
64 function: ShadingFunction,
66 },
67 RadialAxial {
69 coords: [f32; 6],
77 domain: [f32; 2],
79 function: ShadingFunction,
81 extend: [bool; 2],
83 axial: bool,
85 },
86 TriangleMesh {
88 triangles: Vec<Triangle>,
90 function: Option<ShadingFunction>,
92 },
93 CoonsPatchMesh {
95 patches: Vec<CoonsPatch>,
97 function: Option<ShadingFunction>,
99 },
100 TensorProductPatchMesh {
102 patches: Vec<TensorProductPatch>,
104 function: Option<ShadingFunction>,
106 },
107 Dummy,
109}
110
111#[derive(Clone, Debug)]
113pub struct Shading {
114 cache_key: u128,
115 pub shading_type: Arc<ShadingType>,
117 pub color_space: ColorSpace,
119 pub clip_path: Option<BezPath>,
121 pub background: Option<SmallVec<[f32; 4]>>,
123}
124
125impl Shading {
126 pub(crate) fn new(dict: &Dict, stream: Option<&Stream>, cache: &Cache) -> Option<Self> {
127 let cache_key = dict.cache_key();
128
129 let shading_num = dict.get::<u8>(SHADING_TYPE)?;
130
131 let color_space = ColorSpace::new(dict.get(COLORSPACE)?, cache)?;
132
133 let shading_type = match shading_num {
134 1 => {
135 let domain = dict.get::<[f32; 4]>(DOMAIN).unwrap_or([0.0, 1.0, 0.0, 1.0]);
136 let matrix = dict
137 .get::<[f64; 6]>(MATRIX)
138 .map(Affine::new)
139 .unwrap_or_default();
140 let function = read_function(dict, &color_space)?;
141
142 ShadingType::FunctionBased {
143 domain,
144 matrix,
145 function,
146 }
147 }
148 2 | 3 => {
149 let domain = dict.get::<[f32; 2]>(DOMAIN).unwrap_or([0.0, 1.0]);
150 let function = read_function(dict, &color_space)?;
151 let extend = dict.get::<[bool; 2]>(EXTEND).unwrap_or([false, false]);
152 let (coords, invalid) = if shading_num == 2 {
153 let read = dict.get::<[f32; 4]>(COORDS)?;
154 let invalid = (read[0] - read[2]).is_nearly_zero()
155 && (read[1] - read[3]).is_nearly_zero();
156 ([read[0], read[1], read[2], read[3], 0.0, 0.0], invalid)
157 } else {
158 let read = dict.get::<[f32; 6]>(COORDS)?;
159 let invalid = (read[0] - read[3]).is_nearly_zero()
160 && (read[1] - read[4]).is_nearly_zero()
161 && (read[2] - read[5]).is_nearly_zero();
162 (read, invalid)
163 };
164
165 let axial = shading_num == 2;
166
167 if invalid {
168 ShadingType::Dummy
169 } else {
170 ShadingType::RadialAxial {
171 domain,
172 function,
173 extend,
174 coords,
175 axial,
176 }
177 }
178 }
179 4 => {
180 let stream = stream?;
181 let stream_data = stream.decoded().ok()?;
182 let bp_coord = dict.get::<u8>(BITS_PER_COORDINATE)?;
183 let bp_comp = dict.get::<u8>(BITS_PER_COMPONENT)?;
184 let bpf = dict.get::<u8>(BITS_PER_FLAG)?;
185 let function = read_function(dict, &color_space);
186 let decode = dict.get::<Array>(DECODE)?.iter::<f32>().collect::<Vec<_>>();
187
188 let triangles = read_free_form_triangles(
189 stream_data.as_ref(),
190 bpf,
191 bp_coord,
192 bp_comp,
193 function.is_some(),
194 &decode,
195 )?;
196
197 ShadingType::TriangleMesh {
198 triangles,
199 function,
200 }
201 }
202 5 => {
203 let stream = stream?;
204 let stream_data = stream.decoded().ok()?;
205 let bp_coord = dict.get::<u8>(BITS_PER_COORDINATE)?;
206 let bp_comp = dict.get::<u8>(BITS_PER_COMPONENT)?;
207 let function = read_function(dict, &color_space);
208 let decode = dict.get::<Array>(DECODE)?.iter::<f32>().collect::<Vec<_>>();
209 let vertices_per_row = dict.get::<u32>(VERTICES_PER_ROW)?;
210
211 let triangles = read_lattice_triangles(
212 stream_data.as_ref(),
213 bp_coord,
214 bp_comp,
215 function.is_some(),
216 vertices_per_row,
217 &decode,
218 )?;
219
220 ShadingType::TriangleMesh {
221 triangles,
222 function,
223 }
224 }
225 6 => {
226 let stream = stream?;
227 let stream_data = stream.decoded().ok()?;
228 let bp_coord = dict.get::<u8>(BITS_PER_COORDINATE)?;
229 let bp_comp = dict.get::<u8>(BITS_PER_COMPONENT)?;
230 let bpf = dict.get::<u8>(BITS_PER_FLAG)?;
231 let function = read_function(dict, &color_space);
232 let decode = dict.get::<Array>(DECODE)?.iter::<f32>().collect::<Vec<_>>();
233
234 let patches = read_coons_patch_mesh(
235 stream_data.as_ref(),
236 bpf,
237 bp_coord,
238 bp_comp,
239 function.is_some(),
240 &decode,
241 )?;
242
243 ShadingType::CoonsPatchMesh { patches, function }
244 }
245 7 => {
246 let stream = stream?;
247 let stream_data = stream.decoded().ok()?;
248 let bp_coord = dict.get::<u8>(BITS_PER_COORDINATE)?;
249 let bp_comp = dict.get::<u8>(BITS_PER_COMPONENT)?;
250 let bpf = dict.get::<u8>(BITS_PER_FLAG)?;
251 let function = read_function(dict, &color_space);
252 let decode = dict.get::<Array>(DECODE)?.iter::<f32>().collect::<Vec<_>>();
253
254 let patches = read_tensor_product_patch_mesh(
255 stream_data.as_ref(),
256 bpf,
257 bp_coord,
258 bp_comp,
259 function.is_some(),
260 &decode,
261 )?;
262
263 ShadingType::TensorProductPatchMesh { patches, function }
264 }
265 _ => return None,
266 };
267
268 let bbox = dict.get::<Rect>(BBOX);
269 let background = dict
270 .get::<Array>(BACKGROUND)
271 .map(|a| a.iter::<f32>().collect::<SmallVec<_>>());
272
273 Some(Self {
274 cache_key,
275 shading_type: Arc::new(shading_type),
276 color_space,
277 clip_path: bbox.map(|r| r.to_path(0.1)),
278 background,
279 })
280 }
281}
282
283impl CacheKey for Shading {
284 fn cache_key(&self) -> u128 {
285 self.cache_key
286 }
287}
288
289#[derive(Clone, Debug)]
291pub struct Triangle {
292 pub p0: TriangleVertex,
294 pub p1: TriangleVertex,
296 pub p2: TriangleVertex,
298 kurbo_tri: kurbo::Triangle,
299 d00: f64,
300 d01: f64,
301 d11: f64,
302}
303
304impl Triangle {
305 pub fn new(p0: TriangleVertex, p1: TriangleVertex, p2: TriangleVertex) -> Self {
307 let v0 = p1.point - p0.point;
308 let v1 = p2.point - p0.point;
309
310 let d00 = v0.dot(v0);
311 let d01 = v0.dot(v1);
312 let d11 = v1.dot(v1);
313
314 let kurbo_tri = kurbo::Triangle::new(p0.point, p1.point, p2.point);
315
316 Self {
317 p0,
318 p1,
319 kurbo_tri,
320 p2,
321 d00,
322 d01,
323 d11,
324 }
325 }
326
327 pub fn interpolate(&self, pos: Point) -> ColorComponents {
331 let (u, v, w) = self.barycentric_coords(pos);
332
333 let mut result = smallvec![];
334
335 for i in 0..self.p0.colors.len() {
336 let c0 = self.p0.colors[i];
337 let c1 = self.p1.colors[i];
338 let c2 = self.p2.colors[i];
339 result.push(u * c0 + v * c1 + w * c2);
340 }
341
342 result
343 }
344
345 pub fn contains_point(&self, pos: Point) -> bool {
347 self.kurbo_tri.winding(pos) != 0
348 }
349
350 pub fn bounding_box(&self) -> kurbo::Rect {
352 self.kurbo_tri.bounding_box()
353 }
354
355 fn barycentric_coords(&self, p: Point) -> (f32, f32, f32) {
356 let (a, b, c) = (self.p0.point, self.p1.point, self.p2.point);
357 let v0 = b - a;
358 let v1 = c - a;
359 let v2 = p - a;
360
361 let d00 = self.d00;
362 let d01 = self.d01;
363 let d11 = self.d11;
364 let d20 = v2.dot(v0);
365 let d21 = v2.dot(v1);
366
367 let denom = d00 * d11 - d01 * d01;
368 let v = (d11 * d20 - d01 * d21) / denom;
369 let w = (d00 * d21 - d01 * d20) / denom;
370 let u = (1.0 - v - w) as f32;
371
372 (u, v as f32, w as f32)
373 }
374}
375
376#[derive(Clone, Debug)]
378pub struct TriangleVertex {
379 flag: u32,
380 pub point: Point,
382 pub colors: ColorComponents,
384}
385
386#[derive(Clone, Debug)]
388pub struct CoonsPatch {
389 pub control_points: [Point; 12],
391 pub colors: [ColorComponents; 4],
393}
394
395#[derive(Clone, Debug)]
397pub struct TensorProductPatch {
398 pub control_points: [Point; 16],
400 pub colors: [ColorComponents; 4],
402}
403
404impl CoonsPatch {
405 pub fn map_coordinate(&self, p: Point) -> Point {
407 let (u, v) = (p.x, p.y);
408
409 let cp = &self.control_points;
410
411 let c1 = CubicBez::new(cp[0], cp[11], cp[10], cp[9]);
412 let c2 = CubicBez::new(cp[3], cp[4], cp[5], cp[6]);
413 let d1 = CubicBez::new(cp[0], cp[1], cp[2], cp[3]);
414 let d2 = CubicBez::new(cp[9], cp[8], cp[7], cp[6]);
415
416 let sc = (1.0 - v) * c1.eval(u).to_vec2() + v * c2.eval(u).to_vec2();
417 let sd = (1.0 - u) * d1.eval(v).to_vec2() + u * d2.eval(v).to_vec2();
418 let sb = (1.0 - v) * ((1.0 - u) * c1.eval(0.0).to_vec2() + u * c1.eval(1.0).to_vec2())
419 + v * ((1.0 - u) * c2.eval(0.0).to_vec2() + u * c2.eval(1.0).to_vec2());
420
421 (sc + sd - sb).to_point()
422 }
423
424 pub fn to_triangles(&self) -> Vec<Triangle> {
426 const GRID_SIZE: usize = 20;
427 let mut grid = vec![vec![Point::ZERO; GRID_SIZE]; GRID_SIZE];
428
429 for i in 0..GRID_SIZE {
431 for j in 0..GRID_SIZE {
432 let u = i as f64 / (GRID_SIZE - 1) as f64; let v = j as f64 / (GRID_SIZE - 1) as f64; let unit_point = Point::new(u, v);
437 grid[i][j] = self.map_coordinate(unit_point);
438 }
439 }
440
441 let mut triangles = vec![];
443
444 for i in 0..(GRID_SIZE - 1) {
445 for j in 0..(GRID_SIZE - 1) {
446 let p00 = grid[i][j];
447 let p10 = grid[i + 1][j];
448 let p01 = grid[i][j + 1];
449 let p11 = grid[i + 1][j + 1];
450
451 let u0 = i as f64 / (GRID_SIZE - 1) as f64;
453 let u1 = (i + 1) as f64 / (GRID_SIZE - 1) as f64;
454 let v0 = j as f64 / (GRID_SIZE - 1) as f64;
455 let v1 = (j + 1) as f64 / (GRID_SIZE - 1) as f64;
456
457 let v00 = TriangleVertex {
459 flag: 0,
460 point: p00,
461 colors: self.interpolate(Point::new(u0, v0)),
462 };
463 let v10 = TriangleVertex {
464 flag: 0,
465 point: p10,
466 colors: self.interpolate(Point::new(u1, v0)),
467 };
468 let v01 = TriangleVertex {
469 flag: 0,
470 point: p01,
471 colors: self.interpolate(Point::new(u0, v1)),
472 };
473 let v11 = TriangleVertex {
474 flag: 0,
475 point: p11,
476 colors: self.interpolate(Point::new(u1, v1)),
477 };
478
479 triangles.push(Triangle::new(v00.clone(), v10.clone(), v01.clone()));
480 triangles.push(Triangle::new(v10.clone(), v11.clone(), v01.clone()));
481 }
482 }
483
484 triangles
485 }
486
487 pub fn interpolate(&self, pos: Point) -> ColorComponents {
489 let (u, v) = (pos.x, pos.y);
490 let (c0, c1, c2, c3) = {
491 (
492 &self.colors[0],
493 &self.colors[1],
494 &self.colors[2],
495 &self.colors[3],
496 )
497 };
498
499 let mut result = SmallVec::new();
500 for i in 0..c0.len() {
501 let val = (1.0 - u) * (1.0 - v) * c0[i] as f64
502 + u * (1.0 - v) * c3[i] as f64
503 + u * v * c2[i] as f64
504 + (1.0 - u) * v * c1[i] as f64;
505 result.push(val as f32);
506 }
507
508 result
509 }
510}
511
512impl TensorProductPatch {
513 fn bernstein(i: usize, t: f64) -> f64 {
515 match i {
516 0 => (1.0 - t).powi(3),
517 1 => 3.0 * t * (1.0 - t).powi(2),
518 2 => 3.0 * t.powi(2) * (1.0 - t),
519 3 => t.powi(3),
520 _ => 0.0,
521 }
522 }
523
524 pub fn map_coordinate(&self, p: Point) -> Point {
526 let (u, v) = (p.x, p.y);
527
528 let mut x = 0.0;
529 let mut y = 0.0;
530
531 fn idx(i: usize, j: usize) -> usize {
532 match (i, j) {
533 (0, 0) => 0,
534 (0, 1) => 1,
535 (0, 2) => 2,
536 (0, 3) => 3,
537 (1, 0) => 11,
538 (1, 1) => 12,
539 (1, 2) => 13,
540 (1, 3) => 4,
541 (2, 0) => 10,
542 (2, 1) => 15,
543 (2, 2) => 14,
544 (2, 3) => 5,
545 (3, 0) => 9,
546 (3, 1) => 8,
547 (3, 2) => 7,
548 (3, 3) => 6,
549 _ => panic!("Invalid index"),
550 }
551 }
552
553 for i in 0..4 {
554 for j in 0..4 {
555 let control_point_idx = idx(i, j);
556 let basis = Self::bernstein(i, u) * Self::bernstein(j, v);
557
558 x += self.control_points[control_point_idx].x * basis;
559 y += self.control_points[control_point_idx].y * basis;
560 }
561 }
562
563 Point::new(x, y)
564 }
565
566 pub fn to_triangles(&self) -> Vec<Triangle> {
568 const GRID_SIZE: usize = 20;
569 let mut grid = vec![vec![Point::ZERO; GRID_SIZE]; GRID_SIZE];
570
571 for i in 0..GRID_SIZE {
573 for j in 0..GRID_SIZE {
574 let u = i as f64 / (GRID_SIZE - 1) as f64; let v = j as f64 / (GRID_SIZE - 1) as f64; let unit_point = Point::new(u, v);
579 grid[i][j] = self.map_coordinate(unit_point);
580 }
581 }
582
583 let mut triangles = vec![];
585
586 for i in 0..(GRID_SIZE - 1) {
587 for j in 0..(GRID_SIZE - 1) {
588 let p00 = grid[i][j];
589 let p10 = grid[i + 1][j];
590 let p01 = grid[i][j + 1];
591 let p11 = grid[i + 1][j + 1];
592
593 let u0 = i as f64 / (GRID_SIZE - 1) as f64;
595 let u1 = (i + 1) as f64 / (GRID_SIZE - 1) as f64;
596 let v0 = j as f64 / (GRID_SIZE - 1) as f64;
597 let v1 = (j + 1) as f64 / (GRID_SIZE - 1) as f64;
598
599 let v00 = TriangleVertex {
601 flag: 0,
602 point: p00,
603 colors: self.interpolate(Point::new(u0, v0)),
604 };
605 let v10 = TriangleVertex {
606 flag: 0,
607 point: p10,
608 colors: self.interpolate(Point::new(u1, v0)),
609 };
610 let v01 = TriangleVertex {
611 flag: 0,
612 point: p01,
613 colors: self.interpolate(Point::new(u0, v1)),
614 };
615 let v11 = TriangleVertex {
616 flag: 0,
617 point: p11,
618 colors: self.interpolate(Point::new(u1, v1)),
619 };
620
621 triangles.push(Triangle::new(v00.clone(), v10.clone(), v01.clone()));
622 triangles.push(Triangle::new(v10.clone(), v11.clone(), v01.clone()));
623 }
624 }
625
626 triangles
627 }
628
629 pub fn interpolate(&self, pos: Point) -> ColorComponents {
631 let (u, v) = (pos.x, pos.y);
632 let (c0, c1, c2, c3) = {
633 (
634 &self.colors[0],
635 &self.colors[1],
636 &self.colors[2],
637 &self.colors[3],
638 )
639 };
640
641 let mut result = SmallVec::new();
642 for i in 0..c0.len() {
643 let val = (1.0 - u) * (1.0 - v) * c0[i] as f64
644 + u * (1.0 - v) * c3[i] as f64
645 + u * v * c2[i] as f64
646 + (1.0 - u) * v * c1[i] as f64;
647 result.push(val as f32);
648 }
649
650 result
651 }
652}
653
654fn read_free_form_triangles(
655 data: &[u8],
656 bpf: u8,
657 bp_cord: u8,
658 bp_comp: u8,
659 has_function: bool,
660 decode: &[f32],
661) -> Option<Vec<Triangle>> {
662 let bpf = BitSize::from_u8(bpf)?;
663 let bp_cord = BitSize::from_u8(bp_cord)?;
664 let bp_comp = BitSize::from_u8(bp_comp)?;
665
666 let mut triangles = vec![];
667
668 let ([x_min, x_max, y_min, y_max], decode) =
669 decode.split_first_chunk::<4>().map(|(a, b)| (*a, b))?;
670 let num_components = decode.len() / 2;
671
672 let mut reader = BitReader::new(data);
673
674 let interpolate_coord = |n: u32, d_min: f32, d_max: f32| {
675 interpolate(
676 n as f32,
677 0.0,
678 2.0f32.powi(bp_cord.bits() as i32) - 1.0,
679 d_min,
680 d_max,
681 )
682 };
683
684 let interpolate_comp = |n: u32, d_min: f32, d_max: f32| {
685 interpolate(
686 n as f32,
687 0.0,
688 2.0f32.powi(bp_comp.bits() as i32) - 1.0,
689 d_min,
690 d_max,
691 )
692 };
693
694 let read_single = |reader: &mut BitReader| -> Option<TriangleVertex> {
695 let flag = reader.read(bpf)?;
696 let x = interpolate_coord(reader.read(bp_cord)?, x_min, x_max);
697 let y = interpolate_coord(reader.read(bp_cord)?, y_min, y_max);
698
699 let mut colors = smallvec![];
700
701 if has_function {
702 colors.push(interpolate_comp(
704 reader.read(bp_comp)?,
705 *decode.first()?,
706 *decode.get(1)?,
707 ));
708 } else {
709 for (_, decode) in (0..num_components).zip(decode.chunks_exact(2)) {
710 colors.push(interpolate_comp(
711 reader.read(bp_comp)?,
712 decode[0],
713 decode[1],
714 ));
715 }
716 }
717
718 reader.align();
719
720 let point = Point::new(x as f64, y as f64);
721
722 Some(TriangleVertex {
723 flag,
724 point,
725 colors,
726 })
727 };
728
729 let mut a = None;
730 let mut b = None;
731 let mut c = None;
732
733 loop {
734 let Some(first) = read_single(&mut reader) else {
735 break;
736 };
737
738 if first.flag == 0 {
739 let second = read_single(&mut reader)?;
740 let third = read_single(&mut reader)?;
741
742 a = Some(first.clone());
743 b = Some(second.clone());
744 c = Some(third.clone());
745 } else if first.flag == 1 {
746 a = Some(b.clone()?);
747 b = Some(c.clone()?);
748 c = Some(first);
749 } else if first.flag == 2 {
750 b = Some(c.clone()?);
751 c = Some(first);
752 }
753
754 let (p0, p1, p2) = (a.clone()?, b.clone()?, c.clone()?);
755
756 if p0.point.nearly_same(p1.point) || p1.point.nearly_same(p2.point) {
757 return None;
758 }
759
760 triangles.push(Triangle::new(a.clone()?, b.clone()?, c.clone()?));
761 }
762
763 Some(triangles)
764}
765
766fn read_lattice_triangles(
767 data: &[u8],
768 bp_cord: u8,
769 bp_comp: u8,
770 has_function: bool,
771 vertices_per_row: u32,
772 decode: &[f32],
773) -> Option<Vec<Triangle>> {
774 let bp_cord = BitSize::from_u8(bp_cord)?;
775 let bp_comp = BitSize::from_u8(bp_comp)?;
776
777 let mut lattices = vec![];
778
779 let ([x_min, x_max, y_min, y_max], decode) =
780 decode.split_first_chunk::<4>().map(|(a, b)| (*a, b))?;
781 let num_components = decode.len() / 2;
782
783 let mut reader = BitReader::new(data);
784
785 let interpolate_coord = |n: u32, d_min: f32, d_max: f32| {
786 interpolate(
787 n as f32,
788 0.0,
789 2.0f32.powi(bp_cord.bits() as i32) - 1.0,
790 d_min,
791 d_max,
792 )
793 };
794
795 let interpolate_comp = |n: u32, d_min: f32, d_max: f32| {
796 interpolate(
797 n as f32,
798 0.0,
799 2.0f32.powi(bp_comp.bits() as i32) - 1.0,
800 d_min,
801 d_max,
802 )
803 };
804
805 let read_single = |reader: &mut BitReader| -> Option<TriangleVertex> {
806 let x = interpolate_coord(reader.read(bp_cord)?, x_min, x_max);
807 let y = interpolate_coord(reader.read(bp_cord)?, y_min, y_max);
808
809 let mut colors = smallvec![];
810
811 if has_function {
812 colors.push(interpolate_comp(
814 reader.read(bp_comp)?,
815 *decode.first()?,
816 *decode.get(1)?,
817 ));
818 } else {
819 for (_, decode) in (0..num_components).zip(decode.chunks_exact(2)) {
820 colors.push(interpolate_comp(
821 reader.read(bp_comp)?,
822 decode[0],
823 decode[1],
824 ));
825 }
826 }
827
828 reader.align();
829
830 let point = Point::new(x as f64, y as f64);
831
832 Some(TriangleVertex {
833 flag: 0,
834 point,
835 colors,
836 })
837 };
838
839 'outer: loop {
840 let mut single_row = vec![];
841
842 for _ in 0..vertices_per_row {
843 let Some(next) = read_single(&mut reader) else {
844 break 'outer;
845 };
846
847 single_row.push(next);
848 }
849
850 lattices.push(single_row);
851 }
852
853 let mut triangles = vec![];
854
855 for i in 0..(lattices.len() - 1) {
856 for j in 0..(vertices_per_row as usize - 1) {
857 triangles.push(Triangle::new(
858 lattices[i][j].clone(),
859 lattices[i + 1][j].clone(),
860 lattices[i][j + 1].clone(),
861 ));
862
863 triangles.push(Triangle::new(
864 lattices[i + 1][j + 1].clone(),
865 lattices[i + 1][j].clone(),
866 lattices[i][j + 1].clone(),
867 ));
868 }
869 }
870
871 Some(triangles)
872}
873
874fn read_coons_patch_mesh(
875 data: &[u8],
876 bpf: u8,
877 bp_coord: u8,
878 bp_comp: u8,
879 has_function: bool,
880 decode: &[f32],
881) -> Option<Vec<CoonsPatch>> {
882 let bpf = BitSize::from_u8(bpf)?;
883 let bp_coord = BitSize::from_u8(bp_coord)?;
884 let bp_comp = BitSize::from_u8(bp_comp)?;
885
886 let ([x_min, x_max, y_min, y_max], decode) =
887 decode.split_first_chunk::<4>().map(|(a, b)| (*a, b))?;
888 let num_components = decode.len() / 2;
889
890 let mut reader = BitReader::new(data);
891
892 let interpolate_coord = |n: u32, d_min: f32, d_max: f32| {
893 interpolate(
894 n as f32,
895 0.0,
896 2.0f32.powi(bp_coord.bits() as i32) - 1.0,
897 d_min,
898 d_max,
899 )
900 };
901
902 let interpolate_comp = |n: u32, d_min: f32, d_max: f32| {
903 interpolate(
904 n as f32,
905 0.0,
906 2.0f32.powi(bp_comp.bits() as i32) - 1.0,
907 d_min,
908 d_max,
909 )
910 };
911
912 let read_colors = |reader: &mut BitReader| -> Option<ColorComponents> {
913 let mut colors = smallvec![];
914 if has_function {
915 colors.push(interpolate_comp(
916 reader.read(bp_comp)?,
917 *decode.first()?,
918 *decode.get(1)?,
919 ));
920 } else {
921 for (_, decode) in (0..num_components).zip(decode.chunks_exact(2)) {
922 colors.push(interpolate_comp(
923 reader.read(bp_comp)?,
924 decode[0],
925 decode[1],
926 ));
927 }
928 }
929 Some(colors)
930 };
931
932 let mut prev_patch: Option<CoonsPatch> = None;
933 let mut patches = vec![];
934
935 while let Some(flag) = reader.read(bpf) {
936 let mut control_points = [Point::ZERO; 12];
937 let mut colors = [smallvec![], smallvec![], smallvec![], smallvec![]];
938
939 match flag {
940 0 => {
941 for i in 0..12 {
942 let x = interpolate_coord(reader.read(bp_coord)?, x_min, x_max);
943 let y = interpolate_coord(reader.read(bp_coord)?, y_min, y_max);
944 control_points[i] = Point::new(x as f64, y as f64);
945 }
946
947 for i in 0..4 {
948 colors[i] = read_colors(&mut reader)?;
949 }
950
951 prev_patch = Some(CoonsPatch {
952 control_points,
953 colors: colors.clone(),
954 });
955 }
956 1 => {
957 let prev = prev_patch.as_ref()?;
958
959 control_points[0] = prev.control_points[3];
960 control_points[1] = prev.control_points[4];
961 control_points[2] = prev.control_points[5];
962 control_points[3] = prev.control_points[6];
963 colors[0] = prev.colors[1].clone();
964 colors[1] = prev.colors[2].clone();
965 for i in 4..12 {
966 let x = interpolate_coord(reader.read(bp_coord)?, x_min, x_max);
967 let y = interpolate_coord(reader.read(bp_coord)?, y_min, y_max);
968 control_points[i] = Point::new(x as f64, y as f64);
969 }
970
971 colors[2] = read_colors(&mut reader)?;
972 colors[3] = read_colors(&mut reader)?;
973
974 prev_patch = Some(CoonsPatch {
975 control_points,
976 colors: colors.clone(),
977 });
978 }
979 2 => {
980 let prev = prev_patch.as_ref()?;
981 control_points[0] = prev.control_points[6];
982 control_points[1] = prev.control_points[7];
983 control_points[2] = prev.control_points[8];
984 control_points[3] = prev.control_points[9];
985 colors[0] = prev.colors[2].clone();
986 colors[1] = prev.colors[3].clone();
987
988 for i in 4..12 {
989 let x = interpolate_coord(reader.read(bp_coord)?, x_min, x_max);
990 let y = interpolate_coord(reader.read(bp_coord)?, y_min, y_max);
991 control_points[i] = Point::new(x as f64, y as f64);
992 }
993
994 colors[2] = read_colors(&mut reader)?;
995 colors[3] = read_colors(&mut reader)?;
996
997 prev_patch = Some(CoonsPatch {
998 control_points,
999 colors: colors.clone(),
1000 });
1001 }
1002 3 => {
1003 let prev = prev_patch.as_ref()?;
1004 control_points[0] = prev.control_points[9];
1005 control_points[1] = prev.control_points[10];
1006 control_points[2] = prev.control_points[11];
1007 control_points[3] = prev.control_points[0];
1008 colors[0] = prev.colors[3].clone();
1009 colors[1] = prev.colors[0].clone();
1010
1011 for i in 4..12 {
1012 let x = interpolate_coord(reader.read(bp_coord)?, x_min, x_max);
1013 let y = interpolate_coord(reader.read(bp_coord)?, y_min, y_max);
1014 control_points[i] = Point::new(x as f64, y as f64);
1015 }
1016
1017 colors[2] = read_colors(&mut reader)?;
1018 colors[3] = read_colors(&mut reader)?;
1019
1020 prev_patch = Some(CoonsPatch {
1021 control_points,
1022 colors: colors.clone(),
1023 });
1024 }
1025 _ => break,
1026 }
1027
1028 patches.push(CoonsPatch {
1029 control_points,
1030 colors,
1031 });
1032 }
1033 Some(patches)
1034}
1035
1036fn read_tensor_product_patch_mesh(
1037 data: &[u8],
1038 bpf: u8,
1039 bp_coord: u8,
1040 bp_comp: u8,
1041 has_function: bool,
1042 decode: &[f32],
1043) -> Option<Vec<TensorProductPatch>> {
1044 let bpf = BitSize::from_u8(bpf)?;
1045 let bp_coord = BitSize::from_u8(bp_coord)?;
1046 let bp_comp = BitSize::from_u8(bp_comp)?;
1047
1048 let ([x_min, x_max, y_min, y_max], decode) =
1049 decode.split_first_chunk::<4>().map(|(a, b)| (*a, b))?;
1050 let num_components = decode.len() / 2;
1051
1052 let mut reader = BitReader::new(data);
1053
1054 let interpolate_coord = |n: u32, d_min: f32, d_max: f32| {
1055 interpolate(
1056 n as f32,
1057 0.0,
1058 2.0f32.powi(bp_coord.bits() as i32) - 1.0,
1059 d_min,
1060 d_max,
1061 )
1062 };
1063
1064 let interpolate_comp = |n: u32, d_min: f32, d_max: f32| {
1065 interpolate(
1066 n as f32,
1067 0.0,
1068 2.0f32.powi(bp_comp.bits() as i32) - 1.0,
1069 d_min,
1070 d_max,
1071 )
1072 };
1073
1074 let read_colors = |reader: &mut BitReader| -> Option<ColorComponents> {
1075 let mut colors = smallvec![];
1076 if has_function {
1077 colors.push(interpolate_comp(
1078 reader.read(bp_comp)?,
1079 *decode.first()?,
1080 *decode.get(1)?,
1081 ));
1082 } else {
1083 for (_, decode) in (0..num_components).zip(decode.chunks_exact(2)) {
1084 colors.push(interpolate_comp(
1085 reader.read(bp_comp)?,
1086 decode[0],
1087 decode[1],
1088 ));
1089 }
1090 }
1091 Some(colors)
1092 };
1093
1094 let mut prev_patch: Option<TensorProductPatch> = None;
1095 let mut patches = vec![];
1096
1097 while let Some(flag) = reader.read(bpf) {
1098 let mut control_points = [Point::ZERO; 16];
1099 let mut colors = [smallvec![], smallvec![], smallvec![], smallvec![]];
1100
1101 match flag {
1102 0 => {
1103 for i in 0..16 {
1104 let x = interpolate_coord(reader.read(bp_coord)?, x_min, x_max);
1105 let y = interpolate_coord(reader.read(bp_coord)?, y_min, y_max);
1106 control_points[i] = Point::new(x as f64, y as f64);
1107 }
1108
1109 for i in 0..4 {
1110 colors[i] = read_colors(&mut reader)?;
1111 }
1112
1113 prev_patch = Some(TensorProductPatch {
1114 control_points,
1115 colors: colors.clone(),
1116 });
1117 }
1118 1 => {
1119 let prev = prev_patch.as_ref()?;
1120
1121 control_points[0] = prev.control_points[3];
1122 control_points[1] = prev.control_points[4];
1123 control_points[2] = prev.control_points[5];
1124 control_points[3] = prev.control_points[6];
1125 colors[0] = prev.colors[1].clone();
1126 colors[1] = prev.colors[2].clone();
1127
1128 for i in 4..16 {
1129 let x = interpolate_coord(reader.read(bp_coord)?, x_min, x_max);
1130 let y = interpolate_coord(reader.read(bp_coord)?, y_min, y_max);
1131 control_points[i] = Point::new(x as f64, y as f64);
1132 }
1133
1134 colors[2] = read_colors(&mut reader)?;
1135 colors[3] = read_colors(&mut reader)?;
1136
1137 prev_patch = Some(TensorProductPatch {
1138 control_points,
1139 colors: colors.clone(),
1140 });
1141 }
1142 2 => {
1143 let prev = prev_patch.as_ref()?;
1144
1145 control_points[0] = prev.control_points[6];
1146 control_points[1] = prev.control_points[7];
1147 control_points[2] = prev.control_points[8];
1148 control_points[3] = prev.control_points[9];
1149 colors[0] = prev.colors[2].clone();
1150 colors[1] = prev.colors[3].clone();
1151
1152 for i in 4..16 {
1153 let x = interpolate_coord(reader.read(bp_coord)?, x_min, x_max);
1154 let y = interpolate_coord(reader.read(bp_coord)?, y_min, y_max);
1155 control_points[i] = Point::new(x as f64, y as f64);
1156 }
1157
1158 colors[2] = read_colors(&mut reader)?;
1159 colors[3] = read_colors(&mut reader)?;
1160
1161 prev_patch = Some(TensorProductPatch {
1162 control_points,
1163 colors: colors.clone(),
1164 });
1165 }
1166 3 => {
1167 let prev = prev_patch.as_ref()?;
1168
1169 control_points[0] = prev.control_points[9];
1170 control_points[1] = prev.control_points[10];
1171 control_points[2] = prev.control_points[11];
1172 control_points[3] = prev.control_points[0];
1173 colors[0] = prev.colors[3].clone();
1174 colors[1] = prev.colors[0].clone();
1175
1176 for i in 4..16 {
1177 let x = interpolate_coord(reader.read(bp_coord)?, x_min, x_max);
1178 let y = interpolate_coord(reader.read(bp_coord)?, y_min, y_max);
1179 control_points[i] = Point::new(x as f64, y as f64);
1180 }
1181
1182 colors[2] = read_colors(&mut reader)?;
1183 colors[3] = read_colors(&mut reader)?;
1184
1185 prev_patch = Some(TensorProductPatch {
1186 control_points,
1187 colors: colors.clone(),
1188 });
1189 }
1190 _ => break,
1191 }
1192
1193 patches.push(TensorProductPatch {
1194 control_points,
1195 colors,
1196 });
1197 }
1198 Some(patches)
1199}
1200
1201fn read_function(dict: &Dict, color_space: &ColorSpace) -> Option<ShadingFunction> {
1202 if let Some(arr) = dict.get::<Array>(FUNCTION) {
1203 let arr: Option<SmallVec<_>> = arr.iter::<Object>().map(|o| Function::new(&o)).collect();
1204 let arr = arr?;
1205
1206 if arr.len() != color_space.num_components() as usize {
1207 warn!("function array of shading has wrong size");
1208
1209 return None;
1210 }
1211
1212 Some(ShadingFunction::Multiple(arr))
1213 } else if let Some(obj) = dict.get::<Object>(FUNCTION) {
1214 Some(ShadingFunction::Single(Function::new(&obj)?))
1215 } else {
1216 None
1217 }
1218}