/
drawLine.go
154 lines (142 loc) · 4.85 KB
/
drawLine.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package subbios
// lineColour determines the colour - if any - of a particular pixel on a line
func (v *video) lineColour(x, y, lineStyle int, lineStyleIndex []int, firstLogicalColour, secondLogicalColour, transparency int) (colour int) {
if transparency == 1 {
secondLogicalColour = -1 // second logical colour is transparent
}
if lineStyle == 6 {
v.LineStyles[6] = lineStyleIndex // setup user-defined line style
}
// Dither?
if lineStyle == 0 {
return v.ditherLookupTables[lineStyleIndex[0]][y][x]
}
// Or determine if it's first or second logical colour
if v.LineStyles[lineStyle][v.lineStyleCounter] == 1 {
return firstLogicalColour
} else {
return secondLogicalColour
}
}
// drawLine implements Bresenham's line algorithm to draw a line on a 2d array
// adapted from https://github.com/StephaneBunel/bresenham/blob/master/drawline.go
// Todo: fix stepping effect.
func (v *video) drawLine(img [][]int, x1, y1, x2, y2, lineStyle int, lineStyleIndex []int, firstLogicalColour, secondLogicalColour, transparency int) [][]int {
// Todo: fix cool trippy effect.
imgHeight := len(img) - 1
var dx, dy, e, slope int
v.lineStyleCounter = 0
// Because drawing p1 -> p2 is equivalent to draw p2 -> p1,
// I sort points in x-axis order to handle only half of possible cases.
if x1 > x2 {
x1, y1, x2, y2 = x2, y2, x1, y1
}
dx, dy = x2-x1, y2-y1
// Because point is x-axis ordered, dx cannot be negative
if dy < 0 {
dy = -dy
}
switch {
// Is line a point ?
case x1 == x2 && y1 == y2:
img[imgHeight-y1][x1] = v.lineColour(x1, imgHeight-y1, lineStyle, lineStyleIndex, firstLogicalColour, secondLogicalColour, transparency)
// Is line an horizontal ?
case y1 == y2:
for ; dx != 0; dx-- {
img[imgHeight-y1][x1] = v.lineColour(x1, imgHeight-y1, lineStyle, lineStyleIndex, firstLogicalColour, secondLogicalColour, transparency)
v.advanceLineStyleCounter()
x1++
}
img[imgHeight-y1][x1] = v.lineColour(x1, imgHeight-y1, lineStyle, lineStyleIndex, firstLogicalColour, secondLogicalColour, transparency)
// Is line a vertical ?
case x1 == x2:
if y1 > y2 {
y1, y2 = y2, y1
}
for ; dy != 0; dy-- {
img[imgHeight-y1][x1] = v.lineColour(x1, imgHeight-y1, lineStyle, lineStyleIndex, firstLogicalColour, secondLogicalColour, transparency)
v.advanceLineStyleCounter()
y1++
}
img[imgHeight-y1][x1] = v.lineColour(x1, imgHeight-y1, lineStyle, lineStyleIndex, firstLogicalColour, secondLogicalColour, transparency)
// Is line a diagonal ?
case dx == dy:
if y1 < y2 {
for ; dx != 0; dx-- {
img[imgHeight-y1][x1] = v.lineColour(x1, imgHeight-y1, lineStyle, lineStyleIndex, firstLogicalColour, secondLogicalColour, transparency)
v.advanceLineStyleCounter()
x1++
y1++
}
} else {
for ; dx != 0; dx-- {
img[imgHeight-y1][x1] = v.lineColour(x1, imgHeight-y1, lineStyle, lineStyleIndex, firstLogicalColour, secondLogicalColour, transparency)
v.advanceLineStyleCounter()
x1++
y1--
}
}
img[imgHeight-y1][x1] = v.lineColour(x1, imgHeight-y1, lineStyle, lineStyleIndex, firstLogicalColour, secondLogicalColour, transparency)
// wider than high ?
case dx > dy:
if y1 < y2 {
// BresenhamDxXRYD(img, x1, y1, x2, y2, col)
dy, e, slope = 2*dy, dx, 2*dx
for ; dx != 0; dx-- {
img[imgHeight-y1][x1] = v.lineColour(x1, imgHeight-y1, lineStyle, lineStyleIndex, firstLogicalColour, secondLogicalColour, transparency)
v.advanceLineStyleCounter()
x1++
e -= dy
if e < 0 {
y1++
e += slope
}
}
} else {
// BresenhamDxXRYU(img, x1, y1, x2, y2, col)
dy, e, slope = 2*dy, dx, 2*dx
for ; dx != 0; dx-- {
img[imgHeight-y1][x1] = v.lineColour(x1, imgHeight-y1, lineStyle, lineStyleIndex, firstLogicalColour, secondLogicalColour, transparency)
v.advanceLineStyleCounter()
x1++
e -= dy
if e < 0 {
y1--
e += slope
}
}
}
img[imgHeight-y1][x1] = v.lineColour(x1, imgHeight-y1, lineStyle, lineStyleIndex, firstLogicalColour, secondLogicalColour, transparency)
// higher than wide.
default:
if y1 < y2 {
// BresenhamDyXRYD(img, x1, y1, x2, y2, col)
dx, e, slope = 2*dx, dy, 2*dy
for ; dy != 0; dy-- {
img[imgHeight-y1][x1] = v.lineColour(x1, imgHeight-y1, lineStyle, lineStyleIndex, firstLogicalColour, secondLogicalColour, transparency)
v.advanceLineStyleCounter()
y1++
e -= dx
if e < 0 {
x1++
e += slope
}
}
} else {
// BresenhamDyXRYU(img, x1, y1, x2, y2, col)
dx, e, slope = 2*dx, dy, 2*dy
for ; dy != 0; dy-- {
img[imgHeight-y1][x1] = v.lineColour(x1, imgHeight-y1, lineStyle, lineStyleIndex, firstLogicalColour, secondLogicalColour, transparency)
v.advanceLineStyleCounter()
y1--
e -= dx
if e < 0 {
x1++
e += slope
}
}
}
img[imgHeight-y1][x1] = v.lineColour(x1, imgHeight-y1, lineStyle, lineStyleIndex, firstLogicalColour, secondLogicalColour, transparency)
}
return img
}