This one took me actually some hours to fully understand.
I recommend reading the ticket description made by Phil as it already explains 
most of it.

What is the problem (in `Utils`):
- `Utils.computeTextWidth(..)` does not initialize the `boundsType`. As a 
consequence, we do not cache the layout result
  - For the text width, it makes sense to set it, so the result is cached. 
  Note that the `boundsType` does not matter for the width calculation itself, 
but we really want it set so the result will be cached if possible
- At one point due to `Utils.computeTextHeight(..)` method call, the 
`boundsType` is initialized. Now calls to `Utils.computeTextWidth(..)` do cache 
the result
  - So in order to fix that, `Utils.computeTextWidth(..)` does now set the the 
property as well

Ok, but why only cache this specific usecase (Phil was also wondering about 
that) (in `PrismTextLayout`):
- First of all, the previous method name was confusing (me). 
What it actually does: 
  - decide if the layout result should be cached 
  - when we have a cache hit, if we can reuse it completely or ONLY the text 
runs
- So what `PrismTextLayout` does is to cache the layout result for simple cases 
with the default setting. 
  - This is biased towards modena, which specifies `-fx-bounds-type: 
logical_vertical_center;` for ever `Text` node
    - If one of those setting or the bounds type do not match, we will not 
cache the text layout or reuse it completely, but the text runs instead
- That means the logic is fine and there's a thought behind it: Only cache if 
the settings match those we are most likely to receive from the application
  - In case we have already a cache result but for example the `wrapWidth` or 
the `boundsType` is different, we can reuse the runs but not the whole cached 
layout result
  - So we should not cache results with `boundsType = 0`, as those will have 
another height than with `boundsType = BOUNDS_CENTER`
    - So the logic is unchanged there

As `StubTextLayout` extends `PrismTextLayout`, we can actually write meaningful 
tests:
- So I wrote a bunch that make clear how the cache works and when a 
`GlyphLayout` is created (due to a complete cache miss) 
- Note that the tests are green before and after this PR
- Because `PrismTextLayout.setContent(..)` will request the font strike (for 
`hashCode` calculation for the layout result cache), I needed to implement 
`hashCode` and `equals` for some of the stub test classes (the JavaFX font 
classes do that as well)
- I renamed the `StubFontContractTest` to a better name since we do test a bit 
more now
  - And back in 2024 when I wrote this test class, I forgot the copyright 
header 🙃. Added now

Can we improve more?
- The ticket suggests that we could cache more in `LabeledSkinBase`. There are 
also some TODOs in this class. This could be a potential follow-up.

---------
- [x] I confirm that I make this contribution in accordance with the [OpenJDK 
Interim AI Policy](https://openjdk.org/legal/ai).

-------------

Commit messages:
 - 8301283: Util methods for computing text/width height giving up some 
performance

Changes: https://git.openjdk.org/jfx/pull/2145/files
  Webrev: https://webrevs.openjdk.org/?repo=jfx&pr=2145&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8301283
  Stats: 618 lines in 7 files changed: 398 ins; 207 del; 13 mod
  Patch: https://git.openjdk.org/jfx/pull/2145.diff
  Fetch: git fetch https://git.openjdk.org/jfx.git pull/2145/head:pull/2145

PR: https://git.openjdk.org/jfx/pull/2145

Reply via email to