diff --git a/gogame/draw/consts.go b/gogame/draw/consts.go new file mode 100644 index 0000000..e518398 --- /dev/null +++ b/gogame/draw/consts.go @@ -0,0 +1,10 @@ +package draw + + +const ( + LEFT_EDGE=0x1 + RIGHT_EDGE=0x2 + BOTTOM_EDGE=0x4 + TOP_EDGE=0x8 +) + diff --git a/gogame/draw/draw.go b/gogame/draw/draw.go index 71eeecb..d4b1514 100644 --- a/gogame/draw/draw.go +++ b/gogame/draw/draw.go @@ -1,512 +1,15 @@ package draw import ( - "fmt" - "math" +// "fmt" +// "math" "github.com/veandco/go-sdl2/sdl" "../color" - "../rect" + ) -const ( - LEFT_EDGE=0x1 - RIGHT_EDGE=0x2 - BOTTOM_EDGE=0x4 - TOP_EDGE=0x8 -) - -func Line(surf *sdl.Surface, col color.Color,x1,y1,x2,y2 ,width int) sdl.Rect { - pts := make([]int,4) - pts[0] = x1 - pts[1] = y1 - pts[2] = x2 - pts[3] = y2 - - if width < 1 { - return rect.Rect(x1,y1,0,0) - } - - err := surf.Lock() - if err != nil { - return rect.Rect(0,0,0,0) - } - anydraw := clip_and_draw_line_width(surf,&surf.ClipRect, col, width,pts) - surf.Unlock() - if anydraw == 0 { - return rect.Rect(x1,y1,0,0) - } - rleft := 0 - rtop := 0 - - if x1 < x2 { - rleft = x1 - }else { - rleft = x2 - } - - if y1 < y2 { - rtop = y1 - }else { - rtop = y2 - } - - dx := abs(x1-x2) - dy := abs(y1-y2) - - rwidth := 0 - rheight := 0 - if dx > dy { - rwidth = dx +1 - rheight = dy + width - }else { - rwidth = dx + width - rheight = dy + 1 - } - - return rect.Rect(rleft,rtop,rwidth,rheight) -} - -func Rect(surf *sdl.Surface,color color.Color, _rect *sdl.Rect, border_width uint32) { - color_hex := color.ToHex() - fmt.Printf("%x\n",color_hex) - -} - -func clip_and_draw_line(surf *sdl.Surface, rect *sdl.Rect, col color.Color, pts []int) int { +func AARoundRect() { - if clipline(pts, int(rect.X),int(rect.Y),int(rect.X+ rect.W-1), int(rect.Y+rect.H-1) ) == 0 { - return 0 - } - - if pts[1] == pts[3] { - drawhorzline(surf, col, pts[0],pts[1],pts[2]) - }else if pts[0] == pts[2] { - drawvertline(surf,col, pts[0],pts[1],pts[3]) - }else { - drawline(surf, col, pts[0],pts[1],pts[2],pts[3]) - } - - return 1 -} - - -func clip_and_draw_line_width(surf *sdl.Surface,rect *sdl.Rect,col color.Color, width int, pts []int) int { - loop := 0 - xinc :=0 - yinc :=0 - newpts :=make([]int,4) - range_ := make([]int,4) - anydraw := 0 - if abs(pts[0]-pts[2]) > abs(pts[1]-pts[3]) { - yinc = 1 - }else{ - xinc = 1 - } - copy(newpts, pts) - if clip_and_draw_line(surf,rect,col, newpts) > 0 { - anydraw = 1 - copy(range_,newpts) - }else { - range_[0] = 10000 - range_[1] = 10000 - range_[2] = -10000 - range_[3] = -10000 - } - - for loop = 1; loop < width; loop +=2 { - newpts[0] = pts[0] + xinc*(loop/2+1) - newpts[1] = pts[1] + yinc*(loop/2+1) - newpts[2] = pts[2] + xinc*(loop/2+1) - newpts[3] = pts[3] + yinc*(loop/2+1) - if clip_and_draw_line(surf,rect,col,newpts) > 0 { - anydraw = 1 - range_[0] = min(newpts[0],range_[0]) - range_[1] = min(newpts[1],range_[1]) - range_[2] = max(newpts[2],range_[2]) - range_[3] = max(newpts[3],range_[3]) - } - if (loop + 1) < width { - newpts[0] = pts[0] - xinc*(loop/2+1) - newpts[1] = pts[1] - yinc*(loop/2+1) - newpts[2] = pts[2] - xinc*(loop/2+1) - newpts[3] = pts[3] - yinc*(loop/2+1) - if clip_and_draw_line(surf,rect,col, newpts) > 0 { - anydraw = 1 - range_[0] = min(newpts[0],range_[0]) - range_[1] = min(newpts[1],range_[1]) - range_[2] = max(newpts[2],range_[2]) - range_[3] = max(newpts[3],range_[3]) - } - } - } - if anydraw > 0 { - copy(pts,range_) - } - return anydraw -} - -func max(a, b int) int { - if a > b { - return a - } - return b -} - -func min(a, b int) int { - if a < b { - return a - } - return b -} - -func abs(n int) int { - return int(math.Abs(float64(n))) -} - -func encode(x,y,left,top,right,bottom int) int { - code := 0 - if (x < left ) { - code |= LEFT_EDGE - } - if (x > right) { - code |= RIGHT_EDGE - } - if (y < top) { - code |= TOP_EDGE - } - if (y > bottom) { - code |= BOTTOM_EDGE - } - return code -} - -func inside(a int) bool { - if a > 0 { - return false - } - return true -} - -func accept(a,b int) bool { - ret := a | b - if ret > 0 { - return false - }else { - return true - } -} - -func reject(a,b int) bool { - ret := a & b - if ret > 0 { - return true - } - return false -} - -func clipline(pts []int, left,top,right,bottom int) int { - - x1 := pts[0] - y1 := pts[1] - x2 := pts[2] - y2 := pts[3] - - var code1 int - var code2 int - draw := 0 - var swaptmp int - var m float64 /*slope*/ - - for true { - code1 = encode(x1,y1,left,top,right,bottom) - code2 = encode(x2,y2,left,top,right,bottom) - if ( accept(code1,code2) ) { - draw = 1 - break - } else if ( reject(code1,code2 ) ) { - break - }else { - if inside(code1) { - swaptmp = x2 - x2 = x1 - x1 = swaptmp - swaptmp = y2 - y2 = y1 - y1 = swaptmp - swaptmp = code2 - code2 = code1 - code1 = swaptmp - } - if x2 != x1 { - m = float64(y2 - y1) / float64(x2-x1) - }else { - m = 1.0 - } - if (code1 & LEFT_EDGE) > 0 { - y1 += int(float64(left-x1)*m) - x1 = left - }else if (code1 & RIGHT_EDGE) > 0 { - y1 += int(float64(right-x1)*m) - x1 = right - }else if (code1 & BOTTOM_EDGE) > 0 { - if x2 != x1 { - x1 += int(float64(bottom-y1) / m) - } - y1 = bottom - }else if (code1 & TOP_EDGE) > 0 { - if x2 != x1 { - x1 += int( float64(top-y1) / m) - } - y1 = top - } - } - } - - if draw > 0 { - pts[0] = x1 - pts[1] = y1 - pts[2] = x2 - pts[3] = y2 - } - - return draw -} - -func drawline(surf *sdl.Surface, col color.Color, x1,y1,x2,y2 int) { - deltax := x2 - x1 - deltay := y2 - y1 - - signx := 0 - signy := 0 - - if deltax < 0 { - signx = -1 - }else { - signx = 1 - } - - if deltay < 0 { - signy = -1 - }else { - signy = 1 - } - - deltax = signx * deltax + 1 - deltay = signy * deltay + 1 - - bytes_per_pixel := surf.BytesPerPixel() - - pixx := int(bytes_per_pixel) - pixy := int(surf.Pitch) - - addr := pixy* y1 + x1 * bytes_per_pixel - - pixx *= int(signx) - pixy *= int(signy) - - swaptmp := 0 - if deltax < deltay { - swaptmp = deltax - deltax = deltay - deltay = swaptmp - swaptmp = pixx - pixx = pixy - pixy = swaptmp - } - - x := 0 - y := 0 - - color_bytes := col.ToBytes() - pixels := surf.Pixels() - - switch bytes_per_pixel { - case 1: - for ; x < deltax; x++ { - pixels[addr] = color_bytes[0] - y += deltay - if y >= deltax { - y -= deltax - addr += pixy - } - addr +=pixx - } - break - case 2: - for ; x < deltax;x++ { - pixels[addr] = color_bytes[0] - pixels[addr+1] = color_bytes[1] - y+= deltay - if y >= deltax { - y -= deltax - addr += pixy - } - - addr+=pixx - } - break - case 3: - for ; x < deltax; x++ { - pixels[addr] = color_bytes[0] - pixels[addr+1] = color_bytes[1] - pixels[addr+2] = color_bytes[2] - y+=deltay - if y >= deltax { - y-=deltax - addr += pixy - } - addr+=pixx - } - break - case 4: - for ; x < deltax; x++ { - pixels[addr] = color_bytes[0] - pixels[addr+1] = color_bytes[1] - pixels[addr+2] = color_bytes[2] - pixels[addr+3] = color_bytes[3] - y+=deltay - if y >= deltax { - y-=deltax - addr += pixy - } - addr+=pixx - } - break - } - -} - -func drawhorzline(surf *sdl.Surface, col color.Color, x1,y1,x2 int) { - if x1 == x2 { - pixel(surf,col,x1,y1) - return - } - - bytes_per_pixel := surf.BytesPerPixel() - color_bytes := col.ToBytes() - pixels := surf.Pixels() - - addr := int(surf.Pitch) * y1 - end := 0 - start := 0 - if x1 < x2 { - end = addr + x2*bytes_per_pixel - start = addr+x1 *bytes_per_pixel - }else { - end = addr + x1 *bytes_per_pixel - start = addr + x2 * bytes_per_pixel - } - - switch bytes_per_pixel { - case 1: - for ; start <=end; start++ { - pixels[start] = color_bytes[0] - } - case 2: - for ; start <= end; start+=2 { - pixels[start] = color_bytes[0] - pixels[start+1] = color_bytes[1] - } - case 3: - for ; start <= end; start+=3 { - pixels[start] = color_bytes[0] - pixels[start+1] = color_bytes[1] - pixels[start+2] = color_bytes[2] - } - case 4: - for ; start <= end; start +=4 { - pixels[start] = color_bytes[0] - pixels[start+1] = color_bytes[1] - pixels[start+2] = color_bytes[2] - pixels[start+3] = color_bytes[3] - } - } - -} - -func drawvertline(surf *sdl.Surface, col color.Color, x1,y1,y2 int) { - if y1 == y2 { - pixel(surf,col, x1,y1) - } - bytes_per_pixel := surf.BytesPerPixel() - color_bytes := col.ToBytes() - pixels := surf.Pixels() - pitch := int(surf.Pitch) - - addr := x1 * bytes_per_pixel - end := 0 - start := 0 - if y1 < y2 { - end = addr + y2* pitch - start = addr + y1*pitch - }else { - end = addr + y1*pitch - start = addr + y2*pitch - } - - switch bytes_per_pixel { - case 1: - for ; start <=end; start+=pitch { - pixels[start] = color_bytes[0] - } - case 2: - for ; start <= end; start+=pitch { - pixels[start] = color_bytes[0] - pixels[start+1] = color_bytes[1] - } - case 3: - for ; start <= end; start+=pitch { - pixels[start] = color_bytes[0] - pixels[start+1] = color_bytes[1] - pixels[start+2] = color_bytes[2] - } - case 4: - for ; start <= end; start +=pitch { - pixels[start] = color_bytes[0] - pixels[start+1] = color_bytes[1] - pixels[start+2] = color_bytes[2] - pixels[start+3] = color_bytes[3] - } - } - -} - -func pixel(surf *sdl.Surface, c color.Color, x,y int) int { - pixels := surf.Pixels() - bytes_per_pixel := surf.BytesPerPixel() - - addr := y * int(surf.Pitch) + x*bytes_per_pixel // 1 2 3 4 - - color_bytes := c.ToBytes() - - if x < int(surf.ClipRect.X) || x >= int(surf.ClipRect.X + surf.ClipRect.W) || - y < int(surf.ClipRect.Y) || y >= int(surf.ClipRect.Y + surf.ClipRect.H) { - return 0 - } - - if bytes_per_pixel == 1 { - pixels[addr] = color_bytes[0] - } - - if bytes_per_pixel == 2 { - for i :=0; i < bytes_per_pixel; i++ { - pixels[addr+i] = color_bytes[i] - } - } - - if bytes_per_pixel == 3 { - for i :=0; i < bytes_per_pixel; i++ { - pixels[addr+i] = color_bytes[i] - } - } - - if bytes_per_pixel == 4 { - for i :=0; i < bytes_per_pixel; i++ { - pixels[addr+i] = color_bytes[i] - } - } - - return 1 } func Point(surf *sdl.Surface, c color.Color, x,y int) { diff --git a/gogame/draw/line.go b/gogame/draw/line.go new file mode 100644 index 0000000..f57846c --- /dev/null +++ b/gogame/draw/line.go @@ -0,0 +1,542 @@ +package draw + +import ( +// "fmt" + "github.com/veandco/go-sdl2/sdl" + "../color" + "../rect" +) + +//closed true => an additional line segment is drawn between the first and last points. +//pointlist should be [][2] +func Lines(surf *sdl.Surface, col color.Color,closed bool, pointlist [][]int,width int) sdl.Rect { + length := len(pointlist) + if length < 2 { + panic("draw lines at least contains more than 1 points pair") + } + pts := make([]int,4) + + if len(pointlist[0]) < 2 { + panic("start points should be more than 1 at least") + } + + x := pointlist[0][0] + y := pointlist[0][1] + + startx := x + pts[0] = x + left := x + right := x + + starty := y + pts[1] = y + top := y + bottom := y + + if width < 1 { + return rect.Rect(x,y,0,0) + } + + err := surf.Lock() + if err != nil { + return rect.Rect(0,0,0,0) + } + + drawn := 1 + for loop := 1; loop < length; loop++ { + item := pointlist[loop] + if len(item) < 2 { + continue + } + + x = item[0] + y = item[1] + drawn += 1 + pts[0] = startx + pts[1] = starty + startx = x + starty = y + pts[2] = x + pts[3] = y + if clip_and_draw_line_width(surf, &surf.ClipRect, col, width, pts) > 0 { + left = min(min(pts[0],pts[2]),left) + top = min(min(pts[1],pts[3]),top) + right = max(max(pts[0],pts[2]),right) + bottom = max(max(pts[1],pts[3]),bottom) + } + } + + if closed == true && drawn > 2 { + item := pointlist[0] + x = item[0] + y = item[1] + + pts[0] = startx + pts[1] = starty + pts[2] = x + pts[3] = y + clip_and_draw_line_width(surf, &surf.ClipRect, col, width, pts) + } + surf.Unlock() + + return rect.Rect(left,top,right-left+1, bottom-top+1) + +} + +func Line(surf *sdl.Surface, col color.Color,x1,y1,x2,y2 ,width int) sdl.Rect { + pts := make([]int,4) + pts[0] = x1 + pts[1] = y1 + pts[2] = x2 + pts[3] = y2 + + if width < 1 { + return rect.Rect(x1,y1,0,0) + } + + err := surf.Lock() + if err != nil { + return rect.Rect(0,0,0,0) + } + anydraw := clip_and_draw_line_width(surf,&surf.ClipRect, col, width,pts) + surf.Unlock() + if anydraw == 0 { + return rect.Rect(x1,y1,0,0) + } + rleft := 0 + rtop := 0 + + if x1 < x2 { + rleft = x1 + }else { + rleft = x2 + } + + if y1 < y2 { + rtop = y1 + }else { + rtop = y2 + } + + dx := abs(x1-x2) + dy := abs(y1-y2) + + rwidth := 0 + rheight := 0 + if dx > dy { + rwidth = dx +1 + rheight = dy + width + }else { + rwidth = dx + width + rheight = dy + 1 + } + + return rect.Rect(rleft,rtop,rwidth,rheight) +} + + +func clip_and_draw_line(surf *sdl.Surface, rect *sdl.Rect, col color.Color, pts []int) int { + + if clipline(pts, int(rect.X),int(rect.Y),int(rect.X+ rect.W-1), int(rect.Y+rect.H-1) ) == 0 { + return 0 + } + + if pts[1] == pts[3] { + drawhorzline(surf, col, pts[0],pts[1],pts[2]) + }else if pts[0] == pts[2] { + drawvertline(surf,col, pts[0],pts[1],pts[3]) + }else { + drawline(surf, col, pts[0],pts[1],pts[2],pts[3]) + } + + return 1 +} + + +func clip_and_draw_line_width(surf *sdl.Surface,rect *sdl.Rect,col color.Color, width int, pts []int) int { + loop := 0 + xinc :=0 + yinc :=0 + newpts :=make([]int,4) + range_ := make([]int,4) + anydraw := 0 + if abs(pts[0]-pts[2]) > abs(pts[1]-pts[3]) { + yinc = 1 + }else{ + xinc = 1 + } + copy(newpts, pts) + if clip_and_draw_line(surf,rect,col, newpts) > 0 { + anydraw = 1 + copy(range_,newpts) + }else { + range_[0] = 10000 + range_[1] = 10000 + range_[2] = -10000 + range_[3] = -10000 + } + + for loop = 1; loop < width; loop +=2 { + newpts[0] = pts[0] + xinc*(loop/2+1) + newpts[1] = pts[1] + yinc*(loop/2+1) + newpts[2] = pts[2] + xinc*(loop/2+1) + newpts[3] = pts[3] + yinc*(loop/2+1) + if clip_and_draw_line(surf,rect,col,newpts) > 0 { + anydraw = 1 + range_[0] = min(newpts[0],range_[0]) + range_[1] = min(newpts[1],range_[1]) + range_[2] = max(newpts[2],range_[2]) + range_[3] = max(newpts[3],range_[3]) + } + if (loop + 1) < width { + newpts[0] = pts[0] - xinc*(loop/2+1) + newpts[1] = pts[1] - yinc*(loop/2+1) + newpts[2] = pts[2] - xinc*(loop/2+1) + newpts[3] = pts[3] - yinc*(loop/2+1) + if clip_and_draw_line(surf,rect,col, newpts) > 0 { + anydraw = 1 + range_[0] = min(newpts[0],range_[0]) + range_[1] = min(newpts[1],range_[1]) + range_[2] = max(newpts[2],range_[2]) + range_[3] = max(newpts[3],range_[3]) + } + } + } + if anydraw > 0 { + copy(pts,range_) + } + return anydraw +} + + +func encode(x,y,left,top,right,bottom int) int { + code := 0 + if (x < left ) { + code |= LEFT_EDGE + } + if (x > right) { + code |= RIGHT_EDGE + } + if (y < top) { + code |= TOP_EDGE + } + if (y > bottom) { + code |= BOTTOM_EDGE + } + return code +} + +func inside(a int) bool { + if a > 0 { + return false + } + return true +} + +func accept(a,b int) bool { + ret := a | b + if ret > 0 { + return false + }else { + return true + } +} + +func reject(a,b int) bool { + ret := a & b + if ret > 0 { + return true + } + return false +} + +func clipline(pts []int, left,top,right,bottom int) int { + + x1 := pts[0] + y1 := pts[1] + x2 := pts[2] + y2 := pts[3] + + var code1 int + var code2 int + draw := 0 + var swaptmp int + var m float64 /*slope*/ + + for true { + code1 = encode(x1,y1,left,top,right,bottom) + code2 = encode(x2,y2,left,top,right,bottom) + if ( accept(code1,code2) ) { + draw = 1 + break + } else if ( reject(code1,code2 ) ) { + break + }else { + if inside(code1) { + swaptmp = x2 + x2 = x1 + x1 = swaptmp + swaptmp = y2 + y2 = y1 + y1 = swaptmp + swaptmp = code2 + code2 = code1 + code1 = swaptmp + } + if x2 != x1 { + m = float64(y2 - y1) / float64(x2-x1) + }else { + m = 1.0 + } + if (code1 & LEFT_EDGE) > 0 { + y1 += int(float64(left-x1)*m) + x1 = left + }else if (code1 & RIGHT_EDGE) > 0 { + y1 += int(float64(right-x1)*m) + x1 = right + }else if (code1 & BOTTOM_EDGE) > 0 { + if x2 != x1 { + x1 += int(float64(bottom-y1) / m) + } + y1 = bottom + }else if (code1 & TOP_EDGE) > 0 { + if x2 != x1 { + x1 += int( float64(top-y1) / m) + } + y1 = top + } + } + } + + if draw > 0 { + pts[0] = x1 + pts[1] = y1 + pts[2] = x2 + pts[3] = y2 + } + + return draw +} + +func drawline(surf *sdl.Surface, col color.Color, x1,y1,x2,y2 int) { + deltax := x2 - x1 + deltay := y2 - y1 + + signx := 0 + signy := 0 + + if deltax < 0 { + signx = -1 + }else { + signx = 1 + } + + if deltay < 0 { + signy = -1 + }else { + signy = 1 + } + + deltax = signx * deltax + 1 + deltay = signy * deltay + 1 + + bytes_per_pixel := surf.BytesPerPixel() + + pixx := int(bytes_per_pixel) + pixy := int(surf.Pitch) + + addr := pixy* y1 + x1 * bytes_per_pixel + + pixx *= int(signx) + pixy *= int(signy) + + swaptmp := 0 + if deltax < deltay { + swaptmp = deltax + deltax = deltay + deltay = swaptmp + swaptmp = pixx + pixx = pixy + pixy = swaptmp + } + + x := 0 + y := 0 + + color_bytes := col.ToBytes() + pixels := surf.Pixels() + + switch bytes_per_pixel { + case 1: + for ; x < deltax; x++ { + pixels[addr] = color_bytes[0] + y += deltay + if y >= deltax { + y -= deltax + addr += pixy + } + addr +=pixx + } + break + case 2: + for ; x < deltax;x++ { + pixels[addr] = color_bytes[0] + pixels[addr+1] = color_bytes[1] + y+= deltay + if y >= deltax { + y -= deltax + addr += pixy + } + + addr+=pixx + } + break + case 3: + for ; x < deltax; x++ { + pixels[addr] = color_bytes[0] + pixels[addr+1] = color_bytes[1] + pixels[addr+2] = color_bytes[2] + y+=deltay + if y >= deltax { + y-=deltax + addr += pixy + } + addr+=pixx + } + break + case 4: + for ; x < deltax; x++ { + pixels[addr] = color_bytes[0] + pixels[addr+1] = color_bytes[1] + pixels[addr+2] = color_bytes[2] + pixels[addr+3] = color_bytes[3] + y+=deltay + if y >= deltax { + y-=deltax + addr += pixy + } + addr+=pixx + } + break + } + +} + +func drawhorzline(surf *sdl.Surface, col color.Color, x1,y1,x2 int) { + if x1 == x2 { + pixel(surf,col,x1,y1) + return + } + + bytes_per_pixel := surf.BytesPerPixel() + color_bytes := col.ToBytes() + pixels := surf.Pixels() + + addr := int(surf.Pitch) * y1 + end := 0 + start := 0 + if x1 < x2 { + end = addr + x2*bytes_per_pixel + start = addr+x1 *bytes_per_pixel + }else { + end = addr + x1 *bytes_per_pixel + start = addr + x2 * bytes_per_pixel + } + + switch bytes_per_pixel { + case 1: + for ; start <=end; start++ { + pixels[start] = color_bytes[0] + } + case 2: + for ; start <= end; start+=2 { + pixels[start] = color_bytes[0] + pixels[start+1] = color_bytes[1] + } + case 3: + for ; start <= end; start+=3 { + pixels[start] = color_bytes[0] + pixels[start+1] = color_bytes[1] + pixels[start+2] = color_bytes[2] + } + case 4: + for ; start <= end; start +=4 { + pixels[start] = color_bytes[0] + pixels[start+1] = color_bytes[1] + pixels[start+2] = color_bytes[2] + pixels[start+3] = color_bytes[3] + } + } + +} + +func drawhorzlineclip(surf *sdl.Surface, col color.Color, x1 , y1, x2 int ) { + if y1 < int(surf.ClipRect.Y) || y1 >= int( surf.ClipRect.Y + surf.ClipRect.H) { + return + } + + if x2 < x1 { + temp := x1 + x1 = x2 + x2 = temp + } + x1 = max(x1,int(surf.ClipRect.X)) + x2 = min(x2,int(surf.ClipRect.X+surf.ClipRect.W-1)) + if x2 < int(surf.ClipRect.X) || x1 >= int( surf.ClipRect.X + surf.ClipRect.W) { + return + } + + if x1 == x2 { + pixel(surf,col, x1,y1) + }else { + drawhorzline(surf,col,x1,y1,x2) + } +} + +func drawvertline(surf *sdl.Surface, col color.Color, x1,y1,y2 int) { + if y1 == y2 { + pixel(surf,col, x1,y1) + } + bytes_per_pixel := surf.BytesPerPixel() + color_bytes := col.ToBytes() + pixels := surf.Pixels() + pitch := int(surf.Pitch) + + addr := x1 * bytes_per_pixel + end := 0 + start := 0 + if y1 < y2 { + end = addr + y2* pitch + start = addr + y1*pitch + }else { + end = addr + y1*pitch + start = addr + y2*pitch + } + + switch bytes_per_pixel { + case 1: + for ; start <=end; start+=pitch { + pixels[start] = color_bytes[0] + } + case 2: + for ; start <= end; start+=pitch { + pixels[start] = color_bytes[0] + pixels[start+1] = color_bytes[1] + } + case 3: + for ; start <= end; start+=pitch { + pixels[start] = color_bytes[0] + pixels[start+1] = color_bytes[1] + pixels[start+2] = color_bytes[2] + } + case 4: + for ; start <= end; start +=pitch { + pixels[start] = color_bytes[0] + pixels[start+1] = color_bytes[1] + pixels[start+2] = color_bytes[2] + pixels[start+3] = color_bytes[3] + } + } + +} + diff --git a/gogame/draw/polygon.go b/gogame/draw/polygon.go new file mode 100644 index 0000000..ea818a9 --- /dev/null +++ b/gogame/draw/polygon.go @@ -0,0 +1,164 @@ +package draw + +import ( + "fmt" +// "math" + "github.com/veandco/go-sdl2/sdl" + "../color" + "../rect" + "../qsort" + +) + +func draw_fillpoly(surf *sdl.Surface, vx []int, vy []int, numpoints int, col color.Color) { + + miny:=0 + maxy:=0 + y:=0 + x1:=0 + y1:=0 + x2:=0 + y2:=0 + ints := 0 + ind1:=0 + ind2:=0 + + polyints := make([]int,numpoints) + + /* Determine Y maxima */ + miny = vy[0] + maxy = vy[0] + for i:=1; i < numpoints; i++ { + miny = min(miny,vy[i]) + maxy = max(maxy,vy[i]) + } + + /* Draw, scanning y */ + for y=miny;y<=maxy;y++ { + ints = 0 + for i:=0; i< numpoints;i++ { + if i == 0 { + ind1 = numpoints -1 + ind2 = 0 + }else { + ind1 = i-1 + ind2 = i + } + + y1 = vy[ind1] + y2 = vy[ind2] + if y1 < y2 { + x1 = vx[ind1] + x2 = vx[ind2] + }else if y1 > y2 { + y2 = vy[ind1] + y1 = vy[ind2] + x2 = vx[ind1] + x1 = vx[ind2] + }else if miny == maxy { + /* Special case: polygon only 1 pixel high. */ + minx:= vx[0] + maxx:= vx[0] + + for j:= 1; j < numpoints; j++ { + minx = min(minx,vx[j]) + maxx = max(maxx,vx[j]) + } + polyints[ints] = minx + ints+=1 + polyints[ints] = maxx + ints+=1 + break + }else { + continue + } + + if ( y >= y1) && (y < y2 ) { + fmt.Println("ints : ",ints) + polyints[ints] = (y-y1) * (x2-x1) / (y2-y1) + x1 + ints+=1 + + }else if (y == maxy) && (y > y1) && (y <= y2) { + polyints[ints] = (y-y1) * (x2-x1) / (y2-y1) + x1 + ints+=1 + } + } + + new_polyints := make([]int, ints) + copy(new_polyints,polyints) + new_polyints = qsort.QuickSort(new_polyints) + + for i:=0;i 0 { + ret := Lines(surf, color, true,points,border_width) + return ret + } + + bytes_per_pixel := surf.BytesPerPixel() + if bytes_per_pixel <= 0 || bytes_per_pixel > 4 { + panic("unsupport bit depth for line draw") + } + + length := len(points) + if length < 3 { + panic("points argument must contain more than 2 points") + } + + item := points[0] // Needs sequence_get_item to fetch from sorted points list + if len(item) < 2 { + panic("points should be a pair of coordinators") + } + + x := item[0] + y := item[1] + + left := x + right := x + top := y + bottom := y + + xlist := make([]int,length) + ylist := make([]int,length) + + numpoints := 0 + for loop := 0; loop < length; loop++ { + item = points[loop] + if len(item) < 2 { + panic("points should be a pair of coordinators") + } + x = item[0] + y = item[1] + + xlist[numpoints] = x + ylist[numpoints] = y + numpoints+=1 + + left = min(x,left) + top = min(y,top) + right = max(x,right) + bottom = max(y,bottom) + } + + err := surf.Lock() + if err != nil { + return rect.Rect(0,0,0,0) + } + + draw_fillpoly(surf,xlist,ylist,numpoints,color) + + surf.Unlock() + + left = max(left,int(surf.ClipRect.X)) + top = max(top, int(surf.ClipRect.Y)) + right = min(right,int(surf.ClipRect.X + surf.ClipRect.W)) + bottom = min(bottom, int(surf.ClipRect.Y + surf.ClipRect.H)) + return rect.Rect(left,top,right-left+1, bottom-top+1) + +} diff --git a/gogame/draw/rect.go b/gogame/draw/rect.go new file mode 100644 index 0000000..cffbd87 --- /dev/null +++ b/gogame/draw/rect.go @@ -0,0 +1,19 @@ +package draw + +import ( +// "math" + "github.com/veandco/go-sdl2/sdl" + "../color" + +) + +func Rect(surf *sdl.Surface,color color.Color, _rect *sdl.Rect, border_width int) { + l := int(_rect.X) + r := int(_rect.X + _rect.W - 1) + t := int(_rect.Y) + b := int(_rect.Y + _rect.H - 1) + + points := [][]int{ []int{l,t}, []int{r,t}, []int{r,b},[]int{l,b} } + Polygon(surf, color, points, border_width) + +} diff --git a/gogame/draw/utils.go b/gogame/draw/utils.go new file mode 100644 index 0000000..5c98055 --- /dev/null +++ b/gogame/draw/utils.go @@ -0,0 +1,64 @@ +package draw + +import ( + "math" + + "github.com/veandco/go-sdl2/sdl" + "../color" +) + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func abs(n int) int { + return int(math.Abs(float64(n))) +} + +func pixel(surf *sdl.Surface, c color.Color, x,y int) int { + pixels := surf.Pixels() + bytes_per_pixel := surf.BytesPerPixel() + + addr := y * int(surf.Pitch) + x*bytes_per_pixel // 1 2 3 4 + + color_bytes := c.ToBytes() + + if x < int(surf.ClipRect.X) || x >= int(surf.ClipRect.X + surf.ClipRect.W) || + y < int(surf.ClipRect.Y) || y >= int(surf.ClipRect.Y + surf.ClipRect.H) { + return 0 + } + + if bytes_per_pixel == 1 { + pixels[addr] = color_bytes[0] + } + + if bytes_per_pixel == 2 { + for i :=0; i < bytes_per_pixel; i++ { + pixels[addr+i] = color_bytes[i] + } + } + + if bytes_per_pixel == 3 { + for i :=0; i < bytes_per_pixel; i++ { + pixels[addr+i] = color_bytes[i] + } + } + + if bytes_per_pixel == 4 { + for i :=0; i < bytes_per_pixel; i++ { + pixels[addr+i] = color_bytes[i] + } + } + + return 1 +} diff --git a/gogame/qsort/qsort.go b/gogame/qsort/qsort.go new file mode 100644 index 0000000..76b3269 --- /dev/null +++ b/gogame/qsort/qsort.go @@ -0,0 +1,37 @@ +package qsort + +import "math/rand" + +func QuickSort(slice []int) []int { + length := len(slice) + + if length <= 1 { + sliceCopy := make([]int, length) + copy(sliceCopy, slice) + return sliceCopy + } + + m := slice[rand.Intn(length)] + + less := make([]int, 0, length) + middle := make([]int, 0, length) + more := make([]int, 0, length) + + for _, item := range slice { + switch { + case item < m: + less = append(less, item) + case item == m: + middle = append(middle, item) + case item > m: + more = append(more, item) + } + } + + less, more = QuickSort(less), QuickSort(more) + + less = append(less, middle...) + less = append(less, more...) + + return less +} diff --git a/gogame/qsort/qsort_test.go b/gogame/qsort/qsort_test.go new file mode 100644 index 0000000..6e697e2 --- /dev/null +++ b/gogame/qsort/qsort_test.go @@ -0,0 +1,27 @@ +package qsort + +import ( + "reflect" + "testing" +) + +var testData = []struct { + input []int + expectedOutput []int +}{ + {[]int{}, []int{}}, + {[]int{42}, []int{42}}, + {[]int{42, 23}, []int{23, 42}}, + {[]int{23, 42, 32, 64, 12, 4}, []int{4, 12, 23, 32, 42, 64}}, +} + +func TestQuickSort(t *testing.T) { + for _, testCase := range testData { + actual := QuickSort(testCase.input) + expected := testCase.expectedOutput + + if !reflect.DeepEqual(actual, expected) { + t.Errorf("%v != %v\n", actual, expected) + } + } +} diff --git a/gogame/surface/surface.go b/gogame/surface/surface.go index 8be322e..1e13047 100644 --- a/gogame/surface/surface.go +++ b/gogame/surface/surface.go @@ -1,10 +1,22 @@ package surface import ( + "fmt" "github.com/veandco/go-sdl2/sdl" + "../color" ) +func Fill(surface *sdl.Surface, col color.Color) { + + rect := sdl.Rect{0,0,0,0} + + rect.W = surface.W + rect.H = surface.H + + FillRect(surface, &rect, uint32(col.ToHex())) +} + func FillRect(surface *sdl.Surface,rect *sdl.Rect, color uint32) { sdl.Do(func() { @@ -14,3 +26,21 @@ func FillRect(surface *sdl.Surface,rect *sdl.Rect, color uint32) { return } +// Create a New Surface +func Surface(w,h int) *sdl.Surface { + //flags=0, depth=0, masks=None + Rmask := 0x000000ff + Gmask := 0x0000ff00 + Bmask := 0x00ff0000 + Amask := 0xff000000 + + flags := 0 + depth := 32 + + surf,err := sdl.CreateRGBSurface(uint32(flags),int32(w),int32(h), int32(depth), uint32(Rmask), uint32(Gmask), uint32(Bmask), uint32(Amask)) + if err != nil { + panic( fmt.Sprintf("sdl.CreateRGBSurface failed %s",sdl.GetError())) + } + + return surf +} diff --git a/test b/test index e801cc3..5184a7c 100755 Binary files a/test and b/test differ diff --git a/test.go b/test.go index ca1ff59..c758c0f 100644 --- a/test.go +++ b/test.go @@ -22,14 +22,12 @@ func run() int { screen := display.SetMode(320,240,0,32) - surface.FillRect(screen,nil, 0) + surface.Fill(screen, color.Color{0,0,0,0} ) - rect := rect.Rect(0, 0, 200, 200) + rect := rect.Rect(0,10, 12, 10) //surface.FillRect(screen,&rect, 0xffff0000) - rect.X = 12 - draw.Rect(screen,color.Color{129,235,234,0},&rect,1) fmt.Println(screen.Pitch) @@ -41,9 +39,9 @@ func run() int { } */ - draw.Line(screen,color.Color{255,44,255,0}, 0,100, 320,100,3) - - draw.Line(screen,color.Color{255,44,255,0}, 10, 0, 10,250,4) +// draw.Line(screen,color.Color{255,44,255,0}, 0,100, 320,100,3) +// draw.Line(screen,color.Color{255,44,255,0}, 10, 0, 10,250,4) + display.Flip()