func drawGlyphOver(dst *image.RGBA, r Rectangle, src image.Uniform, mask *image.Alpha, mp Point) { x0, x1 := r.Min.X, r.Max.X y0, y1 := r.Min.Y, r.Max.Y cr, cg, cb, ca := src.RGBA() for y, my := y0, mp.Y; y != y1; y, my = y+1, my+1 { dpix := dst.Pixel[y] mpix := mask.Pixel[my] for x, mx := x0, mp.X; x != x1; x, mx = x+1, mx+1 { ma := uint32(mpix[mx].A) if ma == 0 { continue } ma |= ma << 8 rgba := dpix[x] dr := uint32(rgba.R) dg := uint32(rgba.G) db := uint32(rgba.B) da := uint32(rgba.A) // The 0x101 is here for the same reason as in drawRGBA. a := (m - (ca * ma / m)) * 0x101 dr = (dr*a + cr*ma) / m dg = (dg*a + cg*ma) / m db = (db*a + cb*ma) / m da = (da*a + ca*ma) / m dpix[x] = color.RGBA{uint8(dr >> 8), uint8(dg >> 8), uint8(db >> 8), uint8(da >> 8)} } } }
func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform, mask *image.Alpha, mp image.Point) { i0 := dst.PixOffset(r.Min.X, r.Min.Y) i1 := i0 + r.Dx()*4 mi0 := mask.PixOffset(mp.X, mp.Y) sr, sg, sb, sa := src.RGBA() for y, my := r.Min.Y, mp.Y; y != r.Max.Y; y, my = y+1, my+1 { for i, mi := i0, mi0; i < i1; i, mi = i+4, mi+1 { ma := uint32(mask.Pix[mi]) if ma == 0 { continue } ma |= ma << 8 dr := uint32(dst.Pix[i+0]) dg := uint32(dst.Pix[i+1]) db := uint32(dst.Pix[i+2]) da := uint32(dst.Pix[i+3]) // The 0x101 is here for the same reason as in drawRGBA. a := (m - (sa * ma / m)) * 0x101 dst.Pix[i+0] = uint8((dr*a + sr*ma) / m >> 8) dst.Pix[i+1] = uint8((dg*a + sg*ma) / m >> 8) dst.Pix[i+2] = uint8((db*a + sb*ma) / m >> 8) dst.Pix[i+3] = uint8((da*a + sa*ma) / m >> 8) } i0 += dst.Stride i1 += dst.Stride mi0 += mask.Stride } }
func drawFillOver(dst *image.RGBA, r Rectangle, src image.Uniform) { cr, cg, cb, ca := src.RGBA() // The 0x101 is here for the same reason as in drawRGBA. a := (m - ca) * 0x101 x0, x1 := r.Min.X, r.Max.X y0, y1 := r.Min.Y, r.Max.Y for y := y0; y != y1; y++ { dpix := dst.Pixel[y] for x := x0; x != x1; x++ { rgba := dpix[x] dr := (uint32(rgba.R)*a)/m + cr dg := (uint32(rgba.G)*a)/m + cg db := (uint32(rgba.B)*a)/m + cb da := (uint32(rgba.A)*a)/m + ca dpix[x] = color.RGBA{uint8(dr >> 8), uint8(dg >> 8), uint8(db >> 8), uint8(da >> 8)} } } }
func drawFillSrc(dst *image.RGBA, r image.Rectangle, src *image.Uniform) { sr, sg, sb, sa := src.RGBA() // The built-in copy function is faster than a straightforward for loop to fill the destination with // the color, but copy requires a slice source. We therefore use a for loop to fill the first row, and // then use the first row as the slice source for the remaining rows. i0 := dst.PixOffset(r.Min.X, r.Min.Y) i1 := i0 + r.Dx()*4 for i := i0; i < i1; i += 4 { dst.Pix[i+0] = uint8(sr >> 8) dst.Pix[i+1] = uint8(sg >> 8) dst.Pix[i+2] = uint8(sb >> 8) dst.Pix[i+3] = uint8(sa >> 8) } firstRow := dst.Pix[i0:i1] for y := r.Min.Y + 1; y < r.Max.Y; y++ { i0 += dst.Stride i1 += dst.Stride copy(dst.Pix[i0:i1], firstRow) } }
func drawFillSrc(dst *image.RGBA, r Rectangle, src image.Uniform) { if r.Dy() < 1 { return } cr, cg, cb, ca := src.RGBA() color := color.RGBA{uint8(cr >> 8), uint8(cg >> 8), uint8(cb >> 8), uint8(ca >> 8)} // The built-in copy function is faster than a straightforward for loop to fill the destination with // the color, but copy requires a slice source. We therefore use a for loop to fill the first row, and // then use the first row as the slice source for the remaining rows. dx0, dx1 := r.Min.X, r.Max.X dy0, dy1 := r.Min.Y, r.Max.Y firstRow := dst.Pixel[dy0] for x := dx0; x < dx1; x++ { firstRow[x] = color } copySrc := firstRow[dx0:dx1] for y := dy0 + 1; y < dy1; y++ { copy(dst.Pixel[y][dx0:dx1], copySrc) } }
func drawFillOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform) { sr, sg, sb, sa := src.RGBA() // The 0x101 is here for the same reason as in drawRGBA. a := (m - sa) * 0x101 i0 := dst.PixOffset(r.Min.X, r.Min.Y) i1 := i0 + r.Dx()*4 for y := r.Min.Y; y != r.Max.Y; y++ { for i := i0; i < i1; i += 4 { dr := uint32(dst.Pix[i+0]) dg := uint32(dst.Pix[i+1]) db := uint32(dst.Pix[i+2]) da := uint32(dst.Pix[i+3]) dst.Pix[i+0] = uint8((dr*a/m + sr) >> 8) dst.Pix[i+1] = uint8((dg*a/m + sg) >> 8) dst.Pix[i+2] = uint8((db*a/m + sb) >> 8) dst.Pix[i+3] = uint8((da*a/m + sa) >> 8) } i0 += dst.Stride i1 += dst.Stride } }
func drawFillOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform) { sr, sg, sb, sa := src.RGBA() // The 0x101 is here for the same reason as in drawRGBA. a := (m - sa) * 0x101 i0 := dst.PixOffset(r.Min.X, r.Min.Y) i1 := i0 + r.Dx()*4 for y := r.Min.Y; y != r.Max.Y; y++ { for i := i0; i < i1; i += 4 { dr := &dst.Pix[i+0] dg := &dst.Pix[i+1] db := &dst.Pix[i+2] da := &dst.Pix[i+3] *dr = uint8((uint32(*dr)*a/m + sr) >> 8) *dg = uint8((uint32(*dg)*a/m + sg) >> 8) *db = uint8((uint32(*db)*a/m + sb) >> 8) *da = uint8((uint32(*da)*a/m + sa) >> 8) } i0 += dst.Stride i1 += dst.Stride } }