github.com/xxf098/lite-proxy@v0.15.1-0.20230422081941-12c69f323218/web/render/pattern.go (about) 1 package render 2 3 import ( 4 "image" 5 "image/color" 6 7 "github.com/golang/freetype/raster" 8 ) 9 10 type RepeatOp int 11 12 const ( 13 RepeatBoth RepeatOp = iota 14 RepeatX 15 RepeatY 16 RepeatNone 17 ) 18 19 type Pattern interface { 20 ColorAt(x, y int) color.Color 21 } 22 23 // Solid Pattern 24 type solidPattern struct { 25 color color.Color 26 } 27 28 func (p *solidPattern) ColorAt(x, y int) color.Color { 29 return p.color 30 } 31 32 func NewSolidPattern(color color.Color) Pattern { 33 return &solidPattern{color: color} 34 } 35 36 // Surface Pattern 37 type surfacePattern struct { 38 im image.Image 39 op RepeatOp 40 } 41 42 func (p *surfacePattern) ColorAt(x, y int) color.Color { 43 b := p.im.Bounds() 44 switch p.op { 45 case RepeatX: 46 if y >= b.Dy() { 47 return color.Transparent 48 } 49 case RepeatY: 50 if x >= b.Dx() { 51 return color.Transparent 52 } 53 case RepeatNone: 54 if x >= b.Dx() || y >= b.Dy() { 55 return color.Transparent 56 } 57 } 58 x = x%b.Dx() + b.Min.X 59 y = y%b.Dy() + b.Min.Y 60 return p.im.At(x, y) 61 } 62 63 func NewSurfacePattern(im image.Image, op RepeatOp) Pattern { 64 return &surfacePattern{im: im, op: op} 65 } 66 67 type patternPainter struct { 68 im *image.RGBA 69 mask *image.Alpha 70 p Pattern 71 } 72 73 // Paint satisfies the Painter interface. 74 func (r *patternPainter) Paint(ss []raster.Span, done bool) { 75 b := r.im.Bounds() 76 for _, s := range ss { 77 if s.Y < b.Min.Y { 78 continue 79 } 80 if s.Y >= b.Max.Y { 81 return 82 } 83 if s.X0 < b.Min.X { 84 s.X0 = b.Min.X 85 } 86 if s.X1 > b.Max.X { 87 s.X1 = b.Max.X 88 } 89 if s.X0 >= s.X1 { 90 continue 91 } 92 const m = 1<<16 - 1 93 y := s.Y - r.im.Rect.Min.Y 94 x0 := s.X0 - r.im.Rect.Min.X 95 // RGBAPainter.Paint() in $GOPATH/src/github.com/golang/freetype/raster/paint.go 96 i0 := (s.Y-r.im.Rect.Min.Y)*r.im.Stride + (s.X0-r.im.Rect.Min.X)*4 97 i1 := i0 + (s.X1-s.X0)*4 98 for i, x := i0, x0; i < i1; i, x = i+4, x+1 { 99 ma := s.Alpha 100 if r.mask != nil { 101 ma = ma * uint32(r.mask.AlphaAt(x, y).A) / 255 102 if ma == 0 { 103 continue 104 } 105 } 106 c := r.p.ColorAt(x, y) 107 cr, cg, cb, ca := c.RGBA() 108 dr := uint32(r.im.Pix[i+0]) 109 dg := uint32(r.im.Pix[i+1]) 110 db := uint32(r.im.Pix[i+2]) 111 da := uint32(r.im.Pix[i+3]) 112 a := (m - (ca * ma / m)) * 0x101 113 r.im.Pix[i+0] = uint8((dr*a + cr*ma) / m >> 8) 114 r.im.Pix[i+1] = uint8((dg*a + cg*ma) / m >> 8) 115 r.im.Pix[i+2] = uint8((db*a + cb*ma) / m >> 8) 116 r.im.Pix[i+3] = uint8((da*a + ca*ma) / m >> 8) 117 } 118 } 119 } 120 121 func newPatternPainter(im *image.RGBA, mask *image.Alpha, p Pattern) *patternPainter { 122 return &patternPainter{im, mask, p} 123 }