1use crate::display_list::DisplayList;
8use crate::object::PsObject;
9use std::sync::Arc;
10
11pub use stet_fonts::geometry::{Matrix, PathSegment, PsPath, round10};
14pub use stet_graphics::color::{
15 CieAParams, CieAbcParams, CieDefParams, CieDefgParams, DashPattern, DeviceColor, FillRule,
16 LineCap, LineJoin,
17};
18
19#[derive(Clone, Debug)]
23pub enum ColorSpace {
24 DeviceGray,
25 DeviceRGB,
26 DeviceCMYK,
27 Indexed {
31 base: Box<ColorSpace>,
32 hival: u32,
33 lookup: Vec<u8>,
34 lookup_proc: Option<PsObject>,
35 },
36 CIEBasedABC {
38 params: Arc<CieAbcParams>,
39 dict_entity: crate::object::EntityId,
40 },
41 CIEBasedA {
43 params: Arc<CieAParams>,
44 dict_entity: crate::object::EntityId,
45 },
46 CIEBasedDEF {
48 params: Arc<CieDefParams>,
49 dict_entity: crate::object::EntityId,
50 },
51 CIEBasedDEFG {
53 params: Arc<CieDefgParams>,
54 dict_entity: crate::object::EntityId,
55 },
56 ICCBased {
60 dict_entity: crate::object::EntityId,
61 n: u32,
62 profile_hash: Option<crate::icc::ProfileHash>,
63 },
64 Separation {
67 name: Vec<u8>,
68 alt_space: Box<ColorSpace>,
69 tint_transform: crate::object::PsObject,
70 num_alt_components: u32,
71 },
72 DeviceN {
75 names: Vec<Vec<u8>>,
76 num_colorants: u32,
77 alt_space: Box<ColorSpace>,
78 tint_transform: crate::object::PsObject,
79 num_alt_components: u32,
80 },
81}
82
83impl PartialEq for ColorSpace {
84 fn eq(&self, other: &Self) -> bool {
85 use ColorSpace::*;
86 match (self, other) {
87 (DeviceGray, DeviceGray) | (DeviceRGB, DeviceRGB) | (DeviceCMYK, DeviceCMYK) => true,
88 (
89 Indexed {
90 base: b1,
91 hival: h1,
92 lookup: l1,
93 ..
94 },
95 Indexed {
96 base: b2,
97 hival: h2,
98 lookup: l2,
99 ..
100 },
101 ) => b1 == b2 && h1 == h2 && l1 == l2,
102 (
103 CIEBasedABC {
104 dict_entity: d1, ..
105 },
106 CIEBasedABC {
107 dict_entity: d2, ..
108 },
109 ) => d1 == d2,
110 (
111 CIEBasedA {
112 dict_entity: d1, ..
113 },
114 CIEBasedA {
115 dict_entity: d2, ..
116 },
117 ) => d1 == d2,
118 (
119 CIEBasedDEF {
120 dict_entity: d1, ..
121 },
122 CIEBasedDEF {
123 dict_entity: d2, ..
124 },
125 ) => d1 == d2,
126 (
127 CIEBasedDEFG {
128 dict_entity: d1, ..
129 },
130 CIEBasedDEFG {
131 dict_entity: d2, ..
132 },
133 ) => d1 == d2,
134 (
135 ICCBased {
136 dict_entity: d1,
137 n: n1,
138 ..
139 },
140 ICCBased {
141 dict_entity: d2,
142 n: n2,
143 ..
144 },
145 ) => d1 == d2 && n1 == n2,
146 (
147 Separation {
148 name: name1,
149 alt_space: a1,
150 tint_transform: t1,
151 num_alt_components: n1,
152 },
153 Separation {
154 name: name2,
155 alt_space: a2,
156 tint_transform: t2,
157 num_alt_components: n2,
158 },
159 ) => name1 == name2 && a1 == a2 && t1 == t2 && n1 == n2,
160 (
161 DeviceN {
162 names: names1,
163 num_colorants: nc1,
164 alt_space: a1,
165 tint_transform: t1,
166 num_alt_components: n1,
167 },
168 DeviceN {
169 names: names2,
170 num_colorants: nc2,
171 alt_space: a2,
172 tint_transform: t2,
173 num_alt_components: n2,
174 },
175 ) => names1 == names2 && nc1 == nc2 && a1 == a2 && t1 == t2 && n1 == n2,
176 _ => false,
177 }
178 }
179}
180
181#[derive(Clone)]
183pub struct PatternData {
184 pub pattern_type: i32,
186 pub paint_type: i32,
188 pub tiling_type: i32,
190 pub bbox: [f64; 4],
192 pub xstep: f64,
194 pub ystep: f64,
196 pub pattern_matrix: Matrix,
198 pub cached_display_list: DisplayList,
200}
201
202#[derive(Clone, Debug)]
205pub struct GstateEntry {
206 pub state: GraphicsState,
207 pub saved_by_save: bool,
210}
211
212#[derive(Clone, Debug)]
214pub struct GraphicsState {
215 pub ctm: Matrix,
216 pub color: DeviceColor,
217 pub color_space: ColorSpace,
218 pub path: PsPath,
219 pub current_point: Option<(f64, f64)>,
220 pub clip_path: Option<PsPath>,
221 pub clip_path_version: u32,
222 pub line_width: f64,
223 pub line_cap: LineCap,
224 pub line_join: LineJoin,
225 pub miter_limit: f64,
226 pub dash_pattern: DashPattern,
227 pub flatness: f64,
228 pub stroke_adjust: bool,
229 pub overprint: bool,
230 pub smoothness: f64,
231 pub default_ctm: Matrix,
232
233 pub clip_stack: Vec<Option<PsPath>>,
235
236 pub current_font: Option<crate::object::PsObject>,
238
239 pub root_font: Option<crate::object::PsObject>,
242
243 pub page_device: Option<crate::object::EntityId>,
245
246 pub screen_freq: f64,
248 pub screen_angle: f64,
249 pub screen_proc: Option<crate::object::PsObject>,
250 pub color_screen: Option<[(f64, f64, crate::object::PsObject); 4]>,
252 pub halftone: Option<crate::object::PsObject>,
254
255 pub transfer_function: Option<crate::object::PsObject>,
257 pub color_transfer: Option<[crate::object::PsObject; 4]>,
259 pub sampled_transfer: Option<Arc<Vec<f64>>>,
261 pub sampled_color_transfer: Option<[Option<Arc<Vec<f64>>>; 4]>,
263 pub precomputed_halftone: Option<Arc<crate::device::HalftoneScreen>>,
265 pub precomputed_color_halftone: Option<[Option<Arc<crate::device::HalftoneScreen>>; 4]>,
267
268 pub black_generation: Option<crate::object::PsObject>,
270 pub undercolor_removal: Option<crate::object::PsObject>,
271 pub sampled_black_generation: Option<Arc<Vec<f64>>>,
273 pub sampled_ucr: Option<Arc<Vec<f64>>>,
275
276 pub color_rendering: Option<crate::object::PsObject>,
278
279 pub rendering_intent: u8,
282
283 pub current_pattern: Option<u32>,
286 pub pattern_underlying_color: Option<DeviceColor>,
288
289 pub bbox: Option<[f64; 4]>,
291
292 pub tint_values: Option<Vec<f64>>,
295
296 pub cached_tint_table: Option<Arc<crate::device::TintLookupTable>>,
299}
300
301impl GraphicsState {
302 pub fn new() -> Self {
304 Self {
305 ctm: Matrix::identity(),
306 color: DeviceColor::black(),
307 color_space: ColorSpace::DeviceGray,
308 path: PsPath::new(),
309 current_point: None,
310 clip_path: None,
311 clip_path_version: 0,
312 line_width: 1.0,
313 line_cap: LineCap::Butt,
314 line_join: LineJoin::Miter,
315 miter_limit: 10.0,
316 dash_pattern: DashPattern::solid(),
317 flatness: 1.0,
318 stroke_adjust: false,
319 overprint: false,
320 smoothness: 1.0,
321 default_ctm: Matrix::identity(),
322 clip_stack: Vec::new(),
323 current_font: None,
324 root_font: None,
325 page_device: None,
326 screen_freq: 60.0,
327 screen_angle: 45.0,
328 screen_proc: None,
329 color_screen: None,
330 halftone: None,
331 transfer_function: None,
332 color_transfer: None,
333 sampled_transfer: None,
334 sampled_color_transfer: None,
335 precomputed_halftone: None,
336 precomputed_color_halftone: None,
337 black_generation: None,
338 undercolor_removal: None,
339 sampled_black_generation: None,
340 sampled_ucr: None,
341 color_rendering: None,
342 rendering_intent: 0, current_pattern: None,
344 pattern_underlying_color: None,
345 bbox: None,
346 tint_values: None,
347 cached_tint_table: None,
348 }
349 }
350}
351
352impl Default for GraphicsState {
353 fn default() -> Self {
354 Self::new()
355 }
356}
357
358#[cfg(test)]
359mod tests {
360 use super::*;
361
362 #[test]
363 fn test_default_graphics_state() {
364 let gs = GraphicsState::new();
365 assert_eq!(gs.line_width, 1.0);
366 assert_eq!(gs.line_cap, LineCap::Butt);
367 assert_eq!(gs.line_join, LineJoin::Miter);
368 assert_eq!(gs.miter_limit, 10.0);
369 assert!(gs.path.is_empty());
370 assert!(gs.current_point.is_none());
371 assert!(gs.clip_path.is_none());
372 assert_eq!(gs.flatness, 1.0);
373 assert!(!gs.stroke_adjust);
374 }
375}