1use crate::{
4 model::pen::OutlinePen,
5 ps::{
6 cff::{blend::BlendState, charset::Charset, index::Index, stack::Stack},
7 error::Error,
8 num,
9 string::Sid,
10 transform::{FontMatrix, Transform},
11 },
12 tables::cff::Cff,
13 types::{Fixed, Point},
14 Cursor, FontData, FontRead,
15};
16
17pub const NESTING_DEPTH_LIMIT: u32 = 10;
22
23#[derive(Copy, Clone, PartialEq, Eq, Debug)]
25pub enum CharstringKind {
26 Type1,
30 Type2,
34}
35
36pub trait CharstringContext {
38 fn kind(&self) -> CharstringKind;
40
41 fn seac_components(&self, base_code: i32, accent_code: i32) -> Result<[&[u8]; 2], Error>;
44
45 fn global_subr(&self, index: i32) -> Result<&[u8], Error>;
48
49 fn subr(&self, index: i32) -> Result<&[u8], Error>;
52
53 fn weight_vector(&self) -> &[Fixed] {
55 &[]
56 }
57}
58
59impl<'a> CharstringContext for (&'a [u8], &'a Index<'a>, &'a Index<'a>, &'a Index<'a>) {
64 fn kind(&self) -> CharstringKind {
65 CharstringKind::Type2
66 }
67
68 fn seac_components(&self, base_code: i32, accent_code: i32) -> Result<[&[u8]; 2], Error> {
69 let cff = Cff::read(FontData::new(self.0))?;
70 let charset = cff
71 .charset(0)?
72 .or_else(|| Charset::new(FontData::default(), 0, self.1.count()).ok())
73 .ok_or(Error::MissingCharset)?;
74 let seac_to_gid = |code: i32| {
75 let code: u8 = code.try_into().ok()?;
76 let sid = *super::encoding::STANDARD_ENCODING.get(code as usize)?;
77 charset.glyph_id(Sid::new(sid as u16)).ok()
78 };
79 let accent_gid = seac_to_gid(accent_code).ok_or(Error::InvalidSeacCode(accent_code))?;
80 let base_gid = seac_to_gid(base_code).ok_or(Error::InvalidSeacCode(base_code))?;
81 let accent_charstring = self.1.get(accent_gid.to_u32() as usize)?;
82 let base_charstring = self.1.get(base_gid.to_u32() as usize)?;
83 Ok([base_charstring, accent_charstring])
84 }
85
86 fn global_subr(&self, index: i32) -> Result<&[u8], Error> {
87 self.2.get((index + self.2.subr_bias()) as usize)
88 }
89
90 fn subr(&self, index: i32) -> Result<&[u8], Error> {
91 self.3.get((index + self.3.subr_bias()) as usize)
92 }
93}
94
95#[allow(unused_variables)]
105pub trait CommandSink {
106 fn move_to(&mut self, x: Fixed, y: Fixed);
108 fn line_to(&mut self, x: Fixed, y: Fixed);
109 fn curve_to(&mut self, cx0: Fixed, cy0: Fixed, cx1: Fixed, cy1: Fixed, x: Fixed, y: Fixed);
110 fn close(&mut self);
111 fn hstem(&mut self, y: Fixed, dy: Fixed) {}
114 fn vstem(&mut self, x: Fixed, dx: Fixed) {}
116 fn hint_mask(&mut self, mask: &[u8]) {}
119 fn counter_mask(&mut self, mask: &[u8]) {}
122 fn clear_hints(&mut self) {}
124 fn finish(&mut self) {}
126}
127
128pub fn evaluate<'a>(
141 context: &'a impl CharstringContext,
142 blend_state: Option<BlendState<'a>>,
143 charstring_data: &[u8],
144 sink: &'a mut impl CommandSink,
145) -> Result<Option<Fixed>, Error> {
146 let mut evaluator = Evaluator::new(context, blend_state, sink);
147 evaluator.evaluate(charstring_data)?;
148 let width = evaluator.have_read_width.then_some(evaluator.wx);
149 sink.finish();
150 Ok(width)
151}
152
153#[derive(PartialEq)]
155enum SeacMode {
156 Explicit,
158 Implicit,
161}
162
163struct Evaluator<'a, S> {
166 context: &'a dyn CharstringContext,
167 is_type1: bool,
168 blend_state: Option<BlendState<'a>>,
169 sink: &'a mut S,
170 is_open: bool,
171 is_flexing: bool,
175 seen_width_command: bool,
177 have_read_width: bool,
179 stem_count: usize,
180 x: Fixed,
181 y: Fixed,
182 sbx: Fixed,
184 wx: Fixed,
186 stack: Stack,
187 stack_ix: usize,
188 in_seac: bool,
189}
190
191impl<'a, S> Evaluator<'a, S>
192where
193 S: CommandSink,
194{
195 fn new(
196 context: &'a dyn CharstringContext,
197 blend_state: Option<BlendState<'a>>,
198 sink: &'a mut S,
199 ) -> Self {
200 let is_type1 = context.kind() == CharstringKind::Type1;
201 Self {
202 context,
203 is_type1,
204 blend_state,
205 sink,
206 is_open: false,
207 is_flexing: false,
208 seen_width_command: false,
209 have_read_width: false,
210 stem_count: 0,
211 stack: Stack::new(),
212 x: Fixed::ZERO,
213 y: Fixed::ZERO,
214 sbx: Fixed::ZERO,
215 wx: Fixed::ZERO,
216 stack_ix: 0,
217 in_seac: false,
218 }
219 }
220
221 fn evaluate(&mut self, charstring_data: &[u8]) -> Result<(), Error> {
222 let seen_endchar = self.evaluate_impl(charstring_data, 0)?;
223 if !self.is_type1 && !seen_endchar {
224 self.evaluate_operator(
227 Operator::EndChar,
228 &mut crate::FontData::default().cursor(),
229 0,
230 )?;
231 }
232 if self.is_open {
233 self.sink.close();
234 }
235 Ok(())
236 }
237
238 fn evaluate_impl(&mut self, charstring_data: &[u8], nesting_depth: u32) -> Result<bool, Error> {
239 if nesting_depth > NESTING_DEPTH_LIMIT {
240 return Err(Error::CharstringNestingDepthLimitExceeded);
241 }
242 let mut cursor = crate::FontData::new(charstring_data).cursor();
243 let mut seen_endchar = false;
244 while cursor.remaining_bytes() != 0 {
245 let b0 = cursor.read::<u8>()?;
246 match b0 {
247 28 | 32..=254 => {
251 self.stack.push(num::parse_int(&mut cursor, b0)?)?;
252 }
253 255 => {
255 let val = cursor.read::<i32>()?;
256 if self.is_type1 {
257 self.stack.push(val)?;
259 } else {
260 self.stack.push(Fixed::from_bits(val))?;
263 }
264 }
265 _ => {
266 if let Ok(operator) = Operator::read(&mut cursor, b0) {
270 seen_endchar |= operator == Operator::EndChar;
271 if !self.evaluate_operator(operator, &mut cursor, nesting_depth)? {
272 break;
273 }
274 } else {
275 self.reset_stack();
277 }
278 }
279 }
280 }
281 Ok(seen_endchar)
282 }
283
284 fn evaluate_operator(
288 &mut self,
289 operator: Operator,
290 cursor: &mut Cursor,
291 nesting_depth: u32,
292 ) -> Result<bool, Error> {
293 use Operator::*;
294 use PointMode::*;
295 match operator {
296 Flex => {
306 self.emit_curves([DxDy; 6])?;
307 self.reset_stack();
308 }
309 HFlex => {
311 self.emit_curves([DxY, DxDy, DxY, DxY, DxInitialY, DxY])?;
312 self.reset_stack();
313 }
314 HFlex1 => {
316 self.emit_curves([DxDy, DxDy, DxY, DxY, DxDy, DxInitialY])?;
317 self.reset_stack();
318 }
319 Flex1 => {
321 self.emit_curves([DxDy, DxDy, DxDy, DxDy, DxDy, DLargerCoordDist])?;
322 self.reset_stack();
323 }
324 VariationStoreIndex => {
327 if !self.is_type1 {
328 let blend_state = self.blend_state.as_mut().ok_or(Error::MissingBlendState)?;
329 let store_index = self.stack.pop_i32()? as u16;
330 blend_state.set_store_index(store_index)?;
331 }
332 }
333 Blend => {
336 if !self.is_type1 {
337 let blend_state = self.blend_state.as_ref().ok_or(Error::MissingBlendState)?;
338 self.stack.apply_blend(blend_state)?;
339 }
340 }
341 Return => {
344 return Ok(false);
345 }
346 EndChar => {
350 let stack_len = self.stack.len();
351 if (stack_len == 1 || stack_len == 5) && !self.seen_width_command {
352 self.read_width()?;
353 }
354 self.seen_width_command = true;
355 if stack_len > 1 {
356 self.handle_seac(SeacMode::Implicit, nesting_depth)?;
357 }
358 return Ok(false);
359 }
360 HStem | VStem | HStemHm | VStemHm => {
364 let mut i = 0;
365 let len = if self.stack.len_is_odd() && !self.seen_width_command {
366 self.read_width()?;
367 i = 1;
368 self.stack.len() - 1
369 } else {
370 self.stack.len()
371 };
372 self.seen_width_command = true;
373 let is_horizontal = matches!(operator, HStem | HStemHm);
374 let mut u = Fixed::ZERO;
375 while i < self.stack.len() {
376 let args = self.stack.fixed_array::<2>(i)?;
377 u += args[0];
378 let w = args[1];
379 let v = u.wrapping_add(w);
380 if is_horizontal {
381 self.sink.hstem(u, v);
382 } else {
383 self.sink.vstem(u, v);
384 }
385 u = v;
386 i += 2;
387 }
388 self.stem_count += len / 2;
389 self.reset_stack();
390 }
391 HintMask | CntrMask => {
399 let mut i = 0;
400 let len = if self.stack.len_is_odd() && !self.seen_width_command {
401 self.read_width()?;
402 i = 1;
403 self.stack.len() - 1
404 } else {
405 self.stack.len()
406 };
407 self.seen_width_command = true;
408 let mut u = Fixed::ZERO;
409 while i < self.stack.len() {
410 let args = self.stack.fixed_array::<2>(i)?;
411 u += args[0];
412 let w = args[1];
413 let v = u + w;
414 self.sink.vstem(u, v);
415 u = v;
416 i += 2;
417 }
418 self.stem_count += len / 2;
419 let count = self.stem_count.div_ceil(8);
420 let mask = cursor.read_array::<u8>(count)?;
421 if operator == HintMask {
422 self.sink.hint_mask(mask);
423 } else {
424 self.sink.counter_mask(mask);
425 }
426 self.reset_stack();
427 }
428 RMoveTo => {
432 if self.stack.len() > 2 && !self.seen_width_command {
433 self.read_width()?;
434 }
435 self.seen_width_command = true;
436 if !self.is_flexing {
437 let dy = self.stack.pop_fixed()?;
438 let dx = self.stack.pop_fixed()?;
439 self.x += dx;
440 self.y += dy;
441 if !self.is_open {
442 self.is_open = true;
443 } else {
444 self.sink.close();
445 }
446 self.sink.move_to(self.x, self.y);
447 self.reset_stack();
448 }
449 }
450 HMoveTo | VMoveTo => {
455 if self.stack.len() > 1 && !self.seen_width_command {
456 self.read_width()?;
457 }
458 self.seen_width_command = true;
459 if self.is_flexing {
460 self.stack.push(0)?;
463 if operator == VMoveTo {
464 self.stack.exch()?;
467 }
468 } else {
469 let delta = self.stack.pop_fixed()?;
470 if operator == HMoveTo {
471 self.x += delta;
472 } else {
473 self.y += delta;
474 }
475 if !self.is_open {
476 self.is_open = true;
477 } else {
478 self.sink.close();
479 }
480 self.sink.move_to(self.x, self.y);
481 self.reset_stack();
482 }
483 }
484 RLineTo => {
488 let mut i = 0;
489 while i < self.stack.len() {
490 let [dx, dy] = self.stack.fixed_array::<2>(i)?;
491 self.x += dx;
492 self.y += dy;
493 self.emit_line(self.x, self.y);
494 i += 2;
495 }
496 self.reset_stack();
497 }
498 HLineTo | VLineTo => {
503 let mut is_x = operator == HLineTo;
504 for i in 0..self.stack.len() {
505 let delta = self.stack.get_fixed(i)?;
506 if is_x {
507 self.x += delta;
508 } else {
509 self.y += delta;
510 }
511 is_x = !is_x;
512 self.emit_line(self.x, self.y);
513 }
514 self.reset_stack();
515 }
516 HhCurveTo => {
522 let count1 = self.stack.len();
523 let count = count1 & !2;
524 self.stack_ix = count1 - count;
525 while self.stack_ix < count {
526 if (count - self.stack_ix) & 1 != 0 {
527 self.y += self.stack.get_fixed(self.stack_ix)?;
528 self.stack_ix += 1;
529 }
530 self.emit_curves([DxY, DxDy, DxY])?;
531 }
532 self.reset_stack();
533 }
534 HvCurveTo | VhCurveTo => {
539 let count1 = self.stack.len();
540 let count = count1 & !2;
541 let mut is_horizontal = operator == HvCurveTo;
542 self.stack_ix = count1 - count;
543 while self.stack_ix < count {
544 let do_last_delta = count - self.stack_ix == 5;
545 if is_horizontal {
546 self.emit_curves([DxY, DxDy, MaybeDxDy(do_last_delta)])?;
547 } else {
548 self.emit_curves([XDy, DxDy, DxMaybeDy(do_last_delta)])?;
549 }
550 is_horizontal = !is_horizontal;
551 }
552 self.reset_stack();
553 }
554 RrCurveTo | RCurveLine => {
558 while self.coords_remaining() >= 6 {
559 self.emit_curves([DxDy; 3])?;
560 }
561 if operator == RCurveLine {
562 let [dx, dy] = self.stack.fixed_array::<2>(self.stack_ix)?;
563 self.x += dx;
564 self.y += dy;
565 self.emit_line(self.x, self.y);
566 }
567 self.reset_stack();
568 }
569 RLineCurve => {
573 while self.coords_remaining() > 6 {
574 let [dx, dy] = self.stack.fixed_array::<2>(self.stack_ix)?;
575 self.x += dx;
576 self.y += dy;
577 self.emit_line(self.x, self.y);
578 self.stack_ix += 2;
579 }
580 while self.coords_remaining() >= 6 {
581 self.emit_curves([DxDy; 3])?;
582 }
583 self.reset_stack();
584 }
585 VvCurveTo => {
591 let count1 = self.stack.len();
592 let count = count1 & !2;
593 self.stack_ix = count1 - count;
594 while self.stack_ix < count {
595 if (count - self.stack_ix) & 1 != 0 {
596 self.x += self.stack.get_fixed(self.stack_ix)?;
597 self.stack_ix += 1;
598 }
599 self.emit_curves([XDy, DxDy, XDy])?;
600 }
601 self.reset_stack();
602 }
603 CallSubr | CallGsubr => {
607 let index = self.stack.pop_i32()?;
608 let subr_charstring = if operator == CallSubr {
609 self.context.subr(index)?
610 } else {
611 self.context.global_subr(index)?
612 };
613 self.evaluate_impl(subr_charstring, nesting_depth + 1)?;
614 }
615 Hsbw => {
621 if self.is_type1 {
622 let [sbx, wx] = self.stack.fixed_array(0)?;
623 self.sbx += sbx;
624 self.x += sbx;
625 self.wx = wx;
626 self.seen_width_command = true;
627 self.have_read_width = true;
628 self.reset_stack();
629 }
630 }
631 Seac => {
637 self.handle_seac(SeacMode::Explicit, nesting_depth)?;
638 }
639 Sbw => {
645 if self.is_type1 {
646 let [x, y, wx, _wy] = self.stack.fixed_array(0)?;
647 self.x += x;
648 self.y += y;
649 self.sbx += x;
650 self.wx = wx;
651 self.seen_width_command = true;
652 self.have_read_width = true;
653 self.reset_stack();
654 }
655 }
656 DotSection => {
660 }
662 HStem3 | VStem3 => {
666 self.reset_stack();
668 }
669 Div => {
673 self.stack.div(self.is_type1)?;
674 }
675 CallOtherSubr => {
679 let subr_idx = self.stack.pop_i32()?;
680 let num_args = self.stack.pop_i32()? as usize;
681 let weight_vector = self.context.weight_vector();
682 match (subr_idx, num_args) {
683 (0, 3) => {
686 self.is_flexing = false;
687 self.ensure_open();
688 self.handle_flex()?;
689 }
690 (1, 0) => {
692 self.is_flexing = true;
693 }
694 (12 | 13, _) => {
697 self.reset_stack();
698 }
699 (14..=18, _) if weight_vector.len() > 1 => {
702 self.handle_mm_blend(subr_idx, num_args)?;
703 }
704 _ => {
705 self.stack.drop(num_args);
708 }
709 }
710 }
711 Pop => {
717 }
719 SetCurrentPoint => {
723 if self.is_type1 {
724 let [x, y] = self.stack.fixed_array(0)?;
725 self.x = x;
726 self.y = y;
727 self.reset_stack();
728 }
729 }
730 }
731 Ok(true)
732 }
733
734 fn read_width(&mut self) -> Result<(), Error> {
735 self.wx = self.stack.get_fixed(0)?;
736 self.seen_width_command = true;
737 self.have_read_width = true;
738 Ok(())
739 }
740
741 fn handle_seac(&mut self, mode: SeacMode, nesting_depth: u32) -> Result<(), Error> {
743 if self.in_seac {
745 return Err(Error::CharstringNestingDepthLimitExceeded);
746 }
747 self.in_seac = true;
748 let accent_code = self.stack.pop_i32()?;
749 let base_code = self.stack.pop_i32()?;
750 let [base_charstring, accent_charstring] =
751 self.context.seac_components(base_code, accent_code)?;
752 let dy = self.stack.pop_fixed()?;
753 let dx = self.stack.pop_fixed()?;
754 let sb = if self.is_type1 {
755 self.stack.pop_fixed()?
757 } else if !self.stack.is_empty() && !self.seen_width_command {
758 self.wx = self.stack.pop_fixed()?;
759 self.seen_width_command = true;
760 Fixed::ZERO
761 } else {
762 Fixed::ZERO
763 };
764 let mut sbx = self.sbx;
766 let mut wx = self.wx;
767 let seen_width = self.seen_width_command;
768 let read_width = self.have_read_width;
769 struct Component<'a> {
770 charstring: &'a [u8],
771 x: Fixed,
772 y: Fixed,
773 maybe_use_metrics: bool,
776 }
777 let x = self.x;
778 let y = self.y;
779 let [bx, by] = if mode == SeacMode::Explicit {
781 [Fixed::ZERO; 2]
782 } else {
783 [x, y]
784 };
785 let mut components = [
786 Component {
787 charstring: base_charstring,
788 x: bx,
789 y: by,
790 maybe_use_metrics: mode == SeacMode::Explicit,
793 },
794 Component {
795 charstring: accent_charstring,
796 x: dx + self.sbx - sb,
799 y: dy,
800 maybe_use_metrics: false,
801 },
802 ];
803 if mode == SeacMode::Implicit {
806 components.swap(0, 1);
807 }
808 for component in components {
816 self.reset_stack();
817 self.seen_width_command = false;
818 self.sink.clear_hints();
819 self.stem_count = 0;
820 self.x = component.x;
821 self.y = component.y;
822 self.evaluate_impl(component.charstring, nesting_depth + 1)?;
823 if component.maybe_use_metrics && !seen_width {
824 sbx = self.sbx;
825 wx = self.wx;
826 }
827 }
828 self.seen_width_command = seen_width;
829 self.have_read_width = read_width;
830 self.sbx = sbx;
831 self.wx = wx;
832 self.in_seac = false;
833 Ok(())
834 }
835
836 fn handle_flex(&mut self) -> Result<(), Error> {
838 let final_y = self.stack.pop_fixed()?;
843 let final_x = self.stack.pop_fixed()?;
844 let _ = self.stack.pop_fixed()?;
846 let p3y = self.stack.pop_fixed()?;
847 let p3x = self.stack.pop_fixed()?;
848 let bcp4y = self.stack.pop_fixed()?;
849 let bcp4x = self.stack.pop_fixed()?;
850 let bcp3y = self.stack.pop_fixed()?;
851 let bcp3x = self.stack.pop_fixed()?;
852 let p2y = self.stack.pop_fixed()?;
853 let p2x = self.stack.pop_fixed()?;
854 let bcp2y = self.stack.pop_fixed()?;
855 let bcp2x = self.stack.pop_fixed()?;
856 let bcp1y = self.stack.pop_fixed()?;
857 let bcp1x = self.stack.pop_fixed()?;
858 let rpy = self.stack.pop_fixed()?;
859 let rpx = self.stack.pop_fixed()?;
860 self.reset_stack();
861 self.stack.push(bcp1x + rpx)?;
862 self.stack.push(bcp1y + rpy)?;
863 self.stack.push(bcp2x)?;
864 self.stack.push(bcp2y)?;
865 self.stack.push(p2x)?;
866 self.stack.push(p2y)?;
867 self.emit_curves([PointMode::DxDy; 3])?;
868 self.reset_stack();
869 self.stack.push(bcp3x)?;
870 self.stack.push(bcp3y)?;
871 self.stack.push(bcp4x)?;
872 self.stack.push(bcp4y)?;
873 self.stack.push(p3x)?;
874 self.stack.push(p3y)?;
875 self.emit_curves([PointMode::DxDy; 3])?;
876 self.reset_stack();
877 self.stack.push(final_x)?;
879 self.stack.push(final_y)?;
880 Ok(())
881 }
882
883 fn handle_mm_blend(&mut self, subr_idx: i32, num_args: usize) -> Result<(), Error> {
887 let weight_vector = self.context.weight_vector();
888 let num_points = (subr_idx - 13) as usize + (subr_idx == 18) as usize;
889 if num_args != num_points * weight_vector.len() {
890 return Err(Error::Read(crate::ReadError::MalformedData(
891 "incorrect number of multiple masters arguments",
892 )));
893 }
894 let stack_base = self
903 .stack
904 .len()
905 .checked_sub(num_args)
906 .ok_or(Error::StackUnderflow)?;
907 let mut delta_idx = stack_base + num_points;
908 for i in 0..num_points {
909 let mut val = self.stack.get_fixed(stack_base + i)?;
910 for &weight in &weight_vector[1..] {
911 val += self.stack.get_fixed(delta_idx)? * weight;
912 delta_idx += 1;
913 }
914 self.stack.set(stack_base + i, val)?;
915 }
916 self.stack.drop(num_args.saturating_sub(num_points));
917 Ok(())
918 }
919
920 fn coords_remaining(&self) -> usize {
921 self.stack.len().saturating_sub(self.stack_ix)
925 }
926
927 fn ensure_open(&mut self) {
928 if !self.is_open {
929 self.sink.move_to(Fixed::ZERO, Fixed::ZERO);
930 self.is_open = true;
931 }
932 }
933
934 fn emit_line(&mut self, x: Fixed, y: Fixed) {
935 self.ensure_open();
936 self.sink.line_to(x, y);
937 }
938
939 fn emit_curves<const N: usize>(&mut self, modes: [PointMode; N]) -> Result<(), Error> {
940 use PointMode::*;
941 let initial_x = self.x;
942 let initial_y = self.y;
943 let mut count = 0;
944 let mut points = [Point::default(); 2];
945 self.ensure_open();
946 for mode in modes {
947 let stack_used = match mode {
948 DxDy => {
949 self.x += self.stack.get_fixed(self.stack_ix)?;
950 self.y += self.stack.get_fixed(self.stack_ix + 1)?;
951 2
952 }
953 XDy => {
954 self.y += self.stack.get_fixed(self.stack_ix)?;
955 1
956 }
957 DxY => {
958 self.x += self.stack.get_fixed(self.stack_ix)?;
959 1
960 }
961 DxInitialY => {
962 self.x += self.stack.get_fixed(self.stack_ix)?;
963 self.y = initial_y;
964 1
965 }
966 DLargerCoordDist => {
970 let delta = self.stack.get_fixed(self.stack_ix)?;
971 if (self.x - initial_x).abs() > (self.y - initial_y).abs() {
972 self.x += delta;
973 self.y = initial_y;
974 } else {
975 self.y += delta;
976 self.x = initial_x;
977 }
978 1
979 }
980 DxMaybeDy(do_dy) => {
982 self.x += self.stack.get_fixed(self.stack_ix)?;
983 if do_dy {
984 self.y += self.stack.get_fixed(self.stack_ix + 1)?;
985 2
986 } else {
987 1
988 }
989 }
990 MaybeDxDy(do_dx) => {
992 self.y += self.stack.get_fixed(self.stack_ix)?;
993 if do_dx {
994 self.x += self.stack.get_fixed(self.stack_ix + 1)?;
995 2
996 } else {
997 1
998 }
999 }
1000 };
1001 self.stack_ix += stack_used;
1002 if count == 2 {
1003 self.sink.curve_to(
1004 points[0].x,
1005 points[0].y,
1006 points[1].x,
1007 points[1].y,
1008 self.x,
1009 self.y,
1010 );
1011 count = 0;
1012 } else {
1013 points[count] = Point::new(self.x, self.y);
1014 count += 1;
1015 }
1016 }
1017 Ok(())
1018 }
1019
1020 fn reset_stack(&mut self) {
1021 self.stack.clear();
1022 self.stack_ix = 0;
1023 }
1024}
1025
1026#[derive(Copy, Clone)]
1028enum PointMode {
1029 DxDy,
1030 XDy,
1031 DxY,
1032 DxInitialY,
1033 DLargerCoordDist,
1034 DxMaybeDy(bool),
1035 MaybeDxDy(bool),
1036}
1037
1038#[derive(Copy, Clone, PartialEq, Eq, Debug)]
1044enum Operator {
1045 HStem,
1046 VStem,
1047 VMoveTo,
1048 RLineTo,
1049 HLineTo,
1050 VLineTo,
1051 RrCurveTo,
1052 CallSubr,
1053 Return,
1054 Hsbw,
1055 EndChar,
1056 VariationStoreIndex,
1057 Blend,
1058 HStemHm,
1059 HintMask,
1060 CntrMask,
1061 RMoveTo,
1062 HMoveTo,
1063 VStemHm,
1064 RCurveLine,
1065 RLineCurve,
1066 VvCurveTo,
1067 HhCurveTo,
1068 CallGsubr,
1069 VhCurveTo,
1070 HvCurveTo,
1071 DotSection,
1072 VStem3,
1073 HStem3,
1074 Seac,
1075 Sbw,
1076 Div,
1077 CallOtherSubr,
1078 Pop,
1079 SetCurrentPoint,
1080 HFlex,
1081 Flex,
1082 HFlex1,
1083 Flex1,
1084}
1085
1086impl Operator {
1087 fn read(cursor: &mut Cursor, b0: u8) -> Result<Self, Error> {
1088 const ESCAPE: u8 = 12;
1090 let (opcode, operator) = if b0 == ESCAPE {
1091 let b1 = cursor.read::<u8>()?;
1092 (b1, Self::from_two_byte_opcode(b1))
1093 } else {
1094 (b0, Self::from_opcode(b0))
1095 };
1096 operator.ok_or(Error::InvalidCharstringOperator(opcode))
1097 }
1098
1099 fn from_opcode(opcode: u8) -> Option<Self> {
1101 use Operator::*;
1102 Some(match opcode {
1103 1 => HStem,
1104 3 => VStem,
1105 4 => VMoveTo,
1106 5 => RLineTo,
1107 6 => HLineTo,
1108 7 => VLineTo,
1109 8 => RrCurveTo,
1110 10 => CallSubr,
1111 11 => Return,
1112 13 => Hsbw,
1113 14 => EndChar,
1114 15 => VariationStoreIndex,
1115 16 => Blend,
1116 18 => HStemHm,
1117 19 => HintMask,
1118 20 => CntrMask,
1119 21 => RMoveTo,
1120 22 => HMoveTo,
1121 23 => VStemHm,
1122 24 => RCurveLine,
1123 25 => RLineCurve,
1124 26 => VvCurveTo,
1125 27 => HhCurveTo,
1126 29 => CallGsubr,
1127 30 => VhCurveTo,
1128 31 => HvCurveTo,
1129 _ => return None,
1130 })
1131 }
1132
1133 pub fn from_two_byte_opcode(opcode: u8) -> Option<Self> {
1137 use Operator::*;
1138 Some(match opcode {
1139 0 => DotSection,
1140 1 => VStem3,
1141 2 => HStem3,
1142 6 => Seac,
1143 7 => Sbw,
1144 12 => Div,
1145 16 => CallOtherSubr,
1146 17 => Pop,
1147 33 => SetCurrentPoint,
1148 34 => HFlex,
1149 35 => Flex,
1150 36 => HFlex1,
1151 37 => Flex1,
1152 _ => return None,
1153 })
1154 }
1155}
1156
1157const ONE_OVER_64: Fixed = Fixed::from_bits(0x400);
1159
1160pub struct TransformSink<'a, S> {
1162 inner: &'a mut S,
1163 matrix: Option<FontMatrix>,
1164 scale: Option<Fixed>,
1165}
1166
1167impl<'a, S> TransformSink<'a, S> {
1168 pub fn new(sink: &'a mut S, transform: Transform) -> Self {
1170 Self::from_matrix_scale(sink, transform.matrix, transform.scale)
1171 }
1172
1173 pub fn from_matrix_scale(sink: &'a mut S, matrix: FontMatrix, scale: Option<Fixed>) -> Self {
1175 Self {
1176 inner: sink,
1177 matrix: (matrix != FontMatrix::IDENTITY).then_some(matrix),
1178 scale,
1179 }
1180 }
1181
1182 fn transform(&self, x: Fixed, y: Fixed) -> (Fixed, Fixed) {
1183 let ax = x * ONE_OVER_64;
1193 let ay = y * ONE_OVER_64;
1194 let bx = Fixed::from_bits(ax.to_bits() >> 10);
1198 let by = Fixed::from_bits(ay.to_bits() >> 10);
1199 let (cx, cy) = self
1201 .matrix
1202 .as_ref()
1203 .map(|mat| mat.transform(bx, by))
1204 .unwrap_or((bx, by));
1205 if let Some(scale) = self.scale {
1206 let dx = cx * scale;
1210 let dy = cy * scale;
1211 (
1213 Fixed::from_bits(dx.to_bits() << 10),
1214 Fixed::from_bits(dy.to_bits() << 10),
1215 )
1216 } else {
1217 (
1220 Fixed::from_bits(cx.to_bits() << 16),
1221 Fixed::from_bits(cy.to_bits() << 16),
1222 )
1223 }
1224 }
1225}
1226
1227impl<S: CommandSink> CommandSink for TransformSink<'_, S> {
1228 fn hstem(&mut self, y: Fixed, dy: Fixed) {
1229 self.inner.hstem(y, dy);
1230 }
1231
1232 fn vstem(&mut self, x: Fixed, dx: Fixed) {
1233 self.inner.vstem(x, dx);
1234 }
1235
1236 fn hint_mask(&mut self, mask: &[u8]) {
1237 self.inner.hint_mask(mask);
1238 }
1239
1240 fn counter_mask(&mut self, mask: &[u8]) {
1241 self.inner.counter_mask(mask);
1242 }
1243
1244 fn clear_hints(&mut self) {
1245 self.inner.clear_hints();
1246 }
1247
1248 fn move_to(&mut self, x: Fixed, y: Fixed) {
1249 let (x, y) = self.transform(x, y);
1250 self.inner.move_to(x, y);
1251 }
1252
1253 fn line_to(&mut self, x: Fixed, y: Fixed) {
1254 let (x, y) = self.transform(x, y);
1255 self.inner.line_to(x, y);
1256 }
1257
1258 fn curve_to(&mut self, cx1: Fixed, cy1: Fixed, cx2: Fixed, cy2: Fixed, x: Fixed, y: Fixed) {
1259 let (cx1, cy1) = self.transform(cx1, cy1);
1260 let (cx2, cy2) = self.transform(cx2, cy2);
1261 let (x, y) = self.transform(x, y);
1262 self.inner.curve_to(cx1, cy1, cx2, cy2, x, y);
1263 }
1264
1265 fn close(&mut self) {
1266 self.inner.close();
1267 }
1268
1269 fn finish(&mut self) {
1270 self.inner.finish();
1271 }
1272}
1273
1274#[derive(Copy, Clone)]
1275enum PendingElement {
1276 Move([Fixed; 2]),
1277 Line([Fixed; 2]),
1278 Curve([Fixed; 6]),
1279}
1280
1281impl PendingElement {
1282 fn target_point(&self) -> [Fixed; 2] {
1283 match self {
1284 Self::Move(xy) | Self::Line(xy) => *xy,
1285 Self::Curve([.., x, y]) => [*x, *y],
1286 }
1287 }
1288}
1289
1290pub struct NopFilterSink<'a, S> {
1299 is_open: bool,
1300 start: Option<(Fixed, Fixed)>,
1301 pending_element: Option<PendingElement>,
1302 inner: &'a mut S,
1303}
1304
1305impl<'a, S> NopFilterSink<'a, S>
1306where
1307 S: CommandSink,
1308{
1309 pub fn new(inner: &'a mut S) -> Self {
1312 Self {
1313 is_open: false,
1314 start: None,
1315 pending_element: None,
1316 inner,
1317 }
1318 }
1319
1320 fn flush_pending(&mut self, for_close: bool) {
1321 if let Some(pending) = self.pending_element.take() {
1322 match pending {
1323 PendingElement::Move([x, y]) => {
1324 if !for_close {
1325 self.is_open = true;
1326 self.inner.move_to(x, y);
1327 self.start = Some((x, y));
1328 }
1329 }
1330 PendingElement::Line([x, y]) => {
1331 if !for_close || self.start != Some((x, y)) {
1332 self.inner.line_to(x, y);
1333 }
1334 }
1335 PendingElement::Curve([cx0, cy0, cx1, cy1, x, y]) => {
1336 self.inner.curve_to(cx0, cy0, cx1, cy1, x, y);
1337 }
1338 }
1339 }
1340 }
1341}
1342
1343impl<S> CommandSink for NopFilterSink<'_, S>
1344where
1345 S: CommandSink,
1346{
1347 fn hstem(&mut self, y: Fixed, dy: Fixed) {
1348 self.inner.hstem(y, dy);
1349 }
1350
1351 fn vstem(&mut self, x: Fixed, dx: Fixed) {
1352 self.inner.vstem(x, dx);
1353 }
1354
1355 fn hint_mask(&mut self, mask: &[u8]) {
1356 self.inner.hint_mask(mask);
1357 }
1358
1359 fn counter_mask(&mut self, mask: &[u8]) {
1360 self.inner.counter_mask(mask);
1361 }
1362
1363 fn clear_hints(&mut self) {
1364 self.inner.clear_hints();
1365 }
1366
1367 fn move_to(&mut self, x: Fixed, y: Fixed) {
1368 self.pending_element = Some(PendingElement::Move([x, y]));
1369 }
1370
1371 fn line_to(&mut self, x: Fixed, y: Fixed) {
1372 if self
1374 .pending_element
1375 .map(|element| element.target_point() == [x, y])
1376 .unwrap_or_default()
1377 {
1378 return;
1379 }
1380 self.flush_pending(false);
1381 self.pending_element = Some(PendingElement::Line([x, y]));
1382 }
1383
1384 fn curve_to(&mut self, cx1: Fixed, cy1: Fixed, cx2: Fixed, cy2: Fixed, x: Fixed, y: Fixed) {
1385 self.flush_pending(false);
1386 self.pending_element = Some(PendingElement::Curve([cx1, cy1, cx2, cy2, x, y]));
1387 }
1388
1389 fn close(&mut self) {
1390 self.flush_pending(true);
1391 if self.is_open {
1392 self.inner.close();
1393 self.is_open = false;
1394 }
1395 }
1396
1397 fn finish(&mut self) {
1398 self.close();
1399 self.inner.finish();
1400 }
1401}
1402
1403impl<P: OutlinePen> CommandSink for P {
1404 fn move_to(&mut self, x: Fixed, y: Fixed) {
1405 self.move_to(x.to_f32(), y.to_f32());
1406 }
1407
1408 fn line_to(&mut self, x: Fixed, y: Fixed) {
1409 self.line_to(x.to_f32(), y.to_f32());
1410 }
1411
1412 fn curve_to(&mut self, cx0: Fixed, cy0: Fixed, cx1: Fixed, cy1: Fixed, x: Fixed, y: Fixed) {
1413 self.curve_to(
1414 cx0.to_f32(),
1415 cy0.to_f32(),
1416 cx1.to_f32(),
1417 cy1.to_f32(),
1418 x.to_f32(),
1419 y.to_f32(),
1420 );
1421 }
1422
1423 fn close(&mut self) {
1424 self.close()
1425 }
1426}
1427
1428#[cfg(test)]
1429pub(crate) mod test_helpers {
1430 use super::{CommandSink, Fixed};
1431
1432 #[derive(Copy, Clone, PartialEq, Debug)]
1433 #[allow(clippy::enum_variant_names)]
1434 pub enum Command {
1435 MoveTo(Fixed, Fixed),
1436 LineTo(Fixed, Fixed),
1437 CurveTo(Fixed, Fixed, Fixed, Fixed, Fixed, Fixed),
1438 }
1439
1440 #[derive(PartialEq, Default, Debug)]
1441 pub struct CaptureCommandSink(pub Vec<Command>);
1442
1443 impl CommandSink for CaptureCommandSink {
1444 fn move_to(&mut self, x: Fixed, y: Fixed) {
1445 self.0.push(Command::MoveTo(x, y))
1446 }
1447
1448 fn line_to(&mut self, x: Fixed, y: Fixed) {
1449 self.0.push(Command::LineTo(x, y))
1450 }
1451
1452 fn curve_to(&mut self, cx0: Fixed, cy0: Fixed, cx1: Fixed, cy1: Fixed, x: Fixed, y: Fixed) {
1453 self.0.push(Command::CurveTo(cx0, cy0, cx1, cy1, x, y))
1454 }
1455
1456 fn close(&mut self) {
1457 let mut last_move = [Fixed::ZERO; 2];
1461 for command in self.0.iter().rev() {
1462 if let Command::MoveTo(x, y) = command {
1463 last_move = [*x, *y];
1464 break;
1465 }
1466 }
1467 self.0.push(Command::LineTo(last_move[0], last_move[1]));
1468 }
1469 }
1470
1471 impl CaptureCommandSink {
1472 pub fn to_svg(&self) -> String {
1473 use core::fmt::Write;
1474 let mut buf = String::default();
1475 for cmd in &self.0 {
1476 if !buf.is_empty() {
1477 buf.push(' ');
1478 }
1479 match cmd {
1480 Command::MoveTo(x, y) => write!(buf, "M{},{}", x.to_f32(), y.to_f32()).unwrap(),
1481 Command::LineTo(x, y) => write!(buf, "L{},{}", x.to_f32(), y.to_f32()).unwrap(),
1482 Command::CurveTo(x0, y0, x1, y1, x, y) => write!(
1483 buf,
1484 "C{},{} {},{} {},{}",
1485 x0.to_f32(),
1486 y0.to_f32(),
1487 x1.to_f32(),
1488 y1.to_f32(),
1489 x.to_f32(),
1490 y.to_f32()
1491 )
1492 .unwrap(),
1493 }
1494 }
1495 buf
1496 }
1497 }
1498
1499 #[derive(Default)]
1500 pub struct CharstringCommandCounter(pub usize);
1501
1502 impl CommandSink for CharstringCommandCounter {
1503 fn move_to(&mut self, _x: Fixed, _y: Fixed) {
1504 self.0 += 1;
1505 }
1506
1507 fn line_to(&mut self, _x: Fixed, _y: Fixed) {
1508 self.0 += 1;
1509 }
1510
1511 fn curve_to(
1512 &mut self,
1513 _cx0: Fixed,
1514 _cy0: Fixed,
1515 _cx1: Fixed,
1516 _cy1: Fixed,
1517 _x: Fixed,
1518 _y: Fixed,
1519 ) {
1520 self.0 += 1;
1521 }
1522
1523 fn close(&mut self) {
1524 self.0 += 1;
1525 }
1526 }
1527}
1528
1529#[cfg(test)]
1530mod tests {
1531 use super::{test_helpers::*, *};
1532 use crate::{tables::variations::ItemVariationStore, types::F2Dot14, FontData, FontRead};
1533
1534 #[test]
1535 fn cff2_example_subr() {
1536 use Command::*;
1537 let charstring = &font_test_data::cff2::EXAMPLE[0xc8..=0xe1];
1538 let store =
1539 ItemVariationStore::read(FontData::new(&font_test_data::cff2::EXAMPLE[18..])).unwrap();
1540 let coords = &[F2Dot14::from_f32(0.0)];
1541 let blend_state = BlendState::new(store, coords, 0).unwrap();
1542 let mut commands = CaptureCommandSink::default();
1543 evaluate(
1544 &NullContext(CharstringKind::Type2),
1545 Some(blend_state),
1546 charstring,
1547 &mut commands,
1548 )
1549 .unwrap();
1550 let expected = &[
1567 MoveTo(Fixed::from_f64(50.0), Fixed::ZERO),
1568 LineTo(Fixed::from_f64(550.0), Fixed::ZERO),
1569 LineTo(Fixed::from_f64(550.0), Fixed::from_f64(500.0)),
1570 LineTo(Fixed::from_f64(50.0), Fixed::from_f64(500.0)),
1571 LineTo(Fixed::from_f64(50.0), Fixed::ZERO),
1572 ];
1573 assert_eq!(&commands.0, expected);
1574 }
1575
1576 #[test]
1577 fn all_path_ops() {
1578 let charstring = &[
1608 251, 29, 253, 12, 21, 173, 134, 159, 133, 5, 140, 141, 142, 6, 251, 71, 129, 142, 7,
1609 109, 154, 161, 147, 89, 165, 125, 97, 98, 158, 124, 164, 8, 109, 154, 161, 147, 27,
1610 147, 109, 154, 161, 147, 27, 163, 159, 154, 180, 181, 119, 153, 115, 114, 120, 125, 97,
1611 98, 158, 124, 164, 31, 159, 4, 119, 153, 115, 114, 120, 125, 143, 144, 24, 119, 153,
1612 115, 114, 120, 125, 143, 144, 25, 84, 116, 117, 80, 30, 109, 154, 161, 147, 26, 147,
1613 109, 154, 161, 147, 26, 163, 159, 154, 180, 181, 119, 153, 115, 114, 120, 125, 97, 162,
1614 12, 35, 163, 159, 154, 180, 181, 119, 153, 12, 34, 152, 22, 180, 181, 119, 153, 115,
1615 114, 120, 125, 97, 12, 36, 154, 180, 181, 119, 153, 115, 114, 120, 125, 97, 147, 12,
1616 37, 14,
1617 ];
1618 use Command::*;
1619 let mut commands = CaptureCommandSink::default();
1620 evaluate(
1621 &NullContext(CharstringKind::Type2),
1622 None,
1623 charstring,
1624 &mut commands,
1625 )
1626 .unwrap();
1627 let expected = &[
1668 MoveTo(Fixed::from_i32(-137), Fixed::from_i32(-632)),
1669 LineTo(Fixed::from_i32(-103), Fixed::from_i32(-637)),
1670 LineTo(Fixed::from_i32(-83), Fixed::from_i32(-643)),
1671 LineTo(Fixed::from_i32(-82), Fixed::from_i32(-643)),
1672 LineTo(Fixed::from_i32(-82), Fixed::from_i32(-641)),
1673 LineTo(Fixed::from_i32(-79), Fixed::from_i32(-641)),
1674 LineTo(Fixed::from_i32(-79), Fixed::from_i32(-820)),
1675 LineTo(Fixed::from_i32(-89), Fixed::from_i32(-820)),
1676 LineTo(Fixed::from_i32(-89), Fixed::from_i32(-817)),
1677 CurveTo(
1678 Fixed::from_i32(-119),
1679 Fixed::from_i32(-802),
1680 Fixed::from_i32(-97),
1681 Fixed::from_i32(-794),
1682 Fixed::from_i32(-147),
1683 Fixed::from_i32(-768),
1684 ),
1685 CurveTo(
1686 Fixed::from_i32(-161),
1687 Fixed::from_i32(-810),
1688 Fixed::from_i32(-202),
1689 Fixed::from_i32(-791),
1690 Fixed::from_i32(-217),
1691 Fixed::from_i32(-766),
1692 ),
1693 CurveTo(
1694 Fixed::from_i32(-247),
1695 Fixed::from_i32(-766),
1696 Fixed::from_i32(-232),
1697 Fixed::from_i32(-744),
1698 Fixed::from_i32(-224),
1699 Fixed::from_i32(-744),
1700 ),
1701 CurveTo(
1702 Fixed::from_i32(-254),
1703 Fixed::from_i32(-736),
1704 Fixed::from_i32(-239),
1705 Fixed::from_i32(-714),
1706 Fixed::from_i32(-231),
1707 Fixed::from_i32(-714),
1708 ),
1709 CurveTo(
1710 Fixed::from_i32(-207),
1711 Fixed::from_i32(-714),
1712 Fixed::from_i32(-187),
1713 Fixed::from_i32(-699),
1714 Fixed::from_i32(-187),
1715 Fixed::from_i32(-658),
1716 ),
1717 CurveTo(
1718 Fixed::from_i32(-187),
1719 Fixed::from_i32(-616),
1720 Fixed::from_i32(-207),
1721 Fixed::from_i32(-602),
1722 Fixed::from_i32(-231),
1723 Fixed::from_i32(-602),
1724 ),
1725 CurveTo(
1726 Fixed::from_i32(-256),
1727 Fixed::from_i32(-602),
1728 Fixed::from_i32(-275),
1729 Fixed::from_i32(-616),
1730 Fixed::from_i32(-275),
1731 Fixed::from_i32(-658),
1732 ),
1733 CurveTo(
1734 Fixed::from_i32(-275),
1735 Fixed::from_i32(-699),
1736 Fixed::from_i32(-256),
1737 Fixed::from_i32(-714),
1738 Fixed::from_i32(-231),
1739 Fixed::from_i32(-714),
1740 ),
1741 LineTo(Fixed::from_i32(-137), Fixed::from_i32(-632)),
1742 MoveTo(Fixed::from_i32(-231), Fixed::from_i32(-694)),
1743 CurveTo(
1744 Fixed::from_i32(-251),
1745 Fixed::from_i32(-680),
1746 Fixed::from_i32(-275),
1747 Fixed::from_i32(-705),
1748 Fixed::from_i32(-294),
1749 Fixed::from_i32(-719),
1750 ),
1751 LineTo(Fixed::from_i32(-290), Fixed::from_i32(-714)),
1752 LineTo(Fixed::from_i32(-310), Fixed::from_i32(-700)),
1753 CurveTo(
1754 Fixed::from_i32(-334),
1755 Fixed::from_i32(-725),
1756 Fixed::from_i32(-353),
1757 Fixed::from_i32(-739),
1758 Fixed::from_i32(-349),
1759 Fixed::from_i32(-734),
1760 ),
1761 CurveTo(
1762 Fixed::from_i32(-349),
1763 Fixed::from_i32(-789),
1764 Fixed::from_i32(-372),
1765 Fixed::from_i32(-811),
1766 Fixed::from_i32(-431),
1767 Fixed::from_i32(-811),
1768 ),
1769 CurveTo(
1770 Fixed::from_i32(-431),
1771 Fixed::from_i32(-841),
1772 Fixed::from_i32(-416),
1773 Fixed::from_i32(-819),
1774 Fixed::from_i32(-416),
1775 Fixed::from_i32(-811),
1776 ),
1777 CurveTo(
1778 Fixed::from_i32(-408),
1779 Fixed::from_i32(-841),
1780 Fixed::from_i32(-393),
1781 Fixed::from_i32(-819),
1782 Fixed::from_i32(-393),
1783 Fixed::from_i32(-811),
1784 ),
1785 CurveTo(
1786 Fixed::from_i32(-369),
1787 Fixed::from_i32(-791),
1788 Fixed::from_i32(-354),
1789 Fixed::from_i32(-750),
1790 Fixed::from_i32(-312),
1791 Fixed::from_i32(-770),
1792 ),
1793 CurveTo(
1794 Fixed::from_i32(-298),
1795 Fixed::from_i32(-794),
1796 Fixed::from_i32(-323),
1797 Fixed::from_i32(-813),
1798 Fixed::from_i32(-337),
1799 Fixed::from_i32(-855),
1800 ),
1801 CurveTo(
1802 Fixed::from_i32(-313),
1803 Fixed::from_i32(-855),
1804 Fixed::from_i32(-293),
1805 Fixed::from_i32(-840),
1806 Fixed::from_i32(-252),
1807 Fixed::from_i32(-840),
1808 ),
1809 CurveTo(
1810 Fixed::from_i32(-210),
1811 Fixed::from_i32(-840),
1812 Fixed::from_i32(-230),
1813 Fixed::from_i32(-855),
1814 Fixed::from_i32(-216),
1815 Fixed::from_i32(-855),
1816 ),
1817 LineTo(Fixed::from_i32(-231), Fixed::from_i32(-694)),
1818 MoveTo(Fixed::from_i32(-203), Fixed::from_i32(-855)),
1819 CurveTo(
1820 Fixed::from_i32(-162),
1821 Fixed::from_i32(-813),
1822 Fixed::from_i32(-182),
1823 Fixed::from_i32(-799),
1824 Fixed::from_i32(-206),
1825 Fixed::from_i32(-799),
1826 ),
1827 CurveTo(
1828 Fixed::from_i32(-231),
1829 Fixed::from_i32(-799),
1830 Fixed::from_i32(-250),
1831 Fixed::from_i32(-813),
1832 Fixed::from_i32(-292),
1833 Fixed::from_i32(-855),
1834 ),
1835 CurveTo(
1836 Fixed::from_i32(-277),
1837 Fixed::from_i32(-814),
1838 Fixed::from_i32(-235),
1839 Fixed::from_i32(-834),
1840 Fixed::from_i32(-221),
1841 Fixed::from_i32(-858),
1842 ),
1843 CurveTo(
1844 Fixed::from_i32(-246),
1845 Fixed::from_i32(-877),
1846 Fixed::from_i32(-260),
1847 Fixed::from_i32(-919),
1848 Fixed::from_i32(-292),
1849 Fixed::from_i32(-911),
1850 ),
1851 LineTo(Fixed::from_i32(-203), Fixed::from_i32(-855)),
1852 ];
1853 assert_eq!(&commands.0, expected);
1854 }
1855
1856 #[test]
1859 fn coords_remaining_avoid_overflow() {
1860 let mut commands = CaptureCommandSink::default();
1863 let mut evaluator =
1864 Evaluator::new(&NullContext(CharstringKind::Type2), None, &mut commands);
1865 evaluator.stack.push(0).unwrap();
1866 evaluator.stack.push(0).unwrap();
1867 let mut cursor = FontData::new(&[]).cursor();
1868 let _ = evaluator.evaluate_operator(Operator::HhCurveTo, &mut cursor, 0);
1870 }
1871
1872 #[test]
1873 fn ignore_reserved_operators() {
1874 let charstring = &[
1875 0u8, 32, 22, 2, ];
1880 let mut commands = CaptureCommandSink::default();
1881 evaluate(
1882 &NullContext(CharstringKind::Type2),
1883 None,
1884 charstring,
1885 &mut commands,
1886 )
1887 .unwrap();
1888 let x = Fixed::from_i32(-107);
1889 assert_eq!(
1890 commands.0,
1891 [
1892 Command::MoveTo(x, Fixed::ZERO),
1893 Command::LineTo(x, Fixed::ZERO)
1894 ]
1895 );
1896 }
1897
1898 #[test]
1899 fn op_div() {
1900 let mut commands = CaptureCommandSink::default();
1901 let mut eval = Evaluator::new(&NullContext(CharstringKind::Type2), None, &mut commands);
1902 let mut cursor = FontData::new(&[]).cursor();
1903 eval.stack.push(Fixed::from_f64(512.5)).unwrap();
1904 eval.stack.push(2).unwrap();
1905 eval.evaluate_operator(Operator::Div, &mut cursor, 0)
1906 .unwrap();
1907 assert_eq!(
1908 eval.stack.pop_fixed().unwrap(),
1909 Fixed::from_f64(512.5 / 2.0)
1910 );
1911 }
1912
1913 #[test]
1914 fn op_div_type1_large_int() {
1915 let mut commands = CaptureCommandSink::default();
1916 let mut eval = Evaluator::new(&NullContext(CharstringKind::Type1), None, &mut commands);
1917 let mut cursor = FontData::new(&[]).cursor();
1918 eval.stack.push(32001).unwrap();
1920 eval.stack.push(2).unwrap();
1921 eval.evaluate_operator(Operator::Div, &mut cursor, 0)
1922 .unwrap();
1923 assert_eq!(
1924 eval.stack.pop_fixed().unwrap(),
1925 Fixed::from_f64(32001.0 / 2.0)
1926 );
1927 }
1928
1929 fn eval_h_sbw(operator: Operator, kind: CharstringKind) -> [Fixed; 2] {
1933 let mut commands = CaptureCommandSink::default();
1934 let ctx = &NullContext(kind);
1935 let mut eval = Evaluator::new(ctx, None, &mut commands);
1936 let mut cursor = FontData::new(&[]).cursor();
1937 eval.stack.push(Fixed::from_f64(42.5)).unwrap();
1938 if operator == Operator::Sbw {
1939 eval.stack.push(0).unwrap();
1941 }
1942 eval.stack.push(501).unwrap();
1943 eval.stack.push(1000).unwrap();
1944 eval.evaluate_operator(operator, &mut cursor, 0).unwrap();
1945 [eval.sbx, eval.wx]
1946 }
1947
1948 #[test]
1949 fn op_sbw_type1() {
1950 let [sbx, wx] = eval_h_sbw(Operator::Sbw, CharstringKind::Type1);
1951 assert_eq!(sbx, Fixed::from_f64(42.5));
1952 assert_eq!(wx, Fixed::from_f64(501.0));
1953 }
1954
1955 #[test]
1956 fn op_hsbw_type1() {
1957 let [sbx, wx] = eval_h_sbw(Operator::Hsbw, CharstringKind::Type1);
1958 assert_eq!(sbx, Fixed::from_f64(42.5));
1959 assert_eq!(wx, Fixed::from_f64(501.0));
1960 }
1961
1962 #[test]
1964 fn op_sbw_type2_no_effect() {
1965 let [sbx, wx] = eval_h_sbw(Operator::Sbw, CharstringKind::Type2);
1966 assert_eq!(sbx, Fixed::ZERO);
1967 assert_eq!(wx, Fixed::ZERO);
1968 }
1969
1970 #[test]
1972 fn op_hsbw_type2_no_effect() {
1973 let [sbx, wx] = eval_h_sbw(Operator::Hsbw, CharstringKind::Type2);
1974 assert_eq!(sbx, Fixed::ZERO);
1975 assert_eq!(wx, Fixed::ZERO);
1976 }
1977
1978 #[test]
1979 fn op_callothersubr_flex() {
1980 let mut commands = CaptureCommandSink::default();
1981 let mut eval = Evaluator::new(&NullContext(CharstringKind::Type1), None, &mut commands);
1982 let mut cursor = FontData::new(&[]).cursor();
1983 macro_rules! op {
1985 ($nums:expr) => {
1986 for n in $nums {
1987 eval.stack.push(n).unwrap();
1988 }
1989 };
1990 ($nums:expr, $op:ident) => {
1991 op!($nums);
1992 eval.evaluate_operator(Operator::$op, &mut cursor, 0)
1993 .unwrap();
1994 };
1995 }
1996 op!([0, 1], CallOtherSubr);
1999 for vec in [[1, 2]; 7] {
2001 op!(vec, RMoveTo);
2002 }
2003 op!([0, 100, 200]);
2005 op!([3, 0], CallOtherSubr);
2007 let none: [i32; 0] = [];
2010 op!(none, SetCurrentPoint);
2011 let expected = [
2012 Command::MoveTo(Fixed::ZERO, Fixed::ZERO),
2013 Command::CurveTo(
2014 Fixed::from_i32(2),
2015 Fixed::from_i32(4),
2016 Fixed::from_i32(3),
2017 Fixed::from_i32(6),
2018 Fixed::from_i32(4),
2019 Fixed::from_i32(8),
2020 ),
2021 Command::CurveTo(
2022 Fixed::from_i32(5),
2023 Fixed::from_i32(10),
2024 Fixed::from_i32(6),
2025 Fixed::from_i32(12),
2026 Fixed::from_i32(7),
2027 Fixed::from_i32(14),
2028 ),
2029 ];
2030 assert_eq!(eval.x, Fixed::from_i32(100));
2031 assert_eq!(eval.y, Fixed::from_i32(200));
2032 assert_eq!(commands.0, expected);
2033 }
2034
2035 struct NullContext(CharstringKind);
2036
2037 impl CharstringContext for NullContext {
2038 fn kind(&self) -> CharstringKind {
2039 self.0
2040 }
2041
2042 fn seac_components(&self, base_code: i32, _accent_code: i32) -> Result<[&[u8]; 2], Error> {
2043 Err(Error::InvalidSeacCode(base_code))
2044 }
2045
2046 fn global_subr(&self, _index: i32) -> Result<&[u8], Error> {
2047 Err(Error::MissingSubroutines)
2048 }
2049
2050 fn subr(&self, _index: i32) -> Result<&[u8], Error> {
2051 Err(Error::MissingSubroutines)
2052 }
2053 }
2054
2055 #[test]
2056 fn nop_filter_sink() {
2057 let mut commands = CaptureCommandSink::default();
2058 let mut nop_filter = NopFilterSink::new(&mut commands);
2059 let (sx, sy) = (Fixed::from_f64(10.2), Fixed::from_f64(20.4));
2060 nop_filter.move_to(Fixed::from_f64(0.0), Fixed::from_f64(0.0));
2062 nop_filter.move_to(sx, sy);
2063 nop_filter.line_to(sx, sy);
2065 nop_filter.curve_to(
2066 Fixed::from_f64(5.0),
2067 Fixed::from_f64(-5.0),
2068 Fixed::from_f64(1.5),
2069 Fixed::from_f64(2.0),
2070 Fixed::from_f64(4.5),
2071 Fixed::from_f64(-10.0),
2072 );
2073 nop_filter.line_to(Fixed::from_f64(4.5), Fixed::from_f64(-10.0));
2075 nop_filter.line_to(sx, sy);
2077 nop_filter.close();
2078 assert_eq!(
2079 commands.0,
2080 [
2081 Command::MoveTo(sx, sy),
2082 Command::CurveTo(
2083 Fixed::from_f64(5.0),
2084 Fixed::from_f64(-5.0),
2085 Fixed::from_f64(1.5),
2086 Fixed::from_f64(2.0),
2087 Fixed::from_f64(4.5),
2088 Fixed::from_f64(-10.0),
2089 ),
2090 Command::LineTo(sx, sy),
2091 ]
2092 )
2093 }
2094
2095 #[test]
2096 fn scaled_matrix_transform_sink() {
2097 let input = [(150i32, 46i32), (176, 8), (217, -13), (267, -13)]
2100 .map(|(x, y)| (Fixed::from_bits(x << 16), Fixed::from_bits(y << 16)));
2101 let expected = [(404, 118i32), (453, 20), (550, -33), (678, -33)]
2102 .map(|(x, y)| (Fixed::from_bits(x << 10), Fixed::from_bits(y << 10)));
2103 let mut dummy = ();
2104 let sink =
2105 TransformSink::from_matrix_scale(&mut dummy, TRANSFORM, Some(Fixed::from_bits(167772)));
2106 let transformed = input.map(|(x, y)| sink.transform(x, y));
2107 assert_eq!(transformed, expected);
2108 }
2109
2110 #[test]
2111 fn unscaled_matrix_transform_sink() {
2112 let input = [(150i32, 46i32), (176, 8), (217, -13), (267, -13)]
2115 .map(|(x, y)| (Fixed::from_bits(x << 16), Fixed::from_bits(y << 16)));
2116 let expected = [(158, 46i32), (177, 8), (215, -13), (265, -13)]
2117 .map(|(x, y)| (Fixed::from_bits(x << 16), Fixed::from_bits(y << 16)));
2118 let mut dummy = ();
2119 let sink = TransformSink::from_matrix_scale(&mut dummy, TRANSFORM, None);
2120 let transformed = input.map(|(x, y)| sink.transform(x, y));
2121 assert_eq!(transformed, expected);
2122 }
2123
2124 const TRANSFORM: FontMatrix = FontMatrix::from_elements([
2125 Fixed::ONE,
2126 Fixed::ZERO,
2127 Fixed::from_bits(10945),
2129 Fixed::ONE,
2130 Fixed::ZERO,
2131 Fixed::ZERO,
2132 ]);
2133
2134 #[test]
2135 fn unscaled_transform_sink_produces_integers() {
2136 let nothing = &mut ();
2137 let sink = TransformSink::new(nothing, Transform::default());
2138 for coord in [50.0, 50.1, 50.125, 50.5, 50.9] {
2139 assert_eq!(
2140 sink.transform(Fixed::from_f64(coord), Fixed::ZERO)
2141 .0
2142 .to_f32(),
2143 50.0
2144 );
2145 }
2146 }
2147
2148 #[test]
2149 fn scaled_transform_sink() {
2150 let ppem = 20.0;
2151 let upem = 1000.0;
2152 let scale = Fixed::from_bits((ppem * 64.) as i32) / Fixed::from_bits(upem as i32);
2154 let nothing = &mut ();
2155 let sink = TransformSink::from_matrix_scale(nothing, FontMatrix::IDENTITY, Some(scale));
2156 let inputs = [
2157 (0.0, 0.0),
2159 (8.0, 0.15625),
2160 (16.0, 0.3125),
2161 (32.0, 0.640625),
2162 (72.0, 1.4375),
2163 (128.0, 2.5625),
2164 ];
2165 for (coord, expected) in inputs {
2166 assert_eq!(
2167 sink.transform(Fixed::from_f64(coord), Fixed::ZERO)
2168 .0
2169 .to_f32(),
2170 expected,
2171 "scaling coord {coord}"
2172 );
2173 }
2174 }
2175
2176 #[test]
2177 fn mm_blend() {
2178 let mut commands = CaptureCommandSink::default();
2179 let ctx = MmContext([0.0, -0.25, 1.0].map(Fixed::from_f64));
2180 let mut eval = Evaluator::new(&ctx, None, &mut commands);
2181 let mut cursor = FontData::new(&[]).cursor();
2182 for i in [[1, 0], [2, 3], [4, -8], [6, 15]].into_iter().flatten() {
2186 eval.stack.push(i).unwrap();
2187 }
2188 eval.evaluate_operator(Operator::CallOtherSubr, &mut cursor, 0)
2189 .unwrap();
2190 let [a, b] = eval.stack.fixed_array(0).unwrap();
2191 assert_eq!(a.to_f32(), 3.5);
2193 assert_eq!(b.to_f32(), -9.0);
2195 }
2196
2197 struct MmContext([Fixed; 3]);
2198
2199 impl CharstringContext for MmContext {
2200 fn kind(&self) -> CharstringKind {
2201 CharstringKind::Type1
2202 }
2203
2204 fn seac_components(&self, base_code: i32, _accent_code: i32) -> Result<[&[u8]; 2], Error> {
2205 Err(Error::InvalidSeacCode(base_code))
2206 }
2207
2208 fn global_subr(&self, _index: i32) -> Result<&[u8], Error> {
2209 Err(Error::MissingSubroutines)
2210 }
2211
2212 fn subr(&self, _index: i32) -> Result<&[u8], Error> {
2213 Err(Error::MissingSubroutines)
2214 }
2215
2216 fn weight_vector(&self) -> &[Fixed] {
2217 &self.0
2218 }
2219 }
2220}