Beispiel #1
0
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
	}
}
Beispiel #2
0
func (z *Rasterizer) rasterizeDstAlphaSrcOpaqueOpSrc(dst *image.Alpha, r image.Rectangle) {
	// TODO: non-zero vs even-odd winding?
	if r == dst.Bounds() && r == z.Bounds() {
		// We bypass the z.accumulateMask step and convert straight from
		// z.bufF32 or z.bufU32 to dst.Pix.
		if z.useFloatingPointMath {
			if haveFloatingAccumulateSIMD {
				floatingAccumulateOpSrcSIMD(dst.Pix, z.bufF32)
			} else {
				floatingAccumulateOpSrc(dst.Pix, z.bufF32)
			}
		} else {
			if haveFixedAccumulateSIMD {
				fixedAccumulateOpSrcSIMD(dst.Pix, z.bufU32)
			} else {
				fixedAccumulateOpSrc(dst.Pix, z.bufU32)
			}
		}
		return
	}

	z.accumulateMask()
	pix := dst.Pix[dst.PixOffset(r.Min.X, r.Min.Y):]
	for y, y1 := 0, r.Max.Y-r.Min.Y; y < y1; y++ {
		for x, x1 := 0, r.Max.X-r.Min.X; x < x1; x++ {
			ma := z.bufU32[y*z.size.X+x]

			// This formula is like rasterizeOpSrc's, simplified for the
			// concrete dst type and opaque src assumption.
			pix[y*dst.Stride+x] = uint8(ma >> 8)
		}
	}
}
func (r *Rasterizer) Fill(img *image.Alpha, p Polygon, nonZeroWindingRule bool) {
	r.table = make([]*Intersection, img.Bounds().Dy())
	var xmin, ymin, xmax, ymax float64
	xmin = p[0]
	ymin = p[1]
	xmax = xmin
	ymax = ymin
	var x, y float64
	for i := 2; i < len(p); i += 2 {
		x, y = p[i], p[i+1]
		if x > xmax {
			xmax = x
		} else if x < xmin {
			xmin = x
		}
		if y > ymax {
			ymax = y
		} else if y < ymin {
			ymin = y
		}
	}
	prevX, prevY := p[0], p[1]
	for i := 2; i < len(p); i += 2 {
		x, y = p[i], p[i+1]
		r.edge(prevX, prevY, x, y)
		prevX, prevY = x, y
	}
	r.edge(x, y, p[0], p[1])

	if nonZeroWindingRule {
		r.scanNonZero(img, int(ymin), int(ymax+0.5))
	} else {
		r.scanEvenOdd(img, int(ymin), int(ymax+0.5))
	}
}
Beispiel #4
0
func newAtFuncAlpha(p *image.Alpha) AtFunc {
	return func(x, y int) (r, g, b, a uint32) {
		i := p.PixOffset(x, y)
		a = uint32(p.Pix[i])
		a |= a << 8
		return a, a, a, a
	}
}
Beispiel #5
0
func (z *Rasterizer) rasterizeDstAlphaSrcOpaqueOpSrc(dst *image.Alpha, r image.Rectangle) {
	// TODO: add SIMD implementations.
	// TODO: add a fixed point math implementation.
	// TODO: non-zero vs even-odd winding?
	if r == dst.Bounds() && r == z.Bounds() {
		floatingAccumulate(dst.Pix, z.area)
		return
	}
	println("TODO: the general case")
}
Beispiel #6
0
// checkCornersCenter checks that the corners of the image are all 0x00 and the
// center is 0xff.
func checkCornersCenter(m *image.Alpha) error {
	if err := checkCorners(m); err != nil {
		return err
	}
	size := m.Bounds().Size()
	center := m.Pix[(size.Y/2)*m.Stride+(size.X/2)]
	if center != 0xff {
		return fmt.Errorf("center: got %#02x, want 0xff", center)
	}
	return nil
}
Beispiel #7
0
func drawPixels(img *image.Alpha, px, py, pw, ph uint, fill bool) {
	var x, y uint
	for y = 0; y < ph; y++ {
		for x = 0; x < pw; x++ {
			if fill {
				img.Set(int(px*pw+x), int(py*ph+y), image.White)
			} else {
				img.Set(int(px*pw+x), int(py*ph+y), image.Transparent)
			}
		}
	}
}
Beispiel #8
0
// checkCorners checks that the corners of the image are all 0x00.
func checkCorners(m *image.Alpha) error {
	size := m.Bounds().Size()
	corners := [4]uint8{
		m.Pix[(0*size.Y+0)*m.Stride+(0*size.X+0)],
		m.Pix[(0*size.Y+0)*m.Stride+(1*size.X-1)],
		m.Pix[(1*size.Y-1)*m.Stride+(0*size.X+0)],
		m.Pix[(1*size.Y-1)*m.Stride+(1*size.X-1)],
	}
	if corners != [4]uint8{} {
		return fmt.Errorf("corners were not all zero: %v", corners)
	}
	return nil
}
Beispiel #9
0
func Context(dst *image.Alpha, bold bool) *freetype.Context {
	c := freetype.NewContext()
	c.SetDPI(dpi)
	if bold {
		c.SetFont(bld)
	} else {
		c.SetFont(reg)
	}
	c.SetFontSize(size)
	c.SetClip(dst.Bounds())
	c.SetDst(dst)
	c.SetSrc(image.Opaque)
	return c
}
Beispiel #10
0
// Renders the mask to the canvas
func DrawSolidRGBA(dest *image.RGBA, mask *image.Alpha, rgba color.RGBA) {
	rect := dest.Bounds().Intersect(mask.Bounds())
	minX := uint32(rect.Min.X)
	minY := uint32(rect.Min.Y)
	maxX := uint32(rect.Max.X)
	maxY := uint32(rect.Max.Y)

	pixColor := *(*uint32)(unsafe.Pointer(&rgba))

	cs1 := pixColor & 0xff00ff
	cs2 := (pixColor >> 8) & 0xff00ff

	stride1 := uint32(dest.Stride)
	stride2 := uint32(mask.Stride)

	maxY *= stride1
	var pix, pixm []uint8
	var pixelx uint32
	var x, y1, y2 uint32
	for y1, y2 = minY*stride1, minY*stride2; y1 < maxY; y1, y2 = y1+stride1, y2+stride2 {
		pix = dest.Pix[y1:]
		pixm = mask.Pix[y2:]
		pixelx = minX * 4
		for x = minX; x < maxX; x++ {
			alpha := uint32(pixm[x])
			p := (*uint32)(unsafe.Pointer(&pix[pixelx]))
			if alpha != 0 {
				invAlpha := 0xff - alpha
				ct1 := (*p & 0xff00ff) * invAlpha
				ct2 := ((*p >> 8) & 0xff00ff) * invAlpha

				ct1 = ((ct1 + cs1*alpha) >> 8) & 0xff00ff
				ct2 = (ct2 + cs2*alpha) & 0xff00ff00
				*p = ct1 + ct2
			}
			pixelx += 4
		}
	}
}
Beispiel #11
0
func bilinearAlpha(src *image.Alpha, x, y float32) color.Alpha {
	p := findLinearSrc(src.Bounds(), x, y)

	// Slice offsets for the surrounding pixels.
	off00 := src.PixOffset(p.low.X, p.low.Y)
	off01 := src.PixOffset(p.high.X, p.low.Y)
	off10 := src.PixOffset(p.low.X, p.high.Y)
	off11 := src.PixOffset(p.high.X, p.high.Y)

	fa := float32(src.Pix[off00]) * p.frac00
	fa += float32(src.Pix[off01]) * p.frac01
	fa += float32(src.Pix[off10]) * p.frac10
	fa += float32(src.Pix[off11]) * p.frac11

	return color.Alpha{A: uint8(fa + 0.5)}
}
Beispiel #12
0
func FindSDFAlpha(img *image.Alpha, x, y, maxRadius int) int {

	w := img.Bounds().Dx()
	distance := maxRadius*maxRadius + 1
	alpha := uint8(0)
	if (image.Point{x, y}.In(img.Bounds())) {
		alpha = img.Pix[y*w+x]
	}

	a := uint8(0)
	for radius := 1; (radius <= maxRadius) && (radius*radius < distance); radius++ {
		for line := -radius; line <= radius; line++ {
			nx, ny := x+line, y+radius
			if (image.Point{nx, ny}.In(img.Bounds())) {
				a = img.Pix[ny*w+nx]
			} else {
				a = 0
			}
			//fmt.Println(line, x, ny, a, alpha)
			if a != alpha {
				nx = x - nx
				ny = y - ny
				d := (nx * nx) + (ny * ny)
				if d < distance {
					distance = d
				}
			}
			//}
		}

		for line := -radius; line <= radius; line++ {
			nx, ny := x+line, y-radius
			if (image.Point{nx, ny}.In(img.Bounds())) {
				a = img.Pix[ny*w+nx]
			} else {
				a = 0
			}
			if a != alpha {
				nx = x - nx
				ny = y - ny
				d := (nx * nx) + (ny * ny)
				if d < distance {
					distance = d
				}
			}
			//}
		}

		for line := -radius; line < radius; line++ {
			nx, ny := x+radius, y+line
			if (image.Point{nx, ny}.In(img.Bounds())) {
				a = img.Pix[ny*w+nx]
			} else {
				a = 0
			}
			if a != alpha {
				nx = x - nx
				ny = y - ny
				d := (nx * nx) + (ny * ny)
				if d < distance {
					distance = d
				}
			}
			//}
		}

		for line := -radius; line < radius; line++ {
			nx, ny := x-radius, y+line
			if (image.Point{nx, ny}.In(img.Bounds())) {
				a = img.Pix[ny*w+nx]
			} else {
				a = 0
			}
			if a != alpha {
				nx = x - nx
				ny = y - ny
				d := (nx * nx) + (ny * ny)
				if d < distance {
					distance = d
				}
			}
			//}
		}
	}
	SDF := float32(math.Sqrt(float64(distance)))
	if alpha == 0 {
		SDF = -SDF
	}
	SDF *= 127.5 / float32(maxRadius)
	SDF += 127.5
	if SDF < 0 {
		SDF = 0
	} else if SDF > 255 {
		SDF = 255
	}
	return int(SDF + 0.5)
}
Beispiel #13
0
func resizeAlpha(src *image.Alpha, size int) *image.Alpha {
	dst := image.NewAlpha(image.Rect(0, 0, size, size))
	draw.ApproxBiLinear.Scale(dst, dst.Bounds(), src, src.Bounds(), draw.Src, nil)
	return dst
}
Beispiel #14
0
func newSetFuncAlpha(p *image.Alpha) SetFunc {
	return func(x, y int, r, g, b, a uint32) {
		i := p.PixOffset(x, y)
		p.Pix[i] = uint8(a >> 8)
	}
}