## -*- mode: tcl ; fill-column: 90 -*-
# # ## ### ##### ######## ############# #####################
## Generators -- Basic 2D geometry primitives
#
## At the core of the implementation are signed distance functions.
## See these in the sdf.tcl file, with runtime support in op/sdf.[ch].
#
## Instead of having to explicitly set each pixel of the primitive based on some
## drawing algorithm (bresenham, variants, etc.) here each pixel computes the
## distance to the primitive (or its outline (filled yes/no)) and either lights
## up within +/- 0.5 (b/w, jaggy), or gradually lights up within +/- 1 (grey
## scale, antialiased drawing).
#
## This is also naturally parallelizable and fits directly into the multi-
## threaded setup used in AKTIVE (see [VIPS](https://www.libvips.org) for the
## inspiring system).
#
## [..] Bezier
## [ok] Box
## [ok] Box with rounded corners
## [ok] Circle
## [..] Circle arc(s)
## [..] Circle segment(s)
## [ok] Circles (dots)
## [..] Ellipse
## [ok] Line segment
## [ok] Line segments (poly-line)
## [ok] Line segments (separate, scattered)
## [ok] Parallelogram
## [ok] Rhombus
## [..] Rotated ellipse(s)
## [ok] Triangle
## [..] ...
# # ## ### ##### ######## ############# #####################
proc draw-modifier {} {
uplevel 1 {
if {$sdf in {
line lines polyline
}} {
# line element
import sdf/parameter/strokewidth.tcl
} else {
# area element
import sdf/parameter/outlined.tcl
}
}
}
# # ## ### ##### ######## ############# #####################
## Draw elements
operator [sdf-known image::draw::] {
section generator virtual drawing
op -> _ mode sdf ; def on 0
def element [sdf-label $sdf]
note Returns an image with the given dimensions and location, \
with a $element drawn into it.
import sdf/note.tcl
note The returned image is always single-band. It is grey-scale \
when anti-aliasing is active, and black/white if not.
note See also "<!xref: aktive op draw $sdf on>" \
and "<!xref: aktive image sdf ${sdf}>."
pass sdf-common-params
bool? 1 antialiased Draw with antialiasing for smoother contours (Default)
draw-modifier
# !xref-mark draw pass
pass import sdf/parameter/$sdf.tcl
body {
set sdf [aktive image sdf @@sdf@@ @@passthrough@@]
@@modifier@@
if {$antialiased} {
set sdf [aktive op sdf 2image smooth $sdf]
} else {
set sdf [aktive op sdf 2image pixelated $sdf]
}
::return $sdf
}
}
# # ## ### ##### ######## ############# #####################
## Draw elements over a background image
operator [sdf-known op::draw:: ::on] {
section transform drawing
op -> _ mode sdf _ ; def on 1
input background The image to draw on, i.e. the background for the drawing.
def element [sdf-label $sdf]
note Returns an image where a $element is drawn on the input image.
import sdf/note.tcl
note See also "<!xref: aktive image draw ${sdf}>" \
and "<!xref: aktive image sdf ${sdf}>."
pass bool? 1 antialiased Draw with antialiasing for smoother contours (Default)
pass draw-modifier
str color List of band values, color of the drawn $element. \
Their number has to match the input's depth.
pass import sdf/parameter/$sdf.tcl
body {
lassign [aktive query geometry $background] x y w h d
set n [llength $color]
if {$n != $d} { aktive error "Band mismatch, have $n, expected $d" }
set color [aktive image from band width $w height $h x $x y $y values {*}$color]
set draw [aktive image draw @@sdf@@ width $w height $h x $x y $y @@passthrough@@]
if {$antialiased} {
# grayscale ------------------ else then if
set sdf [aktive op math linear $background $color $draw]
} else {
# black/white ----------------- if then else
set sdf [aktive op if-then-else $draw $color $background]
}
::return $sdf
}
}
##
# # ## ### ##### ######## ############# #####################
::return