diff options
-rw-r--r-- | cmd/label-tool/main.go | 50 | ||||
-rw-r--r-- | label/label.go | 87 |
2 files changed, 123 insertions, 14 deletions
diff --git a/cmd/label-tool/main.go b/cmd/label-tool/main.go index 15fb68d..1e5ab4a 100644 --- a/cmd/label-tool/main.go +++ b/cmd/label-tool/main.go @@ -38,7 +38,7 @@ var tmplForm = template.Must(template.New("form").Parse(` <img border=1 src='?font={{ .FontIndex }}&scale={{ .Scale }}{{/* */}}&text={{ .Text }}&render'> </td> -<td valign=top> +<td valign=top><form> <fieldset> {{ if .Printer }} @@ -71,18 +71,26 @@ var tmplForm = template.Must(template.New("form").Parse(` {{ end }} </fieldset> <fieldset> - <p>Font: {{ .Font.Name }} <a href='?'>Change</a> - </fieldset> - <form><fieldset> - <input type=hidden name=font value='{{ .FontIndex }}'> - <p><label for=text>Text:</label> - <input id=text name=text value='{{.Text}}'> - <label for=scale>Scale:</label> + <legend>Font</legend> + <p>{{ .Font.Name }} <a href='?'>Change</a> + <input type=hidden name=font value='{{ .FontIndex }}'> + <p><label for=scale>Scale:</label> <input id=scale name=scale value='{{.Scale}}' size=1> + </fieldset> + <fieldset> + <legend>Label</legend> + <p><textarea name=text>{{.Text}}</textarea> + <p>Kind: + <input type=radio id=kind-text name=kind value=text + {{ if eq .Kind "text" }} checked{{ end }}> + <label for=kind-text>plain text (horizontal)</label> + <input type=radio id=kind-qr name=kind value=qr + {{ if eq .Kind "qr" }} checked{{ end }}> + <label for=kind-qr>QR code (vertical)</label> <p><input type=submit value='Update'> <input type=submit name=print value='Update and Print'> - </fieldset></form> -</td> + </fieldset> +</form></td> </tr></table> </body></html> `)) @@ -130,7 +138,9 @@ func handle(w http.ResponseWriter, r *http.Request) { font = fonts[fontIndex] } else { w.Header().Set("Content-Type", "text/html") - tmplFont.Execute(w, fonts) + if err := tmplFont.Execute(w, fonts); err != nil { + http.Error(w, err.Error(), 500) + } return } @@ -170,6 +180,7 @@ func handle(w http.ResponseWriter, r *http.Request) { FontIndex int Text string Scale int + Kind string }{ Printer: printer, PrinterErr: printerErr, @@ -178,17 +189,26 @@ func handle(w http.ResponseWriter, r *http.Request) { Font: font.Font, FontIndex: fontIndex, Text: r.FormValue("text"), + Kind: r.FormValue("kind"), } params.Scale, err = strconv.Atoi(r.FormValue("scale")) if err != nil { params.Scale = 3 } + if params.Kind == "" { + params.Kind = "text" + } var img image.Image if mediaInfo != nil { - img = &imgutil.LeftRotate{Image: label.GenLabelForHeight( - font.Font, params.Text, mediaInfo.PrintAreaPins, params.Scale)} + if params.Kind == "qr" { + img = &imgutil.LeftRotate{Image: label.GenLabelForHeight( + font.Font, params.Text, mediaInfo.PrintAreaPins, params.Scale)} + } else { + img = label.GenLabelForWidth( + font.Font, params.Text, mediaInfo.PrintAreaPins, params.Scale) + } if r.FormValue("print") != "" { if err := printer.Print(img); err != nil { log.Println("print error:", err) @@ -198,7 +218,9 @@ func handle(w http.ResponseWriter, r *http.Request) { if _, ok := r.Form["render"]; !ok { w.Header().Set("Content-Type", "text/html") - tmplForm.Execute(w, ¶ms) + if err := tmplForm.Execute(w, ¶ms); err != nil { + http.Error(w, err.Error(), 500) + } return } diff --git a/label/label.go b/label/label.go new file mode 100644 index 0000000..062b072 --- /dev/null +++ b/label/label.go @@ -0,0 +1,87 @@ +package label + +import ( + "image" + "image/draw" + "strings" + + "janouch.name/sklad/bdf" + "janouch.name/sklad/imgutil" + + "github.com/boombuler/barcode" + "github.com/boombuler/barcode/qr" +) + +// TODO: Rename to GenQRLabelForHeight. +func GenLabelForHeight(font *bdf.Font, + text string, height, scale int) image.Image { + // Create a scaled bitmap of the text label. + textRect, _ := font.BoundString(text) + textImg := image.NewRGBA(textRect) + draw.Draw(textImg, textRect, image.White, image.ZP, draw.Src) + font.DrawString(textImg, image.ZP, text) + + scaledTextImg := imgutil.Scale{Image: textImg, Scale: scale} + scaledTextRect := scaledTextImg.Bounds() + + remains := height - scaledTextRect.Dy() - 20 + + width := scaledTextRect.Dx() + if remains > width { + width = remains + } + + // Create a scaled bitmap of the QR code. + qrImg, _ := qr.Encode(text, qr.H, qr.Auto) + qrImg, _ = barcode.Scale(qrImg, remains, remains) + qrRect := qrImg.Bounds() + + // Combine. + combinedRect := image.Rect(0, 0, width, height) + combinedImg := image.NewRGBA(combinedRect) + draw.Draw(combinedImg, combinedRect, image.White, image.ZP, draw.Src) + draw.Draw(combinedImg, + combinedRect.Add(image.Point{X: (width - qrRect.Dx()) / 2, Y: 0}), + qrImg, image.ZP, draw.Src) + + target := image.Rect( + (width-scaledTextRect.Dx())/2, qrRect.Dy()+20, + combinedRect.Max.X, combinedRect.Max.Y) + draw.Draw(combinedImg, target, &scaledTextImg, scaledTextRect.Min, draw.Src) + return combinedImg +} + +func GenLabelForWidth(font *bdf.Font, + text string, width, scale int) image.Image { + var lines []string + for _, line := range strings.Split(text, "\n") { + lines = append(lines, strings.TrimSuffix(line, "\r")) + } + + height := 0 + var rects []image.Rectangle + for _, line := range lines { + r, _ := font.BoundString(line) + rects = append(rects, r) + height += r.Dy() * scale + } + + imgRect := image.Rect(0, 0, width, height) + img := image.NewRGBA(imgRect) + draw.Draw(img, imgRect, image.White, image.ZP, draw.Src) + + y := 0 + for i := 0; i < len(lines); i++ { + textImg := image.NewRGBA(rects[i]) + draw.Draw(textImg, rects[i], image.White, image.ZP, draw.Src) + font.DrawString(textImg, image.ZP, lines[i]) + + scaledImg := imgutil.Scale{Image: textImg, Scale: scale} + scaledRect := scaledImg.Bounds() + + target := image.Rect(0, y, imgRect.Max.X, imgRect.Max.Y) + draw.Draw(img, target, &scaledImg, scaledRect.Min, draw.Src) + y += scaledRect.Dy() + } + return img +} |