Add Outer Path, Fix mscv package.json bug

This commit is contained in:
Oliver Davies
2025-04-28 00:31:58 -07:00
parent c78d07eeb0
commit 3287b2d1e5
3 changed files with 112 additions and 21 deletions

View File

@@ -7,7 +7,7 @@
"name": "graphite-web-frontend",
"license": "Apache-2.0",
"dependencies": {
"@tauri-apps/api": "^2.2.0",
"@rollup/rollup-win32-x64-msvc": "^4.40.1",
"class-transformer": "^0.5.1",
"idb-keyval": "^6.2.1",
"reflect-metadata": "^0.2.2"
@@ -989,15 +989,13 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.34.9",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.9.tgz",
"integrity": "sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw==",
"version": "4.40.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.1.tgz",
"integrity": "sha512-ECyOuDeH3C1I8jH2MK1RtBJW+YPMvSfT0a5NN0nHfQYnDSJ6tUiZH3gzwVP5/Kfh/+Tt7tpWVF9LXNTnhTJ3kA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
]
@@ -1050,16 +1048,6 @@
"vite": "^5.0.0"
}
},
"node_modules/@tauri-apps/api": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.2.0.tgz",
"integrity": "sha512-R8epOeZl1eJEl603aUMIGb4RXlhPjpgxbGVEaqY+0G5JG9vzV/clNlzTeqc+NLYXVqXcn8mb4c5b9pJIUDEyAg==",
"license": "Apache-2.0 OR MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/tauri"
}
},
"node_modules/@tsconfig/node10": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
@@ -4668,6 +4656,20 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/rollup/node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.34.9",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.9.tgz",
"integrity": "sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",

View File

@@ -34,6 +34,7 @@
"reflect-metadata": "^0.2.2"
},
"devDependencies": {
"@rollup/rollup-win32-x64-msvc": "^4.40.1",
"@sveltejs/vite-plugin-svelte": "^3.1.2",
"@types/node": "^22.6.1",
"@typescript-eslint/eslint-plugin": "^8.7.0",
@@ -46,17 +47,17 @@
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-svelte": "^2.44.0",
"postcss": "^8.4.47",
"prettier": "^3.3.3",
"prettier-plugin-svelte": "^3.2.6",
"prettier": "^3.3.3",
"process": "^0.11.10",
"rollup-plugin-license": "^3.5.3",
"sass": "1.78.0",
"svelte": "^4.2.19",
"svelte-preprocess": "^6.0.2",
"svelte": "^4.2.19",
"ts-node": "^10.9.2",
"typescript": "^5.6.2",
"vite": "^5.4.14",
"vite-multiple-assets": "1.3.1"
"vite-multiple-assets": "1.3.1",
"vite": "^5.4.14"
},
"//": "The dev dependency for `sass` can be removed once <https://github.com/sveltejs/svelte-preprocess/issues/656> is fixed, but meanwhile we have to",
"///": "list it here and pin it to 1.78.0 so `vite` and `svelte-preprocess` use it instead of 1.79+ which spams the console with deprecation warnings.",

View File

@@ -1,7 +1,7 @@
use super::algorithms::offset_subpath::offset_subpath;
use super::misc::CentroidType;
use super::style::{Fill, Gradient, GradientStops, Stroke};
use super::{PointId, RegionId, SegmentDomain, SegmentId, StrokeId, VectorData, VectorDataTable};
use super::{PointId, SegmentDomain, SegmentId, StrokeId, VectorData, VectorDataTable};
use crate::instances::{InstanceMut, Instances};
use crate::registry::types::{Angle, Fraction, IntegerCount, Length, Multiplier, Percentage, PixelLength, SeedValue};
use crate::renderer::GraphicElementRendered;
@@ -1480,6 +1480,94 @@ async fn offset_path(_: impl Ctx, vector_data: VectorDataTable, distance: f64, l
result
}
#[node_macro::node(category("Vector"), path(graphene_core::vector))]
async fn outer_path(_: impl Ctx, vector_data: VectorDataTable) -> VectorDataTable {
let vector_data_transform = vector_data.transform();
let vector_data = vector_data.one_instance().instance;
// Create a new VectorData to store our result
let mut result = VectorData::empty();
result.style = vector_data.style.clone();
// Collect all closed subpaths with their indices
let subpaths: Vec<_> = vector_data
.stroke_bezier_paths()
.enumerate()
.filter(|(_, subpath)| subpath.closed())
.map(|(i, mut subpath)| {
// Apply transform to work in world space
subpath.apply_transform(vector_data_transform);
(i, subpath)
})
.collect();
if subpaths.is_empty() {
// No closed paths found, return empty result
let mut result_table = VectorDataTable::new(result);
*result_table.transform_mut() = vector_data_transform;
return result_table;
}
// Find the outermost path:
// 1. Start by assuming all subpaths could be the outermost
let mut potential_outer_paths: Vec<_> = subpaths.iter().map(|(i, _)| *i).collect();
// 2. For each subpath, test against all others
for (i, subpath_i) in &subpaths {
// Skip if already eliminated
if !potential_outer_paths.contains(i) {
continue;
}
for (j, subpath_j) in &subpaths {
// Skip comparing to self
if i == j {
continue;
}
// Sample points from subpath_i
let total_points = 20;
let mut contained_points = 0;
// Check several points along subpath_i to see if they're contained in subpath_j
for k in 0..total_points {
let t = k as f64 / total_points as f64;
let point = subpath_i.evaluate(bezier_rs::SubpathTValue::GlobalParametric(t));
if subpath_j.contains_point(point) {
contained_points += 1;
}
}
// If most points from subpath_i are inside subpath_j,
// then subpath_i is not an outer path
if contained_points > total_points / 2 {
potential_outer_paths.retain(|&x| x != *i);
break;
}
}
}
// 3. Among remaining potential outer paths, choose the one with the largest area
if let Some(&outer_index) = potential_outer_paths.iter().max_by(|&&a, &&b| {
let area_a = subpaths.iter().find(|(i, _)| *i == a).map(|(_, s)| s.area(None, None).abs()).unwrap_or(0.0);
let area_b = subpaths.iter().find(|(i, _)| *i == b).map(|(_, s)| s.area(None, None).abs()).unwrap_or(0.0);
area_a.partial_cmp(&area_b).unwrap_or(std::cmp::Ordering::Equal)
}) {
// Find the outer path and add it to the result
if let Some((_, outer_path)) = subpaths.iter().find(|(i, _)| *i == outer_index) {
let mut path_copy = outer_path.clone();
path_copy.apply_transform(vector_data_transform.inverse());
result.append_subpath(path_copy, true);
}
}
// Create the resulting VectorDataTable
let mut result_table = VectorDataTable::new(result);
*result_table.transform_mut() = vector_data_transform;
result_table
}
#[node_macro::node(category("Vector"), path(graphene_core::vector))]
async fn solidify_stroke(_: impl Ctx, vector_data: VectorDataTable) -> VectorDataTable {
let vector_data_transform = vector_data.transform();