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@
*
* ---------------
* AnnotationUtils.java
* ---------------
*/
package org.jpedal.io.annotation.utils;
import java.awt.*;
import java.awt.geom.CubicCurve2D;
import java.awt.geom.Rectangle2D;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.List;
import org.jpedal.PdfDecoderInt;
import org.jpedal.fonts.StandardFonts;
import org.jpedal.io.ObjectDecoder;
import org.jpedal.io.PdfObjectReader;
import org.jpedal.objects.acroforms.AcroRenderer;
import org.jpedal.objects.acroforms.GUIData;
import org.jpedal.objects.acroforms.creation.AnnotationFactory;
import org.jpedal.objects.raw.FormObject;
import org.jpedal.objects.raw.PdfDictionary;
import org.jpedal.objects.raw.PdfObject;
import org.jpedal.objects.raw.ResourcesObject;
import org.jpedal.utils.LogWriter;
/**
* AnnotationUtils contains basic utility methods that are required
* by the annotation creation and editing functionality.
*/
public class AnnotationUtils {
/**
* Checks if the given annotation has editable properties
*
* @param form object representing an annotation
* @return boolean
*/
public static boolean isEditableAnnotation(final FormObject form) {
final int annotType = form.getParameterConstant(PdfDictionary.Subtype);
return annotType == PdfDictionary.Circle
|| annotType == PdfDictionary.Square
|| annotType == PdfDictionary.Line
|| annotType == PdfDictionary.Ink
|| annotType == PdfDictionary.Link
|| annotType == PdfDictionary.Polygon
|| annotType == PdfDictionary.PolyLine
|| annotType == PdfDictionary.Highlight
|| annotType == PdfDictionary.FreeText
|| annotType == PdfDictionary.Text;
}
/**
* Checks if the given annotation can be moved on the page
*
* @param form object representing an annotation
* @return boolean
*/
public static boolean isDraggableAnnotation(final FormObject form) {
final int annotType = form.getParameterConstant(PdfDictionary.Subtype);
return annotType == PdfDictionary.Circle
|| annotType == PdfDictionary.Square
|| annotType == PdfDictionary.Line
|| annotType == PdfDictionary.Ink
|| annotType == PdfDictionary.Polygon
|| annotType == PdfDictionary.PolyLine
|| annotType == PdfDictionary.FreeText
|| annotType == PdfDictionary.Text;
}
/**
* Checks if the given annotation can be resized
*
* @param form object representing an annotation
* @return boolean
*/
public static boolean isResizableAnnotation(final FormObject form) {
final int annotType = form.getParameterConstant(PdfDictionary.Subtype);
return annotType == PdfDictionary.Circle
|| annotType == PdfDictionary.Square
|| annotType == PdfDictionary.Line
|| annotType == PdfDictionary.Ink
|| annotType == PdfDictionary.FreeText
|| annotType == PdfDictionary.Polygon
|| annotType == PdfDictionary.PolyLine;
}
/**
* Checks if there are any form objects at the given point
*
* @param decode_pdf PdfDecoderInt object used to access forms data
* @param x int object representing the x coordinate
* @param y int object representing the y coordinate
* @return the first FormObject found at the given point, else null
*/
public static FormObject isOverForm(final PdfDecoderInt decode_pdf, final int x, final int y) {
if (decode_pdf.isOpen()) {
final AcroRenderer formRenderer = decode_pdf.getFormRenderer();
if (formRenderer != null) {
final GUIData compData = formRenderer.getCompData();
if (compData != null) {
final List[] formList = compData.getFormList(true);
if (formList != null && decode_pdf.getPageNumber() < formList.length) {
final List forms = formList[decode_pdf.getPageNumber()];
if (forms != null) {
for (final FormObject form : forms) {
//Turn off if statement for now
if (form != null && form.getBoundingRectangle().contains(x, y)) {
return form;
}
}
}
}
}
}
}
return null;
}
/**
* Checks if the given coordinates are within the bounds of any editable annotations
* on the current pages
*
* @param decode_pdf PdfDecoderInt object used to access forms data
* @param x int object representing the x coordinate
* @param y int object representing the y coordinate
* @return boolean
*/
public static boolean isOverAnnotation(final PdfDecoderInt decode_pdf, final int x, final int y) {
if (decode_pdf.isOpen() && decode_pdf.getFormRenderer() != null) {
final GUIData compData = decode_pdf.getFormRenderer().getCompData();
if (compData != null) {
final List[] formList = compData.getFormList(true);
if (formList != null && decode_pdf.getPageNumber() < formList.length) {
final List forms = formList[decode_pdf.getPageNumber()];
if (forms != null) {
for (final FormObject form : forms) {
if (form != null && isEditableAnnotation(form)) {
if (form.getBoundingRectangle().contains(x, y)) {
return true;
}
}
}
}
}
}
}
return false;
}
/**
* Return the provided coordinates as an array in the order smallest x,
* smallest y, largest x, largest y
*
* @param sx float value representing one point on the x axis
* @param sy float value representing one point on the y axis
* @param ex float value representing one point on the x axis
* @param ey float value representing one point on the y axis
* @return float array representing the input order as alternating x / y
* coordinates, the first two being the smallest and the final two being the
* largest
*/
public static float[] validateCoordinates(final float sx, final float sy, final float ex, final float ey) {
final float[] values = new float[4];
if (sx < ex) {
values[0] = sx;
values[2] = ex;
} else {
values[0] = ex;
values[2] = sx;
}
if (sy < ey) {
values[1] = sy;
values[3] = ey;
} else {
values[1] = ey;
values[3] = sy;
}
return values;
}
/**
* Takes a FormObject and returns the font name from the the DS value
* contained within. If there is no value for DS set it will retrieve the
* values return by FormObject.getFontName().
*
* @param form FormObject to retrieve the font name from
* @return String value representing the font name for this form
*/
public static String getFontNameFromFormDS(final FormObject form) {
final String DSString = form.getTextStreamValue(PdfDictionary.DS);
if (DSString != null) {
final int startOfFont = DSString.indexOf("font:");
if (startOfFont > -1) {
final String fontString = DSString.substring(startOfFont, DSString.indexOf(';', startOfFont + 1));
final int firstSpace = fontString.indexOf(' ');
final int secondSpace = fontString.lastIndexOf(' ');
return fontString.substring(firstSpace + 1, secondSpace);
}
}
return form.getFontName();
}
/**
* Takes a FormObject and returns the font colour from the the DS value
* contained within. If there is no value for DS set it will return a value
* for black.
*
* @param form FormObject to retrieve the font colour from
* @return String value representing the font colour for this form
*/
public static String getFontHexColorFromFormDS(final FormObject form) {
final String DSString = form.getTextStreamValue(PdfDictionary.DS);
if (DSString != null) {
final int startOfFont = DSString.indexOf("color:");
if (startOfFont > -1) {
int end = DSString.indexOf(';', startOfFont + 1);
if (end < 0) {
end = DSString.length();
}
final String fontString = DSString.substring(startOfFont, end);
final int firstSpace = fontString.indexOf(':');
int last = fontString.length();
if (fontString.endsWith(" ")) {
last--;
}
return fontString.substring(firstSpace + 1, last);
}
}
return "#000000";
}
/**
* Takes a FormObject and returns the font size from the the DS value
* contained within. If there is no value for DS set it will retrieve the
* values return by FormObject.getFontSize().
*
* @param form FormObject to retrieve the font size from
* @return float value representing the font size for this form
*/
public static float getFontSizeFromFormDS(final FormObject form) {
final String DSString = form.getTextStreamValue(PdfDictionary.DS);
if (DSString != null) {
final int startOfFont = DSString.indexOf("font:");
if (startOfFont > -1) {
final String fontString = DSString.substring(startOfFont, DSString.indexOf(';', startOfFont + 1));
final int sizeStart = fontString.lastIndexOf(' ');
final String size = fontString.substring(sizeStart + 1, fontString.indexOf('p', sizeStart + 1));
return Float.parseFloat(size);
}
}
return form.getFontSize();
}
public static void createAPObjectForFormObject(final FormObject form, final PdfObjectReader currentPdfFile) {
switch (form.getParameterConstant(PdfDictionary.Subtype)) {
case PdfDictionary.FreeText:
createFreeTextAPObject(form, currentPdfFile);
break;
case PdfDictionary.Line:
createBasicAPObject(form);
break;
case PdfDictionary.Square:
createBasicAPObject(form);
break;
case PdfDictionary.Text:
createTextAPObject(form, currentPdfFile);
break;
case PdfDictionary.Polygon:
createBasicAPObject(form);
break;
case PdfDictionary.PolyLine:
createBasicAPObject(form);
break;
case PdfDictionary.Ink:
createInkAPObject(form);
break;
case PdfDictionary.Circle:
createBasicAPObject(form);
break;
case PdfDictionary.Highlight:
createHighlightAPObject(form, currentPdfFile);
break;
}
}
/**
* Create a basic AP object with all common values set
*
* @param form FormObject holding the values for an annotation
*
* @return Null if unable to create AP Object for form. Otherwise String for the AP stream so specific code can
* check contents and update objects specific to this form type.
*/
private static String createBasicAPObject(final FormObject form) {
final String APString = createAPStream(form);
if (APString != null) {
boolean newAP = false;
PdfObject AP = form.getDictionary(PdfDictionary.AP);
PdfObject N;
if (AP != null) {
N = AP.getDictionary(PdfDictionary.N);
if (N == null) {
N = new FormObject(PdfDictionary.N);
newAP = true;
}
} else {
AP = new FormObject(PdfDictionary.AP);
N = new FormObject(PdfDictionary.N);
newAP = true;
}
final float[] rect = form.getFloatArray(PdfDictionary.Rect);
final byte[] bytes = APString.getBytes();
N.setDecodedStream(bytes);
N.setIntNumber(PdfDictionary.Length, bytes.length);
N.setFloatArray(PdfDictionary.BBox, new float[]{0, 0, rect[2] - rect[0], rect[3] - rect[1]});
if (newAP) {
N.setConstant(PdfDictionary.Subtype, PdfDictionary.Form);
N.setConstant(PdfDictionary.Type, PdfDictionary.XObject);
N.setIntNumber(PdfDictionary.FormType, 1);
AP.setDictionary(PdfDictionary.N, N);
}
//Disable values that may be set and not needed
N.setName(PdfDictionary.Filter, new byte[0]);
N.setFloatArray(PdfDictionary.Matrix, null);
form.setDictionary(PdfDictionary.AP, AP);
}
return APString;
}
/**
* Create a basic AP object then add additional values for the Ink FormObject provided
* and add it to the FormObject
*
* @param form FormObject holding the values for a Ink annotation
*/
private static void createInkAPObject(final FormObject form) {
createBasicAPObject(form);
final PdfObject AP = form.getDictionary(PdfDictionary.AP);
final PdfObject N = AP.getDictionary(PdfDictionary.N);
final float[] rect = form.getFloatArray(PdfDictionary.Rect);
N.setFloatArray(PdfDictionary.BBox, new float[]{rect[0], rect[1], rect[2], rect[3]});
N.setFloatArray(PdfDictionary.Matrix, new float[]{1, 0, 0, 1, -rect[0], -rect[1]});
}
/**
* Create a basic AP object then add additional values for the FreeText FormObject provided
* and add it to the FormObject
*
* @param form FormObject holding the values for a FreeText annotation
* @param currentPdfFile PdfObjectReader to be used to create any resources
*/
private static void createFreeTextAPObject(final FormObject form, final PdfObjectReader currentPdfFile) {
createBasicAPObject(form);
final PdfObject AP = form.getDictionary(PdfDictionary.AP);
final PdfObject N = AP.getDictionary(PdfDictionary.N);
final String fontName = StandardFonts.expandName(AnnotationUtils.getFontNameFromFormDS(form));
final String sb = "<> >> >>";
final PdfObject resources = getResObjectFromDirect(currentPdfFile, sb.getBytes());
N.setDictionary(PdfDictionary.Resources, resources);
}
/**
* Create a basic AP object then add additional values for the Text FormObject provided
* and add it to the FormObject
*
* @param form FormObject holding the values for a Text annotation
*/
private static void createTextAPObject(final FormObject form, final PdfObjectReader currentPdfFile) {
final String apStream = createBasicAPObject(form);
final PdfObject AP = form.getDictionary(PdfDictionary.AP);
final PdfObject N = AP.getDictionary(PdfDictionary.N);
//Set size base on icon to be used
final float[] apSize = getTextIconDimensions(form.getName(PdfDictionary.Name));
N.setFloatArray(PdfDictionary.BBox, new float[]{0, 0, apSize[0], apSize[1]});
if (apStream.contains("GS0")) {
final String sb = "<> >> >>";
final PdfObject resources = getResObjectFromDirect(currentPdfFile, sb.getBytes());
N.setDictionary(PdfDictionary.Resources, resources);
}
}
/**
* Create a basic AP object then add additional values for the Text FormObject provided
* and add it to the FormObject
*
* @param form FormObject holding the values for a Text annotation
*/
private static void createHighlightAPObject(final FormObject form, final PdfObjectReader currentPdfFile) {
final String apStream = createBasicAPObject(form);
final PdfObject AP = form.getDictionary(PdfDictionary.AP);
final PdfObject N = AP.getDictionary(PdfDictionary.N);
final float[] rect = form.getFloatArray(PdfDictionary.Rect);
N.setFloatArray(PdfDictionary.BBox, new float[]{rect[0], rect[1], rect[2], rect[3]});
N.setFloatArray(PdfDictionary.Matrix, new float[]{1, 0, 0, 1, -rect[0], -rect[1]});
if (apStream.contains("GS0")) {
final String sb = "<> >> >>";
final PdfObject resources = getResObjectFromDirect(currentPdfFile, sb.getBytes());
N.setDictionary(PdfDictionary.Resources, resources);
}
}
public static String createAPStream(final FormObject form) {
switch (form.getParameterConstant(PdfDictionary.Subtype)) {
case PdfDictionary.FreeText:
return createFreeTextAPStream(form);
case PdfDictionary.Square:
return createSquareAPStream(form);
case PdfDictionary.Line:
return createLineAPStream(form);
case PdfDictionary.Text:
return createTextAPStream(form);
case PdfDictionary.Polygon:
return createPolygonAPStream(form, true);
case PdfDictionary.PolyLine:
return createPolygonAPStream(form, false);
case PdfDictionary.Ink:
return createInkAPStream(form);
case PdfDictionary.Circle:
return createCircleAPStream(form);
case PdfDictionary.Highlight:
return createHighlightAPStream(form);
}
return null;
}
private static String createCircleAPStream(final FormObject form) {
final StringBuilder stream = new StringBuilder();
String drawCommand = null;
final float[] color = form.getFloatArray(PdfDictionary.C);
if (color != null && color.length == 3) {
stream.append((color[0]));
stream.append(' ');
stream.append((color[1]));
stream.append(' ');
stream.append((color[2]));
stream.append(" RG\n");
drawCommand = "S";
}
final float[] internalColor = form.getFloatArray(PdfDictionary.IC);
if (internalColor != null && internalColor.length == 3) {
stream.append((internalColor[0]));
stream.append(' ');
stream.append((internalColor[1]));
stream.append(' ');
stream.append((internalColor[2]));
stream.append(" rg\n");
if (drawCommand != null) {
drawCommand = "B";
} else {
drawCommand = "F";
}
}
int w = 1;
final PdfObject bs = form.getDictionary(PdfDictionary.BS);
if (bs != null) {
final int width = bs.getInt(PdfDictionary.W);
if (width != -1) {
w = width;
stream.append(w);
stream.append(" w\n");
}
}
final float[] rect = form.getFloatArray(PdfDictionary.Rect);
if (rect[0] == rect[2] &&
rect[1] == rect[3]) {
stream.append(rect[0]);
stream.append(' ');
stream.append(rect[1]);
stream.append(" m\n");
stream.append(rect[0]);
stream.append(' ');
stream.append(rect[1]);
stream.append(" l\n");
stream.append(" S\n");
} else {
final float width = ((rect[2] - rect[0])) - (w * 2);
final float height = ((rect[3] - rect[1])) - (w * 2);
final float longRatio = 0.777f;
final float shortRatio = 0.222f;
//Left Middle
stream.append(w);
stream.append(' ');
stream.append(w + (height / 2));
stream.append(" m\n");
//Control points to top middle
stream.append(w);
stream.append(' ');
stream.append(w + (height * longRatio));
stream.append(' ');
stream.append(w + (width * shortRatio));
stream.append(' ');
stream.append(w + height);
stream.append(' ');
stream.append(w + (width / 2));
stream.append(' ');
stream.append(w + height);
stream.append(" c\n");
//Control points to right middle
stream.append(w + (width * longRatio));
stream.append(' ');
stream.append(w + height);
stream.append(' ');
stream.append(w + width);
stream.append(' ');
stream.append(w + (height * longRatio));
stream.append(' ');
stream.append(w + width);
stream.append(' ');
stream.append(w + (height / 2));
stream.append(" c\n");
//Control points to bottom middle
stream.append(w + width);
stream.append(' ');
stream.append(w + (height * shortRatio));
stream.append(' ');
stream.append(w + (width * longRatio));
stream.append(' ');
stream.append(w);
stream.append(' ');
stream.append(w + (width / 2));
stream.append(' ');
stream.append(w);
stream.append(" c\n");
//Control points to left middle
stream.append(w + (width * shortRatio));
stream.append(' ');
stream.append(w);
stream.append(' ');
stream.append(w);
stream.append(' ');
stream.append(w + (height * shortRatio));
stream.append(' ');
stream.append(w);
stream.append(' ');
stream.append(w + (height / 2));
stream.append(" c\n");
stream.append("h\n");
stream.append(drawCommand);
}
return stream.toString();
}
private static String createSquareAPStream(final FormObject form) {
final StringBuilder stream = new StringBuilder();
String drawCommand = null;
final float[] color = form.getFloatArray(PdfDictionary.C);
if (color != null && color.length == 3) {
stream.append((color[0]));
stream.append(' ');
stream.append((color[1]));
stream.append(' ');
stream.append((color[2]));
stream.append(" RG\n");
drawCommand = "S";
}
final float[] internalColor = form.getFloatArray(PdfDictionary.IC);
if (internalColor != null && internalColor.length == 3) {
stream.append((internalColor[0]));
stream.append(' ');
stream.append((internalColor[1]));
stream.append(' ');
stream.append((internalColor[2]));
stream.append(" rg\n");
if (drawCommand != null) {
drawCommand = "B";
} else {
drawCommand = "F";
}
}
int w = 1;
final PdfObject bs = form.getDictionary(PdfDictionary.BS);
if (bs != null) {
final int width = bs.getInt(PdfDictionary.W);
if (width != -1) {
w = width;
stream.append(w);
stream.append(" w\n");
}
}
final float[] rect = form.getFloatArray(PdfDictionary.Rect);
stream.append((float) (w / 2));
stream.append(' ');
stream.append((float) (w));
stream.append(' ');
stream.append((rect[2] - rect[0]) - (w));
stream.append(' ');
stream.append((rect[3] - rect[1]) - (w * 2));
stream.append(" re\n");
stream.append(drawCommand);
return stream.toString();
}
private static String createHighlightAPStream(final FormObject form) {
final StringBuilder stream = new StringBuilder();
stream.append("/GS0 gs\n");
final float[] color = form.getFloatArray(PdfDictionary.C);
if (color != null && color.length == 3) {
stream.append(color[0]);
stream.append(' ');
stream.append(color[1]);
stream.append(' ');
stream.append(color[2]);
stream.append(" rg\n");
}
final float[] quads = form.getFloatArray(PdfDictionary.QuadPoints);
final float[] rect = form.getFloatArray(PdfDictionary.Rect);
final float[] modRect = new float[4];
System.arraycopy(rect, 0, modRect, 0, 4);
for (int i = 0; i < quads.length; i += 8) {
final float controlPointDistance = ((quads[i + 1] - rect[1]) - (quads[i + 7] - rect[1])) / 4.24f;
if (modRect[0] > quads[i] - controlPointDistance) {
modRect[0] = quads[i] - controlPointDistance;
}
if (modRect[2] < quads[i + 2] + controlPointDistance) {
modRect[2] = quads[i + 2] + controlPointDistance;
}
stream.append((int) quads[i + 4]);
stream.append(' ');
stream.append((int) quads[i + 5]);
stream.append(" m\n");
stream.append((int) quads[i + 4] - controlPointDistance);
stream.append(' ');
stream.append((int) quads[i + 5] + controlPointDistance);
stream.append(' ');
stream.append((int) quads[i] - controlPointDistance);
stream.append(' ');
stream.append((int) quads[i + 1] - controlPointDistance);
stream.append(' ');
stream.append((int) quads[i]);
stream.append(' ');
stream.append((int) quads[i + 1]);
stream.append(" c\n");
stream.append((int) quads[i + 2]);
stream.append(' ');
stream.append((int) quads[i + 3]);
stream.append(" l\n");
stream.append((int) quads[i + 2] + controlPointDistance);
stream.append(' ');
stream.append((int) quads[i + 3] - controlPointDistance);
stream.append(' ');
stream.append((int) quads[i + 6] + controlPointDistance);
stream.append(' ');
stream.append((int) quads[i + 7] + controlPointDistance);
stream.append(' ');
stream.append((int) quads[i + 6]);
stream.append(' ');
stream.append((int) quads[i + 7]);
stream.append(" c\n");
stream.append("f\n");
}
form.setFloatArray(PdfDictionary.Rect, modRect);
return stream.toString();
}
private static String createTextAPStream(final FormObject form) {
String name = form.getName(PdfDictionary.Name);
if (name == null || name.isEmpty()) {
name = "Note";
}
return loadApTemplate(form, name);
}
private static String loadApTemplate(final FormObject form, final String name) {
final StringBuilder stream = new StringBuilder();
//Load file here
final String iconFile = "/org/jpedal/objects/acroforms/res/" + name + ".txt";
final URL apFile = AnnotationUtils.class.getResource(iconFile);
try {
final BufferedReader in = new BufferedReader(new InputStreamReader(apFile.openStream()));
String line;
while ((line = in.readLine()) != null) {
stream.append(line);
if (!line.endsWith(" ")) {
stream.append(' ');
}
}
in.close();
} catch (final IOException e) {
LogWriter.writeLog("Exception: " + e.getMessage());
}
String apStream = stream.toString();
final float[] color = form.getFloatArray(PdfDictionary.C);
if (color != null && color.length == 3) {
final String colorString = color[0] + " " + color[1] + " " + color[2] + " rg";
//Replace 0 0 0 rg with this string
apStream = apStream.replace("1 0.819611 0 rg", colorString);
}
return apStream;
}
private static String createFreeTextAPStream(final FormObject form) {
final float[] rect = form.getFloatArray(PdfDictionary.Rect);
final String bounds = 0 + " " + 0 + " " + (rect[2] - rect[0]) + " " + (rect[3] - rect[1]) + " re\n";
final String fontName = StandardFonts.expandName(AnnotationUtils.getFontNameFromFormDS(form));
final float fontSize = AnnotationUtils.getFontSizeFromFormDS(form);
final String fontString = "/" + fontName + " " + fontSize + " Tf\n";
final Color c = Color.decode(AnnotationUtils.getFontHexColorFromFormDS(form));
final String colorString = (c.getRed() / 255f) + " " + (c.getGreen() / 255f) + " " + (c.getBlue() / 255f) + " rg\n";
final String content = form.getTextStreamValue(PdfDictionary.Contents);
final String[] contentLines = content.split("\\r\\n|\\n|\\r");
final StringBuilder stream = new StringBuilder();
stream.append("0 w\n");
stream.append(bounds);
stream.append("n\n");
stream.append("q\n");
stream.append("1 0 0 1 0 0 cm\n");
stream.append(bounds);
stream.append("W\n");
stream.append("n\n");
stream.append("0 g\n");
stream.append("1 w\n");
stream.append("BT\n");
stream.append(fontString);
stream.append(colorString);
stream.append((0.01));
stream.append(' ');
stream.append(((rect[3] - rect[1]) - fontSize));
stream.append(" Td\n");
// FontRenderContext fontContext = new FontRenderContext(null, true, true);
// Font font = new Font(fontName, Font.PLAIN, (int)fontSize);
for (int i = 0; i != contentLines.length; i++) {
final int lineCurrentPoint = 0;
//
// StringTokenizer tokens = new StringTokenizer(contentLines[i], ""+((char)9));
//
// if(tokens.countTokens()==1){
stream.append('(');
stream.append(contentLines[i]);
stream.append(") Tj\n");
// }else{
// while(tokens.hasMoreTokens()){
// String tab = tokens.nextToken();
// stream.append("(");
// stream.append(tab);
// stream.append(") Tj\n");
// int textWidth = (int)(font.getStringBounds(tab, fontContext).getWidth());
//
// if(tokens.hasMoreTokens()){
// int nextTab = lineCurrentPoint + textWidth;
// nextTab += (36 - (nextTab%36));
// System.out.println(nextTab+" - "+lineCurrentPoint+" = "+(nextTab - lineCurrentPoint));
// stream.append(nextTab-lineCurrentPoint);
// stream.append(' ');
// stream.append(0);
// stream.append(" Td\n");
// lineCurrentPoint += (nextTab-lineCurrentPoint);
// }
// }
// }
//Drop down to nw line
if (i != (contentLines.length - 1)) {
stream.append(-lineCurrentPoint);
stream.append(' ');
stream.append((-fontSize * 1.3f));
stream.append(" Td\n");
}
}
stream.append("ET\n");
stream.append('Q');
return stream.toString();
}
private static String createPolygonAPStream(final FormObject form, final boolean closeShape) {
final float[] color = form.getFloatArray(PdfDictionary.C);
final float[] icolor = form.getFloatArray(PdfDictionary.IC);
final float coords[] = form.getFloatArray(PdfDictionary.Vertices);
final float rect[] = form.getFloatArray(PdfDictionary.Rect);
//line width
int w = 1;
final PdfObject bs = form.getDictionary(PdfDictionary.BS);
if (bs != null) {
final int width = bs.getInt(PdfDictionary.W);
if (width != -1) {
w = width;
}
}
//Stringbuilder used to create stream
final StringBuilder stream = new StringBuilder();
String drawCommand = null;
stream.append(w);
stream.append(" w\n");
if (color != null && color.length == 3) {
stream.append(color[0]);
stream.append(' ');
stream.append(color[1]);
stream.append(' ');
stream.append(color[2]);
stream.append(' ');
stream.append(" RG\n");
drawCommand = "s";
}
if (icolor != null && icolor.length == 3) {
stream.append(icolor[0]);
stream.append(' ');
stream.append(icolor[1]);
stream.append(' ');
stream.append(icolor[2]);
stream.append(' ');
stream.append(" rg\n");
if (drawCommand != null) {
drawCommand = "b";
} else {
drawCommand = "f";
}
}
stream.append(coords[0] - rect[0]);
stream.append(' ');
stream.append(coords[1] - rect[1]);
stream.append(" m\n");
for (int i = 2; i != coords.length; i += 2) {
stream.append(coords[i] - rect[0]);
stream.append(' ');
stream.append(coords[i + 1] - rect[1]);
stream.append(" l\n");
}
if (closeShape) {
stream.append("h\n");
stream.append(drawCommand);
} else {
stream.append(drawCommand.toUpperCase());
}
return stream.toString();
}
private static String createInkAPStream(final FormObject form) {
final float[] color = form.getFloatArray(PdfDictionary.C);
final float[][] inkList = form.getFloat2DArray(PdfDictionary.InkList);
//line width
int w = 1;
final PdfObject bs = form.getDictionary(PdfDictionary.BS);
if (bs != null) {
final int width = bs.getInt(PdfDictionary.W);
if (width != -1) {
w = width;
}
}
//Stringbuilder used to create stream
final StringBuilder stream = new StringBuilder();
stream.append(w);
stream.append(" w\n");
if (color != null && color.length == 3) {
stream.append(color[0]);
stream.append(' ');
stream.append(color[1]);
stream.append(' ');
stream.append(color[2]);
stream.append(" RG\n");
}
//Curve can extend beyond bounds so resize bounds to compensate for this.
final float[] rect = form.getFloatArray(PdfDictionary.Rect);
Rectangle2D bounds = new Rectangle2D.Float(rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1]);
for (float[] coords : inkList) {
stream.append(coords[0]);
stream.append(' ');
stream.append(coords[1]);
stream.append(" m\n");
if (coords.length > 4) {
coords = AnnotationFactory.createInkCurve(coords);
final CubicCurve2D curve = new CubicCurve2D.Float();
for (int i = 2; i < coords.length - 5; i += 6) {
stream.append(coords[i]);
stream.append(' ');
stream.append(coords[i + 1]);
stream.append(' ');
stream.append(coords[i + 2]);
stream.append(' ');
stream.append(coords[i + 3]);
stream.append(' ');
stream.append(coords[i + 4]);
stream.append(' ');
stream.append(coords[i + 5]);
stream.append(" c\n");
curve.setCurve(coords[i - 2], coords[i - 1], coords[i], coords[i + 1], coords[i + 2], coords[i + 3], coords[i + 4], coords[i + 5]);
bounds = bounds.createUnion(curve.getBounds2D());
}
} else {
if (coords.length == 4) {
stream.append(coords[2]);
stream.append(' ');
stream.append(coords[3]);
stream.append(" l");
} else {
stream.append(coords[0]);
stream.append(' ');
stream.append(coords[1]);
stream.append(" l");
}
}
}
stream.append("S\n");
form.setFloatArray(PdfDictionary.Rect, AnnotationUtils.validateCoordinates((float) bounds.getMinX(), (float) bounds.getMinY(), (float) bounds.getMaxX(), (float) bounds.getMaxY()));
return stream.toString();
}
private static String createLineAPStream(final FormObject form) {
//Stringbuilder used to create stream
final StringBuilder stream = new StringBuilder();
//line color
final float[] color = form.getFloatArray(PdfDictionary.C);
final String colorString = color[0] + " " + color[1] + " " + color[2] + " RG\n";
//line coords
final float coords[] = form.getFloatArray(PdfDictionary.L);
final float[] rect = form.getFloatArray(PdfDictionary.Rect);
final String coordString = (coords[0] - rect[0]) + " " + (coords[1] - rect[1]) + " m\n" + (coords[2] - rect[0]) + " " + (coords[3] - rect[1]) + " l\n";
//line width
int w = 1;
final PdfObject bs = form.getDictionary(PdfDictionary.BS);
if (bs != null) {
final int width = bs.getInt(PdfDictionary.W);
if (width != -1) {
w = width;
}
}
final String widthString = w + " w\n";
//build stream
stream.append(widthString);
stream.append(colorString);
stream.append(coordString);
stream.append('S');
return stream.toString();
}
private static ResourcesObject getResObjectFromDirect(final PdfObjectReader currentPdfFile, final byte[] data) {
final ResourcesObject resObj = new ResourcesObject(new String(data));
resObj.setStatus(PdfObject.UNDECODED_DIRECT);
resObj.setUnresolvedData(data, PdfDictionary.Resources);
final ObjectDecoder objectDecoder = new ObjectDecoder(currentPdfFile.getObjectReader());
objectDecoder.checkResolved(resObj);
return resObj;
}
public static float[] getTextIconDimensions(String name) {
if (name == null || name.isEmpty()) {
name = "Note";
}
if (name.equals("Comment")) {
return new float[]{18f, 18f};
} else if (name.equals("Check")) {
return new float[]{19f, 19f};
} else if (name.equals("Checkmark")) {
return new float[]{20f, 20f};
} else if (name.equals("Circle")) {
return new float[]{20f, 20f};
} else if (name.equals("Cross")) {
return new float[]{19f, 19f};
} else if (name.equals("CrossHairs")) {
return new float[]{20f, 20f};
} else if (name.equals("Help")) {
return new float[]{20f, 20f};
} else if (name.equals("Insert")) {
return new float[]{17f, 20f};
} else if (name.equals("Key")) {
return new float[]{13f, 18f};
} else if (name.equals("NewParagraph")) {
return new float[]{13f, 20f};
} else if (name.equals("Paragraph")) {
return new float[]{20f, 20f};
} else if (name.equals("RightArrow")) {
return new float[]{20f, 20f};
} else if (name.equals("RightPointer")) {
return new float[]{20f, 17f};
} else if (name.equals("Star")) {
return new float[]{20f, 19f};
} else if (name.equals("UpLeftArrow")) {
return new float[]{17f, 17f};
} else if (name.equals("UpArrow")) {
return new float[]{17f, 20f};
} else { //Default option. Name = Note
return new float[]{18f, 20f};
}
}
}