   Font Texture Alignment Issue
  I've been working on font rendering in OpenGL and have run into a big of a snag. When copying the bitmap generated by the FreeType library into an OpenGL texture the bitmap is not rendered correctly. After many hours of debugging/traces I believe it is related to the format of the texture and possibly that I am not providing the data in the correct alignment; but I am unsure (I have not worked with OpenGL for a LONG time). I'm hoping a few more eyes here can help me pick up on my mistake.Thanks.Here's the example code I was working with:#include <SDL.h>#include <windows.h>#include <GL\GL.h>#include "ft2build.h"#include <freetype/freetype.h>#include <freetype/ftglyph.h>#include <freetype/ftoutln.h>#include <freetype/fttrigon.h>#include FT_FREETYPE_H#include <stdio.h>typedef struct {  int width;  int height;  int xoffset;  int yoffset;  float texels[4];} Glyph;int SDL_main(int argc, char *argA[]) {  SDL_Event event = {0};  int running = 1;  GLuint texture = 0;  GLubyte *empty_data = 0;  int x = 50;  int y = 50;  int i, j;  int ok = 0;  const GLsizei TEXTURE_SIZE = 128;  FT_Library lib;  FT_Face face;  FT_Bitmap *bitmap;  FT_Glyph glyph;  FT_BitmapGlyph bitmap_glyph;  GLubyte* padded_bitmap;  int bw = 0;  int bh = 0;  int texNext = 0;  FT_UInt b_glyph = 0;  FT_UInt A_glyph = 0;  Glyph b, A;  FT_Vector kerning = {0};  FILE *test;  ok = !FT_Init_FreeType(&lib);  if (ok) {    FT_New_Face(lib, "Verdana.ttf", 0, &face);    FT_Set_Char_Size(face, 16*64, 16*64, 96, 96);  }  SDL_Init(SDL_INIT_VIDEO);  SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);  SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);  SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);  SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);  SDL_SetVideoMode(800, 600, 24, SDL_OPENGL);  glEnable(GL_BLEND);  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  glEnable(GL_TEXTURE_2D);  glGenTextures(1, &texture);  glBindTexture(GL_TEXTURE_2D, texture);  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);  empty_data = calloc(2 * TEXTURE_SIZE * TEXTURE_SIZE, sizeof(GLubyte));  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXTURE_SIZE, TEXTURE_SIZE, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, empty_data);  free(empty_data);  test = fopen("out.txt", "w");  b_glyph = FT_Get_Char_Index(face, 'b');  FT_Load_Char(face, 'b', FT_LOAD_DEFAULT);  FT_Get_Glyph(face->glyph, &glyph);  if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) {    FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);  }  bitmap_glyph = (FT_BitmapGlyph)glyph;  bitmap = &bitmap_glyph->bitmap;  bw = bitmap->width;  bh = bitmap->rows;  /* pad to add alpha */  padded_bitmap = calloc(2 * bw * bh, sizeof(GLubyte));  memset(padded_bitmap, 0, 2*bw*bh*sizeof(GLubyte));  for(j = 0; j < bh; j++) {    for(i = 0; i < bw; i++) { padded_bitmap[2 * (i + j * bw)] = 255; padded_bitmap[2 * (i + j * bw) + 1] = bitmap->buffer[(i + j * bw)]; putc(bitmap->buffer[(i + j * bw)] > 128 ? ' ' : '.', test);    }    putc('\n', test);  }  putc('\n', test);  b.width = bw; b.height = bh;  b.texels[0] = 0.0;  b.texels[1] = 0.0;  b.xoffset = face->glyph->bitmap_left;  b.yoffset = face->glyph->bitmap_top;  b.texels[2] = b.texels[0] + b.width / (float)TEXTURE_SIZE;  b.texels[3] = b.texels[1] + b.height / (float)TEXTURE_SIZE;  texNext += bw;  glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap->width, bitmap->rows, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, padded_bitmap);  free(padded_bitmap);  A_glyph = FT_Get_Char_Index(face, 'A');  FT_Load_Char(face, 'A', FT_LOAD_DEFAULT);  FT_Get_Glyph(face->glyph, &glyph);  if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) {    FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);  }  bitmap_glyph = (FT_BitmapGlyph)glyph;  bitmap = &bitmap_glyph->bitmap;  bw = bitmap->width;  bh = bitmap->rows;  padded_bitmap = calloc(2 * bw * bh, sizeof(GLubyte));  for(j = 0; j < bh; j++) {    for(i = 0; i < bw; i++) { padded_bitmap[2 * (i + j * bw)] = 255; padded_bitmap[2 * (i + j * bw) + 1] = bitmap->buffer; putc(bitmap-&gt;buffer[(i + j * bw)] &gt; <span class="cpp-number">128</span> ? ' ' : '.', test);    }    putc('\n', test);  }  putc('\n', test);  <span class="cpp-keyword">for</span>(j = <span class="cpp-number">0</span>; j &lt; bh; j++) {    <span class="cpp-keyword">for</span>(i = <span class="cpp-number">0</span>; i &lt; bw; i++) { padded_bitmap[<span class="cpp-number">2</span> * (i + j * bw)] = <span class="cpp-number">255</span>; padded_bitmap[<span class="cpp-number">2</span> * (i + j * bw) + <span class="cpp-number">1</span>] = bitmap-&gt;buffer; putc(padded_bitmap[<span class="cpp-number">2</span> * (i + j * bw) + <span class="cpp-number">1</span>] &gt; <span class="cpp-number">128</span> ? ' ' : '.', test);    }    putc('\n', test);  }  fclose(test);  A.width = bw; A.height = bh;  A.xoffset = face-&gt;glyph-&gt;bitmap_left;  A.yoffset = face-&gt;glyph-&gt;bitmap_top;  A.texels[<span class="cpp-number">0</span>] = (<span class="cpp-keyword">float</span>)texNext / (<span class="cpp-keyword">float</span>)TEXTURE_SIZE;  A.texels[<span class="cpp-number">1</span>] = (<span class="cpp-keyword">float</span>)<span class="cpp-number">0</span> / (<span class="cpp-keyword">float</span>)TEXTURE_SIZE;  A.texels[<span class="cpp-number">2</span>] = A.texels[<span class="cpp-number">0</span>] + A.width / (<span class="cpp-keyword">float</span>)TEXTURE_SIZE;  A.texels[<span class="cpp-number">3</span>] = A.texels[<span class="cpp-number">1</span>] + A.height / (<span class="cpp-keyword">float</span>)TEXTURE_SIZE;  glTexSubImage2D(GL_TEXTURE_2D, <span class="cpp-number">0</span>, texNext, <span class="cpp-number">0</span>, bitmap-&gt;width, bitmap-&gt;rows, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, padded_bitmap);  free(padded_bitmap);  glMatrixMode(GL_PROJECTION);  glOrtho(<span class="cpp-number">0</span>, <span class="cpp-number">800</span>, <span class="cpp-number">600</span>, <span class="cpp-number">0</span>, -<span class="cpp-number">1</span>, <span class="cpp-number">1</span>);  glMatrixMode(GL_MODELVIEW);  glTranslated(<span class="cpp-number">0</span>.<span class="cpp-number">00735</span>, <span class="cpp-number">0</span>.<span class="cpp-number">00735</span>, <span class="cpp-number">0</span>.<span class="cpp-number">0</span>);  <span class="cpp-keyword">while</span> (running) {    glClearColor(<span class="cpp-number">0</span>, <span class="cpp-number">0</span>, <span class="cpp-number">1</span>, <span class="cpp-number">0</span>);    glClear(GL_COLOR_BUFFER_BIT);    SDL_WaitEvent(&amp;event);    <span class="cpp-keyword">switch</span> (event.type) { <span class="cpp-keyword">case</span> SDL_KEYDOWN:   <span class="cpp-keyword">if</span> (event.key.keysym.sym == SDLK_ESCAPE) {running = <span class="cpp-number">0</span>;<span class="cpp-keyword">break</span>;   } <span class="cpp-keyword">case</span> SDL_QUIT:   running = <span class="cpp-number">0</span>;   <span class="cpp-keyword">break</span>; <span class="cpp-keyword">default</span>:   ;    }    FT_Get_Kerning(face, A_glyph, b_glyph, FT_KERNING_DEFAULT, &amp;kerning);    glBegin(GL_QUADS);    <span class="cpp-comment">/*b*/</span>    glTexCoord2d(b.texels[<span class="cpp-number">0</span>], b.texels[<span class="cpp-number">1</span>]); glVertex2i(x, y-b.yoffset);    glTexCoord2d(b.texels[<span class="cpp-number">0</span>], b.texels[<span class="cpp-number">3</span>]); glVertex2i(x, y+b.height-b.yoffset);    glTexCoord2d(b.texels[<span class="cpp-number">2</span>], b.texels[<span class="cpp-number">3</span>]); glVertex2i(x+b.width, y+b.height-b.yoffset);    glTexCoord2d(b.texels[<span class="cpp-number">2</span>], b.texels[<span class="cpp-number">1</span>]); glVertex2i(x+b.width, y-b.yoffset); <span class="cpp-comment">/*A*/</span>    glTexCoord2d(A.texels[<span class="cpp-number">0</span>], A.texels[<span class="cpp-number">1</span>]); glVertex2i(texNext+(kerning.x&gt;&gt;<span class="cpp-number">6</span>)+x, y-A.yoffset);    glTexCoord2d(A.texels[<span class="cpp-number">0</span>], A.texels[<span class="cpp-number">3</span>]); glVertex2i(texNext+(kerning.x&gt;&gt;<span class="cpp-number">6</span>)+x, y+A.height-A.yoffset);    glTexCoord2d(A.texels[<span class="cpp-number">2</span>], A.texels[<span class="cpp-number">3</span>]); glVertex2i(texNext+(kerning.x&gt;&gt;<span class="cpp-number">6</span>)+x+A.width, y+A.height-A.yoffset);    glTexCoord2d(A.texels[<span class="cpp-number">2</span>], A.texels[<span class="cpp-number">1</span>]); glVertex2i(texNext+(kerning.x&gt;&gt;<span class="cpp-number">6</span>)+x+A.width, y-A.yoffset);    glEnd();    SDL_GL_SwapBuffers();  }  glDeleteTextures(<span class="cpp-number">1</span>, &amp;texture);  <span class="cpp-keyword">if</span> (ok) {    FT_Done_Face(face);    FT_Done_FreeType(lib);  }  SDL_Quit();  <span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;}</pre></div><!–ENDSCRIPT–>And here's an ASCII rep of the output. Notice that the Freetype bitmaps are rendering correctly (also I have no idea why 'b' is so messed up):<pre>Freetype's returned bitmaps:  ………  ………  ………  ………  ..    …    ..   ….  ..  ……  .  ……  .  ……  .  ……  .  ……  .  ……  .  …..  ..   …  ….……   ………..    ………..…..…..  .  …..….  ..  …..….  ..   ….….  …  ….…  ….  ….…  ….   ……  …..  …..….. ....  …….  ...  ……..  ...  ………  .   ………  .What ends up &#111;n the screen:  ………  ………  ……...  ………  ..    …    ..   ….  ..  .…..  .  ……  .  ……  .  ……  .  …...  .  ……  .  …..  ..   …  …..  . … … … ……………  …… . …..…….. . . . .…. …….. ..……   …….….    ……..………....  .  ………  ..  ………  ..   ……..  …  …….  ....  …….  ….   ……  …..  …..….. ….  …….  …  ……..  …  ………  .   ………  .…………    </pre>
  That looks like the stride has the wrong value. And that only judging from the output, not even paid attention at the code =P Check if you're setting the proper stride value for the texture data.   