Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 99189e4b51 | |||
| d8781c3981 | |||
| d7ffc17d71 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -28,3 +28,5 @@ go.work.sum
|
||||
build
|
||||
assets
|
||||
libgofunc
|
||||
libgo
|
||||
cmd/out.png
|
||||
|
||||
12
build_lib.sh
12
build_lib.sh
@@ -1,9 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
APP_NAME="libgofunc"
|
||||
VERSION="${1:-v0.1.3}"
|
||||
OUTPUT_DIR="assets"
|
||||
BUILD_DIR="build"
|
||||
VERSION="${1:-v0.1.7}"
|
||||
OUTPUT_DIR="../assets"
|
||||
BUILD_DIR="../build"
|
||||
|
||||
# need Android NDK
|
||||
NDK_HOME="$HOME/Android/Sdk/ndk/28.2.13676358" # <--- CHECK YOUR VERSION
|
||||
@@ -11,7 +11,7 @@ API=21
|
||||
|
||||
TOOLCHAIN="$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin"
|
||||
OS="$(uname -s)"
|
||||
|
||||
cd cmd
|
||||
if [ "$OS" = "Darwin" ]; then
|
||||
export IOS_SDK=$(xcrun --sdk iphoneos --show-sdk-path)
|
||||
export IOS_SIM_SDK=$(xcrun --sdk iphonesimulator --show-sdk-path)
|
||||
@@ -27,7 +27,7 @@ if [ "$OS" = "Darwin" ]; then
|
||||
CC="$(xcrun --sdk iphonesimulator --find clang)" \
|
||||
CGO_CFLAGS="-isysroot $IOS_SIM_SDK -arch x86_64" \
|
||||
CGO_LDFLAGS="-isysroot $IOS_SIM_SDK -arch x86_64" \
|
||||
go build -buildmode=c-archive -o build/ios/sim/libgofunc_arm64_sim.a .
|
||||
go build ./cmd -buildmode=c-archive -o build/ios/sim/libgofunc_arm64_sim.a .
|
||||
|
||||
# xcodebuild -create-xcframework \
|
||||
# -library build/ios/device/libgofunc_arm64.a -headers build/ios/device/ \
|
||||
@@ -74,7 +74,7 @@ elif [ "$OS" = "Linux" ]; then
|
||||
tar -czf "${OUTPUT_DIR}/${VERSION}/${ARCHIVE_NAME}" -C "${BUILD_DIR}" ./${VERSION}/${ARCH}
|
||||
|
||||
export HTTPS_PROXY="socks5://localhost:8080"
|
||||
rclone copy ./assets/${VERSION} s3:mokkon/libs/libgofunc/${VERSION}
|
||||
rclone copy ../assets/${VERSION} s3:mokkon/libs/libgofunc/${VERSION}
|
||||
else
|
||||
echo "Unsupported OS: $OS"
|
||||
exit 1
|
||||
|
||||
94
cmd/main.go
94
cmd/main.go
File diff suppressed because one or more lines are too long
@@ -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
|
||||
}
|
||||
|
||||
|
||||
32
go.mod
32
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
|
||||
)
|
||||
|
||||
134
go.sum
134
go.sum
@@ -1,148 +1,14 @@
|
||||
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=
|
||||
|
||||
149
img.go
149
img.go
@@ -24,7 +24,14 @@ import (
|
||||
|
||||
"github.com/kenshaw/escpos"
|
||||
)
|
||||
import "log"
|
||||
import (
|
||||
"log"
|
||||
"path"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/message"
|
||||
)
|
||||
|
||||
const (
|
||||
defalutFontSize = 18.0
|
||||
@@ -40,11 +47,12 @@ const (
|
||||
var fontFs embed.FS
|
||||
|
||||
//export GenPNG
|
||||
func GenPNG(width C.int, outputPath *C.char, payload *C.char, tmpl *C.char) *C.char {
|
||||
func GenPNG(width C.int, outputPath *C.char, payload *C.char, tmpl *C.char, workingDirC *C.char) *C.char {
|
||||
canvasWidth := int(width)
|
||||
goPath := C.GoString(outputPath)
|
||||
goPayload := C.GoString(payload)
|
||||
goTmpl := C.GoString(tmpl)
|
||||
workingDir := C.GoString(workingDirC)
|
||||
|
||||
data := make(map[string]interface{})
|
||||
err := json.Unmarshal([]byte(goPayload), &data)
|
||||
@@ -85,7 +93,10 @@ func GenPNG(width C.int, outputPath *C.char, payload *C.char, tmpl *C.char) *C.c
|
||||
dc.SetFontFace(*face)
|
||||
|
||||
y := 0
|
||||
renderNode(dc, canvasWidth, body, &y, *face)
|
||||
err = renderNode(dc, canvasWidth, body, &y, *face, workingDir)
|
||||
if err != nil {
|
||||
return NewErr(err)
|
||||
}
|
||||
|
||||
err = dc.SavePNG(goPath)
|
||||
if err != nil {
|
||||
@@ -96,14 +107,22 @@ func GenPNG(width C.int, outputPath *C.char, payload *C.char, tmpl *C.char) *C.c
|
||||
return NewOk(nil)
|
||||
}
|
||||
|
||||
func GenImg(width int, outputPath, payload, tmpl string) string {
|
||||
result := GenPNG(C.int(width), C.CString(outputPath), C.CString(payload), C.CString(tmpl))
|
||||
func GenImg(width int, outputPath, payload, tmpl, workingDir string) string {
|
||||
result := GenPNG(C.int(width), C.CString(outputPath), C.CString(payload), C.CString(tmpl), C.CString(workingDir))
|
||||
r := C.GoString(result)
|
||||
return r
|
||||
}
|
||||
|
||||
var funcMap = template.FuncMap{
|
||||
"formatNumber": FormatNumber,
|
||||
"div": Div,
|
||||
}
|
||||
|
||||
func renderTemplate(tmp string, data map[string]interface{}) (string, error) {
|
||||
tmpl := template.Must(template.New("mytemplate").Parse(tmp))
|
||||
tmpl, err := template.New("mytemplate").Funcs(funcMap).Parse(tmp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
if err := tmpl.Execute(&buf, data); err != nil {
|
||||
return "", err
|
||||
@@ -111,7 +130,7 @@ func renderTemplate(tmp string, data map[string]interface{}) (string, error) {
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func renderNode(dc *gg.Context, canvasWidth int, n *Node, y *int, face font.Face) {
|
||||
func renderNode(dc *gg.Context, canvasWidth int, n *Node, y *int, face font.Face, workingDir string) error {
|
||||
before := *y
|
||||
if n.Style.PaddingTop > 0 {
|
||||
*y += int(n.Style.PaddingTop)
|
||||
@@ -124,11 +143,17 @@ 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":
|
||||
drawImage(dc, n, y)
|
||||
if err := drawImage(dc, n, y, workingDir); err != nil {
|
||||
return err
|
||||
}
|
||||
case "table":
|
||||
renderTable(dc, canvasWidth, n, y, face)
|
||||
}
|
||||
@@ -138,8 +163,9 @@ func renderNode(dc *gg.Context, canvasWidth int, n *Node, y *int, face font.Face
|
||||
log.Printf("render %s y, y', height: %d, %d, %d\n", n.Tag, before, *y, *y-before)
|
||||
|
||||
for _, c := range n.Children {
|
||||
renderNode(dc, canvasWidth, c, y, face)
|
||||
renderNode(dc, canvasWidth, c, y, face, workingDir)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func drawTextBlock(dc *gg.Context, n *Node, canvasWidth int, size float64, y *int, face font.Face) {
|
||||
@@ -176,14 +202,18 @@ func wordWrap(dc *gg.Context, text string, maxWidth int) []string {
|
||||
return lines
|
||||
}
|
||||
|
||||
func drawImage(dc *gg.Context, n *Node, y *int) {
|
||||
func drawImage(dc *gg.Context, n *Node, y *int, workingDir string) error {
|
||||
src := n.getSrc()
|
||||
file, err := os.Open(src)
|
||||
s := path.Join(workingDir, src)
|
||||
file, err := os.Open(s)
|
||||
if err != nil {
|
||||
return
|
||||
return fmt.Errorf("open file src: '%s', working directory: '%s', error : %s", src, workingDir, err.Error())
|
||||
}
|
||||
defer file.Close()
|
||||
img, _, _ := image.Decode(file)
|
||||
img, _, err := image.Decode(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
padding := n.Style.PaddingLeft
|
||||
h := n.Style.Height
|
||||
if n.Style.Width > 0 {
|
||||
@@ -206,10 +236,11 @@ func drawImage(dc *gg.Context, n *Node, y *int) {
|
||||
dc.DrawImage(img, int(padding), *y)
|
||||
*y += img.Bounds().Dy()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
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 +254,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 +266,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 +284,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 +295,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 +308,7 @@ func extractRows(table *Node) [][]string {
|
||||
}
|
||||
}
|
||||
traverse(table)
|
||||
return rows
|
||||
return headers, rows
|
||||
}
|
||||
|
||||
func extractNodeRows(table *html.Node) [][]string {
|
||||
@@ -332,9 +373,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
|
||||
@@ -409,3 +455,66 @@ func nodeHeight(n *html.Node, dc *gg.Context, canvasWidth int, xPadding, yPaddin
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
type RealNumber interface {
|
||||
~int | ~int8 | ~int16 | ~int32 | ~int64 |
|
||||
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 |
|
||||
~float32 | ~float64
|
||||
}
|
||||
|
||||
func FormatNumber(precision int, b any) string {
|
||||
return GenericFormatNumber(precision, convertToFloat64(b))
|
||||
}
|
||||
|
||||
func GenericFormatNumber[T RealNumber](precision int, v T) string {
|
||||
pEnglish := message.NewPrinter(language.English)
|
||||
|
||||
n := float64(v)
|
||||
s := fmt.Sprintf("%.*f", precision, n)
|
||||
|
||||
parts := strings.Split(s, ".")
|
||||
intPart := parts[0]
|
||||
i, err := strconv.Atoi(intPart)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
out := pEnglish.Sprintf("%d", i)
|
||||
|
||||
if len(parts) > 1 {
|
||||
return out + "." + parts[1]
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func Div(a, b any) float64 {
|
||||
return GenericDiv(convertToFloat64(a), convertToFloat64(b))
|
||||
}
|
||||
|
||||
func GenericDiv[T RealNumber](a, b T) float64 {
|
||||
floatB := float64(b)
|
||||
if floatB == 0 {
|
||||
return 0
|
||||
}
|
||||
return float64(a) / floatB
|
||||
}
|
||||
|
||||
func convertToFloat64(v any) float64 {
|
||||
switch t := v.(type) {
|
||||
case float64:
|
||||
return t
|
||||
case float32:
|
||||
return float64(t)
|
||||
case int:
|
||||
return float64(t)
|
||||
case int64:
|
||||
return float64(t)
|
||||
case int32:
|
||||
return float64(t)
|
||||
case uint:
|
||||
return float64(t)
|
||||
case uint64:
|
||||
return float64(t)
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
60
img_test.go
Normal file
60
img_test.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package libgofunc
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDiv(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
a any
|
||||
b any
|
||||
want float64
|
||||
}{
|
||||
{"Float division", 10.5, 2.0, 5.25},
|
||||
{"Float division", 4975, 1000, 4.975},
|
||||
{"Integer division", 10, 4, 2.5},
|
||||
{"Mixed types", int64(100), float64(4.0), 25.0},
|
||||
{"Division by zero (float)", 10.0, 0.0, 0.0},
|
||||
{"Division by zero (int)", 5, 0, 0.0},
|
||||
{"Unsupported type defaults to zero", "string", 2, 0.0},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := Div(tt.a, tt.b)
|
||||
if got != tt.want {
|
||||
t.Errorf("TemplateDiv() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatNumber(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
precision int
|
||||
val any
|
||||
want string
|
||||
}{
|
||||
{"Standard float with commas", 2, 1234567.891, "1,234,567.89"},
|
||||
{"Standard float with commas", 3, 4.975, "4.975"},
|
||||
{"Integer input with commas", 0, 5000000, "5,000,000"},
|
||||
{"Integer input forced decimals", 2, 5000, "5,000.00"},
|
||||
{"Negative float commas", 2, -9876543.21, "-9,876,543.21"},
|
||||
{"Small float rounding up", 2, 0.128, "0.13"},
|
||||
{"Small float rounding down", 2, 0.123, "0.12"},
|
||||
{"Handling NaN", 2, math.NaN(), ""},
|
||||
{"Handling Inf", 2, math.Inf(1), ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := FormatNumber(tt.precision, tt.val)
|
||||
if got != tt.want {
|
||||
t.Errorf("TemplateFloat() = %q, want %q", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
94
printer.go
94
printer.go
@@ -17,33 +17,12 @@ 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)
|
||||
}
|
||||
import "errors"
|
||||
|
||||
//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 +44,58 @@ 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)
|
||||
} else {
|
||||
return NewErr(errors.New("invalid printer"))
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
6
vo.go
6
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())
|
||||
|
||||
Reference in New Issue
Block a user