📄 img.c
字号:
ctype=get_content_type(goi->af->rq->ce->head, goi->af->rq->url); if (!ctype) ctype = stracpy("application/octet-stream"); type(cimg,ctype); } /* Now, if we are in state where decoder is running (8, 10, 12, 14), we may feed * some data into it. */ if (!((cimg->state^8)&9)){ if (get_file(goi->af->rq, &data, &dataend)) goto end; length = dataend - data; if (length<=cimg->last_length) goto end; /* No new data */ data+=cimg->last_length; length-=cimg->last_length; if (length>RESTART_SIZE){ length=RESTART_SIZE; chopped=1; if (fdatac) { refresh_image(fdatac,(struct g_object *)goi,1); } } /* Decoder has been already started */ switch(cimg->image_type){ case IM_PNG: png_restart(cimg,data,length); break;#ifdef HAVE_JPEG case IM_JPG: jpeg_restart(cimg,data,length); break;#endif /* #ifdef HAVE_JPEG */ case IM_XBM: xbm_restart(cimg,data,length); break; case IM_GIF: gif_restart(data,length); break;#ifdef HAVE_TIFF case IM_TIFF: tiff_restart(cimg,data,length); break;#endif /* #ifdef HAVE_TIFF */#ifdef DEBUG default: fprintf(stderr,"cimg->image_type=%d\n",cimg->state); internal("Invalid image_type encountered when processing data in\img_process_download.\n");#endif /* #ifdef DEBUG */ } cimg->last_length+=length; } end: /* Test end */ if (!is_entry_used(goi->af->rq->ce) && (goi->af->rq->state < 0 ||(goi->af->rq->ce&&goi->af->rq->stat.state<0))){ /* We must not perform end with chopped because some * unprocessed data still wait for us :) */ if (!chopped){#ifdef HAVE_TIFF if (!((cimg->state^8)&9)&&cimg->image_type==IM_TIFF) tiff_finish(cimg);#endif cimg->eof_hit=1; if (goi->af->rq->ce) cimg->last_count=goi->af->rq->ce->count; img_end(cimg); } } else if (!chopped) { if (fdatac && f_is_finished(fdatac->f_data)) { refresh_image(fdatac,(struct g_object *)goi,2000); } } return chopped;}/* Input: rgb (sRGB) triplet (0...255) * Returns a color that is very contrasty on that background sRGB color */int get_foreground(int rgb){ int r,g,b; r=(rgb>>16)&255; g=(rgb>>8)&255; b=rgb&255; r=r<128?255:0; g=g<128?255:0; b=b<128?255:0; return (r<<16)|(g<<8)|b;}void draw_frame_mark (struct graphics_driver *drv, struct graphics_device *dev, int x, int y, int xw, int yw , long bg, long fg, int broken){#ifdef DEBUG if (xw<1||yw<1) internal("zero dimension in draw_frame_mark");#endif /* #ifdef DEBUG */ if (broken == 1){ /* Draw between ( 0 and 1/4 ) and ( 3/4 and 1 ) of each * side (0-1) */ int xl, xh, yl, yh; xh=xw-(xl=xw>>2); yh=yw-(yl=yw>>2); /* Draw full sides and the box inside */ drv->draw_hline(dev,x,y,x+xl,fg); drv->draw_hline(dev,x+xl,y,x+xh,bg); drv->draw_hline(dev,x+xh,y,x+xw,fg); if (yw>=1){ if (yw>=2){ drv->draw_vline(dev,x,y+1,y+yl,fg); drv->draw_vline(dev,x,y+yl,y+yh,bg); drv->draw_vline(dev,x,y+yh,y+yw-1,fg); if (xw>=1){ if (xw>=2){ drv->fill_area(dev, x+1,y+1,x+xw-1,y+yw-1, bg); } drv->draw_vline(dev,x+xw-1,y+1,y+yl,fg); drv->draw_vline(dev,x+xw-1,y+yl,y+yh,bg); drv->draw_vline(dev,x+xw-1,y+yh,y+yw-1,fg); } } drv->draw_hline(dev,x,y+yw-1,x+xl,fg); drv->draw_hline(dev,x+xl,y+yw-1,x+xh,bg); drv->draw_hline(dev,x+xh,y+yw-1,x+xw,fg); } }else { /* Draw full sides and the box inside */ drv->draw_hline(dev,x,y,x+xw,fg); if (yw>=1){ if (yw>=2){ drv->draw_vline(dev,x,y+1,y+yw-1,fg); if (xw>=1){ if (xw>=2){ if (broken < 2) drv->fill_area(dev, x+1,y+1,x+xw-1,y+yw-1, bg); } drv->draw_vline(dev,x+xw-1,y+1, y+yw-1,fg); } } drv->draw_hline(dev,x,y+yw-1,x+xw,fg); } if (broken == 2 && xw > 2 && yw > 2) { draw_frame_mark(drv, dev, x + 1, y + 1, xw - 2, yw - 2, bg, fg, 3); } }}/* Entry is allowed only in states 12, 13, 14, 15 * Draws the picture from bitmap. * Before doing so, ensures that bitmap is present and if not, converts it from * the buffer. */static void draw_picture(struct f_data_c *fdatac, struct g_object_image *goi, int x, int y, int bg){ struct graphics_device *dev=fdatac->ses->term->dev; struct cached_image *cimg=goi->cimg; struct rect saved;#ifdef DEBUG if (goi->cimg->state<12||goi->cimg->state>=16){ fprintf(stderr,"cimg->state=%d\n",cimg->state); internal("Invalid cimg->state in draw_picture"); }#endif /* #ifdef DEBUG */ if (!(cimg->state&1)){ if (!cimg->bmp.user) buffer_to_bitmap(cimg); }#ifdef DEBUG else if (!cimg->bmp.user){ fprintf(stderr,"cimg->state=%d\n",cimg->state); internal("Nonexistent bitmap in said cimg->state in draw_picture"); }#endif /* #ifdef DEBUG */ restrict_clip_area(dev, &saved, x, y, x+goi->xw, y+goi->yw); drv->draw_bitmap(dev,&cimg->bmp,x,y); drv->fill_area(dev, x+cimg->bmp.x, y, x+goi->xw,y+cimg->bmp.y, bg); drv->fill_area(dev, x,y+cimg->bmp.y,x+goi->xw, y+goi->yw,bg); drv->set_clip_area(dev,&saved);}/* Ensures in buffer there is not newer picture than in bitmap. Allowed to be * called only in state 12, 13, 14, 15. */void update_bitmap(struct cached_image *cimg){#ifdef DEBUG if (cimg->state<12||cimg->state>=16){ fprintf(stderr,"cimg->state=%d\n",cimg->state); internal("Invalid state in update_bitmap"); }#endif /* #ifdef DEBUG */ if (!(cimg->state&1)&& !cimg->strip_optimized &&cimg->rows_added) buffer_to_bitmap(cimg);}/* Draws the image at x,y. Is called from other C sources. */void img_draw_image (struct f_data_c *fdatac, struct g_object_image *goi, int x, int y){ long color_bg, color_fg; struct cached_image *cimg = goi->cimg; struct rect r; /* refresh_image(fdatac, goi, 1000); To sem asi napsal mikulas jako * navod, jak se vola to refresh_image. Nicmene ja jsem milostive * usoudil, ze zadnejch 1000, ale 0. */ if (cimg) { color_bg=dip_get_color_sRGB(cimg->background_color); color_fg=dip_get_color_sRGB(get_foreground(cimg->background_color)); } else { color_bg = dip_get_color_sRGB(0x00c0c0c0); color_fg = dip_get_color_sRGB(0x00000000); } if (!(goi->xw&&goi->yw)) return; /* At least one dimension is zero */ memcpy(&r, &fdatac->ses->term->dev->clip, sizeof(struct rect)); if (fdatac->vs->g_display_link && fdatac->active && fdatac->vs->current_link != -1 && fdatac->vs->current_link == goi->link_num) { draw_frame_mark(drv, fdatac->ses->term->dev,x,y,goi->xw, goi->yw,color_bg,color_fg,2); restrict_clip_area(fdatac->ses->term->dev, &r, x + 2, y + 2, x + goi->xw - 2, y + goi->yw - 2); } global_goi=goi; global_cimg=goi->cimg; if (img_process_download(goi, fdatac)) goto ret; /* Choked with data, will not * draw. */ /* Now we will only draw... */ if (cimg->state<12){ draw_frame_mark(drv, fdatac->ses->term->dev,x,y,goi->xw, goi->yw,color_bg,color_fg,cimg->state&1); }else#ifdef DEBUG if (cimg->state<16){#else {#endif /* #ifdef DEBUG */ update_bitmap(cimg); draw_picture(fdatac,goi,x,y,color_bg); }#ifdef DEBUG else{ fprintf(stderr,"cimg->state\%d\n",cimg->state); internal("Invalid state in img_draw_image"); }#endif /* #ifdef DEBUG */ ret:; drv->set_clip_area(fdatac->ses->term->dev, &r);}/* Prior to calling this function you have to fill out * image -> xw (<0 means not known) * image -> yw (<0 means not known) * image -> xyw meaning (MEANING_AUTOSCALE or MEANING_DIMS) * image -> background * * The URL will not be freed. */void find_or_make_cached_image(struct g_object_image *image, unsigned char *url, int scale){ struct cached_image *cimg; if (!(cimg = find_cached_image(image->background, url, image->xw, image->yw, image->xyw_meaning,scale, aspect))){ /* We have to make a new image cache entry */ cimg = mem_alloc(sizeof(*cimg)); cimg->refcount = 1; cimg->background_color=image->background;#ifdef DEBUG if (!url) internal ("NULL url as argument of\find_or_make_cached_image");#endif /* #ifdef DEBUG */ cimg->scale = scale; cimg->aspect = aspect; cimg->url = stracpy(url); cimg->wanted_xw = image->xw; cimg->wanted_yw = image->yw; cimg->wanted_xyw_meaning=image->xyw_meaning; cimg->xww = image->xw<0?img_scale_h(cimg->scale, 32):cimg->wanted_xw; cimg->yww = image->yw<0?img_scale_v(cimg->scale, 32):cimg->wanted_yw; cimg->state=0; /* width, height, image_type, buffer, buffer_bytes_per_pixel, red_gamma, * green_gamma, blue_gamma, gamma_stamp, bitmap, last_length, rows_added, * and decoder is invalid in both state 0 and state 2. Thus is need no to * be filled in. */ /* last_count2 is unitialized */ cimg->eof_hit=0; cimg->last_count=-1; cimg->last_count2=-1; if (cimg->wanted_xw>=0&&cimg->wanted_yw>=0) cimg->state|=2; add_image_to_cache(cimg); } global_cimg=image->cimg=cimg;}/* The original (unscaled, in pixels pace) size is requested in im->xsize and im->ysize. * <0 means unknown. Autoscale is requested in autoscale. When autoscale is on, * the requested dimensions are not scaled and they mean maximum allowed * dimensions. */struct g_object_image *insert_image(struct g_part *p, struct image_description *im){ struct g_object_image *image; struct cached_image *cimg; int retval; image=mem_calloc(sizeof(struct g_object_image)); global_goi=image; image->mouse_event=&g_text_mouse; image->draw=&img_draw_image; image->destruct=&img_destruct_image; image->get_list=NULL; image->link_num = im->link_num; image->link_order = im->link_order; image->map = NULL; /* image->x is already filled image->y is already filled */ if (im->align == AL_MIDDLE) image->y = G_OBJ_ALIGN_MIDDLE; if (im->align == AL_TOP) image->y = G_OBJ_ALIGN_TOP; if (im->autoscale_x&&im->autoscale_y) { /* Autoscale requested */ image->xw=im->autoscale_x; image->yw=im->autoscale_y; image->xyw_meaning=MEANING_AUTOSCALE; }else{ /* Autoscale not requested */ image->xw=img_scale_h(d_opt->image_scale, im->xsize); image->yw=img_scale_v(d_opt->image_scale, im->ysize); image->xyw_meaning=MEANING_DIMS; } if (image->xw >= 0 && image->yw >= 0) { if (!is_image_size_sane(image->xw, image->yw)) { mem_free(image); return NULL; } } /* Put the data for javascript inside */ image->id=(current_f_data->n_images)++; image->name=stracpy(im->name); image->alt=stracpy(im->alt); image->orig_src=stracpy(im->src); image->border=im->border; image->vspace=im->vspace; image->hspace=im->hspace; image->src=stracpy(im->url); if (!(image->xw&&image->yw)){ /* At least one is zero */ if (image->xw<0) image->xw=0; if (image->yw<0) image->yw=0; if (im->insert_flag)add_to_list(current_f_data->images,&image->image_list); else image->image_list.prev=NULL,image->image_list.next=NULL; return image; } /* image->parent is already filled */ image->af=request_additional_file(current_f_data,im->url); if (image->xw < 0 || image->yw < 0) image->af->unknown_image_size = 1; image->background=p->root->bg->u.sRGB; /* This supplies the result into image->cimg and global_cimg */ find_or_make_cached_image(image, im->url, d_opt->image_scale); cimg=global_cimg;next_chunk: retval=img_process_download(image,NULL); if (retval&&!(cimg->state&4)) goto next_chunk; image->xw=image->cimg->xww; image->yw=image->cimg->yww; if (cimg->state==0||cimg->state==8||(!image->af->rq->ce && image->af->unknown_image_size)) if (image->af->need_reparse != -1) image->af->need_reparse = 1; if (im->insert_flag)add_to_list(current_f_data->images,&image->image_list); else image->image_list.prev=NULL,image->image_list.next=NULL; return image;}#ifdef JSvoid change_image (struct g_object_image *goi, unsigned char *url, unsigned char *src, struct f_data *fdata){ /*struct cached_image *cimg;*/ global_goi=goi; mem_free(goi->src); goi->src=stracpy(url); if (goi->orig_src)mem_free(goi->orig_src); goi->orig_src=stracpy(src); if (!(goi->xw&&goi->yw)) return; goi->cimg->refcount--; goi->af=request_additional_file(fdata,url); goi->af->need_reparse = -1; find_or_make_cached_image(goi, url, fdata->opt.image_scale); /* Automatically sets up global_cimg */ refresh_image(fdata->fd,(struct g_object*)goi,1);}#endif#endifint known_image_type(char *type){#ifdef G if (!strcasecmp(type, "image/png")) return 1; if (!strcasecmp(type, "image/x-png")) return 1; if (!strcasecmp(type, "image/gif")) return 1; if (!strcasecmp(type, "image/x-xbitmap")) return 1;#ifdef HAVE_JPEG if (!strcasecmp(type, "image/jpeg")) return 1; if (!strcasecmp(type, "image/jpg")) return 1; if (!strcasecmp(type, "image/jpe")) return 1; if (!strcasecmp(type, "image/pjpe")) return 1; if (!strcasecmp(type, "image/pjpeg")) return 1; if (!strcasecmp(type, "image/pjpg")) return 1;#endif#ifdef HAVE_TIFF if (!strcasecmp(type, "image/tiff")) return 1; if (!strcasecmp(type, "image/tif")) return 1;#endif#endif return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -