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