Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
fontforge: support styleMap attribute as a subset of OS/2 fsSelection
  • Loading branch information
adrientetar committed Mar 19, 2015
1 parent e148b70 commit a9c48a6
Show file tree
Hide file tree
Showing 12 changed files with 188 additions and 22 deletions.
2 changes: 2 additions & 0 deletions fontforge/parsettf.c
Expand Up @@ -5098,6 +5098,8 @@ static void readttfos2metrics(FILE *ttf,struct ttfinfo *info) {
info->use_typo_metrics = (sel&128)?1:0;
info->weight_width_slope_only = (sel&256)?1:0;
}
/* Clear the bits we don't support in stylemap and set it. */
info->pfminfo.stylemap = sel & 0x0001100001;
/* firstchar */ getushort(ttf);
/* lastchar */ getushort(ttf);
info->pfminfo.os2_typoascent = getushort(ttf);
Expand Down
31 changes: 31 additions & 0 deletions fontforge/sfd.c
Expand Up @@ -2217,6 +2217,8 @@ int SFD_DumpSplineFontMetadata( FILE *sfd, SplineFont *sf )

if ( sf->version!=NULL )
fprintf(sfd, "Version: %s\n", sf->version );
if ( sf->styleMapFamilyName!=NULL )
fprintf(sfd, "StyleMapFamilyName: %s\n", sf->styleMapFamilyName );
if ( sf->fondname!=NULL )
fprintf(sfd, "FONDName: %s\n", sf->fondname );
if ( sf->defbasefilename!=NULL )
Expand Down Expand Up @@ -2274,6 +2276,8 @@ int SFD_DumpSplineFontMetadata( FILE *sfd, SplineFont *sf )
SFDDumpBase(sfd,"BaseHoriz:",sf->horiz_base);
if ( sf->vert_base!=NULL )
SFDDumpBase(sfd,"BaseVert:",sf->vert_base);
if ( sf->pfminfo.stylemap!=-1 )
fprintf(sfd, "StyleMap: 0x%04x\n", sf->pfminfo.stylemap );
if ( sf->pfminfo.fstype!=-1 )
fprintf(sfd, "FSType: %d\n", sf->pfminfo.fstype );
fprintf(sfd, "OS2Version: %d\n", sf->os2_version );
Expand Down Expand Up @@ -2320,7 +2324,9 @@ int SFD_DumpSplineFontMetadata( FILE *sfd, SplineFont *sf )
fprintf(sfd, "OS2StrikeYSize: %d\n", sf->pfminfo.os2_strikeysize );
fprintf(sfd, "OS2StrikeYPos: %d\n", sf->pfminfo.os2_strikeypos );
}
if ( sf->pfminfo.os2_capheight!=0 )
fprintf(sfd, "OS2CapHeight: %d\n", sf->pfminfo.os2_capheight );
if ( sf->pfminfo.os2_xheight!=0 )
fprintf(sfd, "OS2XHeight: %d\n", sf->pfminfo.os2_xheight );
if ( sf->pfminfo.os2_family_class!=0 )
fprintf(sfd, "OS2FamilyClass: %d\n", sf->pfminfo.os2_family_class );
Expand Down Expand Up @@ -7492,6 +7498,16 @@ bool SFD_GetFontMetaData( FILE *sfd,
geteol(sfd,val);
sf->version = copy(val);
}
else if ( strmatch(tok,"StyleMapFamilyName:")==0 )
{
sf->styleMapFamilyName = SFDReadUTF7Str(sfd);
}
/* Legacy attribute for StyleMapFamilyName. Deprecated. */
else if ( strmatch(tok,"OS2FamilyName:")==0 )
{
char* fname = SFDReadUTF7Str(sfd);
if (sf->styleMapFamilyName == NULL) sf->styleMapFamilyName = fname;
}
else if ( strmatch(tok,"FONDName:")==0 )
{
geteol(sfd,val);
Expand Down Expand Up @@ -7881,6 +7897,21 @@ bool SFD_GetFontMetaData( FILE *sfd,
d->last_base->scripts = bs;
d->last_base_script = bs;
}
else if ( strmatch(tok,"StyleMap:")==0 )
{
gethex(sfd,(uint32 *)&sf->pfminfo.stylemap);
}
/* Legacy attribute for StyleMap. Deprecated. */
else if ( strmatch(tok,"OS2StyleName:")==0 )
{
char* sname = SFDReadUTF7Str(sfd);
if (sf->pfminfo.stylemap == -1) {
if (sname == "bold italic") sf->pfminfo.stylemap = 0x21;
else if (sname == "bold") sf->pfminfo.stylemap = 0x20;
else if (sname == "italic") sf->pfminfo.stylemap = 0x01;
else if (sname == "regular") sf->pfminfo.stylemap = 0x40;
}
}
else if ( strmatch(tok,"FSType:")==0 )
{
getsint(sfd,&sf->pfminfo.fstype);
Expand Down
6 changes: 5 additions & 1 deletion fontforge/splinefont.h
Expand Up @@ -1725,6 +1725,10 @@ struct pfminfo { /* A misnomer now. OS/2 info would be more accurate, but that'
int16 weight;
int16 width;
char panose[10];
/* A subset of OS/2 fsSelection, used for style mapping. */
/* Must agree with macStyle per otspec, takes precedence. */
/* Can't use macStyle because it doesn't have a "regular" bit unlike the OS/2 component. */
int16 stylemap;
int16 fstype;
int16 linegap; /* from hhea */
int16 vlinegap; /* from vhea */
Expand Down Expand Up @@ -1930,7 +1934,7 @@ typedef struct splinefont {
char *woffMetadata;
real ufo_ascent, ufo_descent; /* I don't know what these mean, they don't seem to correspond to any other ascent/descent pair, but retain them so round-trip ufo input/output leaves them unchanged */
/* ufo_descent is negative */

char *styleMapFamilyName;
struct sfundoes *undoes;
char collab_uuid[ FF_UUID_STRING_SIZE ];
int preferred_kerning; // 1 for U. F. O. native, 2 for feature file, 0 undefined. Input functions shall flag 2, I think. This is now in S. F. D. in order to round-trip U. F. O. consistently.
Expand Down
1 change: 1 addition & 0 deletions fontforge/splineutil.c
Expand Up @@ -6467,6 +6467,7 @@ return;
free(sf->xuid);
free(sf->cidregistry);
free(sf->ordering);
if ( sf->styleMapFamilyName && sf->styleMapFamilyName[0]!='\0' ) { free(sf->styleMapFamilyName); sf->styleMapFamilyName = NULL; }
MacFeatListFree(sf->features);
/* We don't free the EncMap. That field is only a temporary pointer. Let the FontViewBase free it, that's where it really lives */
// TODO: But that doesn't always get freed. The statement below causes double-frees, so we need to come up with better conditions.
Expand Down
2 changes: 2 additions & 0 deletions fontforge/splineutil2.c
Expand Up @@ -3801,6 +3801,7 @@ SplineFont *SplineFontEmpty(void) {

sf = calloc(1,sizeof(SplineFont));
sf->pfminfo.fstype = -1;
sf->pfminfo.stylemap = -1;
sf->top_enc = -1;
sf->macstyle = -1;
sf->desired_row_cnt = default_fv_row_count; sf->desired_col_cnt = default_fv_col_count;
Expand Down Expand Up @@ -3867,6 +3868,7 @@ SplineFont *SplineFontBlank(int charcnt) {
sf->glyphmax = charcnt;
sf->glyphs = calloc(charcnt,sizeof(SplineChar *));
sf->pfminfo.fstype = -1;
sf->pfminfo.stylemap = -1;
sf->use_typo_metrics = true;
return( sf );
}
Expand Down
17 changes: 14 additions & 3 deletions fontforge/tottf.c
Expand Up @@ -3316,6 +3316,8 @@ static void WinBB(SplineFont *sf,uint16 *winascent,uint16 *windescent,struct all
*windescent = sf->pfminfo.os2_windescent;
}

static void redohead(struct alltabs *at);

static void setos2(struct os2 *os2,struct alltabs *at, SplineFont *sf,
enum fontformat format) {
int i,cnt1,cnt2,first,last,avg1,avg2,gid;
Expand Down Expand Up @@ -3353,11 +3355,20 @@ static void setos2(struct os2 *os2,struct alltabs *at, SplineFont *sf,
os2->ysupYOff = sf->pfminfo.os2_supyoff;
os2->yStrikeoutSize = sf->pfminfo.os2_strikeysize;
os2->yStrikeoutPos = sf->pfminfo.os2_strikeypos;
os2->fsSel = (at->head.macstyle&1?32:0)|(at->head.macstyle&2?1:0);
if ( sf->pfminfo.stylemap!=-1 ) {
int changed = 0;
os2->fsSel = sf->pfminfo.stylemap;
/* Make sure fsSel and macStyle don't contradict */
if (at->head.macstyle&1 && !(os2->fsSel&32)) {at->head.macstyle &= 1111110; changed=1;}
if (at->head.macstyle&2 && !(os2->fsSel&1)) {at->head.macstyle &= 1111101; changed=1;}
if (changed) redohead(at);
} else {
os2->fsSel = (at->head.macstyle&1?32:0)|(at->head.macstyle&2?1:0);
if ( os2->fsSel==0 && sf->pfminfo.weight==400 )
os2->fsSel = 64; /* Regular */
}
if ( sf->fullname!=NULL && strstrmatch(sf->fullname,"outline")!=NULL )
os2->fsSel |= 8;
if ( os2->fsSel==0 && sf->pfminfo.weight>=400 && sf->pfminfo.weight<=500 )
os2->fsSel = 64; /* Regular */
if ( os2->version>=4 ) {
if ( strstrmatch(sf->fontname,"Obli")!=NULL ) {
os2->fsSel &= ~1; /* Turn off Italic */
Expand Down
62 changes: 62 additions & 0 deletions fontforge/ufo.c
Expand Up @@ -912,6 +912,23 @@ static char* normalizeToASCII(char *str) {
return str;
}

static char* fetchTTFAttribute(const SplineFont *sf, int strid) {
char* value=NULL, nonenglish=NULL;
struct ttflangname *nm;

for ( nm=sf->names; nm!=NULL; nm=nm->next ) {
if ( nm->names[strid]!=NULL ) {
nonenglish = nm->names[strid];
if ( nm->lang == 0x409 ) {
value = nm->names[strid];
break;
}
}
}
if ( value==NULL ) value=nonenglish;
return value;
}

void PListAddString(xmlNodePtr parent, const char *key, const char *value) {
if ( value==NULL ) value = "";
xmlNodePtr keynode = xmlNewChild(parent, NULL, BAD_CAST "key", BAD_CAST key); // "<key>%s</key>" key
Expand Down Expand Up @@ -1086,6 +1103,38 @@ static int UFOOutputFontInfo(const char *basedir, SplineFont *sf, int layer) {
/* Same keys in both formats */
PListAddString(dictnode,"familyName",sf->familyname_with_timestamp ? sf->familyname_with_timestamp : sf->familyname);
PListAddString(dictnode,"styleName",SFGetModifiers(sf));
{
char* preferredFamilyName = fetchTTFAttribute(sf,ttf_preffamilyname);
char* preferredSubfamilyName = fetchTTFAttribute(sf,ttf_prefmodifiers);
char* styleMapFamily;
if (sf->styleMapFamilyName != NULL) {
/* Empty styleMapStyleName means we imported a UFO that does not have this field. Bypass the fallback. */
if (sf->styleMapFamilyName[0]!='\0')
styleMapFamily = sf->styleMapFamilyName;
} else if (preferredFamilyName != NULL && preferredSubfamilyName != NULL) {
styleMapFamily = malloc(strlen(preferredFamilyName)+strlen(preferredSubfamilyName)+2);
strcpy(styleMapFamily, preferredFamilyName);
strcat(styleMapFamily, " ");
strcat(styleMapFamily, preferredSubfamilyName);
} else if (sf->fullname != NULL) styleMapFamily = sf->fullname;
if (styleMapFamily != NULL) PListAddString(dictnode,"styleMapFamilyName", styleMapFamily);
}
{
char* styleMapName = NULL;
if (sf->pfminfo.stylemap != -1) {
if (sf->pfminfo.stylemap == 0x21) styleMapName = "bold italic";
else if (sf->pfminfo.stylemap == 0x20) styleMapName = "bold";
else if (sf->pfminfo.stylemap == 0x01) styleMapName = "italic";
else if (sf->pfminfo.stylemap == 0x40) styleMapName = "regular";
} else {
/* Figure out styleMapStyleName automatically. */
if (sf->pfminfo.weight == 700 && sf->italicangle < 0) styleMapName = "bold italic";
else if (sf->italicangle < 0) styleMapName = "italic";
else if (sf->pfminfo.weight == 700) styleMapName = "bold";
else if (sf->pfminfo.weight == 400) styleMapName = "regular";
}
if (styleMapName != NULL) PListAddString(dictnode,"styleMapStyleName", styleMapName);
}
{
// We attempt to get numeric major and minor versions for U. F. O. out of the FontForge version string.
int versionMajor = -1;
Expand Down Expand Up @@ -3680,6 +3729,8 @@ return( NULL );
sf->pfminfo.pfmset = 1; // We flag the pfminfo as present since we expect the U. F. O. to set any desired values.
int versionMajor = -1; // These are not native SplineFont values.
int versionMinor = -1; // We store the U. F. O. values and then process them at the end.
sf->styleMapFamilyName = ""; // Empty default to disable fallback at export (not user-accessible anyway as of now).
sf->pfminfo.stylemap = 0x0;

temp = buildname(basedir,"fontinfo.plist");
doc = xmlParseFile(temp);
Expand Down Expand Up @@ -3711,6 +3762,17 @@ return( NULL );
if (stylename == NULL) stylename = (char *) valname;
else free(valname);
}
else if ( xmlStrcmp(keyname,(xmlChar *) "styleMapFamilyName")==0 ) {
if (sf->styleMapFamilyName == NULL) sf->styleMapFamilyName = (char *) valname;
else free(valname);
}
else if ( xmlStrcmp(keyname,(xmlChar *) "styleMapStyleName")==0 ) {
if ((char *) valname == "regular") sf->pfminfo.stylemap = 0x40;
else if ((char *) valname == "italic") sf->pfminfo.stylemap = 0x01;
else if ((char *) valname == "bold") sf->pfminfo.stylemap = 0x20;
else if ((char *) valname == "bold italic") sf->pfminfo.stylemap = 0x21;
free(valname);
}
else if ( xmlStrcmp(keyname,(xmlChar *) "fullName")==0 ||
xmlStrcmp(keyname,(xmlChar *) "postscriptFullName")==0 ) {
if (sf->fullname == NULL) sf->fullname = (char *) valname;
Expand Down
2 changes: 2 additions & 0 deletions fontforgeexe/cvstroke.c
Expand Up @@ -527,6 +527,7 @@ static void StrokeInit(StrokeDlg *sd) {
sd->dummy_sf.glyphs = sd->chars;
sd->dummy_sf.glyphcnt = sd->dummy_sf.glyphmax = 1;
sd->dummy_sf.pfminfo.fstype = -1;
sd->dummy_sf.pfminfo.stylemap = -1;
sd->dummy_sf.fontname = sd->dummy_sf.fullname = sd->dummy_sf.familyname = "dummy";
sd->dummy_sf.weight = "Medium";
sd->dummy_sf.origname = "dummy";
Expand Down Expand Up @@ -1357,6 +1358,7 @@ static void GDDInit(GradientDlg *gdd,SplineFont *sf,Layer *ly,struct gradient *g
gdd->dummy_sf.glyphs = gdd->chars;
gdd->dummy_sf.glyphcnt = gdd->dummy_sf.glyphmax = 1;
gdd->dummy_sf.pfminfo.fstype = -1;
gdd->dummy_sf.pfminfo.stylemap = -1;
gdd->dummy_sf.fontname = gdd->dummy_sf.fullname = gdd->dummy_sf.familyname = "dummy";
gdd->dummy_sf.weight = "Medium";
gdd->dummy_sf.origname = "dummy";
Expand Down

0 comments on commit a9c48a6

Please sign in to comment.