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;