struct MATH *MathTableNew(SplineFont *sf) { struct MATH *math = gcalloc(1,sizeof(struct MATH)); /* Too big for chunkalloc */ int emsize = sf->ascent+sf->descent; DBounds b; SplineChar *sc; math->ScriptPercentScaleDown = 80; math->ScriptScriptPercentScaleDown = 60; math->DelimitedSubFormulaMinHeight = emsize*1.5; /* No default given for math->DisplayOperatorMinHeight */ /* No default given for math->AxisHeight */ sc = SFGetChar(sf,'x',NULL); if ( sc!=NULL ) { SplineCharFindBounds(sc,&b); math->AccentBaseHeight = b.maxy; } sc = SFGetChar(sf,'I',NULL); if ( sc!=NULL ) { SplineCharFindBounds(sc,&b); math->FlattenedAccentBaseHeight = b.maxy; } if ( sf->pfminfo.subsuper_set ) math->SubscriptShiftDown = sf->pfminfo.os2_subyoff; math->SubscriptTopMax = math->AccentBaseHeight; /* X-height */ /* No default given for math->SubscriptBaselineDropMin */ if ( sf->pfminfo.subsuper_set ) math->SuperscriptShiftUp = sf->pfminfo.os2_supyoff; /* No default given for math->SuperscriptShiftUpCramped */ math->SuperscriptBottomMin = math->AccentBaseHeight; /* X-height */ /* No default given for math->SuperscriptBaselineDropMax */ math->SubSuperscriptGapMin = 4*sf->uwidth; /* 4* default rule thickness */ math->SuperscriptBottomMaxWithSubscript = math->AccentBaseHeight; /* X-height */ math->SpaceAfterScript = emsize/24; /* .5pt at 12pt */ math->StackGapMin = 3*sf->uwidth; /* 3* default rule thickness */ math->StackDisplayStyleGapMin = 7*sf->uwidth; math->StretchStackGapAboveMin = math->UpperLimitGapMin; math->StretchStackGapBelowMin = math->LowerLimitGapMin; math->FractionNumeratorDisplayStyleShiftUp = math->StackTopDisplayStyleShiftUp; math->FractionDenominatorDisplayStyleShiftDown = math->StackBottomDisplayStyleShiftDown; math->FractionNumeratorGapMin = sf->uwidth; math->FractionNumeratorDisplayStyleGapMin = 3*sf->uwidth; math->FractionRuleThickness = sf->uwidth; math->FractionDenominatorGapMin = sf->uwidth; math->FractionDenominatorDisplayStyleGapMin = 3*sf->uwidth; math->OverbarVerticalGap = 3*sf->uwidth; math->OverbarRuleThickness = sf->uwidth; math->OverbarExtraAscender = sf->uwidth; math->UnderbarVerticalGap = 3*sf->uwidth; math->UnderbarRuleThickness = sf->uwidth; math->UnderbarExtraDescender = sf->uwidth; math->RadicalVerticalGap = sf->uwidth; math->RadicalExtraAscender = sf->uwidth; math->RadicalKernBeforeDegree = 5*emsize/18; math->RadicalKernAfterDegree = -10*emsize/18; math->RadicalDegreeBottomRaisePercent = 60; math->MinConnectorOverlap = emsize/50; return( math ); }
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 ); }
static void SCDefWidthVal(char *buf,SplineChar *sc, enum widthtype wtype) { DBounds bb; if ( wtype==wt_width ) sprintf( buf, "%d", sc->width ); else if ( wtype==wt_vwidth ) sprintf( buf, "%d", sc->vwidth ); else { SplineCharFindBounds(sc,&bb); if ( wtype==wt_lbearing ) sprintf( buf, "%.4g", (double) bb.minx ); else if ( wtype==wt_rbearing ) sprintf( buf, "%.4g", sc->width-(double) bb.maxx ); else sprintf( buf, "%.4g", rint( (sc->width-(double) bb.maxx + (double) bb.minx)/2 ) ); } }
static void BaseLang_FinishEdit(GGadget *g, int r, int c, int wasnew) { if ( wasnew && c==0 ) { BaseLangDlg *b = GDrawGetUserData(GGadgetGetWindow(g)); int rows, cols = GMatrixEditGetColCnt(g); struct matrix_data *md = GMatrixEditGet(g,&rows); uint32 lang = TagFromString(md[r*cols+0].u.md_str); int gid; SplineChar *sc; DBounds bnd, scb; memset(&bnd,0,sizeof(bnd)); for ( gid=0; gid<b->sf->glyphcnt; ++gid ) if ( (sc=b->sf->glyphs[gid])!=NULL ) { if ( lang==CHR('E','N','G',' ') && (sc->unicodeenc<0 || sc->unicodeenc>127)) /* English just uses ASCII */; else if ( b->script==CHR('l','a','t','n') && (sc->unicodeenc<0 || sc->unicodeenc>255) && lang!=CHR('V','I','T',' ') ) /* Most languages in latin script only use one accent per */ /* letter. So latin1 should provide a reasonable bounding */ /* box. Vietnamese is an exception. */; else if ( SCScriptFromUnicode(sc)!=b->script ) /* Not interesting */; else { SplineCharFindBounds(sc,&scb); if ( bnd.minx==bnd.maxx ) bnd = scb; else { if ( scb.minx<bnd.minx ) bnd.minx = scb.minx; if ( scb.miny<bnd.miny ) bnd.miny = scb.miny; if ( scb.maxx>bnd.maxx ) bnd.maxx = scb.maxx; if ( scb.maxy>bnd.maxy ) bnd.maxy = scb.maxy; } } } if ( b->vertical ) { md[r*cols+1].u.md_ival = floor(bnd.minx); md[r*cols+2].u.md_ival = ceil(bnd.maxx); } else { md[r*cols+1].u.md_ival = floor(bnd.miny); md[r*cols+2].u.md_ival = ceil(bnd.maxy); } } }
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); }