I am trying to add some custom fonts (client supplied) to our lucee application. We need these fonts for use with cfimage (not cfdocument PDF generation). We’ve tried 4 different approaches, and had very limited success. Please bear with the length as I try to get all (and only) the pertinent details in.
I’m hoping that someone else has beat this already. We’ve spent literally man-weeks chasing this down.
ENVIRONMENT
Our environment is Java 7 (or 8), Tomcat 8 (or 8.5), installed in Azure Web Apps. (IIS based hosting) We have tried all sorts of combinations of Java version and Tomcat/Jetty versions. Lucee 4.5.x (specifically 4.5.5.006). Coldbox 4.1.
APPROACHES
Here are the four methods we’ve tried and the issues that have stopped us. If you know how to get past the roadblocks we’ve hit on ANY of these options, it would be most excellent.
-
Adding the fonts directly to the Windows fonts directory. The Azure Web App security model does not permit this. This simplest of solutions is a non-starter.
-
Adding the fonts to the fonts.jar file and modifying the pd4fonts.properties files to the lucee install. (as per Adding New Font to PDF using CFDOCUMENT in RAILO iSummation - USA). This gave access to the new fonts for cfdocument, but NOT for cfimage.
-
Adding JAVA_FONTS environment variable specifying the path to our custom fonts. This did not load the fonts for cfimage. (in retrospect - we didn’t check to see if they worked for cfdocument or not). We tried a number of different permutations of argument setting, and none of them seemed to load. I’m not a Java guru, so I’m definitely leaving the door open to having a syntax error.
-
CLOSEST TO SUCCESS - We wrote some code in our Coldbox onAppInit to manually find the fonts in the folder, build Java objects, and register the fonts with the graphics engine. This DOES LOAD the fonts, and we CAN use them with cfimage. Unfortunately, after successfully generating images it crashes. More specifically, after a somewhat variable length of time (between 20 min and a full day) we get a Java exception that crashes the JVM. We can generate thousands of images with font on them, but if we let it sit idle for a longish time, it crashes the next time we try to do anything image related. It feels like it is the Garbage Collection crashing rather than the image manipulation threads. I’ll paste some of the log dump here, and then the code following it. If we run the same tests without loading the custom fonts (and just use one of the built in ones) the app will run for days. We cannot find a case of a crash when we only use the built in fonts.
CRASH LOG
Current thread (0x000000001b5c0000): JavaThread “Java2D Disposer” daemon [_thread_in_native, id=1964, stack (0x000000001fbe0000,0x000000001fce0000)]
siginfo: ExceptionCode=0xc0000005, reading address 0xffffffffc0000022
with the following java frames. Always in the FontStrikeDisposer.
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j sun.java2d.d3d.D3DGraphicsDevice.initD3D()Z+0
j sun.java2d.d3d.D3DGraphicsDevice.<clinit>()V+4
v ~StubRoutines::call_stub
j sun.awt.Win32GraphicsEnvironment.makeScreenDevice(I)Ljava/awt/GraphicsDevice;+9
j sun.java2d.SunGraphicsEnvironment.getScreenDevices()[Ljava/awt/GraphicsDevice;+30
j sun.awt.Win32GraphicsEnvironment.getDefaultScreenDevice()Ljava/awt/GraphicsDevice;+1
j sun.font.StrikeCache.disposeStrike(Lsun/font/FontStrikeDisposer;)V+26
j sun.font.FontStrikeDisposer.dispose()V+19
j sun.java2d.Disposer.run()V+26
j java.lang.Thread.run()V+11
v ~StubRoutines::call_stub
CODE - in the onAppInit method of our Coldbox application
local.p = ExpandPath("./includes/fonts/");
local.d = DirectoryList(local.p,false,"name","*.ttf|*.otf");
for(local.l in local.d){
if(not ArrayFindNoCase(local.loadedFonts,ListFirst(local.l,".")))
ArrayAppend(local.fontsToLoad,local.l);
}
if(ArrayLen(local.fontsToLoad) gt 0){
local.ge = CreateObject('java','java.awt.GraphicsEnvironment').getLocalGraphicsEnvironment();
local.f = StructNew();
for(local.l in local.fontsToLoad){
local.i = CreateObject('java','java.io.FileInputStream').Init(JavaCast("string",local.p&local.l));
local.f[local.l] = CreateObject('java','java.awt.Font');
local.x = local.ge.registerFont(local.f[local.l].createFont(local.f[local.l].TRUETYPE_FONT, local.i));
}
}
Please let me know if you have questions or suggestions. I don’t really have enough hair to pull any more out at this point. I don’t even know if I should be chasing code bugs or environment configuration. Maybe I’ll just go buy a caseload of RAM on Amazon and find the flag to turn off GC altogether.
Thanks!