pull/28/merge
Christopher Schultz 8 years ago committed by GitHub
commit 2c50cd0fd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -24,6 +24,8 @@
package io.nayuki.qrcodegen; package io.nayuki.qrcodegen;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -159,16 +161,12 @@ public final class QrCode {
// Create the QR Code symbol // Create the QR Code symbol
return new QrCode(version, ecl, bb.getBytes(), mask); return new QrCode(version, ecl, bb.getBytes(), mask);
} }
/*---- Public constants ----*/ /*---- Public constants ----*/
public static final int MIN_VERSION = 1; public static final int MIN_VERSION = 1;
public static final int MAX_VERSION = 40; public static final int MAX_VERSION = 40;
/*---- Instance fields ----*/ /*---- Instance fields ----*/
// Public immutable scalar parameters // Public immutable scalar parameters
@ -267,43 +265,100 @@ public final class QrCode {
} }
return result; return result;
} }
/** /**
* Based on the specified number of border modules to add as padding, this returns a * Returns a String containing a Scalable Vector Graphic (SVG) that depicts
* string whose contents represents an SVG XML file that depicts this QR Code symbol. * this QR Code symbol.
* Note that Unix newlines (\n) are always used, regardless of the platform. *
* @param border the number of border modules to add, which must be non-negative * @param border The number of border modules to add, which must be non-negative.
* @return a string representing this QR Code as an SVG document *
*/ * @return A String representing this QR Code as an SVG document.
public String toSvgString(int border) { */
if (border < 0) public String toSvgString(int border) {
throw new IllegalArgumentException("Border must be non-negative"); return toSvgString(border, true, true, true);
StringBuilder sb = new StringBuilder(); }
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
sb.append("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"); /**
sb.append(String.format( * Returns a String containing a Scalable Vector Graphic (SVG) that depicts
"<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 %1$d %1$d\" stroke=\"none\">\n", * this QR Code symbol.
size + border * 2)); *
sb.append("\t<rect width=\"100%\" height=\"100%\" fill=\"#FFFFFF\"/>\n"); * @param border The number of border modules to add, which must be non-negative.
sb.append("\t<path d=\""); * @param includeXMLPI Flag to include the XML processing instruction (&lt;?xml ... ?&gt;).
boolean head = true; * @param includeDoctype Flag to include the DOCTYPE.
for (int y = -border; y < size + border; y++) { * @param prettyPrint Flag to include optional newlines and indents.
for (int x = -border; x < size + border; x++) { *
if (getModule(x, y)) { * @return A String representing this QR Code as an SVG document.
if (head) */
head = false; public String toSvgString(int border, boolean includeXMLPI, boolean includeDoctype, boolean prettyPrint) {
else StringWriter sw = new StringWriter();
sb.append(" "); PrintWriter out = new PrintWriter(sw);
sb.append(String.format("M%d,%dh1v1h-1z", x + border, y + border)); toSvg(out, border, includeXMLPI, includeDoctype, prettyPrint);
} if(prettyPrint)
} out.println(); // Matches previous implementation
} return sw.toString();
sb.append("\" fill=\"#000000\"/>\n");
sb.append("</svg>\n");
return sb.toString();
} }
/**
* Writes a Scalable Vector Graphic (SVG) to the specified PrintWriter
* that depicts this QR Code symbol.
*
* @param border The number of border modules to add, which must be non-negative.
* @param includeXMLPI Flag to include the XML processing instruction (&lt;?xml ... ?&gt;).
* @param includeDoctype Flag to include the DOCTYPE.
* @param prettyPrint Flag to include optional newlines and indents.
*
* @return A String representing this QR Code as an SVG document.
*/
public void toSvg(PrintWriter out, int border, boolean includeXMLPI, boolean includeDoctype, boolean prettyPrint) {
if (border < 0)
throw new IllegalArgumentException("Border must be non-negative");
if(includeXMLPI)
out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
if(prettyPrint)
out.println();
if(includeDoctype)
out.write("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">");
if(prettyPrint)
out.println();
int dim = size + (border << 1); // Double border size by shifting
out.write("<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 ");
out.print(dim);
out.write(' ');
out.print(dim);
out.write("\">", 0, 2);
if(prettyPrint) {
out.println();
out.write('\t');
}
out.write("<path d=\"");
boolean head = true;
for (int y = -border; y < size + border; y++) {
for (int x = -border; x < size + border; x++) {
if (getModule(x, y)) {
if (head)
head = false;
else
out.write(" ");
out.write('M');
out.print(x+border);
out.write(',');
out.print(y+border);
out.write("h1v1h-1z",0,8);
}
}
}
out.write("\"/>");
if(prettyPrint)
out.println();
out.write("</svg>");
}
/*---- Private helper methods for constructor: Drawing function modules ----*/ /*---- Private helper methods for constructor: Drawing function modules ----*/
@ -637,7 +692,7 @@ public final class QrCode {
// used on both the x and y axes. Each value in the resulting array is in the range [0, 177). // used on both the x and y axes. Each value in the resulting array is in the range [0, 177).
// This stateless pure function could be implemented as table of 40 variable-length lists of unsigned bytes. // This stateless pure function could be implemented as table of 40 variable-length lists of unsigned bytes.
private static int[] getAlignmentPatternPositions(int ver) { private static int[] getAlignmentPatternPositions(int ver) {
if (ver < MIN_VERSION || ver > MAX_VERSION) if (ver < 1 || ver > 40)
throw new IllegalArgumentException("Version number out of range"); throw new IllegalArgumentException("Version number out of range");
else if (ver == 1) else if (ver == 1)
return new int[]{}; return new int[]{};
@ -663,7 +718,7 @@ public final class QrCode {
// all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8. // all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8.
// The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table. // The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table.
private static int getNumRawDataModules(int ver) { private static int getNumRawDataModules(int ver) {
if (ver < MIN_VERSION || ver > MAX_VERSION) if (ver < 1 || ver > 40)
throw new IllegalArgumentException("Version number out of range"); throw new IllegalArgumentException("Version number out of range");
int size = ver * 4 + 17; int size = ver * 4 + 17;
@ -688,7 +743,7 @@ public final class QrCode {
// QR Code of the given version number and error correction level, with remainder bits discarded. // QR Code of the given version number and error correction level, with remainder bits discarded.
// This stateless pure function could be implemented as a (40*4)-cell lookup table. // This stateless pure function could be implemented as a (40*4)-cell lookup table.
static int getNumDataCodewords(int ver, Ecc ecl) { static int getNumDataCodewords(int ver, Ecc ecl) {
if (ver < MIN_VERSION || ver > MAX_VERSION) if (ver < 1 || ver > 40)
throw new IllegalArgumentException("Version number out of range"); throw new IllegalArgumentException("Version number out of range");
return getNumRawDataModules(ver) / 8 return getNumRawDataModules(ver) / 8
- ECC_CODEWORDS_PER_BLOCK[ecl.ordinal()][ver] - ECC_CODEWORDS_PER_BLOCK[ecl.ordinal()][ver]
@ -839,5 +894,4 @@ public final class QrCode {
} }
} }
} }

Loading…
Cancel
Save