diff --git a/source/Cosmos.System2/Graphics/Canvas.cs b/source/Cosmos.System2/Graphics/Canvas.cs index 8ce2470e84..a6ac312140 100644 --- a/source/Cosmos.System2/Graphics/Canvas.cs +++ b/source/Cosmos.System2/Graphics/Canvas.cs @@ -117,7 +117,6 @@ public virtual void Clear(Color color) /// The X coordinate. /// The Y coordinate. public abstract Color GetPointColor(int x, int y); - /// /// Gets the index of the pixel at the given coordinates. /// @@ -530,13 +529,17 @@ public virtual void DrawRectangle(Color color, int x, int y, int width, int heig /// The starting point Y coordinate. /// The width of the rectangle. /// The height of the rectangle. - public virtual void DrawFilledRectangle(Color color, int xStart, int yStart, int width, int height) + public virtual void DrawFilledRectangle(Color color, int xStart, int yStart, int width, int height, bool preventOffBoundPixels = true) { if (height == -1) { height = width; } - + if (preventOffBoundPixels) + { + width = Math.Min(width, (int)Mode.Width - xStart); + height = Math.Min(height, (int)Mode.Height - yStart); + } for (int y = yStart; y < yStart + height; y++) { DrawLine(color, xStart, y, xStart + width - 1, y); @@ -566,16 +569,31 @@ public virtual void DrawTriangle(Color color, int v1x, int v1y, int v2x, int v2y /// The image to draw. /// The origin X coordinate. /// The origin Y coordinate. - public virtual void DrawImage(Image image, int x, int y) + public virtual void DrawImage(Image image, int x, int y, bool preventOffBoundPixels = true) { Color color; - - for (int xi = 0; xi < image.Width; xi++) + if (preventOffBoundPixels) { - for (int yi = 0; yi < image.Height; yi++) + var maxWidth = Math.Min(image.Width, (int)Mode.Width - x); + var maxHeight = Math.Min(image.Height, (int)Mode.Height - y); + for (int xi = 0; xi < maxWidth; xi++) { - color = Color.FromArgb(image.RawData[xi + (yi * image.Width)]); - DrawPoint(color, x + xi, y + yi); + for (int yi = 0; yi < maxHeight; yi++) + { + color = Color.FromArgb(image.RawData[xi + (yi * image.Width)]); + DrawPoint(color, x + xi, y + yi); + } + } + } + else + { + for (int xi = 0; xi < image.Width; xi++) + { + for (int yi = 0; yi < image.Height; yi++) + { + color = Color.FromArgb(image.RawData[xi + (yi * image.Width)]); + DrawPoint(color, x + xi, y + yi); + } } } } @@ -611,17 +629,33 @@ static int[] ScaleImage(Image image, int newWidth, int newHeight) /// The Y coordinate. /// The desired width to scale the image to before drawing. /// The desired height to scale the image to before drawing - public virtual void DrawImage(Image image, int x, int y, int w, int h) + public virtual void DrawImage(Image image, int x, int y, int w, int h, bool preventOffBoundPixels = true) { Color color; int[] pixels = ScaleImage(image, w, h); - for (int xi = 0; xi < w; xi++) + if (preventOffBoundPixels) + { + var maxWidth = Math.Min(w, (int)Mode.Width - x); + var maxHeight = Math.Min(h, (int)Mode.Height - y); + for (int xi = 0; xi < maxWidth; xi++) + { + for (int yi = 0; yi < maxHeight; yi++) + { + color = Color.FromArgb(pixels[xi + (yi * w)]); + DrawPoint(color, x + xi, y + yi); + } + } + } + else { - for (int yi = 0; yi < h; yi++) + for (int xi = 0; xi < w; xi++) { - color = Color.FromArgb(pixels[xi + (yi * w)]); - DrawPoint(color, x + xi, y + yi); + for (int yi = 0; yi < h; yi++) + { + color = Color.FromArgb(pixels[xi + (yi * w)]); + DrawPoint(color, x + xi, y + yi); + } } } } @@ -632,16 +666,31 @@ public virtual void DrawImage(Image image, int x, int y, int w, int h) /// The image to draw. /// The X coordinate. /// The Y coordinate. - public void DrawImageAlpha(Image image, int x, int y) + public void DrawImageAlpha(Image image, int x, int y, bool preventOffBoundPixels = true) { Color color; - - for (int xi = 0; xi < image.Width; xi++) + if (preventOffBoundPixels) { - for (int yi = 0; yi < image.Height; yi++) + var maxWidth = Math.Min(image.Width, (int)Mode.Width - x); + var maxHeight = Math.Min(image.Height, (int)Mode.Height - y); + for (int xi = 0; xi < maxWidth; xi++) { - color = Color.FromArgb(image.RawData[xi + (yi * image.Width)]); - DrawPoint(color, x + xi, y + yi); + for (int yi = 0; yi < maxHeight; yi++) + { + color = Color.FromArgb(image.RawData[xi + (yi * image.Width)]); + DrawPoint(color, x + xi, y + yi); + } + } + } + else + { + for (int xi = 0; xi < image.Width; xi++) + { + for (int yi = 0; yi < image.Height; yi++) + { + color = Color.FromArgb(image.RawData[xi + (yi * image.Width)]); + DrawPoint(color, x + xi, y + yi); + } } } } @@ -845,4 +894,4 @@ public static Color AlphaBlend(Color to, Color from, byte alpha) return Color.FromArgb(R, G, B); } } -} +} \ No newline at end of file diff --git a/source/Cosmos.System2/Graphics/SVGAIICanvas.cs b/source/Cosmos.System2/Graphics/SVGAIICanvas.cs index 256769c303..32a01de9fe 100644 --- a/source/Cosmos.System2/Graphics/SVGAIICanvas.cs +++ b/source/Cosmos.System2/Graphics/SVGAIICanvas.cs @@ -80,12 +80,17 @@ public override void DrawPoint(Color color, int x, int y) driver.SetPixel((uint)x, (uint)y, (uint)color.ToArgb()); } - public override void DrawFilledRectangle(Color color, int xStart, int yStart, int width, int height) + public override void DrawFilledRectangle(Color color, int xStart, int yStart, int width, int height, bool preventOffBoundPixels = true) { var argb = color.ToArgb(); var frameSize = (int)driver.FrameSize; + if(preventOffBoundPixels) + { + width = Math.Min(width, (int)mode.Width - xStart); + height = Math.Min(height, (int)mode.Height - yStart); + } + - // For now write directly into video memory, once _xSVGADriver.Fill will be faster it will have to be changed for (int i = yStart; i < yStart + height; i++) { driver.videoMemory.Fill(GetPointOffset(xStart, i) + (int)frameSize, width, argb); @@ -346,17 +351,29 @@ public override void DrawChar(char c, Font font, Color color, int x, int y) } } - public override void DrawImage(Image image, int x, int y) + public override void DrawImage(Image image, int x, int y, bool preventOffBoundPixels = true) { var width = (int)image.Width; var height = (int)image.Height; var frameSize = (int)driver.FrameSize; var data = image.RawData; + if (preventOffBoundPixels) + { + var maxWidth = Math.Min(width, (int)mode.Width - x); + var maxHeight = Math.Min(height, (int)mode.Height - y); - for (int i = 0; i < height; i++) + for (int i = 0; i < maxHeight; i++) + { + driver.videoMemory.Copy(GetPointOffset(x, y + i) + frameSize, data, i * width, maxWidth); + } + } + else { - driver.videoMemory.Copy(GetPointOffset(x, y + i) + frameSize, data, i * width, width); + for (int i = 0; i < height; i++) + { + driver.videoMemory.Copy(GetPointOffset(x, y + i) + frameSize, data, i * width, width); + } } } } -} +} \ No newline at end of file diff --git a/source/Cosmos.System2/Graphics/VBECanvas.cs b/source/Cosmos.System2/Graphics/VBECanvas.cs index bd507873f3..bb86dbf1be 100644 --- a/source/Cosmos.System2/Graphics/VBECanvas.cs +++ b/source/Cosmos.System2/Graphics/VBECanvas.cs @@ -248,9 +248,10 @@ public override void DrawArray(Color[] aColors, int aX, int aY, int aWidth, int } } - public override void DrawFilledRectangle(Color aColor, int aX, int aY, int aWidth, int aHeight) + public override void DrawFilledRectangle(Color aColor, int aX, int aY, int aWidth, int aHeight, bool preventOffBoundPixels = true) { // ClearVRAM clears one uint at a time. So we clear pixelwise not byte wise. That's why we divide by 32 and not 8. + if(preventOffBoundPixels) aWidth = (int)(Math.Min(aWidth, Mode.Width - aX) * (int)Mode.ColorDepth / 32); var color = aColor.ToArgb(); @@ -260,18 +261,30 @@ public override void DrawFilledRectangle(Color aColor, int aX, int aY, int aWidt } } - public override void DrawImage(Image aImage, int aX, int aY) + public override void DrawImage(Image aImage, int aX, int aY, bool preventOffBoundPixels = true) { var xBitmap = aImage.RawData; var xWidth = (int)aImage.Width; var xHeight = (int)aImage.Height; - - int xOffset = GetPointOffset(aX, aY); - - for (int i = 0; i < xHeight; i++) + if (preventOffBoundPixels) { - driver.CopyVRAM((i * (int)Mode.Width) + xOffset, xBitmap, i * xWidth, xWidth); + var maxWidth = Math.Min(xWidth, (int)mode.Width - aX); + var maxHeight = Math.Min(xHeight, (int)mode.Height - aY); + int xOffset = aY * (int)Mode.Width + aX; + for (int i = 0; i < maxHeight; i++) + { + driver.CopyVRAM((i * (int)Mode.Width) + xOffset, xBitmap, i * xWidth, maxWidth); + } } + else + { + int xOffset = aY * xHeight + aX; + for (int i = 0; i < Mode.Height; i++) + { + driver.CopyVRAM((i * (int)Mode.Width) + xOffset, xBitmap, i * xWidth, xWidth); + } + } + } #endregion diff --git a/source/Cosmos.System2/Graphics/VGACanvas.cs b/source/Cosmos.System2/Graphics/VGACanvas.cs index 50934b030a..2157e06dee 100644 --- a/source/Cosmos.System2/Graphics/VGACanvas.cs +++ b/source/Cosmos.System2/Graphics/VGACanvas.cs @@ -86,8 +86,13 @@ public override void Disable() } } - public override void DrawFilledRectangle(Color aColor, int aXStart, int aYStart, int aWidth, int aHeight) + public override void DrawFilledRectangle(Color aColor, int aXStart, int aYStart, int aWidth, int aHeight, bool preventOffBoundPixels = true) { + if (preventOffBoundPixels) + { + aWidth = Math.Min(aWidth, (int)Mode.Width - aXStart); + aHeight = Math.Min(aHeight, (int)Mode.Height - aYStart); + } driver.DrawFilledRectangle(aXStart, aYStart, aWidth, aHeight, driver.GetClosestColorInPalette(aColor)); }