mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-12 23:05:05 +00:00
Ruler guides were a list kept beside the layers. Each guide is now an object of its layer or sublayer, always directly in it and above the layer's art. These behave as on main: - Guides draw on screen only. Exports (SVG, PDF, PNG, PSD), Fit All, Select All, the art bounds, clicks and marquees, and a layer's Pathfinder and Transform effects leave them out. The Layers panel lists them as guide rows of their layer, the highest guide.list index first. - Deleting a layer deletes its guides, and merging layers keeps their guides in the merged layer. - The guide commands number guides as guide.list does, in the order they were made. New: each guide takes an id from the document's object ids. An object command given a guide's id fails with an error, and node.move cannot put a guide into a group or out of its layers. A guide made while an opacity mask, a symbol or a pattern is edited moves to the top visible, unlocked layer when editing ends. File format: native files still save the guides in the document's guides list, in every file version, so older builds read them. Each entry may now also carry the guide's id, name, locked and hidden flags; older builds ignore those fields. Opening a file puts each saved guide on its layer (on the top visible, unlocked layer when the file names none or a layer it does not have), and each saved guide counts against the object limit for opening a file. A ruler guide node that a file holds below a layer's art moves up to the layer's guides, and one anywhere else (in a group or another object, beside the layers, or in a symbol) is removed. Ruler guides read from an .ai file become guide objects on the layer they were on, numbered in the order the file lists them.
80 lines
2.8 KiB
Rust
80 lines
2.8 KiB
Rust
//! Document nodes.
|
|
|
|
use std::sync::Arc;
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
use vectorcraft_color::{BlendMode, Color, Paint};
|
|
use vectorcraft_geom::corners::cut_corners;
|
|
use vectorcraft_geom::shapes::{self, CornerKind};
|
|
use vectorcraft_geom::{Affine, BezPath, FillRule, PathData, Point, Rect, Shape};
|
|
|
|
use crate::appearance::Appearance;
|
|
use crate::live::{BlendSpec, EnvelopeKind, GradientMesh, Outliner};
|
|
use crate::pattern::RepeatSpec;
|
|
use crate::symbols::{SYMBOL_SQUARE, SymbolBoxes};
|
|
use crate::text::TextObject;
|
|
|
|
mod attributes;
|
|
mod clip;
|
|
mod extras;
|
|
mod ids;
|
|
mod kind;
|
|
mod live_shape;
|
|
mod opacity;
|
|
mod ops;
|
|
mod wire;
|
|
|
|
pub use attributes::{ForeignAttribute, ImageMap, MAX_SVG_SCRIPTS, ObjectAttributes, SVG_EVENTS};
|
|
pub use clip::{ClipPaint, Uniter};
|
|
pub use extras::{Extras, ExtrasMut, NodeExtras};
|
|
pub use ids::{LAYER_COLORS, LayerColor, NodeId};
|
|
pub use kind::{ImageObject, MAX_BUFFERED_VALUES, NodeKind, with_buffered_value_budget};
|
|
pub use live_shape::{LiveShape, Scaling};
|
|
pub use opacity::{Knockout, OpacityMask, whiten};
|
|
pub use ops::{flattens, keeps_gradient_fit};
|
|
use wire::NodeWire;
|
|
pub(crate) use wire::counted_list;
|
|
pub use wire::{MAX_READ_NODES, with_node_budget};
|
|
|
|
fn yes() -> bool {
|
|
true
|
|
}
|
|
fn one() -> f32 {
|
|
1.0
|
|
}
|
|
|
|
/// One object in the tree. Children are `Arc`s so documents share structure between undo states.
|
|
///
|
|
/// What most objects have is kept inline; what few have is in [`NodeExtras`], allocated only for
|
|
/// the objects that have any of it: every undo step of an edit copies the nodes it changed, so a
|
|
/// small node is a cheap step. Files keep the flat field list either way: a node is written field
|
|
/// by field from where each lives, and read through a flat `NodeWire`.
|
|
#[derive(Clone, Debug, PartialEq, Deserialize)]
|
|
#[serde(from = "NodeWire")]
|
|
pub struct Node {
|
|
pub id: NodeId,
|
|
pub name: Option<String>,
|
|
pub visible: bool,
|
|
pub locked: bool,
|
|
pub opacity: f32,
|
|
pub blend: BlendMode,
|
|
pub isolate: bool,
|
|
/// Knockout Group: whether a container's children knock each other out (see [`Knockout`]).
|
|
pub knockout: Knockout,
|
|
/// Opacity & Mask Define Knockout Shape: inside a knockout group, this object's opacity and
|
|
/// opacity mask scale how much of the objects below it in the group it knocks out.
|
|
pub knockout_shape: bool,
|
|
pub appearance: crate::Shared<Appearance>,
|
|
pub kind: NodeKind,
|
|
/// The angle of the object's own axes, counter-clockwise degrees (0: square to the page): its
|
|
/// bounding box and handles stand at this angle. Transforms turn it with the object (see
|
|
/// [`crate::orient`]); Reset Bounding Box sets it back to 0.
|
|
pub bbox_angle: f64,
|
|
/// The rarely set parts, read with [`Node::extras`] and changed with [`Node::extras_mut`]
|
|
/// (public so that `Node { opacity: 1.0, ..node }` works).
|
|
pub extras: Extras,
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests;
|