mirror of
https://github.com/Luzifer/badge-gen.git
synced 2024-11-09 13:50:03 +00:00
Initial version
This commit is contained in:
commit
633d1c18ff
6 changed files with 31872 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
badge-gen
|
||||||
|
gin-bin
|
BIN
assets/DejaVuSans.ttf
Normal file
BIN
assets/DejaVuSans.ttf
Normal file
Binary file not shown.
21
assets/badgeTemplate.tpl
Normal file
21
assets/badgeTemplate.tpl
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="{{ .Width }}" height="20">
|
||||||
|
<linearGradient id="b" x2="0" y2="100%">
|
||||||
|
<stop offset="0" stop-color="#bbb" stop-opacity=".1" />
|
||||||
|
<stop offset="1" stop-opacity=".1" />
|
||||||
|
</linearGradient>
|
||||||
|
<mask id="a">
|
||||||
|
<rect width="{{ .Width }}" height="20" rx="3" fill="#fff" />
|
||||||
|
</mask>
|
||||||
|
<g mask="url(#a)">
|
||||||
|
<path fill="#555" d="M0 0 h{{ .TitleWidth }} v20 H0 z" />
|
||||||
|
<path fill="#4c1" d="M{{ .TitleWidth }} 0 H{{ .Width }} v20 H{{ .TitleWidth }} z" />
|
||||||
|
<path fill="url(#b)" d="M0 0 h{{ .Width }} v20 H0 z" />
|
||||||
|
</g>
|
||||||
|
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
|
||||||
|
<text x="{{ .TitleAnchor }}" y="15" fill="#010101" fill-opacity=".3">{{ .Title }}</text>
|
||||||
|
<text x="{{ .TitleAnchor }}" y="14">{{ .Title }}</text>
|
||||||
|
<text x="{{ .TextAnchor }}" y="15" fill="#010101" fill-opacity=".3">{{ .Text }}</text>
|
||||||
|
<text x="{{ .TextAnchor }}" y="14">{{ .Text }}</text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1 KiB |
31744
bindata.go
Normal file
31744
bindata.go
Normal file
File diff suppressed because it is too large
Load diff
35
font.go
Normal file
35
font.go
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// Some of this code (namely the code for computing the
|
||||||
|
// width of a string in a given font) was copied from
|
||||||
|
// code.google.com/p/freetype-go/freetype/ which includes
|
||||||
|
// the following copyright notice:
|
||||||
|
// Copyright 2010 The Freetype-Go Authors. All rights reserved.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "code.google.com/p/freetype-go/freetype/truetype"
|
||||||
|
|
||||||
|
const (
|
||||||
|
fontSize = 11
|
||||||
|
)
|
||||||
|
|
||||||
|
func calculateTextWidth(text string) (int, error) {
|
||||||
|
binFont, _ := Asset("assets/DejaVuSans.ttf")
|
||||||
|
font, err := truetype.Parse(binFont)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
scale := fontSize / float64(font.FUnitsPerEm())
|
||||||
|
|
||||||
|
width := 0
|
||||||
|
prev, hasPrev := truetype.Index(0), false
|
||||||
|
for _, rune := range text {
|
||||||
|
index := font.Index(rune)
|
||||||
|
if hasPrev {
|
||||||
|
width += int(font.Kerning(font.FUnitsPerEm(), prev, index))
|
||||||
|
}
|
||||||
|
width += int(font.HMetric(font.FUnitsPerEm(), index).AdvanceWidth)
|
||||||
|
prev, hasPrev = index, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return int(float64(width) * scale), nil
|
||||||
|
}
|
70
main.go
Normal file
70
main.go
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/alecthomas/template"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
xSpacing = 8
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
port := fmt.Sprintf(":%s", os.Getenv("PORT"))
|
||||||
|
if port == ":" {
|
||||||
|
port = ":3000"
|
||||||
|
}
|
||||||
|
|
||||||
|
r := mux.NewRouter()
|
||||||
|
r.HandleFunc("/v1/badge", generateBadge).Methods("GET")
|
||||||
|
|
||||||
|
http.Handle("/", r)
|
||||||
|
http.ListenAndServe(port, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateBadge(res http.ResponseWriter, r *http.Request) {
|
||||||
|
title := r.URL.Query().Get("title")
|
||||||
|
text := r.URL.Query().Get("text")
|
||||||
|
|
||||||
|
if title == "" || text == "" {
|
||||||
|
http.Error(res, "You must specify parameters 'title' and 'text'.", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
badge := createBadge(title, text)
|
||||||
|
|
||||||
|
res.Header().Add("Content-Type", "image/svg+xml")
|
||||||
|
res.Header().Add("Cache-Control", "public, max-age=31536000")
|
||||||
|
res.Write(badge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createBadge(title, text string) []byte {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
bufw := bufio.NewWriter(&buf)
|
||||||
|
|
||||||
|
titleW, _ := calculateTextWidth(title)
|
||||||
|
textW, _ := calculateTextWidth(text)
|
||||||
|
|
||||||
|
width := titleW + textW + 4*xSpacing
|
||||||
|
|
||||||
|
t, _ := Asset("assets/badgeTemplate.tpl")
|
||||||
|
tpl, _ := template.New("svg").Parse(string(t))
|
||||||
|
|
||||||
|
tpl.Execute(bufw, map[string]interface{}{
|
||||||
|
"Width": width,
|
||||||
|
"TitleWidth": titleW + 2*xSpacing,
|
||||||
|
"Title": title,
|
||||||
|
"Text": text,
|
||||||
|
"TitleAnchor": titleW/2 + xSpacing,
|
||||||
|
"TextAnchor": titleW + textW/2 + 3*xSpacing,
|
||||||
|
})
|
||||||
|
|
||||||
|
bufw.Flush()
|
||||||
|
return buf.Bytes()
|
||||||
|
}
|
Loading…
Reference in a new issue