Skip to content

Commit 00fa3c6

Browse files
simonwuelkerKeavon
andcommitted
Add documentation to many parts of the Rust codebase (#552)
* add lots of doccomments * add conversion traits from layerdatatypes to layers * add suggested doc improvements * Code review changes Co-authored-by: Keavon Chambers <[email protected]>
1 parent 3e37940 commit 00fa3c6

File tree

13 files changed

+470
-21
lines changed

13 files changed

+470
-21
lines changed

graphene/src/document.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@ use std::cmp::max;
1616
use std::collections::hash_map::DefaultHasher;
1717
use std::hash::{Hash, Hasher};
1818

19+
/// A number that identifies a layer.
20+
/// This does not technically need to be unique globally, only within a folder.
1921
pub type LayerId = u64;
2022

2123
#[derive(Debug, Clone, Deserialize, Serialize)]
2224
pub struct Document {
25+
/// The root layer, usually a [FolderLayer](layers::folder_layer::FolderLayer) that contains all other [Layers](layers::layer_info::Layer).
2326
pub root: Layer,
2427
/// The state_identifier serves to provide a way to uniquely identify a particular state that the document is in.
2528
/// This identifier is not a hash and is not guaranteed to be equal for equivalent documents.
@@ -338,6 +341,7 @@ impl Document {
338341
boxes.reduce(|a, b| [a[0].min(b[0]), a[1].max(b[1])])
339342
}
340343

344+
/// Mark the layer at the provided path, as well as all the folders containing it, as dirty.
341345
pub fn mark_upstream_as_dirty(&mut self, path: &[LayerId]) -> Result<(), DocumentError> {
342346
let mut root = &mut self.root;
343347
root.cache_dirty = true;

graphene/src/error.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use super::LayerId;
22
use crate::boolean_ops::BooleanOperationError;
33

4+
/// A set of different errors that can occur when using Graphene.
45
#[derive(Debug, Clone, PartialEq)]
56
pub enum DocumentError {
67
LayerNotFound(Vec<LayerId>),

graphene/src/intersection.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,17 @@ use glam::{DAffine2, DMat2, DVec2};
1010
use kurbo::{BezPath, CubicBez, Line, ParamCurve, ParamCurveExtrema, PathSeg, Point, QuadBez, Rect, Shape, Vec2};
1111

1212
#[derive(Debug, Clone, Default, Copy)]
13+
/// A quad defined by four vertices.
1314
pub struct Quad([DVec2; 4]);
1415

1516
impl Quad {
17+
/// Convert a box defined by two corner points to a quad.
1618
pub fn from_box(bbox: [DVec2; 2]) -> Self {
1719
let size = bbox[1] - bbox[0];
1820
Self([bbox[0], bbox[0] + size * DVec2::X, bbox[1], bbox[0] + size * DVec2::Y])
1921
}
2022

23+
/// Get all the edges in the quad.
2124
pub fn lines(&self) -> [Line; 4] {
2225
[
2326
Line::new(to_point(self.0[0]), to_point(self.0[1])),
@@ -27,6 +30,7 @@ impl Quad {
2730
]
2831
}
2932

33+
/// Generate a [BezPath] of the quad
3034
pub fn path(&self) -> BezPath {
3135
let mut path = kurbo::BezPath::new();
3236
path.move_to(to_point(self.0[0]));
@@ -54,6 +58,11 @@ fn to_point(vec: DVec2) -> Point {
5458
Point::new(vec.x, vec.y)
5559
}
5660

61+
/// Return `true` if `quad` intersects `shape`.
62+
/// This is the case if any of the following conditions are true:
63+
/// * the edges of `quad` and `shape` intersect
64+
/// * `shape` is entirely contained within `quad`
65+
/// * `filled` is `true` and `quad` is entirely contained within `shape`.
5766
pub fn intersect_quad_bez_path(quad: Quad, shape: &BezPath, filled: bool) -> bool {
5867
let mut shape = shape.clone();
5968
// for filled shapes act like shape was closed even if it isn't
@@ -74,6 +83,8 @@ pub fn intersect_quad_bez_path(quad: Quad, shape: &BezPath, filled: bool) -> boo
7483
get_arbitrary_point_on_path(&shape).map(|shape_point| quad.path().contains(shape_point)).unwrap_or_default()
7584
}
7685

86+
/// Returns a point on `path`.
87+
/// This function will usually return the first point from the path's first segment, but callers should not rely on this behavior.
7788
pub fn get_arbitrary_point_on_path(path: &BezPath) -> Option<Point> {
7889
path.segments().next().map(|seg| match seg {
7990
PathSeg::Line(line) => line.p0,
@@ -640,7 +651,7 @@ pub fn quad_line_intersect(a: &Line, b: &QuadBez) -> [Option<f64>; 2] {
640651
}
641652

642653
/// Returns real roots to cubic equation: `f(t) = a0 + t*a1 + t^2*a2 + t^3*a3`.
643-
/// This function uses the Cardano-Viete and Numerical Recipes algorithm, found here: https://quarticequations.com/Cubic.pdf
654+
/// This function uses the Cardano-Viete and Numerical Recipes algorithm, found here: <https://quarticequations.com/Cubic.pdf>
644655
pub fn cubic_real_roots(mut a0: f64, mut a1: f64, mut a2: f64, a3: f64) -> [Option<f64>; 3] {
645656
use std::f64::consts::FRAC_PI_3 as PI_3;
646657

graphene/src/layers/blend_mode.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use serde::{Deserialize, Serialize};
22

3+
/// Describes how overlapping SVG elements should be blended together.
4+
/// See the [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/CSS/blend-mode#examples) for examples.
35
#[derive(PartialEq, Copy, Clone, Debug, Serialize, Deserialize)]
46
pub enum BlendMode {
57
Normal,
@@ -21,6 +23,8 @@ pub enum BlendMode {
2123
}
2224

2325
impl BlendMode {
26+
/// Convert the enum to the CSS string for the blend mode.
27+
/// [Read more](https://developer.mozilla.org/en-US/docs/Web/CSS/blend-mode#values)
2428
pub fn to_svg_style_name(&self) -> &str {
2529
match self {
2630
BlendMode::Normal => "normal",

graphene/src/layers/folder_layer.rs

Lines changed: 108 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,16 @@ use glam::DVec2;
77
use serde::{Deserialize, Serialize};
88
use std::fmt::Write;
99

10+
/// A layer that encapsulates other layers, including potentially more folders.
11+
/// The contained layers are rendered in the same order they are
12+
/// stored in the [layers](FolderLayer::layers) field.
1013
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Default)]
1114
pub struct FolderLayer {
15+
/// The ID that will be assigned to the next layer that is added to the folder
1216
next_assignment_id: LayerId,
17+
/// The IDs of the [Layer]s contained within the Folder
1318
pub layer_ids: Vec<LayerId>,
19+
/// The [Layer]s contained in the folder
1420
layers: Vec<Layer>,
1521
}
1622

@@ -38,12 +44,29 @@ impl LayerData for FolderLayer {
3844
}
3945

4046
impl FolderLayer {
41-
/// When a insertion id is provided, try to insert the layer with the given id.
42-
/// If that id is already used, return None.
43-
/// When no insertion id is provided, search for the next free id and insert it with that.
44-
/// Negative values for insert_index represent distance from the end
47+
/// When a insertion ID is provided, try to insert the layer with the given ID.
48+
/// If that ID is already used, return `None`.
49+
/// When no insertion ID is provided, search for the next free ID and insert it with that.
50+
/// Negative values for `insert_index` represent distance from the end
51+
///
52+
/// # Example
53+
/// ```
54+
/// # use graphite_graphene::layers::shape_layer::ShapeLayer;
55+
/// # use graphite_graphene::layers::folder_layer::FolderLayer;
56+
/// # use graphite_graphene::layers::style::PathStyle;
57+
/// # use graphite_graphene::layers::layer_info::LayerDataType;
58+
/// let mut folder = FolderLayer::default();
59+
///
60+
/// // Create two layers to be added to the folder
61+
/// let mut shape_layer = ShapeLayer::rectangle(PathStyle::default());
62+
/// let mut folder_layer = FolderLayer::default();
63+
///
64+
/// folder.add_layer(shape_layer.into(), None, -1);
65+
/// folder.add_layer(folder_layer.into(), Some(123), 0);
66+
/// ```
4567
pub fn add_layer(&mut self, layer: Layer, id: Option<LayerId>, insert_index: isize) -> Option<LayerId> {
4668
let mut insert_index = insert_index as i128;
69+
4770
if insert_index < 0 {
4871
insert_index = self.layers.len() as i128 + insert_index as i128 + 1;
4972
}
@@ -71,22 +94,42 @@ impl FolderLayer {
7194
}
7295
}
7396

97+
/// Remove a layer with a given ID from the folder.
98+
/// This operation will fail if `id` is not present in the folder.
99+
///
100+
/// # Example
101+
/// ```
102+
/// # use graphite_graphene::layers::folder_layer::FolderLayer;
103+
/// let mut folder = FolderLayer::default();
104+
///
105+
/// // Try to remove a layer that does not exist
106+
/// assert!(folder.remove_layer(123).is_err());
107+
///
108+
/// // Add another folder to the folder
109+
/// folder.add_layer(FolderLayer::default().into(), Some(123), -1);
110+
///
111+
/// // Try to remove that folder again
112+
/// assert!(folder.remove_layer(123).is_ok());
113+
/// assert_eq!(folder.layers().len(), 0)
114+
/// ```
74115
pub fn remove_layer(&mut self, id: LayerId) -> Result<(), DocumentError> {
75116
let pos = self.position_of_layer(id)?;
76117
self.layers.remove(pos);
77118
self.layer_ids.remove(pos);
78119
Ok(())
79120
}
80121

81-
/// Returns a list of layers in the folder
122+
/// Returns a list of [LayerId]s in the folder.
82123
pub fn list_layers(&self) -> &[LayerId] {
83124
self.layer_ids.as_slice()
84125
}
85126

127+
/// Get references to all the [Layer]s in the folder.
86128
pub fn layers(&self) -> &[Layer] {
87129
self.layers.as_slice()
88130
}
89131

132+
/// Get mutable references to all the [Layer]s in the folder.
90133
pub fn layers_mut(&mut self) -> &mut [Layer] {
91134
self.layers.as_mut_slice()
92135
}
@@ -101,14 +144,70 @@ impl FolderLayer {
101144
Some(&mut self.layers[pos])
102145
}
103146

147+
/// Returns `true` if the folder contains a layer with the given [LayerId].
148+
///
149+
/// # Example
150+
/// ```
151+
/// # use graphite_graphene::layers::folder_layer::FolderLayer;
152+
/// let mut folder = FolderLayer::default();
153+
///
154+
/// // Search for an id that does not exist
155+
/// assert!(!folder.folder_contains(123));
156+
///
157+
/// // Add layer with the id "123" to the folder
158+
/// folder.add_layer(FolderLayer::default().into(), Some(123), -1);
159+
///
160+
/// // Search for the id "123"
161+
/// assert!(folder.folder_contains(123));
162+
/// ```
104163
pub fn folder_contains(&self, id: LayerId) -> bool {
105164
self.layer_ids.contains(&id)
106165
}
107166

167+
/// Tries to find the index of a layer with the given [LayerId] within the folder.
168+
/// This operation will fail if no layer with a matching ID is present in the folder.
169+
///
170+
/// # Example
171+
/// ```
172+
/// # use graphite_graphene::layers::folder_layer::FolderLayer;
173+
/// let mut folder = FolderLayer::default();
174+
///
175+
/// // Search for an id that does not exist
176+
/// assert!(folder.position_of_layer(123).is_err());
177+
///
178+
/// // Add layer with the id "123" to the folder
179+
/// folder.add_layer(FolderLayer::default().into(), Some(123), -1);
180+
/// folder.add_layer(FolderLayer::default().into(), Some(42), -1);
181+
///
182+
/// assert_eq!(folder.position_of_layer(123), Ok(0));
183+
/// assert_eq!(folder.position_of_layer(42), Ok(1));
184+
/// ```
108185
pub fn position_of_layer(&self, layer_id: LayerId) -> Result<usize, DocumentError> {
109186
self.layer_ids.iter().position(|x| *x == layer_id).ok_or_else(|| DocumentError::LayerNotFound([layer_id].into()))
110187
}
111188

189+
/// Tries to get a reference to a folder with the given [LayerId].
190+
/// This operation will return `None` if either no layer with `id` exists
191+
/// in the folder, or the layer with matching ID is not a folder.
192+
///
193+
/// # Example
194+
/// ```
195+
/// # use graphite_graphene::layers::folder_layer::FolderLayer;
196+
/// # use graphite_graphene::layers::shape_layer::ShapeLayer;
197+
/// # use graphite_graphene::layers::style::PathStyle;
198+
/// let mut folder = FolderLayer::default();
199+
///
200+
/// // Search for an id that does not exist
201+
/// assert!(folder.folder(132).is_none());
202+
///
203+
/// // add a folder and search for it
204+
/// folder.add_layer(FolderLayer::default().into(), Some(123), -1);
205+
/// assert!(folder.folder(123).is_some());
206+
///
207+
/// // add a non-folder layer and search for it
208+
/// folder.add_layer(ShapeLayer::rectangle(PathStyle::default()).into(), Some(42), -1);
209+
/// assert!(folder.folder(42).is_none());
210+
/// ```
112211
pub fn folder(&self, id: LayerId) -> Option<&FolderLayer> {
113212
match self.layer(id) {
114213
Some(Layer {
@@ -118,6 +217,10 @@ impl FolderLayer {
118217
}
119218
}
120219

220+
/// Tries to get a mutable reference to folder with the given `id`.
221+
/// This operation will return `None` if either no layer with `id` exists
222+
/// in the folder or the layer with matching ID is not a folder.
223+
/// See the [FolderLayer::folder] method for a usage example.
121224
pub fn folder_mut(&mut self, id: LayerId) -> Option<&mut FolderLayer> {
122225
match self.layer_mut(id) {
123226
Some(Layer {

0 commit comments

Comments
 (0)