Example #1
0
func (tr MatrixTransform) TransformRasterPoint(points ...*raster.Point) {
	for _, point := range points {
		x := float64(point.X) / 256
		y := float64(point.Y) / 256
		point.X = raster.Fix32((x*tr[0] + y*tr[2] + tr[4]) * 256)
		point.Y = raster.Fix32((x*tr[1] + y*tr[3] + tr[5]) * 256)
	}
}
Example #2
0
func (vertexAdder *VertexAdder) Vertex(x, y float64) {
	switch vertexAdder.command {
	case VertexStartCommand:
		vertexAdder.adder.Start(raster.Point{raster.Fix32(x * 256), raster.Fix32(y * 256)})
	default:
		vertexAdder.adder.Add1(raster.Point{raster.Fix32(x * 256), raster.Fix32(y * 256)})
	}
	vertexAdder.command = VertexNoCommand
}
Example #3
0
func (pathAdder *PathAdder) Convert(paths ...*PathStorage) {
	for _, path := range paths {
		j := 0
		for _, cmd := range path.commands {
			switch cmd {
			case MoveTo:
				pathAdder.firstPoint = raster.Point{raster.Fix32(path.vertices[j] * 256), raster.Fix32(path.vertices[j+1] * 256)}
				pathAdder.adder.Start(pathAdder.firstPoint)
				j += 2
			case LineTo:
				pathAdder.adder.Add1(raster.Point{raster.Fix32(path.vertices[j] * 256), raster.Fix32(path.vertices[j+1] * 256)})
				j += 2
			case QuadCurveTo:
				pathAdder.adder.Add2(raster.Point{raster.Fix32(path.vertices[j] * 256), raster.Fix32(path.vertices[j+1] * 256)}, raster.Point{raster.Fix32(path.vertices[j+2] * 256), raster.Fix32(path.vertices[j+3] * 256)})
				j += 4
			case CubicCurveTo:
				pathAdder.adder.Add3(raster.Point{raster.Fix32(path.vertices[j] * 256), raster.Fix32(path.vertices[j+1] * 256)}, raster.Point{raster.Fix32(path.vertices[j+2] * 256), raster.Fix32(path.vertices[j+3] * 256)}, raster.Point{raster.Fix32(path.vertices[j+4] * 256), raster.Fix32(path.vertices[j+5] * 256)})
				j += 6
			case ArcTo:
				lastPoint := arcAdder(pathAdder.adder, path.vertices[j], path.vertices[j+1], path.vertices[j+2], path.vertices[j+3], path.vertices[j+4], path.vertices[j+5], pathAdder.ApproximationScale)
				pathAdder.adder.Add1(lastPoint)
				j += 6
			case Close:
				pathAdder.adder.Add1(pathAdder.firstPoint)
			}
		}
	}
}
Example #4
0
// DrawString draws s at p and returns p advanced by the text extent. The text
// is placed so that the left edge of the em square of the first character of s
// and the baseline intersect at p. The majority of the affected pixels will be
// above and to the right of the point, but some may be below or to the left.
// For example, drawing a string that starts with a 'J' in an italic font may
// affect pixels below and left of the point.
// p is a raster.Point and can therefore represent sub-pixel positions.
func (c *Context) DrawString(s string, p raster.Point) (raster.Point, error) {
	if c.font == nil {
		return raster.Point{}, errors.New("freetype: DrawText called with a nil font")
	}
	prev, hasPrev := truetype.Index(0), false
	for _, rune := range s {
		index := c.font.Index(rune)
		if hasPrev {
			kern := raster.Fix32(c.font.Kerning(c.scale, prev, index)) << 2
			if c.hinting != NoHinting {
				kern = (kern + 128) &^ 255
			}
			p.X += kern
		}
		advanceWidth, mask, offset, err := c.glyph(index, p)
		if err != nil {
			return raster.Point{}, err
		}
		p.X += advanceWidth
		glyphRect := mask.Bounds().Add(offset)
		dr := c.clip.Intersect(glyphRect)
		if !dr.Empty() {
			mp := image.Point{0, dr.Min.Y - glyphRect.Min.Y}
			draw.DrawMask(c.dst, dr, c.src, image.ZP, mask, mp, draw.Over)
		}
		prev, hasPrev = index, true
	}
	return p, nil
}
Example #5
0
// rasterize returns the advance width, glyph mask and integer-pixel offset
// to render the given glyph at the given sub-pixel offsets.
// The 24.8 fixed point arguments fx and fy must be in the range [0, 1).
func (c *Context) rasterize(glyph truetype.Index, fx, fy raster.Fix32) (
	raster.Fix32, *image.Alpha, image.Point, error) {

	if err := c.glyphBuf.Load(c.font, c.scale, glyph, truetype.Hinting(c.hinting)); err != nil {
		return 0, nil, image.Point{}, err
	}
	// Calculate the integer-pixel bounds for the glyph.
	xmin := int(fx+raster.Fix32(c.glyphBuf.B.XMin<<2)) >> 8
	ymin := int(fy-raster.Fix32(c.glyphBuf.B.YMax<<2)) >> 8
	xmax := int(fx+raster.Fix32(c.glyphBuf.B.XMax<<2)+0xff) >> 8
	ymax := int(fy-raster.Fix32(c.glyphBuf.B.YMin<<2)+0xff) >> 8
	if xmin > xmax || ymin > ymax {
		return 0, nil, image.Point{}, errors.New("freetype: negative sized glyph")
	}
	// A TrueType's glyph's nodes can have negative co-ordinates, but the
	// rasterizer clips anything left of x=0 or above y=0. xmin and ymin
	// are the pixel offsets, based on the font's FUnit metrics, that let
	// a negative co-ordinate in TrueType space be non-negative in
	// rasterizer space. xmin and ymin are typically <= 0.
	fx += raster.Fix32(-xmin << 8)
	fy += raster.Fix32(-ymin << 8)
	// Rasterize the glyph's vectors.
	c.r.Clear()
	e0 := 0
	for _, e1 := range c.glyphBuf.End {
		c.drawContour(c.glyphBuf.Point[e0:e1], fx, fy)
		e0 = e1
	}
	a := image.NewAlpha(image.Rect(0, 0, xmax-xmin, ymax-ymin))
	c.r.Rasterize(raster.NewAlphaSrcPainter(a))
	return raster.Fix32(c.glyphBuf.AdvanceWidth << 2), a, image.Point{xmin, ymin}, nil
}
Example #6
0
func (ig *ImageGraphics) TextLen(s string, font chart.Font) int {
	c := freetype.NewContext()
	c.SetDPI(dpi)
	c.SetFont(ig.font)
	fontsize := ig.relFontsizeToPixel(font.Size)
	c.SetFontSize(fontsize)
	scale := int32(fontsize * dpi * (64.0 / 72.0))
	var p raster.Point
	prev, hasPrev := truetype.Index(0), false
	for _, rune := range s {
		index := ig.font.Index(rune)
		if hasPrev {
			p.X += raster.Fix32(ig.font.Kerning(scale, prev, index)) << 2
		}
		p.X += raster.Fix32(ig.font.HMetric(scale, index).AdvanceWidth) << 2
		prev, hasPrev = index, true
	}
	return int((p.X + 127) / 256)
}
Example #7
0
File: arc.go Project: mathpl/bosun
func arcAdder(adder raster.Adder, x, y, rx, ry, start, angle, scale float64) raster.Point {
	end := start + angle
	clockWise := true
	if angle < 0 {
		clockWise = false
	}
	ra := (math.Abs(rx) + math.Abs(ry)) / 2
	da := math.Acos(ra/(ra+0.125/scale)) * 2
	//normalize
	if !clockWise {
		da = -da
	}
	angle = start + da
	var curX, curY float64
	for {
		if (angle < end-da/4) != clockWise {
			curX = x + math.Cos(end)*rx
			curY = y + math.Sin(end)*ry
			return raster.Point{raster.Fix32(curX * 256), raster.Fix32(curY * 256)}
		}
		curX = x + math.Cos(angle)*rx
		curY = y + math.Sin(angle)*ry

		angle += da
		adder.Add1(raster.Point{raster.Fix32(curX * 256), raster.Fix32(curY * 256)})
	}
	return raster.Point{raster.Fix32(curX * 256), raster.Fix32(curY * 256)}
}
Example #8
0
// drawContour draws the given closed contour with the given offset.
func (c *Context) drawContour(ps []truetype.Point, dx, dy raster.Fix32) {
	if len(ps) == 0 {
		return
	}

	// The low bit of each point's Flags value is whether the point is on the
	// curve. Truetype fonts only have quadratic Bézier curves, not cubics.
	// Thus, two consecutive off-curve points imply an on-curve point in the
	// middle of those two.
	//
	// See http://chanae.walon.org/pub/ttf/ttf_glyphs.htm for more details.

	// ps[0] is a truetype.Point measured in FUnits and positive Y going
	// upwards. start is the same thing measured in fixed point units and
	// positive Y going downwards, and offset by (dx, dy).
	start := raster.Point{
		X: dx + raster.Fix32(ps[0].X<<2),
		Y: dy - raster.Fix32(ps[0].Y<<2),
	}
	others := []truetype.Point(nil)
	if ps[0].Flags&0x01 != 0 {
		others = ps[1:]
	} else {
		last := raster.Point{
			X: dx + raster.Fix32(ps[len(ps)-1].X<<2),
			Y: dy - raster.Fix32(ps[len(ps)-1].Y<<2),
		}
		if ps[len(ps)-1].Flags&0x01 != 0 {
			start = last
			others = ps[:len(ps)-1]
		} else {
			start = raster.Point{
				X: (start.X + last.X) / 2,
				Y: (start.Y + last.Y) / 2,
			}
			others = ps
		}
	}
	c.r.Start(start)
	q0, on0 := start, true
	for _, p := range others {
		q := raster.Point{
			X: dx + raster.Fix32(p.X<<2),
			Y: dy - raster.Fix32(p.Y<<2),
		}
		on := p.Flags&0x01 != 0
		if on {
			if on0 {
				c.r.Add1(q)
			} else {
				c.r.Add2(q0, q)
			}
		} else {
			if on0 {
				// No-op.
			} else {
				mid := raster.Point{
					X: (q0.X + q.X) / 2,
					Y: (q0.Y + q.Y) / 2,
				}
				c.r.Add2(q0, mid)
			}
		}
		q0, on0 = q, on
	}
	// Close the curve.
	if on0 {
		c.r.Add1(start)
	} else {
		c.r.Add2(q0, start)
	}
}
Example #9
0
// PointToFix32 converts the given number of points (as in ``a 12 point font'')
// into fixed point units.
func (c *Context) PointToFix32(x float64) raster.Fix32 {
	return raster.Fix32(x * float64(c.dpi) * (256.0 / 72.0))
}
Example #10
0
// Pt converts from a co-ordinate pair measured in pixels to a raster.Point
// co-ordinate pair measured in raster.Fix32 units.
func Pt(x, y int) raster.Point {
	return raster.Point{
		X: raster.Fix32(x << 8),
		Y: raster.Fix32(y << 8),
	}
}