1 /* Copyright (C) 2009-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
28 #include <fontforge-config.h>
29
30 #include "autowidth2.h"
31 #include "fontforgeui.h"
32 #include "gkeysym.h"
33 #include "ustring.h"
34 #include "utype.h"
35
36 #include <math.h>
37
38 static int width_last_em_size=1000;
39 static int width_separation=150;
40 static int width_min_side_bearing=10;
41 static int width_max_side_bearing=300;
42 static int width_chunk_height=10;
43 static int width_loop_cnt=1;
44
45 #define CID_Separation 1001
46 #define CID_MinSep 1002
47 #define CID_MaxSep 1003
48 #define CID_Height 1004
49 #define CID_Loop 1005
50
51 struct widthinfo {
52 int done;
53 GWindow gw;
54 FontView *fv;
55 SplineFont *sf;
56 };
57
AW2_OK(GGadget * g,GEvent * e)58 static int AW2_OK(GGadget *g, GEvent *e) {
59 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
60 GWindow gw = GGadgetGetWindow(g);
61 struct widthinfo *wi = GDrawGetUserData(gw);
62 int err = false;
63 int separation, min_side, max_side, height, loop;
64
65 separation = GetInt8(gw,CID_Separation, _("Separation"),&err);
66 min_side = GetInt8(gw,CID_MinSep, _("Min Bearing"),&err);
67 max_side = GetInt8(gw,CID_MaxSep, _("Max Bearing"),&err);
68 height = GetInt8(gw,CID_Height, _("Height"),&err);
69 loop = GetInt8(gw,CID_Loop, _("Loop Count"),&err);
70 if ( err )
71 return( true );
72
73 GDrawSetVisible(gw,false);
74 GDrawSync(NULL);
75 GDrawProcessPendingEvents(NULL);
76
77 width_last_em_size = wi->sf->ascent + wi->sf->descent;
78 width_separation = separation;
79 wi->sf->width_separation=separation;
80 if ( wi->sf->italicangle==0 )
81 width_min_side_bearing = min_side;
82 width_max_side_bearing = max_side;
83 width_chunk_height = height;
84 width_loop_cnt = loop;
85
86 AutoWidth2((FontViewBase *) wi->fv,separation,min_side,max_side,
87 height, loop);
88 wi->done = true;
89 }
90 return( true );
91 }
92
AW2_Cancel(GGadget * g,GEvent * e)93 static int AW2_Cancel(GGadget *g, GEvent *e) {
94 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
95 GWindow gw = GGadgetGetWindow(g);
96 struct widthinfo *wi = GDrawGetUserData(gw);
97 wi->done = true;
98 }
99 return( true );
100 }
101
AW2_e_h(GWindow gw,GEvent * event)102 static int AW2_e_h(GWindow gw, GEvent *event) {
103 if ( event->type==et_close ) {
104 struct widthinfo *wi = GDrawGetUserData(gw);
105 wi->done = true;
106 } else if ( event->type == et_char ) {
107 if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
108 /*struct widthinfo *wi = GDrawGetUserData(gw);*/
109 help("ui/dialogs/autowidth.html", NULL);
110 return( true );
111 }
112 return( false );
113 }
114 return( true );
115 }
116
FVAutoWidth2(FontView * fv)117 void FVAutoWidth2(FontView *fv) {
118 struct widthinfo wi;
119 GWindow gw;
120 GWindowAttrs wattrs;
121 GRect pos;
122 GGadgetCreateData *harray1[4], *harray2[6], *harray3[6], *barray[9], *varray[14];
123 GGadgetCreateData gcd[29], boxes[6];
124 GTextInfo label[29];
125 int i,v;
126 char sepbuf[20], minbuf[20], maxbuf[20], hbuf[20], lbuf[20];
127 SplineFont *sf = fv->b.sf;
128 double emsize = (sf->ascent + sf->descent);
129
130 memset(&wi,0,sizeof(wi));
131 wi.fv = fv;
132 wi.sf = sf;
133
134 memset(&wattrs,0,sizeof(wattrs));
135 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict|wam_isdlg;
136 wattrs.event_masks = ~(1<<et_charup);
137 wattrs.restrict_input_to_me = 1;
138 wattrs.is_dlg = 1;
139 wattrs.undercursor = 1;
140 wattrs.cursor = ct_pointer;
141 wattrs.utf8_window_title = _("Auto Width");
142 pos.x = pos.y = 0;
143 pos.width = GGadgetScale(GDrawPointsToPixels(NULL,200));
144 pos.height = GDrawPointsToPixels(NULL,180);
145 wi.gw = gw = GDrawCreateTopWindow(NULL,&pos,AW2_e_h,&wi,&wattrs);
146
147 memset(&label,0,sizeof(label));
148 memset(&boxes,0,sizeof(boxes));
149 memset(&gcd,0,sizeof(gcd));
150
151 i = v = 0;
152
153 label[i].text = (unichar_t *) _(
154 "FontForge will attempt to adjust the left and right\n"
155 "sidebearings of the selected glyphs so that the average\n"
156 "separation between glyphs in a script will be the\n"
157 "specified amount. You may also specify a minimum and\n"
158 "maximum value for each glyph's sidebearings." );
159 label[i].text_is_1byte = true;
160 gcd[i].gd.label = &label[i];
161 gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 6;
162 gcd[i].gd.flags = gg_visible | gg_enabled;
163 gcd[i++].creator = GLabelCreate;
164 varray[v++] = &gcd[i-1]; varray[v++] = NULL;
165
166 label[i].text = (unichar_t *) _( "_Separation:" );
167 label[i].text_is_1byte = true;
168 label[i].text_in_resource = true;
169 gcd[i].gd.label = &label[i];
170 gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 6;
171 gcd[i].gd.flags = gg_visible | gg_enabled;
172 gcd[i++].creator = GLabelCreate;
173 harray1[0] = &gcd[i-1];
174
175 if ( sf->width_separation>0 )
176 sprintf( sepbuf, "%d", sf->width_separation );
177 else
178 sprintf( sepbuf, "%d", (int) rint( width_separation * emsize / width_last_em_size ));
179 label[i].text = (unichar_t *) sepbuf;
180 label[i].text_is_1byte = true;
181 gcd[i].gd.label = &label[i];
182 gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 6;
183 gcd[i].gd.flags = gg_visible | gg_enabled;
184 gcd[i].gd.cid = CID_Separation;
185 gcd[i++].creator = GTextFieldCreate;
186 harray1[1] = &gcd[i-1]; harray1[2] = GCD_Glue; harray1[3] = NULL;
187
188 boxes[2].gd.flags = gg_enabled|gg_visible;
189 boxes[2].gd.u.boxelements = harray1;
190 boxes[2].creator = GHBoxCreate;
191 varray[v++] = &boxes[2]; varray[v++] = NULL;
192
193 label[i].text = (unichar_t *) _( "_Min:" );
194 label[i].text_is_1byte = true;
195 label[i].text_in_resource = true;
196 gcd[i].gd.label = &label[i];
197 gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 6;
198 gcd[i].gd.flags = gg_visible | gg_enabled;
199 gcd[i++].creator = GLabelCreate;
200 harray2[0] = &gcd[i-1];
201
202 if ( sf->italicangle<0 )
203 sprintf( minbuf, "%d", (int) rint( sf->descent*tan(sf->italicangle*FF_PI/180 )) );
204 else if ( sf->italicangle>0 )
205 sprintf( minbuf, "%d", (int) -rint( sf->ascent*tan(sf->italicangle*FF_PI/180 )) );
206 else
207 sprintf( minbuf, "%d", (int) rint( width_min_side_bearing * emsize / width_last_em_size ));
208 label[i].text = (unichar_t *) minbuf;
209 label[i].text_is_1byte = true;
210 gcd[i].gd.label = &label[i];
211 gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 6;
212 gcd[i].gd.flags = gg_visible | gg_enabled;
213 gcd[i].gd.cid = CID_MinSep;
214 gcd[i++].creator = GTextFieldCreate;
215 harray2[1] = &gcd[i-1];
216
217 label[i].text = (unichar_t *) _( "Ma_x:" );
218 label[i].text_is_1byte = true;
219 label[i].text_in_resource = true;
220 gcd[i].gd.label = &label[i];
221 gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 6;
222 gcd[i].gd.flags = gg_visible | gg_enabled;
223 gcd[i++].creator = GLabelCreate;
224 harray2[2] = &gcd[i-1];
225
226 sprintf( maxbuf, "%d", (int) rint( width_max_side_bearing * emsize / width_last_em_size ));
227 label[i].text = (unichar_t *) maxbuf;
228 label[i].text_is_1byte = true;
229 gcd[i].gd.label = &label[i];
230 gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 6;
231 gcd[i].gd.flags = gg_visible | gg_enabled;
232 gcd[i].gd.cid = CID_MaxSep;
233 gcd[i++].creator = GTextFieldCreate;
234 harray2[3] = &gcd[i-1]; harray2[4] = GCD_Glue; harray2[5] = NULL;
235
236 boxes[3].gd.flags = gg_enabled|gg_visible;
237 boxes[3].gd.u.boxelements = harray2;
238 boxes[3].creator = GHBoxCreate;
239 varray[v++] = &boxes[3]; varray[v++] = NULL;
240
241 label[i].text = (unichar_t *) _( "_Height:" );
242 label[i].text_is_1byte = true;
243 label[i].text_in_resource = true;
244 gcd[i].gd.label = &label[i];
245 gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 6;
246 gcd[i].gd.flags = /* gg_visible |*/ gg_enabled;
247 gcd[i++].creator = GLabelCreate;
248 harray3[0] = &gcd[i-1];
249
250 sprintf( hbuf, "%d", (int) rint( width_chunk_height * emsize / width_last_em_size ));
251 label[i].text = (unichar_t *) hbuf;
252 label[i].text_is_1byte = true;
253 gcd[i].gd.label = &label[i];
254 gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 6;
255 gcd[i].gd.flags = /* gg_visible |*/ gg_enabled;
256 gcd[i].gd.cid = CID_Height;
257 gcd[i++].creator = GTextFieldCreate;
258 harray3[1] = &gcd[i-1];
259
260 label[i].text = (unichar_t *) _( "_Loops:" );
261 label[i].text_is_1byte = true;
262 label[i].text_in_resource = true;
263 gcd[i].gd.label = &label[i];
264 gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 6;
265 gcd[i].gd.flags = /* gg_visible |*/ gg_enabled;
266 gcd[i++].creator = GLabelCreate;
267 harray3[2] = &gcd[i-1];
268
269 sprintf( lbuf, "%d", (int) rint( width_loop_cnt * emsize / width_last_em_size ));
270 label[i].text = (unichar_t *) lbuf;
271 label[i].text_is_1byte = true;
272 gcd[i].gd.label = &label[i];
273 gcd[i].gd.pos.x = 5; gcd[i].gd.pos.y = 6;
274 gcd[i].gd.flags = /* gg_visible |*/ gg_enabled;
275 gcd[i].gd.cid = CID_Loop;
276 gcd[i++].creator = GTextFieldCreate;
277 harray3[3] = &gcd[i-1]; harray3[4] = GCD_Glue; harray3[5] = NULL;
278
279 boxes[4].gd.flags = gg_enabled/*|gg_visible*/;
280 boxes[4].gd.u.boxelements = harray3;
281 boxes[4].creator = GHBoxCreate;
282 varray[v++] = &boxes[4]; varray[v++] = NULL;
283
284 gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_default;
285 label[i].text = (unichar_t *) _("_OK");
286 label[i].text_is_1byte = true;
287 label[i].text_in_resource = true;
288 gcd[i].gd.label = &label[i];
289 gcd[i].gd.handle_controlevent = AW2_OK;
290 gcd[i++].creator = GButtonCreate;
291 barray[0] = GCD_Glue; barray[1] = &gcd[i-1]; barray[2] = GCD_Glue;
292
293 gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
294 label[i].text = (unichar_t *) _("_Cancel");
295 label[i].text_is_1byte = true;
296 label[i].text_in_resource = true;
297 gcd[i].gd.label = &label[i];
298 gcd[i].gd.handle_controlevent = AW2_Cancel;
299 gcd[i++].creator = GButtonCreate;
300 barray[3] = barray[4] = GCD_Glue;
301 barray[5] = &gcd[i-1]; barray[6] = GCD_Glue; barray[7] = NULL;
302
303 boxes[5].gd.flags = gg_enabled|gg_visible;
304 boxes[5].gd.u.boxelements = barray;
305 boxes[5].creator = GHBoxCreate;
306 varray[v++] = GCD_Glue; varray[v++] = NULL;
307 varray[v++] = &boxes[5]; varray[v++] = NULL; varray[v++] = NULL;
308
309 boxes[0].gd.pos.x = gcd[i].gd.pos.y = 2;
310 boxes[0].gd.flags = gg_enabled|gg_visible;
311 boxes[0].gd.u.boxelements = varray;
312 boxes[0].creator = GHVGroupCreate;
313
314 GGadgetsCreate(gw,boxes);
315 GHVBoxSetExpandableRow(boxes[0].ret,gb_expandglue);
316 GHVBoxSetExpandableCol(boxes[2].ret,gb_expandglue);
317 GHVBoxSetExpandableCol(boxes[3].ret,gb_expandglue);
318 GHVBoxSetExpandableCol(boxes[4].ret,gb_expandglue);
319 GHVBoxSetExpandableCol(boxes[5].ret,gb_expandgluesame);
320 GHVBoxFitWindow(boxes[0].ret);
321
322 GWidgetIndicateFocusGadget(gcd[2].ret);
323 GTextFieldSelect(gcd[2].ret,0,-1);
324 GWidgetHidePalettes();
325 GDrawSetVisible(gw,true);
326 while ( !wi.done )
327 GDrawProcessOneEvent(NULL);
328 GDrawDestroyWindow(gw);
329 }
330