Line data Source code
1 : /* Copyright (C) 2000-2012 by George Williams */
2 : /*
3 : * Redistribution and use in source and binary forms, with or without
4 : * modification, are permitted provided that the following conditions are met:
5 :
6 : * Redistributions of source code must retain the above copyright notice, this
7 : * list of conditions and the following disclaimer.
8 :
9 : * Redistributions in binary form must reproduce the above copyright notice,
10 : * this list of conditions and the following disclaimer in the documentation
11 : * and/or other materials provided with the distribution.
12 :
13 : * The name of the author may not be used to endorse or promote products
14 : * derived from this software without specific prior written permission.
15 :
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 : * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 : * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 : #include "bvedit.h"
28 : #include "splineutil.h"
29 : #include "fontforgeui.h"
30 : #include <math.h>
31 : #include <ustring.h>
32 : #include "fvmetrics.h"
33 :
34 : typedef struct createwidthdlg {
35 : CreateWidthData wd;
36 : GWindow gw;
37 : } CreateWidthDlg;
38 :
39 : #define CID_Set 1001
40 : #define CID_Incr 1002
41 : #define CID_Scale 1003
42 : #define CID_SetVal 1011
43 : #define CID_IncrVal 1012
44 : #define CID_ScaleVal 1013
45 :
46 : static char *rb1[] = { N_("Set Width To:"), N_("Set LBearing To:"), N_("Set RBearing To:"), N_("Set Bearings To:"), N_("Set Vert. Advance To:") };
47 : static char *rb2[] = { N_("Increment Width By:"), N_("Increment LBearing By:"), N_("Increment RBearing By:"), N_("Increment Bearings By:"), N_("Increment V. Adv. By:") };
48 : static char *rb3[] = { N_("Scale Width By:"), N_("Scale LBearing By:"), N_("Scale RBearing By:"), N_("Scale Bearings By:"), N_("Scale VAdvance By:") };
49 : static char *info[] = { N_("Left Side Bearing does not change."), N_("Advance Width does not change."), N_("Left Side Bearing does not change."), N_("ThisSpaceIntentionallyLeftBlank-PleaseDoNotTranslate-LeaveThisOut|"), N_("Top Bearing does not change.") };
50 :
51 0 : static int CW_OK(GGadget *g, GEvent *e) {
52 :
53 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
54 0 : int err = false;
55 0 : CreateWidthDlg *wd = GDrawGetUserData(GGadgetGetWindow(g));
56 0 : if ( GGadgetIsChecked(GWidgetGetControl(wd->gw,CID_Set)) ) {
57 0 : wd->wd.type = st_set;
58 0 : wd->wd.setto = GetReal8(wd->gw,CID_SetVal,rb1[wd->wd.wtype],&err);
59 0 : if ( wd->wd.setto<0 && wd->wd.wtype==wt_width ) {
60 : char *yesno[3];
61 0 : yesno[0] = _("_Yes");
62 0 : yesno[1] = _("_No");
63 0 : yesno[2] = NULL;
64 0 : if ( gwwv_ask(_("Negative Width"), (const char **) yesno, 0, 1, _("Negative glyph widths are not allowed in TrueType\nDo you really want a negative width?") )==1 )
65 0 : return( true );
66 : }
67 0 : } else if ( GGadgetIsChecked(GWidgetGetControl(wd->gw,CID_Incr)) ) {
68 0 : wd->wd.type = st_incr;
69 0 : wd->wd.increment = GetReal8(wd->gw,CID_IncrVal,rb2[wd->wd.wtype],&err);
70 : } else {
71 0 : wd->wd.type = st_scale;
72 0 : wd->wd.scale = GetReal8(wd->gw,CID_ScaleVal,rb2[wd->wd.wtype],&err);
73 : }
74 0 : if ( err )
75 0 : return(true);
76 0 : (wd->wd.doit)((CreateWidthData *) wd);
77 : }
78 0 : return( true );
79 : }
80 :
81 0 : static int CW_Cancel(GGadget *g, GEvent *e) {
82 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
83 0 : CreateWidthDlg *wd = GDrawGetUserData(GGadgetGetWindow(g));
84 0 : wd->wd.done = true;
85 : }
86 0 : return( true );
87 : }
88 :
89 0 : static int CW_FocusChange(GGadget *g, GEvent *e) {
90 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_textfocuschanged ) {
91 0 : CreateWidthDlg *wd = GDrawGetUserData(GGadgetGetWindow(g));
92 0 : int cid = (intpt) GGadgetGetUserData(g);
93 0 : GGadgetSetChecked(GWidgetGetControl(wd->gw,cid),true);
94 : }
95 0 : return( true );
96 : }
97 :
98 0 : static int CW_RadioChange(GGadget *g, GEvent *e) {
99 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
100 0 : CreateWidthDlg *wd = GDrawGetUserData(GGadgetGetWindow(g));
101 0 : int cid = (intpt) GGadgetGetUserData(g);
102 0 : GWidgetIndicateFocusGadget(GWidgetGetControl(wd->gw,cid));
103 0 : GTextFieldSelect(GWidgetGetControl(wd->gw,cid),0,-1);
104 : }
105 0 : return( true );
106 : }
107 :
108 0 : static int cwd_e_h(GWindow gw, GEvent *event) {
109 0 : if ( event->type==et_close ) {
110 0 : CreateWidthDlg *wd = GDrawGetUserData(gw);
111 0 : wd->wd.done = true;
112 0 : } else if ( event->type == et_char ) {
113 0 : return( false );
114 0 : } else if ( event->type == et_map ) {
115 : /* Above palettes */
116 0 : GDrawRaise(gw);
117 : }
118 0 : return( true );
119 : }
120 :
121 0 : static void FVCreateWidth( void *_fv,SplineChar* _sc,void (*doit)(CreateWidthData *),
122 : enum widthtype wtype, char *def) {
123 : GRect pos;
124 : GWindowAttrs wattrs;
125 : GGadgetCreateData gcd[11], boxes[2], topbox[2], *hvs[17], *varray[8], *buttons[6];
126 : GTextInfo label[11];
127 : static CreateWidthDlg cwd;
128 : static GWindow winds[5];
129 : static char *title[] = { N_("Set Width..."), N_("Set LBearing..."), N_("Set RBearing..."), N_("Set Both Side Bearings..."), N_("Set Vertical Advance...") };
130 :
131 0 : cwd.wd.done = false;
132 0 : cwd.wd._fv = _fv;
133 0 : cwd.wd._sc = _sc;
134 0 : cwd.wd.wtype = wtype;
135 0 : cwd.wd.doit = doit;
136 0 : cwd.gw = winds[wtype];
137 :
138 0 : if ( cwd.gw==NULL ) {
139 0 : memset(&wattrs,0,sizeof(wattrs));
140 0 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
141 0 : wattrs.event_masks = ~(1<<et_charup);
142 0 : wattrs.restrict_input_to_me = 1;
143 0 : wattrs.undercursor = 1;
144 0 : wattrs.cursor = ct_pointer;
145 0 : wattrs.utf8_window_title = _(title[wtype]);
146 0 : wattrs.is_dlg = true;
147 0 : pos.x = pos.y = 0;
148 0 : pos.width = GGadgetScale(GDrawPointsToPixels(NULL,180));
149 0 : pos.height = GDrawPointsToPixels(NULL,100);
150 0 : cwd.gw = winds[wtype] = GDrawCreateTopWindow(NULL,&pos,cwd_e_h,&cwd,&wattrs);
151 :
152 0 : memset(&label,0,sizeof(label));
153 0 : memset(&gcd,0,sizeof(gcd));
154 :
155 0 : label[0].text = (unichar_t *) _(rb1[wtype]);
156 0 : label[0].text_is_1byte = true;
157 0 : gcd[0].gd.label = &label[0];
158 0 : gcd[0].gd.flags = gg_enabled|gg_visible|gg_cb_on;
159 0 : gcd[0].gd.cid = CID_Set;
160 0 : gcd[0].gd.handle_controlevent = CW_RadioChange;
161 0 : gcd[0].data = (void *) CID_SetVal;
162 0 : gcd[0].creator = GRadioCreate;
163 :
164 0 : label[1].text = (unichar_t *) _(rb2[wtype]);
165 0 : label[1].text_is_1byte = true;
166 0 : gcd[1].gd.label = &label[1];
167 0 : gcd[1].gd.flags = gg_enabled|gg_visible|gg_rad_continueold ;
168 0 : gcd[1].gd.cid = CID_Incr;
169 0 : gcd[1].gd.handle_controlevent = CW_RadioChange;
170 0 : gcd[1].data = (void *) CID_IncrVal;
171 0 : gcd[1].creator = GRadioCreate;
172 :
173 0 : label[2].text = (unichar_t *) _(rb3[wtype]);
174 0 : label[2].text_is_1byte = true;
175 0 : gcd[2].gd.label = &label[2];
176 0 : gcd[2].gd.flags = gg_enabled|gg_visible|gg_rad_continueold ;
177 0 : gcd[2].gd.cid = CID_Scale;
178 0 : gcd[2].gd.handle_controlevent = CW_RadioChange;
179 0 : gcd[2].data = (void *) CID_ScaleVal;
180 0 : gcd[2].creator = GRadioCreate;
181 :
182 0 : label[3].text = (unichar_t *) def;
183 0 : label[3].text_is_1byte = true;
184 0 : gcd[3].gd.label = &label[3];
185 0 : gcd[3].gd.pos.width = 60;
186 0 : gcd[3].gd.flags = gg_enabled|gg_visible;
187 0 : gcd[3].gd.cid = CID_SetVal;
188 0 : gcd[3].gd.handle_controlevent = CW_FocusChange;
189 0 : gcd[3].data = (void *) CID_Set;
190 0 : gcd[3].creator = GTextFieldCreate;
191 :
192 0 : label[4].text = (unichar_t *) "0";
193 0 : label[4].text_is_1byte = true;
194 0 : gcd[4].gd.label = &label[4];
195 0 : gcd[4].gd.pos.width = 60;
196 0 : gcd[4].gd.flags = gg_enabled|gg_visible;
197 0 : gcd[4].gd.cid = CID_IncrVal;
198 0 : gcd[4].gd.handle_controlevent = CW_FocusChange;
199 0 : gcd[4].data = (void *) CID_Incr;
200 0 : gcd[4].creator = GTextFieldCreate;
201 :
202 0 : label[5].text = (unichar_t *) "100";
203 0 : label[5].text_is_1byte = true;
204 0 : gcd[5].gd.label = &label[5];
205 0 : gcd[5].gd.pos.width = 60;
206 0 : gcd[5].gd.flags = gg_enabled|gg_visible;
207 0 : gcd[5].gd.cid = CID_ScaleVal;
208 0 : gcd[5].gd.handle_controlevent = CW_FocusChange;
209 0 : gcd[5].data = (void *) CID_Scale;
210 0 : gcd[5].creator = GTextFieldCreate;
211 :
212 0 : gcd[6].gd.flags = gg_visible | gg_enabled | gg_but_default;
213 0 : label[6].text = (unichar_t *) _("_OK");
214 0 : label[6].text_is_1byte = true;
215 0 : label[6].text_in_resource = true;
216 0 : gcd[6].gd.mnemonic = 'O';
217 0 : gcd[6].gd.label = &label[6];
218 0 : gcd[6].gd.handle_controlevent = CW_OK;
219 0 : gcd[6].creator = GButtonCreate;
220 :
221 0 : gcd[7].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
222 0 : label[7].text = (unichar_t *) _("_Cancel");
223 0 : label[7].text_is_1byte = true;
224 0 : label[7].text_in_resource = true;
225 0 : gcd[7].gd.label = &label[7];
226 0 : gcd[7].gd.mnemonic = 'C';
227 0 : gcd[7].gd.handle_controlevent = CW_Cancel;
228 0 : gcd[7].creator = GButtonCreate;
229 :
230 0 : label[8].text = (unichar_t *) S_(info[wtype]);
231 0 : label[8].text_is_1byte = true;
232 0 : gcd[8].gd.label = &label[8];
233 0 : gcd[8].gd.pos.x = 5; gcd[8].gd.pos.y = 59;
234 0 : gcd[8].gd.flags = gg_enabled|gg_visible ;
235 0 : gcd[8].creator = GLabelCreate;
236 :
237 0 : label[9].text = (unichar_t *) "%";
238 0 : label[9].text_is_1byte = true;
239 0 : gcd[9].gd.label = &label[9];
240 0 : gcd[9].gd.flags = gg_enabled|gg_visible;
241 0 : gcd[9].creator = GLabelCreate;
242 :
243 0 : hvs[0] = &gcd[0]; hvs[1] = &gcd[3]; hvs[2] = GCD_Glue; hvs[3] = NULL;
244 0 : hvs[4] = &gcd[1]; hvs[5] = &gcd[4]; hvs[6] = GCD_Glue; hvs[7] = NULL;
245 0 : hvs[8] = &gcd[2]; hvs[9] = &gcd[5]; hvs[10] = &gcd[9]; hvs[11] = NULL;
246 0 : hvs[12] = &gcd[8]; hvs[13] = GCD_ColSpan; hvs[14] = GCD_Glue; hvs[15] = NULL;
247 0 : hvs[16] = NULL;
248 :
249 0 : buttons[0] = buttons[2] = buttons[4] = GCD_Glue; buttons[5] = NULL;
250 0 : buttons[1] = &gcd[6]; buttons[3] = &gcd[7];
251 :
252 0 : varray[0] = &boxes[1]; varray[1] = NULL;
253 0 : varray[2] = GCD_Glue; varray[3] = NULL;
254 0 : varray[4] = &boxes[0]; varray[5] = NULL;
255 0 : varray[6] = NULL;
256 :
257 0 : memset(boxes,0,sizeof(boxes));
258 0 : boxes[0].gd.flags = gg_enabled|gg_visible;
259 0 : boxes[0].gd.u.boxelements = buttons;
260 0 : boxes[0].creator = GHBoxCreate;
261 :
262 0 : boxes[1].gd.flags = gg_enabled|gg_visible;
263 0 : boxes[1].gd.u.boxelements = hvs;
264 0 : boxes[1].creator = GHVBoxCreate;
265 :
266 0 : memset(topbox,0,sizeof(topbox));
267 0 : topbox[0].gd.pos.x = topbox[0].gd.pos.y = 2;
268 0 : topbox[0].gd.pos.width = pos.width-4; topbox[0].gd.pos.height = pos.height-4;
269 0 : topbox[0].gd.flags = gg_enabled|gg_visible;
270 0 : topbox[0].gd.u.boxelements = varray;
271 0 : topbox[0].creator = GHVGroupCreate;
272 :
273 0 : GGadgetsCreate(cwd.gw,topbox);
274 0 : GHVBoxSetExpandableRow(topbox[0].ret,1);
275 0 : GHVBoxSetExpandableCol(boxes[0].ret,gb_expandgluesame);
276 0 : GHVBoxSetExpandableCol(boxes[1].ret,1);
277 0 : GWidgetIndicateFocusGadget(GWidgetGetControl(cwd.gw,CID_SetVal));
278 0 : GTextFieldSelect(GWidgetGetControl(cwd.gw,CID_SetVal),0,-1);
279 0 : GHVBoxFitWindow(topbox[0].ret);
280 : } else {
281 0 : unichar_t *temp = uc_copy(def);
282 0 : GGadgetSetTitle(GWidgetGetControl(cwd.gw,CID_SetVal),temp);
283 0 : free( temp );
284 : }
285 :
286 0 : GWidgetHidePalettes();
287 0 : GDrawSetVisible(cwd.gw,true);
288 0 : while ( !cwd.wd.done )
289 0 : GDrawProcessOneEvent(NULL);
290 0 : GDrawSetVisible(cwd.gw,false);
291 0 : }
292 :
293 0 : static void BCDefWidthVal(char *buf,BDFChar *bc, FontView *fv, enum widthtype wtype) {
294 : IBounds bb;
295 :
296 0 : if ( wtype==wt_width )
297 0 : sprintf( buf, "%d", bc->width );
298 0 : else if ( wtype==wt_vwidth )
299 0 : sprintf( buf, "%d", fv->show->pixelsize );
300 : else {
301 0 : BDFCharFindBounds(bc,&bb);
302 0 : if ( wtype==wt_lbearing )
303 0 : sprintf( buf, "%d", bb.minx );
304 0 : else if ( wtype==wt_rbearing )
305 0 : sprintf( buf, "%d", bc->width-bb.maxx-1 );
306 : else
307 0 : sprintf( buf, "%d", (int) rint( (bc->width-bb.maxx-1 + bb.minx)/2 ));
308 : }
309 0 : }
310 :
311 0 : static void SCDefWidthVal(char *buf,SplineChar *sc, enum widthtype wtype) {
312 : DBounds bb;
313 :
314 0 : if ( wtype==wt_width )
315 0 : sprintf( buf, "%d", sc->width );
316 0 : else if ( wtype==wt_vwidth )
317 0 : sprintf( buf, "%d", sc->vwidth );
318 : else {
319 0 : SplineCharFindBounds(sc,&bb);
320 0 : if ( wtype==wt_lbearing )
321 0 : sprintf( buf, "%.4g", (double) bb.minx );
322 0 : else if ( wtype==wt_rbearing )
323 0 : sprintf( buf, "%.4g", sc->width-(double) bb.maxx );
324 : else
325 0 : sprintf( buf, "%.4g", rint( (sc->width-(double) bb.maxx + (double) bb.minx)/2 ) );
326 : }
327 0 : }
328 :
329 0 : void FVSetWidth(FontView *fv,enum widthtype wtype) {
330 : char buffer[12];
331 0 : int em = fv->b.sf->ascent + fv->b.sf->descent;
332 : int i, gid;
333 :
334 0 : if ( !fv->b.sf->onlybitmaps || fv->b.sf->bitmaps==NULL ) {
335 0 : sprintf(buffer,"%d",wtype==wt_width?6*em/10:wtype==wt_vwidth?em: em/10 );
336 0 : for ( i=0; i<fv->b.map->enccount; ++i ) if ( fv->b.selected[i] && (gid=fv->b.map->map[i])!=-1 && fv->b.sf->glyphs[gid]!=NULL ) {
337 0 : SCDefWidthVal(buffer,fv->b.sf->glyphs[gid],wtype);
338 0 : break;
339 : }
340 : } else {
341 0 : int size = fv->show->pixelsize;
342 0 : sprintf(buffer,"%d",wtype==wt_width?6*size/10:wtype==wt_vwidth?size: size/10 );
343 0 : for ( i=0; i<fv->b.map->enccount; ++i ) if ( fv->b.selected[i] && (gid=fv->b.map->map[i])!=-1 && fv->show->glyphs[gid]!=NULL ) {
344 0 : BCDefWidthVal(buffer,fv->show->glyphs[gid],fv,wtype);
345 0 : break;
346 : }
347 : }
348 0 : FVCreateWidth(fv,0,FVDoit,wtype,buffer);
349 0 : }
350 :
351 0 : void CVSetWidth(CharView *cv,enum widthtype wtype) {
352 : char buf[10];
353 :
354 0 : SCDefWidthVal(buf,cv->b.sc,wtype);
355 0 : FVCreateWidth(cv,cv->b.sc,CVDoit,wtype,buf);
356 0 : }
357 :
358 :
359 0 : void GenericVSetWidth(FontView *fv,SplineChar* sc,enum widthtype wtype) {
360 : char buf[10];
361 :
362 0 : SCDefWidthVal(buf,sc,wtype);
363 0 : FVCreateWidth(fv,sc,GenericVDoit,wtype,buf);
364 0 : }
365 :
|