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.
123 lines
3.1 KiB
123 lines
3.1 KiB
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 |
|
}
|
|
|