sr, sg, sb, sa := src.RGBA()
// The 0x101 is here for the same reason as in drawRGBA.
a := (m - sa) * 0x101
- i0 := (r.Min.Y-dst.Rect.Min.Y)*dst.Stride + (r.Min.X-dst.Rect.Min.X)*4
+ 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 {
// 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 := (r.Min.Y-dst.Rect.Min.Y)*dst.Stride + (r.Min.X-dst.Rect.Min.X)*4
+ 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)
func drawCopyOver(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.Point) {
dx, dy := r.Dx(), r.Dy()
- d0 := (r.Min.Y-dst.Rect.Min.Y)*dst.Stride + (r.Min.X-dst.Rect.Min.X)*4
- s0 := (sp.Y-src.Rect.Min.Y)*src.Stride + (sp.X-src.Rect.Min.X)*4
+ d0 := dst.PixOffset(r.Min.X, r.Min.Y)
+ s0 := src.PixOffset(sp.X, sp.Y)
var (
ddelta, sdelta int
i0, i1, idelta int
func drawCopySrc(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.Point) {
n, dy := 4*r.Dx(), r.Dy()
- d0 := (r.Min.Y-dst.Rect.Min.Y)*dst.Stride + (r.Min.X-dst.Rect.Min.X)*4
- s0 := (sp.Y-src.Rect.Min.Y)*src.Stride + (sp.X-src.Rect.Min.X)*4
+ d0 := dst.PixOffset(r.Min.X, r.Min.Y)
+ s0 := src.PixOffset(sp.X, sp.Y)
var ddelta, sdelta int
if r.Min.Y <= sp.Y {
ddelta = dst.Stride
func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Point) {
// An image.YCbCr is always fully opaque, and so if the mask is implicitly nil
// (i.e. fully opaque) then the op is effectively always Src.
- var (
- yy, cb, cr uint8
- )
+ var yy, cb, cr uint8
x0 := (r.Min.X - dst.Rect.Min.X) * 4
x1 := (r.Max.X - dst.Rect.Min.X) * 4
y0 := r.Min.Y - dst.Rect.Min.Y
}
func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform, mask *image.Alpha, mp image.Point) {
- i0 := (r.Min.Y-dst.Rect.Min.Y)*dst.Stride + (r.Min.X-dst.Rect.Min.X)*4
+ i0 := dst.PixOffset(r.Min.X, r.Min.Y)
i1 := i0 + r.Dx()*4
- mi0 := (mp.Y-mask.Rect.Min.Y)*mask.Stride + mp.X - mask.Rect.Min.X
+ 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 {
sx0 := sp.X + x0 - r.Min.X
mx0 := mp.X + x0 - r.Min.X
sx1 := sx0 + (x1 - x0)
- i0 := (y0-dst.Rect.Min.Y)*dst.Stride + (x0-dst.Rect.Min.X)*4
+ i0 := dst.PixOffset(x0, y0)
di := dx * 4
for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx {
if !(Point{x, y}.In(p.Rect)) {
return color.RGBA{}
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
+ i := p.PixOffset(x, y)
return color.RGBA{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
}
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *RGBA) PixOffset(x, y int) int {
+ return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
+}
+
func (p *RGBA) Set(x, y int, c color.Color) {
if !(Point{x, y}.In(p.Rect)) {
return
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
+ i := p.PixOffset(x, y)
c1 := color.RGBAModel.Convert(c).(color.RGBA)
p.Pix[i+0] = c1.R
p.Pix[i+1] = c1.G
if !(Point{x, y}.In(p.Rect)) {
return
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
+ i := p.PixOffset(x, y)
p.Pix[i+0] = c.R
p.Pix[i+1] = c.G
p.Pix[i+2] = c.B
if r.Empty() {
return &RGBA{}
}
- i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*4
+ i := p.PixOffset(r.Min.X, r.Min.Y)
return &RGBA{
Pix: p.Pix[i:],
Stride: p.Stride,
if !(Point{x, y}.In(p.Rect)) {
return color.RGBA64{}
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
+ i := p.PixOffset(x, y)
return color.RGBA64{
uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1]),
uint16(p.Pix[i+2])<<8 | uint16(p.Pix[i+3]),
}
}
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *RGBA64) PixOffset(x, y int) int {
+ return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
+}
+
func (p *RGBA64) Set(x, y int, c color.Color) {
if !(Point{x, y}.In(p.Rect)) {
return
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
+ i := p.PixOffset(x, y)
c1 := color.RGBA64Model.Convert(c).(color.RGBA64)
p.Pix[i+0] = uint8(c1.R >> 8)
p.Pix[i+1] = uint8(c1.R)
if !(Point{x, y}.In(p.Rect)) {
return
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
+ i := p.PixOffset(x, y)
p.Pix[i+0] = uint8(c.R >> 8)
p.Pix[i+1] = uint8(c.R)
p.Pix[i+2] = uint8(c.G >> 8)
if r.Empty() {
return &RGBA64{}
}
- i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*8
+ i := p.PixOffset(r.Min.X, r.Min.Y)
return &RGBA64{
Pix: p.Pix[i:],
Stride: p.Stride,
if !(Point{x, y}.In(p.Rect)) {
return color.NRGBA{}
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
+ i := p.PixOffset(x, y)
return color.NRGBA{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
}
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *NRGBA) PixOffset(x, y int) int {
+ return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
+}
+
func (p *NRGBA) Set(x, y int, c color.Color) {
if !(Point{x, y}.In(p.Rect)) {
return
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
+ i := p.PixOffset(x, y)
c1 := color.NRGBAModel.Convert(c).(color.NRGBA)
p.Pix[i+0] = c1.R
p.Pix[i+1] = c1.G
if !(Point{x, y}.In(p.Rect)) {
return
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
+ i := p.PixOffset(x, y)
p.Pix[i+0] = c.R
p.Pix[i+1] = c.G
p.Pix[i+2] = c.B
if r.Empty() {
return &NRGBA{}
}
- i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*4
+ i := p.PixOffset(r.Min.X, r.Min.Y)
return &NRGBA{
Pix: p.Pix[i:],
Stride: p.Stride,
if !(Point{x, y}.In(p.Rect)) {
return color.NRGBA64{}
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
+ i := p.PixOffset(x, y)
return color.NRGBA64{
uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1]),
uint16(p.Pix[i+2])<<8 | uint16(p.Pix[i+3]),
}
}
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *NRGBA64) PixOffset(x, y int) int {
+ return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
+}
+
func (p *NRGBA64) Set(x, y int, c color.Color) {
if !(Point{x, y}.In(p.Rect)) {
return
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
+ i := p.PixOffset(x, y)
c1 := color.NRGBA64Model.Convert(c).(color.NRGBA64)
p.Pix[i+0] = uint8(c1.R >> 8)
p.Pix[i+1] = uint8(c1.R)
if !(Point{x, y}.In(p.Rect)) {
return
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
+ i := p.PixOffset(x, y)
p.Pix[i+0] = uint8(c.R >> 8)
p.Pix[i+1] = uint8(c.R)
p.Pix[i+2] = uint8(c.G >> 8)
if r.Empty() {
return &NRGBA64{}
}
- i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*8
+ i := p.PixOffset(r.Min.X, r.Min.Y)
return &NRGBA64{
Pix: p.Pix[i:],
Stride: p.Stride,
if !(Point{x, y}.In(p.Rect)) {
return color.Alpha{}
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
+ i := p.PixOffset(x, y)
return color.Alpha{p.Pix[i]}
}
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *Alpha) PixOffset(x, y int) int {
+ return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
+}
+
func (p *Alpha) Set(x, y int, c color.Color) {
if !(Point{x, y}.In(p.Rect)) {
return
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
+ i := p.PixOffset(x, y)
p.Pix[i] = color.AlphaModel.Convert(c).(color.Alpha).A
}
if !(Point{x, y}.In(p.Rect)) {
return
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
+ i := p.PixOffset(x, y)
p.Pix[i] = c.A
}
if r.Empty() {
return &Alpha{}
}
- i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*1
+ i := p.PixOffset(r.Min.X, r.Min.Y)
return &Alpha{
Pix: p.Pix[i:],
Stride: p.Stride,
if !(Point{x, y}.In(p.Rect)) {
return color.Alpha16{}
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
+ i := p.PixOffset(x, y)
return color.Alpha16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
}
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *Alpha16) PixOffset(x, y int) int {
+ return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
+}
+
func (p *Alpha16) Set(x, y int, c color.Color) {
if !(Point{x, y}.In(p.Rect)) {
return
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
+ i := p.PixOffset(x, y)
c1 := color.Alpha16Model.Convert(c).(color.Alpha16)
p.Pix[i+0] = uint8(c1.A >> 8)
p.Pix[i+1] = uint8(c1.A)
if !(Point{x, y}.In(p.Rect)) {
return
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
+ i := p.PixOffset(x, y)
p.Pix[i+0] = uint8(c.A >> 8)
p.Pix[i+1] = uint8(c.A)
}
if r.Empty() {
return &Alpha16{}
}
- i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*2
+ i := p.PixOffset(r.Min.X, r.Min.Y)
return &Alpha16{
Pix: p.Pix[i:],
Stride: p.Stride,
if !(Point{x, y}.In(p.Rect)) {
return color.Gray{}
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
+ i := p.PixOffset(x, y)
return color.Gray{p.Pix[i]}
}
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *Gray) PixOffset(x, y int) int {
+ return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
+}
+
func (p *Gray) Set(x, y int, c color.Color) {
if !(Point{x, y}.In(p.Rect)) {
return
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
+ i := p.PixOffset(x, y)
p.Pix[i] = color.GrayModel.Convert(c).(color.Gray).Y
}
if !(Point{x, y}.In(p.Rect)) {
return
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
+ i := p.PixOffset(x, y)
p.Pix[i] = c.Y
}
if r.Empty() {
return &Gray{}
}
- i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*1
+ i := p.PixOffset(r.Min.X, r.Min.Y)
return &Gray{
Pix: p.Pix[i:],
Stride: p.Stride,
if !(Point{x, y}.In(p.Rect)) {
return color.Gray16{}
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
+ i := p.PixOffset(x, y)
return color.Gray16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
}
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *Gray16) PixOffset(x, y int) int {
+ return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
+}
+
func (p *Gray16) Set(x, y int, c color.Color) {
if !(Point{x, y}.In(p.Rect)) {
return
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
+ i := p.PixOffset(x, y)
c1 := color.Gray16Model.Convert(c).(color.Gray16)
p.Pix[i+0] = uint8(c1.Y >> 8)
p.Pix[i+1] = uint8(c1.Y)
if !(Point{x, y}.In(p.Rect)) {
return
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
+ i := p.PixOffset(x, y)
p.Pix[i+0] = uint8(c.Y >> 8)
p.Pix[i+1] = uint8(c.Y)
}
if r.Empty() {
return &Gray16{}
}
- i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*2
+ i := p.PixOffset(r.Min.X, r.Min.Y)
return &Gray16{
Pix: p.Pix[i:],
Stride: p.Stride,
if !(Point{x, y}.In(p.Rect)) {
return p.Palette[0]
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
+ i := p.PixOffset(x, y)
return p.Palette[p.Pix[i]]
}
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *Paletted) PixOffset(x, y int) int {
+ return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
+}
+
func (p *Paletted) Set(x, y int, c color.Color) {
if !(Point{x, y}.In(p.Rect)) {
return
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
+ i := p.PixOffset(x, y)
p.Pix[i] = uint8(p.Palette.Index(c))
}
if !(Point{x, y}.In(p.Rect)) {
return 0
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
+ i := p.PixOffset(x, y)
return p.Pix[i]
}
if !(Point{x, y}.In(p.Rect)) {
return
}
- i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
+ i := p.PixOffset(x, y)
p.Pix[i] = index
}
Palette: p.Palette,
}
}
- i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*1
+ i := p.PixOffset(r.Min.X, r.Min.Y)
return &Paletted{
Pix: p.Pix[i:],
Stride: p.Stride,