diff options
author | TSR Berry <20988865+TSRBerry@users.noreply.github.com> | 2023-04-08 01:22:00 +0200 |
---|---|---|
committer | Mary <thog@protonmail.com> | 2023-04-27 23:51:14 +0200 |
commit | cee712105850ac3385cd0091a923438167433f9f (patch) | |
tree | 4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs | |
parent | cd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff) |
Move solution and projects to src
Diffstat (limited to 'Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs')
-rw-r--r-- | Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs | 606 |
1 files changed, 0 insertions, 606 deletions
diff --git a/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs b/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs deleted file mode 100644 index 9a91fa32..00000000 --- a/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs +++ /dev/null @@ -1,606 +0,0 @@ -using Ryujinx.HLE.Ui; -using Ryujinx.Memory; -using SixLabors.Fonts; -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.Drawing.Processing; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using System; -using System.Diagnostics; -using System.IO; -using System.Numerics; -using System.Reflection; -using System.Runtime.InteropServices; - -namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard -{ - /// <summary> - /// Base class that generates the graphics for the software keyboard applet during inline mode. - /// </summary> - internal class SoftwareKeyboardRendererBase - { - public const int TextBoxBlinkThreshold = 8; - - const string MessageText = "Please use the keyboard to input text"; - const string AcceptText = "Accept"; - const string CancelText = "Cancel"; - const string ControllerToggleText = "Toggle input"; - - private readonly object _bufferLock = new object(); - - private RenderingSurfaceInfo _surfaceInfo = null; - private Image<Argb32> _surface = null; - private byte[] _bufferData = null; - - private Image _ryujinxLogo = null; - private Image _padAcceptIcon = null; - private Image _padCancelIcon = null; - private Image _keyModeIcon = null; - - private float _textBoxOutlineWidth; - private float _padPressedPenWidth; - - private Color _textNormalColor; - private Color _textSelectedColor; - private Color _textOverCursorColor; - - private IBrush _panelBrush; - private IBrush _disabledBrush; - private IBrush _cursorBrush; - private IBrush _selectionBoxBrush; - - private Pen _textBoxOutlinePen; - private Pen _cursorPen; - private Pen _selectionBoxPen; - private Pen _padPressedPen; - - private int _inputTextFontSize; - private Font _messageFont; - private Font _inputTextFont; - private Font _labelsTextFont; - - private RectangleF _panelRectangle; - private Point _logoPosition; - private float _messagePositionY; - - public SoftwareKeyboardRendererBase(IHostUiTheme uiTheme) - { - int ryujinxLogoSize = 32; - - string ryujinxIconPath = "Ryujinx.HLE.HOS.Applets.SoftwareKeyboard.Resources.Logo_Ryujinx.png"; - _ryujinxLogo = LoadResource(Assembly.GetExecutingAssembly(), ryujinxIconPath, ryujinxLogoSize, ryujinxLogoSize); - - string padAcceptIconPath = "Ryujinx.HLE.HOS.Applets.SoftwareKeyboard.Resources.Icon_BtnA.png"; - string padCancelIconPath = "Ryujinx.HLE.HOS.Applets.SoftwareKeyboard.Resources.Icon_BtnB.png"; - string keyModeIconPath = "Ryujinx.HLE.HOS.Applets.SoftwareKeyboard.Resources.Icon_KeyF6.png"; - - _padAcceptIcon = LoadResource(Assembly.GetExecutingAssembly(), padAcceptIconPath , 0, 0); - _padCancelIcon = LoadResource(Assembly.GetExecutingAssembly(), padCancelIconPath , 0, 0); - _keyModeIcon = LoadResource(Assembly.GetExecutingAssembly(), keyModeIconPath , 0, 0); - - Color panelColor = ToColor(uiTheme.DefaultBackgroundColor, 255); - Color panelTransparentColor = ToColor(uiTheme.DefaultBackgroundColor, 150); - Color borderColor = ToColor(uiTheme.DefaultBorderColor); - Color selectionBackgroundColor = ToColor(uiTheme.SelectionBackgroundColor); - - _textNormalColor = ToColor(uiTheme.DefaultForegroundColor); - _textSelectedColor = ToColor(uiTheme.SelectionForegroundColor); - _textOverCursorColor = ToColor(uiTheme.DefaultForegroundColor, null, true); - - float cursorWidth = 2; - - _textBoxOutlineWidth = 2; - _padPressedPenWidth = 2; - - _panelBrush = new SolidBrush(panelColor); - _disabledBrush = new SolidBrush(panelTransparentColor); - _cursorBrush = new SolidBrush(_textNormalColor); - _selectionBoxBrush = new SolidBrush(selectionBackgroundColor); - - _textBoxOutlinePen = new Pen(borderColor, _textBoxOutlineWidth); - _cursorPen = new Pen(_textNormalColor, cursorWidth); - _selectionBoxPen = new Pen(selectionBackgroundColor, cursorWidth); - _padPressedPen = new Pen(borderColor, _padPressedPenWidth); - - _inputTextFontSize = 20; - - CreateFonts(uiTheme.FontFamily); - } - - private void CreateFonts(string uiThemeFontFamily) - { - // Try a list of fonts in case any of them is not available in the system. - - string[] availableFonts = new string[] - { - uiThemeFontFamily, - "Liberation Sans", - "FreeSans", - "DejaVu Sans", - "Lucida Grande" - }; - - foreach (string fontFamily in availableFonts) - { - try - { - _messageFont = SystemFonts.CreateFont(fontFamily, 26, FontStyle.Regular); - _inputTextFont = SystemFonts.CreateFont(fontFamily, _inputTextFontSize, FontStyle.Regular); - _labelsTextFont = SystemFonts.CreateFont(fontFamily, 24, FontStyle.Regular); - - return; - } - catch - { - } - } - - throw new Exception($"None of these fonts were found in the system: {String.Join(", ", availableFonts)}!"); - } - - private Color ToColor(ThemeColor color, byte? overrideAlpha = null, bool flipRgb = false) - { - var a = (byte)(color.A * 255); - var r = (byte)(color.R * 255); - var g = (byte)(color.G * 255); - var b = (byte)(color.B * 255); - - if (flipRgb) - { - r = (byte)(255 - r); - g = (byte)(255 - g); - b = (byte)(255 - b); - } - - return Color.FromRgba(r, g, b, overrideAlpha.GetValueOrDefault(a)); - } - - private Image LoadResource(Assembly assembly, string resourcePath, int newWidth, int newHeight) - { - Stream resourceStream = assembly.GetManifestResourceStream(resourcePath); - - return LoadResource(resourceStream, newWidth, newHeight); - } - - private Image LoadResource(Stream resourceStream, int newWidth, int newHeight) - { - Debug.Assert(resourceStream != null); - - var image = Image.Load(resourceStream); - - if (newHeight != 0 && newWidth != 0) - { - image.Mutate(x => x.Resize(newWidth, newHeight, KnownResamplers.Lanczos3)); - } - - return image; - } - - private void SetGraphicsOptions(IImageProcessingContext context) - { - context.GetGraphicsOptions().Antialias = true; - context.GetShapeGraphicsOptions().GraphicsOptions.Antialias = true; - } - - private void DrawImmutableElements() - { - if (_surface == null) - { - return; - } - - _surface.Mutate(context => - { - SetGraphicsOptions(context); - - context.Clear(Color.Transparent); - context.Fill(_panelBrush, _panelRectangle); - context.DrawImage(_ryujinxLogo, _logoPosition, 1); - - float halfWidth = _panelRectangle.Width / 2; - float buttonsY = _panelRectangle.Y + 185; - - PointF disableButtonPosition = new PointF(halfWidth + 180, buttonsY); - - DrawControllerToggle(context, disableButtonPosition); - }); - } - - public void DrawMutableElements(SoftwareKeyboardUiState state) - { - if (_surface == null) - { - return; - } - - _surface.Mutate(context => - { - var messageRectangle = MeasureString(MessageText, _messageFont); - float messagePositionX = (_panelRectangle.Width - messageRectangle.Width) / 2 - messageRectangle.X; - float messagePositionY = _messagePositionY - messageRectangle.Y; - var messagePosition = new PointF(messagePositionX, messagePositionY); - var messageBoundRectangle = new RectangleF(messagePositionX, messagePositionY, messageRectangle.Width, messageRectangle.Height); - - SetGraphicsOptions(context); - - context.Fill(_panelBrush, messageBoundRectangle); - - context.DrawText(MessageText, _messageFont, _textNormalColor, messagePosition); - - if (!state.TypingEnabled) - { - // Just draw a semi-transparent rectangle on top to fade the component with the background. - // TODO (caian): This will not work if one decides to add make background semi-transparent as well. - - context.Fill(_disabledBrush, messageBoundRectangle); - } - - DrawTextBox(context, state); - - float halfWidth = _panelRectangle.Width / 2; - float buttonsY = _panelRectangle.Y + 185; - - PointF acceptButtonPosition = new PointF(halfWidth - 180, buttonsY); - PointF cancelButtonPosition = new PointF(halfWidth , buttonsY); - PointF disableButtonPosition = new PointF(halfWidth + 180, buttonsY); - - DrawPadButton(context, acceptButtonPosition, _padAcceptIcon, AcceptText, state.AcceptPressed, state.ControllerEnabled); - DrawPadButton(context, cancelButtonPosition, _padCancelIcon, CancelText, state.CancelPressed, state.ControllerEnabled); - }); - } - - public void CreateSurface(RenderingSurfaceInfo surfaceInfo) - { - if (_surfaceInfo != null) - { - return; - } - - _surfaceInfo = surfaceInfo; - - Debug.Assert(_surfaceInfo.ColorFormat == Services.SurfaceFlinger.ColorFormat.A8B8G8R8); - - // Use the whole area of the image to draw, even the alignment, otherwise it may shear the final - // image if the pitch is different. - uint totalWidth = _surfaceInfo.Pitch / 4; - uint totalHeight = _surfaceInfo.Size / _surfaceInfo.Pitch; - - Debug.Assert(_surfaceInfo.Width <= totalWidth); - Debug.Assert(_surfaceInfo.Height <= totalHeight); - Debug.Assert(_surfaceInfo.Pitch * _surfaceInfo.Height <= _surfaceInfo.Size); - - _surface = new Image<Argb32>((int)totalWidth, (int)totalHeight); - - ComputeConstants(); - DrawImmutableElements(); - } - - private void ComputeConstants() - { - int totalWidth = (int)_surfaceInfo.Width; - int totalHeight = (int)_surfaceInfo.Height; - - int panelHeight = 240; - int panelPositionY = totalHeight - panelHeight; - - _panelRectangle = new RectangleF(0, panelPositionY, totalWidth, panelHeight); - - _messagePositionY = panelPositionY + 60; - - int logoPositionX = (totalWidth - _ryujinxLogo.Width) / 2; - int logoPositionY = panelPositionY + 18; - - _logoPosition = new Point(logoPositionX, logoPositionY); - } - private static RectangleF MeasureString(string text, Font font) - { - RendererOptions options = new RendererOptions(font); - - if (text == "") - { - FontRectangle emptyRectangle = TextMeasurer.Measure(" ", options); - - return new RectangleF(0, emptyRectangle.Y, 0, emptyRectangle.Height); - } - - FontRectangle rectangle = TextMeasurer.Measure(text, options); - - return new RectangleF(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); - } - - private static RectangleF MeasureString(ReadOnlySpan<char> text, Font font) - { - RendererOptions options = new RendererOptions(font); - - if (text == "") - { - FontRectangle emptyRectangle = TextMeasurer.Measure(" ", options); - return new RectangleF(0, emptyRectangle.Y, 0, emptyRectangle.Height); - } - - FontRectangle rectangle = TextMeasurer.Measure(text, options); - - return new RectangleF(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); - } - - private void DrawTextBox(IImageProcessingContext context, SoftwareKeyboardUiState state) - { - var inputTextRectangle = MeasureString(state.InputText, _inputTextFont); - - float boxWidth = (int)(Math.Max(300, inputTextRectangle.Width + inputTextRectangle.X + 8)); - float boxHeight = 32; - float boxY = _panelRectangle.Y + 110; - float boxX = (int)((_panelRectangle.Width - boxWidth) / 2); - - RectangleF boxRectangle = new RectangleF(boxX, boxY, boxWidth, boxHeight); - - RectangleF boundRectangle = new RectangleF(_panelRectangle.X, boxY - _textBoxOutlineWidth, - _panelRectangle.Width, boxHeight + 2 * _textBoxOutlineWidth); - - context.Fill(_panelBrush, boundRectangle); - - context.Draw(_textBoxOutlinePen, boxRectangle); - - float inputTextX = (_panelRectangle.Width - inputTextRectangle.Width) / 2 - inputTextRectangle.X; - float inputTextY = boxY + 5; - - var inputTextPosition = new PointF(inputTextX, inputTextY); - - context.DrawText(state.InputText, _inputTextFont, _textNormalColor, inputTextPosition); - - // Draw the cursor on top of the text and redraw the text with a different color if necessary. - - Color cursorTextColor; - IBrush cursorBrush; - Pen cursorPen; - - float cursorPositionYTop = inputTextY + 1; - float cursorPositionYBottom = cursorPositionYTop + _inputTextFontSize + 1; - float cursorPositionXLeft; - float cursorPositionXRight; - - bool cursorVisible = false; - - if (state.CursorBegin != state.CursorEnd) - { - Debug.Assert(state.InputText.Length > 0); - - cursorTextColor = _textSelectedColor; - cursorBrush = _selectionBoxBrush; - cursorPen = _selectionBoxPen; - - ReadOnlySpan<char> textUntilBegin = state.InputText.AsSpan(0, state.CursorBegin); - ReadOnlySpan<char> textUntilEnd = state.InputText.AsSpan(0, state.CursorEnd); - - var selectionBeginRectangle = MeasureString(textUntilBegin, _inputTextFont); - var selectionEndRectangle = MeasureString(textUntilEnd , _inputTextFont); - - cursorVisible = true; - cursorPositionXLeft = inputTextX + selectionBeginRectangle.Width + selectionBeginRectangle.X; - cursorPositionXRight = inputTextX + selectionEndRectangle.Width + selectionEndRectangle.X; - } - else - { - cursorTextColor = _textOverCursorColor; - cursorBrush = _cursorBrush; - cursorPen = _cursorPen; - - if (state.TextBoxBlinkCounter < TextBoxBlinkThreshold) - { - // Show the blinking cursor. - - int cursorBegin = Math.Min(state.InputText.Length, state.CursorBegin); - ReadOnlySpan<char> textUntilCursor = state.InputText.AsSpan(0, cursorBegin); - var cursorTextRectangle = MeasureString(textUntilCursor, _inputTextFont); - - cursorVisible = true; - cursorPositionXLeft = inputTextX + cursorTextRectangle.Width + cursorTextRectangle.X; - - if (state.OverwriteMode) - { - // The blinking cursor is in overwrite mode so it takes the size of a character. - - if (state.CursorBegin < state.InputText.Length) - { - textUntilCursor = state.InputText.AsSpan(0, cursorBegin + 1); - cursorTextRectangle = MeasureString(textUntilCursor, _inputTextFont); - cursorPositionXRight = inputTextX + cursorTextRectangle.Width + cursorTextRectangle.X; - } - else - { - cursorPositionXRight = cursorPositionXLeft + _inputTextFontSize / 2; - } - } - else - { - // The blinking cursor is in insert mode so it is only a line. - cursorPositionXRight = cursorPositionXLeft; - } - } - else - { - cursorPositionXLeft = inputTextX; - cursorPositionXRight = inputTextX; - } - } - - if (state.TypingEnabled && cursorVisible) - { - float cursorWidth = cursorPositionXRight - cursorPositionXLeft; - float cursorHeight = cursorPositionYBottom - cursorPositionYTop; - - if (cursorWidth == 0) - { - PointF[] points = new PointF[] - { - new PointF(cursorPositionXLeft, cursorPositionYTop), - new PointF(cursorPositionXLeft, cursorPositionYBottom), - }; - - context.DrawLines(cursorPen, points); - } - else - { - var cursorRectangle = new RectangleF(cursorPositionXLeft, cursorPositionYTop, cursorWidth, cursorHeight); - - context.Draw(cursorPen , cursorRectangle); - context.Fill(cursorBrush, cursorRectangle); - - Image<Argb32> textOverCursor = new Image<Argb32>((int)cursorRectangle.Width, (int)cursorRectangle.Height); - textOverCursor.Mutate(context => - { - var textRelativePosition = new PointF(inputTextPosition.X - cursorRectangle.X, inputTextPosition.Y - cursorRectangle.Y); - context.DrawText(state.InputText, _inputTextFont, cursorTextColor, textRelativePosition); - }); - - var cursorPosition = new Point((int)cursorRectangle.X, (int)cursorRectangle.Y); - context.DrawImage(textOverCursor, cursorPosition, 1); - } - } - else if (!state.TypingEnabled) - { - // Just draw a semi-transparent rectangle on top to fade the component with the background. - // TODO (caian): This will not work if one decides to add make background semi-transparent as well. - - context.Fill(_disabledBrush, boundRectangle); - } - } - - private void DrawPadButton(IImageProcessingContext context, PointF point, Image icon, string label, bool pressed, bool enabled) - { - // Use relative positions so we can center the the entire drawing later. - - float iconX = 0; - float iconY = 0; - float iconWidth = icon.Width; - float iconHeight = icon.Height; - - var labelRectangle = MeasureString(label, _labelsTextFont); - - float labelPositionX = iconWidth + 8 - labelRectangle.X; - float labelPositionY = 3; - - float fullWidth = labelPositionX + labelRectangle.Width + labelRectangle.X; - float fullHeight = iconHeight; - - // Convert all relative positions into absolute. - - float originX = (int)(point.X - fullWidth / 2); - float originY = (int)(point.Y - fullHeight / 2); - - iconX += originX; - iconY += originY; - - var iconPosition = new Point((int)iconX, (int)iconY); - var labelPosition = new PointF(labelPositionX + originX, labelPositionY + originY); - - var selectedRectangle = new RectangleF(originX - 2 * _padPressedPenWidth, originY - 2 * _padPressedPenWidth, - fullWidth + 4 * _padPressedPenWidth, fullHeight + 4 * _padPressedPenWidth); - - var boundRectangle = new RectangleF(originX, originY, fullWidth, fullHeight); - boundRectangle.Inflate(4 * _padPressedPenWidth, 4 * _padPressedPenWidth); - - context.Fill(_panelBrush, boundRectangle); - context.DrawImage(icon, iconPosition, 1); - context.DrawText(label, _labelsTextFont, _textNormalColor, labelPosition); - - if (enabled) - { - if (pressed) - { - context.Draw(_padPressedPen, selectedRectangle); - } - } - else - { - // Just draw a semi-transparent rectangle on top to fade the component with the background. - // TODO (caian): This will not work if one decides to add make background semi-transparent as well. - - context.Fill(_disabledBrush, boundRectangle); - } - } - - private void DrawControllerToggle(IImageProcessingContext context, PointF point) - { - var labelRectangle = MeasureString(ControllerToggleText, _labelsTextFont); - - // Use relative positions so we can center the the entire drawing later. - - float keyWidth = _keyModeIcon.Width; - float keyHeight = _keyModeIcon.Height; - - float labelPositionX = keyWidth + 8 - labelRectangle.X; - float labelPositionY = -labelRectangle.Y - 1; - - float keyX = 0; - float keyY = (int)((labelPositionY + labelRectangle.Height - keyHeight) / 2); - - float fullWidth = labelPositionX + labelRectangle.Width; - float fullHeight = Math.Max(labelPositionY + labelRectangle.Height, keyHeight); - - // Convert all relative positions into absolute. - - float originX = (int)(point.X - fullWidth / 2); - float originY = (int)(point.Y - fullHeight / 2); - - keyX += originX; - keyY += originY; - - var labelPosition = new PointF(labelPositionX + originX, labelPositionY + originY); - var overlayPosition = new Point((int)keyX, (int)keyY); - - context.DrawImage(_keyModeIcon, overlayPosition, 1); - context.DrawText(ControllerToggleText, _labelsTextFont, _textNormalColor, labelPosition); - } - - public void CopyImageToBuffer() - { - lock (_bufferLock) - { - if (_surface == null) - { - return; - } - - // Convert the pixel format used in the image to the one used in the Switch surface. - - if (!_surface.TryGetSinglePixelSpan(out Span<Argb32> pixels)) - { - return; - } - - _bufferData = MemoryMarshal.AsBytes(pixels).ToArray(); - Span<uint> dataConvert = MemoryMarshal.Cast<byte, uint>(_bufferData); - - Debug.Assert(_bufferData.Length == _surfaceInfo.Size); - - for (int i = 0; i < dataConvert.Length; i++) - { - dataConvert[i] = BitOperations.RotateRight(dataConvert[i], 8); - } - } - } - - public bool WriteBufferToMemory(IVirtualMemoryManager destination, ulong position) - { - lock (_bufferLock) - { - if (_bufferData == null) - { - return false; - } - - try - { - destination.Write(position, _bufferData); - } - catch - { - return false; - } - - return true; - } - } - } -} |