github.com/xxf098/lite-proxy@v0.15.1-0.20230422081941-12c69f323218/web/render/util.go (about) 1 package render 2 3 import ( 4 "fmt" 5 "image" 6 "image/draw" 7 "image/jpeg" 8 _ "image/jpeg" 9 "image/png" 10 "math" 11 "os" 12 "strings" 13 14 "github.com/golang/freetype" 15 "github.com/golang/freetype/truetype" 16 17 "golang.org/x/image/font" 18 "golang.org/x/image/math/fixed" 19 ) 20 21 func Radians(degrees float64) float64 { 22 return degrees * math.Pi / 180 23 } 24 25 func Degrees(radians float64) float64 { 26 return radians * 180 / math.Pi 27 } 28 29 func LoadImage(path string) (image.Image, error) { 30 file, err := os.Open(path) 31 if err != nil { 32 return nil, err 33 } 34 defer file.Close() 35 im, _, err := image.Decode(file) 36 return im, err 37 } 38 39 func LoadPNG(path string) (image.Image, error) { 40 file, err := os.Open(path) 41 if err != nil { 42 return nil, err 43 } 44 defer file.Close() 45 return png.Decode(file) 46 } 47 48 func SavePNG(path string, im image.Image) error { 49 file, err := os.Create(path) 50 if err != nil { 51 return err 52 } 53 defer file.Close() 54 return png.Encode(file, im) 55 } 56 57 func LoadJPG(path string) (image.Image, error) { 58 file, err := os.Open(path) 59 if err != nil { 60 return nil, err 61 } 62 defer file.Close() 63 return jpeg.Decode(file) 64 } 65 66 func SaveJPG(path string, im image.Image, quality int) error { 67 file, err := os.Create(path) 68 if err != nil { 69 return err 70 } 71 defer file.Close() 72 73 var opt jpeg.Options 74 opt.Quality = quality 75 76 return jpeg.Encode(file, im, &opt) 77 } 78 79 func imageToRGBA(src image.Image) *image.RGBA { 80 bounds := src.Bounds() 81 dst := image.NewRGBA(bounds) 82 draw.Draw(dst, bounds, src, bounds.Min, draw.Src) 83 return dst 84 } 85 86 func parseHexColor(x string) (r, g, b, a int) { 87 x = strings.TrimPrefix(x, "#") 88 a = 255 89 if len(x) == 3 { 90 format := "%1x%1x%1x" 91 fmt.Sscanf(x, format, &r, &g, &b) 92 r |= r << 4 93 g |= g << 4 94 b |= b << 4 95 } 96 if len(x) == 6 { 97 format := "%02x%02x%02x" 98 fmt.Sscanf(x, format, &r, &g, &b) 99 } 100 if len(x) == 8 { 101 format := "%02x%02x%02x%02x" 102 fmt.Sscanf(x, format, &r, &g, &b, &a) 103 } 104 return 105 } 106 107 func fixp(x, y float64) fixed.Point26_6 { 108 return fixed.Point26_6{fix(x), fix(y)} 109 } 110 111 func fix(x float64) fixed.Int26_6 { 112 return fixed.Int26_6(x * 64) 113 } 114 115 func unfix(x fixed.Int26_6) float64 { 116 const shift, mask = 6, 1<<6 - 1 117 if x >= 0 { 118 return float64(x>>shift) + float64(x&mask)/64 119 } 120 x = -x 121 if x >= 0 { 122 return -(float64(x>>shift) + float64(x&mask)/64) 123 } 124 return 0 125 } 126 127 // LoadFontFace is a helper function to load the specified font file with 128 // the specified point size. Note that the returned `font.Face` objects 129 // are not thread safe and cannot be used in parallel across goroutines. 130 // You can usually just use the Context.LoadFontFace function instead of 131 // this package-level function. 132 func LoadFontFace(path string, points float64) (font.Face, error) { 133 fontBytes, err := os.ReadFile(path) 134 if err != nil { 135 return nil, err 136 } 137 f, err := truetype.Parse(fontBytes) 138 if err != nil { 139 return nil, err 140 } 141 face := truetype.NewFace(f, &truetype.Options{ 142 Size: points, 143 // Hinting: font.HintingFull, 144 }) 145 return face, nil 146 } 147 148 func LoadFontFaceByBytes(fontBytes []byte, fontPath string, points float64) (font.Face, error) { 149 if fontBytes == nil || len(fontBytes) < 1 { 150 return LoadFontFace(fontPath, points) 151 } 152 f, err := truetype.Parse(fontBytes) 153 if err != nil { 154 return nil, err 155 } 156 face := truetype.NewFace(f, &truetype.Options{ 157 Size: points, 158 // Hinting: font.HintingFull, 159 }) 160 return face, nil 161 } 162 163 func LoadFontFace1(path string, points float64) (font.Face, error) { 164 fontBytes, err := os.ReadFile(path) 165 if err != nil { 166 return nil, err 167 } 168 f, err := freetype.ParseFont(fontBytes) 169 if err != nil { 170 return nil, err 171 } 172 face := truetype.NewFace(f, &truetype.Options{ 173 Size: points, 174 // Hinting: font.HintingFull, 175 }) 176 return face, nil 177 }