add printer
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -25,3 +25,4 @@ go.work.sum
|
||||
# env file
|
||||
.env
|
||||
|
||||
build
|
||||
39
build_lib.sh
Executable file
39
build_lib.sh
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
|
||||
export PATH=$HOME/apps/go1.22.12/bin:$PATH
|
||||
go version
|
||||
|
||||
# need Android NDK
|
||||
NDK_HOME="$HOME/Android/Sdk/ndk/28.2.13676358" # <--- CHECK YOUR VERSION
|
||||
API=21
|
||||
|
||||
TOOLCHAIN="$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin"
|
||||
|
||||
echo "Building for Android x86_64..."
|
||||
CC="$TOOLCHAIN/x86_64-linux-android$API-clang" \
|
||||
CGO_ENABLED=1 GOOS=android GOARCH=amd64 \
|
||||
go build -buildmode=c-shared -o ./build/libgofunc_x64.so .
|
||||
|
||||
echo "Building for Android ARM64..."
|
||||
CC="$TOOLCHAIN/aarch64-linux-android$API-clang" \
|
||||
CGO_ENABLED=1 GOOS=android GOARCH=arm64 \
|
||||
go build -buildmode=c-shared -o ./build/libgofunc_arm64.so .
|
||||
|
||||
echo "Building for Android ARMv7..."
|
||||
CC="$TOOLCHAIN/armv7a-linux-androideabi$API-clang" \
|
||||
CGO_ENABLED=1 GOOS=android GOARCH=arm GOARM=7 \
|
||||
go build -buildmode=c-shared -o ./build/libgofunc_armv7a.so .
|
||||
|
||||
|
||||
# echo "Building for iOS ARM64..."
|
||||
# CGO_ENABLED=1 GOOS=darwin GOARCH=arm64 \
|
||||
# go build -buildmode=c-archive -o ./libgofunc_arm64.a .
|
||||
|
||||
# cp ./libgofunc_x64.so /home/sainw/ws/forward_pos/android/app/src/main/jniLibs/x86_64/libgofuncso
|
||||
|
||||
cp ./build/libgofunc_x64.so $HOME/ws/forward_pos/native/android/x86_64/libgofunc.so
|
||||
cp ./build/libgofunc_arm64.so $HOME/ws/forward_pos/native/android/arm64-v8a/libgofunc.so
|
||||
cp ./build/libgofunc_armv7a.so $HOME/ws/forward_pos/native/android/armeabi-v7a/libgofunc.so
|
||||
|
||||
|
||||
echo "Done!"
|
||||
192
escpos_printer.go
Normal file
192
escpos_printer.go
Normal file
@@ -0,0 +1,192 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Printer wraps an io.Writer (USB file, TCP conn, etc.)
|
||||
type Printer struct {
|
||||
w io.Writer
|
||||
}
|
||||
|
||||
func NewPrinter(w io.Writer) *Printer {
|
||||
return &Printer{w: w}
|
||||
}
|
||||
|
||||
func (p *Printer) Write(data []byte) error {
|
||||
_, err := p.w.Write(data)
|
||||
return err
|
||||
}
|
||||
|
||||
// Print plain text
|
||||
func (p *Printer) PrintText(text string) error {
|
||||
return p.Write([]byte(text))
|
||||
}
|
||||
|
||||
// New line
|
||||
func (p *Printer) LF(num int) error {
|
||||
for range num {
|
||||
err := p.PrintText("\n")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Bold text ON
|
||||
func (p *Printer) BoldOn() error {
|
||||
return p.Write([]byte{0x1b, 0x45, 0x01})
|
||||
}
|
||||
|
||||
// Bold text OFF
|
||||
func (p *Printer) BoldOff() error {
|
||||
return p.Write([]byte{0x1b, 0x45, 0x00})
|
||||
}
|
||||
|
||||
// Alignment: 0=left, 1=center, 2=right
|
||||
func (p *Printer) Align(n int) error {
|
||||
return p.Write([]byte{0x1b, 0x61, byte(n)})
|
||||
}
|
||||
|
||||
// Cut paper
|
||||
func (p *Printer) Cut() error {
|
||||
return p.Write([]byte{0x1d, 0x56, 0x00})
|
||||
}
|
||||
|
||||
// SelectFont chooses printer's built-in font (0=A, 1=B, 2=C if supported)
|
||||
func (p *Printer) SelectFont(n int) error {
|
||||
return p.Write([]byte{0x1b, 0x4d, byte(n)})
|
||||
}
|
||||
|
||||
// SetFontSize scales text (x, y from 1–8)
|
||||
func (p *Printer) SetFontSize(x, y int) error {
|
||||
n := byte(((y - 1) << 4) | (x - 1))
|
||||
return p.Write([]byte{0x1d, 0x21, n})
|
||||
}
|
||||
|
||||
// Underline: 0=off, 1=thin, 2=thick
|
||||
func (p *Printer) Underline(n int) error {
|
||||
return p.Write([]byte{0x1b, 0x2d, byte(n)})
|
||||
}
|
||||
|
||||
// UpsideDown: 0=off, 1=on
|
||||
func (p *Printer) UpsideDown(n int) error {
|
||||
return p.Write([]byte{0x1b, 0x7b, byte(n)})
|
||||
}
|
||||
|
||||
// SetCharSpacing sets extra spacing between characters
|
||||
func (p *Printer) SetCharSpacing(n int) error {
|
||||
return p.Write([]byte{0x1b, 0x20, byte(n)})
|
||||
}
|
||||
|
||||
// ---------------- IMAGE PRINTING ----------------
|
||||
|
||||
// convert to monochrome
|
||||
func toMonochrome(img image.Image) *image.Gray {
|
||||
bounds := img.Bounds()
|
||||
gray := image.NewGray(bounds)
|
||||
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
|
||||
for x := bounds.Min.X; x < bounds.Max.X; x++ {
|
||||
r, g, b, _ := img.At(x, y).RGBA()
|
||||
grayValue := uint8((r + g + b) / 3 >> 8)
|
||||
if grayValue > 128 {
|
||||
gray.Set(x, y, color.White)
|
||||
} else {
|
||||
gray.Set(x, y, color.Black)
|
||||
}
|
||||
}
|
||||
}
|
||||
return gray
|
||||
}
|
||||
|
||||
// ESC/POS: GS v 0
|
||||
func escposRaster(img *image.Gray) []byte {
|
||||
bounds := img.Bounds()
|
||||
w := bounds.Dx()
|
||||
h := bounds.Dy()
|
||||
|
||||
// Width must be in bytes (8 pixels per byte)
|
||||
wBytes := (w + 7) / 8
|
||||
data := []byte{}
|
||||
|
||||
// ESC/POS raster format: GS v 0 m xL xH yL yH [data]
|
||||
// GS v 0
|
||||
data = append(data, 0x1d, 0x76, 0x30, 0x00)
|
||||
|
||||
// xL, xH
|
||||
data = append(data, byte(wBytes%256), byte(wBytes/256))
|
||||
// yL, yH
|
||||
data = append(data, byte(h%256), byte(h/256))
|
||||
|
||||
// Image data
|
||||
for y := 0; y < h; y++ {
|
||||
for xByte := 0; xByte < wBytes; xByte++ {
|
||||
var b byte
|
||||
for bit := 0; bit < 8; bit++ {
|
||||
x := xByte*8 + bit
|
||||
if x < w {
|
||||
grayColor := img.GrayAt(x, y).Y
|
||||
if grayColor < 128 {
|
||||
// Black pixel = 1
|
||||
b |= (1 << (7 - bit))
|
||||
}
|
||||
}
|
||||
}
|
||||
data = append(data, b)
|
||||
}
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
// PrintImage sends an image using GS v 0 (raster bit image)
|
||||
func (p *Printer) PrintImage(img image.Image) error {
|
||||
gray := toMonochrome(img)
|
||||
data := escposRaster(gray)
|
||||
return p.Write(data)
|
||||
}
|
||||
|
||||
// PrintBarcode prints a CODE128 barcode (most supported)
|
||||
func (p *Printer) PrintBarcode(data string) error {
|
||||
// Select barcode height
|
||||
p.Write([]byte{0x1d, 0x68, 100}) // height in dots
|
||||
// Select barcode width
|
||||
p.Write([]byte{0x1d, 0x77, 2}) // module width (2 = medium)
|
||||
// HRI (human readable interpretation) below barcode
|
||||
p.Write([]byte{0x1d, 0x48, 2})
|
||||
|
||||
// GS k m d1...dk NUL
|
||||
cmd := []byte{0x1d, 0x6b, 73, byte(len(data))} // 73 = CODE128 auto
|
||||
cmd = append(cmd, []byte(data)...)
|
||||
return p.Write(cmd)
|
||||
}
|
||||
|
||||
// ---------------- QR CODE ----------------
|
||||
|
||||
// PrintQRCode prints a QR code
|
||||
func (p *Printer) PrintQRCode(data string, size int, ecLevel byte) error {
|
||||
// size: module size (1–16)
|
||||
// ecLevel: error correction (48=L, 49=M, 50=Q, 51=H)
|
||||
|
||||
// [1] Store QR data
|
||||
storeLen := len(data) + 3
|
||||
cmdStore := []byte{0x1d, 0x28, 0x6b, byte(storeLen % 256), byte(storeLen / 256), 49, 80, 48}
|
||||
cmdStore = append(cmdStore, []byte(data)...)
|
||||
|
||||
// [2] Set module size
|
||||
cmdSize := []byte{0x1d, 0x28, 0x6b, 3, 0, 49, 67, byte(size)}
|
||||
|
||||
// [3] Set error correction level
|
||||
cmdErr := []byte{0x1d, 0x28, 0x6b, 3, 0, 49, 69, ecLevel}
|
||||
|
||||
// [4] Print
|
||||
cmdPrint := []byte{0x1d, 0x28, 0x6b, 3, 0, 49, 81, 48}
|
||||
|
||||
p.Write(cmdSize)
|
||||
p.Write(cmdErr)
|
||||
p.Write(cmdStore)
|
||||
return p.Write(cmdPrint)
|
||||
}
|
||||
16
go.mod
Normal file
16
go.mod
Normal file
@@ -0,0 +1,16 @@
|
||||
module libgofunc
|
||||
|
||||
go 1.22.0
|
||||
|
||||
require (
|
||||
github.com/dlclark/regexp2 v1.11.5
|
||||
github.com/fogleman/gg v1.3.0
|
||||
github.com/kenshaw/escpos v0.0.0-20221114190919-df06b682a8fc
|
||||
golang.org/x/image v0.24.0
|
||||
golang.org/x/net v0.34.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
)
|
||||
14
go.sum
Normal file
14
go.sum
Normal file
@@ -0,0 +1,14 @@
|
||||
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
|
||||
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
|
||||
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/kenshaw/escpos v0.0.0-20221114190919-df06b682a8fc h1:4JwmN2Scz1vR+hfSxkdy2IE/DzxX2Cftm2lhWHyN0k0=
|
||||
github.com/kenshaw/escpos v0.0.0-20221114190919-df06b682a8fc/go.mod h1:M+GIBmg2MqaSWIJrXCZS+/wRFbr9fOguRz3SHn8DRPE=
|
||||
golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ=
|
||||
golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8=
|
||||
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
||||
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
317
img.go
Normal file
317
img.go
Normal file
@@ -0,0 +1,317 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"C"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"image"
|
||||
_ "image/png"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"embed"
|
||||
|
||||
"github.com/fogleman/gg"
|
||||
"golang.org/x/image/font"
|
||||
"golang.org/x/image/font/opentype"
|
||||
"golang.org/x/net/html"
|
||||
|
||||
"encoding/json"
|
||||
|
||||
"github.com/kenshaw/escpos"
|
||||
)
|
||||
|
||||
const (
|
||||
canvasWidth = 550
|
||||
padding = 5
|
||||
lineGap = 12
|
||||
)
|
||||
|
||||
//go:embed static/*
|
||||
var fontFs embed.FS
|
||||
|
||||
//export GenPNG
|
||||
func GenPNG(outputPath *C.char, payload *C.char, tmpl *C.char) *C.char {
|
||||
goPath := C.GoString(outputPath)
|
||||
goPayload := C.GoString(payload)
|
||||
goTmpl := C.GoString(tmpl)
|
||||
|
||||
data := make(map[string]interface{})
|
||||
err := json.Unmarshal([]byte(goPayload), &data)
|
||||
if err != nil {
|
||||
return NewErr(err)
|
||||
}
|
||||
|
||||
htmlStr, err := renderTemplate(goTmpl, data)
|
||||
if err != nil {
|
||||
return NewErr(err)
|
||||
}
|
||||
|
||||
htmlStr = uni2zg(htmlStr)
|
||||
root, err := html.Parse(strings.NewReader(htmlStr))
|
||||
if err != nil {
|
||||
return NewErr(err)
|
||||
}
|
||||
|
||||
fontBytes, err := fontFs.ReadFile("static/Zawgyi-One.ttf")
|
||||
if err != nil {
|
||||
return NewErr(err)
|
||||
}
|
||||
ttfFont, err := opentype.Parse(fontBytes)
|
||||
if err != nil {
|
||||
return NewErr(err)
|
||||
}
|
||||
|
||||
face, err := opentype.NewFace(ttfFont, &opentype.FaceOptions{
|
||||
Size: 24,
|
||||
DPI: 72,
|
||||
Hinting: font.HintingFull,
|
||||
})
|
||||
if err != nil {
|
||||
return NewErr(err)
|
||||
}
|
||||
|
||||
// First pass: compute required height
|
||||
dummyDC := gg.NewContext(canvasWidth, 150)
|
||||
dummyDC.SetFontFace(face)
|
||||
bodyNode := findNode(root, "body")
|
||||
if bodyNode == nil {
|
||||
bodyNode = root
|
||||
}
|
||||
|
||||
computedHeight := computeHeight(bodyNode, padding, dummyDC, face)
|
||||
|
||||
// Second pass: actual rendering
|
||||
dc := gg.NewContext(canvasWidth, computedHeight+50)
|
||||
dc.SetRGB(1, 1, 1)
|
||||
dc.Clear()
|
||||
dc.SetFontFace(face)
|
||||
|
||||
y := padding
|
||||
renderNode(dc, bodyNode, &y, face)
|
||||
|
||||
err = dc.SavePNG(goPath)
|
||||
if err != nil {
|
||||
return NewErr(err)
|
||||
}
|
||||
|
||||
// PrintReceipt(goPath)
|
||||
return NewOk(nil)
|
||||
}
|
||||
|
||||
func renderTemplate(tmp string, data map[string]interface{}) (string, error) {
|
||||
tmpl := template.Must(template.New("mytemplate").Parse(tmp))
|
||||
var buf bytes.Buffer
|
||||
if err := tmpl.Execute(&buf, data); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func renderNode(dc *gg.Context, n *html.Node, y *int, face font.Face) {
|
||||
if n.Type == html.ElementNode {
|
||||
switch n.Data {
|
||||
case "h1":
|
||||
drawTextBlock(dc, getText(n), 28, y, face)
|
||||
case "p":
|
||||
drawTextBlock(dc, getText(n), 24, y, face)
|
||||
case "img":
|
||||
drawImage(dc, n, y)
|
||||
case "table":
|
||||
renderTable(dc, n, y, face)
|
||||
}
|
||||
}
|
||||
|
||||
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||
renderNode(dc, c, y, face)
|
||||
}
|
||||
}
|
||||
|
||||
func drawTextBlock(dc *gg.Context, text string, size float64, y *int, face font.Face) {
|
||||
dc.SetFontFace(face)
|
||||
lines := wordWrap(dc, text, canvasWidth-padding*2)
|
||||
for _, line := range lines {
|
||||
dc.SetRGB(0, 0, 0)
|
||||
dc.DrawString(line, padding, float64(*y))
|
||||
*y += int(size) + lineGap
|
||||
}
|
||||
*y += 5
|
||||
}
|
||||
|
||||
func wordWrap(dc *gg.Context, text string, maxWidth int) []string {
|
||||
words := strings.Fields(text)
|
||||
if len(words) == 0 {
|
||||
return []string{}
|
||||
}
|
||||
var lines []string
|
||||
current := words[0]
|
||||
for _, w := range words[1:] {
|
||||
test := current + " " + w
|
||||
wWidth, _ := dc.MeasureString(test)
|
||||
if int(wWidth) > maxWidth {
|
||||
lines = append(lines, current)
|
||||
current = w
|
||||
} else {
|
||||
current = test
|
||||
}
|
||||
}
|
||||
lines = append(lines, current)
|
||||
return lines
|
||||
}
|
||||
|
||||
func drawImage(dc *gg.Context, n *html.Node, y *int) {
|
||||
src := getAttr(n, "src")
|
||||
file, err := os.Open(src)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
img, _, _ := image.Decode(file)
|
||||
widthStr := getAttr(n, "width")
|
||||
if widthStr != "" {
|
||||
w, _ := strconv.Atoi(widthStr)
|
||||
scale := float64(w) / float64(img.Bounds().Dx())
|
||||
dc.Push()
|
||||
dc.Scale(scale, scale)
|
||||
dc.DrawImage(img, padding, *y)
|
||||
dc.Pop()
|
||||
*y += int(float64(img.Bounds().Dy()) * scale)
|
||||
} else {
|
||||
dc.DrawImage(img, padding, *y)
|
||||
*y += img.Bounds().Dy()
|
||||
}
|
||||
*y += 10
|
||||
}
|
||||
|
||||
func renderTable(dc *gg.Context, table *html.Node, y *int, face font.Face) {
|
||||
rows := extractRows(table)
|
||||
if len(rows) == 0 {
|
||||
return
|
||||
}
|
||||
colCount := len(rows[0])
|
||||
cellWidth := (canvasWidth - padding*2) / colCount
|
||||
dc.SetFontFace(face)
|
||||
for _, row := range rows {
|
||||
x := padding
|
||||
for _, cell := range row {
|
||||
dc.DrawRectangle(float64(x), float64(*y), float64(cellWidth), 30)
|
||||
dc.Stroke()
|
||||
dc.SetRGB(0, 0, 0)
|
||||
dc.DrawString(cell, float64(x+8), float64(*y+20))
|
||||
x += cellWidth
|
||||
}
|
||||
*y += 30
|
||||
}
|
||||
*y += 10
|
||||
}
|
||||
|
||||
func extractRows(table *html.Node) [][]string {
|
||||
var rows [][]string
|
||||
var traverse func(*html.Node)
|
||||
traverse = func(n *html.Node) {
|
||||
if n.Type == html.ElementNode && n.Data == "tr" {
|
||||
var row []string
|
||||
for td := n.FirstChild; td != nil; td = td.NextSibling {
|
||||
if td.Type == html.ElementNode && (td.Data == "td" || td.Data == "th") {
|
||||
row = append(row, getText(td))
|
||||
}
|
||||
}
|
||||
if len(row) > 0 {
|
||||
rows = append(rows, row)
|
||||
}
|
||||
}
|
||||
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||
traverse(c)
|
||||
}
|
||||
}
|
||||
traverse(table)
|
||||
return rows
|
||||
}
|
||||
|
||||
func getText(n *html.Node) string {
|
||||
if n == nil {
|
||||
return ""
|
||||
}
|
||||
if n.Type == html.TextNode {
|
||||
return strings.TrimSpace(n.Data)
|
||||
}
|
||||
var buf strings.Builder
|
||||
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||
buf.WriteString(getText(c))
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func getAttr(n *html.Node, key string) string {
|
||||
for _, a := range n.Attr {
|
||||
if a.Key == key {
|
||||
return a.Val
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func findNode(n *html.Node, tag string) *html.Node {
|
||||
if n.Type == html.ElementNode && n.Data == tag {
|
||||
return n
|
||||
}
|
||||
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||
if res := findNode(c, tag); res != nil {
|
||||
return res
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func computeHeight(n *html.Node, currentY int, dc *gg.Context, face font.Face) int {
|
||||
y := currentY
|
||||
if n.Type == html.ElementNode {
|
||||
switch n.Data {
|
||||
case "h1":
|
||||
dc.SetFontFace(face)
|
||||
lines := wordWrap(dc, getText(n), canvasWidth-padding*2)
|
||||
y += len(lines)*28 + len(lines)*lineGap + 5
|
||||
case "p":
|
||||
dc.SetFontFace(face)
|
||||
lines := wordWrap(dc, getText(n), canvasWidth-padding*2)
|
||||
y += len(lines)*18 + len(lines)*lineGap + 5
|
||||
case "table":
|
||||
rows := extractRows(n)
|
||||
y += len(rows)*30 + 10
|
||||
case "img":
|
||||
widthStr := getAttr(n, "width")
|
||||
h := 100
|
||||
if widthStr != "" {
|
||||
h = 100
|
||||
}
|
||||
y += h + 10
|
||||
}
|
||||
}
|
||||
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||
y = computeHeight(c, y, dc, face)
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
func printImg(prt *escpos.Escpos, imgPath string) error {
|
||||
imgFile, err := os.Open(imgPath)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
img, _, err := image.Decode(imgFile)
|
||||
defer imgFile.Close()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
gray := toMonochrome(img)
|
||||
data := escposRaster(gray)
|
||||
|
||||
_, err = prt.WriteRaw(data)
|
||||
return err
|
||||
}
|
||||
43
main.go
Normal file
43
main.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"C"
|
||||
"fmt"
|
||||
_ "image/png"
|
||||
)
|
||||
|
||||
func main() {
|
||||
payload := `{"Name":"Ko Myo","Amount":3000}`
|
||||
const temp = `
|
||||
<table>
|
||||
<tr>
|
||||
<th><img src="static/logo.png" width="80"/></th>
|
||||
<th><h1 style="font-size:28">မြန်မာစာသည်တို့စာ (Invoice)</h1></th>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>မင်္ဂလာပါ {{.Name}}, သင်၏ အိုင်ဗွိုင်းစိန်း အချက်အလက်များပါသည်။</p>
|
||||
<p>အထက်ပါ အကွက်နှစ်ကွက်ကတော့ အချိန်နဲ့ တပြေးညီ ဖောင့်ပြောင်းပေးတဲ့ မြန်မာဖောင့် ကွန်ဗာတာပဲ ဖြစ်ပါတယ်။ စာရိုက်ထည့်တာနဲ့ဖြစ်ဖြစ် ဒါမှမဟုတ် ကူးထည့်တာနဲ့ဖြစ်ဖြစ် မြန်မာဖောင့် တစ်ခုကနေ တစ်ခုကို ပြောင်းပေးပါတယ်။ မြန်မာ ယူနီကုဒ်ကနေ ပြောင်းချင်တယ်ဆို မြန်မာ ယူနီကုဒ်ဘက်မှာ ရိုက်ထည့်၊ ကူးထည့်လိုက်တာနဲ့ ဇော်ဂျီဝမ်းဘက်မှာ ဇော်ဂျီဖောင့်ကိုပြောင်းပြီးသား တိုက်ရိုက်ထွက်လာပါမယ်။ အပြန်အလှန်ပါပဲ၊ ဇော်ဂျီကနေပြောင်းချင်တယ်ဆိုရင် ဇော်ဂျီဝမ်းဘက်မှာ ရိုက်ထည့်၊ ကူးထည့်တာနဲ့ မြန်မာ ယူနီကုဒ်ဖောင့်ကို ပြောင်းပြီးသားက မြန်မာ ယူနီကုဒ်အကွက်ထဲမှာ ပေါ်လာမှာဖြစ်ပါတယ်။</p>
|
||||
|
||||
<table border="1">
|
||||
<tr>
|
||||
<th>ပစ္စည်း</th>
|
||||
<th>အရေအတွက်</th>
|
||||
<th>ဈေးနှုန်း</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Hosting</td>
|
||||
<td>1</td>
|
||||
<td>{{.Amount}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Domain registration</td>
|
||||
<td>1</td>
|
||||
<td>$15</td>
|
||||
</tr>
|
||||
</table>`
|
||||
result := GenPNG(C.CString("build/out.png"), C.CString(payload), C.CString(temp))
|
||||
goResult := C.GoString(result)
|
||||
fmt.Println("Result:", goResult)
|
||||
PrintImg(C.CString("usb:/dev/usb/lp1"), C.CString("build/out.png"))
|
||||
}
|
||||
58
printer.go
Normal file
58
printer.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"C"
|
||||
_ "image/png"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"bufio"
|
||||
"log"
|
||||
"net"
|
||||
|
||||
"time"
|
||||
|
||||
"github.com/kenshaw/escpos"
|
||||
)
|
||||
|
||||
//export PrintImg
|
||||
func PrintImg(printer *C.char, imagePath *C.char) *C.char {
|
||||
goPrinter := C.GoString(printer)
|
||||
goImagePath := C.GoString(imagePath)
|
||||
|
||||
// printer := "tcp:192.168.100.151:9100"
|
||||
// printer := "usb:/dev/usb/lp1"
|
||||
var w *bufio.ReadWriter
|
||||
if strings.HasPrefix(goPrinter, "tcp:") {
|
||||
location := strings.TrimLeft(goPrinter, "tcp:")
|
||||
conn, err := net.Dial("tcp", location)
|
||||
if err != nil {
|
||||
log.Println("error dialing:", err.Error())
|
||||
return NewErr(err)
|
||||
}
|
||||
defer conn.Close()
|
||||
w = bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
|
||||
} else if strings.HasPrefix(goPrinter, "usb:") {
|
||||
location := strings.TrimLeft(goPrinter, "usb:")
|
||||
f, err := os.OpenFile(location, os.O_RDWR, os.ModeDevice)
|
||||
if err != nil {
|
||||
log.Println("error OpenFile usb:", err.Error())
|
||||
return NewErr(err)
|
||||
}
|
||||
defer f.Close()
|
||||
w = bufio.NewReadWriter(bufio.NewReader(f), bufio.NewWriter(f))
|
||||
}
|
||||
prt := escpos.New(w)
|
||||
|
||||
prt.Init()
|
||||
prt.SetSmooth(1)
|
||||
err := printImg(prt, goImagePath)
|
||||
if err != nil {
|
||||
return NewErr(err)
|
||||
}
|
||||
prt.Cut()
|
||||
prt.End()
|
||||
w.Flush()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
return NewOk(nil)
|
||||
}
|
||||
833
rabbit.go
Normal file
833
rabbit.go
Normal file
@@ -0,0 +1,833 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/dlclark/regexp2"
|
||||
)
|
||||
|
||||
type RuleStruct struct {
|
||||
From string
|
||||
To string
|
||||
}
|
||||
|
||||
func uni2zg(str string) string {
|
||||
unizgRule := `[
|
||||
{
|
||||
"from": "\u1004\u103a\u1039",
|
||||
"to": "\u1064"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u1010\u103d",
|
||||
"to": "\u1096"
|
||||
},
|
||||
{
|
||||
"from": "\u102b\u103a",
|
||||
"to": "\u105a"
|
||||
},
|
||||
{
|
||||
"from": "\u102d\u1036",
|
||||
"to": "\u108e"
|
||||
},
|
||||
{
|
||||
"from": "\u104e\u1004\u103a\u1038",
|
||||
"to": "\u104e"
|
||||
},
|
||||
{
|
||||
"from": "[\u1025\u1009](?=\u1039)",
|
||||
"to": "\u106a"
|
||||
},
|
||||
{
|
||||
"from": "\u1009(?=[\u102f\u1030])",
|
||||
"to": "\u1025"
|
||||
},
|
||||
{
|
||||
"from": "[\u1025\u1009](?=[\u1037]?[\u103a])",
|
||||
"to": "\u1025"
|
||||
},
|
||||
{
|
||||
"from": "\u100a(?=[\u1039\u103d])",
|
||||
"to": "\u106b"
|
||||
},
|
||||
{
|
||||
"from": "(\u1039[\u1000-\u1021])(\u102D){0,1}\u102f",
|
||||
"to": "$1$2\u1033"
|
||||
},
|
||||
{
|
||||
"from": "(\u1039[\u1000-\u1021])\u1030",
|
||||
"to": "$1\u1034"
|
||||
},
|
||||
{
|
||||
"from": "\u1014(?=[\u102d\u102e\u102f\u103A]?[\u1030\u103d\u103e\u102f\u1039])",
|
||||
"to": "\u108f"
|
||||
},
|
||||
{
|
||||
"from": "\u1014(?=\u103A\u102F )",
|
||||
"to": "\u108f"
|
||||
},
|
||||
{
|
||||
"from" : "\u1014\u103c",
|
||||
"to" : "\u108f\u103c"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u1000",
|
||||
"to": "\u1060"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u1001",
|
||||
"to": "\u1061"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u1002",
|
||||
"to": "\u1062"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u1003",
|
||||
"to": "\u1063"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u1005",
|
||||
"to": "\u1065"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u1006",
|
||||
"to": "\u1066"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u1007",
|
||||
"to": "\u1068"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u1008",
|
||||
"to": "\u1069"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u100b",
|
||||
"to": "\u106c"
|
||||
},
|
||||
{
|
||||
"from": "\u100b\u1039\u100c",
|
||||
"to": "\u1092"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u100c",
|
||||
"to": "\u106d"
|
||||
},
|
||||
{
|
||||
"from": "\u100d\u1039\u100d",
|
||||
"to": "\u106e"
|
||||
},
|
||||
{
|
||||
"from": "\u100d\u1039\u100e",
|
||||
"to": "\u106f"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u100f",
|
||||
"to": "\u1070"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u1010",
|
||||
"to": "\u1071"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u1011",
|
||||
"to": "\u1073"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u1012",
|
||||
"to": "\u1075"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u1013",
|
||||
"to": "\u1076"
|
||||
},
|
||||
{
|
||||
"from": "\u1039[\u1014\u108f]",
|
||||
"to": "\u1077"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u1015",
|
||||
"to": "\u1078"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u1016",
|
||||
"to": "\u1079"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u1017",
|
||||
"to": "\u107a"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u1018",
|
||||
"to": "\u107b"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u1019",
|
||||
"to": "\u107c"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u101c",
|
||||
"to": "\u1085"
|
||||
},
|
||||
{
|
||||
"from": "\u103f",
|
||||
"to": "\u1086"
|
||||
},
|
||||
{
|
||||
"from": "\u103d\u103e",
|
||||
"to": "\u108a"
|
||||
},
|
||||
{
|
||||
"from": "(\u1064)([\u1000-\u1021])([\u103b\u103c]?)\u102d",
|
||||
"to": "$2$3\u108b"
|
||||
},
|
||||
{
|
||||
"from": "(\u1064)([\u1000-\u1021])([\u103b\u103c]?)\u102e",
|
||||
"to": "$2$3\u108c"
|
||||
},
|
||||
{
|
||||
"from": "(\u1064)([\u1000-\u1021])([\u103b\u103c]?)\u1036",
|
||||
"to": "$2$3\u108d"
|
||||
},
|
||||
{
|
||||
"from": "(\u1064)([\u1000-\u1021\u1040-\u1049])([\u103b\u103c]?)([\u1031]?)",
|
||||
"to": "$2$3$4$1"
|
||||
},
|
||||
{
|
||||
"from": "\u101b(?=([\u102d\u102e]?)[\u102f\u1030\u103d\u108a])",
|
||||
"to": "\u1090"
|
||||
},
|
||||
{
|
||||
"from": "\u100f\u1039\u100d",
|
||||
"to": "\u1091"
|
||||
},
|
||||
{
|
||||
"from": "\u100b\u1039\u100b",
|
||||
"to": "\u1097"
|
||||
},
|
||||
{
|
||||
"from": "([\u1000-\u1021\u108f\u1029\u106e\u106f\u1086\u1090\u1091\u1092\u1097])([\u1060-\u1069\u106c\u106d\u1070-\u107c\u1085\u108a])?([\u103b-\u103e]*)?\u1031",
|
||||
"to": "\u1031$1$2$3"
|
||||
},
|
||||
{
|
||||
"from": "\u103c\u103e",
|
||||
"to": "\u103c\u1087"
|
||||
},
|
||||
{
|
||||
"from": "([\u1000-\u1021\u108f\u1029])([\u1060-\u1069\u106c\u106d\u1070-\u107c\u1085])?(\u103c)",
|
||||
"to": "$3$1$2"
|
||||
},
|
||||
{
|
||||
"from": "\u103a",
|
||||
"to": "\u1039"
|
||||
},
|
||||
{
|
||||
"from": "\u103b",
|
||||
"to": "\u103a"
|
||||
},
|
||||
{
|
||||
"from": "\u103c",
|
||||
"to": "\u103b"
|
||||
},
|
||||
{
|
||||
"from": "\u103d",
|
||||
"to": "\u103c"
|
||||
},
|
||||
{
|
||||
"from": "\u103e",
|
||||
"to": "\u103d"
|
||||
},
|
||||
{
|
||||
"from": "([^\u103a\u100a])\u103d([\u102d\u102e]?)\u102f",
|
||||
"to": "$1\u1088$2"
|
||||
},
|
||||
{
|
||||
"from": "([\u101b\u103a\u103c\u108a\u1088\u1090])([\u1030\u103d])?([\u1032\u1036\u1039\u102d\u102e\u108b\u108c\u108d\u108e]?)(\u102f)?\u1037",
|
||||
"to": "$1$2$3$4\u1095"
|
||||
},
|
||||
{
|
||||
"from": "([\u102f\u1014\u1030\u103d])([\u1032\u1036\u1039\u102d\u102e\u108b\u108c\u108d\u108e]?)\u1037",
|
||||
"to": "$1$2\u1094"
|
||||
},
|
||||
{
|
||||
"from": "([\u103b])([\u1000-\u1021])([\u1087]?)([\u1036\u102d\u102e\u108b\u108c\u108d\u108e]?)\u102f",
|
||||
"to": "$1$2$3$4\u1033"
|
||||
},
|
||||
{
|
||||
"from": "([\u103b])([\u1000-\u1021])([\u1087]?)([\u1036\u102d\u102e\u108b\u108c\u108d\u108e]?)\u1030",
|
||||
"to": "$1$2$3$4\u1034"
|
||||
},
|
||||
{
|
||||
"from": "([\u103a\u103c\u100a\u1008\u100b\u100c\u100d\u1020\u1025])([\u103d]?)([\u1036\u102d\u102e\u108b\u108c\u108d\u108e]?)\u102f",
|
||||
"to": "$1$2$3\u1033"
|
||||
},
|
||||
{
|
||||
"from": "([\u103a\u103c\u100a\u1008\u100b\u100c\u100d\u1020\u1025])(\u103d?)([\u1036\u102d\u102e\u108b\u108c\u108d\u108e]?)\u1030",
|
||||
"to": "$1$2$3\u1034"
|
||||
},
|
||||
{
|
||||
"from": "([\u100a\u1020\u1009])\u103d",
|
||||
"to": "$1\u1087"
|
||||
},
|
||||
{
|
||||
"from": "\u103d\u1030",
|
||||
"to": "\u1089"
|
||||
},
|
||||
{
|
||||
"from": "\u103b([\u1000\u1003\u1006\u100f\u1010\u1011\u1018\u101a\u101c\u101a\u101e\u101f])",
|
||||
"to": "\u107e$1"
|
||||
},
|
||||
{
|
||||
"from": "\u107e([\u1000\u1003\u1006\u100f\u1010\u1011\u1018\u101a\u101c\u101a\u101e\u101f])([\u103c\u108a])([\u1032\u1036\u102d\u102e\u108b\u108c\u108d\u108e])",
|
||||
"to": "\u1084$1$2$3"
|
||||
},
|
||||
{
|
||||
"from": "\u107e([\u1000\u1003\u1006\u100f\u1010\u1011\u1018\u101a\u101c\u101a\u101e\u101f])([\u103c\u108a])",
|
||||
"to": "\u1082$1$2"
|
||||
},
|
||||
{
|
||||
"from": "\u107e([\u1000\u1003\u1006\u100f\u1010\u1011\u1018\u101a\u101c\u101a\u101e\u101f])([\u1033\u1034]?)([\u1032\u1036\u102d\u102e\u108b\u108c\u108d\u108e])",
|
||||
"to": "\u1080$1$2$3"
|
||||
},
|
||||
{
|
||||
"from": "\u103b([\u1000-\u1021])([\u103c\u108a])([\u1032\u1036\u102d\u102e\u108b\u108c\u108d\u108e])",
|
||||
"to": "\u1083$1$2$3"
|
||||
},
|
||||
{
|
||||
"from": "\u103b([\u1000-\u1021])([\u103c\u108a])",
|
||||
"to": "\u1081$1$2"
|
||||
},
|
||||
{
|
||||
"from": "\u103b([\u1000-\u1021])([\u1033\u1034]?)([\u1032\u1036\u102d\u102e\u108b\u108c\u108d\u108e])",
|
||||
"to": "\u107f$1$2$3"
|
||||
},
|
||||
{
|
||||
"from": "\u103a\u103d",
|
||||
"to": "\u103d\u103a"
|
||||
},
|
||||
{
|
||||
"from": "\u103a([\u103c\u108a])",
|
||||
"to": "$1\u107d"
|
||||
},
|
||||
{
|
||||
"from": "([\u1033\u1034])(\u1036?)\u1094",
|
||||
"to": "$1$2\u1095"
|
||||
},
|
||||
{
|
||||
"from": "\u108F\u1071",
|
||||
"to" : "\u108F\u1072"
|
||||
},
|
||||
{
|
||||
"from": "([\u1000-\u1021])([\u107B\u1066])\u102C",
|
||||
"to": "$1\u102C$2"
|
||||
},
|
||||
{
|
||||
"from": "\u102C([\u107B\u1066])\u1037",
|
||||
"to": "\u102C$1\u1094"
|
||||
},
|
||||
{
|
||||
"from": "\u1047((?=[\u1000-\u1021]\u1039)|(?=[\u102c-\u1030\u1032\u1036-\u1038\u103c\u103d]))",
|
||||
"to": "\u101b"
|
||||
}
|
||||
]
|
||||
`
|
||||
|
||||
return replaceRule(unizgRule, str)
|
||||
}
|
||||
|
||||
func Zg2uni(str string) string {
|
||||
zguniRule := `[
|
||||
{
|
||||
"from" : "([\u102D\u102E\u103D\u102F\u1037\u1095])\\1+",
|
||||
"to" : "$1"
|
||||
},
|
||||
{
|
||||
"from": "\u200B",
|
||||
"to": ""
|
||||
},
|
||||
{
|
||||
"from" : "\u103d\u103c",
|
||||
"to" : "\u108a"
|
||||
},
|
||||
{
|
||||
"from": "(\u103d|\u1087)",
|
||||
"to": "\u103e"
|
||||
},
|
||||
{
|
||||
"from": "\u103c",
|
||||
"to": "\u103d"
|
||||
},
|
||||
{
|
||||
"from": "(\u103b|\u107e|\u107f|\u1080|\u1081|\u1082|\u1083|\u1084)",
|
||||
"to": "\u103c"
|
||||
},
|
||||
{
|
||||
"from": "(\u103a|\u107d)",
|
||||
"to": "\u103b"
|
||||
},
|
||||
{
|
||||
"from": "\u1039",
|
||||
"to": "\u103a"
|
||||
},
|
||||
{
|
||||
"from": "(\u1066|\u1067)",
|
||||
"to": "\u1039\u1006"
|
||||
},
|
||||
{
|
||||
"from": "\u106a",
|
||||
"to": "\u1009"
|
||||
},
|
||||
{
|
||||
"from": "\u106b",
|
||||
"to": "\u100a"
|
||||
},
|
||||
{
|
||||
"from": "\u106c",
|
||||
"to": "\u1039\u100b"
|
||||
},
|
||||
{
|
||||
"from": "\u106d",
|
||||
"to": "\u1039\u100c"
|
||||
},
|
||||
{
|
||||
"from": "\u106e",
|
||||
"to": "\u100d\u1039\u100d"
|
||||
},
|
||||
{
|
||||
"from": "\u106f",
|
||||
"to": "\u100d\u1039\u100e"
|
||||
},
|
||||
{
|
||||
"from": "\u1070",
|
||||
"to": "\u1039\u100f"
|
||||
},
|
||||
{
|
||||
"from": "(\u1071|\u1072)",
|
||||
"to": "\u1039\u1010"
|
||||
},
|
||||
{
|
||||
"from": "\u1060",
|
||||
"to": "\u1039\u1000"
|
||||
},
|
||||
{
|
||||
"from": "\u1061",
|
||||
"to": "\u1039\u1001"
|
||||
},
|
||||
{
|
||||
"from": "\u1062",
|
||||
"to": "\u1039\u1002"
|
||||
},
|
||||
{
|
||||
"from": "\u1063",
|
||||
"to": "\u1039\u1003"
|
||||
},
|
||||
{
|
||||
"from": "\u1065",
|
||||
"to": "\u1039\u1005"
|
||||
},
|
||||
{
|
||||
"from": "\u1068",
|
||||
"to": "\u1039\u1007"
|
||||
},
|
||||
{
|
||||
"from": "\u1069",
|
||||
"to": "\u1039\u1008"
|
||||
},
|
||||
{
|
||||
"from": "(\u1073|\u1074)",
|
||||
"to": "\u1039\u1011"
|
||||
},
|
||||
{
|
||||
"from": "\u1075",
|
||||
"to": "\u1039\u1012"
|
||||
},
|
||||
{
|
||||
"from": "\u1076",
|
||||
"to": "\u1039\u1013"
|
||||
},
|
||||
{
|
||||
"from": "\u1077",
|
||||
"to": "\u1039\u1014"
|
||||
},
|
||||
{
|
||||
"from": "\u1078",
|
||||
"to": "\u1039\u1015"
|
||||
},
|
||||
{
|
||||
"from": "\u1079",
|
||||
"to": "\u1039\u1016"
|
||||
},
|
||||
{
|
||||
"from": "\u107a",
|
||||
"to": "\u1039\u1017"
|
||||
},
|
||||
{
|
||||
"from": "\u107c",
|
||||
"to": "\u1039\u1019"
|
||||
},
|
||||
{
|
||||
"from": "\u1085",
|
||||
"to": "\u1039\u101c"
|
||||
},
|
||||
{
|
||||
"from": "\u1033",
|
||||
"to": "\u102f"
|
||||
},
|
||||
{
|
||||
"from": "\u1034",
|
||||
"to": "\u1030"
|
||||
},
|
||||
{
|
||||
"from": "\u103f",
|
||||
"to": "\u1030"
|
||||
},
|
||||
{
|
||||
"from": "\u1086",
|
||||
"to": "\u103f"
|
||||
},
|
||||
{
|
||||
"from": "\u1036\u1088",
|
||||
"to": "\u1088\u1036"
|
||||
},
|
||||
{
|
||||
"from": "\u1088",
|
||||
"to": "\u103e\u102f"
|
||||
},
|
||||
{
|
||||
"from": "\u1089",
|
||||
"to": "\u103e\u1030"
|
||||
},
|
||||
{
|
||||
"from": "\u108a",
|
||||
"to": "\u103d\u103e"
|
||||
},
|
||||
{
|
||||
"from": "\u103B\u1064",
|
||||
"to": "\u1064\u103B"
|
||||
},
|
||||
{
|
||||
"from": "\u103c([\u1000-\u1021])(\u1064|\u108b)",
|
||||
"to": "$1\u103c$2"
|
||||
},
|
||||
{
|
||||
"from": "(\u1031)?([\u1000-\u1021\u1040-\u1049])(\u103c)?\u1064",
|
||||
"to": "\u1004\u103a\u1039$1$2$3"
|
||||
},
|
||||
{
|
||||
"from": "(\u1031)?([\u1000-\u1021])(\u103b|\u103c)?\u108b",
|
||||
"to": "\u1004\u103a\u1039$1$2$3\u102d"
|
||||
},
|
||||
{
|
||||
"from": "(\u1031)?([\u1000-\u1021])(\u103b)?\u108c",
|
||||
"to": "\u1004\u103a\u1039$1$2$3\u102e"
|
||||
},
|
||||
{
|
||||
"from": "(\u1031)?([\u1000-\u1021])(\u103b)?\u108d",
|
||||
"to": "\u1004\u103a\u1039$1$2$3\u1036"
|
||||
},
|
||||
{
|
||||
"from": "\u108e",
|
||||
"to": "\u102d\u1036"
|
||||
},
|
||||
{
|
||||
"from": "\u108f",
|
||||
"to": "\u1014"
|
||||
},
|
||||
{
|
||||
"from": "\u1090",
|
||||
"to": "\u101b"
|
||||
},
|
||||
{
|
||||
"from": "\u1091",
|
||||
"to": "\u100f\u1039\u100d"
|
||||
},
|
||||
{
|
||||
"from": "\u1092",
|
||||
"to": "\u100b\u1039\u100c"
|
||||
},
|
||||
{
|
||||
"from": "\u1019\u102c(\u107b|\u1093)",
|
||||
"to": "\u1019\u1039\u1018\u102c"
|
||||
},
|
||||
{
|
||||
"from": "(\u107b|\u1093)",
|
||||
"to": "\u1039\u1018"
|
||||
},
|
||||
{
|
||||
"from": "(\u1094|\u1095)",
|
||||
"to": "\u1037"
|
||||
},
|
||||
{
|
||||
"from": "([\u1000-\u1021])\u1037\u1032",
|
||||
"to": "$1\u1032\u1037"
|
||||
},
|
||||
{
|
||||
"from": "\u1096",
|
||||
"to": "\u1039\u1010\u103d"
|
||||
},
|
||||
{
|
||||
"from": "\u1097",
|
||||
"to": "\u100b\u1039\u100b"
|
||||
},
|
||||
{
|
||||
"from": "\u103c([\u1000-\u1021])([\u1000-\u1021])?",
|
||||
"to": "$1\u103c$2"
|
||||
},
|
||||
{
|
||||
"from": "([\u1000-\u1021])\u103c\u103a",
|
||||
"to": "\u103c$1\u103a"
|
||||
},
|
||||
{
|
||||
"from": "\u1047(?=[\u102c-\u1030\u1032\u1036-\u1038\u103d\u1038])",
|
||||
"to": "\u101b"
|
||||
},
|
||||
{
|
||||
"from": "\u1031\u1047",
|
||||
"to": "\u1031\u101b"
|
||||
},
|
||||
{
|
||||
"from": "\u1040(\u102e|\u102f|\u102d\u102f|\u1030|\u1036|\u103d|\u103e)",
|
||||
"to": "\u101d$1"
|
||||
},
|
||||
{
|
||||
"from": "([^\u1040\u1041\u1042\u1043\u1044\u1045\u1046\u1047\u1048\u1049])\u1040\u102b",
|
||||
"to": "$1\u101d\u102b"
|
||||
},
|
||||
{
|
||||
"from": "([\u1040\u1041\u1042\u1043\u1044\u1045\u1046\u1047\u1048\u1049])\u1040\u102b(?!\u1038)",
|
||||
"to": "$1\u101d\u102b"
|
||||
},
|
||||
{
|
||||
"from": "^\u1040(?=\u102b)",
|
||||
"to": "\u101d"
|
||||
},
|
||||
{
|
||||
"from": "\u1040\u102d(?!\u0020?/)",
|
||||
"to": "\u101d\u102d"
|
||||
},
|
||||
{
|
||||
"from": "([^\u1040-\u1049])\u1040([^\u1040-\u1049\u0020]|[\u104a\u104b])",
|
||||
"to": "$1\u101d$2"
|
||||
},
|
||||
{
|
||||
"from": "([^\u1040-\u1049])\u1040(?=[\\f\\n\\r])",
|
||||
"to": "$1\u101d"
|
||||
},
|
||||
{
|
||||
"from": "([^\u1040-\u1049])\u1040$",
|
||||
"to": "$1\u101d"
|
||||
},
|
||||
{
|
||||
"from": "\u1031([\u1000-\u1021\u103f])(\u103e)?(\u103b)?",
|
||||
"to": "$1$2$3\u1031"
|
||||
},
|
||||
{
|
||||
"from": "([\u1000-\u1021])\u1031([\u103b\u103c\u103d\u103e]+)",
|
||||
"to": "$1$2\u1031"
|
||||
},
|
||||
{
|
||||
"from": "\u1032\u103d",
|
||||
"to": "\u103d\u1032"
|
||||
},
|
||||
{
|
||||
"from": "([\u102d\u102e])\u103b",
|
||||
"to": "\u103b$1"
|
||||
},
|
||||
{
|
||||
"from": "\u103d\u103b",
|
||||
"to": "\u103b\u103d"
|
||||
},
|
||||
{
|
||||
"from": "\u103a\u1037",
|
||||
"to": "\u1037\u103a"
|
||||
},
|
||||
{
|
||||
"from": "\u102f(\u102d|\u102e|\u1036|\u1037)\u102f",
|
||||
"to": "\u102f$1"
|
||||
},
|
||||
{
|
||||
"from": "(\u102f|\u1030)(\u102d|\u102e)",
|
||||
"to": "$2$1"
|
||||
},
|
||||
{
|
||||
"from": "(\u103e)(\u103b|\u103c)",
|
||||
"to": "$2$1"
|
||||
},
|
||||
{
|
||||
"from": "\u1025(?=[\u1037]?[\u103a\u102c])",
|
||||
"to": "\u1009"
|
||||
},
|
||||
{
|
||||
"from": "\u1025\u102e",
|
||||
"to": "\u1026"
|
||||
},
|
||||
{
|
||||
"from": "\u1005\u103b",
|
||||
"to": "\u1008"
|
||||
},
|
||||
{
|
||||
"from": "\u1036(\u102f|\u1030)",
|
||||
"to": "$1\u1036"
|
||||
},
|
||||
{
|
||||
"from": "\u1031\u1037\u103e",
|
||||
"to": "\u103e\u1031\u1037"
|
||||
},
|
||||
{
|
||||
"from": "\u1031\u103e\u102c",
|
||||
"to": "\u103e\u1031\u102c"
|
||||
},
|
||||
{
|
||||
"from": "\u105a",
|
||||
"to": "\u102b\u103a"
|
||||
},
|
||||
{
|
||||
"from": "\u1031\u103b\u103e",
|
||||
"to": "\u103b\u103e\u1031"
|
||||
},
|
||||
{
|
||||
"from": "(\u102d|\u102e)(\u103d|\u103e)",
|
||||
"to": "$2$1"
|
||||
},
|
||||
{
|
||||
"from": "\u102c\u1039([\u1000-\u1021])",
|
||||
"to": "\u1039$1\u102c"
|
||||
},
|
||||
{
|
||||
"from": "\u1039\u103c\u103a\u1039([\u1000-\u1021])",
|
||||
"to": "\u103a\u1039$1\u103c"
|
||||
},
|
||||
{
|
||||
"from": "\u103c\u1039([\u1000-\u1021])",
|
||||
"to": "\u1039$1\u103c"
|
||||
},
|
||||
{
|
||||
"from": "\u1036\u1039([\u1000-\u1021])",
|
||||
"to": "\u1039$1\u1036"
|
||||
},
|
||||
{
|
||||
"from": "\u104e",
|
||||
"to": "\u104e\u1004\u103a\u1038"
|
||||
},
|
||||
{
|
||||
"from": "\u1040(\u102b|\u102c|\u1036)",
|
||||
"to": "\u101d$1"
|
||||
},
|
||||
{
|
||||
"from": "\u1025\u1039",
|
||||
"to": "\u1009\u1039"
|
||||
},
|
||||
{
|
||||
"from": "([\u1000-\u1021])\u103c\u1031\u103d",
|
||||
"to": "$1\u103c\u103d\u1031"
|
||||
},
|
||||
{
|
||||
"from": "([\u1000-\u1021])\u103b\u1031\u103d(\u103e)?",
|
||||
"to": "$1\u103b\u103d$2\u1031"
|
||||
},
|
||||
{
|
||||
"from": "([\u1000-\u1021])\u103d\u1031\u103b",
|
||||
"to": "$1\u103b\u103d\u1031"
|
||||
},
|
||||
{
|
||||
"from": "([\u1000-\u1021])\u1031(\u1039[\u1000-\u1021])",
|
||||
"to": "$1$2\u1031"
|
||||
},
|
||||
{
|
||||
"from": "\u1038\u103a",
|
||||
"to": "\u103a\u1038"
|
||||
},
|
||||
{
|
||||
"from": "\u102d\u103a|\u103a\u102d",
|
||||
"to": "\u102d"
|
||||
},
|
||||
{
|
||||
"from": "\u102d\u102f\u103a",
|
||||
"to": "\u102d\u102f"
|
||||
},
|
||||
{
|
||||
"from": "\u0020\u1037",
|
||||
"to": "\u1037"
|
||||
},
|
||||
{
|
||||
"from": "\u1037\u1036",
|
||||
"to": "\u1036\u1037"
|
||||
},
|
||||
{
|
||||
"from": "[\u102d]+",
|
||||
"to": "\u102d"
|
||||
},
|
||||
{
|
||||
"from": "[\u103a]+",
|
||||
"to": "\u103a"
|
||||
},
|
||||
{
|
||||
"from": "[\u103d]+",
|
||||
"to": "\u103d"
|
||||
},
|
||||
{
|
||||
"from": "[\u1037]+",
|
||||
"to": "\u1037"
|
||||
},
|
||||
{
|
||||
"from": "[\u102e]+",
|
||||
"to": "\u102e"
|
||||
},
|
||||
{
|
||||
"from": "\u102d\u102e|\u102e\u102d",
|
||||
"to": "\u102e"
|
||||
},
|
||||
{
|
||||
"from": "\u102f\u102d",
|
||||
"to": "\u102d\u102f"
|
||||
},
|
||||
{
|
||||
"from": "\u1037\u1037",
|
||||
"to": "\u1037"
|
||||
},
|
||||
{
|
||||
"from": "\u1032\u1032",
|
||||
"to": "\u1032"
|
||||
},
|
||||
{
|
||||
"from": "\u1044\u1004\u103a\u1038",
|
||||
"to": "\u104E\u1004\u103a\u1038"
|
||||
},
|
||||
{
|
||||
"from": "([\u102d\u102e])\u1039([\u1000-\u1021])",
|
||||
"to": "\u1039$2$1"
|
||||
},
|
||||
{
|
||||
"from": "(\u103c\u1031)\u1039([\u1000-\u1021])",
|
||||
"to": "\u1039$2$1"
|
||||
},
|
||||
{
|
||||
"from": "\u1036\u103d",
|
||||
"to": "\u103d\u1036"
|
||||
},
|
||||
{
|
||||
"from": "\u1047((?=[\u1000-\u1021]\u103a)|(?=[\u102c-\u1030\u1032\u1036-\u1038\u103d\u103e]))",
|
||||
"to": "\u101b"
|
||||
}
|
||||
]`
|
||||
|
||||
return replaceRule(zguniRule, str)
|
||||
}
|
||||
|
||||
func replaceRule(ruleJson string, output string) string {
|
||||
var rules []RuleStruct
|
||||
json.Unmarshal([]byte(ruleJson), &rules)
|
||||
text := output
|
||||
for _, rule := range rules {
|
||||
re := regexp2.MustCompile(rule.From, 1)
|
||||
res, err := re.Replace(text, rule.To, 0, -1)
|
||||
text = res
|
||||
if err != nil {
|
||||
//nothing to do
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return text
|
||||
|
||||
}
|
||||
BIN
static/Zawgyi-One.ttf
Normal file
BIN
static/Zawgyi-One.ttf
Normal file
Binary file not shown.
31
vo.go
Normal file
31
vo.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"C"
|
||||
"encoding/json"
|
||||
"log"
|
||||
)
|
||||
|
||||
type Reply struct {
|
||||
Status int `json:"status"`
|
||||
Err string `json:"err"`
|
||||
Result interface{} `json:"result"`
|
||||
}
|
||||
|
||||
func NewErr(err error) *C.char {
|
||||
e := Reply{Status: 1, Err: err.Error()}
|
||||
b, err := json.Marshal(e)
|
||||
if err != nil {
|
||||
log.Println("Error json.Marshal:", err.Error())
|
||||
}
|
||||
return C.CString(string(b))
|
||||
}
|
||||
|
||||
func NewOk(data interface{}) *C.char {
|
||||
e := Reply{Status: 0, Result: data}
|
||||
b, err := json.Marshal(e)
|
||||
if err != nil {
|
||||
log.Println("Error json.Marshal:", err.Error())
|
||||
}
|
||||
return C.CString(string(b))
|
||||
}
|
||||
Reference in New Issue
Block a user