diff --git a/README.md b/README.md index 248e1b1d..6cfbbddb 100644 --- a/README.md +++ b/README.md @@ -719,7 +719,7 @@ print("run[CQ:image,file="+j["img"]+"]") `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/font"` - - [x] (用[终末体|终末变体|紫罗兰体|樱酥体|Consolas体|苹方体])渲染文字xxx + - [x] (用[终末体|终末变体|紫罗兰体|樱酥体|Consolas体|苹方体])渲染(抖动)文字xxx
每日运势 diff --git a/plugin/font/main.go b/plugin/font/main.go index d77553c1..06657a8c 100644 --- a/plugin/font/main.go +++ b/plugin/font/main.go @@ -2,7 +2,17 @@ package font import ( + "bytes" + "image" + "image/color" + "image/gif" + "math/rand" + "strings" + "github.com/FloatTech/floatbox/binary" + "github.com/FloatTech/floatbox/file" + "github.com/FloatTech/gg" + "github.com/FloatTech/imgfactory" ctrl "github.com/FloatTech/zbpctrl" "github.com/FloatTech/zbputils/control" "github.com/FloatTech/zbputils/ctxext" @@ -15,10 +25,10 @@ func init() { control.Register("font", &ctrl.Options[*zero.Ctx]{ DisableOnDefault: false, Brief: "渲染任意文字到图片", - Help: "- (用[字体])渲染文字xxx\n可选字体: [终末体|终末变体|紫罗兰体|樱酥体|Consolas体|苹方体]", - }).OnRegex(`^(用.+)?渲染文字([\s\S]+)$`).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) { + Help: "- (用[字体])渲染(抖动)文字xxx\n可选字体: [终末体|终末变体|紫罗兰体|樱酥体|Consolas体|苹方体]", + }).OnRegex(`^(用.+)?渲染(抖动)?文字([\s\S]+)$`).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) { fnt := ctx.State["regex_matched"].([]string)[1] - txt := ctx.State["regex_matched"].([]string)[2] + txt := ctx.State["regex_matched"].([]string)[3] switch fnt { case "用终末体": fnt = text.SyumatuFontFile @@ -35,11 +45,56 @@ func init() { default: fnt = text.FontFile } - b, err := text.RenderToBase64(txt, fnt, 400, 20) + if ctx.State["regex_matched"].([]string)[2] == "" { + b, err := text.RenderToBase64(txt, fnt, 400, 20) + if err != nil { + ctx.SendChain(message.Text("ERROR: ", err)) + return + } + ctx.SendChain(message.Image("base64://" + binary.BytesToString(b))) + return + } + nilx, nily := 1.0, 8.0 + s := []*image.NRGBA{} + strlist := strings.Split(txt, "\n") + data, err := file.GetLazyData(fnt, control.Md5File, true) if err != nil { ctx.SendChain(message.Text("ERROR: ", err)) return } - ctx.SendChain(message.Image("base64://" + binary.BytesToString(b))) + //获得画布预计 + testcov := gg.NewContext(1, 1) + if err = testcov.ParseFontFace(data, 30); err != nil { + ctx.SendChain(message.Text("ERROR: ", err)) + return + } + //取最长段 + txt = "" + for _, v := range strlist { + if len([]rune(v)) > len([]rune(txt)) { + txt = v + } + } + w, h := testcov.MeasureString(txt) + for i := 0; i < 10; i++ { + cov := gg.NewContext(int(w+float64(len([]rune(txt)))*nilx)+40, int(h+nily)*len(strlist)+30) + cov.SetRGB(1, 1, 1) + cov.Clear() + if err = cov.ParseFontFace(data, 30); err != nil { + ctx.SendChain(message.Text("ERROR: ", err)) + return + } + cov.SetColor(color.NRGBA{R: 0, G: 0, B: 0, A: 127}) + for k, v := range strlist { + for kk, vv := range []rune(v) { + x, y := cov.MeasureString(string([]rune(v)[:kk])) + cov.DrawString(string(vv), x+float64(rand.Intn(5))+10+nilx, y+float64(rand.Intn(5))+15+float64(k)*(y+nily)) + } + } + s = append(s, imgfactory.Size(cov.Image(), 0, 0).Image()) + } + var buf bytes.Buffer + _ = gif.EncodeAll(&buf, imgfactory.MergeGif(5, s)) + ctx.SendChain(message.ImageBytes(buf.Bytes())) }) }