As with Cornelis, I’d direct you to look at jimfs, which is an in- memory
filesystem for Java
That is not needed, I think. All I need to do is to implement FontProvider
on top of our internal resource provider API which reads the stuff from the
database. But I need multiple instances of FontMapper/FontProvider in one
JVM (because more than one application/customer can be running in the
application server instance) and I need to be able to flush the FontMapper
if the configuration changes and the FontProvider has new files.
So you have fonts for specific customers for rendering only their
documents and you expect those to change frequently?
Really? Why don’t your customers embed such fonts? ...
Customers do all kind of wild things. Most usually, the PDFs we are dealing
with are supposed to be PDF/A, so there is no problem. But I have already
seen PDFs in a company's archive which were using external fonts. Or
customers with an old application nobody is able to touch, producing such
PDFs. I cannot send the customer to hell then.
The fonts do not change frequently, of course. But as the Universe wants it,
a missing font or wrong configuration is never found on a test system. It
happens somewhere in the production and then it is really impossible to
restart the JVM.
In any case, external fonts are possible and in a perfect solution I need to
cover the two previously mentioned use cases - multiple FontMapper instances
in a single JVM and a change of fonts available to a FontMapper after it has
already been initialized.
As a minimal solution, it should be enough for me if I can re-initialize the
FontMapper using a new instance of FontProvider. It will be tricky to make
it thread safe, but I hope I will manage to do that using a "readers–writer
lock" pattern. This does not cover the multiple different configurations
case very well (or at all because only a single configuration can be used
for concurrent renderings), but at least enables to change the configuration
at runtime. Maybe this should already work if I use
FontMapper.setProvider()?
Unfortunately, PDFBox 2.0 release escaped our own release cycle by one year
once again, so I will have no resources to really try to implement against
the new version until somewhere in the next year. If you say having a
non-static FontMapper would break all the APIs and postpone the 2.0 release
by yet another year, I will rather live with what we have now.
Best regards,
Petr.
-----Původní zpráva-----
From: John Hewson
Sent: Wednesday, September 02, 2015 4:43 AM
To: [email protected]
Subject: Re: Font provider since PDFBOX-2842
On 1 Sep 2015, at 06:12, Petr Slabý <[email protected]> wrote:
John,
I am facing basically the same issues as Cornelis.
Our application is running in a J2EE application server, so installing
anything into the operation system is usually not an option. It is already
difficult in a cluster environment managed by the customer, but becomes
virtually impossible in a dynamic cloud. Everything has to come from a
database.
As with Cornelis, I’d direct you to look at jimfs,
https://github.com/google/jimfs <https://github.com/google/jimfs> which is
an in- memory filesystem for Java. You could pull fonts from your database
into there. Maybe one directory for each customer.
Some of our customers are (document) service providers working for a
bunch of other companies. There it is important to be able to use
different configurations for different groups of documents, because of
licencing and other reasons.
So you have fonts for specific customers for rendering only their documents
and you expect those to change frequently? Really? Why don’t your customers
embed such fonts?
Are you talking about providing “desired” mappings, e.g. allowing
“Helvetica” to be mapped to the customer’s own “Helvetica.ttf” or are you
talking about support for custom fonts, e.g. “MyCorporateFont.ttf”?
Are you wanting to customise the substation behaviour, or just provide
additional font files?
Last but not least, the configuration (available fonts) can be changed by
storing some new resources into the database. Restarting the application
server (cluster) - so that a static class gets instantiated again and
reads the new configuration - is no option.
Yes, obviously you don’t want to have to restart. So we do need some way in
PDFBox to allow the FontMapper to be re-initialized at runtime. Note that
PDFBox no longer requests one font at a time, it requests all fonts because
we need to examine all fonts to find the best match. You’re also going to
need to store all of the font metadata in your database, so that your custom
FontProvider can pull all of it when it’s initialised. That means all of the
fields in the FontInfo class need to be present in your database.
Initialising FileSystemFontProvider can take 10 seconds or more, so it’s
not practical to create a new one for each document.
I do not care :-) I am not reading file system (usually not allowed to
anyway). And I know the place where to initialize and cache the fonts in
my application.
Everyone else does care if it takes 10sec to open every PDDocument but...
We could switch to having a per-document FontMapper or FontProvider, with
the default being to use a shared static provider
Would be perfect, I think.
… this mitigates that issue, so it should be fine.
— John
Best regards,
Petr
-----Original message----- From: Cornelis Hoeflake
Sent: Tuesday, September 01, 2015 2:26 PM
To: [email protected]
Subject: Re: Font provider since PDFBOX-2842
Sorry for my delayed reply, I missed your reply for some reason...
2015-08-24 20:54 GMT+02:00 John Hewson <[email protected]>:
Hi Cornelis,
> On 24 Aug 2015, at 02:20, Cornelis Hoeflake <[email protected]>
wrote:
>
> Hi,
>
> In the before PDFBOX-2842 situation we set the FontProvider on
> ExternalFonts to a thread bound font provider (uses ThreadLocal).
> This is done because we have a systemen where multiple customers which
have
> their own fonts. That fonts could also dynamically added to the system
> > at
> runtime. We have implemented the FontProvider so that it looks in the
> database for a font request.
My first question is: do you really need this? What fonts are your users
uploading and
why are they missing from PDFs? Could you make them available in some
other way?
Do the fonts really need to be locked down to a given user? Why not keep
it simple and
copy the font files to the local system?
My customers have licensed (and custom made) fonts. So the first issue is
that a license for customer 1 is not valid for customer 2. The next
problem
is dat the name of custom made fonts does not have to be globally unique.
The last problem is that the server environment is provisioned on services
like Amazon Elastic Beanstalk wit autoscaling etc. In that case there is
no
decent option to copy fonts to the system.
> In the new situation FontMapper reads the font information once (at
> setProvider) and uses this global for the whole system.
The old approach, ExternalFonts used the font name to perform a direct
lookup,
delegating this to the FontProvider. The new FontMapper performs a
best-fit
lookup using multiple attributes such as the name, ROS, weight, family,
unicode
ranges, style, and panose classification. This requires that we first
build an index
of those attributes for each font.
Ok, that is a nice feature. But for my case customers want the correct
font, not a best-fit.
> How can we create a situation like we had but then with the new code? I
do
> not see an option.
Could you explain how you’re currently using ThreadLocal? There might be
a
workaround. Failing that we could provide a mechanism to allow the font
index
to be updated dynamically.
I have set a custom made 'general' FontProvider. Before doing any
operation
which uses ExternalFonts.getProvider(), I set a customer FontProvider
(which knows all about the fonts of that customer) in a ThreadLocal in de
'general' FontProvider. The 'general' FontProvider delegates each request
to the customer FontProvider.
> I think it is a good idea to drop static FontMapper, FontProvider etc.
And
> replace it with a given FontProvider/Mapper at start of a document.
Initialising FileSystemFontProvider can take 10 seconds or more, so it’s
not practical
to create a new one for each document. We could switch to having a
per-document
FontMapper or FontProvider, with the default being to use a shared static
provider,
with the user being able to set their own, however we have static APIs
which require
a FontMapper to exist independently from a document, namely:
- all PDFont subclass constructors
- PDType1Font constants (TIMES_ROMAN, HELVETICA, COURIER, etc.)
I don’t see any way to make the changes you’re after without breaking all
those APIs.
Yes, that is true... On the other hand, more and more server software
products are switching to services like Amazon Elastic Beanstalk etc. And
last but not least, the API for FontProvider/Mapper and the previous
ExternalFonts is already broken. Withint 2.0 and between 1.8 and 2.0.
— John
> Kind regards,
> Cornelis Hoeflake
---------------------------------------------------------------------
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]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]