source-foundry / Hack

A typeface designed for source code
http://sourcefoundry.org/hack/
Other
16.47k stars 616 forks source link

Examine shape + hinting of the zero oval fill across range of text sizes #138

Closed Grimy closed 8 years ago

Grimy commented 9 years ago

Here’s a screenshot of how the digit 0 looks in my xterm:

0

As you can see, the bold ones render correctly, but the regular ones have a middle dot that is way too big and extends more to the top than to the bottom.

I have the following config:

*faceName:     Hack
*faceSize:     11
Xft.antialias: 1
Xft.autohint:  1 
Xft.hinting:   1
Xft.hintstyle: hintslight
Xft.rgba:      rgb

Disabling antialising solves this particular problem, but then everything looks ugly.

Grimy commented 9 years ago

Here’s the result when turning hinting off:

02

The middle dot is now symmetrical, but still quite big. Is that the intended design?

chrissimpkins commented 9 years ago

Any idea what Xft.autohint is doing there?

chrissimpkins commented 9 years ago

And to confirm, these are the ttf fonts?

chrissimpkins commented 9 years ago

The middle dot is now symmetrical, but still quite big

It is not intended to render as a dot, but rather as an oval fill. That is the correct design

Grimy commented 9 years ago

Yes, these are the ttf fonts. Turning off Xft.autohint has no visible effect. Turning off Xft.hinting produces the second screenshot I posted.

chrissimpkins commented 9 years ago

I have not particular expertise with xterm hinting settings, but the second image is the intended appearance with the ttfautohint instruction sets that are included in the ttf builds.

Grimy commented 9 years ago

Okay, thanks for the quick reply (= I’ll leave hinting off and autohint on, then.

That “oval fill” looks really good on the samples in the README, but much less so at font size 11, where it looks more like a vertical bar. Well, I guess that’s just a matter of opinion x)

chrissimpkins commented 9 years ago

Mind trying it at a couple of other text sizes, both smaller and larger? The shape changes as it gets constrained to different sized pixel grids. Interested to see how it appears on your platform with that renderer.

chrissimpkins commented 9 years ago

Here is the design:

hack-numbers

chrissimpkins commented 9 years ago

Updated title of your issue report and we will leave this open to delve a bit deeper into the issue. I think that there is room for improvement here. Perhaps a slight adjustment to the shape at smaller text sizes. Thanks for pointing this out. Will update here with additional information and any changes that are made.

Grimy commented 9 years ago

I tried at font sizes 6, 7, 8, 9, 10, 11, 12, 13, 14 and 16, here are the results:

all

In my opinion, it looks bad at sizes 9, 11 and 13.

Thanks for your attention!

chrissimpkins commented 9 years ago

That's extremely helpful and will guide our tests. Thanks much!

chrissimpkins commented 8 years ago

@lemzwerg:

We have a reasonably complex fill on the zero glyph here and I am trying to adjust the hints on the fill at a number of ppem. Here is an example of what I am seeing with the attempt to manually adjust the fill in the regular set with the following line in our Control Instructions File at 14ppem:

zero touch 39-48,65-71  y -1    @ 12,13,14

Pre-Adjustment to the Hinting

zero-pre-adjust

Post-Adjustment to the Hinting

zero-post-adjust

Thoughts? I'm not sure why we are seeing that notch at points 39 and 71 at the bottom of the oval fill. This occurs at several ppem when I attempt adjustments of the oval shape.

lemzwerg commented 8 years ago

The touch instruction implements pre-IUP deltas; in other words, after applying the deltas there comes the final IUP[y] instruction, interpolating the 'weak' points of the outlines that are not positioned on edges. If you call ttfautohint with the --debug option, you get a table of points for every glyph that shows whether a point is 'weak', and whether it lies on an edge.

In general, it is not necessary to explicitly move 'weak' points that are not positioned on horizontal edges. Instead, you should move either 'strong' points or points that lie on horizontal edges.

Without knowing in detail what ttfautohint reports for your 'zero' glyph, I thus think it should be sufficient to move points 39, 40, and 71:

zero  touch 39,40,71  y -1  @ 12,13,14

If you move weak non-edge-points for whatever reason, you have to also compensate the IUP[y] movement that follows. I guess this is the problem that you experience here.

lemzwerg commented 8 years ago

A minor follow-up. It seems that you are using ftview for showing glyph outlines. Here's a snapshot of the git version, which you probably enjoy :-) ftview-current

chrissimpkins commented 8 years ago

@lemzwerg Thank you very much Werner! That is incredibly helpful. I’ll give it a try later today.

The repository version of ftview looks great! Is it stable enough for use at this point? I am assuming that image is with the antialiasing view switched ‘on’?

lemzwerg commented 8 years ago

ftview is stable, yes; the image shows subpixel rendering, but normal grayscale anti-aliasing can also be displayed.

chrissimpkins commented 8 years ago

:+1: thanks!

chrissimpkins commented 8 years ago

@lemzwerg:

So here is what I get with the --debug flag for the zero glyph. It only indicates that 39 is a strong point (I assume that the absence of a ‘weak’ indicator in the list means that this is strong point?):

glyph 548 (zero)
================

size 4
------

latin horizontal edge hinting (style `latn_dflt')
  BLUE_ANCHOR: edge 0 (opos=-0.05) snapped to 0.00, was -0.05 (anchor=edge 0)
  LINK: edge 1 (opos=0.23) linked to 0.28, dist was 0.28, now 0.28
  BLUE: edge 3 (opos=1.92) snapped to 2.00, was 1.92
  LINK: edge 2 (opos=0.69) linked to 0.77, dist was -1.23, now -1.23
  BLUE: edge 5 (opos=2.66) snapped to 3.00, was 2.66
  LINK: edge 4 (opos=2.38) linked to 2.72, dist was -0.28, now -0.28

Table of horizontal edges:
  index   pos    dir   link  serif  blue  opos    pos      flags
      0  -0.047   left     1     --    y   -0.05   0.00        round
      1   0.23  right     0     --    n    0.23   0.28        round
      2   0.69   left     3     --    n    0.69   0.77        round
      3    1.9  right     2     --    y    1.92   2.00        round
      4    2.4   left     5     --    n    2.38   2.72        round
      5    2.7  right     4     --    y    2.66   3.00        round

Table of horizontal segments:
  index   pos    dir   from   to   link  serif  edge  height  extra     flags
      0  -0.047   left    18     1     2     --     0     600    121        round
      1    2.7  right     7     9     3     --     5     509    151        round
      2   0.23  right    38    20     0     --     1     246    104        round
      3    2.4   left    28    30     1     --     4     301     86        round
      4    1.9  right    55    57     5     --     3     111     33        round
      5   0.69   left    71    39     4     --     2      54     28        round

Table of points:
  index  hedge  hseg  flags  xorg  yorg  xscale  yscale   xfit    yfit
      0      0     0  weak    616   -29    1.20   -0.05    1.20    0.00
      1      0     0  weak    376   -29    0.73   -0.05    0.73    0.00
      2     --    --  weak    255   167    0.50    0.30    0.50    0.38
      3     --    --  weak    133   364    0.27    0.64    0.27    0.77
      4     --    --  weak    133   745    0.27    1.30    0.27    1.48
      5     --    --  weak    133  1127    0.27    1.97    0.27    2.23
      6     --    --  weak    255  1324    0.50    2.31    0.50    2.62
      7      5     1  weak    376  1520    0.73    2.66    0.73    3.00
      8      5     1  weak    616  1520    1.20    2.66    1.20    3.00
      9      5     1  weak    734  1520    1.44    2.66    1.44    3.00
     10     --    --  weak    916  1424    1.80    2.48    1.80    2.81
     11     --    --  weak    978  1324    1.91    2.31    1.91    2.62
     12     --    --  weak   1038  1228    2.03    2.14    2.03    2.42
     13     --    --  weak   1100   941    2.16    1.64    2.16    1.88
     14     --    --  weak   1100   745    2.16    1.30    2.16    1.48
     15     --    --  weak   1100   549    2.16    0.95    2.16    1.11
     16     --    --  weak   1038   263    2.03    0.45    2.03    0.56
     17     --    --  weak    978   167    1.91    0.30    1.91    0.38
     18      0     0  weak    855   -29    1.67   -0.05    1.67    0.00
     19      1     2  weak    616   131    1.20    0.23    1.20    0.28
     20      1     2  weak    689   131    1.34    0.23    1.34    0.28
     21     --    --  weak    794   209    1.55    0.36    1.55    0.42
     22     --    --  weak    828   283    1.62    0.50    1.62    0.58
     23     --    --  weak    897   434    1.75    0.77    1.75    0.89
     24     --    --  weak    897   745    1.75    1.30    1.75    1.48
     25     --    --  weak    897  1057    1.75    1.84    1.75    2.11
     26     --    --  weak    828  1207    1.62    2.11    1.62    2.42
     27     --    --  weak    794  1282    1.55    2.23    1.55    2.56
     28      4     3  weak    690  1360    1.34    2.38    1.34    2.72
     29      4     3  weak    616  1360    1.20    2.38    1.20    2.72
     30      4     3  weak    475  1360    0.92    2.38    0.92    2.72
     31     --    --  weak    406  1208    0.80    2.11    0.80    2.42
     32     --    --  weak    371  1133    0.72    1.98    0.72    2.28
     33     --    --  weak    336   906    0.66    1.58    0.66    1.81
     34     --    --  weak    336   745    0.66    1.30    0.66    1.48
     35     --    --  weak    336   433    0.66    0.75    0.66    0.88
     36     --    --  weak    406   283    0.80    0.50    0.80    0.58
     37     --    --  weak    442   205    0.86    0.36    0.86    0.42
     38      1     2  weak    547   131    1.06    0.23    1.06    0.28
     39      2     5   --     618   396    1.20    0.69    1.20    0.77
     40     --    --  weak    603   396    1.17    0.69    1.17    0.77
     41     --    --  weak    578   419    1.12    0.73    1.12    0.81
     42     --    --  weak    559   458    1.09    0.80    1.09    0.88
     43     --    --  weak    545   511    1.06    0.89    1.06    0.97
     44     --    --  weak    539   540    1.05    0.94    1.05    1.02
     45     --    --  weak    534   564    1.05    0.98    1.05    1.06
     46     --    --  weak    526   622    1.03    1.09    1.03    1.17
     47     --    --  weak    520   681    1.02    1.19    1.02    1.27
     48     --    --  weak    516   733    1.02    1.28    1.02    1.36
     49     --    --  weak    516   750    1.02    1.31    1.02    1.39
     50     --    --  weak    516   762    1.02    1.33    1.02    1.41
     51     --    --  weak    518   808    1.02    1.41    1.02    1.48
     52     --    --  weak    523   864    1.02    1.52    1.02    1.59
     53     --    --  weak    530   925    1.03    1.62    1.03    1.70
     54     --    --  weak    536   953    1.05    1.67    1.05    1.75
     55      3     4  weak    564  1096    1.11    1.92    1.11    2.00
     56      3     4  weak    614  1096    1.20    1.92    1.20    2.00
     57      3     4  weak    642  1096    1.25    1.92    1.25    2.00
     58     --    --  weak    681  1020    1.33    1.78    1.33    1.86
     59     --    --  weak    695   950    1.36    1.66    1.36    1.73
     60     --    --  weak    700   925    1.38    1.62    1.38    1.70
     61     --    --  weak    708   867    1.39    1.52    1.39    1.59
     62     --    --  weak    714   810    1.39    1.42    1.39    1.50
     63     --    --  weak    717   759    1.41    1.33    1.41    1.41
     64     --    --  weak    717   742    1.41    1.30    1.41    1.38
     65     --    --  weak    717   732    1.41    1.28    1.41    1.36
     66     --    --  weak    716   690    1.41    1.20    1.41    1.28
     67     --    --  weak    712   635    1.39    1.11    1.39    1.19
     68     --    --  weak    705   573    1.38    1.00    1.38    1.08
     69     --    --  weak    700   542    1.38    0.95    1.38    1.03
     70     --    --  weak    687   468    1.34    0.81    1.34    0.89
     71      2     5  weak    644   396    1.27    0.69    1.27    0.77

action hints record:
   76  0 70  0  0  1  6 95  0  2  2  1  7 75 64  4  4  0 95  4  5  5  1  8 75 69  1  1  0 95  1  3  3  0
point hints record:
  (none)
chrissimpkins commented 8 years ago

@lemzwerg :

and here is where we are when 39 is the only point that is used at 14ppem:

zero touch 39  y -1    @ 12,13,14
zero-with-39

Getting closer...

chrissimpkins commented 8 years ago

And after a bit of experimentation this might be as close as we are going to get.

Using the following:

zero touch 39  y -1    @ 12,13,14
zero touch 71  y -0.5  @ 12,13,14
zero touch 39  y -0.5  @ 7,8
zero touch 71  y -0.25 @ 7,8
zero touch 71  x  0.5  @ 7,8,12,13,14

12ppem

12ppem

13ppem

13ppem

14ppem

14ppem
chrissimpkins commented 8 years ago

7ppem

7ppem

8ppem

8ppem
chrissimpkins commented 8 years ago

@Grimy Victor, here are the 9 and 11ppem renders. I did not modify the hints because they appear as designed.

9ppem

9ppem

11ppem

11ppem
lemzwerg commented 8 years ago

This looks fishy... I'll test by myself later this evening.

chrissimpkins commented 8 years ago

@Grimy Test builds of the ttf fonts (v2.020; DEV03172016) are available in this directory if you would be willing to test them:

https://github.com/chrissimpkins/Hack/tree/development/build/test_builds/DEV03172016

chrissimpkins commented 8 years ago

This looks fishy... I'll test by myself later this evening.

Thanks for your help @lemzwerg. Let me know if you have any other thoughts.

lemzwerg commented 8 years ago

I've now investigated the issue. Point 40 should form a segment together with points 39 and 71, and point 39 shouldn't be tagged as 'strong'. This is a bug in ttfautohint v1.5 which I'm going to fix in the next version – thanks for the report :-)

A fix to this bug is to change the direction of point 40 to 'left' (ttfautohint must have assigned a different direction, otherwise the point would have already been merged with the segment consisting of points 39 and 71); now you can move the segment as expected with touch.

zero  left  40
zero  touch 39,40,71  y -1  @ 12-18
zero  touch 55,56,57  y -1  @ 8,19-25
chrissimpkins commented 8 years ago

Thank you very much @lemzwerg. I really appreciate it. I will give this a try over the weekend. Is this something that we will need to change once the issue is addressed in ttfautohint?

lemzwerg commented 8 years ago

Fortunately no :-) Even if ttfautohint has improved segment recognition so that it can find out by itself that point 40 must have a 'left' direction, the left command doesn't do any harm.

chrissimpkins commented 8 years ago

@lemzwerg great! I tried this last night and it worked. Just a small tweak on the <10ppem sizes and we are in good shape.

chrissimpkins commented 8 years ago

There are updated pre-release builds of the fonts (v2.020;DEV-03192016) that include the new hints on the zero glyph here:

https://github.com/chrissimpkins/Hack/tree/development/build/test_builds/DEV03192016

These will be included in the upcoming v2.020 release.

Grimy commented 8 years ago

Thanks for the update! Using DEV-03192016, the 0 glyph now looks nice with the following settings:

xterm*faceName:    Hack
xterm*faceSize:    11
Xft.antialias:     1
Xft.autohint:      0
Xft.hinting:       1
Xft.hintstyle:     hintfull

Oddly enough, when setting hintstyle to hintslight, the asymmetrical fill problem persists. I’m not even sure what this setting is supposed to do, so I’ll stick to hintfull.

chrissimpkins commented 8 years ago

@Grimy We will release these changes in the upcoming v2.020 release Victor. Thank you very much for reporting this issue. The zero is a prominent character that helps to establish the identity of the typeface. This was an important issue for us to address. Glad to hear that it works for you.

Thanks again @lemzwerg! Greatly appreciate your help with this.

lemzwerg commented 8 years ago

@Grimy 'Hintslight' is FreeType's auto-hinter. Contrary to manual hinting corrections (which you get with 'hintfull'), the auto-hinter cannot correctly handle the interior of the 'zero' glyph due to technical restrictions.

chrissimpkins commented 8 years ago

@lemzwerg thanks!

chrissimpkins commented 8 years ago

@lemzwerg is it appropriate to recommend that Linux users apply full hinting when they use our fonts? Wondering if we need this in our documentation. I wasn't aware that FreeType ignored all manual hints in hint slight mode.

lemzwerg commented 8 years ago

To be pedantic: It's up to the font rendering stack to decide what the three hinting modes 'full', 'medium', and 'slight' exactly do. The FontConfig library only sets up those values without defining them.

For TrueType fonts, 'full' normally means bytecode hinting, and 'slight' the hinting as provided by FreeType's auto-hinter, ignoring bytecode completely. The basic question is what 'medium' means for TrueType fonts...

ttfautohint produces bytecode hinting, thus any manual improvements coming from a control instructions file are only present if bytecode hinting is active, and this normally implies full hinting.

Grimy commented 8 years ago

is it appropriate to recommend that Linux users apply full hinting when they use our fonts?

I don’t think that’s necessary: full hinting is the default. Maybe a warning to the effect of “Don’t mess up with fontconfig settings unless you know what you’re doing”.

chrissimpkins commented 8 years ago

@lemzwerg That is very helpful information. I wasn't aware of this. Thank you very much Werner.

@Grimy That sounds good Victor. We will leave the docs as is for now. Is there a reason why you modified the settings? Does this make other fonts look better on your system?

chrissimpkins commented 8 years ago

@Grimy I came across this information on the FreeType site that addresses these font setting issues:

http://www.freetype.org/freetype2/docs/text-rendering-general.html

It seems that the FreeType project has the goal to move towards increased use of some degree of autohinting as the default based upon these comments in that document:

I also hope this change will make it easier for the non-Windows-and-Apple ecosystem to switch over to slight hinting as the default. Current full/medium native hinting, as is the default, tends to bring out the worst in many, many fonts that haven’t seen the same insane dedication to on-screen display and hinting as many popular Microsoft fonts, for example. And since ClearType is still not fully supported, you usually get a very poor default experience. Slight hinting gives a much better one, as Ubuntu has proven over the years.

This is probably a reasonable goal based upon the quality of autohinting that is now available and the reasons cited there; however, this move would definitely lead to problems with the many typefaces that are currently using ttfautohint with manual hinting guidance via Control Instruction Files for their TrueType font builds (we want the byte code hinting). I looked into this a bit more and it appears that Debian’s official documentation and the Ubuntu wiki both suggest that their users apply the hintslight setting in order to improve the general appearance of their fonts system wide. The Arch documentation shows hintfull in the fontconfig hinting example, but takes a very balanced approach to their documentation of the issue.

Given the above, I am wondering whether we should put a Hack project specific fontconfig setting out there for Linux users so that our intended manual hints are always used by applications that obey these configuration settings?

I am a fontconfig novice but I gather that a granular approach by font family can be defined like this?:

<match target="font">
 <test qual="any" name="family" compare="eq">
      <string>Hack</string>
 </test>
 <edit name=“hintstyle" mode="assign">
      <const>hintfull</const>
 </edit>
</match>

Will this suggestion broadly address the hinting issue across commonly used Linux distros? Is the above setting correct?

Grimy commented 8 years ago

I read the advice to use hintslight somewhere, tried it, noticed it made my terminal font of the time look better, and kept the config fragment ever since.

Yes, I believe shipping a fontconfig file is reasonable. However, the example you show does not work, because the opening quote before hintstyle is a typographic quote (, U+201C) rather than an ASCII quote (", U+0022). Once this is fixed, it works just fine.

chrissimpkins commented 8 years ago

Excellent, thanks. I will work this into the documentation so that others are aware.

chrissimpkins commented 8 years ago

These fixes are available in the v2.020 release. Thanks to all here for your help with this issue!