diff options
Diffstat (limited to 'widgets/drawille-go/drawille.go')
-rw-r--r-- | widgets/drawille-go/drawille.go | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/widgets/drawille-go/drawille.go b/widgets/drawille-go/drawille.go new file mode 100644 index 0000000..f9954d0 --- /dev/null +++ b/widgets/drawille-go/drawille.go @@ -0,0 +1,275 @@ +package drawille + +//import "code.google.com/p/goncurses" +import "math" + +var pixel_map = [4][2]int{ + {0x1, 0x8}, + {0x2, 0x10}, + {0x4, 0x20}, + {0x40, 0x80}} + +// Braille chars start at 0x2800 +var braille_char_offset = 0x2800 + +func getPixel(y, x int) int { + var cy, cx int + if y >= 0 { + cy = y % 4 + } else { + cy = 3 + ((y + 1) % 4) + } + if x >= 0 { + cx = x % 2 + } else { + cx = 1 + ((x + 1) % 2) + } + return pixel_map[cy][cx] +} + +type Canvas struct { + LineEnding string + chars map[int]map[int]int +} + +// Make a new canvas +func NewCanvas() Canvas { + c := Canvas{LineEnding: "\n"} + c.Clear() + return c +} + +func (c Canvas) MaxY() int { + max := 0 + for k, _ := range c.chars { + if k > max { + max = k + } + } + return max * 4 +} + +func (c Canvas) MinY() int { + min := 0 + for k, _ := range c.chars { + if k < min { + min = k + } + } + return min * 4 +} + +func (c Canvas) MaxX() int { + max := 0 + for _, v := range c.chars { + for k, _ := range v { + if k > max { + max = k + } + } + } + return max * 2 +} + +func (c Canvas) MinX() int { + min := 0 + for _, v := range c.chars { + for k, _ := range v { + if k < min { + min = k + } + } + } + return min * 2 +} + +// Clear all pixels +func (c *Canvas) Clear() { + c.chars = make(map[int]map[int]int) +} + +// Convert x,y to cols, rows +func (c Canvas) get_pos(x, y int) (int, int) { + return (x / 2), (y / 4) +} + +// Set a pixel of c +func (c *Canvas) Set(x, y int) { + px, py := c.get_pos(x, y) + if m := c.chars[py]; m == nil { + c.chars[py] = make(map[int]int) + } + val := c.chars[py][px] + mapv := getPixel(y, x) + c.chars[py][px] = val | mapv +} + +// Unset a pixel of c +func (c *Canvas) UnSet(x, y int) { + px, py := c.get_pos(x, y) + x, y = int(math.Abs(float64(x))), int(math.Abs(float64(y))) + if m := c.chars[py]; m == nil { + c.chars[py] = make(map[int]int) + } + c.chars[py][px] = c.chars[py][px] &^ getPixel(y, x) +} + +// Toggle a point +func (c *Canvas) Toggle(x, y int) { + px, py := c.get_pos(x, y) + if (c.chars[py][px] & getPixel(y, x)) != 0 { + c.UnSet(x, y) + } else { + c.Set(x, y) + } +} + +// Set text to the given coordinates +func (c *Canvas) SetText(x, y int, text string) { + x, y = x/2, y/4 + if m := c.chars[y]; m == nil { + c.chars[y] = make(map[int]int) + } + for i, char := range text { + c.chars[y][x+i] = int(char) - braille_char_offset + } +} + +// Get pixel at the given coordinates +func (c Canvas) Get(x, y int) bool { + dot_index := pixel_map[y%4][x%2] + x, y = x/2, y/4 + char := c.chars[y][x] + return (char & dot_index) != 0 +} + +// GetScreenCharacter gets character at the given screen coordinates +func (c Canvas) GetScreenCharacter(x, y int) rune { + return rune(c.chars[y][x] + braille_char_offset) +} + +// GetCharacter gets character for the given pixel +func (c Canvas) GetCharacter(x, y int) rune { + return c.GetScreenCharacter(x/4, y/4) +} + +// Rows retrieves the rows from a given view +func (c Canvas) Rows(minX, minY, maxX, maxY int) []string { + minrow, maxrow := minY/4, (maxY)/4 + mincol, maxcol := minX/2, (maxX)/2 + + ret := make([]string, 0) + for rownum := minrow; rownum < (maxrow + 1); rownum = rownum + 1 { + row := "" + for x := mincol; x < (maxcol + 1); x = x + 1 { + char := c.chars[rownum][x] + row += string(rune(char + braille_char_offset)) + } + ret = append(ret, row) + } + return ret +} + +// Frame retrieves a string representation of the frame at the given parameters +func (c Canvas) Frame(minX, minY, maxX, maxY int) string { + var ret string + for _, row := range c.Rows(minX, minY, maxX, maxY) { + ret += row + ret += c.LineEnding + } + return ret +} + +func (c Canvas) String() string { + return c.Frame(c.MinX(), c.MinY(), c.MaxX(), c.MaxY()) +} + +type Point struct { + X, Y int +} + +// Line returns []Point where each Point is a dot in the line +func Line(x1, y1, x2, y2 int) []Point { + xdiff := abs(x1 - x2) + ydiff := abs(y2 - y1) + + var xdir, ydir int + if x1 <= x2 { + xdir = 1 + } else { + xdir = -1 + } + if y1 <= y2 { + ydir = 1 + } else { + ydir = -1 + } + + r := max(xdiff, ydiff) + + points := make([]Point, r+1) + + for i := 0; i <= r; i++ { + x, y := x1, y1 + if ydiff != 0 { + y += (i * ydiff) / (r * ydir) + } + if xdiff != 0 { + x += (i * xdiff) / (r * xdir) + } + points[i] = Point{x, y} + } + + return points +} + +// DrawLine draws a line onto the Canvas +func (c *Canvas) DrawLine(x1, y1, x2, y2 int) { + for _, p := range Line(x1, y1, x2, y2) { + c.Set(p.X, p.Y) + } +} + +func (c *Canvas) DrawPolygon(center_x, center_y, sides, radius float64) { + degree := 360 / sides + for n := 0; n < int(sides); n = n + 1 { + a := float64(n) * degree + b := float64(n+1) * degree + + x1 := int(center_x + (math.Cos(radians(a)) * (radius/2 + 1))) + y1 := int(center_y + (math.Sin(radians(a)) * (radius/2 + 1))) + x2 := int(center_x + (math.Cos(radians(b)) * (radius/2 + 1))) + y2 := int(center_y + (math.Sin(radians(b)) * (radius/2 + 1))) + + c.DrawLine(x1, y1, x2, y2) + } +} + +func radians(d float64) float64 { + return d * (math.Pi / 180) +} + +func round(x float64) int { + return int(x + 0.5) +} + +func min(x, y int) int { + if x < y { + return x + } + return y +} + +func max(x, y int) int { + if x > y { + return x + } + return y +} + +func abs(x int) int { + if x < 0 { + return x * -1 + } + return x +} |