hayro_interpret/
soft_mask.rs1use crate::cache::Cache;
2use crate::context::Context;
3use crate::device::Device;
4use crate::interpret::state::State;
5use crate::util::hash128;
6use crate::x_object::{XObject, draw_xobject};
7use crate::{CacheKey, InterpreterSettings};
8use hayro_syntax::object::Dict;
9use hayro_syntax::object::Name;
10use hayro_syntax::object::ObjectIdentifier;
11use hayro_syntax::object::Stream;
12use hayro_syntax::object::dict::keys::*;
13use hayro_syntax::page::Resources;
14use hayro_syntax::xref::XRef;
15use kurbo::Affine;
16use std::fmt::Debug;
17use std::hash::{Hash, Hasher};
18use std::ops::Deref;
19use std::sync::Arc;
20
21#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub enum MaskType {
24 Luminosity,
26 Alpha,
28}
29
30struct Repr<'a> {
31 obj_id: ObjectIdentifier,
32 group: XObject<'a>,
33 mask_type: MaskType,
34 parent_resources: Resources<'a>,
35 root_transform: Affine,
36 bbox: kurbo::Rect,
37 object_cache: Cache,
38 settings: InterpreterSettings,
39 xref: &'a XRef,
40}
41
42#[derive(Clone)]
44pub struct SoftMask<'a>(Arc<Repr<'a>>);
45
46impl Debug for SoftMask<'_> {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 write!(f, "SoftMask({:?})", self.0.obj_id)
49 }
50}
51
52impl Hash for SoftMask<'_> {
53 fn hash<H: Hasher>(&self, state: &mut H) {
54 self.0.obj_id.hash(state);
56 }
57}
58
59impl PartialEq for SoftMask<'_> {
60 fn eq(&self, other: &Self) -> bool {
61 self.0.obj_id == other.0.obj_id
62 }
63}
64
65impl Eq for SoftMask<'_> {}
66
67impl CacheKey for SoftMask<'_> {
68 fn cache_key(&self) -> u128 {
69 hash128(self)
70 }
71}
72
73impl<'a> SoftMask<'a> {
74 pub(crate) fn new(
75 dict: &Dict<'a>,
76 context: &Context<'a>,
77 parent_resources: Resources<'a>,
78 ) -> Option<SoftMask<'a>> {
79 let obj_id = dict.get_ref(G)?.into();
82 let group_stream = dict.get::<Stream>(G)?;
83 let group = XObject::new(
84 &group_stream,
85 &context.settings.warning_sink,
86 &context.object_cache,
87 )?;
88 let mask_type = match dict.get::<Name>(S)?.deref() {
89 LUMINOSITY => MaskType::Luminosity,
90 ALPHA => MaskType::Alpha,
91 _ => return None,
92 };
93
94 Some(Self(Arc::new(Repr {
95 obj_id,
96 group,
97 mask_type,
98 root_transform: context.get().ctm,
99 bbox: context.bbox(),
100 object_cache: context.object_cache.clone(),
101 settings: context.settings.clone(),
102 xref: context.xref,
103 parent_resources,
104 })))
105 }
106
107 pub fn interpret(&self, device: &mut impl Device<'a>) {
109 let state = State::new(self.0.root_transform);
110 let mut ctx = Context::new_with(
111 self.0.root_transform,
112 self.0.bbox,
113 self.0.object_cache.clone(),
114 self.0.xref,
115 self.0.settings.clone(),
116 state,
117 );
118 draw_xobject(&self.0.group, &self.0.parent_resources, &mut ctx, device);
119 }
120
121 pub fn id(&self) -> ObjectIdentifier {
125 self.0.obj_id
126 }
127
128 pub fn mask_type(&self) -> MaskType {
130 self.0.mask_type
131 }
132}