// Copyright 2025 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
/// Path commands.
///
/// Ported from upstream `zeno/src/command.rs` (Apache-2.0 OR MIT).
pub(all) enum Command {
MoveTo(Point)
LineTo(Point)
QuadTo(Point, Point)
CurveTo(Point, Point, Point)
Close
}
///|
/// Returns the associated verb for the command.
pub fn Command::verb(self : Command) -> Verb {
match self {
Command::MoveTo(_) => Verb::MoveTo
Command::LineTo(_) => Verb::LineTo
Command::QuadTo(_, _) => Verb::QuadTo
Command::CurveTo(_, _, _) => Verb::CurveTo
Command::Close => Verb::Close
}
}
///|
pub fn Command::transform(self : Command, transform : Transform) -> Command {
match self {
Command::MoveTo(p) => Command::MoveTo(transform.transform_point(p))
Command::LineTo(p) => Command::LineTo(transform.transform_point(p))
Command::QuadTo(c, p) =>
Command::QuadTo(
transform.transform_point(c),
transform.transform_point(p),
)
Command::CurveTo(c1, c2, p) =>
Command::CurveTo(
transform.transform_point(c1),
transform.transform_point(c2),
transform.transform_point(p),
)
Command::Close => Command::Close
}
}
///|
/// Iterator over point/verb lists (equivalent to `PointsCommands` in upstream).
priv struct PointsCommands {
points : Array[Point]
verbs : Array[Verb]
mut ppos : Int
mut vpos : Int
}
///|
fn PointsCommands::new(
points : Array[Point],
verbs : Array[Verb],
) -> PointsCommands {
PointsCommands::{ points, verbs, ppos: 0, vpos: 0 }
}
///|
fn PointsCommands::next(self : PointsCommands) -> Command? {
if self.vpos >= self.verbs.length() {
return None
}
let verb = self.verbs[self.vpos]
self.vpos = self.vpos + 1
match verb {
Verb::MoveTo => {
if self.ppos >= self.points.length() {
return None
}
let p = self.points[self.ppos]
self.ppos = self.ppos + 1
Some(Command::MoveTo(p))
}
Verb::LineTo => {
if self.ppos >= self.points.length() {
return None
}
let p = self.points[self.ppos]
self.ppos = self.ppos + 1
Some(Command::LineTo(p))
}
Verb::QuadTo => {
if self.ppos + 1 >= self.points.length() {
return None
}
let c = self.points[self.ppos]
let p = self.points[self.ppos + 1]
self.ppos = self.ppos + 2
Some(Command::QuadTo(c, p))
}
Verb::CurveTo => {
if self.ppos + 2 >= self.points.length() {
return None
}
let c1 = self.points[self.ppos]
let c2 = self.points[self.ppos + 1]
let p = self.points[self.ppos + 2]
self.ppos = self.ppos + 3
Some(Command::CurveTo(c1, c2, p))
}
Verb::Close => Some(Command::Close)
}
}