Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* ===========================================
* Java Pdf Extraction Decoding Access Library
* ===========================================
*
* Project Info: http://www.idrsolutions.com
* Help section for developers at http://www.idrsolutions.com/support/
*
* (C) Copyright 1997-2017 IDRsolutions and Contributors.
*
* This file is part of JPedal/JPDF2HTML5
*
@LICENSE@
*
* ---------------
* FormStream.java
* ---------------
*/
package org.jpedal.objects.raw;
import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.util.StringTokenizer;
import org.jpedal.external.ExternalHandlers;
import org.jpedal.fonts.FontMappings;
import org.jpedal.fonts.PdfFont;
import org.jpedal.fonts.StandardFonts;
import org.jpedal.io.ObjectStore;
import org.jpedal.io.PdfFileReader;
import org.jpedal.io.PdfObjectFactory;
import org.jpedal.io.PdfObjectReader;
import org.jpedal.parser.PdfStreamDecoder;
import org.jpedal.parser.ValueTypes;
import org.jpedal.render.T3Display;
import org.jpedal.render.T3Renderer;
import org.jpedal.utils.LogWriter;
/**
* Scan object and create images, set values in Appearances
*/
public class FormStream {
public static final boolean debugUnimplemented = false; //to show unimplemented parts*/
public static final boolean debug = false; //print info to screen
//only display once
private static boolean showFontMessage;
/**
* exit when an unimplemented feature or error has occured in form/annot
* code
*/
public static final boolean exitOnError = false;
public static Object[] getRolloverKeyValues(final PdfObject form, final PdfFileReader pdfFileReader) {
String key = null;
PdfObject val = null;
PdfObject rollOffDic = null;
final PdfKeyPairsIterator APkeys = form.getKeyPairsIterator();
if (APkeys != null && APkeys.getTokenCount() > 0) {
while (APkeys.hasMorePairs()) {
final String glyphKey = APkeys.getNextKeyAsString();
final byte[] data = APkeys.getNextValueAsBytes();
if (data != null) {
if (glyphKey.equals("Off")) {
rollOffDic = PdfObjectFactory.getPDFObjectObjectFromRefOrDirect(new FormObject(glyphKey), pdfFileReader, data, PdfDictionary.AP);
} else {
key = glyphKey;
val = PdfObjectFactory.getPDFObjectObjectFromRefOrDirect(new FormObject(glyphKey), pdfFileReader, data, PdfDictionary.AP);
}
}
APkeys.nextPair();
}
} else {
if (form.getDictionary(PdfDictionary.Off) != null) {
rollOffDic = form.getDictionary(PdfDictionary.Off);
} else if (form.getDecodedStream() != null) {
rollOffDic = form;
}
//if we have a root stream then it is the off value
if (form.getDictionary(PdfDictionary.On) != null) {
key = "On";
val = form.getDictionary(PdfDictionary.On);
}
}
return new Object[]{key, val, rollOffDic};
}
public static Object[] getNormalKeyValues(final PdfObject form, final PdfFileReader pdfFileReader) {
final PdfObject APobjN = form.getDictionary(PdfDictionary.AP).getDictionary(PdfDictionary.N);
String key = null;
PdfObject val = null;
PdfObject normalOffDic = null;
final PdfKeyPairsIterator APkeys = APobjN.getKeyPairsIterator();
if (APkeys != null && APkeys.getTokenCount() > 0) {
while (APkeys.hasMorePairs()) {
final String glyphKey = APkeys.getNextKeyAsString();
final byte[] data = APkeys.getNextValueAsBytes();
if (data != null) {
if (glyphKey.equals("Off")) {
normalOffDic = PdfObjectFactory.getPDFObjectObjectFromRefOrDirect(new FormObject(glyphKey), pdfFileReader, data, PdfDictionary.AP);
} else {
key = glyphKey;
val = PdfObjectFactory.getPDFObjectObjectFromRefOrDirect(new FormObject(glyphKey), pdfFileReader, data, PdfDictionary.AP);
}
}
APkeys.nextPair();
}
} else {
//if we have a root stream then it is the off value
//check in order of N Off, MK I, then N
//as N Off overrides others and MK I is in preference to N
if (APobjN.getDictionary(PdfDictionary.Off) != null) {
normalOffDic = APobjN.getDictionary(PdfDictionary.Off);
} else if (form.getDictionary(PdfDictionary.MK).getDictionary(PdfDictionary.I) != null
&& form.getDictionary(PdfDictionary.MK).getDictionary(PdfDictionary.IF) == null) {
//look here for MK IF
//if we have an IF inside the MK then use the MK I as some files shown that this value is there
//only when the MK I value is not as important as the AP N.
normalOffDic = form.getDictionary(PdfDictionary.MK).getDictionary(PdfDictionary.I);
} else if (APobjN.getDecodedStream() != null) {
normalOffDic = APobjN;
}
if (APobjN.getDictionary(PdfDictionary.On) != null) {
val = APobjN.getDictionary(PdfDictionary.On);
key = "On";
}
}
return new Object[]{key, val, normalOffDic};
}
public static Object[] getDownKeyValues(final PdfObject form, final PdfFileReader pdfFileReader) {
String key = null;
PdfObject val = null;
PdfObject downOffDic = null;
final PdfKeyPairsIterator APkeys = form.getKeyPairsIterator();
if (APkeys != null && APkeys.getTokenCount() > 0) {
while (APkeys.hasMorePairs()) {
final String glyphKey = APkeys.getNextKeyAsString();
final byte[] data = APkeys.getNextValueAsBytes();
if (data != null) {
if (glyphKey.equals("Off")) {
downOffDic = PdfObjectFactory.getPDFObjectObjectFromRefOrDirect(new FormObject(glyphKey), pdfFileReader, data, PdfDictionary.AP);
} else {
key = glyphKey;
val = PdfObjectFactory.getPDFObjectObjectFromRefOrDirect(new FormObject(glyphKey), pdfFileReader, data, PdfDictionary.AP);
}
}
APkeys.nextPair();
}
} else {
//down on
if (form.getDictionary(PdfDictionary.On) != null) {
key = "On";
val = form.getDictionary(PdfDictionary.On);
}
//down off
//if we have a root stream then it is the off value
if (form.getDecodedStream() != null) {
downOffDic = form;
} else if (form.getDictionary(PdfDictionary.Off) != null) {
downOffDic = form.getDictionary(PdfDictionary.Off);
}
}
return new Object[]{key, val, downOffDic};
}
/**
* handle of file reader for form streams
*/
protected PdfObjectReader currentPdfFile;
/**
* flag to show if XFA (will be disabled if XFA from version which is not
* pure XFA)
*/
public boolean isXFA;
public FormStream() {
}
public static final int[] id = {PdfDictionary.A, PdfDictionary.C2, PdfDictionary.Bl,
PdfDictionary.E, PdfDictionary.X, PdfDictionary.D, PdfDictionary.U, PdfDictionary.Fo,
PdfDictionary.PO, PdfDictionary.PC, PdfDictionary.PV,
PdfDictionary.PI, PdfDictionary.O, PdfDictionary.C1, PdfDictionary.K,
PdfDictionary.F, PdfDictionary.V, PdfDictionary.C2, PdfDictionary.DC,
PdfDictionary.WS, PdfDictionary.DS, PdfDictionary.WP, PdfDictionary.DP};
/**
* takes in a FormObject already populated with values for the child to
* overwrite
*/
public void createAppearanceString(final FormObject formObj, final PdfObjectReader inCurrentPdfFile) {
currentPdfFile = inCurrentPdfFile;
init(formObj);
}
private void init(final FormObject formObject) {
final boolean debug = false; //formObject.getPDFRef().equals("68 0 R");
if (debug) {
System.out.println("------------------------------setValues-------------------------------" + formObject + ' ' + formObject.getObjectRefAsString());
}
//set Ff flags
final int Ff = formObject.getInt(PdfDictionary.Ff);
if (Ff != PdfDictionary.Unknown) {
formObject.commandFf(Ff);
}
//set Javascript
resolveAdditionalAction(formObject);
if (debug) {
System.out.println("AP=" + formObject.getDictionary(PdfDictionary.AP));
}
// //Check if AP is missing and add if possible
// if (formObject.getDictionary(PdfDictionary.AP) == null ||
// formObject.getDictionary(PdfDictionary.AP).getDictionary(PdfDictionary.N) == null) {
// AnnotationUtils.createAPObjectForFormObject(formObject, currentPdfFile);
// }
//at the moment only handles static
// (and not dynamic which are created at Runtime if
// formObject.getBoolean(PdfDictionary.NeedAppearances) is true
setupAPimages(formObject, currentPdfFile.getObjectReader());
//set H
final int key = formObject.getNameAsConstant(PdfDictionary.H);
if (key != PdfDictionary.Unknown) {
/*
* highlighting mode
* done when the mouse is pressed or held down inside the fields active area
* N nothing
* I invert the contents
* O invert the border
* P display down appearance stream, or if non available offset the normal to look down
* T same as P
*
* this overides the down appearance
* Default value = I
*/
if (key == PdfDictionary.T || key == PdfDictionary.P) {
if (!formObject.hasDownImage()) {
formObject.setOffsetDownApp();
}
} else if (key == PdfDictionary.N) {
//do nothing on press
formObject.setNoDownIcon();
} else if (key == PdfDictionary.I) {
//invert the contents colors
formObject.setInvertForDownIcon();
}
}
//set Fonts
final String textStream = formObject.getTextStreamValue(PdfDictionary.DA);
if (textStream != null) {
decodeFontCommandObj(textStream, formObject);
}
}
/**
* set correct flags for AP images
*/
private static void setupAPimages(final FormObject formObject, final PdfFileReader pdfFileReader) {
final PdfObject APobjN = formObject.getDictionary(PdfDictionary.AP).getDictionary(PdfDictionary.N);
//if valid AP, setup flags to show we use images
if (APobjN != null) {
final String ASvalue = formObject.getName(PdfDictionary.AS);
formObject.setAppreancesUsed(true);
final String key = (String) getNormalKeyValues(formObject, pdfFileReader)[0];
if (key != null) {
formObject.setNormalOnState(key);
if (ASvalue != null && ASvalue.equals(key)) {
formObject.setSelected(true);
}
}
}
}
/**
* defines actions to be executed on events 'Trigger Events'
*
* @Action This is where the raw data is parsed and put into the FormObject
*/
private void resolveAdditionalAction(final FormObject formObject) {
/*
* entries NP, PP, FP, LP never used
* A action when pressed in active area ?some others should now be ignored?
* E action when cursor enters active area
* X action when cursor exits active area
* D action when cursor button pressed inside active area
* U action when cursor button released inside active area
* Fo action on input focus
* BI action when input focus lost
* PO action when page containing is opened,
* actions O of pages AA dic, and OpenAction in document catalog should be done first
* PC action when page is closed, action C from pages AA dic follows this
* PV action on viewing containing page
* PI action when no longer visible in viewer
* K action on - [javascript]
* keystroke in textfield or combobox
* modifys the list box selection
* (can access the keystroke for validity and reject or modify)
* F the display formatting of the field (e.g 2 decimal places) [javascript]
* V action when fields value is changed [javascript]
* C action when another field changes (recalculate this field) [javascript]
*/
int idValue;
for (final int anId : id) {
//store most actions in lookup table to make code shorter/faster
idValue = anId;
currentPdfFile.setJavascriptForObject(formObject, PdfDictionary.AA, idValue);
currentPdfFile.setJavascriptForObject(formObject, PdfDictionary.A, idValue);
}
}
/**
* decode appearance stream and convert into VectorRenderObject we can
* redraw if width and height are 0 we define the size hear offsetImage - 0=
* no change, 1= offset, 2= invert image pScaling used by HTML - set to 1
* otherwise
*/
public static BufferedImage decode(final PdfObject formObj, final PdfObjectReader currentPdfFile, final PdfObject XObject, final int subtype,
int width, int height, final int offsetImage, final float pageScaling) {
//handle XFA differently
if (XObject.getObjectType() == PdfDictionary.XFA_APPEARANCE) {
return ExternalHandlers.decode(formObj, currentPdfFile, XObject, subtype, width, height, offsetImage, pageScaling);
}
currentPdfFile.checkResolved(XObject);
try {
//create renderer object
final org.jpedal.fonts.glyph.T3Glyph form = decodeStream(currentPdfFile, XObject);
final float[] matrix = XObject.getFloatArray(PdfDictionary.Matrix);
final float[] BBox = XObject.getFloatArray(PdfDictionary.BBox);
final float scaling;
float rectX1 = 0, rectY1 = 0;
if (BBox != null) {
for (int ii = 0; ii < 4; ii++) {
BBox[ii] *= pageScaling;
}
rectX1 = (BBox[0]);
rectY1 = (BBox[1]);
//Some files have fractions of a pixel in their size In some cases
//this needs to be ignored, other times it should be expanded to a full pixel
//At the moment this is not required, this note is left as a reminder.
int boxWidth = (int) (((BBox[2] + 0.5f) - BBox[0]));
if (boxWidth < 0) {
boxWidth = -boxWidth;
}
int boxHeight = (int) (((BBox[3] + 0.5f) - BBox[1]));
if (boxHeight < 0) {
boxHeight = -boxHeight;
}
if (boxWidth == 0 && boxHeight > 0) {
boxWidth = 1;
}
if (boxWidth > 0 && boxHeight == 0) {
boxHeight = 1;
}
//if the width and height scaling are miles apart then the width and height
//are probably the wrong way round so swap them. and recalc the scalings.
float ws = width / ((float) boxWidth);
float hs = height / ((float) boxHeight);
//check if dimensions are correct and alter if not
final float diff = ws - hs;
final int diffInt = (int) diff;
if (diffInt != 0) {
//NOTE width and height sent in need to be rotated
//as they are not as the image is drawn
final int tmpI = width;
width = height;
height = tmpI;
ws = width / ((float) boxWidth);
hs = height / ((float) boxHeight);
}
//NOTE now we re set the width and height to scaled
//value of Bounding box to keep the orientation
//if scaling less than 1 use 1
if (ws < 1 || hs < 1) {
scaling = 1;
width = boxWidth;
height = boxHeight;
} else {
//use larger scaling as will produce better image
if (ws > hs) {
scaling = ws;
height = (int) (boxHeight * scaling);
} else {
scaling = hs;
width = (int) (boxWidth * scaling);
}
//make sure image position is scaled
rectX1 *= scaling;
rectY1 *= scaling;
}
} else {
final float defaultSize = 20;
if (height < defaultSize) {
height = (int) defaultSize;
}
if (width < defaultSize) {
width = (int) defaultSize;
}
final float ws = width / defaultSize;
final float hs = height / defaultSize;
if (ws > hs) {
scaling = ws;
height = (int) (defaultSize * scaling);
} else {
scaling = hs;
width = (int) (defaultSize * scaling);
}
//make sure image position is scaled
rectX1 *= scaling;
rectY1 *= scaling;
}
if (width == 0 || height == 0) {
return null;
}
//if offset
if (offsetImage == 1) {
width += 2;
height += 2;
}
final BufferedImage aa;
if (matrix != null && matrix[2] != 0) {
aa = new BufferedImage(height, width, BufferedImage.TYPE_INT_ARGB);
} else {
aa = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
}
final Graphics2D g2 = createGraphics(aa, formObj, matrix, BBox, pageScaling, scaling, rectX1, rectY1, width, height);
if (offsetImage == 2) { //invert
g2.scale(-1, -1);
} else if (offsetImage == 1) { //offset
g2.translate(1, 1);
}
//carry the sclaing through to the render method
form.render(0, g2, scaling * pageScaling, true);
g2.dispose();
if (subtype == PdfDictionary.Highlight) {
final BufferedImage i = new BufferedImage(aa.getWidth(), aa.getHeight(), aa.getType());
final Graphics2D gg = i.createGraphics();
gg.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
gg.drawImage(aa, 0, 0, null);
gg.dispose();
return i;
}
return aa;
} catch (final Exception e) {
LogWriter.writeLog("Exception: " + e.getMessage());
return null;
} catch (final Error e) {
LogWriter.writeLog("Error: " + e.getMessage());
if (ExternalHandlers.throwMissingCIDError && e.getMessage() != null && e.getMessage().contains("kochi")) {
throw e;
}
return null;
}
}
private static Graphics2D createGraphics(final BufferedImage aa, final PdfObject formObj, float[] matrix, final float[] BBox, final float pageScaling, final float scaling, final float transformOffsetX, final float transformOffsetY, final int width, final int height) {
final Graphics2D g2;
int offset = height;
if (matrix != null) {
//Added for odd case 22179
//pageScaling!=1 added to lock out of html as when not 1 html baseline is affected
if (pageScaling == 1 && matrix[4] > 0 && matrix[5] > 0) {
matrix = createMatrixFromBoundingBoxes(BBox, formObj.getFloatArray(PdfDictionary.Rect));
} else {
//scale so they offset correctly
matrix[4] = matrix[4] * scaling * pageScaling;
matrix[5] = matrix[5] * scaling * pageScaling;
}
if (matrix[2] != 0) {
offset = width;
} else if (matrix[1] >= 0) {
//rectX1 and rectY1 already have the scaling applied
if (matrix[4] != 0f) {
matrix[4] = -transformOffsetX;
}
if (matrix[5] != 0f) {
matrix[5] = -transformOffsetY;
}
}
g2 = (Graphics2D) aa.getGraphics();
final AffineTransform flip = new AffineTransform();
flip.translate(0, offset);
flip.scale(1, -1);
g2.setTransform(flip);
if (debug) {
System.out.println(" rectX1 = " + transformOffsetX + " rectY1 = " + transformOffsetY + " width = " + width + " height = " + height);
}
final AffineTransform affineTransform = new AffineTransform(matrix);
g2.transform(affineTransform);
} else {
g2 = (Graphics2D) aa.getGraphics();
final AffineTransform flip = new AffineTransform();
flip.translate(0, offset);
flip.scale(1, -1);
g2.setTransform(flip);
}
return g2;
}
private static float[] createMatrixFromBoundingBoxes(final float[] BBox, final float[] BBox2) {
final float[] matrix = new float[6];
if (BBox2[1] > BBox2[3]) {
final float t = BBox2[1];
BBox2[1] = BBox2[3];
BBox2[3] = t;
}
if (BBox2[0] > BBox2[2]) {
final float t = BBox2[0];
BBox2[0] = BBox2[2];
BBox2[2] = t;
}
matrix[0] = (BBox2[2] - BBox2[0]) / (BBox[2] - BBox[0]);
matrix[1] = 0;
matrix[2] = 0;
matrix[3] = (BBox2[3] - BBox2[1]) / (BBox[3] - BBox[1]);
matrix[4] = (BBox2[0] - BBox[0]);
matrix[5] = (BBox2[1] - BBox[1]);
return matrix;
}
private static org.jpedal.fonts.glyph.T3Glyph decodeStream(final PdfObjectReader currentPdfFile, final PdfObject XObject) {
//generate local object to decode the stream
final ObjectStore localStore = new ObjectStore();
final T3Renderer glyphDisplay = new T3Display(0, false, 20, localStore);
final PdfStreamDecoder glyphDecoder = new PdfStreamDecoder(currentPdfFile);
glyphDecoder.setParameters(false, true, 15, 0, false, false);
glyphDecoder.setStreamType(ValueTypes.FORM);
glyphDecoder.setObjectValue(ValueTypes.ObjectStore, localStore);
glyphDecoder.setRenderer(glyphDisplay);
/*read any resources*/
try {
final PdfObject Resources = XObject.getDictionary(PdfDictionary.Resources);
if (Resources != null) {
glyphDecoder.readResources(Resources, false);
}
} catch (final Exception e) {
LogWriter.writeLog("Exception: " + e.getMessage());
}
/*decode the stream*/
final byte[] commands = XObject.getDecodedStream();
if (commands != null) {
glyphDecoder.decodeStreamIntoObjects(commands, false);
}
final boolean ignoreColors = glyphDecoder.ignoreColors;
localStore.flush();
return new org.jpedal.fonts.glyph.T3Glyph(glyphDisplay, 0, 0, ignoreColors);
}
/**
* Accepts PdfObjectReader and PdfObject containing an AP stream This reads
* the AP stream, and returns the display text from stream
*
* @param currentPdfFile PdfObjectReader object to read the AP stream
* @param Xobject PdfObject containing the AP stream to be read
* @return String containing display text from AP stream
*/
public static String decipherTextFromAP(final PdfObjectReader currentPdfFile, final PdfObject Xobject) {
try {
final ObjectStore localStore = new ObjectStore();
/*
* create renderer object
*/
final T3Renderer glyphDisplay = new T3Display(0, false, 20, localStore);
/*
* generate local object to decode the stream
*/
final PdfStreamDecoder glyphDecoder = new PdfStreamDecoder(currentPdfFile, null);
glyphDecoder.setParameters(false, true, 15, 0, false, false);
glyphDecoder.setObjectValue(ValueTypes.ObjectStore, localStore);
glyphDecoder.setRenderer(glyphDisplay);
/*read any resources*/
try {
final PdfObject Resources = Xobject.getDictionary(PdfDictionary.Resources);
if (Resources != null) {
glyphDecoder.readResources(Resources, false);
}
} catch (final Exception e) {
LogWriter.writeLog("Exception: " + e.getMessage());
}
/*decode the stream*/
final byte[] commands = Xobject.getDecodedStream();
String textString = "";
if (commands != null) {
textString = glyphDecoder.decodeStreamIntoObjects(commands, true);
}
if (textString == null || textString.isEmpty()) {
textString = null;
}
localStore.flush();
return textString;
} catch (final Exception e) {
LogWriter.writeLog("Exception: " + e.getMessage());
return null;
} catch (final Error e) {
LogWriter.writeLog("Error: " + e.getMessage());
if (ExternalHandlers.throwMissingCIDError && e.getMessage() != null && e.getMessage().contains("kochi")) {
throw e;
}
return null;
}
}
/**
* method to rotate an image through a given angle
*
* @param src the source image
* @param rotation the angle to rotate the image through
* @return the rotated image
*/
public static BufferedImage rotate(final BufferedImage src, final int rotation) {
final BufferedImage dst;
if (src == null) {
return null;
}
//if angle is 0 we dont need to do anything
if (rotation == 0) {
return src;
}
final double angle = rotation * Math.PI / 180;
final int w = src.getWidth();
final int h = src.getHeight();
final int newW = (int) (Math.round(h * Math.abs(Math.sin(angle)) + w * Math.abs(Math.cos(angle))));
final int newH = (int) (Math.round(h * Math.abs(Math.cos(angle)) + w * Math.abs(Math.sin(angle))));
final AffineTransform at = AffineTransform.getTranslateInstance((newW - w) / 2, (newH - h) / 2);
at.rotate(angle, w / 2, h / 2);
dst = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB);
final Graphics2D g2 = dst.createGraphics();
g2.drawRenderedImage(src, at);
g2.dispose();
return dst;
}
public boolean hasXFADataSet() {
return false;
}
/**
* takes the PDF commands and creates a font
*
* @param
*/
public static void decodeFontCommandObj(final String fontStream, final FormObject formObject) {
//now parse the stream into a sequence of tokens
final StringTokenizer tokens = new StringTokenizer(fontStream, "() []");
final int tokenCount = tokens.countTokens();
final String[] tokenValues = new String[tokenCount];
int i = 0;
while (tokens.hasMoreTokens()) {
tokenValues[i] = tokens.nextToken();
i++;
}
//now work out what it does and build up info
for (i = tokenCount - 1; i > -1; i--) {
// System.out.println(tokenValues[i]+" "+i);
//look for commands
if (tokenValues[i].equals("g")) { //set color (takes 1 values
i--;
float col = 0;
try {
col = Float.parseFloat(handleComma(tokenValues[i]));
} catch (final Exception e) {
LogWriter.writeLog("Error in generating g value " + tokenValues[i] + ' ' + e);
}
formObject.setTextColor(new float[]{col});
} else if (tokenValues[i].equals("Tf")) { //set font (takes 2 values - size and font
i--;
int textSize = 8;
try {
textSize = (int) Float.parseFloat(handleComma(tokenValues[i]));
// if(textSize==0)
// textSize = 0; //TODO check for 0 sizes CHANGE size to best fit on 0
} catch (final Exception e) {
LogWriter.writeLog("Error in generating Tf size " + tokenValues[i] + ' ' + e);
}
i--; //decriment for font name
String font = null;
try {
font = tokenValues[i];
if (font.startsWith("/")) {
font = font.substring(1);
}
} catch (final Exception e) {
LogWriter.writeLog("Error in generating Tf font " + tokenValues[i] + " " + e);
}
final PdfFont currentFont = new PdfFont();
currentFont.setFont(font, textSize);
String fontName = StandardFonts.expandName(font);
final String altName = FontMappings.fontSubstitutionAliasTable.get(fontName.toLowerCase());
if (altName != null) {
fontName = altName;
}
formObject.setFontName(fontName);
formObject.setTextFont(currentFont.getGlyphData().getUnscaledFont());
formObject.setTextSize(textSize);
} else if (tokenValues[i].equals("rg") || tokenValues[i].equals("r")) {
i--;
final float b = Float.parseFloat(handleComma(tokenValues[i]));
i--;
final float g = Float.parseFloat(handleComma(tokenValues[i]));
i--;
final float r = Float.parseFloat(handleComma(tokenValues[i]));
formObject.setTextColor(new float[]{r, g, b});
} else if (tokenValues[i].equals("Sig")) {
LogWriter.writeFormLog("Sig- UNIMPLEMENTED=" + fontStream + "< " + i, debugUnimplemented);
} else if (tokenValues[i].equals("\\n")) {
//ignore \n
if (debug) {
System.out.println("ignore \\n");
}
} else if (!showFontMessage) {
showFontMessage = true;
LogWriter.writeFormLog("{stream} Unknown FONT command " + tokenValues[i] + ' ' + i + " string=" + fontStream, debugUnimplemented);
}
}
}
private static String handleComma(String tokenValue) {
//if comma used as full stop remove
final int comma = tokenValue.indexOf(',');
if (comma != -1) {
tokenValue = tokenValue.substring(0, comma);
}
return tokenValue;
}
@SuppressWarnings("UnusedDeclaration")
/*
* Unimplemented in base class, intended for use in XFAFormStream
*
* @throws RuntimeException if called from this class, it throws an exception
**/
public byte[] getXFA(final int xfaTemplate) {
throw new RuntimeException("getXFA Should never be called in base class");
}
public boolean isXFA() {
return isXFA;
}
}