diff --git a/.gitignore b/.gitignore index 6561e4f..0b542e8 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ go.work.sum build assets libgofunc +libgo diff --git a/cmd/logo.png b/cmd/logo.png new file mode 100644 index 0000000..0568ee9 Binary files /dev/null and b/cmd/logo.png differ diff --git a/cmd/main.go b/cmd/main.go index 13e367b..cd27e83 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -7,11 +7,8 @@ import ( "C" "fmt" _ "image/png" - - "github.com/google/gousb" ) import ( - "github.com/google/gousb/usbid" "gt.mokkon.com/sainw/libgofunc" ) @@ -21,39 +18,41 @@ func Sum(a, b int) int { } func main() { - payload := `{"Name":"Ko Myo","Amount":3000}` + payload := `{ "sales": [ { "shiftId": "1001", "tran_seq": 1, "salePerson": "John Doe", "timeSec": "1717243200", "timeValue": "2026-06-01 14:30:00", "fpId": 3, "productId": 101, "product": "Diesel Premium", "price": "2500", "volume": "40", "amount": "100000", "discount_amount": "5000", "discount_percent": 5.0, "discount_money": 5000, "rule_types": "LOYALTY,FLEET", "promotion_status": true, "custom_promotion_status": false, "discount_volume": "2", "customerId": 5001, "customer_name": "ABC Logistics Pte Ltd", "vehicle_type": "Truck", "vehicle_type_extension": "10-Wheeler", "carNumber": "SGX1234A", "status": "COMPLETED", "receiptNumber": "RCP-20260601-0001", "receiptCount": 1, "mop": "CARD", "local_used_credit": 100.50, "local_credit_limit": 5000.00, "local_credit_balance": 4899.50, "local_debit_balance": 250.75, "loyalty_type": "GOLD", "points_balance": 12500, "reward_amount": 50.25, "reward_points": 500, "redeem_amount": 25.00, "redeem_points": 250, "redeem_exchange_rate": 0.1, "point_exchange_rate": 10.0, "used_credit": 100.50, "credit_limit": 10000.00, "credit_amount": 100.50, "credit_balance": 9899.50, "debit_amount": 50.25, "debit_balance": 449.75, "payment_customer_id": "PAYCUST001", "payment_customer_name": "ABC Logistics", "payment_customer_number": "+6591234567", "corp_id": "CORP001", "corp_name": "ABC Logistics Group", "card_number": "411111******1111", "upload": true, "upload_status": "SUCCESS", "send_sale_data_confirm": true, "loan_amount": 1000, "tax_percent": 9.0, "tax_status": true, "tier": 2, "dealNumber": "DL-20260601-001", "bank_name": "DBS", "bank_payment_type": "VISA", "session_id": "sess_abc123xyz", "tran_id": "txn_987654321", "qrcode_data": "SGQR|PAYNOW|ABCLOGISTICS", "fp_total": 8, "missed_sale_status": false, "opo_status": true, "ip_printer_status": true, "sale_type": "NORMAL" }, { "shiftId": "1001", "tran_seq": 1, "salePerson": "John Doe", "timeSec": "1717243200", "timeValue": "2026-06-01 14:30:00", "fpId": 3, "productId": 101, "product": "Diesel Premium", "price": "2500", "volume": "40", "amount": "100000", "discount_amount": "5000", "discount_percent": 5.0, "discount_money": 5000, "rule_types": "LOYALTY,FLEET", "promotion_status": true, "custom_promotion_status": false, "discount_volume": "2", "customerId": 5001, "customer_name": "ABC Logistics Pte Ltd", "vehicle_type": "Truck", "vehicle_type_extension": "10-Wheeler", "carNumber": "SGX1234A", "status": "COMPLETED", "receiptNumber": "RCP-20260601-0001", "receiptCount": 1, "mop": "CARD", "local_used_credit": 100.50, "local_credit_limit": 5000.00, "local_credit_balance": 4899.50, "local_debit_balance": 250.75, "loyalty_type": "GOLD", "points_balance": 12500, "reward_amount": 50.25, "reward_points": 500, "redeem_amount": 25.00, "redeem_points": 250, "redeem_exchange_rate": 0.1, "point_exchange_rate": 10.0, "used_credit": 100.50, "credit_limit": 10000.00, "credit_amount": 100.50, "credit_balance": 9899.50, "debit_amount": 50.25, "debit_balance": 449.75, "payment_customer_id": "PAYCUST001", "payment_customer_name": "ABC Logistics", "payment_customer_number": "+6591234567", "corp_id": "CORP001", "corp_name": "ABC Logistics Group", "card_number": "411111******1111", "upload": true, "upload_status": "SUCCESS", "send_sale_data_confirm": true, "loan_amount": 1000, "tax_percent": 9.0, "tax_status": true, "tier": 2, "dealNumber": "DL-20260601-001", "bank_name": "DBS", "bank_payment_type": "VISA", "session_id": "sess_abc123xyz", "tran_id": "txn_987654321", "qrcode_data": "SGQR|PAYNOW|ABCLOGISTICS", "fp_total": 8, "missed_sale_status": false, "opo_status": true, "ip_printer_status": true, "sale_type": "NORMAL" } ], "station": { "id": "1", "name": "Jurong Fuel Station", "address": "123 Boon Lay Way, Singapore 640123", "phones": "+65 6123 4567,+65 6987 6543", "code": "STN001", "money_divider": 100, "volume_divider": 1000, "check_tran_duration": 60, "fho_server_offline_duration": 300, "loyalty_backlog_duration": 1440, "token": "station-secret-token-123", "monthly_view": true, "pump_status": true, "currency": "SGD", "tank_manual_status": false, "update_price_type": "AUTO", "show_price_history": true, "old_receipt_status": false, "car_number_modification_status": true, "car_number_entry_status": 2, "shop_code": "SHOP001" }}` const temp = ` -

New Day Energy

+

{{.station.name}}

-

Address: မင်္ဂလာပါ {{.Name}}

-

Receipt: RCPT001

-

Phone: 0977777777

-

Date: 4 Jan 2026 15:38:38

-

Car No.: 3J/3883

-

Casher: မနှင်းနှင်း

-

MOP: B2B

-

Tier: 1

-

Deal No.: RR

-
+

Address: မင်္ဂလာပါ {{(index .sales 0).salePerson}}

+

Receipt: RCPT001

+

Phone: 0977777777

+

Date: 4 Jan 2026 15:38:38

+

Car No.: 3J/3883

+

Casher: မနှင်းနှင်း

+

MOP: B2B

+

Tier: 1

+

Deal No.: RR

+
- +
- - + + +{{range .sales}} - - - - - - + + + + + + +{{end}}
ItemPumpItemPump Price Liter Gallon Amount
95 RONP82,0003.250.7156,500{{.product}}{{.fpId}}{{.price}}{{.volume}}{{.volume}}{{.amount}}

@@ -63,47 +62,8 @@ func main() { fmt.Println("Result:", result) // PrintImg(C.CString("usb:/dev/usb/lp1"), C.CString("build/out.png")) // libgofunc.Print("int:/dev/bus/usb/001/046", "./out.png") - libgofunc.Print("tcp:192.168.100.151:9100", "./out.png") + // libgofunc.Print("tcp:192.168.100.110:9100", "./out.png") + // libgofunc.Print("usb:/dev/usb/lp1", "./out.png") // printer := "tcp:192.168.100.151:9100" // ListUSB() } - -func ListUSB() { - ctx := gousb.NewContext() - defer ctx.Close() - - // OpenDevices returns all devices that return 'true' in the filter - devices, _ := ctx.OpenDevices(func(desc *gousb.DeviceDesc) bool { - // fmt.Println(usbid.Describe(desc)) - - // path := fmt.Sprintf("/dev/bus/usb/%03d/%03d", desc.Bus, desc.Address) - // fmt.Printf("Device Path: %s\n", path) - - // switch desc.Class { - // case 7: - // fmt.Println("Found a standard printer") - // case 0xFF: - // fmt.Println("Found a vendor-specific device (likely your printer)") - // } - - return true // Open every device to read its name - }) - defer func() { - for _, d := range devices { - - d.Close() - } - }() - - for _, d := range devices { - fmt.Println(usbid.Describe(d.Desc)) - fmt.Printf("Bus: %d, Address: %d\n", d.Desc.Bus, d.Desc.Address) - // Read human-readable names from the device strings - manufacturer, _ := d.Manufacturer() - product, _ := d.Product() - serial, _ := d.SerialNumber() - // d.Desc.Path - fmt.Printf("ID: %s:%s | Manufacturer: %s | Product: %s | Serial: %s\n", - d.Desc.Vendor, d.Desc.Product, manufacturer, product, serial) - } -} diff --git a/escpos_printer.go b/escpos_printer.go index 85d39a7..4d378b4 100644 --- a/escpos_printer.go +++ b/escpos_printer.go @@ -91,7 +91,8 @@ func toMonochrome(img image.Image) *image.Gray { 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) + // grayValue := uint8((r + g + b) / 3 >> 8) + grayValue := uint8((0.299*float64(r) + 0.587*float64(g) + 0.114*float64(b)) / 256.0) if grayValue > 128 { gray.Set(x, y, color.White) } else { @@ -138,7 +139,6 @@ func escposRaster(img *image.Gray) []byte { data = append(data, b) } } - return data } diff --git a/go.mod b/go.mod index 7010b5a..5e70a30 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module gt.mokkon.com/sainw/libgofunc -go 1.25.0 +go 1.26.0 require ( github.com/dlclark/regexp2 v1.11.5 @@ -10,37 +10,7 @@ require ( golang.org/x/net v0.52.0 ) -require ( - codeberg.org/go-latex/latex v0.2.0 // indirect - codeberg.org/go-pdf/fpdf v0.11.1 // indirect - github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298 // indirect - github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966 // indirect - github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc // indirect - github.com/BurntSushi/xgbutil v0.0.0-20190907113008-ad855c713046 // indirect - github.com/ByteArena/poly2tri-go v0.0.0-20170716161910-d102ad91854f // indirect - github.com/Kagami/go-avif v0.1.0 // indirect - github.com/andybalholm/brotli v1.2.1 // indirect - github.com/benoitkugler/textlayout v0.3.2 // indirect - github.com/benoitkugler/textprocessing v0.0.6 // indirect - github.com/go-fonts/latin-modern v0.3.3 // indirect - github.com/go-text/typesetting v0.3.4 // indirect - github.com/kolesa-team/go-webp v1.0.5 // indirect - github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect - github.com/srwiley/scanx v0.0.0-20190309010443-e94503791388 // indirect - github.com/tdewolff/font v0.0.0-20260314002930-9f995dac393e // indirect - github.com/tdewolff/minify/v2 v2.24.11 // indirect - github.com/tdewolff/parse/v2 v2.8.11 // indirect - github.com/wcharczuk/go-chart/v2 v2.1.2 // indirect - github.com/yuin/goldmark v1.8.2 // indirect - gonum.org/v1/plot v0.16.0 // indirect - modernc.org/knuth v0.5.5 // indirect - modernc.org/token v1.1.0 // indirect - star-tex.org/x/tex v0.7.1 // indirect -) - require ( github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect - github.com/google/gousb v1.1.3 - github.com/tdewolff/canvas v0.0.0-20260406091912-5d4f7059846e golang.org/x/text v0.35.0 // indirect ) diff --git a/go.sum b/go.sum index 5b1156d..c646e8a 100644 --- a/go.sum +++ b/go.sum @@ -1,148 +1,16 @@ -codeberg.org/go-latex/latex v0.2.0 h1:Ol/a6VHY06N+5gPfewswymoRb5ZcKDXWVaVegcx4hbI= -codeberg.org/go-latex/latex v0.2.0/go.mod h1:VJAwQir7/T8LZxj7xAPivISKiVOwkMpQ8bTuPQ31X0Y= -codeberg.org/go-pdf/fpdf v0.11.1 h1:U8+coOTDVLxHIXZgGvkfQEi/q0hYHYvEHFuGNX2GzGs= -codeberg.org/go-pdf/fpdf v0.11.1/go.mod h1:Y0DGRAdZ0OmnZPvjbMp/1bYxmIPxm0ws4tfoPOc4LjU= -github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298 h1:1qlsVAQJXZHsaM8b6OLVo6muQUQd4CwkH/D3fnnbHXA= -github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298/go.mod h1:D+QujdIlUNfa0igpNMk6UIvlb6C252URs4yupRUV4lQ= -github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966 h1:lTG4HQym5oPKjL7nGs+csTgiDna685ZXjxijkne828g= -github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:Mid70uvE93zn9wgF92A/r5ixgnvX8Lh68fxp9KQBaI0= -github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc h1:7D+Bh06CRPCJO3gr2F7h1sriovOZ8BMhca2Rg85c2nk= -github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/BurntSushi/xgbutil v0.0.0-20190907113008-ad855c713046 h1:O/r2Sj+8QcMF7V5IcmiE2sMFV2q3J47BEirxbXJAdzA= -github.com/BurntSushi/xgbutil v0.0.0-20190907113008-ad855c713046/go.mod h1:uw9h2sd4WWHOPdJ13MQpwK5qYWKYDumDqxWWIknEQ+k= -github.com/ByteArena/poly2tri-go v0.0.0-20170716161910-d102ad91854f h1:l7moT9o/v/9acCWA64Yz/HDLqjcRTvc0noQACi4MsJw= -github.com/ByteArena/poly2tri-go v0.0.0-20170716161910-d102ad91854f/go.mod h1:vIOkSdX3NDCPwgu8FIuTat2zDF0FPXXQ0RYFRy+oQic= -github.com/Kagami/go-avif v0.1.0 h1:8GHAGLxCdFfhpd4Zg8j1EqO7rtcQNenxIDerC/uu68w= -github.com/Kagami/go-avif v0.1.0/go.mod h1:OPmPqzNdQq3+sXm0HqaUJQ9W/4k+Elbc3RSfJUemDKA= -github.com/andybalholm/brotli v1.2.1 h1:R+f5xP285VArJDRgowrfb9DqL18yVK0gKAW/F+eTWro= -github.com/andybalholm/brotli v1.2.1/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= -github.com/benoitkugler/pstokenizer v1.0.0/go.mod h1:l1G2Voirz0q/jj0TQfabNxVsa8HZXh/VMxFSRALWTiE= -github.com/benoitkugler/textlayout v0.3.2 h1:Y/LTkwpQ9G0Fia9yhPmZA9IR5AnE8Cq30j3C+Gx5/IE= -github.com/benoitkugler/textlayout v0.3.2/go.mod h1:o+1hFV+JSHBC9qNLIuwVoLedERU7sBPgEFcuSgfvi/w= -github.com/benoitkugler/textlayout-testdata v0.1.1/go.mod h1:i/qZl09BbUOtd7Bu/W1CAubRwTWrEXWq6JwMkw8wYxo= -github.com/benoitkugler/textprocessing v0.0.6 h1:obkMyj62GEPg3xUVYqROlCN22z1OleuZm6ULqX9Om1g= -github.com/benoitkugler/textprocessing v0.0.6/go.mod h1:Io0gN08/PXEzrSOWFa88xHx2Xv3VjvLMY7H76YoI23A= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/go-fonts/latin-modern v0.3.3 h1:g2xNgI8yzdNzIVm+qvbMryB6yGPe0pSMss8QT3QwlJ0= -github.com/go-fonts/latin-modern v0.3.3/go.mod h1:tHaiWDGze4EPB0Go4cLT5M3QzRY3peya09Z/8KSCrpY= -github.com/go-text/typesetting v0.3.4 h1:YYurUOtEb9kGSOz4uE3k4OpBGsp1dDL8+fjCeaFamAU= -github.com/go-text/typesetting v0.3.4/go.mod h1:4qZCQphq4KSgGTAeI0uMEkVbROgfah8BuyF5LRYr7XY= 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/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gousb v1.1.3 h1:xt6M5TDsGSZ+rlomz5Si5Hmd/Fvbmo2YCJHN+yGaK4o= github.com/google/gousb v1.1.3/go.mod h1:GGWUkK0gAXDzxhwrzetW592aOmkkqSGcj5KLEgmCVUg= 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= -github.com/kolesa-team/go-webp v1.0.5 h1:GZQHJBaE8dsNKZltfwqsL0qVJ7vqHXsfA+4AHrQW3pE= -github.com/kolesa-team/go-webp v1.0.5/go.mod h1:QmJu0YHXT3ex+4SgUvs+a+1SFCDcCqyZg+LbIuNNTnE= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ= -github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE= -github.com/srwiley/scanx v0.0.0-20190309010443-e94503791388 h1:ZdkidVdpLW13BQ9a+/3uerT2ezy9J7KQWH18JCfhDmI= -github.com/srwiley/scanx v0.0.0-20190309010443-e94503791388/go.mod h1:C/WY5lmWfMtPFYYBTd3Lzdn4FTLr+RxlIeiBNye+/os= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/tdewolff/canvas v0.0.0-20260406091912-5d4f7059846e h1:A8iHpv0I/IDv+i5YQ/km/UlqSmonRz4UNIrckFxYc+A= -github.com/tdewolff/canvas v0.0.0-20260406091912-5d4f7059846e/go.mod h1:xCHrGFuVb9eeblIAffMuLzKoRnYHQj8xZq8yZ7YQfEw= -github.com/tdewolff/font v0.0.0-20260314002930-9f995dac393e h1:20EEwnJWwKApfX5KttlWbIjgXrXa+HUvkiVUow1hdJ0= -github.com/tdewolff/font v0.0.0-20260314002930-9f995dac393e/go.mod h1:EFuulYdR5cCTF2zKMW6NxchFgd5xtEPSrjkD1MFWDpA= -github.com/tdewolff/minify/v2 v2.24.11 h1:JlANsiWaRBXedoYtsiZgY3YFkdr42oF32vp2SLgQKi4= -github.com/tdewolff/minify/v2 v2.24.11/go.mod h1:exq1pjdrh9uAICdfVKQwqz6MsJmWmQahZuTC6pTO6ro= -github.com/tdewolff/parse/v2 v2.8.11 h1:SGyjEy3xEqd+W9WVzTlTQ5GkP/en4a1AZNZVJ1cvgm0= -github.com/tdewolff/parse/v2 v2.8.11/go.mod h1:Hwlni2tiVNKyzR1o6nUs4FOF07URA+JLBLd6dlIXYqo= -github.com/tdewolff/test v1.0.11/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= -github.com/wcharczuk/go-chart/v2 v2.1.2 h1:Y17/oYNuXwZg6TFag06qe8sBajwwsuvPiJJXcUcLL6E= -github.com/wcharczuk/go-chart/v2 v2.1.2/go.mod h1:Zi4hbaqlWpYajnXB2K22IUYVXRXaLfSGNNR7P4ukyyQ= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yuin/goldmark v1.8.2 h1:kEGpgqJXdgbkhcOgBxkC0X0PmoPG1ZyoZ117rDVp4zE= -github.com/yuin/goldmark v1.8.2/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/image v0.0.0-20210504121937-7319ad40d33e/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= -golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ= -golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8= golang.org/x/image v0.38.0 h1:5l+q+Y9JDC7mBOMjo4/aPhMDcxEptsX+Tt3GgRQRPuE= golang.org/x/image v0.38.0/go.mod h1:/3f6vaXC+6CEanU4KJxbcUZyEePbyKbaLoDOe4ehFYY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -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/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= -golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/plot v0.16.0 h1:dK28Qx/Ky4VmPUN/2zeW0ELyM6ucDnBAj5yun7M9n1g= -gonum.org/v1/plot v0.16.0/go.mod h1:Xz6U1yDMi6Ni6aaXILqmVIb6Vro8E+K7Q/GeeH+Pn0c= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -modernc.org/knuth v0.5.5 h1:6lap2U/ISm8aC/4NU58ALFCRllNPaK0EZcIGY/oDgUg= -modernc.org/knuth v0.5.5/go.mod h1:e5SBb35HQBj2aFwbBO3ClPcViLY3Wi0LzaOd7c/3qMk= -modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= -modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -star-tex.org/x/tex v0.7.1 h1:4qGAByRyY0WQsOjtcHlxz+FgrYxz8fzxIds2Gjepp5U= -star-tex.org/x/tex v0.7.1/go.mod h1:Y3y0U7sZTltTh/CDZIx0oAtMjG7eMaTuTtvDZGdyhJo= diff --git a/img.go b/img.go index 7bc9ae8..880decd 100644 --- a/img.go +++ b/img.go @@ -103,7 +103,10 @@ func GenImg(width int, outputPath, payload, tmpl string) string { } func renderTemplate(tmp string, data map[string]interface{}) (string, error) { - tmpl := template.Must(template.New("mytemplate").Parse(tmp)) + tmpl, err := template.New("mytemplate").Parse(tmp) + if err != nil { + return "", err + } var buf bytes.Buffer if err := tmpl.Execute(&buf, data); err != nil { return "", err @@ -124,7 +127,11 @@ func renderNode(dc *gg.Context, canvasWidth int, n *Node, y *int, face font.Face case "h3": drawTextBlock(dc, n, canvasWidth, eleH3Size, y, face) case "p": - drawTextBlock(dc, n, canvasWidth, elePSize, y, face) + size := float64(elePSize) + if n.Style.FontSize > 0 { + size = n.Style.FontSize + } + drawTextBlock(dc, n, canvasWidth, size, y, face) case "hr": renderLine(dc, n, canvasWidth, y) case "img": @@ -209,7 +216,7 @@ func drawImage(dc *gg.Context, n *Node, y *int) { } func renderTable(dc *gg.Context, canvasWidth int, table *Node, y *int, face font.Face) { - rows := extractRows(table) + headers, rows := extractRows(table) if len(rows) == 0 { return } @@ -223,9 +230,11 @@ func renderTable(dc *gg.Context, canvasWidth int, table *Node, y *int, face font colCount := len(rows[0]) cellWidth := (canvasWidth - padding) / colCount border := table.Style.Border + for _, row := range rows { x := padding - for _, cell := range row { + for i, cell := range row { + header := headers[i] if border > 0 { dc.SetLineWidth(border) dc.DrawRectangle(float64(x), float64(*y), float64(cellWidth), fontSize+defalutTableBorder) @@ -233,7 +242,11 @@ func renderTable(dc *gg.Context, canvasWidth int, table *Node, y *int, face font dc.Stroke() dc.SetRGB(0, 0, 0) dc.DrawStringAnchored(cell, float64(x+8), float64(*y+20), 0, 0) - x += cellWidth + if w := header.Style.Width; w > 0 { + x += int(w) + } else { + x += cellWidth + } } *y += int(fontSize) + defalutTableBorder } @@ -247,8 +260,9 @@ func renderLine(dc *gg.Context, line *Node, canvasWidth int, y *int) { *y += int(height) } -func extractRows(table *Node) [][]string { +func extractRows(table *Node) ([]*Node, [][]string) { var rows [][]string + var headers []*Node var traverse func(*Node) traverse = func(n *Node) { if n.Tag == "tr" { @@ -257,6 +271,9 @@ func extractRows(table *Node) [][]string { if td.Tag == "td" || td.Tag == "th" { row = append(row, td.Text) } + if td.Tag == "th" { + headers = append(headers, td) + } } if len(row) > 0 { rows = append(rows, row) @@ -267,7 +284,7 @@ func extractRows(table *Node) [][]string { } } traverse(table) - return rows + return headers, rows } func extractNodeRows(table *html.Node) [][]string { @@ -332,9 +349,14 @@ func printImg(prt *escpos.Escpos, imgPath string) error { fmt.Println(err) return err } + data := []byte{0x1D, 0x4C, 0x00, 0x00} + _, err = prt.WriteRaw(data) + if err != nil { + fmt.Println("error 0x1D, 0x4C:", err.Error()) + } gray := toMonochrome(img) - data := escposRaster(gray) + data = escposRaster(gray) _, err = prt.WriteRaw(data) return err diff --git a/printer.go b/printer.go index d8e2396..5a774bf 100644 --- a/printer.go +++ b/printer.go @@ -17,33 +17,11 @@ import ( "github.com/kenshaw/escpos" ) -import ( - "fmt" - - "github.com/google/gousb" -) - -type USBReadWriter struct { - out *gousb.OutEndpoint - in *gousb.InEndpoint // Optional, can be nil if you only write -} - -func (urw *USBReadWriter) Write(p []byte) (n int, err error) { - return urw.out.Write(p) -} - -func (urw *USBReadWriter) Read(p []byte) (n int, err error) { - if urw.in == nil { - return 0, fmt.Errorf("read not supported") - } - return urw.in.Read(p) -} //export PrintImg func PrintImg(printer *C.char, imagePath *C.char) *C.char { goPrinter := C.GoString(printer) goImagePath := C.GoString(imagePath) - var out *gousb.OutEndpoint // printer := "tcp:192.168.100.151:9100" // printer := "usb:/dev/usb/lp1" var w *bufio.ReadWriter @@ -65,53 +43,56 @@ func PrintImg(printer *C.char, imagePath *C.char) *C.char { } defer f.Close() w = bufio.NewReadWriter(bufio.NewReader(f), bufio.NewWriter(f)) - } else if strings.HasPrefix(goPrinter, "int:") { - ctx := gousb.NewContext() - // location := strings.TrimLeft(goPrinter, "int:") - targetBus := 1 - targetAddr := 5 - devs, err := ctx.OpenDevices(func(desc *gousb.DeviceDesc) bool { - return int(desc.Bus) == targetBus && int(desc.Address) == targetAddr - }) - if err != nil || len(devs) == 0 { - log.Fatal("Could not find or open the device") - } - dev := devs[0] - defer dev.Close() - dev.SetAutoDetach(true) + // } else if strings.HasPrefix(goPrinter, "int:") { + // ctx := gousb.NewContext() + // // location := strings.TrimLeft(goPrinter, "int:") + // targetBus := 1 + // targetAddr := 5 + // devs, err := ctx.OpenDevices(func(desc *gousb.DeviceDesc) bool { + // return int(desc.Bus) == targetBus && int(desc.Address) == targetAddr + // }) + // if err != nil || len(devs) == 0 { + // log.Fatal("Could not find or open the device") + // } + // dev := devs[0] + // defer dev.Close() + // dev.SetAutoDetach(true) - // 2. Claim the default interface (usually 0 for printers) - // Note: This may require detaching the kernel driver on Linux - intf, done, err := dev.DefaultInterface() - if err != nil { - log.Fatalf("Failed to claim interface: %v", err) - } - defer done() + // // 2. Claim the default interface (usually 0 for printers) + // // Note: This may require detaching the kernel driver on Linux + // intf, done, err := dev.DefaultInterface() + // if err != nil { + // log.Fatalf("Failed to claim interface: %v", err) + // } + // defer done() - // 3. Open the Bulk Output Endpoint (usually endpoint #1 or #2) - // You may need to inspect desc.Endpoints to find the correct Bulk Out ID - out, err = intf.OutEndpoint(1) - if err != nil { - log.Fatalf("Failed to open OUT endpoint: %v", err) - } - // w = bufio.NewReadWriter(bufio.NewReader(outPort), bufio.NewWriter(f)) - rw := &USBReadWriter{out: out} - reader := bufio.NewReader(rw) - writer := bufio.NewWriter(rw) - w = bufio.NewReadWriter(reader, writer) + // // 3. Open the Bulk Output Endpoint (usually endpoint #1 or #2) + // // You may need to inspect desc.Endpoints to find the correct Bulk Out ID + // out, err = intf.OutEndpoint(1) + // if err != nil { + // log.Fatalf("Failed to open OUT endpoint: %v", err) + // } + // // w = bufio.NewReadWriter(bufio.NewReader(outPort), bufio.NewWriter(f)) + // rw := &USBReadWriter{out: out} + // reader := bufio.NewReader(rw) + // writer := bufio.NewWriter(rw) + // w = bufio.NewReadWriter(reader, writer) } prt := escpos.New(w) prt.Init() prt.SetSmooth(1) + prt.SetAlign("left") + err := printImg(prt, goImagePath) if err != nil { return NewErr(err) } + prt.WriteRaw([]byte{0x1B, 0x64, 0x03}) prt.Cut() prt.End() w.Flush() - time.Sleep(100 * time.Millisecond) + time.Sleep(1 * time.Second) return NewOk(nil) } diff --git a/vo.go b/vo.go index 360fcd2..9f46f68 100644 --- a/vo.go +++ b/vo.go @@ -10,13 +10,13 @@ import ( ) type Reply struct { - Status int `json:"status"` + Status string `json:"status"` // "ok", "error" Err string `json:"err"` Result interface{} `json:"result"` } func NewErr(err error) *C.char { - e := Reply{Status: 1, Err: err.Error()} + e := Reply{Status: "error", Err: err.Error()} b, err := json.Marshal(e) if err != nil { log.Println("Error json.Marshal:", err.Error()) @@ -25,7 +25,7 @@ func NewErr(err error) *C.char { } func NewOk(data interface{}) *C.char { - e := Reply{Status: 0, Result: data} + e := Reply{Status: "ok", Result: data} b, err := json.Marshal(e) if err != nil { log.Println("Error json.Marshal:", err.Error())