Overlays on the grid

Status: implemented

Motivation: Now that libipuz can read styles like barred, dashed, etc., we need a way to display those decorations.

The drawing code currently assumes that the puzzle’s shape can be represented by a grid of border items (corners and horizontal or vertical edges), or cells — see grid-layout.md.

One shortcoming of that scheme is that border items cannot easily draw outside of their allocation. For example, drawing a border that is thicker than the others is impossible. Similarly, a “dashed” border should have a hyphen struck through the border line; the dash overlaps the adjacent cells, but hopefully does not intrude their text.

If we allow for having decorations overlaid on the normal grid, we can solve these problems.

Overlaid decorations

When the GridLayout is computed, we can also compute a list of decorations that are to be overlaid on the grid. Each decoration has a kind (barred, dotted, dashed, etc.) and a grid position.

For the sake of example, consider this 2x1 puzzle with a barred border in the middle:

┌───┬───┐
│   ┃   │
└───┴───┘

The grid coordinates of that barred border are (2, 1). So, the overlay struct would look like:

Overlay {
    kind: barred,
    x: 2,
    y: 1,
}

The drawing code is then expected to translate that into actual coordinates for its drawing primitives, or to get as exotic as it wants by first creating a mask against which to clip the borders.

Holes in the border

Consider a dashed style like this:

┌───┬───┐
│   -   │
└───┴───┘

The vertical border needs a “hole” to allow the dash overlay to fit without being visually joined to the border.

The GridLayout code can easily have a boolean has_hole flag in LayoutBorderHorizontal and LayoutBorderVertical. Then, PlayBorder draw such a border in two pieces, or however it needs.

Borders as SVG

At GUADEC we briefly talked about leaving the cells as PlayCell widgets, but leaving all the border-drawing to an SVG overlay.

If we do that, the SVG can be generated with holes in the borders as appropriate, either with two little rectangles for each border-with-a-hole, or with masking or a clipping path.

Moving all border drawing to SVG seems like an easy way to do printing, at the expense of more complicated event handling for things like the editor, where the user will want to tweak border pieces individually. Maybe using widgets or SVG for borders are not exclusive, and we can take advantage of both?