using Cosmos.Core; using Cosmos.System; using Cosmos.System.Graphics; using CMLeonOS; using System; using System.Drawing; namespace CMLeonOS.Gui { internal class Window { internal Window(Process process, int x, int y, int width, int height) { WM = ProcessManager.GetProcess(); Process = process; X = x; Y = y; this.width = width; this.height = height; ResizeBuffer(); } internal Window(Process process, Window parent, int x, int y, int width, int height) { WM = ProcessManager.GetProcess(); Process = process; _relativeTo = parent; X = x; Y = y; this.width = width; this.height = height; ResizeBuffer(); } internal int[] Buffer { get; private set; } private Window _relativeTo = null; internal Process Process { get; private set; } protected WindowManager WM; private int x; private int y; private int width; private int height; private const int bytesPerPixel = 4; #region Events internal Action OnDown; internal Action OnClick; internal Action OnDoubleClick; internal Action OnKeyPressed; internal Action OnFocused; internal Action OnUnfocused; internal Action UserResized; #endregion private void ResizeBuffer() { Buffer = new int[Width * Height]; Cosmos.Core.MemoryOperations.Fill(Buffer, Color.White.ToArgb()); } internal void Move(int x, int y, bool sendWMEvent = true) { if (x != X || y != Y) { this.x = x; this.y = y; if (sendWMEvent) { ProcessManager.GetProcess().RerenderAll(); } } } internal void Resize(int width, int height, bool sendWMEvent = true) { if (width != Width || height != Height) { this.width = width; this.height = height; ResizeBuffer(); if (sendWMEvent) { ProcessManager.GetProcess().RerenderAll(); } } } internal void MoveAndResize(int x, int y, int width, int height, bool sendWMEvent = true) { Move(x, y, sendWMEvent: false); Resize(width, height, sendWMEvent: false); if (sendWMEvent) { ProcessManager.GetProcess().RerenderAll(); } } #region Graphics private Color AlphaBlend(Color to, Color from, byte alpha) { byte R = (byte)((to.R * alpha + from.R * (255 - alpha)) >> 8); byte G = (byte)((to.G * alpha + from.G * (255 - alpha)) >> 8); byte B = (byte)((to.B * alpha + from.B * (255 - alpha)) >> 8); return Color.FromArgb(R, G, B); } // https://github.com/CosmosOS/Cosmos/blob/master/source/Cosmos.System2/Graphics/Canvas.cs private void TrimLine(ref int x1, ref int y1, ref int x2, ref int y2) { if (x1 == x2) { x1 = Math.Min(width - 1, Math.Max(0, x1)); x2 = x1; y1 = Math.Min(height - 1, Math.Max(0, y1)); y2 = Math.Min(height - 1, Math.Max(0, y2)); return; } float x1_out = x1, y1_out = y1; float x2_out = x2, y2_out = y2; float m = (y2_out - y1_out) / (x2_out - x1_out); float c = y1_out - m * x1_out; if (x1_out < 0) { x1_out = 0; y1_out = c; } else if (x1_out >= width) { x1_out = width - 1; y1_out = (width - 1) * m + c; } if (x2_out < 0) { x2_out = 0; y2_out = c; } else if (x2_out >= width) { x2_out = width - 1; y2_out = (width - 1) * m + c; } if (y1_out < 0) { x1_out = -c / m; y1_out = 0; } else if (y1_out >= height) { x1_out = (height - 1 - c) / m; y1_out = height - 1; } if (y2_out < 0) { x2_out = -c / m; y2_out = 0; } else if (y2_out >= width) { x2_out = (width - 1 - c) / m; y2_out = width - 1; } if (x1_out < 0 || x1_out >= width || y1_out < 0 || y1_out >= height) { x1_out = 0; x2_out = 0; y1_out = 0; y2_out = 0; } if (x2_out < 0 || x2_out >= width || y2_out < 0 || y2_out >= height) { x1_out = 0; x2_out = 0; y1_out = 0; y2_out = 0; } x1 = (int)x1_out; y1 = (int)y1_out; x2 = (int)x2_out; y2 = (int)y2_out; } // https://github.com/CosmosOS/Cosmos/blob/master/source/Cosmos.System2/Graphics/Canvas.cs internal void DrawHorizontalLine(int dx, int x1, int y1, Color color) { int i; if (dx > 0) { for (i = 0; i < dx; i++) { DrawPoint(x1 + i, y1, color); } } else { for (i = 0; i > dx; i--) { DrawPoint(x1 + i, y1, color); } } } // https://github.com/CosmosOS/Cosmos/blob/master/source/Cosmos.System2/Graphics/Canvas.cs internal void DrawVerticalLine(int dy, int x1, int y1, Color color) { int i; if (dy > 0) { for (i = 0; i < dy; i++) { DrawPoint(x1, y1 + i, color); } } else { for (i = 0; i > dy; i--) { DrawPoint(x1, y1 + i, color); } } } // https://github.com/CosmosOS/Cosmos/blob/master/source/Cosmos.System2/Graphics/Canvas.cs private void DrawDiagonalLine(int dx, int dy, int x1, int y1, Color color) { int i, sdx, sdy, dxabs, dyabs, x, y, px, py; dxabs = Math.Abs(dx); dyabs = Math.Abs(dy); sdx = Math.Sign(dx); sdy = Math.Sign(dy); x = dyabs >> 1; y = dxabs >> 1; px = x1; py = y1; if (dxabs >= dyabs) { for (i = 0; i < dxabs; i++) { y += dyabs; if (y >= dxabs) { y -= dxabs; py += sdy; } px += sdx; DrawPoint(px, py, color); } } else { for (i = 0; i < dyabs; i++) { x += dxabs; if (x >= dyabs) { x -= dyabs; px += sdx; } py += sdy; DrawPoint(px, py, color); } } } public void Clear(Color color) { MemoryOperations.Fill(Buffer, color.ToArgb()); } // To-do: Optimise. public void DrawFilledRectangle(int x, int y, int width, int height, Color color) { int argb = color.ToArgb(); for (int i = Math.Max(0, x); i < Math.Min(Width, x + width); i++) { for (int j = Math.Max(0, y); j < Math.Min(Height, y + height); j++) { Buffer[(j * Width) + i] = argb; } } } public void DrawRectangle(int x, int y, int width, int height, Color color) { DrawHorizontalLine(width, x, y, color); DrawHorizontalLine(width, x, y + height - 1, color); DrawVerticalLine(height - 1, x, y + 1, color); DrawVerticalLine(height - 1, x + width - 1, y + 1, color); } public void DrawPoint(int x, int y, Color color) { if (x < 0 || x >= width) return; if (y < 0 || y >= height) return; int index = x + (y * width); Buffer[index] = color.ToArgb(); } public Color GetPixel(int x, int y) { if (x < 0 || x >= width) return Color.Transparent; if (y < 0 || y >= height) return Color.Transparent; int index = x + (y * width); return Color.FromArgb(Buffer[index]); } // https://github.com/CosmosOS/Cosmos/blob/master/source/Cosmos.System2/Graphics/Canvas.cs public void DrawCircle(int x, int y, int radius, Color color) { int i = radius; int j = 0; int e = 0; while (i >= j) { DrawPoint(x + i, y + j, color); DrawPoint(x + j, y + i, color); DrawPoint(x - j, y + i, color); DrawPoint(x - i, y + j, color); DrawPoint(x - i, y - j, color); DrawPoint(x - j, y - i, color); DrawPoint(x + j, y - i, color); DrawPoint(x + i, y - j, color); j++; if (e <= 0) { e += 2 * j + 1; } if (e > 0) { i--; e -= 2 * i + 1; } } } // https://github.com/CosmosOS/Cosmos/blob/master/source/Cosmos.System2/Graphics/Canvas.cs public void DrawLine(int x1, int y1, int x2, int y2, Color color) { TrimLine(ref x1, ref y1, ref x2, ref y2); int dx, dy; dx = x2 - x1; dy = y2 - y1; if (dy == 0) { DrawHorizontalLine(dx, x1, y1, color); return; } if (dx == 0) { DrawVerticalLine(dy, x1, y1, color); return; } DrawDiagonalLine(dx, dy, x1, y1, color); } public void DrawString(string str, Color color, int x, int y) { //Asc16.DrawAsciiString(str, color, x, y, Buffer, width, height); SmoothMono.TextRenderer.DrawString(str, color, Buffer, width, height, x, y); } public void DrawImage(Bitmap bitmap, int x, int y) { /*if (bitmap.rawData.Length != bitmap.Width * bitmap.Height) { throw new Exception("Invalid bitmap."); } for (int i = 0; i < y; i++) { int destOffset = ((i + y) * width) + x; int srcOffset = (int)(i * bitmap.Width); fixed (int* destPtr = &Buffer[destOffset]) fixed (int* sourcePtr = &bitmap.rawData[srcOffset]) { MemoryOperations.Copy(destPtr, sourcePtr, (int)bitmap.Width); } }*/ for (int i = 0; i < bitmap.Height; i++) { for (int j = 0; j < bitmap.Width; j++) { DrawPoint(x + j, y + i, Color.FromArgb(bitmap.RawData[(i * bitmap.Width) + j])); } } } public void DrawImageAlpha(Bitmap bitmap, int x, int y) { /*if (bitmap.rawData.Length != bitmap.Width * bitmap.Height) { throw new Exception("Invalid bitmap."); } for (int i = 0; i < y; i++) { int destOffset = ((i + y) * width) + x; int srcOffset = (int)(i * bitmap.Width); fixed (int* destPtr = &Buffer[destOffset]) fixed (int* sourcePtr = &bitmap.rawData[srcOffset]) { MemoryOperations.Copy(destPtr, sourcePtr, (int)bitmap.Width); } }*/ for (int i = 0; i < bitmap.Height; i++) { for (int j = 0; j < bitmap.Width; j++) { Color from = GetPixel(x + j, y + i); Color to = Color.FromArgb(bitmap.RawData[(i * bitmap.Width) + j]); DrawPoint(x + j, y + i, AlphaBlend(to, from, to.A)); } } } #endregion Graphics public int X { get { return x; } set { if (value != x) { x = value; ProcessManager.GetProcess().RerenderAll(); } } } public int Y { get { return y; } set { if (value != y) { y = value; ProcessManager.GetProcess().RerenderAll(); } } } public int Width { get { return width; } set { if (value != width) { if (value < width) { ProcessManager.GetProcess().RerenderAll(); } width = value; ResizeBuffer(); } } } public int Height { get { return height; } set { if (value != height) { if (value < height) { ProcessManager.GetProcess().RerenderAll(); } height = value; ResizeBuffer(); } } } public int BytesPerPixel { get { return bytesPerPixel; } } public int ScreenX { get { if (_relativeTo != null) { return x + _relativeTo.ScreenX; } else { return x; } } } public int ScreenY { get { if (_relativeTo != null) { return y + _relativeTo.ScreenY; } else { return y; } } } public Window RelativeTo { get { return _relativeTo; } set { _relativeTo = value; } } } }