Font.renderGlyph creates distorted images (lime.text.Font.renderGlyph)

Hello, I am experiencing an issue when creating an image from text with lime.text.Font.renderGlyph. Namely, the created image is distorted when certain values for the parameter fontSize are given.
Here are two images visualizing the result, first being the correct image, e.g. when using a size of 32:

And the result with font size 64:

Most other sizes look similar, but it seems arbitrary; E.g. 25, 26, 27 look fine while 24 or 28 do not.

This is the code I am using to create the image:

font = Font.fromFile("assets/DejaVuSansMono.ttf");
var image = font.renderGlyph(font.getGlyph("a"), 32); 

Am I doing something wrong, or is this an internal issue with freetype?

The rest of the test application is almost the same as the TextRendering sample.

var vertices = new Array<Float>();
var indices = new Array<Int>();
var left, top, right, bottom;
var buffer = image.buffer;
var left = 0;
var top = 0;
var right = 1;
var bottom = 1;
var pointLeft = x + image.x;
var pointTop = y - image.y;
var pointRight = pointLeft + image.width;
var pointBottom = pointTop + image.height;

vertices.push (pointRight);
vertices.push (pointBottom);
vertices.push (right);
vertices.push (bottom);

vertices.push (pointLeft);
vertices.push (pointBottom);
vertices.push (left);
vertices.push (bottom);

vertices.push (pointRight);
vertices.push (pointTop);
vertices.push (right);
vertices.push (top);

vertices.push (pointLeft);
vertices.push (pointTop);
vertices.push (left);
vertices.push (top);

var i = Std.int(indices.length / 6) * 4;
indices.push (i);
indices.push (i + 1);
indices.push (i + 2);
indices.push (i + 1);
indices.push (i + 2);
indices.push (i + 3);

trinum = indices.length;

textvbo = context.createBuffer ();
context.bindBuffer (ARRAY_BUFFER, textvbo);
context.bufferData (ARRAY_BUFFER, new Float32Array (vertices), STATIC_DRAW);

indexBuffer = context.createBuffer ();
context.bindBuffer (ELEMENT_ARRAY_BUFFER, indexBuffer);
context.bufferData (ELEMENT_ARRAY_BUFFER, new UInt8Array (indices), STATIC_DRAW);

var format = (buffer.bitsPerPixel == 1 ? context.ALPHA : context.RGBA);
texttexture = context.createTexture ();
context.bindTexture (context.TEXTURE_2D, texttexture);
context.texImage2D (context.TEXTURE_2D, 0, format, buffer.width, buffer.height, 0, format, context.UNSIGNED_BYTE, buffer.data);
context.texParameteri (context.TEXTURE_2D, context.TEXTURE_MAG_FILTER, context.NEAREST);
context.texParameteri (context.TEXTURE_2D, context.TEXTURE_MIN_FILTER, context.NEAREST);


//...
//...
public override function render (renderer:Renderer):Void {
    switch(renderer.context) {
        case OPENGL(context):
            context.clear(COLOR_BUFFER_BIT);
            context.uniformMatrix4fv(matrix, false, projection);

            context.activeTexture(TEXTURE0);
            context.bindTexture(TEXTURE_2D, texttexture);
            context.bindBuffer(ARRAY_BUFFER, textvbo);
            context.vertexAttribPointer(position, 2, FLOAT, false, 4 * Float32Array.BYTES_PER_ELEMENT, 0);
            context.vertexAttribPointer(texcoord, 2, FLOAT, false, 4 * Float32Array.BYTES_PER_ELEMENT, 2 * Float32Array.BYTES_PER_ELEMENT);
            context.bindBuffer(ELEMENT_ARRAY_BUFFER, indexBuffer);
            context.drawElements(TRIANGLES, trinum, UNSIGNED_BYTE, 0);

        default: 
    }
}

System is OSX 10.11 with haxe 3.2.1 and lime 2.8.3 (-also tested with the latest lime from github and a more recent freetype library, with the same results).

1 Like

After looking further into the topic of opengl freetype distortion I found a solution.

It is required to call context.pixelStorei( UNPACK_ALIGNMENT, 1); before creating the image from the glyph. With that statement images of every font size render correctly.

1 Like

Hi @adams !
I’ve got a question about pixelStorei, since I got similar problems with freetype on C application - should UNPACK_ALIGNMENT be switched back to 4 after loading font?

Hi! A little correction and clarification to my previous comment: The part that requires UNPACK_ALIGNMENT set to 1 is texImage2D. This is apparently because the image buffer generated by freetype only contains the alpha channel and therefore has only one bit per pixel. Normally it’s set to 4, e.g. for buffers containing RGBA channels.

So as long as it’s set to 1 when you call texImage2D you can set it to different values afterwards if you need to, e.g. if you load need to unpack other buffers that contain more than 1 channel.

1 Like

Ahh, good point.
Thank You for explain,
Best Regards, Ret.