16
$\begingroup$

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.

$\endgroup$
20
  • 7
    $\begingroup$ Any thoughts? Yes: Attributes[Grid] == {Sadistic || Bugged} $\endgroup$
    – Mr.Wizard
    Commented Jan 15, 2013 at 4:25
  • $\begingroup$ @Mr.Wizard yes very frustrating. $\endgroup$ Commented Jan 15, 2013 at 5:23
  • $\begingroup$ 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? $\endgroup$
    – Verbeia
    Commented Jan 15, 2013 at 5:40
  • $\begingroup$ @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. $\endgroup$ Commented Jan 15, 2013 at 5:50
  • $\begingroup$ Is Mathematica's definition of 'em' not the same as the accepted definition (same as point size)?. $\endgroup$
    – cormullion
    Commented Jan 15, 2013 at 10:41

1 Answer 1

7
$\begingroup$

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".

$\endgroup$
1
  • 2
    $\begingroup$ 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. $\endgroup$
    – Kuba
    Commented Mar 13, 2016 at 9:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.