1 module CPUblit.draw;
2 
3 import CPUblit.colorspaces;
4 /**
5  * Draws a line using a fixed point method. Is capable of drawing lines diagonally.
6  */
7 public @nogc void drawLine(T)(int x0, int y0, int x1, int y1, T color, T* dest, int destWidth){
8 	static if(!(T == "ubyte" || T == "ushort" || T == "Color32Bit")){
9 		static assert("Template parameter '" ~ T.stringof ~ "' is not supported!");
10 	}
11 	if(x1 < x0){
12 		int k = x1;
13 		x1 = x0;
14 		x0 = k;
15 	}
16 	if(y1 < y0){
17 		int k = y1;
18 		y1 = y0;
19 		y0 = k;
20 	}
21 	int dx = x1 - x0;
22 	int dy = y1 - y0;
23 	if(!dx || !dy){
24 		if(!dy){
25 			sizediff_t offset = destWidth * y1;
26 			for(int x = x0; x <= x1; x++){
27 				dest[offset + x] = color;
28 			}
29 		}else{
30 			sizediff_t offset = destWidth * y0 + x0;
31 			for(int y = y0; y <= y1; y++){
32 				dest[offset] = color;
33 				offset += destWidth;
34 			}
35 		}
36 	}else if(dx>=dy){
37 		int D = 2*dy - dx;
38 		int y = y0;
39 		for(int x = x0; x <= x1; x++){
40 			dest[destWidth * y + x] = color;
41 			if(D > 0){
42 				y += 1;
43 				D -= 2*dx;
44 			}
45 			D += 2*dx;
46 		}
47 	}else{
48 		int D = 2*dx - dy;
49 		int x = x0;
50 		for(int y = y0; y <= y1; y++){
51 			dest[destWidth * y + x] = color;
52 			if(D > 0){
53 				x += 1;
54 				D -= 2*dy;
55 			}
56 			D += 2*dy;
57 		}
58 	}
59 }
60 /**
61  * Draws a rectangle.
62  */
63 public @nogc void drawRectangle(T)(int x0, int y0, int x1, int y1, T color, T*dest, int destWidth){
64 	static if(!(T == "ubyte" || T == "ushort" || T == "Color32Bit")){
65 		static assert("Template parameter '" ~ T.stringof ~ "' is not supported!");
66 	}
67 	drawLine(x0,y0,x0,y1,color,dest,destWidth);
68 	drawLine(x0,y0,x1,y0,color,dest,destWidth);
69 	drawLine(x1,y0,x1,y1,color,dest,destWidth);
70 	drawLine(x0,y1,x1,y1,color,dest,destWidth);
71 }
72 /**
73  * Draws a filled rectangle.
74  * TODO: Upgrade algorhithm to use SSE2/MMX for faster filling.
75  */
76 public @nogc void drawFilledRectangle(T)(int x0, int y0, int x1, int y1, T color, T* dest, int destWidth){
77 	if(x1 < x0){
78 		int k = x1;
79 		x1 = x0;
80 		x0 = k;
81 	}
82 	if(y1 < y0){
83 		int k = y1;
84 		y1 = y0;
85 		y0 = k;
86 	}
87 	int targetWidth = y1 - y0;
88 	
89 	while(targetWidth){
90 		drawLine!T(x0, y0, x1, y0, color, dest, destWidth);
91 		targetWidth--;
92 	}
93 }