Skip to content

Commit

Permalink
Merge pull request #110 from atomfrede/95-add-svg-support-again
Browse files Browse the repository at this point in the history
add svg support again
  • Loading branch information
kenglxn committed Oct 1, 2018
2 parents 6e52800 + 654dfd6 commit 7bb6f68
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 28 deletions.
8 changes: 8 additions & 0 deletions README.md
Expand Up @@ -192,6 +192,14 @@ QRCode.from(johnSpecial).withCharset("UTF-8").file();
// - Wifi
// - YouTube
```
#### Java SE only

When using java you can create svg files via `.svg()` terminal operator:

```java
File file = QRCode.from("www.example.org").svg();
File file = QRCode.from("www.example.com").withSize(250, 250).withColor(30, 90).svg();
```

#### Android only

Expand Down
2 changes: 2 additions & 0 deletions core/pom.xml
Expand Up @@ -48,6 +48,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<goals>
Expand All @@ -59,6 +60,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${maven-javadoc-plugin.version}</version>
<executions>
<execution>
<goals>
Expand Down
14 changes: 14 additions & 0 deletions javase/pom.xml
Expand Up @@ -49,6 +49,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>${maven-source-plugin.version}</version>
<executions>
<execution>
<goals>
Expand All @@ -60,6 +61,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${maven-javadoc-plugin.version}</version>
<executions>
<execution>
<goals>
Expand All @@ -81,10 +83,22 @@
<artifactId>core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-svggen</artifactId>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-dom</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
</dependency>
</dependencies>

</project>
53 changes: 53 additions & 0 deletions javase/src/main/java/net/glxn/qrgen/javase/MatrixToSvgWriter.java
@@ -0,0 +1,53 @@
package net.glxn.qrgen.javase;

import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.common.BitMatrix;
import org.apache.batik.dom.GenericDOMImplementation;
import org.apache.batik.svggen.SVGGraphics2D;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;

import java.awt.*;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Path;

class MatrixToSvgWriter {

private MatrixToSvgWriter() {
// private utility class constuctor
}

private static SVGGraphics2D toSvgDocument(BitMatrix matrix, MatrixToImageConfig config) {

int width = matrix.getWidth();
int height = matrix.getHeight();

DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
String svgNS = "http://www.w3.org/2000/svg";
Document document = domImpl.createDocument(svgNS, "svg", null);

SVGGraphics2D svgGraphics = new SVGGraphics2D(document);
svgGraphics.setColor(new Color(config.getPixelOffColor()));
svgGraphics.fillRect(0,0, width, height);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
if (matrix.get(x,y)) {
svgGraphics.setColor(new Color(config.getPixelOnColor()));
svgGraphics.fillRect(x, y, 1, 1);
}
}
}

return svgGraphics;


}

static void writeToPath(BitMatrix matrix, Path file, MatrixToImageConfig matrixToImageConfig) throws IOException {
SVGGraphics2D g2 = toSvgDocument(matrix, matrixToImageConfig);

FileWriter out = new FileWriter(file.toFile());
g2.stream(out);
}
}
22 changes: 22 additions & 0 deletions javase/src/main/java/net/glxn/qrgen/javase/QRCode.java
Expand Up @@ -150,6 +150,28 @@ protected void writeToStream(OutputStream stream) throws IOException, WriterExce
MatrixToImageWriter.writeToStream(createMatrix(text), imageType.toString(), stream, matrixToImageConfig);
}

public File svg() {
File file;
try {
file = createTempSvgFile();
MatrixToSvgWriter.writeToPath(createMatrix(text), file.toPath(), matrixToImageConfig);
} catch (Exception e) {
throw new QRGenerationException("Failed to create QR svg from text due to underlying exception", e);
}
return file;
}

public File svg(String name) {
File file;
try {
file = createTempSvgFile(name);
MatrixToSvgWriter.writeToPath(createMatrix(text), file.toPath(), matrixToImageConfig);
} catch (Exception e) {
throw new QRGenerationException("Failed to create QR svg from text due to underlying exception", e);
}
return file;
}

private File createTempSvgFile() throws IOException {
return createTempSvgFile("QRCode");
}
Expand Down
99 changes: 71 additions & 28 deletions javase/src/test/java/net/glxn/qrgen/javase/QRCodeTest.java
Expand Up @@ -20,10 +20,12 @@
import java.nio.file.Files;
import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;

public class QRCodeTest {

@Test
public void shouldGetFileFromVCardWithDefaults() throws Exception {
public void shouldGetFileFromVCardWithDefaults() {
VCard johnDoe = new VCard("John Doe")
.setName("John Doe")
.setEmail("john.doe@example.org")
Expand All @@ -33,11 +35,13 @@ public void shouldGetFileFromVCardWithDefaults() throws Exception {
.setPhoneNumber("1234")
.setWebsite("www.example.org");
File file = QRCode.from(johnDoe).file();
Assert.assertNotNull(file);
assertThat(file).exists();
assertThat(file).canRead();
assertThat(file.length()).isGreaterThan(0);
}

@Test
public void shouldGetFileFromVCardWithExtendedChars() throws Exception {
public void shouldGetFileFromVCardWithExtendedChars() {
VCard johnDoe = new VCard("John Doe")
.setName("Björkelundsvägen")
.setEmail("john.doe@example.org")
Expand All @@ -47,36 +51,44 @@ public void shouldGetFileFromVCardWithExtendedChars() throws Exception {
.setPhoneNumber("1234")
.setWebsite("www.Björkelundsvägen.org");
File file = QRCode.from(johnDoe).file();
Assert.assertNotNull(file);
assertThat(file).exists();
assertThat(file).canRead();
assertThat(file.length()).isGreaterThan(0);
}

@Test
public void shouldGetBitmapFileFromText() throws Exception {
public void shouldGetBitmapFileFromText() {
File file = QRCode.from("www.example.org").to(ImageType.BMP).file();
Assert.assertNotNull(file);
assertThat(file).exists();
assertThat(file).canRead();
assertThat(file.length()).isGreaterThan(0);
}

@Test
public void shouldGetFileFromTextWithDefaults() throws Exception {
public void shouldGetFileFromTextWithDefaults() {
File file = QRCode.from("Hello World").file();
Assert.assertNotNull(file);
assertThat(file).exists();
assertThat(file).canRead();
assertThat(file.length()).isGreaterThan(0);
}

@Test
public void shouldGetFileWithNameFromTextWithDefaults() throws Exception {
public void shouldGetFileWithNameFromTextWithDefaults() {
File file = QRCode.from("Hello World").file("Hello World");
Assert.assertNotNull(file);
assertThat(file).exists();
assertThat(file).canRead();
assertThat(file.length()).isGreaterThan(0);
Assert.assertTrue(file.getName().startsWith("Hello World"));
}

@Test
public void shouldGetSTREAMFromTextWithDefaults() throws Exception {
public void shouldGetSTREAMFromTextWithDefaults() {
ByteArrayOutputStream stream = QRCode.from("Hello World").stream();
Assert.assertNotNull(stream);
}

@Test
public void shouldHandleLargeString() throws Exception {
public void shouldHandleLargeString() {
int length = 2950;
char[] chars = new char[length];
for (int i = 0; i < length; i++) {
Expand All @@ -86,24 +98,30 @@ public void shouldHandleLargeString() throws Exception {
Assert.assertEquals(length, text.length());

File file = QRCode.from(text).to(ImageType.PNG).file();
Assert.assertNotNull(file);
assertThat(file).exists();
assertThat(file).canRead();
assertThat(file.length()).isGreaterThan(0);
}

@Test
public void shouldGetFileFromTextWithImageTypeOverrides() throws Exception {
public void shouldGetFileFromTextWithImageTypeOverrides() {
File jpg = QRCode.from("Hello World").to(ImageType.JPG).file();
Assert.assertNotNull(jpg);
File gif = QRCode.from("Hello World").to(ImageType.GIF).file();
Assert.assertNotNull(gif);
assertThat(gif).exists();
assertThat(gif).canRead();
assertThat(gif.length()).isGreaterThan(0);
}

@Test
public void shouldGetFileWithNameFromTextWithImageTypeOverrides() throws Exception {
public void shouldGetFileWithNameFromTextWithImageTypeOverrides() {
File jpg = QRCode.from("Hello World").to(ImageType.JPG).file("Hello World");
Assert.assertNotNull(jpg);
Assert.assertTrue(jpg.getName().startsWith("Hello World"));
File gif = QRCode.from("Hello World").to(ImageType.GIF).file("Hello World");
Assert.assertNotNull(gif);
assertThat(gif).exists();
assertThat(gif).canRead();
assertThat(gif.length()).isGreaterThan(0);
Assert.assertTrue(gif.getName().startsWith("Hello World"));
}

Expand All @@ -115,7 +133,7 @@ public void shouldGetStreamFromText() throws Exception {
long lengthBefore = tempFile.length();
FileOutputStream fileOutputStream = new FileOutputStream(tempFile);
stream.writeTo(fileOutputStream);
Assert.assertTrue(lengthBefore < tempFile.length());
assertThat(tempFile.length()).isGreaterThan(lengthBefore);
}

@Test
Expand All @@ -128,32 +146,36 @@ public void shouldWriteToSuppliedStream() throws Exception {
long lengthBefore = tempFile.length();
FileOutputStream fileOutputStream = new FileOutputStream(tempFile);
stream.writeTo(fileOutputStream);
Assert.assertTrue(lengthBefore < tempFile.length());
assertThat(tempFile.length()).isGreaterThan(lengthBefore);
}

@Test
public void shouldBeAbleToOverrideDimensionsToFile() throws Exception {
public void shouldBeAbleToOverrideDimensionsToFile() {
long defaultSize = QRCode.from("Hello World").to(ImageType.PNG).file().length();
long defaultSize2 = QRCode.from("Hello World").to(ImageType.PNG).file().length();
File file = QRCode.from("Hello World").to(ImageType.PNG).withSize(250, 250).file();
Assert.assertNotNull(file);
Assert.assertTrue(defaultSize == defaultSize2);
assertThat(file).exists();
assertThat(file).canRead();
assertThat(file.length()).isGreaterThan(0);
Assert.assertEquals(defaultSize, defaultSize2);
Assert.assertTrue(defaultSize < file.length());
}

@Test
public void shouldBeAbleToOverrideDimensionsToFileWithName() throws Exception {
public void shouldBeAbleToOverrideDimensionsToFileWithName() {
long defaultSize = QRCode.from("Hello World").to(ImageType.PNG).file("Hello World").length();
long defaultSize2 = QRCode.from("Hello World").to(ImageType.PNG).file("Hello World").length();
File file = QRCode.from("Hello World").to(ImageType.PNG).withSize(250, 250).file("Hello World");
Assert.assertNotNull(file);
Assert.assertTrue(defaultSize == defaultSize2);
assertThat(file).exists();
assertThat(file).canRead();
assertThat(file.length()).isGreaterThan(0);
Assert.assertEquals(defaultSize, defaultSize2);
Assert.assertTrue(defaultSize < file.length());
Assert.assertTrue(file.getName().startsWith("Hello World"));
}

@Test
public void shouldBeAbleToSupplyEncodingHint() throws Exception {
public void shouldBeAbleToSupplyEncodingHint() {
String expected = "UTF-8";
final Object[] capture = new Object[1];
try {
Expand All @@ -166,7 +188,7 @@ public void shouldBeAbleToSupplyEncodingHint() throws Exception {
}

@Test
public void shouldBeAbleToSupplyErrorCorrectionHint() throws Exception {
public void shouldBeAbleToSupplyErrorCorrectionHint() {
ErrorCorrectionLevel expected = ErrorCorrectionLevel.L;
final Object[] capture = new Object[1];
try {
Expand Down Expand Up @@ -199,7 +221,28 @@ public void shouldColorOutput() throws IOException {
File file = QRCode.from("Hello World").withColor(0xFFFF0000, 0xFFFFFFAA).file();
File tempFile = File.createTempFile("qr_", ".png");
Files.copy(file.toPath(), new FileOutputStream(tempFile));
System.out.println(tempFile.getAbsoluteFile());
}

@Test
public void shouldGetSvgFromText() {
File file = QRCode.from("www.example.org").svg();
assertThat(file).exists();
assertThat(file).canRead();
assertThat(file.length()).isGreaterThan(0);
}
@Test
public void shouldGetSvgWithSizeFromText() {
File file = QRCode.from("www.example.com").withSize(250, 250).svg();
assertThat(file).exists();
assertThat(file).canRead();
assertThat(file.length()).isGreaterThan(0);
}
@Test
public void shouldGetSvgWithSizeAndColorFromText() {
File file = QRCode.from("www.example.com").withSize(250, 250).withColor(30, 90).svg();
assertThat(file).exists();
assertThat(file).canRead();
assertThat(file.length()).isGreaterThan(0);
}

@SuppressWarnings("unchecked")
Expand Down

0 comments on commit 7bb6f68

Please sign in to comment.