diff --git a/Launcher2/Drawing/Drawer2DExt.cs b/Launcher2/Drawing/Drawer2DExt.cs new file mode 100644 index 000000000..1c67a21c4 --- /dev/null +++ b/Launcher2/Drawing/Drawer2DExt.cs @@ -0,0 +1,108 @@ +// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT +using System; +using System.Drawing; +using ClassicalSharp; + +namespace Launcher { + public unsafe static class Drawer2DExt { + + public static void DrawScaledPixels( FastBitmap src, FastBitmap dst, Size scale, + Rectangle srcRect, Rectangle dstRect, byte scaleA, byte scaleB ) { + int srcWidth = srcRect.Width, dstWidth = dstRect.Width; + int srcHeight = srcRect.Height, dstHeight = dstRect.Height; + int srcX = srcRect.X, dstX = dstRect.X; + int srcY = srcRect.Y, dstY = dstRect.Y; + int scaleWidth = scale.Width, scaleHeight = scale.Height; + + for( int yy = 0; yy < dstHeight; yy++ ) { + int scaledY = (yy + dstY) * srcHeight / scaleHeight; + int* srcRow = src.GetRowPtr( srcY + (scaledY % srcHeight) ); + int* dstRow = dst.GetRowPtr( dstY + yy ); + byte rgbScale = (byte)Utils.Lerp( scaleA, scaleB, (float)yy / dstHeight ); + + for( int xx = 0; xx < dstWidth; xx++ ) { + int scaledX = (xx + dstX) * srcWidth / scaleWidth; + int pixel = srcRow[srcX + (scaledX % srcWidth)]; + + int col = pixel & ~0xFFFFFF; // keep a, but clear rgb + col |= ((pixel & 0xFF) * rgbScale / 255); + col |= (((pixel >> 8) & 0xFF) * rgbScale / 255) << 8; + col |= (((pixel >> 16) & 0xFF) * rgbScale / 255) << 16; + dstRow[dstX + xx] = col; + } + } + } + + public static void DrawTiledPixels( FastBitmap src, FastBitmap dst, + Rectangle srcRect, Rectangle dstRect ) { + int srcX = srcRect.X, srcWidth = srcRect.Width, srcHeight = srcRect.Height; + int x, y, width, height; + if( !ClampCoords( dst, dstRect, out x, out y, out width, out height ) ) + return; + + for( int yy = 0; yy < height; yy++ ) { + // srcY is always 0 so we don't need to add + int* srcRow = src.GetRowPtr( ((yy + y) % srcHeight) ); + int* dstRow = dst.GetRowPtr( y + yy ); + + for( int xx = 0; xx < width; xx++ ) + dstRow[x + xx] = srcRow[srcX + ((xx + x) % srcWidth)]; + } + } + + public static void Clear( FastBitmap dst, Rectangle dstRect, FastColour col ) { + int x, y, width, height; + if( !ClampCoords( dst, dstRect, out x, out y, out width, out height ) ) + return; + int pixel = col.ToArgb(); + + for( int yy = 0; yy < height; yy++ ) { + int* row = dst.GetRowPtr( y + yy ); + for( int xx = 0; xx < width; xx++ ) + row[x + xx] = pixel; + } + } + + + public static bool ClampCoords( FastBitmap bmp, Rectangle rect, out int x, + out int y, out int width, out int height ) { + width = rect.Width; height = rect.Height; + x = rect.X; y = rect.Y; + if( x >= bmp.Width || y >= bmp.Height ) return false; + + if( x < 0 ) { width += x; x = 0; } + if( y < 0 ) { height += y; y = 0; } + + width = Math.Min( x + width, bmp.Width ) - x; + height = Math.Min( y + height, bmp.< 0 Height ) - y; + return width > 0 && height > 0; + } + + + public static void DrawClippedText( ref DrawTextArgs args, IDrawer2D drawer, + int x, int y, int maxWidth ) { + Size size = drawer.MeasureSize( ref args ); + // No clipping necessary + if( size.Width <= maxWidth ) { drawer.DrawText( ref args, x, y ); return; } + DrawTextArgs copy = args; + copy.SkipPartsCheck = true; + + char[] chars = new char[args.Text.Length + 2]; + for( int i = 0; i < args.Text.Length; i++ ) + chars[i] = args.Text[i]; + chars[args.Text.Length] = '.'; + chars[args.Text.Length + 1] = '.'; + + for( int len = args.Text.Length; len > 0; len-- ) { + chars[len] = '.'; + if( chars[len - 1] == ' ' ) continue; + + copy.Text = new string( chars, 0, len + 2 ); + size = drawer.MeasureSize( ref copy ); + if( size.Width > maxWidth ) continue; + + drawer.DrawText( ref copy, x, y ); return; + } + } + } +} \ No newline at end of file diff --git a/Launcher2/Drawing/Gradient.cs b/Launcher2/Drawing/Gradient.cs new file mode 100644 index 000000000..dd8685763 --- /dev/null +++ b/Launcher2/Drawing/Gradient.cs @@ -0,0 +1,55 @@ +// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT +using System; +using System.Drawing; +using ClassicalSharp; + +namespace Launcher { + public unsafe static class Gradient { + + public static void Noise( FastBitmap dst, Rectangle dstRect, + FastColour col, int variation ) { + int x, y, width, height; + if( !Drawer2DExt.ClampCoords( dst, dstRect, out x, out y, + out width, out height ) ) return; + + const int alpha = 255 << 24; + for( int yy = 0; yy < height; yy++ ) { + int* row = dst.GetRowPtr( y + yy ); + for( int xx = 0; xx < width; xx++ ) { + int n = (x + xx) + (y + yy) * 57; + n = (n << 13) ^ n; + float noise = 1f - ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824f; + + int r = col.R + (int)(noise * variation); + r = r < 0 ? 0 : (r > 255 ? 255 : r); + int g = col.G + (int)(noise * variation); + g = g < 0 ? 0 : (g > 255 ? 255 : g); + int b = col.B + (int)(noise * variation); + b = b < 0 ? 0 : (b > 255 ? 255 : b); + row[x + xx] = alpha | (r << 16) | (g << 8) | b; + } + } + } + + public static void Vertical( FastBitmap dst, Rectangle dstRect, + FastColour a, FastColour b ) { + int x, y, width, height; + if( !Drawer2DExt.ClampCoords( dst, dstRect, out x, out y, + out width, out height ) ) return; + FastColour c = a; + + for( int yy = 0; yy < height; yy++ ) { + int* row = dst.GetRowPtr( y + yy ); + float t = (float)yy / height; + + c.R = (byte)Utils.Lerp( a.R, b.R, t ); + c.G = (byte)Utils.Lerp( a.G, b.G, t ); + c.B = (byte)Utils.Lerp( a.B, b.B, t ); + int pixel = c.ToArgb(); + + for( int xx = 0; xx < width; xx++ ) + row[x + xx] = pixel; + } + } + } +} \ No newline at end of file diff --git a/Launcher2/Gui/Drawer/OSXDrawer.cs b/Launcher2/Drawing/Platform/OSXDrawer.cs similarity index 100% rename from Launcher2/Gui/Drawer/OSXDrawer.cs rename to Launcher2/Drawing/Platform/OSXDrawer.cs diff --git a/Launcher2/Gui/Drawer/PlatformDrawer.cs b/Launcher2/Drawing/Platform/PlatformDrawer.cs similarity index 90% rename from Launcher2/Gui/Drawer/PlatformDrawer.cs rename to Launcher2/Drawing/Platform/PlatformDrawer.cs index 7371f37ae..ac8889f19 100644 --- a/Launcher2/Gui/Drawer/PlatformDrawer.cs +++ b/Launcher2/Drawing/Platform/PlatformDrawer.cs @@ -26,6 +26,8 @@ namespace Launcher { public abstract void Redraw( Bitmap framebuffer ); /// Redraws a portion of the framebuffer to the window. + /// This is only a hint, the entire framebuffer may still be + /// redrawn on some platforms. public virtual void Redraw( Bitmap framebuffer, Rectangle rec ) { Redraw( framebuffer ); } diff --git a/Launcher2/Gui/Drawer/WindowsDrawer.cs b/Launcher2/Drawing/Platform/WindowsDrawer.cs similarity index 100% rename from Launcher2/Gui/Drawer/WindowsDrawer.cs rename to Launcher2/Drawing/Platform/WindowsDrawer.cs diff --git a/Launcher2/Gui/Drawer/X11Drawer.cs b/Launcher2/Drawing/Platform/X11Drawer.cs similarity index 100% rename from Launcher2/Gui/Drawer/X11Drawer.cs rename to Launcher2/Drawing/Platform/X11Drawer.cs diff --git a/Launcher2/Gui/Drawer2DExt.cs b/Launcher2/Gui/Drawer2DExt.cs deleted file mode 100644 index 9268cef96..000000000 --- a/Launcher2/Gui/Drawer2DExt.cs +++ /dev/null @@ -1,156 +0,0 @@ -// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT -using System; -using System.Drawing; -using ClassicalSharp; - -namespace Launcher { - public unsafe static class Drawer2DExt { - - public static void DrawScaledPixels( FastBitmap src, FastBitmap dst, Size scale, - Rectangle srcRect, Rectangle dstRect, byte scaleA, byte scaleB ) { - int srcWidth = srcRect.Width, dstWidth = dstRect.Width; - int srcHeight = srcRect.Height, dstHeight = dstRect.Height; - int srcX = srcRect.X, dstX = dstRect.X; - int srcY = srcRect.Y, dstY = dstRect.Y; - int scaleWidth = scale.Width, scaleHeight = scale.Height; - - for( int yy = 0; yy < dstHeight; yy++ ) { - int scaledY = (yy + dstY) * srcHeight / scaleHeight; - int* srcRow = src.GetRowPtr( srcY + (scaledY % srcHeight) ); - int* dstRow = dst.GetRowPtr( dstY + yy ); - byte rgbScale = (byte)Utils.Lerp( scaleA, scaleB, (float)yy / dstHeight ); - - for( int xx = 0; xx < dstWidth; xx++ ) { - int scaledX = (xx + dstX) * srcWidth / scaleWidth; - int pixel = srcRow[srcX + (scaledX % srcWidth)]; - - int col = pixel & ~0xFFFFFF; // keep a, but clear rgb - col |= ((pixel & 0xFF) * rgbScale / 255); - col |= (((pixel >> 8) & 0xFF) * rgbScale / 255) << 8; - col |= (((pixel >> 16) & 0xFF) * rgbScale / 255) << 16; - dstRow[dstX + xx] = col; - } - } - } - - public static void DrawTiledPixels( FastBitmap src, FastBitmap dst, - Rectangle srcRect, Rectangle dstRect ) { - int srcX = srcRect.X, srcWidth = srcRect.Width, srcHeight = srcRect.Height; - int dstX, dstY, dstWidth, dstHeight; - if( !CheckCoords( dst, dstRect, out dstX, out dstY, out dstWidth, out dstHeight ) ) - return; - - for( int yy = 0; yy < dstHeight; yy++ ) { - // srcY is always 0 so we don't need to add - int* srcRow = src.GetRowPtr( ((yy + dstY) % srcHeight) ); - int* dstRow = dst.GetRowPtr( dstY + yy ); - - for( int xx = 0; xx < dstWidth; xx++ ) - dstRow[dstX + xx] = srcRow[srcX + ((xx + dstX) % srcWidth)]; - } - } - - public static void DrawNoise( FastBitmap dst, Rectangle dstRect, - FastColour col, int variation ) { - int dstX, dstY, dstWidth, dstHeight; - if( !CheckCoords( dst, dstRect, out dstX, out dstY, out dstWidth, out dstHeight ) ) - return; - const int alpha = 255 << 24; - for( int yy = 0; yy < dstHeight; yy++ ) { - int* row = dst.GetRowPtr( dstY + yy ); - for( int xx = 0; xx < dstWidth; xx++ ) { - int n = (dstX + xx) + (dstY + yy) * 57; - n = (n << 13) ^ n; - float noise = 1f - ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824f; - - int r = col.R + (int)(noise * variation); - r = r < 0 ? 0 : (r > 255 ? 255 : r); - int g = col.G + (int)(noise * variation); - g = g < 0 ? 0 : (g > 255 ? 255 : g); - int b = col.B + (int)(noise * variation); - b = b < 0 ? 0 : (b > 255 ? 255 : b); - row[dstX + xx] = alpha | (r << 16) | (g << 8) | b; - } - } - } - - public static void Clear( FastBitmap dst, Rectangle dstRect, - FastColour col ) { - int dstX, dstY, dstWidth, dstHeight; - if( !CheckCoords( dst, dstRect, out dstX, out dstY, out dstWidth, out dstHeight ) ) - return; - int pixel = col.ToArgb(); - - for( int yy = 0; yy < dstHeight; yy++ ) { - int* row = dst.GetRowPtr( dstY + yy ); - for( int xx = 0; xx < dstWidth; xx++ ) - row[dstX + xx] = pixel; - } - } - - public static void DrawGradient( FastBitmap dst, Rectangle dstRect, - FastColour a, FastColour b ) { - int dstX, dstY, dstWidth, dstHeight; - if( !CheckCoords( dst, dstRect, out dstX, out dstY, out dstWidth, out dstHeight ) ) - return; - FastColour c = a; - - for( int yy = 0; yy < dstHeight; yy++ ) { - int* row = dst.GetRowPtr( dstY + yy ); - float t = (float)yy / dstHeight; - - c.R = (byte)Utils.Lerp( a.R, b.R, t ); - c.G = (byte)Utils.Lerp( a.G, b.G, t ); - c.B = (byte)Utils.Lerp( a.B, b.B, t ); - int pixel = c.ToArgb(); - - for( int xx = 0; xx < dstWidth; xx++ ) - row[dstX + xx] = pixel; - } - } - - - static bool CheckCoords( FastBitmap dst, Rectangle dstRect, out int dstX, - out int dstY, out int dstWidth, out int dstHeight ) { - dstWidth = dstRect.Width; dstHeight = dstRect.Height; - dstX = dstRect.X; dstY = dstRect.Y; - if( dstX >= dst.Width || dstY >= dst.Height ) return false; - - if( dstX < 0 ) { dstWidth += dstX; dstX = 0; } - if( dstY < 0 ) { dstHeight += dstY; dstY = 0; } - - dstWidth = Math.Min( dstX + dstWidth, dst.Width ) - dstX; - dstHeight = Math.Min( dstY + dstHeight, dst.Height ) - dstY; - if( dstWidth < 0 || dstHeight < 0 ) return false; - return true; - } - - - - public static void DrawClippedText( ref DrawTextArgs args, IDrawer2D drawer, - int x, int y, int maxWidth ) { - Size size = drawer.MeasureSize( ref args ); - // No clipping necessary - if( size.Width <= maxWidth ) { drawer.DrawText( ref args, x, y ); return; } - DrawTextArgs copy = args; - copy.SkipPartsCheck = true; - - char[] chars = new char[args.Text.Length + 2]; - for( int i = 0; i < args.Text.Length; i++ ) - chars[i] = args.Text[i]; - chars[args.Text.Length] = '.'; - chars[args.Text.Length + 1] = '.'; - - for( int len = args.Text.Length; len > 0; len-- ) { - chars[len] = '.'; - if( chars[len - 1] == ' ' ) continue; - - copy.Text = new string( chars, 0, len + 2 ); - size = drawer.MeasureSize( ref copy ); - if( size.Width > maxWidth ) continue; - - drawer.DrawText( ref copy, x, y ); return; - } - } - } -} \ No newline at end of file diff --git a/Launcher2/Gui/Widgets/LauncherButtonWidget.cs b/Launcher2/Gui/Widgets/LauncherButtonWidget.cs index e3b0202b4..bfbb16a73 100644 --- a/Launcher2/Gui/Widgets/LauncherButtonWidget.cs +++ b/Launcher2/Gui/Widgets/LauncherButtonWidget.cs @@ -73,12 +73,11 @@ namespace Launcher.Gui.Widgets { Rectangle rect = new Rectangle( X + border, Y + border, Width - border * 2, Height - border * 2 ); if( Window.ClassicBackground ) { FastColour foreCol = Active ? new FastColour( 126, 136, 191 ) : new FastColour( 111, 111, 111 ); - Drawer2DExt.DrawNoise( dst, rect, foreCol, 8 ); + Gradient.Noise( dst, rect, foreCol, 8 ); } else { FastColour foreCol = Active ? LauncherSkin.ButtonForeActiveCol : LauncherSkin.ButtonForeCol; - FastColour top = Expand( foreCol, 8 ); - FastColour bottom = Expand( foreCol, -8 ); - Drawer2DExt.DrawGradient( dst, rect, top, bottom ); + FastColour top = Expand( foreCol, 8 ), bottom = Expand( foreCol, -8 ); + Gradient.Vertical( dst, rect, top, bottom ); } } diff --git a/Launcher2/Launcher2.csproj b/Launcher2/Launcher2.csproj index c139c211b..c253ed4b1 100644 --- a/Launcher2/Launcher2.csproj +++ b/Launcher2/Launcher2.csproj @@ -57,11 +57,12 @@ - - - - - + + + + + + @@ -127,11 +128,12 @@ - + + diff --git a/Launcher2/LauncherWindow.Background.cs b/Launcher2/LauncherWindow.Background.cs index 1de1cd35b..939f63e81 100644 --- a/Launcher2/LauncherWindow.Background.cs +++ b/Launcher2/LauncherWindow.Background.cs @@ -131,7 +131,7 @@ namespace Launcher { ClearTile( x, y, width, height, 0, dst ); } else { FastColour col = LauncherSkin.BackgroundCol; - Drawer2DExt.DrawNoise( dst, new Rectangle( x, y, width, height ), col, 6 ); + Gradient.Noise( dst, new Rectangle( x, y, width, height ), col, 6 ); } }