Skip to content

Instantly share code, notes, and snippets.

@tommy351
Created November 7, 2016 06:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tommy351/12017c09c650fe6b19f93f3e383f6705 to your computer and use it in GitHub Desktop.
Save tommy351/12017c09c650fe6b19f93f3e383f6705 to your computer and use it in GitHub Desktop.
func drawLine(gc *draw2dimg.GraphicContext, str string, maxX float64, maxY float64, x float64, y float64) (bool, float64) {
// Handle empty line
if len(strings.TrimSpace(str)) == 0 {
return false, y + gc.Current.FontSize*lineHeight
}
list := []rune(str)
length := len(list)
offsetX := x
offsetY := y
fontSize := gc.Current.FontSize
lineSize := fontSize * lineHeight
for i := 0; i < length; i++ {
chunk := string(list[i])
if isEmoji(chunk) {
emojis := []rune{list[i]}
for j := 1; j <= 6 && i+j < length && (isEmoji(string(list[i+j])) || isZWJ(string(list[i+j]))); j++ {
emojis = append(emojis, list[i+j])
}
var img image.Image
var err error
for j := len(emojis); j > 0; j-- {
img, err = loadEmoji(emojis[:j])
if err != nil {
continue
}
i = i + j - 1
break
}
if err != nil {
continue
}
rect := img.Bounds()
dx := float64(rect.Dx())
dy := float64(rect.Dy())
gc.Save()
gc.Translate(offsetX, offsetY-fontSize)
gc.Scale(fontSize/dx, fontSize/dy)
gc.DrawImage(img)
gc.Restore()
offsetX += fontSize
continue
}
textWidth := gc.FillStringAt(chunk, offsetX, offsetY)
offsetX += textWidth
if offsetX >= maxX {
newY := offsetY + lineSize
if newY >= maxY {
return true, offsetY
}
offsetX = x
offsetY = newY
}
}
offsetY += lineSize
return false, offsetY
}
func isRuneBetween(r rune, from rune, to rune) bool {
return r >= from && r <= to
}
func isEmoji(s string) bool {
r, size := utf8.DecodeRuneInString(s)
if size > 3 {
return true
}
return isRuneBetween(r, 0x2700, 0x27bf) || // Dingbats
isRuneBetween(r, 0x2600, 0x26ff) || // Miscellaneous Symbols
isRuneBetween(r, 0x2b00, 0x2bff) || // Miscellaneous Symbols and Arrows
isRuneBetween(r, 0x25a0, 0x25ff) || // Geometric Shapes
isRuneBetween(r, 0x20d0, 0x20ff) // Combining Diacritical Marks for Symbols
}
func isZWJ(s string) bool {
r, _ := utf8.DecodeRuneInString(s)
return isRuneBetween(r, 0x200d, 0x200d)
}
func loadEmoji(emojis []rune) (image.Image, error) {
var codes []string
for _, r := range emojis {
if !isZWJ(string(r)) {
codes = append(codes, strconv.FormatInt(int64(r), 16))
}
}
code := strings.Join(codes, "-")
path := path.Join(emojiDir, code+".png")
return images.Get(path)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment