|
View:
New views
1 Messages
—
Rating Filter:
Alert me
|
|
|
UFO patches last submissionDear All,
OK, I think I've finished hacking at ufo.c. I enclose 2 patches that replace the previous patches I sent. ufo_fix.patch should be applied first and fixes a few missing metrics, fixes some UFO names and sorts out things like unicoderanges and panose. This brings the input and output of fontinfo.xml in the ufo dir to be in line with what is generated by the current version of RoboFab. The second patch: ufo_anchor.patch should be applied after ufo_fix.patch and does the anchor point trickery. I don't really like this solution because it's really hard to switch an anchor class from one lookup to another (is it even possible?) and some of the anchors which are defaulted to basechar should really be basemark or even baselig. Perhaps these can be sorted out with some python. Anyway it's a first start and round tripping anchor points via UFO is very important to me. Yours, Martin [ufo_anchor.patch] diff -r ae285801e2d0 fontforge/ufo.c --- a/fontforge/ufo.c Wed Sep 16 07:45:47 2009 +0000 +++ b/fontforge/ufo.c Sat Oct 10 11:26:03 2009 +0700 @@ -223,6 +223,7 @@ SplinePoint *sp; RefChar *ref; int err; + AnchorPoint *ap; if ( glif==NULL ) return( false ); @@ -258,6 +259,16 @@ fprintf( glif, " yOffset=\"%g\"", (double) ref->transform[5] ); fprintf( glif, "/>\n" ); } + for ( ap = sc->anchor; ap!=NULL; ap=ap->next ) { + fprintf( glif, " <contour>\n" ); + if ( ap->type==at_mark ) + fprintf( glif, " <point x=\"%g\" y=\"%g\" type\"move\" name=\"_%s\"/>\n", + (double) ap->me.x, (double) ap->me.y, ap->anchor->name ); + else + fprintf( glif, " <point x=\"%g\" y=\"%g\" type\"move\" name=\"%s\"/>\n", + (double) ap->me.x, (double) ap->me.y, ap->anchor->name ); + fprintf( glif, " </contour>\n" ); + } for ( spl=sc->layers[layer].splines; spl!=NULL; spl=spl->next ) { fprintf( glif, " <contour>\n" ); for ( sp=spl->first; sp!=NULL; ) { @@ -1127,7 +1138,46 @@ return( head ); } -static SplineChar *_UFOLoadGlyph(xmlDocPtr doc,char *glifname) { +static AnchorClass *UFOGetAnchorClass(char *name,SplineFont *sf) { + struct lookup_subtable *sub; + AnchorClass *ac; + OTLookup *otl; + + if ( sf==NULL ) + return( NULL ); + for ( ac = sf->anchor; ac!=NULL && strcmp(ac->name,name)!=0; ac = ac->next); + if ( ac!=NULL ) + return( ac ); + for ( otl = sf->gpos_lookups; otl!=NULL && strcmp(otl->lookup_name,"_holdAnchors")!=0; otl = otl->next); + if ( otl==NULL ) { + otl = chunkalloc(sizeof(OTLookup)); + otl->lookup_name=galloc(13); + strcpy(otl->lookup_name,"_holdAnchors"); + otl->lookup_type = gpos_mark2base; + otl->next = sf->gpos_lookups; + sf->gpos_lookups = otl; + } + for ( sub = otl->subtables; sub!=NULL && strcmp(sub->subtable_name,"_someAnchors")!=0; sub = sub->next); + if ( sub==NULL ) { + sub = chunkalloc(sizeof(struct lookup_subtable)); + sub->subtable_name=galloc(14); + strcpy(sub->subtable_name,"_someAnchors"); + sub->anchor_classes = true; + sub->lookup = otl; + sub->next = otl->subtables; + otl->subtables = sub; + } + ac = chunkalloc(sizeof(AnchorClass)); + ac->name = galloc(strlen(name)+1); + strcpy(ac->name,name); + ac->subtable = sub; + ac->type = act_mark; + ac->next = sf->anchor; + sf->anchor = ac; + return( ac ); +} + +static SplineChar *_UFOLoadGlyph(xmlDocPtr doc,char *glifname,SplineFont *sf) { xmlNodePtr glyph, kids, contour, points; SplineChar *sc; xmlChar *format, *width, *height, *u; @@ -1223,7 +1273,7 @@ ss = chunkalloc(sizeof(SplineSet)); for ( points = contour->children; points!=NULL; points=points->next ) { - char *xs, *ys, *type; + char *xs, *ys, *type, *name; double x,y; if ( _xmlStrcmp(points->name,(const xmlChar *) "point")!=0 ) continue; @@ -1233,10 +1283,29 @@ if ( xs==NULL || ys == NULL ) continue; x = strtod(xs,NULL); y = strtod(ys,NULL); - if ( type!=NULL && (strcmp(type,"move")==0 || + name = _xmlGetProp(points,(xmlChar *) "name"); + /* test for anchor points */ + if ( name!=NULL && strcmp(type,"move")==0 ) { + AnchorPoint *ap = chunkalloc(sizeof(AnchorPoint)); + if (name[0] == '_') { + ap->type = at_mark; + ap->anchor = UFOGetAnchorClass(name+1,sf); + ap->anchor->has_mark = true; + } else { + ap->type = at_basechar; + ap->anchor = UFOGetAnchorClass(name,sf); + ap->anchor->has_base = true; + } + ap->me.x = x; + ap->me.y = y; + ap->next = sc->anchor; + sc->anchor = ap; + open = true; + continue; + } else if ( type!=NULL && (strcmp(type,"move")==0 || strcmp(type,"line")==0 || strcmp(type,"curve")==0 || strcmp(type,"qcurve")==0 )) { sp = SplinePointCreate(x,y); if ( strcmp(type,"move")==0 ) { open = true; @@ -1356,11 +1425,13 @@ SplineMake(ss->last,ss->first,wasquad); ss->last = ss->first; } - if ( last==NULL ) - sc->layers[ly_fore].splines = ss; - else - last->next = ss; - last = ss; + if ( ss->first!=NULL) { + if ( last==NULL ) + sc->layers[ly_fore].splines = ss; + else + last->next = ss; + last = ss; + } } } } else if ( _xmlStrcmp(kids->name,(const xmlChar *) "lib")==0 ) { @@ -1397,7 +1468,7 @@ return( sc ); } -static SplineChar *UFOLoadGlyph(char *glifname) { +static SplineChar *UFOLoadGlyph(char *glifname,SplineFont *sf) { xmlDocPtr doc; doc = _xmlParseFile(glifname); @@ -1405,7 +1476,7 @@ LogError( _("Bad glif file %s\n" ), glifname); return( NULL ); } -return( _UFOLoadGlyph(doc,glifname)); +return( _UFOLoadGlyph(doc,glifname,sf)); } @@ -1473,7 +1544,7 @@ valname = (char *) _xmlNodeListGetString(doc,value->children,true); glyphfname = buildname(glyphdir,valname); free(valname); - sc = UFOLoadGlyph(glyphfname); + sc = UFOLoadGlyph(glyphfname,sf); if ( sc!=NULL ) { sc->parent = sf; if ( sf->glyphcnt>=sf->glyphmax ) @@ -2018,7 +2089,7 @@ return( NULL ); oldloc = setlocale(LC_NUMERIC,"C"); - sc = _UFOLoadGlyph(doc,filename); + sc = _UFOLoadGlyph(doc,filename,NULL); setlocale(LC_NUMERIC,oldloc); if ( sc==NULL ) [ufo_fix.patch] diff -r ae285801e2d0 fontforge/ufo.c --- a/fontforge/ufo.c Wed Sep 16 07:45:47 2009 +0000 +++ b/fontforge/ufo.c Sat Oct 10 11:26:03 2009 +0700 @@ -561,13 +561,13 @@ PListOutputInteger(plist,"openTypeOS2TypoDescender",sf->pfminfo.os2_typodescent); PListOutputInteger(plist,"openTypeOS2TypoLineGap",sf->pfminfo.os2_typolinegap); if ( sf->pfminfo.winascent_add ) - PListOutputInteger(plist,"openTypeOS2WinAscender",bb.maxy+sf->pfminfo.os2_winascent); + PListOutputInteger(plist,"openTypeOS2WinAscent",bb.maxy+sf->pfminfo.os2_winascent); else - PListOutputInteger(plist,"openTypeOS2WinAscender",sf->pfminfo.os2_winascent); + PListOutputInteger(plist,"openTypeOS2WinAscent",sf->pfminfo.os2_winascent); if ( sf->pfminfo.windescent_add ) - PListOutputInteger(plist,"openTypeOS2WinDescender",bb.miny+sf->pfminfo.os2_windescent); + PListOutputInteger(plist,"openTypeOS2WinDescent",bb.miny+sf->pfminfo.os2_windescent); else - PListOutputInteger(plist,"openTypeOS2WinDescender",sf->pfminfo.os2_windescent); + PListOutputInteger(plist,"openTypeOS2WinDescent",sf->pfminfo.os2_windescent); } if ( sf->pfminfo.subsuper_set ) { PListOutputInteger(plist,"openTypeOS2SubscriptXSize",sf->pfminfo.os2_subxsize); @@ -583,6 +583,28 @@ } if ( sf->pfminfo.vheadset ) PListOutputInteger(plist,"openTypeVheaTypoLineGap",sf->pfminfo.vlinegap); + if ( sf->pfminfo.hasunicoderanges ) { + char ranges[128]; + int i, j, c = 0; + + for ( i = 0; i<4; i++ ) + for ( j = 0; j<32; j++ ) + if ( sf->pfminfo.unicoderanges[i] & (1 << j) ) + ranges[c++] = i*32+j; + if ( c!=0 ) + PListOutputIntArray(plist,"openTypeOS2UnicodeRanges",ranges,c); + } + if ( sf->pfminfo.hascodepages ) { + char pages[64]; + int i, j, c = 0; + + for ( i = 0; i<2; i++) + for ( j=0; j<32; j++ ) + if ( sf->pfminfo.codepages[i] & (1 << j) ) + pages[c++] = i*32+j; + if ( c!=0 ) + PListOutputIntArray(plist,"openTypeOS2CodePageRanges",pages,c); + } PListOutputString(plist,"postscriptFontName",sf->fontname); PListOutputString(plist,"postscriptFullName",sf->fullname); PListOutputString(plist,"postscriptWeightName",sf->weight); @@ -1614,7 +1636,7 @@ if ( _xmlStrcmp(kid->name,(const xmlChar *) "integer")==0 ) { char *valName = (char *) _xmlNodeListGetString(doc,kid->children,true); if ( i<cnt ) - array[i] = strtol(valName,NULL,10); + array[i++] = strtol(valName,NULL,10); free(valName); } } @@ -1636,6 +1658,23 @@ return( mask ); } +static void UFOGetBitArray(xmlDocPtr doc,xmlNodePtr value,uint32 *res,int len) { + xmlNodePtr kid; + int index; + + if ( _xmlStrcmp(value->name,(const xmlChar *) "array")!=0 ) +return; + for ( kid = value->children; kid!=NULL; kid=kid->next ) { + if ( _xmlStrcmp(kid->name,(const xmlChar *) "integer")==0 ) { + char *valName = (char *) _xmlNodeListGetString(doc,kid->children,true); + index = strtol(valName,NULL,10); + if ( index < len<<5 ) + res[index>>5] |= 1<<(index&31); + free(valName); + } + } +} + SplineFont *SFReadUFO(char *basedir, int flags) { xmlNodePtr plist, dict, keys, value; xmlDocPtr doc; @@ -1739,11 +1778,13 @@ else free(valname); } else if ( strncmp((char *) keyname, "openTypeHhea",12)==0 ) { - if ( _xmlStrcmp(keyname+12,(xmlChar *) "Ascender")==0 ) + if ( _xmlStrcmp(keyname+12,(xmlChar *) "Ascender")==0 ) { sf->pfminfo.hhead_ascent = strtol((char *) valname,&end,10); - else if ( _xmlStrcmp(keyname+12,(xmlChar *) "Descender")==0 ) + sf->pfminfo.hheadascent_add = false; + } else if ( _xmlStrcmp(keyname+12,(xmlChar *) "Descender")==0 ) { sf->pfminfo.hhead_descent = strtol((char *) valname,&end,10); - else if ( _xmlStrcmp(keyname+12,(xmlChar *) "LineGap")==0 ) + sf->pfminfo.hheaddescent_add = false; + } else if ( _xmlStrcmp(keyname+12,(xmlChar *) "LineGap")==0 ) sf->pfminfo.linegap = strtol((char *) valname,&end,10); free(valname); sf->pfminfo.hheadset = true; @@ -1754,9 +1795,10 @@ free(valname); } else if ( strncmp((char *) keyname,"openTypeOS2",11)==0 ) { sf->pfminfo.pfmset = true; - if ( _xmlStrcmp(keyname+11,(xmlChar *) "Panose")==0 ) + if ( _xmlStrcmp(keyname+11,(xmlChar *) "Panose")==0 ) { UFOGetByteArray(sf->pfminfo.panose,sizeof(sf->pfminfo.panose),doc,value); - else if ( _xmlStrcmp(keyname+11,(xmlChar *) "Type")==0 ) + sf->pfminfo.panose_set = true; + } else if ( _xmlStrcmp(keyname+11,(xmlChar *) "Type")==0 ) sf->pfminfo.fstype = UFOGetBits(doc,value); else if ( _xmlStrcmp(keyname+11,(xmlChar *) "FamilyClass")==0 ) { char fc[2]; @@ -1766,19 +1808,25 @@ sf->pfminfo.width = strtol((char *) valname,&end,10); else if ( _xmlStrcmp(keyname+11,(xmlChar *) "WeightClass")==0 ) sf->pfminfo.weight = strtol((char *) valname,&end,10); - else if ( _xmlStrcmp(keyname+11,(xmlChar *) "VendorID")==0 ) - memcpy(sf->pfminfo.os2_vendor,valname,4); - else if ( _xmlStrcmp(keyname+11,(xmlChar *) "TypoAscender")==0 ) + else if ( _xmlStrcmp(keyname+11,(xmlChar *) "VendorID")==0 ) { + char *temp = sf->pfminfo.os2_vendor + 3; + strncpy(sf->pfminfo.os2_vendor,valname,4); + while ( *temp == 0 && temp >= sf->pfminfo.os2_vendor ) *temp-- = ' '; + } else if ( _xmlStrcmp(keyname+11,(xmlChar *) "TypoAscender")==0 ) { + sf->pfminfo.typoascent_add = false; sf->pfminfo.os2_typoascent = strtol((char *) valname,&end,10); - else if ( _xmlStrcmp(keyname+11,(xmlChar *) "TypoDescender")==0 ) + } else if ( _xmlStrcmp(keyname+11,(xmlChar *) "TypoDescender")==0 ) { + sf->pfminfo.typodescent_add = false; sf->pfminfo.os2_typodescent = strtol((char *) valname,&end,10); - else if ( _xmlStrcmp(keyname+11,(xmlChar *) "TypoLineGap")==0 ) + } else if ( _xmlStrcmp(keyname+11,(xmlChar *) "TypoLineGap")==0 ) sf->pfminfo.os2_typolinegap = strtol((char *) valname,&end,10); - else if ( _xmlStrcmp(keyname+11,(xmlChar *) "WinAscender")==0 ) + else if ( _xmlStrcmp(keyname+11,(xmlChar *) "WinAscent")==0 ) { + sf->pfminfo.winascent_add = false; sf->pfminfo.os2_winascent = strtol((char *) valname,&end,10); - else if ( _xmlStrcmp(keyname+11,(xmlChar *) "WinDescender")==0 ) + } else if ( _xmlStrcmp(keyname+11,(xmlChar *) "WinDescent")==0 ) { + sf->pfminfo.windescent_add = false; sf->pfminfo.os2_windescent = strtol((char *) valname,&end,10); - else if ( strncmp((char *) keyname+11,"Subscript",9)==0 ) { + } else if ( strncmp((char *) keyname+11,"Subscript",9)==0 ) { sf->pfminfo.subsuper_set = true; if ( _xmlStrcmp(keyname+20,(xmlChar *) "XSize")==0 ) sf->pfminfo.os2_subxsize = strtol((char *) valname,&end,10); @@ -1804,6 +1852,12 @@ sf->pfminfo.os2_strikeysize = strtol((char *) valname,&end,10); else if ( _xmlStrcmp(keyname+20,(xmlChar *) "Position")==0 ) sf->pfminfo.os2_strikeypos = strtol((char *) valname,&end,10); + } else if ( strncmp((char *) keyname+11, "CodePageRanges",14)==0 ) { + UFOGetBitArray(doc,value,sf->pfminfo.codepages,2); + sf->pfminfo.hascodepages = true; + } else if ( strncmp((char *) keyname+11, "UnicodeRanges",13)==0 ) { + UFOGetBitArray(doc,value,sf->pfminfo.unicoderanges,4); + sf->pfminfo.hasunicoderanges = true; } free(valname); } else if ( strncmp((char *) keyname, "postscript",10)==0 ) { ------------------------------------------------------------------------------ Come build with us! The BlackBerry(R) Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9 - 12, 2009. Register now! http://p.sf.net/sfu/devconference _______________________________________________ Fontforge-devel mailing list Fontforge-devel@... https://lists.sourceforge.net/lists/listinfo/fontforge-devel |
| Free embeddable forum powered by Nabble | Forum Help |