Skip to content

Commit 476d32f

Browse files
committed
Add convenient methods for setting annotation default appearance
The new class provides setters for font-color, font-size and font itself. Note that only standard font names that don't require font resources are supported. Note that it is possible to create annotation with custom font name in DA, but this require manual resource modifications (you have to put font in DR of AcroForm and use it's resource name in DA) and only Acrobat supports that workflow. DEVSIX-1401
1 parent 47479eb commit 476d32f

File tree

9 files changed

+251
-4
lines changed

9 files changed

+251
-4
lines changed

kernel/src/main/java/com/itextpdf/kernel/pdf/annot/PdfFreeTextAnnotation.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ This file is part of the iText (R) project.
4848
import com.itextpdf.kernel.pdf.PdfDictionary;
4949
import com.itextpdf.kernel.pdf.PdfName;
5050
import com.itextpdf.kernel.pdf.PdfString;
51+
import com.itextpdf.kernel.pdf.annot.da.AnnotationDefaultAppearance;
5152

5253
public class PdfFreeTextAnnotation extends PdfMarkupAnnotation {
5354

@@ -59,6 +60,25 @@ public class PdfFreeTextAnnotation extends PdfMarkupAnnotation {
5960
public static final int CENTERED = 1;
6061
public static final int RIGHT_JUSTIFIED = 2;
6162

63+
/**
64+
* Creates new instance
65+
*
66+
* @param rect - rectangle that specifies annotation position and bounds on page
67+
* @param contents - the displayed text
68+
*/
69+
public PdfFreeTextAnnotation(Rectangle rect, PdfString contents) {
70+
super(rect);
71+
setContents(contents);
72+
}
73+
74+
/**
75+
* Creates new instance
76+
*
77+
* @param rect - bounding rectangle of annotation
78+
* @param appearanceString - appearance string of annotation
79+
* @deprecated unintuitive, will be removed in 7.1 use {@link #PdfFreeTextAnnotation(Rectangle, PdfString)} instead
80+
*/
81+
@Deprecated
6282
public PdfFreeTextAnnotation(Rectangle rect, String appearanceString) {
6383
super(rect);
6484
setDefaultAppearance(new PdfString(appearanceString));
@@ -81,6 +101,10 @@ public PdfFreeTextAnnotation setDefaultStyleString(PdfString defaultStyleString)
81101
return (PdfFreeTextAnnotation) put(PdfName.DS, defaultStyleString);
82102
}
83103

104+
public PdfFreeTextAnnotation setDefaultAppearance(AnnotationDefaultAppearance da) {
105+
return (PdfFreeTextAnnotation) setDefaultAppearance(da.toPdfString());
106+
}
107+
84108
public PdfArray getCalloutLine() {
85109
return getPdfObject().getAsArray(PdfName.CL);
86110
}
@@ -100,6 +124,4 @@ public PdfName getLineEndingStyle() {
100124
public PdfFreeTextAnnotation setLineEndingStyle(PdfName lineEndingStyle) {
101125
return (PdfFreeTextAnnotation) put(PdfName.LE, lineEndingStyle);
102126
}
103-
104-
105127
}

kernel/src/main/java/com/itextpdf/kernel/pdf/annot/PdfRedactAnnotation.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ This file is part of the iText (R) project.
4949
import com.itextpdf.kernel.pdf.PdfName;
5050
import com.itextpdf.kernel.pdf.PdfStream;
5151
import com.itextpdf.kernel.pdf.PdfString;
52+
import com.itextpdf.kernel.pdf.annot.da.AnnotationDefaultAppearance;
5253

5354
public class PdfRedactAnnotation extends PdfMarkupAnnotation {
5455

@@ -67,6 +68,10 @@ public PdfName getSubtype() {
6768
return PdfName.Redact;
6869
}
6970

71+
public PdfRedactAnnotation setDefaultAppearance(AnnotationDefaultAppearance da) {
72+
return (PdfRedactAnnotation) setDefaultAppearance(da.toPdfString());
73+
}
74+
7075
public PdfRedactAnnotation setOverlayText(PdfString text){
7176
return (PdfRedactAnnotation) put(PdfName.OverlayText, text);
7277
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package com.itextpdf.kernel.pdf.annot.da;
2+
3+
import com.itextpdf.io.font.FontConstants;
4+
import com.itextpdf.kernel.color.DeviceCmyk;
5+
import com.itextpdf.kernel.color.DeviceGray;
6+
import com.itextpdf.kernel.color.DeviceRgb;
7+
import com.itextpdf.kernel.pdf.PdfString;
8+
9+
import java.util.HashMap;
10+
import java.util.Map;
11+
12+
/**
13+
* Helper class for setting
14+
*/
15+
public class AnnotationDefaultAppearance {
16+
17+
private static final Map<StandardAnnotationFont, String> stdAnnotFontNames = new HashMap<>();
18+
private static final Map<ExtendedAnnotationFont, String> extAnnotFontNames = new HashMap<>();
19+
static {
20+
stdAnnotFontNames.put(StandardAnnotationFont.CourierBoldOblique, "/" + FontConstants.COURIER_BOLDOBLIQUE);
21+
stdAnnotFontNames.put(StandardAnnotationFont.CourierBold, "/" + FontConstants.COURIER_BOLD);
22+
stdAnnotFontNames.put(StandardAnnotationFont.CourierOblique, "/" + FontConstants.COURIER_OBLIQUE);
23+
stdAnnotFontNames.put(StandardAnnotationFont.Courier, "/" + FontConstants.COURIER);
24+
stdAnnotFontNames.put(StandardAnnotationFont.HelveticaBoldOblique, "/" + FontConstants.HELVETICA_BOLDOBLIQUE);
25+
stdAnnotFontNames.put(StandardAnnotationFont.HelveticaBold, "/" + FontConstants.HELVETICA_BOLD);
26+
stdAnnotFontNames.put(StandardAnnotationFont.HelveticaOblique, "/" + FontConstants.COURIER_OBLIQUE);
27+
stdAnnotFontNames.put(StandardAnnotationFont.Helvetica, "/" + FontConstants.HELVETICA);
28+
stdAnnotFontNames.put(StandardAnnotationFont.Symbol, "/" + FontConstants.SYMBOL);
29+
stdAnnotFontNames.put(StandardAnnotationFont.TimesBoldItalic, "/" + FontConstants.TIMES_BOLDITALIC);
30+
stdAnnotFontNames.put(StandardAnnotationFont.TimesBold, "/" + FontConstants.TIMES_BOLD);
31+
stdAnnotFontNames.put(StandardAnnotationFont.TimesItalic, "/" + FontConstants.TIMES_ITALIC);
32+
stdAnnotFontNames.put(StandardAnnotationFont.TimesRoman, "/" + FontConstants.TIMES_ROMAN);
33+
stdAnnotFontNames.put(StandardAnnotationFont.ZapfDingbats, "/" + FontConstants.ZAPFDINGBATS);
34+
35+
extAnnotFontNames.put(ExtendedAnnotationFont.HYSMyeongJoMedium, "/HySm");
36+
extAnnotFontNames.put(ExtendedAnnotationFont.HYGoThicMedium, "/HyGo");
37+
extAnnotFontNames.put(ExtendedAnnotationFont.HeiseiKakuGoW5, "/KaGo");
38+
extAnnotFontNames.put(ExtendedAnnotationFont.HeiseiMinW3, "/KaMi");
39+
extAnnotFontNames.put(ExtendedAnnotationFont.MHeiMedium, "/MHei");
40+
extAnnotFontNames.put(ExtendedAnnotationFont.MSungLight, "/MSun");
41+
extAnnotFontNames.put(ExtendedAnnotationFont.STSongLight, "/STSo");
42+
extAnnotFontNames.put(ExtendedAnnotationFont.MSungStdLight, "/MSun");
43+
extAnnotFontNames.put(ExtendedAnnotationFont.STSongStdLight, "/STSo");
44+
extAnnotFontNames.put(ExtendedAnnotationFont.HYSMyeongJoStdMedium, "/HySm");
45+
extAnnotFontNames.put(ExtendedAnnotationFont.KozMinProRegular, "/KaMi");
46+
}
47+
48+
private String colorOperand = "0 g";
49+
private String rawFontName = "/Helv";
50+
private float fontSize = 0;
51+
52+
public AnnotationDefaultAppearance() {
53+
setFont(StandardAnnotationFont.Helvetica);
54+
setFontSize(12);
55+
}
56+
57+
public AnnotationDefaultAppearance setFont(StandardAnnotationFont font) {
58+
setRawFontName(stdAnnotFontNames.get(font));
59+
return this;
60+
}
61+
62+
public AnnotationDefaultAppearance setFont(ExtendedAnnotationFont font) {
63+
setRawFontName(extAnnotFontNames.get(font));
64+
return this;
65+
}
66+
67+
public AnnotationDefaultAppearance setFontSize(float fontSize) {
68+
this.fontSize = fontSize;
69+
return this;
70+
}
71+
72+
public AnnotationDefaultAppearance setColor(DeviceRgb rgbColor) {
73+
setColorOperand(rgbColor.getColorValue(), "rg");
74+
return this;
75+
}
76+
77+
public AnnotationDefaultAppearance setColor(DeviceCmyk cmykColor) {
78+
setColorOperand(cmykColor.getColorValue(), "k");
79+
return this;
80+
}
81+
82+
public AnnotationDefaultAppearance setColor(DeviceGray grayColor) {
83+
setColorOperand(grayColor.getColorValue(), "g");
84+
return this;
85+
}
86+
87+
public PdfString toPdfString() {
88+
return new PdfString(rawFontName + " " + fontSize + " Tf " + colorOperand);
89+
}
90+
91+
private void setColorOperand(float[] colorValues, String operand) {
92+
StringBuilder builder = new StringBuilder();
93+
for (float value : colorValues) {
94+
builder.append(value);
95+
builder.append(' ');
96+
}
97+
builder.append(operand);
98+
this.colorOperand = builder.toString();
99+
}
100+
101+
private void setRawFontName(String rawFontName) {
102+
if (rawFontName == null) {
103+
throw new NullPointerException();
104+
}
105+
this.rawFontName = rawFontName;
106+
}
107+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.itextpdf.kernel.pdf.annot.da;
2+
3+
/**
4+
* Extended annotation fonts that are supported only by Acrobat
5+
*/
6+
public enum ExtendedAnnotationFont {
7+
HYSMyeongJoMedium,
8+
HYGoThicMedium,
9+
HeiseiKakuGoW5,
10+
HeiseiMinW3,
11+
MHeiMedium,
12+
MSungLight,
13+
STSongLight,
14+
MSungStdLight,
15+
STSongStdLight,
16+
HYSMyeongJoStdMedium,
17+
KozMinProRegular
18+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.itextpdf.kernel.pdf.annot.da;
2+
3+
/**
4+
* Standard fonts that can be used in pdf annotation
5+
*/
6+
public enum StandardAnnotationFont {
7+
CourierBoldOblique,
8+
CourierBold,
9+
CourierOblique,
10+
Courier,
11+
HelveticaBoldOblique,
12+
HelveticaBold,
13+
HelveticaOblique,
14+
Helvetica,
15+
Symbol,
16+
TimesBoldItalic,
17+
TimesBold,
18+
TimesItalic,
19+
TimesRoman,
20+
ZapfDingbats
21+
}

kernel/src/test/java/com/itextpdf/kernel/pdf/PdfAnnotationTest.java

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,18 @@ This file is part of the iText (R) project.
4545
import com.itextpdf.io.LogMessageConstant;
4646
import com.itextpdf.io.font.FontConstants;
4747
import com.itextpdf.kernel.color.ColorConstants;
48+
import com.itextpdf.kernel.color.Color;
49+
import com.itextpdf.kernel.color.DeviceCmyk;
50+
import com.itextpdf.kernel.color.DeviceGray;
51+
import com.itextpdf.kernel.color.DeviceRgb;
4852
import com.itextpdf.kernel.font.PdfFontFactory;
4953
import com.itextpdf.kernel.geom.PageSize;
5054
import com.itextpdf.kernel.geom.Rectangle;
5155
import com.itextpdf.kernel.pdf.action.PdfAction;
5256
import com.itextpdf.kernel.pdf.annot.*;
57+
import com.itextpdf.kernel.pdf.annot.da.AnnotationDefaultAppearance;
58+
import com.itextpdf.kernel.pdf.annot.da.ExtendedAnnotationFont;
59+
import com.itextpdf.kernel.pdf.annot.da.StandardAnnotationFont;
5360
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
5461
import com.itextpdf.kernel.pdf.canvas.PdfCanvasConstants;
5562
import com.itextpdf.kernel.pdf.filespec.PdfFileSpec;
@@ -289,8 +296,9 @@ public void addFreeTextAnnotation01() throws Exception {
289296
PdfPage page = document.addNewPage();
290297

291298
new PdfCanvas(page).beginText().setFontAndSize(PdfFontFactory.createFont(FontConstants.COURIER), 24).moveText(100, 600).showText("Annotated text").endText().release();
292-
PdfFreeTextAnnotation textannot = new PdfFreeTextAnnotation(new Rectangle(300, 700, 150, 20), "");
293-
textannot.setContents(new PdfString("FreeText annotation")).setColor(new float[]{1, 0, 0});
299+
PdfFreeTextAnnotation textannot = new PdfFreeTextAnnotation(new Rectangle(300, 700, 150, 20), new PdfString("FreeText annotation"));
300+
textannot.setDefaultAppearance(new AnnotationDefaultAppearance().setFont(StandardAnnotationFont.TimesRoman));
301+
textannot.setColor(new float[]{1, 0, 0});
294302
textannot.setIntent(PdfName.FreeTextCallout);
295303
textannot.setCalloutLine(new float[]{120, 616, 180, 680, 300, 710}).setLineEndingStyle(PdfName.OpenArrow);
296304
page.addAnnotation(textannot);
@@ -1176,4 +1184,70 @@ public void redactionTest() throws IOException, InterruptedException {
11761184
Assert.fail(errorMessage);
11771185
}
11781186
}
1187+
1188+
@Test
1189+
public void defaultAppearanceTest() throws IOException, InterruptedException {
1190+
String name = "defaultAppearance";
1191+
String inPath = sourceFolder + "in_" + name + ".pdf";
1192+
String outPath = destinationFolder + name + ".pdf";
1193+
String cmpPath = sourceFolder + "cmp_" + name + ".pdf";
1194+
String diff = "diff_" + name + "_";
1195+
1196+
PdfDocument pdfDoc = new PdfDocument(new PdfReader(inPath), new PdfWriter(outPath));
1197+
PdfPage page = pdfDoc.getPage(1);
1198+
1199+
Rectangle rect = new Rectangle(20, 700, 250, 50);
1200+
page.addAnnotation(new PdfRedactAnnotation(rect)
1201+
.setDefaultAppearance(new AnnotationDefaultAppearance()
1202+
.setColor(new DeviceRgb(1.0f, 0, 0))
1203+
.setFont(StandardAnnotationFont.TimesBold)
1204+
.setFontSize(20))
1205+
.setOverlayText(new PdfString("Redact RGB times-bold"))
1206+
);
1207+
rect.moveDown(80);
1208+
page.addAnnotation(new PdfRedactAnnotation(rect)
1209+
.setDefaultAppearance(new AnnotationDefaultAppearance()
1210+
.setColor(DeviceCmyk.MAGENTA)
1211+
.setFont(StandardAnnotationFont.CourierOblique)
1212+
.setFontSize(20))
1213+
.setOverlayText(new PdfString("Redact CMYK courier-oblique"))
1214+
1215+
);
1216+
rect.moveDown(80);
1217+
page.addAnnotation(new PdfRedactAnnotation(rect)
1218+
.setDefaultAppearance(new AnnotationDefaultAppearance()
1219+
.setColor(DeviceGray.GRAY)
1220+
.setFont(ExtendedAnnotationFont.HeiseiMinW3)
1221+
.setFontSize(20))
1222+
.setOverlayText(new PdfString("Redact Gray HeiseiMinW3"))
1223+
);
1224+
1225+
rect.moveUp(160).moveRight(260);
1226+
page.addAnnotation(new PdfFreeTextAnnotation(rect, new PdfString("FreeText RGB times-bold"))
1227+
.setDefaultAppearance(new AnnotationDefaultAppearance()
1228+
.setColor(new DeviceRgb(1.0f, 0, 0))
1229+
.setFont(StandardAnnotationFont.TimesBold)
1230+
.setFontSize(20))
1231+
.setColor(Color.WHITE)
1232+
);
1233+
rect.moveDown(80);
1234+
page.addAnnotation(new PdfFreeTextAnnotation(rect, new PdfString("FreeText CMYK courier-oblique"))
1235+
.setDefaultAppearance(new AnnotationDefaultAppearance()
1236+
.setColor(DeviceCmyk.MAGENTA)
1237+
.setFont(StandardAnnotationFont.CourierOblique)
1238+
.setFontSize(20))
1239+
.setColor(Color.WHITE)
1240+
);
1241+
rect.moveDown(80);
1242+
page.addAnnotation(new PdfFreeTextAnnotation(rect, new PdfString("FreeText Gray HeiseiMinW3"))
1243+
.setDefaultAppearance(new AnnotationDefaultAppearance()
1244+
.setColor(DeviceGray.GRAY)
1245+
.setFont(ExtendedAnnotationFont.HeiseiMinW3)
1246+
.setFontSize(20))
1247+
.setColor(Color.WHITE)
1248+
);
1249+
1250+
pdfDoc.close();
1251+
Assert.assertNull(new CompareTool().compareByContent(outPath, cmpPath, destinationFolder, diff));
1252+
}
11791253
}

0 commit comments

Comments
 (0)