Migrate PDF font layout to per-document GlyphLayoutManager (#2444) - #2463
Conversation
|
It would be better if you maintained a single commit by rebasing on master (as necessary), amending your commit and force pushing the changes. |
merks
left a comment
There was a problem hiding this comment.
Many small comments. In general copyright dates should be a range and type names should be imported not fully qualified in the body.
For Git noobs like me: Once you |
a9480cd to
11fb171
Compare
11fb171 to
244b8a0
Compare
hvbtup
left a comment
There was a problem hiding this comment.
Some questions here and there.
I think we need a test case that allows manually checking the PDF results.
In particular, some of the examples from the old issues with Arabic, Chinese etc, and a demo report with a large font size to make the kerning actually visible.
Like this text: "AV cables VA Maya Vase WM WA AW with Kerning".
|
I startet a CI run. Using the build artifacts, it will be easier for other users to test. |
244b8a0 to
51b5aa4
Compare
|
Pushed an update (amended, single commit):
Verification details in the comment above. |
51b5aa4 to
04275e8
Compare
hvbtup
left a comment
There was a problem hiding this comment.
I couldn't spot an error in the code, but I tested it and it simply does not work.
What I did for testing:
- Downloaded and unpacked the build artifact (birt-report-designer-win32-x86_64.zip)
- Downloaded the report glm-manual-check.rptdesign
- Opened the report in the designer
- No Kerning or ligatures visibile (so far, this is expected)
- Closed the designer
- Modified the file birt.ini and added -Dbirt.pdf.complex.font.layout.enabled=true
- Repeated the steps 3-5, still no kerning, still, this is expected
- Modified the file D:\eclipse\birt-pr-2463\eclipse\plugins\org.eclipse.birt.report.engine.fonts_4.25.0.v202606101527\fontsConfig.xml and changed the line 68 to
<kerning-and-ligatures enabled="true" /> - Repeated steps 3-5, still no kerning.
Since the kerning is enabled in fontConfig.xml and in the system property now, this should work AFAIK, but it does not.
The visible result is no different with kerning enabled, the gap between the letters V and A is still the same (too far).
I also created a report of my own, which shows the system property and user property; with the same result. Please find it attached here.
04275e8 to
26bc0da
Compare
Test Case Verification Update@hvbtup Thanks for sharing the I’ve made some minor fixes based on the observations and verified the following scenarios before and after the fix:
With Arial (which has kern pairs, unlike the bundled Noto Sans), the content stream changes from a plain show-text to a positioned array, and the adjustments match the font's kern table: kerning off: <0024 0039 ...>Tj 0024=A, 0039=V — 74.22 matches Arial's AV kern of -74; W/A shows 37.11, matching -37. Your own report renders the same way via the user property alone: [<0024>74.22<0039>...]TJ for "AV module VA". The attached results show the behavior before and after the fix. Could you please give your test case another shot with the latest changes? Thanks! |
|
OK, I can now see that it seems to works with my test report. What did you change in the code to make it work now? I can also see that kerning works for the English text in the I can not verify if the rendering of the Arabic and Chinese texts is correct in that report's PDF output. To me it seems that there might be an issue with the reading direction LTR / RTL? I think we need someone who can read Arabic to verify if it's correct. |
…irt#2444) Replace OpenPDF's deprecated, process-global LayoutProcessor with the per-document GlyphLayoutManager, which holds no static state and is safe for concurrent multi-document rendering (issue eclipse-birt#2444). - Remove LayoutProcessor usage from FontHandler and PDFPage.validateSymbolicFont. - PDFPageDevice creates a per-document GlyphLayoutManager behind an opt-in property (birt.pdf.complex.font.layout.enabled / PdfEmitter.ComplexFontLayoutEnabled), off by default, so existing output is unchanged. It is created lazily on first draw, since the report's user properties are not available when the device is constructed. - Fonts are loaded lazily on first draw, resolved per font via the font factory rather than scanning font directories; kerning and ligatures are applied when enabled by the kerning-and-ligatures font configuration. - PDFPage.drawText sets the manager on the writer for fonts loaded into it, and draws with the base font the manager created, since the manager only recognises its own instance. Base-14/Type1/symbolic fonts draw on the normal path. - Fix the run direction to left-to-right: BIRT applies bidi reordering and shaping before the emitter, so right-to-left text must be drawn as delivered. - Add PdfConcurrentRenderTest as a concurrency regression guard. - Add glm-manual-check.rptdesign for manual verification of glyph layout. - Remove FontHandlingPdfTest, a manual LayoutProcessor demo tied to the removed API. - Document the new property in the emitter README. Signed-off-by: Rahul Pal <hyrahulpal@gmail.com>
26bc0da to
39295f9
Compare
|
|
@wimjongman @merks I think for the next release this change should be emphasized; people who use BIRT for non-latin writing system should definitely test. Also, it should be pointed out that, for kerning and ligatures to work, two settings are necessary: |
|
I don't know where such documentation should exist that people would find it. We have the root READ.md buch not much else. I have no clue how the website is maintained. https://github.com/eclipse-birt/birt-website/commits/main/ There is a massive ignored backlog of security issues https://github.com/eclipse-birt/birt-website/security/dependabot |

What this does
Migrates the PDF emitter's complex-font layout from OpenPDF's deprecated,
process-global
LayoutProcessorto the per-DocumentGlyphLayoutManager(OpenPDF's designated replacement, from LibrePDF/OpenPDF#1519). The manager holds
no static state and is designed for concurrent multi-document rendering, which is
the goal of #2444.
The global
LayoutProcessorstate is the root of the thread-safety problem in#2444 — the same class of race that surfaced in production as #2385 (multi-threaded
PDF export failing with Chinese characters). By moving to per-document state, that
class of race is removed. (Note: races are non-deterministic, so this is addressed
by the design change rather than proven by a test; see Testing below.)
Approach
FontHandlerandPDFPage.validateSymbolicFont— removed allLayoutProcessorusage.PDFPageDevice— creates a per-DocumentGlyphLayoutManager, gated behindan opt-in property (
birt.pdf.complex.font.layout.enabledsystem property orPdfEmitter.ComplexFontLayoutEnableduser property), off by default soexisting output is unchanged.
is constructed (the registered font paths are empty at that point), so fonts are
loaded into the manager lazily on the first draw. TrueType/OpenType fonts are
loaded with kerning and ligatures enabled via
FontOptions.PDFPage.drawText— attaches the manager only for fonts it has loaded, anddetaches (
setGlyphLayoutManager(null)) for base-14/Type1/symbolic fonts. Thisis required because
GlyphLayoutManager.supportsFont(...)throws for any font notloaded through it, so un-loadable fonts must not reach it — they draw on the
normal path instead.
Why off by default / no regression
With the property off, no manager is created or attached, and rendering is
byte-for-byte unchanged. The removed
LayoutProcessorpath was only ever reachablewhen
LayoutProcessor.supportsFont(...)was true, i.e. for fonts loaded into it;default rendering already flowed through
showTextBasic.Testing
PdfConcurrentRenderTest(inemitter.pdf.tests) — renders the samedesign from multiple threads on a shared engine and asserts none fail. It is a
regression guard / demonstration of concurrent rendering, not a proof that
the race is gone (by nature, races can't be deterministically triggered). The
real safety argument is the per-document design.
unchanged with it off.
(kerning/ligatures/non-Latin shaping) — automated glyph-position checks are
impractical, consistent with the existing tests in this module. I'd very much
value review against the non-Latin cases this feature originally targeted
(Arabic Content with Arabic Characters is incorrect for output format PDF since 4.17 #2133, Chinese BIRT 4.22 Export PDF fails in multi threaded environment when report uses Chinese characters #2385), since you have the reference for what correct
output looks like.
Removed test
Removed
FontHandlingPdfTest— a manual demo (main()with hardcodedC:/temp/paths, no assertions; its own Javadoc says results must be validated manually) built
entirely on the
LayoutProcessorAPI this PR removes. Its purpose is superseded bythe
GlyphLayoutManagerpath.OpenPDF version
No version change needed — both bundles already declare
com.github.librepdf.openpdf;bundle-version="[3.0.0,4.0.0)"in their manifests.Open questions / for review
GlyphLayoutManagerand the existingsetGlyphSubstitutionEnabled(...)(FopGlyphProcessor, Enhance pdf glyph substitution handling (#2133) #2141) are mutuallyexclusive. This PR does not yet coordinate them; guidance welcome (@speckyspooky).
validateSymbolicFont's handling is now implicit (symbolicfonts take the detached/normal path). Please confirm this preserves the intended
behaviour for Webdings-type fonts.