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 import dimage.types : ARGB8888BE; 12 13 /** 14 * Graphics primitive. Represents a single point on a 2D field. 15 */ 16 public struct Point { 17 public int x, y; 18 /** 19 * Moves the point by the given amount 20 */ 21 public void relMove (int rX, int rY) @safe @nogc pure nothrow { 22 x += rX; 23 y += rY; 24 } 25 public string toString() const { 26 import std.conv : to; 27 return "x: " ~ to!string(x) ~ " ; y: " ~ to!string(y); 28 } 29 } 30 /** 31 * Graphics primitive. Represents a box on a 2D field. 32 * Note on area calculation: The smallest box that can be represented is 1 * 1, as it counts the endpoints as part of the box. 33 * This behavior got added with 0.10.0, to standardize various behaviors of the engine, and fix some odd behavior the GUI 34 * drawing functions had. 35 */ 36 public struct Box { 37 public int left, top, right, bottom; 38 this(int left, int top, int right, int bottom) @safe pure nothrow @nogc { 39 this.left=left; 40 this.top=top; 41 this.right=right; 42 this.bottom=bottom; 43 } 44 /** 45 * Returns the width of the represented box. 46 */ 47 public @property @nogc @safe nothrow pure int width() const { 48 return right - left + 1; 49 } 50 /** 51 * Sets the width of the represented box while keeping the lefthand coordinate. 52 */ 53 public @property int width(int val) @nogc @safe pure nothrow { 54 right = left + val - 1; 55 return right - left + 1; 56 } 57 /** 58 * Returns the height of the represented box. 59 */ 60 public @property @nogc @safe nothrow pure int height() const { 61 return bottom - top + 1; 62 } 63 /** 64 * Sets the height of the represented box while keeping the top coordinate. 65 */ 66 public @property int height(int val) @nogc @safe pure nothrow { 67 bottom = top + val - 1; 68 return bottom - top + 1; 69 } 70 /** 71 * Returns the area of the represented box. 72 */ 73 public @property @nogc @safe nothrow pure size_t area() const { 74 return width * height; 75 } 76 /** 77 * Moves the box to the given position. 78 */ 79 public void move(int x, int y) @nogc @safe nothrow pure { 80 right = x + width(); 81 bottom = y + height(); 82 left = x; 83 top = y; 84 } 85 /** 86 * Moves the box by the given values. 87 */ 88 public void relMove(int x, int y) @nogc @safe nothrow pure { 89 left = left + x; 90 right = right + x; 91 top = top + y; 92 bottom = bottom + y; 93 } 94 /** 95 * Returns true if the given point is between the coordinates. 96 */ 97 public bool isBetween(int x, int y) @nogc @safe pure nothrow const { 98 return (x >= left && x <= right && y >= top && y <= bottom); 99 } 100 ///Ditto 101 public bool isBetween(Point p) @nogc @safe pure nothrow const { 102 return (p.x >= left && p.x <= right && p.y >= top && p.y <= bottom); 103 } 104 /** 105 * Operator overloading for scalar values. 106 * `-`: Adds to left and top, substracts from right and bottom. (Shrinks by amount) 107 * `+`: Subtracts from left and top, adds to right and bottom. (Grows by amount) 108 */ 109 public Box opBinary(string op)(const int rhs) @nogc @safe pure nothrow const { 110 static if (op == "-") { 111 return Box(left + rhs, top + rhs, right - rhs, bottom - rhs); 112 } else static if (op == "+") { 113 return Box(left - rhs, top - rhs, right + rhs, bottom + rhs); 114 } else static assert(0, "Unsupported operator!"); 115 } 116 ///Returns the upper-left corner. 117 public @property Point cornerUL() @nogc @safe pure nothrow const { 118 return Point(left, top); 119 } 120 ///Returns the upper-right corner. 121 public @property Point cornerUR() @nogc @safe pure nothrow const { 122 return Point(right, top); 123 } 124 ///Returns the lowew-left corner. 125 public @property Point cornerLL() @nogc @safe pure nothrow const { 126 return Point(left, bottom); 127 } 128 ///Returns the lower-right corner. 129 public @property Point cornerLR() @nogc @safe pure nothrow const { 130 return Point(right, bottom); 131 } 132 ///Pads the edges of the given box by the given amounts and returns a new Box. 133 public Box pad(const int horiz, const int vert) @nogc @safe pure nothrow const { 134 return Coordinate(left + horiz, top + vert, right - horiz, bottom - vert); 135 } 136 /** 137 * Returns a string with the coordinates that is useful for debugging 138 */ 139 public string toString() const { 140 import PixelPerfectEngine.system.etc; 141 import std.conv; 142 /*return "Coordinate: Left: 0x" ~ intToHex(left, 8) ~ " Top: 0x" ~ intToHex(top, 8) ~ " Right: 0x" ~ intToHex(right, 8) ~ " Bottom: 0x" ~ intToHex(bottom, 8) ~ 143 " Width: 0x" ~ intToHex(width(), 8) ~ " Height: 0x" ~ intToHex(height(), 8);*/ 144 return "Coordinate: Left: " ~ to!string(left) ~ " Top: " ~ to!string(top) ~ " Right: " ~ to!string(right) ~ 145 " Bottom: " ~ to!string(bottom) ~ " Width: " ~ to!string(width()) ~ " Height: " ~ to!string(height()); 146 } 147 } 148 alias Coordinate = Box; 149 /** 150 * Defines polygons for sprite transformation (eg. scaling, rotation). 151 * Most likely will be removed due to lack of use. 152 */ 153 public struct Quad{ 154 public int midX, midY; ///Defines the midpoint to reduce the need for precision. Corners are referenced to this point 155 public float cornerAX, cornerAY, cornerAZ; ///Upper-left corner mapping 156 public float cornerBX, cornerBY, cornerBZ; ///Upper-right corner mapping 157 public float cornerCX, cornerCY, cornerCZ; ///Lower-left corner mapping 158 public float cornerDX, cornerDY, cornerDZ; ///Lower-right corner mapping 159 } 160 alias Color = ARGB8888BE; 161 /+ 162 /** 163 * Various representations of color with various accessibility modes. 164 * Probably will be replaced with a struct from either CPUBLiT or dimage. 165 */ 166 public struct Color{ 167 union{ 168 uint raw; ///Raw representation in integer form, also forces the system to align in INT32. 169 ubyte[4] colors; ///Normal representation, aliases are used for color naming. 170 } 171 version(LittleEndian){ 172 ///Returns the alpha channel of the color 173 public @nogc @safe @property pure nothrow ubyte alpha() const{ return colors[0]; } 174 ///Returns the red channel of the color 175 public @nogc @safe @property pure nothrow ubyte red() const{ return colors[1]; } 176 ///Returns the green channel of the color 177 public @nogc @safe @property pure nothrow ubyte green() const{ return colors[2]; } 178 ///Returns the blue channel of the color 179 public @nogc @safe @property pure nothrow ubyte blue() const{ return colors[3]; } 180 ///Sets the alpha channel of the color 181 public @nogc @safe @property pure nothrow ubyte alpha(ubyte value) { return colors[0] = value; } 182 ///Sets the red channel of the color 183 public @nogc @safe @property pure nothrow ubyte red(ubyte value) { return colors[1] = value; } 184 ///Sets the green channel of the color 185 public @nogc @safe @property pure nothrow ubyte green(ubyte value) { return colors[2] = value; } 186 ///Sets the blue channel of the color 187 public @nogc @safe @property pure nothrow ubyte blue(ubyte value) { return colors[3] = value; } 188 }else{ 189 ///Returns the alpha channel of the color 190 public @nogc @safe @property pure nothrow ubyte alpha() const{ return colors[3]; } 191 ///Returns the red channel of the color 192 public @nogc @safe @property pure nothrow ubyte red() const{ return colors[2]; } 193 ///Returns the green channel of the color 194 public @nogc @safe @property pure nothrow ubyte green() const{ return colors[1]; } 195 ///Returns the blue channel of the color 196 public @nogc @safe @property pure nothrow ubyte blue() const{ return colors[0]; } 197 ///Sets the alpha channel of the color 198 public @nogc @safe @property pure nothrow ubyte alpha(ubyte value) { return colors[3] = value; } 199 ///Sets the red channel of the color 200 public @nogc @safe @property pure nothrow ubyte red(ubyte value) { return colors[2] = value; } 201 ///Sets the green channel of the color 202 public @nogc @safe @property pure nothrow ubyte green(ubyte value) { return colors[1] = value; } 203 ///Sets the blue channel of the color 204 public @nogc @safe @property pure nothrow ubyte blue(ubyte value) { return colors[0] = value; } 205 } 206 /** 207 * Contructs a color from four individual values. 208 */ 209 public @nogc this(ubyte alpha, ubyte red, ubyte green, ubyte blue) nothrow pure @safe { 210 this.alpha = alpha; 211 this.red = red; 212 this.green = green; 213 this.blue = blue; 214 } 215 /** 216 * Constructs a color from a single 32 bit unsigned integer. 217 */ 218 public @nogc this(uint val) nothrow pure @safe { 219 raw = val; 220 } 221 /** 222 * Operator overloading for quick math. '*' is alpha-blending, '^' is XOR blitter, '&' is normal "blitter". 223 * Alpha is used from right hand side and kept on left hand side when needed 224 */ 225 public Color opBinary(string op)(Color rhs){ 226 static if(op == "+"){ 227 int r = red + rhs.red, g = green + rhs.green, b = blue + rhs.blue, a = alpha + rhs.alpha; 228 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); 229 }else static if(op == "-"){ 230 int r = red - rhs.red, g = green - rhs.green, b = blue - rhs.blue, a = alpha - rhs.alpha; 231 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); 232 }else static if(op == "^"){ 233 return Color(alpha ^ rhs.alpha, red ^ rhs.red, green ^ rhs.green, blue ^ rhs.blue); 234 }else static if(op == "&"){ 235 return rhs.alpha ? rhs : this; 236 }else static if(op == "*"){ 237 return Color(alpha, cast(ubyte)( ( (rhs.red * (1 + rhs.alpha)) + (red * (256 - rhs.alpha)) )>>8 ), 238 cast(ubyte)( ( (rhs.green * (1 + rhs.alpha)) + (green * (256 - rhs.alpha)) )>>8 ), 239 cast(ubyte)( ( (rhs.blue * (1 + rhs.alpha)) + (blue * (256 - rhs.alpha)) )>>8 )); 240 }else static assert(0, "Operator '" ~ op ~ "' not supported!"); 241 } 242 /** 243 * Returns a string for debugging. 244 */ 245 public string toString() const{ 246 import PixelPerfectEngine.system.etc; 247 return "0x" ~ intToHex(raw, 8); 248 } 249 }+/ 250 //alias Pixel32Bit Color;