From 3f9492b69473aa4082901c4ec80da6c101138d05 Mon Sep 17 00:00:00 2001 From: ptrcnull Date: Sun, 2 Jan 2022 07:08:11 +0100 Subject: [PATCH] refactor: Clean up code --- README.md | 5 ++ app_clock.go | 27 ++++++++++ app_simpleclock.go | 27 ++++++++++ main.go | 125 +++++++++------------------------------------ system/battery.go | 18 +++++++ text.go | 63 +++++++++++++++++++++++ 6 files changed, 163 insertions(+), 102 deletions(-) create mode 100644 README.md create mode 100644 app_clock.go create mode 100644 app_simpleclock.go create mode 100644 system/battery.go create mode 100644 text.go diff --git a/README.md b/README.md new file mode 100644 index 0000000..156a767 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# watchface + +Custom watch face for ~~Ticwatch C2+~~ any watch running Linux with RGBA /dev/fb0 and 360x360 resolution + +**Warning: this code is ugly and might be unstable** diff --git a/app_clock.go b/app_clock.go new file mode 100644 index 0000000..b5b4158 --- /dev/null +++ b/app_clock.go @@ -0,0 +1,27 @@ +package main + +import ( + "git.ddd.rip/ptrcnull/watchface/system" + "time" +) + +var ClockTime = Text(62, 162, 8, 36, LightGray) +var ClockBattery = Text(90, 240, 3, 24, LightGray) + +type Clock struct{} + +func (s Clock) Init(face *Face) { + s.draw(face, time.Now()) +} + +func (s Clock) Render(face *Face) { + t := time.Now() + if t.Second() == 0 { + s.draw(face, t) + } +} + +func (Clock) draw(face *Face, t time.Time) { + face.Text(ClockTime, t.Format("15:04")) + face.Text(ClockBattery, system.GetBattery()) +} diff --git a/app_simpleclock.go b/app_simpleclock.go new file mode 100644 index 0000000..27b530d --- /dev/null +++ b/app_simpleclock.go @@ -0,0 +1,27 @@ +package main + +import ( + "git.ddd.rip/ptrcnull/watchface/system" + "time" +) + +var SimpleClockTime = Text(108, 162, 5, 36, LightGray) +var SimpleClockBattery = Text(90, 240, 3, 24, LightGray) + +type SimpleClock struct{} + +func (s SimpleClock) Init(face *Face) { + s.draw(face, time.Now()) +} + +func (s SimpleClock) Render(face *Face) { + t := time.Now() + if t.Second() == 0 { + s.draw(face, t) + } +} + +func (SimpleClock) draw(face *Face, t time.Time) { + face.Text(SimpleClockTime, t.Format("15:04")) + face.Text(SimpleClockBattery, system.GetBattery()) +} diff --git a/main.go b/main.go index ac89b52..347418d 100644 --- a/main.go +++ b/main.go @@ -3,16 +3,9 @@ package main import ( "image" "image/color" - "io/ioutil" - "strings" "time" "golang.org/x/image/draw" - "golang.org/x/image/font" - "golang.org/x/image/math/fixed" - - "github.com/golang/freetype" - "github.com/golang/freetype/truetype" "git.ddd.rip/ptrcnull/watchface/framebuffer" ) @@ -21,110 +14,38 @@ var Gray = color.RGBA{R: 60, G: 60, B: 60, A: 60} var LightGray = color.RGBA{R: 150, G: 150, B: 150, A: 150} var White = color.RGBA{R: 255, G: 255, B: 255, A: 255} -func addLabel(img draw.Image, face font.Face, rect image.Rectangle, label string) { - point := fixed.Point26_6{X: fixed.Int26_6(rect.Min.X * 64), Y: fixed.Int26_6(rect.Max.Y * 64)} - - d := &font.Drawer{ - Dst: img, - Src: image.NewUniform(LightGray), - Face: face, - Dot: point, - } - d.DrawString(label) +type App interface { + Init(*Face) + Render(*Face) } -var SecondClock = image.Rect(62, 162, 298, 198) -var MinuteClock = image.Rect(108, 162, 253, 198) -var Battery = image.Rect(90, 240, 150, 240+32) - -var notoSans *truetype.Font - -func sized(size float64) font.Face { - return truetype.NewFace(notoSans, &truetype.Options{ - Size: size, - Hinting: font.HintingFull, - DPI: 0, - }) -} - -func main() { - fontData, _ := ioutil.ReadFile("/usr/share/fonts/noto/NotoSansMono-Regular.ttf") - notoSans, _ = freetype.ParseFont(fontData) - - fb, _ := framebuffer.Open("/dev/fb0") - Fill(fb, fb.Bounds(), color.RGBA{}) - - face := Face{ - //tmp: &framebuffer.SimpleRGBA{ - // Pixels: make([]uint8, fb.Xres*fb.Yres*4), - // Stride: fb.Yres * 4, - // Xres: fb.Xres, - // Yres: fb.Yres, - //}, - tmp: image.NewRGBA(fb.Bounds()), - fb: fb.SimpleRGBA, - } - - simple := true - go face.MinuteClock(time.Now()) - go face.Battery() - - ticker := time.NewTicker(time.Second) - for { - t := time.Now() - if simple { - if t.Second() == 0 { - go face.MinuteClock(t) - go face.Battery() - } - } else { - go face.SecondClock(t) - if t.Second() == 0 { - go face.Battery() - } - } - <-ticker.C - } -} +var app App = SimpleClock{} +var launch func(App) type Face struct { tmp draw.Image fb draw.Image } -func (f *Face) Battery() { - Fill(f.tmp, Battery, color.RGBA{}) - addLabel(f.tmp, sized(32), Battery, getBattery()) - Copy(f.fb, f.tmp, Battery) -} +func main() { + fb, _ := framebuffer.Open("/dev/fb0") + Fill(fb, fb.Bounds(), color.RGBA{}) -func (f *Face) SecondClock(t time.Time) { - Fill(f.tmp, SecondClock, color.RGBA{}) - addLabel(f.tmp, sized(48), SecondClock, t.Format("15:04:05")) - Copy(f.fb, f.tmp, SecondClock) -} - -func (f *Face) MinuteClock(t time.Time) { - Fill(f.tmp, MinuteClock, color.RGBA{}) - addLabel(f.tmp, sized(48), MinuteClock, t.Format("15:04")) - Copy(f.fb, f.tmp, MinuteClock) -} - -//func Loop(duration time.Duration, handler func()) { -// for { -// go handler() -// time.Sleep(duration) -// } -//} - -func getBattery() string { - res, _ := ioutil.ReadFile("/sys/class/power_supply/battery/capacity") - value := strings.Trim(string(res), "\n") - if len(value) == 1 { - value = "0" + value + face := Face{ + tmp: image.NewRGBA(fb.Bounds()), + fb: fb.SimpleRGBA, } - if value == "100" { - return "uwu" + + launch = func(newApp App) { + app = newApp + app.Init(&face) + } + + app.Init(&face) + + ticker := time.NewTicker(time.Second) + for { + go app.Render(&face) + <-ticker.C } - return value + "%" } diff --git a/system/battery.go b/system/battery.go new file mode 100644 index 0000000..ef73919 --- /dev/null +++ b/system/battery.go @@ -0,0 +1,18 @@ +package system + +import ( + "io/ioutil" + "strings" +) + +func GetBattery() string { + res, _ := ioutil.ReadFile("/sys/class/power_supply/battery/capacity") + value := strings.Trim(string(res), "\n") + if len(value) == 1 { + value = "0" + value + } + if value == "100" { + return "uwu" + } + return value + "%" +} diff --git a/text.go b/text.go new file mode 100644 index 0000000..1fc713d --- /dev/null +++ b/text.go @@ -0,0 +1,63 @@ +package main + +import ( + "image" + "image/color" + "io/ioutil" + + "golang.org/x/image/font" + "golang.org/x/image/math/fixed" + + "github.com/golang/freetype" + "github.com/golang/freetype/truetype" +) + +const GlyphRatio = 0.85 + +var notoSans = loadNoto() + +func sized(size float64) font.Face { + return truetype.NewFace(notoSans, &truetype.Options{ + Size: size, + Hinting: font.HintingFull, + DPI: 100, + }) +} + +func loadNoto() *truetype.Font { + fontData, _ := ioutil.ReadFile("/usr/share/fonts/noto/NotoSansMono-Regular.ttf") + ttf, _ := freetype.ParseFont(fontData) + return ttf +} + +func Text(x, y int, textLength, fontSize float64, color color.RGBA) *textData { + width := int(textLength * fontSize * GlyphRatio) + return &textData{ + rect: image.Rect(x, y, x+width, y+int(fontSize)), + fontSize: fontSize, + color: color, + } +} + +type textData struct { + rect image.Rectangle + fontSize float64 + color color.RGBA +} + +func (f *Face) Text(textData *textData, text string) { + Fill(f.tmp, textData.rect, color.RGBA{}) + + d := &font.Drawer{ + Dst: f.tmp, + Src: image.NewUniform(textData.color), + Face: sized(textData.fontSize), + Dot: fixed.Point26_6{ + X: fixed.Int26_6(textData.rect.Min.X * 64), + Y: fixed.Int26_6(textData.rect.Max.Y * 64), + }, + } + d.DrawString(text) + + Copy(f.fb, f.tmp, textData.rect) +}