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: dev@pdfbox.apache.org
Subject: Re: Font provider since PDFBOX-2842


On 1 Sep 2015, at 06:12, Petr Slabý <sl...@kadel.cz> 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: dev@pdfbox.apache.org
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 <j...@jahewson.com>:

Hi Cornelis,

> On 24 Aug 2015, at 02:20, Cornelis Hoeflake <c.hoefl...@postex.com>
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: dev-unsubscr...@pdfbox.apache.org
For additional commands, e-mail: dev-h...@pdfbox.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@pdfbox.apache.org
For additional commands, e-mail: dev-h...@pdfbox.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@pdfbox.apache.org
For additional commands, e-mail: dev-h...@pdfbox.apache.org

Reply via email to