Пример #1
0
real SFGuessItalicAngle(SplineFont *sf) {
    static const char *easyserif = "IBDEFHKLNPR";
    int i,si;
    real as, topx, bottomx;
    DBounds bb;
    double angle;

    for ( i=0; easyserif[i]!='\0'; ++i )
	if ( (si=SFFindExistingSlot(sf,easyserif[i],NULL))!=-1 && sf->glyphs[si]!=NULL )
    break;
    if ( easyserif[i]=='\0' )		/* can't guess */
return( 0 );

    SplineCharFindBounds(sf->glyphs[si],&bb);
    as = bb.maxy-bb.miny;

    topx = SCFindMinXAtY(sf->glyphs[si],ly_fore,2*as/3+bb.miny);
    bottomx = SCFindMinXAtY(sf->glyphs[si],ly_fore,as/3+bb.miny);
    if ( topx==bottomx )
return( 0 );

    angle = atan2(as/3,topx-bottomx)*180/3.1415926535897932-90;
    if ( angle<1 && angle>-1 ) angle = 0;
return( angle );
}
Пример #2
0
SplineChar *SCBuildDummy(SplineChar *dummy,SplineFont *sf,EncMap *map,int i) {
    static char namebuf[100];
    static Layer layers[2];

    memset(dummy,'\0',sizeof(*dummy));
    dummy->color = COLOR_DEFAULT;
    dummy->layer_cnt = 2;
    dummy->layers = layers;
    if ( sf->cidmaster!=NULL ) {
	/* CID fonts don't have encodings, instead we must look up the cid */
	if ( sf->cidmaster->loading_cid_map )
	    dummy->unicodeenc = -1;
	else
	    dummy->unicodeenc = CID2NameUni(FindCidMap(sf->cidmaster->cidregistry,sf->cidmaster->ordering,sf->cidmaster->supplement,sf->cidmaster),
		    i,namebuf,sizeof(namebuf));
    } else
	dummy->unicodeenc = UniFromEnc(i,map->enc);

    if ( sf->cidmaster!=NULL )
	dummy->name = namebuf;
    else if ( map->enc->psnames!=NULL && i<map->enc->char_cnt &&
	    map->enc->psnames[i]!=NULL )
	dummy->name = map->enc->psnames[i];
    else if ( dummy->unicodeenc==-1 )
	dummy->name = NULL;
    else
	dummy->name = (char *) StdGlyphName(namebuf,dummy->unicodeenc,sf->uni_interp,sf->for_new_glyphs);
    if ( dummy->name==NULL ) {
	/*if ( dummy->unicodeenc!=-1 || i<256 )
	    dummy->name = ".notdef";
	else*/ {
	    int j;
	    sprintf( namebuf, "NameMe.%d", i);
	    j=0;
	    while ( SFFindExistingSlot(sf,-1,namebuf)!=-1 )
		sprintf( namebuf, "NameMe.%d.%d", i, ++j);
	    dummy->name = namebuf;
	}
    }
    dummy->width = dummy->vwidth = sf->ascent+sf->descent;
    if ( dummy->unicodeenc>0 && dummy->unicodeenc<0x10000 &&
	    iscombining(dummy->unicodeenc)) {
	/* Mark characters should be 0 width */
	dummy->width = 0;
	/* Except in monospaced fonts on windows, where they should be the */
	/*  same width as everything else */
    }
    /* Actually, in a monospace font, all glyphs should be the same width */
    /*  whether mark or not */
    if ( sf->pfminfo.panose_set && sf->pfminfo.panose[3]==9 &&
	    sf->glyphcnt>0 ) {
	for ( i=sf->glyphcnt-1; i>=0; --i )
	    if ( SCWorthOutputting(sf->glyphs[i])) {
		dummy->width = sf->glyphs[i]->width;
	break;
	    }
    }
    dummy->parent = sf;
    dummy->orig_pos = 0xffff;
return( dummy );
}
Пример #3
0
static int figurekernsets(WidthInfo *wi,struct kernsets *ks) {
    int i,j,k;
    unsigned cnt,lcnt,max;
    unichar_t *ch2s;
    unichar_t *cpt, *upt;
    struct charpair *cp;
    SplineFont *sf = wi->sf;

    if ( ks->cur==0 )
return( false );

    wi->left = malloc((ks->cur+1)*sizeof(struct charone *));
    for ( i=cnt=0; i<ks->cur; ++i ) {
	j = SFFindExistingSlot(sf,ks->ch1[i],NULL);
	if ( j!=-1 && sf->glyphs[j]!=NULL &&
		(sf->glyphs[j]->layers[wi->layer].splines!=NULL || sf->glyphs[j]->layers[wi->layer].refs!=NULL ))
	    wi->left[cnt++] = AW_MakeCharOne(sf->glyphs[j]);
	else
	    ks->ch1[i] = '\0';
    }
    wi->lcnt = cnt;
    wi->left[cnt] = NULL;
    if ( cnt==0 ) {
	free(wi->left); wi->left = NULL;
return( false );
    }

    for ( i=max=0; i<ks->cur; ++i )
	if ( ks->ch1[i]!='\0' )
	    max += u_strlen(ks->ch2s[i]);
    ch2s = malloc((max+1)*sizeof(unichar_t));
    for ( i=0; i<ks->cur && ks->ch1[i]=='\0'; ++i );
    u_strcpy(ch2s,ks->ch2s[i]);
    for ( ++i; i<ks->cur; ++i ) if ( ks->ch1[i]!='\0' ) {
	for ( upt=ks->ch2s[i]; *upt!='\0'; ++upt ) {
	    for ( cpt = ch2s; *cpt!='\0' && *upt<*cpt; ++cpt );
	    if ( *cpt==*upt )	/* already listed */
	continue;
	    for ( k=u_strlen(cpt)+1; k>0; --k )
		cpt[k] = cpt[k-1];
	    *cpt = *upt;
	}
    }

    wi->right = malloc((u_strlen(ch2s)+1)*sizeof(struct charone *));
    for ( cnt=0,cpt=ch2s; *cpt ; ++cpt ) {
	j = SFFindExistingSlot(sf,*cpt,NULL);
	if ( j!=-1 && sf->glyphs[j]!=NULL &&
		(sf->glyphs[j]->layers[wi->layer].splines!=NULL || sf->glyphs[j]->layers[wi->layer].refs!=NULL ))
	    wi->right[cnt++] = AW_MakeCharOne(sf->glyphs[j]);
    }
    wi->rcnt = cnt;
    wi->right[cnt] = NULL;
    free( ch2s );
    if ( cnt==0 ) {
	free(wi->left); wi->left = NULL;
	free(wi->right); wi->right = NULL;
return( false );
    }
    AW_ScriptSerifChecker(wi);

    wi->pairs = malloc(max*sizeof(struct charpair *));
    for ( i=lcnt=cnt=0; i<ks->cur; ++i ) if ( ks->ch1[i]!='\0' ) {
	for ( cpt=ks->ch2s[i]; *cpt; ++cpt ) {
	    for ( j=0; j<wi->rcnt && (unichar_t)wi->right[j]->sc->unicodeenc!=*cpt; ++j );
	    if ( j<wi->rcnt ) {
		wi->pairs[cnt++] = cp = calloc(1,sizeof(struct charpair));
		cp->left = wi->left[lcnt];
		cp->right = wi->right[j];
		cp->nextasleft = cp->left->asleft;
		cp->left->asleft = cp;
		cp->nextasright = cp->right->asright;
		cp->right->asright = cp;
	    }
	}
	++lcnt;
    }
    wi->pcnt = cnt;
return( true );
}
Пример #4
0
void AW_FindFontParameters(WidthInfo *wi) {
    DBounds bb;
    SplineFont *sf=wi->sf;
    unsigned i, j;
    int si=-1;
    real caph, ds, xh, serifsize, angle, ca, seriflength = 0;
    int cnt;
    static unichar_t caps[] = { 'A', 'Z', 0x391, 0x3a9, 0x40f, 0x418, 0x41a, 0x42f, 0 };
    static unichar_t descent[] = { 'p','q','g','y','j',
	    0x3c8, 0x3b7, 0x3b3, 0x3b2, 0x3b6, 0x3bc, 0x3be, 0x3c1, 0x3c6,
	    0x444, 0x443, 0x458, 0x434, 0 };
    static unichar_t xheight[] = { 'x','u','v','w','y','z',
	    0x3b3, 0x3b9, 0x3ba, 0x3bc, 0x3bd, 0x3c0, 0x3c4, 0x3c5, 0x3c7, 0x3c8,
	    0x432, 0x433, 0x436, 0x438, 0x43a, 0x43d, 0x43f, 0x442, 0x443, 0x445,
	    0x446, 0x447, 0x448, 0x449, 0 };
    static unichar_t easyserif[] = { 'I','B','D','E','F','H','K','L','N','P','R',
	    0x399, 0x406, 0x392, 0x393, 0x395, 0x397, 0x39a,
	    0x3a0, 0x3a1, 0x40a, 0x412, 0x413, 0x415, 0x41a, 0x41d, 0x41f,
	    0x420, 0x428, 0 };
    real stemx, testx, y, ytop, ybottom, yorig, topx, bottomx;

    caph = 0; cnt = 0;
    for ( i=0; caps[i]!='\0' && cnt<5; i+=2 )
	for ( j=caps[i]; j<=caps[i+1] && cnt<5; ++j )
	    if ( (si=SFFindExistingSlot(sf,j,NULL))!=-1 && sf->glyphs[si]!=NULL ) {
		SplineCharQuickBounds(sf->glyphs[si],&bb);
		caph += bb.maxy;
		++cnt;
	    }
    if ( cnt!=0 )
	caph /= cnt;
    else
	caph = sf->ascent;

    for ( i=0; descent[i]!='\0'; ++i )
	if ( (si=SFFindExistingSlot(sf,descent[i],NULL))!=-1 && sf->glyphs[si]!=NULL )
    break;
    if ( descent[i]!='\0' ) {
	SplineCharQuickBounds(sf->glyphs[si],&bb);
	ds = bb.miny;
    } else
	ds = -sf->descent;

    cnt = 0; xh = 0;
    for ( i=0; xheight[i]!='\0' && cnt<5; ++i )
	if ( (si=SFFindExistingSlot(sf,xheight[i],NULL))!=-1 && sf->glyphs[si]!=NULL ) {
	    SplineCharQuickBounds(sf->glyphs[si],&bb);
	    xh += bb.maxy;
	    ++cnt;
	}
    if ( cnt!=0 )
	xh /= cnt;
    else
	xh = 3*caph/4;

    for ( i=0; easyserif[i]!='\0'; ++i )
	if ( (si=SFFindExistingSlot(sf,easyserif[i],NULL))!=-1 && sf->glyphs[si]!=NULL )
    break;
    if ( si!=-1 ) {
	topx = SCFindMinXAtY(sf->glyphs[si],wi->layer,2*caph/3);
	bottomx = SCFindMinXAtY(sf->glyphs[si],wi->layer,caph/3);
	/* Some fonts don't sit on the baseline... */
	SplineCharQuickBounds(sf->glyphs[si],&bb);
	/* beware of slanted (italic, oblique) fonts */
	ytop = caph/2; ybottom=bb.miny;
	stemx = SCFindMinXAtY(sf->glyphs[si],wi->layer,ytop);
	if ( topx==bottomx ) {
	    ca = 0;
	    yorig = 0;	/* Irrelevant because we will multiply it by 0, but makes gcc happy */
	    while ( ytop-ybottom>=.5 ) {
		y = (ytop+ybottom)/2;
		testx = SCFindMinXAtY(sf->glyphs[si],wi->layer,y);
		if ( testx+1>=stemx )
		    ytop = y;
		else
		    ybottom = y;
	    }
	} else {
	    angle = atan2(caph/3,topx-bottomx);
	    ca = cos(angle);
	    yorig = ytop;
	    while ( ytop-ybottom>=.5 ) {
		y = (ytop+ybottom)/2;
		testx = SCFindMinXAtY(sf->glyphs[si],wi->layer,y)+
		    (yorig-y)*ca;
		if ( testx+4>=stemx )		/* the +4 is to counteract rounding */
		    ytop = y;
		else
		    ybottom = y;
	    }
	}
	/* If "I" has a curved stem then it's probably in a script style and */
	/*  serifs don't really make sense (or not the simplistic ones I deal with) */
	if ( ytop<=bb.miny+.5 || SCIsMinXAtYCurved(sf->glyphs[si],wi->layer,caph/2) )
	    serifsize = 0;
	else if ( ytop>caph/4 )
	    serifsize = /*.06*(sf->ascent+sf->descent)*/ 0;
	else
	    serifsize = ytop-bb.miny;

	if ( serifsize!=0 ) {
	    y = serifsize/4 + bb.miny;
	    testx = SCFindMinXAtY(sf->glyphs[si],wi->layer,y);
	    if ( testx==NOTREACHED )
		serifsize=0;
	    else {
		testx += (yorig-y)*ca;
		seriflength = stemx-testx;
		if ( seriflength < (sf->ascent+sf->descent)/200 )
		    serifsize = 0;
	    }
	}
    } else
	serifsize = .06*(sf->ascent+sf->descent);
    serifsize = rint(serifsize);
    if ( seriflength>.1*(sf->ascent+sf->descent) || serifsize<0 ) {
	seriflength = 0;		/* that's an unreasonable value, we must be wrong */
	serifsize = 0;
    }

    if ( (si=SFFindExistingSlot(sf,'n',"n"))!=-1 && sf->glyphs[si]!=NULL ) {
	SplineChar *sc = sf->glyphs[si];
	if ( sc->changedsincelasthinted && !sc->manualhints )
	    SplineCharAutoHint(sc,wi->layer,NULL);
	SplineCharQuickBounds(sc,&bb);
	if ( sc->vstem!=NULL && sc->vstem->next!=NULL ) {
	    wi->n_stem_exterior_width = sc->vstem->next->start+sc->vstem->next->width-
		    sc->vstem->start;
	    wi->n_stem_interior_width = sc->vstem->next->start-
		    (sc->vstem->start+sc->vstem->width);
	}
	if ( wi->n_stem_exterior_width<bb.maxx-bb.minx-3*seriflength ||
		wi->n_stem_exterior_width>bb.maxx-bb.minx+seriflength ||
		wi->n_stem_interior_width <= 0 ) {
	    wi->n_stem_exterior_width = bb.maxx-bb.minx - 2*seriflength;
	    /* guess that the stem width is somewhere around the seriflength and */
	    /*  one quarter of the character width */
	    wi->n_stem_interior_width = wi->n_stem_exterior_width - seriflength -
		    wi->n_stem_exterior_width/4;
	}
    }
    if ( ((si=SFFindExistingSlot(sf,'I',"I"))!=-1 && sf->glyphs[si]!=NULL ) ||
	    ((si=SFFindExistingSlot(sf,0x399,"Iota"))!=-1 && sf->glyphs[si]!=NULL ) ||
	    ((si=SFFindExistingSlot(sf,0x406,"afii10055"))!=-1 && sf->glyphs[si]!=NULL ) ) {
	SplineChar *sc = sf->glyphs[si];
	SplineCharQuickBounds(sc,&bb);
	wi->current_I_spacing = sc->width - (bb.maxx-bb.minx);
    }

    wi->caph = caph;
    wi->descent = ds;
    wi->xheight = xh;
    wi->serifsize = serifsize;
    wi->seriflength = seriflength;
    wi->decimation = caph<=1?10:caph/60;

    if ( serifsize==0 ) {
	wi->serifs[0][0] = wi->serifs[0][1] = wi->serifs[1][0] = wi->serifs[1][1] = NOTREACHED;
	wi->serifs[2][0] = wi->serifs[2][1] = wi->serifs[3][0] = wi->serifs[3][1] = NOTREACHED;
    } else {
	wi->serifs[0][0] = rint(ds/wi->decimation);
	wi->serifs[0][1] = rint((ds+serifsize)/wi->decimation);
	wi->serifs[1][0] = 0;
	wi->serifs[1][1] = rint(serifsize/wi->decimation);
	wi->serifs[2][0] = rint((xh-serifsize)/wi->decimation);
	wi->serifs[2][1] = rint(xh/wi->decimation);
	wi->serifs[3][0] = rint((caph-serifsize)/wi->decimation);
	wi->serifs[3][1] = rint(caph/wi->decimation);
    }

    if ( wi->sf==aw_old_sf )
	wi->space_guess = aw_old_spaceguess;
    else if ( wi->autokern && wi->current_I_spacing )
	wi->space_guess = rint(wi->current_I_spacing);
    else if ( wi->n_stem_interior_width>0 )
	wi->space_guess = rint(wi->n_stem_interior_width);
    else if ( caph!=sf->ascent && ds!=-sf->descent )
	wi->space_guess = rint(.205*(caph-ds));
    else
	wi->space_guess = rint(.184*(sf->ascent+sf->descent));
}