mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-11 02:19:56 -06:00
Merge pull request #5569 from dotCooCoo/fix/ai-incomplete-brush-object-counted
.ai import: a brush object without a name counts as a brush left out
This commit is contained in:
@@ -126,8 +126,9 @@ pub(super) enum BrushError {
|
||||
}
|
||||
|
||||
/// The strings of a plug-in object's section (`section`: what follows `%AI8_BeginPluginObject`):
|
||||
/// its plug-in name, its name and its parameters, joined. `None` with fewer than two strings.
|
||||
pub(super) fn plugin_strings(section: &[u8]) -> Option<(String, String, String)> {
|
||||
/// its plug-in name, its name and its parameters, joined. The name is `None` with one string, and
|
||||
/// the whole is `None` with none.
|
||||
pub(super) fn plugin_strings(section: &[u8]) -> Option<(String, Option<String>, String)> {
|
||||
let mut lex = Lexer::new(section);
|
||||
let mut strings = vec![];
|
||||
let mut params = vec![];
|
||||
@@ -142,8 +143,9 @@ pub(super) fn plugin_strings(section: &[u8]) -> Option<(String, String, String)>
|
||||
}
|
||||
}
|
||||
}
|
||||
let [kind, name]: [String; 2] = strings.try_into().ok()?;
|
||||
Some((kind, name, obj::text(¶ms)))
|
||||
let mut strings = strings.into_iter();
|
||||
let kind = strings.next()?;
|
||||
Some((kind, strings.next(), obj::text(¶ms)))
|
||||
}
|
||||
|
||||
/// The brush manager's order (`params`: its parameters): the kind and name of each brush. Pairs
|
||||
|
||||
@@ -518,16 +518,23 @@ impl<'a> Reader<'a> {
|
||||
}
|
||||
|
||||
/// A plug-in object (`section`: what follows `%AI8_BeginPluginObject`): the brush manager's
|
||||
/// order or a brush ([`brush`]); other objects are left alone.
|
||||
/// order or a brush ([`brush`]); other objects are left alone. A brush without a name is counted
|
||||
/// as not read.
|
||||
fn plugin_object(&mut self, section: &[u8]) {
|
||||
let Some((kind, name, params)) = brush::plugin_strings(section) else { return };
|
||||
if kind == brush::MANAGER {
|
||||
self.brush_objects = true;
|
||||
self.brush_order = brush::parse_brush_manager(¶ms);
|
||||
if name.is_some() {
|
||||
self.brush_objects = true;
|
||||
self.brush_order = brush::parse_brush_manager(¶ms);
|
||||
}
|
||||
return;
|
||||
}
|
||||
let Some(tool) = brush::tool(&kind) else { return };
|
||||
self.brush_objects = true;
|
||||
let Some(name) = name else {
|
||||
self.brushes_unread += 1;
|
||||
return;
|
||||
};
|
||||
if self.brush_drafts.len() >= brush::MAX_BRUSHES {
|
||||
self.brushes_unread += 1;
|
||||
return;
|
||||
|
||||
@@ -5224,6 +5224,20 @@ fn a_file_whose_brushes_are_all_left_out_has_none() {
|
||||
assert!(vectorcraft_brush::library(&r.doc).is_empty());
|
||||
}
|
||||
|
||||
/// A brush object that ends after its plug-in name is counted as a brush left out, and the file
|
||||
/// gets no default brushes.
|
||||
#[test]
|
||||
fn a_brush_object_without_a_name_is_counted_as_left_out() {
|
||||
let nameless = format!("%AI5_Begin_NonPrinting\nNp\n%AI8_BeginPluginObject\n({CALLIGRAPHIC})\n%AI8_EndPluginObject\n%AI5_End_NonPrinting--\n");
|
||||
let r = read_ok(&format!("{nameless}{}", layer("")));
|
||||
assert!(vectorcraft_brush::library(&r.doc).is_empty(), "{:?}", r.warnings);
|
||||
assert!(r.warnings.iter().any(|w| w.ends_with("Brushes panel (1)")), "{:?}", r.warnings);
|
||||
let r = read_ok(&format!("{}{nameless}{}", plugin_object(CALLIGRAPHIC, "Nib", NIB), layer("")));
|
||||
let lib = vectorcraft_brush::library(&r.doc);
|
||||
assert_eq!(lib.iter().map(|b| b.name.as_str()).collect::<Vec<_>>(), ["Nib"], "{:?}", r.warnings);
|
||||
assert!(r.warnings.iter().any(|w| w.ends_with("Brushes panel (1)")), "{:?}", r.warnings);
|
||||
}
|
||||
|
||||
/// A gradient's `Br` (a stop's ramp) isn't a brush: the gradient keeps its stops.
|
||||
#[test]
|
||||
fn a_gradients_br_is_not_a_brush() {
|
||||
|
||||
Reference in New Issue
Block a user