1 /* 2 * Copyright (C) 2015-2017, by Laszlo Szeremi under the Boost license. 3 * 4 * Pixel Perfect Engine, graphics.draw module 5 */ 6 7 module PixelPerfectEngine.graphics.draw; 8 9 import std.stdio; 10 import std.math; 11 import std.conv; 12 13 import PixelPerfectEngine.graphics.bitmap; 14 import compose = CPUblit.composing; 15 import draw = CPUblit.draw; 16 import bmfont; 17 public import PixelPerfectEngine.graphics.fontsets; 18 public import PixelPerfectEngine.graphics.common; 19 //import system.etc; 20 /** 21 * Draws into a 8bit bitmap. 22 */ 23 public class BitmapDrawer{ 24 public Bitmap8Bit output; 25 public ubyte brushTransparency; 26 ///Creates the object alongside its output. 27 public this(int x, int y){ 28 output = new Bitmap8Bit(x, y); 29 30 } 31 ///Draws a single line. 32 public void drawLine(int xa, int xb, int ya, int yb, ubyte color){ 33 draw.drawLine(xa, ya, xb, yb, color, output.getPtr(), output.width); 34 } 35 ///Draws a line using a brush. 36 public void drawLine(int xa, int xb, int ya, int yb, Bitmap8Bit brush){ 37 if(xa == xb){ 38 39 if(ya < yb){ 40 for(int j ; j < (yb - ya) ; j++){ 41 insertBitmap(xa, ya + j, brush); 42 } 43 }else{ 44 for(int j ; j > (yb - ya) ; j--){ 45 insertBitmap(xa, ya + j, brush); 46 } 47 } 48 xa++; 49 xb++; 50 51 }else if(ya == yb){ 52 53 if(xa > xb){ 54 for(int j ; j < (xa - xb) ; j++){ 55 insertBitmap(xa + j, ya, brush); 56 } 57 }else{ 58 for(int j ; j > (xa - xb) ; j--){ 59 insertBitmap(xa + j, ya, brush); 60 } 61 } 62 ya++; 63 yb++; 64 65 }else{ 66 if(xa < xb){ 67 if(ya < yb){ 68 int xy = to!int(sqrt(to!double((xb - xa) * (xb - xa)) + ((yb - ya) * (yb - ya)))); 69 70 for(int j ; j < xb - xa ; j++){ 71 int y = to!int(sqrt(to!double(xy * xy) - ((xa + j)*(xa + j)))); 72 insertBitmap(xa + j, ya + y, brush); 73 } 74 75 }else{ 76 int xy = to!int(sqrt(to!double((xb - xa) * (xb - xa)) + ((ya - yb) * (ya - yb)))); 77 78 for(int j ; j < xb - xa ; j++){ 79 int y = to!int(sqrt(to!double(xy * xy) - ((xa + j)*(xa + j)))); 80 insertBitmap(xa + j, ya - y, brush); 81 } 82 83 } 84 }else{ 85 if(ya < yb){ 86 int xy = to!int(sqrt(to!double((xa - xb) * (xa - xb)) + ((yb - ya) * (yb - ya)))); 87 88 for(int j ; j > xb - xa ; j--){ 89 int y = to!int(sqrt(to!double(xy * xy) - ((xa + j)*(xa + j)))); 90 insertBitmap(xa + j, ya + y, brush); 91 } 92 93 }else{ 94 int xy = to!int(sqrt(to!double((xa - xb) * (xa - xb)) + ((ya - yb) * (ya - yb)))); 95 96 for(int j ; j > xb - xa ; j--){ 97 int y = to!int(sqrt(to!double(xy * xy) - ((xa + j)*(xa + j)))); 98 insertBitmap(xa + j, ya - y, brush); 99 } 100 101 } 102 } 103 } 104 } 105 ///Inserts a bitmap using blitter. 106 public void insertBitmap(int x, int y, Bitmap8Bit bitmap){ 107 ubyte* psrc = bitmap.getPtr, pdest = output.getPtr; 108 pdest += x + output.width * y; 109 int length = bitmap.width; 110 for(int iy ; iy < bitmap.height ; iy++){ 111 compose.blitter(psrc,pdest,length); 112 psrc += length; 113 pdest += output.width; 114 } 115 } 116 ///Inserts a color letter. 117 public void insertColorLetter(int x, int y, Bitmap8Bit bitmap, ubyte color){ 118 ubyte* psrc = bitmap.getPtr, pdest = output.getPtr; 119 pdest += x + output.width * y; 120 int length = bitmap.width; 121 for(int iy ; iy < bitmap.height ; iy++){ 122 compose.textBlitter(psrc,pdest,length,color); 123 psrc += length; 124 pdest += output.width; 125 } 126 } 127 ///Inserts a midsection of the bitmap defined by slice 128 public void insertBitmapSlice(int x, int y, Bitmap8Bit bitmap, Coordinate slice){ 129 ubyte* psrc = bitmap.getPtr, pdest = output.getPtr; 130 pdest += x + output.width * y; 131 int bmpWidth = bitmap.width; 132 psrc += slice.left + bmpWidth * slice.top; 133 int length = slice.width; 134 for(int iy ; iy < slice.height ; iy++){ 135 compose.blitter(psrc,pdest,length); 136 psrc += bmpWidth; 137 pdest += output.width; 138 } 139 } 140 ///Inserts a midsection of the bitmap defined by slice as a color letter 141 public void insertColorLetter(int x, int y, Bitmap8Bit bitmap, ubyte color, Coordinate slice){ 142 ubyte* psrc = bitmap.getPtr, pdest = output.getPtr; 143 pdest += x + output.width * y; 144 int bmpWidth = bitmap.width; 145 psrc += slice.left + bmpWidth * slice.top; 146 int length = slice.width; 147 for(int iy ; iy < slice.height ; iy++){ 148 compose.textBlitter(psrc,pdest,length,color); 149 psrc += bmpWidth; 150 pdest += output.width; 151 } 152 } 153 ///Draws a rectangle. 154 public void drawRectangle(int xa, int xb, int ya, int yb, ubyte color){ 155 drawLine(xa, xa, ya, yb, color); 156 drawLine(xb, xb, ya, yb, color); 157 drawLine(xa, xb, ya, ya, color); 158 drawLine(xa, xb, yb, yb, color); 159 } 160 161 public void drawRectangle(int xa, int xb, int ya, int yb, Bitmap8Bit brush){ 162 xa = xa + brush.width; 163 ya = ya + brush.height; 164 xb = xb - brush.width; 165 yb = yb - brush.height; 166 drawLine(xa, xa, ya, yb, brush); 167 drawLine(xb, xb, ya, yb, brush); 168 drawLine(xa, xb, ya, ya, brush); 169 drawLine(xa, xb, yb, yb, brush); 170 } 171 ///Draws a filled rectangle. 172 public void drawFilledRectangle(int xa, int xb, int ya, int yb, ubyte color){ 173 draw.drawFilledRectangle(xa, ya, xb, yb, color, output.getPtr(), output.width); 174 } 175 ///Fills the area with a pattern. 176 public void patternFill(int xa, int ya, int xb, int yb, Bitmap8Bit pattern){ 177 178 } 179 ///Draws texts. (deprecated, will be removed after Version 1.0.0) 180 public deprecated void drawText(int x, int y, wstring text, Bitmap8Bit[wchar] fontSet, int style = 0){ 181 int length; 182 for(int i ; i < text.length ; i++){ 183 length += fontSet[text[i]].width; 184 } 185 //writeln(text); 186 if(style == 0){ 187 x = x - (length / 2); 188 y -= fontSet['a'].height / 2; 189 } 190 foreach(wchar c ; text){ 191 192 insertBitmap(x, y, fontSet[c]); 193 x = x + fontSet[c].width; 194 } 195 } 196 ///Draws text to the given point. 197 public void drawText(int x, int y, dstring text, Fontset!(Bitmap8Bit) fontset, uint style = 0){ 198 int length = fontset.getTextLength(text); 199 //writeln(text); 200 /+if(style == 0){ 201 x = x - (length / 2); 202 y -= fontset.getSize() / 2; 203 }else if(style == 2){ 204 y -= fontset.getSize(); 205 }+/ 206 if(style & FontFormat.HorizCentered) 207 x = x - (length / 2); 208 if(style & FontFormat.VertCentered) 209 y -= fontset.getSize() / 2; 210 foreach(dchar c ; text){ 211 const Font.Char chinfo = fontset.chars[c]; 212 const Coordinate letterSlice = Coordinate(chinfo.x, chinfo.y, chinfo.x + chinfo.width, chinfo.y + chinfo.height); 213 insertBitmapSlice(x + chinfo.xoffset, y + chinfo.yoffset, fontset.pages[chinfo.page], letterSlice); 214 x += chinfo.xadvance; 215 } 216 } 217 ///Draws colored text from monocromatic font. 218 public void drawColorText(int x, int y, dstring text, Fontset!(Bitmap8Bit) fontset, ubyte color, uint style = 0){ 219 //color = 1; 220 int length = fontset.getTextLength(text); 221 if(style & FontFormat.HorizCentered) 222 x = x - (length / 2); 223 if(style & FontFormat.VertCentered) 224 y -= fontset.getSize() / 2; 225 if(style & FontFormat.RightJustified) 226 x -= length; 227 int fontheight = fontset.getSize(); 228 foreach(dchar c ; text){ 229 const Font.Char chinfo = fontset.chars[c]; 230 const Coordinate letterSlice = Coordinate(chinfo.x, chinfo.y, chinfo.x + chinfo.width, chinfo.y + chinfo.height); 231 insertColorLetter(x + chinfo.xoffset, y + chinfo.yoffset, fontset.pages[chinfo.page], color, letterSlice); 232 x += chinfo.xadvance; 233 } 234 } 235 236 } 237 238 enum FontFormat : uint{ 239 HorizCentered = 0x1, 240 VertCentered = 0x2, 241 RightJustified = 0x10, 242 }