Packages

Elixir binding for Harfbuzz using Rustybuzz as NIF, with RustlerPrecompiled

Current section

Files

Jump to
harfbuzz_ex lib pool.ex
Raw

lib/pool.ex

defmodule HarfbuzzEx.Pool do
@moduledoc """
A NimblePool for concurrent Harfbuzz text shaping.
"""
@behaviour NimblePool
# --- Public API ---
def child_spec(opts) do
%{
id: Keyword.get(opts, :name, __MODULE__),
start: {__MODULE__, :start_link, [opts]}
}
end
def start_link(opts) do
name = Keyword.fetch!(opts, :name)
pool_size = Keyword.get(opts, :pool_size, System.schedulers_online())
NimblePool.start_link(
worker: {__MODULE__, opts},
pool_size: pool_size,
name: name
)
end
@doc """
Check out a Shaper resource to shape text, executing in the calling process.
"""
def shape(pool_name, text) do
NimblePool.checkout!(pool_name, :checkout, fn _pool_pid, resource ->
result = HarfbuzzEx.Native.shaper_shape(resource, text)
# NimblePool expects {return_value, state_to_checkin}
{{:ok, result}, resource}
end)
end
def shape!(pool_name, text) do
{:ok, results} = shape(pool_name, text)
results
end
def shape!(pool_name, text, data) when data in [:name, :x_advance, :y_advance, :x_offset, :y_offset] do
shape!(pool_name, text)
|> Enum.map(&Map.get(&1, data))
end
def shape(pool_name, text, data) when data in [:name, :x_advance, :y_advance, :x_offset, :y_offset] do
{:ok, shape!(pool_name, text, data)}
end
# --- NimblePool Callbacks ---
@impl NimblePool
def init_worker(pool_state) do
font_path = Keyword.fetch!(pool_state, :font_path)
case HarfbuzzEx.Native.shaper_new(font_path) do
{:error, reason} -> {:error, reason}
# Returns {:ok, worker_state, pool_state}
resource -> {:ok, resource, pool_state}
end
end
@impl NimblePool
def handle_checkout(:checkout, _from, resource, pool_state) do
# Returns {:ok, client_state, worker_state, pool_state}
{:ok, resource, resource, pool_state}
end
@impl NimblePool
def handle_checkin(_client_state, _from, resource, pool_state) do
{:ok, resource, pool_state}
end
@impl NimblePool
def terminate_worker(_reason, _resource, _pool_state) do
:ok
end
end