font_load_ft.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,172 行 · 第 1/3 页
C
1,172 行
t = tmp2; for(x=0; x<width; x++){ for(y=0; y<r; y++){ unsigned short *srcp= t + y*(width+1) + 1; int src= *srcp; if(src){ register unsigned short *dstp= srcp - 1 + width+1; const int src2= (src + 128)>>8; unsigned *m3= m2 + src2*mwidth; int mx; *srcp= 128; for(mx=r-1; mx<mwidth; mx++){ *dstp += m3[mx]; dstp+= width+1; } } } for(; y<height-r; y++){ unsigned short *srcp= t + y*(width+1) + 1; int src= *srcp; if(src){ register unsigned short *dstp= srcp - 1 - r*(width+1); const int src2= (src + 128)>>8; unsigned *m3= m2 + src2*mwidth; int mx; *srcp= 128; for(mx=0; mx<mwidth; mx++){ *dstp += m3[mx]; dstp+= width+1; } } } for(; y<height; y++){ unsigned short *srcp= t + y*(width+1) + 1; int src= *srcp; if(src){ const int y2=r+height-y; register unsigned short *dstp= srcp - 1 - r*(width+1); const int src2= (src + 128)>>8; unsigned *m3= m2 + src2*mwidth; int mx; *srcp= 128; for(mx=0; mx<y2; mx++){ *dstp += m3[mx]; dstp+= width+1; } } } t++; } t = tmp2; s = buffer; for(y=0; y<height; y++){ for(x=0; x<width; x++){ s[x]= t[x]>>8; } s+= stride; t+= width + 1; }}static void resample_alpha(unsigned char *abuf, unsigned char *bbuf, int width, int height, int stride, float factor){ int f=factor*256.0f; int i,j; for (i = 0; i < height; i++) { unsigned char *a = abuf+i*stride; unsigned char *b = bbuf+i*stride; for(j=0;j<width;j++,a++,b++){ int x=*a; // alpha int y=*b; // bitmap x=255-((x*f)>>8); // scale if (x+y>255) x=255-y; // to avoid overflows if (x<1) x=1; else if (x>=252) x=0; *a=x; } }}#define ALLOC_INCR 32void render_one_glyph(font_desc_t *desc, int c){ FT_GlyphSlot slot; FT_UInt glyph_index; FT_BitmapGlyph glyph; int width, height, stride, maxw, off; unsigned char *abuffer, *bbuffer; int const load_flags = FT_LOAD_DEFAULT; int pen_xa; int font = desc->font[c]; int error; // fprintf(stderr, "render_one_glyph %d\n", c); if (!desc->dynamic) return; if (desc->width[c] != -1) return; if (desc->font[c] == -1) return; glyph_index = desc->glyph_index[c]; // load glyph error = FT_Load_Glyph(desc->faces[font], glyph_index, load_flags); if (error) { WARNING("FT_Load_Glyph 0x%02x (char 0x%04x) failed.", glyph_index, c); desc->font[c] = -1; return; } slot = desc->faces[font]->glyph; // render glyph if (slot->format != ft_glyph_format_bitmap) { error = FT_Render_Glyph(slot, ft_render_mode_normal); if (error) { WARNING("FT_Render_Glyph 0x%04x (char 0x%04x) failed.", glyph_index, c); desc->font[c] = -1; return; } } // extract glyph image error = FT_Get_Glyph(slot, (FT_Glyph*)&glyph); if (error) { WARNING("FT_Get_Glyph 0x%04x (char 0x%04x) failed.", glyph_index, c); desc->font[c] = -1; return; }// fprintf(stderr, "glyph generated\n"); maxw = desc->pic_b[font]->charwidth; if (glyph->bitmap.width > maxw) { fprintf(stderr, "glyph too wide!\n"); } // allocate new memory, if needed// fprintf(stderr, "\n%d %d %d\n", desc->pic_b[font]->charwidth, desc->pic_b[font]->charheight, desc->pic_b[font]->current_alloc); if (desc->pic_b[font]->current_count >= desc->pic_b[font]->current_alloc) { int newsize = desc->pic_b[font]->charwidth*desc->pic_b[font]->charheight*(desc->pic_b[font]->current_alloc+ALLOC_INCR); int increment = desc->pic_b[font]->charwidth*desc->pic_b[font]->charheight*ALLOC_INCR; desc->pic_b[font]->current_alloc += ALLOC_INCR;// fprintf(stderr, "\nns = %d inc = %d\n", newsize, increment); desc->pic_b[font]->bmp = realloc(desc->pic_b[font]->bmp, newsize); desc->pic_a[font]->bmp = realloc(desc->pic_a[font]->bmp, newsize); off = desc->pic_b[font]->current_count*desc->pic_b[font]->charwidth*desc->pic_b[font]->charheight; memset(desc->pic_b[font]->bmp+off, 0, increment); memset(desc->pic_a[font]->bmp+off, 0, increment); } abuffer = desc->pic_a[font]->bmp; bbuffer = desc->pic_b[font]->bmp; off = desc->pic_b[font]->current_count*desc->pic_b[font]->charwidth*desc->pic_b[font]->charheight; paste_bitmap(bbuffer+off, &glyph->bitmap, desc->pic_b[font]->padding + glyph->left, desc->pic_b[font]->baseline - glyph->top, desc->pic_b[font]->charwidth, desc->pic_b[font]->charheight, glyph->bitmap.width <= maxw ? glyph->bitmap.width : maxw); // fprintf(stderr, "glyph pasted\n"); FT_Done_Glyph((FT_Glyph)glyph); /* advance pen */ pen_xa = f266ToInt(slot->advance.x) + 2*desc->pic_b[font]->padding; if (pen_xa > maxw) pen_xa = maxw; desc->start[c] = off; width = desc->width[c] = pen_xa; height = desc->pic_b[font]->charheight; stride = desc->pic_b[font]->w; if (desc->tables.o_r == 0) { outline0(bbuffer+off, abuffer+off, width, height, stride); } else if (desc->tables.o_r == 1) { outline1(bbuffer+off, abuffer+off, width, height, stride); } else { outline(bbuffer+off, abuffer+off, width, height, stride, desc->tables.omt, desc->tables.o_r, desc->tables.o_w, desc->tables.o_size); }// fprintf(stderr, "fg: outline t = %lf\n", GetTimer()-t); if (desc->tables.g_r) { blur(abuffer+off, desc->tables.tmp, width, height, stride, desc->tables.gt2, desc->tables.g_r, desc->tables.g_w);// fprintf(stderr, "fg: blur t = %lf\n", GetTimer()-t); } resample_alpha(abuffer+off, bbuffer+off, width, height, stride, font_factor); desc->pic_b[font]->current_count++;}static int prepare_font(font_desc_t *desc, FT_Face face, float ppem, int pic_idx, int charset_size, FT_ULong *charset, FT_ULong *charcodes, int unicode, double thickness, double radius){ int i, err; int padding = ceil(radius) + ceil(thickness); desc->faces[pic_idx] = face; desc->pic_a[pic_idx] = malloc(sizeof(raw_file)); if (!desc->pic_a[pic_idx]) return -1; desc->pic_b[pic_idx] = malloc(sizeof(raw_file)); if (!desc->pic_b[pic_idx]) return -1; desc->pic_a[pic_idx]->bmp = NULL; desc->pic_a[pic_idx]->pal = NULL; desc->pic_b[pic_idx]->bmp = NULL; desc->pic_b[pic_idx]->pal = NULL; desc->pic_a[pic_idx]->pal = malloc(sizeof(unsigned char)*256*3); if (!desc->pic_a[pic_idx]->pal) return -1; for (i = 0; i<768; ++i) desc->pic_a[pic_idx]->pal[i] = i/3; desc->pic_b[pic_idx]->pal = malloc(sizeof(unsigned char)*256*3); if (!desc->pic_b[pic_idx]->pal) return -1; for (i = 0; i<768; ++i) desc->pic_b[pic_idx]->pal[i] = i/3;// ttime = GetTimer(); err = check_font(desc, ppem, padding, pic_idx, charset_size, charset, charcodes, unicode);// ttime=GetTimer()-ttime;// printf("render: %7lf us\n",ttime); if (err) return -1;// fprintf(stderr, "fg: render t = %lf\n", GetTimer()-t); desc->pic_a[pic_idx]->w = desc->pic_b[pic_idx]->w; desc->pic_a[pic_idx]->h = desc->pic_b[pic_idx]->h; desc->pic_a[pic_idx]->c = colors; desc->pic_a[pic_idx]->bmp = NULL;// fprintf(stderr, "fg: w = %d, h = %d\n", desc->pic_a[pic_idx]->w, desc->pic_a[pic_idx]->h); return 0; }static int generate_tables(font_desc_t *desc, double thickness, double radius){ int width = desc->max_height; int height = desc->max_width; double A = log(1.0/base)/(radius*radius*2); int mx, my, i; double volume_diff, volume_factor = 0; unsigned char *omtp; desc->tables.g_r = ceil(radius); desc->tables.o_r = ceil(thickness); desc->tables.g_w = 2*desc->tables.g_r+1; desc->tables.o_w = 2*desc->tables.o_r+1; desc->tables.o_size = desc->tables.o_w * desc->tables.o_w;// fprintf(stderr, "o_r = %d\n", desc->tables.o_r); if (desc->tables.g_r) { desc->tables.g = malloc(desc->tables.g_w * sizeof(unsigned)); desc->tables.gt2 = malloc(256 * desc->tables.g_w * sizeof(unsigned)); if (desc->tables.g==NULL || desc->tables.gt2==NULL) { return -1; } } desc->tables.om = malloc(desc->tables.o_w*desc->tables.o_w * sizeof(unsigned)); desc->tables.omt = malloc(desc->tables.o_size*256); omtp = desc->tables.omt; desc->tables.tmp = malloc((width+1)*height*sizeof(short)); if (desc->tables.om==NULL || desc->tables.omt==NULL || desc->tables.tmp==NULL) { return -1; }; if (desc->tables.g_r) { // gaussian curve with volume = 256 for (volume_diff=10000000; volume_diff>0.0000001; volume_diff*=0.5){ volume_factor+= volume_diff; desc->tables.volume=0; for (i = 0; i<desc->tables.g_w; ++i) { desc->tables.g[i] = (unsigned)(exp(A * (i-desc->tables.g_r)*(i-desc->tables.g_r)) * volume_factor + .5); desc->tables.volume+= desc->tables.g[i]; } if(desc->tables.volume>256) volume_factor-= volume_diff; } desc->tables.volume=0; for (i = 0; i<desc->tables.g_w; ++i) { desc->tables.g[i] = (unsigned)(exp(A * (i-desc->tables.g_r)*(i-desc->tables.g_r)) * volume_factor + .5); desc->tables.volume+= desc->tables.g[i]; } // gauss table: for(mx=0;mx<desc->tables.g_w;mx++){ for(i=0;i<256;i++){ desc->tables.gt2[mx+i*desc->tables.g_w] = i*desc->tables.g[mx]; } } } /* outline matrix */ for (my = 0; my<desc->tables.o_w; ++my) { for (mx = 0; mx<desc->tables.o_w; ++mx) { // antialiased circle would be perfect here, but this one is good enough double d = thickness + 1 - sqrt((mx-desc->tables.o_r)*(mx-desc->tables.o_r)+(my-desc->tables.o_r)*(my-desc->tables.o_r)); desc->tables.om[mx+my*desc->tables.o_w] = d>=1 ? base : d<=0 ? 0 : (d*base + .5); } } // outline table: for(i=0;i<256;i++){ for(mx=0;mx<desc->tables.o_size;mx++) *(omtp++) = (i*desc->tables.om[mx] + (base/2))/base; } return 0;}#ifdef USE_ICONV/* decode from 'encoding' to unicode */static FT_ULong decode_char(iconv_t *cd, char c) { FT_ULong o; char *inbuf = &c; char *outbuf = (char*)&o; size_t inbytesleft = 1; size_t outbytesleft = sizeof(FT_ULong); iconv(*cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); /* convert unicode BigEndian -> MachineEndian */ o = be2me_32(o); // if (count==-1) o = 0; // not OK, at least my iconv() returns E2BIG for all if (outbytesleft!=0) o = 0; /* we don't want control characters */ if (o>=0x7f && o<0xa0) o = 0; return o;}static int prepare_charset(char *charmap, char *encoding, FT_ULong *charset, FT_ULong *charcodes) { FT_ULong i; int count = 0; int charset_size; iconv_t cd; // check if ucs-4 is available cd = iconv_open(charmap, charmap); if (cd==(iconv_t)-1) { mp_msg(MSGT_OSD, MSGL_ERR, "iconv doesn't know %s encoding. Use the source!\n", charmap); return -1; } iconv_close(cd); cd = iconv_open(charmap, encoding); if (cd==(iconv_t)-1) { mp_msg(MSGT_OSD, MSGL_ERR, "Unsupported encoding `%s', use iconv --list to list character sets known on your system.\n", encoding); return -1; } charset_size = 256 - first_char; for (i = 0; i<charset_size; ++i) { charcodes[count] = i+first_char; charset[count] = decode_char(&cd, i+first_char); if (charset[count]!=0) ++count; } charcodes[count] = charset[count] = 0; ++count; charset_size = count; iconv_close(cd); if (charset_size==0) { mp_msg(MSGT_OSD, MSGL_ERR, "No characters to render!\n"); return -1; } return charset_size;}static int prepare_charset_unicode(FT_Face face, FT_ULong *charset, FT_ULong *charcodes) {#ifdef HAVE_FREETYPE21 FT_ULong charcode;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?