#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->buffer[(i + j * bw)] > <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 < bh; j++) {
<span class="cpp-keyword">for</span>(i = <span class="cpp-number">0</span>; i < 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->buffer;
putc(padded_bitmap[<span class="cpp-number">2</span> * (i + j * bw) + <span class="cpp-number">1</span>] > <span class="cpp-number">128</span> ? ' ' : '.', test);
}
putc('\n', test);
}
fclose(test);
A.width = bw; A.height = bh;
A.xoffset = face->glyph->bitmap_left;
A.yoffset = face->glyph->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->width, bitmap->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(&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, &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>><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>><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>><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>><span class="cpp-number">6</span>)+x+A.width, y-A.yoffset);
glEnd();
SDL_GL_SwapBuffers();
}
glDeleteTextures(<span class="cpp-number">1</span>, &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 on the screen:
……… …
…… ……..
. ……… ..
…
.. …. .. .
….. . ……
. …… .
…… . …..
. . …… .
….. ..
… ….
. . … … …
……………
…… . …..
…….. . . . .
…. …….. ..
…… …….
…. ……..
… ……..
.. . ………
.. ………
.. ……..
… ……. ..
.. ……. …
. …… ….
. …..
…..
…. …….
… ……..
… ………
. ……… .
…………
</pre>
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:
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.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement