Exemplo n.º 1
0
        public static void PrintHeader(ICellSurface target, SadConsole.UI.Colors themeColors, Point position, int totalWidth, string text)
        {
            totalWidth = totalWidth - text.Length - 3;

            if (totalWidth < 0)
            {
                throw new Exception("Header text too small");
            }

            var lineText = ColoredString.FromGradient(
                new Gradient(
                    new[] { themeColors.White, themeColors.White, themeColors.Gray, themeColors.Gray, themeColors.GrayDark, themeColors.GrayDark },
                    new[] { 0f, 0.3f, 0.31f, 0.65f, 0.66f, 1f }),
                new string((char)196, totalWidth));

            target.Print(position.X, position.Y, new ColoredString(new ColoredGlyph(themeColors.White, Color.Transparent, 196))
                         + new ColoredString(new ColoredGlyph(themeColors.Cyan, Color.Transparent, 254))
                         + new ColoredString(text, themeColors.Title, Color.Transparent)
                         + new ColoredString(new ColoredGlyph(themeColors.Cyan, Color.Transparent, 254))
                         );

            var targetPosition = Point.FromIndex(position.ToIndex(target.Width) + text.Length + 3, target.Width);

            target.Print(targetPosition.X, targetPosition.Y, lineText);
        }
Exemplo n.º 2
0
 /// <summary>
 /// Creates a new console using the existing surface.
 /// </summary>
 /// <param name="surface">The surface.</param>
 /// <param name="font">The font to use with the surface.</param>
 /// <param name="fontSize">The font size.</param>
 public Console(ICellSurface surface, IFont font = null, Point?fontSize = null) : base(surface, font, fontSize)
 {
     Cursor = new Cursor()
     {
         IsVisible = false, IsEnabled = false
     };
     SadComponents.Add(Cursor);
     UseKeyboard = Settings.DefaultConsoleUseKeyboard;
 }
Exemplo n.º 3
0
        public BorderComponent(int[] connectedLineStyle, Color foreground, Color background)
        {
            if (!ICellSurface.ValidateLineStyle(connectedLineStyle))
            {
                throw new ArgumentException("The connected line array is invalid.", nameof(connectedLineStyle));
            }

            _borderGlyphs    = connectedLineStyle;
            _borderCellStyle = new ColoredGlyph(foreground, background);
        }
Exemplo n.º 4
0
        private ParseCommandBase CustomParseCommand(string command, string parameters, ColoredGlyph[] glyphString,
                                                    ICellSurface surface, ParseCommandStacks commandStacks)
        {
            switch (command)
            {
            case "t":
                return(new ParseCommandRetext(parameters));

            default:
                return(null);;
            }
        }
        /// <inheritdoc />
        public override void Build(ref ColoredString.ColoredGlyphEffect glyphState, ColoredString.ColoredGlyphEffect[] glyphString, int surfaceIndex,
                                   ICellSurface surface, ref int stringIndex, string processedString, ParseCommandStacks commandStack)
        {
            glyphState.Mirror = Mirror;

            if (_counter != -1)
            {
                _counter--;

                if (_counter == 0)
                {
                    commandStack.RemoveSafe(this);
                }
            }
        }
Exemplo n.º 6
0
        /// <inheritdoc />
        public override void Build(ref ColoredString.ColoredGlyphEffect glyphState, ColoredString.ColoredGlyphEffect[] glyphString, int surfaceIndex,
                                   ICellSurface surface, ref int stringIndex, string processedString, ParseCommandStacks commandStack)
        {
            if (CommandType == CommandTypes.Background)
            {
                glyphState.Background = GradientString[Length - _counter].Foreground;
            }
            else
            {
                glyphState.Foreground = GradientString[Length - _counter].Foreground;
            }

            _counter--;

            if (_counter == 0)
            {
                commandStack.RemoveSafe(this);
            }
        }
Exemplo n.º 7
0
        public void Surface_Equals(ICellSurface surface1, ICellSurface surface2)
        {
            Assert.AreEqual(surface1.View, surface2.View);
            Assert.AreEqual(surface1.Area, surface2.Area);
            Assert.AreEqual(surface1.Count, surface2.Count);
            Assert.AreEqual(surface1.DefaultBackground, surface2.DefaultBackground);
            Assert.AreEqual(surface1.DefaultForeground, surface2.DefaultForeground);
            Assert.AreEqual(surface1.DefaultGlyph, surface2.DefaultGlyph);
            Assert.AreEqual(surface1.IsScrollable, surface2.IsScrollable);
            Assert.AreEqual(surface1.TimesShiftedDown, surface2.TimesShiftedDown);
            Assert.AreEqual(surface1.TimesShiftedLeft, surface2.TimesShiftedLeft);
            Assert.AreEqual(surface1.TimesShiftedRight, surface2.TimesShiftedRight);
            Assert.AreEqual(surface1.TimesShiftedUp, surface2.TimesShiftedUp);
            Assert.AreEqual(surface1.UsePrintProcessor, surface2.UsePrintProcessor);

            for (int i = 0; i < surface1.Count; i++)
            {
                Assert.IsTrue(surface1[i].Matches(surface2[i]));
            }
        }
Exemplo n.º 8
0
        /// <inheritdoc />
        public override void Build(ref ColoredString.ColoredGlyphEffect glyphState, ColoredString.ColoredGlyphEffect[] glyphString, int surfaceIndex,
                                   ICellSurface surface, ref int stringIndex, string processedString, ParseCommandStacks commandStack)
        {
            if (RandomGlyph)
            {
                glyphState.GlyphCharacter = (char)SadConsole.GameHost.Instance.Random.Next(RandomGlyphMin, RandomGlyphMax);
            }
            else
            {
                glyphState.GlyphCharacter = Glyph;
            }

            if (_counter != -1)
            {
                _counter--;
            }

            if (_counter == 0)
            {
                commandStack.RemoveSafe(this);
            }
        }
Exemplo n.º 9
0
 public DrawCallSurface(ICellSurface surface, Point position)
 {
     _surface  = surface;
     _position = position;
 }
Exemplo n.º 10
0
        /// <summary>
        /// Creates a colored string by parsing commands embedded in the string.
        /// </summary>
        /// <param name="value">The string to parse.</param>
        /// <param name="surfaceIndex">Index of where this string will be printed.</param>
        /// <param name="surface">The surface the string will be printed to.</param>
        /// <param name="initialBehaviors">Any initial defaults.</param>
        /// <returns>The finalized string.</returns>
        public static ColoredString Parse(string value, int surfaceIndex = -1, ICellSurface surface = null, ParseCommandStacks initialBehaviors = null)
        {
            ParseCommandStacks        commandStacks = initialBehaviors ?? new ParseCommandStacks();
            List <ColoredGlyphEffect> glyphs        = new List <ColoredGlyphEffect>(value.Length);

            for (int i = 0; i < value.Length; i++)
            {
                ColoredGlyphEffect[] existingGlyphs = glyphs.ToArray();

                if (value[i] == '`' && i + 1 < value.Length && value[i + 1] == '[')
                {
                    continue;
                }

                if (value[i] == '[' && (i == 0 || value[i - 1] != '`'))
                {
                    try
                    {
                        if (i + 4 < value.Length && value[i + 1] == 'c' && value[i + 2] == ':' && value.IndexOf(']', i + 2) != -1)
                        {
                            int    commandExitIndex = value.IndexOf(']', i + 2);
                            string command          = value.Substring(i + 3, commandExitIndex - (i + 3));
                            string commandParams    = "";

                            if (command.Contains(" "))
                            {
                                string[] commandSections = command.Split(new char[] { ' ' }, 2);
                                command       = commandSections[0].ToLower();
                                commandParams = commandSections[1];
                            }

                            // Check for custom command
                            ParseCommandBase commandObject = CustomProcessor?.Invoke(command, commandParams, existingGlyphs, surface, commandStacks);

                            // No custom command found, run build in ones
                            if (commandObject == null)
                            {
                                switch (command)
                                {
                                case "recolor":
                                case "r":
                                    commandObject = new ParseCommandRecolor(commandParams);
                                    break;

                                case "mirror":
                                case "m":
                                    commandObject = new ParseCommandMirror(commandParams);
                                    break;

                                case "undo":
                                case "u":
                                    commandObject = new ParseCommandUndo(commandParams, commandStacks);
                                    break;

                                case "grad":
                                case "g":
                                    commandObject = new ParseCommandGradient(commandParams);
                                    break;

                                case "blink":
                                case "b":
                                    commandObject = new ParseCommandBlink(commandParams, existingGlyphs, commandStacks, surface);
                                    break;

                                case "sglyph":
                                case "sg":
                                    commandObject = new ParseCommandSetGlyph(commandParams);
                                    break;

                                case "ceffect":
                                case "ce":
                                    commandObject = new ParseCommandClearEffect(commandParams, commandStacks);
                                    break;

                                default:
                                    break;
                                }
                            }

                            if (commandObject != null && commandObject.CommandType != CommandTypes.Invalid)
                            {
                                commandStacks.AddSafe(commandObject);

                                i = commandExitIndex;
                                continue;
                            }
                        }
                    }
                    catch (Exception e1)
                    {
#if DEBUG
                        // Helps track down parsing bugs
                        System.Diagnostics.Debugger.Break();
#endif
                    }
                }

                int fixedSurfaceIndex;

                if (surfaceIndex == -1 || surface == null)
                {
                    fixedSurfaceIndex = -1;
                }
                else
                {
                    fixedSurfaceIndex = i + surfaceIndex < surface.Count ? i + surfaceIndex : -1;
                }

                ColoredGlyphEffect newGlyph;

                if (fixedSurfaceIndex != -1)
                {
                    newGlyph = new ColoredGlyphEffect();
                    surface[i + surfaceIndex].CopyAppearanceTo(newGlyph);
                    newGlyph.Glyph = value[i];
                }
                else
                {
                    newGlyph = new ColoredGlyphEffect()
                    {
                        Glyph = value[i]
                    };
                }


                // Foreground
                if (commandStacks.Foreground.Count != 0)
                {
                    commandStacks.Foreground.Peek().Build(ref newGlyph, existingGlyphs, fixedSurfaceIndex, surface, ref i, value, commandStacks);
                }

                // Background
                if (commandStacks.Background.Count != 0)
                {
                    commandStacks.Background.Peek().Build(ref newGlyph, existingGlyphs, fixedSurfaceIndex, surface, ref i, value, commandStacks);
                }

                // Glyph
                if (commandStacks.Glyph.Count != 0)
                {
                    commandStacks.Glyph.Peek().Build(ref newGlyph, existingGlyphs, fixedSurfaceIndex, surface, ref i, value, commandStacks);
                }

                // Mirror
                if (commandStacks.Mirror.Count != 0)
                {
                    commandStacks.Mirror.Peek().Build(ref newGlyph, existingGlyphs, fixedSurfaceIndex, surface, ref i, value, commandStacks);
                }

                // Effect
                if (commandStacks.Effect.Count != 0)
                {
                    commandStacks.Effect.Peek().Build(ref newGlyph, existingGlyphs, fixedSurfaceIndex, surface, ref i, value, commandStacks);
                }

                glyphs.Add(newGlyph);
            }

            return(new ColoredString(glyphs.ToArray())
            {
                IgnoreEffect = !commandStacks.TurnOnEffects
            });
        }
Exemplo n.º 11
0
 /// <summary>
 /// Builds a glyph.
 /// </summary>
 /// <param name="glyphState">The current glyph being built.</param>
 /// <param name="glyphString">The current string of glyphs that has been processed until now.</param>
 /// <param name="surfaceIndex">Where on the surface this flyph will appear.</param>
 /// <param name="surface">The surface associated with the glyph.</param>
 /// <param name="stringIndex">Where in the original string this glyph is from.</param>
 /// <param name="processedString">The entire string being processed.</param>
 /// <param name="commandStack">The state of commands.</param>
 public abstract void Build(ref ColoredString.ColoredGlyphEffect glyphState, ColoredString.ColoredGlyphEffect[] glyphString, int surfaceIndex,
                            ICellSurface surface, ref int stringIndex, string processedString, ParseCommandStacks commandStack);
Exemplo n.º 12
0
 /// <summary>
 /// Creates a new effects manager associated with a text surface.
 /// </summary>
 /// <param name="surface">Text surface to manage.</param>
 public EffectsManager(ICellSurface surface)
 {
     _effects        = new Dictionary <ICellEffect, ColoredGlyphEffectData>(20);
     _effectCells    = new Dictionary <int, ColoredGlyphEffectData>(50);
     _backingSurface = surface;
 }
Exemplo n.º 13
0
        /// <summary>
        /// Converts a texture's pixels to the specified <see cref="ICellSurface"/>.
        /// </summary>
        /// <param name="image">The texture to process.</param>
        /// <param name="surface">The surface to draw on.</param>
        /// <param name="cachedColorArray">A buffer holding the color information from the texture.</param>
        /// <param name="font">The font used with the cell surface.</param>
        /// <param name="fontSize">The size of the font.</param>
        /// <param name="blockMode"><see langword="true"/> to indicate the result should use block characters instead of text characters.</param>
        public static void ToSurface(this Texture2D image, ICellSurface surface, Color[] cachedColorArray, IFont font, SadRogue.Primitives.Point fontSize, bool blockMode = false)
        {
            int imageWidth  = image.Width;
            int imageHeight = image.Height;

            image.GetData <Color>(cachedColorArray);

            surface.Clear();
            global::System.Threading.Tasks.Parallel.For(0, imageHeight / fontSize.Y, (h) =>
                                                        //for (int h = 0; h < imageHeight / fontSize.Y; h++)
            {
                int startY = (h * fontSize.Y);
                //System.Threading.Tasks.Parallel.For(0, imageWidth / fontSize.X, (w) =>
                for (int w = 0; w < imageWidth / fontSize.X; w++)
                {
                    int startX = (w * fontSize.X);

                    float allR = 0;
                    float allG = 0;
                    float allB = 0;

                    for (int y = 0; y < fontSize.Y; y++)
                    {
                        for (int x = 0; x < fontSize.X; x++)
                        {
                            int cY = y + startY;
                            int cX = x + startX;

                            Color color = cachedColorArray[cY * imageWidth + cX];

                            allR += color.R;
                            allG += color.G;
                            allB += color.B;
                        }
                    }

                    byte sr = (byte)(allR / (fontSize.X * fontSize.Y));
                    byte sg = (byte)(allG / (fontSize.X * fontSize.Y));
                    byte sb = (byte)(allB / (fontSize.X * fontSize.Y));

                    var newColor = new SadRogue.Primitives.Color(sr, sg, sb);

                    float sbri = newColor.GetBrightness() * 255;

                    if (blockMode)
                    {
                        if (sbri > 204)
                        {
                            surface.SetGlyph(w, h, 219, newColor); //█
                        }
                        else if (sbri > 152)
                        {
                            surface.SetGlyph(w, h, 178, newColor); //▓
                        }
                        else if (sbri > 100)
                        {
                            surface.SetGlyph(w, h, 177, newColor); //▒
                        }
                        else if (sbri > 48)
                        {
                            surface.SetGlyph(w, h, 176, newColor); //░
                        }
                    }
                    else
                    {
                        if (sbri > 230)
                        {
                            surface.SetGlyph(w, h, '#', newColor);
                        }
                        else if (sbri > 207)
                        {
                            surface.SetGlyph(w, h, '&', newColor);
                        }
                        else if (sbri > 184)
                        {
                            surface.SetGlyph(w, h, '$', newColor);
                        }
                        else if (sbri > 161)
                        {
                            surface.SetGlyph(w, h, 'X', newColor);
                        }
                        else if (sbri > 138)
                        {
                            surface.SetGlyph(w, h, 'x', newColor);
                        }
                        else if (sbri > 115)
                        {
                            surface.SetGlyph(w, h, '=', newColor);
                        }
                        else if (sbri > 92)
                        {
                            surface.SetGlyph(w, h, '+', newColor);
                        }
                        else if (sbri > 69)
                        {
                            surface.SetGlyph(w, h, ';', newColor);
                        }
                        else if (sbri > 46)
                        {
                            surface.SetGlyph(w, h, ':', newColor);
                        }
                        else if (sbri > 23)
                        {
                            surface.SetGlyph(w, h, '.', newColor);
                        }
                    }
                }
            }
                                                        );
        }
 public ICellSurface ToSurface(TextureConvertMode mode, int surfaceWidth, int surfaceHeight, TextureConvertBackgroundStyle backgroundStyle = TextureConvertBackgroundStyle.Pixel, TextureConvertForegroundStyle foregroundStyle = TextureConvertForegroundStyle.Block, Color[] cachedColorArray = null, ICellSurface cachedSurface = null) => throw new NotImplementedException();
Exemplo n.º 15
0
        /// <summary>
        /// Creates a new instance of this command.
        /// </summary>
        /// <param name="parameters">The string to parse for parameters.</param>
        /// <param name="glyphString">The string that has been processed so far.</param>
        /// <param name="commandStack">The current commands for the string.</param>
        /// <param name="surface">The surface hosting the string.</param>
        public ParseCommandBlink(string parameters, ColoredGlyph[] glyphString, ParseCommandStacks commandStack, ICellSurface surface)
        {
            string[] parametersArray = parameters.Split(':');

            if (parametersArray.Length == 2)
            {
                Speed = double.Parse(parametersArray[1], CultureInfo.InvariantCulture);
            }

            if (parametersArray.Length >= 1 && parametersArray[0] != "")
            {
                _counter = int.Parse(parametersArray[0], CultureInfo.InvariantCulture);
            }
            else
            {
                _counter = -1;
            }

            // Try sync with surface editor
            if (surface != null)
            {
                IEnumerable <Effects.ICellEffect> effects = surface.Effects.GetEffects();
                if (effects != null)
                {
                    var existingBlinks = new List <Effects.ICellEffect>(effects);

                    foreach (Effects.ICellEffect item in existingBlinks)
                    {
                        if (item is CustomBlinkEffect)
                        {
                            if (Speed == ((CustomBlinkEffect)item).BlinkSpeed)
                            {
                                _blinkEffect = (CustomBlinkEffect)item;
                            }

                            break;
                        }
                    }
                }
            }

            // Failed, look within this parse for existing
            if (_blinkEffect == null)
            {
                foreach (ColoredString.ColoredGlyphEffect item in glyphString)
                {
                    if (item.Effect != null && item.Effect is CustomBlinkEffect)
                    {
                        if (Speed == ((CustomBlinkEffect)item.Effect).BlinkSpeed)
                        {
                            _blinkEffect = (CustomBlinkEffect)item.Effect;
                        }
                    }
                }
            }


            if (_blinkEffect == null)
            {
                _blinkEffect = new CustomBlinkEffect()
                {
                    BlinkSpeed = Speed
                }
            }
            ;

            commandStack.TurnOnEffects = true;

            // No exceptions, set the type
            CommandType = CommandTypes.Effect;
        }
Exemplo n.º 16
0
        /// <inheritdoc />
        public ICellSurface ToSurface(TextureConvertMode mode, int surfaceWidth, int surfaceHeight, TextureConvertBackgroundStyle backgroundStyle = TextureConvertBackgroundStyle.Pixel, TextureConvertForegroundStyle foregroundStyle = TextureConvertForegroundStyle.Block, Color[] cachedColorArray = null, ICellSurface cachedSurface = null)
        {
            if (surfaceWidth <= 0 || surfaceHeight <= 0 || surfaceWidth > _texture.Size.X || surfaceHeight > _texture.Size.Y)
            {
                throw new ArgumentOutOfRangeException("The size of the surface must be equal to or smaller than the texture.");
            }

            ICellSurface surface = cachedSurface ?? new CellSurface(surfaceWidth, surfaceHeight);

            // Background mode with simple resizing.
            if (mode == TextureConvertMode.Background && backgroundStyle == TextureConvertBackgroundStyle.Pixel)
            {
                using var resizer = GetResizedTexture(surface.Width, surface.Height);

                var colors = new Color[(int)resizer.Size.X * (int)resizer.Size.Y];
                using Image image = resizer.Texture.CopyToImage();
                byte[] imagePixels = image.Pixels;

                int colorIndex = 0;
                for (int i = 0; i < imagePixels.Length; i += 4)
                {
                    surface[colorIndex++].Background = new Color(imagePixels[i], imagePixels[i + 1], imagePixels[i + 2], imagePixels[i + 3]);
                }

                return(surface);
            }

            // Calculating color based on surrounding pixels
            Color[] pixels = GetPixels();

            int fontSizeX = (int)_texture.Size.X / surfaceWidth;
            int fontSizeY = (int)_texture.Size.Y / surfaceHeight;

            global::System.Threading.Tasks.Parallel.For(0, (int)_texture.Size.Y / fontSizeY, (h) =>
                                                        //for (int h = 0; h < imageHeight / fontSizeY; h++)
            {
                int startY = h * fontSizeY;
                //System.Threading.Tasks.Parallel.For(0, imageWidth / fontSizeX, (w) =>
                for (int w = 0; w < _texture.Size.X / fontSizeX; w++)
                {
                    int startX = w * fontSizeX;

                    float allR = 0;
                    float allG = 0;
                    float allB = 0;

                    for (int y = 0; y < fontSizeY; y++)
                    {
                        for (int x = 0; x < fontSizeX; x++)
                        {
                            int cY = y + startY;
                            int cX = x + startX;

                            Color color = pixels[cY * _texture.Size.X + cX];

                            allR += color.R;
                            allG += color.G;
                            allB += color.B;
                        }
                    }

                    byte sr = (byte)(allR / (fontSizeX * fontSizeY));
                    byte sg = (byte)(allG / (fontSizeX * fontSizeY));
                    byte sb = (byte)(allB / (fontSizeX * fontSizeY));

                    var newColor = new SadRogue.Primitives.Color(sr, sg, sb);

                    if (mode == TextureConvertMode.Background)
                    {
                        surface.SetBackground(w, h, newColor);
                    }

                    else if (foregroundStyle == TextureConvertForegroundStyle.Block)
                    {
                        float sbri = newColor.GetBrightness() * 255;

                        if (sbri > 204)
                        {
                            surface.SetGlyph(w, h, 219, newColor); //█
                        }
                        else if (sbri > 152)
                        {
                            surface.SetGlyph(w, h, 178, newColor); //▓
                        }
                        else if (sbri > 100)
                        {
                            surface.SetGlyph(w, h, 177, newColor); //▒
                        }
                        else if (sbri > 48)
                        {
                            surface.SetGlyph(w, h, 176, newColor); //░
                        }
                    }
                    else //else if (foregroundStyle == TextureConvertForegroundStyle.AsciiSymbol)
                    {
                        float sbri = newColor.GetBrightness() * 255;

                        if (sbri > 230)
                        {
                            surface.SetGlyph(w, h, '#', newColor);
                        }
                        else if (sbri > 207)
                        {
                            surface.SetGlyph(w, h, '&', newColor);
                        }
                        else if (sbri > 184)
                        {
                            surface.SetGlyph(w, h, '$', newColor);
                        }
                        else if (sbri > 161)
                        {
                            surface.SetGlyph(w, h, 'X', newColor);
                        }
                        else if (sbri > 138)
                        {
                            surface.SetGlyph(w, h, 'x', newColor);
                        }
                        else if (sbri > 115)
                        {
                            surface.SetGlyph(w, h, '=', newColor);
                        }
                        else if (sbri > 92)
                        {
                            surface.SetGlyph(w, h, '+', newColor);
                        }
                        else if (sbri > 69)
                        {
                            surface.SetGlyph(w, h, ';', newColor);
                        }
                        else if (sbri > 46)
                        {
                            surface.SetGlyph(w, h, ':', newColor);
                        }
                        else if (sbri > 23)
                        {
                            surface.SetGlyph(w, h, '.', newColor);
                        }
                    }
                }
            }
                                                        );

            return(surface);
        }
Exemplo n.º 17
0
 /// <summary>
 /// Creates a new console using the existing surface.
 /// </summary>
 /// <param name="surface">The surface.</param>
 /// <param name="font">The font to use with the surface.</param>
 /// <param name="fontSize">The font size.</param>
 public ControlsConsole(ICellSurface surface, IFont font = null, Point?fontSize = null) : base(surface, font, fontSize)
 {
     Controls = new ControlHost();
     SadComponents.Add(Controls);
 }
 public MessageLogConsole(ICellSurface surface, IFont font = null, Point?fontSize = null)
     : base(surface, font, fontSize)
 {
     Initialize();
 }
Exemplo n.º 19
0
 public TextField(Point position, int width, ICellSurface surface) =>
 (Position, Width, _surface) = (position, width, surface);
Exemplo n.º 20
0
        /// <inheritdoc />
        public override void Build(ref ColoredString.ColoredGlyphEffect glyphState, ColoredString.ColoredGlyphEffect[] glyphString, int surfaceIndex,
                                   ICellSurface surface, ref int stringIndex, string processedString, ParseCommandStacks commandStack)
        {
            byte r = 0;
            byte g = 0;
            byte b = 0;
            byte a = 0;

            if (Default)
            {
                if (CommandType == CommandTypes.Background)
                {
                    (surface != null ? surface.DefaultBackground : Color.Transparent).Deconstruct(out r, out g, out b, out a);
                }
                else
                {
                    (surface != null ? surface.DefaultForeground : Color.White).Deconstruct(out r, out g, out b, out a);
                }
            }
            else
            {
                if (CommandType == CommandTypes.Background)
                {
                    glyphState.Background.Deconstruct(out r, out g, out b, out a);
                }
                else
                {
                    glyphState.Foreground.Deconstruct(out r, out g, out b, out a);
                }

                if (!KeepRed)
                {
                    r = R;
                }

                if (!KeepGreen)
                {
                    g = G;
                }

                if (!KeepBlue)
                {
                    b = B;
                }

                if (!KeepAlpha)
                {
                    a = A;
                }
            }

            if (CommandType == CommandTypes.Background)
            {
                glyphState.Background = new Color(r, g, b, a);
            }
            else
            {
                glyphState.Foreground = new Color(r, g, b, a);
            }

            if (_counter != -1)
            {
                _counter--;

                if (_counter == 0)
                {
                    commandStack.RemoveSafe(this);
                }
            }
        }