Linocut.Derive (Linocut v0.1.3)

Copy Markdown View Source

A picture made from another by a short line of operations, so one drawing gives many views: a recoloured costume, a mirrored heading, a hat laid on.

from knight; colour C #c02020; flip h
from walk; frame 2; over hat 0 -2

The operations, separated by ;, in the order they run:

  • from NAME — the picture to start from; always first
  • colour KEY COLOUR (or color) — what KEY means, as a palette line takes it
  • swap KEY KEY — exchange what two keys mean
  • flip h / flip v — mirror left to right, or top to bottom
  • turn 90 / 180 / 270 — clockwise, a quarter turn at a time
  • shift DX DY — move the picture, what leaves the edge lost, what enters transparent
  • frame N — keep the Nth frame alone, counting from 1
  • reverse — the frames in the other order
  • over NAME [DX DY] — lay NAME's first frame on every frame, its transparent keys letting the picture through, moved by DX DY; the palettes are merged, and a key the two pictures use for different colours is refused

Everything works on the text of a .pic — keys, not pixels — so a derived picture is a picture like any other, edited in the same editors and rendered the same way. derive/2 takes the line and a function from a name to the text it names — {:ok, text}, :error for a name it does not know, or {:error, message} with a reason of its own.

Summary

Functions

The picture line describes, with lookup giving the text behind each name it uses.

The operations in line, or why it could not be read.

The picture the operations make, as text.

Types

lookup()

@type lookup() :: (String.t() -> {:ok, String.t()} | :error | {:error, String.t()})

op()

@type op() ::
  {:from, String.t()}
  | {:colour, String.t(), String.t()}
  | {:swap, String.t(), String.t()}
  | {:flip, :h | :v}
  | {:turn, 90 | 180 | 270}
  | {:shift, integer(), integer()}
  | {:frame, pos_integer()}
  | :reverse
  | {:over, String.t(), integer(), integer()}

Functions

derive(line, lookup)

@spec derive(String.t(), lookup()) :: {:ok, String.t()} | {:error, String.t()}

The picture line describes, with lookup giving the text behind each name it uses.

parse(line)

@spec parse(String.t()) :: {:ok, [op()]} | {:error, String.t()}

The operations in line, or why it could not be read.

Examples

iex> Linocut.Derive.parse("from ship; flip h; colour H #fff")
{:ok, [{:from, "ship"}, {:flip, :h}, {:colour, "H", "#fff"}]}

run(arg1, lookup)

@spec run([op()], lookup()) :: {:ok, String.t()} | {:error, String.t()}

The picture the operations make, as text.