Skip to content

Commit

Permalink
Merge branch 'main' into libadw-1-4-migration
Browse files Browse the repository at this point in the history
  • Loading branch information
flxzt committed Aug 16, 2023
2 parents 3e1b064 + 2d249be commit 674c106
Show file tree
Hide file tree
Showing 31 changed files with 921 additions and 202 deletions.
11 changes: 9 additions & 2 deletions crates/rnote-compose/src/builders/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ mod penpathbuildable;
mod penpathcurvedbuilder;
mod penpathmodeledbuilder;
mod penpathsimplebuilder;
mod polylinebuilder;
mod quadbezbuilder;
mod quadrantcoordsystem2dbuilder;
mod rectanglebuilder;
Expand All @@ -31,6 +32,7 @@ pub use penpathbuildable::PenPathBuilderProgress;
pub use penpathcurvedbuilder::PenPathCurvedBuilder;
pub use penpathmodeledbuilder::PenPathModeledBuilder;
pub use penpathsimplebuilder::PenPathSimpleBuilder;
pub use polylinebuilder::PolylineBuilder;
pub use quadbezbuilder::QuadBezBuilder;
pub use quadrantcoordsystem2dbuilder::QuadrantCoordSystem2DBuilder;
pub use rectanglebuilder::RectangleBuilder;
Expand Down Expand Up @@ -75,12 +77,15 @@ pub enum ShapeBuilderType {
/// A foci ellipse builder
#[serde(rename = "foci_ellipse")]
FociEllipse,
/// An quadbez builder
/// A quadbez builder
#[serde(rename = "quadbez")]
QuadBez,
/// An cubic bezier builder
/// A cubic bezier builder
#[serde(rename = "cubbez")]
CubBez,
/// A poyline builder
#[serde(rename = "polyline")]
Polyline,
}

impl ShapeBuilderType {
Expand All @@ -98,6 +103,7 @@ impl ShapeBuilderType {
"shapebuilder-fociellipse-symbolic" => Some(Self::FociEllipse),
"shapebuilder-quadbez-symbolic" => Some(Self::QuadBez),
"shapebuilder-cubbez-symbolic" => Some(Self::CubBez),
"shapebuilder-polyline-symbolic" => Some(Self::Polyline),
_ => None,
}
}
Expand All @@ -118,6 +124,7 @@ impl ShapeBuilderType {
Self::FociEllipse => String::from("shapebuilder-fociellipse-symbolic"),
Self::QuadBez => String::from("shapebuilder-quadbez-symbolic"),
Self::CubBez => String::from("shapebuilder-cubbez-symbolic"),
Self::Polyline => String::from("shapebuilder-polyline-symbolic"),
}
}
}
Expand Down
153 changes: 153 additions & 0 deletions crates/rnote-compose/src/builders/polylinebuilder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// Imports
use super::shapebuildable::{ShapeBuilderCreator, ShapeBuilderProgress};
use super::ShapeBuildable;
use crate::constraints::ConstraintRatio;
use crate::penevents::{KeyboardKey, PenEvent, PenState};
use crate::penpath::Element;
use crate::shapes::Polyline;
use crate::style::{indicators, Composer};
use crate::Constraints;
use crate::{Shape, Style};
use p2d::bounding_volume::{Aabb, BoundingVolume};
use piet::RenderContext;
use std::time::Instant;

/// Line builder.
#[derive(Debug, Clone)]
pub struct PolylineBuilder {
/// Start position.
start: na::Vector2<f64>,
/// Position of the next/current path segment.
current: na::Vector2<f64>,
/// Path.
path: Vec<na::Vector2<f64>>,
/// Pen state.
pen_state: PenState,
/// Pen position.
pen_pos: na::Vector2<f64>,
/// Finish the polyline on the next `PenEvent::Up`.
finish: bool,
}

impl ShapeBuilderCreator for PolylineBuilder {
fn start(element: Element, _now: Instant) -> Self {
Self {
start: element.pos,
current: element.pos,
path: Vec::new(),
pen_state: PenState::Down,
pen_pos: element.pos,
finish: false,
}
}
}

impl ShapeBuildable for PolylineBuilder {
fn handle_event(
&mut self,
event: PenEvent,
_now: Instant,
mut constraints: Constraints,
) -> ShapeBuilderProgress {
// we always want to allow horizontal and vertical constraints while building a polyline
constraints.ratios.insert(ConstraintRatio::Horizontal);
constraints.ratios.insert(ConstraintRatio::Vertical);

match event {
PenEvent::Down { element, .. } => {
if (self.pen_state == PenState::Up || self.pen_state == PenState::Proximity)
&& self.pos_in_finish(element.pos)
{
self.finish = true;
}
self.pen_state = PenState::Down;
self.pen_pos = element.pos;
let last_pos = self.path.last().copied().unwrap_or(self.start);
self.current = constraints.constrain(element.pos - last_pos) + last_pos;
}
PenEvent::Up { element, .. } => {
if self.finish {
return ShapeBuilderProgress::Finished(vec![Shape::Polyline(
self.state_as_polyline(),
)]);
}
if self.pen_state == PenState::Down {
self.path.push(self.current);
}
self.pen_state = PenState::Up;
self.pen_pos = element.pos;
}
PenEvent::Proximity { element, .. } => {
self.pen_state = PenState::Proximity;
self.pen_pos = element.pos;
}
PenEvent::KeyPressed { keyboard_key, .. } => match keyboard_key {
KeyboardKey::Escape | KeyboardKey::CarriageReturn | KeyboardKey::Linefeed => {
return ShapeBuilderProgress::Finished(vec![Shape::Polyline(
self.state_as_polyline(),
)]);
}
_ => {}
},
PenEvent::Text { .. } => {}
PenEvent::Cancel => {
self.pen_state = PenState::Up;
self.finish = false;
}
}

ShapeBuilderProgress::InProgress
}

fn bounds(&self, style: &Style, zoom: f64) -> Option<Aabb> {
let mut polyline = self.state_as_polyline();
if !self.finish {
polyline.path.push(self.current);
}
Some(
polyline
.composed_bounds(style)
.loosened(indicators::POS_INDICATOR_RADIUS / zoom),
)
}

fn draw_styled(&self, cx: &mut piet_cairo::CairoRenderContext, style: &Style, zoom: f64) {
cx.save().unwrap();

let mut polyline = self.state_as_polyline();
if !self.finish {
polyline.path.push(self.current);
}

polyline.draw_composed(cx, style);
indicators::draw_pos_indicator(cx, PenState::Up, self.start, zoom);
if !self.finish {
if self.pos_in_finish(self.pen_pos)
&& (self.pen_state == PenState::Up || self.pen_state == PenState::Proximity)
{
indicators::draw_finish_indicator(cx, self.pen_state, self.current, zoom);
} else {
indicators::draw_pos_indicator(cx, self.pen_state, self.current, zoom);
}
}

cx.restore().unwrap();
}
}

impl PolylineBuilder {
const FINISH_TRESHOLD_DIST: f64 = 8.0;

/// The current state as a polyline.
pub fn state_as_polyline(&self) -> Polyline {
Polyline {
start: self.start,
path: self.path.clone(),
}
}

fn pos_in_finish(&self, pos: na::Vector2<f64>) -> bool {
(pos - self.path.last().copied().unwrap_or(self.start)).magnitude()
< Self::FINISH_TRESHOLD_DIST
}
}
2 changes: 2 additions & 0 deletions crates/rnote-compose/src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ rnote_compose_sources = files(
'builders/penpathcurvedbuilder.rs',
'builders/penpathmodeledbuilder.rs',
'builders/penpathsimplebuilder.rs',
'builders/polylinebuilder.rs',
'builders/quadbezbuilder.rs',
'builders/quadrantcoordsystem2dbuilder.rs',
'builders/rectanglebuilder.rs',
Expand All @@ -25,6 +26,7 @@ rnote_compose_sources = files(
'shapes/ellipse.rs',
'shapes/line.rs',
'shapes/mod.rs',
'shapes/polyline.rs',
'shapes/quadbez.rs',
'shapes/rectangle.rs',
'shapes/shape.rs',
Expand Down
2 changes: 1 addition & 1 deletion crates/rnote-compose/src/penevents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ pub enum ModifierKey {
}

/// The current pen state. Used wherever there is internal state.
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum PenState {
/// Up.
Up,
Expand Down
19 changes: 8 additions & 11 deletions crates/rnote-compose/src/penpath/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ impl Shapeable for PenPath {
end: end.pos,
};

bounds.merge(&quadbez.to_kurbo().bounding_box().bounds_to_p2d_aabb());
bounds.merge(&quadbez.outline_path().bounding_box().bounds_to_p2d_aabb());
prev = *end;
}
Segment::CubBezTo { cp1, cp2, end } => {
Expand All @@ -56,7 +56,7 @@ impl Shapeable for PenPath {
end: end.pos,
};

bounds.merge(&cubbez.to_kurbo().bounding_box().bounds_to_p2d_aabb());
bounds.merge(&cubbez.outline_path().bounding_box().bounds_to_p2d_aabb());
prev = *end;
}
}
Expand All @@ -71,6 +71,10 @@ impl Shapeable for PenPath {
.flat_map(|(_, hb)| hb)
.collect()
}

fn outline_path(&self) -> kurbo::BezPath {
kurbo::BezPath::from_iter(self.to_kurbo_el_iter())
}
}

impl Transformable for PenPath {
Expand Down Expand Up @@ -183,7 +187,7 @@ impl PenPath {
};

let n_splits =
no_subsegments_for_segment_len(quadbez.to_kurbo().perimeter(0.25));
no_subsegments_for_segment_len(quadbez.outline_path().perimeter(0.25));

hitboxes.push((
i,
Expand All @@ -204,7 +208,7 @@ impl PenPath {
};

let n_splits =
no_subsegments_for_segment_len(cubbez.to_kurbo().perimeter(0.25));
no_subsegments_for_segment_len(cubbez.outline_path().perimeter(0.25));

hitboxes.push((
i,
Expand All @@ -222,13 +226,6 @@ impl PenPath {
hitboxes
}

/// Convert to [kurbo::BezPath].
pub fn to_kurbo(&self) -> kurbo::BezPath {
let elements = self.to_kurbo_el_iter();

kurbo::BezPath::from_iter(elements)
}

/// Convert to [kurbo::BezPath], flattened to the given precision.
pub fn to_kurbo_flattened(&self, tolerance: f64) -> kurbo::BezPath {
let elements = self.to_kurbo_el_iter();
Expand Down
49 changes: 20 additions & 29 deletions crates/rnote-compose/src/shapes/arrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use super::Line;
use crate::ext::Vector2Ext;
use crate::shapes::Shapeable;
use crate::transform::Transformable;
use kurbo::PathEl;
use kurbo::{PathEl, Shape};
use na::Rotation2;
use p2d::bounding_volume::Aabb;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -71,6 +71,10 @@ impl Shapeable for Arrow {
.map(|line| line.bounds())
.collect()
}

fn outline_path(&self) -> kurbo::BezPath {
self.to_kurbo(None)
}
}

impl Arrow {
Expand Down Expand Up @@ -109,25 +113,21 @@ impl Arrow {
.collect::<Vec<Line>>()
}

/// Convert to kurbo shapes.
pub fn to_kurbo(&self, stroke_width: Option<f64>) -> ArrowKurbo {
let main = kurbo::Line::new(self.start.to_kurbo_point(), self.tip.to_kurbo_point());
let tip_triangle = {
let tip = self.tip.to_kurbo_point();
let lline = self.compute_lline(stroke_width).to_kurbo_point();
let rline = self.compute_rline(stroke_width).to_kurbo_point();

kurbo::BezPath::from_vec(vec![
PathEl::MoveTo(lline),
PathEl::LineTo(tip),
PathEl::LineTo(rline),
])
};

ArrowKurbo {
stem: main,
tip_triangle,
}
/// Convert to kurbo shape.
pub fn to_kurbo(&self, stroke_width: Option<f64>) -> kurbo::BezPath {
let mut bez_path =
kurbo::Line::new(self.start.to_kurbo_point(), self.tip.to_kurbo_point()).to_path(0.25);
let tip = self.tip.to_kurbo_point();
let lline = self.compute_lline(stroke_width).to_kurbo_point();
let rline = self.compute_rline(stroke_width).to_kurbo_point();

bez_path.extend([
PathEl::MoveTo(lline),
PathEl::LineTo(tip),
PathEl::LineTo(rline),
]);

bez_path
}

/// Compute the `lline` of the arrow tip.
Expand Down Expand Up @@ -186,12 +186,3 @@ impl Arrow {
Self::TIP_LINES_DEFAULT_LENGTH * (1.0 + 0.18 * factor)
}
}

/// A helper struct which holds the kurbo-elements of the arrow.
#[derive(Debug, Clone, PartialEq)]
pub struct ArrowKurbo {
/// The line from `start` -> `tip`.
pub stem: kurbo::Line,
/// The line from `lline` -> `tip` -> `rline`.
pub tip_triangle: kurbo::BezPath,
}
Loading

0 comments on commit 674c106

Please sign in to comment.