Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade \sqrt zoom and width #890

Merged
merged 9 commits into from
Sep 18, 2017
Merged

Upgrade \sqrt zoom and width #890

merged 9 commits into from
Sep 18, 2017

Conversation

ronkok
Copy link
Collaborator

@ronkok ronkok commented Sep 17, 2017

This PR does two things:

  1. It evades a Safari bug which improperly zooms nested SVGs. The fix applies to \sqrt and to single-ended stretchy arrows. These SVGs are now single level. Their tails are sliced off using CSS overflow: hidden. Double-ended stretchy arrows and horizontal braces are not fixed. Fixes part of \sqrt doesn't scale properly when browser is zoomed in or out on Safari #883.

  2. It adds a min-width to \sqrt so that a \sqrt{} with an empty argument will still render an SVG whose width matches the font glyph width. Fixes \sqrt{} doesn't render anything #888.

This PR evades a Safari bug which causes nested SVGs to zoom improperly. `\sqrt` and single-ended arrow SVGs have been modified.

These have been converted from nested SVGs to single level. Their long tails are now sliced off using CSS `overflow: hidden`.

Safari will still improperly zoom any double-ended stretchy arrows and horizontal braces.
Even if the function argument is empty, still render an SVG whose width equals the surd glyph.
@ronkok ronkok changed the title Upgrade \sqrt Upgrade \sqrt zoom and width Sep 17, 2017
@ronkok
Copy link
Collaborator Author

ronkok commented Sep 17, 2017

I've updated the test page.

@ronkok
Copy link
Collaborator Author

ronkok commented Sep 17, 2017

I've added a commit which fixes #889.

@kevinbarabash
Copy link
Member

I assumed that DisplayStyle and Smash screenshots hadn't actually changed b/c the screenshots were different for Chrome only. I should've looked at travis-ci output before making the P. @ronkok I'll send you another PR later this evening with these screenshots.

Copy link
Member

@kevinbarabash kevinbarabash left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice solution using overflow: hidden to avoid nested SVGs.

// still get a line. So, we use a simple heuristic to decide if we
// should omit the body entirely. (note this doesn't work for something
// like `\sqrt{\rlap{x}}`, but if someone is doing that they deserve for
// it not to work.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lol. I missed this comment in the previous review.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I take no credit for that comment. It was there before I got here.

Copy link
Member

@kevinbarabash kevinbarabash Sep 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's explains why I missed in previous reviews. 😅

src/delimiter.js Outdated
@@ -329,14 +329,12 @@ const sqrtSvg = function(sqrtName, height, viewBoxHeight, options) {
}
const pathNode = new domTree.pathNode(sqrtName, alternate);

let attributes = [["width", "100%"], ["height", height + "em"]];
const attributes = [["width", "400em"], ["height", height + "em"]];
attributes.push(["viewBox", "0 0 400000 " + viewBoxHeight]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be good to compute the width attribute in terms of the viewBox's width (or vice versa) so that they stay in sync.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've consistently used 400 ems for all the wide paths. I suppose that might not be obvious to someone looking at this cold. I'll look at it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is good enough for now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is good enough for now.

Let's suppose that someone other than me comes along and writes a PR with an SVG in it. They will need to coordinate viewBox geometry and document geometry. They will need to realize this early, when they are arranging the <path> geometry. So I am trying to leave multiple comments regarding the 1000:1 ratio.

Such is my reasoning for writing 400em. Reasoning with which you may disagree, but there it is.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to define a const hugeWidth = '400em' somewhere and use that variable repeatedly, instead of repeating a constant like this? (And one comment could explain why this choice is sensible.) Sorry if this suggestion doesn't make sense, coming from out of context.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A constant for 400em would do no harm. But the more critical concept is the 1000:1 ratio between ems and viewBox geometry. Some future contributor could waste a lot of time if they don't realize that early in their work. So any constant, defined in one place, would be improved by adding multiple comments, scattered widely.

src/delimiter.js Outdated
@@ -353,21 +351,24 @@ const sqrtSpan = function(height, delim, options) {
sizeMultiplier = newOptions.sizeMultiplier / options.sizeMultiplier;
spanHeight = 1 * sizeMultiplier;
span = sqrtSvg("sqrtMain", spanHeight, viewBoxHeight, options);
span.style.minWidth = "0.781em";
span.surdWidth = 0.833 * sizeMultiplier; // from the font.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is minWidth different from surdWidth?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not the best choice of variable names. For the CSS minWidth, I used the actual width of the ink in the glyph. What I have called surdwidth is actually the horizontal advance value from the font. Horizontal advance value is of course, a little wider than the ink.

I might adjust the surdwidth name and re-commit.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will also adjust the values of min-width. The paths in these surds have the xMin value baked into the SVG paths. So I'll increase each min-width by that amount.

span.surdWidth = 1.0 / sizeMultiplier; // from the font

} else {
// Tall sqrt. In TeX, this would be stacked using multiple glyphs.
// We'll use a single SVG to accomplish the same thing.
spanHeight = height / sizeMultiplier;
viewBoxHeight = Math.floor(1000 * spanHeight);
viewBoxHeight = Math.floor(1000 * height);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixes the issue with the tall \sqrt being the wrong size when sizing functions are involved?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct.

src/delimiter.js Outdated
@@ -329,14 +329,12 @@ const sqrtSvg = function(sqrtName, height, viewBoxHeight, options) {
}
const pathNode = new domTree.pathNode(sqrtName, alternate);

let attributes = [["width", "100%"], ["height", height + "em"]];
const attributes = [["width", "400em"], ["height", height + "em"]];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this have to be 400em as opposed to 100%?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll give 100% a try, but I don't think it will work. I'm now defining the viewBox dimensions in the same SVG as the width attribute. The height has a factor of 1000, so I think the width needs consistent treatment.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wrong. It does work to use width='100%'. Not only that but when width='100%', I can remove the CSS oveflow:hidden and it still works. So consider that done.

I wonder if that will cause sub-pixel changes in all the screenshots.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I retract my last statement. When I use width='100%, IE does not slice off the long tail. I going back to width='400em' and CSS overflow:hidden.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Final word. It turns out that it doesn't matter if I write width='400em' or width='100%'. It would matter, except that IE will not work unless I include CSS overflow:hidden. Once I include the CSS condition, both widths work. I'm going with 400em.

src/delimiter.js Outdated
span.style.minWidth = "0.781em";
span.surdWidth = 0.833 * sizeMultiplier; // from the font.
span.style.minWidth = "0.853em";
span.advanceWidth = 0.833 * sizeMultiplier; // from the font.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is clearer. Thank you.

Copy link
Member

@kevinbarabash kevinbarabash left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@kevinbarabash
Copy link
Member

@ronkok thanks for the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

\sqrt{} doesn't render anything
3 participants