Example #1
1
func drawPerimeterNumber(dst draw.Image, pt image.Point, number string) {
	dot := fixed.P(pt.X, pt.Y)
	d := font.Drawer{
		Dst:  dst,
		Src:  image.NewUniform(color.RGBA{B: 0xFF, A: 0xFF}),
		Face: basicfont.Face7x13,
		Dot:  dot,
	}
	d.DrawString(number)
}
Example #2
0
func (c *Context) Render(txt string, size float64, col color.Color) (*image.RGBA, error) {
	bnd := c.fnt.Bounds(fixed.I(int(size + 0.5)))
	lh := int26_6ToFloat64(bnd.Max.Y) - int26_6ToFloat64(bnd.Min.Y) - 0.5

	c.ft.SetSrc(image.NewUniform(col))
	c.ft.SetFontSize(size)

	/* Render image to temporary buffer to determine final size */
	tmp := nullImage{}
	c.ft.SetDst(tmp)
	c.ft.SetClip(tmp.Bounds())
	p, err := c.ft.DrawString(txt, fixed.P(0, int(lh)))
	if err != nil {
		return nil, err
	}

	dst := image.NewRGBA(image.Rect(0, 0, int(int26_6ToFloat64(p.X)+0.5), int(lh)))
	draw.Draw(dst, dst.Bounds(), image.NewUniform(color.RGBA{}), image.ZP, draw.Src)
	c.ft.SetDst(dst)
	c.ft.SetClip(dst.Bounds())

	p, err = c.ft.DrawString(txt, fixed.P(0, int(size)))
	if err != nil {
		return nil, err
	}

	return dst, nil
}
Example #3
0
func main() {
	const (
		w = 400
		h = 400
	)
	r := raster.NewRasterizer(w, h)
	r.UseNonZeroWinding = true

	cjs := []struct {
		c raster.Capper
		j raster.Joiner
	}{
		{raster.RoundCapper, raster.RoundJoiner},
		{raster.ButtCapper, raster.BevelJoiner},
		{raster.SquareCapper, raster.BevelJoiner},
	}

	for i, cj := range cjs {
		var path raster.Path
		path.Start(fixed.P(30+100*i, 30+120*i))
		path.Add1(fixed.P(180+100*i, 80+120*i))
		path.Add1(fixed.P(50+100*i, 130+120*i))
		raster.Stroke(r, path, fixed.I(20), cj.c, cj.j)
	}

	rgba := image.NewRGBA(image.Rect(0, 0, w, h))
	draw.Draw(rgba, rgba.Bounds(), image.Black, image.Point{}, draw.Src)
	p := raster.NewRGBAPainter(rgba)
	p.SetColor(color.RGBA{0x7f, 0x7f, 0x7f, 0xff})
	r.Rasterize(p)

	white := color.RGBA{0xff, 0xff, 0xff, 0xff}
	for i := range cjs {
		rgba.SetRGBA(30+100*i, 30+120*i, white)
		rgba.SetRGBA(180+100*i, 80+120*i, white)
		rgba.SetRGBA(50+100*i, 130+120*i, white)
	}

	// Save that RGBA image to disk.
	outFile, err := os.Create("out.png")
	if err != nil {
		log.Println(err)
		os.Exit(1)
	}
	defer outFile.Close()
	b := bufio.NewWriter(outFile)
	err = png.Encode(b, rgba)
	if err != nil {
		log.Println(err)
		os.Exit(1)
	}
	err = b.Flush()
	if err != nil {
		log.Println(err)
		os.Exit(1)
	}
	fmt.Println("Wrote out.png OK.")
}
Example #4
0
func TestHorizontalLayout(t *testing.T) {
	layout := NewHorizontalLayout(fixed.P(10, 10), fixed.P(100, 100))

	if r, ok := layout.NextBounds(); !ok {
		t.Error("no bounds returned by the horizontal layout")
	} else if r != fixed.R(10, 10, 110, 110) {
		t.Error("invalid bounds returned by the horizontal layout:", r)
	}

	if r, ok := layout.NextBounds(); !ok {
		t.Error("no bounds returned by the horizontal layout")
	} else if r != fixed.R(110, 10, 210, 110) {
		t.Error("invalid bounds returned by the horizontal layout:", r)
	}
}
Example #5
0
func BenchmarkDrawString(b *testing.B) {
	data, err := ioutil.ReadFile("../licenses/gpl.txt")
	if err != nil {
		b.Fatal(err)
	}
	lines := strings.Split(string(data), "\n")
	data, err = ioutil.ReadFile("../testdata/luxisr.ttf")
	if err != nil {
		b.Fatal(err)
	}
	f, err := Parse(data)
	if err != nil {
		b.Fatal(err)
	}
	dst := image.NewRGBA(image.Rect(0, 0, 800, 600))
	draw.Draw(dst, dst.Bounds(), image.White, image.ZP, draw.Src)
	d := &font.Drawer{
		Dst:  dst,
		Src:  image.Black,
		Face: NewFace(f, nil),
	}
	b.ReportAllocs()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		for j, line := range lines {
			d.Dot = fixed.P(0, (j*16)%600)
			d.DrawString(line)
		}
	}
}
Example #6
0
func TestDrawView(t *testing.T) {
	const str = "Hello World!\nHow are you doing?"

	f1 := truetype.NewFace(clearSans, &truetype.Options{DPI: 144})
	f2 := truetype.NewFace(clearSansBoldItalic, &truetype.Options{DPI: 144})

	red := image.NewUniform(color.RGBA{255, 0, 0, 255})
	yellow := image.NewUniform(color.RGBA{255, 255, 0, 255})

	view, _ := Render(
		NewReader(
			strings.NewReader("Hello World!\nHow are you doing?"),
			Style{Offset: 0, Face: f1, Foreground: image.Black, Background: yellow},
			Style{Offset: 10, Face: f2, Foreground: red, Background: yellow},
			Style{Offset: 20, Face: f1, Foreground: image.Black, Background: image.White},
		),
		NewNaturalLayout(fixed.P(0, 0)),
	)

	size := view.Bounds.Max.Sub(view.Bounds.Min)

	for _, a := range []Alignment{Left, Right, Center, Justify} {
		dst := image.NewRGBA(image.Rect(0, 0, int(size.X>>6)+1, int(size.Y>>6)+1))
		view.Align(a)
		view.Draw(dst, LeftToRight)
		saveTest(t, dst, "text.View.Draw_"+a.(fmt.Stringer).String()+".png")
	}
}
Example #7
0
func (l *Label) newTextTexture(eng sprite.Engine) sprite.SubTex {

	fg, bg := image.Black, image.White
	draw.Draw(l.rgba, l.rgba.Bounds(), bg, image.ZP, draw.Src)
	d := &sfont.Drawer{
		Dst: l.rgba,
		Src: fg,
		Face: truetype.NewFace(l.font, truetype.Options{
			Size:    l.fontSize,
			DPI:     72,
			Hinting: sfont.HintingFull,
		}),
	}

	spacing := 1.5
	dy := int(math.Ceil(l.fontSize * spacing))
	for i, s := range strings.Split(l.Text, "\n") {
		d.Dot = fixed.P(0, int(l.fontSize*0.8)+dy*i)
		d.DrawString(s)
	}

	t, err := eng.LoadTexture(l.rgba)
	if err != nil {
		log.Fatal(err)
	}

	return sprite.SubTex{t, l.rgba.Bounds()}
}
Example #8
0
func drawLayerNumber(dst draw.Image, n int) {
	d := font.Drawer{
		Dst:  dst,
		Src:  image.Black,
		Face: basicfont.Face7x13,
		Dot:  fixed.P(2, 13),
	}
	d.DrawString(fmt.Sprintf("Layer %03d", n))
}
Example #9
0
func TestVerticalLayout(t *testing.T) {
	layout := NewVerticalLayout(fixed.P(10, 10), fixed.I(100))

	if r, ok := layout.NextBounds(); !ok {
		t.Error("no bounds returned by the vertical layout")
	} else if r != fixed.R(10, 10, 110, 33554431) {
		t.Error("invalid bounds returned by the vertical layout:", r)
	}

	if _, ok := layout.NextBounds(); ok {
		t.Error("incomplete vertical layout")
	}
}
Example #10
0
func (f *Font) RenderNRGBA(text string) *image.NRGBA {
	width, height, yBearing := f.TextDimensions(text)
	font := f.TTF
	size := f.Size

	if size <= 0 {
		panic("Font size cannot be <= 0")
	}

	// Default colors
	if f.FG == nil {
		f.FG = color.NRGBA{0, 0, 0, 0}
	}
	if f.BG == nil {
		f.BG = color.NRGBA{0, 0, 0, 0}
	}

	// Colors
	fg := image.NewUniform(f.FG)
	bg := image.NewUniform(f.BG)

	// Create the font context
	c := freetype.NewContext()

	nrgba := image.NewNRGBA(image.Rect(0, 0, width, height))
	draw.Draw(nrgba, nrgba.Bounds(), bg, image.ZP, draw.Src)

	c.SetDPI(dpi)
	c.SetFont(font)
	c.SetFontSize(size)
	c.SetClip(nrgba.Bounds())
	c.SetDst(nrgba)
	c.SetSrc(fg)

	// Draw the text.
	pt := fixed.P(0, int(yBearing))
	_, err := c.DrawString(text, pt)
	if err != nil {
		log.Println(err)
		return nil
	}

	return nrgba
}
Example #11
0
func TestCharAtSuccess(t *testing.T) {
	f := truetype.NewFace(clearSans, nil)
	defer f.Close()

	c := NewReader(strings.NewReader("Hello World!\n"),
		Style{Offset: 0, Face: f, Foreground: image.Black, Background: image.White},
	)

	view, err := Render(c, NewNaturalLayout(fixed.P(1, 1)))

	if err != nil {
		t.Error(err)
		return
	}

	char, bounds, ok := view.CharAt(fixed.Point26_6{
		X: int26_6(31, 0),
		Y: int26_6(5, 0),
	}, LeftToRight)

	if !ok {
		t.Error("no char found")
		return
	}

	if char != (Char{
		Offset:     5,
		Rune:       ' ',
		Face:       f,
		Foreground: image.Black,
		Background: image.White,
	}) {
		t.Error("invalid char found:", char)
	}

	if bounds != (fixed.Rectangle26_6{
		Min: fixed.Point26_6{X: int26_6(28, 37), Y: int26_6(1, 0)},
		Max: fixed.Point26_6{X: int26_6(31, 35), Y: int26_6(15, 5)},
	}) {
		t.Error("invalid char bounds:", bounds)
	}
}
Example #12
0
func (t *TextTexture) Create(eng sprite.Engine, text string) (sprite.SubTex, error) {
	draw.Draw(t.rgba, t.rgba.Bounds(), t.bg, image.ZP, draw.Src)
	d := &sfont.Drawer{
		Dst:  t.rgba,
		Src:  t.fg,
		Face: t.Face,
	}

	dy := int(math.Ceil(t.Face.Size * t.Spacing))
	for i, s := range strings.Split(text, "\n") {
		d.Dot = fixed.P(0, int(t.Face.Size*0.8)+dy*i)
		d.DrawString(s)
	}

	tex, err := eng.LoadTexture(t.rgba)
	if err != nil {
		return sprite.SubTex{}, err
	}

	return sprite.SubTex{tex, t.rgba.Bounds()}, nil
}
Example #13
0
func (f *Font) Render(text string, width, height float32, color Color) *Texture {
	/* Set color */
	f.drawer.Src = image.NewUniform(color.RGBA())

	line := math.Ceil(f.Size * f.DPI / 72)
	//height := int(f.Spacing * line)
	//width := int(float64(f.drawer.MeasureString(text)) / f.Size)

	/* Create and attach destination image */
	rgba := image.NewRGBA(image.Rect(0, 0, int(width), int(height)))
	f.drawer.Dst = rgba

	/* Draw text */
	f.drawer.Dot = fixed.P(0, int(line))
	f.drawer.DrawString(text)

	fmt.Println("Font texture size W:", width, "H:", height)
	tx := CreateTexture(int32(width), int32(height))
	tx.Buffer(rgba)
	return tx
}
Example #14
0
func TestCharAtFailure(t *testing.T) {
	f := truetype.NewFace(clearSans, nil)
	defer f.Close()

	c := NewReader(strings.NewReader("Hello World!\n"),
		Style{Offset: 0, Face: f, Foreground: image.Black, Background: image.White},
	)

	view, err := Render(c, NewNaturalLayout(fixed.P(1, 1)))

	if err != nil {
		t.Error(err)
		return
	}

	char, bounds, ok := view.CharAt(fixed.Point26_6{}, LeftToRight)

	if char != (Char{}) || bounds != (fixed.Rectangle26_6{}) || ok {
		t.Error("not char should have been found at (0, 0) but we got", char, bounds, ok)
	}
}
Example #15
0
func (app *App) drawText(img draw.Image, metrics *battery.Metrics, f battery.MetricFormatter) error {
	// measure the text so that it can be centered within the text area.  if f
	// is a MaxMetricFormatter use it's MaxFormattedWidth method to determine
	// the appropriate centering position so that a change in metric values
	// (but not formatter) will have a smooth transition in the ui.
	app.font.Dst = img
	text := f.Format(metrics)
	measuretext := text
	if fmax, ok := f.(battery.MaxMetricFormatter); ok {
		measuretext = fmax.MaxFormattedWidth()
	}
	xoffset := app.font.MeasureString(measuretext)
	ttwidth := int(xoffset >> 6)
	ttheight := int(app.tt.PointToFixed(app.Layout.fontSize) >> 6)
	padleft := (app.Layout.textRect.Size().X - ttwidth) / 2
	padtop := (app.Layout.textRect.Size().Y - ttheight) / 2
	x := app.Layout.textRect.Min.X + padleft
	y := app.Layout.textRect.Max.Y - padtop
	app.font.Dot = fixed.P(x, y)
	app.font.DrawString(text)
	return nil
}
Example #16
0
func parseFont() error {
	f, err := ebitenutil.OpenFile("_resources/fonts/mplus-1p-regular.ttf")
	if err != nil {
		return err
	}
	defer func() {
		_ = f.Close()
	}()
	b, err := ioutil.ReadAll(f)
	if err != nil {
		return err
	}
	tt, err := truetype.Parse(b)
	if err != nil {
		return err
	}
	w, h := textImage.Size()
	dst := image.NewRGBA(image.Rect(0, 0, w, h))
	const size = 24
	const dpi = 72
	d := &font.Drawer{
		Dst: dst,
		Src: image.White,
		Face: truetype.NewFace(tt, &truetype.Options{
			Size:    size,
			DPI:     dpi,
			Hinting: font.HintingFull,
		}),
	}
	y := size
	for _, s := range text {
		d.Dot = fixed.P(0, y)
		d.DrawString(s)
		y += size
	}
	return textImage.ReplacePixels(dst.Pix)
}
Example #17
0
func (atlas *FontAtlas) loadGlyph(r rune) {
	if _, ok := atlas.Rendered[r]; ok {
		return
	}
	atlas.Dirty = true

	glyph := Glyph{}
	glyph.Rune = r

	bounds, advance, _ := atlas.Face.GlyphBounds(r)
	glyph.Bounds = bounds
	glyph.Advance = advance

	width := ceilPx(bounds.Max.X-bounds.Min.X) + glyphPadding*2
	height := ceilPx(bounds.Max.Y-bounds.Min.Y) + glyphPadding*2

	if atlas.CursorX+glyphMargin+width+glyphMargin > atlas.Image.Bounds().Dx() {
		atlas.CursorX = 0
		atlas.CursorY += glyphMargin + atlas.maxGlyphInRow
	}

	x := atlas.CursorX + glyphMargin
	y := atlas.CursorY + glyphMargin

	glyph.Loc = image.Rect(x, y, x+width, y+height)
	glyph.RelLoc = RelBounds(glyph.Loc, atlas.Image.Bounds())

	pt := fixed.P(x+glyphPadding, y+glyphPadding).Sub(bounds.Min)
	atlas.Context.DrawString(string(r), pt)

	if height > atlas.maxGlyphInRow {
		atlas.maxGlyphInRow = height
	}
	atlas.CursorX += glyphMargin + width + glyphMargin

	atlas.Rendered[r] = glyph
}
Example #18
0
func (atlas *FontAtlas) Draw(text string, b Bounds) {
	m := atlas.Face.Metrics()
	w := pow2(font.MeasureString(atlas.Face, text).Ceil())
	h := pow2(m.Ascent.Ceil() + m.Descent.Ceil())
	if w > 2048 {
		w = 2048
	}
	if h > 2048 {
		h = 2048
	}
	b.Max.X = b.Min.X + float32(w)
	b.Max.Y = b.Min.Y + float32(h)

	rendered := image.NewRGBA(image.Rect(0, 0, w, h))
	drawer := font.Drawer{
		Dst:  rendered,
		Src:  image.Black,
		Face: atlas.Face,
	}
	drawer.Dot = fixed.P(0, m.Ascent.Ceil())
	drawer.DrawString(text)

	atlas.draw(rendered, b)
}
Example #19
0
func main() {
	flag.Parse()

	if *flagFontfile == "" || *flagOutdir == "" || *flagPkgname == "" {
		flag.Usage()
		return
	}

	if *flagScale < 1 {
		log.Println("scale must be >= 1")
		return
	}

	bin, err := ioutil.ReadFile(*flagFontfile)
	if err != nil {
		log.Println(err)
		return
	}
	f, err := truetype.Parse(bin)
	if err != nil {
		log.Println(err)
		return
	}

	sdf := NewSDF(*flagTSize, *flagFSize, *flagPad, *flagScale)
	d := &font.Drawer{
		Dst: sdf.src,
		Src: image.Black,
		Face: truetype.NewFace(f, &truetype.Options{
			Size:    sdf.fsize,
			Hinting: font.HintingNone,
		}),
	}

	var glyphs []*glyph
	if *flagAscii {
		glyphs = fromString(ascii, d.Face)
	} else {
		glyphs = enumerate(f, d.Face)
	}
	if len(glyphs) == 0 {
		log.Fatalf("sdf: failed to enumerate glyphs from %s\n", *flagFontfile)
	}
	if a := area(glyphs, sdf.pad); a > sdf.tsize*sdf.tsize {
		asq := math.Sqrt(float64(a))
		log.Fatalf("sdf: glyphs area %[1]v ~= %.2[2]fx%.2[2]f greater than texture area %[3]vx%[3]v\n", a, asq, sdf.tsize)
	}
	sort.Sort(byHeight(glyphs))

	x, y, dy := 0, 0, glyphs[0].height()+sdf.pad*2
	var wg sync.WaitGroup
	for _, g := range glyphs {
		adx, ady := g.width()+sdf.pad*2, g.height()+sdf.pad*2
		if x+adx > sdf.tsize {
			x = 0
			y += dy
			dy = ady
		}

		g.tc = [4]float32{
			float32(x+sdf.pad) / float32(sdf.tsize),
			float32(y+sdf.pad) / float32(sdf.tsize),
			float32(g.width()) / float32(sdf.tsize),
			float32(g.height()) / float32(sdf.tsize),
		}

		d.Dot = fixed.P(x+sdf.pad-int(g.b.Min.X>>6), y+sdf.pad-g.b.Min.Y.Ceil())
		d.DrawString(string(g.r))

		wg.Add(1)
		go func(m image.Image) {
			sdf.calc(m)
			wg.Done()
		}(sdf.src.SubImage(image.Rect(x, y, x+adx, y+ady)))

		x += adx
	}
	wg.Wait()

	sdf.writeSrc()
	sdf.writeDst()
	sdf.writeOut()

	// generate source file to accompany out.png
	buf := new(bytes.Buffer)
	buf.WriteString("// generated by gen.go; DO NOT EDIT\n")
	fmt.Fprintf(buf, "package %s\n\n", *flagPkgname)

	ascent := float32(d.Face.Metrics().Ascent.Ceil())
	descent := float32(d.Face.Metrics().Descent.Floor())
	scale := float32(sdf.fsize) / (ascent + descent)
	fmt.Fprintf(buf, "const AscentUnit = %v\n", (ascent*scale)/float32(sdf.fsize))
	fmt.Fprintf(buf, "const DescentUnit = %v\n", (descent*scale)/float32(sdf.fsize))
	fmt.Fprintf(buf, "const TextureSize = %v\n", *flagTSize)
	fmt.Fprintf(buf, "const FontSize = %v\n", *flagFSize)
	fmt.Fprintf(buf, "const Pad = %v\n\n", *flagPad)

	buf.WriteString("var Texcoords = map[rune][4]float32{\n")
	for _, g := range glyphs {
		s := string(g.r)
		if s == "'" {
			s = `\'`
		} else if s == "\\" {
			s = `\\`
		}
		fmt.Fprintf(buf, "\t'%s': {%v, %v, %v, %v},\n", s, g.tc[0], g.tc[1], g.tc[2], g.tc[3])
	}
	buf.WriteString("}\n\n")

	buf.WriteString("var Bounds = map[rune][5]float32{\n")
	for _, g := range glyphs {
		s := string(g.r)
		if s == "'" {
			s = `\'`
		} else if s == "\\" {
			s = `\\`
		}
		nx := float32(g.b.Min.X>>6) / float32(sdf.fsize)
		ny := float32(g.b.Max.Y>>6) / float32(sdf.fsize)
		rect := g.b.Max.Sub(g.b.Min)
		w, h := float32(rect.X>>6), float32(rect.Y>>6)
		nw := float32(w) / float32(sdf.fsize)
		nh := float32(h) / float32(sdf.fsize)
		na := float32(g.a>>6) / float32(sdf.fsize)
		fmt.Fprintf(buf, "\t'%s': {%v, %v, %v, %v, %v},\n", s, nx, ny, nw, nh, na)
	}
	buf.WriteString("}\n\n")

	if err := ioutil.WriteFile(filepath.Join(*flagOutdir, "texcoords.go"), buf.Bytes(), 0644); err != nil {
		log.Fatal(err)
	}
}
Example #20
0
func ExampleParseFont() {
	readFile := func(name string) ([]byte, error) {
		return ioutil.ReadFile(filepath.FromSlash(path.Join("../testdata/fixed", name)))
	}
	fontData, err := readFile("unicode.7x13.font")
	if err != nil {
		log.Fatal(err)
	}
	face, err := plan9font.ParseFont(fontData, readFile)
	if err != nil {
		log.Fatal(err)
	}
	// TODO: derive the ascent from the face's metrics.
	const ascent = 11

	dst := image.NewRGBA(image.Rect(0, 0, 4*7, 13))
	draw.Draw(dst, dst.Bounds(), image.Black, image.Point{}, draw.Src)
	d := &font.Drawer{
		Dst:  dst,
		Src:  image.White,
		Face: face,
		Dot:  fixed.P(0, ascent),
	}
	// Draw:
	// 	- U+0053 LATIN CAPITAL LETTER S
	//	- U+03A3 GREEK CAPITAL LETTER SIGMA
	//	- U+222B INTEGRAL
	//	- U+3055 HIRAGANA LETTER SA
	// The testdata does not contain the CJK subfont files, so U+3055 HIRAGANA
	// LETTER SA (さ) should be rendered as U+FFFD REPLACEMENT CHARACTER (�).
	//
	// The missing subfont file will trigger an "open
	// ../testdata/shinonome/k12.3000: no such file or directory" log message.
	// This is expected and can be ignored.
	d.DrawString("SΣ∫さ")

	// Convert the dst image to ASCII art.
	var out []byte
	b := dst.Bounds()
	for y := b.Min.Y; y < b.Max.Y; y++ {
		out = append(out, '0'+byte(y%10), ' ')
		for x := b.Min.X; x < b.Max.X; x++ {
			if dst.RGBAAt(x, y).R > 0 {
				out = append(out, 'X')
			} else {
				out = append(out, '.')
			}
		}
		// Highlight the last row before the baseline. Glyphs like 'S' without
		// descenders should not affect any pixels whose Y coordinate is >= the
		// baseline.
		if y == ascent-1 {
			out = append(out, '_')
		}
		out = append(out, '\n')
	}
	os.Stdout.Write(out)

	// Output:
	// 0 ..................X.........
	// 1 .................X.X........
	// 2 .XXXX..XXXXXX....X.....XXX..
	// 3 X....X.X.........X....XX.XX.
	// 4 X.......X........X....X.X.X.
	// 5 X........X.......X....XXX.X.
	// 6 .XXXX.....X......X....XX.XX.
	// 7 .....X...X.......X....XX.XX.
	// 8 .....X..X........X....XXXXX.
	// 9 X....X.X.........X....XX.XX.
	// 0 .XXXX..XXXXXX....X.....XXX.._
	// 1 ...............X.X..........
	// 2 ................X...........
}
Example #21
0
func TestAlign(t *testing.T) {
	f := truetype.NewFace(clearSans, nil)
	defer f.Close()

	view, _ := Render(
		NewReader(
			strings.NewReader("Hello World!\nHow are you doing?"),
			Style{Offset: 0, Face: f, Foreground: image.Black, Background: image.White},
		),
		NewNaturalLayout(fixed.P(1, 1)),
	)

	// -- test right alignment --
	view.Align(Right)

	if !reflect.DeepEqual(view, View{
		Frames: []Frame{{
			Lines: []Line{
				{
					Runs: []Run{{
						Offset:     0,
						Text:       "Hello World!",
						Face:       f,
						Foreground: image.Black,
						Background: image.White,
						Bounds: fixed.Rectangle26_6{
							Min: fixed.Point26_6{X: int26_6(41, 6), Y: int26_6(1, 0)},
							Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(15, 5)},
						},
					}},

					Bounds: fixed.Rectangle26_6{
						Min: fixed.Point26_6{X: int26_6(41, 6), Y: int26_6(1, 0)},
						Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(15, 5)},
					},
				},
				{
					LF: Char{
						Offset:     12,
						Rune:       '\n',
						Face:       f,
						Foreground: image.Black,
						Background: image.White,
					},

					Runs: []Run{{
						Offset:     13,
						Text:       "How are you doing?",
						Face:       f,
						Foreground: image.Black,
						Background: image.White,
						Bounds: fixed.Rectangle26_6{
							Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(13, 0)},
							Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(27, 5)},
						},
					}},

					Bounds: fixed.Rectangle26_6{
						Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(13, 0)},
						Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(27, 5)},
					},
				},
			},

			Bounds: fixed.Rectangle26_6{
				Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(1, 0)},
				Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(27, 5)},
			},
		}},

		Bounds: fixed.Rectangle26_6{
			Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(1, 0)},
			Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(27, 5)},
		},
	}) {
		t.Error("invalid right alignment:", view)
	}

	// -- test center alignment --
	view.Align(Center)

	if !reflect.DeepEqual(view, View{
		Frames: []Frame{{
			Lines: []Line{
				{
					Runs: []Run{{
						Offset:     0,
						Text:       "Hello World!",
						Face:       f,
						Foreground: image.Black,
						Background: image.White,
						Bounds: fixed.Rectangle26_6{
							Min: fixed.Point26_6{X: int26_6(21, 3), Y: int26_6(1, 0)},
							Max: fixed.Point26_6{X: int26_6(85, 58), Y: int26_6(15, 5)},
						},
					}},

					Bounds: fixed.Rectangle26_6{
						Min: fixed.Point26_6{X: int26_6(21, 3), Y: int26_6(1, 0)},
						Max: fixed.Point26_6{X: int26_6(85, 58), Y: int26_6(15, 5)},
					},
				},
				{
					LF: Char{
						Offset:     12,
						Rune:       '\n',
						Face:       f,
						Foreground: image.Black,
						Background: image.White,
					},

					Runs: []Run{{
						Offset:     13,
						Text:       "How are you doing?",
						Face:       f,
						Foreground: image.Black,
						Background: image.White,
						Bounds: fixed.Rectangle26_6{
							Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(13, 0)},
							Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(27, 5)},
						},
					}},

					Bounds: fixed.Rectangle26_6{
						Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(13, 0)},
						Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(27, 5)},
					},
				},
			},

			Bounds: fixed.Rectangle26_6{
				Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(1, 0)},
				Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(27, 5)},
			},
		}},

		Bounds: fixed.Rectangle26_6{
			Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(1, 0)},
			Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(27, 5)},
		},
	}) {
		t.Error("invalid center alignment:", view)
	}

	// -- test left alignment --
	view.Align(Left)

	if !reflect.DeepEqual(view, View{
		Frames: []Frame{{
			Lines: []Line{
				{
					Runs: []Run{{
						Offset:     0,
						Text:       "Hello World!",
						Face:       f,
						Foreground: image.Black,
						Background: image.White,
						Bounds: fixed.Rectangle26_6{
							Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(1, 0)},
							Max: fixed.Point26_6{X: int26_6(65, 55), Y: int26_6(15, 5)},
						},
					}},

					Bounds: fixed.Rectangle26_6{
						Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(1, 0)},
						Max: fixed.Point26_6{X: int26_6(65, 55), Y: int26_6(15, 5)},
					},
				},
				{
					LF: Char{
						Offset:     12,
						Rune:       '\n',
						Face:       f,
						Foreground: image.Black,
						Background: image.White,
					},

					Runs: []Run{{
						Offset:     13,
						Text:       "How are you doing?",
						Face:       f,
						Foreground: image.Black,
						Background: image.White,
						Bounds: fixed.Rectangle26_6{
							Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(13, 0)},
							Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(27, 5)},
						},
					}},

					Bounds: fixed.Rectangle26_6{
						Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(13, 0)},
						Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(27, 5)},
					},
				},
			},

			Bounds: fixed.Rectangle26_6{
				Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(1, 0)},
				Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(27, 5)},
			},
		}},

		Bounds: fixed.Rectangle26_6{
			Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(1, 0)},
			Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(27, 5)},
		},
	}) {
		t.Error("invalid left alignment:", view)
	}

	// -- test justify alignment --
	view.Align(Justify)

	if !reflect.DeepEqual(view, View{
		Frames: []Frame{{
			Lines: []Line{
				{
					Runs: []Run{
						{
							Offset:     0,
							Text:       "Hello",
							Face:       f,
							Foreground: image.Black,
							Background: image.White,
							Bounds: fixed.Rectangle26_6{
								Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(1, 0)},
								Max: fixed.Point26_6{X: int26_6(28, 37), Y: int26_6(15, 5)},
							},
						},

						{
							Offset:     5,
							Text:       " ",
							Face:       f,
							Foreground: image.Black,
							Background: image.White,
							Bounds: fixed.Rectangle26_6{
								Min: fixed.Point26_6{X: int26_6(28, 37), Y: int26_6(1, 0)},
								Max: fixed.Point26_6{X: int26_6(71, 41), Y: int26_6(15, 5)},
							},
						},

						{
							Offset:     6,
							Text:       "World!",
							Face:       f,
							Foreground: image.Black,
							Background: image.White,
							Bounds: fixed.Rectangle26_6{
								Min: fixed.Point26_6{X: int26_6(71, 41), Y: int26_6(1, 0)},
								Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(15, 5)},
							},
						},
					},

					Bounds: fixed.Rectangle26_6{
						Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(1, 0)},
						Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(15, 5)},
					},
				},
				{
					LF: Char{
						Offset:     12,
						Rune:       '\n',
						Face:       f,
						Foreground: image.Black,
						Background: image.White,
					},

					Runs: []Run{
						{
							Offset:     13,
							Text:       "How",
							Face:       f,
							Foreground: image.Black,
							Background: image.White,
							Bounds: fixed.Rectangle26_6{
								Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(13, 0)},
								Max: fixed.Point26_6{X: int26_6(25, 27), Y: int26_6(27, 5)},
							},
						},

						{
							Offset:     16,
							Text:       " ",
							Face:       f,
							Foreground: image.Black,
							Background: image.White,
							Bounds: fixed.Rectangle26_6{
								Min: fixed.Point26_6{X: int26_6(25, 27), Y: int26_6(13, 0)},
								Max: fixed.Point26_6{X: int26_6(28, 25), Y: int26_6(27, 5)},
							},
						},

						{
							Offset:     17,
							Text:       "are",
							Face:       f,
							Foreground: image.Black,
							Background: image.White,
							Bounds: fixed.Rectangle26_6{
								Min: fixed.Point26_6{X: int26_6(28, 25), Y: int26_6(13, 0)},
								Max: fixed.Point26_6{X: int26_6(45, 22), Y: int26_6(27, 5)},
							},
						},

						{
							Offset:     20,
							Text:       " ",
							Face:       f,
							Foreground: image.Black,
							Background: image.White,
							Bounds: fixed.Rectangle26_6{
								Min: fixed.Point26_6{X: int26_6(45, 22), Y: int26_6(13, 0)},
								Max: fixed.Point26_6{X: int26_6(48, 20), Y: int26_6(27, 5)},
							},
						},

						{
							Offset:     21,
							Text:       "you",
							Face:       f,
							Foreground: image.Black,
							Background: image.White,
							Bounds: fixed.Rectangle26_6{
								Min: fixed.Point26_6{X: int26_6(48, 20), Y: int26_6(13, 0)},
								Max: fixed.Point26_6{X: int26_6(67, 28), Y: int26_6(27, 5)},
							},
						},

						{
							Offset:     24,
							Text:       " ",
							Face:       f,
							Foreground: image.Black,
							Background: image.White,
							Bounds: fixed.Rectangle26_6{
								Min: fixed.Point26_6{X: int26_6(67, 28), Y: int26_6(13, 0)},
								Max: fixed.Point26_6{X: int26_6(70, 26), Y: int26_6(27, 5)},
							},
						},

						{
							Offset:     25,
							Text:       "doing?",
							Face:       f,
							Foreground: image.Black,
							Background: image.White,
							Bounds: fixed.Rectangle26_6{
								Min: fixed.Point26_6{X: int26_6(70, 26), Y: int26_6(13, 0)},
								Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(27, 5)},
							},
						},
					},

					Bounds: fixed.Rectangle26_6{
						Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(13, 0)},
						Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(27, 5)},
					},
				},
			},

			Bounds: fixed.Rectangle26_6{
				Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(1, 0)},
				Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(27, 5)},
			},
		}},

		Bounds: fixed.Rectangle26_6{
			Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(1, 0)},
			Max: fixed.Point26_6{X: int26_6(105, 61), Y: int26_6(27, 5)},
		},
	}) {
		t.Error("invalid text justification:", view)
	}
}
Example #22
0
func TestRenderSimpleText(t *testing.T) {
	f := truetype.NewFace(clearSans, nil)
	defer f.Close()

	c := NewReader(strings.NewReader("Hello World!\n"),
		Style{Offset: 0, Face: f, Foreground: image.Black, Background: image.White},
		Style{Offset: 5, Face: f, Foreground: image.White},
	)

	view, err := Render(c, NewNaturalLayout(fixed.P(1, 1)))

	if err != nil {
		t.Error(err)
	}

	if !reflect.DeepEqual(view, View{
		Frames: []Frame{
			{
				Lines: []Line{
					{
						Runs: []Run{
							{
								Offset:     0,
								Text:       "Hello",
								Face:       f,
								Foreground: image.Black,
								Background: image.White,
								Bounds: fixed.Rectangle26_6{
									Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(1, 0)},
									Max: fixed.Point26_6{X: int26_6(28, 37), Y: int26_6(15, 5)},
								},
							},

							{
								Offset:     5,
								Text:       " World!",
								Face:       f,
								Foreground: image.White,
								Background: image.White,
								Bounds: fixed.Rectangle26_6{
									Min: fixed.Point26_6{X: int26_6(28, 37), Y: int26_6(1, 0)},
									Max: fixed.Point26_6{X: int26_6(65, 55), Y: int26_6(15, 5)},
								},
							},
						},

						Bounds: fixed.Rectangle26_6{
							Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(1, 0)},
							Max: fixed.Point26_6{X: int26_6(65, 55), Y: int26_6(15, 5)},
						},
					},

					{
						LF: Char{
							Offset:     12,
							Rune:       '\n',
							Face:       f,
							Foreground: image.White,
							Background: image.White,
						},

						Bounds: fixed.Rectangle26_6{
							Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(13, 0)},
							Max: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(25, 0)},
						},
					},
				},

				Bounds: fixed.Rectangle26_6{
					Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(1, 0)},
					Max: fixed.Point26_6{X: int26_6(65, 55), Y: int26_6(25, 0)},
				},
			},
		},

		Bounds: fixed.Rectangle26_6{
			Min: fixed.Point26_6{X: int26_6(1, 0), Y: int26_6(1, 0)},
			Max: fixed.Point26_6{X: int26_6(65, 55), Y: int26_6(25, 0)},
		},
	}) {
		t.Error("invalid view rendered from non-empty string:", view)
	}
}
Example #23
0
func main() {
	flag.Parse()

	// TODO: mmap the files.
	if *fontFlag == "" {
		flag.Usage()
		log.Fatal("no font specified")
	}
	var face font.Face
	if strings.HasSuffix(*fontFlag, ".font") {
		fontData, err := ioutil.ReadFile(*fontFlag)
		if err != nil {
			log.Fatal(err)
		}
		dir := filepath.Dir(*fontFlag)
		face, err = plan9font.ParseFont(fontData, func(name string) ([]byte, error) {
			return ioutil.ReadFile(filepath.Join(dir, filepath.FromSlash(name)))
		})
		if err != nil {
			log.Fatal(err)
		}
	} else {
		fontData, err := ioutil.ReadFile(*fontFlag)
		if err != nil {
			log.Fatal(err)
		}
		face, err = plan9font.ParseSubfont(fontData, rune(*firstRuneFlag))
		if err != nil {
			log.Fatal(err)
		}
	}

	dst := image.NewRGBA(image.Rect(0, 0, 800, 300))
	draw.Draw(dst, dst.Bounds(), image.Black, image.Point{}, draw.Src)

	d := &font.Drawer{
		Dst:  dst,
		Src:  image.White,
		Face: face,
	}
	ss := []string{
		"The quick brown fox jumps over the lazy dog.",
		"Hello, 世界.",
		"U+FFFD is \ufffd.",
	}
	for i, s := range ss {
		d.Dot = fixed.P(20, 100*i+80)
		dot0 := pt(d.Dot)
		d.DrawString(s)
		dot1 := pt(d.Dot)
		dst.SetRGBA(dot0.X, dot0.Y, color.RGBA{0xff, 0x00, 0x00, 0xff})
		dst.SetRGBA(dot1.X, dot1.Y, color.RGBA{0x00, 0x00, 0xff, 0xff})
	}

	out, err := os.Create("out.png")
	if err != nil {
		log.Fatal(err)
	}
	defer out.Close()
	if err := png.Encode(out, dst); err != nil {
		log.Fatal(err)
	}
}
Example #24
0
// returns image of rendered font
func (this FontInfo) GetImage() image.Image {

	f := truetype.Font(this)

	maxWidth := 0
	curW := 0
	maxHeight := int(f.Bounds(sizeFixed).Max.Sub(f.Bounds(sizeFixed).Min).Y) + insetPadding
	for idx, val := range text {
		if idx > 0 && int(math.Mod(float64(idx), float64(itemsPerRow))) == 0 {
			maxHeight += int(f.Bounds(sizeFixed).Max.Sub(f.Bounds(sizeFixed).Min).Y) + insetPadding
			curW = 0

		}

		i := f.Index(val)
		hmet := f.HMetric(sizeFixed, i)

		curW += int(hmet.AdvanceWidth) + insetPadding

		if curW > maxWidth {
			maxWidth = curW
		}

	}

	Logging.Debug("Font ", this.Name())
	Logging.Debug("Max width: ", maxWidth)
	Logging.Debug("Max height: ", maxHeight)

	// Draw the background and the guidelines.
	fg, bg := image.Black, image.Transparent

	// diffY := int(f.Bounds(sizeFixed).Max.Sub(f.Bounds(sizeFixed).Min).Y)

	// add a constant to the y term because of subtle bleeding between vertical space, probably because of advance height
	rgba := image.NewRGBA(image.Rect(0, 0, maxWidth, maxHeight)) //diffY+5))

	draw.Draw(rgba, rgba.Bounds(), bg, image.ZP, draw.Src)

	// Draw the text.
	h := font.HintingNone
	switch hinting {
	case "full":
		h = font.HintingFull
	}
	d := &font.Drawer{
		Dst: rgba,
		Src: fg,
		Face: truetype.NewFace(&f, &truetype.Options{
			Size:    size,
			DPI:     dpi,
			Hinting: h,
		}),
	}

	// y := int(math.Abs(float64(f.Bounds(sizeFixed).Max.Y))) //10 + int(math.Ceil(*size**dpi/72))
	// dy := int(math.Ceil(size * spacing * dpi / 72))

	tWidth := 0
	tHeight := int(math.Abs(float64(f.Bounds(sizeFixed).Max.Y)))
	for idx, r := range text {
		if idx > 0 && int(math.Mod(float64(idx), float64(itemsPerRow))) == 0 {
			tHeight += int(f.Bounds(sizeFixed).Max.Sub(f.Bounds(sizeFixed).Min).Y) + insetPadding
			tWidth = 0
		}
		i := f.Index(r)
		hmet := f.HMetric(sizeFixed, i)

		d.Dot = fixed.P(tWidth, tHeight)
		tWidth += int(hmet.AdvanceWidth) + insetPadding

		d.DrawString(string(r))

	}

	return rgba
}
Example #25
0
func main() {
	// nGlyphs is the number of glyphs to generate: 95 characters in the range
	// [0x20, 0x7e], plus the replacement character.
	const nGlyphs = 95 + 1
	// The particular font (unicode.7x13.font) leaves the right-most column
	// empty in its ASCII glyphs. We don't have to include that column in the
	// generated glyphs, so we subtract one off the effective width.
	const width, height, ascent = 7 - 1, 13, 11

	readFile := func(name string) ([]byte, error) {
		return ioutil.ReadFile(filepath.FromSlash(path.Join("../testdata/fixed", name)))
	}
	fontData, err := readFile("unicode.7x13.font")
	if err != nil {
		log.Fatalf("readFile: %v", err)
	}
	face, err := plan9font.ParseFont(fontData, readFile)
	if err != nil {
		log.Fatalf("plan9font.ParseFont: %v", err)
	}

	dst := image.NewRGBA(image.Rect(0, 0, width, nGlyphs*height))
	draw.Draw(dst, dst.Bounds(), image.Black, image.Point{}, draw.Src)
	d := &font.Drawer{
		Dst:  dst,
		Src:  image.White,
		Face: face,
	}
	for i := 0; i < nGlyphs; i++ {
		r := '\ufffd'
		if i < nGlyphs-1 {
			r = 0x20 + rune(i)
		}
		d.Dot = fixed.P(0, height*i+ascent)
		d.DrawString(string(r))
	}

	w := bytes.NewBuffer(nil)
	w.WriteString(preamble)
	fmt.Fprintf(w, "// mask7x13 contains %d %d×%d glyphs in %d Pix bytes.\n", nGlyphs, width, height, nGlyphs*width*height)
	fmt.Fprintf(w, "var mask7x13 = &image.Alpha{\n")
	fmt.Fprintf(w, "  Stride: %d,\n", width)
	fmt.Fprintf(w, "  Rect: image.Rectangle{Max: image.Point{%d, %d*%d}},\n", width, nGlyphs, height)
	fmt.Fprintf(w, "  Pix: []byte{\n")
	b := dst.Bounds()
	for y := b.Min.Y; y < b.Max.Y; y++ {
		if y%height == 0 {
			if y != 0 {
				w.WriteByte('\n')
			}
			i := y / height
			if i < nGlyphs-1 {
				i += 0x20
				fmt.Fprintf(w, "// %#2x %q\n", i, rune(i))
			} else {
				fmt.Fprintf(w, "// U+FFFD REPLACEMENT CHARACTER\n")
			}
		}

		for x := b.Min.X; x < b.Max.X; x++ {
			if dst.RGBAAt(x, y).R > 0 {
				w.WriteString("0xff,")
			} else {
				w.WriteString("0x00,")
			}
		}
		w.WriteByte('\n')
	}
	w.WriteString("},\n}\n")

	fmted, err := format.Source(w.Bytes())
	if err != nil {
		log.Fatalf("format.Source: %v", err)
	}
	if err := ioutil.WriteFile("data.go", fmted, 0644); err != nil {
		log.Fatalf("ioutil.WriteFile: %v", err)
	}
}
Example #26
0
func createImages(dir, mode string) {

	os.Mkdir(dir, 0777)

	//Load font file
	b, err := ioutil.ReadFile("Arial.ttf")
	if err != nil {
		log.Println(err)
		return
	}

	//Parse font file
	ttf, err := truetype.Parse(b)
	if err != nil {
		log.Println(err)
		return
	}

	//Create Font.Face from font
	face := truetype.NewFace(ttf, &truetype.Options{
		Size:    size,
		DPI:     dpi,
		Hinting: font.HintingNone,
	})

	//Create initial matrix
	m := make([]Bit, 0)
	for y := 17; y <= height; y = y + int(size) {
		for x := 4; x <= width; x = x + int(size) {
			val := "1"
			rand.Seed(time.Now().UnixNano())
			if rand.Intn(2) == 1 {
				val = "0"
			}

			m = append(m, Bit{X: x, Y: y, Val: val})
		}
	}

	//Create next matrix
	mm := make([][]Bit, 0)
	mm = append(mm, m)

	//Get a random list
	rand.Seed(time.Now().UnixNano())
	randBit := rand.Perm(len(m))

	//Create each next matrix
	for i := 0; i < len(randBit); i++ {

		tmpM := make([]Bit, len(m))

		//Copy last matrix
		copy(tmpM, mm[len(mm)-1])

		//Update one bit
		tmpBit := tmpM[randBit[i]]
		if tmpBit.Val == "0" {
			tmpBit.Val = "1"
		} else {
			tmpBit.Val = "0"
		}

		//Save bit in matrix
		tmpM[randBit[i]] = tmpBit

		//Append new matrix
		mm = append(mm, tmpM)

	}

	//Get a random list
	rand.Seed(time.Now().UnixNano())
	randBit = rand.Perm(len(m))

	//Create each next matrix
	for i := 0; i < len(randBit); i++ {

		tmpM := make([]Bit, len(m))

		//Copy last matrix
		copy(tmpM, mm[len(mm)-1])

		//Update one bit
		tmpBit := tmpM[randBit[i]]
		if tmpBit.Val == "0" {
			tmpBit.Val = "1"
		} else {
			tmpBit.Val = "0"
		}

		//Save bit in matrix
		tmpM[randBit[i]] = tmpBit

		//Append new matrix
		mm = append(mm, tmpM)

	}

	//Create all matrix images
	for i := 0; i < len(mm); i++ {

		if i%100 == 0 {
			log.Printf("i:%d/%d", i, len(mm))
		}

		//Create template images
		src := image.NewNRGBA(image.Rect(0, 0, width, height))
		dst := image.NewNRGBA(image.Rect(0, 0, width, height))
		for y := 0; y < height; y++ {
			for x := 0; x < width; x++ {
				if mode == "black" {
					src.Set(x, y, color.NRGBA{uint8(255), uint8(255), uint8(255), 255})
					dst.Set(x, y, color.NRGBA{uint8(0), uint8(0), uint8(0), 255})
				} else {
					src.Set(x, y, color.NRGBA{uint8(0), uint8(0), uint8(0), 255})
					dst.Set(x, y, color.NRGBA{uint8(255), uint8(255), uint8(255), 255})
				}

			}
		}

		//Create file
		f, err := os.OpenFile(fmt.Sprintf("%s/%d.png", dir, i), os.O_CREATE|os.O_WRONLY, 0666)
		if err != nil {
			log.Fatalf("OpenFile - Err:%s", err)
		}

		//Draw the bit
		for _, val := range mm[i] {
			p := fixed.P(val.X, val.Y)
			d := font.Drawer{Dst: dst, Src: src, Face: face, Dot: p}
			d.DrawString(val.Val)
		}

		//Save the file
		if err = png.Encode(f, dst); err != nil {
			log.Fatalf("Encode0 - Err:%s", err)
		}

	}
}
Example #27
0
func main() {
	flag.Parse()

	// Read the font data.
	fontBytes, err := ioutil.ReadFile(*fontfile)
	if err != nil {
		log.Println(err)
		return
	}
	f, err := truetype.Parse(fontBytes)
	if err != nil {
		log.Println(err)
		return
	}

	// Draw the background and the guidelines.
	fg, bg := image.Black, image.White
	ruler := color.RGBA{0xdd, 0xdd, 0xdd, 0xff}
	if *wonb {
		fg, bg = image.White, image.Black
		ruler = color.RGBA{0x22, 0x22, 0x22, 0xff}
	}
	const imgW, imgH = 640, 480
	rgba := image.NewRGBA(image.Rect(0, 0, imgW, imgH))
	draw.Draw(rgba, rgba.Bounds(), bg, image.ZP, draw.Src)
	for i := 0; i < 200; i++ {
		rgba.Set(10, 10+i, ruler)
		rgba.Set(10+i, 10, ruler)
	}

	// Draw the text.
	h := font.HintingNone
	switch *hinting {
	case "full":
		h = font.HintingFull
	}
	d := &font.Drawer{
		Dst: rgba,
		Src: fg,
		Face: truetype.NewFace(f, &truetype.Options{
			Size:    *size,
			DPI:     *dpi,
			Hinting: h,
		}),
	}
	y := 10 + int(math.Ceil(*size**dpi/72))
	dy := int(math.Ceil(*size * *spacing * *dpi / 72))
	d.Dot = fixed.Point26_6{
		X: (fixed.I(imgW) - d.MeasureString(title)) / 2,
		Y: fixed.I(y),
	}
	d.DrawString(title)
	y += dy
	for _, s := range text {
		d.Dot = fixed.P(10, y)
		d.DrawString(s)
		y += dy
	}

	// Save that RGBA image to disk.
	outFile, err := os.Create("out.png")
	if err != nil {
		log.Println(err)
		os.Exit(1)
	}
	defer outFile.Close()
	b := bufio.NewWriter(outFile)
	err = png.Encode(b, rgba)
	if err != nil {
		log.Println(err)
		os.Exit(1)
	}
	err = b.Flush()
	if err != nil {
		log.Println(err)
		os.Exit(1)
	}
	fmt.Println("Wrote out.png OK.")
}
Example #28
0
// Draw renders the demo state to the screen
func (p *StatusPainter) Draw(sz size.Event, pad int, opt *truetype.Options) {

	if sz.WidthPx == 0 && sz.HeightPx == 0 {
		return
	}
	fsize := opt.Size
	if fsize == 0 {
		fsize = 12
	}
	pixY := int(float64(fsize)*float64(sz.PixelsPerPt)) + pad

	if p.sz != sz {
		p.sz = sz
		if p.image != nil {
			p.image.Release()
		}
		p.image = p.images.NewImage(sz.WidthPx, pixY)
		// BUG: face will not update if opt changes
		p.opt = nil

	}

	if p.opt == nil || *opt != *p.opt {
		if p.opt != nil {
			dpi := p.opt.DPI
			p.opt.DPI = opt.DPI
			if *opt == *p.opt {
				// we have already correctly computed the DPI so this opt is
				// nothing new.
				p.opt.DPI = dpi
			} else {
				p.opt = nil
			}
		}
		if p.opt == nil {
			p.opt = &truetype.Options{}
			*p.opt = *opt
			p.opt.DPI = float64(sz.PixelsPerPt) * 72
			p.face = truetype.NewFace(p.ttf, p.opt)
		}
	}

	state := p.demo.State()
	state.Mut = nil
	if p.frozen == nil || *state != *p.frozen {
		// generate a current image
		draw.Draw(p.image.RGBA, p.image.RGBA.Bounds(), p.bg, image.Pt(0, 0), draw.Over)

		originX := 2
		originY := pixY - 2

		drawer := &font.Drawer{
			Dst:  p.image.RGBA,
			Src:  image.NewUniform(color.Black),
			Face: p.face,
			Dot:  fixed.P(originX, originY),
		}

		text := fmt.Sprintf("%v Count=%d", state.Last.Format(time.RFC3339), state.Counter)
		drawer.DrawString(text)
		p.image.Upload()
	}
	p.image.Draw(
		sz,
		geom.Point{X: 0, Y: 0},
		geom.Point{X: sz.WidthPt, Y: 0},
		geom.Point{X: 0, Y: geom.Pt(float64(pixY) / float64(sz.PixelsPerPt))},
		p.image.RGBA.Bounds(),
	)

}
Example #29
0
File: graph.go Project: rsc/tmp
func Handler(w http.ResponseWriter, req *http.Request) {
	const size = 500
	c := image.NewRGBA(image.Rect(0, 0, size, size))
	white := &image.Uniform{C: color.White}
	draw.Draw(c, c.Bounds(), white, image.ZP, draw.Src)

	p := raster.NewRGBAPainter(c)
	p.SetColor(color.Black)
	r := raster.NewRasterizer(500, 500)
	r.UseNonZeroWinding = true
	var path raster.Path
	path.Start(nudge(fixed.P(50, 50)))
	path.Add1(nudge(fixed.P(50, 450)))
	path.Add1(nudge(fixed.P(450, 450)))
	r.AddStroke(path, fixed.I(2), raster.ButtCapper, raster.BevelJoiner)
	r.Rasterize(p)
	r.Clear()

	p.SetColor(color.Gray16{0x7FFF})
	path.Clear()
	r.Clear()
	path.Start(nudge(fixed.P(450, 450)))
	path.Add1(nudge(fixed.P(450, 50)))
	path.Add1(nudge(fixed.P(50, 50)))
	r.AddStroke(path, fixed.I(1), raster.ButtCapper, raster.BevelJoiner)
	r.Rasterize(p)

	p.SetColor(color.Gray16{0x7FFF})
	for x := 50; x <= 450; x += 50 {
		path.Clear()
		path.Start(nudge(fixed.P(x, 450)))
		path.Add1(nudge(fixed.P(x, 460)))
		r.AddStroke(path, fixed.I(1), raster.ButtCapper, raster.BevelJoiner)
	}
	for x := 50; x <= 450; x += 50 {
		path.Clear()
		path.Start(nudge(fixed.P(50, x)))
		path.Add1(nudge(fixed.P(40, x)))
		r.AddStroke(path, fixed.I(1), raster.ButtCapper, raster.BevelJoiner)
	}
	r.Rasterize(p)

	p.SetColor(color.RGBA{0x00, 0x00, 0xFF, 0xFF})
	r.Clear()
	path.Clear()
	path.Start(nudge(fixed.P(50, 450)))
	path.Add1(nudge(fixed.P(450, 50)))
	r.AddStroke(path, fixed.I(1), raster.ButtCapper, raster.BevelJoiner)
	r.Rasterize(p)

	p.SetColor(color.RGBA{0xCC, 0x00, 0x00, 0xFF})
	r.Clear()
	window := fixed.Rectangle26_6{fixed.P(50, 450), fixed.P(450, 50)}
	//	path = plotPath(ratSin, big.NewRat(0, 1), big.NewRat(-1, 1), big.NewRat(10, 1), big.NewRat(1, 1), window)

	//	path = plotPath(ratProb, big.NewRat(0, 1), big.NewRat(0, 1), big.NewRat(1, 1<<57), big.NewRat(1, 1<<57), window)

	var lo, hi *big.Rat
	var locap, hicap, scalecap string
	id, _ := strconv.Atoi(req.FormValue("x"))
	switch id {
	case 0:
		lo = big.NewRat(1<<53-1<<3, 1<<54)
		hi = big.NewRat(1<<53+1<<3, 1<<54)
		locap = "1/2 - 1/2^51"
		hicap = "1/2 + 1/2^51"
		scalecap = "1/2^53"
	case 1:
		lo = big.NewRat(1<<54-1<<4, 1<<54)
		hi = big.NewRat(1<<54, 1<<54)
		locap = "1 - 1/2^50"
		hicap = "1"
		scalecap = "1/2^53"
	case 2:
		lo = big.NewRat(0, 1<<54)
		hi = big.NewRat(1<<4, 1<<54)
		locap = "0"
		hicap = "1/2^50"
		scalecap = "1/2^53"
	case 3:
		lo = big.NewRat(0, 1<<54)
		hi = big.NewRat(1<<2, 1<<62)
		locap = "0"
		hicap = "1/2^59"
		scalecap = "1/2^63"
	}

	mode, _ := strconv.Atoi(req.FormValue("mode"))
	path = plotPath(ratProb(mode), lo, lo, hi, hi, window)
	r.AddStroke(path, fixed.I(1), raster.ButtCapper, raster.BevelJoiner)
	r.Rasterize(p)

	var modestr string
	switch mode {
	case 0:
		modestr = "original behavior (can return 1)"
	case 1:
		modestr = "new behavior (too much 0)"
	case 2:
		modestr = "retry loop"
	}

	data, err := ioutil.ReadFile("/tmp/luxisr.ttf")
	if err != nil {
		panic(err)
	}
	tfont, err := freetype.ParseFont(data)
	if err != nil {
		panic(err)
	}
	const pt = 10
	ft := freetype.NewContext()
	ft.SetDst(c)
	ft.SetDPI(100)
	ft.SetFont(tfont)
	ft.SetFontSize(float64(pt))
	ft.SetSrc(image.NewUniform(color.Black))

	ft.SetClip(image.Rect(0, 0, 0, 0))
	wid, err := ft.DrawString(locap, freetype.Pt(0, 0))
	if err != nil {
		panic(err)
	}
	pp := freetype.Pt(50, 480)
	pp.X -= wid.X / 2
	ft.SetClip(c.Bounds())
	ft.DrawString(locap, pp)

	ft.SetClip(image.Rect(0, 0, 0, 0))
	wid, err = ft.DrawString(hicap, freetype.Pt(0, 0))
	if err != nil {
		panic(err)
	}
	pp = freetype.Pt(450, 480)
	pp.X -= wid.X / 2
	ft.SetClip(c.Bounds())
	ft.DrawString(hicap, pp)

	r.Clear()
	p.SetColor(color.Black)
	path.Clear()
	const dy = 5
	path.Start(nudge(fixed.P(400, 400)))
	path.Add1(nudge(fixed.P(400, 400-dy)))
	path.Add1(nudge(fixed.P(400, 400+dy)))
	path.Add1(nudge(fixed.P(400, 400)))
	path.Add1(nudge(fixed.P(450, 400)))
	path.Add1(nudge(fixed.P(450, 400-dy)))
	path.Add1(nudge(fixed.P(450, 400+dy)))
	path.Add1(nudge(fixed.P(450, 400)))
	r.AddStroke(path, fixed.I(2), raster.ButtCapper, raster.BevelJoiner)
	r.Rasterize(p)

	ft.SetClip(image.Rect(0, 0, 0, 0))
	wid, err = ft.DrawString(scalecap, freetype.Pt(0, 0))
	if err != nil {
		panic(err)
	}
	pp = freetype.Pt(425, 420)
	pp.X -= wid.X / 2
	ft.SetClip(c.Bounds())
	ft.DrawString(scalecap, pp)

	ft.SetClip(image.Rect(0, 0, 0, 0))
	wid, err = ft.DrawString(modestr, freetype.Pt(0, 0))
	if err != nil {
		panic(err)
	}
	pp = freetype.Pt(250, 490)
	pp.X -= wid.X / 2
	ft.SetClip(c.Bounds())
	ft.DrawString(modestr, pp)

	w.Write(pngEncode(c))
}
Example #30
-1
func drawRGBA(m *image.RGBA, tp image.Point) {
	draw.Draw(m, m.Bounds(), image.White, image.Point{}, draw.Src)
	for _, p := range crossPoints {
		m.SetRGBA(p.X, p.Y, crossColor)
	}
	d := font.Drawer{
		Dst:  m,
		Src:  image.Black,
		Face: basicfont.Face7x13,
		Dot:  fixed.P(0, 12),
	}
	d.DrawString(fmt.Sprint(tp))
}