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  }