Skip to content

Commit 851ff57

Browse files
committed
Add a SVG Generator example
1 parent c504425 commit 851ff57

File tree

2 files changed

+200
-5
lines changed

2 files changed

+200
-5
lines changed

src/examples/java/io/sf/carte/example/EchoSVGTest.java

Lines changed: 106 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,42 @@
11
/*
22
3-
Copyright (c) 2017-2021, Carlos Amengual.
4-
5-
SPDX-License-Identifier: BSD-3-Clause
3+
Copyright (c) 2017-2024, Carlos Amengual.
64
75
Licensed under a BSD-style License. You can find the license here:
86
https://css4j.github.io/LICENSE.txt
97
108
*/
9+
/*
10+
* SPDX-License-Identifier: BSD-3-Clause
11+
*/
1112

1213
package io.sf.carte.example;
1314

1415
import static org.junit.jupiter.api.Assertions.assertTrue;
1516

17+
import java.awt.Dimension;
18+
import java.awt.Font;
1619
import java.io.ByteArrayOutputStream;
20+
import java.io.CharArrayWriter;
1721
import java.io.InputStream;
1822
import java.io.InputStreamReader;
1923
import java.io.Reader;
2024
import java.nio.charset.StandardCharsets;
2125

26+
import javax.xml.parsers.DocumentBuilder;
27+
import javax.xml.parsers.DocumentBuilderFactory;
28+
import javax.xml.parsers.ParserConfigurationException;
29+
2230
import org.junit.jupiter.api.Test;
31+
import org.w3c.dom.Document;
32+
import org.w3c.dom.DocumentType;
33+
import org.w3c.dom.Element;
2334

2435
import io.sf.carte.echosvg.anim.dom.SVGDOMImplementation;
2536
import io.sf.carte.echosvg.dom.util.SAXDocumentFactory;
37+
import io.sf.carte.echosvg.svggen.SVGGeneratorContext;
38+
import io.sf.carte.echosvg.svggen.SVGGeneratorContext.GraphicContextDefaults;
39+
import io.sf.carte.echosvg.svggen.SVGGraphics2D;
2640
import io.sf.carte.echosvg.transcoder.ErrorHandler;
2741
import io.sf.carte.echosvg.transcoder.TranscoderException;
2842
import io.sf.carte.echosvg.transcoder.TranscoderInput;
@@ -35,22 +49,109 @@
3549
*/
3650
public class EchoSVGTest {
3751

52+
@Test
53+
public void testSVGGraphics2D() throws Exception {
54+
FontDecorationPainter painter = new FontDecorationPainter();
55+
56+
SVGGraphics2D g2d = createSVGGraphics2D();
57+
58+
// Set some appropriate dimension
59+
g2d.setSVGCanvasSize(new Dimension(300, 400));
60+
61+
painter.paint(g2d);
62+
63+
CharArrayWriter wri = new CharArrayWriter(1900);
64+
g2d.stream(wri);
65+
66+
int len = wri.toCharArray().length;
67+
assertTrue(len > 1800, "Char array had length of only " + len + ".");
68+
}
69+
70+
/**
71+
* Creates a <code>SVGGraphics2D</code> with certain defaults.
72+
*
73+
* @return the <code>SVGGraphics2D</code>.
74+
*/
75+
static SVGGraphics2D createSVGGraphics2D() {
76+
// We need a Document that holds an SVG root element.
77+
// First obtain a DocumentBuilder as a way to get it.
78+
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
79+
factory.setNamespaceAware(true);
80+
81+
DocumentBuilder builder;
82+
try {
83+
builder = factory.newDocumentBuilder();
84+
} catch (ParserConfigurationException e) {
85+
throw new IllegalStateException(e);
86+
}
87+
88+
// Now the document which is what is needed
89+
Document doc = builder.newDocument();
90+
91+
// Create a SVG DTD
92+
DocumentType dtd = builder.getDOMImplementation().createDocumentType("svg",
93+
"-//W3C//DTD SVG 1.1//EN", "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd");
94+
// And the root element in the SVG namespace
95+
Element svgRoot = doc.createElementNS("http://www.w3.org/2000/svg", "svg");
96+
97+
// Append those to the document
98+
doc.appendChild(dtd);
99+
doc.appendChild(svgRoot);
100+
101+
/*
102+
* Now the document is ready: let's create some context objects and then the
103+
* SVGGraphics2D.
104+
*/
105+
106+
// For simplicity, create a generator context with some defaults
107+
SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(doc);
108+
// Set a comment to put in the SVG documents, overriding the default
109+
ctx.setComment("Generated by My Application");
110+
111+
// Set a compression a bit higher than the default
112+
ctx.setCompressionLevel(6);
113+
114+
// Create the context defaults, with a default font just in case
115+
GraphicContextDefaults defaults = new GraphicContextDefaults();
116+
defaults.setFont(new Font("Arial", Font.PLAIN, 12));
117+
// Set the defaults
118+
ctx.setGraphicContextDefaults(defaults);
119+
120+
return new SVGGraphics2D(ctx, false);
121+
}
122+
38123
@Test
39124
public void testTranscoding() throws Exception {
40125
org.w3c.dom.DOMImplementation impl = SVGDOMImplementation.getDOMImplementation();
41126
SAXDocumentFactory f = new SAXDocumentFactory(impl);
42127
Reader re = loadDocumentFromClasspath("/hdrbg.svg");
43-
org.w3c.dom.Document document = f.createDocument("https://css4j.github.io/imag/hdrbg.svg", re);
128+
org.w3c.dom.Document document = f.createDocument("https://css4j.github.io/imag/hdrbg.svg",
129+
re);
44130

45131
PNGTranscoder trans = new PNGTranscoder();
46132
TranscoderInput input = new TranscoderInput(document);
47133
ByteArrayOutputStream ostream = new ByteArrayOutputStream(700);
48134
TranscoderOutput output = new TranscoderOutput(ostream);
49135
ErrorHandler handler = new ExceptionErrorHandler();
50136
trans.setErrorHandler(handler);
137+
138+
String[] text = { "Copyright", "Copyright © 2024 ACME Inc.", "Description",
139+
"Header background", "Software", "EchoSVG" };
140+
141+
String[] iText = { "Description", "en", "Description", "My image.", "Description", "es",
142+
"Descripción", "Mi imagen." };
143+
144+
trans.addTranscodingHint(PNGTranscoder.KEY_KEYWORD_TEXT, text);
145+
146+
trans.addTranscodingHint(PNGTranscoder.KEY_COMPRESSED_TEXT, text);
147+
148+
trans.addTranscodingHint(PNGTranscoder.KEY_INTERNATIONAL_TEXT, iText);
149+
150+
trans.addTranscodingHint(PNGTranscoder.KEY_COMPRESSION_LEVEL, 4);
151+
51152
trans.transcode(input, output);
52153

53-
assertTrue(ostream.size() > 400);
154+
assertTrue(ostream.size() > 1070, "Image had size of only " + ostream.size() + ".");
54155
}
55156

56157
private Reader loadDocumentFromClasspath(String filename) {
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
3+
Copyright (c) 2024, Carlos Amengual.
4+
5+
Licensed under a BSD-style License. You can find the license here:
6+
https://css4j.github.io/LICENSE.txt
7+
8+
*/
9+
/*
10+
* SPDX-License-Identifier: BSD-3-Clause
11+
*/
12+
package io.sf.carte.example;
13+
14+
import java.awt.Color;
15+
import java.awt.Font;
16+
import java.awt.Graphics2D;
17+
import java.awt.RenderingHints;
18+
import java.awt.font.TextAttribute;
19+
import java.awt.geom.Rectangle2D;
20+
import java.awt.image.BufferedImage;
21+
import java.util.HashMap;
22+
import java.util.Map;
23+
24+
/**
25+
* Draw text with decoration attributes.
26+
*/
27+
public class FontDecorationPainter {
28+
29+
public void paint(Graphics2D g) {
30+
// Set anti-aliasing
31+
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
32+
33+
// Set a background color
34+
Color backgroundColor = new Color(0x08081a);
35+
g.setBackground(backgroundColor);
36+
37+
// Set default font
38+
g.setFont(new Font("Arial", Font.BOLD, 12));
39+
40+
// Create a font with the desired attributes, including STRIKETHROUGH
41+
Map<TextAttribute, Object> attributes = new HashMap<>();
42+
attributes.put(TextAttribute.FAMILY, "Helvetica");
43+
attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_EXTRABOLD);
44+
attributes.put(TextAttribute.SIZE, 20);
45+
attributes.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON);
46+
Font fontST = new Font(attributes);
47+
48+
// A similar font but with UNDERLINE instead of STRIKETHROUGH
49+
Map<TextAttribute, Object> attributes2 = new HashMap<>(attributes);
50+
attributes2.remove(TextAttribute.STRIKETHROUGH);
51+
attributes2.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
52+
Font fontUL = new Font(attributes2);
53+
54+
// Set the STRIKETHROUGH font and a color
55+
g.setFont(fontST);
56+
g.setPaint(new Color(0x666699));
57+
// Draw a string
58+
g.drawString("Strike Through", 10, 40);
59+
60+
// Embed an image
61+
BufferedImage image = createImage();
62+
g.drawImage(image, 25, 60, new Color(0xcccccc), null);
63+
64+
// Now draw with a different color and the UNDERLINE font
65+
g.setPaint(Color.black);
66+
g.setFont(fontUL);
67+
g.translate(0, 30);
68+
// Draw a new string
69+
g.drawString("Underline", 10, 70);
70+
}
71+
72+
private static BufferedImage createImage() {
73+
// Create an Image
74+
BufferedImage image = new BufferedImage(100, 75, BufferedImage.TYPE_INT_ARGB);
75+
Graphics2D ig = image.createGraphics();
76+
ig.scale(.5, .5);
77+
ig.setPaint(new Color(128, 0, 0));
78+
ig.fillRect(0, 0, 100, 50);
79+
ig.setPaint(Color.orange);
80+
ig.fillRect(100, 0, 100, 50);
81+
ig.setPaint(Color.yellow);
82+
ig.fillRect(0, 50, 100, 50);
83+
ig.setPaint(Color.red);
84+
ig.fillRect(100, 50, 100, 50);
85+
ig.setPaint(new Color(255, 127, 127));
86+
ig.fillRect(0, 100, 100, 50);
87+
ig.setPaint(Color.black);
88+
ig.draw(new Rectangle2D.Double(0.5, 0.5, 199, 149));
89+
ig.dispose();
90+
91+
return image;
92+
}
93+
94+
}

0 commit comments

Comments
 (0)