#[derive(Debug, Clone, PartialEq, Default)]
pub struct Components(pub SmallVec<[f32; 4]>);
impl FromOperands for Components {
fn extract(ring: &OperandRing, _index: usize) -> Self {
Self(ring.numbers(ring.len().min(4)))
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct PatternComponents {
pub values: SmallVec<[f32; 4]>,
pub pattern: Option<Name>,
}
impl FromOperands for PatternComponents {
fn extract(ring: &OperandRing, _index: usize) -> Self {
if ring.is_name(0) {
Self {
values: ring.named_numbers(),
pattern: Some(Name::new(ring.string(0))),
}
} else {
Self {
values: ring.numbers(ring.len()),
pattern: None,
}
}
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct DashPattern {
pub array: SmallVec<[f32; 4]>,
pub phase: f32,
pub valid: bool,
}
impl FromOperands for DashPattern {
fn extract(ring: &OperandRing, _index: usize) -> Self {
let phase = ring.number(0);
match ring.object(1) {
Object::Array(a) => Self {
array: a.iter().map(|o| o.number().unwrap_or(0.0)).collect(),
phase,
valid: true,
},
_ => Self {
array: SmallVec::new(),
phase,
valid: false,
},
}
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct TextArray {
pub items: Box<[TextItem]>,
pub valid: bool,
}
impl FromOperands for TextArray {
fn extract(ring: &OperandRing, _index: usize) -> Self {
match ring.object(0) {
Object::Array(a) => {
let items = a
.iter()
.filter_map(|o| match o {
Object::Str(s) => Some(TextItem::Show(s.bytes.clone())),
Object::Int(_) | Object::Real(_) => {
o.number().map(TextItem::Adjust)
}
_ => None,
})
.collect();
Self { items, valid: true }
}
_ => Self {
items: Box::default(),
valid: false,
},
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct MarkProps(pub Option<MarkProperties>);
impl FromOperands for MarkProps {
fn extract(ring: &OperandRing, _index: usize) -> Self {
Self(match ring.object(0) {
Object::Name(n) => Some(MarkProperties::Named(n)),
Object::Dict(d) => Some(MarkProperties::Inline(Box::new(d))),
_ => None,
})
}
}
ops! {
b"q" => SaveState();
b"Q" => RestoreState();
b"cm" => Concat(Affine: 0);
b"w" => SetLineWidth(f32: 0);
b"J" => SetLineCap(LineCap: 0);
b"j" => SetLineJoin(LineJoin: 0);
b"M" => SetMiterLimit(f32: 0);
b"d" => SetDash(DashPattern: 0);
b"ri" => SetRenderIntent(Name: 0);
b"i" => SetFlatness(f32: 0);
b"gs" => SetExtGState(Name: 0);
b"m" => MoveTo(Point: 0) 2;
b"l" => LineTo(Point: 0) 2;
b"c" => CurveTo(Point: 4, Point: 2, Point: 0);
b"v" => CurveToV(Point: 2, Point: 0);
b"y" => CurveToY(Point: 2, Point: 0);
b"h" => ClosePath();
b"re" => Rectangle(f32: 3, f32: 2, f32: 1, f32: 0);
b"S" => Stroke();
b"s" => CloseStroke();
b"f" => Fill();
b"F" => FillObsolete();
b"f*" => FillEvenOdd();
b"B" => FillStroke();
b"B*" => FillStrokeEvenOdd();
b"b" => CloseFillStroke();
b"b*" => CloseFillStrokeEvenOdd();
b"n" => EndPath();
b"W" => Clip();
b"W*" => ClipEvenOdd();
b"BT" => BeginText();
b"ET" => EndText();
b"Td" => TextMove(f32: 1, f32: 0);
b"TD" => TextMoveSetLeading(f32: 1, f32: 0);
b"Tm" => SetTextMatrix(Affine: 0);
b"T*" => TextNextLine();
b"TL" => SetLeading(f32: 0);
b"Ts" => SetTextRise(f32: 0);
b"Tz" => SetHorzScale(f32: 0) 1;
b"Tc" => SetCharSpace(f32: 0);
b"Tw" => SetWordSpace(f32: 0);
b"Tf" => SetFont(Name: 1, f32: 0);
b"Tr" => SetTextRenderMode(i64: 0);
b"Tj" => ShowText(PdfString: 0);
b"'" => NextLineShowText(PdfString: 0);
b"\"" => SetSpacingShowText(f32: 2, f32: 1, PdfString: 0);
b"TJ" => ShowTextAdjusted(TextArray: 0);
b"d0" => Type3Width(f32: 1, f32: 0);
b"d1" => Type3WidthBBox(f32: 5, f32: 4, f32: 3, f32: 2, f32: 1, f32: 0);
b"CS" => SetStrokeColorSpace(Name: 0);
b"cs" => SetFillColorSpace(Name: 0);
b"SC" => SetStrokeColor(Components: 0);
b"sc" => SetFillColor(Components: 0);
b"SCN" => SetStrokeColorN(PatternComponents: 0);
b"scn" => SetFillColorN(PatternComponents: 0);
b"G" => SetStrokeGray(f32: 0);
b"g" => SetFillGray(f32: 0);
b"RG" => SetStrokeRgb(f32: 2, f32: 1, f32: 0) 3;
b"rg" => SetFillRgb(f32: 2, f32: 1, f32: 0) 3;
b"K" => SetStrokeCmyk(f32: 3, f32: 2, f32: 1, f32: 0) 4;
b"k" => SetFillCmyk(f32: 3, f32: 2, f32: 1, f32: 0) 4;
b"Do" => DoXObject(Name: 0);
b"sh" => ShadeFill(Name: 0);
b"BI" => BeginInlineImage();
b"ID" => InlineImageData();
b"EI" => EndInlineImage();
b"BMC" => BeginMarkedContent(Name: 0);
b"BDC" => BeginMarkedContentDict(Name: 1, MarkProps: 0);
b"EMC" => EndMarkedContent();
b"MP" => MarkPoint(Name: 0);
b"DP" => MarkPointDict(Name: 1, MarkProps: 0);
b"BX" => BeginCompat();
b"EX" => EndCompat();
}