Unless you are very clear on the requirements for your GUI and define its elements, you may find it very uphill to find enough room to handle the elements later on. Best way to do that is to draw the various screens (by hand if you may) to decide what you really need

Usually, a GUI is built up with graphic elements like icons, rectangles, rounded-rectangles, sometimes circles, images, text of various sizes and such. The usual way to draw these would be to store the images of them somewhere and retrieve when needed. The other way would be to generate them via code. the code approach needs a processor with a decent speed to enable drawing the screen multiple times. The larger the graphic element, the longer it takes to put to screen; so, storing the graphic as an image and pulling it on demand is the faster way to do things. However, the disadvantage is you cannot size up/down easily.

Typically, a RGB display would use the RGB565 16bit format for color handling. You could also use the 24 bit full color format. An image 320x240 pixels rendered in full color will need 320x240/8 bytes per plane. So, rendering the 3 planes of Red, Green and Blue will need data worth 320x240/8*3 (=28800) bytes. So, now you see how big the demands can be. AFAIK, visualglcd uses a display with a SD card memory bank to store visual elements. I may be wrong there. I am not conversant with how displays with the backing SD memory work.

There are ways around this situation in a slightly restrictive way. For one, you could render a monochrome bitmap in a single color of your choice. So, the icon could be rendered with pixels of a single color only. Dithering can help generate monochromic shades in the color.

Fonts too require a lot of room to store. More fonts, more space needed. Ideally, a couple of font sizes is what may be really needed.

There are some tools that will help you convert on-screen fonts to data arrays and also on-screen bitmaps to data arrays. Unfortunately, most of them are C-oriented. One that I like best is a GPL'ed tool called "The Dot Factory" from Eran 'Pavius' Duchan http://www.pavius.net

Drawing primitives like line, circle can be done using the Bresenhams' algorithm - plenty online references. Drawing rectangles is just an extension to drawing lines. Filled / unfilled, same story. Rounded rectangles needs a little more. As you keep building the primitives library, you will realize, graphics is not intended for tiny embedded systems with limited resources. You need a capable processor with lots of flash and RAM for double buffering. At most times, embedded systems will use static / slow moving dynamic screens. Achieving video frame speeds needs a lot of hardware support too(like DMA and External memory interface).

There is another site that was quite an inspiration to me - Andy's workshop. Though most code is in C++, you can get quite a lot of knowledge there. http://andybrown.me.uk

I hope this has been of some use to you