User Interface

Hi all!

After seeing how fast SITCore is I decided to put it to the test with a UI that stressed the ‘old’ G400 a lot, and here’s some feedback.

Despite the usual NETMF limitations (maximum string table size, max items per assembly, …) and a new entry (string doesn’t implement IEnumerable?), a rough port does not take long, and the UI is indeed noticeably more responsive (I’m using the UD700).

I couldn’t find a lossless image format digested by TinyCLR: compressed BMP doesn’t seem to be supported, and loading uncompressed images from the SD card takes 1.4’’ each (fullscreen, much less for smaller elements of course), not to mention the space cost (1.1 MB), which can be a problem if data is stored on a less generous media. With G400 this kind of problems were easily solved by writing your own algorithms with RLP, but as I understand that’s no longer an option.

Is transparency supported somehow? With NETMF there was Bitmap.MakeTransparent, but I couldn’t find anything similar in TinyCLR, and I think that’s a mandatory feature for most UIs.

Opacity support appears to be limited in Graphics.* (I’m talking about the blending NETMF implemented in Bitmap.* drawing methods): it works with FillEllipse and FillRectangle, it throws with DrawEllipse, DrawLine, DrawRectangle and DrawString (these too weren’t available with NETMF - if I remember correctly - but it was easy to work around using DrawImage), and there’s no parameter I could think of for DrawImage (which in my opinion is the most important).

Image translucency (similar to what happens when drawing fonts) is also something that greatly improves the look of a UI, and while alpha channel was not supported by NETMF’s Bitmap, it could be efficiently coded with RLP, same as many other things.

Available managed memory is very low for a complex UI - and possibly in other contexts as well - though I gather this has already been addressed in the next release, with external RAM. I understand it comes with a small security cost, but 300 KB is really very limiting for something as powerful as the SITCore.

Similarly, available code space is a bit limited (700 KB), but I understand loading the managed application from external flash would further reduce security. Still, I think many applications could benefit from this trade-off.

1 Like

First of all, THANKS for the fantastic feedback! And welcome to the community forum.

We have a note to look into PNG but we have never really had a need. This was more of a “nice to have” feature. Using high quality JPEG for small displays has always looked great. Maybe you are doing something different?

@Dat_Tran we need an example for this please.

What exactly do you need here? Opacity for DrawImage?

UI/Graphics does not use managed heap as there is (usually) minimal security risk from placing images in external memory.

This is only a concern for those with a lot of resources. 700KB in code is a LOT of code. I would love to see what app for TinyCLR that would use 700KB! We do have 8MB of external flash which we are yet to activate! We are still departing if it should be a deployment region or file system device.

1 Like

JPEG looks nice, but you can notice artifacts on certain images, and it would be terrible for image borders where transparency/translucency is involved. Take a look at this page we’re writing on: I see no JPEGs here, just PNGs… and that’s not because it’s trendy - your logo, the avatars, the action buttons, everything would look bad if encoded in JPEG. The same applies to a good-looking embedded UI.

Anyway, this and the others are just a few cases of missing RLP I stumbled upon with this UI, the point is that I think a lot of people will miss the possibility of injecting fast algorithms in native code. Supporting standard PNGs would mean maybe 5-10K lines of code on your part, while these 10 lines of custom RLP achieved (brutally, with RLE) the same goal on a G400 app:

while (data != dataEnd)
{
	byte code = *data++;

	if (code & 0x80)
	{
		ushort color = data[0] + (data[1] << 8);
		data += 2;

		code -= 126;
		while (code-- > 0)
			*bitmap++ = color;
	}
	else
	{
		code++;
		while (code-- > 0)
		{
			*bitmap++ = data[0] + (data[1] << 8);
			data += 2;
		}
	}
}

Well, I think it’s needed for all drawing primitives, really… but if DrawImage supported it you could get around the issue by just drawing other primitives on a temporary surface first. The performance loss would still be negligible compared to blending in manged code.

Translucency is a different thing, though… it’s required for controls with anti-aliased borders, shadows and stuff like that. Doing that in managed code is too slow, even on SITCore.

I didn’t express myself very clearly, of course images go to unmanaged memory… I’m loading MBs of surfaces just for this test, it would be impossible to fit them in 300 KB, I meant objects that aren’t easily stored in byte arrays, such as texts, cache for data to be displayed, the whole visual tree, …

Well then I’m sure you’ll be happy if I tell you that the managed code for an instrument whose UI was handled by a G400 was 1 MB + 400 KB of resources, the rest was stored in external memory because 1.4 MB is all the space available on the G400. The same application would not fit on a SITCore, even without resources.

Still, I know that’s a lot of code… but when you have something as powerful as .NET on your hands (even just NETMF) code just keeps growing!

PS: I’m not raising these issues to ‘solve my problem’ (as I see it there would be nothing wrong in NETMF products being complementary to TinyCLR, but I don’t think you want that), I’m just giving you my perspective hoping it’s representative of part of your customer base that’s not here to discuss all this!

1 Like