/** * $Id:$ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * The contents of this file may be used under the terms of either the GNU * General Public License Version 2 or later (the "GPL", see * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or * later (the "BL", see http://www.blender.org/BL/ ) which has to be * bought from the Blender Foundation to become active, in which case the * above mentioned GPL option does not apply. * * The Original Code is Copyright (C) 1997 by Ton Roosendaal, Frank van Beek and Joeri Kassenaar. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ /* font.c april 92 */ #include #include #include #include #include #include #include #include #include #include #include "/usr/people/include/Trace.h" #define CLIP MAKE_ID('C','L','I','P') #define CLNM MAKE_ID('C','L','N','M') #define VBOX MAKE_ID('V','B','O','X') #define OBJ MAKE_ID('O','B','J',' ') #define OFLG MAKE_ID('O','F','L','G') #define FILL MAKE_ID('F','I','L','L') #define DATA MAKE_ID('D','A','T','A') #define OEND MAKE_ID('O','E','N','D') #define OFIN MAKE_ID('O','F','I','N') #define PDFF MAKE_ID('P','D','F','F') #define CLFN MAKE_ID('C','L','F','N') #define KRNP MAKE_ID('K','R','N','P') #define BEZ4 MAKE_ID('B','E','Z','4') #define MAX_VF_CHARS 256 /* bezres hangt aan button en is word, bezresF is float en moet ingesteld worden */ /* bezmax hangt aan button, bezmaxF wordt uitgevoerd */ float fscale = 0.5,bezresF,wordr_ofsx,wordr_ofsy,wordr_fac; float AreaF2Dfl(); short textediting= 0,bezres=12,bezmax=6,bezmaxF; /* Nieuwe opzet voor vectorfont: * * Standaard worden de beziers onthouden, elk font wordt eerst naar dit formaat. * geconverteerd. Beziers 'draaien' al goed voor bijvoorbeeld beveling. * Dit is het formaat zoals in de curve gebruikt wordt. * * Daarnaast is er een cache waarin geinterpoleerde versies bewaard worden. * Nodig: resolutie, pointer naar punten. * Dit is het nog oude formaat van de poly's. * * De psfont moet helemaal netjes gemaakt worden zodat er alleen nog maar * curves uit kunnen komen. * */ /* * Pdraw en postscript fonts worden een op een gecopieerd, pas op het moment * dat er kopieen gemaakt worden wordt een matrix toegepast (scale, shear, rot?) */ struct bezpart { struct bezpart *next,*prev; long count; float points[1][3]; }; struct bezcurve { struct bezcurve *next,*prev; struct bezpart *first,*last; short count,hole; }; struct chartrans { long xof,yof; float rot; short linenr,charnr; }; struct VFont { struct VFont *next,*prev; char name[255], namenull; float scale; struct ListBase nurbsbase[MAX_VF_CHARS]; float resol[MAX_VF_CHARS]; float width[MAX_VF_CHARS]; float *points[MAX_VF_CHARS]; short kcount,us; short *kern; }; void freevfontN(struct VFont *vf) { long i; struct Nurb *nu; struct BezTriple *bezt; if (vf == 0) return; /* vf->us--; */ /* if (vf->us < 0){ */ /* patch */ /* remlink(&G.vfbase,vf); */ for (i = 0; i < MAX_VF_CHARS; i++){ while (nu = vf->nurbsbase[i].first){ bezt = nu->bezt; if (bezt) freeN(bezt); remlink(&vf->nurbsbase[i], nu); freeN(nu); } } if (vf->kern) freeN(vf->kern); freeN(vf); /* } */ } void freevfont(vf) struct VectorFont *vf; { if(vf==0) return; vf->us--; if(vf->us<=0) { remlink(&G.vfbase,vf); freeN(vf->name); if (vf->type == FNT_PDRAW) freeN(vf->base); freevfontN(vf->objfnt); freeN(vf); } } struct VectorFont *initvfont(name) char *name; { /* vfont->us (users) zelf instellen, wordt hier op nul gezet */ long file,len,totlen, i; uchar *mem, *p, ascii; struct VectorFont *vfont; struct VFont * loadvfont(), *Vfont; file = open(name,O_RDONLY); if (file<=0) return (0); len = lseek(file,0L,SEEK_END); lseek(file,0L,SEEK_SET); mem = (uchar *) mallocN(len,"initvfontmem"); if (mem == 0) { close(file) ; return(0); } if (read(file,mem,len) != len) { close(file) ; freeN(mem) ; return (0); } close(file); if (GL(mem) != PDFF){ /* look for %!PS-AdobeFont-1 */ for (i = 0; i < len; i++){ if (mem[i] == '%'){ if (memcmp(mem + i, "%!PS-AdobeFont-1", 16) == 0) break; } } freeN(mem); if (i > len) { printf("No Vectorfont or Postscript-1 file %s\n",name); return(0); } /*printf("Found PSfont\n");*/ Vfont = loadvfont(name); if (Vfont == 0) return(0); vfont = callocstructN(struct VectorFont,1,"initvfontfont"); if (vfont == 0) { freeN(mem) ; return(0); } vfont->name = mallocN(strlen(name)+1,"initvfontname"); strcpy(vfont->name,name); vfont->type = FNT_HAEBERLI; vfont->objfnt = (struct objfnt *) Vfont; addtail(&G.vfbase,vfont); return(vfont); } vfont = callocstructN(struct VectorFont,1,"initvfontfont"); if (vfont == 0) { freeN(mem) ; return(0); } vfont->name = mallocN(strlen(name)+1,"initvfontname"); strcpy(vfont->name,name); vfont->base = mem; vfont->type = FNT_PDRAW; totlen = len - 8; mem += 8; while(totlen > 0){ len = GL(mem + 4); switch(GL(mem)){ case CLNM: ascii = mem[8]; break; case VBOX: if (ascii) vfont->index[ascii] = mem; RMK(printf("found %d %x\n",ascii,mem);) break; case OFIN: ascii = 0; break; case KRNP: vfont->kern = (short *) (mem + 10); vfont->kcount = vfont->kern[-1]; } len= ((len + 1) & ~1) + 8; mem += len; totlen -= len; } addtail(&G.vfbase,vfont); /* patch */ vfont->objfnt = (struct objfnt *) loadvfont(name); return(vfont); } struct VFont *loadpdrawfont(uchar * mem, long totlen) { struct BezTriple *bezt; struct Nurb *nu; struct VFont *vfont = 0; struct ListBase *curve; long len, ascii = 0, ok = FALSE, hole, i; short *point; vfont = callocstructN(struct VFont,1,"initvfontfont"); if (vfont) { vfont->scale = 0.5; totlen -= 8; mem += 8; while(totlen > 0){ len = GL(mem + 4); switch(GL(mem)){ case CLNM: ascii = mem[8]; if (ascii >= 0 && ascii < MAX_VF_CHARS){ curve = &vfont->nurbsbase[ascii]; } else{ curve = 0; ascii = 0; } break; case FILL: hole = mem[9]; break; case OBJ : if (GL(mem+8) == BEZ4) ok = TRUE; else ok = FALSE; break; case VBOX: i = GL(mem + 4) + 8; vfont->width[ascii] = GL(mem + i - 8); break; case OFIN: ascii = 0; curve = 0; break; case KRNP: vfont->kcount = GS(mem + 8); if (vfont->kcount){ vfont->kern = mallocstructN(short, 2 * vfont->kcount, "kerndata"); if (vfont->kern) memcpy(vfont->kern, mem + 10, vfont->kcount * 2 * sizeof(short)); else vfont->kcount = 0; } break; case DATA: point = (short *)(mem + 8); i = (*point++) - 1; if (ok == FALSE || curve == 0 || i < 1) break; nu = callocstructN(struct Nurb,1, "pdrawnurb"); if (nu == 0) break; nu->type = 9; nu->pntsu = i; nu->resolu = 12; nu->flagu = 1; bezt = callocstructN(struct BezTriple, i, "pdrawbezt"); if (bezt == 0) { freeN(nu); break; } nu->bezt = bezt; addtail(curve, nu); if (hole) { /* volgorde omdraaien */ bezt += (i - 1); for (; i > 0 ; i--) { bezt->vec[2][0] = fscale * point[2]; bezt->vec[2][1] = - fscale * point[3]; bezt->vec[1][0] = fscale * point[0]; bezt->vec[1][1] = - fscale * point[1]; bezt->vec[0][0] = fscale * point[4]; bezt->vec[0][1] = - fscale * point[5]; bezt--; point += 6; } } else{ for (; i > 0 ; i--) { bezt->vec[0][0] = fscale * point[2]; bezt->vec[0][1] = - fscale * point[3]; bezt->vec[1][0] = fscale * point[0]; bezt->vec[1][1] = - fscale * point[1]; bezt->vec[2][0] = fscale * point[4]; bezt->vec[2][1] = - fscale * point[5]; bezt++; point += 6; } } /*printf("Added %d for character '%c'\n", nu->pntsu, ascii);*/ autocalchandlesNurb(nu, 0); /* flag=0, alles doen */ break; } len= ((len + 1) & ~1) + 8; mem += len; totlen -= len; } } return(vfont); } struct VFont *objfnt_to_vfont(struct objfnt *fnt) { struct VFont * vfont = 0; chardesc *cd; short *_data, *data; long i, count, stop, ready, meet; short first[2], last[2]; struct Nurb *nu; struct BezTriple *bezt, *bez2; float scale, dx, dy; if (fnt == 0) return (0); if (fnt->type != SP_TYPE){ printf("objfnt is wrong type: need splines\n"); return(0); } scale = 4 * fscale * fnt->scale / 10000.0; vfont = callocstructN(struct VFont,1,"initvfontfont"); if (vfont == 0) return(0); vfont->scale = 2 * fnt->scale / 1000.0; for (i = 0; i < MAX_VF_CHARS; i++){ cd = getchardesc(fnt, i); if (cd && cd->data && cd->datalen){ vfont->width[i] = scale * cd->movex / fscale; _data = data = cd->data; do{ /* eerst even tellen */ _data = data; count = 0; ready = stop = FALSE; do{ switch(*data++){ case SP_MOVETO: first[0] = data[0]; first[1] = data[1]; case SP_LINETO: count++; last[0] = data[0]; last[1] = data[1]; data += 2; break; case SP_CURVETO: count++; last[0] = data[4]; last[1] = data[5]; data += 6; break; case SP_RET: case SP_RETCLOSEPATH: stop = TRUE; ready = TRUE; break; case SP_CLOSEPATH: stop = TRUE; break; } }while (stop == FALSE); if (last[0] == first[0] && last[1] == first[1]) meet = 1; else meet = FALSE; /* is er meer dan 1 uniek punt ?*/ if (count - meet > 0) { data = _data; nu = callocstructN(struct Nurb,1, "objfnt_nurb"); bezt = callocstructN(struct BezTriple, count, "objfnt_bezt"); if (nu != 0 && bezt != 0){ addtail(&vfont->nurbsbase[i], nu); nu->type= 9; nu->pntsu = count; nu->resolu= 12; nu->flagu= 1; nu->bezt = bezt; stop = FALSE; /* punten inlezen */ do{ switch(*data++){ case SP_MOVETO: bezt->vec[1][0] = scale * *data++; bezt->vec[1][1] = scale * *data++; break; case SP_LINETO: bez2 = bezt++; bezt->vec[1][0] = scale * *data++; bezt->vec[1][1] = scale * *data++; /* vector handles */ dx = (bezt->vec[1][0] - bez2->vec[1][0]) / 3.0; dy = (bezt->vec[1][1] - bez2->vec[1][1]) / 3.0; bezt->vec[0][0] = bezt->vec[1][0] - dx; bezt->vec[0][1] = bezt->vec[1][1] - dy; bez2->vec[2][0] = bez2->vec[1][0] + dx; bez2->vec[2][1] = bez2->vec[1][1] + dy; break; case SP_CURVETO: bezt->vec[2][0] = scale * *data++; bezt->vec[2][1] = scale * *data++; bezt++; bezt->vec[0][0] = scale * *data++; bezt->vec[0][1] = scale * *data++; bezt->vec[1][0] = scale * *data++; bezt->vec[1][1] = scale * *data++; break; case SP_RET: case SP_RETCLOSEPATH: stop = TRUE; ready = TRUE; break; case SP_CLOSEPATH: stop = TRUE; break; } }while (stop == FALSE); if (meet) { /* kopieer handles */ nu->bezt->vec[0][0] = bezt->vec[0][0]; nu->bezt->vec[0][1] = bezt->vec[0][1]; /* en vergeet laatste punt */ nu->pntsu--; } else{ /* vector handles */ bez2 = nu->bezt; dx = (bezt->vec[1][0] - bez2->vec[1][0]) / 3.0; dy = (bezt->vec[1][1] - bez2->vec[1][1]) / 3.0; bezt->vec[2][0] = bezt->vec[1][0] - dx; bezt->vec[2][1] = bezt->vec[1][1] - dy; bez2->vec[0][0] = bez2->vec[1][0] + dx; bez2->vec[0][1] = bez2->vec[1][1] + dy; } autocalchandlesNurb(nu, 0); /* flag=0, alles doen */ } else{ if (nu) freeN(nu); if (bezt) freeN(bezt); } } _data = data; }while (ready == FALSE); } } return(vfont); } struct VFont *loadpsfont(char * name) { struct objfnt * fnt; struct VFont *vfont = 0; extern struct objfnt * loadpostcriptfont(char *); fnt = loadpostcriptfont(name); if (fnt == 0) return(0); vfont = objfnt_to_vfont(fnt); freeobjfnt(fnt); return(vfont); } struct VFont *loadvfont(char * name) { long file,len, i; uchar *mem; struct VFont *vfont = 0; file = open(name,O_RDONLY); if (file != -1){ len = lseek(file,0L,SEEK_END); lseek(file,0L,SEEK_SET); mem = (uchar *) mallocN(len,"initvfontmem"); if (mem) { if (read(file,mem,len) == len) { switch (GL(mem)){ case PDFF: vfont = loadpdrawfont(mem, len); break; case OFMAGIC: break; default: /* look for %!PS-AdobeFont-1 */ for (i = 0; i < len; i++){ if (mem[i] == '%'){ if (memcmp(mem + i, "%!PS-AdobeFont-1", 16) == 0) break; } } if (i > len) { printf("No Vectorfont or Postscript-1 file %s\n",name); } else { vfont = loadpsfont(name); } } } else perror("read"); freeN(mem); } else perror("malloc"); close(file); } else perror("open"); if (vfont){ strncpy(vfont->name, name, sizeof(vfont->name)); /*addtail(&G.vfbase,vfont);*/ } return(vfont); } short *find_diff_array(start,place,ofs,len) short *start,*place,ofs; long len; { /* - loopt array af en geeft adres terug van de eerste verschillende - is cyclisch! - ofs is negatief: achterwaarts */ short *end,*walk,a,absofs,around=0; absofs= abs(ofs); end= start+ absofs*(len-1); walk= place+ ofs; while(walk!=place) { if(walk>=end) { walk= start; around+= 1; } else if(walk<=start) { walk= end; around+=1; } for(a=0;a1) return place; } return place; } void extrudepoly(base) struct Base *base; { struct ObData *ob; struct PolyData *po; float t01,t02,cosh,x1,x2,x3,y1,y2,y3; short *a1,*a2,*a3,*adr,*adrp,*start,p,vorm,a=0,b,button(); if(base==0) return; if(base->soort!=7 && base->soort!=9) return; ob=(struct ObData *)base->d; po=(struct PolyData *)ob->po; if(po->f45m!=0 || po->f45p!=0) { if(po->f45) return; if(po->vert==0) return; p= po->vert; vorm= po->poly; po->f45=adr= (short *)mallocN(6*p,"45 faces"); adrp= (short *)(po+1); for(a=0;a=1.0) t02= .5*PI; else t02= (facos(t02))/2.0; t02= fsin(t02); if(t02==0) { /* printf("t02 nul \n"); */ t02= 1; } { t02= 1000.0/t02; x3= x1-x2; y3= y1-y2; if(x3==0 && y3==0) { printf("x3 en y3 nul \n"); x3= y1; y3= -x1; } else { t01= fsqrt(x3*x3+y3*y3); x3/=t01; y3/=t01; } *(adr++)= (short)-t02*y3; *(adr++)= (short)t02*x3; *(adr++)= -1000; } adrp+=3; } } } else if(po->f45) { freeN(po->f45); po->f45=0; } } void makescreenpoints(points,x1,x2,x3,x4,num) float *points; double x1,x2,x3,x4; long num; { double t1,t2,t3,fnum1,fnum2; fnum1 = fnum2 = num; t1 = 3.0*(x2-x1) / fnum1; fnum1 *= fnum2; t2 = 3.0*(x1-2.0*x2+x3) / fnum1; fnum1 *= fnum2; t3 = (x4-x1+3.0*(x2-x3)) / fnum1; x2 = t1+t2+t3; x3 = 2.0*t2+6.0*t3; x4 = 6.0*t3; for(;num >0; num--){ *points = x1; points += 3; x1 += x2; x2 += x3; x3 += x4; } } long screen_inter(points,bez,res,max) float *points,bez[5][3],res; long max; { long num,i,xtra = 0; float fnum,buig,x1,y1,z1,x2,y2,z2,len,area; x1 = bez[1][0] - bez[0][0]; y1 = bez[1][1] - bez[0][1]; z1 = bez[1][2] - bez[0][2]; x2 = bez[2][0] - bez[1][0]; y2 = bez[2][1] - bez[1][1]; z2 = bez[2][2] - bez[1][2]; len = fsqrt((x2 * x2 + y2 * y2 + z2 * z2) * (x1 * x1 + y1 * y1 + z1 * z1)); if (len == 0.0 ) len = 1.0; if ((x1 * x2 + y1 * y2 + z1 * z2) / len < 0.9999){ /* groter dan 0.6 graden */ xtra = 1; *points++ = bez[1][0] ; *points++ = bez[1][1] ; *points++ = bez[1][2]; } /* dit moet berekend worden aan de hand van de geprojecteerde coordinaten !!*/ area = AreaF2Dfl(bez+1,bez+2,bez+3)+AreaF2Dfl(bez+1,bez+3,bez+4) +AreaF2Dfl(bez+1,bez+2,bez+4)+AreaF2Dfl(bez+2,bez+3,bez+4); x1 = bez[1][0] - bez[4][0]; y1 = bez[1][1] - bez[4][1]; z1 = bez[1][2] - bez[4][2]; len = fsqrt(x1*x1 + y1*y1 + z1*z1); fnum = res * fsqrt(area / 2.0); if (len != 0.0) fnum = res * area / len; else fnum = 0; num = fnum; if (num > max) num = max; RMK( /* voor als we ooit nog perfecte interpolatie willen , afhankelijk van de buiging punten berekenen*/ x1 = bez[1][0] - 2.0*bez[2][0] + bez[3][0]; x2 = (bez[4][0]-bez[1][0]+3.0*(bez[2][0]-bez[3][0]))/max; y1 = bez[1][1] - 2.0*bez[2][1] + bez[3][1]; y2 = (bez[4][1]-bez[1][1]+3.0*(bez[2][1]-bez[3][1]))/max; z1 = bez[1][2] - 2.0*bez[2][2] + bez[3][2]; z2 = (bez[4][2]-bez[1][2]+3.0*(bez[2][2]-bez[3][2]))/max; for (i = max-1;i>0;i--){ x1 += x2; y1 += y2; z1 += z2; buig += fabs(x1) + fabs(y1) + fabs(z1); } ) if (num <= 1){ *points++ = bez[1][0] ; *points++ = bez[1][1] ; *points++ = bez[1][2]; num = 1; } else { makescreenpoints(points+0,bez[1][0],bez[2][0],bez[3][0],bez[4][0],num); makescreenpoints(points+1,bez[1][1],bez[2][1],bez[3][1],bez[4][1],num); makescreenpoints(points+2,bez[1][2],bez[2][2],bez[3][2],bez[4][2],num); } return (num + xtra); } void buildchar(bezbase,vfont,ascii,lofsx,lofsy,shear) struct ListBase * bezbase; struct VFont *vfont; uchar ascii; long lofsx,lofsy; float shear; { float bez[5][3], points[100][3]; long i,pres; struct bezcurve * bezc; struct bezpart * bezp; struct Nurb * nu; struct BezTriple * bezt1, *bezt2; float ofsx, ofsy; if (vfont == 0) return; bez[0][2] = 0.0; bez[1][2] = 0.0; bez[2][2] = 0.0; bez[3][2] = 0.0; bez[4][2] = 0.0; ofsx = fscale * lofsx; ofsy = fscale * lofsy; shear /= fscale; nu = vfont->nurbsbase[ascii].first; while (nu) { bezt1 = nu->bezt; if (bezt1) { bezc = callocstructN(struct bezcurve,1, "buildchar"); if (bezc == 0) return; i = bezc->count = nu->pntsu; bezt2 = bezt1 + 1; for (; i > 0 ; i--){ if (i == 1) bezt2 = nu->bezt; bez[0][0] = bezt1->vec[0][0] + ofsx; bez[0][1] = bezt1->vec[0][1] + ofsy; bez[1][0] = bezt1->vec[1][0] + ofsx; bez[1][1] = bezt1->vec[1][1] + ofsy; bez[2][0] = bezt1->vec[2][0] + ofsx; bez[2][1] = bezt1->vec[2][1] + ofsy; bez[3][0] = bezt2->vec[0][0] + ofsx; bez[3][1] = bezt2->vec[0][1] + ofsy; bez[4][0] = bezt2->vec[1][0] + ofsx; bez[4][1] = bezt2->vec[1][1] + ofsy; if(shear!=0.0) { bez[0][0] -= shear * bezt1->vec[0][1]; bez[1][0] -= shear * bezt1->vec[1][1]; bez[2][0] -= shear * bezt1->vec[2][1]; bez[3][0] -= shear * bezt2->vec[0][1]; bez[4][0] -= shear * bezt2->vec[1][1]; } pres = screen_inter(points,bez,1.0 /bezresF , bezmaxF); bezp = (struct bezpart *) callocN( (3 * sizeof(float)*pres) + sizeof(struct bezpart),"bezp"); if (bezp == 0) return; addtail(&bezc->first,bezp); memcpy(bezp->points,points,3 * sizeof(float) * pres); bezp->count = pres; bezt1++; bezt2++; } addtail(bezbase,bezc); } nu = nu->next; } } void buildcharN(curve,vfont,ascii,lofsx,lofsy,shear) struct ListBase *curve; struct VFont *vfont; uchar ascii; long lofsx,lofsy; float shear; { struct BezTriple *bezt1, *bezt2; struct Nurb *nu1, *nu2; float ofsx, ofsy; long i; if (vfont == 0) return; if (curve == 0) return; ofsx = fscale * lofsx; ofsy = fscale * lofsy; shear /= fscale; /* maak een kopie op afstand ofsx, ofsy met shear*/ nu1 = vfont->nurbsbase[ascii].first; while(nu1) { bezt1 = nu1->bezt; if (bezt1){ nu2 = mallocstructN(struct Nurb,1, "duplichar_nurb"); if (nu2 == 0) break; memcpy(nu2, nu1, sizeof(struct Nurb)); nu2->bp = 0; nu2->knotsu = nu2->knotsv = 0; nu2->trim.first = 0; nu2->trim.last = 0; i = nu2->pntsu; bezt2= mallocstructN(struct BezTriple, i, "duplichar_bezt2"); if (bezt2 == 0){ freeN(nu2); break; } memcpy(bezt2, bezt1, i * sizeof(struct BezTriple)); nu2->bezt = bezt2; for (; i > 0; i--){ bezt2->vec[0][0] += ofsx; bezt2->vec[0][1] += ofsy; bezt2->vec[1][0] += ofsx; bezt2->vec[1][1] += ofsy; bezt2->vec[2][0] += ofsx; bezt2->vec[2][1] += ofsy; bezt2++; } if (shear != 0.0){ bezt1 = nu1->bezt; bezt2 = nu2->bezt; i = nu2->pntsu; for (; i > 0; i--){ bezt2->vec[0][0] -= shear * bezt1->vec[0][1]; bezt2->vec[1][0] -= shear * bezt1->vec[1][1]; bezt2->vec[2][0] -= shear * bezt1->vec[2][1]; bezt1++; bezt2++; } } addtail(curve, nu2); } nu1 = nu1->next; } } void buildtext(bezbase,fo,mode) struct ListBase * bezbase; struct FontData *fo; short mode; /* mode>0: alleen textcurs doen, mode==-1: Nurblist maken */ { struct VectorFont *vectfont; struct VFont *vfont; struct chartrans *chartransdata,*ct; float *f,maxlen=0,shear; long len,i,slen,xof=0,yof=0,linedist,*ld,*linedata,*linedata2; short *kern,kcount,str,cnr=0,lnr=0,xtrax; uchar ascii,*mem; /* opmerking: berekeningen altijd tot en met de '\0' van de string omdat de cursor op die plek moet kunnen staan */ if(fo==0) return; vectfont= fo->vf; if (vectfont==0) return; /* patch */ vfont = (struct VFont *) vectfont->objfnt; if (fo->str==0) return; mem= fo->str; slen = strlen(fo->str); fo->lines= 1; for (i= 0; i<=slen; i++,mem++) { ascii = *mem; if(ascii== '\n' || ascii== '\r') fo->lines++; } /* bereken ofset en rotatie van iedere letter */ ct=chartransdata= callocstructN(struct chartrans, slen+1, "buildtext"); linedata= (long *)mallocN(4*fo->lines,"buildtext2"); linedata2= (long *)mallocN(4*fo->lines,"buildtext2"); xof= fo->xof; yof= fo->yof; xtrax= 32*fo->set[1]; linedist= 3200+64*fo->set[3]; shear= -0.02*( (float)fo->set[4])*fscale; for (i = 0 ; i<=slen ; i++) { ascii = fo->str[i]; if(ascii== '\n' || ascii== '\r' || ascii==0) { ct->xof= xof; ct->yof= yof; ct->linenr= lnr; ct->charnr= cnr; yof-= linedist; maxlen= MAX2(maxlen,xof); linedata[lnr]= xof; linedata2[lnr]= cnr; xof= fo->xof; lnr++; cnr= 0; } else { ct->xof= xof; ct->yof= yof; ct->linenr= lnr; ct->charnr= cnr++; xof += vfont->width[ascii] + xtrax; if(fo->set[2] && vfont->kern) { kern = vfont->kern; str = (ascii << 8) + fo->str[i+1]; for (kcount = vfont->kcount ; kcount >0 ; kcount--) { if (*kern++ == str) { xof += *kern; break; } kern++; } } } ct++; } /* met alle fontsettings plekken letters berekenen */ if(fo->set[0]>0 && lnr>1) { ct= chartransdata; if(fo->set[0]==1) { /* right */ for(i=0;ixof+= linedata[ct->linenr]; ct++; } } else if(fo->set[0]==2) { /* middle */ for(i=0;ixof+= linedata[ct->linenr]; ct++; } } else if(fo->set[0]==3) { /* flush */ for(i=0;i1) linedata[i]= (maxlen-linedata[i])/(linedata2[i]-1); for (i=0; i<=slen; i++) { ct->xof+= ct->charnr*linedata[ct->linenr]; ct++; } } } if(mode>1) { /* 2: curs omhoog 3: curs omlaag */ ct= chartransdata+fo->pos; if(mode==2 && ct->linenr==0); else if(mode==3 && ct->linenr==lnr); else { if(mode==2) lnr= ct->linenr-1; else lnr= ct->linenr+1; cnr= ct->charnr; /* zoek karakter met lnr en cnr */ fo->pos= 0; ct= chartransdata; for (i= 0; ilinenr==lnr) { if(ct->charnr==cnr) break; if( (ct+1)->charnr==0) break; } else if(ct->linenr>lnr) break; fo->pos++; ct++; } } } /* eerst cursor */ if(textediting) { ct= chartransdata+fo->pos; f= G.textcurs[0]; f[0]= fscale * (-140.0 + ct->xof); f[1]= fscale * (0.0 + ct->yof); f[2]= fscale * (140.0 + ct->xof); f[3]= fscale * (0.0 + ct->yof); f[4]= fscale * (140.0 + ct->xof) -2200*shear; f[5]= fscale * (2200.0 + ct->yof); f[6]= fscale * (-100.0 + ct->xof) -2200*shear; f[7]= fscale * (2200.0 + ct->yof); } if(mode>0) { for(i=0; i<4; i++) { G.textcurs[i][0]= wordr_fac*(G.textcurs[i][0]-wordr_ofsx); G.textcurs[i][1]= wordr_fac*(G.textcurs[i][1]-wordr_ofsy); } } else if(mode== -1) { /* nurbdata */ ct= chartransdata; for (i= 0; istr[i]; buildcharN(bezbase, vfont, ascii, ct->xof, ct->yof, shear); ct++; } } else { /* bereken letters */ ct= chartransdata; for (i= 0; istr[i]; buildchar(bezbase,vfont,ascii,ct->xof,ct->yof,shear); ct++; } } freeN(chartransdata); freeN(linedata); freeN(linedata2); } void text_to_curve(base) struct Base *base; { struct ObData *ob; struct FontData *fo; ob= (struct ObData *)base->d; fo= ob->fo; ob->cu= callocstructN(struct CurveData, 1, "text_to_curve"); ob->cu->ws= 1.0; ob->cu->width= 100; ob->cu->flag= 255; fscale= ((float)fo->set[5])/20.0; buildtext(&(ob->cu->curve), fo, -1); freevfont(fo->vf); if(fo->str) freeN(fo->str); /* OUD! if(fo->bez) freeN(fo->bez); */ freeN(fo); if(ob->po->f45) freeN(ob->po->f45); freeN(ob->po); ob->po= 0; ob->fo= 0; base->soort= 11; makeBevelList(base); makeDispList(base); } void makepolytext(base) struct Base *base; { struct ObData *ob; struct PolyData *po,*pon; struct FontData *fo; struct ListBase _bezbase; struct ListBase *bezbase = &_bezbase; struct bezcurve * bezc; struct bezpart * bezp; float fac,min[3],max[3]; long i,c,vert=0,poly=0; short *p,*pnr; char *tempstr= 0; bezbase->first = bezbase->last = 0; min[0]= min[1]= min[2]= 1.0e20; max[0]= max[1]= max[2]= -1.0e20; ob= (struct ObData *)base->d; po= ob->po; fo= ob->fo; fscale= ((float)fo->set[5])/20.0; bezresF= fscale*((float)bezres); bezmaxF= bezmax; if(textediting==0 && ob->ef==4) { /* build effect */ i= strlen(fo->str); if(i) { tempstr= mallocN(i+1, "makepolytext"); strcpy(tempstr, fo->str); c= build_schiphol(base, i); if(c>=0 && c<=i) fo->str[c]= 0; } } buildtext(bezbase,fo,0); if(ob->ef==4 && tempstr) { strcpy(fo->str, tempstr); freeN(tempstr); } /* aantal punten en poly's tellen */ bezc = bezbase->first; while (bezc){ bezp = bezc->first; if (bezp) { poly++; vert+=1; while(bezp){ for(i=0; icount; i++) { min[0]= MIN2(min[0],bezp->points[i][0]); min[1]= MIN2(min[1],bezp->points[i][1]); max[0]= MAX2(max[0],bezp->points[i][0]); max[1]= MAX2(max[1],bezp->points[i][1]); } vert+= bezp->count; bezp = bezp->next; } } bezc = bezc->next; } pon= (struct PolyData *)callocN(sizeof(struct PolyData)+6*vert+2*poly, "makepolytext"); if(po) { if(po->f45) { freeN(po->f45); po->f45= 0; } memcpy(pon,po,sizeof(struct PolyData)); freeN(po); } else { /* polydata initialiseren */ pon->f1= 31; } po= pon; ob->po= po; po->vert= vert; po->poly= poly; po->us= 1; /* wordruimte */ if(fo->set[0]==2) { /* middle */ po->afm[0]= (max[0]-min[0]+1)/2; po->afm[1]= (max[1]-min[1]+1)/2; wordr_ofsx= (min[0]+max[0])/2; wordr_ofsy= (min[1]+max[1])/2; fac= MAX2(max[0]-min[0]+1,max[1]-min[1]+1); fo->xof-= wordr_ofsx; fo->yof-= wordr_ofsy; } else { po->afm[0]= MAX2(fabs(max[0]),fabs(min[0])); po->afm[1]= MAX2(fabs(max[1]),fabs(min[1])); wordr_ofsx= 0; wordr_ofsy= 0; fac= MAX4(fabs(max[0]),fabs(min[0]),fabs(max[1]),fabs(min[1])); } if(fac>1.0e19) { fac= 32760.0; wordr_ofsx= 0; wordr_ofsy= 0; } fac= 32760.0/fac; po->ws= 1.0/fac; po->depth= fscale*8.0*fac; po->n[2]= -32767; /* word array maken */ p= (short *)(po+1); bezc = bezbase->first; while (bezc) { if(bezc->hole==1) { bezp = bezc->first; if (bezp) { pnr= p; p++; while(bezp){ *pnr+= bezp->count; for(i=0; icount; i++) { p[0]= fac*(bezp->points[i][0]-wordr_ofsx); p[1]= fac*(bezp->points[i][1]-wordr_ofsy); p+=3; } bezp = bezp->next; } (*pnr)++; bezp = bezc->first; p[0]= fac*(bezp->points[0][0]-wordr_ofsx); p[1]= fac*(bezp->points[0][1]-wordr_ofsy); p+=3; } } else { bezp = bezc->last; if (bezp) { pnr= p; p++; while(bezp){ *pnr+= bezp->count; for(i=bezp->count-1; i>=0; i--) { p[0]= fac*(bezp->points[i][0]-wordr_ofsx); p[1]= fac*(bezp->points[i][1]-wordr_ofsy); p+=3; } bezp = bezp->prev; } (*pnr)++; bezp = bezc->last; p[0]= fac*(bezp->points[bezp->count-1][0]-wordr_ofsx); p[1]= fac*(bezp->points[bezp->count-1][1]-wordr_ofsy); p+=3; } } bezc= bezc->next; } /* cursor? */ if(textediting) { wordr_fac= fac; for(i=0; i<4; i++) { G.textcurs[i][0]= fac*(G.textcurs[i][0]-wordr_ofsx); G.textcurs[i][1]= fac*(G.textcurs[i][1]-wordr_ofsy); } } /* vrijgeven */ bezc = bezbase->first; while (bezc){ freelistN(&bezc->first); bezc = bezc->next; } freelistN(bezbase); } char findaccent(char char1, char code) { char new= 0; if(char1=='a') { if(code=='`') new= 224; else if(code==39) new= 255; else if(code=='^') new= 226; else if(code=='~') new= 227; else if(code=='"') new= 228; else if(code=='o') new= 229; else if(code=='e') new= 230; else if(code=='-') new= 170; } else if(char1=='c') { if(code==',') new= 231; if(code=='|') new= 162; } else if(char1=='e') { if(code=='`') new= 232; else if(code==39) new= 233; else if(code=='^') new= 234; else if(code=='"') new= 235; } else if(char1=='i') { if(code=='`') new= 236; else if(code==39) new= 237; else if(code=='^') new= 238; else if(code=='"') new= 239; } else if(char1=='n') { if(code=='~') new= 241; } else if(char1=='o') { if(code=='`') new= 242; else if(code==39) new= 243; else if(code=='^') new= 244; else if(code=='~') new= 245; else if(code=='"') new= 246; else if(code=='/') new= 248; else if(code=='-') new= 186; else if(code=='e') new= 143; } else if(char1=='s') { if(code=='s') new= 167; } else if(char1=='u') { if(code=='`') new= 249; else if(code==39) new= 250; else if(code=='^') new= 251; else if(code=='"') new= 252; } else if(char1=='y') { if(code==39) new= 253; else if(code=='"') new= 255; } else if(char1=='A') { if(code=='`') new= 192; else if(code==39) new= 193; else if(code=='^') new= 194; else if(code=='~') new= 195; else if(code=='"') new= 196; else if(code=='o') new= 197; else if(code=='e') new= 198; } else if(char1=='C') { if(code==',') new= 199; } else if(char1=='E') { if(code=='`') new= 200; else if(code==39) new= 201; else if(code=='^') new= 202; else if(code=='"') new= 203; } else if(char1=='I') { if(code=='`') new= 204; else if(code==39) new= 205; else if(code=='^') new= 206; else if(code=='"') new= 207; } else if(char1=='N') { if(code=='~') new= 209; } else if(char1=='O') { if(code=='`') new= 210; else if(code==39) new= 211; else if(code=='^') new= 212; else if(code=='~') new= 213; else if(code=='"') new= 214; else if(code=='/') new= 216; else if(code=='e') new= 141; } else if(char1=='U') { if(code=='`') new= 217; else if(code==39) new= 218; else if(code=='^') new= 219; else if(code=='"') new= 220; } else if(char1=='Y') { if(code==39) new= 221; } else if(char1=='1') { if(code=='4') new= 188; if(code=='2') new= 189; } else if(char1=='3') { if(code=='4') new= 190; } else if(char1==':') { if(code=='-') new= 247; } else if(char1=='-') { if(code==':') new= 247; if(code=='|') new= 135; if(code=='+') new= 177; } else if(char1=='|') { if(code=='-') new= 135; if(code=='=') new= 136; } else if(char1=='=') { if(code=='|') new= 136; } else if(char1=='+') { if(code=='-') new= 177; } if(new) return new; else return char1; } void textedit() { struct ObData *ob; struct FontData *fo; int accentcode= 0; short max=1000,dev,c,x,temp,doit,cursmove=0; char buf[1000],*str; if(G.ebase==0 || G.ebase->soort!=9) return; G.ebase->f&= ~1; ob= (struct ObData *)G.ebase->d; fo= ob->fo; strcpy(buf,fo->str); str= fo->str; fo->str= buf; fo->pos= fo->len= strlen(buf); setcursorN(1); G.f|= 8; /* geen overdraw cursor tekenen */ textediting= 1; makepolytext(G.ebase); projektie(); qdevice(KEYBD); while(getbutton(RIGHTMOUSE)); if(qtest()==KEYBD) dev= traces_qread(&c); /* event 'A' weghalen */ while(textediting) { dev = traces_qread(&c); if(c) { if(dev==INPUTCHANGE) { winset(c); G.winakt= c; continue; } else if(dev==LEFTMOUSE) break; else if(dev==RIGHTMOUSE) break; else if(dev==ESCKEY ) break; else if(dev==TABKEY ) break; else if(dev == KEYBD){ if ((c > 31 && c < 256 && c != 127) || (c == 13)) { if(accentcode && fo->pos>1) { buf[fo->pos-1]= findaccent(buf[fo->pos-1], c); } else if(fo->len') c= 187; else if(c=='<') c= 171; else if(c=='v') c= 1001; } if(c==1001) { int file, filelen; char *strp; file= open("/tmp/.cutbuffer", O_RDONLY); if(file>0) { filelen= lseek(file, 0, 2); /* seek end */ lseek(file, 0, 0); /* en weer terug */ strp= mallocN(filelen+1, "tempstr"); read(file, strp, filelen); close(file); strp[filelen]= 0; if(fo->len+filelenlen= strlen(buf); fo->pos= fo->len; } freeN(strp); } } else { for(x=fo->len;x>fo->pos;x--) buf[x]= buf[x-1]; buf[fo->pos]= c; fo->pos++; fo->len++; buf[fo->len]='\0'; } } accentcode= 0; } } else { cursmove= 0; c= rawtoascii(dev); switch(c) { case 0: break; case '\b': /* backspace */ if(fo->len!=0) { if(getbutton(LEFTALTKEY) || getbutton(RIGHTALTKEY) ) { if(fo->pos>0) accentcode= 1; } else if(fo->pos>0) { for(x=fo->pos;x<=fo->len;x++) buf[x-1]= buf[x]; fo->pos--; buf[--fo->len]='\0'; } } break; case 255: /* right */ fo->pos++; cursmove= 1; break; case 254: /* left */ fo->pos--; cursmove= 1; break; case 253: /* shift right */ while(fo->poslen) { if( buf[fo->pos]==0) break; if( buf[fo->pos]=='\n') break; if( buf[fo->pos]=='\r') break; fo->pos++; } cursmove= 1; break; case 252: /* shift left */ while(fo->pos>0) { if( buf[fo->pos-1]=='\n') break; if( buf[fo->pos-1]=='\r') break; fo->pos--; } cursmove= 1; break; case 250: /* up */ if (getbutton(RIGHTALTKEY)){ if (fo->pos && buf[fo->pos - 1] < 255) buf[fo->pos - 1]++; } else cursmove= 2; break; case 251: /* down */ if (getbutton(RIGHTALTKEY)){ if (fo->pos && buf[fo->pos - 1] > 1) buf[fo->pos - 1]--; } else cursmove= 3; break; case 248: /* shift up */ fo->pos= 0; cursmove= 1; break; case 249: /* shift down */ fo->pos= fo->len; cursmove= 1; break; default: if (getbutton(RIGHTALTKEY) == 0 || getbutton(LEFTALTKEY)==0) break; /* alleen nog maar voor speciale toetsen */ c += 128; if(fo->lenlen;x>fo->pos;x--) buf[x]= buf[x-1]; buf[fo->pos]=c; fo->pos++; fo->len++; buf[fo->len]='\0'; } } } if(fo->pos>fo->len) fo->pos= fo->len; else if(fo->pos>=max) fo->pos= max; else if(fo->pos<0) fo->pos= 0; else doit= 1; } if(doit && qtest()==0) { if(cursmove) { buildtext(0,ob->fo,cursmove); } else makepolytext(G.ebase); projektie(); doit= 0; } } unqdevice(KEYBD); textediting= 0; if(dev!=ESCKEY) { freeN(str); fo->str= mallocN(fo->len+1,"tekstedit"); strcpy(fo->str,buf); } else fo->str= str; fo->len= strlen(fo->str); G.ebase->f|= 1; makepolytext(G.ebase); G.f &= ~8; setcursorN(0); extrudepoly(G.ebase); projektie(); G.ebase= 0; tekenmainbuts(2); /* omdat polydata-pointer veranderd is */ } void to_upper() { struct Base *base; struct ObData *ob; struct FontData *fo; int len, ok; char *str; if(G.ebase) { error("Not in editmode!"); return; } base= G.firstbase; while(base) { if(base->f & 1) { if(base->lay & view0.lay) { if(base->soort==9) { ok= 0; ob= (struct ObData *)(base->d); fo= ob->fo; len= strlen(fo->str); str= fo->str; while(len) { if( *str>=97 && *str<=122) { ok= 1; *str-= 32; } len--; str++; } if(ok==0) { len= strlen(fo->str); str= fo->str; while(len) { if( *str>=65 && *str<=90) { *str+= 32; } len--; str++; } } makepolytext(base); extrudepoly(base); } } } base= base->next; } projektie(); }