# Incorrect widths of math elements in Gecko #558

Closed
opened this issue Aug 30, 2013 · 40 comments

Projects
None yet
3 participants
Contributor

### fred-wang commented Aug 30, 2013

 Follow-up of Peter's report on the dev list, there are issues with width of math elements in Gecko. MML.math has the following block: if (nMML.widthBug && !mtable.nMMLforceWidth && mtable.nMMLlaMatch))) { // // Convert size to ex's so that it scales properly if the print media // has a different font size. // parent.style.width = (math.firstChild.scrollWidth/nMML.ex).toFixed(3) + "ex"; }  As I read it, this will not be executed if there is not any mtable. I think we disabled the correction when we added the mlabeldtr workaround in 0891402#L5L621 (issue #356). The condition should probably be:  nMML.widthBug && !(mtable.nMMLhasLabels && (mtable.nMMLforceWidth || !mtable.nMMLlaMatch))  But then this gives too large widths. It seems to be due to the conversion to ex which was introduced in debc240#L3L618 (issue #386)
Member

### pkra commented Aug 30, 2013

 Thanks, Fred!

### fred-wang referenced this issue Sep 9, 2013

Closed

#### Remove the automatic resizing of formulas in Native MathML #564

Contributor Author

### fred-wang commented Sep 10, 2013

 Peter's original test case was test/sample-mml but it's somewhat difficult to reproduce. Here are some test cases related to this bug: 

Gecko's bug 415413 (for the Zoom we have a workaround):

$ffffffffff$

Gecko's bug 415413 with mlabeledtr

$LABEL ffffffffff$

Gecko's bug 415413 with mlabeledtr

$LABEL ffffffffff$ 
Contributor Author

### fred-wang commented Sep 10, 2013

 So here is how it looked like in v2.1: The "ex" changes of issue386 made the widths too large: The changes for the mlabedledtr workaround removed the width correction in general:
Contributor Author

### fred-wang commented Sep 10, 2013

 So I've committed a patch that restores the width correction of the math in Gecko's native MathML but removes the incorrect fix of issue #386 in that case (I guess the latter is less likely to happen than the former). However, the width may still be wrong for mtable cells so we definitely need to fix bug 415413 upstream. I suspect that in general, each time we measure some width in native MathML (not only Gecko), this width is likely to change after Web fonts are loaded. So in particular we'd rather implement mlabeledtr upstream and remove the workaround introduced in #356 in the future (or we'll have to do ugly measure verifications on each math, which will be a performance loss for the native MathML). Having #301 to ensure correct stretching of operators is more important to me and anyway people will always be able to use Web fonts themselves.
Member

### dpvc commented Sep 12, 2013

 I am not able to reproduce the problem that you are seeing. With the v2.1, the v2.2, and the develop branches, I get correct results for your test file. Your image looks like it is using the MathJax fonts, is that correct? Are they locally installed, or web-based?
Member

### dpvc commented Sep 12, 2013

 Sorry, I forgot to switch to MathML output (D'oh!)
Contributor Author

### fred-wang commented Sep 12, 2013

 They were local fonts. The result may well be system-dependent. For example I didn't see Peter's original bug without trying with a larger zoom. That may depend on default font preference of Firefox (font-family and font-size). Probably that worked on your system and so didn't see the issue when fixing the bug.
Contributor Author

### fred-wang commented Sep 12, 2013

 Sorry, I forgot to switch to MathML output (D'oh!) OK :-)
Member

### dpvc commented Sep 12, 2013

 Here's what I've found out about the problem. It used to be that the $ element itself had the wrong width, which is why we added the , and that even with the  the math element didn't get the right width. The latter seems to have been fixed (at least with the test cases I've tried). So it seems that [itex] now has the correct width. The problem, however, is that that width does not propagate up to the enclosing element properly (at least when that element is "shrink-wrap" element like a   or  or an element with display:inline-block). The following code shows the issue:  Firefox MathML size errors ffffffffff$

$ffffffffff$

 The output for me is the following: Note that the true width of the math is 76 pixels, while the width of the containing element ( or ) is only 53. The container has a red border and the math has a black one. The second example shows that the same is true internally within the math, in this case the  also fails to get the width of its content correct. This has nothing to do with MathJax, as this example doesn't load MathJax. MathJax tries to compensate for the first error by transferring the scrollWidth of the top-level  to the  that contains it. MathJax doesn't currently try to adjust the width in the second case (the  one), though it does add an explicit  to overcome other problems. (Fred points this out above where he says the upstream bug needs to be fixed.) Fred correctly points out that this correction was lost in the change for the  support. I suspect he is also right that the ex versus px change is probably the reason for the wrong amount of space being reserved for the expression. I want to look into this further, as it suggests that the determination of the ex value is wrong. This could also account for your seeing font sizes that are too big.
Member

 I suspect that in general, each time we measure some width in native MathML (not only Gecko), this width is likely to change after Web fonts are loaded. The only widths that are being measured (currently) is the size of the  inside the $ element. And yes, you are right that if web fonts are used, that means the size could change after we have set it. That is one of my concerns about using web fonts for MathML. Since Gecko doesn't propagate the sizes of the math element properly, we have to correct the size of the container (since it is a span with display:inline-block, one of the cases that Gecko gets wrong), otherwise all the math will have the wrong amount of space, not just math that uses web fonts. we'd rather implement mlabeledtr upstream and remove the workaround introduced in #356 in the future (or we'll have to do ugly measure verifications on each math, which will be a performance loss for the native MathML). I'm not sure I understand the linkage between the  workaround and the measurements for the Gecko bug with wrong widths. There is no special measuring in the mlabeledtr code, so that patch is independent of setting the widths of the container spans, as far as I can tell. Yes, having  work in Gecko would be great, and I'm all for that, but I don't see how it affects the decision about setting the size of the  that contains the resulting [itex] element. That has to be done in either case. The only solution I can think if is the one I suggested in #301 and that you suggest above: looping through the math periodically to see if the width has changed and updating it. It is ugly, but it is not that inefficient (it is merely checking if the top-level 's width is no longer the same size as the containing 's width. Running through the math elements to check this should be reasonably fast, and if one does all the checking before making any changes, you should not get the multiple reflow problem in the situation where something has changed. Certinaly fixing the measurement errors in Gecko is a better solution, but we have to work with the Firefox browser as it currently stands (and will still have to support some older versions even once it is fixed, at least for a while). Contributor Author ### fred-wang commented Sep 12, 2013  There are two distinct Gecko bugs here: clientWidth, clientHeight, offsetLeft & offsetTop values are incorrect. Boris Zbarsky says they are not supposed to be used on MathML see https://bugzilla.mozilla.org/show_bug.cgi?id=491668#c12. Intrinsic widths of some token elements are incorrectly computed (bug 415413). This affects the layout of elements like table cells. Contributor Author ### fred-wang commented Sep 12, 2013  since it is a span with display:inline-block, one of the cases that Gecko gets wrong), Why do we have to put each math element in an inline-block span? I'm not sure I understand the linkage between the workaround and the measurements for the Gecko bug with wrong widths. There is no special measuring in the mlabeledtr code, so that patch is independent of setting the widths of the container spans, as far as I can tell. Yes, having work in Gecko would be great, and I'm all for that, but I don't see how it affects the decision about setting the size of the that contains the resulting element. I think I remember that in mlabeledtr we take the width of the parent table at some point but didn't check in details. Anyway, my point is that we should ideally not measure anything in the NativeMML code since that's a performance loss and interfere with the user's CSS. So things like #564 must be fixed now. Of course if there are bugs, we have no other choice than to workaround them and to temporarily measure sizes. Another bug in Gecko affecting height: Member ### dpvc commented Sep 12, 2013  Note that we don't use any of clientWidth, clientHeight, offsetLeft, or offsetTop from MathML elements in MathJax. Never have. I certainly don't know anything about how Gecko works internally, but it doesn't to me that this problem is about the widths of token elements. Those all seem to have the correct widths. Even the math element has the correct width. It is that that width doesn't seem to be recognize by the parent element. Unless what you are saying is that the parent element asks the math element for its width, and the math element asks the mrow, and the mrow asks the token elements, and they report something wrong, and the mrow adds up the wrong values and reports it back to the math element, and it reports back the wrong sum to the parent. In that case, I don't see how the scrollWidth and the bounding rect size can be right. But, as I said, I don't know anything about the internals of Gecko; it just seems weird. Member ### dpvc commented Sep 12, 2013  I think I remember that in mlabeledtr we take the width of the parent table at some point but didn't check in details. There is a check to see if there is an explicit width that is a percentage, as the work around is different in that case, but no actual measuring of elements is performed. Contributor Author ### fred-wang commented Sep 12, 2013  Note that we don't use any of clientWidth, clientHeight, offsetLeft, or offsetTop from MathML elements in MathJax. Never have. I just copied the bug report name, but the comment holds for all the offset_, scroll_ and client* metrics I think. I remember that in the Zoom code we use one on the math. I certainly don't know anything about how Gecko works internally, but it doesn't to me that this problem is about the widths of token elements. Those all seem to have the correct widths. The intrinsic widths of these tokens are incorrect, not the final ones that are returned by Javascript. That means it will affect the width of elements like table cells that require these intrinsic widths to decide their layout. So finally, the final widths of the cells get wrong, but that's because of the incorrect intrinsic widths of tokens. Member ### dpvc commented Sep 12, 2013  Another bug in Gecko affecting height: Personally, I think the current behavior is correct. It's like a span with a large image in it, it's height is still that of a standard line. But that may be a matter of viewpoint. Contributor Author ### fred-wang commented Sep 12, 2013  There is a check to see if there is an explicit width that is a percentage, as the work around is different in that case, but no actual measuring of elements is performed. OK, I didn't check in details. Contributor Author ### fred-wang commented Sep 12, 2013  Personally, I think the current behavior is correct. It's like a span with a large image in it, it's height is still that of a standard line. But that may be a matter of viewpoint. OK, that was just to point it out. But I don't think it affect MathJax. Member ### dpvc commented Sep 12, 2013  I just copied the bug report name, but the comment holds for all the offset_, scroll_ and client* metrics I think. Comment 14 on that bug report indicates scrollWidth is defined for all elements (and this seems to be supported by the CSSOM View Model documentation. According to that, the clientWidth should be defined and 0 (my mistake saying 0 was wrong). Contributor Author ### fred-wang commented Sep 17, 2013  @dpvc you can take this bug if you wish. At the moment, the best I can see is 110b149, given that the print bug in native MathML is less likely to show up. Member ### dpvc commented Sep 17, 2013  Yes, I'll look into it and see if I can figure out what is wrong. The px width will certainly work (other than the print problem when the media scaling is different from the screen scaling), but I'd like to figure out why the ex width is off. ### ghost assigned dpvcSep 17, 2013 ### dpvc pushed a commit to dpvc/MathJax that referenced this issue Sep 24, 2013  Properly handle the width of math and mtd elements by explicitly sett…  …ing the width from the child mrow (works around FF bug that gets these widths wrong). Resolves issue mathjax#558.  ed932ec  Member ### dpvc commented Sep 24, 2013  I found the problem with the widths when given in ex's: the span being styled was inside the one that had the font-size style use for scaling the math, and that extra scaling wasn't taken into account. I have fixed that, and the sizes used for the containers now match the size of the math for me. See if that is the case for you as well. I've also added a work-around for the problem with the  widths as well, so the table cells should now get the proper width also (so my second example in the test file above should work properly in MathJax). I still have to add the option to disable automatic scaling, and to do the loop that checks if web fonts have changed the sizes of the math. I'll post again when I have that taken care of. Contributor Author ### fred-wang commented Sep 25, 2013  I'm not sure the loop that checks if the surrounding font size has changed is necessary for MathML, since I expect the incorrect width to be fixed in future versions of Gecko and the workaround to be removed in the next version when we deprecate old browsers. However, this will still be necessary for the HTML-CSS / SVG output, if that's what you mean. Member ### dpvc commented Sep 29, 2013  My issue558-noscale branch adds a matchFontHeight option to the HTML-CS and NativeMML output jax to control whether font height matching will be performed. (Note that it doesn't make sense to do this with SVG, since we aren't using system fonts, so the size matching comes automatically.) ### dpvc pushed a commit to dpvc/MathJax that referenced this issue Sep 29, 2013  Add a loop to check for font changes due to web fonts either in the m…  …ath or the surrounding font. Resolves issue mathjax#558.  c777547  ### dpvc pushed a commit to dpvc/MathJax that referenced this issue Sep 29, 2013  Add support for matching web fonts in HTML-CSS. Change the names of t…  …he paramters that control it in NativeMML (so both have the same names). Add a global matchWebFonts option to control whether to do the loop to check for web fonts (off by default). Resolves more of issue mathjax#558.  a012354  Member ### dpvc commented Sep 30, 2013  OK, these last two commits (to the issue558-loop branch of my fork of MathJax) include support for handling pages that include web fonts in the text around the math, or in CSS controlling the native MathML rendering. This is done through a loop that checks if the ex size of the surrounding font or the MathML font has changed, and if not whether the width of the math has changed (presumably due to the loading of a web font). If a change is detected, the width reserved for the math is reset, and the font-siz recalculated (if necessary). There is a global parameter matchWebFonts that controls whether the output jax perform these tests. It is off by default (since it performs a loop after MathJax has typeset anything). There are also fontCheckDelay and fontCheckTimeout (for each output jax) that controls the initial delay between checks (this gets longer for each loop), and the total time elapsed when the loop should be terminated. One pass through the loop is pretty fast (60 equations used about 15 to 20 milliseconds for me), and it doesn't seem to interfere with scrolling and other user interaction. For the HTML-CSS output, if a change is detected, the output is re-rendered. This is because the output is sensitive to font-size changes, particularly at small font sizes, and also because dimensions using absolute units (like inches or pixels) need to be recomputed when the surrounding font's em-size changes. This may need more performance data to see if that is reasonable or not. The SVG output doesn't need such a loop since it scales automatically (its size is given in units of ex, so a change to the surrounding font changes it automatically). Technically, we should re-render it on a font change as well, since the absolute units would need to be adjusted. But it probably isn't worth it, so I didn't add the loop. If you think it should be added for completeness, I can do that. Perhaps being able to disable the loop in individual output jax would be useful as well. Member ### dpvc commented Sep 30, 2013  I'm not sure the loop that checks if the surrounding font size has changed is necessary for MathML, since I expect the incorrect width to be fixed in future versions of Gecko and the workaround to be removed in the next version The loop actually serves two purposes: detecting web font's within the MathML itself (and fixing the width values when that occurs), and detecting detecting font changes either within or without the MathML so that the math font can be scaled to match the surrounding text. While the first of these may be fixed in the next Firefox release, I suspect the second will not be resolved for some time, so if the MathML uses web fonts (as you have planned to do), or if the page does, then I still think there is a need for this feature. Of course, the page author can disable it (it is opt-in rather than opt-out anyway at the moment). I also added matchFontHeight option to NativeMML and HTML-CSS output to allow you to opt out of the font matching font-size setting. Member ### dpvc commented Sep 30, 2013 Member ### dpvc commented Sep 30, 2013  Why do we have to put each math element in an inline-block span? It is used for various event handlers for things like zoom click or hover events, and for the "discoverability" interface (which is not on by default, but is still there). For example, the border of this span can be made to "fade in" when the mouse is over the math, and a menu icon can appear at the upper right corner to give access to the contextual menu. This was designed to make the mobile interface easier, but the decisions about how to proceed with it where grounded when Robert went into the hospital. Contributor Author ### fred-wang commented Sep 30, 2013  While the first of these may be fixed in the next Firefox release, I suspect the second will not be resolved for some time I hope the first to be fixed in Gecko Nightly soon. As for the second, this could just be modifying the CSS stylesheet not to change the font-family on the element, so that the font for the math matches the font of the surrounding text by default. However, a mechanism to automatically rescale the font size of the math will probably never be implemented. If a user decides to set the font-family or font-size on the math, then the native rendering engine must use that. While it could be considered a "feature" for a Javascript library as MathJax, it is just a CSS bug for a native rendering engine. It is used for various event handlers for things like zoom click or hover events, and for the "discoverability" interface (which is not on by default, but is still there). This is a very bad idea if linebreaking is implemented correctly in native MathML in the future and we'll have to reconsider this choice if we don't want to have yet another CSS compatibility issue. Consider for example  Blah Blah Blah Blah Blah Blah [itex]x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x$ Blah Blah Blah Blah Blah Blah $x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x$ Blah Blah Blah Blah Blah Blah

 or equivalently, with pure HTML: 

Blah Blah Blah Blah Blah Blah x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x Blah Blah Blah Blah Blah Blah x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x Blah Blah Blah Blah Blah Blah

 and here how they render in Gecko: while an inline frame splits into several lines and behaves well with respect to the surrounding text, an inline-block frame does not split and the linebreaking of the MathML happens inside that inline-block itself, without interaction with the surrounding text. To say it simple, it's just like if we were putting all the equations inside a HTML table with a single cell, preventing any interaction with the surrounding text...

Closed

Member

### pkra commented Sep 30, 2013

 Great to hear that the FF nightly might fix this. How much does the NativeMML output differentiate between browser versions? Weighing accessibility (zoom, discoverability) against line breaking is a tough call. Perhaps we can solve some of these problems by using page-wide tools, e.g. zoom libraries.
Member

### dpvc commented Oct 1, 2013

 It is probably worth making this a separate issue for future consideration. Changing the display:inline-block span would require changes in a variety of other locations in the code, so is non-trivial.
Member

### dpvc commented Oct 1, 2013

 Perhaps since the web-font-testing loop is off by default, that code should be made into an extension rather than be included in the core? (If so, however, that would also mean that the future use of web fonts for NativeMML output would also have to be an extension, since it would rely on this one.)
Contributor Author

### fred-wang commented Oct 2, 2013

 there is a "console.log(element); " debug logging yes, I think we should make the web-font-testing loop an extension. I still believe the ideal goal will be to make MathJax entirely compatible with the browser layout engine (at least for the MathML mode). So hopefully the scale & width hacks for native MathML won't be necessary anymore in the future and in that case we will be able to add Web fonts without a testing loop. I think for consistency we should do the web-font-testing loop for SVG too. Having a single option for all the output modes makes sense to me: if people use Web fonts for the text on their page they are likely to use them whatever the output mode. However, it's easy to change that later if necessary (for example people might want to use Web fonts for the native MathML only).
Member

### dpvc commented Oct 2, 2013

 Sorry about the debug message. I thought I had caught them all. OK, I'll turn the loops into an extension. About SVG, remember that the font height matching is automatic in that case, so the only advantage to doing this will be to adjust the size of dimensions given in absolute units within the math. Since those are seldom used, and it requires re-rendering the math to do it, I'm not sure it is worth it. But I can certainly add it.
Contributor Author

### fred-wang commented Oct 2, 2013

 About SVG, remember that the font height matching is automatic in that case, so the only advantage to doing this will be to adjust the size of dimensions given in absolute units within the math. Since those are seldom used, and it requires re-rendering the math to do it, I'm not sure it is worth it. But I can certainly add it. Yes, I got that. To be honest, I don't really have a preference but that seemed weird to not have the option for SVG. In that case, perhaps use one config option per rendering mode so that people can e.g. enable it for HTML but not SVG. And people who really need it for SVG could enable it too.
Member

### dpvc commented Oct 2, 2013

 OK, sounds good.
Member

### dpvc commented Oct 7, 2013

 I've moved the code to an extension, and made it possible to configure the renderers separately. This is the issue558-loop branch. => Ready for Review
Contributor Author

### fred-wang commented Oct 7, 2013

 I have not checked in details, but I'm OK with the changes in general so let's merge them to start the testing. => Ready For Release

### dpvc pushed a commit that referenced this issue Oct 7, 2013

 Merge pull request #598 from dpvc/issue558-loop 
Improve width computation for MathML elements (issue #558)
 ff06343 
Member

### dpvc commented Oct 7, 2013

 => Merged

### dpvc closed this Oct 7, 2013

Contributor Author

### fred-wang commented Oct 9, 2013

 There seem to be a couple of failures do to spacing changes. I wonder if this is caused by #558

Closed

Closed