Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

utilities: fix issues related to conversion of lengths to pt #84

Merged
merged 13 commits into from
Dec 8, 2023

Conversation

dixslyf
Copy link
Contributor

@dixslyf dixslyf commented Dec 1, 2023

This PR fixes some issues regarding the conversion of lengths to pt in hopes of progressing #74. Please see each commit's message for details.

I don't see any regressions in tablex-test.typ (compiled it to PNG before and after this PR's commits, then checked their hashes).

I'm marking this as a draft for now as I haven't added any tests. I did some quick testing with negative line expansion, and surprisingly, it seems to work, so I'd like to investigate this further before readying this PR.

EDIT: should resolve #74.

@PgBiel
Copy link
Owner

PgBiel commented Dec 1, 2023

Oh, I didn't realize that the problem occurred even when you were reducing the stroke below a single cell (not between cells, which is expected to fail). That is interesting. Thanks for looking into this!

I can't take a look at the proper logic right now, but I'll give some initial feedback.

src/utilities.typ Outdated Show resolved Hide resolved
src/utilities.typ Outdated Show resolved Hide resolved
@PgBiel PgBiel added the bug Something isn't working label Dec 2, 2023
@dixslyf
Copy link
Contributor Author

dixslyf commented Dec 2, 2023

I've rewritten the functions to use regex (yeah, quite ugly) and added some tests (still need to add more for ratio and fraction types).

One concern I have: the repr for the abs component of a length rounds to a precision of 2 (src), so there will be a loss of precision. This is true for at least Typst 0.9.0, but I haven't looked at previous versions and other length types.

@dixslyf dixslyf force-pushed the fix-pt-conversion branch 2 times, most recently from 65aae94 to a9f73ca Compare December 2, 2023 07:56
@dixslyf dixslyf marked this pull request as ready for review December 2, 2023 08:43
The `convert-length-to-pt` function did not properly handle converting
negative `length`s to pt. They would get converted to 0pt because the
line drawn for measurement would (I presume) have a width of 0pt
when given a negative `length`.
`convert-length-to-pt` had a couple of issues regarding relative
lengths.

When the `length` component has an em part, there would be an error
because Typst does not allow comparing `length`s with an em part with
those that do not.

It also did not account for ratios with a fraction (e.g., 1.5%).

This commit fixes those issues and, at the same time, simplifies the
implementation to re-use the other conversion functions for better
consistency.
@PgBiel PgBiel added this to the v0.0.7 milestone Dec 3, 2023
@PgBiel
Copy link
Owner

PgBiel commented Dec 3, 2023

One concern I have: the repr for the abs component of a length rounds to a precision of 2 (src), so there will be a loss of precision. This is true for at least Typst 0.9.0, but I haven't looked at previous versions and other length types.

That seems to be the case since before Typst was released... In this case, I think a good workaround might be to keep the old algorithm (just measure the line) if there are no negative numbers in the length's parts (checking if either of the "minus" symbols is present in the repr() should be enough). That way, we only lose a bit of precision when dealing with the specific case of negative numbers. Of course, this is bound to be improved if/when we switch to 0.7.0's constructs.

Copy link
Owner

@PgBiel PgBiel left a comment

Choose a reason for hiding this comment

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

This is looking great! Thanks for the clean code 😎

tablex-test.typ Outdated Show resolved Hide resolved
tablex-test.typ Outdated Show resolved Hide resolved
src/utilities.typ Outdated Show resolved Hide resolved
tablex-test.typ Outdated Show resolved Hide resolved
@dixslyf
Copy link
Contributor Author

dixslyf commented Dec 3, 2023

One concern I have: the repr for the abs component of a length rounds to a precision of 2 (src), so there will be a loss of precision. This is true for at least Typst 0.9.0, but I haven't looked at previous versions and other length types.

Seems like this is true for the other length types as well (and angle). The em component seems to be the only exception. The rounding also seems inconsistent, so I've filed a bug report in Typst's repo (typst/typst#2836).

@dixslyf dixslyf force-pushed the fix-pt-conversion branch 2 times, most recently from 967115a to b64ca4a Compare December 3, 2023 13:43
@dixslyf
Copy link
Contributor Author

dixslyf commented Dec 3, 2023

I've gone ahead and implemented what I came up with in #84 (comment). I've also managed to come up with a solution for the same precision issue for relative lengths (we don't use repr for fraction and ratio, so those are unaffected).

On the testing side:

  • Added tests for line expansion
  • Updated the conversion tests to check the return type (length) and use values that can better ensure that there is no precision loss

I think we're nearly done with this PR. All that's left is another round of review and ensuring that this PR works with older versions of Typst (still trying to work out the best way to do this).

I've left the commit history mostly intact because I didn't want to accidentally remove commits when force pushing. However, I can squash some of them if you prefer.

EDIT: Forgot to check for regressions; will do tomorrow.

@PgBiel PgBiel linked an issue Dec 3, 2023 that may be closed by this pull request
@PgBiel
Copy link
Owner

PgBiel commented Dec 3, 2023

Thanks, you're doing great work! I'll try to provide a final round of review soon.

Regarding commit history, don't worry too much about it, I'll probably squash before merging.

Unfortunately, `repr` rounds the `pt` component of `length`s to 2
decimal places, which results in a loss of precision.

This commit rewrites the conversion of `length`s to `pt` without
relying on the numerical values in the `repr`. We instead draw and
measure lines.
Typst rounds all length components, except `em` components, to 2 decimal
places for their `repr`, which results in a loss of precision.

This commit resolves the loss of precision. Some aspects of Typst's
behaviour are important:
- The `repr` of `em` is lossless.
- The "draw and measure a line" technique applied on `relative` lengths
  returns the length of the `length` component only (the ratio component
  is ignored due to limitations of the technique).
@dixslyf
Copy link
Contributor Author

dixslyf commented Dec 5, 2023

Re-ordered the commits so that changes to tablex-test.typ come later. Makes it easier to check for regressions before tablex-test.typ got modified.

I managed to hack together a bunch of scripts using Nix and diff-pdf to semi-automate regression testing for the different Typst versions. (Didn't include them here since they're out of scope and pretty makeshift, but they can be found at: dixslyf@7d078eb.) I don't see any regressions for any of the supported Typst versions.

@PgBiel PgBiel merged commit 77048e9 into PgBiel:0.1.0-dev Dec 8, 2023
@PgBiel
Copy link
Owner

PgBiel commented Dec 8, 2023

Thank you! The result looks great. I also appreciate very much that you tested much more than I could ever ask someone to! 😂 Great job 👍

@PgBiel
Copy link
Owner

PgBiel commented Dec 8, 2023

I plan on having a better testing system in the future. I'll probably consider using PNG instead of PDF though as it's a pain to work with :p

I'm particularly interested in Lau's efforts towards a standard testing solution for packages, although I might also try out something like CeTZ's system. We'll see...

@dixslyf
Copy link
Contributor Author

dixslyf commented Dec 8, 2023

I'll probably consider using PNG instead of PDF though as it's a pain to work with :p

Indeed, PDFs are a huge pain to work with. I initially wanted to go with PNG for my tests, but PNG export was only added in Typst v0.5.0. What I tried at first was to convert the PDFs to PNGs using ImageMagick (I also tried pdftoppm), but the conversion took a while and you need to tune the options to get decent quality output. I later realized you could just use magick compare on two PDFs (it'll do the conversion for you, but you'll still need to tune the options) to generate a diff image (the exit code also tells you whether the PDFs were similar). I went with diff-pdf (which does more or less the same thing) in the end just because it was easier to use.

Another thing I tried was to compare the output across different Typst versions (e.g., compare the outputs for Typst v0.2.0 and v0.9.0). The outputs were slightly different — mostly differences in spacing. However, even for pages that look the same to our eyes, if you compared them using magick compare, there would be differences in the anti-aliasing (I think) of rendered text. I figured it wasn't worth it to test across Typst versions.

I'm particularly interested in Lau's efforts towards a standard testing solution for packages,

Same!

although I might also try out something like CeTZ's system. We'll see...

I took a look at CeTZ's testing when I was trying to test this PR, and it did look nice and promising. My only concern was it tests only a single version of Typst as far as I can tell. It's probably not too difficult to expand on that, however (e.g., modifying PATH to use a different Typst version, though fetching the different Typst versions and caching them somewhere sounds like a bit of a pain).

@dixslyf dixslyf deleted the fix-pt-conversion branch December 8, 2023 04:37
PgBiel added a commit that referenced this pull request Dec 8, 2023
Fixes negative length parsing

Co-authored-by: Dixon Sean Low Yan Feng <56017218+dixslyf@users.noreply.github.com>
This was referenced Dec 13, 2023
PgBiel pushed a commit that referenced this pull request Dec 17, 2023
* utilities: fix conversion of negative `length` lengths

The `convert-length-to-pt` function did not properly handle converting
negative `length`s to pt. They would get converted to 0pt because the
line drawn for measurement would (I presume) have a width of 0pt
when given a negative `length`.

* utilities: factor out pt conversions into functions

* utilities: simplify and fix conversion of relative lengths to pt

`convert-length-to-pt` had a couple of issues regarding relative
lengths.

When the `length` component has an em part, there would be an error
because Typst does not allow comparing `length`s with an em part with
those that do not.

It also did not account for ratios with a fraction (e.g., 1.5%).

This commit fixes those issues and, at the same time, simplifies the
implementation to re-use the other conversion functions for better
consistency.

* utilities: convert `convert-length-to-pt` variables to kebab case

* utilities: convert `length`s to pt without losing precision

Unfortunately, `repr` rounds the `pt` component of `length`s to 2
decimal places, which results in a loss of precision.

This commit rewrites the conversion of `length`s to `pt` without
relying on the numerical values in the `repr`. We instead draw and
measure lines.

* utilities: convert `relative` lengths to pt without losing precision

Typst rounds all length components, except `em` components, to 2 decimal
places for their `repr`, which results in a loss of precision.

This commit resolves the loss of precision. Some aspects of Typst's
behaviour are important:
- The `repr` of `em` is lossless.
- The "draw and measure a line" technique applied on `relative` lengths
  returns the length of the `length` component only (the ratio component
  is ignored due to limitations of the technique).

* utilities: assert `page-size` and `frac-total` are purely pt lengths

* tablex-test: add tests for `convert-length-to-pt`

* tablex-test: add tests for line expansion

* tablex-test: check return type of conversion to pt

* tablex-test: test precision of conversion to pt

* add issue number to tablex-test.typ

* pdf will be in separate commit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Single-cell negative line expansion does not work
2 participants