GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Bad font hinting / quality with Agg renderer by mdboom · Pull Request #719 · matplotlib/matplotlib

Conversation

@mdboom

@mdboom mdboom commented Feb 27, 2012

Copy link
Copy Markdown
Member

When using the agg backend to create PNGs, fonts are poorly hinted, and always look blurry. Setting text.hinting = True has no effect.

The below script creates two images that demonstrate the problem. It generates some text in multiple sizes, with both the agg and the cairo backends. While the progression of sizes generally looks smoother with the agg backend, there seems to be no way to replicate the crispness of the cairo backend, particularly around sizes 9, 10, 11, and 12.

I have copies of the images, and zoomed-in versions for comparision, available at
http://jim.sh/~jim/tmp/matplotlib-font

# Test rendering of different font sizes with Cairo vs. Agg backend

import sys, os
if "DISPLAY" in os.environ:
    del os.environ["DISPLAY"]

for backend in [ 'cairo', 'agg' ]:
    # Reload with proper backend
    print "Rendering with " + backend
    for module in list(sys.modules):
        if module.startswith(('matplotlib','pylab')):
            sys.modules.pop(module)
    import matplotlib
    matplotlib.use(backend)
    import pylab

    # This has no effect, but try it anyway
    matplotlib.rcParams['text.hinting'] = True

    # Make plot
    fig = pylab.figure(figsize=[2,5])
    ax = fig.add_subplot(1,1,1)
    ax.set_frame_on(False)
    ax.axes.get_xaxis().set_visible(False)
    ax.axes.get_yaxis().set_visible(False)
    ax.set_xlim([0, 1])
    ax.set_ylim([15, 0])
    pylab.title(backend)

    for size in range(1,25):
        ax.text(0.1, (size ** 1.6) / 10, "hello " + str(size), 
                fontdict = { "size" : size, "family" : "arial" })
    pylab.savefig("test-" + backend + ".png", format="png")
    pylab.clf()

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@ghost ghost assigned mdboom Feb 27, 2012
@mdboom
Makes the "hinting factor" tweakable at runtime.
1d78d3d
The hinting factor is the amount of softness in hinting is applied in
the horizontal direction.  For years, matplotlib has hinted to 1/8
pixels in the horizontal direction and whole pixels in the vertical
direction.  This results in text that is often more
legible (particularly at smaller sizes) than standard 1:1 hinting.
This is based on idea from this paper from the author of Agg:

    http://www.antigrain.com/research/font_rasterization/

However, sometimes the user may want full-on hinting, so this value is
now tweakable using the `text.hinting_factor` rcParam.
@mdboom

mdboom commented Feb 27, 2012

Copy link
Copy Markdown
Member

What you're seeing is the effect of "soft hinting" where it hints to subpixels in the x direction. Years ago we did a sort of survey on the mailing list of which kind of hinting looked best and that's what we determined. Of course, it doesn't have to be hardcoded, so I've attached some changes that make the amount of softness tweakable with an rcParam. Can you try this out (setting "text.hinting_factor" to 1) and let me know if this resolves your issue? I'm hesitant to change the default as many users (and the testing framework) are relying on the present behavior.

Attached is a pull request that makes the "hinting factor" tweakable at runtime.

The hinting factor is the amount of softness in hinting is applied in
the horizontal direction.  For years, matplotlib has hinted to 1/8
pixels in the horizontal direction and whole pixels in the vertical
direction.  This results in text that is often more
legible (particularly at smaller sizes) than standard 1:1 hinting.
This is based on idea from this paper from the author of Agg:

    http://www.antigrain.com/research/font_rasterization/

However, sometimes the user may want full-on hinting, so this value is
now tweakable using the `text.hinting_factor` rcParam.
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@jimparis

jimparis commented Feb 28, 2012

Copy link
Copy Markdown
Author

Thanks for the patch! It does improve things, but the hinting still leaves a bit to be desired, at least compared to the Cairo backend. I've updated the images at http://jim.sh/~jim/tmp/matplotlib-font to show how the text.hinting_factor = 1 changes things. I also included a plot that attempts to force hinting with text.hinting = True, but that doesn't seem to make a difference. Notice how vertical letters like the Ls are now sharper horizontally, but still don't fully snap to pixels like in the Cairo case.

Regarding the default, I agree that the present behavior shouldn't be changed at this point. I'm fine with setting a variable in my own scripts.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@jimparis

jimparis commented Feb 28, 2012

Copy link
Copy Markdown
Author

I think I figured it out: currently, text.hinting can choose between the FreeType options LOAD_NO_HINTING or LOAD_FORCE_AUTOHINT. The option I need is LOAD_DEFAULT -- use the font's native hinting if available. If I hack lib/matplotlib/backends/backend_agg.py so that _get_hinting_flag always returns LOAD_DEFAULT, then the Agg font rendering matches Cairo exactly.

Maybe text.hinting could be extended in a compatible way, e.g.:

{
False: LOAD_NO_HINTING,
True: LOAD_FORCE_AUTOHINT,
"auto": LOAD_FORCE_AUTOHINT,
"native": LOAD_NO_AUTOHINT,
"either": LOAD_DEFAULT,
}
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@mdboom
Expose more hinting options to the user.
cf5e358
@mdboom

mdboom commented Feb 28, 2012

Copy link
Copy Markdown
Member

Ok. I've incorporated this.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@jimparis

jimparis commented Feb 28, 2012

Copy link
Copy Markdown
Author

Works perfectly. Now text.hinting_factor: 1 and text.hinting: native gives me exactly what I wanted. Thanks so much!

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@mdboom

mdboom commented Feb 29, 2012

Copy link
Copy Markdown
Member

Great! Merging...

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

mdboom added a commit that referenced this pull request Feb 29, 2012
@mdboom
Merge pull request #719 from mdboom/hinting
d9186fe
Bad font hinting / quality with Agg renderer
@mdboom
mdboom merged commit d9186fe into matplotlib:master Feb 29, 2012
@mdboom
mdboom deleted the hinting branch March 3, 2015 18:43
@QuLogic QuLogic mentioned this pull request Apr 3, 2025
Determine if hinting_factor setting can be dropped #9681
Closed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

@mdboom mdboom

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@mdboom @jimparis
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.