Skip to content

Commit

Permalink
Use Exa.Dispatch for Colorb
Browse files Browse the repository at this point in the history
Change order of behaviour arguments
  • Loading branch information
red-jade committed Sep 1, 2024
1 parent b46c7f8 commit e67581e
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 49 deletions.
8 changes: 3 additions & 5 deletions lib/color/col1b.ex
Original file line number Diff line number Diff line change
Expand Up @@ -73,20 +73,18 @@ defmodule Exa.Color.Col1b do

# binary conversions ----------

@c1 [:gray, :index]

@behaviour Colorb

@impl Colorb
def to_bin(i, pix \\ :gray) when pix in @c1 and is_col1b(i),
def to_bin(pix \\ :gray, i) when is_pix1(pix) and is_col1b(i),
do: <<i>>

@impl Colorb
def append_bin(buf, pix \\ :gray, i) when pix in @c1 and is_binary(buf) and is_col1b(i),
def append_bin(pix \\ :gray, buf, i) when is_pix1(pix) and is_binary(buf) and is_col1b(i),
do: <<buf::binary, i>>

@impl Colorb
def from_bin(<<i, rest::binary>>, pix \\ :gray) when pix in @c1,
def from_bin(pix \\ :gray, <<i, rest::binary>>) when is_pix1(pix),
do: {i, rest}

# -----------------
Expand Down
8 changes: 4 additions & 4 deletions lib/color/col3b.ex
Original file line number Diff line number Diff line change
Expand Up @@ -184,15 +184,15 @@ defmodule Exa.Color.Col3b do
@behaviour Colorb

@impl Colorb
def to_bin(col, pix \\ :rgb) when is_pix3(pix),
do: append_bin(<<>>, pix, col)
def to_bin(pix \\ :rgb, col) when is_pix3(pix),
do: append_bin(pix, <<>>, col)

@impl Colorb
def append_bin(buf, pix \\ :rgb, {c1, c2, c3}) when is_pix3(pix) and is_binary(buf),
def append_bin(pix \\ :rgb, buf, {c1, c2, c3}) when is_pix3(pix) and is_binary(buf),
do: <<buf::binary, c1, c2, c3>>

@impl Colorb
def from_bin(<<c1, c2, c3, rest::binary>>, pix \\ :rgb) when is_pix3(pix),
def from_bin(pix \\ :rgb, <<c1, c2, c3, rest::binary>>) when is_pix3(pix),
do: {{c1, c2, c3}, rest}

# -----------------
Expand Down
11 changes: 5 additions & 6 deletions lib/color/col4b.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ defmodule Exa.Color.Col4b do
require Logger
import Exa.Types

import Exa.Color.Types
alias Exa.Color.Types, as: C

alias Exa.Math
Expand Down Expand Up @@ -146,19 +147,17 @@ defmodule Exa.Color.Col4b do
# unless the src and dst pixels are different
# then need 2 args

@c4 [:rgba, :argb, :bgra, :abgr]

@behaviour Colorb

@impl Colorb
def to_bin(col, pix \\ :rgba) when pix in @c4,
do: append_bin(<<>>, pix, col)
def to_bin(pix \\ :rgba, col) when is_pix4(pix),
do: append_bin(pix, <<>>, col)

@impl Colorb
def append_bin(buf, pix \\ :rgba, {c1, c2, c3, c4}) when pix in @c4 and is_binary(buf),
def append_bin(pix \\ :rgba, buf, {c1, c2, c3, c4}) when is_pix4(pix) and is_binary(buf),
do: <<buf::binary, c1, c2, c3, c4>>

@impl Colorb
def from_bin(<<c1, c2, c3, c4, rest::binary>>, pix \\ :rgba) when pix in @c4,
def from_bin(pix \\ :rgba, <<c1, c2, c3, c4, rest::binary>>) when is_pix4(pix),
do: {{c1, c2, c3, c4}, rest}
end
69 changes: 35 additions & 34 deletions lib/color/colorb.ex
Original file line number Diff line number Diff line change
@@ -1,48 +1,49 @@
defmodule Exa.Color.Colorb do
@moduledoc "A behaviour for byte colors."
@moduledoc """
A behaviour for byte colors,
with a generic interface that dispatches
to concrete implementations.
"""

import Exa.Color.Types
alias Exa.Color.Types, as: C

alias Exa.Color.Col1b
alias Exa.Color.Col3b
alias Exa.Color.Col4b

# dispatch map from tags to implementation module
@disp %{
:gray => Col1b,
:index => Col1b,
:rgb => Col3b,
:bgr => Col3b,
:rgba => Col4b,
:bgra => Col4b,
:argb => Col4b,
:abgr => Col4b,
}

# it's more natural to have the buffer as first arg for piping
# but dispatching implementations must have the tag as 1st arg

@doc "Convert a color to a binary."
@callback to_bin(C.colorb(), C.pixel()) :: binary()
@callback to_bin(C.pixel(), C.colorb()) :: binary()

@doc "Append a color to a binary."
@callback append_bin(binary(), C.pixel(), C.colorb()) :: binary()
@callback append_bin(C.pixel(), binary(), C.colorb()) :: binary()

@doc "Read a color from a binary."
@callback from_bin(binary(), C.pixel()) :: {C.colorb(), binary()}

# kinda like a protocol, but with tagged pixels instead of a struct...

def from_bin(buf, :gray), do: Col1b.from_bin(buf, :gray)
def from_bin(buf, :index), do: Col1b.from_bin(buf, :index)
def from_bin(buf, :rgb), do: Col3b.from_bin(buf, :rgb)
def from_bin(buf, :bgr), do: Col3b.from_bin(buf, :bgr)
def from_bin(buf, :rgba), do: Col4b.from_bin(buf, :rgba)
def from_bin(buf, :bgra), do: Col4b.from_bin(buf, :bgra)
def from_bin(buf, :argb), do: Col4b.from_bin(buf, :argb)
def from_bin(buf, :abgr), do: Col4b.from_bin(buf, :abgr)

def append_bin(buf, :gray, col), do: Col1b.append_bin(buf, :gray, col)
def append_bin(buf, :index, col), do: Col1b.append_bin(buf, :index, col)
def append_bin(buf, :rgb, col), do: Col3b.append_bin(buf, :rgb, col)
def append_bin(buf, :bgr, col), do: Col3b.append_bin(buf, :bgr, col)
def append_bin(buf, :rgba, col), do: Col4b.append_bin(buf, :rgba, col)
def append_bin(buf, :bgra, col), do: Col4b.append_bin(buf, :bgra, col)
def append_bin(buf, :argb, col), do: Col4b.append_bin(buf, :argb, col)
def append_bin(buf, :abgr, col), do: Col4b.append_bin(buf, :abgr, col)

def to_bin(col, :gray) when is_col1b(col), do: Col1b.to_bin(col, :gray)
def to_bin(col, :index) when is_col1b(col), do: Col1b.to_bin(col, :index)
def to_bin(col, :rgb) when is_col3b(col), do: Col3b.to_bin(col, :rgb)
def to_bin(col, :bgr) when is_col3b(col), do: Col3b.to_bin(col, :bgr)
def to_bin(col, :argb) when is_col4b(col), do: Col4b.to_bin(col, :argb)
def to_bin(col, :abgr) when is_col4b(col), do: Col4b.to_bin(col, :abgr)
def to_bin(col, :rgba) when is_col4b(col), do: Col4b.to_bin(col, :rgba)
def to_bin(col, :bgra) when is_col4b(col), do: Col4b.to_bin(col, :bgra)
@callback from_bin(C.pixel(), binary()) :: {C.colorb(), binary()}

def from_bin(pix, buf) do
Exa.Dispatch.dispatch(@disp, pix, :from_bin, [buf])
end

def append_bin(pix, buf, col) do
Exa.Dispatch.dispatch(@disp, pix, :append_bin, [buf, col])
end

def to_bin(pix, col) do
Exa.Dispatch.dispatch(@disp, pix, :to_bin, [col])
end
end

0 comments on commit e67581e

Please sign in to comment.