mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-15 10:05:42 +00:00
Metafile import: a file that reaches the most objects one file may hold says so
The reader keeps at most 200,000 objects from one file and stops reading there. A picture that reaches that count now carries a warning that any objects after them were not read, and objects dropped past the import's own object limit carry a warning too.
This commit is contained in:
@@ -36,6 +36,13 @@ use crate::{Imported, Kind};
|
||||
|
||||
const PATTERNS: &str = "hatched and pattern brushes are filled with their average color";
|
||||
const ENDS_EARLY: &str = "the file ends early: what it held was imported";
|
||||
const TOO_MANY: &str = "objects past the most one file may hold were left out";
|
||||
const AT_LIMIT: &str = "the file reached the most objects one file may hold: any after them were not read";
|
||||
|
||||
/// The most items `craft_metafile` keeps from one file (its `MAX_ITEMS`). It stops reading at the
|
||||
/// limit and does not say whether more items followed, so a picture holding this many may have
|
||||
/// been cut short.
|
||||
const READER_ITEMS: usize = 200_000;
|
||||
|
||||
/// Points a unit of a WMF without a placeable header (1440 units an inch).
|
||||
const WMF_UNIT: f64 = 72.0 / 1440.0;
|
||||
@@ -243,7 +250,7 @@ impl Mapper {
|
||||
|
||||
fn push(&mut self, clips: Vec<Arc<Clip>>, mut node: Node) {
|
||||
if self.out.len() >= MAX_NODES {
|
||||
return;
|
||||
return self.warn(TOO_MANY);
|
||||
}
|
||||
if !node.visual_bounds().is_none_or(sane) {
|
||||
return self.warn(FAR_AWAY);
|
||||
@@ -526,6 +533,9 @@ pub(crate) fn import(bytes: &[u8]) -> Result<Imported, String> {
|
||||
if ends_early(bytes, kind) {
|
||||
m.warn(ENDS_EARLY);
|
||||
}
|
||||
if pic.items.len() >= READER_ITEMS {
|
||||
m.warn(AT_LIMIT);
|
||||
}
|
||||
for item in pic.items {
|
||||
m.item(item);
|
||||
}
|
||||
|
||||
@@ -370,6 +370,18 @@ fn damaged_files_fail_or_import_partly() {
|
||||
assert!(import(&huge).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_file_with_more_objects_than_are_read_says_so() {
|
||||
// RECTANGLE records: 10 more than the reader keeps, then a few under that.
|
||||
let rect = (43, le(&[0, 0, 100, 100]));
|
||||
let many = hand_emf(5000, 3000, &vec![rect.clone(); 200_010]);
|
||||
let back = import(&many).unwrap();
|
||||
assert_eq!(paths(&back.document).len(), 200_000);
|
||||
assert!(back.warnings.iter().any(|w| w.contains("reached the most objects")), "{:?}", back.warnings);
|
||||
let few = import(&hand_emf(5000, 3000, &vec![rect; 3])).unwrap();
|
||||
assert!(few.warnings.is_empty(), "{:?}", few.warnings);
|
||||
}
|
||||
|
||||
/// An EMR_STRETCHDIBITS copying `png` (a BI_PNG bitmap) to a 10 × 10 box.
|
||||
fn png_stretch_dibits(png: &[u8]) -> Vec<u8> {
|
||||
// Bounds; destination, source and its size; the BITMAPINFO and the bits (from the record start);
|
||||
|
||||
Reference in New Issue
Block a user