draw.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package dao
  2. import (
  3. "image"
  4. "image/draw"
  5. "io/ioutil"
  6. "math"
  7. "unicode/utf8"
  8. "go-common/library/log"
  9. "github.com/golang/freetype"
  10. "golang.org/x/image/font"
  11. "golang.org/x/image/math/fixed"
  12. )
  13. // TextImgConf text img conf.
  14. type TextImgConf struct {
  15. Fontsize int
  16. Length int
  17. Ansfontsize int
  18. Spacing float64
  19. Ansspacing float64
  20. }
  21. // QueConf question img conf.
  22. func (d *Dao) QueConf(mobile bool) (c *TextImgConf) {
  23. if mobile {
  24. // Mobile
  25. c = &TextImgConf{
  26. Fontsize: 16, // mobile font size in points
  27. Length: 11, // mobile question length
  28. Ansfontsize: 12, // mobile ans font size in points
  29. }
  30. } else {
  31. // PC
  32. c = &TextImgConf{
  33. Fontsize: 12, //font size in points
  34. Length: 36, //question length
  35. Ansfontsize: 10, //ans font size in points
  36. }
  37. }
  38. c.Spacing = 2 // line spacing (e.g. 2 means double spaced)
  39. c.Ansspacing = 2 // line ansspacing (e.g. 2 means double spaced)
  40. return
  41. }
  42. // DrawQue draw question title.
  43. func (d *Dao) DrawQue(c *freetype.Context, s string, conf *TextImgConf, pt *fixed.Point26_6) {
  44. c.SetFontSize(float64(conf.Fontsize))
  45. srune := []rune(s)
  46. var end = conf.Length
  47. for len(srune) > 0 {
  48. if conf.Length > len(srune) {
  49. end = len(srune)
  50. }
  51. d.text(c, string(srune[:end]), pt, conf.Fontsize, conf.Spacing)
  52. srune = srune[end:]
  53. }
  54. }
  55. // DrawAns draw ans
  56. func (d *Dao) DrawAns(c *freetype.Context, conf *TextImgConf, anss [2]string, pt *fixed.Point26_6) {
  57. c.SetFontSize(float64(conf.Ansfontsize))
  58. arr := [4]string{"A.", "B."}
  59. for i, a := range anss {
  60. d.text(c, arr[i]+a, pt, conf.Ansfontsize, conf.Ansspacing)
  61. }
  62. }
  63. // Board init draw board.
  64. func (d *Dao) Board(h int) (r *image.Gray) {
  65. bg := image.White
  66. r = image.NewGray(image.Rect(0, 0, 600, h))
  67. draw.Draw(r, r.Bounds(), bg, image.ZP, draw.Src)
  68. return
  69. }
  70. //Height get img height
  71. func (d *Dao) Height(c *TextImgConf, que string, anslen int) (h int) {
  72. len := utf8.RuneCountInString(que)
  73. line := math.Ceil(float64(len) / float64(c.Length))
  74. h = int(math.Ceil(c.Spacing*line*float64(c.Fontsize))) + int(math.Ceil(c.Ansspacing*float64(anslen)*float64(c.Ansfontsize)))
  75. return
  76. }
  77. // text Draw text.
  78. func (d *Dao) text(c *freetype.Context, s string, pt *fixed.Point26_6, size int, spacing float64) (err error) {
  79. _, err = c.DrawString(s, *pt)
  80. if err != nil {
  81. log.Error("c.DrawString() error:%+v", err)
  82. return
  83. }
  84. pt.Y += fixed.Int26_6(int(float64(size)*spacing) << 6)
  85. return
  86. }
  87. var (
  88. dpi = float64(72) // screen resolution in Dots Per Inch
  89. hinting = "none" // none | full
  90. )
  91. // Context freetype init context.
  92. func (d *Dao) Context(r *image.Gray, fileStr string) (c *freetype.Context) {
  93. fg := image.Black
  94. // Read the font data.
  95. fontBytes, err := ioutil.ReadFile(fileStr)
  96. if err != nil {
  97. log.Error("ioutil.ReadFile(%s) error:%+v", fileStr, err)
  98. return
  99. }
  100. f, err := freetype.ParseFont(fontBytes)
  101. if err != nil {
  102. log.Error("freetype.ParseFont(%s) error:%+v", fileStr, err)
  103. return
  104. }
  105. c = freetype.NewContext()
  106. c.SetDPI(dpi)
  107. c.SetFont(f)
  108. c.SetClip(r.Bounds())
  109. c.SetDst(r)
  110. c.SetSrc(fg)
  111. switch hinting {
  112. default:
  113. c.SetHinting(font.HintingNone)
  114. case "full":
  115. c.SetHinting(font.HintingFull)
  116. }
  117. return
  118. }