Skip to content

Commit 9a0af2f

Browse files
committed
SVG: Add possibility to customize renderers for text chunks
DEVSIX-5428
1 parent e1a2380 commit 9a0af2f

File tree

5 files changed

+102
-2
lines changed

5 files changed

+102
-2
lines changed

svg/src/main/java/com/itextpdf/svg/SvgConstants.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,11 @@ public static final class Tags {
458458
*/
459459
public static final String TEXT = "text";
460460

461+
/**
462+
* Phantom tag for text leaf.
463+
*/
464+
public static final String TEXT_LEAF = ":text-leaf";
465+
461466
/**
462467
* Tag defining a path on which text can be drawn.
463468
*/

svg/src/main/java/com/itextpdf/svg/processors/impl/DefaultSvgProcessor.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,14 @@ This file is part of the iText (R) project.
4343
package com.itextpdf.svg.processors.impl;
4444

4545
import com.itextpdf.styledxmlparser.css.ICssResolver;
46+
import com.itextpdf.styledxmlparser.jsoup.nodes.Element;
47+
import com.itextpdf.styledxmlparser.jsoup.parser.Tag;
4648
import com.itextpdf.styledxmlparser.node.IElementNode;
4749
import com.itextpdf.styledxmlparser.node.INode;
4850
import com.itextpdf.styledxmlparser.node.ITextNode;
51+
import com.itextpdf.styledxmlparser.node.impl.jsoup.node.JsoupElementNode;
4952
import com.itextpdf.svg.SvgConstants;
53+
import com.itextpdf.svg.SvgConstants.Tags;
5054
import com.itextpdf.svg.css.impl.SvgStyleResolver;
5155
import com.itextpdf.svg.exceptions.SvgLogMessageConstant;
5256
import com.itextpdf.svg.exceptions.SvgProcessingException;
@@ -63,7 +67,6 @@ This file is part of the iText (R) project.
6367
import com.itextpdf.svg.renderers.impl.ISvgTextNodeRenderer;
6468
import com.itextpdf.svg.renderers.impl.LinearGradientSvgNodeRenderer;
6569
import com.itextpdf.svg.renderers.impl.StopSvgNodeRenderer;
66-
import com.itextpdf.svg.renderers.impl.TextLeafSvgNodeRenderer;
6770
import com.itextpdf.svg.renderers.impl.TextSvgBranchRenderer;
6871
import com.itextpdf.svg.utils.SvgTextUtil;
6972

@@ -255,7 +258,9 @@ private void processText(ITextNode textNode) {
255258
if (parentRenderer instanceof TextSvgBranchRenderer) {
256259
String wholeText = textNode.wholeText();
257260
if (!"".equals(wholeText) && !SvgTextUtil.isOnlyWhiteSpace(wholeText)) {
258-
TextLeafSvgNodeRenderer textLeaf = new TextLeafSvgNodeRenderer();
261+
final IElementNode textLeafElement = new JsoupElementNode(new Element(Tag.valueOf(Tags.TEXT_LEAF), ""));
262+
ISvgTextNodeRenderer textLeaf = (ISvgTextNodeRenderer) this.rendererFactory
263+
.createSvgNodeRendererForTag(textLeafElement, parentRenderer);
259264
textLeaf.setParent(parentRenderer);
260265
textLeaf.setAttribute(SvgConstants.Attributes.TEXT_CONTENT, wholeText);
261266
((TextSvgBranchRenderer) parentRenderer).addChild(textLeaf);

svg/src/main/java/com/itextpdf/svg/renderers/factories/DefaultSvgNodeRendererMapper.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ This file is part of the iText (R) project.
6161
import com.itextpdf.svg.renderers.impl.StopSvgNodeRenderer;
6262
import com.itextpdf.svg.renderers.impl.SvgTagSvgNodeRenderer;
6363
import com.itextpdf.svg.renderers.impl.SymbolSvgNodeRenderer;
64+
import com.itextpdf.svg.renderers.impl.TextLeafSvgNodeRenderer;
6465
import com.itextpdf.svg.renderers.impl.TextSvgBranchRenderer;
6566
import com.itextpdf.svg.renderers.impl.TextSvgTSpanBranchRenderer;
6667
import com.itextpdf.svg.renderers.impl.UseSvgNodeRenderer;
@@ -109,6 +110,7 @@ public Map<String, Class<? extends ISvgNodeRenderer>> getMapping() {
109110
result.put(SvgConstants.Tags.TEXT, TextSvgBranchRenderer.class);
110111
result.put(SvgConstants.Tags.TSPAN, TextSvgTSpanBranchRenderer.class);
111112
result.put(SvgConstants.Tags.USE, UseSvgNodeRenderer.class);
113+
result.put(SvgConstants.Tags.TEXT_LEAF, TextLeafSvgNodeRenderer.class);
112114

113115
return result;
114116
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package com.itextpdf.svg.customization;
2+
3+
import com.itextpdf.kernel.colors.ColorConstants;
4+
import com.itextpdf.kernel.geom.Rectangle;
5+
import com.itextpdf.kernel.pdf.PdfDocument;
6+
import com.itextpdf.kernel.pdf.PdfWriter;
7+
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
8+
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
9+
import com.itextpdf.kernel.utils.CompareTool;
10+
import com.itextpdf.styledxmlparser.node.IElementNode;
11+
import com.itextpdf.svg.SvgConstants;
12+
import com.itextpdf.svg.SvgConstants.Tags;
13+
import com.itextpdf.svg.converter.SvgConverter;
14+
import com.itextpdf.svg.processors.impl.SvgConverterProperties;
15+
import com.itextpdf.svg.renderers.ISvgNodeRenderer;
16+
import com.itextpdf.svg.renderers.SvgDrawContext;
17+
import com.itextpdf.svg.renderers.SvgIntegrationTest;
18+
import com.itextpdf.svg.renderers.factories.DefaultSvgNodeRendererFactory;
19+
import com.itextpdf.svg.renderers.impl.TextLeafSvgNodeRenderer;
20+
import com.itextpdf.test.ITextTest;
21+
22+
import java.io.IOException;
23+
import org.junit.Assert;
24+
import org.junit.BeforeClass;
25+
import org.junit.Test;
26+
27+
public class CustomizeTextLeafSvgNodeRendererTest extends SvgIntegrationTest {
28+
29+
public static final String SOURCE_FOLDER = "./src/test/resources/com/itextpdf/svg/customization/CustomizeTextLeafSvgNodeRendererTest/";
30+
public static final String DESTINATION_FOLDER = "./target/test/com/itextpdf/svg/customization/CustomizeTextLeafSvgNodeRendererTest/";
31+
32+
@BeforeClass
33+
public static void beforeClass() {
34+
ITextTest.createDestinationFolder(DESTINATION_FOLDER);
35+
}
36+
37+
@Test
38+
public void testCustomizeTextLeafSvgNodeRenderer() throws IOException, InterruptedException {
39+
String pdfFilename = "customizeTextLeafSvgNodeRenderer.pdf";
40+
PdfDocument doc = new PdfDocument(new PdfWriter(DESTINATION_FOLDER + pdfFilename));
41+
doc.addNewPage();
42+
43+
SvgConverterProperties properties = new SvgConverterProperties();
44+
properties.setRendererFactory(new CustomTextLeafOverridingSvgNodeRendererFactory());
45+
46+
String svg = "<svg viewBox=\"0 0 240 80\" xmlns=\"http://www.w3.org/2000/svg\">\n"
47+
+ " <text x=\"20\" y=\"35\" class=\"small\">Hello world</text>\n"
48+
+ "</svg>";
49+
50+
PdfFormXObject form = SvgConverter.convertToXObject(svg, doc, properties);
51+
new PdfCanvas(doc.getPage(1)).addXObjectFittedIntoRectangle(form, new Rectangle(100, 100, 240, 80));
52+
53+
doc.close();
54+
Assert.assertNull(new CompareTool().compareByContent(DESTINATION_FOLDER + pdfFilename, SOURCE_FOLDER + "cmp_" + pdfFilename, DESTINATION_FOLDER, "diff_"));
55+
}
56+
57+
private static class CustomTextLeafOverridingSvgNodeRendererFactory extends DefaultSvgNodeRendererFactory {
58+
@Override
59+
public ISvgNodeRenderer createSvgNodeRendererForTag(IElementNode tag, ISvgNodeRenderer parent) {
60+
if (Tags.TEXT_LEAF.equals(tag.name())) {
61+
return new CustomTextLeafSvgNodeRenderer();
62+
} else {
63+
return super.createSvgNodeRendererForTag(tag, parent);
64+
}
65+
}
66+
}
67+
68+
private static class CustomTextLeafSvgNodeRenderer extends TextLeafSvgNodeRenderer {
69+
@Override
70+
public ISvgNodeRenderer createDeepCopy() {
71+
CustomTextLeafSvgNodeRenderer copy = new CustomTextLeafSvgNodeRenderer();
72+
deepCopyAttributesAndStyles(copy);
73+
return copy;
74+
}
75+
76+
@Override
77+
protected void doDraw(SvgDrawContext context) {
78+
if (this.attributesAndStyles != null && this.attributesAndStyles.containsKey(SvgConstants.Attributes.TEXT_CONTENT)) {
79+
PdfCanvas currentCanvas = context.getCurrentCanvas();
80+
currentCanvas.setFillColor(ColorConstants.RED);
81+
currentCanvas.moveText(context.getTextMove()[0], context.getTextMove()[1]);
82+
String initialText = this.attributesAndStyles.get(SvgConstants.Attributes.TEXT_CONTENT);
83+
String amendedText = "_" + initialText + "_";
84+
currentCanvas.showText(amendedText);
85+
}
86+
}
87+
}
88+
}

0 commit comments

Comments
 (0)