Add new font for cfdocument

currently I have a barcode font, but when I print as pdf with cfdocument the font is not change. In coldfusion we can add the font at font folder. How we do it in lucee?

I read in some forum, we can do it with updating the fonts.jar in /lucee/lib folder. But I cannot find it fonts.jar in that folder, anyone know about this ?

Thanks
Andri

This discussion might help…

https://lucee.daemonite.io/t/problem-with-chinese-characters-in-pdf/467

i have the same problem… i want to add barcode fonts to custom fonts… i’ve added the ttf files to fonts.jar and added font name in pd4fonts.properties

i have tried several times like below :

  • added fonts.jar in folder /srv/apps/lucee/lib/ ( folder lib that contains "lucee-5.X.X.XXX.jar), after that i cannot start my lucee in my vagrant… i have to delete this file then i can restart lucee successfully.

  • added fonts.jar in opt/lucee/lib folder (previously this folder doesn’t exist) and nothing happens

  • added Code39.ttf, code39u.ttf and IDAutomationHC39M.ttf in /srv/apps/lucee/jdk/jre/jre/lib/fonts/ folder (in this folder contains ttf font files). after that i cannot start my lucee properly until delete those files.

  • added fonts.jar in /srv/apps/lucee/tomcat/lucee-server/bundles/ folder (in this folder contains a lot of jars, so i think i can include fonts.jar in this folder), but still doesn’t work…

  • Finally, i tried to add fonts.jar in WEB-INF/lucee/lib/ folder in my vagrant installation and fonts.jar was loaded in WEB-INF/lucee/logs/application.log… but still i cannot use custom fonts…

is there any way that i missed, using wrong method, placing fonts.jar in wrong folder, or anything? i’m really confused why it still won’t show…

We gave up on using fonts to create barcodes and create images using ZXing instead. You include the zxing files (core-3.1.0.jar and javase-3.1.0.jar in our case, which can be found at http://central.maven.org/maven2/com/google/zxing/core/3.1.0/ and http://central.maven.org/maven2/com/google/zxing/javase/3.1.0/) in [lucee]/tomcat/lib, then the following code will produce a barcode:

<cfset format=createObject('java','com.google.zxing.BarcodeFormat')>
<cfset writer=createObject('java','com.google.zxing.oned.Code128Writer').init()>
<cfset matrix=createObject('java','com.google.zxing.client.j2se.MatrixToImageWriter')>
<cfset output="My Barcode">
<cfset barcode=writer.encode(output,format.CODE_128,75,75)>
<cfset image=ImageNew(matrix.toBufferedImage(barcode))>
<cfoutput>#image#</cfoutput>

Put the relevant text in the ‘output’ variable and fiddle with the parameters in the ‘barcode’ variable to adjust the barcode to your needs.

Simon

2 Likes

thank you for the suggestion… i tried this method and successful…

but the problem is, my custom fonts aren’t barcodes only… i have several fonts like verdana, gothic and other fonts that not included in lucee…

this is really frustating just to add custom fonts… in coldfusion, adding custom fonts is really simple… :confused:

load font style on tag html

<style>
body {font-family:"Code39",IDAutomationHC39M; font-size:12px;}
</style>

it still won’t work… i also try to show it in cfm, not in cfdocument but also doesn’t work… is there anyone have a clue what is wrong with it? i really need to use custom fonts and it kinda frustating that it won’t work at all… :frowning:

here is my example code to test custom font

<cfscript>
	document name="pdfOutput" format="PDF" pageType="A4" marginBottom="0.1" marginLeft="1.5" marginRight="1.5" marginTop="0.2" unit="cm" {
		writeOutput('
			<style type="text/css">
				p.barcode, h3.barcode {font-family:"Code39",IDAutomationHC39M; font-size:12px;}
			</style>
			<p>Barcode Custom Font Test:</p>
			<h3 class="barcode">1234567890</h3>
			<p class="barcode">1234567890</p>
		');
	}
	header name="Content-Disposition" value="inline; filename=test.pdf";
	content reset="true" type="application/pdf" variable="pdfOutput";
</cfscript>

after copy file font, did you restart your lucee?

of course i have… i even restart my vagrant for this… but still no result…

I just had a long custom font loading fight with lucee too. We’re deployed on PaaS, so we can’t touch the fonts.jar file, or any of the java folders or libraries.

What we needed to do is pass the java launch some JAVA_OPTS. Here’s the JAVA_OPTS we used…

-Dsun.java2d.fontpath=D:\home\site\wwwroot\webapps\ROOT\MyApplication\includes\fonts

We just put the ttf files in that directory and java picked up on them and loaded them. You need to restart your java engine for this to take effect.

I’m really thank you for your reply and information… but i not familiar about JAVA_OPTS…

where do we add the “Dsun.java2d.fontpath” path?

from your example path given, are you using windows? do you know where do we add it in linux?

i’m using vagrant and linux as the OS for my virtualization…

It is an argument passed into java when you launch your j2ee server. Where and how you specify that is probably unique to your environment.

For me - I’m using Azure Webapps - so I can just put it in the environment variable in the setup (method 2) https://blogs.msdn.microsoft.com/azureossds/2015/10/09/setting-environment-variable-and-accessing-it-in-java-program-on-azure-webapp/

You will need to find where/how you pass in arguments to java when it launches your Tomcat (or whatever J2EE server you are running).

(The more I think about it, the more I think that JAVA_OPTS is just the method that Azure uses. You will probably want to search for adding java arguments to the command line)

What if you’re using cfimage?

Dale

Hey Simon,

i have been enjoying doing CFML for the first time in 15 years working on a PoC over lockdown and i tried your code above but i get the below error -

com/google/zxing/common/BitMatrix
 
The error occurred in D:\wwwroot\cps.cp3.luceeplanet.com\httpdocs\cfqr\index.cfm: line 6

4: <cfset output="My Barcode">
5: <cfset barcode=writer.encode(output,format.CODE_128,75,75)>
6: <cfset image=ImageNew(matrix.toBufferedImage(barcode))>
7: <cfoutput>#image#</cfoutput>

I have seen this code in a number of places and i have tested it multiple times, but i get the same error. I have put the core & j2se 3.4 Jar files in the lucee/lib/ directory. Lucee can see it loaded … i am just a bit stumped … is there anything else i need to do … ?

Hi Rory,
Try placing the two .jar files in the lucee/tomcat/lib directory instead, restart Tomcat and see if you get a result.
Simon

May be this jars won’t be loaded because of not being OSGI compliant? You can try creating the OSGI Manifest/Metadata (what I’ve never done) or try using Mark Mandels Javaloader, a very valuable tip that I’ve learnt from @Julian_Halliwell1. If this works for you, do the following:

  1. Go to Mark Mandels Github Javaloader Repository and download the Javaloader (this is the javaloader-folder in his repository) to your webroot:

  2. Create a folder in your webroot named lib, and add the jars to the lib directory (in this case I’ve added the barcode image processing library ZXING core-3.4.0.jar and javase-3.4.0.jar)

  3. create cfm file barcode128.cfm with the following content:

<cfscript>
filePaths = ArrayNew(1);
filePaths[1] = expandPath("lib\core-3.4.0.jar");
filePaths[2] = expandPath("lib\javase-3.4.0.jar");
 
//Creating a java loader object by passing in the array containing the file paths –
loaderObj =createObject("component","Javaloader.JavaLoader").init(filePaths);

format 	= loaderObj.create("com.google.zxing.BarcodeFormat");
writer 	= loaderObj.create("com.google.zxing.oned.Code128Writer");
matrix 	= loaderObj.create("com.google.zxing.client.j2se.MatrixToImageWriter");

</cfscript>

<cfset output="My Barcode">
<cfset barcode=writer.encode(output,format.CODE_128,75,75)>
<cfset image=ImageNew(matrix.toBufferedImage(barcode))>
<cfoutput>#image#</cfoutput>

Here you have a working example in zip-file, I’ve uploaded this also to keep it documented for myself: barcode128Javaloader.zip (575.5 KB)

1 Like

By the way, welcome back!!!

Andreas and team,

great tested it and updated it for 2d which is what i wanted … I will now use the same technique for reading them.

<cfscript>
filePaths = ArrayNew(1);
filePaths[1] = expandPath("lib\core-3.4.0.jar");
filePaths[2] = expandPath("lib\javase-3.4.0.jar");

//Creating a java loader object by passing in the array containing the file paths –
loaderObj =createObject("component","Javaloader.JavaLoader").init(filePaths);

format 	= loaderObj.create("com.google.zxing.BarcodeFormat");
writer 	= loaderObj.create("com.google.zxing.qrcode.QRCodeWriter");
matrix 	= loaderObj.create("com.google.zxing.client.j2se.MatrixToImageWriter");

</cfscript>

<cfset output="Thanks great job !">
<cfset barcode=writer.encode(output,format.QR_CODE,75,75)>
<cfset image=ImageNew(matrix.toBufferedImage(barcode))>
<cfoutput>#image#</cfoutput>

Once again thanks guys - see its works scan the below !

thanks

1 Like

I have bolt the reading part in to the PoC and it seams to work OK.

One more question - i assume i can wrap all this into a CFC and call it like a normal component ?


<cfscript>
filePaths = ArrayNew(1);
filePaths[1] = expandPath("lib\core-3.4.0.jar");
filePaths[2] = expandPath("lib\javase-3.4.0.jar");

//Creating a java loader object by passing in the array containing the file paths –
loaderObj =createObject("component","Javaloader.JavaLoader").init(filePaths);

format 	= loaderObj.create("com.google.zxing.BarcodeFormat");
writer 	= loaderObj.create("com.google.zxing.qrcode.QRCodeWriter");
matrix 	= loaderObj.create("com.google.zxing.client.j2se.MatrixToImageWriter");

</cfscript>

<cfset output="Thanks great job !">
<cfset barcode=writer.encode(output,format.QR_CODE,75,75)>
<cfset image=ImageNew(matrix.toBufferedImage(barcode))>
<cfoutput>#image#</cfoutput>



<!--- extract the BufferedImage of the current barcode --->
<cfset buff = ImageGetBufferedImage( #image# ) />
<!--- prepare the image for decoding --->
<cfset source = loaderobj.create("com.google.zxing.client.j2se.BufferedImageLuminanceSource").init( buff ) />
<cfset binarizer = loaderobj.create("com.google.zxing.common.GlobalHistogramBinarizer").init( source ) />
<cfset bitmap = loaderobj.create("com.google.zxing.BinaryBitmap").init( binarizer ) />
<cfset reader = loaderobj.create("com.google.zxing.qrcode.QRCodeReader").init() />
<!--- decode the barcode. skipping "hints" just for simplicity --->
<cfset decodedResult = reader.decode( bitmap, javacast("null", "")) />

<!--- display results --->
<b>Decoded Text = </b> <cfoutput>#decodedResult.getText()#</cfoutput>

it all work … once again guys thanks a lot. i wasted quite a while trying to get this to work … Thx

Rory

1 Like

One thing to bear in mind when using the JavaLoader is that you need to store it in the server scope in order to avoid memory problems…