/* 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 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); }
void AutoWidth2(FontViewBase *fv,int separation,int min_side,int max_side, int chunk_height, int loop_cnt) { struct scriptlist { uint32 script; AW_Glyph *glyphs; int gcnt; } *scripts; int scnt, smax; int enc, gid, s, i; SplineFont *sf = fv->sf; SplineChar *sc; AW_Data all; if ( chunk_height <= 0 ) chunk_height = (sf->ascent + sf->descent)/100; if ( loop_cnt <= 0 ) loop_cnt = 4; scnt = 0; smax = 10; scripts = malloc(smax*sizeof(struct scriptlist)); for ( gid=0; gid<sf->glyphcnt; ++gid ) { if ( (sc = sf->glyphs[gid])!=NULL ) sc->ticked = false; } for ( enc=0; enc<fv->map->enccount; ++enc ) { if ( fv->selected[enc] && (gid=fv->map->map[enc])!=-1 && (sc = sf->glyphs[gid])!=NULL && ! sc->ticked && HasUseMyMetrics(sc,fv->active_layer)==NULL ) { /* If Use My Metrics is set, then we can't change the width (which we grab from a refchar) */ uint32 script; script = SCScriptFromUnicode(sc); for ( s=0; s<scnt; ++s ) { if ( scripts[s].script == script ) break; } if ( s==scnt ) { if ( scnt>=smax ) scripts = realloc(scripts,(smax+=10)*sizeof(struct scriptlist)); memset(&scripts[scnt],0,sizeof(struct scriptlist)); scripts[scnt].script = script; scripts[scnt].glyphs = calloc(sf->glyphcnt+1,sizeof(AW_Glyph)); ++scnt; } i = scripts[s].gcnt; scripts[s].glyphs[i].sc = sc; SplineCharLayerFindBounds(sc,fv->active_layer,&scripts[s].glyphs[i].bb); if ( scripts[s].glyphs[i].bb.minx<-16000 || scripts[s].glyphs[i].bb.maxx>16000 || scripts[s].glyphs[i].bb.miny<-16000 || scripts[s].glyphs[i].bb.maxy>16000 ) ff_post_notice(_("Glyph too big"),_("%s has a bounding box which is too big for this algorithm to work. Ignored."),sc->name); else ++scripts[s].gcnt; } } memset(&all,0,sizeof(all)); all.sf = sf; all.fv = fv; all.layer = fv->active_layer; all.normalize = true; all.sub_height = chunk_height; all.loop_cnt = loop_cnt; all.desired_separation = separation; all.min_sidebearing = min_side; all.max_sidebearing = max_side; for ( s=0; s<scnt; ++s ) { memset(&scripts[s].glyphs[scripts[s].gcnt], 0, sizeof(AW_Glyph)); all.glyphs = scripts[s].glyphs; all.gcnt = scripts[s].gcnt; aw2_handlescript(&all); free(all.glyphs); } <<<<<<< HEAD