Skip to content

Commit eceaa07

Browse files
committed
Add AppearanceResources and AppearanceXObject
Those classes will save font names from default resources. Update javadoc for PdfAcroForm#setGenerateAppearance() DEVSIX-1916
1 parent e2a322a commit eceaa07

File tree

9 files changed

+131
-17
lines changed

9 files changed

+131
-17
lines changed

forms/src/main/java/com/itextpdf/forms/PdfAcroForm.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,8 @@ public boolean isGenerateAppearance() {
595595
* If generateAppearance is set to <code>true</code>, then
596596
* <code>NeedAppearances</code> is set to <code>false</code>. This does not
597597
* apply vice versa.
598+
* <p>
599+
* Note, this method does not change default behaviour of {@link PdfFormField#setValue(String)} method.
598600
*
599601
* @param generateAppearance a boolean
600602
*/
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.itextpdf.forms.fields;
2+
3+
import com.itextpdf.kernel.font.PdfFont;
4+
import com.itextpdf.kernel.pdf.PdfDictionary;
5+
import com.itextpdf.kernel.pdf.PdfDocument;
6+
import com.itextpdf.kernel.pdf.PdfIndirectReference;
7+
import com.itextpdf.kernel.pdf.PdfName;
8+
import com.itextpdf.kernel.pdf.PdfResources;
9+
10+
import java.util.HashMap;
11+
import java.util.Map;
12+
13+
/**
14+
* AppearanceResources allows to register font names that will be used as resource name.
15+
* Preserving existed font names in default resources of AcroForm is the only goal of this class.
16+
* <p>
17+
* Shall be used only in {@link PdfFormField}.
18+
*
19+
* @see AppearanceXObject
20+
*/
21+
class AppearanceResources extends PdfResources {
22+
23+
private static final long serialVersionUID = -1991503804376023468L;
24+
25+
private Map<PdfIndirectReference, PdfName> drFonts = new HashMap<>();
26+
27+
AppearanceResources(PdfDictionary pdfObject) {
28+
super(pdfObject);
29+
}
30+
31+
void addFontFromDefaultResources(PdfName name, PdfFont font) {
32+
if (name != null && font != null && font.getPdfObject().getIndirectReference() != null) {
33+
//So, most likely it's a document PdfFont
34+
drFonts.put(font.getPdfObject().getIndirectReference(), name);
35+
}
36+
}
37+
38+
@Override
39+
public PdfName addFont(PdfDocument pdfDocument, PdfFont font) {
40+
PdfName fontName = null;
41+
if (font != null && font.getPdfObject().getIndirectReference() != null) {
42+
fontName = drFonts.get(font.getPdfObject().getIndirectReference());
43+
}
44+
45+
if (fontName != null) {
46+
addResource(font.getPdfObject(), PdfName.Font, fontName);
47+
return fontName;
48+
} else {
49+
return super.addFont(pdfDocument, font);
50+
}
51+
}
52+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.itextpdf.forms.fields;
2+
3+
import com.itextpdf.kernel.font.PdfFont;
4+
import com.itextpdf.kernel.geom.Rectangle;
5+
import com.itextpdf.kernel.pdf.PdfDictionary;
6+
import com.itextpdf.kernel.pdf.PdfName;
7+
import com.itextpdf.kernel.pdf.PdfResources;
8+
import com.itextpdf.kernel.pdf.PdfStream;
9+
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
10+
11+
/**
12+
* AppearanceXObject allows font names registration. Those names will be used as resource name
13+
* for a particular {@link PdfFont}.
14+
* <p>
15+
* Preserving existed font names in default resources of AcroForm is the only goal of this class.
16+
* <p>
17+
* Shall be used only in {@link PdfFormField}.
18+
*/
19+
class AppearanceXObject extends PdfFormXObject {
20+
21+
private static final long serialVersionUID = 6098843657444897565L;
22+
23+
AppearanceXObject(PdfStream pdfStream) {
24+
super(pdfStream);
25+
}
26+
27+
AppearanceXObject(Rectangle bBox) {
28+
super(bBox);
29+
}
30+
31+
void addFontFromDR(PdfName fontName, PdfFont font) {
32+
if (fontName != null && font != null) {
33+
((AppearanceResources) getResources()).addFontFromDefaultResources(fontName, font);
34+
}
35+
}
36+
37+
@Override
38+
public PdfResources getResources() {
39+
if (this.resources == null) {
40+
PdfDictionary resourcesDict = getPdfObject().getAsDictionary(PdfName.Resources);
41+
if (resourcesDict == null) {
42+
resourcesDict = new PdfDictionary();
43+
getPdfObject().put(PdfName.Resources, resourcesDict);
44+
}
45+
this.resources = new AppearanceResources(resourcesDict);
46+
}
47+
return resources;
48+
}
49+
}

forms/src/main/java/com/itextpdf/forms/fields/PdfFormField.java

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,7 @@ public static PdfButtonFormField createPushButton(PdfDocument doc, Rectangle rec
876876
field.fontSize = fontSize;
877877
field.backgroundColor = ColorConstants.LIGHT_GRAY;
878878

879-
PdfFormXObject xObject = field.drawPushButtonAppearance(rect.getWidth(), rect.getHeight(), caption, font, fontSize);
879+
PdfFormXObject xObject = field.drawPushButtonAppearance(rect.getWidth(), rect.getHeight(), caption, font, null, fontSize);
880880
annot.setNormalAppearance(xObject.getPdfObject());
881881

882882
PdfDictionary mk = new PdfDictionary();
@@ -1962,6 +1962,7 @@ public boolean regenerateField() {
19621962

19631963
Object[] fontAndSize = getFontAndSize(asNormal);
19641964
PdfFont localFont = (PdfFont) fontAndSize[0];
1965+
PdfName localFontName = (PdfName) fontAndSize[2];
19651966
float fontSize = normalizeFontSize((float) fontAndSize[1], localFont, bBox, value);
19661967

19671968
//Apply Page rotation
@@ -2043,14 +2044,16 @@ public boolean regenerateField() {
20432044
bBox = new PdfArray(rect);
20442045
}
20452046
//Create appearance
2046-
PdfFormXObject appearance = null;
2047+
AppearanceXObject appearance = null;
20472048
if (asNormal != null) {
2048-
appearance = new PdfFormXObject(asNormal);
2049+
appearance = new AppearanceXObject(asNormal);
2050+
20492051
appearance.setBBox(new PdfArray(new float[]{0, 0, bBox.toRectangle().getWidth(), bBox.toRectangle().getHeight()}));
20502052
}
20512053
if (appearance == null) {
2052-
appearance = new PdfFormXObject(new Rectangle(0, 0, bBox.toRectangle().getWidth(), bBox.toRectangle().getHeight()));
2054+
appearance = new AppearanceXObject(new Rectangle(0, 0, bBox.toRectangle().getWidth(), bBox.toRectangle().getHeight()));
20532055
}
2056+
appearance.addFontFromDR(localFontName, localFont);
20542057
appearance.put(PdfName.Matrix, matrix);
20552058
//Create text appearance
20562059
if (PdfName.Tx.equals(type)) {
@@ -2099,20 +2102,19 @@ public boolean regenerateField() {
20992102
apDic = widgets.get(0).getPdfObject().getAsDictionary(PdfName.AP);
21002103
}
21012104
}
2102-
if (img != null) {
2103-
appearance = drawPushButtonAppearance(rect.getWidth(), rect.getHeight(), value, null, 0);
2104-
} else if (form != null) {
2105-
appearance = drawPushButtonAppearance(rect.getWidth(), rect.getHeight(), value, null, 0);
2105+
if (img != null || form != null) {
2106+
appearance = drawPushButtonAppearance(rect.getWidth(), rect.getHeight(), value, null, null, 0);
21062107
} else {
21072108
PdfStream asNormal = null;
21082109
if (apDic != null) {
21092110
asNormal = apDic.getAsStream(PdfName.N);
21102111
}
21112112
Object[] fontAndSize = getFontAndSize(asNormal);
21122113
PdfFont localFont = (PdfFont) fontAndSize[0];
2114+
PdfName localFontName = (PdfName) fontAndSize[2];
21132115
float fontSize = (float) fontAndSize[1];
2114-
appearance = drawPushButtonAppearance(rect.getWidth(), rect.getHeight(), value, localFont, fontSize);
2115-
appearance.getResources().addFont(getDocument(), localFont);
2116+
appearance = drawPushButtonAppearance(rect.getWidth(), rect.getHeight(), value,
2117+
localFont, localFontName, fontSize);
21162118
}
21172119

21182120
if (apDic == null) {
@@ -2632,7 +2634,7 @@ protected String generateDefaultAppearanceString(PdfFont font, float fontSize, C
26322634
}
26332635

26342636
protected Object[] getFontAndSize(PdfDictionary asNormal) throws IOException {
2635-
Object[] fontAndSize = new Object[2];
2637+
Object[] fontAndSize = new Object[3];
26362638
PdfDictionary normalResources = null;
26372639
PdfDictionary defaultResources = null;
26382640
PdfDocument document = getDocument();
@@ -2648,6 +2650,7 @@ protected Object[] getFontAndSize(PdfDictionary asNormal) throws IOException {
26482650
if ((normalFontDic != null || defaultFontDic != null) && defaultAppearance != null) {
26492651
Object[] dab = splitDAelements(defaultAppearance.toUnicodeString());
26502652
PdfName fontName = new PdfName(dab[DA_FONT].toString());
2653+
fontAndSize[2] = fontName;
26512654
PdfDictionary requiredFontDictionary = null;
26522655
if (normalFontDic != null && null != normalFontDic.getAsDictionary(fontName)) {
26532656
requiredFontDictionary = normalFontDic.getAsDictionary(fontName);
@@ -2759,7 +2762,10 @@ protected void drawTextAppearance(Rectangle rect, PdfFont font, float fontSize,
27592762
PdfResources resources = appearance.getResources();
27602763
PdfCanvas canvas = new PdfCanvas(stream, resources, getDocument());
27612764

2762-
setDefaultAppearance(generateDefaultAppearanceString(font, fontSize, color, resources));
2765+
//TODO seems that FontName shall be passed
2766+
if (getDefaultAppearance() == null) {
2767+
setDefaultAppearance(generateDefaultAppearanceString(font, fontSize, color, resources));
2768+
}
27632769

27642770
float height = rect.getHeight();
27652771
float width = rect.getWidth();
@@ -3157,11 +3163,12 @@ protected void drawPdfA2CheckAppearance(float width, float height, String value,
31573163
* @param fontSize the size of the font
31583164
* @return a new {@link PdfFormXObject}
31593165
*/
3160-
protected PdfFormXObject drawPushButtonAppearance(float width, float height, String text, PdfFont font, float fontSize) {
3166+
protected PdfFormXObject drawPushButtonAppearance(float width, float height, String text,
3167+
PdfFont font, PdfName fontName, float fontSize) {
31613168
PdfStream stream = (PdfStream) new PdfStream().makeIndirect(getDocument());
31623169
PdfCanvas canvas = new PdfCanvas(stream, new PdfResources(), getDocument());
31633170

3164-
PdfFormXObject xObject = new PdfFormXObject(new Rectangle(0, 0, width, height));
3171+
AppearanceXObject xObject = new AppearanceXObject(new Rectangle(0, 0, width, height));
31653172
drawBorder(canvas, xObject, width, height);
31663173

31673174
if (img != null) {
@@ -3173,8 +3180,11 @@ protected PdfFormXObject drawPushButtonAppearance(float width, float height, Str
31733180
xObject.getResources().addForm(form);
31743181
} else {
31753182
drawButton(canvas, 0, 0, width, height, text, font, fontSize);
3176-
setDefaultAppearance(generateDefaultAppearanceString(font, fontSize, color, new PdfResources()));
3177-
xObject.getResources().addFont(getDocument(), font);
3183+
xObject.addFontFromDR(fontName, font);
3184+
if (getDefaultAppearance() == null) {
3185+
setDefaultAppearance(generateDefaultAppearanceString(font, fontSize, color, new PdfResources()));
3186+
xObject.getResources().addFont(getDocument(), font);
3187+
}
31783188
}
31793189
xObject.getPdfObject().getOutputStream().writeBytes(stream.getBytes());
31803190

@@ -3223,6 +3233,7 @@ protected void drawCheckBox(PdfCanvas canvas, float width, float height, float f
32233233
DrawingUtil.drawCross(canvas, width, height, borderWidth);
32243234
return;
32253235
}
3236+
//TODO what is current font actually?
32263237
PdfFont ufont = getFont();
32273238
if (fontSize <= 0) {
32283239
fontSize = approximateFontSizeToFitBBox(ufont, new Rectangle(width, height), text);

kernel/src/main/java/com/itextpdf/kernel/pdf/xobject/PdfFormXObject.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ This file is part of the iText (R) project.
6363
public class PdfFormXObject extends PdfXObject {
6464

6565
private static final long serialVersionUID = 467500482711722178L;
66-
private PdfResources resources = null;
66+
protected PdfResources resources = null;
6767

6868
/**
6969
* Creates a new instance of Form XObject.

0 commit comments

Comments
 (0)