/* Copyright (C) 2002-2011 by George Williams */ /* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "fontforgeui.h" #include "ustring.h" #define CID_Extrema 1000 #define CID_Slopes 1001 #define CID_Error 1002 #define CID_Smooth 1003 #define CID_SmoothTan 1004 #define CID_SmoothHV 1005 #define CID_FlattenBumps 1006 #define CID_FlattenBound 1007 #define CID_LineLenMax 1008 #define CID_Start 1009 #define CID_SetAsDefault 1010 static double olderr_rat = 1/1000., oldsmooth_tan=.2, oldlinefixup_rat = 10./1000., oldlinelenmax_rat = 1/100.; static int set_as_default = true; static int oldextrema = false; static int oldslopes = false; static int oldsmooth = true; static int oldsmoothhv = true; static int oldlinefix = false; static int oldstart = false; typedef struct simplifydlg { int flags; double err; double tan_bounds; double linefixup; double linelenmax; int done; int cancelled; int em_size; int set_as_default; } Simple; static int Sim_OK(GGadget *g, GEvent *e) { if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) { Simple *sim = GDrawGetUserData(GGadgetGetWindow(g)); int badparse=false; sim->flags = 0; if ( GGadgetIsChecked(GWidgetGetControl(GGadgetGetWindow(g),CID_Extrema)) ) sim->flags = sf_ignoreextremum; if ( GGadgetIsChecked(GWidgetGetControl(GGadgetGetWindow(g),CID_Slopes)) ) sim->flags |= sf_ignoreslopes; if ( GGadgetIsChecked(GWidgetGetControl(GGadgetGetWindow(g),CID_Smooth)) ) sim->flags |= sf_smoothcurves; if ( GGadgetIsChecked(GWidgetGetControl(GGadgetGetWindow(g),CID_SmoothHV)) ) sim->flags |= sf_choosehv; if ( GGadgetIsChecked(GWidgetGetControl(GGadgetGetWindow(g),CID_FlattenBumps)) ) sim->flags |= sf_forcelines; if ( GGadgetIsChecked(GWidgetGetControl(GGadgetGetWindow(g),CID_Start)) ) sim->flags |= sf_setstart2extremum; sim->err = GetReal8(GGadgetGetWindow(g),CID_Error,_("_Error Limit:"),&badparse); if ( sim->flags&sf_smoothcurves ) sim->tan_bounds= GetReal8(GGadgetGetWindow(g),CID_SmoothTan,_("_Tangent"),&badparse); if ( sim->flags&sf_forcelines ) sim->linefixup= GetReal8(GGadgetGetWindow(g),CID_FlattenBound,_("Bump Size"),&badparse); sim->linelenmax = GetReal8(GGadgetGetWindow(g),CID_LineLenMax,_("Line length max"),&badparse); if ( badparse ) return( true ); olderr_rat = sim->err/sim->em_size; oldextrema = (sim->flags&sf_ignoreextremum); oldslopes = (sim->flags&sf_ignoreslopes); oldsmooth = (sim->flags&sf_smoothcurves); oldlinefix = (sim->flags&sf_forcelines); oldstart = (sim->flags&sf_setstart2extremum); if ( oldsmooth ) { oldsmooth_tan = sim->tan_bounds; oldsmoothhv = (sim->flags&sf_choosehv); } if ( oldlinefix ) oldlinefixup_rat = sim->linefixup/sim->em_size; oldlinelenmax_rat = sim->linelenmax/sim->em_size; sim->set_as_default = GGadgetIsChecked(GWidgetGetControl(GGadgetGetWindow(g),CID_SetAsDefault) ); sim->done = true; } return( true ); } static int Sim_Cancel(GGadget *g, GEvent *e) { if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) { Simple *sim = GDrawGetUserData(GGadgetGetWindow(g)); sim->done = sim->cancelled = true; } return( true ); } static int sim_e_h(GWindow gw, GEvent *event) { if ( event->type==et_close ) { Simple *sim = GDrawGetUserData(gw); sim->done = sim->cancelled = true; } else if ( event->type == et_char ) { return( false ); } else if ( event->type == et_map ) { /* Above palettes */ GDrawRaise(gw); } return( true ); } int SimplifyDlg(SplineFont *sf, struct simplifyinfo *smpl) { GRect pos; GWindow gw; GWindowAttrs wattrs; GGadgetCreateData gcd[24], boxes[7], *harray1[6], *harray2[6], *harray3[6], *harray4[4][6], *barray[9], *varray[18][2]; GTextInfo label[24]; Simple sim; char buffer[12], buffer2[12], buffer3[12], buffer4[12]; int k,l; memset(&sim,0,sizeof(sim)); sim.em_size = sf->ascent+sf->descent; memset(&wattrs,0,sizeof(wattrs)); wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict; wattrs.event_masks = ~(1<layers[ly_fore].order2 ) gcd[k].gd.flags = gg_visible|gg_utf8_popup; else { gcd[k].gd.flags = gg_enabled|gg_visible|gg_utf8_popup; if ( oldsmooth ) gcd[k].gd.flags |= gg_cb_on; } gcd[k].gd.popup_msg = (unichar_t *) _("Simplify will examine corner points whose control points are almost\ncolinear and smooth them into curve points"); gcd[k].gd.cid = CID_Smooth; gcd[k++].creator = GCheckBoxCreate; varray[l][0] = &gcd[k-1]; varray[l++][1] = NULL; /* GT: here "tan" means trigonometric tangent */ label[k].text = (unichar_t *) _("if tan less than"); label[k].text_is_1byte = true; gcd[k].gd.label = &label[k]; gcd[k].gd.pos.x = 20; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+24; gcd[k].gd.flags = gg_enabled|gg_visible; if ( sf->layers[ly_fore].order2 ) gcd[k].gd.flags = gg_visible; gcd[k++].creator = GLabelCreate; harray2[0] = GCD_HPad10; harray2[1] = &gcd[k-1]; sprintf( buffer2, "%.3g", oldsmooth_tan ); label[k].text = (unichar_t *) buffer2; label[k].text_is_1byte = true; gcd[k].gd.label = &label[k]; gcd[k].gd.pos.x = 94; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-6; gcd[k].gd.pos.width = 40; gcd[k].gd.flags = gg_enabled|gg_visible; if ( sf->layers[ly_fore].order2 ) gcd[k].gd.flags = gg_visible; gcd[k].gd.cid = CID_SmoothTan; gcd[k++].creator = GTextFieldCreate; harray2[2] = &gcd[k-1]; harray2[3] = GCD_Glue; harray2[4] = NULL; boxes[3].gd.flags = gg_enabled|gg_visible; boxes[3].gd.u.boxelements = harray2; boxes[3].creator = GHBoxCreate; varray[l][0] = &boxes[3]; varray[l++][1] = NULL; label[k].text = (unichar_t *) _("S_nap to horizontal/vertical"); label[k].text_is_1byte = true; label[k].text_in_resource = true; gcd[k].gd.label = &label[k]; gcd[k].gd.pos.x = 17; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+24; if ( sf->layers[ly_fore].order2 ) gcd[k].gd.flags = gg_visible; else { gcd[k].gd.flags = gg_enabled|gg_visible|gg_utf8_popup; if ( oldsmoothhv ) gcd[k].gd.flags |= gg_cb_on|gg_utf8_popup; } gcd[k].gd.popup_msg = (unichar_t *) _("If the slope of an adjusted point is near horizontal or vertical\nsnap to that"); gcd[k].gd.cid = CID_SmoothHV; gcd[k++].creator = GCheckBoxCreate; harray3[0] = GCD_HPad10; harray3[1] = &gcd[k-1]; harray3[2] = GCD_Glue; harray3[3] = NULL; boxes[4].gd.flags = gg_enabled|gg_visible; boxes[4].gd.u.boxelements = harray3; boxes[4].creator = GHBoxCreate; varray[l][0] = &boxes[4]; varray[l++][1] = NULL; label[k].text = (unichar_t *) _("_Flatten bumps on lines"); label[k].text_is_1byte = true; label[k].text_in_resource = true; gcd[k].gd.label = &label[k]; gcd[k].gd.pos.x = 8; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+14; if ( sf->layers[ly_fore].order2 ) gcd[k].gd.flags = gg_visible|gg_utf8_popup; else { gcd[k].gd.flags = gg_enabled|gg_visible|gg_utf8_popup; if ( oldlinefix ) gcd[k].gd.flags |= gg_cb_on; } gcd[k].gd.popup_msg = (unichar_t *) _("If a line has a bump on it then flatten out that bump"); gcd[k].gd.cid = CID_FlattenBumps; gcd[k++].creator = GCheckBoxCreate; varray[l][0] = &gcd[k-1]; varray[l++][1] = NULL; label[k].text = (unichar_t *) _("if smaller than"); label[k].text_is_1byte = true; gcd[k].gd.label = &label[k]; gcd[k].gd.pos.x = 20; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+24; gcd[k].gd.flags = gg_enabled|gg_visible; if ( sf->layers[ly_fore].order2 ) gcd[k].gd.flags = gg_visible; gcd[k++].creator = GLabelCreate; harray4[0][0] = GCD_HPad10; harray4[0][1] = &gcd[k-1]; sprintf( buffer3, "%.3g", oldlinefixup_rat*sim.em_size ); label[k].text = (unichar_t *) buffer3; label[k].text_is_1byte = true; gcd[k].gd.label = &label[k]; gcd[k].gd.pos.x = 90; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-6; gcd[k].gd.pos.width = 40; gcd[k].gd.flags = gg_enabled|gg_visible; if ( sf->layers[ly_fore].order2 ) gcd[k].gd.flags = gg_visible; gcd[k].gd.cid = CID_FlattenBound; gcd[k++].creator = GTextFieldCreate; harray4[0][2] = &gcd[k-1]; gcd[k].gd.pos.x = gcd[k-1].gd.pos.x+gcd[k-1].gd.pos.width+3; gcd[k].gd.pos.y = gcd[k-2].gd.pos.y; gcd[k].gd.flags = gg_visible | gg_enabled ; if ( sf->layers[ly_fore].order2 ) gcd[k].gd.flags = gg_visible; label[k].text = (unichar_t *) _("em-units"); label[k].text_is_1byte = true; gcd[k].gd.label = &label[k]; gcd[k++].creator = GLabelCreate; harray4[0][3] = &gcd[k-1]; harray4[0][4] = GCD_Glue; harray4[0][5] = NULL; label[k].text = (unichar_t *) _("Don't smooth lines"); label[k].text_is_1byte = true; gcd[k].gd.label = &label[k]; gcd[k].gd.pos.x = 8; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+14; gcd[k].gd.flags = gg_enabled|gg_visible; gcd[k++].creator = GLabelCreate; harray4[1][0] = &gcd[k-1]; harray4[1][1] = harray4[1][2] = harray4[1][3] = GCD_ColSpan; harray4[1][4] = GCD_Glue; harray4[1][5] = NULL; label[k].text = (unichar_t *) _("longer than"); label[k].text_is_1byte = true; gcd[k].gd.label = &label[k]; gcd[k].gd.pos.x = 20; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+24; gcd[k].gd.flags = gg_enabled|gg_visible; gcd[k++].creator = GLabelCreate; harray4[2][0] = GCD_HPad10; harray4[2][1] = &gcd[k-1]; sprintf( buffer4, "%.3g", oldlinelenmax_rat*sim.em_size ); label[k].text = (unichar_t *) buffer4; label[k].text_is_1byte = true; gcd[k].gd.label = &label[k]; gcd[k].gd.pos.x = 90; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-6; gcd[k].gd.pos.width = 40; gcd[k].gd.flags = gg_enabled|gg_visible; gcd[k].gd.cid = CID_LineLenMax; gcd[k++].creator = GTextFieldCreate; harray4[2][2] = &gcd[k-1]; gcd[k].gd.pos.x = gcd[k-1].gd.pos.x+gcd[k-1].gd.pos.width+3; gcd[k].gd.pos.y = gcd[k-2].gd.pos.y; gcd[k].gd.flags = gg_visible | gg_enabled ; label[k].text = (unichar_t *) _("em-units"); label[k].text_is_1byte = true; gcd[k].gd.label = &label[k]; gcd[k++].creator = GLabelCreate; harray4[2][3] = &gcd[k-1]; harray4[2][4] = GCD_Glue; harray4[2][5] = NULL; harray4[3][0] = NULL; boxes[5].gd.flags = gg_enabled|gg_visible; boxes[5].gd.u.boxelements = harray4[0]; boxes[5].creator = GHVBoxCreate; varray[l][0] = &boxes[5]; varray[l++][1] = NULL; gcd[k].gd.pos.x = 10; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+20; gcd[k].gd.flags = gg_visible | gg_enabled | (set_as_default ? gg_cb_on : 0); label[k].text = (unichar_t *) _("Set as Default"); label[k].text_is_1byte = true; gcd[k].gd.label = &label[k]; gcd[k].gd.cid = CID_SetAsDefault; gcd[k++].creator = GCheckBoxCreate; varray[l][0] = &gcd[k-1]; varray[l++][1] = NULL; gcd[k].gd.pos.x = 15; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y + 20; gcd[k].gd.pos.width = 150; gcd[k].gd.flags = gg_enabled|gg_visible; gcd[k++].creator = GLineCreate; varray[l][0] = &gcd[k-1]; varray[l++][1] = NULL; gcd[k].gd.pos.x = 20-3; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+30; gcd[k].gd.pos.width = -1; gcd[k].gd.pos.height = 0; gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_default; label[k].text = (unichar_t *) _("_OK"); label[k].text_is_1byte = true; label[k].text_in_resource = true; gcd[k].gd.mnemonic = 'O'; gcd[k].gd.label = &label[k]; gcd[k].gd.handle_controlevent = Sim_OK; gcd[k++].creator = GButtonCreate; barray[0] = GCD_Glue; barray[1] = &gcd[k-1]; barray[2] = GCD_Glue; gcd[k].gd.pos.x = -20; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+3; gcd[k].gd.pos.width = -1; gcd[k].gd.pos.height = 0; gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_cancel; label[k].text = (unichar_t *) _("_Cancel"); label[k].text_is_1byte = true; label[k].text_in_resource = true; gcd[k].gd.label = &label[k]; gcd[k].gd.mnemonic = 'C'; gcd[k].gd.handle_controlevent = Sim_Cancel; gcd[k++].creator = GButtonCreate; barray[3] = GCD_Glue; barray[4] = &gcd[k-1]; barray[5] = GCD_Glue; barray[6] = NULL; boxes[6].gd.flags = gg_enabled|gg_visible; boxes[6].gd.u.boxelements = barray; boxes[6].creator = GHBoxCreate; varray[l][0] = &boxes[6]; varray[l++][1] = NULL; varray[l][0] = NULL; boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2; boxes[0].gd.flags = gg_enabled|gg_visible; boxes[0].gd.u.boxelements = varray[0]; boxes[0].creator = GHVGroupCreate; GGadgetsCreate(gw,boxes); GWidgetIndicateFocusGadget(GWidgetGetControl(gw,CID_Error)); GTextFieldSelect(GWidgetGetControl(gw,CID_Error),0,-1); GHVBoxSetExpandableCol(boxes[2].ret,gb_expandglue); GHVBoxSetExpandableCol(boxes[3].ret,gb_expandglue); GHVBoxSetExpandableCol(boxes[4].ret,gb_expandglue); GHVBoxSetExpandableCol(boxes[5].ret,gb_expandglue); GHVBoxSetExpandableCol(boxes[6].ret,gb_expandgluesame); GHVBoxFitWindow(boxes[0].ret); GWidgetHidePalettes(); GDrawSetVisible(gw,true); while ( !sim.done ) GDrawProcessOneEvent(NULL); GDrawDestroyWindow(gw); if ( sim.cancelled ) return( false ); smpl->flags = sim.flags; smpl->err = sim.err; smpl->tan_bounds = sim.tan_bounds; smpl->linefixup = sim.linefixup; smpl->linelenmax = sim.linelenmax; smpl->set_as_default = sim.set_as_default; set_as_default = sim.set_as_default; return( true ); }