@@ -8,6 +8,11 @@ import (
8
8
"image/png"
9
9
"math"
10
10
"os"
11
+
12
+ "github.com/golang/freetype"
13
+ "github.com/golang/freetype/truetype"
14
+ "golang.org/x/image/font"
15
+ "golang.org/x/image/font/gofont/goregular"
11
16
)
12
17
13
18
type circle struct {
@@ -233,6 +238,72 @@ const (
233
238
barToDotBorderRatio = 5
234
239
)
235
240
241
+ func drawWindowTitle (
242
+ dotsSpace ,
243
+ borderSpace int ,
244
+ dotsRight bool ,
245
+ opts StyleOptions ,
246
+ windowBar * image.RGBA ,
247
+ ) error {
248
+ ttf , err := freetype .ParseFont (goregular .TTF )
249
+ if err != nil {
250
+ return err
251
+ }
252
+
253
+ title := opts .WindowTitle
254
+
255
+ titleMinX := dotsSpace
256
+ titleMaxX := borderSpace
257
+ if dotsRight {
258
+ titleMinX , titleMaxX = titleMaxX , titleMinX
259
+ }
260
+
261
+ img := image .NewRGBA (
262
+ image.Rectangle {
263
+ image.Point {
264
+ windowBar .Rect .Min .X + titleMinX ,
265
+ windowBar .Rect .Min .Y ,
266
+ },
267
+ image.Point {
268
+ windowBar .Rect .Max .X - titleMaxX ,
269
+ windowBar .Rect .Max .Y ,
270
+ },
271
+ },
272
+ )
273
+
274
+ fg , _ := parseHexColor (opts .WindowTitleColor )
275
+
276
+ c := freetype .NewContext ()
277
+ c .SetDPI (72 )
278
+ c .SetFont (ttf )
279
+ c .SetFontSize (float64 (half (opts .WindowBarSize )))
280
+ c .SetClip (img .Bounds ())
281
+ c .SetDst (windowBar )
282
+ c .SetSrc (& image.Uniform {fg })
283
+ c .SetHinting (font .HintingNone )
284
+
285
+ fontFace := truetype .NewFace (ttf , & truetype.Options {})
286
+ titleTextWidth := font .MeasureString (fontFace , title ).Ceil ()
287
+ titleBarWidth := img .Rect .Max .X - img .Rect .Min .X
288
+
289
+ // Center-align title text if it will fit, else left-align (truncated by bounds)
290
+ var textStartX int
291
+ if titleBarWidth >= titleTextWidth {
292
+ textStartX = (img .Rect .Max .X - titleTextWidth - titleMaxX ) / 2
293
+ } else {
294
+ textStartX = titleMinX
295
+ }
296
+
297
+ // Font size is half window bar size, thus Y start pos is 0.75 of window bar size
298
+ textStartY := int (c .PointToFixed (float64 (opts .WindowBarSize )* 0.75 ) >> 6 )
299
+
300
+ pt := freetype .Pt (textStartX , textStartY )
301
+ if _ , err := c .DrawString (title , pt ); err != nil {
302
+ return err
303
+ }
304
+ return nil
305
+ }
306
+
236
307
func makeColorfulBar (termWidth int , termHeight int , isRight bool , opts StyleOptions , targetpng string ) error {
237
308
// Radius of dots
238
309
dotRad := opts .WindowBarSize / barToDotRatio
@@ -305,6 +376,21 @@ func makeColorfulBar(termWidth int, termHeight int, isRight bool, opts StyleOpti
305
376
draw .Over ,
306
377
)
307
378
379
+ if opts .WindowTitle != "" {
380
+ titleDotsSpace := dotGap + dotRad * 3 + dotSpace * 3
381
+ titleBorderSpace := dotGap + dotSpace
382
+
383
+ if err := drawWindowTitle (
384
+ titleDotsSpace ,
385
+ titleBorderSpace ,
386
+ isRight ,
387
+ opts ,
388
+ img ,
389
+ ); err != nil {
390
+ fmt .Println (ErrorStyle .Render (fmt .Sprintf ("Couldn't draw window title: %s." , err )))
391
+ }
392
+ }
393
+
308
394
f , err := os .Create (targetpng )
309
395
if err != nil {
310
396
fmt .Println (ErrorStyle .Render ("Couldn't draw colorful bar: unable to save file." ))
@@ -379,6 +465,21 @@ func makeRingBar(termWidth int, termHeight int, isRight bool, opts StyleOptions,
379
465
)
380
466
}
381
467
468
+ if opts .WindowTitle != "" {
469
+ titleDotsSpace := ringGap + outerRad * 3 + ringSpace * 3
470
+ titleBorderSpace := ringGap + ringSpace
471
+
472
+ if err := drawWindowTitle (
473
+ titleDotsSpace ,
474
+ titleBorderSpace ,
475
+ isRight ,
476
+ opts ,
477
+ img ,
478
+ ); err != nil {
479
+ fmt .Println (ErrorStyle .Render (fmt .Sprintf ("Couldn't draw window title: %s." , err )))
480
+ }
481
+ }
482
+
382
483
f , err := os .Create (targetpng )
383
484
if err != nil {
384
485
fmt .Println (ErrorStyle .Render ("Couldn't draw ring bar: unable to save file." ))
0 commit comments