📄 font.c
字号:
/* font.c**** create pixmaps from text using freetype** Copyright (C) 2001 Florian Berger** Email: harpin_floh@yahoo.de, florian.berger@jk.uni-linz.ac.at**** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License Version 2 as** published by the Free Software Foundation;**** This program is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the** GNU General Public License for more details.**** You should have received a copy of the GNU General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.***/#include "options.h"#ifdef options_use_freetype#include <ft2build.h>#include FT_FREETYPE_H#include FT_OUTLINE_H#endif#include <stdio.h>#include <stdlib.h>#include <GL/gl.h>#include <GL/glu.h>#include "vmath.h"#define divisor 64000.0static int init_me=1;#ifdef options_use_freetypestatic FT_Library library; /* handle to library */#endifstruct TessDataVec{ GLdouble d[3]; int is_start; struct TessDataVec * next;};struct TessData { int points_per_spline; struct GLUtesselator * tobj; struct TessDataVec * v; FT_Vector from; int first_call;};struct TessData * new_tessdata(){ struct TessData * tessdata; tessdata=malloc(sizeof(struct TessData)); tessdata->first_call=1; tessdata->v=NULL; tessdata->tobj=gluNewTess(); tessdata->points_per_spline=3; return(tessdata);}void free_tessdata(struct TessData * tessdata){ struct TessDataVec * v; struct TessDataVec * vn; v=tessdata->v; while(v!=NULL){ vn=v->next; free(v); v=vn; } gluDeleteTess(tessdata->tobj); free( tessdata );}void my_draw_bitmap( char * src, int w1, int h1, int x0, int y0, char * dst , int w, int h ){ int x,y;// fprintf(stderr,"my_draw_bitmap: \n"); for(y=0;y<h1;y++){// fprintf(stderr,"my_draw_bitmap: y=%d\n",y); for(x=0;x<w1;x++){ dst[(y+y0)*w+x+x0]+=src[y*w1+x]; } }}void getStringPixmapFT(char *str, char *fontname, int font_height, char ** data, int * dwidth, int * dheight, int * width, int * height)/* data containes the pixmap */{#ifdef options_use_freetype FT_Face face; /* handle to face object */ int pen_x, pen_y, n,i,w,h, error, w1,h1; w1=0; h1=0; //.. initialise library .. if(init_me){ error = FT_Init_FreeType( &library ); if ( error ) { fprintf(stderr,"FT_Init_FreeType error\n"); exit(1); } else { // fprintf(stderr,"FT_New_Face OK!\n"); } init_me=0; }//#if 0//.. create face object ..// error = FT_New_Face( library, "/usr/X11/lib/X11/fonts/win-ttf/comic.ttf", 0, &face ); error = FT_New_Face( library, fontname, 0, &face );// error = FT_New_Face( library, "/usr/X11/lib/X11/fonts/win-ttf/tahomabd.ttf", 0, &face ); if ( error == FT_Err_Unknown_File_Format ){ fprintf(stderr,"the font file could be opened and read, but it appears that its font format is unsupported\n"); exit(1); } else if ( error ) { fprintf(stderr,"another error code means that the font file could not e opened or read, or simply that it is broken\n"); exit(1); } else {// fprintf(stderr,"FT_New_Face OK!\n"); } //.. set character size ..// error = FT_Set_Char_Size(// face, /* handle to face object */// 0, /* char_width in 1/64th of points */// 16*64, /* char_height in 1/64th of points */// 300, /* horizontal device resolution */// 300 ); /* vertical device resolution */ error = FT_Set_Pixel_Sizes( face, /* handle to face object */ 0, /* pixel_width */ font_height ); /* pixel_height */ pen_x = 0; pen_y = 0; // fprintf(stderr,"getStringPixmapFT: num_glyphs=%d\n",face->num_glyphs); w=0; h=font_height; for(i=0;i<2;i++){ if (i==1){ int j; for(w1=w,w=8;w<w1;w*=2); for(h1=h,h=8;h<h1;h*=2);// fprintf(stderr,"getStringPixmapFT: allocing w=%d h=%d\n",w,h); (*data)=malloc(w*h); for(j=0;j<w*h;j++) (*data)[j]=0; } for ( n = 0; str[n]!=0; n++ ) { FT_UInt glyph_index; // retrieve glyph index from character code glyph_index = FT_Get_Char_Index( face, str[n] ); // load glyph image into the slot (erase previous one) error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); if (error) { fprintf(stderr,"FT_Load_Glyph:error#%X\n",error); exit(1); } // convert to an anti-aliased bitmap// error = FT_Render_Glyph( face->glyph, ft_render_mode_mono ); error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); if (error) { fprintf(stderr,"FT_Render_Glyph:error#%X\n",error); exit(1); }/* fprintf(stderr,"getStringPixmapFT: face->glyph->bitmap_top=%d\n",face->glyph->bitmap_top); fprintf(stderr,"getStringPixmapFT: face->glyph->bitmap.rows=%d\n",face->glyph->bitmap.rows); fprintf(stderr,"getStringPixmapFT: face->glyph->bitmap.pitch=%d\n",face->glyph->bitmap.pitch); fprintf(stderr,"getStringPixmapFT: face->glyph->bitmap.width=%d\n",face->glyph->bitmap.width); fprintf(stderr,"getStringPixmapFT: face->glyph->metrics.horiBearingY=%d\n",face->glyph->metrics.horiBearingY); fprintf(stderr,"getStringPixmapFT: face->height=%d\n",face->height); fprintf(stderr,"getStringPixmapFT: face->ascender=%d\n",face->bbox.yMax); fprintf(stderr,"getStringPixmapFT: face->descender=%d\n",face->descender);*/ if(i!=0){ // now, draw to our target surface my_draw_bitmap( (char *)face->glyph->bitmap.buffer, face->glyph->bitmap.width, face->glyph->bitmap.rows,// pen_x, pen_y, pen_x + face->glyph->bitmap_left, pen_y + font_height*face->ascender/(face->ascender-face->descender) - face->glyph->bitmap_top, *data , w, h); pen_x += (face->glyph->advance.x >> 6); } else {// fprintf(stderr,"getStringPixmapFT: w=%d h=%d\n",w,h); w += (face->glyph->advance.x >> 6);// fprintf(stderr,"getStringPixmapFT: w=%d h=%d\n",w,h); }// free(face->glyph->bitmap.buffer); } } error = FT_Done_Face(face); if ( error ) { fprintf(stderr,"FT_Done_Face error# %d\n",error); exit(1); }//#endif/* fprintf(stderr,"FT_Done_FreeType\n"); error = FT_Done_FreeType( library ); if ( error ) { fprintf(stderr,"FT_Done_FreeType error# %d\n",error); exit(1); }*/ DPRINTF("FT_Done_FreeType ready\n"); *dwidth=w; *dheight=h; if( width != NULL ) *width = w1; if( height != NULL ) *height = h1;#endif}void my_Vertex_cb(void * data){ GLdouble * d; d=(GLdouble *)data; glNormal3f(0,0,-1); glVertex3f(d[0],d[1],d[2]);}void tess_add_point( VMvect v, struct TessData * data, int is_start ){ struct TessDataVec * tdv; struct TessDataVec * tdv_p = NULL; tdv=data->v; while(tdv!=NULL){ tdv_p=tdv; tdv=tdv->next; } tdv=malloc(sizeof(struct TessDataVec)); tdv->d[0]=v.x/divisor; tdv->d[1]=v.y/divisor; tdv->d[2]=v.z/divisor; tdv->is_start=is_start; tdv->next=NULL; if(data->v == NULL){ data->v=tdv; } if(tdv_p != NULL){ tdv_p->next=tdv; } gluTessVertex(data->tobj, tdv->d, tdv->d);}int cb_tess_move_to( FT_Vector * to, void * user ){ // int * first_call = (int *) user; VMvect v; struct TessData * data = (struct TessData *) user; if( ! data->first_call ){ gluTessEndContour(data->tobj); } else { data->first_call=0; } gluTessBeginContour(data->tobj); v=vec_xyz( to->x, to->y, 0.0 ); tess_add_point(v, data, 1); data->from=*to; return 0;}int cb_tess_line_to( FT_Vector * to, void * user ){ VMvect v; struct TessData * data = (struct TessData *) user; v=vec_xyz( to->x, to->y, 0.0 ); tess_add_point(v, data, 0); data->from=*to; return 0;}VMvect conic_spline_point( VMvect vi, VMvect vf, VMvect vc, double t ){ VMvect v1, v2, v; v1=vec_add(vi,vec_scale(vec_diff(vc,vi),t)); v2=vec_add(vc,vec_scale(vec_diff(vf,vc),t)); v =vec_add(v1,vec_scale(vec_diff(v2,v1),t)); return v;}VMvect cubic_spline_point( VMvect vi, VMvect vf, VMvect vc1, VMvect vc2, double t ){ VMvect v1, v2, v3, v4, v5, v; v1=vec_add(vi, vec_scale(vec_diff(vc1,vi ),t)); v2=vec_add(vc1,vec_scale(vec_diff(vc2,vc1),t));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -