package io.rudefox.cold; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.WriterException; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.QRCodeWriter; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; class QRCode { private static final String FALLBACK_SET_STRING = "##"; static String toQRCode(String data) { QRCodeWriter qrCodeWriter = new QRCodeWriter(); Map hints = new HashMap<>(); hints.put(EncodeHintType.MARGIN, 0); hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); BitMatrix bitMatrix = null; try { bitMatrix = qrCodeWriter.encode(data, BarcodeFormat.QR_CODE, 0, 0, hints); } catch (WriterException e) { e.printStackTrace(); } if (bitMatrix == null) return "[Error Generating QR Code]"; if (charsetDoesNotSupportFullBlockChar()) return bitMatrix.toString(FALLBACK_SET_STRING, " "); return toUTF8(bitMatrix); } private static String toUTF8(BitMatrix bitMatrix) { char SPACE = '\u0020'; char LOWER_BLOCK = '\u2584'; char UPPER_BLOCK = '\u2580'; char FULL_BLOCK = '\u2588'; int[] blockCodepoints = new int[] {SPACE, LOWER_BLOCK, UPPER_BLOCK, FULL_BLOCK}; StringBuilder qrCode = new StringBuilder(); for (int y = 0; y < bitMatrix.getHeight(); y += 2) { for (int x = 0; x < bitMatrix.getWidth(); x++) { int upper_bit = bitMatrix.get(x, y) ? 1 : 0; int lower_bit = y+1 < bitMatrix.getHeight() && bitMatrix.get(x, y+1) ? 1 : 0; int index = upper_bit << 1 | lower_bit; int blockCodepoint = blockCodepoints[index]; qrCode.appendCodePoint(blockCodepoint); } if (y < bitMatrix.getHeight() - 1) qrCode.append("\n"); } return qrCode.toString(); } private static boolean charsetDoesNotSupportFullBlockChar() { Charset charset = ServiceLocator.DEFAULT_CHARSET; String charsetString = charset.toString(); return charset.equals(StandardCharsets.ISO_8859_1) || charset.equals(StandardCharsets.US_ASCII) || charsetString.equalsIgnoreCase("euc-jp") || charsetString.equalsIgnoreCase("euc-kr") || charsetString.equalsIgnoreCase("iso-2022-jp") || charsetString.equalsIgnoreCase("iso-8859-10") || charsetString.equalsIgnoreCase("iso-8859-13") || charsetString.equalsIgnoreCase("iso-8859-14") || charsetString.equalsIgnoreCase("iso-8859-15") || charsetString.equalsIgnoreCase("iso-8859-16") || charsetString.equalsIgnoreCase("iso-8859-2") || charsetString.equalsIgnoreCase("iso-8859-3") || charsetString.equalsIgnoreCase("iso-8859-4") || charsetString.equalsIgnoreCase("iso-8859-5") || charsetString.equalsIgnoreCase("iso-8859-6") || charsetString.equalsIgnoreCase("iso-8859-7") || charsetString.equalsIgnoreCase("iso-8859-8") || charsetString.equalsIgnoreCase("iso-8859-8-i") || charsetString.equalsIgnoreCase("macintosh") || charsetString.equalsIgnoreCase("shift_jis") || charsetString.equalsIgnoreCase("windows-1250") || charsetString.equalsIgnoreCase("windows-1251") || charsetString.equalsIgnoreCase("windows-1252") || charsetString.equalsIgnoreCase("windows-1253") || charsetString.equalsIgnoreCase("windows-1254") || charsetString.equalsIgnoreCase("windows-1255") || charsetString.equalsIgnoreCase("windows-1256") || charsetString.equalsIgnoreCase("windows-1257") || charsetString.equalsIgnoreCase("windows-1258") || charsetString.equalsIgnoreCase("windows-874") || charsetString.equalsIgnoreCase("x-mac-cyrillic") || charsetString.equalsIgnoreCase("x-user-defined"); } }