Each bound slot's budget, derived from what its cell draws at its size, and each feed's, the largest of its slots' (spec/15 §8.2, #864, D-226).
A mark that reads a slot needs rows by its type at its plot width w — the width of its
frame's box at the cell's size less the frame's left and right margins, in whole pixels:
| Marks | Rows |
|---|---|
:line, :area, :percentile_band | 4 × w, M4's lossless bound |
:rect, :band, :rose | ceil(w / 2), a bar per two pixels |
| any other mark that draws rows | w |
:tiles | none |
A slot's budget is the largest of its marks' needs — marks on one slot read the same
rows — or the design's budget where it declares one (spec/14 §2.10), and never more
than the board's ceiling. A feed is asked the largest budget of the slots it fills.
Everything here is pure, read from the design without applying it, so the board process that holds the feeds never pays for a cell's chart.
Examples
iex> chart = Visualize.Chart.from_map!(%{
...> version: 3,
...> sources: %{primary: %{fields: [:t, :v]}},
...> frames: %{main: %{kind: :cartesian, margin: %{left: 40, right: 20}}},
...> marks: [%{type: :line, data: :primary, channels: %{x: :t, y: :v}}]
...> })
iex> Visualize.Board.Budget.slot(chart, %{}, "primary", {560, 200}, nil)
2000
iex> Visualize.Board.Budget.slot(chart, %{}, "primary", {560, 200}, 500)
500
Summary
Functions
Each feed's budget, the largest of the feed-bound slots' it fills (nil, no bound, the
largest of all): a feed of feeds that no slot binds, or that a virtual source reads
(read), is asked the ceiling. A slot of budgets bound to a virtual source is in no
feed's: its source's inputs are asked the ceiling, and its output is reduced to the
slot's budget where it is handed (spec/15 §8.2, D-230).
A slot's budget in a cell of size ({width, height}, pixels): the design's budget
where it declares one, else the largest of the needs of the marks that read the slot,
capped by ceiling. A slot no mark reads, with no integer declared, is the ceiling.
vars are the cell's variables, which a frame's box, cell or margin may read.
Every bound slot's budget, by {cell, slot}: each slot of needs (a cell's slots by
name) that slot_refs binds — to a feed, {:feed, name}, or to a virtual source,
{:source, path} — in its cell's box of boxes (Visualize.Board.boxes/2), its
component's chart and variables from components. A budget is what the cell draws,
whoever produces the rows (spec/15 §8.2, D-230).
Types
@type t() :: pos_integer() | nil
A slot's or a feed's budget: rows, or nil for no bound.
Functions
@spec feeds([term()], %{required({term(), String.t()}) => t()}, map(), [term()], t()) :: %{ required(term()) => t() }
Each feed's budget, the largest of the feed-bound slots' it fills (nil, no bound, the
largest of all): a feed of feeds that no slot binds, or that a virtual source reads
(read), is asked the ceiling. A slot of budgets bound to a virtual source is in no
feed's: its source's inputs are asked the ceiling, and its output is reduced to the
slot's budget where it is handed (spec/15 §8.2, D-230).
iex> refs = %{
...> {:a, "p"} => {:feed, :f},
...> {:b, "p"} => {:feed, :f},
...> {:c, "p"} => {:source, ["s"]}
...> }
iex> budgets = %{{:a, "p"} => 300, {:b, "p"} => 800, {:c, "p"} => 2000}
iex> Visualize.Board.Budget.feeds([:f, :g], budgets, refs, [], 5000)
%{f: 800, g: 5000}
A slot's budget in a cell of size ({width, height}, pixels): the design's budget
where it declares one, else the largest of the needs of the marks that read the slot,
capped by ceiling. A slot no mark reads, with no integer declared, is the ceiling.
vars are the cell's variables, which a frame's box, cell or margin may read.
@spec slots(map(), %{required(term()) => [String.t()]}, map(), map(), t()) :: %{ required({term(), String.t()}) => t() }
Every bound slot's budget, by {cell, slot}: each slot of needs (a cell's slots by
name) that slot_refs binds — to a feed, {:feed, name}, or to a virtual source,
{:source, path} — in its cell's box of boxes (Visualize.Board.boxes/2), its
component's chart and variables from components. A budget is what the cell draws,
whoever produces the rows (spec/15 §8.2, D-230).
iex> chart = Visualize.Chart.from_map!(%{
...> version: 3,
...> sources: %{primary: %{fields: [:t, :v]}},
...> frames: %{main: %{kind: :cartesian, margin: %{left: 40, right: 20}}},
...> marks: [%{type: :line, data: :primary, channels: %{x: :t, y: :v}}]
...> })
iex> components = %{a: %{chart: chart, vars: %{}}, b: %{chart: chart, vars: %{}}}
iex> needs = %{a: ["primary"], b: ["primary"]}
iex> refs = %{{:a, "primary"} => {:feed, :f}, {:b, "primary"} => {:source, ["s"]}}
iex> boxes = %{a: {0, 0, 560, 200}, b: {0, 0, 160, 200}}
iex> Visualize.Board.Budget.slots(components, needs, refs, boxes, nil)
%{{:a, "primary"} => 2000, {:b, "primary"} => 400}