Repository navigation
Added automatic character range detection that determines font - #3155
Conversation
bsweeney
left a comment
There was a problem hiding this comment.
I think these suggested changes should help with performance. The changes I made are:
- Always perform font mapping. This removes duplicate processing of text in those cases where the full block of text was not supported by the font. This imparts a slight performance hit in the case where the full text is supported by the font, but it's negligible (with my limited testing).
- Only process as much text as necessary when mapping the font. Since in this particular use case we only want the first block of mapped text there's no need to map beyond that.
- Commented out the building the string for each mapped block. That adds overhead for something we don't currently use. I think it could still be worthwhile, just not in this particular use case. Maybe we can optionally generated that content based on an additional argument?
Worth noting that the additional frame count resulting from the font mapping still impacts performance, but less so than before.
It may be possible to squeeze a bit more performance out of this by processing the string one character at a time instead of splitting it at the start. However, I think this would only improve performance on extremely long strings, which seems like an outlier.
381bd55 to
43f4b87
Compare
bsweeney
left a comment
There was a problem hiding this comment.
Updated suggestions. A lot of the other functions would not longer be needed, though once we go 'round a few more times we can figure out what can be extracted.
a6a0df8 to
b775f96
Compare
|
If you think this is ready for review, I can take a look at the changes. |
|
Thanks ... I'm doing some last minute testing to see if I can squeeze out a bit more performance. Plus I need to update the render tests. But I think the basic logic is ready for review so have at it. |
b775f96 to
ed44712
Compare
|
@robvanderlee FYI I rewrote the history to make this change a bit easier to follow. There will always be a performance impact with this change since we're a) parsing each character of a text frame, and b) generating more frames (when required by font matching). I don't have a clean system for performance testing, but what testing I did do shows minimal impact on most documents. The greatest impact would be in the target scenario where the user just wants to specify a sequence of fonts and let Dompdf pick the right one. But even there the impact is not significant. I tested with both PHP 7.1 and 8.2 using the current release of Dompdf and this branch with each of the backend options. The document I used was fairly simple in structure. Times below are in milliseconds. The base document looks like this: First test, 100 paragraphs of lorem ipsum:
Next test, a document with lots of manual font styling to render the text with the appropriate font. The document was 100 of the following paragraphs. This is not ideal since there is no text variability, but there aren't many lorem ipsum generators that work with multiple languages in the body content. Let alone segment the text appropriately.
Final test, the same as above without the any manual text styling.
|
|
As a quick note, the render tests fail because bold and italic font styles are not applied anymore. |
|
Thank for finding that. An embarrassing oversight on my part for sure. I neglected to include the font style/weight as part of the font mapping logic. Should be OK now. I obviously was too focused on a particular test case. I'm sure I would have figured that out ... eventually. |
8a31640 to
aad3206
Compare
|
Unit tests seem happy and most of the "core" test I have up in the debug helper look OK on first pass. I am seeing a slight difference in the rendering of some document (e.g., https://eclecticgeek.com/dompdf/core_tests/encoding_utf-8_w3.html) that I need to investigate. |
|
Will look at the rest of the code later this week. |
aad3206 to
de8257f
Compare
Found two issues.
|
de8257f to
bab1064
Compare
|
The font-resolve logic is now essentially duplicated: We have the existing logic in the
But maybe this does not need to be addressed right now, and can be tackled later. |
|
One more thing: Shrink-to-fit width determination (for table columns, float, etc.) is now incorrect when text is split via the new logic, since |
bab1064 to
2a48504
Compare
2a48504 to
5e972a6
Compare
5e972a6 to
235fc6c
Compare
There appear to be two issues related to this?
I think you're right that performing the font mapping earlier in the process is probably necessary. I'll need to look at this some more. |
To support PHP versions < 7.2
This method allows the user to determine if the characters in a string are fully supported by the specified font. This is arguably a FontMetrics operation, but since support is also dependent on the PDF back end this is, perhaps, a more robust option. Complimentary logic will be added to FontMetrics. GD does not have a built-in method for determing support so logic to retrieve the character glyph mapping is borrowed from Cpdf.
With this change the text reflower scans the text of the frame to determine which font from the styled font families supports the characters contained within. Font preference is based on the order the fonts in the style declarations value. When characters in the text are supported by different fonts the frame is split at the character where the font changes. The used value of the current frame's font-family style is set to the supporting font. fixes dompdf#3142 should help enable full unicode-range support (dompdf#913)
...since these should be represented in the text with the replacement character. Excludes non-printable characters.
235fc6c to
5646d0c
Compare
|
Update to address the shrink-to-fit issue by moving the font mapping logic to the decorator so that it can be called as necessary. Duplicated calls are avoided by recording the mapped font in a private property. I do think it would work better to handle recognition of mapping being complete by inspecting the used value ... somehow. I didn't see an obvious good way to do this so I'll leave that as an optimization for another time. |
No description provided.