From 5e07ccc4f61ea347aa7982411cf8cb8c52736456 Mon Sep 17 00:00:00 2001 From: tiennm99 Date: Mon, 6 Jul 2026 14:37:35 +0700 Subject: [PATCH] fix(misc): improve wheel beta label readability --- internal/modules/misc/handlers_test.go | 35 +++++++++++++++++++ .../modules/misc/wheelofnames_beta_drawing.go | 18 ++++++---- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/internal/modules/misc/handlers_test.go b/internal/modules/misc/handlers_test.go index aacc065..7bb2da3 100644 --- a/internal/modules/misc/handlers_test.go +++ b/internal/modules/misc/handlers_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "image" + "image/color" "image/gif" "math" "math/rand/v2" @@ -12,6 +13,7 @@ import ( "time" "github.com/go-telegram/bot/models" + "golang.org/x/image/font/sfnt" "github.com/tiennm99/miti99bot/internal/modules" "github.com/tiennm99/miti99bot/internal/storage" @@ -425,6 +427,25 @@ func TestWheelOfNamesBeta_RotatesOptionLabelsWithSlices(t *testing.T) { } } +func TestWheelOfNamesBeta_RotatedLabelIgnoresFaintMaskPixels(t *testing.T) { + img := image.NewPaletted(image.Rect(0, 0, 7, 7), wheelBetaPalette) + mask := image.NewAlpha(image.Rect(0, 0, 3, 1)) + mask.SetAlpha(0, 0, color.Alpha{A: wheelBetaSliceLabelAlphaThreshold - 1}) + mask.SetAlpha(1, 0, color.Alpha{A: wheelBetaSliceLabelAlphaThreshold}) + mask.SetAlpha(2, 0, color.Alpha{A: 255}) + + stampRotatedTextMask(img, mask, 3, 3, 0, wheelBetaInkColorIndex, wheelBetaSliceLabelAlphaThreshold) + + if got := img.ColorIndexAt(2, 3); got == wheelBetaInkColorIndex { + t.Fatalf("faint mask pixel became ink color %d", got) + } + for _, x := range []int{3, 4} { + if got := img.ColorIndexAt(x, 3); got != wheelBetaInkColorIndex { + t.Fatalf("strong mask pixel at x=%d color = %d, want ink color %d", x, got, wheelBetaInkColorIndex) + } + } +} + func TestWheelOfNamesBeta_DisplayTextPreservesVietnamese(t *testing.T) { input := "Tiếng Việt Đặng" got := wheelBetaDisplayText(input, 32) @@ -436,6 +457,20 @@ func TestWheelOfNamesBeta_DisplayTextPreservesVietnamese(t *testing.T) { } } +func TestWheelOfNamesBeta_FontUsesNormalWeight(t *testing.T) { + subfamily, err := wheelBetaTextFont.Name(nil, sfnt.NameIDSubfamily) + if err != nil { + t.Fatalf("font subfamily: %v", err) + } + normalized := strings.ToLower(subfamily) + if strings.Contains(normalized, "bold") { + t.Fatalf("font subfamily = %q, want normal non-bold face", subfamily) + } + if normalized != "book" && normalized != "regular" { + t.Fatalf("font subfamily = %q, want normal face such as Book or Regular", subfamily) + } +} + func TestWheelOfNamesBeta_FontSupportsVietnameseGlyphs(t *testing.T) { for _, r := range "Tiếng Việt Đặng Ơ Ư ấ ệ" { if r == ' ' { diff --git a/internal/modules/misc/wheelofnames_beta_drawing.go b/internal/modules/misc/wheelofnames_beta_drawing.go index 78e9e8a..17710a0 100644 --- a/internal/modules/misc/wheelofnames_beta_drawing.go +++ b/internal/modules/misc/wheelofnames_beta_drawing.go @@ -14,9 +14,10 @@ import ( ) const ( - wheelBetaSliceLabelRadius = 64 - wheelBetaFontSize = 10 - wheelBetaFontDPI = 72 + wheelBetaSliceLabelRadius = 64 + wheelBetaSliceLabelAlphaThreshold = 96 + wheelBetaFontSize = 10 + wheelBetaFontDPI = 72 ) //go:embed fonts/dejavu-sans.ttf @@ -56,8 +57,7 @@ func drawWheelSliceLabels(img *image.Paletted, options []string, rotation float6 centerX := cx + int(math.Round(math.Cos(angle)*float64(wheelBetaSliceLabelRadius))) centerY := cy + int(math.Round(math.Sin(angle)*float64(wheelBetaSliceLabelRadius))) text := wheelBetaDisplayText(option, limit) - drawRotatedCenteredTextAt(img, text, centerX+1, centerY+1, angle, wheelBetaPaperColorIndex) - drawRotatedCenteredTextAt(img, text, centerX, centerY, angle, wheelBetaInkColorIndex) + drawRotatedCenteredTextAt(img, text, centerX, centerY, angle, wheelBetaInkColorIndex, wheelBetaSliceLabelAlphaThreshold) } } @@ -247,7 +247,7 @@ func drawCenteredTextAt(img *image.Paletted, text string, centerX, baselineY int drawer.DrawString(text) } -func drawRotatedCenteredTextAt(img *image.Paletted, text string, centerX, centerY int, angle float64, colorIndex byte) { +func drawRotatedCenteredTextAt(img *image.Paletted, text string, centerX, centerY int, angle float64, colorIndex byte, alphaThreshold byte) { face := newWheelBetaTextFace() defer func() { _ = face.Close() @@ -265,12 +265,16 @@ func drawRotatedCenteredTextAt(img *image.Paletted, text string, centerX, center } drawer.DrawString(text) + stampRotatedTextMask(img, mask, centerX, centerY, angle, colorIndex, alphaThreshold) +} + +func stampRotatedTextMask(img *image.Paletted, mask *image.Alpha, centerX, centerY int, angle float64, colorIndex byte, alphaThreshold byte) { sourceCenterX := float64(mask.Bounds().Dx()-1) / 2 sourceCenterY := float64(mask.Bounds().Dy()-1) / 2 sin, cos := math.Sin(angle), math.Cos(angle) for y := mask.Bounds().Min.Y; y < mask.Bounds().Max.Y; y++ { for x := mask.Bounds().Min.X; x < mask.Bounds().Max.X; x++ { - if mask.AlphaAt(x, y).A == 0 { + if mask.AlphaAt(x, y).A < alphaThreshold { continue } localX := float64(x) - sourceCenterX