📄 dip.c
字号:
apply_gamma_single_8_to_16(style->r1,user_gamma/sRGB_gamma), apply_gamma_single_8_to_16(style->g1,user_gamma/sRGB_gamma), apply_gamma_single_8_to_16(style->b1,user_gamma/sRGB_gamma) ); if (display_optimize){ /* A correction for LCD */ new->bitmap.x/=3; decimate_3(&primary_data,new->bitmap.x,new->bitmap.y); } /* We have a buffer with photons */ gd->get_empty_bitmap(&(new->bitmap)); if (dither_letters) dither(primary_data, &(new->bitmap)); else (*round_fn)(primary_data,&(new->bitmap)); mem_free(primary_data); gd->register_bitmap(&(new->bitmap)); if (do_free){ mem_free(found->bitmap.data); mem_free(found); } bytes_consumed=new->bitmap.x*new->bitmap.y*(gd->depth&7); /* Number of bytes per pixel in passed bitmaps */ bytes_consumed+=sizeof(*new); bytes_consumed+=sizeof(struct lru_entry); lru_insert(&font_cache, new, &(letter->color_list), bytes_consumed); return new;}/* Prunes the cache to comply with maximum size */static inline void prune_font_cache(struct graphics_driver *gd){ struct font_cache_entry *bottom; while(font_cache.bytes>font_cache.max_bytes){ /* Prune bottom entry of font cache */ bottom=lru_get_bottom(&font_cache); if (!bottom){#ifdef DEBUG if (font_cache.bytes||font_cache.items){ internal("font cache is empty and contains\some items or bytes at the same time.\n"); }#endif break; } if (bottom->type==FC_COLOR){ gd->unregister_bitmap(&(bottom->bitmap)); }else{ mem_free(bottom->bitmap.data); } mem_free(bottom); lru_destroy_bottom(&font_cache); }}/* Prints a letter to the specified position and * returns the width of the printed letter */inline static int print_letter(struct graphics_driver *gd, struct graphics_device *device, int x, int y, struct style *style, int char_number){ struct font_cache_entry *found; struct font_cache_entry template; struct letter *letter; /* Find a suitable letter */ letter=find_stored_letter(style->table,char_number);#ifdef DEBUG if (!letter) internal("print_letter could not find a letter - even not the blotch!");#endif /* #ifdef DEBUG */ template.type=FC_COLOR; template.r0=style->r0; template.r1=style->r1; template.g0=style->g0; template.g1=style->g1; template.b0=style->b0; template.b1=style->b1; template.bitmap.y=style->height; template.mono_space=style->mono_space; template.mono_height=style->mono_height; found=lru_lookup(&font_cache, &template, letter->color_list); if (!found) found=supply_color_cache_entry(gd, style, letter); gd->draw_bitmap(device, &(found->bitmap), x, y); prune_font_cache(gd); return found->bitmap.x;}/* Must return values that are: * >=0 * <=height * at least 1 apart * Otherwise g_print_text will print nonsense (but won't segfault) */void get_underline_pos(int height, int *top, int *bottom){ int thickness, baseline; thickness=(height+15)/16; baseline=height/7; if (baseline<=0) baseline=1; if (thickness>baseline) thickness=baseline; *top=height-baseline; *bottom=*top+thickness;}/* *width will be advanced by the width of the text */void g_print_text(struct graphics_driver *gd, struct graphics_device *device,int x, int y, struct style *style, unsigned char *text, int *width){ int original_flags, top_underline, bottom_underline, original_width, my_width; struct rect saved_clip; if (y+style->height<=device->clip.y1||y>=device->clip.y2) goto o; if (style -> flags){ /* Underline */ if (!width){ width=&my_width; *width=0; } original_flags=style->flags; original_width=*width; style -> flags=0; get_underline_pos(style->height, &top_underline, &bottom_underline); restrict_clip_area(device, &saved_clip, 0, 0, device->size.x2, y+ top_underline); g_print_text(gd, device, x, y, style, text, width); gd->set_clip_area(device, &saved_clip); if (bottom_underline-top_underline==1){ /* Line */ drv->draw_hline(device, x, y+top_underline , x+*width-original_width , style->underline_color); }else{ /* Area */ drv->fill_area(device, x, y+top_underline, x+*width-original_width ,y+bottom_underline, style->underline_color); } if (bottom_underline<style->height){ /* Do the bottom half only if the underline is above * the bottom of the letters. */ *width=original_width; restrict_clip_area(device, &saved_clip, 0, y+bottom_underline, device->size.x2, device->size.y2); g_print_text(gd, device, x, y, style, text, width); gd->set_clip_area(device, &saved_clip); } style -> flags=original_flags; return; } while (*text){ int p; int u; GET_UTF_8(text, u); /* 00-09, 0b-1f, 80, 81, 84, 86-9f ignorovat * 0a = LF * 82 = ' ' * 83 = nobrk * 85 = radkovy zlom * a0 = NBSP * ad = soft hyphen */ #if 0 if ( (u>=0x00&&u<=0x09)|| (u>=0x0b&&u<=0x1f)|| u==0x80|| u==0x82|| u==0x84|| (u>=0x86&&u<=0x9f) )continue; if (u==0x82)u=' '; #endif /* stare Mikulasovo patchovani, musim to opravit -- Brain */ if (!u || u == 0xad) continue; if (u == 0x01 || u == 0xa0) u = ' '; p=print_letter(gd,device,x,y,style, u); x += p; if (width) { *width += p; continue; } if (x>=device->clip.x2) return; } return; o: if (width) *width += g_text_width(style, text);}/* 0=equality 1=inequality */int compare_font_entries(void *entry, void *template){ struct font_cache_entry*e1=entry; struct font_cache_entry*e2=template; if (e1->type==FC_COLOR){ return( (e1->r0!=e2->r0)|| (e1->g0!=e2->g0)|| (e1->b0!=e2->b0)|| (e1->r1!=e2->r1)|| (e1->g1!=e2->g1)|| (e1->b1!=e2->b1)|| (e1->bitmap.y!=e2->bitmap.y)|| (e1->mono_space!=e2->mono_space)|| (e1->mono_space>=0&&e1->mono_height!=e2->mono_height)); }else{ return e1->bitmap.y!=e2->bitmap.y; } }/* If the cache already exists, it is destroyed and reallocated. If you call it with the same * size argument, only a cache flush will yield. */void init_font_cache(int bytes){ lru_init(&font_cache, &compare_font_entries, bytes);}/* Ensures there are no lru_entry objects allocated - destroys them. * Also destroys the bitmaps asociated with them. Does not destruct the font_cache per se. */void destroy_font_cache(void){ struct font_cache_entry *bottom; while((bottom=lru_get_bottom(&font_cache))){ if (bottom->type==FC_COLOR){ drv->unregister_bitmap(&(bottom->bitmap)); }else{ /* Then it must be FC_BW. */ mem_free(bottom->bitmap.data); } mem_free(bottom); lru_destroy_bottom(&font_cache); }}/* Returns 0 in case the char is not found. */static inline int g_get_width(struct style *style, int charcode){ int x, y, width; if (!charcode || charcode == 0xad) return 0; if (charcode == 0x01 || charcode == 0xa0) charcode = ' '; if (style->mono_space>=0){ x=style->mono_space; y=style->mono_height; }else load_metric(&x,&y,charcode,style->table); if (!(x&&y)) width=0; else width=compute_width(x,y,style->height); return width;}int g_text_width(struct style *style, unsigned char *text){ int w = 0; while (*text) { int u; GET_UTF_8(text, u); w += g_get_width(style, u); } return w;}int g_char_width(struct style *style, int charcode){ return g_get_width(style, charcode);}int g_wrap_text(struct wrap_struct *w){ while (*w->text) { int u; int s; if (*w->text == ' ') w->last_wrap = w->text, w->last_wrap_obj = w->obj; GET_UTF_8(w->text, u); if (!u) continue; if (u == 0x01 || u == 0xa0) u = ' '; s = g_get_width(w->style, u); if (u == 0xad) s = 0; if ((w->pos += s) <= w->width) { c: if (u != 0xad || *w->text == ' ') continue; s = g_char_width(w->style, '-'); if (w->pos + s <= w->width || (!w->last_wrap && !w->last_wrap_obj)) { w->last_wrap = w->text; w->last_wrap_obj = w->obj; continue; } } if (!w->last_wrap && !w->last_wrap_obj) goto c; return 0; } return 1;}void update_aspect(void){ aspect=aspect_on?(aspect_native*bfu_aspect+0.5):65536UL;}void init_dip(void){ update_aspect(); /* Initializes to 2 MByte */ init_font_cache(2000000);}void shutdown_dip(void){ destroy_font_cache();}void recode_font_name(unsigned char **name){ int dashes=0; unsigned char *p; if (!strcmp(*name,"monospaced")) *name="courier-medium-roman-serif-mono"; if (!strcmp(*name,"monospace")) *name="courier-medium-roman-serif-mono"; else if (!strcmp(*name,"")) *name="century_school-medium-roman-serif-vari"; p=*name; while(*p){ if (*p=='-')dashes++; p++; } if (dashes!=4) *name="century_school-medium-roman-serif-vari";}/* Compares single=a multi=b-c-a as matching. * 0 matches * 1 doesn't match */int compare_family(unsigned char *single, unsigned char *multi){ unsigned char *p,*r; int single_length=strlen(single); r=multi; while(1){ p=r; while (*r&&*r!='-')r++; if ((r-p==single_length)&&!strncmp(single,p,r-p)) return 0; if (!*r) return 1; r++; } return 1;}/* Input name must contain exactly 4 dashes, otherwise the * result is undefined (parsing into weight, slant, adstyl, spacing * will result deterministically random results). * Returns 1 if the font is monospaced or 0 if not. */int fill_style_table(int * table, unsigned char *name){ unsigned char *p; unsigned char *family, *weight, *slant, *adstyl, *spacing; int pass,result,f; int masks[6]={0x1f,0x1f,0xf,0x7,0x3,0x1}; int xors[6]={0,0x10,0x8,0x4,0x2,0x1}; /* Top bit of the values belongs to family, bottom to spacing */ int monospaced; /* Parse the name */ recode_font_name(&name); family=stracpy(name); p=family; while(*p&&*p!='-') p++; *p=0; p++; weight=p; while(*p&&*p!='-') p++; *p=0; p++; slant=p; while(*p&&*p!='-') p++; *p=0; p++; adstyl=p; while(*p&&*p!='-') p++; *p=0; p++; spacing=p; monospaced=!strcmp(spacing,"mono"); for (pass=0;pass<6;pass++){ for (f=1;f<n_fonts;f++){ /* Font 0 must not be int style_table */ result=compare_family(family,font_table[f].family); result<<=1; result|=!!strcmp(weight,font_table[f].weight); result<<=1; result|=!!strcmp(slant,font_table[f].slant); result<<=1; result|=!!strcmp(adstyl,font_table[f].adstyl); result<<=1; result|=!!strcmp(spacing,font_table[f].spacing); result^=xors[pass]; result&=masks[pass]; if (!result) /* Fot complies */ *table++=f; } } mem_free(family); return monospaced;}struct style *g_invert_style(struct style *old){ int length; struct style *st; st = mem_alloc(sizeof(struct style)); st->refcount=1; st->r0=old->r1; st->g0=old->g1; st->b0=old->b1; st->r1=old->r0; st->g1=old->g0; st->b1=old->b0; st->height=old->height; st->flags=old->flags; if (st->flags) { /* We have to get a foreground color for underlining */ st->underline_color=dip_get_color_sRGB( (st->r1<<16)|(st->g1<<8)|(st->b1)); } if ((unsigned)n_fonts > MAXINT / sizeof(*st->table)) overalloc(); length=sizeof(*st->table)*(n_fonts-1); st->table=mem_alloc(length); memcpy(st->table,old->table,length); st->mono_space=old->mono_space; st->mono_height=old->mono_height; return st;}/* Never returns NULL. */struct style *g_get_style(int fg, int bg, int size, unsigned char *font, int flags){ struct style *st; st = mem_alloc(sizeof(struct style)); /* strcpy(st->font, font); */ st->refcount = 1; st->r0 = bg >> 16; st->g0 = (bg >> 8) & 255; st->b0 = bg & 255; st->r1 = fg >> 16; st->g1 = (fg >> 8) & 255; st->b1 = fg & 255; if (size<=0) size=1; st->height = size; st->flags=flags&FF_UNDERLINE; if (st->flags) { /* We have to get a foreground color for underlining */ st->underline_color=dip_get_color_sRGB(fg); } if ((unsigned)n_fonts > MAXINT / sizeof(*st->table)) overalloc(); st->table=mem_alloc(sizeof(*st->table)*(n_fonts-1)); if(fill_style_table(st->table, font)) load_metric(&(st->mono_space), &(st->mono_height),' ',st->table); else st->mono_space=-1; return st;}struct style *g_clone_style(struct style *st){ st->refcount++; return st;}void g_free_style(struct style *st){ if (--st->refcount) return; mem_free(st->table); mem_free(st);}long gamma_cache_color;int gamma_cache_rgb = -2;/* IEC 61966-2-1 * Input gamma: sRGB space (directly from HTML, i. e. unrounded) * Output: color index for graphics driver that is closest to the * given sRGB value. * We assume unsigned short holds at least 16 bits. */long real_dip_get_color_sRGB(int rgb){ unsigned short r,g,b; int new_rgb; round_color_sRGB_to_48(&r,&g,&b,rgb); r=apply_gamma_single_16_to_8(r,1/display_red_gamma); g=apply_gamma_single_16_to_8(g,1/display_green_gamma); b=apply_gamma_single_16_to_8(b,1/display_blue_gamma); new_rgb=b|(g<<8)|(r<<16); gamma_cache_rgb = rgb; /* The get_color takes values with gamma of display_*_gamma */ return gamma_cache_color = drv->get_color(new_rgb);}/* ATTENTION!!! allocates using malloc. Due to braindead Xlib, which * frees it using free and thus it is not possible to use mem_alloc. */void get_links_icon(unsigned char **data, int *width, int* height, int depth){ struct bitmap b; unsigned short *tmp1; double g=user_gamma/sRGB_gamma; b.x=48; b.y=48; *width=b.x; *height=b.y; b.skip=b.x*(depth&7); if (!(b.data=*data=malloc(b.skip*b.y))) { malloc_oom(); } tmp1=mem_alloc(6*b.y*b.x); apply_gamma_exponent_24_to_48(tmp1,links_icon,b.x*b.y,g,g,g); dither(tmp1, &b); mem_free(tmp1);}#endif /* G */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -