Search code examples
cfontsfreetypetext-renderingfreetype2

Rendered font looks bolder than it should be


I'm rendering the font Consolas using freetype2.

I rendered the glyphs using

FT_Load_Glyph(face, glyphIndex, FT_LOAD_DEFAULT);
FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);

and converted the bitmap to an ARGB map using a simple loop:

uint32_t* content = ... // ARGB bitmap

for (int py = 0; py < bitmap->rows; py++) {
    for (int px = 0; px < bitmap->width; px++) {
        uint8_t intensity = bitmap->buffer[py * bitmap->pitch + px];
        content[py * bitmap->width + px] = (intensity << 24);
    }
}

The result is that my rendered text looks much bolder than when it's rendered from for example notepad:

Upper font rendered by freetype2, lower one by Notepad.

What could be the reason for this issue?


Solution

  • I'm not a Freetype expert (at all), but if you look at your example bitmap with a magnifying glass you'll see that the Notpad rendering has light blue and pink shades around it. Your rendering is anti-aliased, but all grey.

    So I assume that Notepad renders in LCD mode , which really renders three subpixels (corresponding to the RBG rays of the Cathode Ray Display) per pixel and then smears them with the neighbouring pixels.

    That also means that vertical hinting takes place along these subpixels and that, for example, the width of the vertical stems in the Notepad rendering is four or five sub-pixels, whereas in your rendering is is alwys at full pixel borders, i.e. six subpixels. This makes your rendering look bold in comparison to Notepad's. (Perhaps you can find font sizes where the effect is reversed: Your rendering looks lighter than Notepad's.)

    You could do your rendering also in LCD mode (FT_RENDER_MODE_LCD). You'd render to a bitmap three times as wide and when you copy the text bitmap to your ARGB bitmap, you should take the average value of three adjacent pixels. (This will not give you true LCD rendering, but a lighter greyscale rendering.)