static void d2alaw_array (double *ptr, unsigned int index, unsigned char *buffer, unsigned int count, double normfact) { unsigned int k ; for (k = 0 ; k < count ; k++) { if (ptr [index] >= 0) buffer [k] = alaw_encode [(DOUBLE_TO_INT (normfact * ptr [index])) / 16] ; else buffer [k] = 0x7F & alaw_encode [(DOUBLE_TO_INT (normfact * ptr [index])) / -16] ; index ++ ; } ; } /* d2alaw_array */
static void image_ttf_faceinstance_set_height(INT32 args) { struct image_ttf_face_struct *face_s; struct image_ttf_faceinstance_struct *face_i=THISi; int h=0; if (!args) Pike_error("Image.TTF.FaceInstance->set_height(): missing arguments\n"); if (sp[-args].type==T_INT) h = sp[-args].u.integer*64; else if (sp[-args].type==T_FLOAT) h = DOUBLE_TO_INT(sp[-args].u.float_number*64); else Pike_error("Image.TTF.FaceInstance->set_height(): illegal argument 1\n"); if (h<1) h=1; if (!(face_s=(struct image_ttf_face_struct*) get_storage(THISi->faceobj,image_ttf_face_program))) Pike_error("Image.TTF.FaceInstance->write(): lost Face\n"); ttf_instance_setc(face_s,face_i,h,"Image.TTF.FaceInstance->set_height()"); pop_n_elems(args); ref_push_object(THISOBJ); }
static void ttf_instance_setc(struct image_ttf_face_struct *face_s, struct image_ttf_faceinstance_struct *face_i, int towhat, char *where) { TT_Face_Properties prop; TT_Instance_Metrics metr; int res; int resol; if ((res=TT_Get_Face_Properties(face_s->face,&prop))) my_tt_error(where,"TT_Get_Face_Properties",res); resol=58; /* should be 72, but glyphs fit using this value */ /* (int)((72*(prop.horizontal->Ascender+ prop.horizontal->Descender)/ (float)prop.horizontal->Ascender)); */ if ((res=TT_Set_Instance_Resolutions(face_i->instance, (TT_UShort)resol, (TT_UShort)resol))) my_tt_error("Image.TTF.FaceInstance()", "TT_Set_Instance_Resolutions: ",res); if ((res=TT_Get_Instance_Metrics(face_i->instance,&metr))) my_tt_error(where,"TT_Get_Instance_Metrics",res); if ((res=TT_Set_Instance_CharSize(face_i->instance,towhat))) my_tt_error(where,"TT_Set_Instance_CharSize: ",res); face_i->baseline= DOUBLE_TO_INT(((double)(towhat/64.0+towhat/640.0)* prop.horizontal->Ascender)/ (prop.horizontal->Ascender - prop.horizontal->Descender)); face_i->height= (towhat/64 + towhat/640); face_i->trans = ~63 & (32 + DOUBLE_TO_INT(64*((towhat/64.0+towhat/640.0)* prop.horizontal->Ascender)/ (prop.horizontal->Ascender-prop.horizontal->Descender))); }
static INLINE void polyfill_slant_add(double *buf, double xmin, double xmax, double lot, double y1, double dy) { int i; int xmin_i = DOUBLE_TO_INT(floor(xmin)); int xmax_i = DOUBLE_TO_INT(floor(xmax)); if (xmax_i<0) return; if (xmin_i == xmax_i) { double dx = xmax - xmin; buf[xmin_i] += lot*(y1+dy*dx/2)*dx; } else if (xmin_i>=0) { double dx = DO_NOT_WARN(1.0 - (xmin-((double)xmin_i))); buf[xmin_i] += lot*(y1+dy*dx/2.0)*dx; y1 += dy*dx; for (i=xmin_i+1; i<xmax_i; i++) { buf[i] += lot*(y1+dy/2.0); y1 += dy; } dx = (xmax-((double)xmax_i)); buf[xmax_i] += lot*(y1+dy*dx/2.0)*dx; } else { double dx; y1 -= dy*xmin; /* Adjust y1 for the first -xmin steps. */ for (i=0; i<xmax_i; i++) { buf[i] += lot*(y1+dy/2.0); y1 += dy; } dx = (xmax-((double)xmax_i)); buf[xmax_i] += lot*(y1+dy*dx/2)*dx; } }
static INLINE void polyfill_row_add(double *buf, double xmin, double xmax, double add) { int i; int xmin_i = DOUBLE_TO_INT(floor(xmin)); int xmax_i = DOUBLE_TO_INT(floor(xmax)); if (xmax_i<0) return; if (xmin_i == xmax_i) buf[xmin_i] += (xmax-xmin)*add; else if (xmin_i>=0) { buf[xmin_i] += (1-(xmin-((double)xmin_i)))*add; for (i=xmin_i+1; i<xmax_i; i++) buf[i]+=add; buf[xmax_i] += add*(xmax-((double)xmax_i)); } else { for (i=0; i<xmax_i; i++) buf[i]+=add; buf[xmax_i] += add*(xmax-((float)xmax_i)); } }
void image_dct(INT32 args) { rgbd_group *area,*val; struct object *o; struct image *img; INT32 x,y,u,v; double xsz2,ysz2,enh,xp,yp,dx,dy; double *costbl; rgb_group *pix; if (!THIS->img) Pike_error("Called Image.Image object is not initialized\n"); #ifdef DCT_DEBUG fprintf(stderr,"%lu bytes, %lu bytes\n", DO_NOT_WARN((unsigned long)(sizeof(rgbd_group)*THIS->xsize*THIS->ysize)), DO_NOT_WARN((unsigned long)(sizeof(rgb_group)*THIS->xsize*THIS->ysize+1))); #endif area=xalloc(sizeof(rgbd_group)*THIS->xsize*THIS->ysize+1); if (!(costbl=malloc(sizeof(double)*THIS->xsize+1))) { free(area); resource_error(NULL,0,0,"memory",0,"Out of memory.\n"); } o=clone_object(image_program,0); img=(struct image*)(o->storage); *img=*THIS; if (args>=2 && sp[-args].type==T_INT && sp[1-args].type==T_INT) { img->xsize=MAXIMUM(1,sp[-args].u.integer); img->ysize=MAXIMUM(1,sp[1-args].u.integer); } else { free(area); free(costbl); free_object(o); bad_arg_error("image->dct",sp-args,args,0,"",sp-args, "Bad arguments to image->dct()\n"); } if (!(img->img=(rgb_group*)malloc(sizeof(rgb_group)* img->xsize*img->ysize+1))) { free(area); free(costbl); free_object(o); resource_error(NULL,0,0,"memory",0,"Out of memory.\n"); } xsz2=THIS->xsize*2.0; ysz2=THIS->ysize*2.0; enh=(8.0/THIS->xsize)*(8.0/THIS->ysize); for (u=0; u<THIS->xsize; u++) { double d,z0; rgbd_group sum; for (v=0; v<THIS->ysize; v++) { d=(u?1:c0)*(v?1:c0)/4.0; sum.r=sum.g=sum.b=0; pix=THIS->img; for (x=0; x<THIS->xsize; x++) costbl[x]=cos( (2*x+1)*u*pi/xsz2 ); for (y=0; y<THIS->ysize; y++) { z0=cos( (2*y+1)*v*pi/ysz2 ); for (x=0; x<THIS->xsize; x++) { double z; z = costbl[x] * z0; sum.r += (float)(pix->r*z); sum.g += (float)(pix->g*z); sum.b += (float)(pix->b*z); pix++; } } sum.r *= (float)d; sum.g *= (float)d; sum.b *= (float)d; area[u+v*THIS->xsize]=sum; } #ifdef DCT_DEBUG fprintf(stderr,"."); fflush(stderr); #endif } #ifdef DCT_DEBUG fprintf(stderr,"\n"); #endif dx=((double)(THIS->xsize-1))/(img->xsize); dy=((double)(THIS->ysize-1))/(img->ysize); pix=img->img; for (y=0,yp=0; y<img->ysize; y++,yp+=dy) { double z0; rgbd_group sum; for (x=0,xp=0; x<img->xsize; x++,xp+=dx) { sum.r=sum.g=sum.b=0; val=area; for (u=0; u<THIS->xsize; u++) costbl[u]=cos( (2*xp+1)*u*pi/xsz2 ); for (v=0; v<THIS->ysize; v++) { z0=cos( (2*yp+1)*v*pi/ysz2 )*(v?1:c0)/4.0; for (u=0; u<THIS->xsize; u++) { double z; z = (u?1:c0) * costbl[u] * z0; sum.r += DO_NOT_WARN((float)(val->r*z)); sum.g += DO_NOT_WARN((float)(val->g*z)); sum.b += DO_NOT_WARN((float)(val->b*z)); val++; } } sum.r *= (float)enh; sum.g *= (float)enh; sum.b *= (float)enh; pix->r=testrange((DOUBLE_TO_INT(sum.r+0.5))); pix->g=testrange((DOUBLE_TO_INT(sum.g+0.5))); pix->b=testrange((DOUBLE_TO_INT(sum.b+0.5))); pix++; } #ifdef DCT_DEBUG fprintf(stderr,"."); fflush(stderr); #endif } free(area); free(costbl); pop_n_elems(args); push_object(o); }
static void image_ttf_faceinstance_write(INT32 args) { int **sstr; int *slen; int i,res=0,base=0,a; struct image_ttf_face_struct *face_s; struct image_ttf_faceinstance_struct *face_i=THISi; TT_CharMap charMap; TT_Kerning kerning; int has_kerning = 0; char *errs=NULL; int scalefactor=0; int xmin=1000,xmax=-1000,pos=0,ypos; int width,height,mod; unsigned char* pixmap; int maxcharwidth = 0; if (!(face_s=(struct image_ttf_face_struct*) get_storage(THISi->faceobj,image_ttf_face_program))) Pike_error("Image.TTF.FaceInstance->write(): lost Face\n"); if(!TT_Get_Kerning_Directory( face_s->face, &kerning )) { TT_Instance_Metrics metrics; /* fprintf(stderr, "has kerning!\n"); */ has_kerning = 1; if(TT_Get_Instance_Metrics( face_i->instance, &metrics )) Pike_error("Nope. No way.\n"); scalefactor = metrics.x_scale; /* fprintf(stderr, "offset=%d\n", (int)metrics.x_scale); */ } if (args && sp[-1].type==T_INT) { base=sp[-1].u.integer; args--; pop_stack(); } if (!args) { push_empty_string(); args=1; } ttf_get_nice_charmap(face_s->face,&charMap, "Image.TTF.FaceInstance->write()"); sstr=alloca(args*sizeof(int*)); slen=alloca(args*sizeof(int)); /* first pass: figure out total bounding box */ for (a=0; a<args; a++) { char *errs=NULL; TT_Glyph_Metrics metrics; if (sp[a-args].type!=T_STRING) Pike_error("Image.TTF.FaceInstance->write(): illegal argument %d\n",a+1); switch(sp[a-args].u.string->size_shift) { case 0: ttf_translate_8bit(charMap,(unsigned char*)sp[a-args].u.string->str, sstr+a, DO_NOT_WARN(slen[a]=sp[a-args].u.string->len), base); break; case 1: ttf_translate_16bit(charMap,(unsigned short*)sp[a-args].u.string->str, sstr+a, DO_NOT_WARN(slen[a]=sp[a-args].u.string->len), base); break; case 2: Pike_error("Too wide string for truetype\n"); break; } pos=0; for (i=0; i<slen[a]; i++) { TT_Glyph glyph; int ind; ind=sstr[a][i]; /* fprintf(stderr,"glyph: %d\n",ind); */ if ((res=TT_New_Glyph(face_s->face,&glyph))) { errs="TT_New_Glyph: "; break; } if ((res=TT_Load_Glyph(face_i->instance, glyph, (TT_UShort)ind, (TT_UShort)face_i->load_flags))) { errs="TT_Load_Glyph: "; break; } if ((res=TT_Get_Glyph_Metrics(glyph,&metrics))) { errs="TT_Get_Glyph_Metrics: "; break; } if (pos+metrics.bbox.xMin<xmin) xmin=pos+metrics.bbox.xMin; if (pos+metrics.bbox.xMax>xmax) xmax=pos+metrics.bbox.xMax; if((metrics.bbox.xMax-(metrics.bbox.xMin<0?metrics.bbox.xMin:0)) >maxcharwidth) maxcharwidth = (metrics.bbox.xMax-(metrics.bbox.xMin<0?metrics.bbox.xMin:0)); pos+=metrics.advance; if(has_kerning && i<slen[a]-1) { int kern = find_kerning( kerning, ind, sstr[a][i+1] ); pos += DOUBLE_TO_INT(kern * (scalefactor/65535.0)); } if ((res=TT_Done_Glyph(glyph))) { errs="TT_Done_Glyph: "; break; } } pos -= metrics.advance; pos += metrics.bbox.xMax-metrics.bbox.xMin; if (pos>xmax) xmax=pos; if (errs) { for (i=0; i<a; i++) free(sstr[i]); my_tt_error("Image.TTF.FaceInstance->write()",errs,res); } } pop_n_elems(args); /* fprintf(stderr,"xmin=%f xmax=%f\n",xmin/64.0,xmax/64.0); */ xmin&=~63; width=((xmax-xmin+63)>>6)+4; height=face_i->height*args; mod=(4-(maxcharwidth&3))&3; if (width<1) width=1; if ((pixmap=malloc((maxcharwidth+mod)*face_i->height))) { /* second pass: write the stuff */ TT_Raster_Map rastermap; struct object *o; struct image *img; rgb_group *d; rastermap.rows=face_i->height; rastermap.cols=rastermap.width=maxcharwidth+mod; rastermap.flow=TT_Flow_Down; rastermap.bitmap=pixmap; rastermap.size=rastermap.cols*rastermap.rows; ypos=0; /* fprintf(stderr,"rastermap.rows=%d cols=%d width=%d\n", */ /* rastermap.rows,rastermap.cols,rastermap.width); */ push_int(width); push_int(height); o=clone_object(image_program,2); img=(struct image*)get_storage(o,image_program); d=img->img; for (a=0; a<args; a++) { pos=-xmin; for (i=0; i<slen[a]; i++) { int sw, xp; TT_Glyph glyph; TT_Glyph_Metrics metrics; int ind, x, y; ind=sstr[a][i]; /* fprintf(stderr,"glyph: %d\n",ind); */ if ((res=TT_New_Glyph(face_s->face,&glyph))) { errs="TT_New_Glyph: "; break; } if ((res=TT_Load_Glyph(face_i->instance, glyph, (TT_UShort)ind, (TT_UShort)face_i->load_flags))) { errs="TT_Load_Glyph: "; break; } if ((res=TT_Get_Glyph_Metrics(glyph,&metrics))) { errs="TT_Get_Glyph_Metrics: "; break; } MEMSET(pixmap,0,rastermap.size); if ((res=TT_Get_Glyph_Pixmap(glyph, &rastermap, -metrics.bbox.xMin /*+pos%64*/, face_i->height*64- face_i->trans))) { errs="TT_Get_Glyph_Pixmap: "; break; } sw = metrics.bbox.xMax-(metrics.bbox.xMin<0?metrics.bbox.xMin:0); /* Copy source pixmap to destination image object. */ for(y=0; y<face_i->height; y++) { unsigned int s; unsigned char * source = pixmap+rastermap.width*y; rgb_group *dt=d+(ypos+y)*width+(xp=(metrics.bbox.xMin+pos)/64); for(x=0; x<sw && xp<width; x++,xp++,source++,dt++) if(xp<0 || !(s = *source)) continue; else if((s=dt->r+s) < 256) dt->r=dt->g=dt->b=s; else dt->r=dt->g=dt->b=255; } pos+=metrics.advance; /* if(metrics.bbox.xMin < 0) */ /* pos += metrics.bbox.xMin; */ if(has_kerning && i<slen[a]-1) { int kern = find_kerning( kerning, sstr[a][i], sstr[a][i+1] ); pos += DOUBLE_TO_INT(kern * (scalefactor/65535.0)); /* fprintf(stderr, "Adjusted is %d\n", */ /* (int)(kern * (scalefactor/65535.0))); */ } if ((res=TT_Done_Glyph(glyph))) { errs="TT_Done_Glyph: "; break; } } if (errs) { for (a=0; a<args; a++) free(sstr[a]); free(pixmap); free_object(o); my_tt_error("Image.TTF.FaceInstance->write()",errs,res); } ypos+=face_i->height; } free(pixmap); push_object(o); } else { Pike_error("Image.TTF.FaceInstance->write(): out of memory\n"); } for (a=0; a<args; a++) free(sstr[a]); }
static void polyfill_some(struct image *img, struct vertex *v, double *buf) { struct line_list *ll=NULL; int y=0; double ixmax = (double)img->xsize; struct vertex *to_add=v,*to_loose=v; /* beat row for row */ if (y+1.0+1e-10<v->y) y = DOUBLE_TO_INT(v->y); while (y<img->ysize && (to_loose||to_add) ) { double yp = y; struct line_list *c; double xmin, xmax; rgb_group *d; int tog=0; int i; #ifdef POLYDEBUG fprintf(stderr,"\nline %d..%d\n",y,y+1); #endif /* update values for current lines */ c=ll; while (c) { c->xmin=line_xmin(c,yp,&c->yxmin); c->xmax=line_xmax(c,yp,&c->yxmax); c=c->next; } /* add any new vertices */ while (to_add && to_add->y<yp+1.0) { struct vertex *vx=to_add; to_add=to_add->next; add_vertices(&ll,vx->below,yp); } #ifdef POLYDEBUG c=ll; while (c) { fprintf(stderr," line %g,%g - %g,%g [%g,%g - %g,%g]\n", c->xmin,c->yxmin,c->xmax,c->yxmax, c->above->x,c->above->y,c->below->x,c->below->y); c=c->next; } #endif if (!ll) { y++; continue; } /* begin with zeros */ for (i=0; i<img->xsize; i++) buf[i]=0.0; /* sanity check */ c=ll; while (c && c->next) { if (c->xmin > c->next->xmax || c->xmax > c->next->xmin || ( c->xmin!=c->xmax && c->next->xmin!=c->next->xmax && c->next->xmax>=c->xmin && c->next->xmin<=c->xmin && VY(c,c->xmin)>VY(c->next,c->xmin))) { struct line_list *l1; /* resort */ #ifdef POLYDEBUG fprintf(stderr," !!! resort !!!\n"); #endif l1=NULL; add_vertices(&l1,ll,yp); while ((c=ll)) { ll=c->next; free(c); } ll=l1; break; } c=c->next; } /* find first horisintal event */ xmin=ll->xmin; c=ll; while (c) { if (c->xmin<xmin) xmin=c->xmin; c=c->next; } /* loop through all horisontal events */ while (xmin<ixmax) { xmax=1e10; c=ll; while (c) { /* each line has two events: beginning and end */ if (c->xmin<xmax && c->xmin>xmin) xmax=c->xmin; if (c->xmax<xmax && c->xmax>xmin) xmax=c->xmax; c=c->next; } if (xmax==1e10) break; /* no more events */ if (xmax>ixmax) xmax=ixmax; tog=polyfill_event(xmin,xmax,yp,buf,&ll,tog); /* shift to get next event */ xmin = xmax; xmax = DO_NOT_WARN(xmin - 1.0); } /* remove any old vertices */ while (to_loose!=to_add && to_loose->y<yp+1.0-1e-10) { struct vertex *vx=to_loose; to_loose=to_loose->next; sub_vertices(&ll,vx,yp); } /* write this row */ d=img->img+img->xsize*y; if(THIS->alpha) { for (i=0; i<img->xsize; i++) { #ifdef POLYDEBUG fprintf(stderr,"%3.2f ",buf[i]); #endif #define apply_alpha(x,y,alpha) \ ((unsigned char)((y*(255L-(alpha))+x*(alpha))/255L)) d->r = apply_alpha( d->r, DOUBLE_TO_COLORTYPE((d->r*(1.0-buf[i]))+ (img->rgb.r*buf[i])), THIS->alpha ); d->g = apply_alpha( d->g, DOUBLE_TO_COLORTYPE((d->g*(1.0-buf[i]))+ (img->rgb.g*buf[i])), THIS->alpha ); d->b = apply_alpha( d->b, DOUBLE_TO_COLORTYPE((d->b*(1.0-buf[i]))+ (img->rgb.b*buf[i])), THIS->alpha ); d++; } #ifdef POLYDEBUG fprintf(stderr,"\n"); #endif } else { for (i=0; i<img->xsize; i++) { #ifdef POLYDEBUG fprintf(stderr,"%3.2f ",buf[i]); #endif d->r = DOUBLE_TO_COLORTYPE((d->r*(1.0-buf[i]))+(img->rgb.r*buf[i])); d->g = DOUBLE_TO_COLORTYPE((d->g*(1.0-buf[i]))+(img->rgb.g*buf[i])); d->b = DOUBLE_TO_COLORTYPE((d->b*(1.0-buf[i]))+(img->rgb.b*buf[i])); d++; } #ifdef POLYDEBUG fprintf(stderr,"\n"); #endif } y++; } while (ll) { struct line_list *c; ll=(c=ll)->next; free(c); } }