Closed rgreinho closed 8 months ago
Since it's happening in resvg
too I presume that for some reason fontdb
fails to select the right font variant when converting the text into paths.
Just a dumb bug in the font-family
parser. We need a better one...
No regression test required after this correction?
font-family
parser should be rewritten anyway and then it will have proper testing.
Just so there is no duplicate work going on, I'm currently trying to rewrite the font-family
parser. Let's see how it goes.
Got it. I do not plan working on resvg anytime soon, sadly...
I have a small question, while working on this I noticed that as far as I can tell the current implementation does not support escaping of idents. So that you can for example write "\0054imes new Roman" instead of "Times New Roman".
Was it a conscious decision to not implement this or have you just not bothered to do it yet?
They are simply unimplemented. A very rare edge-case. You can try adding them to simplecss
. There are a couple things we do not support: https://github.com/RazrFalcon/simplecss?tab=readme-ov-file#limitations
By the way this bug isn't fixed yet, I think. I tried it out and can still reproduce it on main. This wasn't a font parsing issue but it's some issue within fontdb
. So maybe this should be reopened.
Okay so the reason is that for some reason both fonts are recognized as being style "Normal", so both are match. Now the question is whether it's a font issue or whether it's fontdb
not recognizing it correctly.
/// Returns style.
pub fn style(&self) -> Style {
let flags = SelectionFlags(self.fs_selection());
if flags.italic() {
Style::Italic
} else if self.version >= 4 && flags.oblique() {
Style::Oblique
} else {
Style::Normal
}
}
I think maybe the boolean condition here is mixed up?
Bit 9: If bit 9 is set, then this font is to be considered an βobliqueβ style by processes which make a distinction between oblique and italic styles, such as Cascading Style Sheets font matching. For example, a font created by algorithmically slanting an upright face will set this bit.
If a font has a version 4 or later OS/2 table and this bit is not set, then this font is not to be considered an βobliqueβ style. For example, a font that has a classic italic design will not set this bit.
I'm not sure what this implies though, obviously if the bit is not set then it's not oblique, I'm not sure how it relates to version 4... In any case, Dharma Gothic Italic's version seems to be 2 and that's why in this case, it matches Normal
instead of Oblique
. So this seems to be the root of the problem. I can't tell who's right and who's wrong though.
EDIT: Okay, nevermind, I should've kept on reading...
Versions 0 to 3: Only bit 0 (italic) to bit 6 (regular) are assigned. Bits 7 to 15 are reserved and must be set to 0. Applications should ignore bits 7 to 15 in a font that has a version 0 to version 3 OS/2 table.
So I guess this is the fault of the font then.
Thanks for the investigation!
So I guess this is the fault of the font then.
I guess so. TrueType parsing is a minefield. There is a spec and there is reality.
According to https://www.w3.org/TR/2018/REC-css-fonts-3-20180920/#font-style-matching :
If the value is βnormalβ, normal faces are checked first, then oblique faces, then italic faces. Faces with other style values are excluded from the matching set.
That's why fontdb
chooses Normal face instead of Bold. Therefore setting font-style="bold"
should help. Both SVG and font are not quite correct.
But honestly, I have no idea how it should be handled...
@LaurenzV I double checked and resvg selects the correct font on master. Try this:
<svg viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg">
<text x="300" y="500" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:240;font-family:DharmaGothicE-Bold, 'Dharma Gothic E';-inkscape-font-specification:'DharmaGothicE-Bold, Dharma Gothic E, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal">2023</text>
<text x="300" y="700" style="font-size:240;font-family:'Dharma Gothic E'">2023</text>
</svg>
As you can see, the bold font was choosen correctly. So resvg works just fine, at least "on my machine".
It works fine for me too, assuming that I don't have "Dharma Gothic E Italic" in my fonts folder.
But as soon as I add the italic variant font to my system fonts, the result looks like this:
Interesting. The font file I've found isn't marked as italic in OS/2 selection
bitflags. But Apple recognizes it as Italic anyway.
Maybe because post.italicAngle
isn't zero...
Tried looking into freetype2 sources, but got even more confused. Not only there are like 3 ways to mark a TrueType font as italic. But freetype2 treats Oblique as Italic to begin with. Which is against CSS.
Here is what freetype2 does.
I guess I should update ttf_parser::Face::is_italic
.
The font file I've found isn't marked as italic in OS/2 selection bitflags.
Yup, the same is the case for my file. Only the oblique flag is set, but since the version is 2 it will be ignored.
Mine doesn't even have Oblique. But all apps except resvg still match the correct font. Even italic-angle fix in ttf-parser didn't help. Mystery...
I'm not using ttf-parser methods in fontdb... Will publish a fix soon.
Here are the font files we are using in case that helps: https://github.com/PeopleForBikes/brokenspoke/tree/main/assets/fonts/DharmaGothicExtended.
Thanks!
Fixed in master.
I am reporting the issue here after I found a problem when using svg2pdf. Since they are using ReSVG for the rendering, they suggested to communicate the issue upstream as well.
So my issue is that when I am trying to convert an SVG file to a PNG file (or an PDF file when using svg2pdf), some fonts are not being taken into account, leading to an incorrect rendering. The problematic fonts are the
Dharma Gothic E
fonts in the example I chose.Using svg2pdf, I can see that they are correctly detected by fontdb:
But for some reason, the rendering is broken.
Here is a screenshot of the original SVG file:
And here the rendering using ReSVG:
Bellow is a snippet of the code I used to reproduce the issue:
However, when using Inkscape or CairoSVG the rendering works correctly.
Rendering with CairoSVG:
Rendering with Inkscape:
And bellow is code of the SVG I am trying to convert: