Skip to content

Commit 7c12b05

Browse files
committed
Remove Cursor and CursorReset
Print now accepts mandatory x,y position instead. Cursor, CursorReset functions were removed. It still possible to print multi-line text by using special '\n' character inside the string text.
1 parent 9f4f3f0 commit 7c12b05

17 files changed

+106
-293
lines changed

examples/boot/main.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ func main() {
1414
pi.MustBoot()
1515

1616
// once boot is executed all drawing functions are available:
17-
pi.Cursor(0, 18)
18-
pi.Print("TINY SCREEN", 7) // print text on the screen before game loop
17+
pi.Print("TINY SCREEN", 0, 18, 7) // print text on the screen before game loop
1918

2019
// Run the game loop.
2120
pi.MustRun()

examples/keyboard/main.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,7 @@ func drawKey(x, y, w int, b key.Button) {
6969

7070
str := b.String()
7171
if len(str) == 1 {
72-
pi.Cursor(x+2, y+2)
73-
pi.Print(str, 15)
72+
pi.Print(str, x+2, y+2, 15)
7473
}
7574

7675
}

examples/print/custom-font.png

1.29 KB
Loading

examples/print/main.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@
22
package main
33

44
import (
5+
"embed"
6+
57
"github.com/elgopher/pi"
68
)
79

10+
//go:embed custom-font.png
11+
var resources embed.FS
12+
813
func main() {
14+
pi.Resources = resources
915
pi.Draw = func() {
10-
pi.CursorReset() // set cursor to 0,0
11-
pi.Cursor(50, 58) // set cursor position
12-
pi.Print("HELLO,", 9) // print yellow text and go to next line
13-
pi.Print("GOPHER!", 12)
16+
pi.Print("HELLO,\nWORLD!", 50, 58, 9) // print two lines of yellow text using system font
1417
}
1518
pi.MustRun()
1619
}

examples/shapes/main.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,33 +23,37 @@ var drawFunctions = []func(x0, y0, x1, y1 int){
2323
func(x0, y0, x1, y1 int) {
2424
pi.Rect(x0, y0, x1, y1, shapeColor)
2525
command := fmt.Sprintf("Rect(%d,%d,%d,%d,%d)", x0, y0, x1, y1, shapeColor)
26-
pi.Print(command, textColor)
26+
printCmd(command)
2727
},
2828
func(x0, y0, x1, y1 int) {
2929
pi.RectFill(x0, y0, x1, y1, shapeColor)
3030
command := fmt.Sprintf("RectFill(%d,%d,%d,%d,%d)", x0, y0, x1, y1, shapeColor)
31-
pi.Print(command, textColor)
31+
printCmd(command)
3232
},
3333
func(x0, y0, x1, y1 int) {
3434
pi.Line(x0, y0, x1, y1, shapeColor)
3535
command := fmt.Sprintf("Line(%d,%d,%d,%d,%d)", x0, y0, x1, y1, shapeColor)
36-
pi.Print(command, textColor)
36+
printCmd(command)
3737
},
3838
func(x0, y0, x1, y1 int) {
3939
r := radius(x0, y0, x1, y1)
4040
pi.Circ(x0, y0, r, shapeColor)
4141

4242
command := fmt.Sprintf("Circ(%d,%d,%d,%d)", x0, y0, r, shapeColor)
43-
pi.Print(command, textColor)
43+
printCmd(command)
4444
},
4545
func(x0, y0, x1, y1 int) {
4646
r := radius(x0, y0, x1, y1)
4747
pi.CircFill(x0, y0, r, shapeColor)
4848
command := fmt.Sprintf("CircFill(%d,%d,%d,%d)", x0, y0, r, shapeColor)
49-
pi.Print(command, textColor)
49+
printCmd(command)
5050
},
5151
}
5252

53+
func printCmd(command string) {
54+
pi.Print(command, 8, 128-6-6, textColor)
55+
}
56+
5357
var current = 0
5458

5559
var x0, y0 int
@@ -74,8 +78,6 @@ func main() {
7478

7579
}
7680

77-
pi.Cursor(8, 128-6-6)
78-
7981
// set coordinates during dragging
8082
if drawShape != nil {
8183
x1, y1 := pi.MousePos()

internal/bench/print_bench_test.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,13 @@ import (
1212
func BenchmarkPrint(b *testing.B) {
1313
runBenchmarks(b, func(r Resolution) {
1414
for j := 0; j < 10; j++ {
15-
pi.Cursor(0, 0)
16-
pi.Print("Hello", color)
15+
pi.Print("Hello", 0, 0, color)
1716
}
1817
})
1918
}
2019

2120
func BenchmarkPrintWithScroll(b *testing.B) {
2221
runBenchmarks(b, func(r Resolution) {
23-
pi.Print("Hello", color)
22+
pi.Print("Hello", 0, 0, color)
2423
})
2524
}

internal/fuzz/print_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ func FuzzPrint(f *testing.F) {
1616
pi.ScreenHeight = 24
1717
pi.MustBoot()
1818
f.Fuzz(func(t *testing.T, x, y int) {
19-
pi.Cursor(x, y)
20-
pi.Print("A", color)
19+
pi.Print("A", x, y, color)
2120
})
2221
}
101 Bytes
Loading
128 Bytes
Loading

pi.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ func Boot() error {
117117
return err
118118
}
119119

120-
if err := loadSystemFont(); err != nil {
120+
if err := loadFontData(systemFontPNG, systemFont.Data[:]); err != nil {
121121
return err
122122
}
123123

@@ -146,7 +146,6 @@ func Boot() error {
146146
CameraReset()
147147
PaltReset()
148148
PalReset()
149-
CursorReset()
150149

151150
booted = true
152151

@@ -172,7 +171,11 @@ func validateUserParameters() error {
172171
}
173172

174173
func loadResources(resources fs.ReadFileFS) error {
175-
return loadSpriteSheet(resources)
174+
if err := loadSpriteSheet(resources); err != nil {
175+
return err
176+
}
177+
178+
return nil
176179
}
177180

178181
// MustBoot does the same as Boot, but panics instead of returning an error.

print.go

Lines changed: 55 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -31,116 +31,56 @@ type Font struct {
3131
Width int
3232
// WidthSpecial is a with of all special characters (code>=128)
3333
WidthSpecial int
34-
Height int
34+
// Height of line
35+
Height int
3536
}
3637

37-
func loadSystemFont() error {
38-
img, err := image.DecodePNG(bytes.NewReader(systemFontPNG))
39-
if err != nil {
40-
return fmt.Errorf("decoding system font failed: %w", err)
41-
}
42-
43-
if err = font.Load(img, systemFont.Data[:]); err != nil {
44-
return fmt.Errorf("error loading system font: %w", err)
45-
}
46-
47-
return nil
48-
}
49-
50-
var cursor pos
51-
52-
// Cursor set cursor position (in pixels) used by Print.
53-
//
54-
// Cursor returns previously set cursor position.
55-
func Cursor(x, y int) (prevX, prevY int) {
56-
prevX, prevY = cursor.x, cursor.y
57-
cursor.x = x
58-
cursor.y = y
59-
return
60-
}
61-
62-
// CursorReset resets cursor position used by Print to 0,0.
63-
//
64-
// CursorReset returns previously set cursor position.
65-
func CursorReset() (prevX, prevY int) {
66-
return Cursor(0, 0)
67-
}
68-
69-
// Print prints text on the screen. It takes into consideration cursor position,
38+
// Print prints text on the screen at given coordinates. It takes into account
7039
// clipping region and camera position.
7140
//
72-
// After printing all characters Print goes to the next line. When there is no space
73-
// left on screen the clipping region is scrolled to make room.
74-
//
7541
// Only unicode characters with code < 256 are supported. Unsupported chars
7642
// are printed as question mark. The entire table of available chars can be
7743
// found here: https://github.com/elgopher/pi/blob/master/internal/system-font.png
7844
//
7945
// Print returns the right-most x position that occurred while printing.
80-
func Print(text string, color byte) (x int) {
81-
if cursor.y > scrHeight-systemFont.Height {
82-
lines := systemFont.Height - (scrHeight - cursor.y)
83-
scroll(lines)
84-
}
46+
func (f Font) Print(text string, x, y int, color byte) int {
47+
startX := x
8548

86-
startingX := cursor.x
8749
for _, r := range text {
88-
printRune(r, color)
89-
}
90-
91-
x = cursor.x
92-
cursor.x = startingX
93-
cursor.y += systemFont.Height
94-
if cursor.y > scrHeight-systemFont.Height {
95-
scroll(systemFont.Height)
96-
}
97-
98-
return
99-
}
100-
101-
func scroll(lines int) {
102-
if scrHeight <= lines {
103-
cls()
104-
cursor.y = scrHeight - systemFont.Height
105-
return
106-
}
107-
108-
for y := clippingRegion.y; y < scrHeight-lines; y++ {
109-
srcOffset := y*scrWidth + clippingRegion.x
110-
dstOffset := srcOffset + lines*scrWidth
111-
copy(ScreenData[srcOffset:], ScreenData[dstOffset:dstOffset+clippingRegion.w])
112-
}
113-
114-
for y := scrHeight - lines; y < clippingRegion.y+clippingRegion.h; y++ {
115-
offset := y*scrWidth + clippingRegion.x
116-
copy(ScreenData[offset:], zeroScreenData[:clippingRegion.w])
50+
if r != '\n' {
51+
width := f.printRune(r, x, y, color)
52+
x += width
53+
} else {
54+
x = startX
55+
y += f.Height
56+
}
11757
}
11858

119-
cursor.y -= lines
59+
return x
12060
}
12161

122-
func printRune(r rune, color byte) {
62+
func (f Font) printRune(r rune, sx, sy int, color byte) int {
12363
if r > 255 {
12464
r = '?'
12565
}
12666

12767
index := int(r) * 8
12868

12969
for y := 0; y < 8; y++ {
130-
if clippingRegion.y > cursor.y+y-camera.y {
70+
if clippingRegion.y > sy+y-camera.y {
13171
continue
13272
}
133-
if clippingRegion.y+clippingRegion.h <= cursor.y+y-camera.y {
73+
if clippingRegion.y+clippingRegion.h <= sy+y-camera.y {
13474
continue
13575
}
13676

137-
offset := scrWidth*y + cursor.x + cursor.y*scrWidth - camera.y*scrWidth - camera.x
138-
line := systemFont.Data[index+y]
77+
offset := scrWidth*y + sx + sy*scrWidth - camera.y*scrWidth - camera.x
78+
line := f.Data[index+y]
13979
for bit := 0; bit < 8; bit++ {
140-
if clippingRegion.x > cursor.x+bit-camera.x {
80+
if clippingRegion.x > sx+bit-camera.x {
14181
continue
14282
}
143-
if clippingRegion.x+clippingRegion.w <= cursor.x+bit-camera.x {
83+
if clippingRegion.x+clippingRegion.w <= sx+bit-camera.x {
14484
continue
14585
}
14686
if line&(1<<bit) == 1<<bit {
@@ -150,8 +90,41 @@ func printRune(r rune, color byte) {
15090
}
15191

15292
if r < 128 {
153-
cursor.x += systemFont.Width
93+
return f.Width
15494
} else {
155-
cursor.x += systemFont.WidthSpecial
95+
return f.WidthSpecial
96+
}
97+
}
98+
99+
// loadFontData loads font-sheet (png image) and converts
100+
// it to font data. Image must be 128x128. Each char is 8x8.
101+
// Char 0 is in the top-left corner. Char 1 to the right.
102+
//
103+
// This function can be used if you want to use 3rd font:
104+
//
105+
// myFont := pi.Font{Width:4, WidthSpecial:8,Height: 8}
106+
// pi.loadFontData(png, myFont.Data[:])
107+
func loadFontData(png []byte, out []byte) error {
108+
img, err := image.DecodePNG(bytes.NewReader(png))
109+
if err != nil {
110+
return fmt.Errorf("decoding font failed: %w", err)
111+
}
112+
113+
if err = font.Load(img, out[:]); err != nil {
114+
return fmt.Errorf("error system font: %w", err)
156115
}
116+
117+
return nil
118+
}
119+
120+
// Print prints text on the screen using system font. It takes into consideration
121+
// clipping region and camera position.
122+
//
123+
// Only unicode characters with code < 256 are supported. Unsupported chars
124+
// are printed as question mark. The entire table of available chars can be
125+
// found here: https://github.com/elgopher/pi/blob/master/internal/system-font.png
126+
//
127+
// Print returns the right-most x position that occurred while printing.
128+
func Print(text string, x, y int, color byte) (rightMostX int) {
129+
return systemFont.Print(text, x, y, color)
157130
}

0 commit comments

Comments
 (0)