Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Borghetti <bdiego@gmail.com>2009-04-07 12:42:28 +0400
committerDiego Borghetti <bdiego@gmail.com>2009-04-07 12:42:28 +0400
commit59190778a8606079644b91992a3c90b7723e0adf (patch)
tree5c85797ca089fb34bab6ae4edc5f778538636692 /source/blender/blenfont/intern/blf_glyph.c
parent44877d0add0101e92bdfc48d065df83a7b541063 (diff)
New Bitmap draw mode for Freetype2 fonts.
The library can load any font supported by the Freetype2 library or used the internal bitmap font. With both types it's possible draw the text as texture or bitmap, and using texture it's possible rotate, scale and clipping text. Still have things to fix/add, but I think it's ready to move-on and start droping the old api, most of (if it's not all) the editors/interface/text.c will be remove, but some things still has to be define, like: * Where is store the fonts ? (default font, panel font, filesel font, etc) I mean, every space have own fonts ? or we keep it on the context ? It's not a really problem from the blenfont side, because every font have reference number, so it's load only the first time. * What we do about gettext ? Keep the old system that call gettext inside the blenfont or replace it for _() in the Blender source ? Also things like pupmen has to be take care, if we want translate the menu. Ok, time to sleep, back tomorrow to start moving the things :)
Diffstat (limited to 'source/blender/blenfont/intern/blf_glyph.c')
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c229
1 files changed, 195 insertions, 34 deletions
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 7212deff8c8..628e5f3e6af 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -197,20 +197,30 @@ GlyphBLF *blf_glyph_search(GlyphCacheBLF *gc, unsigned int c)
return(NULL);
}
-GlyphBLF *blf_glyph_add(FontBLF *font, FT_UInt index, unsigned int c)
+GlyphBLF *blf_glyph_texture_add(FontBLF *font, FT_UInt index, unsigned int c)
{
FT_GlyphSlot slot;
GlyphCacheBLF *gc;
GlyphBLF *g;
+ GlyphTextureBLF *gt;
FT_Face face;
FT_Error err;
FT_Bitmap bitmap;
FT_BBox bbox;
unsigned int key;
+ int do_new;
g= blf_glyph_search(font->glyph_cache, c);
- if (g)
+
+ /* The glyph can be add on Bitmap mode, so we have the
+ * glyph, but not the texture data.
+ */
+ if (g && g->tex_data)
return(g);
+ else if (g)
+ do_new= 0;
+ else
+ do_new= 1;
face= (FT_Face)font->engine;
err= FT_Load_Glyph(face, index, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP);
@@ -224,12 +234,18 @@ GlyphBLF *blf_glyph_add(FontBLF *font, FT_UInt index, unsigned int c)
if (err || slot->format != FT_GLYPH_FORMAT_BITMAP)
return(NULL);
- g= (GlyphBLF *)MEM_mallocN(sizeof(GlyphBLF), "blf_glyph_add");
- g->next= NULL;
- g->prev= NULL;
- g->c= c;
+ if (do_new) {
+ g= (GlyphBLF *)MEM_mallocN(sizeof(GlyphBLF), "blf_glyph_add");
+ g->next= NULL;
+ g->prev= NULL;
+ g->tex_data= NULL;
+ g->bitmap_data= NULL;
+ g->c= c;
+ }
+ gt= (GlyphTextureBLF *)MEM_mallocN(sizeof(GlyphTextureBLF), "blf_glyph_texture_add");
gc= font->glyph_cache;
+
if (gc->cur_tex == -1) {
blf_glyph_cache_texture(font, gc);
gc->x_offs= gc->pad;
@@ -247,27 +263,27 @@ GlyphBLF *blf_glyph_add(FontBLF *font, FT_UInt index, unsigned int c)
}
bitmap= slot->bitmap;
- g->tex= gc->textures[gc->cur_tex];
+ gt->tex= gc->textures[gc->cur_tex];
- g->xoff= gc->x_offs;
- g->yoff= gc->y_offs;
- g->width= bitmap.width;
- g->height= bitmap.rows;
+ gt->xoff= gc->x_offs;
+ gt->yoff= gc->y_offs;
+ gt->width= bitmap.width;
+ gt->height= bitmap.rows;
- if (g->width && g->height) {
+ if (gt->width && gt->height) {
glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glBindTexture(GL_TEXTURE_2D, g->tex);
- glTexSubImage2D(GL_TEXTURE_2D, 0, g->xoff, g->yoff, g->width, g->height, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.buffer);
+ glBindTexture(GL_TEXTURE_2D, gt->tex);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, gt->xoff, gt->yoff, gt->width, gt->height, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.buffer);
glPopClientAttrib();
}
g->advance= ((float)slot->advance.x) / 64.0f;
- g->pos_x= slot->bitmap_left;
- g->pos_y= slot->bitmap_top;
+ gt->pos_x= slot->bitmap_left;
+ gt->pos_y= slot->bitmap_top;
FT_Outline_Get_CBox(&(slot->outline), &bbox);
g->box.xmin= ((float)bbox.xMin) / 64.0f;
@@ -275,38 +291,160 @@ GlyphBLF *blf_glyph_add(FontBLF *font, FT_UInt index, unsigned int c)
g->box.ymin= ((float)bbox.yMin) / 64.0f;
g->box.ymax= ((float)bbox.yMax) / 64.0f;
- g->uv[0][0]= ((float)g->xoff) / ((float)gc->p2_width);
- g->uv[0][1]= ((float)g->yoff) / ((float)gc->p2_height);
- g->uv[1][0]= ((float)(g->xoff + g->width)) / ((float)gc->p2_width);
- g->uv[1][1]= ((float)(g->yoff + g->height)) / ((float)gc->p2_height);
+ gt->uv[0][0]= ((float)gt->xoff) / ((float)gc->p2_width);
+ gt->uv[0][1]= ((float)gt->yoff) / ((float)gc->p2_height);
+ gt->uv[1][0]= ((float)(gt->xoff + gt->width)) / ((float)gc->p2_width);
+ gt->uv[1][1]= ((float)(gt->yoff + gt->height)) / ((float)gc->p2_height);
/* update the x offset for the next glyph. */
gc->x_offs += (int)(g->box.xmax - g->box.xmin + gc->pad);
- key= blf_hash(g->c);
- BLI_addhead(&(gc->bucket[key]), g);
- gc->rem_glyphs--;
+ if (do_new) {
+ key= blf_hash(g->c);
+ BLI_addhead(&(gc->bucket[key]), g);
+ gc->rem_glyphs--;
+ }
+
+ /* and attach the texture information. */
+ g->tex_data= gt;
+
+ return(g);
+}
+
+GlyphBLF *blf_glyph_bitmap_add(FontBLF *font, FT_UInt index, unsigned int c)
+{
+ FT_GlyphSlot slot;
+ GlyphCacheBLF *gc;
+ GlyphBLF *g;
+ GlyphBitmapBLF *gt;
+ FT_Face face;
+ FT_Error err;
+ FT_Bitmap bitmap;
+ FT_BBox bbox;
+ unsigned char *dest, *src;
+ unsigned int key, y;
+ unsigned int src_width, src_height, src_pitch;
+ int do_new;
+
+ g= blf_glyph_search(font->glyph_cache, c);
+
+ /*
+ * The glyph can be add on Texture mode, so we have the
+ * glyph, but not the bitmap data.
+ */
+ if (g && g->bitmap_data)
+ return(g);
+ else if (g)
+ do_new= 0;
+ else
+ do_new= 1;
+
+ face= (FT_Face)font->engine;
+ err= FT_Load_Glyph(face, index, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP);
+ if (err)
+ return(NULL);
+
+ /* get the glyph. */
+ slot= face->glyph;
+
+ err= FT_Render_Glyph(slot, FT_RENDER_MODE_MONO);
+ if (err || slot->format != FT_GLYPH_FORMAT_BITMAP)
+ return(NULL);
+
+ if (do_new) {
+ g= (GlyphBLF *)MEM_mallocN(sizeof(GlyphBLF), "blf_glyph_add");
+ g->next= NULL;
+ g->prev= NULL;
+ g->tex_data= NULL;
+ g->bitmap_data= NULL;
+ g->c= c;
+ }
+
+ gt= (GlyphBitmapBLF *)MEM_mallocN(sizeof(GlyphBitmapBLF), "blf_glyph_bitmap_add");
+ gc= font->glyph_cache;
+
+ bitmap= slot->bitmap;
+
+ src_width= bitmap.width;
+ src_height= bitmap.rows;
+ src_pitch= bitmap.pitch;
+
+ gt->width= src_width;
+ gt->height= src_height;
+ gt->pitch= src_pitch;
+ gt->image= NULL;
+
+ if (gt->width && gt->height) {
+ gt->image= (unsigned char *)malloc(gt->pitch * gt->height);
+
+ dest= gt->image + ((gt->height - 1) * gt->pitch);
+ src= bitmap.buffer;
+
+ for (y= 0; y < src_height; ++y) {
+ memcpy((void *)dest, (void *)src, src_pitch);
+ dest -= gt->pitch;
+ src += src_pitch;
+ }
+ }
+
+ g->advance= ((float)slot->advance.x) / 64.0f;
+ gt->pos_x= slot->bitmap_left;
+ gt->pos_y= ((int)src_height) - slot->bitmap_top;
+
+ FT_Outline_Get_CBox(&(slot->outline), &bbox);
+ g->box.xmin= ((float)bbox.xMin) / 64.0f;
+ g->box.xmax= ((float)bbox.xMax) / 64.0f;
+ g->box.ymin= ((float)bbox.yMin) / 64.0f;
+ g->box.ymax= ((float)bbox.yMax) / 64.0f;
+
+ if (do_new) {
+ key= blf_hash(g->c);
+ BLI_addhead(&(gc->bucket[key]), g);
+ gc->rem_glyphs--;
+ }
+
+ /* and attach the bitmap information. */
+ g->bitmap_data= gt;
+
return(g);
}
+GlyphBLF *blf_glyph_add(FontBLF *font, FT_UInt index, unsigned int c)
+{
+ if (font->mode == BLF_MODE_BITMAP)
+ return(blf_glyph_bitmap_add(font, index, c));
+ return(blf_glyph_texture_add(font, index, c));
+}
+
void blf_glyph_free(GlyphBLF *g)
{
+ if (g->tex_data)
+ MEM_freeN(g->tex_data);
+
+ if (g->bitmap_data) {
+ if (g->bitmap_data->image)
+ free((void *)g->bitmap_data->image);
+ MEM_freeN(g->bitmap_data);
+ }
+
/* don't need free the texture, the GlyphCache already
* have a list of all the texture and free it.
*/
MEM_freeN(g);
}
-int blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
+int blf_glyph_texture_render(FontBLF *font, GlyphBLF *g, float x, float y)
{
+ GlyphTextureBLF *gt;
GLint cur_tex;
float dx, dx1;
float y1, y2;
- dx= floor(x + g->pos_x);
- dx1= dx + g->width;
- y1= y + g->pos_y;
- y2= y + g->pos_y - g->height;
+ gt= g->tex_data;
+ dx= floor(x + gt->pos_x);
+ dx1= dx + gt->width;
+ y1= y + gt->pos_y;
+ y2= y + gt->pos_y - gt->height;
if (font->flags & BLF_CLIPPING) {
if (!BLI_in_rctf(&font->clip_rec, dx + font->pos[0], y1 + font->pos[1]))
@@ -320,24 +458,47 @@ int blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
}
glGetIntegerv(GL_TEXTURE_2D_BINDING_EXT, &cur_tex);
- if (cur_tex != g->tex)
- glBindTexture(GL_TEXTURE_2D, g->tex);
+ if (cur_tex != gt->tex)
+ glBindTexture(GL_TEXTURE_2D, gt->tex);
glBegin(GL_QUADS);
- glTexCoord2f(g->uv[0][0], g->uv[0][1]);
+ glTexCoord2f(gt->uv[0][0], gt->uv[0][1]);
glVertex2f(dx, y1);
- glTexCoord2f(g->uv[0][0], g->uv[1][1]);
+ glTexCoord2f(gt->uv[0][0], gt->uv[1][1]);
glVertex2f(dx, y2);
- glTexCoord2f(g->uv[1][0], g->uv[1][1]);
+ glTexCoord2f(gt->uv[1][0], gt->uv[1][1]);
glVertex2f(dx1, y2);
- glTexCoord2f(g->uv[1][0], g->uv[0][1]);
+ glTexCoord2f(gt->uv[1][0], gt->uv[0][1]);
glVertex2f(dx1, y1);
glEnd();
return(1);
}
+int blf_glyph_bitmap_render(FontBLF *font, GlyphBLF *g, float x, float y)
+{
+ GlyphBitmapBLF *gt;
+ GLubyte null_bitmap= 0;
+
+ gt= g->bitmap_data;
+ if (!gt->image)
+ return(1);
+
+ glBitmap(0, 0, 0.0, 0.0, x + font->pos[0], y - font->pos[1], (const GLubyte *)&null_bitmap);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, gt->pitch * 8);
+ glBitmap(gt->width, gt->height, 0.0, gt->pos_y, 0.0, 0.0, (const GLubyte *)gt->image);
+ glBitmap(0, 0, 0.0, 0.0, -x - font->pos[0], -y + font->pos[1], (const GLubyte *)&null_bitmap);
+ return(1);
+}
+
+int blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
+{
+ if (font->mode == BLF_MODE_BITMAP)
+ return(blf_glyph_bitmap_render(font, g, x, y));
+ return(blf_glyph_texture_render(font, g, x, y));
+}
+
#endif /* WITH_FREETYPE2 */