Archived

This topic is now archived and is closed to further replies.

Rocky

GDI+ question about transformations

Recommended Posts

I have a quick question about the GDI+ transformations.At this time, I use a world transformation that draws the gauge whatever the gauge size, using the ScaleTransform method of the Graphics class. It works perfect and each GDI+ drawn gauge can be resized without any loss of information. But I was wondering if this has a strong impact on the drawing performance. Do you have the answer?There are ways to avoid the use of a ScaleTransform, but is it necessary?Any information is welcome.Eric

Share this post


Link to post
Share on other sites
Help AVSIM continue to serve you!
Please donate today!

Ok now I am really not a specialist but the only other method that I'd know of is the dx/dy scaling factor thing that, I believe, originated from the ole Flight Map SDK gauge (GDI classic). That means you simply scale all coordinates by hand, using a certain factor that you determine somewhere at the beginning of the drawing process, using information about how large the gauge actually appears on screen. Other than that, whenever I fiddled around with GDI+, I always used the ScaleXForm method, for the sake of laziness, but even more inability, and it kinda did the job for me. :(RegardsEtienne

Share this post


Link to post
Share on other sites
Ok now I am really not a specialist but the only other method that I'd know of is the dx/dy scaling factor thing that, I believe, originated from the ole Flight Map SDK gauge (GDI classic). That means you simply scale all coordinates by hand, using a certain factor that you determine somewhere at the beginning of the drawing process, using information about how large the gauge actually appears on screen. Other than that, whenever I fiddled around with GDI+, I always used the ScaleXForm method, for the sake of laziness, but even more inability, and it kinda did the job for me. :(RegardsEtienne
Hello Etienne,I already tried the solution you're talking about, but it is not as good as ScaleTransform.Why? Because it works perfect for simple cases: you multiply all the X coordinates by the dx factor, and Y corrdinates by dy. Easy... But what about things that are related to both X and Y. Example: a circle. How do you compute the radius? You multiply by dx or by dy? Whatever you do, the circle will always be a circle. With ScaleTransform, the circle can become an ellipse if the user resizes the window by increasing the width and not height. The problem is even worse for the fonts. ScaleTransorm is perfect for lazy people like you and me :( but it is also perfect because it works in any case.I should say that resizing the window without keeping the original proportion is VERY important because some of us have 4/3 monitors, and others have 16:9 or other wide monitors.Eric

Share this post


Link to post
Share on other sites

Keeping your gauge's size ratio constant regardless of the user's "resizing" isn't really that useful unless you can find a way to keep the 2d panel bitmap's ratio constant as well...That's why at Eaglesoft we now supply both normal 4:3 ratio and widescreen 16:9 ratio panel.cfg files.

// in the main gauge is this functionvoid __fastcall ResetTransform (Graphics &graphics){	graphics.ResetTransform ();	graphics.ScaleTransform (dx, dy);}// in PANEL_SERVICE_PRE_DRAW		if (pelement)		{			HDC hdc = pelement->hdc;			PIXPOINT dim = pelement->image_data.final->dim;			sADI_params = pgauge->parameters;			dx = dim.x / width_sADI;;			dy = dim.y / height_sADI;			if (hdc)			{				Graphics graphics(hdc);				if (MASTER_BATTERYvar.var_value.n == 1 && brt > 0)				{					// Global String Declarations 					graphics.SetSmoothingMode(SmoothingModeAntiAlias);					graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);						graphics.SetInterpolationMode (InterpolationModeHighQualityBicubic);					ResetTransform (graphics);.... et cetera

Share this post


Link to post
Share on other sites

Hello Bill,The code you provided here is very similar to the one I use in my gauges. You use ScaleTransform like I do, and the x,y transformation factors depend on the size of the gauge.Thanks for your help anyway.Eric

Share this post


Link to post
Share on other sites
I already tried the solution you're talking about, but it is not as good as ScaleTransform.
That is so true. :(
Why? Because it works perfect for simple cases: you multiply all the X coordinates by the dx factor, and Y corrdinates by dy. Easy... But what about things that are related to both X and Y. Example: a circle. How do you compute the radius? You multiply by dx or by dy? Whatever you do, the circle will always be a circle. With ScaleTransform, the circle can become an ellipse if the user resizes the window by increasing the width and not height. The problem is even worse for the fonts. ScaleTransorm is perfect for lazy people like you and me :( but it is also perfect because it works in any case.
I hear ya, yeah well when I got started with vector gauges back then I was doing some ADI/HSI thing in pure classic GDI, that means no ScaleTransform avail, unfortunately. Just to draw the HSI and CDI without scaling was some sort of a nightmare, at least for me. Let alone scaling then. Some serious trig involved there haha. For noobs like me I am glad we've got GDI+. :(
The code you provided here is very similar to the one I use in my gauges.
Second that, lol... Seems we're all pretty much on the same page here. :(RegardsEtienne

Share this post


Link to post
Share on other sites
Hello Bill,The code you provided here is very similar to the one I use in my gauges. You use ScaleTransform like I do, and the x,y transformation factors depend on the size of the gauge.Thanks for your help anyway.Eric
Have you used __fastcall (which uses the register directly) at all? If so, have you noticed any performance improvement over the use of __stdcall (which uses the stack)?

Share this post


Link to post
Share on other sites
Have you used __fastcall (which uses the register directly) at all? If so, have you noticed any performance improvement over the use of __stdcall (which uses the stack)?
No, I never used this, I didn't even know about it...Is it somewhere in the compilation options?Does it mean the stack size is reduced?Thanks,Eric

Share this post


Link to post
Share on other sites
Is it somewhere in the compilation options?
No it's not, but you can define any function as such:
int __fastcall Function (int i){ ... }int __stdcall Function (int i){ ... }

If there is any effect on performace I can't comment on either, though. :(RegardsEtienne

Share this post


Link to post
Share on other sites

I will test the fastcall.In the meantime, I made some tests with multi-threading. I didn't get very interesting results at this time.It works very well on a small test gauge, but with 3 or 4 complex EFIS, the benefit is very low...But I'm not sure I was the multi-threading in the right way.Eric

Share this post


Link to post
Share on other sites
No, I never used this, I didn't even know about it...Is it somewhere in the compilation options?Does it mean the stack size is reduced?
Those are simply two of the available ways to speed up function calls - at least in theory. I've read some who claim up to 10% increase in execution time using __fastcall vs __stdcall......then again, I've also read some who've reported just the opposite... :( http://msdn.microsoft.com/en-us/library/984x0h58(VS.71).aspxAccording to MS, the default __cdecl (which is what is used unless otherwise specified) produces more bloated executables, which is presumably why specifying either __stdcall or __fastcall is more efficient:__cdecl"This is the default calling convention for C and C++ programs. Because the stack is cleaned up by the caller, it can do vararg functions. The __cdecl calling convention creates larger executables than __stdcall, because it requires each function call to include stack cleanup code. The following list shows the implementation of this calling convention."__fastcall on the other hand, doesn't use the stack at all, but instead uses the ECX and EDX registers directly.

Share this post


Link to post
Share on other sites
Those are simply two of the available ways to speed up function calls - at least in theory. I've read some who claim up to 10% increase in execution time using __fastcall vs __stdcall......then again, I've also read some who've reported just the opposite... :( http://msdn.microsoft.com/en-us/library/984x0h58(VS.71).aspxAccording to MS, the default __cdecl (which is what is used unless otherwise specified) produces more bloated executables, which is presumably why specifying either __stdcall or __fastcall is more efficient:__cdecl"This is the default calling convention for C and C++ programs. Because the stack is cleaned up by the caller, it can do vararg functions. The __cdecl calling convention creates larger executables than __stdcall, because it requires each function call to include stack cleanup code. The following list shows the implementation of this calling convention."__fastcall on the other hand, doesn't use the stack at all, but instead uses the ECX and EDX registers directly.
If I understand this correctly, it means the usage of __fastcall limits the size of the stack because the registers are not infinite... My function calls usually have few parameters, so it should be OK, but I'd like to know...I would like to test this, but I have so many functions/methods in my code that it will take many hours to add __fastcall on each function/method.Eric

Share this post


Link to post
Share on other sites
If I understand this correctly, it means the usage of __fastcall limits the size of the stack because the registers are not infinite... My function calls usually have few parameters, so it should be OK, but I'd like to know...I would like to test this, but I have so many functions/methods in my code that it will take many hours to add __fastcall on each function/method.Eric
Well, according to MS, if you use the compiler optimization switch /Gr you don't need to convert anything at all!"Using the /Gr compiler option causes each function in the module to compile as fastcall unless the function is declared with a conflicting attribute, or the name of the function is main."

Share this post


Link to post
Share on other sites