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