void FVOutline(FontViewBase *fv, real width) { StrokeInfo si; SplineSet *temp, *spl; int i, cnt=0, changed, gid; SplineChar *sc; int layer = fv->active_layer; for ( i=0; i<fv->map->enccount; ++i ) if ( (gid=fv->map->map[i])!=-1 && (sc=fv->sf->glyphs[gid])!=NULL && fv->selected[i] && sc->layers[layer].splines ) ++cnt; ff_progress_start_indicator(10,_("Outlining glyphs"),_("Outlining glyphs"),0,cnt,1); memset(&si,0,sizeof(si)); si.removeexternal = true; si.radius = width; /*si.removeoverlapifneeded = true;*/ SFUntickAll(fv->sf); for ( i=0; i<fv->map->enccount; ++i ) if ( (gid=fv->map->map[i])!=-1 && (sc=fv->sf->glyphs[gid])!=NULL && fv->selected[i] && sc->layers[layer].splines && !sc->ticked ) { sc->ticked = true; SCPreserveLayer(sc,layer,false); temp = SplineSetStroke(sc->layers[layer].splines,&si,sc->layers[layer].order2); for ( spl=sc->layers[layer].splines; spl->next!=NULL; spl=spl->next ); spl->next = temp; SplineSetsCorrect(sc->layers[layer].splines,&changed); SCCharChangedUpdate(sc,layer); if ( !ff_progress_next()) break; } ff_progress_end_indicator(); }
/* by LoadSplineFont (which does) and by RevertFile (which knows what it's doing) */ SplineFont *_ReadSplineFont(FILE *file,char *filename,enum openflags openflags) { SplineFont *sf; char ubuf[250], *temp; int fromsfd = false; int i; char *pt, *strippedname, *oldstrippedname, *tmpfile=NULL, *paren=NULL, *fullname=filename, *rparen; int len; int checked; int compression=0; int wasurl = false, nowlocal = true; if ( filename==NULL ) return( NULL ); strippedname = filename; pt = strrchr(filename,'/'); if ( pt==NULL ) pt = filename; /* Someone gave me a font "Nafees Nastaleeq(Updated).ttf" and complained */ /* that ff wouldn't open it */ /* Now someone will complain about "Nafees(Updated).ttc(fo(ob)ar)" */ if ( (paren = strrchr(pt,'('))!=NULL && (rparen = strrchr(paren,')'))!=NULL && rparen[1]=='\0' ) { strippedname = copy(filename); strippedname[paren-filename] = '\0'; } pt = strrchr(strippedname,'.'); i = -1; if ( pt!=NULL ) for ( i=0; compressors[i].ext!=NULL; ++i ) if ( strcmp(compressors[i].ext,pt)==0 ) break; oldstrippedname = strippedname; if ( i==-1 || compressors[i].ext==NULL ) i=-1; else { if ( file!=NULL ) { char *spuriousname = ForceFileToHaveName(file,compressors[i].ext); tmpfile = Decompress(spuriousname,i); fclose(file); file = NULL; unlink(spuriousname); free(spuriousname); } else tmpfile = Decompress(strippedname,i); if ( tmpfile!=NULL ) { strippedname = tmpfile; } else { ff_post_error(_("Decompress Failed!"),_("Decompress Failed!")); return( NULL ); } compression = i+1; if ( strippedname!=filename && paren!=NULL ) { fullname = galloc(strlen(strippedname)+strlen(paren)+1); strcpy(fullname,strippedname); strcat(fullname,paren); } else fullname = strippedname; } /* If there are no pfaedit windows, give them something to look at */ /* immediately. Otherwise delay a bit */ strcpy(ubuf,_("Loading font from ")); len = strlen(ubuf); if ( !wasurl || i==-1 ) /* If it wasn't compressed, or it wasn't an url, then the fullname is reasonable, else use the original name */ strncat(ubuf,temp = copy(GFileNameTail(fullname)),100); else strncat(ubuf,temp = copy(GFileNameTail(filename)),100); free(temp); ubuf[100+len] = '\0'; ff_progress_start_indicator(FontViewFirst()==NULL?0:10,_("Loading..."),ubuf,_("Reading Glyphs"),0,1); ff_progress_enable_stop(0); if ( file==NULL ) { file = fopen(strippedname,"rb"); nowlocal = true; } sf = NULL; checked = false; /* checked == false => not checked */ /* checked == 'u' => UFO */ /* checked == 't' => TTF/OTF */ /* checked == 'p' => pfb/general postscript */ /* checked == 'P' => pdf */ /* checked == 'c' => cff */ /* checked == 'S' => svg */ /* checked == 'f' => sfd */ /* checked == 'F' => sfdir */ /* checked == 'b' => bdf */ /* checked == 'i' => ikarus */ if ( file!=NULL ) { /* Try to guess the file type from the first few characters... */ int ch1 = getc(file); int ch2 = getc(file); int ch3 = getc(file); int ch4 = getc(file); int ch9, ch10; fseek(file, 98, SEEK_SET); ch9 = getc(file); ch10 = getc(file); rewind(file); if (( ch1==0 && ch2==1 && ch3==0 && ch4==0 ) || (ch1=='O' && ch2=='T' && ch3=='T' && ch4=='O') || (ch1=='t' && ch2=='r' && ch3=='u' && ch4=='e') || (ch1=='t' && ch2=='t' && ch3=='c' && ch4=='f') ) { sf = _SFReadTTF(file,0,openflags,fullname,NULL); checked = 't'; } else if (( ch1=='%' && ch2=='!' ) || ( ch1==0x80 && ch2=='\01' ) ) { /* PFB header */ sf = _SFReadPostscript(file,fullname); checked = 'p'; } else if ( ch1==1 && ch2==0 && ch3==4 ) { int len; fseek(file,0,SEEK_END); len = ftell(file); fseek(file,0,SEEK_SET); sf = _CFFParse(file,len,NULL); checked = 'c'; } /* Too hard to figure out a valid mark for a mac resource file */ if ( file!=NULL ) fclose(file); } if ( sf!=NULL ) /* good */; else if (( strmatch(fullname+strlen(fullname)-4, ".ttf")==0 || strmatch(fullname+strlen(strippedname)-4, ".ttc")==0 || strmatch(fullname+strlen(fullname)-4, ".gai")==0 || strmatch(fullname+strlen(fullname)-4, ".otf")==0 || strmatch(fullname+strlen(fullname)-4, ".otb")==0 ) && checked!='t') { sf = SFReadTTF(fullname,0,openflags); } else if ( strmatch(fullname+strlen(strippedname)-4, ".bin")==0 || strmatch(fullname+strlen(strippedname)-4, ".hqx")==0 || strmatch(fullname+strlen(strippedname)-6, ".dfont")==0 ) { sf = SFReadMacBinary(fullname,0,openflags); } else if ( (strmatch(fullname+strlen(fullname)-4, ".pfa")==0 || strmatch(fullname+strlen(fullname)-4, ".pfb")==0 || strmatch(fullname+strlen(fullname)-4, ".pf3")==0 || strmatch(fullname+strlen(fullname)-4, ".cid")==0 || strmatch(fullname+strlen(fullname)-4, ".gsf")==0 || strmatch(fullname+strlen(fullname)-4, ".pt3")==0 || strmatch(fullname+strlen(fullname)-3, ".ps")==0 ) && checked!='p' ) { sf = SFReadPostscript(fullname); } else if ( strmatch(fullname+strlen(fullname)-4, ".cff")==0 && checked!='c' ) { sf = CFFParse(fullname); } else { sf = SFReadMacBinary(fullname,0,openflags); } ff_progress_end_indicator(); if ( sf!=NULL ) { SplineFont *norm = sf->mm!=NULL ? sf->mm->normal : sf; if ( compression!=0 ) { free(sf->filename); *strrchr(oldstrippedname,'.') = '\0'; sf->filename = copy( oldstrippedname ); } if ( fromsfd ) sf->compression = compression; free( norm->origname ); if ( sf->chosenname!=NULL && strippedname==filename ) { norm->origname = galloc(strlen(filename)+strlen(sf->chosenname)+8); strcpy(norm->origname,filename); strcat(norm->origname,"("); strcat(norm->origname,sf->chosenname); strcat(norm->origname,")"); } else norm->origname = copy(filename); free( norm->chosenname ); norm->chosenname = NULL; if ( sf->mm!=NULL ) { int j; for ( j=0; j<sf->mm->instance_count; ++j ) { free(sf->mm->instances[j]->origname); sf->mm->instances[j]->origname = copy(norm->origname); } } } else if ( !GFileExists(filename) ) ff_post_error(_("Couldn't open font"),_("The requested file, %.100s, does not exist"),GFileNameTail(filename)); else if ( !GFileReadable(filename) ) ff_post_error(_("Couldn't open font"),_("You do not have permission to read %.100s"),GFileNameTail(filename)); else ff_post_error(_("Couldn't open font"),_("%.100s is not in a known format (or is so badly corrupted as to be unreadable)"),GFileNameTail(filename)); if ( oldstrippedname!=filename ) free(oldstrippedname); if ( fullname!=filename && fullname!=strippedname ) free(fullname); if ( tmpfile!=NULL ) { unlink(tmpfile); free(tmpfile); } if ( (openflags&of_fstypepermitted) && sf!=NULL && (sf->pfminfo.fstype&0xff)==0x0002 ) { /* Ok, they have told us from a script they have access to the font */ } else if ( !fromsfd && sf!=NULL && (sf->pfminfo.fstype&0xff)==0x0002 ) { char *buts[3]; buts[0] = _("_Yes"); buts[1] = _("_No"); buts[2] = NULL; if ( ff_ask(_("Restricted Font"),(const char **) buts,1,1,_("This font is marked with an FSType of 2 (Restricted\nLicense). That means it is not editable without the\npermission of the legal owner.\n\nDo you have such permission?"))==1 ) { SplineFontFree(sf); return( NULL ); } } return( sf ); }
static int FtpURLAndTempFile(const char *url,FILE **to,FILE *from) { struct sockaddr_in addr, data_addr; char *host, *filename, *username, *password; int port; FILE *ret; char buffer[300]; int soc, data; int datalen, len; char *databuf, *cmd; if ( from==NULL ) { snprintf(buffer,sizeof(buffer),_("Downloading from %s"), url); *to = NULL; } else snprintf(buffer,sizeof(buffer),_("Uploading to %s"), url); if ( strncasecmp(url,"ftp://",6)!=0 ) { ff_post_error(_("Could not parse URL"),_("Got something else when expecting an ftp URL")); return( false ); } filename = decomposeURL(url, &host, &port, &username, &password); ff_progress_start_indicator(0,_("Font Download..."),buffer, _("Resolving host"),1,1); ff_progress_enable_stop(false); ff_progress_allow_events(); ff_progress_allow_events(); if ( !findFTPhost(&addr, host, port)) { ff_progress_end_indicator(); ff_post_error(_("Could not find host"),_("Could not find \"%s\"\nAre you connected to the internet?"), host ); free( host ); free( filename ); return( false ); } soc = makeConnection(&addr); if ( soc==-1 ) { ff_progress_end_indicator(); ff_post_error(_("Could not connect to host"),_("Could not connect to \"%s\"."), host ); free( host ); free( filename ); return( false ); } datalen = 8*8*1024; databuf = malloc(datalen+1); cmd = databuf; ChangeLine2_8(_("Logging in...")); if ( getresponse(soc,databuf,datalen) == -1 ) { /* ftp servers say "Hi" when then connect */ ff_progress_end_indicator(); ff_post_error(_("Could not connect to host"),_("Could not connect to \"%s\"."), host ); free( host ); free( filename ); free(username); free(password); close( soc ); return( false ); } free( host ); if ( username==NULL ) { username=copy("anonymous"); if ( password==NULL ) password=copy("FontForge"); } else if ( password==NULL ) password = copy(""); sprintf(cmd,"USER %s\r\n", username); if ( ftpsendr(soc,cmd,databuf,datalen)== -1 ) { ff_progress_end_indicator(); close( soc ); free(filename); free(databuf); free(username); free(password); return( false ); } sprintf(cmd,"PASS %s\r\n", password); free(username); free(password); if ( ftpsendr(soc,cmd,databuf,datalen)<=0 ) { ff_progress_end_indicator(); LogError(_("Bad Username/Password\n")); close( soc ); free(filename); free(databuf); return( false ); } if ( ftpsendr(soc,"TYPE I\r\n",databuf,datalen)==-1 ) { /* Binary */ ff_progress_end_indicator(); close( soc ); free(filename); free(databuf); return( false ); } if ( from==NULL ) ChangeLine2_8(_("Requesting font...")); else ChangeLine2_8(_("Transmitting font...")); if ( ftpsendpassive(soc,&data_addr,databuf,datalen)<= 0 ) { ff_progress_end_indicator(); close( soc ); free(filename); free(databuf); return( false ); } if (( data = socket(PF_INET,SOCK_STREAM,0))==-1 || connect(data,(struct sockaddr *) &data_addr,sizeof(data_addr))== -1 ) { ff_progress_end_indicator(); if ( data!=-1 ) close(data); close( soc ); free(filename); free(databuf); LogError(_("FTP passive Data Connect failed\n")); return( 0 ); } if ( from==NULL ) { sprintf(cmd,"RETR %s\r\n", filename); if ( ftpsendr(soc,cmd, databuf, datalen)<=0 ) { ff_progress_end_indicator(); ff_post_error(_("Could not download data"),_("Could not find file.") ); close(data); close( soc ); free(filename); free(databuf); return( false ); } ChangeLine2_8(_("Downloading font...")); ret = tmpfile(); while ((len = read(data,databuf,datalen))>0 ) { fwrite(databuf,1,len,ret); } *to = ret; rewind(ret); } else { sprintf(cmd,"STOR %s\r\n", filename); if ( ftpsendr(soc,cmd, databuf, datalen)<=0 ) { ff_progress_end_indicator(); ff_post_error(_("Could not download data"),_("Could not find file.") ); close(data); close( soc ); free(filename); free(databuf); return( false ); } ChangeLine2_8(_("Uploading font...")); rewind(from); while ((len = fread(databuf,1,datalen,from))>0 ) { if ( (len = write(data,databuf,len))<0 ) break; } ret = NULL; } ff_progress_end_indicator(); close( soc ); close( data ); free( databuf ); free( filename ); if ( len==-1 ) { ff_post_error(_("Could not transmit data"),_("Could not transmit data.") ); if ( ret!=NULL ) fclose(ret); return( false ); } return( true ); }
static FILE *HttpURLToTempFile(const char *url, void *_lock) { pthread_mutex_t *lock = _lock; struct sockaddr_in addr; char *pt, *host, *filename, *username, *password; int port; FILE *ret; char buffer[300]; int first, code; int soc; int datalen, len; char *databuf; snprintf(buffer,sizeof(buffer),_("Downloading from %s"), url); if ( strncasecmp(url,"http://",7)!=0 ) { if ( lock!=NULL ) pthread_mutex_lock(lock); ff_post_error(_("Could not parse URL"),_("Got something else when expecting an http URL")); if ( lock!=NULL ) pthread_mutex_unlock(lock); return( NULL ); } if ( lock!=NULL ) pthread_mutex_lock(lock); filename = decomposeURL(url, &host, &port, &username, &password); /* I don't support username/passwords for http */ free( username ); free( password ); if ( lock!=NULL ) pthread_mutex_unlock(lock); if ( lock==NULL ) { ff_progress_start_indicator(0,_("Font Download..."),buffer, _("Resolving host"),1,1); ff_progress_enable_stop(false); ff_progress_allow_events(); ff_progress_allow_events(); } /* This routine contains it's own lock */ if ( !findHTTPhost(&addr, host, port)) { if ( lock==NULL ) ff_progress_end_indicator(); else pthread_mutex_lock(lock); ff_post_error(_("Could not find host"),_("Could not find \"%s\"\nAre you connected to the internet?"), host ); free( host ); free( filename ); if ( lock!=NULL ) pthread_mutex_unlock(lock); return( false ); } soc = makeConnection(&addr); if ( soc==-1 ) { if ( lock==NULL ) ff_progress_end_indicator(); else pthread_mutex_lock(lock); ff_post_error(_("Could not connect to host"),_("Could not connect to \"%s\"."), host ); free( host ); free( filename ); if ( lock!=NULL ) pthread_mutex_unlock(lock); return( false ); } if ( lock!=NULL ) pthread_mutex_lock(lock); datalen = 8*8*1024; databuf = malloc(datalen+1); if ( lock!=NULL ) pthread_mutex_unlock(lock); else ChangeLine2_8(_("Requesting font...")); sprintf( databuf,"GET %s HTTP/1.1\r\n" "Host: %s\r\n" "User-Agent: FontForge\r\n" "Connection: close\r\n\r\n", filename, host ); if ( write(soc,databuf,strlen(databuf))==-1 ) { if ( lock==NULL ) ff_progress_end_indicator(); if ( lock!=NULL ) pthread_mutex_lock(lock); ff_post_error(_("Could not send request"),_("Could not send request to \"%s\"."), host ); close( soc ); free( databuf ); free( host ); free( filename ); free( host ); free( filename ); if ( lock!=NULL ) pthread_mutex_unlock(lock); return( NULL ); } if ( lock==NULL ) ChangeLine2_8(_("Downloading font...")); if ( lock!=NULL ) pthread_mutex_lock(lock); ret = tmpfile(); if ( lock!=NULL ) pthread_mutex_unlock(lock); first = 1; code = 404; while ((len = read(soc,databuf,datalen))>0 ) { if ( first ) { databuf[len] = '\0'; sscanf(databuf,"HTTP/%*f %d", &code ); first = 0; /* check for redirects */ if ( code>=300 && code<399 && (pt=strstr(databuf,"Location: "))!=NULL ) { char *newurl = pt + strlen("Location: "); pt = strchr(newurl,'\r'); if ( *pt ) *pt = '\0'; close( soc ); if ( lock!=NULL ) pthread_mutex_lock(lock); fclose(ret); free(host); free( filename ); free(databuf); if ( lock!=NULL ) pthread_mutex_unlock(lock); ret = URLToTempFile(newurl,lock); return( ret ); } pt = strstr(databuf,"Content-Length: "); if ( lock==NULL && pt!=NULL ) { pt += strlen( "Content-Length: "); ff_progress_change_total(strtol(pt,NULL,10)); } pt = strstr(databuf,"\r\n\r\n"); if ( pt!=NULL ) { pt += strlen("\r\n\r\n"); fwrite(pt,1,len-(pt-databuf),ret); if ( lock==NULL ) ff_progress_increment(len-(pt-databuf)); } } else { fwrite(databuf,1,len,ret); if ( lock==NULL ) ff_progress_increment(len); } } if ( lock==NULL ) ff_progress_end_indicator(); close( soc ); free( databuf ); if ( lock!=NULL ) pthread_mutex_lock(lock); free( host ); free( filename ); if ( len==-1 ) { ff_post_error(_("Could not download data"),_("Could not download data.") ); fclose(ret); ret = NULL; } else if ( code<200 || code>299 ) { ff_post_error(_("Could not download data"),_("HTTP return code: %d."), code ); fclose(ret); ret = NULL; } else rewind(ret); if ( lock!=NULL ) pthread_mutex_unlock(lock); return( ret ); }