diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/PlasticBagPrinterService.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/PlasticBagPrinterService.kt
index 5fa18b0..b8b6d8a 100644
--- a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/PlasticBagPrinterService.kt
+++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/PlasticBagPrinterService.kt
@@ -7,6 +7,8 @@ import org.springframework.stereotype.Service
import java.awt.Color
import java.awt.Font
+import java.awt.Graphics2D
+import java.awt.RenderingHints
import java.awt.image.BufferedImage
import java.io.ByteArrayOutputStream
import java.util.zip.ZipEntry
@@ -20,6 +22,9 @@ import java.io.PrintWriter
import java.io.DataOutputStream
import java.nio.charset.Charset
+// 1. Data class to store both the raw bytes and the width for XML injection
+data class BitmapResult(val bytes: ByteArray, val width: Int)
+
@Service
open class PlasticBagPrinterService(
val jobOrderRepository: JobOrderRepository,
@@ -28,65 +33,105 @@ open class PlasticBagPrinterService(
val baos = ByteArrayOutputStream()
ZipOutputStream(baos).use { zos ->
- // Use unique names based on the Lot Number
+ // Generate Bitmaps and capture their widths
+ val productBmp = createMonochromeBitmap(productName, 704)
+ val codeBmp = createMonochromeBitmap(itemCode, 1173)
+ val expBmp = createMonochromeBitmap(expiryDate, 1173)
+ val qrBmp = createQrCodeBitmap("$itemCode|$lotNo|$expiryDate", 1000)
+
val nameFile = "${lotNo}_product.bmp"
+ val codeFile = "${lotNo}_code.bmp"
val expFile = "${lotNo}_expiry.bmp"
val qrFile = "${lotNo}_qr.bmp"
- // 1. Generate Bitmaps
- addToZip(zos, nameFile, createMonochromeBitmap(productName, 5365, 704))
- addToZip(zos, expFile, createMonochromeBitmap(expiryDate, 4203, 1173))
- addToZip(zos, qrFile, createQrCodeBitmap("$itemCode|$lotNo|$expiryDate", 1000))
+ // Now "bytes" property is resolved
+ addToZip(zos, nameFile, productBmp.bytes)
+ addToZip(zos, codeFile, codeBmp.bytes)
+ addToZip(zos, expFile, expBmp.bytes)
+ addToZip(zos, qrFile, qrBmp.bytes)
- // 2. Generate the .image file with dynamic references
+ // 2. Generate the .image file with XML headers and mandatory X40 tags
val imageXml = """
+
""".trimIndent()
- addToZip(zos, "$lotNo.image", imageXml.toByteArray())
+ addToZip(zos, "$lotNo.image", imageXml.toByteArray(Charsets.UTF_8))
- // 3. Generate the .job file pointing to the new .image [cite: 2]
- val jobXml = "$lotNo.image"
- addToZip(zos, "$lotNo.job", jobXml.toByteArray())
+ val jobXml = """$lotNo.image"""
+ addToZip(zos, "$lotNo.job", jobXml.toByteArray(Charsets.UTF_8))
}
return baos.toByteArray()
}
- private fun createMonochromeBitmap(text: String, width: Int, height: Int): ByteArray {
- val image = BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY) // Essential for printers
- val g = image.createGraphics()
- g.color = Color.WHITE
- g.fillRect(0, 0, width, height)
- g.color = Color.BLACK
- g.font = Font("Arial", Font.BOLD, 400)
- g.drawString(text, 50, height - 200)
- g.dispose()
+ private fun createMonochromeBitmap(text: String, maxHeight: Int): BitmapResult {
+ val tempImg = BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY)
+ val g2dTemp = tempImg.createGraphics()
+ val font = Font("SimSun", Font.BOLD, (maxHeight * 0.8).toInt())
+ g2dTemp.font = font
+ val metrics = g2dTemp.getFontMetrics(font)
+
+ val width = metrics.stringWidth(text).let { if (it < 1) 1 else it }
+ val height = maxHeight
+ g2dTemp.dispose()
+
+ val finalImg = BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY)
+ val g2d = finalImg.createGraphics()
+ g2d.color = Color.WHITE
+ g2d.fillRect(0, 0, width, height)
+ g2d.color = Color.BLACK
+ g2d.font = font
+ g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)
+ g2d.drawString(text, 0, metrics.ascent)
+ g2d.dispose()
val baos = ByteArrayOutputStream()
- ImageIO.write(image, "bmp", baos)
- return baos.toByteArray()
+ ImageIO.write(finalImg, "bmp", baos)
+ return BitmapResult(baos.toByteArray(), width)
}
- private fun createQrCodeBitmap(content: String, size: Int): ByteArray {
- val bitMatrix = QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, size, size)
+ private fun createQrCodeBitmap(content: String, size: Int): BitmapResult {
+ val writer = QRCodeWriter()
+ val bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, size, size)
val image = BufferedImage(size, size, BufferedImage.TYPE_BYTE_BINARY)
for (x in 0 until size) {
for (y in 0 until size) {
@@ -95,11 +140,13 @@ open class PlasticBagPrinterService(
}
val baos = ByteArrayOutputStream()
ImageIO.write(image, "bmp", baos)
- return baos.toByteArray()
+ // For QR code, width and height are the same (size)
+ return BitmapResult(baos.toByteArray(), size)
}
- private fun addToZip(zos: ZipOutputStream, fileName: String, content: ByteArray) {
- zos.putNextEntry(ZipEntry(fileName))
+ private fun addToZip(zos: ZipOutputStream, entryName: String, content: ByteArray) {
+ val entry = ZipEntry(entryName)
+ zos.putNextEntry(entry)
zos.write(content)
zos.closeEntry()
}