1use read_fonts::{
4 tables::{
5 colr::*,
6 variations::{
7 DeltaSetIndex, DeltaSetIndexMap, FloatItemDelta, FloatItemDeltaTarget,
8 ItemVariationStore,
9 },
10 },
11 types::{BoundingBox, F2Dot14, GlyphId16, Point},
12 ReadError,
13};
14
15use core::ops::{Deref, Range};
16
17pub type PaintId = usize;
19
20#[derive(Clone)]
25pub struct ColrInstance<'a> {
26 colr: Colr<'a>,
27 index_map: Option<DeltaSetIndexMap<'a>>,
28 var_store: Option<ItemVariationStore<'a>>,
29 coords: &'a [F2Dot14],
30}
31
32impl<'a> ColrInstance<'a> {
33 pub fn new(colr: Colr<'a>, coords: &'a [F2Dot14]) -> Self {
36 let index_map = colr.var_index_map().and_then(|res| res.ok());
37 let var_store = colr.item_variation_store().and_then(|res| res.ok());
38 Self {
39 colr,
40 coords,
41 index_map,
42 var_store,
43 }
44 }
45
46 fn var_deltas<const N: usize>(&self, var_index_base: u32) -> [FloatItemDelta; N] {
49 const NO_VARIATION_DELTAS: u32 = 0xFFFFFFFF;
51 let mut deltas = [FloatItemDelta::ZERO; N];
56 if self.coords.is_empty()
57 || self.var_store.is_none()
58 || var_index_base == NO_VARIATION_DELTAS
59 {
60 return deltas;
61 }
62 let var_store = self.var_store.as_ref().unwrap();
63 if let Some(index_map) = self.index_map.as_ref() {
64 for (i, delta) in deltas.iter_mut().enumerate() {
65 let var_index = var_index_base + i as u32;
66 if let Ok(delta_ix) = index_map.get(var_index) {
67 *delta = var_store
68 .compute_float_delta(delta_ix, self.coords)
69 .unwrap_or_default();
70 }
71 }
72 } else {
73 for (i, delta) in deltas.iter_mut().enumerate() {
74 let var_index = var_index_base + i as u32;
75 let delta_ix = DeltaSetIndex {
78 outer: 0,
79 inner: var_index as u16,
80 };
81 *delta = var_store
82 .compute_float_delta(delta_ix, self.coords)
83 .unwrap_or_default();
84 }
85 }
86 deltas
87 }
88}
89
90impl<'a> Deref for ColrInstance<'a> {
91 type Target = Colr<'a>;
92
93 fn deref(&self) -> &Self::Target {
94 &self.colr
95 }
96}
97
98pub fn resolve_clip_box(instance: &ColrInstance, clip_box: &ClipBox) -> BoundingBox<f32> {
101 match clip_box {
102 ClipBox::Format1(cbox) => BoundingBox {
103 x_min: cbox.x_min().to_i16() as f32,
104 y_min: cbox.y_min().to_i16() as f32,
105 x_max: cbox.x_max().to_i16() as f32,
106 y_max: cbox.y_max().to_i16() as f32,
107 },
108 ClipBox::Format2(cbox) => {
109 let deltas = instance.var_deltas::<4>(cbox.var_index_base());
110 BoundingBox {
111 x_min: cbox.x_min().apply_float_delta(deltas[0]),
112 y_min: cbox.y_min().apply_float_delta(deltas[1]),
113 x_max: cbox.x_max().apply_float_delta(deltas[2]),
114 y_max: cbox.y_max().apply_float_delta(deltas[3]),
115 }
116 }
117 }
118}
119
120#[derive(Clone, Debug)]
123pub struct ResolvedColorStop {
124 pub offset: f32,
125 pub palette_index: u16,
126 pub alpha: f32,
127}
128
129#[derive(Clone)]
135pub struct ColorStops<'a> {
136 stops: &'a [ColorStop],
137 var_stops: &'a [VarColorStop],
138}
139
140impl ColorStops<'_> {
141 pub fn len(&self) -> usize {
142 self.stops.len() + self.var_stops.len()
143 }
144
145 pub fn is_empty(&self) -> bool {
146 self.stops.is_empty() && self.var_stops.is_empty()
147 }
148}
149
150impl<'a> From<ColorLine<'a>> for ColorStops<'a> {
151 fn from(value: ColorLine<'a>) -> Self {
152 Self {
153 stops: value.color_stops(),
154 var_stops: &[],
155 }
156 }
157}
158
159impl<'a> From<VarColorLine<'a>> for ColorStops<'a> {
160 fn from(value: VarColorLine<'a>) -> Self {
161 Self {
162 stops: &[],
163 var_stops: value.color_stops(),
164 }
165 }
166}
167
168impl<'a> ColorStops<'a> {
169 pub fn resolve(
172 &self,
173 instance: &'a ColrInstance<'a>,
174 ) -> impl Iterator<Item = ResolvedColorStop> + 'a {
175 self.stops
176 .iter()
177 .map(|stop| ResolvedColorStop {
178 offset: stop.stop_offset().to_f32(),
179 palette_index: stop.palette_index(),
180 alpha: stop.alpha().to_f32(),
181 })
182 .chain(self.var_stops.iter().map(|stop| {
183 let deltas = instance.var_deltas::<2>(stop.var_index_base());
184 ResolvedColorStop {
185 offset: stop.stop_offset().apply_float_delta(deltas[0]),
186 palette_index: stop.palette_index(),
187 alpha: stop.alpha().apply_float_delta(deltas[1]),
188 }
189 }))
190 }
191}
192
193pub enum ResolvedPaint<'a> {
201 ColrLayers {
202 range: Range<usize>,
203 },
204 Solid {
205 palette_index: u16,
206 alpha: f32,
207 },
208 LinearGradient {
209 x0: f32,
210 y0: f32,
211 x1: f32,
212 y1: f32,
213 x2: f32,
214 y2: f32,
215 color_stops: ColorStops<'a>,
216 extend: Extend,
217 },
218 RadialGradient {
219 x0: f32,
220 y0: f32,
221 radius0: f32,
222 x1: f32,
223 y1: f32,
224 radius1: f32,
225 color_stops: ColorStops<'a>,
226 extend: Extend,
227 },
228 SweepGradient {
229 center_x: f32,
230 center_y: f32,
231 start_angle: f32,
232 end_angle: f32,
233 color_stops: ColorStops<'a>,
234 extend: Extend,
235 },
236 Glyph {
237 glyph_id: GlyphId16,
238 paint: Paint<'a>,
239 },
240 ColrGlyph {
241 glyph_id: GlyphId16,
242 },
243 Transform {
244 xx: f32,
245 yx: f32,
246 xy: f32,
247 yy: f32,
248 dx: f32,
249 dy: f32,
250 paint: Paint<'a>,
251 },
252 Translate {
253 dx: f32,
254 dy: f32,
255 paint: Paint<'a>,
256 },
257 Scale {
258 scale_x: f32,
259 scale_y: f32,
260 around_center: Option<Point<f32>>,
261 paint: Paint<'a>,
262 },
263 Rotate {
264 angle: f32,
265 around_center: Option<Point<f32>>,
266 paint: Paint<'a>,
267 },
268 Skew {
269 x_skew_angle: f32,
270 y_skew_angle: f32,
271 around_center: Option<Point<f32>>,
272 paint: Paint<'a>,
273 },
274 Composite {
275 source_paint: Paint<'a>,
276 mode: CompositeMode,
277 backdrop_paint: Paint<'a>,
278 },
279}
280
281pub fn resolve_paint<'a>(
292 instance: &ColrInstance<'a>,
293 paint: &Paint<'a>,
294) -> Result<ResolvedPaint<'a>, ReadError> {
295 Ok(match paint {
296 Paint::ColrLayers(layers) => {
297 let start = layers.first_layer_index() as usize;
298 ResolvedPaint::ColrLayers {
299 range: start..start + layers.num_layers() as usize,
300 }
301 }
302 Paint::Solid(solid) => ResolvedPaint::Solid {
303 palette_index: solid.palette_index(),
304 alpha: solid.alpha().to_f32(),
305 },
306 Paint::VarSolid(solid) => {
307 let deltas = instance.var_deltas::<1>(solid.var_index_base());
308 ResolvedPaint::Solid {
309 palette_index: solid.palette_index(),
310 alpha: solid.alpha().apply_float_delta(deltas[0]),
311 }
312 }
313 Paint::LinearGradient(gradient) => {
314 let color_line = gradient.color_line()?;
315 let extend = color_line.extend();
316 ResolvedPaint::LinearGradient {
317 x0: gradient.x0().to_i16() as f32,
318 y0: gradient.y0().to_i16() as f32,
319 x1: gradient.x1().to_i16() as f32,
320 y1: gradient.y1().to_i16() as f32,
321 x2: gradient.x2().to_i16() as f32,
322 y2: gradient.y2().to_i16() as f32,
323 color_stops: color_line.into(),
324 extend,
325 }
326 }
327 Paint::VarLinearGradient(gradient) => {
328 let color_line = gradient.color_line()?;
329 let extend = color_line.extend();
330 let deltas = instance.var_deltas::<6>(gradient.var_index_base());
331 ResolvedPaint::LinearGradient {
332 x0: gradient.x0().apply_float_delta(deltas[0]),
333 y0: gradient.y0().apply_float_delta(deltas[1]),
334 x1: gradient.x1().apply_float_delta(deltas[2]),
335 y1: gradient.y1().apply_float_delta(deltas[3]),
336 x2: gradient.x2().apply_float_delta(deltas[4]),
337 y2: gradient.y2().apply_float_delta(deltas[5]),
338 color_stops: color_line.into(),
339 extend,
340 }
341 }
342 Paint::RadialGradient(gradient) => {
343 let color_line = gradient.color_line()?;
344 let extend = color_line.extend();
345 ResolvedPaint::RadialGradient {
346 x0: gradient.x0().to_i16() as f32,
347 y0: gradient.y0().to_i16() as f32,
348 radius0: gradient.radius0().to_u16() as f32,
349 x1: gradient.x1().to_i16() as f32,
350 y1: gradient.y1().to_i16() as f32,
351 radius1: gradient.radius1().to_u16() as f32,
352 color_stops: color_line.into(),
353 extend,
354 }
355 }
356 Paint::VarRadialGradient(gradient) => {
357 let color_line = gradient.color_line()?;
358 let extend = color_line.extend();
359 let deltas = instance.var_deltas::<6>(gradient.var_index_base());
360 ResolvedPaint::RadialGradient {
361 x0: gradient.x0().apply_float_delta(deltas[0]),
362 y0: gradient.y0().apply_float_delta(deltas[1]),
363 radius0: gradient.radius0().apply_float_delta(deltas[2]),
364 x1: gradient.x1().apply_float_delta(deltas[3]),
365 y1: gradient.y1().apply_float_delta(deltas[4]),
366 radius1: gradient.radius1().apply_float_delta(deltas[5]),
367 color_stops: color_line.into(),
368 extend,
369 }
370 }
371 Paint::SweepGradient(gradient) => {
372 let color_line = gradient.color_line()?;
373 let extend = color_line.extend();
374 ResolvedPaint::SweepGradient {
375 center_x: gradient.center_x().to_i16() as f32,
376 center_y: gradient.center_y().to_i16() as f32,
377 start_angle: gradient.start_angle().to_f32(),
378 end_angle: gradient.end_angle().to_f32(),
379 color_stops: color_line.into(),
380 extend,
381 }
382 }
383 Paint::VarSweepGradient(gradient) => {
384 let color_line = gradient.color_line()?;
385 let extend = color_line.extend();
386 let deltas = instance.var_deltas::<4>(gradient.var_index_base());
387 ResolvedPaint::SweepGradient {
388 center_x: gradient.center_x().apply_float_delta(deltas[0]),
389 center_y: gradient.center_y().apply_float_delta(deltas[1]),
390 start_angle: gradient.start_angle().apply_float_delta(deltas[2]),
391 end_angle: gradient.end_angle().apply_float_delta(deltas[3]),
392 color_stops: color_line.into(),
393 extend,
394 }
395 }
396 Paint::Glyph(glyph) => ResolvedPaint::Glyph {
397 glyph_id: glyph.glyph_id(),
398 paint: glyph.paint()?,
399 },
400 Paint::ColrGlyph(glyph) => ResolvedPaint::ColrGlyph {
401 glyph_id: glyph.glyph_id(),
402 },
403 Paint::Transform(transform) => {
404 let affine = transform.transform()?;
405 let paint = transform.paint()?;
406 ResolvedPaint::Transform {
407 xx: affine.xx().to_f32(),
408 yx: affine.yx().to_f32(),
409 xy: affine.xy().to_f32(),
410 yy: affine.yy().to_f32(),
411 dx: affine.dx().to_f32(),
412 dy: affine.dy().to_f32(),
413 paint,
414 }
415 }
416 Paint::VarTransform(transform) => {
417 let affine = transform.transform()?;
418 let paint = transform.paint()?;
419 let deltas = instance.var_deltas::<6>(affine.var_index_base());
420 ResolvedPaint::Transform {
421 xx: affine.xx().apply_float_delta(deltas[0]),
422 yx: affine.yx().apply_float_delta(deltas[1]),
423 xy: affine.xy().apply_float_delta(deltas[2]),
424 yy: affine.yy().apply_float_delta(deltas[3]),
425 dx: affine.dx().apply_float_delta(deltas[4]),
426 dy: affine.dy().apply_float_delta(deltas[5]),
427 paint,
428 }
429 }
430 Paint::Translate(transform) => ResolvedPaint::Translate {
431 dx: transform.dx().to_i16() as f32,
432 dy: transform.dy().to_i16() as f32,
433 paint: transform.paint()?,
434 },
435 Paint::VarTranslate(transform) => {
436 let deltas = instance.var_deltas::<2>(transform.var_index_base());
437 ResolvedPaint::Translate {
438 dx: transform.dx().apply_float_delta(deltas[0]),
439 dy: transform.dy().apply_float_delta(deltas[1]),
440 paint: transform.paint()?,
441 }
442 }
443 Paint::Scale(transform) => ResolvedPaint::Scale {
444 scale_x: transform.scale_x().to_f32(),
445 scale_y: transform.scale_y().to_f32(),
446 around_center: None,
447 paint: transform.paint()?,
448 },
449 Paint::VarScale(transform) => {
450 let deltas = instance.var_deltas::<2>(transform.var_index_base());
451 ResolvedPaint::Scale {
452 scale_x: transform.scale_x().apply_float_delta(deltas[0]),
453 scale_y: transform.scale_y().apply_float_delta(deltas[1]),
454 around_center: None,
455 paint: transform.paint()?,
456 }
457 }
458 Paint::ScaleAroundCenter(transform) => ResolvedPaint::Scale {
459 scale_x: transform.scale_x().to_f32(),
460 scale_y: transform.scale_y().to_f32(),
461 around_center: Some(Point::new(
462 transform.center_x().to_i16() as f32,
463 transform.center_y().to_i16() as f32,
464 )),
465 paint: transform.paint()?,
466 },
467 Paint::VarScaleAroundCenter(transform) => {
468 let deltas = instance.var_deltas::<4>(transform.var_index_base());
469 ResolvedPaint::Scale {
470 scale_x: transform.scale_x().apply_float_delta(deltas[0]),
471 scale_y: transform.scale_y().apply_float_delta(deltas[1]),
472 around_center: Some(Point::new(
473 transform.center_x().apply_float_delta(deltas[2]),
474 transform.center_y().apply_float_delta(deltas[3]),
475 )),
476 paint: transform.paint()?,
477 }
478 }
479 Paint::ScaleUniform(transform) => {
480 let scale = transform.scale().to_f32();
481 ResolvedPaint::Scale {
482 scale_x: scale,
483 scale_y: scale,
484 around_center: None,
485 paint: transform.paint()?,
486 }
487 }
488 Paint::VarScaleUniform(transform) => {
489 let deltas = instance.var_deltas::<1>(transform.var_index_base());
490 let scale = transform.scale().apply_float_delta(deltas[0]);
491 ResolvedPaint::Scale {
492 scale_x: scale,
493 scale_y: scale,
494 around_center: None,
495 paint: transform.paint()?,
496 }
497 }
498 Paint::ScaleUniformAroundCenter(transform) => {
499 let scale = transform.scale().to_f32();
500 ResolvedPaint::Scale {
501 scale_x: scale,
502 scale_y: scale,
503 around_center: Some(Point::new(
504 transform.center_x().to_i16() as f32,
505 transform.center_y().to_i16() as f32,
506 )),
507 paint: transform.paint()?,
508 }
509 }
510 Paint::VarScaleUniformAroundCenter(transform) => {
511 let deltas = instance.var_deltas::<3>(transform.var_index_base());
512 let scale = transform.scale().apply_float_delta(deltas[0]);
513 ResolvedPaint::Scale {
514 scale_x: scale,
515 scale_y: scale,
516 around_center: Some(Point::new(
517 transform.center_x().apply_float_delta(deltas[1]),
518 transform.center_y().apply_float_delta(deltas[2]),
519 )),
520 paint: transform.paint()?,
521 }
522 }
523 Paint::Rotate(transform) => ResolvedPaint::Rotate {
524 angle: transform.angle().to_f32(),
525 around_center: None,
526 paint: transform.paint()?,
527 },
528 Paint::VarRotate(transform) => {
529 let deltas = instance.var_deltas::<1>(transform.var_index_base());
530 ResolvedPaint::Rotate {
531 angle: transform.angle().apply_float_delta(deltas[0]),
532 around_center: None,
533 paint: transform.paint()?,
534 }
535 }
536 Paint::RotateAroundCenter(transform) => ResolvedPaint::Rotate {
537 angle: transform.angle().to_f32(),
538 around_center: Some(Point::new(
539 transform.center_x().to_i16() as f32,
540 transform.center_y().to_i16() as f32,
541 )),
542 paint: transform.paint()?,
543 },
544 Paint::VarRotateAroundCenter(transform) => {
545 let deltas = instance.var_deltas::<3>(transform.var_index_base());
546 ResolvedPaint::Rotate {
547 angle: transform.angle().apply_float_delta(deltas[0]),
548 around_center: Some(Point::new(
549 transform.center_x().apply_float_delta(deltas[1]),
550 transform.center_y().apply_float_delta(deltas[2]),
551 )),
552 paint: transform.paint()?,
553 }
554 }
555 Paint::Skew(transform) => ResolvedPaint::Skew {
556 x_skew_angle: transform.x_skew_angle().to_f32(),
557 y_skew_angle: transform.y_skew_angle().to_f32(),
558 around_center: None,
559 paint: transform.paint()?,
560 },
561 Paint::VarSkew(transform) => {
562 let deltas = instance.var_deltas::<2>(transform.var_index_base());
563 ResolvedPaint::Skew {
564 x_skew_angle: transform.x_skew_angle().apply_float_delta(deltas[0]),
565 y_skew_angle: transform.y_skew_angle().apply_float_delta(deltas[1]),
566 around_center: None,
567 paint: transform.paint()?,
568 }
569 }
570 Paint::SkewAroundCenter(transform) => ResolvedPaint::Skew {
571 x_skew_angle: transform.x_skew_angle().to_f32(),
572 y_skew_angle: transform.y_skew_angle().to_f32(),
573 around_center: Some(Point::new(
574 transform.center_x().to_i16() as f32,
575 transform.center_y().to_i16() as f32,
576 )),
577 paint: transform.paint()?,
578 },
579 Paint::VarSkewAroundCenter(transform) => {
580 let deltas = instance.var_deltas::<4>(transform.var_index_base());
581 ResolvedPaint::Skew {
582 x_skew_angle: transform.x_skew_angle().apply_float_delta(deltas[0]),
583 y_skew_angle: transform.y_skew_angle().apply_float_delta(deltas[1]),
584 around_center: Some(Point::new(
585 transform.center_x().apply_float_delta(deltas[2]),
586 transform.center_y().apply_float_delta(deltas[3]),
587 )),
588 paint: transform.paint()?,
589 }
590 }
591 Paint::Composite(composite) => ResolvedPaint::Composite {
592 source_paint: composite.source_paint()?,
593 mode: composite.composite_mode(),
594 backdrop_paint: composite.backdrop_paint()?,
595 },
596 })
597}