typst / typst

A new markup-based typesetting system that is powerful and easy to learn.
https://typst.app
Apache License 2.0
29.17k stars 793 forks source link

`typst` does not pass the correct figure dimensions to `set page()` #4176

Closed tapyu closed 1 week ago

tapyu commented 2 weeks ago

Description

Consider the following MWE:

#import "@preview/cetz:0.2.2": canvas, draw//, plot, decorations
#set page(width: auto, height: auto, margin: .5cm)

#grid(
    columns: (1fr, 1fr),
    rows: (1fr, 1fr),
    gutter: 90pt,
    rect(width: 1cm, height: 1cm),
    rect(width: 1cm, height: 1cm),
    rect(width: 1cm, height: 1cm),
    rect(width: 1cm, height: 1cm),
  )

This produces

image

It is clear that #set page() is not getting the correct ratio (height x width) of the figure.

Reproduction URL

No response

Operating system

Linux

Typst version

PgBiel commented 2 weeks ago

This is because there are two competing mechanisms here: auto page dimensions, which scale based on content, and grid tracks (columns and rows) sized with 1fr. Note that 1fr does not scale together with content (so the size of what's inside the grid is irrelevant - you'd use auto tracks here if you wanted that behavior). Instead, 1fr slices the remaining available space based on how many fractional units there are, and assigns proportional space to the grid tracks.

So, you have the page dimensions wanting to scale based on content, but the content (the grid) wants to scale based on the page dimensions (to occupy all of the remaining available space). There is a conflict here, so what happens is that 1fr loses, and the grid tracks get 0pt of size. Thus, the only reason you see any separation there at all is because of the 90pt gutter.

You need to use auto tracks instead of 1fr if you want to be able to use auto page width/height. Otherwise, 1fr will always produce zero-width and/or zero-height tracks.

tapyu commented 2 weeks ago

Note that 1fr does not scale together with content.

This is not a reasonable behavior.

So, you have the page dimensions wanting to scale based on content, but the content (the grid) wants to scale based on the page dimensions (to occupy all of the remaining available space). There is a conflict here, so what happens is that 1fr loses, and the grid tracks get 0pt of size. Thus, the only reason you see any separation there at all is because of the 90pt gutter.

If the content (the grid) fails in getting the available space from the page dimensions, it should infer that from the content dimensions instead of simply assuming that the content size is 0pt.

PgBiel commented 2 weeks ago

This is not a reasonable behavior.

It is reasonable insofar as that's how 1fr works, similarly to how writing 0cm will also not scale together with content. 1fr means precisely this - take the available space and divide it proportionally to the amount of fractional units, nothing more.

If the content (the grid) fails in getting the available space from the page dimensions, it should infer that from the content dimensions instead of simply assuming that the content size is 0pt.

We could consider this a feature request, but in principle this feels a bit hacky to me, as in 1fr is suddenly exhibiting new behavior depending on the context.

I think you can do this today already by checking the page dimensions through layout. When dimensions are infinite, you have auto dimensions, so you can just use auto tracks instead of 1fr in those cases.

tapyu commented 2 weeks ago

this feels a bit hacky to me

Yeah, it might be a time-consuming task, which may decrease the compilation time. The main problem is that, for a NxN grid, the the algorithm that tries to arrange the content in a dimensionless page scales with time cost of $O(N^2)$, unless there is a optimized way to solve it. I don't see how to solve it at the moment.

If it is in fact time consuming, whenever typst finds this situation, I suggest falling back to auto and prompting a warning to the user, saying that it is not possible to slice up a dimensionless page (and suggesting auto instead of fractional units). It is better than compiling a PDF with this no sense content size.

Enivex commented 1 week ago

I'll close this issue as not really actionable (unless I'm missing something), but feel free to post a more concrete one.

tapyu commented 1 week ago

Prompting a warning about this issue is really actionable, actually. Moreover, one can consider falling back to auto when fractional values cannot define the content size (this is also actionable).