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 @safe nothrow pure int width() const{ 26 return right-left; 27 } 28 /** 29 * Returns the height of the represented box. 30 */ 31 public @property @nogc @safe nothrow pure int height() const{ 32 return bottom-top; 33 } 34 /** 35 * Returns the area of the represented box. 36 */ 37 public @property @nogc @safe nothrow pure size_t area() const{ 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() const{ 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) ~ 67 " Bottom: " ~ to!string(bottom) ~ " 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 * Probably will be replaced with a struct from either CPUBLiT or dimage. 83 */ 84 public struct Color{ 85 union{ 86 uint raw; ///Raw representation in integer form, also forces the system to align in INT32. 87 ubyte[4] colors; ///Normal representation, aliases are used for color naming. 88 } 89 version(LittleEndian){ 90 ///Returns the alpha channel of the color 91 public @nogc @safe @property pure nothrow ubyte alpha() const{ return colors[0]; } 92 ///Returns the red channel of the color 93 public @nogc @safe @property pure nothrow ubyte red() const{ return colors[1]; } 94 ///Returns the green channel of the color 95 public @nogc @safe @property pure nothrow ubyte green() const{ return colors[2]; } 96 ///Returns the blue channel of the color 97 public @nogc @safe @property pure nothrow ubyte blue() const{ return colors[3]; } 98 ///Sets the alpha channel of the color 99 public @nogc @safe @property pure nothrow ubyte alpha(ubyte value) { return colors[0] = value; } 100 ///Sets the red channel of the color 101 public @nogc @safe @property pure nothrow ubyte red(ubyte value) { return colors[1] = value; } 102 ///Sets the green channel of the color 103 public @nogc @safe @property pure nothrow ubyte green(ubyte value) { return colors[2] = value; } 104 ///Sets the blue channel of the color 105 public @nogc @safe @property pure nothrow ubyte blue(ubyte value) { return colors[3] = value; } 106 }else{ 107 ///Returns the alpha channel of the color 108 public @nogc @safe @property pure nothrow ubyte alpha() const{ return colors[3]; } 109 ///Returns the red channel of the color 110 public @nogc @safe @property pure nothrow ubyte red() const{ return colors[2]; } 111 ///Returns the green channel of the color 112 public @nogc @safe @property pure nothrow ubyte green() const{ return colors[1]; } 113 ///Returns the blue channel of the color 114 public @nogc @safe @property pure nothrow ubyte blue() const{ return colors[0]; } 115 ///Sets the alpha channel of the color 116 public @nogc @safe @property pure nothrow ubyte alpha(ubyte value) { return colors[3] = value; } 117 ///Sets the red channel of the color 118 public @nogc @safe @property pure nothrow ubyte red(ubyte value) { return colors[2] = value; } 119 ///Sets the green channel of the color 120 public @nogc @safe @property pure nothrow ubyte green(ubyte value) { return colors[1] = value; } 121 ///Sets the blue channel of the color 122 public @nogc @safe @property pure nothrow ubyte blue(ubyte value) { return colors[0] = value; } 123 } 124 /** 125 * Contructs a color from four individual values. 126 */ 127 public @nogc this(ubyte alpha, ubyte red, ubyte green, ubyte blue) nothrow pure @safe { 128 this.alpha = alpha; 129 this.red = red; 130 this.green = green; 131 this.blue = blue; 132 } 133 /** 134 * Constructs a color from a single 32 bit unsigned integer. 135 */ 136 public @nogc this(uint val) nothrow pure @safe { 137 raw = val; 138 } 139 /** 140 * Operator overloading for quick math. '*' is alpha-blending, '^' is XOR blitter, '&' is normal "blitter". 141 * Alpha is used from right hand side and kept on left hand side when needed 142 */ 143 public Color opBinary(string op)(Color rhs){ 144 static if(op == "+"){ 145 int r = red + rhs.red, g = green + rhs.green, b = blue + rhs.blue, a = alpha + rhs.alpha; 146 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); 147 }else static if(op == "-"){ 148 int r = red - rhs.red, g = green - rhs.green, b = blue - rhs.blue, a = alpha - rhs.alpha; 149 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); 150 }else static if(op == "^"){ 151 return Color(alpha ^ rhs.alpha, red ^ rhs.red, green ^ rhs.green, blue ^ rhs.blue); 152 }else static if(op == "&"){ 153 return rhs.alpha ? rhs : this; 154 }else static if(op == "*"){ 155 return Color(alpha, cast(ubyte)( ( (rhs.red * (1 + rhs.alpha)) + (red * (256 - rhs.alpha)) )>>8 ), 156 cast(ubyte)( ( (rhs.green * (1 + rhs.alpha)) + (green * (256 - rhs.alpha)) )>>8 ), 157 cast(ubyte)( ( (rhs.blue * (1 + rhs.alpha)) + (blue * (256 - rhs.alpha)) )>>8 )); 158 }else static assert(0, "Operator '" ~ op ~ "' not supported!"); 159 } 160 /** 161 * Returns a string for debugging. 162 */ 163 public string toString() const{ 164 import PixelPerfectEngine.system.etc; 165 return "0x" ~ intToHex(raw, 8); 166 } 167 } 168 //alias Pixel32Bit Color;