📄 vgadisp.c
字号:
/* hopefully the following is fairly quick as fewer ifs... ? */ if(virtual && scaling==1) /* 320x400 or 360x480 */ { if((realline=calloc(1,scrnwide))==NULL) return; for(y=0;(y<sheight-py)&&(y<scrnhigh);y++) { for(x=0;x<xdim;x++) *(realline+(x>>1))=getvpix(px,py,x,y); vga_drawscansegment(realline,x_add,y+y_add,xdim>>1); } free(realline); } else if(scaling>1) { /* Better grab your Joo Janta 200 Super-Chromatic Peril Sensitive * Sunglasses (both pairs) for this next bit... */ int cdown=-1,i,pxx,pyy,pyym; int a1,a2,a3,a4,in_rg,in_dn,in_dr; int wp=width*pixelsize,sci=scaling*inextpix; int scaleincr=0,subpix_xpos,subpix_ypos,sxmulsiz,symulsiz,simulsiz=0; int sisize=0,sis2=0; unsigned char *ptr1,*ptr2,*ptr3,*ptr4; unsigned char *src,*dst; if((realline=calloc(pixelsize,scrnwide))==NULL) return; if(interp) { sisize=0; while(sisize<256) sisize+=scaling; scaleincr=sisize/scaling; simulsiz=scaleincr*sisize; sis2=sisize*sisize; } for(y=0,pyy=py;(y<sheight-py)&&(y<scrnhigh);y++,pyy++) { /* this is horribly slow... :-( */ if(cdown<=0 || interp) { src=theimage+pixelsize*(pyy/scaling)*width; dst=realline; if(pixelsize==1) if(virtual) for(x=0;(x<swidth-px)&&(x<scrnwide);x+=2) *dst++=*(src+(px+x)/scaling); else for(x=0;(x<swidth-px)&&(x<scrnwide);x++) *dst++=*(src+(px+x)/scaling); else if(interp==0) /* normal */ for(x=0;(x<swidth-px)&&(x<scrnwide);x++) { ptr=src+((px+x)/scaling)*pixelsize; *dst++=*ptr++; *dst++=*ptr++; *dst++=*ptr; } else { /* interpolated */ /* This has been hacked into unreadability in an attempt to get it * as fast as possible. * It's still really slow. :-( */ in_rg=inextpix*3; in_dn=inextpix*wp; in_dr=in_dn+in_rg; pyym=pyy%scaling; subpix_ypos=(pyy%scaling)*scaleincr; subpix_xpos=(px%scaling)*scaleincr; /* yes px not pxx */ ptr1=ptr3=src+(px/scaling)*3; ptr2=ptr4=ptr1+in_rg; if(pyy<sheight-sci) { ptr3=ptr1+in_dn; ptr4=ptr1+in_dr; } symulsiz=sisize*subpix_ypos; sxmulsiz=sisize*subpix_xpos; for(x=0,pxx=px;x<swidth-px && x<scrnwide;x++,pxx++) { a3=symulsiz-(a4=subpix_xpos*subpix_ypos); a2=sxmulsiz-a4; a1=sis2-sxmulsiz-symulsiz+a4; for(i=0;i<3;i++) *dst++=(ptr1[i]*a1+ptr2[i]*a2+ ptr3[i]*a3+ptr4[i]*a4)/sis2; subpix_xpos+=scaleincr; sxmulsiz+=simulsiz; if(subpix_xpos>=sisize) { subpix_xpos=sxmulsiz=0; ptr1+=3; ptr2+=3; ptr3+=3; ptr4+=3; } if(pxx>=swidth-sci) { ptr2-=3; ptr4-=3; } } } cdown=(cdown==-1)?(scaling-(py%scaling)):scaling; } cdown--; if(scrnpixelsize==3 && !doing_hicol_bc) gl_putbox(x_add,y+y_add,linelen,1,realline); else if(virtual) vga_drawscansegment(realline,x_add,y+y_add,linelen>>1); else eventuallydrawscansegment(realline,x_add,y+y_add,linelen*pixelsize); } free(realline); } else /* if not scaled and not zoomed... */ { switch(scrnpixelsize) { case 3: if(!doing_hicol_bc) { gl_putboxpart(x_add,y_add,(scrnwide<width)?scrnwide:width, (scrnhigh<height)?scrnhigh:height,width,height,theimage,px,py); break; } /* otherwise, FALLS THROUGH */ default: /* for 320x200 (I think), 320x240, 320x400, 360x480 we need the * length to be a multiple of 8. :-( We allocate an image-width * line (blanked), and display via that. * (320x400/360x480 were dealt with earlier though; can only * be 320x200/320x240 if it gets here.) * * This isn't needed for svgalib >=1.3.1, but I'm leaving it in * for `if it ain't broke don't fix it' reasons. :-) */ if(curvgamode==G320x200x256 || curvgamode==G320x240x256) { static unsigned char hack[320]; memset(hack,0,320); for(y=0;(y<height-py)&&(y<scrnhigh);y++) { /* assume pixelsize==1, because it must be */ memcpy(hack+x_add,theimage+((py+y)*width+px),xdim); vga_drawscansegment(hack,0,y+y_add,scrnwide); } } else for(y=0;(y<height-py)&&(y<scrnhigh);y++) eventuallydrawscansegment(theimage+pixelsize*((py+y)*width+px), x_add,y+y_add,xdim*pixelsize); break; } } }}#define MODE_WIDTH_BUF_SIZE 16384/* this variant should never be called with scrnpixelsize==3. */void eventuallydrawscansegment_without_bc(byte *ptr,int x,int y,int len){static unsigned short buf[MODE_WIDTH_BUF_SIZE];switch(scrnpixelsize) { case 4: /* 32-bit */ { unsigned long *bufref=(unsigned long *)buf; unsigned char *ptrend=ptr+len; int i=0; for(;ptr<ptrend;ptr+=3,i++) *bufref++=GET32BITCOLOUR(ptr[2],ptr[1],*ptr); gl_putbox(x,y,i,1,buf); } break; case 2: /* 15/16-bit */ { unsigned short *bufref=buf; unsigned char *ptrend=ptr+len; if(scrncols==32768) for(;ptr<ptrend;ptr+=3) *bufref++=GET15BITCOLOUR(ptr[2],ptr[1],*ptr); else for(;ptr<ptrend;ptr+=3) *bufref++=GET16BITCOLOUR(ptr[2],ptr[1],*ptr); gl_putbox(x,y,bufref-buf,1,buf); } break; default: /* 8-bit */ if(curvgamode==G640x480x16) dither16scansegment(ptr,x,y,len); else vga_drawscansegment(ptr,x,y,len); }}void eventuallydrawscansegment_with_bc(byte *ptr,int x,int y,int len){static unsigned short buf[MODE_WIDTH_BUF_SIZE];unsigned char *ptrend=ptr+len;/* if we get here, scrnpixelsize must be 2, 3, or 4. */switch(scrnpixelsize) { case 4: /* 32-bit */ { unsigned long *bufref=(unsigned long *)buf; unsigned char *ptrend=ptr+len; int i=0; for(;ptr<ptrend;ptr+=3,i++) *bufref++=GET32BITCOLOUR(palt[ptr[2]],palt[ptr[1]],palt[*ptr]); gl_putbox(x,y,i,1,buf); } break; case 3: /* 24-bit */ { unsigned char *bufref=(unsigned char *)buf; /* no kludges here, senor */ while(ptr<ptrend) *bufref++=palt[*ptr++]; gl_putbox(x,y,(bufref-(unsigned char *)buf)/3,1,buf); break; } case 2: /* 15/16-bit */ { unsigned short *bufref=buf; if(scrncols==32768) for(;ptr<ptrend;ptr+=3) *bufref++=GET15BITCOLOUR(palt[ptr[2]],palt[ptr[1]],palt[*ptr]); else for(;ptr<ptrend;ptr+=3) *bufref++=GET16BITCOLOUR(palt[ptr[2]],palt[ptr[1]],palt[*ptr]); gl_putbox(x,y,bufref-buf,1,buf); break; } default: fprintf(stderr,"not high-colour in ..._with_bc, can't happen!\n"); exit(1); }}/* only called for 640x480x4-bit */void dither16scansegment(unsigned char *ptr,int x,int y,int len){static unsigned char scanline[640];unsigned char *lptr=scanline;int f;if(!cfg.viewer16col) { /* greyscale, but dithered between the scales; * dithering slows it down more than a direct mapping would, * but it just looks too nasty without it. */ static unsigned char ditherdata[4]= { 1,4, 3,2 }; unsigned char c,*dithptr=ditherdata+(y&1)*2+(x&1); int xm=2-(x&1); for(f=0;f<len;f++) { if((c=dither16_greylookup[ptr[f]])>=60) c=60; /* saves needing a range check after :-) */ *lptr++=((c>>2)+((c&3)>=*dithptr++)); if(!(--xm)) dithptr-=(xm=2); } }else { /* colour */ if(cfg.fastdither16col) { /* ordered dither */ static unsigned char ditherdata[48]= { /* red */ 1*4-2,13*4-2, 4*4-2,16*4-2, 9*4-2, 5*4-2,12*4-2, 8*4-2, 3*4-2,15*4-2, 2*4-2,14*4-2, 7*4-2,10*4-2, 6*4-2,11*4-2, /* green - mirrored */ 16*4-2, 4*4-2,13*4-2, 1*4-2, 8*4-2,12*4-2, 5*4-2, 9*4-2, 14*4-2, 2*4-2,15*4-2, 3*4-2, 11*4-2, 6*4-2,10*4-2, 7*4-2, /* blue - flipped */ 7*4-2,10*4-2, 6*4-2,11*4-2, 3*4-2,15*4-2, 2*4-2,14*4-2, 9*4-2, 5*4-2,12*4-2, 8*4-2, 1*4-2,13*4-2, 4*4-2,16*4-2 }; unsigned char *dithptr=ditherdata+(y&3)*4+(x&3); unsigned char *palptr; int xm=4-(x&3); for(f=0;f<len;f++) { palptr=dither16_rgb+ptr[f]*3; *lptr++=(((*palptr>=*dithptr)*4)| ((palptr[1]>=dithptr[16])*2)| (palptr[2]>=dithptr[32])); dithptr++; if(!(--xm)) dithptr-=(xm=4); } } else { /* error-diffused dither, based on the one in readpnm.c */ static int evenerr[(640+10)*3],odderr[(640+10)*3]; /* 640x480-only */ static int oldline=(1<<30); unsigned char *theline=ptr; int width=len; int xx,lx; int c0,c1,c2,times2; int terr0,terr1,terr2,actual0,actual1,actual2; int start,addon,r,g,b,c; int *thiserr; int *nexterr; /* we assume going backwards = new set of lines being drawn */ if(y<oldline) { memset(evenerr,0,sizeof(evenerr)); memset(odderr,0,sizeof(odderr)); } oldline=y; if((y&1)==0) {start=0; addon=1; thiserr=evenerr+3; nexterr=odderr+width*3;} else {start=width-1; addon=-1; thiserr=odderr+3; nexterr=evenerr+width*3;} nexterr[0]=nexterr[1]=nexterr[2]=0; xx=start; for(lx=0;lx<width;lx++) { c=theline[xx]; b=palb[c]; g=palg[c]; r=palr[c]; terr0=r+((thiserr[0]+8)>>4); terr1=g+((thiserr[1]+8)>>4); terr2=b+((thiserr[2]+8)>>4); actual0=(terr0>=128)?255:0; actual1=(terr1>=128)?255:0; actual2=(terr2>=128)?255:0; c=(((actual0&1)<<2)|((actual1&1)<<1)|(actual2&1)); c0=terr0-actual0; c1=terr1-actual1; c2=terr2-actual2; times2=(c0<<1); nexterr[-3] =c0; c0+=times2; nexterr[ 3]+=c0; c0+=times2; nexterr[ 0]+=c0; c0+=times2; thiserr[ 3]+=c0; times2=(c1<<1); nexterr[-2] =c1; c1+=times2; nexterr[ 4]+=c1; c1+=times2; nexterr[ 1]+=c1; c1+=times2; thiserr[ 4]+=c1; times2=(c2<<1); nexterr[-1] =c2; c2+=times2; nexterr[ 5]+=c2; c2+=times2; nexterr[ 2]+=c2; c2+=times2; thiserr[ 5]+=c2; scanline[xx]=c; thiserr+=3; nexterr-=3; xx+=addon; } } }vga_drawscansegment(scanline,x,y,len);}int getvpix(int px,int py,int x,int y){int p1,p2;if((vkludge)&&(pixelsize==1)) { p1=*(theimage+(py+y)*width+px+x); if(px+x+1>=width) return(p1); p1*=3; p2=*(theimage+(py+y)*width+px+x+1)*3; return(closest((pal32_no_bc[p1 ]+pal32_no_bc[p2 ])>>1, (pal32_no_bc[p1+1]+pal32_no_bc[p2+1])>>1, (pal32_no_bc[p1+2]+pal32_no_bc[p2+2])>>1)); }else return(*(theimage+pixelsize*((py+y)*width+px+x)));}/* this routine is nasty writ big, but about as quick as I can manage */void drawzoomedgif(){int a,b,x,yp,yw;long y,sw,sh,lastyp;int xoff,yoff;int x_add,y_add; /* for centering */int pixwide,pixhigh;int bigimage;byte *rline,*sptr,*dptr;int tmp1,tmp2,tr,tg,tb,tn;if((rline=calloc(scrnwide*pixelsize,1))==NULL) return;/* try landscapey */sw=scrnwide; sh=(scrnwide*height)/width;if(sh>scrnhigh) /* no, oh well portraity then */ sh=scrnhigh,sw=(scrnhigh*width)/height;/* so now our zoomed image will be sw x sh *//* fix centering if needed */x_add=y_add=0;if(cfg.centreflag) { if(sw<scrnwide) x_add=((scrnwide-sw)>>1); if(sh<scrnhigh) y_add=((scrnhigh-sh)>>1); if(virtual) x_add>>=1; }bigimage=(width>sw)?1:0; /* 1 if image has been reduced, 0 if made bigger */if(bigimage) /* it's been reduced - easy, just make 'em fit in less space */ { if(virtual) sw>>=1; lastyp=-1; if(!override_zoom_clear) /* for animate_gif() */ vga_clear(); pixhigh=(int)(((float)height)/((float)sh)+0.5); pixwide=(int)(((float)width)/((float)sw)+0.5); pixhigh++; pixwide++; for(y=0;y<height;y+
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -