HTML-like box-model layouting and rendering engine in Terra with a C API.
Written by Cosmin Apreutesei. Public Domain.
Discuss at luapower.com/forum or at github.com/luapower/terra.layer/issues.
Uses `cairo` for path filling, stroking, clipping, masking and blending.
Uses `terra.tr` for text shaping and rendering.
Uses `terra.boxblur` and `boxblur` for shadows.
NOTE: This is the implementation module. In here, invalid input data is
undefined behavior and changing layer properties does not keep the internal
state consistent. Use `layer_api` instead which takes care of all of that.
* the "layer box" is defined by (x, y, w, h).
* paddings are applied to the layer box, creating the "content box".
* child layers are positioned relative to the content box.
* child layers can be clipped to the content box subject to `clip_content`.
* border can be inside or outside the layer box, subject to `border_offset`.
* border and padding are independent as both are relative to the layer box
so to make room for an inner border, you need to add some padding.
* background can be clipped to the inside or outside of the border outline,
subject to `background_clip_border_offset`.
* none (default): manual positioning via x, y, w, h properties.
* textbox: content box grows to contain the text.
* flexbox: "css flexbox"-like layout type.
* grid: "css grid"-like layout type.
Content-wrapping in layout systems:
The presence of auto-wrapped content (text or wrapped flexbox items) in
content-based layout systems (i.e. layouts that expand based on the
content's minimum size) imposes that the layout be computed on the
content's main flow axis before being computed on the cross-axis. This is
because the minimum height of the content (assuming the main axis is the
x-axis) cannot be known until wrapping the content, but wrapping requires
knowing the final width of the container. This means that a layout that
contains a mix of both horizontally and vertically flowing wrapped content
cannot be computed correctly because such layout doesn't have a single
solution. The current implementation simply favors one axis over another
via `axis_order = AXIS_ORDER_XY` which means that vertically flowing
wrapped flexboxes aren't able to impose a minimum size on their container.
See the source code for more info.