Преглед на файлове

* OpenGL builtin font support

tags/v0.99.beta14
Jean-Yves Lamoureux jylam преди 18 години
родител
ревизия
280132493f
променени са 3 файла, в които са добавени 198 реда и са изтрити 95 реда
  1. +121
    -95
      caca/driver_gl.c
  2. +2
    -0
      cucul/cucul.h
  3. +75
    -0
      cucul/font.c

+ 121
- 95
caca/driver_gl.c Целия файл

@@ -38,6 +38,7 @@
#include "cucul.h" #include "cucul.h"
#include "cucul_internals.h" #include "cucul_internals.h"



/* /*
* Global variables * Global variables
*/ */
@@ -56,12 +57,15 @@ static void gl_handle_mouse_motion(int, int);
static void gl_handle_close(void); static void gl_handle_close(void);
#endif #endif
static void _display(void); static void _display(void);
void gl_generate_glyph(uint32_t c, uint32_t tid, caca_display_t *dp);
void gl_generate_unicode_glyph(uint32_t c, uint32_t tid, caca_display_t *dp);


struct driver_private struct driver_private
{ {
int window; int window;
unsigned int width, height; unsigned int width, height;
unsigned int new_width, new_height; unsigned int new_width, new_height;
cucul_font_t *f;
float font_width, font_height; float font_width, font_height;
float incx, incy; float incx, incy;
int id[(128 - 32)]; int id[(128 - 32)];
@@ -76,6 +80,7 @@ struct driver_private
int special_key; int special_key;


float sw, sh; float sw, sh;

}; };


static int gl_init_graphics(caca_display_t *dp) static int gl_init_graphics(caca_display_t *dp)
@@ -83,6 +88,7 @@ static int gl_init_graphics(caca_display_t *dp)
char *empty_texture; char *empty_texture;
char const *geometry; char const *geometry;
char *argv[2] = { "", NULL }; char *argv[2] = { "", NULL };
char const * const * fonts;
unsigned int width = 0, height = 0; unsigned int width = 0, height = 0;
int argc = 1; int argc = 1;
int i; int i;
@@ -100,8 +106,23 @@ static int gl_init_graphics(caca_display_t *dp)
if(width && height) if(width && height)
_cucul_set_canvas_size(dp->cv, width, height); _cucul_set_canvas_size(dp->cv, width, height);


dp->drv.p->font_width = 9;
dp->drv.p->font_height = 15;

/* Load a libcucul internal font */
fonts = cucul_get_font_list();
if(fonts[0] == NULL)
{
fprintf(stderr, "error: libcucul was compiled without any fonts\n");
return -1;
}
dp->drv.p->f = cucul_load_font(fonts[0], 0);
if(dp->drv.p->f == NULL)
{
fprintf(stderr, "error: could not load font \"%s\"\n", fonts[0]);
return -1;
}

dp->drv.p->font_width = cucul_get_font_width(dp->drv.p->f);
dp->drv.p->font_height = cucul_get_font_height(dp->drv.p->f);


dp->drv.p->width = dp->cv->width * dp->drv.p->font_width; dp->drv.p->width = dp->cv->width * dp->drv.p->font_width;
dp->drv.p->height = dp->cv->height * dp->drv.p->font_height; dp->drv.p->height = dp->cv->height * dp->drv.p->font_height;
@@ -117,12 +138,12 @@ static int gl_init_graphics(caca_display_t *dp)
dp->drv.p->key = 0; dp->drv.p->key = 0;
dp->drv.p->special_key = 0; dp->drv.p->special_key = 0;


dp->drv.p->sw = 9.0f / 16.0f;
dp->drv.p->sh = 15.0f / 16.0f;
dp->drv.p->sw = ((float)dp->drv.p->font_width) / 16.0f;
dp->drv.p->sh = ((float)dp->drv.p->font_height) / 16.0f;


glutInit(&argc, argv); glutInit(&argc, argv);


glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(dp->drv.p->width, dp->drv.p->height); glutInitWindowSize(dp->drv.p->width, dp->drv.p->height);
dp->drv.p->window = glutCreateWindow("caca for GL"); dp->drv.p->window = glutCreateWindow("caca for GL");


@@ -162,112 +183,41 @@ static int gl_init_graphics(caca_display_t *dp)
memset(empty_texture, 0xff, 16 * 16 * 4); memset(empty_texture, 0xff, 16 * 16 * 4);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);


/* ASCII glyphes textures initialisation */
for(i = 32; i < 128; i++) for(i = 32; i < 128; i++)
{ {
glGenTextures(1, (GLuint*)&dp->drv.p->id[i - 32]); glGenTextures(1, (GLuint*)&dp->drv.p->id[i - 32]);
glBindTexture(GL_TEXTURE_2D, dp->drv.p->id[i - 32]); glBindTexture(GL_TEXTURE_2D, dp->drv.p->id[i - 32]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8,
16, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, empty_texture);
glTexImage2D(GL_TEXTURE_2D, 0, 4,
16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, empty_texture);
} }


/* Unicode (CP437) glyphes textures initialisation */
for(i = 0; i < 8; i++) for(i = 0; i < 8; i++)
{ {
glGenTextures(1, (GLuint*)&dp->drv.p->id_uni[i]); glGenTextures(1, (GLuint*)&dp->drv.p->id_uni[i]);
glBindTexture(GL_TEXTURE_2D, dp->drv.p->id_uni[i]); glBindTexture(GL_TEXTURE_2D, dp->drv.p->id_uni[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8,
16, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, empty_texture);
glTexImage2D(GL_TEXTURE_2D, 0, 4,
16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, empty_texture);
} }


/* Get textures for ASCII glyphs */
for(i = 32; i < 128; i++) for(i = 32; i < 128; i++)
{
glDisable(GL_TEXTURE_2D);
glClear(GL_COLOR_BUFFER_BIT);

glColor3f(1, 1, 1);
glRasterPos2f(0, 15);
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, i);

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, dp->drv.p->id[i - 32]);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
0, dp->drv.p->height - 16, 16, 16, 0);

#ifdef HAVE_GLUTCHECKLOOP
glutCheckLoop();
#else
glutMainLoopEvent();
#endif
glutSwapBuffers();
gl_generate_glyph(i, i-32, dp);


}


/* CP437 hack */
for(i = 0; i < 8; i++)
{
glDisable(GL_TEXTURE_2D);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1, 1, 1);
glTranslatef(0.5,0.5,0);

switch(i)
{
case 0: /* 0x00002580 */
glBegin(GL_QUADS);
glVertex2f(0,0); glVertex2f(9,0); glVertex2f(9,7); glVertex2f(0,7);
glEnd();
break;
case 1: /* 0x00002584 */
glBegin(GL_QUADS);
glVertex2f(0,7); glVertex2f(9,7); glVertex2f(9,15); glVertex2f(0,15);
glEnd();
break;
case 2: /* 0x00002588 */
glBegin(GL_QUADS);
glVertex2f(0,0); glVertex2f(9,0); glVertex2f(9,15); glVertex2f(0,15);
glEnd();
break;
case 3: /* 0x0000258c */
glBegin(GL_QUADS);
glVertex2f(0,0); glVertex2f(4,0); glVertex2f(4,15); glVertex2f(0,15);
glEnd();
break;
case 4: /* 0x00002590 */
glBegin(GL_QUADS);
glVertex2f(4,0); glVertex2f(9,0); glVertex2f(9,15); glVertex2f(4,15);
glEnd();
break;
default: /* 0x0000259[123] */
{
int a, j, k = i - 5;
for(j = dp->drv.p->font_height; j--; )
for(a = dp->drv.p->font_width; a--; )
{
if(((a + 2 * (j & 1)) & 3) > k)
continue;

glBegin(GL_POINTS);
glVertex2f(a, j);
glEnd();
}
}
}

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, dp->drv.p->id_uni[i]);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
0, dp->drv.p->height - 16, 16, 16, 0);
#ifdef HAVE_GLUTCHECKLOOP
glutCheckLoop();
#else
glutMainLoopEvent();
#endif
glutSwapBuffers();
glutPostRedisplay();
}
gl_generate_unicode_glyph(0x00002580, 0, dp);
gl_generate_unicode_glyph(0x00002584, 1, dp);
gl_generate_unicode_glyph(0x00002588, 2, dp);
gl_generate_unicode_glyph(0x0000258c, 3, dp);
gl_generate_unicode_glyph(0x00002590, 4, dp);
gl_generate_unicode_glyph(0x00002591, 5, dp);
gl_generate_unicode_glyph(0x00002592, 6, dp);
gl_generate_unicode_glyph(0x00002593, 7, dp);


return 0; return 0;
} }
@@ -310,9 +260,10 @@ static void gl_display(caca_display_t *dp)
{ {
uint16_t bg = _cucul_argb32_to_rgb12bg(*attr++); uint16_t bg = _cucul_argb32_to_rgb12bg(*attr++);
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
glColor3b(((bg & 0xf00) >> 8) * 8,
glColor4b(((bg & 0xf00) >> 8) * 8,
((bg & 0x0f0) >> 4) * 8, ((bg & 0x0f0) >> 4) * 8,
(bg & 0x00f) * 8);
(bg & 0x00f) * 8,
0xff);
glBegin(GL_QUADS); glBegin(GL_QUADS);
glVertex2f(x, y); glVertex2f(x, y);
glVertex2f(x + dp->drv.p->font_width, y); glVertex2f(x + dp->drv.p->font_width, y);
@@ -328,7 +279,7 @@ static void gl_display(caca_display_t *dp)
/* 2nd pass, avoids changing render state too much */ /* 2nd pass, avoids changing render state too much */
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
glBlendFunc(GL_SRC_ALPHA,GL_ONE);


line = 0; line = 0;
for(y = 0; y < dp->drv.p->height; y += dp->drv.p->font_height, line++) for(y = 0; y < dp->drv.p->height; y += dp->drv.p->font_height, line++)
@@ -611,5 +562,80 @@ int gl_install(caca_display_t *dp)
return 0; return 0;
} }




void gl_generate_glyph(uint32_t c, uint32_t tid, caca_display_t *dp) {
int s,d;
uint8_t *glyph8 = calloc(dp->drv.p->font_width*dp->drv.p->font_height, 1);
uint8_t *glyph32 = calloc(16*16*4, 1);

cucul_render_glyph(dp->drv.p->f, c,
glyph8, dp->drv.p->font_width, dp->drv.p->font_height);


/* Convert resulting 8bbp glyph to 32bits, 16x16*/
for(s=0;s<(dp->drv.p->font_height<=16?dp->drv.p->font_height:16);s++) {
for(d=0;d<dp->drv.p->font_width;d++)
{
uint32_t offset = d*4+(15-s)*16*4;
uint8_t c = glyph8[d+s*(int)dp->drv.p->font_width];
glyph32[offset] = c;
glyph32[1+offset] = c;
glyph32[2+offset] = c;
glyph32[3+offset] = c;
}
}

glBindTexture(GL_TEXTURE_2D, dp->drv.p->id[tid]);
glTexImage2D(GL_TEXTURE_2D,
0, 4,
16,16,
0, GL_RGBA, GL_UNSIGNED_BYTE,
glyph32);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
free(glyph8);
free(glyph32);
}

void gl_generate_unicode_glyph(uint32_t c, uint32_t tid, caca_display_t *dp) {
int s,d;
uint8_t *glyph8 = calloc(dp->drv.p->font_width*dp->drv.p->font_height, 1);
uint8_t *glyph32 = calloc(16*16*4, 1);

cucul_render_glyph(dp->drv.p->f, c,
glyph8, dp->drv.p->font_width, dp->drv.p->font_height);


/* Convert resulting 8bbp glyph to 32bits, 16x16*/
for(s=0;s<(dp->drv.p->font_height<=16?dp->drv.p->font_height:16);s++) {
for(d=0;d<(dp->drv.p->font_width<=16?dp->drv.p->font_width:16);d++)
{
uint32_t offset = d*4+(15-s)*16*4;
uint8_t c = glyph8[d+s*(int)dp->drv.p->font_width];
glyph32[offset] = c;
glyph32[1+offset] = c;
glyph32[2+offset] = c;
glyph32[3+offset] = c;
}
}

glBindTexture(GL_TEXTURE_2D, dp->drv.p->id_uni[tid]);
glTexImage2D(GL_TEXTURE_2D,
0, 4,
16,16,
0, GL_RGBA, GL_UNSIGNED_BYTE,
glyph32);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
free(glyph8);
free(glyph32);
}






#endif /* USE_GL */ #endif /* USE_GL */



+ 2
- 0
cucul/cucul.h Целия файл

@@ -208,6 +208,8 @@ unsigned int cucul_get_font_width(cucul_font_t *);
unsigned int cucul_get_font_height(cucul_font_t *); unsigned int cucul_get_font_height(cucul_font_t *);
int cucul_render_canvas(cucul_canvas_t *, cucul_font_t *, void *, int cucul_render_canvas(cucul_canvas_t *, cucul_font_t *, void *,
unsigned int, unsigned int, unsigned int); unsigned int, unsigned int, unsigned int);
int cucul_render_glyph(cucul_font_t *, unsigned int, void *,
unsigned int, unsigned int);
int cucul_free_font(cucul_font_t *); int cucul_free_font(cucul_font_t *);
/* @} */ /* @} */




+ 75
- 0
cucul/font.c Целия файл

@@ -445,6 +445,81 @@ int cucul_render_canvas(cucul_canvas_t *cv, cucul_font_t *f,
return 0; return 0;
} }


/** \brief Render the given character onto given buffer
*
* This function renders the given character on an image buffer using a specific
* font. The pixel format is fixed (8 bits per pixel).
*
* The required buffer width can be computed using
* cucul_get_canvas_width() and cucul_get_font_width(). The required
* height can be computed using cucul_get_canvas_height() and
* cucul_get_font_height().
*
* Glyphs that do not fit in the image buffer are currently not rendered at
* all. They may be cropped instead in future versions.
*
* This function never fails.
*
* \param f The font, as returned by cucul_load_font()
* \param ch The character to render
* \param buf The image buffer
* \param width The width (in pixels) of the image buffer
* \param height The height (in pixels) of the image buffer
* \return This function return 1 if glyph is succesfully renderer, 0 otherwise
*/
int cucul_render_glyph(cucul_font_t *f, unsigned int ch, void *buffer,
unsigned int width, unsigned int height)
{
unsigned int b;
struct glyph_info *g;
uint8_t *glyph = buffer;



/* Find the Unicode block where our glyph lies */
for(b = 0; b < f->header.blocks; b++)
{
if(ch < f->block_list[b].start)
{
b = f->header.blocks;
break;
}
if(ch < f->block_list[b].stop) {
break;
}
}

/* Glyph not in font? Skip it. */
if(b == f->header.blocks)
return 0;

g = &f->glyph_list[f->block_list[b].index
+ ch - f->block_list[b].start];

/* Step 1: unpack glyph */
switch(f->header.bpp)
{
case 8:
glyph = f->font_data + g->data_offset;
break;
case 4:
unpack_glyph4(glyph, f->font_data + g->data_offset,
g->width * g->height);
break;
case 2:
unpack_glyph2(glyph, f->font_data + g->data_offset,
g->width * g->height);
break;
case 1:
unpack_glyph1(glyph, f->font_data + g->data_offset,
g->width * g->height);
break;
}
return 1;
}



/* /*
* The libcaca font format, version 1 * The libcaca font format, version 1
* ---------------------------------- * ----------------------------------


Зареждане…
Отказ
Запис