You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
3.1 KiB

2 years ago
package base64Captcha
import (
"fmt"
"image/color"
"math/rand"
"github.com/golang/freetype/truetype"
)
//https://en.wikipedia.org/wiki/Unicode_block
var langMap = map[string][]int{
//"zh-CN": []int{19968, 40869},
"latin": {0x0000, 0x007f},
"zh": {0x4e00, 0x9fa5},
"ko": {12593, 12686},
"jp": {12449, 12531}, //[]int{12353, 12435}
"ru": {1025, 1169},
"th": {0x0e00, 0x0e7f},
"greek": {0x0380, 0x03ff},
"arabic": {0x0600, 0x06ff},
"hebrew": {0x0590, 0x05ff},
//"emotion": []int{0x1f601, 0x1f64f},
}
func generateRandomRune(size int, code string) string {
lang, ok := langMap[code]
if !ok {
fmt.Sprintf("can not font language of %s", code)
lang = langMap["latin"]
}
start := lang[0]
end := lang[1]
randRune := make([]rune, size)
for i := range randRune {
idx := rand.Intn(end-start) + start
randRune[i] = rune(idx)
}
return string(randRune)
}
//DriverLanguage generates language unicode by lanuage
type DriverLanguage struct {
// Height png height in pixel.
Height int
// Width Captcha png width in pixel.
Width int
//NoiseCount text noise count.
NoiseCount int
//ShowLineOptions := OptionShowHollowLine | OptionShowSlimeLine | OptionShowSineLine .
ShowLineOptions int
//Length random string length.
Length int
//BgColor captcha image background color (optional)
BgColor *color.RGBA
//fontsStorage font storage (optional)
fontsStorage FontsStorage
//Fonts loads by name see fonts.go's comment
Fonts []*truetype.Font
LanguageCode string
}
//NewDriverLanguage creates a driver
func NewDriverLanguage(height int, width int, noiseCount int, showLineOptions int, length int, bgColor *color.RGBA, fontsStorage FontsStorage, fonts []*truetype.Font, languageCode string) *DriverLanguage {
return &DriverLanguage{Height: height, Width: width, NoiseCount: noiseCount, ShowLineOptions: showLineOptions, Length: length, BgColor: bgColor, fontsStorage: fontsStorage, Fonts: fonts, LanguageCode: languageCode}
}
//GenerateIdQuestionAnswer creates content and answer
func (d *DriverLanguage) GenerateIdQuestionAnswer() (id, content, answer string) {
id = RandomId()
content = generateRandomRune(d.Length, d.LanguageCode)
return id, content, content
}
//DrawCaptcha creates item
func (d *DriverLanguage) DrawCaptcha(content string) (item Item, err error) {
var bgc color.RGBA
if d.BgColor != nil {
bgc = *d.BgColor
} else {
bgc = RandLightColor()
}
itemChar := NewItemChar(d.Width, d.Height, bgc)
//draw hollow line
if d.ShowLineOptions&OptionShowHollowLine == OptionShowHollowLine {
itemChar.drawHollowLine()
}
//draw slime line
if d.ShowLineOptions&OptionShowSlimeLine == OptionShowSlimeLine {
itemChar.drawSlimLine(3)
}
//draw sine line
if d.ShowLineOptions&OptionShowSineLine == OptionShowSineLine {
itemChar.drawSineLine()
}
//draw noise
if d.NoiseCount > 0 {
noise := RandText(d.NoiseCount, TxtNumbers+TxtAlphabet+",.[]<>")
err = itemChar.drawNoise(noise, fontsAll)
if err != nil {
return
}
}
//draw content
//use font that match your language
err = itemChar.drawText(content, []*truetype.Font{fontChinese})
if err != nil {
return
}
return itemChar, nil
}