Skip to content

Commit

Permalink
boundingBox with underflow (fix #86)
Browse files Browse the repository at this point in the history
* `boundingBox` supports both overflow and underflow
* `boundingBox="none"` to not touch the bounding box at all
* `boundingBox="null -5 null 10"` to modify y but not x (say)
* `overflowBox` remains an alias for `boundingBox`
  • Loading branch information
edemaine committed Oct 18, 2022
1 parent ab4f32f commit 9899aac
Show file tree
Hide file tree
Showing 13 changed files with 186 additions and 47 deletions.
28 changes: 22 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ or return value of a function) should be specified as one of the following:
10. An `Array` of tiles of any of the listed formats (including more `Array`s,
which get flattened), meaning to stack multiple tiles on top of each other,
where the first non-null tile defines the `viewBox` and size
(but all can influence the [`overflowBox`](#overflow-and-bounding-box)).
(but all can influence the [`boundingBox`](#overflow-and-bounding-box)).
Use [`z-index`](#z-index-stacking-order-of-tiles)
to control stacking order.
Null items in the array get ignored, and an empty array acts like `null`
Expand Down Expand Up @@ -366,7 +366,7 @@ The top-level code of your .js or .coffee mapping file can also call:
Specify a [`z-index`](#z-index-stacking-order-of-tiles)
to control the stacking order relative to other symbols
or overlays/underlays.
Specify [`overflowBox`](#overflow-and-bounding-box) to increase the
Specify [`boundingBox`](#overflow-and-bounding-box) to increase the
overall size of the rendered drawing.
* `svgtiler.background(fillColor)` to set the default background color
for the SVG drawing (implemented via a `<rect>` underneath the bounding box).
Expand Down Expand Up @@ -552,19 +552,31 @@ When `overflow` is `visible`, `viewBox` still represents the size of the
element in the [grid layout](#layout-algorithm),
but allows the element's actual bounding box to be something else.
To correctly set the bounding box of the overall SVG drawing, SVG Tiler
defines an additional `<symbol>` attribute called `overflowBox`, which is like
defines an additional `<symbol>` attribute called `boundingBox`, which is like
`viewBox` but for specifying the actual bounding box of the content
(when they differ &mdash; `overflowBox` defaults to the value of `viewBox`).
(when they differ &mdash; `boundingBox` defaults to the value of `viewBox`).
The `viewBox` of the overall SVG is set to the minimum rectangle
containing all tiles' `overflowBox`s.
containing all tiles' `boundingBox`s.

For example,
`<symbol viewBox="0 0 10 10" overflowBox="-5 -5 20 20" overflow="visible">...</symbol>`
`<symbol viewBox="0 0 10 10" boundingBox="-5 -5 20 20">...</symbol>`
defines a tile that gets laid out as if it occupies the [0, 10] &times;
[0, 10] square, but the tile can draw outside that square, and the overall
drawing bounding box will be set as if the tile occupies the
[&minus;5, 15] &times; [&minus;5, 15] square.

The `boundingBox` can also be *smaller* than the `viewBox`, in case the
`viewBox` needs to be larger for proper grid alignment but the particular
symbol doesn't actually use the whole space.
For example, `<symbol viewBox="0 0 10 10" boundingBox="5 5 10 10"/>`
allocates 10×10 of space but may shrink down to 10×5 when used on the
top edge of the diagram (if no other symbols' bounding box extend above)
or 5×10 when used on the left edge of the diagram,
or 5×5 in the top-left corner.
You can also use the special value `boundingBox="none"` to specify that
the symbol should not influence the drawing's `viewBox` at all,
or `boundingBox="null -5 null 10"` to just affect the vertical extent (say).

Even zero-width and zero-height `<symbol>`s will get rendered (unless
`overflow="hidden"`). This can be useful for drawing grid
outlines without affecting the overall grid layout, for example.
Expand All @@ -573,6 +585,10 @@ height](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox),
so SVG Tiler automatically works around this by using slightly positive
widths and heights in the output `viewBox`.)

The `boundingBox` attribute used to be called `overflowBox` (prior to v3).
For backward compatibility, the old name is still supported, but in either
case it can cause both overflow and underflow relative to `viewBox`.

## Autosizing Tiles

Normally, a tile specifies its layout size by setting the
Expand Down
2 changes: 1 addition & 1 deletion examples/grid-graph/Maketile.args
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
-f
( flip_parity.coffee background.css path.coffee ips_example*asc )
( background.css path.coffee ips_*path*asc )
( background.css path.coffee ips_*path*asc ortho*.asc )
6 changes: 6 additions & 0 deletions examples/grid-graph/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,9 @@ the vertex coloring, to match the figure in the paper.
![Underlying graph figure](ips_example_graph.svg)

[ASCII input](ips_example_graph.asc), [SVG output](ips_example_graph.svg)

## Orthogonal graph layout

![Orthogonal graph layout figure](ortho_test.svg)

[ASCII input](ortho_test.asc), [SVG output](ortho_test.svg)
7 changes: 7 additions & 0 deletions examples/grid-graph/ortho_test.asc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.-.
| |
.-O-O-.
| | | |
.-O-O-.
| |
.-.
66 changes: 66 additions & 0 deletions examples/grid-graph/ortho_test.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 20 additions & 4 deletions examples/grid-graph/path.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ parity = null
svgtiler.onInit ->
parity = (share.flipParity ? 0) * 2

blank = <symbol viewBox={viewBox} overflowBox="-5.5 -5.5 11 11"/>
blank = <symbol viewBox={viewBox} boundingBox="0 0 0 0"/>

vertex = ->
<symbol viewBox={viewBox} z-index="1"
overflowBox="#{-(size+vertexStroke)/2} #{-(size+vertexStroke)/2} #{size+vertexStroke} #{size+vertexStroke}">
boundingBox="#{-(size+vertexStroke)/2} #{-(size+vertexStroke)/2} #{size+vertexStroke} #{size+vertexStroke}">
<circle r="5" stroke="black" stroke-width={vertexStroke}
fill={if (@i + @j) % 4 == parity then 'white' else 'black'}/>
</symbol>
Expand All @@ -32,13 +32,13 @@ arrow = svgtiler.def(

horizontal = (start, end) ->
<symbol viewBox={viewBox}
overflowBox="#{-(size+edgeStroke)/2} #{-edgeStroke/2} #{size+edgeStroke} #{edgeStroke}">
boundingBox="#{-(size+edgeStroke)/2} #{-edgeStroke/2} #{size+edgeStroke} #{edgeStroke}">
<line x1={-size/2} x2={size/2} stroke={edgeColor} stroke-width={edgeStroke}
marker-start={start} marker-end={end}/>
</symbol>
vertical = (start, end) ->
<symbol viewBox={viewBox}
overflowBox="#{-edgeStroke/2} #{-(size+edgeStroke)/2} #{edgeStroke} #{size+edgeStroke}">
boundingBox="#{-edgeStroke/2} #{-(size+edgeStroke)/2} #{edgeStroke} #{size+edgeStroke}">
<line y1={-size/2} y2={size/2} stroke={edgeColor} stroke-width={edgeStroke}
marker-start={start} marker-end={end}/>
</symbol>
Expand All @@ -53,3 +53,19 @@ o: vertex
'>': horizontal null, arrow
'^': vertical arrow, null
'v': vertical null, arrow
'.': -> # connecting turn between -s and |s
<symbol viewBox={viewBox} boundingBox="#{-edgeStroke/2} #{-edgeStroke/2} #{edgeStroke} #{edgeStroke}">
<circle r={edgeStroke/2} fill={edgeColor}/>
{if @neighbor(-1, 0).includes '-'
<line x1={-size/2} stroke={edgeColor} stroke-width={edgeStroke}/>
}
{if @neighbor(+1, 0).includes '-'
<line x2={+size/2} stroke={edgeColor} stroke-width={edgeStroke}/>
}
{if @neighbor(0, -1).includes '|'
<line y1={-size/2} stroke={edgeColor} stroke-width={edgeStroke}/>
}
{if @neighbor(0, +1).includes '|'
<line y2={+size/2} stroke={edgeColor} stroke-width={edgeStroke}/>
}
</symbol>
2 changes: 1 addition & 1 deletion examples/polyomino/outlines.cjsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Border = (props) ->
<line {...props} stroke="black" stroke-width="5" stroke-linecap="round"/>

(key) ->
<symbol viewBox="-10 -10 20 20" overflowBox="-12.5 -12.5 25 25">
<symbol viewBox="-10 -10 20 20" boundingBox="-12.5 -12.5 25 25">
{if @neighbor(-1,0).key != key
<Border x1="-10" y1="-10" x2="-10" y2="10"/>
}
Expand Down
2 changes: 1 addition & 1 deletion examples/polyomino/outlines.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ borderStyle = 'stroke="black" stroke-width="5" stroke-linecap="round"'

(key) ->
s = '''
<symbol viewBox="-10 -10 20 20" overflowBox="-12.5 -12.5 25 25">
<symbol viewBox="-10 -10 20 20" boundingBox="-12.5 -12.5 25 25">
'''
if @neighbor(-1,0).key != key
s += """<line x1="-10" y1="-10" x2="-10" y2="10" #{borderStyle}/>"""
Expand Down
2 changes: 1 addition & 1 deletion examples/polyomino/outlines.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const Border = (props) =>
<line {...props} stroke="black" stroke-width="5" stroke-linecap="round"/>;

(key, context) => {
return <symbol viewBox="-10 -10 20 20" overflowBox="-12.5 -12.5 25 25">
return <symbol viewBox="-10 -10 20 20" boundingBox="-12.5 -12.5 25 25">
{context.neighbor(-1,0).key !== key &&
<Border x1="-10" y1="-10" x2="-10" y2="10"/>}
{context.neighbor(+1,0).key !== key &&
Expand Down
2 changes: 1 addition & 1 deletion examples/test/mapping.coffee
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Test svgtiler.Mappings being provided as mapping values

export map1 = new svgtiler.Mapping (key) ->
<symbol width="50" height="50" overflowBox="-3 -3 56 56"
<symbol width="50" height="50" boundingBox="-3 -3 56 56"
z-index={if key == 'purple' then 1}>
<rect width="50" height="50" stroke={key} stroke-width="6" fill="gray"/>
</symbol>
Expand Down
2 changes: 1 addition & 1 deletion examples/unicode/maze.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<symbol viewBox="-10 -10 20 20"></symbol>
█ <symbol viewBox="0 0 20 20" overflowBox="-0.5 -0.5 21 21"><rect width="20" height="20" stroke="black" fill="purple"/></symbol>
█ <symbol viewBox="0 0 20 20" boundingBox="-0.5 -0.5 21 21"><rect width="20" height="20" stroke="black" fill="purple"/></symbol>
😊 <symbol viewBox="-10 -10 20 20"><circle r="6" fill="red"/><circle cx="-2" cy="-2" r="1" fill="white"/><circle cx="2" cy="-2" r="1" fill="white"/><path d="M -3 1 Q 0 4, 3 1" fill="none" stroke="white"/></symbol>
👍🏽 <symbol viewBox="-10 -10 20 20"><line x1="-5" y1="-5" x2="5" y2="5" stroke="green" stroke-width="2" stroke-linecap="round"/><line x1="-5" y1="5" x2="5" y2="-5" stroke="green" stroke-width="2" stroke-linecap="round"/></symbol>
2 changes: 1 addition & 1 deletion examples/witness/witness.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ blank = ->

start = (solution) -> ->
s = """
<symbol viewBox="-10 -10 20 20" overflowBox="-25 -25 50 50" z-index="2">
<symbol viewBox="-10 -10 20 20" boundingBox="-25 -25 50 50" z-index="2">
<circle cx="0" cy="0" r="25" fill="COLOR" />
"""
if @neighbor(-1,0).includes('-s') + @neighbor(+1,0).includes('-s') +
Expand Down
Loading

0 comments on commit 9899aac

Please sign in to comment.