123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- package gg
- import (
- "image"
- "image/color"
- "github.com/golang/freetype/raster"
- )
- type RepeatOp int
- const (
- RepeatBoth RepeatOp = iota
- RepeatX
- RepeatY
- RepeatNone
- )
- type Pattern interface {
- ColorAt(x, y int) color.Color
- }
- // Solid Pattern
- type solidPattern struct {
- color color.Color
- }
- func (p *solidPattern) ColorAt(x, y int) color.Color {
- return p.color
- }
- func NewSolidPattern(color color.Color) Pattern {
- return &solidPattern{color: color}
- }
- // Surface Pattern
- type surfacePattern struct {
- im image.Image
- op RepeatOp
- }
- func (p *surfacePattern) ColorAt(x, y int) color.Color {
- b := p.im.Bounds()
- switch p.op {
- case RepeatX:
- if y >= b.Dy() {
- return color.Transparent
- }
- case RepeatY:
- if x >= b.Dx() {
- return color.Transparent
- }
- case RepeatNone:
- if x >= b.Dx() || y >= b.Dy() {
- return color.Transparent
- }
- }
- x = x%b.Dx() + b.Min.X
- y = y%b.Dy() + b.Min.Y
- return p.im.At(x, y)
- }
- func NewSurfacePattern(im image.Image, op RepeatOp) Pattern {
- return &surfacePattern{im: im, op: op}
- }
- type patternPainter struct {
- im *image.RGBA
- mask *image.Alpha
- p Pattern
- }
- // Paint satisfies the Painter interface.
- func (r *patternPainter) Paint(ss []raster.Span, done bool) {
- b := r.im.Bounds()
- for _, s := range ss {
- if s.Y < b.Min.Y {
- continue
- }
- if s.Y >= b.Max.Y {
- return
- }
- if s.X0 < b.Min.X {
- s.X0 = b.Min.X
- }
- if s.X1 > b.Max.X {
- s.X1 = b.Max.X
- }
- if s.X0 >= s.X1 {
- continue
- }
- const m = 1<<16 - 1
- y := s.Y - r.im.Rect.Min.Y
- x0 := s.X0 - r.im.Rect.Min.X
- // RGBAPainter.Paint() in $GOPATH/src/github.com/golang/freetype/raster/paint.go
- i0 := (s.Y-r.im.Rect.Min.Y)*r.im.Stride + (s.X0-r.im.Rect.Min.X)*4
- i1 := i0 + (s.X1-s.X0)*4
- for i, x := i0, x0; i < i1; i, x = i+4, x+1 {
- ma := s.Alpha
- if r.mask != nil {
- ma = ma * uint32(r.mask.AlphaAt(x, y).A) / 255
- if ma == 0 {
- continue
- }
- }
- c := r.p.ColorAt(x, y)
- cr, cg, cb, ca := c.RGBA()
- dr := uint32(r.im.Pix[i+0])
- dg := uint32(r.im.Pix[i+1])
- db := uint32(r.im.Pix[i+2])
- da := uint32(r.im.Pix[i+3])
- a := (m - (ca * ma / m)) * 0x101
- r.im.Pix[i+0] = uint8((dr*a + cr*ma) / m >> 8)
- r.im.Pix[i+1] = uint8((dg*a + cg*ma) / m >> 8)
- r.im.Pix[i+2] = uint8((db*a + cb*ma) / m >> 8)
- r.im.Pix[i+3] = uint8((da*a + ca*ma) / m >> 8)
- }
- }
- }
- func newPatternPainter(im *image.RGBA, mask *image.Alpha, p Pattern) *patternPainter {
- return &patternPainter{im, mask, p}
- }
|