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 + -
显示快捷键?