mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-07 12:13:19 +00:00
engine, plugins: cap radar dimensions, resume slice-name suffixes, weigh cache keys
This commit is contained in:
committed by
bflatastic
parent
64b1fa5ab2
commit
0cdcf3039b
@@ -244,7 +244,8 @@ impl<'a> Plot<'a> {
|
||||
if marker_cost(g, &designs) > MARKER_BUDGET {
|
||||
designs.clear();
|
||||
}
|
||||
let nser = g.rows.iter().map(Vec::len).max().unwrap_or(0).max(1);
|
||||
// The same dimensions `GraphSpec::cells` reads: raw rows can be longer than the grid they are read through.
|
||||
let nser = g.rows.iter().map(Vec::len).max().unwrap_or(0).clamp(1, vectorcraft_doc::MAX_GRAPH_SERIES);
|
||||
let kinds: Vec<GraphKind> = (0..nser).map(|s| g.series_kind(s)).collect();
|
||||
Plot {
|
||||
g,
|
||||
@@ -253,7 +254,7 @@ impl<'a> Plot<'a> {
|
||||
designs,
|
||||
r: g.rect,
|
||||
nser,
|
||||
ncat: g.rows.len().max(1),
|
||||
ncat: g.rows.len().clamp(1, vectorcraft_doc::MAX_GRAPH_CATEGORIES),
|
||||
vs: label_size(&g.label_styles, Role::Value),
|
||||
cs: label_size(&g.label_styles, Role::Category),
|
||||
ls: label_size(&g.label_styles, Role::Legend),
|
||||
|
||||
@@ -21,7 +21,7 @@ use vectorcraft_render::encode::quantize::{self, Dither, Indexed, PaletteOptions
|
||||
use vectorcraft_render::encode::web::{self, ColorSort};
|
||||
use vectorcraft_render::encode::{gif, jpeg, png};
|
||||
|
||||
use super::{CommandSpec, Result, Session, always, bad, bool_or, cmd, f64_or, has_doc, str_param, unique_name};
|
||||
use super::{CommandSpec, Result, Session, always, bad, bool_or, cmd, f64_or, has_doc, str_param, unique_name_from};
|
||||
|
||||
const C: &str = "document.exportForWeb";
|
||||
|
||||
@@ -866,6 +866,8 @@ pub fn export_files(doc: &Document, selected: &[NodeId], s: &WebSettings, stem:
|
||||
placed.push((None, Some(name)));
|
||||
} else {
|
||||
let mut taken = HashSet::new();
|
||||
// Per base, where the suffix search resumes, so many slices of one name don't each count up from 2.
|
||||
let mut next = std::collections::HashMap::new();
|
||||
for c in &cells {
|
||||
let kind = c.area.id.and_then(|id| doc.slice_options(id)).map(|o| o.kind).unwrap_or_default();
|
||||
if kind != SliceKind::Image {
|
||||
@@ -875,7 +877,7 @@ pub fn export_files(doc: &Document, selected: &[NodeId], s: &WebSettings, stem:
|
||||
let base: String = doc.slice_name(c.area).chars().map(|ch| if ch.is_alphanumeric() || "-_.".contains(ch) { ch } else { '-' }).collect();
|
||||
// A slice named after a Windows device (`aux`, `NUL`…) gets a `-` after the device name.
|
||||
let file = |base: &str| super::fileio::safe_file_name(&format!("{base}.{ext}"));
|
||||
let base = unique_name(&base, |n| taken.contains(&file(n).to_lowercase()));
|
||||
let base = unique_name_from(&base, &mut next, |n| taken.contains(&file(n).to_lowercase()));
|
||||
taken.insert(file(&base).to_lowercase());
|
||||
let name = format!("{IMAGES}/{}", file(&base));
|
||||
let [x0, y0, x1, y1] = c.px;
|
||||
|
||||
@@ -120,8 +120,15 @@ struct Cache {
|
||||
|
||||
static CACHE: Mutex<Option<Cache>> = Mutex::new(None);
|
||||
|
||||
/// Cache units a path takes: its anchors, and one for each subpath's own allocation.
|
||||
fn anchors(p: &PathData) -> usize {
|
||||
p.subpaths.iter().map(|sp| sp.anchors.len()).sum()
|
||||
p.subpaths.iter().map(|sp| sp.anchors.len() + 1).sum()
|
||||
}
|
||||
|
||||
/// Cache units an entry takes: its input and result paths, and the serialized parameters and
|
||||
/// paints its key owns (one unit per [`CACHE_ANCHORS`]'s 50 bytes an anchor stands for).
|
||||
fn weight(key: &Key, out: Option<&PathData>) -> usize {
|
||||
anchors(&key.path) + out.map_or(0, anchors) + (key.params.len() + key.paints.len()) / 50 + 1
|
||||
}
|
||||
static ERRORS: Mutex<Option<HashMap<String, String>>> = Mutex::new(None);
|
||||
|
||||
@@ -168,7 +175,7 @@ pub fn apply(id: &str, params: &Value, path: &PathData, bounds: Rect, rule: Fill
|
||||
}
|
||||
note(id, &r);
|
||||
let out = r.ok();
|
||||
let size = anchors(&key.path) + out.as_ref().map_or(0, anchors);
|
||||
let size = weight(&key, out.as_ref());
|
||||
if size > CACHE_ANCHORS / 4 {
|
||||
return out;
|
||||
}
|
||||
@@ -178,7 +185,7 @@ pub fn apply(id: &str, params: &Value, path: &PathData, bounds: Rect, rule: Fill
|
||||
*cache = Cache::default();
|
||||
}
|
||||
if let Some((old, old_out)) = cache.entries.insert(h, (key, out.clone())) {
|
||||
cache.anchors = cache.anchors.saturating_sub(anchors(&old.path) + old_out.as_ref().map_or(0, anchors));
|
||||
cache.anchors = cache.anchors.saturating_sub(weight(&old, old_out.as_ref()));
|
||||
}
|
||||
cache.anchors += size;
|
||||
out
|
||||
|
||||
Reference in New Issue
Block a user