///|
fn pdf_content_path_empty_result(
partial_path : PdfContentPartialPath,
) -> PdfContentPathOpResult {
{ partial_path, drawn_path: None, }
}
///|
fn pdf_content_path_copy_segments(
segments : ArrayView[PdfPathSegment],
) -> Array[PdfPathSegment] {
[
for segment in segments => segment
]
}
///|
fn pdf_content_path_append_segment(
segments : ArrayView[PdfPathSegment],
segment : PdfPathSegment,
) -> Array[PdfPathSegment] {
let output = pdf_content_path_copy_segments(segments)
output.push(segment)
output
}
///|
fn pdf_content_path_copy_subpaths(
subpaths : ArrayView[PdfPathSubpath],
) -> Array[PdfPathSubpath] {
[
for subpath in subpaths => subpath
]
}
///|
fn pdf_content_path_reverse_subpaths(
subpaths : ArrayView[PdfPathSubpath],
) -> Array[PdfPathSubpath] {
pdf_content_path_copy_subpaths(subpaths).rev()
}
///|
fn pdf_content_path_append_subpath(
subpaths : ArrayView[PdfPathSubpath],
subpath : PdfPathSubpath,
) -> Array[PdfPathSubpath] {
let output = pdf_content_path_copy_subpaths(subpaths)
output.push(subpath)
output
}
///|
fn pdf_content_path_subpath(
closure : PdfPathClosure,
segments : ArrayView[PdfPathSegment],
) -> PdfPathSubpath {
{
hole: PdfPathNotHole,
closure,
segments: pdf_content_path_copy_segments(segments),
}
}
///|
fn pdf_content_partial_path_clear(
state : PdfContentPartialPathState,
) -> PdfContentPartialPath {
PdfContentPartialPath({ ..state, segments: [], subpaths: [], })
}
///|
fn pdf_content_path_copy_paths(paths : ArrayView[PdfPath]) -> Array[PdfPath] {
[
for path in paths => path
]
}
///|
fn pdf_content_path_prepend_path(
paths : ArrayView[PdfPath],
path : PdfPath,
) -> Array[PdfPath] {
let output = [path]
for existing in paths {
output.push(existing)
}
output
}
///|
fn PdfContentPartialPath::content_move_to(
self : PdfContentPartialPath,
point : Point2,
) -> PdfContentPartialPath {
match self {
PdfContentPartialPath(state) if state.segments.length() == 0 =>
PdfContentPartialPath({
start_point: point,
current_point: point,
segments: [],
subpaths: state.subpaths,
})
PdfContentPartialPath(state) =>
PdfContentPartialPath({
start_point: point,
current_point: point,
segments: [],
subpaths: pdf_content_path_append_subpath(
state.subpaths,
pdf_content_path_subpath(PdfPathOpen, state.segments),
),
})
PdfContentNoPartialPath =>
PdfContentPartialPath({
start_point: point,
current_point: point,
segments: [],
subpaths: [],
})
}
}
///|
fn PdfContentPartialPath::content_line_to(
self : PdfContentPartialPath,
point : Point2,
) -> PdfContentPartialPath {
match self {
PdfContentPartialPath(state) =>
PdfContentPartialPath({
..state,
current_point: point,
segments: pdf_content_path_append_segment(
state.segments,
PdfPathStraight(state.current_point, point),
),
})
PdfContentNoPartialPath => self
}
}
///|
fn PdfContentPartialPath::content_curve_to(
self : PdfContentPartialPath,
control1 : Point2,
control2 : Point2,
finish : Point2,
) -> PdfContentPartialPath {
match self {
PdfContentPartialPath(state) =>
PdfContentPartialPath({
..state,
current_point: finish,
segments: pdf_content_path_append_segment(
state.segments,
PdfPathBezier(state.current_point, control1, control2, finish),
),
})
PdfContentNoPartialPath => self
}
}
///|
fn PdfContentPartialPath::content_close_path(
self : PdfContentPartialPath,
) -> PdfContentPartialPath {
match self {
PdfContentPartialPath(state) =>
PdfContentPartialPath({
..state,
segments: [],
subpaths: pdf_content_path_append_subpath(
state.subpaths,
pdf_content_path_subpath(PdfPathClosed, state.segments),
),
})
PdfContentNoPartialPath => self
}
}
///|
fn PdfContentPartialPath::content_rectangle(
self : PdfContentPartialPath,
x : Double,
y : Double,
width : Double,
height : Double,
) -> PdfContentPartialPath {
self
.content_move_to(@geometry.point2(x, y))
.content_line_to(@geometry.point2(x + width, y))
.content_line_to(@geometry.point2(x + width, y + height))
.content_line_to(@geometry.point2(x, y + height))
.content_close_path()
}
///|
fn pdf_content_path_finish_subpaths(
state : PdfContentPartialPathState,
close_current : Bool,
) -> Array[PdfPathSubpath] {
if state.segments.length() == 0 {
pdf_content_path_copy_subpaths(state.subpaths)
} else {
pdf_content_path_append_subpath(
state.subpaths,
pdf_content_path_subpath(
if close_current {
PdfPathClosed
} else {
PdfPathOpen
},
state.segments,
),
)
}
}
///|
fn PdfContentPartialPath::content_paint(
self : PdfContentPartialPath,
winding_rule : PdfPathWindingRule,
filled : Bool,
stroked : Bool,
close_current : Bool,
) -> PdfContentPathOpResult {
match self {
PdfContentPartialPath(state) => {
let subpaths = pdf_content_path_finish_subpaths(state, close_current)
{
partial_path: pdf_content_partial_path_clear(state),
drawn_path: Some({ stroked, filled, path: { winding_rule, subpaths, }, }),
}
}
PdfContentNoPartialPath => pdf_content_path_empty_result(self)
}
}
///|
fn PdfContentPartialPath::content_clipping_path(
self : PdfContentPartialPath,
winding_rule : PdfPathWindingRule,
) -> PdfPath? {
match self {
PdfContentPartialPath(state) =>
if state.segments.length() == 0 && state.subpaths.length() == 0 {
None
} else {
let subpaths = if state.segments.length() == 0 {
pdf_content_path_reverse_subpaths(state.subpaths)
} else {
let output = [pdf_content_path_subpath(PdfPathClosed, state.segments)]
for subpath in pdf_content_path_reverse_subpaths(state.subpaths) {
output.push(subpath)
}
output
}
Some({ winding_rule, subpaths, })
}
PdfContentNoPartialPath => None
}
}
///|
fn PdfContentPartialPath::content_clip(
self : PdfContentPartialPath,
clipping_path : ArrayView[PdfPath],
winding_rule : PdfPathWindingRule,
) -> PdfContentClippingOpResult {
match self.content_clipping_path(winding_rule) {
Some(path) =>
{
partial_path: self,
clipping_path: pdf_content_path_prepend_path(clipping_path, path),
}
None =>
{
partial_path: self,
clipping_path: pdf_content_path_copy_paths(clipping_path),
}
}
}