Skip to content

Commit 75d858e

Browse files
PdfCleanUp: support overlay text in redaction annotations
DEVSIX-483
1 parent 94c45e3 commit 75d858e

File tree

6 files changed

+87
-57
lines changed

6 files changed

+87
-57
lines changed

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

Lines changed: 53 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1797,55 +1797,6 @@ public void release() {
17971797
getPdfObject().release();
17981798
}
17991799

1800-
protected static Object[] splitDAelements(String da) {
1801-
PdfTokenizer tk = new PdfTokenizer(new RandomAccessFileOrArray(new RandomAccessSourceFactory().createSource(PdfEncodings.convertToBytes(da, null))));
1802-
List<String> stack = new ArrayList<>();
1803-
Object ret[] = new Object[3];
1804-
try {
1805-
while (tk.nextToken()) {
1806-
if (tk.getTokenType() == PdfTokenizer.TokenType.Comment)
1807-
continue;
1808-
if (tk.getTokenType() == PdfTokenizer.TokenType.Other) {
1809-
String operator = tk.getStringValue();
1810-
if (operator.equals("Tf")) {
1811-
if (stack.size() >= 2) {
1812-
ret[DA_FONT] = stack.get(stack.size() - 2);
1813-
ret[DA_SIZE] = new Integer(stack.get(stack.size() - 1));
1814-
}
1815-
} else if (operator.equals("g")) {
1816-
if (stack.size() >= 1) {
1817-
float gray = new Float(stack.get(stack.size() - 1));
1818-
if (gray != 0) {
1819-
ret[DA_COLOR] = new DeviceGray(gray);
1820-
}
1821-
}
1822-
} else if (operator.equals("rg")) {
1823-
if (stack.size() >= 3) {
1824-
float red = new Float(stack.get(stack.size() - 3));
1825-
float green = new Float(stack.get(stack.size() - 2));
1826-
float blue = new Float(stack.get(stack.size() - 1));
1827-
ret[DA_COLOR] = new DeviceRgb(red, green, blue);
1828-
}
1829-
} else if (operator.equals("k")) {
1830-
if (stack.size() >= 4) {
1831-
float cyan = new Float(stack.get(stack.size() - 4));
1832-
float magenta = new Float(stack.get(stack.size() - 3));
1833-
float yellow = new Float(stack.get(stack.size() - 2));
1834-
float black = new Float(stack.get(stack.size() - 1));
1835-
ret[DA_COLOR] = new DeviceCmyk(cyan, magenta, yellow, black);
1836-
}
1837-
}
1838-
stack.clear();
1839-
} else {
1840-
stack.add(tk.getStringValue());
1841-
}
1842-
}
1843-
} catch (IOException e) {
1844-
1845-
}
1846-
return ret;
1847-
}
1848-
18491800
@Override
18501801
protected boolean isWrappedObjectMustBeIndirect() {
18511802
return true;
@@ -1946,6 +1897,55 @@ protected Object[] getFontAndSize(PdfDictionary asNormal) throws IOException {
19461897
return fontAndSize;
19471898
}
19481899

1900+
protected static Object[] splitDAelements(String da) {
1901+
PdfTokenizer tk = new PdfTokenizer(new RandomAccessFileOrArray(new RandomAccessSourceFactory().createSource(PdfEncodings.convertToBytes(da, null))));
1902+
List<String> stack = new ArrayList<>();
1903+
Object ret[] = new Object[3];
1904+
try {
1905+
while (tk.nextToken()) {
1906+
if (tk.getTokenType() == PdfTokenizer.TokenType.Comment)
1907+
continue;
1908+
if (tk.getTokenType() == PdfTokenizer.TokenType.Other) {
1909+
String operator = tk.getStringValue();
1910+
if (operator.equals("Tf")) {
1911+
if (stack.size() >= 2) {
1912+
ret[DA_FONT] = stack.get(stack.size() - 2);
1913+
ret[DA_SIZE] = new Integer(stack.get(stack.size() - 1));
1914+
}
1915+
} else if (operator.equals("g")) {
1916+
if (stack.size() >= 1) {
1917+
float gray = new Float(stack.get(stack.size() - 1));
1918+
if (gray != 0) {
1919+
ret[DA_COLOR] = new DeviceGray(gray);
1920+
}
1921+
}
1922+
} else if (operator.equals("rg")) {
1923+
if (stack.size() >= 3) {
1924+
float red = new Float(stack.get(stack.size() - 3));
1925+
float green = new Float(stack.get(stack.size() - 2));
1926+
float blue = new Float(stack.get(stack.size() - 1));
1927+
ret[DA_COLOR] = new DeviceRgb(red, green, blue);
1928+
}
1929+
} else if (operator.equals("k")) {
1930+
if (stack.size() >= 4) {
1931+
float cyan = new Float(stack.get(stack.size() - 4));
1932+
float magenta = new Float(stack.get(stack.size() - 3));
1933+
float yellow = new Float(stack.get(stack.size() - 2));
1934+
float black = new Float(stack.get(stack.size() - 1));
1935+
ret[DA_COLOR] = new DeviceCmyk(cyan, magenta, yellow, black);
1936+
}
1937+
}
1938+
stack.clear();
1939+
} else {
1940+
stack.add(tk.getStringValue());
1941+
}
1942+
}
1943+
} catch (IOException e) {
1944+
1945+
}
1946+
return ret;
1947+
}
1948+
19491949
/**
19501950
* Draws the visual appearance of text in a form field.
19511951
*
@@ -1999,8 +1999,6 @@ protected void drawTextAppearance(Rectangle rect, PdfFont font, int fontSize, St
19991999
endVariableText();
20002000

20012001
appearance.getPdfObject().setData(stream.getBytes());
2002-
2003-
// return stream.getBytes();
20042002
}
20052003

20062004
/**
@@ -2033,6 +2031,10 @@ protected void drawMultiLineTextAppearance(Rectangle rect, PdfFont font, int fon
20332031

20342032
Canvas modelCanvas = new Canvas(canvas, getDocument(), new Rectangle(3, 0, Math.max(0, width - 6), Math.max(0, height - 2)));
20352033
for (int index = 0; index < strings.size(); index++) {
2034+
Boolean isFull = modelCanvas.getRenderer().getPropertyAsBoolean(Property.FULL);
2035+
if (isFull != null && isFull) {
2036+
break;
2037+
}
20362038
Paragraph paragraph = new Paragraph(strings.get(index)).setFont(font).setFontSize(fontSize).setMargins(0, 0, 0, 0).setMultipliedLeading(1);
20372039
if (color != null) {
20382040
paragraph.setFontColor(color);
@@ -2055,8 +2057,6 @@ protected void drawMultiLineTextAppearance(Rectangle rect, PdfFont font, int fon
20552057
endVariableText();
20562058

20572059
appearance.getPdfObject().setData(stream.getBytes());
2058-
2059-
// return stream.getBytes();
20602060
}
20612061

20622062
/**

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public class PdfFreeTextAnnotation extends PdfMarkupAnnotation {
1717

1818
public PdfFreeTextAnnotation(Rectangle rect, String appearanceString) {
1919
super(rect);
20-
setDrawnAfter(new PdfString(appearanceString));
20+
setDefaultAppearance(new PdfString(appearanceString));
2121
}
2222

2323
public PdfFreeTextAnnotation(PdfDictionary pdfObject) {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,11 @@ public <T extends PdfMarkupAnnotation> T setIconName(PdfName name) {
166166
return put(PdfName.Name, name);
167167
}
168168

169-
public <T extends PdfMarkupAnnotation> T setDrawnAfter(PdfString appearanceString) {
169+
public <T extends PdfMarkupAnnotation> T setDefaultAppearance(PdfString appearanceString) {
170170
return put(PdfName.DA, appearanceString);
171171
}
172172

173-
public PdfString getDrawnAfter() {
173+
public PdfString getDefaultAppearance() {
174174
return getPdfObject().getAsString(PdfName.DA);
175175
}
176176

layout/src/main/java/com/itextpdf/layout/Canvas.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.itextpdf.kernel.pdf.PdfDocument;
66
import com.itextpdf.kernel.pdf.PdfPage;
77
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
8+
import com.itextpdf.layout.element.IElement;
89
import com.itextpdf.layout.renderer.CanvasRenderer;
910
import com.itextpdf.layout.renderer.RootRenderer;
1011

@@ -39,6 +40,20 @@ public Canvas(PdfCanvas pdfCanvas, PdfDocument pdfDocument, Rectangle rootArea)
3940
this.rootArea = rootArea;
4041
}
4142

43+
/**
44+
* Creates a new Canvas to manipulate a specific document and page.
45+
*
46+
* @param pdfCanvas the low-level content stream writer
47+
* @param pdfDocument the document that the resulting content stream will be written to
48+
* @param rootArea the maximum area that the Canvas may write upon
49+
*/
50+
public Canvas(PdfCanvas pdfCanvas, PdfDocument pdfDocument, Rectangle rootArea, boolean immediateFlush) {
51+
this.pdfDocument = pdfDocument;
52+
this.pdfCanvas = pdfCanvas;
53+
this.rootArea = rootArea;
54+
this.immediateFlush = immediateFlush;
55+
}
56+
4257
/**
4358
* Creates a new Canvas to manipulate a specific {@link PdfFormXObject}.
4459
*
@@ -107,6 +122,18 @@ public boolean isAutoTaggingEnabled() {
107122
return page != null;
108123
}
109124

125+
public void relayout() {
126+
if (immediateFlush) {
127+
throw new IllegalStateException("Operation not supported with immediate flush");
128+
}
129+
130+
rootRenderer = new CanvasRenderer(this, immediateFlush);
131+
132+
for (IElement element : childElements) {
133+
rootRenderer.addChild(element.createRendererSubTree());
134+
}
135+
}
136+
110137
@Override
111138
protected RootRenderer ensureRootRendererNotNull() {
112139
if (rootRenderer == null)

layout/src/main/java/com/itextpdf/layout/Property.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public enum Property {
3333
FONT_KERNING(true),
3434
FONT_SCRIPT(true),
3535
FONT_SIZE(true),
36+
FULL,
3637
FORCED_PLACEMENT(true),
3738
HEIGHT,
3839
HORIZONTAL_ALIGNMENT,

layout/src/main/java/com/itextpdf/layout/renderer/CanvasRenderer.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.itextpdf.kernel.pdf.tagutils.PdfTagStructure;
44
import com.itextpdf.layout.Canvas;
5+
import com.itextpdf.layout.Property;
56
import com.itextpdf.layout.layout.LayoutArea;
67
import com.itextpdf.layout.layout.LayoutResult;
78

@@ -38,8 +39,9 @@ protected void flushSingleRenderer(IRenderer resultRenderer) {
3839
@Override
3940
protected LayoutArea updateCurrentArea(LayoutResult overflowResult) {
4041
if (currentArea == null) {
41-
currentArea = new LayoutArea(0, canvas.getRootArea());
42+
currentArea = new LayoutArea(0, canvas.getRootArea().clone());
4243
} else {
44+
setProperty(Property.FULL, true);
4345
currentArea = null;
4446
}
4547
return currentArea;

0 commit comments

Comments
 (0)