Start work on emoji (mostly to be scrapped tho)

This commit is contained in:
Hamcha 2018-11-14 18:08:36 +01:00
parent 1d07a50459
commit 752f9e4be4
Signed by: hamcha
GPG key ID: A40413D21021EAEE
4 changed files with 218 additions and 2 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
noto_emojis
example/emojis/out.png

76
emoji.go Normal file
View file

@ -0,0 +1,76 @@
package freetype
import (
"errors"
"fmt"
"strings"
"unicode/utf8"
)
type Emoji struct {
Codepoints []rune
Bytes int
}
var (
errNotAnEmoji = errors.New("not an emoji")
)
func inrange(val, min, max rune) bool {
return val >= min && val < max
}
// https://stackoverflow.com/questions/30757193/find-out-if-character-in-string-is-emoji/39425959
func isEmoji(chr rune) bool {
switch {
case inrange(chr, 0x1f600, 0x1f64f), // Emoticons
inrange(chr, 0x1f300, 0x1f5ff), // Misc Symbols and Pictographs
inrange(chr, 0x1f680, 0x1f6ff), // Transport and Map
inrange(chr, 0x1f1e6, 0x1f1ff), // Regional country flags
inrange(chr, 0x2600, 0x26ff), // Misc symbols
inrange(chr, 0x2700, 0x27bf), // Dingbats
inrange(chr, 0xfe00, 0xfe0f), // Variation Selectors
inrange(chr, 0x1f900, 0x1f9ff), // Supplemental Symbols and Pictographs
inrange(chr, 127000, 127600), // Various asian characters
inrange(chr, 65024, 65039), // Variation selector
inrange(chr, 9100, 9300), // Misc items
inrange(chr, 8400, 8447): // Combining Diacritical Marks for Symbols
return true
}
return false
}
func isZWJ(chr rune) bool {
return chr == 8205
}
func parseEmoji(str string) (Emoji, error) {
if len(str) < 1 {
return Emoji{}, errNotAnEmoji
}
emoji := Emoji{}
for _, r := range str {
// Check if rune is emoji
if !isEmoji(r) && !isZWJ(r) {
if len(emoji.Codepoints) < 1 {
return emoji, errNotAnEmoji
}
break
}
emoji.Codepoints = append(emoji.Codepoints, r)
emoji.Bytes += utf8.RuneLen(r)
}
return emoji, nil
}
func (e Emoji) String() string {
codepoints := []string{}
for _, cp := range e.Codepoints {
codepoints = append(codepoints, fmt.Sprintf("%U", cp))
}
return "Emoji(" + strings.Join(codepoints, ", ") + ")"
}

124
example/emojis/main.go Normal file
View file

@ -0,0 +1,124 @@
// Copyright 2010 The Freetype-Go Authors. All rights reserved.
// Use of this source code is governed by your choice of either the
// FreeType License or the GNU General Public License version 2 (or
// any later version), both of which can be found in the LICENSE file.
// +build example
//
// This build tag means that "go install github.com/golang/freetype/..."
// doesn't install this example program. Use "go run main.go" to run it or "go
// install -tags=example" to install it.
package main
import (
"bufio"
"flag"
"fmt"
"image"
"image/color"
"image/draw"
"image/png"
"io/ioutil"
"log"
"os"
"git.fromouter.space/crunchy-rocks/freetype"
"golang.org/x/image/font"
)
var (
dpi = flag.Float64("dpi", 72, "screen resolution in Dots Per Inch")
fontfile = flag.String("fontfile", "../../testdata/luxisr.ttf", "filename of the ttf font")
hinting = flag.String("hinting", "none", "none | full")
size = flag.Float64("size", 20, "font size in points")
spacing = flag.Float64("spacing", 1.5, "line spacing (e.g. 2 means double spaced)")
wonb = flag.Bool("whiteonblack", false, "white text on a black background")
)
var text = []string{
"Single glyph emoji: 😂",
"Gender-modified emoji: 💂‍♀️",
"Skin-modified emoji: 🖐🏽",
"Mixed emoji: 👩‍👩‍👧‍👧",
"👌👀👌👀👌👀👌👀👌👀 good shit goԁ sHit👌 thats ✔ some good👌👌shit right👌👌",
"th 👌 ere👌👌👌 right✔there ✔✔if i doƽaү somy sel 💯 i say so ",
"💯 thats what im talking about right there right there (chorus: ʳᶦᵍʰᵗ ᵗʰᵉʳᵉ)",
"mMMMMМ💯 👌👌 👌НO0ОOOOОOoooᵒᵒᵒᵒᵒᵒᵒᵒᵒ👌 👌👌 👌 💯 👌 👀 👀 👀 👌👌Good shit",
}
func main() {
flag.Parse()
// Read the font data.
fontBytes, err := ioutil.ReadFile(*fontfile)
if err != nil {
log.Println(err)
return
}
f, err := freetype.ParseFont(fontBytes)
if err != nil {
log.Println(err)
return
}
// Initialize the context.
fg, bg := image.Black, image.White
ruler := color.RGBA{0xdd, 0xdd, 0xdd, 0xff}
if *wonb {
fg, bg = image.White, image.Black
ruler = color.RGBA{0x22, 0x22, 0x22, 0xff}
}
rgba := image.NewRGBA(image.Rect(0, 0, 640, 480))
draw.Draw(rgba, rgba.Bounds(), bg, image.ZP, draw.Src)
c := freetype.NewContext()
c.SetDPI(*dpi)
c.SetFont(f)
c.SetFontSize(*size)
c.SetClip(rgba.Bounds())
c.SetDst(rgba)
c.SetSrc(fg)
switch *hinting {
default:
c.SetHinting(font.HintingNone)
case "full":
c.SetHinting(font.HintingFull)
}
// Draw the guidelines.
for i := 0; i < 200; i++ {
rgba.Set(10, 10+i, ruler)
rgba.Set(10+i, 10, ruler)
}
// Draw the text.
pt := freetype.Pt(10, 10+int(c.PointToFixed(*size)>>6))
for _, s := range text {
_, err = c.DrawString(s, pt)
if err != nil {
log.Println(err)
return
}
pt.Y += c.PointToFixed(*size * *spacing)
}
// Save that RGBA image to disk.
outFile, err := os.Create("out.png")
if err != nil {
log.Println(err)
os.Exit(1)
}
defer outFile.Close()
b := bufio.NewWriter(outFile)
err = png.Encode(b, rgba)
if err != nil {
log.Println(err)
os.Exit(1)
}
err = b.Flush()
if err != nil {
log.Println(err)
os.Exit(1)
}
fmt.Println("Wrote out.png OK.")
}

View file

@ -10,6 +10,7 @@ package freetype // import "git.fromouter.space/crunchy-rocks/freetype"
import (
"errors"
"fmt"
"image"
"image/draw"
@ -232,8 +233,21 @@ func (c *Context) DrawString(s string, p fixed.Point26_6) (fixed.Point26_6, erro
return fixed.Point26_6{}, errors.New("freetype: DrawText called with a nil font")
}
prev, hasPrev := truetype.Index(0), false
for _, rune := range s {
index := c.f.Index(rune)
nextchar := 0
for index, r := range s {
// Check if we need to skip entries
if nextchar > index {
continue
}
// Check if rune is an emoji
if isEmoji(r) {
emoji, err := parseEmoji(s[index:])
if err == nil {
fmt.Println("Found emoji:", emoji)
nextchar = index + emoji.Bytes
}
}
index := c.f.Index(r)
if hasPrev {
kern := c.f.Kern(c.scale, prev, index)
if c.hinting != font.HintingNone {