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

Incorrect rendering of triple-wide code ligatures in NetBeans on Windows #369

Closed
javlaks opened this issue Aug 4, 2020 · 20 comments
Closed
Assignees

Comments

@javlaks
Copy link

javlaks commented Aug 4, 2020

Problem description
Your font is amazing, beautiful, however, some ligatures are not being displayed correctly in NetBeans

Expected behavior
Display ligatures correctly as in Visual Studio Code

Screenshots
This is from NetBeans 12.0
image

This is from Visual Studio Code 1.47.3
image

To Reproduce
Steps to reproduce the behavior:

  1. Install the font
  2. Change the default font to Rec Mono Duotone (or any style for ligatures, duotone also has different italic and regular)
  3. Apply changes
  4. See in the code

Environment

  • OS: Windows 10 v1909
  • NetBeans: 12.0
  • Java: 14.0.2+12
  • Fonts: 1.053

Additional context
Other ligatures fonts as JetBrains Mono or Fira Code, doesn't have this issue. They display correctly

@arrowtype
Copy link
Owner

Huh, that is a strange effect. 🤔

I’ve tried to copy the feature code for the *** ligature from Fira Code, but in my VM, Fira Code basically isn’t working at all in Netbeans, so I am unable to properly test this.

When you have time, could you perhaps try out the fonts at https://github.com/arrowtype/recursive/tree/3908d42b866d7c56c6de17612775fe8d0501e171/fonts/rec_mono-for-code, and let me know whether the *** is rendering any differently, now?

@arrowtype arrowtype changed the title Wrong display at NetBeans Incorrect rendering of triple-wide code ligatures in NetBeans on Windows Aug 6, 2020
@arrowtype arrowtype self-assigned this Aug 6, 2020
@javlaks
Copy link
Author

javlaks commented Aug 6, 2020

The fix doesn't work. And just to complement, the issue is not only for three ***, it happens with each ligature

This is Rec Mono
image

This is Fira Code
image

This is JetBrains Mono
image

This is a closer image of the issue
image

One character looks good, two are cutting a little, and three, the first char and the half of the second one are not being displayed.

@arrowtype
Copy link
Owner

Thanks for checking on that!

Thanks also for the clear screenshots. I realized that the issue was in many of the ligatures, but wanted to try fixing just one to start, as a test of where the problem might be coming from.

I'll have to work on other issues before checking further into this one, but will try to get to it soonish!

@iansan5653
Copy link

iansan5653 commented Aug 7, 2020

I'm also seeing exactly the same issue in IntelliJ on Windows with the code fonts (both linear and duotone). Notably I did not see this in Fira Code (ie with the *** ligature) or I'd assume it's an IntelliJ bug. Unfortunately I cannot provide screenshots as I am not permitted to take screenshots of my work machine, but the effect is exactly the same.

@iansan5653
Copy link

What's really bad is that the <!-- ligature totally disappears in my editor.

@arrowtype
Copy link
Owner

Sorry, I wish the fix were more obvious. For now, I suggest either configuring a version of Rec Mono for Code that doesn't have code ligatures, or using another font. You can configure a custom build with:

https://github.com/arrowtype/recursive-code-config

I will try to fix this, but it will probably take a few weeks to get to it.

@javlaks
Copy link
Author

javlaks commented Aug 25, 2020

Not sure if this help to solve this issue.

In JetBrain Mono, at the moment to create NO Ligatures versions, they are removing the properties for the ligatures to the font with Ligatures.

Not sure if these properties exist in Recursive Code

image

You can check the complete code in JetBrains Mono Script

@javlaks
Copy link
Author

javlaks commented Aug 25, 2020

Checking in FontDrop both font, I cann see these ddiferences

JetBrains Mono has kern attribute
image

In Scripts section, they have DFLT, cyrl & latn, and Recursive only has DFLT
image

Hope this information will be helpful :)

@arrowtype
Copy link
Owner

arrowtype commented Aug 28, 2020

Thanks, @javlaks! Hmm, that is interesting to see how JetBrains has approached their "No Ligature" font and that may obliquely provide clues as to how their normal ligatured font works. But, that is probably more as a way to keep the NL version smaller for the web than directly making the ligature version work in Netbeans.

I’ve asked whether the kern is intentional – it’s barely there, so it makes functionally no difference, unless is makes all the difference.

Assuming that isn’t the relevant difference, the main approach here will be to use fdiff to compare the font internals, and look specifically at various metadata that could be making this difference, especially in the head and OS/2 tables. Maybe also the maxp table could be meaningful, though I haven’t really had to think about this one before.

Things that interest me most at first look are below (JB Mono is "before" - and Recursive is "after" +). A more comprehensive diff follows.

# maxp
-    <maxPoints value="400"/>
-    <maxContours value="100"/>
-    <maxCompositePoints value="123"/>
+    <maxPoints value="332"/>
+    <maxContours value="8"/>
+    <maxCompositePoints value="186"/>
-    <maxZones value="2"/>
-    <maxTwilightPoints value="400"/>
-    <maxStorage value="624"/>
-    <maxFunctionDefs value="141"/>
+    <maxZones value="1"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
-    <maxStackElements value="746"/>
-    <maxSizeOfInstructions value="3605"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
-    <maxComponentDepth value="2"/>
+    <maxComponentDepth value="3"/>

# OS/2
-    <xMax value="680"/>
+    <xMax value="2358"/>

# head
     <panose>
-      <bFamilyType value="2"/>
-      <bSerifStyle value="11"/>
-      <bWeight value="5"/>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="0"/>
       <bProportion value="9"/>
-      <bContrast value="2"/>
-      <bStrokeVariation value="1"/>
-      <bArmStyle value="2"/>
-      <bLetterForm value="5"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
       <bMidline value="0"/>
-      <bXHeight value="4"/>
+      <bXHeight value="0"/>
     </panose>
full diff of maxp, head, OS/2 (Click to expand)
--- /Users/stephennixon/Library/Fonts/JetBrains Mono/JetBrainsMono-Regular.ttf	2020-08-27T07:05:42-04:00
+++ /Users/stephennixon/type-repos/recursive/fonts/ArrowType-Recursive-1.062/Recursive_Code/Casual/RecMono-Casual-1.062.ttf	2020-08-27T16:46:35.222633-04:00
@@ -4,38 +4,38 @@
   <maxp>
     <!-- Most of this table will be recalculated by the compiler -->
     <tableVersion value="0x10000"/>
-    <numGlyphs value="1012"/>
-    <maxPoints value="400"/>
-    <maxContours value="100"/>
-    <maxCompositePoints value="123"/>
+    <numGlyphs value="1260"/>
+    <maxPoints value="332"/>
+    <maxContours value="8"/>
+    <maxCompositePoints value="186"/>
     <maxCompositeContours value="6"/>
-    <maxZones value="2"/>
-    <maxTwilightPoints value="400"/>
-    <maxStorage value="624"/>
-    <maxFunctionDefs value="141"/>
+    <maxZones value="1"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
     <maxInstructionDefs value="0"/>
-    <maxStackElements value="746"/>
-    <maxSizeOfInstructions value="3605"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
     <maxComponentElements value="3"/>
-    <maxComponentDepth value="2"/>
+    <maxComponentDepth value="3"/>
   </maxp>
 
   <head>
     <!-- Most of this table will be recalculated by the compiler -->
     <tableVersion value="1.0"/>
-    <fontRevision value="2.002"/>
-    <checkSumAdjustment value="0x79472689"/>
+    <fontRevision value="1.062"/>
+    <checkSumAdjustment value="0x60629b0b"/>
     <magicNumber value="0x5f0f3cf5"/>
-    <flags value="00000000 00000111"/>
+    <flags value="00000000 00000001"/>
     <unitsPerEm value="1000"/>
-    <created value="Wed Aug 26 09:25:38 2020"/>
-    <modified value="Thu Aug 27 07:39:24 2020"/>
-    <xMin value="-1735"/>
-    <yMin value="-365"/>
-    <xMax value="680"/>
-    <yMax value="1075"/>
+    <created value="Thu Aug 27 17:23:42 2020"/>
+    <modified value="Thu Aug 27 20:46:35 2020"/>
+    <xMin value="-244"/>
+    <yMin value="-367"/>
+    <xMax value="2358"/>
+    <yMax value="1129"/>
     <macStyle value="00000000 00000000"/>
-    <lowestRecPPEM value="7"/>
+    <lowestRecPPEM value="6"/>
     <fontDirectionHint value="2"/>
     <indexToLocFormat value="0"/>
     <glyphDataFormat value="0"/>
@@ -48,7 +48,7 @@
     <xAvgCharWidth value="600"/>
     <usWeightClass value="400"/>
     <usWidthClass value="5"/>
-    <fsType value="00000000 00001000"/>
+    <fsType value="00000000 00000000"/>
     <ySubscriptXSize value="650"/>
     <ySubscriptYSize value="600"/>
     <ySubscriptXOffset value="0"/>
@@ -57,41 +57,41 @@
     <ySuperscriptYSize value="600"/>
     <ySuperscriptXOffset value="0"/>
     <ySuperscriptYOffset value="350"/>
-    <yStrikeoutSize value="50"/>
-    <yStrikeoutPosition value="320"/>
+    <yStrikeoutSize value="45"/>
+    <yStrikeoutPosition value="282"/>
     <sFamilyClass value="0"/>
     <panose>
-      <bFamilyType value="2"/>
-      <bSerifStyle value="11"/>
-      <bWeight value="5"/>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="0"/>
       <bProportion value="9"/>
-      <bContrast value="2"/>
-      <bStrokeVariation value="1"/>
-      <bArmStyle value="2"/>
-      <bLetterForm value="5"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
       <bMidline value="0"/>
-      <bXHeight value="4"/>
+      <bXHeight value="0"/>
     </panose>
-    <ulUnicodeRange1 value="00100000 00000000 00000010 00000111"/>
-    <ulUnicodeRange2 value="00000000 00000000 00011000 00000001"/>
+    <ulUnicodeRange1 value="10100001 00000000 00000000 11111111"/>
+    <ulUnicodeRange2 value="01010000 00000000 11100000 01111011"/>
     <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
     <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
-    <achVendID value="JB  "/>
+    <achVendID value="ARRW"/>
     <fsSelection value="00000000 11000000"/>
-    <usFirstCharIndex value="0"/>
-    <usLastCharIndex value="65279"/>
-    <sTypoAscender value="970"/>
-    <sTypoDescender value="-270"/>
+    <usFirstCharIndex value="13"/>
+    <usLastCharIndex value="64260"/>
+    <sTypoAscender value="950"/>
+    <sTypoDescender value="-250"/>
     <sTypoLineGap value="0"/>
-    <usWinAscent value="1085"/>
-    <usWinDescent value="270"/>
-    <ulCodePageRange1 value="01100000 00000000 00000001 10010111"/>
+    <usWinAscent value="1207"/>
+    <usWinDescent value="271"/>
+    <ulCodePageRange1 value="01100000 00000000 00000001 10010011"/>
     <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
-    <sxHeight value="550"/>
-    <sCapHeight value="730"/>
+    <sxHeight value="532"/>
+    <sCapHeight value="700"/>
     <usDefaultChar value="0"/>
     <usBreakChar value="32"/>
-    <usMaxContext value="5"/>
+    <usMaxContext value="6"/>
   </OS_2>
 
 </ttFont>

@iansan5653
Copy link

For some reason, with the latest IntelliJ and latest Recursive, the issue is fixed for Duotone only. It still happens for Linear, Casual, and SemiCasual.

@arrowtype
Copy link
Owner

Ahhh looking at these fonts in a code editor showed me something which I bet is responsible for this issue.

Rec Mono’s ligatures are made monospace by overflowing to the right of their space, and adding empty spaces. Fira Code & JB Mono do the reverse, putting blank spaces & overflow to the left of glyphs.

My guess is, maybe NetBeans renders glyphs in a way that constrains overflow to the right to 150% of width, but allows more overflow to the left due to fonts like Fira Code. Or, maybe it’s to do with the way glyphs overlapping – glyphs that come after others will always overlap them.

I’ll figure out how to reverse my approach, then try to test it out / ask whether it works for people.

Recursive code ligature for ===

Fira Code ligature for ===

JetBrains Mono ligature for ===

@arrowtype
Copy link
Owner

Oh, hmm. No, it isn’t quite as simple as I had expected.

The hmtx table includes the width and "left side bearing" for each glyph, and if you compare JB Mono & Rec Mono, these are very similar:

- <mtx name="equal_equal_equal.liga" width="600" lsb="-1120"/> <!-- JB Mono -->
+ <mtx name="equal_equal_equal.code" width="600" lsb="-1107"/> <!-- Rec Mono -->

Fira Code is similar, though it has a UPM of 2000, so values are just doubled.

- <mtx name="equal_equal_equal.liga" width="1200" lsb="-2189"/> # Fira Code

But, there must be something which causes Glyphs to show the JB Mono TTF & the Rec Mono TTF differently, and maybe this is related to the layout issues in NetBeans. I’ll keep investigating.

@arrowtype
Copy link
Owner

Okay, HERE it is (maybe).

In the glyf table, the glyph contours are drawn with points on a coordinate grid. In JB Mono, these points are laid out in the grid as if drawn with mostly negative / left values. In Rec Mono, these are not edited from their original values. My guess is, NetBeans & GlyphsApp just disregard the hmtx (horizontal metrics) table when showing glyphs, while other apps do check it and adjust things accordingly.

# JB Mono
- <TTGlyph name="equal_equal_equal.liga" xMin="-1120" yMin="110" xMax="520" yMax="550">
-       <contour>
-         <pt x="520" y="480" on="1"/>
-         <pt x="-1120" y="480" on="1"/>
-         <pt x="-1120" y="550" on="1"/>
-         <pt x="520" y="550" on="1"/>
-       </contour>

# Rec Mono
+ <TTGlyph name="equal_equal_equal.code" xMin="93" yMin="78" xMax="1707" yMax="615"> # Rec Mono
+       <contour>
+         <pt x="1707" y="78" on="1"/>
+         <pt x="1707" y="156" on="1"/>
+         <pt x="1707" y="160" on="0"/>
+         <pt x="1704" y="164" on="0"/>
+         <pt x="1700" y="167" on="0"/>
+         <pt x="1696" y="167" on="1"/>
+         <pt x="93" y="167" on="1"/>
+         <pt x="93" y="89" on="1"/>
+         <pt x="93" y="86" on="0"/>
+         <pt x="96" y="81" on="0"/>
+         <pt x="101" y="78" on="0"/>
+         <pt x="104" y="78" on="1"/>
+       </contour>

So, I have to find a way to transform not just the htmx values, but all values in .code glyphs. Ha, this might be fairly straightforward, or might be pretty tricky. 😅 Will update soon.

@arrowtype
Copy link
Owner

Okay, things are looking promising! I have updated the dlig2calt.py script to adjust the glyph coordinates (currently just at recursive-code-config):

arrowtype/recursive-code-config@3f3a14e#diff-9aaa3ec606057e41b8b37ee20a0f1308

After the changes, they seem to work much better for me:

image

New glyph in GlyphsApp, comparison to previous font in NetBeans (Click to expand)

The glyphs now overflow to the left when viewed in GlyphsApp:

image

This is how the previous code ligatures look for me in NetBeans, running on a Windows 10 virtual machine:

image

@javlaks could you please try this out on your end and let me know if it seems to fix the problem for you?

You could either download the fonts individually from recursive-code-config or download this zip of them:

ArrowType-RecMonoCode-v1.062.zip

@javlaks
Copy link
Author

javlaks commented Aug 31, 2020

Hey man,

You're great.

The ligatures now are being showed correctly
image

My only concern is why the style has been changed by default in DuoTone...

If you see in above image, the g in word "String" is different that the below one.
image

Thank you so much for your effort to make it possible. I can have my favorite font on all my dev applications :)

@javlaks
Copy link
Author

javlaks commented Aug 31, 2020

This is the Original latest font
image

This is your modified version
image

And this is the modified version from "B" Folder
image

What's the difference between Regular and B folder?

@arrowtype
Copy link
Owner

Awesome! Thanks for trying that out. Glad we got this sorted! 🎉

What's the difference between Duotone and Duotone B folder?

I should document this better or maybe come up with a more creative name.

  • Duotone uses Linear styles for Regular & Bold, then Casual styles for Bold & Bold Italic
  • Duotone B uses Linear for Regular, then Casual for Italic, Bold, and Bold Italic. This just uses Casual for all "emphasis" text in my code theme. It also uses the default g, which I like better.

@arrowtype arrowtype reopened this Aug 31, 2020
@arrowtype
Copy link
Owner

@arrowtype
Copy link
Owner

Oh, and as for the specific style of g in the code fonts, it was unintentional to set them to the single-story version when I made the code-config repo. In general, I think the double-story g is more recognizable at a glance, due to it have a more unique shape from other characters. Of course, whether someone finds it better or worse depends largely on what they are used to and whether they have a personal preference, so if you prefer something else, please try cloning the config repo and adjusting options to build a version suited to your own preferences! Hopefully, the readme documents this clearly enough that it is fairly approachable, but feel free to file an issue if you try it and get stuck on something!

@javlaks
Copy link
Author

javlaks commented Sep 1, 2020

Thanks for your hard work on this. It looks amazing. 😉

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

No branches or pull requests

3 participants