Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>What you want is a <code>DocumentFont</code>. You cannot create them directly, the constructor is package private, but <code>BaseFont.createFont(PRIndirectReference)</code> will do the trick.</p> <p>So you just need to get a <code>PRIndirectReference</code> to the font you want. "PR"s come from a PdfReader. There are two ways to find the font you're looking for and get a reference to it:</p> <p>1) Enumerate every object in the PdfReader, filtering out everything that's not a <code>PRStream</code>, from there dropping everything that's not a <code>/Type /Font</code>, and looking for a font with the correct name.</p> <pre><code>public PRIndirectReference findNamedFont( PdfReader myReader, String desiredFontName) { int objNum = 0; PdfObject curObj; do { //The "Release" version doesn't keep a reference //to the object so it can be GC'd later. Quite Handy //when dealing with Really Big PDFs. curObj = myReader.getPdfObjectRelease( objNum++ ); if (curObj instanceof PRStream) { PRStream stream = (PRStream)curObj; PdfName type = stream.getAsName(PdfName.TYPE); if (PdfName.FONT.equals(type)) { PdfString fontName = stream.getAsString(PdfName.BASEFONT); if (desiredFontName.equals(fontName.toString())) { return curObj.getIndRef(); } } } } while (curObj != null); return null; } </code></pre> <p>2) Examine your pages' resource dictionaries <code>/Font &lt;&lt;&gt;&gt;</code> dicts, looking for a font with the correct name. Keep in mind that XObject Form resources have resources of their own you'll have to check to:</p> <pre><code>public PRIndirectReference findFontInPage(PdfReader reader, String desiredName, int i) { PdfDictionary page = reader.getPageN(i); return findFontInResources(page.getAsDict(PdfName.RESOURCES), desiredName); } public PRIndirectReference findFontInResources(PdfDictionary resources, String desiredName) { if (resources != null) { PdfDictionary fonts = resources.getAsDict(PdfName.FONTS); if (fonts != null) { for (PdfName curFontName : fonts.keySet()) { PRStream curFont (PRStream)= fonts.getAsStream(curFontName); if (desiredName.equals(curFont.getAsString(PdfName.BASEFONT).toString()) { return (PRIndirectReference) curFont.getIndirectReference(); } } } PdfDictionary xobjs = resources.getAsDict(PdfName.XOBJECTS); if (xobjs != null) { for (PdfName curXObjName : xobjs.keySet()) { PRStream curXObj = (PRStream)xobjs.getAsStream(curXObjName); if (curXObj != null &amp;&amp; PdfName.FORM.equals(curXObj.getAsName(PdfName.SUBTYPE)) { PdfDictionary resources = curXObj.getAsDict(PdfName.RESOURCES); PRIndirectReference ref = findFontInResources(resources, desiredName); if (ref != null) { return ref; } } } } } return null; } </code></pre> <p>Either one of those will get you the <code>PRIndirectReference</code> you're after. Then you call <code>BaseFont.createFont(myPRRef)</code> and you'll have the <code>DocumentFont</code> you need. The first method will find any font in the PDF, while the second will only find fonts That Are Actually Used.</p> <p>Also, subsetted fonts are supposed to have a "6-random-letters-plus-sign" tag prepended to the font name. DO NOT use a font subset. The characters you're using may not be in the subset, leading to what I call the " arry ole" problem. It sounds nice and dirty, but it was really just our sales guy's name: "Harry Vole" missing the upper case letters because I'd subsetted some font I shouldn't have Many Moons Ago.</p> <p>PS: never embed subsets of fonts you intend to be used in a form field. No Bueno.</p> <p>The usual "I wrote all that code in the answer box here" disclaimer applies, but I've written a LOT of this sort of code, so it just might work out of the box. Cross your fingers. ;)</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload