16

From the documentation for ItemSize:

{w,h} make all items the specified width and height

and

In Grid, w is measured in ems, and h in line heights.

This implies that a specification ItemSize->{4,2} means the item is 4ems wide and 2 line heights high, which in turn suggests that the item size in pixels will be CurrentValue["FontMWidth"]*4 wide and CurrentValue["FontLineHeight"]*high. Therefore to make grids that render to a fixed number of pixels across various platforms you presumably should do (for an item of pixel dimension w,h = 100,20):

ItemSize:>{100/CurrentValue["FontMWidth"],20/CurrentValue["FontLineHeight"]}

If this is not correct stop reading now and let me know!

The problem I have is that from Mac to Windows I am unable to get the same dimensions:

img1 = Rasterize[Grid[RandomInteger[{1, 100}, {10, 8}],
   Alignment -> {Center, Center},
   Background -> None,
   BaseStyle -> 
    Directive[FontFamily :> CurrentValue["PanelFontFamily"], 
     FontSize :> CurrentValue["PanelFontSize"], 
     RGBColor[0, 0, 0.25]],
   Frame -> All,
   FrameStyle -> Directive[AbsoluteThickness[0.5], GrayLevel[0.7]],
   ItemSize :> {{80, 260, {130}}/CurrentValue["FontMWidth"], 
     22/CurrentValue["FontLineHeight"]},
   Spacings -> {0, 0}]]

enter image description here

ImageDimensions[img1]

Mma 8.0.4 on Mac 10.6.8

(* {751, 224} *)

Mma 8.0.4 on on Windows 7

(* {983, 274} *)

And when we check the em widths and line heights on both systems:

Mma 8.0.4 on Mac 10.6.8

{CurrentValue["FontMWidth"], CurrentValue["FontLineHeight"]}
(* {12.9621, 9.875} *)

Mma 8.0.4 on Windows

{CurrentValue["FontMWidth"], CurrentValue["FontLineHeight"]}
(* {12.6, 10} *)

In other words similar em widths and line heights. The upshot is that I have had problems creating a grid on a Mac that doesn't go offscale when viewed on Windows.

The screen resolutions (SystemInformation["Devices", "ScreenInformation"]) are 72 for Mac and 96 for Windows. The ratio of Windows image width for Mac width is close to 96/72 but the heights are not close to that ratio at all -- but in any case there is no mention of screen resolutions in the documentation.

Does anyone have any thoughts on what is happening here and how I can get a grid of the same size on both Mac and Windows?

Edit

I think this example by @SjoerdC.deVries nails it:

Grid[{{"MMMMMMMMMMM", "MMMMMMMMMMMMMMMMMMMM"}}, ItemSize -> 5,
 Spacings -> {0, 0}]

If the item size is in ems then you should expect only 5 "M" characters to fit in a grid cell ...right?

Following the comment from @Silvia I have tested Serif, Sans-serif and monospace fonts:

Sans-serif -- Helvetica gives 4Ms

enter image description here

Serif -- Times gives 4Ms

enter image description here

Monospace -- Monaco gives many Ms

enter image description here

Note that using lower case "m" made no difference. Note that further investigation shows that the word wrapping has an effect here. With just 5Ms the item size almost works.

enter image description here

Initial summary: So either the documentation is wrong, or it is incomplete, or the implementation is broken.

Subsequent summary: the problem seems to reside with how Mathematica determines the font being used when doing the size calculations. It clearly responds when StandardForm is changed but does not respond to local font usage (apparently). Otherwise an item size of x/CurrentValue["FontMWidth"] should surely deliver an item xMs wide.

Edit #2

Confirmed as a bug by WRI tech support.

Mike Honeychurch
  • 37,541
  • 3
  • 85
  • 158
  • 7
    Any thoughts? Yes: Attributes[Grid] == {Sadistic || Bugged} – Mr.Wizard Jan 15 '13 at 04:25
  • @Mr.Wizard yes very frustrating. – Mike Honeychurch Jan 15 '13 at 05:23
  • Do you really need it to be the exact same number of pixels or show the same amount of text? Since Windows uses more pixels to show text of the same point size, don't you actually want your grid to consume more pixels on Windows? – Verbeia Jan 15 '13 at 05:40
  • @Verbeia I make a notebook of a given size containing a grid of a given size. I looks a certain way on Mac but when opened in Windows is way way too big -- and i would prefer not to have scrollbars. I have both Mac and Windows computers but would prefer not to have to make a specific version (layout) for each. Presumably with pixels the screen resolution ratios between the platforms cannot account for some of the differences but not all. If an item size is a certain number of ems then surely we just need to know how many pixels to an em on each platform?? Ditto line heights. – Mike Honeychurch Jan 15 '13 at 05:50
  • Is Mathematica's definition of 'em' not the same as the accepted definition (same as point size)?. – cormullion Jan 15 '13 at 10:41
  • Seems version dependent. On my system, win7-64 I get {983, 274} on v8 and {863, 274} on v9. My screen is 120 dpi. Interestingly, if I put the seemingly useless (1 #;#)&@ before the first (of 4) CurrentValue in your code I get {804,254} and {707, 254}, respectively. – Sjoerd C. de Vries Jan 15 '13 at 11:13
  • @SjoerdC.deVries is CurrentValue["FontMWidth"] also varying? – Mike Honeychurch Jan 15 '13 at 19:33
  • Indeed, it is 12.6 and 14.4 for v8 and v9, respectively. – Sjoerd C. de Vries Jan 15 '13 at 20:04
  • @SjoerdC.deVries with this information are you able to derive -- perhaps by magic? -- how item sizes are determined :) – Mike Honeychurch Jan 15 '13 at 20:06
  • No idea how to approach this, but I'll be trying to gather some information that may be useful. For instance your line {CurrentValue["FontMWidth"], CurrentValue["FontLineHeight"]} takes up 829 pixels in v8 and 948 in v9. Their ratio is precisely that of their respective em values. So, it seems that the standard font differs between those versions. – Sjoerd C. de Vries Jan 15 '13 at 20:29
  • @SjoerdC.deVries where I say in bold to stop reading if I am wrong ...am i wrong ...misunderstanding things? If an item size is in em units and you specify the size as x/(em) then shouldn't you get the same size in the layout (x) -- and by extension same grid size -- regardless of the size of the em? – Mike Honeychurch Jan 15 '13 at 20:36
  • ItemSize is a strange beast. Check the first example on the help page and count the item size there in terms of number of characters and see if you understand that. I don't. Could also try Grid[{{"MMMMMMMMMM", "MMMMMMMMMMMMMMMMMMMM"}}, ItemSize -> 5]. – Sjoerd C. de Vries Jan 15 '13 at 20:43
  • As to your question: perhaps padding plays a role as well? – Sjoerd C. de Vries Jan 15 '13 at 20:49
  • It would be nice if we could have 2D layouts that just work! – Mike Honeychurch Jan 15 '13 at 20:56
  • @SjoerdC.deVries An interesting thing I found from your example is, if I set the "StandardForm" in the stylesheet to any (I guess) serif font, the output looks indeed 5 M width! But any sans-serif font would behave strange! (A screen capture) – Silvia Jan 16 '13 at 00:15
  • @Silvia that is an interesting development in this mystery. thanks for this information. – Mike Honeychurch Jan 16 '13 at 01:17
  • You're welcome! I always use my own stylesheet, with a serif font StandardForm, otherwise there would be no chance for me to notice that:) – Silvia Jan 16 '13 at 01:33
  • @Silvia I repeated this on my Mac. Note that your screen grab is actually 4Ms not 5. I randomly tested maybe 30 fonts and all (both serif and sans serif) bar the fixed width fonts Courier and Monaco produced 4Ms. To get 5Ms I had to make the item size 5.7! – Mike Honeychurch Jan 16 '13 at 02:47
  • It is indeed 5Ms in my screen grab. The 5th place is occupied by the \[Continuation] symbols. If there are no more than 5 Ms, they will be placed in the same row. (See my screen grab please.) And I agree with you that it's not about sans-serif or serif but something else, which makes it more confusing.. – Silvia Jan 16 '13 at 10:03
  • Another wrinkle, FontMWidth is exactly twice FontNWidth for all fonts I tested on my Mac. Surely this will all be ironed out when Mathematica goes HiDPI. – duozmo Nov 05 '13 at 23:11

1 Answers1

7

Here are a few things I have learnt trying to find work arounds -- they may or may not be useful to others. As I indicated in my final edit to the question Wolfram tech support have indicated that the behaviour is a bug.

1: Test items size for "M" width

The font family setting for ItemStylehas no effect on how the grid cell size is determined. It is solely controlled by BaseStyle but even then monospace fonts fail.

Grid[{{"MMMMM", "MMMMMMMMMM", "MMMMMMMMMMMMMMMMMMMM"}},
 Alignment -> {Left, Top},
 BaseStyle -> Directive[FontFamily -> "Times", 12],
 Frame -> All,
 ItemSize -> 5,
 Spacings -> {0, 0}]

enter image description here

enter image description here

enter image description here

2: Consistent grid pixel widths across platforms

A barrier is that CurrentValue["FontMWidth"] when entered as an ItemSize specification does not return the CurrentValue["FontMWidth"] of the font being used in the grid. So while something like

ItemSize->Dynamic@{100/CurrentValue["FontMWidth"],2}

might be expected to give the same pixel size per cell regardless of font it does not. A work around is to determine CurrentValue["FontMWidth"] for a given font separately. You could have a library with this information or you could do it dynamically.

This

img = Rasterize@
  Grid[{{"MMMMM", Dynamic@(m1 = CurrentValue["FontMWidth"]), 
     "MMMMMMMMMMMMMMMMMMMM"}},
   Alignment -> {Left, Top},
   BaseStyle -> Directive[FontFamily -> "Times", 12],
   Frame -> All,
   ItemSize -> Dynamic@(size/m1),
   Spacings -> {0, 0}]

ImageDimensions[img]

only works on a second and subsequent evaluation because the value of m1 isn't available the first time around. The way around this is to use Overlay

Clear[m1];

img = Rasterize@Overlay[{
    Grid[{{Dynamic@(m1 = CurrentValue["FontMWidth"])}},
     Alignment -> {Left, Top},
     BaseStyle -> Directive[FontFamily -> "Courier", 12, White],
     Frame -> All,
     Spacings -> {0, 0}],
    Grid[{{"MMMMM", "MMMMM", "MMMMMMMMMMMMMMMMMMMM"}},
     Alignment -> {Left, Top},
     BaseStyle -> Directive[FontFamily -> "Courier", 12],
     Frame -> All,
     ItemSize -> Dynamic@(size/m1),
     Spacings -> {0, 0}]
    }]

ImageDimensions[img]

On my Mac (10.6.8 V8.0.4) this renders a grid width of 302 pixels for all fonts I tried except "Georgia" which gave 305 pixels. I then switched to Windows (V8.0.4) and got the same pixel width as well as the same exception (and width) for "Georgia".

Mike Honeychurch
  • 37,541
  • 3
  • 85
  • 158
  • 2
    Btw, I'm no longer trying to use Grid for anything more than a grid structure. For size control I'm always setting Grid Spacings to {0,0} and I map/wrap items with Pane/Panel or friends with specific size (ofc don't forget to set ImageMargins->0). Just a loose thoughts. – Kuba Mar 13 '16 at 09:29