Monorepo for Tangled
at op/lrpyxormllvp 91 lines 2.2 kB view raw
1package state 2 3import ( 4 "bytes" 5 "fmt" 6 "html/template" 7 "image" 8 "image/color" 9 "net/http" 10 11 "github.com/srwiley/oksvg" 12 "github.com/srwiley/rasterx" 13 "golang.org/x/image/draw" 14 "tangled.org/core/appview/pages" 15 "tangled.org/core/ico" 16) 17 18func (s *State) FaviconSvg(w http.ResponseWriter, r *http.Request) { 19 w.Header().Set("Content-Type", "image/svg+xml") 20 w.Header().Set("Cache-Control", "public, max-age=31536000") // one year 21 w.Header().Set("ETag", `"favicon-svg-v1"`) 22 23 if match := r.Header.Get("If-None-Match"); match == `"favicon-svg-v1"` { 24 w.WriteHeader(http.StatusNotModified) 25 return 26 } 27 28 s.pages.Favicon(w) 29} 30 31func (s *State) FaviconIco(w http.ResponseWriter, r *http.Request) { 32 w.Header().Set("Content-Type", "image/x-icon") 33 w.Header().Set("Cache-Control", "public, max-age=31536000") // one year 34 w.Header().Set("ETag", `"favicon-ico-v1"`) 35 36 if match := r.Header.Get("If-None-Match"); match == `"favicon-ico-v1"` { 37 w.WriteHeader(http.StatusNotModified) 38 return 39 } 40 41 ico, err := dollyIco() 42 if err != nil { 43 s.logger.Error("failed to render ico", "err", err) 44 w.WriteHeader(http.StatusNotFound) 45 return 46 } 47 48 w.Write(ico) 49} 50 51func dollyIco() ([]byte, error) { 52 // first, get the bytes from the svg 53 tpl, err := template.New("dolly"). 54 ParseFS(pages.Files, "templates/fragments/dolly/silhouette.html") 55 if err != nil { 56 return nil, err 57 } 58 59 var svgData bytes.Buffer 60 if err := tpl.ExecuteTemplate(&svgData, "fragments/dolly/silhouette", "#000000"); err != nil { 61 return nil, err 62 } 63 64 img, err := svgToImage(svgData.Bytes(), 48, 48) 65 if err != nil { 66 return nil, err 67 } 68 69 ico, err := ico.ImageToIco(img) 70 if err != nil { 71 return nil, err 72 } 73 74 return ico, nil 75} 76 77func svgToImage(svgData []byte, w, h int) (image.Image, error) { 78 icon, err := oksvg.ReadIconStream(bytes.NewReader(svgData)) 79 if err != nil { 80 return nil, fmt.Errorf("error parsing SVG: %v", err) 81 } 82 83 icon.SetTarget(0, 0, float64(w), float64(h)) 84 rgba := image.NewRGBA(image.Rect(0, 0, w, h)) 85 draw.Draw(rgba, rgba.Bounds(), &image.Uniform{color.Transparent}, image.Point{}, draw.Src) 86 scanner := rasterx.NewScannerGV(w, h, rgba, rgba.Bounds()) 87 raster := rasterx.NewDasher(w, h, scanner) 88 icon.Draw(raster, 1.0) 89 90 return rgba, nil 91}