Hi,

Thanks for the comfirmation and the suggestion. I've committed it and there's a 
snapshot build in
https://repository.apache.org/content/groups/snapshots/org/apache/pdfbox/pdfbox-app/3.0.9-SNAPSHOT/

or get it from the repository and build yourself.

Tilman

On 2026/07/20 12:45:53 Olivier Bruchez wrote:
> Hi Tilman,
> 
> It's way cleaner than my POC.
> 
> I tested your changes locally (the setFont change plus the splitter map). I
> got the same speedup as my original patch, with no output change. On a
> 96-page PDF, the time spent drawing text went from 3.1 s to 0.85 s.
> 
> That's great. Thanks a lot!
> 
> Olivier
> 
> On Fri, 17 Jul 2026 at 15:08, Tilman Hausherr <[email protected]> wrote:
> 
> > Hi,
> >
> > I prefer something more simple because I don't want to keep a static map
> > forever. Like this:
> >
> >     Map<String,GlyphArraySplitter> map = new WeakHashMap<>();
> >
> > and in applyGsubFeature:
> >
> > GlyphArraySplitter glyphArraySplitter =
> > map.computeIfAbsent(scriptFeature.getName(), (__) -> new
> > GlyphArraySplitterRegexImpl(allGlyphIdsForSubstitution));
> >
> > is this what you had in mind?
> >
> > Tilman
> >
> > On 2026/07/17 10:08:44 Olivier Bruchez wrote:
> > > Hi Tilman,
> > >
> > > Thanks for your reply and for opening an issue.
> > >
> > >
> > > > I assume what you did was to check the gsubWorkers map before calling
> > > > gsubWorkerFactory.getGsubWorker(), correct?
> > > >
> > >
> > > Not exactly. I should have included my patch/"hack" in the original
> > message
> > > for more clarity. I'm basically simply adding a global cache for the
> > > GlyphArraySplitter, inside GsubWorkerForLatin. I left setFont and the
> > > gsubWorkers map alone. It is built in applyGsubFeature (once per
> > showText),
> > > not in the constructor, so reusing the GsubWorker alone would not stop
> > the
> > > rebuild and the performance hit. I memoized the GlyphArraySplitter per
> > font
> > > and then per script feature (I think this is correct, but I'm not 100%
> > > sure).
> > >
> > > The whole change is one line in applyGsubFeature:
> > >
> > > - GlyphArraySplitter glyphArraySplitter = new
> > >
> > GlyphArraySplitterRegexImpl(scriptFeature.getAllGlyphIdsForSubstitution());
> > > + GlyphArraySplitter glyphArraySplitter = splitterFor(scriptFeature);
> > >
> > >
> > https://github.com/apache/pdfbox/blob/3.0.4/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GsubWorkerForLatin.java#L91-L92
> > >
> > > Plus a static cache keyed on the font's GsubData and a small helper:
> > >
> > > private static final Map<GsubData, Map<String, GlyphArraySplitter>>
> > > SPLITTER_CACHE = new WeakHashMap<>();
> > >
> > > private GlyphArraySplitter splitterFor(ScriptFeature scriptFeature)
> > > {
> > >     synchronized (SPLITTER_CACHE)
> > >     {
> > >         Map<String, GlyphArraySplitter> perFont =
> > > SPLITTER_CACHE.get(gsubData);
> > >         if (perFont == null)
> > >         {
> > >             perFont = new HashMap<>();
> > >             SPLITTER_CACHE.put(gsubData, perFont);
> > >         }
> > >         GlyphArraySplitter splitter =
> > perFont.get(scriptFeature.getName());
> > >         if (splitter == null)
> > >         {
> > >             splitter = new
> > >
> > GlyphArraySplitterRegexImpl(scriptFeature.getAllGlyphIdsForSubstitution());
> > >             perFont.put(scriptFeature.getName(), splitter);
> > >         }
> > >         return splitter;
> > >     }
> > > }
> > >
> > > This is a proof of concept, of course. This was just to convince myself
> > > that rebuilding GlyphArraySplitter multiple times was indeed the problem
> > I
> > > was observing. On larger PDF files (dozens of pages), the speedup with
> > the
> > > code above is really huge (3-4x on the total PDF generation times).
> > >
> > > Thanks,
> > > Olivier
> > >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [email protected]
> > For additional commands, e-mail: [email protected]
> >
> >
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to