Skip to content

Conversation

valadaptive
Copy link
Contributor

@valadaptive valadaptive commented Mar 21, 2025

While integrating Parley with egui, I noticed a lot of extra padding around the glyphs' bounding boxes, and traced it back here. It seems the placement computation was deliberately padding the bounds horizontally. I can take an educated guess as to what might've caused this:

  • Swash renders glyphs by passing the render_offset option into zeno::Mask. It doesn't use the offset option because, despite what the documentation says, it did not actually affect the rendered position of the path, just the bounding box.
  • However, since render_offset doesn't adjust the bounds, glyphs were being cut off as they were shifted horizontally.
  • To fix this, the bounds were unconditionally expanded by a few pixels horizontally.

I've changed the offset option in Mask to affect both the bounds' offset and the rendered path's position. This is a breaking change--I could also just change the code up in Swash to pass the same value for both offset and render_offset. Either way, this'll require a change in Swash, but I think it's clearer to have offset do what it says on the tin. It's your call.

(EDIT: Went with the more conservative option for now; see comment)

With that working properly, there is no reason for the bounds to be padded anymore. Here's a comparison:

Before After
image image

As an added bonus, this fixes the glyphs being vertically cut off in the Parley swash_render example, since vertical bounds were not being similarly padded here:

Before After
image image

In a later (breaking) release, the behavior could be changed so offset
affects the path's position as well.
@valadaptive valadaptive changed the title Tighten bounds calculations and make the mask offset actually apply to both the path and bounds Tighten bounds calculations and update Mask::offset documentation Mar 27, 2025
@valadaptive
Copy link
Contributor Author

I don't think this is a breaking change in Swash, but there seems to be at least one other package that re-exports zeno, and changing Mask::offset's behavior is technically a breaking change here in zeno. I've decided to go with the more conservative option of just passing both offset and render_offset in from Swash, just to make extra sure there's no breakage.

@narodnik
Copy link

I tried to use this branch, but it seems the vertical cut offs don't seem to be fixed. Here's what I see in cargo tree:

├── parley v0.3.0 (/tmp/parley/parley)
│   └── swash v0.2.1 (/tmp/swash)
│       └── zeno v0.3.2 (/tmp/zeno)
[/tmp/zeno]$ git branch -v
  main         dbdd3d3 bump patch version for release (0.3.2)
* tight-bounds 696f941 Update documentation for Mask::offset

Here's the image I get with parley's swash_render example:

swash

Do I need to activate this branch somehow to get the fix? Thanks

@valadaptive
Copy link
Contributor Author

You'll need to switch Swash to this branch. You can point it at mine:

swash = { git = "https://github.com/valadaptive/swash", branch = "tight-bounds" }

which is the same as the one in dfrg/swash#88, except patched to use this branch of zeno.

@narodnik
Copy link

Great! That fixed it. Brilliant work.

@narodnik
Copy link

Result:
swash

Copy link

@xStrom xStrom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!

@xStrom
Copy link

xStrom commented Apr 27, 2025

The added bonus of Parley's swash_render example being fixed goes away with parley#343 applied. Which is to say that the swash_render issue may have had a different root cause.

With this padding removal here applied (combind with swash#88), swash_render output will end up being visually unchanged.

parley#343 + zeno#15 + zeno#15 & swash#88
swash_render baseline swash_render zeno swash_render swash_and_zeno
Looks good Clipped because of Swash bug Back to looking good

@nicoburns
Copy link

Isn't removing the padding from the output a breaking change for consumers of Swash? If they were previously accounting for that then they might need to undo their adjustment? Or will that "just work"?

@xStrom
Copy link

xStrom commented Apr 27, 2025

That's what swash#88 is for. If both Swash and Zeno get a patch release, then both will be picked up by cargo update - or neither. (Unless someone goes out of their way to update their lock file with just one.)

There's no compilation issues or indeed any required action by consumers. So all of this can go quite smoothly with patch releases.

@dfrg
Copy link
Owner

dfrg commented Apr 30, 2025

Thanks, the reasoning makes sense so let’s go ahead and land this.

Subpixel formats might require some additional padding which might explain why I hacked this in unconditionally. I’ll double check that before releasing.

@dfrg dfrg merged commit e8f4566 into dfrg:main Apr 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants