Jump to content
  • Advertisement
Sign in to follow this  
Taylor001

Distorted freetype fonts

This topic is 2792 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi!

I'm trying to load and display a character bitmap rendered by the freetype library.


FT_Library library;

if (FT_Init_FreeType(&library)) {

LogManager::GetInstance()->LogMessage("Could not initialize FreeType library.", LL_ERROR);
return 0;
}

FT_Face face;
unsigned int error;

error = FT_New_Face(library, "tests/font/arialbd.ttf", 0, &face);

if (error == FT_Err_Unknown_File_Format) {

LogManager::GetInstance()->LogMessage("Unknown file format.", LL_ERROR);
} else if (error) {
LogManager::GetInstance()->LogMessage("Could not load font file.", LL_ERROR);
}

error = FT_Set_Char_Size(face, 25 << 6, 25 << 6, 96, 96);


FT_Load_Glyph(face, FT_Get_Char_Index(face, 'A'), FT_LOAD_RENDER);
FT_Bitmap& bitmap = face->glyph->bitmap;

unsigned char* bitmapBuffer = new unsigned char[bitmap.width * bitmap.rows];

for (unsigned int i = 0; i < bitmap.rows; i++) {
for (unsigned int j = 0; j < bitmap.width; j++) {

bitmapBuffer[j + i * bitmap.width] = bitmap.buffer[j + i * bitmap.width];
}
}



The above code initializes the freetype library and loads a character in ('A' in this case).
After that, it gets the glyph's bitmap dimensions and allocates a buffer to store the glyph image.
Unfortunately, all I get is a distorted version of the character, as you can see from the following picture:


The weird thing is that for some other characters, it works just fine:


I really can't figure out what's wrong.

Thanks in advance!

Share this post


Link to post
Share on other sites
Advertisement
Looks like your rows are too tight for some characters. My bet is that for these characters the width is NOT a multiple of four and is rounded down to satisfy width % 4 == 0

I don't see it at one glance, I find freetype a little cumbersome in this respect, but what you must do is debug (write to a log) the character you're printing, width, height, pitch, ... all metrics. And see what is different for bad glyphs over good glyphs.

One thing to note, is that you should use pitch for row offsets from the destination (from FT).
bitmapBuffer[j + i * bitmap.width] = bitmap.buffer[j + i * bitmap.pitch];

Keep the other widths the same, it should be good like this.

EDIT: looking closer, it looks like your B is up-side-down!

Share this post


Link to post
Share on other sites
Could be the bitmap's width is different from its pitch?
bitmapBuffer[j + i * bitmap.width] = bitmap.buffer[j + i * bitmap.pitch];
Does that help?

EDIT: Beaten :(

EDIT2:
Quote:
Original post by Decrius
EDIT: looking closer, it looks like your B is up-side-down!

I think Freetype stores its bitmaps with the origin in the lower-left, so you need to reverse the row order to get things right-side-up... either that or some other bit of what he's doing acts that way... it's always so hard to keep straight which libraries keep their origin where once I already have "black box" code that just deals with it all for me, but it's upside down because of that I'd bet.

Share this post


Link to post
Share on other sites
Yes, the B is up-side-down, as Shinkage said, the problem is the way freetype stores bitmaps. Not really a problem indeed, just have to reverse the rows.

However, using pitch instead of width doesn't solve the issue. It seems that for some characters the buffer size doesn't match width * rows (or width * pitch). It's like freetype uses a fixed width/height for all glyphs and uses that one for all the others. I'm going to do some debug and update as soon as possible.

Share this post


Link to post
Share on other sites
Ok, wrote a little program to check bitmaps that don't look right, here the results:


A - WRONG
bitmap width : 37
bitmap rows : 38
bitmap pitch : 37

B - CORRECT
bitmap width : 32
bitmap rows : 38
bitmap pitch : 32

C - WRONG
bitmap width : 33
bitmap rows : 39
bitmap pitch : 33

D - CORRECT
bitmap width : 32
bitmap rows : 38
bitmap pitch : 32

E - CORRECT
bitmap width : 28
bitmap rows : 38
bitmap pitch : 28

F - WRONG
bitmap width : 25
bitmap rows : 38
bitmap pitch : 25

G - CORRECT
bitmap width : 36
bitmap rows : 40
bitmap pitch : 36

H - WRONG
bitmap width : 30
bitmap rows : 38
bitmap pitch : 30

I - WRONG
bitmap width : 7
bitmap rows : 38
bitmap pitch : 7

J - CORRECT
bitmap width : 24
bitmap rows : 39
bitmap pitch : 24

K - WRONG
bitmap width : 34
bitmap rows : 38
bitmap pitch : 34

L - WRONG
bitmap width : 26
bitmap rows : 38
bitmap pitch : 26

M - WRONG
bitmap width : 35
bitmap rows : 38
bitmap pitch : 35

N - WRONG
bitmap width : 30
bitmap rows : 38
bitmap pitch : 30

O - WRONG
bitmap width : 37
bitmap rows : 40
bitmap pitch : 37

P - WRONG
bitmap width : 29
bitmap rows : 38
bitmap pitch : 29

Q - WRONG
bitmap width : 38
bitmap rows : 43
bitmap pitch : 38

R - WRONG
bitmap width : 34
bitmap rows : 38
bitmap pitch : 34

S - WRONG
bitmap width : 30
bitmap rows : 40
bitmap pitch : 30

T - WRONG
bitmap width : 29
bitmap rows : 38
bitmap pitch : 29

U - WRONG
bitmap width : 30
bitmap rows : 39
bitmap pitch : 30

V - WRONG
bitmap width : 35
bitmap rows : 38
bitmap pitch : 35

W - WRONG
bitmap width : 49
bitmap rows : 38
bitmap pitch : 49

X - WRONG
bitmap width : 35
bitmap rows : 38
bitmap pitch : 35

Y - WRONG
bitmap width : 35
bitmap rows : 38
bitmap pitch : 35

Z - WRONG
bitmap width : 30
bitmap rows : 38
bitmap pitch : 30



So I think you are right Decrius, bitmaps' widths should be aligned to the nearest largest multiple of 4, shouldn't they?

Share this post


Link to post
Share on other sites
Quote:
Original post by Taylor001
However, using pitch instead of width doesn't solve the issue. It seems that for some characters the buffer size doesn't match width * rows (or width * pitch). It's like freetype uses a fixed width/height for all glyphs and uses that one for all the others. I'm going to do some debug and update as soon as possible.


Are you sure that you're not accidentally using the pitch when writing into the memory buffer you allocated yourself?

Besides the pitch thing I can't see what should be wrong with your code, although I don't understand why your glyphs are coming out upside down - in my freetype code I certainly don't flip them and it works fine.

Can you post how your code looks after you changed the pitch thing?

Have you tried printing your glyphs to stdout with printf() to verify that the problem isn't later in your rendering pipeline?

Share this post


Link to post
Share on other sites
Quote:
Original post by rneckelmann
Quote:
Original post by Taylor001
However, using pitch instead of width doesn't solve the issue. It seems that for some characters the buffer size doesn't match width * rows (or width * pitch). It's like freetype uses a fixed width/height for all glyphs and uses that one for all the others. I'm going to do some debug and update as soon as possible.


Are you sure that you're not accidentally using the pitch when writing into the memory buffer you allocated yourself?

Besides the pitch thing I can't see what should be wrong with your code, although I don't understand why your glyphs are coming out upside down - in my freetype code I certainly don't flip them and it works fine.

Can you post how your code looks after you changed the pitch thing?

Have you tried printing your glyphs to stdout with printf() to verify that the problem isn't later in your rendering pipeline?


The new pitched code looks like this:


for (unsigned int i = 0; i &lt; bitmap.rows; i++) {
for (unsigned int j = 0; j &lt; bitmap.width; j++) {

bitmapBuffer[j + i * bitmap.width] = bitmap.buffer[j + i * bitmap.pitch];
}
}



Bitmap rendering is done through a call to glDrawPixels(bitmap.width, bitmap.height, GL_LUMINANCE, GL_UNSIGNED_BYTE, bitmapBuffer);

Share this post


Link to post
Share on other sites
Quote:
Bitmap rendering is done through a call to glDrawPixels(bitmap.width, bitmap.height, GL_LUMINANCE, GL_UNSIGNED_BYTE, bitmapBuffer);


Ah, okay, that atleast explains the flipping :P.

I looked at my old code again and saw that I'm using FT_Set_Pixel_Sizes() to specify the size of my font in screen pixels in contrary to your FT_Set_Char_Size() which works in device units.

For the individual glyphs I calculate the width and height in pixels:

int nWidth = SomeFace->glyph->metrics.width / 64;
int nHeight = SomeFace->glyph->metrics.height / 64;


I guess you can fix your problem by doing something similar, although I have no clue why FT_Set_Char_Size() isn't producing the same results. (It's probably related to your glyph dimensions ending up as non-integer for some specific glyphs...)

[Edited by - rneckelmann on August 27, 2010 6:35:27 PM]

Share this post


Link to post
Share on other sites
Tried switching to FT_Set_Pixel_Sizes but result is the same.
bitmap.rows/width and metrics.width/height >> 6 produce the same results, so, nothing changes. :\

Share this post


Link to post
Share on other sites
Quote:
Original post by Taylor001
Tried switching to FT_Set_Pixel_Sizes but result is the same.
bitmap.rows/width and metrics.width/height >> 6 produce the same results, so, nothing changes. :\


Very strange. Someone above mentioned something about multiple of 4. Tried snapping your glyph sizes to that?

Otherwise try to grab one of the tutorials from freetype.org and slowly change it into what you got now - and check when it stops to work :P

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!