void ffw_import_svg_glyph(int code, const char * filename, double ox, double oy, double width) { int enc = SFFindSlot(cur_fv->sf, cur_fv->map, code, ""); if(enc == -1) return; SplineChar * sc = SFMakeChar(cur_fv->sf, cur_fv->map, enc); memset(cur_fv->selected, 0, cur_fv->map->enccount); cur_fv->selected[enc] = 1; int ok = FVImportImages(cur_fv, (char*)filename, fv_svg, 0, -1); if(!ok) err("Import SVG glyph failed"); // correct origin and width { int a = cur_fv->sf->ascent; int d = cur_fv->sf->descent; real transform[6]; transform[0] = 1.0; transform[3] = 1.0; transform[1] = transform[2] = 0.0; transform[4] = -ox * (a+d); transform[5] = -oy * (a+d) + d; FVTrans(cur_fv, sc, transform, NULL, fvt_alllayers | fvt_dontmovewidth); SCSynchronizeWidth(sc, floor(width * (a+d) + 0.5), sc->width, cur_fv); } }
/* * There is no check if a glyph with the same unicode exists! * TODO: let FontForge fill in the standard glyph name <- or maybe this might cause collision? */ void ffw_add_empty_char(int32_t unicode, int width) { SplineChar * sc = SFMakeChar(cur_fv->sf, cur_fv->map, cur_fv->map->enccount); char buffer[400]; SCSetMetaData(sc, strcopy(StdGlyphName(buffer, unicode, cur_fv->sf->uni_interp, cur_fv->sf->for_new_glyphs)), unicode, sc->comment); SCSynchronizeWidth(sc, width, sc->width, cur_fv); }
/* * TODO:bitmap, reference have not been considered in this function */ void ffw_set_widths(int * width_list, int mapping_len, int stretch_narrow, int squeeze_wide) { SplineFont * sf = cur_fv->sf; if(sf->onlybitmaps && cur_fv->active_bitmap != NULL && sf->bitmaps != NULL) { printf("TODO: width vs bitmap\n"); } EncMap * map = cur_fv->map; int i; int imax = min(mapping_len, map->enccount); for(i = 0; i < imax; ++i) { /* * Don't mess with it if the glyphs is not used. */ if(width_list[i] == -1) { continue; } int j = map->map[i]; if(j == -1) continue; SplineChar * sc = sf->glyphs[j]; if(sc == NULL) { sc = SFMakeChar(cur_fv->sf, cur_fv->map, j); } else if(((sc->width > EPS) && (((sc->width > width_list[i] + EPS) && (squeeze_wide)) || ((sc->width < width_list[i] - EPS) && (stretch_narrow))))) { real transform[6]; transform[0] = ((double)width_list[i]) / (sc->width); transform[3] = 1.0; transform[1] = transform[2] = transform[4] = transform[5] = 0; FVTrans(cur_fv, sc, transform, NULL, fvt_alllayers | fvt_dontmovewidth); } SCSynchronizeWidth(sc, width_list[i], sc->width, cur_fv); } }
/* width of A, we'll also change that of À and Ä and ... */ void SCSynchronizeWidth(SplineChar *sc,real newwidth, real oldwidth) { struct splinecharlist *dlist; RefChar *r = HasUseMyMetrics(sc,ly_fore); int isprobablybase; sc->widthset = true; if( r!=NULL ) { if ( oldwidth==r->sc->width ) { sc->width = r->sc->width; return; } newwidth = r->sc->width; } if ( newwidth==oldwidth ) return; sc->width = newwidth; if ( !adjustwidth ) return; isprobablybase = true; if ( sc->unicodeenc==-1 || sc->unicodeenc>=0x10000 || !isalpha(sc->unicodeenc) || iscombining(sc->unicodeenc)) isprobablybase = false; for ( dlist=sc->dependents; dlist!=NULL; dlist=dlist->next ) { RefChar *metrics = HasUseMyMetrics(dlist->sc,ly_fore); if ( metrics!=NULL && metrics->sc!=sc ) continue; else if ( metrics==NULL && !isprobablybase ) continue; if ( dlist->sc->width==oldwidth && (metrics!=NULL)) { SCSynchronizeWidth(dlist->sc,newwidth,oldwidth); if ( !dlist->sc->changed ) { dlist->sc->changed = true; } } } }
static void ApplyChanges(WidthInfo *wi) { EncMap *map = wi->fv->map; uint8 *rsel = calloc(map->enccount,sizeof(char)); int i, width; real transform[6]; struct charone *ch; DBounds bb; for ( i=0; i<wi->real_rcnt; ++i ) { int gid = map->map[wi->right[i]->sc->orig_pos]; if ( gid!=-1 ) rsel[gid] = true; } transform[0] = transform[3] = 1.0; transform[1] = transform[2] = transform[5] = 0; for ( i=0; i<wi->real_rcnt; ++i ) { ch = wi->right[i]; transform[4] = ch->newl-ch->lbearing; if ( transform[4]!=0 ) { FVTrans(wi->fv,ch->sc,transform,rsel,false); SCCharChangedUpdate(ch->sc,ly_none); } } free(rsel); for ( i=0; i<wi->real_lcnt; ++i ) { ch = wi->left[i]; SplineCharLayerFindBounds(ch->sc,wi->layer,&bb); width = rint(bb.maxx + ch->newr); if ( width!=ch->sc->width ) { SCPreserveWidth(ch->sc); SCSynchronizeWidth(ch->sc,width,ch->sc->width,wi->fv); SCCharChangedUpdate(ch->sc,ly_none); } } }
static void DoChar(SplineChar *sc,CreateWidthData *wd, FontViewBase *fv, BDFChar *bc) { real transform[6]; DBounds bb; IBounds ib; int width=0; BVTFunc bvts[2]; BDFFont *bdf; RefChar *r = HasUseMyMetrics(sc,fv->active_layer); /* Can't change the horizontal or vertical advance if there's a "use my metrics" bit set */ if ( r!=NULL && wd->wtype != wt_lbearing ) return; if ( wd->wtype == wt_width ) { if ( wd->type==st_set ) width = wd->setto; else if ( wd->type == st_incr ) width = sc->width + wd->increment; else width = sc->width * wd->scale/100; sc->widthset = true; if ( width!=sc->width ) { SCPreserveWidth(sc); SCSynchronizeWidth(sc,width,sc->width,fv); } } else if ( wd->wtype == wt_lbearing ) { transform[0] = transform[3] = 1.0; transform[1] = transform[2] = transform[5] = 0; bvts[1].func = bvt_none; bvts[0].func = bvt_transmove; bvts[0].y = 0; if ( bc==NULL ) { SplineCharFindBounds(sc,&bb); if ( wd->type==st_set ) transform[4] = wd->setto-bb.minx; else if ( wd->type == st_incr ) transform[4] = wd->increment; else transform[4] = bb.minx*wd->scale/100 - bb.minx; } else { double scale = (fv->sf->ascent+fv->sf->descent)/(double) (fv->active_bitmap->pixelsize); BDFCharFindBounds(bc,&ib); if ( wd->type==st_set ) transform[4] = wd->setto-ib.minx*scale; else if ( wd->type == st_incr ) transform[4] = wd->increment; else transform[4] = scale*ib.minx*wd->scale/100 - ib.minx; } if ( transform[4]!=0 ) { FVTrans(fv,sc,transform,NULL,fvt_dontmovewidth); bvts[0].x = transform[4]; for ( bdf = fv->sf->bitmaps; bdf!=NULL; bdf=bdf->next ) if ( bdf->glyphs[sc->orig_pos]!=NULL ) BCTrans(bdf,bdf->glyphs[sc->orig_pos],bvts,fv); } return; } else if ( wd->wtype == wt_rbearing ) { if ( bc==NULL ) { SplineCharFindBounds(sc,&bb); if ( wd->type==st_set ) width = bb.maxx + wd->setto; else if ( wd->type == st_incr ) width = sc->width+wd->increment; else width = (sc->width-bb.maxx) * wd->scale/100 + bb.maxx; } else { double scale = (fv->sf->ascent+fv->sf->descent)/(double) (fv->active_bitmap->pixelsize); BDFCharFindBounds(bc,&ib); ++ib.maxx; if ( wd->type==st_set ) width = rint(ib.maxx*scale + wd->setto); else if ( wd->type == st_incr ) width = rint(sc->width+wd->increment); else width = rint(scale * (bc->width-ib.maxx) * wd->scale/100 + ib.maxx*scale); } if ( width!=sc->width ) { SCPreserveWidth(sc); SCSynchronizeWidth(sc,width,sc->width,fv); } } else if ( wd->wtype == wt_bearings ) { transform[0] = transform[3] = 1.0; transform[1] = transform[2] = transform[5] = 0; bvts[1].func = bvt_none; bvts[0].func = bvt_transmove; bvts[0].y = 0; if ( bc==NULL ) { SplineCharFindBounds(sc,&bb); if ( wd->type==st_set ) { transform[4] = wd->setto-bb.minx; width = bb.maxx-bb.minx + 2*wd->setto; } else if ( wd->type == st_incr ) { transform[4] = wd->increment; width += 2*wd->increment; } else { transform[4] = bb.minx*wd->scale/100 - bb.minx; width = bb.maxx-bb.minx + (bb.minx + (sc->width-bb.maxx))*wd->scale/100; } } else { double scale = (fv->sf->ascent+fv->sf->descent)/(double) (fv->active_bitmap->pixelsize); BDFCharFindBounds(bc,&ib); ++ib.maxx; if ( wd->type==st_set ) { transform[4] = wd->setto-ib.minx; width = (ib.maxx-ib.minx + 2*wd->setto); } else if ( wd->type == st_incr ) { transform[4] = wd->increment; width += 2*wd->increment; } else { transform[4] = ib.minx*wd->scale/100 - ib.minx; width = ib.maxx-ib.minx + (ib.minx + (bc->width-ib.maxx))*wd->scale/100; } transform[4] *= scale; width = rint(width*scale); } if ( width!=sc->width ) { SCPreserveWidth(sc); SCSynchronizeWidth(sc,width,sc->width,fv); } if ( transform[4]!=0 ) { FVTrans(fv,sc,transform,NULL,fvt_dontmovewidth); bvts[0].x = transform[4]; for ( bdf = fv->sf->bitmaps; bdf!=NULL; bdf=bdf->next ) if ( bdf->glyphs[sc->orig_pos]!=NULL ) BCTrans(bdf,bdf->glyphs[sc->orig_pos],bvts,fv); } return; } else { if ( wd->type==st_set ) width = wd->setto; else if ( wd->type == st_incr ) width = sc->vwidth + wd->increment; else width = sc->vwidth * wd->scale/100; if ( width!=sc->vwidth ) { SCPreserveVWidth(sc); sc->vwidth = width; } } SCCharChangedUpdate(sc,fv->active_layer); }
static void aw2_figure_all_sidebearing(AW_Data *all) { int i,j; AW_Glyph *me, *other; real transform[6], half; int width, changed; uint8 *rsel = calloc(all->fv->map->enccount,sizeof(char)); real denom = (all->sf->ascent + all->sf->descent)/DENOM_FACTOR_OF_EMSIZE; int ldiff, rdiff; all->denom = denom; all->visual_separation = malloc(all->gcnt*all->gcnt*sizeof(int)); for ( i=0; i<all->gcnt; ++i ) { int *vpt = all->visual_separation + i*all->gcnt; me = &all->glyphs[i]; for ( j=0; j<all->gcnt; ++j ) { other = &all->glyphs[j]; vpt[j] = aw2_bbox_separation(me,other,all); } } half = all->desired_separation/2; for ( i=0; i<all->gcnt; ++i ) { me = &all->glyphs[i]; me->lsb = me->rsb = half; } for ( j=0; j<all->loop_cnt; ++j ) { for ( i=0; i<all->gcnt; ++i ) aw2_figure_lsb(i,all); for ( i=0; i<all->gcnt; ++i ) aw2_figure_rsb(i,all); for ( i=0; i<all->gcnt; ++i ) { AW_Glyph *me = &all->glyphs[i]; me->rsb = me->nrsb; me->lsb = me->nlsb; } } free(all->visual_separation); all->visual_separation = NULL; if ( all->normalize ) { /* This is the dummy flat edge we added. We want the separation between */ /* two adjacent flat edges to be desired_separation */ me = &all->glyphs[all->gcnt-1]; if ( me->lsb+me->rsb != all->desired_separation && me->sc==NULL ) { if ( me->lsb+me->rsb!=0 ) { ldiff = (all->desired_separation-(me->lsb+me->rsb)) * me->lsb/(me->lsb+me->rsb); } else { ldiff = all->desired_separation/2; } rdiff = (all->desired_separation-(me->lsb+me->rsb)) - ldiff; for ( i=0; (me = &all->glyphs[i])->sc!=NULL; ++i ) { me->lsb += ldiff; me->rsb += rdiff; } } } transform[0] = transform[3] = 1.0; transform[1] = transform[2] = transform[5] = 0; for ( i=0; (me = &all->glyphs[i])->sc!=NULL; ++i ) { changed = 0; if ( me->lsb != me->bb.minx ) { transform[4] = me->lsb-me->bb.minx; FVTrans(all->fv,me->sc,transform,rsel,false); changed = true; } width = me->lsb + me->rsb + rint(me->bb.maxx - me->bb.minx); if ( me->sc->width != width ) { SCPreserveWidth(me->sc); SCSynchronizeWidth(me->sc,width,me->sc->width,all->fv); changed = true; } if ( changed ) SCCharChangedUpdate(me->sc,ly_none); } free(rsel); }
/* * There is no check if a glyph with the same unicode exists! */ void ffw_add_empty_char(int32_t unicode, int width) { SplineChar * sc = SFMakeChar(cur_fv->sf, cur_fv->map, cur_fv->map->enccount); SCSetMetaData(sc, sc->name, unicode, sc->comment); SCSynchronizeWidth(sc, width, sc->width, cur_fv); }