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

loadSVGFromString issue with letter-spacing #5417

Closed
rikkarv opened this issue Dec 3, 2018 · 14 comments · Fixed by #5424
Closed

loadSVGFromString issue with letter-spacing #5417

rikkarv opened this issue Dec 3, 2018 · 14 comments · Fixed by #5424

Comments

@rikkarv
Copy link

rikkarv commented Dec 3, 2018

Version
2.3.0 & 2.4.4

Test Case
https://jsfiddle.net/rikkarv/98mc60ow/8/ (for version 2.3.0)
https://jsfiddle.net/rikkarv/98mc60ow/7/ (for version 2.4.4)

Information about environment
chrome

Steps to reproduce
click on svg's (outline with dashed blue) and see output in fabric (outline with dashed red)

Expected Behavior
svg text should be imported to canvas with correct letter-spacing, despite the letter-spacing unit

Actual Behavior
If (fabric version 2.3.0) {
svg using letter-spacing value as "0.5em" works perfectly and outputs correct object.charSpacing value (500);
svg using letter-spacing value as "10" doesn't work and outputs a wrong object.charSpacing value (625);
} else if (fabric version 2.3.0) {
svg using letter-spacing value as "0.5em" doesn't work and outputs a wrong object.charSpacing value (0.5em);
svg using letter-spacing value as "10" doesn't work and outputs a wrong object.charSpacing value (10);
}

@rikkarv
Copy link
Author

rikkarv commented Dec 3, 2018

In my tests i get the following:

- Since version 2.4.1 to 2.4.4:

  • using svg with unit 'em', the method fabric.normalizeValue() calls parseUnit(0.5rem, 20px) and the parseUnit() returns NaN because fontSize is a string (20px instead of 20);

  • using svg with unit 'px', the method fabric.normalizeValue() calls parseUnit(10, 20px) and the parseUnit() returns 10, however parsed is NaN because fontSize is a string (20px instead of 20);

In both cases we get NaN because we are doing maths with a variable fontSize that is a string.
And in the final line of fabric.normalizeValue() we return the original value (0.5em in the first case and 10 in the second case) because isNaN(parsed) ? value : parsed

For this version i suggest changing to:
else if (attr === 'charSpacing') {
fixFontSize = Number(fontSize.replace('px', '');
parsed = parseUnit(value, fixFontSize) / fixFontSize * 1000;
}

- Since version 2.3.0 to 2.4.0:

  • using svg with unit 'em', works very good, the parsed value is 500 (= 0.5em);

  • using svg with unit 'px', the method fabric.normalizeValue() calls parseUnit(-3, 16) and the parseUnit() returns 10, the parsed value is 625 because fontSize is default value (16) and not the real value (20);

@rikkarv
Copy link
Author

rikkarv commented Dec 5, 2018

Please note that i pointed Chrome as environment.
The test cases in fiddle are easier to understand using Chrome, IE/Edge does not support letter-spacing without 'px' and that it is the reason why the second SVG is not right if using IE/Edge.
Using Chrome should be visible that both svg's have the same letter-spacing.
However, despite the lack of support from IE/Edge, in my case, it is mandatory to support "letter-spacing: 10" without refering "px". I think that Adobe Illustrator outputs svg like that.

@asturur
Copy link
Member

asturur commented Dec 8, 2018

The px should be solved.
I'll take the reference of https://jsfiddle.net/rikkarv/98mc60ow/7/ (for version 2.4.4) and be sure is fixed.
I did not get exactly the comment about fontsie being 16 vs 20. Can you clarify more?

@rikkarv
Copy link
Author

rikkarv commented Dec 8, 2018 via email

@rikkarv
Copy link
Author

rikkarv commented Dec 9, 2018

I'm looking at changelog, and in version 2.4.1 there is commit 0a9466a that come from "fix letterspace parsing #5258" and i believe from issue #5192.
Before 2.4.1 element.getAttribute('font-size') was returning null then fabric was always setting fontSize to fabric.Text.DEFAULT_SVG_FONT_SIZE (that returned the number 16). With the commit 0a9466a element.getAttribute('font-size') was replaced by ownAttributes['font-size'] that returns a string and breaks all the maths done at parseUnit() called by normalizeValue()

@asturur
Copy link
Member

asturur commented Dec 9, 2018

that commit did fix svgs anyway, so probably the truth is in the middle.

@asturur
Copy link
Member

asturur commented Dec 9, 2018

image

this seems more correct to me.
I ll link you to the code diffs, let me know what you think of it.

@rikkarv
Copy link
Author

rikkarv commented Dec 9, 2018

Thank you Andrea.

Later or tomorrow i will see in detail your idea.

However, i think the version before 2.4.1, was better. It seems that in those older versions the problem was not getting font-size when set inline in style attribute instead of font-size own attribute (like: style="font-size: 16px;").

Anyway, tomorrow i will you give notice of my tests in your pull request.

Please note that in your pull request "fontSize = parseUnit(ownAttributes['font-size'], parentFontSize);" ignores parentFontSize if ownAttributes['font-size'] has 'px' unit (because it falls in default case)

@asturur
Copy link
Member

asturur commented Dec 9, 2018

If it has px it has to ignore the parent.
The parent is used only when you are parsing a font-size expressed in 'em', so you need to read the container font-size.
While for other things like strokeWidth or letterSpacing expressed in 'em' you refer to current font-size.

I ll merge the code without publishing 2.4.5, let me know if you it still do not work.

@rikkarv
Copy link
Author

rikkarv commented Dec 9, 2018

The picture above is some kind of output of the 'test/visual/assets/svg_text_letterspacing.svg' file?

If so, you have to notice that the first text tag has font-size: 20px and letter-spacing: 20px which is equivalent to letter-spacing: 1em, right? So the letter-spacing of the first tag should be the double of the space compared to the second tag.

In the third and fourth tag, the 'em' is relative to 16px default?

Can you get the objects charSpacing property?

@asturur
Copy link
Member

asturur commented Dec 9, 2018

well the visual test compares what fabric parse and render with what the browser rendered on the same svg, important is that match.

@rikkarv
Copy link
Author

rikkarv commented Dec 10, 2018

I have already tested your changes and

ownAttributes['font-size'] = fontSize = parseUnit(ownAttributes['font-size'], parentFontSize);

is really doing his job. Now i have fontSize as a number instead of a string and the following maths doesn't break.

Thank you very much for your effort

@asturur
Copy link
Member

asturur commented Dec 10, 2018 via email

@rikkarv
Copy link
Author

rikkarv commented Dec 10, 2018

test.zip

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 a pull request may close this issue.

2 participants