driver_math.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. package base64Captcha
  2. import (
  3. "fmt"
  4. "image/color"
  5. "math/rand"
  6. "strings"
  7. "github.com/golang/freetype/truetype"
  8. )
  9. //DriverMath captcha config for captcha math
  10. type DriverMath struct {
  11. //Height png height in pixel.
  12. Height int
  13. // Width Captcha png width in pixel.
  14. Width int
  15. //NoiseCount text noise count.
  16. NoiseCount int
  17. //ShowLineOptions := OptionShowHollowLine | OptionShowSlimeLine | OptionShowSineLine .
  18. ShowLineOptions int
  19. //BgColor captcha image background color (optional)
  20. BgColor *color.RGBA
  21. //fontsStorage font storage (optional)
  22. fontsStorage FontsStorage
  23. //Fonts loads by name see fonts.go's comment
  24. Fonts []string
  25. fontsArray []*truetype.Font
  26. }
  27. //NewDriverMath creates a driver of math
  28. func NewDriverMath(height int, width int, noiseCount int, showLineOptions int, bgColor *color.RGBA, fontsStorage FontsStorage, fonts []string) *DriverMath {
  29. if fontsStorage == nil {
  30. fontsStorage = DefaultEmbeddedFonts
  31. }
  32. tfs := []*truetype.Font{}
  33. for _, fff := range fonts {
  34. tf := fontsStorage.LoadFontByName("fonts/" + fff)
  35. tfs = append(tfs, tf)
  36. }
  37. if len(tfs) == 0 {
  38. tfs = fontsAll
  39. }
  40. return &DriverMath{Height: height, Width: width, NoiseCount: noiseCount, ShowLineOptions: showLineOptions, fontsArray: tfs, BgColor: bgColor, Fonts: fonts}
  41. }
  42. //ConvertFonts loads fonts from names
  43. func (d *DriverMath) ConvertFonts() *DriverMath {
  44. if d.fontsStorage == nil {
  45. d.fontsStorage = DefaultEmbeddedFonts
  46. }
  47. tfs := []*truetype.Font{}
  48. for _, fff := range d.Fonts {
  49. tf := d.fontsStorage.LoadFontByName("fonts/" + fff)
  50. tfs = append(tfs, tf)
  51. }
  52. if len(tfs) == 0 {
  53. tfs = fontsAll
  54. }
  55. d.fontsArray = tfs
  56. return d
  57. }
  58. //GenerateIdQuestionAnswer creates id,captcha content and answer
  59. func (d *DriverMath) GenerateIdQuestionAnswer() (id, question, answer string) {
  60. id = RandomId()
  61. operators := []string{"+", "-", "x"}
  62. var mathResult int32
  63. switch operators[rand.Int31n(3)] {
  64. case "+":
  65. a := rand.Int31n(20)
  66. b := rand.Int31n(20)
  67. question = fmt.Sprintf("%d+%d=?", a, b)
  68. mathResult = a + b
  69. case "x":
  70. a := rand.Int31n(10)
  71. b := rand.Int31n(10)
  72. question = fmt.Sprintf("%dx%d=?", a, b)
  73. mathResult = a * b
  74. default:
  75. a := rand.Int31n(80) + rand.Int31n(20)
  76. b := rand.Int31n(80)
  77. question = fmt.Sprintf("%d-%d=?", a, b)
  78. mathResult = a - b
  79. }
  80. answer = fmt.Sprintf("%d", mathResult)
  81. return
  82. }
  83. //DrawCaptcha creates math captcha item
  84. func (d *DriverMath) DrawCaptcha(question string) (item Item, err error) {
  85. var bgc color.RGBA
  86. if d.BgColor != nil {
  87. bgc = *d.BgColor
  88. } else {
  89. bgc = RandLightColor()
  90. }
  91. itemChar := NewItemChar(d.Width, d.Height, bgc)
  92. //波浪线 比较丑
  93. if d.ShowLineOptions&OptionShowHollowLine == OptionShowHollowLine {
  94. itemChar.drawHollowLine()
  95. }
  96. //背景有文字干扰
  97. if d.NoiseCount > 0 {
  98. noise := RandText(d.NoiseCount, strings.Repeat(TxtNumbers, d.NoiseCount))
  99. err = itemChar.drawNoise(noise, fontsAll)
  100. if err != nil {
  101. return
  102. }
  103. }
  104. //画 细直线 (n 条)
  105. if d.ShowLineOptions&OptionShowSlimeLine == OptionShowSlimeLine {
  106. itemChar.drawSlimLine(3)
  107. }
  108. //画 多个小波浪线
  109. if d.ShowLineOptions&OptionShowSineLine == OptionShowSineLine {
  110. itemChar.drawSineLine()
  111. }
  112. //draw question
  113. err = itemChar.drawText(question, d.fontsArray)
  114. if err != nil {
  115. return
  116. }
  117. return itemChar, nil
  118. }