driver_language.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package base64Captcha
  2. import (
  3. "fmt"
  4. "image/color"
  5. "math/rand"
  6. "github.com/golang/freetype/truetype"
  7. )
  8. //https://en.wikipedia.org/wiki/Unicode_block
  9. var langMap = map[string][]int{
  10. //"zh-CN": []int{19968, 40869},
  11. "latin": {0x0000, 0x007f},
  12. "zh": {0x4e00, 0x9fa5},
  13. "ko": {12593, 12686},
  14. "jp": {12449, 12531}, //[]int{12353, 12435}
  15. "ru": {1025, 1169},
  16. "th": {0x0e00, 0x0e7f},
  17. "greek": {0x0380, 0x03ff},
  18. "arabic": {0x0600, 0x06ff},
  19. "hebrew": {0x0590, 0x05ff},
  20. //"emotion": []int{0x1f601, 0x1f64f},
  21. }
  22. func generateRandomRune(size int, code string) string {
  23. lang, ok := langMap[code]
  24. if !ok {
  25. fmt.Sprintf("can not font language of %s", code)
  26. lang = langMap["latin"]
  27. }
  28. start := lang[0]
  29. end := lang[1]
  30. randRune := make([]rune, size)
  31. for i := range randRune {
  32. idx := rand.Intn(end-start) + start
  33. randRune[i] = rune(idx)
  34. }
  35. return string(randRune)
  36. }
  37. //DriverLanguage generates language unicode by lanuage
  38. type DriverLanguage struct {
  39. // Height png height in pixel.
  40. Height int
  41. // Width Captcha png width in pixel.
  42. Width int
  43. //NoiseCount text noise count.
  44. NoiseCount int
  45. //ShowLineOptions := OptionShowHollowLine | OptionShowSlimeLine | OptionShowSineLine .
  46. ShowLineOptions int
  47. //Length random string length.
  48. Length int
  49. //BgColor captcha image background color (optional)
  50. BgColor *color.RGBA
  51. //fontsStorage font storage (optional)
  52. fontsStorage FontsStorage
  53. //Fonts loads by name see fonts.go's comment
  54. Fonts []*truetype.Font
  55. LanguageCode string
  56. }
  57. //NewDriverLanguage creates a driver
  58. func NewDriverLanguage(height int, width int, noiseCount int, showLineOptions int, length int, bgColor *color.RGBA, fontsStorage FontsStorage, fonts []*truetype.Font, languageCode string) *DriverLanguage {
  59. return &DriverLanguage{Height: height, Width: width, NoiseCount: noiseCount, ShowLineOptions: showLineOptions, Length: length, BgColor: bgColor, fontsStorage: fontsStorage, Fonts: fonts, LanguageCode: languageCode}
  60. }
  61. //GenerateIdQuestionAnswer creates content and answer
  62. func (d *DriverLanguage) GenerateIdQuestionAnswer() (id, content, answer string) {
  63. id = RandomId()
  64. content = generateRandomRune(d.Length, d.LanguageCode)
  65. return id, content, content
  66. }
  67. //DrawCaptcha creates item
  68. func (d *DriverLanguage) DrawCaptcha(content string) (item Item, err error) {
  69. var bgc color.RGBA
  70. if d.BgColor != nil {
  71. bgc = *d.BgColor
  72. } else {
  73. bgc = RandLightColor()
  74. }
  75. itemChar := NewItemChar(d.Width, d.Height, bgc)
  76. //draw hollow line
  77. if d.ShowLineOptions&OptionShowHollowLine == OptionShowHollowLine {
  78. itemChar.drawHollowLine()
  79. }
  80. //draw slime line
  81. if d.ShowLineOptions&OptionShowSlimeLine == OptionShowSlimeLine {
  82. itemChar.drawSlimLine(3)
  83. }
  84. //draw sine line
  85. if d.ShowLineOptions&OptionShowSineLine == OptionShowSineLine {
  86. itemChar.drawSineLine()
  87. }
  88. //draw noise
  89. if d.NoiseCount > 0 {
  90. noise := RandText(d.NoiseCount, TxtNumbers+TxtAlphabet+",.[]<>")
  91. err = itemChar.drawNoise(noise, fontsAll)
  92. if err != nil {
  93. return
  94. }
  95. }
  96. //draw content
  97. //use font that match your language
  98. err = itemChar.drawText(content, []*truetype.Font{fontChinese})
  99. if err != nil {
  100. return
  101. }
  102. return itemChar, nil
  103. }