[M3devel] strange problem w/new Image/ImageInit
Jay
jay.krell at cornell.edu
Tue Aug 12 21:58:42 CEST 2008
Twice I've lost my message here, darnit.
LOGPIXELSX (look it up on MSDN/Google/LiveSearch) is pixels per inch on the x axis. It is stuck at 96 for compatibility. And the docs say it has just one value in a multimon situation.
So you can ask Windows for pixels per inch and get 96.
Or you can ask for pixels and millimeters and do the division and get the truth.
Or you can tell it you are "high dpi aware" on Vista and get the truth either way.
I understand the attempt to do the right thing, but it clearly doesn't work out -- the rest of the gui doesn't scale/move correctly with it.
What makes sense and is ideal is often at odds with the bulk of existing code. The bulk of existing code wins, and sometimes nobody can do the right thing in contradiction do it.
- Jay
Date: Tue, 12 Aug 2008 11:51:25 -0400From: rcoleburn at scires.comTo: jay.krell at cornell.eduCC: m3devel at elegosoft.comSubject: Re: [M3devel] strange problem w/new Image/ImageInit
Jay:
Thanks for your insights here. I'll try some more tests and see what I come up with. I've attached my current Image.i3/Image.m3 and Win32/ScrollerVBTClass.m3 for your reference. I've removed use of ImageInit from all of these. And yes, I have reverted to the 75.0 hardcoded value.
Based on my limited understanding of the code, I still think I will get scaled behavior even if Modula-3 thinks the dpi is 96, because 147 / 96 = 1.53125, which rounds to 2. So my pixmaps will still appear double-size.
In actuality, I think Modula-3 is trying to do the right thing with the scaling. At some point on a high-enough dpi monitor, the pixmaps will be so tiny that you can't really see them if they are unscaled. I've already observed this with some of my boolean and choice indicators--I had to reduce the shadowsize in order to tell whether the boolean/choice was TRUE or FALSE. From the way Trestle/FormsVBT are set up, it appears that the designers wanted to get approximately the same size rendering on different dpi screens. That's why you see millimeters everywhere in the code being converted to pixels. Indeed, VBT has a procedure MMToPixels that is dependent on getting the screen type of the underlying VBT.T so it can get the ppm setting for this screen and do the computation. Provided that the underlying implementation gives correct ppm info to Modula-3 for each screen, the current Trestle/FormsVBT should do the right thing even in multiple monitor situations. I haven't tested this, but I should be able to drag a window from a monitor at one dpi onto a monitor at a different dpi and have everything scale to look correct on the new monitor.
The problem in my case with the 1920x1200 monitor is that the scaled pixmaps look huge in proportion to the text and other features of the window. Maybe this other stuff isn't being scaled the same way pixmaps are scaled.
Does LOGPIXELSX stand for Logical Pixels X-Axis ? I know that Windows has a dpi setting for fonts. If set to normal, fonts are supposed to render at 96 dpi, but you can switch to large mode and have them rendered at 120 dpi, or you can make up a custom number. This Windows setting applies only to fonts, not graphical elements.
You say that Modula-3 is computing LOGPIXELS via a "seemingly redundant equivalent way." In my reading of the code in WinScreenType, it appears that Modula-3 is requesting from Windows the actual number of pixels in both axes and also the number of millimeters in both axes. It uses these to compute the resolution in pixels per millimeter (ppm). The ppm is what is stored and used internally when scaling pixmaps. When necessary, ppm is converted to dpi using the formula (dpi = ppm x 25.4).
On my 4:3 aspect ratio IBM T60 at 1280x1024, the ppm is 3.41333 in both axes yielding a dpi of 86.698667.
On the widescreen (16:10 aspect ratio) Dell 4300 at 1920x1200 the ppm is slightly different in each axis, but is close to 5.8xxx yielding at dpi of 147.xxx (again, the fractional part is different in each axis).
I don't mind running a test program for you on the hi-res system here--just send it to me via email. I have the VC++ 2008 redistributables installed.
I think you are on the west coast and I'm on the east coast, so we have a time difference of 3 hours, but lately I've been working round the clock seemingly, so I'll try to respond with test results as soon as I can.
Regards,
Randy>>> Jay <jay.krell at cornell.edu> 8/12/2008 6:49 AM >>>Randy I don't think you need to add a way to use the unscaled data.I think the fix isa) go back to Image hardcoding 75b) Have WinScreenType hardcode 96 or use GetDeviceCaps(LOGPIXELSX Y) -- same thing really.And then see what happens.Basically, the scale of pixmaps and the scale of screens has always been close to 1:1.75:96, close enough.Therefore, unscaled has been the norm.Most GUI code uses GetDeviceCaps(LOGPIXELSX Y) I believe.However, most code is not prepared to get back anything other than 96 from it.Modula-3, at least for the pixmap code, was computing LOGPIXELSX and Y via a seemingly redundant equivalent way.However, my believe is that LOGPIXELSX and Y is forced to lie, but the other route is not.It seems an arbitrary discprecancy, but not beyond imagination.By switching to the lying method, we will get back the nearly unscaled 75:96 behavior.Vista adds a way for an application to declare that it is "high dpi aware", which then makes GetDeviceCaps(LOGPIXELX and Y) report the truth presumably. You can see, by the very existance of this ability to declare that you are high dpi aware -- to declare that your code is merely correct -- that most code is not correct.What remains to be determined is why Modula-3 pixmaps behave "differently" than Modula-3 buttons, text, etc.I also think there is a likely disconnect between painting and hit testing, but this is gross speculation.I should fiddle with the numbers myself.I will go ahead with a+b fairly soon.I will verify the numbers computed in #b before and after.I don't have any high dpi systems, so I expect the numbers to be roughly the same either way.I think the only systems that will see a change are high dpi, and they will see an improvement.Sorry for the back and forth regarding ImageInit -- a medium size change is going to be completely undone.- Jay________________________________Date: Tue, 12 Aug 2008 04:25:11 -0400From: rcoleburn at scires.comTo: jay.krell at cornell.eduCC: m3devel at elegosoft.comSubject: Re: [M3devel] strange problem w/new Image/ImageInitJay:For LOGPIXELS X & Y, I get 96 on the hi-res Dell M4300 system and also on my ThinkPad T60.I've put together revised versions of Image.i3/m3 and my ScrollerVBTClass.m3. The good news is that I've managed to get the scroll bar to look correct in both scaled and unscaled modes.I've added a new procedure to Image.i3/m3 that will force subsequent calls to Scaled() to behave like Unscaled(). Using this, I can get the appearance I need on the hi-res monitor without resorting to changes in the original intent of the Image interface. The advantage of this procedure is that it does not change the Image interface (except for addition of the procedure) and it therefore won't have any affect on pickles or anyone else's code. Plus, it lets the programmer override use of Scaled() in all library modules without having to modify any source code.Before I commit any of these changes, I want to do some more testing and to fix the problem with subwindows (ZChassisVBT) not being able to move.Alas, my problem of the ZChassisVBTs not being able to move on the hi-res monitor persists with these changes, even though I left the xres/yres at 75. Of course, these numbers are ignored for Unscaled images anyway.I'm at a loss to explain this behavior. Here is what I know based on testing:1. Using Scaled images and Image.Raw.xres/yres = 75.0, ZChassisVBT movement works on the hi-res monitor.2. Using Scaled images and Image.Raw.xres/yres set to 86.xxx or to 147.xxx, ZChassisVBT movement does not work on the hi-res 147.xxx dpi monitor, but it still works on my 86.xxx dpi monitor3. Using Unscaled images, ZChassisVBT movement does not work on the hi-res 147.xxx dpi monitor, but it still works on my 86.xxx dpi monitorSo, there seems to be something in the implementation somewhere of ZChassisVBT, or maybe ZMoveVBT, that doesn't like 147.xxx dpi monitors unless you scale all images assuming they were designed at 75 dpi. At the 147 dpi, the 75 dpi pixmaps will be scaled by a factor of 2, which corresponds to what I am seeing on the screen.I'm too sleepy to make any more progress for now. If anyone has an idea on what to do next, please let me know. I'm stumped at this point.Regards,Randy>>> Jay 8/11/2008 3:52 PM>>>Hm. Ok then, where does it get the screen resolution from?Probably here?WinScreenType.m3:PROCEDURE InnerNew ((* IN-OUT *) res: T) = BEGIN WITH pix_hor = WinUser.GetSystemMetrics(WinUser.SM_CXSCREEN), pix_ver = WinUser.GetSystemMetrics(WinUser.SM_CYSCREEN), mm_hor = GetDeviceCaps (WinGDI.HORZSIZE), mm_ver = GetDeviceCaps (WinGDI.VERTSIZE) DO res.rootDom := Rect.FromSize(pix_hor, pix_ver); res.res[Axis.T.Hor] := FLOAT(pix_hor) / FLOAT(mm_hor); res.res[Axis.T.Ver] := FLOAT(pix_ver) / FLOAT(mm_ver);ok.Perhaps we should accept the numbers that Windows makes up instead?GetDeviceCaps(LOGPIXELSX)and GetDeviceCaps(LOGPIXELSY)Please try that, in the WinScreenType.m3 code.With removing ImageInit (or just have it hardcoded at 75).This will most likely be 96 even on your high dpi system, unless you are on Vistaand tell the system you are high dpi aware.I think there is disagreement in drawing vs. hit test as to where you are clicking.Try making ImageInit always 75.Try making the above convert from a hardcoded 96.And then try GetDeviceCaps(LOGPIXELSX and Y) -- which I expect always returns 96 for you.You can plug that into my dpi.c to see what it prints.I think part of what is happening is that Modula-3 was very rare in doing the right thing for high dpimonitors. But so much code is wrong that Windows has to counteract the wrongness,which means Modula-3 needs to go along and do things wrong in order for the counteractionto leave it doing the right thing also.I'm not sure.Oh, and presumably other places in Modula-3 are wrong, and the counteraction works for them.That's a bit of a mystery -- drawing of pixmaps vs. drawing of everything else.- Jay________________________________Date: Mon, 11 Aug 2008 15:23:17 -0400From: rcoleburn at scires.comTo: jay.krell at cornell.eduCC: m3devel at elegosoft.com; wagner at elegosoft.comSubject: RE: strange problem w/new Image/ImageInitJay:I have been experimenting quite a bit and I've come up with some "new old" information.I say "new old" because, after spending the time to read some of the comments in the original code (before we modified it), I think I now have a better idea of what the designers intended and why I had/have a problem.If you read carefully, the xres/yres fields in Image.Raw are supposed to represent the resolution at which the pixmap was originally DEVELOPED, not the resolution of the current screen. It seems the designers went to great lengths to represent everything as screen-independent until it is actually rendered.The Image interface gives 3 ways of dealing with pixmaps: (1) unscaled, (2) scaled, and (3) scaled to "most appropriate". The change you and I conspired actually changes this behavior to make #2 (scaled) work as #1 (unscaled). (It probably also changes #3.) This is the behavior I want for my current program, but it changes the intent of the original interface, so I'm afraid we are going to have to revert all those changes.Digging deeper into Image.m3, I've discovered that it is smart-enough already to deduce the screen resolution. If you look into the ApplyScaled1 procedure, you see that it converts the current screen resolution in millimeters to pixels in order to scale the pixmap. The change we introduced, namely making Raw.xres/yres equal to the current screen resolution, effectively caused the Scaled procedure to do nothing since (ScreenDPI / ImageDPI) = 1.The problem that brought all this on in the first place is that my GUI was looking bad on the 1920x1200 screen. The reason I have discovered *now* is that FormsVBT apparently uses the #2 (scaled) version for pixmaps. In the old code, the interface defaulted the developed resolution of the pixmaps to be 75 dpi. At my 147+ dpi screen, the scaled implementation would effectively double the size of the pixmap when rendered on the screen in an effort to make the pixmap look the same size on the 147dpi screen that it appeared on a 75 dpi screen.All of this to say that the changes to Image.i3/m3 need to be undone in order to get back the original intent of the developers.Of course, once these changes are undone, my problem returns with the GUI looking bad on 1920x1200 at 147+ dpi. So, how to solve it properly now requires more thought.I need to do some more reading of the code I guess to see if there is a way already to cause FormsVBT to use unscaled for all pixmaps. Otherwise, a quick fix would be to add a new procedure to the interface that would force use of the unscaled implementation.Now, back to the problem of not being able to drag the subwindows, I'm still puzzled. To test my "understanding" as related above, I went back to the original Image.i3/m3, but this time changed the Scaled procedure to effectively do the same thing as Unscaled. The pixmaps render fine on the 1920x1200 monitor, but the subwindows still can't be dragged. If I back out my change to Scaled (effectively, revert to the original Image.m3), the subwindows drag with ease on the 1920x1200 monitor, but of course the pixmaps look bad. I can't explain this behavior yet. Any ideas?Regards,Randy>>> Jay 8/11/2008 2:41 PM>>>MemoryBarrier ensures that all the reads and writes before it finish before any reads and writes after it.Look at winnt.h or MSDN, as well the comment I put in explains it.It probably has no effect, since our compiler is not aggressive.What is confusing in these cases is the compiler and processor both need to be informed.There is a concurrency issue and the barrier should make extra certain to solve it.Multiple monitors are not considered.Do you have them?Randy, please experiment.Change the code to return hard coded numbers -- like the old 75. Either without the globals, or initialize the globals.And then add in the the various calls one at a time, ignoring their return values.Furthermore, I guess you could just say: IF xres = 0 THEN Init() END;and IF yres = 0 THEN Init() END;and maybe change the globals to INTEGER.Though REAL should be 32 bits and be written atomatically.The idea is, even if the code does run multiple times concurrently, it should always return the same information.Anyway, like I said, try various or every combination between the two and findout which part triggers the difference, then we can think more about just that.I might be able to get an expert friend to give me some help, later.- Jay________________________________Date: Mon, 11 Aug 2008 12:15:40 -0400From: rcoleburn at scires.comTo: jay.krell at cornell.eduCC: wagner at elegosoft.comSubject: RE: strange problem w/new Image/ImageInitJay:I tested your change, but it has no effect on the problem I am having. I also tried having the accessor functions just return a hardcoded number, but again, no effect on the problem. This is real strange to me, because if I remove ImageInit and revert Image.i3/m3 back to the way it was before, the problem disappears.Questions,1. What does the WinNT.MemoryBarrier() call do?2. What would happen if this code was run by multiple threads? Are there any concurrency issues that need to be guarded?3. What would happen in the case of multiple monitors at different resolutions?Regards,Randy>>> Jay 8/11/2008 6:46 AM>>>Also try the change I just commited with ReleaseDC.- Jay> From: jayk123 at hotmail.com> To: rcoleburn at scires.com> CC: wagner at elegosoft.com> Subject: RE: strange problem w/new Image/ImageInit> Date: Mon, 11 Aug 2008 07:51:52 +0000>>> Randy, this makes no sense to me.> What happens if you just hardcode the numbers instead of computing them?>>> - Jay>>>>>>> ________________________________>>>> Date: Mon, 11 Aug 2008 02:55:56 -0400> From: rcoleburn at scires.com> To: jayk123 at hotmail.com> CC: Olaf Wagner
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://m3lists.elegosoft.com/pipermail/m3devel/attachments/20080812/41806d4a/attachment-0002.html>
More information about the M3devel
mailing list