mirror of
https://github.com/cwinfo/matterbridge.git
synced 2024-11-10 14:30:26 +00:00
154 lines
3.8 KiB
Go
154 lines
3.8 KiB
Go
|
package qrterminal
|
||
|
|
||
|
import (
|
||
|
"io"
|
||
|
"strings"
|
||
|
|
||
|
"rsc.io/qr"
|
||
|
)
|
||
|
|
||
|
const WHITE = "\033[47m \033[0m"
|
||
|
const BLACK = "\033[40m \033[0m"
|
||
|
|
||
|
// Use ascii blocks to form the QR Code
|
||
|
const BLACK_WHITE = "▄"
|
||
|
const BLACK_BLACK = " "
|
||
|
const WHITE_BLACK = "▀"
|
||
|
const WHITE_WHITE = "█"
|
||
|
|
||
|
// Level - the QR Code's redundancy level
|
||
|
const H = qr.H
|
||
|
const M = qr.M
|
||
|
const L = qr.L
|
||
|
|
||
|
// default is 4-pixel-wide white quiet zone
|
||
|
const QUIET_ZONE = 4
|
||
|
|
||
|
//Config for generating a barcode
|
||
|
type Config struct {
|
||
|
Level qr.Level
|
||
|
Writer io.Writer
|
||
|
HalfBlocks bool
|
||
|
BlackChar string
|
||
|
BlackWhiteChar string
|
||
|
WhiteChar string
|
||
|
WhiteBlackChar string
|
||
|
QuietZone int
|
||
|
}
|
||
|
|
||
|
func (c *Config) writeFullBlocks(w io.Writer, code *qr.Code) {
|
||
|
white := c.WhiteChar
|
||
|
black := c.BlackChar
|
||
|
|
||
|
// Frame the barcode in a 1 pixel border
|
||
|
w.Write([]byte(stringRepeat(stringRepeat(white,
|
||
|
code.Size+c.QuietZone*2)+"\n", c.QuietZone))) // top border
|
||
|
for i := 0; i <= code.Size; i++ {
|
||
|
w.Write([]byte(stringRepeat(white, c.QuietZone))) // left border
|
||
|
for j := 0; j <= code.Size; j++ {
|
||
|
if code.Black(j, i) {
|
||
|
w.Write([]byte(black))
|
||
|
} else {
|
||
|
w.Write([]byte(white))
|
||
|
}
|
||
|
}
|
||
|
w.Write([]byte(stringRepeat(white, c.QuietZone-1) + "\n")) // right border
|
||
|
}
|
||
|
w.Write([]byte(stringRepeat(stringRepeat(white,
|
||
|
code.Size+c.QuietZone*2)+"\n", c.QuietZone-1))) // bottom border
|
||
|
}
|
||
|
|
||
|
func (c *Config) writeHalfBlocks(w io.Writer, code *qr.Code) {
|
||
|
ww := c.WhiteChar
|
||
|
bb := c.BlackChar
|
||
|
wb := c.WhiteBlackChar
|
||
|
bw := c.BlackWhiteChar
|
||
|
// Frame the barcode in a 4 pixel border
|
||
|
// top border
|
||
|
if c.QuietZone%2 != 0 {
|
||
|
w.Write([]byte(stringRepeat(bw, code.Size+c.QuietZone*2) + "\n"))
|
||
|
w.Write([]byte(stringRepeat(stringRepeat(ww,
|
||
|
code.Size+c.QuietZone*2)+"\n", c.QuietZone/2)))
|
||
|
} else {
|
||
|
w.Write([]byte(stringRepeat(stringRepeat(ww,
|
||
|
code.Size+c.QuietZone*2)+"\n", c.QuietZone/2)))
|
||
|
}
|
||
|
for i := 0; i <= code.Size; i += 2 {
|
||
|
w.Write([]byte(stringRepeat(ww, c.QuietZone))) // left border
|
||
|
for j := 0; j <= code.Size; j++ {
|
||
|
next_black := false
|
||
|
if i+1 < code.Size {
|
||
|
next_black = code.Black(j, i+1)
|
||
|
}
|
||
|
curr_black := code.Black(j, i)
|
||
|
if curr_black && next_black {
|
||
|
w.Write([]byte(bb))
|
||
|
} else if curr_black && !next_black {
|
||
|
w.Write([]byte(bw))
|
||
|
} else if !curr_black && !next_black {
|
||
|
w.Write([]byte(ww))
|
||
|
} else {
|
||
|
w.Write([]byte(wb))
|
||
|
}
|
||
|
}
|
||
|
w.Write([]byte(stringRepeat(ww, c.QuietZone-1) + "\n")) // right border
|
||
|
}
|
||
|
// bottom border
|
||
|
if c.QuietZone%2 == 0 {
|
||
|
w.Write([]byte(stringRepeat(stringRepeat(ww,
|
||
|
code.Size+c.QuietZone*2)+"\n", c.QuietZone/2-1)))
|
||
|
w.Write([]byte(stringRepeat(wb, code.Size+c.QuietZone*2) + "\n"))
|
||
|
} else {
|
||
|
w.Write([]byte(stringRepeat(stringRepeat(ww,
|
||
|
code.Size+c.QuietZone*2)+"\n", c.QuietZone/2)))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func stringRepeat(s string, count int) string {
|
||
|
if count <= 0 {
|
||
|
return ""
|
||
|
}
|
||
|
return strings.Repeat(s, count)
|
||
|
}
|
||
|
|
||
|
// GenerateWithConfig expects a string to encode and a config
|
||
|
func GenerateWithConfig(text string, config Config) {
|
||
|
if config.QuietZone < 1 {
|
||
|
config.QuietZone = 1 // at least 1-pixel-wide white quiet zone
|
||
|
}
|
||
|
w := config.Writer
|
||
|
code, _ := qr.Encode(text, config.Level)
|
||
|
if config.HalfBlocks {
|
||
|
config.writeHalfBlocks(w, code)
|
||
|
} else {
|
||
|
config.writeFullBlocks(w, code)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Generate a QR Code and write it out to io.Writer
|
||
|
func Generate(text string, l qr.Level, w io.Writer) {
|
||
|
config := Config{
|
||
|
Level: l,
|
||
|
Writer: w,
|
||
|
BlackChar: BLACK,
|
||
|
WhiteChar: WHITE,
|
||
|
QuietZone: QUIET_ZONE,
|
||
|
}
|
||
|
GenerateWithConfig(text, config)
|
||
|
}
|
||
|
|
||
|
// Generate a QR Code with half blocks and write it out to io.Writer
|
||
|
func GenerateHalfBlock(text string, l qr.Level, w io.Writer) {
|
||
|
config := Config{
|
||
|
Level: l,
|
||
|
Writer: w,
|
||
|
HalfBlocks: true,
|
||
|
BlackChar: BLACK_BLACK,
|
||
|
WhiteBlackChar: WHITE_BLACK,
|
||
|
WhiteChar: WHITE_WHITE,
|
||
|
BlackWhiteChar: BLACK_WHITE,
|
||
|
QuietZone: QUIET_ZONE,
|
||
|
}
|
||
|
GenerateWithConfig(text, config)
|
||
|
}
|