Refactor internal shape and reduce reliance on Kurbo (#617)

* Dissolve Points from path

* Add handling for removing the first anchor

* Add function to turn handles into bez_paths

* Created overlay manager, wip

* WIP Refactor of VectorShape / Overlays / ShapeEditor

* WIP stripping vector shape, anchor, point.

* WIP Removed kurbo deps from vector shape, anchor, point

* WIP Further work to make vector shapes / anchors / points more standalone.

* WIP more pruning

* WIP Progress on overlay_renderer

* WIP more overlay_renderer work

* WIP more pruning, cleared warnings

* WIP decided ShapeRenderer wasn't an accurate name, ShapeAdapter now. Error squashing continues.

* WIP squashed more errors, now need to decide if anchors should have unique IDs

* WIP Errors squashed, now to actually make it work.

* WIP Moved vector structs to graphene, beginning to remove bezpath from shape_layer

* Refactoring: disentangle kurbo from apply_affine

* Refactor internal shape and remove reliance on Kurbo (PR #617) - Disentangle Kurbo (#619)

* Refactoring: disentangle kurbo from apply_affine

* Broke boolean operations, refactor in state which compiles

* "fixed" boolean operation refactor related errors

* fixed apply_affine, which would not have applied any type of affine

* Small Cleanup, readability

* Fix issue with overlay styles no longer showing selection state.

* Resolved error with point option

* WIP, figuring out how to have one source of truth for VectorShape. Trying to avoid cloning.

* WIP work on single source of truth vectorshapes

* More steps toward single source of truth VectorShape

* Continued wip on making VectorShapes mutably accessible without cloning

* Wip using paths to reference vectorshapes instead, need to restructure ShapeEditor

* Decided to allow temporary copies of vectorshapes.

* Removed HashSet for selected shape indices

* Added @TrueDoctor's id_storage.rs with some heavy modification. Added it to VectorShape. Isn't yet used for folders.

* Integrated UniqueElements<T> with VectorShape to store VectorAnchors

* Improved storage_id.rs perf and cleaned up it's interface

* Iterator Implementations and fixes (#637)

* Refactoring: disentangle kurbo from apply_affine

* Broke boolean operations, refactor in state which compiles

* "fixed" boolean operation refactor related errors

* fixed apply_affine, which would not have applied any type of affine

* implemented transforms for VectorAnchors
implemented Not for VectorControlPointType

* started adding Vector Shape implementations of shape prototypes

* added several useful implemtations to UniqueElements

* added another implemnation for UniqueElements to make working with iterators easier, fixed vector-shape errors

* package-lock.json

* clean up rebase, added back Layer paths

* added deref implementation for VectorShape

* unnecesary variable

* simplify code by removing levels of indirection

* fixed errors

* merge cleanup

* removed package-lock.json

* Removed .selected from VectorShape, it isn't needed as layers are selected not shapes specifically.

* Removed transform and layer_path from VectorShape

* Auto-saving tentitively working. Work toward Overlay transform issues.

* Overlays properly hiding and caching. Not clearing cache yet and some tool switching issues remain, but progress.

* Putting layers in folders changes their unique ID. This is problematic. Assumed this was not the case.

* Removed need for closed bool, changed VectorShape to a tuple struct.

* WIP Switched to layer paths as opposed to VectorShapes. Next up add messages for changing VectorShapes.

* Added initial messages to edit VectorShape points.

* DeleteSelectedPoints messages implemented, selection isn't working currently though.

* Selection messages arriving in document, but transform is wrong.

* Selection, Deselection working, delete working for first point.

* Working towards moving points again

* Removed extra vec from UniqueElements, attempting to squash ordering bug. Still appears to occur though.

* Delete more stable, clean up, renamed to HandleIn, HandleOut

* Further vec_unique cleanup

* Further cleanup

* Removed Deref / DerefMut from VectorShape

* Document version++, will likely revert before merge into master

* Seleting / deleting handles tentitively working again.

* Version number bump, fixed tests.

* Fixed comment in VecUnique

* Improved VecUnique descriptor comment

* Renamed VecUnique to IdBackedVec to further clarify usage.

* Resolved formatting.

* WIP Fixing dragging points

* Fixed an instance where an OverlayMessage could be sent to the main document incorrectly.

* Deleting all of a shapes points now gracefully deletes the layer instead of crashing.

* Fixed handle configurations that would panic on deletion

* Single anchor dragging restored with multi-dragging next plus handles

* sides.into()

* Handle and Multi-point dragging working

* WIP Handle symmetry working again

* Handle mirroring functional again.

* Cleaned up warnings

* Fixed overlay outline not matching shape

* Git branch fix of compatibility with new master

* Fixed closed shape bug, replaced kurbo ellipse

* Removed unused func, updated comments

* Deleting points can undo, multiple shape selection deletes now working

* Removed AddOverlay* operations

* Partial fix for select drift, added helpers

* Don't snap against dragging points

* Properly cleanup path outline with multiple shapes

* Clear all points in other selected shapes

* Actually don't snap against dragging points

* Fix path tool & add snap angle and break handle

* Fix handle being set to NaN causing render issues

* Fix cached overlays not showing line -> curve

* Add operations for modifying paths

* Remove kurbo from pen tool

* Do not snap against handles when anchor selected

* Fix overlays not being cleaned up on path tool

* Fix handle position after dragging

* Use `Anchor` for text & no kurbo in operations

* Replace kurbo to_svg function

* Ngon no longer center scales by default, still some weird behaviour when holding alt

* Cleanup overlays

* Fix render and bounding box doctests

* Fix fun to_svg error

* Fix compile error

* Some code review

* Remove legacy `SelectPoint` on doubleclick

* Remove font from test document

* Fix the pen tool selection changed

* Reorder imports

Co-authored-by: Dennis <dennis@kobert.dev>
Co-authored-by: Caleb Dennis <caleb.dennis429@gmail.com>
Co-authored-by: caleb <56044292+caleb-ad@users.noreply.github.com>
Co-authored-by: Keavon Chambers <keavon@keavon.com>
Co-authored-by: 0hypercube <0hypercube@gmail.com>
Co-authored-by: 0HyperCube <78500760+0HyperCube@users.noreply.github.com>
This commit is contained in:
Oliver Davies
2022-07-05 15:02:18 -07:00
committed by Keavon Chambers
co-authored by Dennis Caleb Dennis caleb Keavon Chambers 0hypercube 0HyperCube
parent 3c2fff4465
commit 58675eb64d
48 changed files with 2461 additions and 1807 deletions
+18 -26
View File
@@ -1,21 +1,17 @@
use super::layer_info::LayerData;
use super::style::{PathStyle, RenderData, ViewMode};
use super::vector::vector_shape::VectorShape;
use crate::intersection::{intersect_quad_bez_path, Quad};
use crate::LayerId;
pub use font_cache::{Font, FontCache};
use glam::{DAffine2, DMat2, DVec2};
use kurbo::{Affine, BezPath, Rect, Shape};
use rustybuzz::Face;
use serde::{Deserialize, Serialize};
use std::fmt::Write;
mod font_cache;
mod to_kurbo;
fn glam_to_kurbo(transform: DAffine2) -> Affine {
Affine::new(transform.to_cols_array())
}
mod to_path;
/// A line, or multiple lines, of text drawn in the document.
/// Like [ShapeLayers](super::shape_layer::ShapeLayer), [TextLayer] are rendered as
@@ -33,7 +29,7 @@ pub struct TextLayer {
#[serde(skip)]
pub editable: bool,
#[serde(skip)]
pub cached_path: Option<BezPath>,
pub cached_path: Option<VectorShape>,
}
impl LayerData for TextLayer {
@@ -72,12 +68,12 @@ impl LayerData for TextLayer {
} else {
let buzz_face = self.load_face(render_data.font_cache);
let mut path = self.to_bez_path(buzz_face);
let mut path = self.to_vector_path(buzz_face);
let kurbo::Rect { x0, y0, x1, y1 } = path.bounding_box();
let bounds = [(x0, y0).into(), (x1, y1).into()];
path.apply_affine(glam_to_kurbo(transform));
path.apply_affine(transform);
let kurbo::Rect { x0, y0, x1, y1 } = path.bounding_box();
let transformed_bounds = [(x0, y0).into(), (x1, y1).into()];
@@ -95,21 +91,17 @@ impl LayerData for TextLayer {
fn bounding_box(&self, transform: glam::DAffine2, font_cache: &FontCache) -> Option<[DVec2; 2]> {
let buzz_face = Some(self.load_face(font_cache)?);
let mut path = self.bounding_box(&self.text, buzz_face).to_path(0.1);
if transform.matrix2 == DMat2::ZERO {
return None;
}
path.apply_affine(glam_to_kurbo(transform));
let kurbo::Rect { x0, y0, x1, y1 } = path.bounding_box();
Some([(x0, y0).into(), (x1, y1).into()])
Some((transform * self.bounding_box(&self.text, buzz_face)).bounding_box())
}
fn intersects_quad(&self, quad: Quad, path: &mut Vec<LayerId>, intersections: &mut Vec<Vec<LayerId>>, font_cache: &FontCache) {
let buzz_face = self.load_face(font_cache);
if intersect_quad_bez_path(quad, &self.bounding_box(&self.text, buzz_face).to_path(0.), true) {
if intersect_quad_bez_path(quad, &self.bounding_box(&self.text, buzz_face).path(), true) {
intersections.push(path.clone());
}
}
@@ -144,10 +136,10 @@ impl TextLayer {
new
}
/// Converts to a [BezPath], populating the cache if necessary.
/// Converts to a [VectorShape], populating the cache if necessary.
#[inline]
pub fn to_bez_path(&mut self, buzz_face: Option<Face>) -> BezPath {
if self.cached_path.as_ref().filter(|x| !x.is_empty()).is_none() {
pub fn to_vector_path(&mut self, buzz_face: Option<Face>) -> VectorShape {
if self.cached_path.as_ref().filter(|x| !x.anchors().is_empty()).is_none() {
let path = self.generate_path(buzz_face);
self.cached_path = Some(path.clone());
return path;
@@ -155,23 +147,23 @@ impl TextLayer {
self.cached_path.clone().unwrap()
}
/// Converts to a [BezPath], without populating the cache.
/// Converts to a [VectorShape], without populating the cache.
#[inline]
pub fn to_bez_path_nonmut(&self, font_cache: &FontCache) -> BezPath {
pub fn to_vector_path_nonmut(&self, font_cache: &FontCache) -> VectorShape {
let buzz_face = self.load_face(font_cache);
self.cached_path.clone().filter(|x| !x.is_empty()).unwrap_or_else(|| self.generate_path(buzz_face))
self.cached_path.clone().filter(|x| !x.anchors().is_empty()).unwrap_or_else(|| self.generate_path(buzz_face))
}
#[inline]
pub fn generate_path(&self, buzz_face: Option<Face>) -> BezPath {
to_kurbo::to_kurbo(&self.text, buzz_face, self.size, self.line_width)
pub fn generate_path(&self, buzz_face: Option<Face>) -> VectorShape {
to_path::to_path(&self.text, buzz_face, self.size, self.line_width)
}
#[inline]
pub fn bounding_box(&self, text: &str, buzz_face: Option<Face>) -> Rect {
let far = to_kurbo::bounding_box(text, buzz_face, self.size, self.line_width);
Rect::new(0., 0., far.x, far.y)
pub fn bounding_box(&self, text: &str, buzz_face: Option<Face>) -> Quad {
let far = to_path::bounding_box(text, buzz_face, self.size, self.line_width);
Quad::from_box([DVec2::ZERO, far])
}
pub fn update_text(&mut self, text: String, font_cache: &FontCache) {