diff options
-rw-r--r-- | fontforge/autowidth2.c | 14 | ||||
-rw-r--r-- | fontforge/baseviews.h | 1 | ||||
-rw-r--r-- | fontforge/fontinfo.c | 53 | ||||
-rw-r--r-- | fontforge/kernclass.c | 45 | ||||
-rw-r--r-- | fontforge/libffstamp.h | 4 | ||||
-rw-r--r-- | fontforge/lookupui.c | 97 | ||||
-rw-r--r-- | fontforge/python.c | 126 | ||||
-rw-r--r-- | fontforge/sfd.c | 7 | ||||
-rw-r--r-- | fontforge/splinefont.h | 3 | ||||
-rw-r--r-- | fontforge/splineutil2.c | 2 | ||||
-rw-r--r-- | fontforge/stamp.c | 4 | ||||
-rw-r--r-- | htdocs/python.html | 6 | ||||
-rw-r--r-- | htdocs/sfdformat.html | 9 |
13 files changed, 219 insertions, 152 deletions
diff --git a/fontforge/autowidth2.c b/fontforge/autowidth2.c index 67821d8a..e746f311 100644 --- a/fontforge/autowidth2.c +++ b/fontforge/autowidth2.c @@ -824,6 +824,7 @@ void AutoKern2BuildClasses(SplineFont *sf,int layer, SplineChar **leftglyphs,SplineChar **rightglyphs, struct lookup_subtable *sub, int separation, int min_kern, int touching, int only_closer, + int autokern, real good_enough) { AW_Data all; AW_Glyph *glyphs, *me, *other; @@ -847,22 +848,26 @@ return; good_enough = (sf->ascent+sf->descent)/100.0; if ( separation==0 && !touching ) { + /* Use default values. Generate them if they don't exist */ if ( sub->separation==0 && !sub->kerning_by_touch ) { sub->separation = sf->width_separation; if ( sf->width_separation==0 ) sub->separation = 15*(sf->ascent+sf->descent)/100; separation = sub->separation; + autokern = true; } else { separation = sub->separation; touching = sub->kerning_by_touch; min_kern = sub->minkern; only_closer = sub->onlyCloser; + autokern = !sub->dontautokern; } } sub->separation = separation; sub->minkern = min_kern; sub->kerning_by_touch = touching; sub->onlyCloser = only_closer; + sub->dontautokern = !autokern; chunk_height = (sf->ascent + sf->descent)/200; memset(&all,0,sizeof(all)); @@ -1006,10 +1011,11 @@ return; kc->adjusts = gcalloc(lclasscnt*rclasscnt,sizeof(DeviceTable)); #endif - AutoKern2NewClass(sf,layer,kc->firsts, kc->seconds, - kc->first_cnt, kc->second_cnt, - kc2AddOffset, kc, - separation,min_kern,touching,only_closer,chunk_height); + if ( autokern ) + AutoKern2NewClass(sf,layer,kc->firsts, kc->seconds, + kc->first_cnt, kc->second_cnt, + kc2AddOffset, kc, + separation,min_kern,touching,only_closer,chunk_height); if ( sub->lookup->lookup_flags & pst_r2l ) { char **temp = kc->seconds; diff --git a/fontforge/baseviews.h b/fontforge/baseviews.h index caf67c44..0bc2b11b 100644 --- a/fontforge/baseviews.h +++ b/fontforge/baseviews.h @@ -610,6 +610,7 @@ extern void AutoKern2BuildClasses(SplineFont *sf,int layer, SplineChar **leftglyphs,SplineChar **rightglyphs, struct lookup_subtable *sub, int separation, int min_kern, int touching, int only_closer, + int autokern, real good_enough); #endif diff --git a/fontforge/fontinfo.c b/fontforge/fontinfo.c index 62fe90fa..56490e1a 100644 --- a/fontforge/fontinfo.c +++ b/fontforge/fontinfo.c @@ -24,7 +24,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "pfaeditui.h" +#include "fontforgeui.h" #include "ofl.h" #include <ustring.h> #include <chardata.h> @@ -2013,7 +2013,7 @@ static struct psdict *GFI_ParsePrivate(struct gfi_data *d) { struct psdict *ret = gcalloc(1,sizeof(struct psdict)); GGadget *private = GWidgetGetControl(d->gw,CID_Private); int rows, cols = GMatrixEditGetColCnt(private); - struct matrix_data *strings = _GMatrixEditGet(private, &rows); + struct matrix_data *strings = GMatrixEditGet(private, &rows); int i,j; ret->cnt = rows; @@ -3497,6 +3497,20 @@ static int GFI_AddOFL(GGadget *g, GEvent *e) { return( true ); } +static int ss_cmp(const void *_md1, const void *_md2) { + const struct matrix_data *md1 = _md1, *md2 = _md2; + + char buf1[20], buf2[20]; + const char *l1, *l2; + + if ( md1[1].u.md_ival == md2[1].u.md_ival ) { + l1 = langname(md1[0].u.md_ival,buf1); + l2 = langname(md2[0].u.md_ival,buf2); +return( strcoll(l1,l2)); + } +return( md1[1].u.md_ival - md2[1].u.md_ival ); +} + static void SSMatrixInit(struct matrixinit *mi,struct gfi_data *d) { SplineFont *sf = d->sf; struct matrix_data *md; @@ -3519,6 +3533,7 @@ static void SSMatrixInit(struct matrixinit *mi,struct gfi_data *d) { md[3*cnt+2].u.md_str = copy(on->name); } } + qsort( md, cnt, 3*sizeof(struct matrix_data), ss_cmp ); mi->matrix_data = md; mi->initial_row_cnt = cnt; } @@ -3945,7 +3960,8 @@ static void StoreSSNames(struct gfi_data *d) { OtfFeatNameListFree(sf->feat_names); sf->feat_names = NULL; - for ( i=0; i<rows; ++i ) { + qsort( strings, rows, 3*sizeof(struct matrix_data), ss_cmp ); + for ( i=rows-1; i>=0; --i ) { if ( strings[3*i+2].u.md_str == NULL ) continue; tag = strings[3*i+1].u.md_ival; @@ -4142,6 +4158,7 @@ static int GFI_OK(GGadget *g, GEvent *e) { int32 len; GTextInfo **ti; int subs[4], super[4], strike[2]; + struct otfname *fontstyle_name; int design_size, size_top, size_bottom, styleid; int strokedfont = false; real strokewidth; @@ -4212,7 +4229,7 @@ return( true ); } if ( layer_cnt>=BACK_LAYER_MAX-2 ) { ff_post_error(_("Too many layers"),_("FontForge supports at most %d layers"),BACK_LAYER_MAX-2); - /* This can be increased in configure-pfaedit.h */ + /* This can be increased in configure-fontforge.h */ return( true ); } if ( !CheckNames(d)) @@ -4252,6 +4269,34 @@ return(true); size_bottom = rint(10*GetReal8(gw,CID_DesignBottom,_("_Bottom"),&err)); size_top = rint(10*GetReal8(gw,CID_DesignTop,_("_Top"),&err)); styleid = GetInt8(gw,CID_StyleID,_("Style _ID:"),&err); + fontstyle_name = OtfNameFromStyleNames(GWidgetGetControl(gw,CID_StyleName)); + OtfNameListFree(fontstyle_name); + if ( design_size==0 && ( size_bottom!=0 || size_top!=0 || styleid!=0 || fontstyle_name!=NULL )) { + ff_post_error(_("Bad Design Size Info"),_("If the design size is 0, then all other fields on that pane must be zero (or unspecified) too.")); +return( true ); + } else if ( styleid!=0 && fontstyle_name==NULL ) { + ff_post_error(_("Bad Design Size Info"),_("If you specify a style id for the design size, then you must specify a style name")); +return( true ); + } else if ( fontstyle_name==NULL && styleid!=0 ) { + ff_post_error(_("Bad Design Size Info"),_("If you specify a style name for the design size, then you must specify a style id")); +return( true ); + } else if ( design_size<0 ) { + ff_post_error(_("Bad Design Size Info"),_("If you specify a design size, it must be positive")); +return( true ); + } else if ( size_bottom!=0 && size_bottom>design_size ) { + ff_post_error(_("Bad Design Size Info"),_("In the design size range, the bottom field must be less than the design size.")); +return( true ); + } else if ( size_top!=0 && size_top<design_size ) { + ff_post_error(_("Bad Design Size Info"),_("In the design size range, the bottom top must be more than the design size.")); +return( true ); + } else if ( styleid!=0 && size_top==0 ) { + ff_post_error(_("Bad Design Size Info"),_("If you specify a style id for the design size, then you must specify a size range")); +return( true ); + } else if ( size_top!=0 && styleid==0 ) { + ff_post_notice(_("Bad Design Size Info"),_("If you specify a design size range, then you are supposed to specify a style id and style name too. FontForge will allow you to leave those fields blank, but other applications may not.")); + /* no return, this is just a warning */ + } + if ( *_GGadgetGetTitle(GWidgetGetControl(gw,CID_Revision))!='\0' ) sfntRevision = rint(65536.*GetReal8(gw,CID_Revision,_("sfnt Revision:"),&err)); if ( *_GGadgetGetTitle(GWidgetGetControl(gw,CID_WoffMajor))!='\0' ) { diff --git a/fontforge/kernclass.c b/fontforge/kernclass.c index 485e6c8b..5411cbac 100644 --- a/fontforge/kernclass.c +++ b/fontforge/kernclass.c @@ -119,6 +119,7 @@ typedef struct kernclasslistdlg { #define CID_MinKern 2009 #define CID_Touched 2010 #define CID_OnlyCloser 2011 +#define CID_Autokern 2012 #define CID_SizeLabel 3000 #define CID_MagLabel 3001 @@ -1157,7 +1158,7 @@ static int KC_OK(GGadget *g, GEvent *e) { int i; int len; struct matrix_data *classes; - int err, touch=0, separation=0, minkern=0, onlyCloser; + int err, touch=0, separation=0, minkern=0, onlyCloser, autokern; sf = kcd->sf; if ( sf->cidmaster!=NULL ) sf = sf->cidmaster; @@ -1168,6 +1169,7 @@ static int KC_OK(GGadget *g, GEvent *e) { separation = GetInt8(kcd->gw,CID_Separation,_("Separation"),&err); minkern = GetInt8(kcd->gw,CID_MinKern,_("Min Kern"),&err); onlyCloser = GGadgetIsChecked(GWidgetGetControl(kcd->gw,CID_OnlyCloser)); + autokern = GGadgetIsChecked(GWidgetGetControl(kcd->gw,CID_Autokern)); if ( err ) return( true ); KCD_Finalize(kcd); @@ -1188,6 +1190,7 @@ return( true ); kc->subtable->minkern = minkern; kc->subtable->kerning_by_touch = touch; kc->subtable->onlyCloser = onlyCloser; + kc->subtable->dontautokern = !autokern; kc->first_cnt = kcd->first_cnt; kc->second_cnt = kcd->second_cnt; @@ -1983,11 +1986,12 @@ void ME_ClassCheckUnique(GGadget *g,int r, int c, SplineFont *sf) { static void KCD_FinishEdit(GGadget *g,int r, int c, int wasnew) { KernClassDlg *kcd = GDrawGetUserData(GGadgetGetWindow(g)); int is_first = GGadgetGetCid(g) == CID_ClassList; - int i; + int i, autokern; ME_ClassCheckUnique(g, r, c, kcd->sf); if ( wasnew ) { + autokern = GGadgetIsChecked(GWidgetGetControl(kcd->gw,CID_Autokern)); if ( is_first ) { kcd->offsets = grealloc(kcd->offsets,(kcd->first_cnt+1)*kcd->second_cnt*sizeof(int16)); memset(kcd->offsets+kcd->first_cnt*kcd->second_cnt, @@ -1998,7 +2002,8 @@ static void KCD_FinishEdit(GGadget *g,int r, int c, int wasnew) { 0, kcd->second_cnt*sizeof(DeviceTable)); #endif ++kcd->first_cnt; - KCD_AutoKernAClass(kcd,kcd->first_cnt-1,true); + if ( autokern ) + KCD_AutoKernAClass(kcd,kcd->first_cnt-1,true); } else { int16 *new = galloc(kcd->first_cnt*(kcd->second_cnt+1)*sizeof(int16)); for ( i=0; i<kcd->first_cnt; ++i ) { @@ -2021,7 +2026,8 @@ static void KCD_FinishEdit(GGadget *g,int r, int c, int wasnew) { } #endif ++kcd->second_cnt; - KCD_AutoKernAClass(kcd,kcd->second_cnt-1,false); + if ( autokern ) + KCD_AutoKernAClass(kcd,kcd->second_cnt-1,false); } KCD_SBReset(kcd); GDrawRequestExpose(kcd->gw,NULL,false); @@ -2524,10 +2530,10 @@ static void FillShowKerningWindow(KernClassDlg *kcd, GGadgetCreateData *left, void KernClassD(KernClass *kc, SplineFont *sf, int layer, int isv) { GRect pos; GWindowAttrs wattrs; - GGadgetCreateData gcd[53], sepbox, classbox, hvbox, buttonbox, mainbox[2], topbox[2], titbox; + GGadgetCreateData gcd[54], sepbox, classbox, hvbox, buttonbox, mainbox[2], topbox[2], titbox, hbox; GGadgetCreateData *harray1[17], *harray2[17], *varray1[5], *varray2[5]; - GGadgetCreateData *hvarray[13], *buttonarray[8], *varray[19], *h4array[8], *harrayclasses[6], *titlist[4]; - GTextInfo label[53]; + GGadgetCreateData *hvarray[13], *buttonarray[8], *varray[19], *h4array[8], *harrayclasses[6], *titlist[4], *h5array[3]; + GTextInfo label[54]; KernClassDlg *kcd; int i, j, kc_width, vi; int as, ds, ld, sbsize; @@ -2574,6 +2580,7 @@ return; memset(&wattrs,0,sizeof(wattrs)); memset(&gcd,0,sizeof(gcd)); memset(&classbox,0,sizeof(classbox)); + memset(&hbox,0,sizeof(hbox)); memset(&hvbox,0,sizeof(hvbox)); memset(&buttonbox,0,sizeof(buttonbox)); memset(&mainbox,0,sizeof(mainbox)); @@ -2725,7 +2732,6 @@ return; label[i].text_is_1byte = true; label[i].text_in_resource = true; gcd[i].gd.label = &label[i]; - gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 5+4; gcd[i].gd.flags = gg_enabled|gg_visible|gg_utf8_popup; if ( kc->subtable->onlyCloser ) gcd[i].gd.flags = gg_enabled|gg_visible|gg_utf8_popup|gg_cb_on; @@ -2734,7 +2740,28 @@ return; "so the kerning offset will be negative."); gcd[i].gd.cid = CID_OnlyCloser; gcd[i].creator = GCheckBoxCreate; - varray[j++] = &gcd[i++]; varray[j++] = NULL; + h5array[0] = &gcd[i++]; + + label[i].text = (unichar_t *) _("Autokern new entries"); + label[i].text_is_1byte = true; + label[i].text_in_resource = true; + gcd[i].gd.label = &label[i]; + gcd[i].gd.flags = gg_enabled|gg_visible|gg_utf8_popup; + if ( !kc->subtable->dontautokern ) + gcd[i].gd.flags = gg_enabled|gg_visible|gg_utf8_popup|gg_cb_on; + gcd[i].gd.popup_msg = (unichar_t *) _( + "When adding a new class provide default kerning values\n" + "Between it and every class with which it interacts."); + gcd[i].gd.cid = CID_Autokern; + gcd[i].creator = GCheckBoxCreate; + h5array[1] = &gcd[i++]; h5array[2] = NULL; + + memset(&hbox,0,sizeof(hbox)); + hbox.gd.flags = gg_enabled|gg_visible; + hbox.gd.u.boxelements = h5array; + hbox.creator = GHBoxCreate; + + varray[j++] = &hbox; varray[j++] = NULL; gcd[i].gd.pos.x = 10; gcd[i].gd.pos.y = GDrawPointsToPixels(gw,gcd[i-1].gd.pos.y+17); gcd[i].gd.pos.width = pos.width-20; diff --git a/fontforge/libffstamp.h b/fontforge/libffstamp.h index a29b549b..c691f9f5 100644 --- a/fontforge/libffstamp.h +++ b/fontforge/libffstamp.h @@ -1,3 +1,3 @@ -#define LibFF_ModTime 1298320590L /* Seconds since 1970 (standard unix time) */ -#define LibFF_ModTime_Str "20:36 GMT 21-Feb-2011" +#define LibFF_ModTime 1298329534L /* Seconds since 1970 (standard unix time) */ +#define LibFF_ModTime_Str "23:05 GMT 21-Feb-2011" #define LibFF_VersionDate 20110221 /* Year, month, day */ diff --git a/fontforge/lookupui.c b/fontforge/lookupui.c index 1fc1da61..8c0e0f19 100644 --- a/fontforge/lookupui.c +++ b/fontforge/lookupui.c @@ -2011,6 +2011,7 @@ typedef struct anchorclassdlg { #define CID_MinKern 2009 #define CID_Touched 2010 #define CID_OnlyCloser 2011 +#define CID_Autokern 2012 #define CID_KernDisplay 2022 #define CID_PixelSize 2023 @@ -3493,6 +3494,9 @@ return( true ); static int PSTKD_DoAutoKern(PSTKernDlg *pstkd,SplineChar **glyphlist) { int err, touch, separation, minkern, onlyCloser; + if ( !GGadgetIsChecked(GWidgetGetControl(pstkd->gw,CID_Autokern)) ) +return( false ); + err = false; touch = GGadgetIsChecked(GWidgetGetControl(pstkd->gw,CID_Touched)); separation = GetInt8(pstkd->gw,CID_Separation,_("Separation"),&err); @@ -3670,7 +3674,7 @@ static int PSTKD_Ok(GGadget *g, GEvent *e) { char *buts[3]; KernPair *kp, *kpprev, *kpnext; PST *pst, *pstprev, *pstnext; - int err, touch=0, separation=0, minkern=0, onlyCloser=0; + int err, touch=0, separation=0, minkern=0, onlyCloser=0, autokern=0; int _t = lookup_type == gpos_single ? pst_position : lookup_type == gpos_pair ? pst_pair : lookup_type == gsub_single ? pst_substitution @@ -3686,6 +3690,7 @@ static int PSTKD_Ok(GGadget *g, GEvent *e) { separation = GetInt8(pstkd->gw,CID_Separation,_("Separation"),&err); minkern = GetInt8(pstkd->gw,CID_MinKern,_("Min Kern"),&err); onlyCloser = GGadgetIsChecked(GWidgetGetControl(pstkd->gw,CID_OnlyCloser)); + autokern = GGadgetIsChecked(GWidgetGetControl(pstkd->gw,CID_Autokern)); if ( err ) return( true ); } @@ -3879,6 +3884,7 @@ return( true ); pstkd->sub->minkern = minkern; pstkd->sub->kerning_by_touch = touch; pstkd->sub->onlyCloser = onlyCloser; + pstkd->sub->dontautokern = !autokern; } pstkd->done = true; } @@ -4159,9 +4165,9 @@ static void PSTKernD(SplineFont *sf, struct lookup_subtable *sub, int def_layer) GWindowAttrs wattrs; char title[300]; struct matrixinit mi; - GGadgetCreateData gcd[22], buttongcd[6], box[6]; - GGadgetCreateData *h1array[8], *h2array[7], *h3array[7], *varray[20], *h4array[8]; - GTextInfo label[22], buttonlabel[6]; + GGadgetCreateData gcd[23], buttongcd[6], box[6], hbox; + GGadgetCreateData *h1array[8], *h2array[7], *h3array[7], *varray[20], *h4array[8], *h5array[4]; + GTextInfo label[23], buttonlabel[6]; int i,k,mi_pos, mi_k; enum otlookup_type lookup_type = sub->lookup->lookup_type; char sepbuf[40], mkbuf[40]; @@ -4470,7 +4476,6 @@ static void PSTKernD(SplineFont *sf, struct lookup_subtable *sub, int def_layer) label[i].text_is_1byte = true; label[i].text_in_resource = true; gcd[i].gd.label = &label[i]; - gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 5+4; gcd[i].gd.flags = gg_enabled|gg_visible|gg_utf8_popup; if ( sub->onlyCloser ) gcd[i].gd.flags = gg_enabled|gg_visible|gg_utf8_popup|gg_cb_on; @@ -4479,7 +4484,26 @@ static void PSTKernD(SplineFont *sf, struct lookup_subtable *sub, int def_layer) "so the kerning offset will be negative."); gcd[i].gd.cid = CID_OnlyCloser; gcd[i].creator = GCheckBoxCreate; - varray[k++] = &gcd[i++]; varray[k++] = NULL; + h5array[0] = &gcd[i++]; + + label[i].text = (unichar_t *) _("Autokern new entries"); + label[i].text_is_1byte = true; + label[i].text_in_resource = true; + gcd[i].gd.label = &label[i]; + gcd[i].gd.flags = gg_enabled|gg_visible|gg_utf8_popup; + if ( !sub->dontautokern ) + gcd[i].gd.flags = gg_enabled|gg_visible|gg_utf8_popup|gg_cb_on; + gcd[i].gd.popup_msg = (unichar_t *) _( + "When adding new entries provide default kerning values."); + gcd[i].gd.cid = CID_Autokern; + gcd[i].creator = GCheckBoxCreate; + h5array[1] = &gcd[i++]; h5array[2] = NULL; + + memset(&hbox,0,sizeof(hbox)); + hbox.gd.flags = gg_enabled|gg_visible; + hbox.gd.u.boxelements = h5array; + hbox.creator = GHBoxCreate; + varray[k++] = &hbox; varray[k++] = NULL; label[i].text = (unichar_t *) _("Size:"); label[i].text_is_1byte = true; @@ -5011,6 +5035,7 @@ return( true ); #undef CID_MinKern #undef CID_Touched #undef CID_OnlyCloser +#undef CID_Autokern #define CID_KPairs 1000 #define CID_KClasses 1001 #define CID_KCBuild 1002 @@ -5018,9 +5043,9 @@ return( true ); #define CID_MinKern 1004 #define CID_Touched 1005 #define CID_ClassDistance 1006 -#define CID_KPAuto 1007 #define CID_Guts 1008 #define CID_OnlyCloser 1009 +#define CID_Autokern 1010 struct kf_results { int asked; @@ -5039,12 +5064,10 @@ static int KF_FormatChange(GGadget *g, GEvent *e) { kf = GDrawGetUserData(GGadgetGetWindow(g)); if ( GGadgetIsChecked(GWidgetGetControl(kf->gw,CID_KPairs)) ) { GGadgetSetEnabled(GWidgetGetControl(kf->gw,CID_KCBuild),0); - GGadgetSetEnabled(GWidgetGetControl(kf->gw,CID_KPAuto),1); sprintf(mkbuf,"%d",15*(kf->sf->ascent+kf->sf->descent)/1000 ); GGadgetSetTitle8(GWidgetGetControl(kf->gw,CID_MinKern),mkbuf); } else { GGadgetSetEnabled(GWidgetGetControl(kf->gw,CID_KCBuild),1); - GGadgetSetEnabled(GWidgetGetControl(kf->gw,CID_KPAuto),0); GGadgetSetTitle8(GWidgetGetControl(kf->gw,CID_MinKern),"0"); } } @@ -5087,9 +5110,9 @@ static int KF_OK(GGadget *g, GEvent *e) { if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) { struct kf_dlg *kf = GDrawGetUserData(GGadgetGetWindow(g)); - int touch, separation, minkern, err, onlyCloser; + int touch, separation, minkern, err, onlyCloser, autokern; real good_enough=0; - int isclass, autobuild=0, autokern=0; + int isclass, autobuild=0; struct kf_results *results = kf->results; err = false; @@ -5097,6 +5120,7 @@ static int KF_OK(GGadget *g, GEvent *e) { separation = GetInt8(kf->gw,CID_Separation,_("Separation"),&err); minkern = GetInt8(kf->gw,CID_MinKern,_("Min Kern"),&err); onlyCloser = GGadgetIsChecked(GWidgetGetControl(kf->gw,CID_OnlyCloser)); + autokern = GGadgetIsChecked(GWidgetGetControl(kf->gw,CID_Autokern)); if ( err ) return( true ); @@ -5106,8 +5130,7 @@ return( true ); good_enough = GetReal8(kf->gw,CID_ClassDistance,_("Intra Class Distance"),&err); if ( err ) return( true ); - } else - autokern = GGadgetIsChecked(GWidgetGetControl(kf->gw,CID_KPAuto)); + } if ( autobuild || autokern ) { results->firstglyphs = SelectedGlyphs(kf->first_fv); if ( results->firstglyphs == NULL ) @@ -5122,6 +5145,7 @@ return( true ); kf->sub->minkern = minkern; kf->sub->kerning_by_touch = touch; kf->sub->onlyCloser = onlyCloser; + kf->sub->dontautokern = !autokern; results->good_enough = good_enough; if ( !isclass ) results->asked = 0; @@ -5162,8 +5186,8 @@ static int kern_format_dlg( SplineFont *sf, int def_layer, struct lookup_subtable *sub, struct kf_results *results ) { GRect pos; GWindowAttrs wattrs; - GGadgetCreateData gcd[15], boxes[7]; - GGadgetCreateData *varray[21], *h1array[5], *h2array[6], *h3array[6], *h4array[8], *buttonarray[8]; + GGadgetCreateData gcd[16], boxes[7], hbox; + GGadgetCreateData *varray[21], *h2array[6], *h3array[6], *h4array[8], *buttonarray[8], *h5array[4]; GTextInfo label[15]; char sepbuf[40], mkbuf[40], distancebuf[40]; struct kf_dlg kf; @@ -5236,22 +5260,6 @@ static int kern_format_dlg( SplineFont *sf, int def_layer, gcd[i].creator = GRadioCreate; varray[j++] = &gcd[i++]; varray[j++] = NULL; - label[i].text = (unichar_t *) _("FontForge will auto kern the selected glyphs"); - label[i].text_is_1byte = true; - label[i].text_in_resource = true; - gcd[i].gd.label = &label[i]; - gcd[i].gd.flags = gg_enabled|gg_visible|gg_utf8_popup|gg_cb_on; - gcd[i].gd.popup_msg = (unichar_t *) _( - "FontForge will look at the glyphs selected in the font view\n" - "and guess at good kerning values for them" ); - gcd[i].gd.cid = CID_KPAuto; - gcd[i].creator = GCheckBoxCreate; - h1array[0] = GCD_HPad10; h1array[1] = &gcd[i++]; h1array[2] = GCD_Glue; h1array[3] = NULL; - boxes[2].gd.flags = gg_enabled|gg_visible; - boxes[2].gd.u.boxelements = h1array; - boxes[2].creator = GHBoxCreate; - varray[j++] = &boxes[2]; varray[j++] = NULL; - label[i].text = (unichar_t *) _("Use a matrix of kerning classes"); label[i].text_is_1byte = true; label[i].text_in_resource = true; @@ -5396,7 +5404,6 @@ static int kern_format_dlg( SplineFont *sf, int def_layer, label[i].text_is_1byte = true; label[i].text_in_resource = true; gcd[i].gd.label = &label[i]; - gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 5+4; gcd[i].gd.flags = gg_enabled|gg_visible|gg_utf8_popup|gg_cb_on; if ( sub->onlyCloser ) gcd[i].gd.flags = gg_enabled|gg_visible|gg_utf8_popup|gg_cb_on; @@ -5405,7 +5412,26 @@ static int kern_format_dlg( SplineFont *sf, int def_layer, "so the kerning offset will be negative."); gcd[i].gd.cid = CID_OnlyCloser; gcd[i].creator = GCheckBoxCreate; - varray[j++] = &gcd[i++]; varray[j++] = NULL; + h5array[0] = &gcd[i++]; + + label[i].text = (unichar_t *) _("Autokern new entries"); + label[i].text_is_1byte = true; + label[i].text_in_resource = true; + gcd[i].gd.label = &label[i]; + gcd[i].gd.flags = gg_enabled|gg_visible|gg_utf8_popup; + if ( !sub->dontautokern ) + gcd[i].gd.flags = gg_enabled|gg_visible|gg_utf8_popup|gg_cb_on; + gcd[i].gd.popup_msg = (unichar_t *) _( + "When adding new entries provide default kerning values."); + gcd[i].gd.cid = CID_Autokern; + gcd[i].creator = GCheckBoxCreate; + h5array[1] = &gcd[i++]; h5array[2] = NULL; + + memset(&hbox,0,sizeof(hbox)); + hbox.gd.flags = gg_enabled|gg_visible; + hbox.gd.u.boxelements = h5array; + hbox.creator = GHBoxCreate; + varray[j++] = &hbox; varray[j++] = NULL; guts_row = j/2; gcd[i].gd.flags = gg_enabled|gg_visible; @@ -5446,7 +5472,6 @@ static int kern_format_dlg( SplineFont *sf, int def_layer, GGadgetsCreate(kf.gw,boxes); GHVBoxSetExpandableRow(boxes[0].ret,guts_row); - GHVBoxSetExpandableCol(boxes[2].ret,gb_expandglue); GHVBoxSetExpandableCol(boxes[3].ret,gb_expandglue); GHVBoxSetExpandableCol(boxes[4].ret,gb_expandglue); GHVBoxSetExpandableCol(boxes[5].ret,gb_expandglue); @@ -5545,6 +5570,7 @@ return; } AutoKern2(sf, def_layer,lefts,rights, sub, + /* If separation==0 and !touch then use default values */ 0,0,0,0, 0, NULL, NULL); } } else { @@ -5566,8 +5592,9 @@ return; #endif /* Need to fix for Hebrew !!!! */ if ( results.autobuild ) + /* Specifying separation==0 and !touching means use default values */ AutoKern2BuildClasses(sf,def_layer,results.firstglyphs, - results.secondglyphs,sub,0,0,0,0,results.good_enough); + results.secondglyphs,sub,0,0,0,0,0,results.good_enough); } free(results.firstglyphs); free(results.secondglyphs); diff --git a/fontforge/python.c b/fontforge/python.c index 39e50f5c..72c203a3 100644 --- a/fontforge/python.c +++ b/fontforge/python.c @@ -5734,75 +5734,6 @@ return( -1 ); return( 0 ); } -static PyObject *PyFF_Glyph_get_lcarets(PyFF_Glyph *self,void *closure) { - - SplineChar *sc = ((PyFF_Glyph *) self)->sc; - int cnt=0, i; - PST *pst, *lcar = NULL; - PyObject *tuple; - - for ( pst = sc->possub; pst!=NULL; pst=pst->next ) { - if ( pst->type==pst_lcaret ) { - lcar = pst; - cnt = lcar->u.lcaret.cnt; - break; - } - } - tuple = PyTuple_New(cnt); - - if ( lcar != NULL ) { - for ( i=0; i<cnt; ++i ) { - PyTuple_SetItem( tuple,i,Py_BuildValue("i",lcar->u.lcaret.carets[i]) ); - } - } -return( tuple ); -} - -static int PyFF_Glyph_set_lcarets(PyFF_Glyph *self,PyObject *value,void *closure) { - SplineChar *sc = self->sc; - int i, cnt, lig_comp_max = 0, lc; - char *pt; - int16 *carets; - PST *pst, *lcar = NULL; - - cnt = PySequence_Size(value); - if ( cnt==-1 ) -return( -1 ); - - if ( cnt > 0 ) - carets = galloc( cnt*sizeof(int16) ); - for ( i=0; i<cnt; ++i ) { - carets[i] = PyInt_AsLong( PySequence_GetItem(value,i) ); - if ( PyErr_Occurred()) -return( -1 ); - } - - for ( pst = sc->possub; pst!=NULL; pst=pst->next ) { - if ( pst->type==pst_lcaret ) { - lcar = pst; - free( lcar->u.lcaret.carets ); - } else if ( pst->type==pst_ligature ) { - for ( lc=0, pt=pst->u.lig.components; *pt; ++pt ) - if ( *pt==' ' ) ++lc; - if ( lc>lig_comp_max ) - lig_comp_max = lc; - } - } - - if ( lcar == NULL && cnt > 0 ) { - lcar = chunkalloc(sizeof(PST)); - lcar->type = pst_lcaret; - lcar->next = sc->possub; - sc->possub = lcar; - } - if ( lcar != NULL ) { - lcar->u.lcaret.cnt = cnt; - lcar->u.lcaret.carets = cnt > 0 ? carets : NULL; - sc->lig_caret_cnt_fixed = ( cnt != lig_comp_max ) ? true : false; - } -return( 0 ); -} - static PyObject *PyFF_Glyph_get_font(PyFF_Glyph *self,void *closure) { return( PyFV_From_FV_I(self->sc->parent->fv)); @@ -6683,9 +6614,6 @@ static PyGetSetDef PyFF_Glyph_getset[] = { {"manualHints", (getter)PyFF_Glyph_get_manualhints, (setter)PyFF_Glyph_set_manualhints, "The hints have been set manually, and the glyph should not be autohinted by default" }, - {"lcarets", - (getter)PyFF_Glyph_get_lcarets, (setter)PyFF_Glyph_set_lcarets, - "The ligature caret locations, defined for this glyph, as a tuple.", NULL}, {"validation_state", (getter)PyFF_Glyph_get_validation_state, (setter)PyFF_cant_set, "glyph's validation state (readonly)", NULL}, @@ -12760,6 +12688,7 @@ return( false ); return( false ); AutoKern2BuildClasses(fv->sf,fv->active_layer,first,second,sub, sub->separation,0,sub->kerning_by_touch, sub->onlyCloser, + !sub->dontautokern, good_enough); free(first); if ( first!=second ) @@ -12806,13 +12735,15 @@ static PyObject *PyFFFont_addKerningClass(PyObject *self, PyObject *args) { char **class1_strs, **class2_strs; int cnt1, cnt2, acnt; int16 *offs=NULL; - int separation= -1, touch=0, do_autokern=false, only_closer=0; + int separation= -1, touch=0, do_autokern=false, only_closer=0, autokern=true; double class_error_distance; /* arguments: * (char *lookupname, char *newsubtabname, char ***classes1, char ***classes2, int *offsets [,char *after_sub_name]) - * (char *lookupname, char *newsubtabname, int separation, char ***classes1, char ***classes2 [, int only_closer, char *after_sub_name]) - * (char *lookupname, char *newsubtabname, int separation, double err, char **list1, char **list2 [, int only_closer, char *after_sub_name]) - * (char *lookupname, char *newsubtabname, int separation, double err [, int only_closer, char *after_sub_name]) + * (char *lookupname, char *newsubtabname, int separation, char ***classes1, char ***classes2 [, int only_closer, int autokern, char *after_sub_name]) + * (char *lookupname, char *newsubtabname, int separation, double err, char **list1, char **list2 [, int only_closer, int autokern, char *after_sub_name]) + * (char *lookupname, char *newsubtabname, int separation, double err [, int only_closer, int autokern, char *after_sub_name]) + * Also support arguments where [,int autokern] is absent as we used not to + * allow the user to specify it * First is fully specified set of classes with offsets cnt=5/6 * Second fully specified set of classes, to be autokerned cnt=5/7 * Third two lists of glyphs to be turned into classes and then autokerned cnt=6/8 @@ -12831,21 +12762,45 @@ return( NULL ); return( NULL ); do_autokern = false; } else if ( !PyInt_Check(arg4) && !PyLong_Check(arg4) && !PyFloat_Check(arg4)) { - if ( !PyArg_ParseTuple(args,"ssiOO|is", &lookup, &subtable, - &separation, &class1s, &class2s, - &only_closer, &after_str )) + PyObject *arg7 = acnt>=7 ? PySequence_GetItem(args,6) : NULL; + if ( arg7!=NULL && (PyInt_Check(arg7) || PyLong_Check(arg7))) { + if ( !PyArg_ParseTuple(args,"ssiOO|iis", &lookup, &subtable, + &separation, &class1s, &class2s, + &only_closer, &autokern, &after_str )) +return( NULL ); + } else { + if ( !PyArg_ParseTuple(args,"ssiOO|is", &lookup, &subtable, + &separation, &class1s, &class2s, + &only_closer, &after_str )) return( NULL ); + } } else if ( acnt>5 && (arg5=PySequence_GetItem(args,4)) && PySequence_Check(arg5) ) { - if ( !PyArg_ParseTuple(args,"ssidOO|is", &lookup, &subtable, - &separation, &class_error_distance, &list1, &list2, - &only_closer, &after_str )) + PyObject *arg8 = acnt>=8 ? PySequence_GetItem(args,7) : NULL; + if ( arg8!=NULL && (PyInt_Check(arg8) || PyLong_Check(arg8))) { + if ( !PyArg_ParseTuple(args,"ssidOO|iis", &lookup, &subtable, + &separation, &class_error_distance, &list1, &list2, + &only_closer, &autokern, &after_str )) return( NULL ); + } else { + if ( !PyArg_ParseTuple(args,"ssidOO|is", &lookup, &subtable, + &separation, &class_error_distance, &list1, &list2, + &only_closer, &after_str )) +return( NULL ); + } } else { - if ( !PyArg_ParseTuple(args,"ssid|is", &lookup, &subtable, - &separation, &class_error_distance, - &only_closer, &after_str )) + PyObject *arg6 = acnt>=6 ? PySequence_GetItem(args,5) : NULL; + if ( arg6!=NULL && (PyInt_Check(arg6) || PyLong_Check(arg6))) { + if ( !PyArg_ParseTuple(args,"ssid|iis", &lookup, &subtable, + &separation, &class_error_distance, + &only_closer, &autokern, &after_str )) return( NULL ); + } else { + if ( !PyArg_ParseTuple(args,"ssid|is", &lookup, &subtable, + &separation, &class_error_distance, + &only_closer, &after_str )) +return( NULL ); + } } if ( separation==0 ) touch=1; @@ -12880,6 +12835,7 @@ return( NULL ); sub->separation = separation; sub->kerning_by_touch = touch; sub->onlyCloser = only_closer; + sub->dontautokern = !autokern; } sub->kc = chunkalloc(sizeof(KernClass)); sub->kc->subtable = sub; diff --git a/fontforge/sfd.c b/fontforge/sfd.c index 25c15d72..b31f0d82 100644 --- a/fontforge/sfd.c +++ b/fontforge/sfd.c @@ -1626,10 +1626,10 @@ static void SFDDumpOtfFeatNames(FILE *sfd, SplineFont *sf) { fprintf( sfd, "OtfFeatName: '%c%c%c%c' ", fn->tag>>24, fn->tag>>16, fn->tag>>8, fn->tag ); for ( on=fn->names; on!=NULL; on=on->next ) { - fprintf( sfd, "%d ", on->lang ); + fprintf( sfd, " %d ", on->lang ); SFDDumpUTF7Str(sfd, on->name); + putc('\n',sfd); } - putc('\n',sfd); } } @@ -1961,7 +1961,7 @@ static int SFD_Dump(FILE *sfd,SplineFont *sf,EncMap *map,EncMap *normal, } else if ( otl->lookup_type==gpos_pair && sub->vertical_kerning ) fprintf(sfd,"(1)"); if ( otl->lookup_type==gpos_pair && (sub->separation!=0 || sub->kerning_by_touch)) - fprintf(sfd,"[%d,%d,%d]", sub->separation, sub->minkern, sub->kerning_by_touch+2*sub->onlyCloser ); + fprintf(sfd,"[%d,%d,%d]", sub->separation, sub->minkern, sub->kerning_by_touch+2*sub->onlyCloser+4*sub->dontautokern ); putc(' ',sfd); } fprintf( sfd, "} [" ); @@ -5979,6 +5979,7 @@ static void SFDParseLookup(FILE *sfd,SplineFont *sf,OTLookup *otl) { ch = nlgetc(sfd); sub->kerning_by_touch = ((ch-'0')&1)?1:0; sub->onlyCloser = ((ch-'0')&2)?1:0; + sub->dontautokern = ((ch-'0')&4)?1:0; nlgetc(sfd); /* slurp final bracket */ } else { ungetc(ch,sfd); diff --git a/fontforge/splinefont.h b/fontforge/splinefont.h index 15d35fb2..7da111bd 100644 --- a/fontforge/splinefont.h +++ b/fontforge/splinefont.h @@ -428,7 +428,8 @@ typedef struct otlookup { unsigned int vertical_kerning: 1; unsigned int ticked: 1; unsigned int kerning_by_touch: 1; /* for gpos_pair, calculate kerning so that glyphs will touch */ - unsigned int onlyCloser: 1; + unsigned int onlyCloser: 1; /* for kerning classes */ + unsigned int dontautokern: 1; /* for kerning classes */ struct kernclass *kc; struct generic_fpst *fpst; struct generic_asm *sm; diff --git a/fontforge/splineutil2.c b/fontforge/splineutil2.c index 9e718a4f..9e3a3437 100644 --- a/fontforge/splineutil2.c +++ b/fontforge/splineutil2.c @@ -24,7 +24,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "pfaedit.h" +#include "fontforge.h" #include <math.h> #include "ustring.h" #include "chardata.h" diff --git a/fontforge/stamp.c b/fontforge/stamp.c index 3c000b36..d32791dc 100644 --- a/fontforge/stamp.c +++ b/fontforge/stamp.c @@ -1,5 +1,5 @@ #include <time.h> -const time_t source_modtime = 1298320590L; -const char *source_modtime_str = "20:36 GMT 21-Feb-2011"; +const time_t source_modtime = 1298329534L; +const char *source_modtime_str = "23:05 GMT 21-Feb-2011"; const char *source_version_str = "20110221"; diff --git a/htdocs/python.html b/htdocs/python.html index eec8bdde..75b417ba 100644 --- a/htdocs/python.html +++ b/htdocs/python.html @@ -3684,7 +3684,7 @@ pen = None; # Finalize the pen. This tells FontForge separation,<BR> first-classes,<BR> second-classes<BR> - [,onlyCloser,after])</CODE> + [,onlyCloser,autokern,after])</CODE> <P ALIGN=Center> <STRONG>or</STRONG> <P> @@ -3692,13 +3692,13 @@ pen = None; # Finalize the pen. This tells FontForge separation,class-distance,<BR> ,first-glyph-list,<BR> second-glyph-list,<BR> - [,onlyCloser,after])</CODE> + [,onlyCloser,autokern,after])</CODE> <P ALIGN=Center> <STRONG>or</STRONG> <P> <CODE>(lookup-name,new-subtable-name,<BR> separation,class-distance,<BR> - [,onlyCloser,after])</CODE></TD> + [,onlyCloser,autokern,after])</CODE></TD> <TD>Creates a new subtable and a new kerning class in the named lookup. The classes arguments are tuples of tuples of glyph names (each sub-tuble of glyph names is a kerning class). The offsets argument is a tuple of kerning diff --git a/htdocs/sfdformat.html b/htdocs/sfdformat.html index d1cdb1e3..c864f6f5 100644 --- a/htdocs/sfdformat.html +++ b/htdocs/sfdformat.html @@ -430,9 +430,12 @@ Lookup: 258 0 0 "'kern' Horizontal Kerning in Latin lookup 0" {"'kern' Horizont represent default values for autokerning in this subtable, the first is the desired separation between glyphs, the next is the minimum (absolute) value that will generate a kerning pair (kerning by 1 em unit isn't interesting - and if that's what autokern comes up with, there is really no point to it), - and the last is an indication if separation is based on closest approach - (touching). + and if that's what autokern comes up with, there is really no point to it + and it wastes time), and the last is a set of bit flags: if the number is + odd then it means separation is based on closest approach (touching), if + the number has bit 2 set, then only negative (closer) kerning values will + be generated by autokerning and if the number has bit 4 set then no auto- + kerning will happen at all. <P> The order in which lookups are applied is the order listed here. The order in which subtables are applied is the order listed here. |