diff options
Diffstat (limited to 'modules/badge/badge.go')
-rw-r--r-- | modules/badge/badge.go | 133 |
1 files changed, 79 insertions, 54 deletions
diff --git a/modules/badge/badge.go b/modules/badge/badge.go index b30d0b4729..d2e9bd9d1b 100644 --- a/modules/badge/badge.go +++ b/modules/badge/badge.go @@ -4,6 +4,10 @@ package badge import ( + "strings" + "sync" + "unicode" + actions_model "code.gitea.io/gitea/models/actions" ) @@ -11,94 +15,115 @@ import ( // We use 10x scale to calculate more precisely // Then scale down to normal size in tmpl file -type Label struct { - text string - width int -} - -func (l Label) Text() string { - return l.text -} - -func (l Label) Width() int { - return l.width -} - -func (l Label) TextLength() int { - return int(float64(l.width-defaultOffset) * 9.5) -} - -func (l Label) X() int { - return l.width*5 + 10 -} - -type Message struct { +type Text struct { text string width int x int } -func (m Message) Text() string { - return m.text +func (t Text) Text() string { + return t.text } -func (m Message) Width() int { - return m.width +func (t Text) Width() int { + return t.width } -func (m Message) X() int { - return m.x +func (t Text) X() int { + return t.x } -func (m Message) TextLength() int { - return int(float64(m.width-defaultOffset) * 9.5) +func (t Text) TextLength() int { + return int(float64(t.width-defaultOffset) * 10) } type Badge struct { - Color string - FontSize int - Label Label - Message Message + IDPrefix string + FontFamily string + Color string + FontSize int + Label Text + Message Text } func (b Badge) Width() int { return b.Label.width + b.Message.width } +// Style follows https://shields.io/badges const ( - defaultOffset = 9 - defaultFontSize = 11 - DefaultColor = "#9f9f9f" // Grey - defaultFontWidth = 7 // approximate speculation + StyleFlat = "flat" + StyleFlatSquare = "flat-square" ) -var StatusColorMap = map[actions_model.Status]string{ - actions_model.StatusSuccess: "#4c1", // Green - actions_model.StatusSkipped: "#dfb317", // Yellow - actions_model.StatusUnknown: "#97ca00", // Light Green - actions_model.StatusFailure: "#e05d44", // Red - actions_model.StatusCancelled: "#fe7d37", // Orange - actions_model.StatusWaiting: "#dfb317", // Yellow - actions_model.StatusRunning: "#dfb317", // Yellow - actions_model.StatusBlocked: "#dfb317", // Yellow -} +const ( + defaultOffset = 10 + defaultFontSize = 11 + DefaultColor = "#9f9f9f" // Grey + DefaultFontFamily = "DejaVu Sans,Verdana,Geneva,sans-serif" + DefaultStyle = StyleFlat +) + +var GlobalVars = sync.OnceValue(func() (ret struct { + StatusColorMap map[actions_model.Status]string + DejaVuGlyphWidthData map[rune]uint8 + AllStyles []string +}, +) { + ret.StatusColorMap = map[actions_model.Status]string{ + actions_model.StatusSuccess: "#4c1", // Green + actions_model.StatusSkipped: "#dfb317", // Yellow + actions_model.StatusUnknown: "#97ca00", // Light Green + actions_model.StatusFailure: "#e05d44", // Red + actions_model.StatusCancelled: "#fe7d37", // Orange + actions_model.StatusWaiting: "#dfb317", // Yellow + actions_model.StatusRunning: "#dfb317", // Yellow + actions_model.StatusBlocked: "#dfb317", // Yellow + } + ret.DejaVuGlyphWidthData = dejaVuGlyphWidthDataFunc() + ret.AllStyles = []string{StyleFlat, StyleFlatSquare} + return ret +}) // GenerateBadge generates badge with given template func GenerateBadge(label, message, color string) Badge { - lw := defaultFontWidth*len(label) + defaultOffset - mw := defaultFontWidth*len(message) + defaultOffset - x := lw*10 + mw*5 - 10 + lw := calculateTextWidth(label) + defaultOffset + mw := calculateTextWidth(message) + defaultOffset + + lx := lw * 5 + mx := lw*10 + mw*5 - 10 return Badge{ - Label: Label{ + FontFamily: DefaultFontFamily, + Label: Text{ text: label, width: lw, + x: lx, }, - Message: Message{ + Message: Text{ text: message, width: mw, - x: x, + x: mx, }, FontSize: defaultFontSize * 10, Color: color, } } + +func calculateTextWidth(text string) int { + width := 0 + widthData := GlobalVars().DejaVuGlyphWidthData + for _, char := range strings.TrimSpace(text) { + charWidth, ok := widthData[char] + if !ok { + // use the width of 'm' in case of missing glyph width data for a printable character + if unicode.IsPrint(char) { + charWidth = widthData['m'] + } else { + charWidth = 0 + } + } + width += int(charWidth) + } + + return width +} |