1 /*
2  * Copyright (c) 2015-2017, by Laszlo Szeremi, under Boost license
3  * 
4  * Pixel Perfect Engine, graphics.common module
5  */
6 
7 module PixelPerfectEngine.graphics.common;
8 
9 //public import CPUblit.colorspaces;
10 
11 /**
12  * Represents a box on a 2D field.
13  */
14 public struct Coordinate{
15 	public int left, top, right, bottom;
16 	@nogc this(int left, int top, int right, int bottom){
17 		this.left=left;
18 		this.top=top;
19 		this.right=right;
20 		this.bottom=bottom;
21 	}
22 	/** 
23 	 * Returns the width of the represented box.
24 	 */
25 	public @property @nogc int width(){
26 		return right-left;
27 	}
28 	/** 
29 	 * Returns the height of the represented box.
30 	 */
31 	public @property @nogc int height(){
32 		return bottom-top;
33 	}
34 	/**
35 	 * Returns the area of the represented box.
36 	 */
37 	public @property @nogc size_t area(){
38 		return width * height;
39 	}
40 	/** 
41 	 * Moves the box to the given position.
42 	 */
43 	public @nogc void move(int x, int y){
44 		right = x + width();
45 		bottom = y + height();
46 		left = x;
47 		top = y;
48 	}
49 	/** 
50 	 * Moves the box by the given values.
51 	 */
52 	public @nogc void relMove(int x, int y){
53 		left = left + x;
54 		right = right + x;
55 		top = top + y;
56 		bottom = bottom + y;
57 	}
58 	/**
59 	 * Returns a string with the coordinates that is useful for debugging
60 	 */
61 	public string toString(){
62 		import PixelPerfectEngine.system.etc;
63 		import std.conv;
64 		/*return "Coordinate: Left: 0x" ~ intToHex(left, 8) ~ " Top: 0x" ~ intToHex(top, 8) ~ " Right: 0x" ~ intToHex(right, 8) ~ " Bottom: 0x" ~ intToHex(bottom, 8) ~
65 				" Width: 0x" ~ intToHex(width(), 8) ~ " Height: 0x" ~ intToHex(height(), 8);*/
66 		return "Coordinate: Left: " ~ to!string(left) ~ " Top: " ~ to!string(top) ~ " Right: " ~ to!string(right) ~ " Bottom: " ~ to!string(bottom) ~
67 				" Width: " ~ to!string(width()) ~ " Height: " ~ to!string(height());
68 	}
69 }
70 /**
71  * Defines polygons for sprite transformation (eg. scaling, rotation).
72  */
73 public struct Quad{
74 	public int midX, midY;		///Defines the midpoint to reduce the need for precision. Corners are referenced to this point
75 	public float cornerAX, cornerAY, cornerAZ;	///Upper-left corner mapping
76 	public float cornerBX, cornerBY, cornerBZ;	///Upper-right corner mapping
77 	public float cornerCX, cornerCY, cornerCZ;	///Lower-left corner mapping
78 	public float cornerDX, cornerDY, cornerDZ;	///Lower-right corner mapping
79 }
80 /**
81  * Various representations of color with various accessibility modes.
82  */
83 public struct Color{
84 	union{
85 		uint raw;	///Raw representation in integer form, also forces the system to align in INT32.
86 		ubyte[4] colors;	///Normal representation, aliases are used for color naming.
87 	}
88 	version(LittleEndian){
89 		public @nogc @property ubyte alpha(){ return colors[0]; }
90 		public @nogc @property ubyte red(){ return colors[1]; }
91 		public @nogc @property ubyte green(){ return colors[2]; }
92 		public @nogc @property ubyte blue(){ return colors[3]; }
93 		public @nogc @property ubyte alpha(ubyte value){ return colors[0] = value; }
94 		public @nogc @property ubyte red(ubyte value){ return colors[1] = value; }
95 		public @nogc @property ubyte green(ubyte value){ return colors[2] = value; }
96 		public @nogc @property ubyte blue(ubyte value){ return colors[3] = value; }
97 	}else{
98 		public @nogc @property ubyte alpha(){ return colors[3]; }
99 		public @nogc @property ubyte red(){ return colors[2]; }
100 		public @nogc @property ubyte green(){ return colors[1]; }
101 		public @nogc @property ubyte blue(){ return colors[0]; }
102 		public @nogc @property ubyte alpha(ubyte value){ return colors[3] = value; }
103 		public @nogc @property ubyte red(ubyte value){ return colors[2] = value; }
104 		public @nogc @property ubyte green(ubyte value){ return colors[1] = value; }
105 		public @nogc @property ubyte blue(ubyte value){ return colors[0] = value; }
106 	}
107 	/**
108 	 * Contructs a color from four individual values.
109 	 */
110 	public @nogc this(ubyte alpha, ubyte red, ubyte green, ubyte blue){
111 		this.alpha = alpha;
112 		this.red = red;
113 		this.green = green;
114 		this.blue = blue;
115 	}
116 	/**
117 	 * Constructs a color from a single 32 bit unsigned integer.
118 	 */
119 	public @nogc this(uint val){
120 		raw = val;
121 	}
122 	/**
123 	 * Operator overloading for quick math. '*' is alpha-blending, '^' is XOR blitter, '&' is normal "blitter". 
124 	 * Alpha is used from right hand side and kept on left hand side when needed
125 	 */
126 	public Color opBinary(string op)(Color rhs){
127 		static if(op == "+"){
128 			int r = red + rhs.red, g = green + rhs.green, b = blue + rhs.blue, a = alpha + rhs.alpha;
129 			return Color(a > 255 ? 255 : cast(ubyte)a, r > 255 ? 255 : cast(ubyte)r, g > 255 ? 255 : cast(ubyte)g, b > 255 ? 255 : cast(ubyte)b);
130 		}else static if(op == "-"){
131 			int r = red - rhs.red, g = green - rhs.green, b = blue - rhs.blue, a = alpha - rhs.alpha;
132 			return Color(a < 0 ? 0 : cast(ubyte)a, r < 0 ? 0 : cast(ubyte)r, g < 0 ? 0 : cast(ubyte)g, b < 0 ? 0 : cast(ubyte)b);
133 		}else static if(op == "^"){
134 			return Color(alpha ^ rhs.alpha, red ^ rhs.red, green ^ rhs.green, blue ^ rhs.blue);
135 		}else static if(op == "&"){
136 			return rhs.alpha ? rhs : this;
137 		}else static if(op == "*"){
138 			return Color(alpha, cast(ubyte)( ( (rhs.red * (1 + rhs.alpha)) + (red * (256 - rhs.alpha)) )>>8 ),
139 								cast(ubyte)( ( (rhs.green * (1 + rhs.alpha)) + (green * (256 - rhs.alpha)) )>>8 ), 
140 								cast(ubyte)( ( (rhs.blue * (1 + rhs.alpha)) + (blue * (256 - rhs.alpha)) )>>8 ));
141 		}else static assert(0, "Operator '" ~ op ~ "' not supported!");
142 	}
143 	/**
144 	 * Returns a string for debugging.
145 	 */
146 	public string toString(){
147 		import PixelPerfectEngine.system.etc;
148 		return "0x" ~ intToHex(raw, 8);
149 	}
150 }
151 //alias Pixel32Bit Color;