mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-29 12:17:14 -06:00
Separate metafile record parsing into focused handlers
This commit is contained in:
+152
-117
@@ -166,24 +166,154 @@ pub(super) fn play(bytes: &[u8]) -> Result<Imported, String> {
|
||||
Ok(p.finish())
|
||||
}
|
||||
|
||||
/// PolyBezier, Polygon, Polyline, PolyBezierTo, PolylineTo and their 16-bit forms.
|
||||
fn rec_poly(p: &mut Player, kind: u32, r: &mut Reader) -> Option<()> {
|
||||
let wide = kind < 85;
|
||||
r.skip(16)?;
|
||||
let n = r.u32()?;
|
||||
let pts = points(r, n, wide)?;
|
||||
match if wide { kind } else { kind - 83 } {
|
||||
2 => p.poly(&pts, false, true),
|
||||
3 => p.poly(&pts, true, false),
|
||||
4 => p.poly(&pts, false, false),
|
||||
5 => p.poly_to(&pts, true),
|
||||
_ => p.poly_to(&pts, false),
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// CreatePen (38).
|
||||
fn rec_create_pen(p: &mut Player, r: &mut Reader) -> Option<()> {
|
||||
let ih = r.u32()?;
|
||||
let style = r.u32()?;
|
||||
let width = f64::from(r.i32()?);
|
||||
r.skip(4)?;
|
||||
p.create_at(ih, Obj::Pen(PenObj { style, width, color: color(r)?, entries: vec![] }));
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// ExtCreatePen (95).
|
||||
fn rec_ext_create_pen(p: &mut Player, r: &mut Reader) -> Option<()> {
|
||||
let ih = r.u32()?;
|
||||
r.skip(16)?;
|
||||
let style = r.u32()?;
|
||||
let width = f64::from(r.u32()?);
|
||||
let brush = r.u32()?;
|
||||
let c = color(r)?;
|
||||
r.skip(4)?;
|
||||
let n = (r.u32()? as usize).min(64);
|
||||
let entries: Vec<f64> = (0..n).map_while(|_| r.u32()).map(f64::from).collect();
|
||||
// A pen painted with the null brush draws nothing.
|
||||
let style = if brush == 1 { super::PS_NULL } else { style };
|
||||
p.create_at(ih, Obj::Pen(PenObj { style, width, color: c, entries }));
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// GdiComment (70): EMF+ records ride in comments starting "EMF+".
|
||||
fn rec_comment(p: &mut Player, r: &mut Reader) -> Option<()> {
|
||||
r.skip(4)?;
|
||||
p.emf_plus |= r.u32()? == 0x2B46_4D45;
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// ExtSelectClipRgn (75).
|
||||
fn rec_clip_region(p: &mut Player, r: &mut Reader) -> Option<()> {
|
||||
let cb = r.u32()?;
|
||||
let mode = r.u32()?;
|
||||
let data = r.bytes(cb as usize)?;
|
||||
let mut d = Reader::new(data);
|
||||
let rects = if cb >= 32 {
|
||||
d.skip(8)?;
|
||||
let n = d.u32()? as usize;
|
||||
d.skip(20)?;
|
||||
if n > MAX_POINTS || d.rest().len() < n * 16 {
|
||||
return None;
|
||||
}
|
||||
(0..n).map(|_| rect(&mut d)).collect::<Option<Vec<_>>>()?
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
p.clip_region(&rects, mode);
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// The rectangle at `(x, y)` of size `(w, h)`.
|
||||
fn at_size(x: i32, y: i32, w: i32, h: i32) -> Rect {
|
||||
Rect::new(f64::from(x), f64::from(y), f64::from(x) + f64::from(w), f64::from(y) + f64::from(h))
|
||||
}
|
||||
|
||||
/// BitBlt (76) and StretchBlt (77).
|
||||
fn rec_blt(p: &mut Player, kind: u32, rec: &[u8], r: &mut Reader) -> Option<()> {
|
||||
r.skip(16)?;
|
||||
let dest = (r.i32()?, r.i32()?, r.i32()?, r.i32()?);
|
||||
let rop = r.u32()?;
|
||||
let (xs, ys) = (r.i32()?, r.i32()?);
|
||||
r.skip(24 + 4 + 4)?;
|
||||
let (off_bmi, cb_bmi, off_bits, cb_bits) = (r.u32()?, r.u32()?, r.u32()?, r.u32()?);
|
||||
let (ws, hs) = if kind == 77 { (r.i32()?, r.i32()?) } else { (dest.2, dest.3) };
|
||||
let d = at_size(dest.0, dest.1, dest.2, dest.3);
|
||||
if cb_bmi == 0 {
|
||||
p.pattern_blit(d, rop);
|
||||
} else {
|
||||
let img = bitmap(rec, off_bmi, cb_bmi, off_bits, cb_bits, Alpha::Ignore, &mut p.pixels_left);
|
||||
let src = source(xs, ys, ws, hs, &img, false);
|
||||
p.image(img, src, d, rop, 1.0);
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// StretchDIBits (81).
|
||||
fn rec_stretch_dibits(p: &mut Player, rec: &[u8], r: &mut Reader) -> Option<()> {
|
||||
r.skip(16)?;
|
||||
let (xd, yd, xs, ys, ws, hs) = (r.i32()?, r.i32()?, r.i32()?, r.i32()?, r.i32()?, r.i32()?);
|
||||
let (off_bmi, cb_bmi, off_bits, cb_bits) = (r.u32()?, r.u32()?, r.u32()?, r.u32()?);
|
||||
r.skip(4)?;
|
||||
let rop = r.u32()?;
|
||||
let (wd, hd) = (r.i32()?, r.i32()?);
|
||||
let img = bitmap(rec, off_bmi, cb_bmi, off_bits, cb_bits, Alpha::Ignore, &mut p.pixels_left);
|
||||
let src = source(xs, ys, ws, hs, &img, bottom_up(rec, off_bmi));
|
||||
p.image(img, src, at_size(xd, yd, wd, hd), rop, 1.0);
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// AlphaBlend (114).
|
||||
fn rec_alpha_blend(p: &mut Player, rec: &[u8], r: &mut Reader) -> Option<()> {
|
||||
r.skip(16)?;
|
||||
let (xd, yd, wd, hd) = (r.i32()?, r.i32()?, r.i32()?, r.i32()?);
|
||||
let blend = r.bytes(4)?;
|
||||
let (constant, per_pixel) = (blend.get(2).copied().unwrap_or(255), blend.get(3).is_some_and(|f| *f & 1 != 0));
|
||||
let (xs, ys) = (r.i32()?, r.i32()?);
|
||||
r.skip(24 + 4 + 4)?;
|
||||
let (off_bmi, cb_bmi, off_bits, cb_bits) = (r.u32()?, r.u32()?, r.u32()?, r.u32()?);
|
||||
let (ws, hs) = (r.i32()?, r.i32()?);
|
||||
let alpha = if per_pixel { Alpha::Premultiplied } else { Alpha::Ignore };
|
||||
let img = bitmap(rec, off_bmi, cb_bmi, off_bits, cb_bits, alpha, &mut p.pixels_left);
|
||||
let src = source(xs, ys, ws, hs, &img, false);
|
||||
p.image(img, src, at_size(xd, yd, wd, hd), crate::import::SRCCOPY, f64::from(constant) / 255.0);
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// ExtTextOutA (83) and ExtTextOutW (84).
|
||||
fn rec_text(p: &mut Player, kind: u32, rec: &[u8], r: &mut Reader) -> Option<()> {
|
||||
r.skip(16 + 4 + 8)?;
|
||||
let at = point32(r)?;
|
||||
let n = r.u32()? as usize;
|
||||
let off = r.u32()?;
|
||||
let s = if kind == 84 {
|
||||
let raw = slice(rec, off, u32::try_from(n.checked_mul(2)?).ok()?)?;
|
||||
String::from_utf16_lossy(&raw.as_chunks::<2>().0.iter().map(|c| u16::from_le_bytes(*c)).collect::<Vec<_>>())
|
||||
} else {
|
||||
slice(rec, off, u32::try_from(n).ok()?)?.iter().map(|b| char::from(*b)).collect()
|
||||
};
|
||||
p.text(at, &s);
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// Play one record (`rec`: all of it, with its type and size). `None`: unknown or damaged.
|
||||
fn record(p: &mut Player, kind: u32, rec: &[u8]) -> Option<()> {
|
||||
let mut r = Reader::new(rec.get(8..)?);
|
||||
match kind {
|
||||
// PolyBezier, Polygon, Polyline, PolyBezierTo, PolylineTo and their 16-bit forms.
|
||||
2..=6 | 85..=89 => {
|
||||
let wide = kind < 85;
|
||||
r.skip(16)?;
|
||||
let n = r.u32()?;
|
||||
let pts = points(&mut r, n, wide)?;
|
||||
match if wide { kind } else { kind - 83 } {
|
||||
2 => p.poly(&pts, false, true),
|
||||
3 => p.poly(&pts, true, false),
|
||||
4 => p.poly(&pts, false, false),
|
||||
5 => p.poly_to(&pts, true),
|
||||
_ => p.poly_to(&pts, false),
|
||||
}
|
||||
}
|
||||
2..=6 | 85..=89 => rec_poly(p, kind, &mut r)?,
|
||||
7 | 90 => p.poly_poly(&polys(&mut r, kind == 7)?, false),
|
||||
8 | 91 => p.poly_poly(&polys(&mut r, kind == 8)?, true),
|
||||
9 => p.set_window_ext(f64::from(r.i32()?), f64::from(r.i32()?)),
|
||||
@@ -209,13 +339,7 @@ fn record(p: &mut Player, kind: u32, rec: &[u8]) -> Option<()> {
|
||||
p.world(x, r.u32()?);
|
||||
}
|
||||
37 => p.select(r.u32()?),
|
||||
38 => {
|
||||
let ih = r.u32()?;
|
||||
let style = r.u32()?;
|
||||
let width = f64::from(r.i32()?);
|
||||
r.skip(4)?;
|
||||
p.create_at(ih, Obj::Pen(PenObj { style, width, color: color(&mut r)?, entries: vec![] }));
|
||||
}
|
||||
38 => rec_create_pen(p, &mut r)?,
|
||||
39 => {
|
||||
let ih = r.u32()?;
|
||||
let style = r.u32()?;
|
||||
@@ -249,107 +373,18 @@ fn record(p: &mut Player, kind: u32, rec: &[u8]) -> Option<()> {
|
||||
64 => p.paint_path(false, true),
|
||||
67 => p.clip_path(r.u32()?),
|
||||
68 => p.abort_path(),
|
||||
70 => {
|
||||
// EMF+ records ride in comments starting "EMF+".
|
||||
r.skip(4)?;
|
||||
if r.u32()? == 0x2B46_4D45 {
|
||||
p.emf_plus = true;
|
||||
}
|
||||
}
|
||||
75 => {
|
||||
let cb = r.u32()?;
|
||||
let mode = r.u32()?;
|
||||
let data = r.bytes(cb as usize)?;
|
||||
let mut d = Reader::new(data);
|
||||
let rects = if cb >= 32 {
|
||||
d.skip(8)?;
|
||||
let n = d.u32()? as usize;
|
||||
d.skip(20)?;
|
||||
if n > MAX_POINTS || d.rest().len() < n * 16 {
|
||||
return None;
|
||||
}
|
||||
(0..n).map(|_| rect(&mut d)).collect::<Option<Vec<_>>>()?
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
p.clip_region(&rects, mode);
|
||||
}
|
||||
76 | 77 => {
|
||||
r.skip(16)?;
|
||||
let dest = (r.i32()?, r.i32()?, r.i32()?, r.i32()?);
|
||||
let rop = r.u32()?;
|
||||
let (xs, ys) = (r.i32()?, r.i32()?);
|
||||
r.skip(24 + 4 + 4)?;
|
||||
let (off_bmi, cb_bmi, off_bits, cb_bits) = (r.u32()?, r.u32()?, r.u32()?, r.u32()?);
|
||||
let (ws, hs) = if kind == 77 { (r.i32()?, r.i32()?) } else { (dest.2, dest.3) };
|
||||
let d = Rect::new(f64::from(dest.0), f64::from(dest.1), f64::from(dest.0) + f64::from(dest.2), f64::from(dest.1) + f64::from(dest.3));
|
||||
if cb_bmi == 0 {
|
||||
p.pattern_blit(d, rop);
|
||||
} else {
|
||||
let img = bitmap(rec, off_bmi, cb_bmi, off_bits, cb_bits, Alpha::Ignore, &mut p.pixels_left);
|
||||
let src = source(xs, ys, ws, hs, &img, false);
|
||||
p.image(img, src, d, rop, 1.0);
|
||||
}
|
||||
}
|
||||
81 => {
|
||||
r.skip(16)?;
|
||||
let (xd, yd, xs, ys, ws, hs) = (r.i32()?, r.i32()?, r.i32()?, r.i32()?, r.i32()?, r.i32()?);
|
||||
let (off_bmi, cb_bmi, off_bits, cb_bits) = (r.u32()?, r.u32()?, r.u32()?, r.u32()?);
|
||||
r.skip(4)?;
|
||||
let rop = r.u32()?;
|
||||
let (wd, hd) = (r.i32()?, r.i32()?);
|
||||
let img = bitmap(rec, off_bmi, cb_bmi, off_bits, cb_bits, Alpha::Ignore, &mut p.pixels_left);
|
||||
let src = source(xs, ys, ws, hs, &img, bottom_up(rec, off_bmi));
|
||||
let d = Rect::new(f64::from(xd), f64::from(yd), f64::from(xd) + f64::from(wd), f64::from(yd) + f64::from(hd));
|
||||
p.image(img, src, d, rop, 1.0);
|
||||
}
|
||||
70 => rec_comment(p, &mut r)?,
|
||||
75 => rec_clip_region(p, &mut r)?,
|
||||
76 | 77 => rec_blt(p, kind, rec, &mut r)?,
|
||||
81 => rec_stretch_dibits(p, rec, &mut r)?,
|
||||
82 => {
|
||||
let ih = r.u32()?;
|
||||
p.create_at(ih, Obj::Font(font(&mut r)?));
|
||||
}
|
||||
83 | 84 => {
|
||||
r.skip(16 + 4 + 8)?;
|
||||
let at = point32(&mut r)?;
|
||||
let n = r.u32()? as usize;
|
||||
let off = r.u32()?;
|
||||
let s = if kind == 84 {
|
||||
let raw = slice(rec, off, u32::try_from(n.checked_mul(2)?).ok()?)?;
|
||||
String::from_utf16_lossy(&raw.as_chunks::<2>().0.iter().map(|c| u16::from_le_bytes(*c)).collect::<Vec<_>>())
|
||||
} else {
|
||||
slice(rec, off, u32::try_from(n).ok()?)?.iter().map(|b| char::from(*b)).collect()
|
||||
};
|
||||
p.text(at, &s);
|
||||
}
|
||||
83 | 84 => rec_text(p, kind, rec, &mut r)?,
|
||||
93 | 94 => p.create_at(r.u32()?, Obj::Brush(BrushObj::Pattern)),
|
||||
95 => {
|
||||
let ih = r.u32()?;
|
||||
r.skip(16)?;
|
||||
let style = r.u32()?;
|
||||
let width = f64::from(r.u32()?);
|
||||
let brush = r.u32()?;
|
||||
let c = color(&mut r)?;
|
||||
r.skip(4)?;
|
||||
let n = (r.u32()? as usize).min(64);
|
||||
let entries: Vec<f64> = (0..n).map_while(|_| r.u32()).map(f64::from).collect();
|
||||
// A pen painted with the null brush draws nothing.
|
||||
let style = if brush == 1 { super::PS_NULL } else { style };
|
||||
p.create_at(ih, Obj::Pen(PenObj { style, width, color: c, entries }));
|
||||
}
|
||||
114 => {
|
||||
r.skip(16)?;
|
||||
let (xd, yd, wd, hd) = (r.i32()?, r.i32()?, r.i32()?, r.i32()?);
|
||||
let blend = r.bytes(4)?;
|
||||
let (constant, per_pixel) = (blend.get(2).copied().unwrap_or(255), blend.get(3).is_some_and(|f| *f & 1 != 0));
|
||||
let (xs, ys) = (r.i32()?, r.i32()?);
|
||||
r.skip(24 + 4 + 4)?;
|
||||
let (off_bmi, cb_bmi, off_bits, cb_bits) = (r.u32()?, r.u32()?, r.u32()?, r.u32()?);
|
||||
let (ws, hs) = (r.i32()?, r.i32()?);
|
||||
let alpha = if per_pixel { Alpha::Premultiplied } else { Alpha::Ignore };
|
||||
let img = bitmap(rec, off_bmi, cb_bmi, off_bits, cb_bits, alpha, &mut p.pixels_left);
|
||||
let src = source(xs, ys, ws, hs, &img, false);
|
||||
let d = Rect::new(f64::from(xd), f64::from(yd), f64::from(xd) + f64::from(wd), f64::from(yd) + f64::from(hd));
|
||||
p.image(img, src, d, crate::import::SRCCOPY, f64::from(constant) / 255.0);
|
||||
}
|
||||
95 => rec_ext_create_pen(p, &mut r)?,
|
||||
114 => rec_alpha_blend(p, rec, &mut r)?,
|
||||
k if IGNORED.contains(&k) => {}
|
||||
_ => return None,
|
||||
}
|
||||
|
||||
@@ -174,6 +174,109 @@ fn blit(p: &mut Player, rop: u32, src: (i16, i16, i16, i16), dest: (i16, i16, i1
|
||||
p.image(img, Rect::new(xs, top, xs + ws, top + hs), d, rop, 1.0);
|
||||
}
|
||||
|
||||
/// PolyPolygon (0x0538).
|
||||
fn rec_poly_polygon(p: &mut Player, r: &mut Reader) -> Option<()> {
|
||||
let n = usize::from(r.u16()?);
|
||||
if r.rest().len() < n * 2 {
|
||||
return None;
|
||||
}
|
||||
let counts: Vec<usize> = (0..n).map(|_| r.u16().map(usize::from)).collect::<Option<_>>()?;
|
||||
let mut polys = Vec::with_capacity(n);
|
||||
for c in counts {
|
||||
polys.push(points(r, c)?);
|
||||
}
|
||||
p.poly_poly(&polys, true);
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// Arc (0x0817), Pie (0x081A) and Chord (0x0830).
|
||||
fn rec_arc(p: &mut Player, function: u16, r: &mut Reader) -> Option<()> {
|
||||
let (end, start) = (point_yx(r)?, point_yx(r)?);
|
||||
let b = rect_brtl(r)?;
|
||||
let kind = match function {
|
||||
0x0817 => ArcKind::Open,
|
||||
0x081A => ArcKind::Pie,
|
||||
_ => ArcKind::Chord,
|
||||
};
|
||||
p.arc(b, start, end, kind);
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// CreateFontIndirect (0x02FB).
|
||||
fn rec_create_font(p: &mut Player, r: &mut Reader) -> Option<()> {
|
||||
let height = f64::from(r.i16()?);
|
||||
r.skip(2)?;
|
||||
let escapement = f64::from(r.i16()?);
|
||||
r.skip(2)?;
|
||||
let weight = i32::from(r.i16()?);
|
||||
let italic = r.bytes(1)?.first().is_some_and(|b| *b != 0);
|
||||
r.skip(7)?;
|
||||
let face: Vec<u8> = r.rest().iter().take(32).take_while(|b| **b != 0).copied().collect();
|
||||
p.create(Obj::Font(FontObj { height, escapement, weight, italic, face: ansi(&face) }));
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// TextOut (0x0521).
|
||||
fn rec_text_out(p: &mut Player, r: &mut Reader) -> Option<()> {
|
||||
let n = usize::try_from(r.i16()?).ok()?;
|
||||
let s = ansi(r.bytes(n)?);
|
||||
r.skip(n % 2)?;
|
||||
let at = point_yx(r)?;
|
||||
p.text(at, &s);
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// ExtTextOut (0x0A32).
|
||||
fn rec_ext_text_out(p: &mut Player, r: &mut Reader) -> Option<()> {
|
||||
let at = point_yx(r)?;
|
||||
let n = usize::try_from(r.i16()?).ok()?;
|
||||
let opts = r.u16()?;
|
||||
// ETO_OPAQUE or ETO_CLIPPED: a rectangle comes first.
|
||||
if opts & 0x6 != 0 {
|
||||
r.skip(8)?;
|
||||
}
|
||||
let s = ansi(r.bytes(n)?);
|
||||
p.text(at, &s);
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// StretchDIB (0x0F43).
|
||||
fn rec_stretch_dib(p: &mut Player, r: &mut Reader) -> Option<()> {
|
||||
let rop = r.u32()?;
|
||||
r.skip(2)?;
|
||||
let (hs, ws, ys, xs) = (r.i16()?, r.i16()?, r.i16()?, r.i16()?);
|
||||
let (hd, wd, yd, xd) = (r.i16()?, r.i16()?, r.i16()?, r.i16()?);
|
||||
blit(p, rop, (xs, ys, ws, hs), (xd, yd, wd, hd), Some(r.rest()));
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// StretchBlt (0x0B41).
|
||||
fn rec_stretch_blt(p: &mut Player, body: &[u8], r: &mut Reader) -> Option<()> {
|
||||
let rop = r.u32()?;
|
||||
let (hs, ws, ys, xs) = (r.i16()?, r.i16()?, r.i16()?, r.i16()?);
|
||||
// Without a bitmap, a reserved word comes before the destination.
|
||||
let with_bitmap = body.len() > 22;
|
||||
if !with_bitmap {
|
||||
r.skip(2)?;
|
||||
}
|
||||
let (hd, wd, yd, xd) = (r.i16()?, r.i16()?, r.i16()?, r.i16()?);
|
||||
blit(p, rop, (xs, ys, ws, hs), (xd, yd, wd, hd), with_bitmap.then(|| r.rest()));
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// BitBlt (0x0940).
|
||||
fn rec_bit_blt(p: &mut Player, body: &[u8], r: &mut Reader) -> Option<()> {
|
||||
let rop = r.u32()?;
|
||||
let (ys, xs) = (r.i16()?, r.i16()?);
|
||||
let with_bitmap = body.len() > 20;
|
||||
if !with_bitmap {
|
||||
r.skip(2)?;
|
||||
}
|
||||
let (h, w, yd, xd) = (r.i16()?, r.i16()?, r.i16()?, r.i16()?);
|
||||
blit(p, rop, (xs, ys, w, h), (xd, yd, w, h), with_bitmap.then(|| r.rest()));
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// Play one record (`r`: its parameters). `None`: unknown or damaged.
|
||||
fn record(p: &mut Player, function: u16, body: &[u8]) -> Option<()> {
|
||||
let mut r = Reader::new(body);
|
||||
@@ -193,34 +296,14 @@ fn record(p: &mut Player, function: u16, body: &[u8]) -> Option<()> {
|
||||
let pts = points(&mut r, n)?;
|
||||
p.poly(&pts, function == 0x0324, false);
|
||||
}
|
||||
0x0538 => {
|
||||
let n = usize::from(r.u16()?);
|
||||
if r.rest().len() < n * 2 {
|
||||
return None;
|
||||
}
|
||||
let counts: Vec<usize> = (0..n).map(|_| r.u16().map(usize::from)).collect::<Option<_>>()?;
|
||||
let mut polys = Vec::with_capacity(n);
|
||||
for c in counts {
|
||||
polys.push(points(&mut r, c)?);
|
||||
}
|
||||
p.poly_poly(&polys, true);
|
||||
}
|
||||
0x0538 => rec_poly_polygon(p, &mut r)?,
|
||||
0x041B => p.figure(shapes::rectangle(rect_brtl(&mut r)?.abs()).to_bezpath(), true),
|
||||
0x0418 => p.figure(shapes::ellipse(rect_brtl(&mut r)?.abs()).to_bezpath(), true),
|
||||
0x061C => {
|
||||
let (h, w) = (f64::from(r.i16()?), f64::from(r.i16()?));
|
||||
p.figure(super::round_rect(rect_brtl(&mut r)?, w, h), true);
|
||||
}
|
||||
0x0817 | 0x081A | 0x0830 => {
|
||||
let (end, start) = (point_yx(&mut r)?, point_yx(&mut r)?);
|
||||
let b = rect_brtl(&mut r)?;
|
||||
let kind = match function {
|
||||
0x0817 => ArcKind::Open,
|
||||
0x081A => ArcKind::Pie,
|
||||
_ => ArcKind::Chord,
|
||||
};
|
||||
p.arc(b, start, end, kind);
|
||||
}
|
||||
0x0817 | 0x081A | 0x0830 => rec_arc(p, function, &mut r)?,
|
||||
0x0416 => p.clip_rect(rect_brtl(&mut r)?),
|
||||
0x0415 => p.exclude_clip(),
|
||||
0x012D => p.select(u32::from(r.u16()?)),
|
||||
@@ -235,65 +318,14 @@ fn record(p: &mut Player, function: u16, body: &[u8]) -> Option<()> {
|
||||
let style = u32::from(r.u16()?);
|
||||
p.create(Obj::Brush(BrushObj::from_log(style, color(&mut r)?)));
|
||||
}
|
||||
0x02FB => {
|
||||
let height = f64::from(r.i16()?);
|
||||
r.skip(2)?;
|
||||
let escapement = f64::from(r.i16()?);
|
||||
r.skip(2)?;
|
||||
let weight = i32::from(r.i16()?);
|
||||
let italic = r.bytes(1)?.first().is_some_and(|b| *b != 0);
|
||||
r.skip(7)?;
|
||||
let face: Vec<u8> = r.rest().iter().take(32).take_while(|b| **b != 0).copied().collect();
|
||||
p.create(Obj::Font(FontObj { height, escapement, weight, italic, face: ansi(&face) }));
|
||||
}
|
||||
0x02FB => rec_create_font(p, &mut r)?,
|
||||
0x00F7 | 0x06FF => p.create(Obj::Other),
|
||||
0x01F9 | 0x0142 => p.create(Obj::Brush(BrushObj::Pattern)),
|
||||
0x0521 => {
|
||||
let n = usize::try_from(r.i16()?).ok()?;
|
||||
let s = ansi(r.bytes(n)?);
|
||||
r.skip(n % 2)?;
|
||||
let at = point_yx(&mut r)?;
|
||||
p.text(at, &s);
|
||||
}
|
||||
0x0A32 => {
|
||||
let at = point_yx(&mut r)?;
|
||||
let n = usize::try_from(r.i16()?).ok()?;
|
||||
let opts = r.u16()?;
|
||||
// ETO_OPAQUE or ETO_CLIPPED: a rectangle comes first.
|
||||
if opts & 0x6 != 0 {
|
||||
r.skip(8)?;
|
||||
}
|
||||
let s = ansi(r.bytes(n)?);
|
||||
p.text(at, &s);
|
||||
}
|
||||
0x0F43 => {
|
||||
let rop = r.u32()?;
|
||||
r.skip(2)?;
|
||||
let (hs, ws, ys, xs) = (r.i16()?, r.i16()?, r.i16()?, r.i16()?);
|
||||
let (hd, wd, yd, xd) = (r.i16()?, r.i16()?, r.i16()?, r.i16()?);
|
||||
blit(p, rop, (xs, ys, ws, hs), (xd, yd, wd, hd), Some(r.rest()));
|
||||
}
|
||||
0x0B41 => {
|
||||
let rop = r.u32()?;
|
||||
let (hs, ws, ys, xs) = (r.i16()?, r.i16()?, r.i16()?, r.i16()?);
|
||||
// Without a bitmap, a reserved word comes before the destination.
|
||||
let with_bitmap = body.len() > 22;
|
||||
if !with_bitmap {
|
||||
r.skip(2)?;
|
||||
}
|
||||
let (hd, wd, yd, xd) = (r.i16()?, r.i16()?, r.i16()?, r.i16()?);
|
||||
blit(p, rop, (xs, ys, ws, hs), (xd, yd, wd, hd), with_bitmap.then(|| r.rest()));
|
||||
}
|
||||
0x0940 => {
|
||||
let rop = r.u32()?;
|
||||
let (ys, xs) = (r.i16()?, r.i16()?);
|
||||
let with_bitmap = body.len() > 20;
|
||||
if !with_bitmap {
|
||||
r.skip(2)?;
|
||||
}
|
||||
let (h, w, yd, xd) = (r.i16()?, r.i16()?, r.i16()?, r.i16()?);
|
||||
blit(p, rop, (xs, ys, w, h), (xd, yd, w, h), with_bitmap.then(|| r.rest()));
|
||||
}
|
||||
0x0521 => rec_text_out(p, &mut r)?,
|
||||
0x0A32 => rec_ext_text_out(p, &mut r)?,
|
||||
0x0F43 => rec_stretch_dib(p, &mut r)?,
|
||||
0x0B41 => rec_stretch_blt(p, body, &mut r)?,
|
||||
0x0940 => rec_bit_blt(p, body, &mut r)?,
|
||||
0x061D => {
|
||||
let rop = r.u32()?;
|
||||
let (h, w, y, x) = (f64::from(r.i16()?), f64::from(r.i16()?), f64::from(r.i16()?), f64::from(r.i16()?));
|
||||
|
||||
Reference in New Issue
Block a user