label-tool: make it possible to print free form text

Also commit the label subpackage that we forgot to.
This commit is contained in:
Přemysl Eric Janouch 2019-04-25 21:30:15 +02:00
parent 154f3147e3
commit 2f47b3f5da
Signed by: p
GPG Key ID: A0420B94F92B9493
2 changed files with 123 additions and 14 deletions

View File

@ -38,7 +38,7 @@ var tmplForm = template.Must(template.New("form").Parse(`
<img border=1 src='?font={{ .FontIndex }}&amp;scale={{ .Scale }}{{/* <img border=1 src='?font={{ .FontIndex }}&amp;scale={{ .Scale }}{{/*
*/}}&amp;text={{ .Text }}&amp;render'> */}}&amp;text={{ .Text }}&amp;render'>
</td> </td>
<td valign=top> <td valign=top><form>
<fieldset> <fieldset>
{{ if .Printer }} {{ if .Printer }}
@ -71,18 +71,26 @@ var tmplForm = template.Must(template.New("form").Parse(`
{{ end }} {{ end }}
</fieldset> </fieldset>
<fieldset> <fieldset>
<p>Font: {{ .Font.Name }} <a href='?'>Change</a> <legend>Font</legend>
</fieldset> <p>{{ .Font.Name }} <a href='?'>Change</a>
<form><fieldset> <input type=hidden name=font value='{{ .FontIndex }}'>
<input type=hidden name=font value='{{ .FontIndex }}'> <p><label for=scale>Scale:</label>
<p><label for=text>Text:</label>
<input id=text name=text value='{{.Text}}'>
<label for=scale>Scale:</label>
<input id=scale name=scale value='{{.Scale}}' size=1> <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'> <p><input type=submit value='Update'>
<input type=submit name=print value='Update and Print'> <input type=submit name=print value='Update and Print'>
</fieldset></form> </fieldset>
</td> </form></td>
</tr></table> </tr></table>
</body></html> </body></html>
`)) `))
@ -130,7 +138,9 @@ func handle(w http.ResponseWriter, r *http.Request) {
font = fonts[fontIndex] font = fonts[fontIndex]
} else { } else {
w.Header().Set("Content-Type", "text/html") 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 return
} }
@ -170,6 +180,7 @@ func handle(w http.ResponseWriter, r *http.Request) {
FontIndex int FontIndex int
Text string Text string
Scale int Scale int
Kind string
}{ }{
Printer: printer, Printer: printer,
PrinterErr: printerErr, PrinterErr: printerErr,
@ -178,17 +189,26 @@ func handle(w http.ResponseWriter, r *http.Request) {
Font: font.Font, Font: font.Font,
FontIndex: fontIndex, FontIndex: fontIndex,
Text: r.FormValue("text"), Text: r.FormValue("text"),
Kind: r.FormValue("kind"),
} }
params.Scale, err = strconv.Atoi(r.FormValue("scale")) params.Scale, err = strconv.Atoi(r.FormValue("scale"))
if err != nil { if err != nil {
params.Scale = 3 params.Scale = 3
} }
if params.Kind == "" {
params.Kind = "text"
}
var img image.Image var img image.Image
if mediaInfo != nil { if mediaInfo != nil {
img = &imgutil.LeftRotate{Image: label.GenLabelForHeight( if params.Kind == "qr" {
font.Font, params.Text, mediaInfo.PrintAreaPins, params.Scale)} 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 r.FormValue("print") != "" {
if err := printer.Print(img); err != nil { if err := printer.Print(img); err != nil {
log.Println("print error:", err) log.Println("print error:", err)
@ -198,7 +218,9 @@ func handle(w http.ResponseWriter, r *http.Request) {
if _, ok := r.Form["render"]; !ok { if _, ok := r.Form["render"]; !ok {
w.Header().Set("Content-Type", "text/html") w.Header().Set("Content-Type", "text/html")
tmplForm.Execute(w, &params) if err := tmplForm.Execute(w, &params); err != nil {
http.Error(w, err.Error(), 500)
}
return return
} }

87
label/label.go Normal file
View File

@ -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
}