diff options
Diffstat (limited to 'lib/Fornax/GenerateFrame.rakumod')
-rw-r--r-- | lib/Fornax/GenerateFrame.rakumod | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/lib/Fornax/GenerateFrame.rakumod b/lib/Fornax/GenerateFrame.rakumod new file mode 100644 index 0000000..e19d342 --- /dev/null +++ b/lib/Fornax/GenerateFrame.rakumod @@ -0,0 +1,100 @@ +use Cairo; +use Fornax::Hex2RGB; + +# Cells as defined by fornax format. +constant $PATH = '.'; +constant $BLOK = '#'; +constant $DEST = '$'; +constant $STRT = '^'; +constant $VIS = '-'; +constant $CUR = '@'; +constant $CURPATH = '~'; + +# Colors. +constant %C = ( + bg-main => "#ffffff", + + red-subtle-bg => "#f2b0a2", + blue-subtle-bg => "#b5d0ff", + cyan-subtle-bg => "#c0efff", + green-subtle-bg => "#aecf90", + + fg-main => "#000000", + + fg-special-cold => "#093060", + fg-special-warm => "#5d3026", + fg-special-mild => "#184034", + fg-special-calm => "#61284f", +).map: {.key => hex2rgb(.value)}; + +enum IterStatus <Walking Blocked Completed>; + +sub generate-frame( + :%CANVAS, :$out, :%excess, :$side, :%meta, :$iter is copy + , :$idx, :$debug, +) is export { + my IterStatus $status; + given $iter.substr(0, 1) { + when '|' { $status = Completed } + when '!' { $status = Blocked } + default { $status = Walking } + }; + + # Remove marker. + $iter .= substr(1) if $status == Completed|Blocked; + + put "\n[fornax] $idx $iter $status" if $debug; + + my @grid = $iter.comb.rotor: %meta<cols>; + warn "Invalid grid: $idx $iter $status" unless @grid.elems == %meta<rows>; + + given Cairo::Image.create( + Cairo::FORMAT_ARGB32, %CANVAS<width>, %CANVAS<height> + ) { + given Cairo::Context.new($_) { + # Paint the entire canvas white. + .rgb: |%C<bg-main>; + .rectangle(0, 0, %CANVAS<width>, %CANVAS<height>); + .fill; + + # This seems to be slower than creating an intermediate + # variable and assigning from that. Difference is not much + # so we'll ignore it. + for ^%meta<rows> X ^%meta<cols> -> ($r, $c) { + my Int @target = %excess<width> div 2 + $c * $side, + %excess<height> div 2 + $r * $side, + $side, $side; + + .rectangle: |@target; + + given @grid[$r][$c] -> $cell { + # According to the format, current position may be + # prioritized over Destination symbol so we + # colorize it according to $status. + when $cell eq $CUR { + .rgba: |%C<fg-special-cold>, 0.56; + .rgba: |%C<fg-special-mild>, 0.72 if $status == Completed; + .rgba: |%C<fg-special-warm>, 0.72 if $status == Blocked; + } + when $cell eq $CURPATH { + .rgba: |%C<blue-subtle-bg>, 0.84; + .rgba: |%C<green-subtle-bg>, 0.96 if $status == Completed; + .rgba: |%C<red-subtle-bg>, 0.96 if $status == Blocked; + } + when $cell eq $VIS { + .rgba: |%C<cyan-subtle-bg>, 0.72; + } + when $cell eq $BLOK { .rgba: |%C<fg-main>, 0.56 } + when $cell eq $STRT|$DEST { .rgba: |%C<fg-special-mild>, 0.72 } + default { .rgba: |%C<fg-main>, 0.08 } + } + .fill :preserve; + + .rgb: |%C<fg-main>; + .stroke; + } + } + .write_png($out); + .finish; + } +} |