Gradient in standard graphics library

Hi All,
The answer to this may just be “no” but is it possible to do a gradient brush in the standard graphics library? (switching to the tinyclr.UI library is unfortunately not practical) the function is there in the source code, so I tried to do my own edits to it then import the new library which did one of 2 things:

a) broke the firmware, or
b) broke the resource manager.

All I did was add a gradient brush object then add some functionality to the FillRectangle method:

Brush:

public class GradientBrush : Brush    

    {

        public Color startColor { get; set; }

        public Color endColor { get; set; }

        public GradientDirection direction { get; set; }

        public GradientBrush(Color startColor, Color endColor, GradientDirection direction)

        {

            this.startColor = startColor;

            this.endColor = endColor;  

            this.direction = direction;

        }

        public override object Clone()

        {

            return new GradientBrush(startColor, endColor, direction);

        }

    }

    public enum GradientDirection

    {

        TopToBottom,

        BottomToTop,

        LeftToRight,

        RightToLeft,

    }

Graphics:

public void FillRectangle(Brush brush, int x, int y, int width, int height)

        {

            if (brush is SolidBrush b)

            {

                var rgb = (uint)(b.Color.ToArgb() & 0x00FFFFFF);

                this.surface.DrawRectangle(rgb, 0, x, y, width, height, 0, 0, rgb, x, y, rgb, x + width, y + height, b.Color.A);

            }

            else if(brush is GradientBrush gb)

            {

                uint colorA = (uint)(gb.startColor.ToArgb() & 0x00FFFFFF);

                uint colorB = (uint)(gb.endColor.ToArgb() & 0x00FFFFFF);

                switch (gb.direction)

                {

                    case GradientDirection.TopToBottom:

                        this.surface.DrawRectangle(colorA, 0, x, y, width, height, 0, 0, colorA, x, y, colorB, x, y + height, gb.startColor.A);

                        break;

                    case GradientDirection.BottomToTop:

                        throw new NotSupportedException();

                        break;

                    case GradientDirection.LeftToRight:

                        throw new NotSupportedException();

                        break;

                    case GradientDirection.RightToLeft:

                        throw new NotSupportedException();

                        break;

                }                

            }

            else

            {

                throw new NotSupportedException();

            }

        }

I really just need to figure out how to expose the internal DrawRectangle method - this would allow me to also do some less-Windows 95-looking buttons and such. At this point, the project I inherited has so much work built over the Graphics library that it would take an extraordinary amount of work to jump to the UI. Any pointers or ideas?

My only other option is draw a bunch of lines that slowly change color, which i’ve done before, but it is insanely inefficient.

This is supported natively and it is how the UI library does it. The UI library is 100% done in C#

I looked into how that was done, but what’s surprising to me is that the UI library must be doing some black magic on the back end - this function call here:

namespace GHIElectronics.TinyCLR.UI {

    internal class Bitmap : IDisposable {

        private readonly System.Drawing.Graphics g;

        private readonly System.Drawing.Internal.Bitmap surface; //both internal and bitmap shouldn't be accessible

        .

        .

        .

        public Bitmap(System.Drawing.Graphics g) {

            this.g = g;

            this.surface = Extract(g);

        }

by all accounts shouldn’t work. the entire Internal namespace and, by extension, the Bitmap/surface object is blocked by an ‘internal’ keyword and isn’t accessible outside of the Drawing assembly, but somehow this (the UI assembly) accesses it no problem and it shouldn’t be able to. I’m a little lost as to why this works - any insight on that? This is turning into more of a ‘for my enrichment’ thing, but I’ll still use it if i can figure it out

.NET allows internals to be made visible to other assemblies using the InternalsVisibleTo attribute. I searched the source code and found GHIElectronics.TinyCLR.Drawing/Font.cs has the following

[assembly: InternalsVisibleTo(“GHIElectronics.TinyCLR.UI”)]

This is why the UI assembly has access to the Drawing assembly internals.

1 Like