1 /* -*- coding: utf-8 -*- */
2 /* Copyright (C) 2007-2012 by George Williams */
3 /*
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13
14 * The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <fontforge-config.h>
30
31 #include "autohint.h"
32 #include "cvundoes.h"
33 #include "dumppfa.h"
34 #include "fontforgeui.h"
35 #include "gkeysym.h"
36 #include "scstyles.h"
37 #include "ustring.h"
38 #include "utype.h"
39
40 #include <math.h>
41
42 /* Code for various stylistic changes embolden/thin, condense/extend, oblique */
43
44
45 /* ************************************************************************** */
46 /* ***************************** Condense/Extend **************************** */
47 /* ************************************************************************** */
48
CVCondenseExtend(CharView * cv,struct counterinfo * ci)49 static void CVCondenseExtend(CharView *cv,struct counterinfo *ci) {
50 SplineChar *sc = cv->b.sc;
51
52 if ( cv->b.drawmode == dm_grid )
53 return;
54
55 SCCondenseExtend(ci, sc, CVLayer((CharViewBase *) cv),true);
56
57 free( ci->zones[0]);
58 free( ci->zones[1]);
59 }
60
61 typedef struct styledlg {
62 int done;
63 GWindow gw;
64 CharView *cv;
65 FontView *fv;
66 SplineFont *sf;
67 int layer;
68 struct smallcaps *small;
69 enum glyphchange_type gc;
70 bigreal scale;
71 } StyleDlg;
72
73 #define CID_C_Factor 1001
74 #define CID_C_Add 1002
75 #define CID_SB_Factor 1003
76 #define CID_SB_Add 1004
77 #define CID_CorrectItalic 1005
78
79 static struct counterinfo last_ci = {
80 90, 0, 90, 0, true,
81 /* initializers below are dummy... will be set later */
82 BLUEDATA_EMPTY, 0, NULL, 0, DBOUNDS_EMPTY, 0.0, 0.0, 0.0, 0,
83 { 0, 0 }, /* cnts */
84 { 0, 0 }, /* maxes */
85 { NULL, NULL } /* zones */
86 };
87
CondenseExtend_OK(GGadget * g,GEvent * e)88 static int CondenseExtend_OK(GGadget *g, GEvent *e) {
89 struct counterinfo ci;
90 int err = false;
91
92 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
93 GWindow ew = GGadgetGetWindow(g);
94 StyleDlg *ed = GDrawGetUserData(ew);
95 memset(&ci,0,sizeof(ci));
96 err = false;
97 ci.c_factor = GetReal8(ew,CID_C_Factor,_("Counter Expansion Factor"),&err);
98 ci.c_add = GetReal8(ew,CID_C_Add,_("Counter Addition"),&err);
99 ci.sb_factor = GetReal8(ew,CID_SB_Factor,_("Side Bearing Expansion Factor"),&err);
100 ci.sb_add = GetReal8(ew,CID_SB_Add,_("Side Bearing Addition"),&err);
101 ci.correct_italic= GGadgetIsChecked( GWidgetGetControl(ew,CID_CorrectItalic));
102 if ( err )
103 return( true );
104
105 last_ci = ci;
106
107 CI_Init(&ci,ed->sf);
108 if ( ed->fv!=NULL )
109 FVCondenseExtend((FontViewBase *) ed->fv, &ci);
110 else
111 CVCondenseExtend(ed->cv, &ci);
112 ed->done = true;
113 }
114 return( true );
115 }
116
CondenseExtend_Cancel(GGadget * g,GEvent * e)117 static int CondenseExtend_Cancel(GGadget *g, GEvent *e) {
118 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
119 StyleDlg *ed = GDrawGetUserData(GGadgetGetWindow(g));
120 ed->done = true;
121 }
122 return( true );
123 }
124
style_e_h(GWindow gw,GEvent * event)125 static int style_e_h(GWindow gw, GEvent *event) {
126 if ( event->type==et_close ) {
127 StyleDlg *ed = GDrawGetUserData(gw);
128 ed->done = true;
129 } else if ( event->type == et_char ) {
130 if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
131 help("ui/dialogs/Styles.html", NULL);
132 return( true );
133 }
134 return( false );
135 }
136 return( true );
137 }
138
CondenseExtendDlg(FontView * fv,CharView * cv)139 void CondenseExtendDlg(FontView *fv, CharView *cv) {
140 StyleDlg ed;
141 SplineFont *sf = fv!=NULL ? fv->b.sf : cv->b.sc->parent;
142 GRect pos;
143 GWindow gw;
144 GWindowAttrs wattrs;
145 GGadgetCreateData gcd[15], boxes[6], *barray[8], *hvarray[31];
146 GTextInfo label[15];
147 int k;
148 char c_factor[40], c_add[40], sb_factor[40], sb_add[40];
149
150 memset(&ed,0,sizeof(ed));
151 ed.fv = fv;
152 ed.cv = cv;
153 ed.sf = sf;
154
155 memset(&wattrs,0,sizeof(wattrs));
156 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
157 wattrs.event_masks = ~(1<<et_charup);
158 wattrs.restrict_input_to_me = 1;
159 wattrs.undercursor = 1;
160 wattrs.cursor = ct_pointer;
161 wattrs.utf8_window_title = _("Condense/Extend");
162 wattrs.is_dlg = true;
163 pos.x = pos.y = 0;
164 pos.width = 100;
165 pos.height = 100;
166 ed.gw = gw = GDrawCreateTopWindow(NULL,&pos,style_e_h,&ed,&wattrs);
167
168
169 k=0;
170
171 memset(gcd,0,sizeof(gcd));
172 memset(boxes,0,sizeof(boxes));
173 memset(label,0,sizeof(label));
174
175 hvarray[0] = GCD_Glue;
176
177 label[k].text = (unichar_t *) _("Scale By");
178 label[k].text_is_1byte = true;
179 label[k].text_in_resource = true;
180 gcd[k].gd.label = &label[k];
181 gcd[k].gd.flags = gg_enabled | gg_visible;
182 gcd[k++].creator = GLabelCreate;
183 hvarray[1] = &gcd[k-1];
184 hvarray[2] = GCD_Glue;
185
186 label[k].text = (unichar_t *) _("Add");
187 label[k].text_is_1byte = true;
188 label[k].text_in_resource = true;
189 gcd[k].gd.label = &label[k];
190 gcd[k].gd.flags = gg_enabled | gg_visible;
191 gcd[k++].creator = GLabelCreate;
192 hvarray[3] = &gcd[k-1];
193 hvarray[4] = NULL;
194
195 label[k].text = (unichar_t *) _("Counters:");
196 label[k].text_is_1byte = true;
197 label[k].text_in_resource = true;
198 gcd[k].gd.label = &label[k];
199 gcd[k].gd.flags = gg_enabled | gg_visible;
200 gcd[k++].creator = GLabelCreate;
201 hvarray[5] = &gcd[k-1];
202
203 sprintf( c_factor, "%g", last_ci.c_factor );
204 label[k].text = (unichar_t *) c_factor;
205 label[k].text_is_1byte = true;
206 gcd[k].gd.label = &label[k];
207 gcd[k].gd.pos.width = 60;
208 gcd[k].gd.flags = gg_enabled | gg_visible;
209 gcd[k].gd.cid = CID_C_Factor;
210 gcd[k++].creator = GNumericFieldCreate;
211 hvarray[6] = &gcd[k-1];
212
213 label[k].text = (unichar_t *) " % + ";
214 label[k].text_is_1byte = true;
215 label[k].text_in_resource = true;
216 gcd[k].gd.label = &label[k];
217 gcd[k].gd.flags = gg_enabled | gg_visible;
218 gcd[k++].creator = GLabelCreate;
219 hvarray[7] = &gcd[k-1];
220
221 sprintf( c_add, "%g", last_ci.c_add );
222 label[k].text = (unichar_t *) c_add;
223 label[k].text_is_1byte = true;
224 gcd[k].gd.label = &label[k];
225 gcd[k].gd.pos.width = 60;
226 gcd[k].gd.flags = gg_enabled | gg_visible;
227 gcd[k].gd.cid = CID_C_Add;
228 gcd[k++].creator = GNumericFieldCreate;
229 hvarray[8] = &gcd[k-1];
230 hvarray[9] = NULL;
231
232 label[k].text = (unichar_t *) _("Side Bearings:");
233 label[k].text_is_1byte = true;
234 label[k].text_in_resource = true;
235 gcd[k].gd.label = &label[k];
236 gcd[k].gd.flags = gg_enabled | gg_visible;
237 gcd[k++].creator = GLabelCreate;
238 hvarray[10] = &gcd[k-1];
239
240 sprintf( sb_factor, "%g", last_ci.sb_factor );
241 label[k].text = (unichar_t *) sb_factor;
242 label[k].text_is_1byte = true;
243 gcd[k].gd.label = &label[k];
244 gcd[k].gd.pos.width = 60;
245 gcd[k].gd.flags = gg_enabled | gg_visible;
246 gcd[k].gd.cid = CID_SB_Factor;
247 gcd[k++].creator = GNumericFieldCreate;
248 hvarray[11] = &gcd[k-1];
249
250 label[k].text = (unichar_t *) " % + ";
251 label[k].text_is_1byte = true;
252 label[k].text_in_resource = true;
253 gcd[k].gd.label = &label[k];
254 gcd[k].gd.flags = gg_enabled | gg_visible;
255 gcd[k++].creator = GLabelCreate;
256 hvarray[12] = &gcd[k-1];
257
258 sprintf( sb_add, "%g", last_ci.sb_add );
259 label[k].text = (unichar_t *) sb_add;
260 label[k].text_is_1byte = true;
261 gcd[k].gd.label = &label[k];
262 gcd[k].gd.pos.width = 60;
263 gcd[k].gd.flags = gg_enabled | gg_visible;
264 gcd[k].gd.cid = CID_SB_Add;
265 gcd[k++].creator = GNumericFieldCreate;
266 hvarray[13] = &gcd[k-1];
267 hvarray[14] = NULL;
268
269 label[k].text = (unichar_t *) _("Correct for Italic Angle");
270 label[k].text_is_1byte = true;
271 label[k].text_in_resource = true;
272 gcd[k].gd.label = &label[k];
273 gcd[k].gd.flags = gg_enabled | gg_visible| (last_ci.correct_italic?gg_cb_on:0);
274 gcd[k].gd.cid = CID_CorrectItalic;
275 gcd[k].gd.popup_msg = _("When FontForge detects that an expanded stroke will self-intersect,\nthen setting this option will cause it to try to make things nice\nby removing the intersections");
276 gcd[k++].creator = GCheckBoxCreate;
277 hvarray[15] = &gcd[k-1];
278 hvarray[16] = hvarray[17] = hvarray[18] = GCD_ColSpan; hvarray[19] = NULL;
279 if ( sf->italicangle==0 )
280 gcd[k-1].gd.flags = ~gg_enabled;
281
282 hvarray[20] = hvarray[21] = hvarray[22] = hvarray[23] = GCD_ColSpan; hvarray[24] = NULL;
283
284 gcd[k].gd.pos.x = 30-3; gcd[k].gd.pos.y = 5;
285 gcd[k].gd.pos.width = -1;
286 gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_default;
287 label[k].text = (unichar_t *) _("_OK");
288 label[k].text_is_1byte = true;
289 label[k].text_in_resource = true;
290 gcd[k].gd.label = &label[k];
291 gcd[k].gd.handle_controlevent = CondenseExtend_OK;
292 gcd[k++].creator = GButtonCreate;
293 barray[0] = GCD_Glue; barray[1] = &gcd[k-1]; barray[2] = GCD_Glue;
294
295 gcd[k].gd.pos.x = -30; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+3;
296 gcd[k].gd.pos.width = -1;
297 gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
298 label[k].text = (unichar_t *) _("_Cancel");
299 label[k].text_is_1byte = true;
300 label[k].text_in_resource = true;
301 gcd[k].gd.label = &label[k];
302 gcd[k].gd.handle_controlevent = CondenseExtend_Cancel;
303 gcd[k].creator = GButtonCreate;
304 barray[3] = GCD_Glue; barray[4] = &gcd[k]; barray[5] = GCD_Glue;
305 barray[6] = NULL;
306
307 boxes[3].gd.flags = gg_enabled|gg_visible;
308 boxes[3].gd.u.boxelements = barray;
309 boxes[3].creator = GHBoxCreate;
310 hvarray[25] = &boxes[3];
311 hvarray[26] = hvarray[27] = hvarray[28] = GCD_ColSpan; hvarray[29] = NULL;
312 hvarray[30] = NULL;
313
314 boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
315 boxes[0].gd.flags = gg_enabled|gg_visible;
316 boxes[0].gd.u.boxelements = hvarray;
317 boxes[0].creator = GHVGroupCreate;
318
319 GGadgetsCreate(gw,boxes);
320 GHVBoxSetExpandableRow(boxes[0].ret,gb_expandglue);
321 GHVBoxSetExpandableCol(boxes[3].ret,gb_expandgluesame);
322 GHVBoxFitWindow(boxes[0].ret);
323 GDrawSetVisible(gw,true);
324
325 while ( !ed.done )
326 GDrawProcessOneEvent(NULL);
327 GDrawDestroyWindow(gw);
328 }
329
330 /* ************************************************************************** */
331 /* ************************* Generic Change Dialog ************************** */
332 /* ************************************************************************** */
333
334 #undef CID_Letter_Ext
335 #undef CID_Symbol_Ext
336 #undef CID_Symbols_Too
337
338 #undef CID_HScale
339 #undef CID_VScale
340
341 #define CID_Feature 1001
342 #define CID_Extension 1002
343 #define CID_StemsUniform 1003
344 #define CID_Stems_H_V 1004
345 #define CID_Stems_by_Width 1005
346 #define CID_StemThreshold 1006
347 #define CID_StemHeight 1007
348 #define CID_StemHeightLabel 1008
349 #define CID_StemWidth 1009
350 #define CID_StemWidthLabel 1010
351 #define CID_StemHeightAdd 1011
352 #define CID_StemWidthAdd 1012
353 #define CID_DStemOn 1013
354
355 #define CID_Counter_SameAdvance 1020
356 #define CID_Counter_PropAdvance 1021
357 #define CID_Counter_is_SideB 1022
358 #define CID_Counter_isnt_SideB 1023
359 #define CID_CounterPercent 1024
360 #define CID_CounterAdd 1025
361 #define CID_LSBPercent 1026
362 #define CID_LSBAdd 1027
363 #define CID_RSBPercent 1028
364 #define CID_RSBAdd 1029
365
366 #define CID_UseVerticalCounters 1040
367 #define CID_VCounterPercent 1041
368 #define CID_VCounterAdd 1042
369 #define CID_UseVerticalMappings 1043
370 #define CID_VerticalScale 1044
371 #define CID_VMappings 1045
372
373 #define CID_VerticalOff 1060
374
375 #define CID_Letter_Ext 1081
376 #define CID_Symbol_Ext 1082
377 #define CID_Symbols_Too 1083
378 #define CID_SmallCaps 1084
379 #define CID_PetiteCaps 1085
380
381 #define CID_TabSet 1100
382
383 static GTextInfo ss_features[] = {
384 { (unichar_t *) N_("Superscript"), NULL, 0, 0, (void *) CHR('s','u','p','s'), NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
385 { (unichar_t *) N_("Scientific Inferiors"), NULL, 0, 0, (void *) CHR('s','i','n','f'), NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
386 { (unichar_t *) N_("Subscript"), NULL, 0, 0, (void *) CHR('s','u','b','s'), NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
387 { (unichar_t *) N_("Denominators"), NULL, 0, 0, (void *) CHR('d','n','o','m'), NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
388 { (unichar_t *) N_("Numerators"), NULL, 0, 0, (void *) CHR('n','u','m','r'), NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
389 GTEXTINFO_EMPTY
390 };
391 /* Not translated */
392 static char *ss_extensions[] = {
393 "superior",
394 "inferior",
395 "subscript",
396 "denominator",
397 "numerator",
398 NULL
399 };
400 static int ss_percent_xh_up[] = {
401 90,
402 -100,
403 -70,
404 -50,
405 50
406 };
407
GuessStemThreshold(SplineFont * sf)408 static double GuessStemThreshold(SplineFont *sf) {
409 double stdvw = 0, stdhw = 0, avg;
410 char *ret;
411
412 if ( sf->private!=NULL ) {
413 if ((ret=PSDictHasEntry(sf->private,"StdVW"))!=NULL ) {
414 if ( ret[0] == '[' ) ret++;
415 stdvw = strtod(ret,NULL);
416 }
417 if ((ret=PSDictHasEntry(sf->private,"StdHW"))!=NULL ) {
418 if ( ret[0] == '[' ) ret++;
419 stdhw = strtod(ret,NULL);
420 }
421 }
422 avg = (stdvw + stdhw)/2;
423 if ( avg<=0 )
424 avg = (sf->ascent+sf->descent)/25;
425 return( avg );
426 }
427
SS_Feature_Changed(GGadget * g,GEvent * e)428 static int SS_Feature_Changed(GGadget *g, GEvent *e) {
429
430 if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged &&
431 e->u.control.u.tf_changed.from_pulldown!=-1 ) {
432 GWindow ew = GGadgetGetWindow(g);
433 StyleDlg *ed = GDrawGetUserData(ew);
434 int index = e->u.control.u.tf_changed.from_pulldown;
435 uint32 tag = (intpt) ss_features[index].userdata;
436 char tagbuf[5], offset[40];
437
438 tagbuf[0] = tag>>24; tagbuf[1] = tag>>16; tagbuf[2] = tag>>8; tagbuf[3] = tag; tagbuf[4] = 0;
439 GGadgetSetTitle8(g,tagbuf);
440 GGadgetSetTitle8(GWidgetGetControl(ew,CID_Extension), ss_extensions[index]);
441
442 sprintf( offset, "%g", rint( ed->small->xheight*ss_percent_xh_up[index]/100.0 ));
443 GGadgetSetTitle8(GWidgetGetControl(ew,CID_VerticalOff), offset);
444 }
445 return( true );
446 }
447
GlyphChange_OK(GGadget * g,GEvent * e)448 static int GlyphChange_OK(GGadget *g, GEvent *e) {
449 int err = false;
450
451 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
452 GWindow ew = GGadgetGetWindow(g);
453 StyleDlg *ed = GDrawGetUserData(ew);
454 struct genericchange genchange;
455 int stem_xy_same = GGadgetIsChecked(GWidgetGetControl(ew,CID_StemsUniform));
456 int stem_bywidth = GGadgetIsChecked(GWidgetGetControl(ew,CID_Stems_by_Width));
457 enum glyphchange_type gc = ed->gc;
458
459 memset(&genchange,0,sizeof(genchange));
460 genchange.gc = gc;
461 genchange.small = ed->small;
462 genchange.stem_height_scale = GetReal8(ew,CID_StemHeight,_("Horizontal Stem Height Scale"),&err)/100.;
463 genchange.stem_height_add = GetReal8(ew,CID_StemHeightAdd,_("Horizontal Stem Height Add"),&err);
464 genchange.stem_threshold = stem_bywidth ? GetReal8(ew,CID_StemThreshold,_("Threshold between Thin and Thick Stems"),&err) : 0;
465 if ( stem_xy_same ) {
466 genchange.stem_width_scale = genchange.stem_height_scale;
467 genchange.stem_width_add = genchange.stem_height_add;
468 } else {
469 genchange.stem_width_scale = GetReal8(ew,CID_StemWidth,_("Vertical Stem Width Scale"),&err)/100.;
470 genchange.stem_width_add = stem_bywidth ? genchange.stem_height_add : GetReal8(ew,CID_StemWidthAdd,_("Vertical Stem Width Add"),&err);
471 }
472 genchange.dstem_control = GGadgetIsChecked(GWidgetGetControl(ew,CID_DStemOn));
473 if ( err )
474 return( true );
475 if (stem_bywidth && genchange.stem_threshold <= 0)
476 ff_post_error(_("Unlikely stem threshold"), _("Stem threshold should be positive"));
477 if ( genchange.stem_width_scale<.03 || genchange.stem_width_scale>10 ||
478 genchange.stem_height_scale<.03 || genchange.stem_height_scale>10 ) {
479 ff_post_error(_("Unlikely scale factor"), _("Scale factors must be between 3 and 1000 percent"));
480 return( true );
481 }
482 if ( genchange.stem_height_add!=genchange.stem_width_add ) {
483 if (( genchange.stem_height_add==0 && genchange.stem_width_add!=0 ) ||
484 ( genchange.stem_height_add!=0 && genchange.stem_width_add==0 )) {
485 ff_post_error(_("Bad stem add"), _("The horizontal and vertical stem add amounts must either both be zero, or neither may be 0"));
486 return( true );
487 }
488 /* if width_add has a different sign than height_add that's also */
489 /* a problem, but this test will catch that too */
490 if (( genchange.stem_height_add/genchange.stem_width_add>4 ) ||
491 ( genchange.stem_height_add/genchange.stem_width_add<.25 )) {
492 ff_post_error(_("Bad stem add"), _("The horizontal and vertical stem add amounts may not differ by more than a factor of 4"));
493 return( true );
494 }
495 }
496 if ( gc==gc_subsuper ) {
497 const unichar_t *tag_str = _GGadgetGetTitle(GWidgetGetControl(ew,CID_Feature));
498 char tag[4];
499
500 memset(tag,' ',sizeof(tag));
501 if ( *tag_str=='\0' )
502 genchange.feature_tag = 0; /* Perfectly valid to have no tag */
503 else {
504 tag[0] = *tag_str;
505 if ( tag_str[1]!='\0' ) {
506 tag[1] = tag_str[1];
507 if ( tag_str[2]!='\0' ) {
508 tag[2] = tag_str[2];
509 if ( tag_str[3]!='\0' ) {
510 tag[3] = tag_str[3];
511 if ( tag_str[4]!='\0' ) {
512 ff_post_error(_("Bad tag"), _("Feature tags are limited to 4 letters"));
513 return( true );
514 }
515 }
516 }
517 }
518 genchange.feature_tag = (tag[0]<<24) | (tag[1]<<16) | (tag[2]<<8) | tag[3];
519 }
520 genchange.glyph_extension = GGadgetGetTitle8(GWidgetGetControl(ew,CID_Extension));
521 if ( *genchange.glyph_extension=='\0' ) {
522 ff_post_error(_("Missing glyph extension"),_("You must specify a glyph extension"));
523 free(genchange.glyph_extension);
524 return( true );
525 }
526 genchange.vertical_offset = GetReal8(ew,CID_VerticalOff,_("Vertical Offset"),&err);
527 if ( err )
528 return( true );
529 } else if ( gc==gc_smallcaps ) {
530 genchange.do_smallcap_symbols = GGadgetIsChecked(GWidgetGetControl(ew,CID_Symbols_Too));
531 genchange.petite = GGadgetIsChecked(GWidgetGetControl(ew,CID_PetiteCaps));
532 genchange.extension_for_letters = GGadgetGetTitle8(GWidgetGetControl(ew,CID_Letter_Ext));
533 genchange.extension_for_symbols = GGadgetGetTitle8(GWidgetGetControl(ew,CID_Symbol_Ext));
534 if ( *genchange.extension_for_letters=='\0' || (*genchange.extension_for_symbols=='\0' && genchange.do_smallcap_symbols )) {
535 free( genchange.extension_for_letters );
536 free( genchange.extension_for_symbols );
537 ff_post_error(_("Missing extension"),_("You must provide a glyph extension"));
538 return( true );
539 }
540 }
541
542 if (GGadgetIsChecked(GWidgetGetControl(ew,CID_Counter_SameAdvance)))
543 genchange.center_in_hor_advance = 1;
544 else if (GGadgetIsChecked(GWidgetGetControl(ew,CID_Counter_PropAdvance)))
545 genchange.center_in_hor_advance = 2;
546 else
547 genchange.center_in_hor_advance = 0;
548 genchange.hcounter_scale = GetReal8(ew,CID_CounterPercent,_("Horizontal Counter Scale"),&err)/100.;
549 genchange.hcounter_add = GetReal8(ew,CID_CounterAdd,_("Horizontal Counter Add"),&err);
550 if ( GGadgetIsChecked(GWidgetGetControl(ew,CID_Counter_is_SideB)) ) {
551 genchange.lsb_scale = genchange.hcounter_scale;
552 genchange.lsb_add = genchange.hcounter_add;
553 genchange.rsb_scale = genchange.hcounter_scale;
554 genchange.rsb_add = genchange.hcounter_add;
555 } else {
556 genchange.lsb_scale = GetReal8(ew,CID_LSBPercent,_("Left Side Bearing Scale"),&err)/100.;
557 genchange.lsb_add = GetReal8(ew,CID_LSBAdd,_("Left Side Bearing Add"),&err);
558 genchange.rsb_scale = GetReal8(ew,CID_RSBPercent,_("Right Side Bearing Scale"),&err)/100.;
559 genchange.rsb_add = GetReal8(ew,CID_RSBAdd,_("Right Side Bearing Add"),&err);
560 }
561 if ( err )
562 return( true );
563
564 genchange.use_vert_mapping = GGadgetIsChecked(GWidgetGetControl(ew,CID_UseVerticalMappings));
565 if ( genchange.use_vert_mapping ) {
566 GGadget *map = GWidgetGetControl(ew,CID_VMappings);
567 int i,j;
568 int rows, cols = GMatrixEditGetColCnt(map);
569 struct matrix_data *mappings = GMatrixEditGet(map, &rows);
570
571 genchange.v_scale = GetReal8(ew,CID_VerticalScale,_("Vertical Scale"),&err)/100.;
572 if ( err )
573 return( true );
574 genchange.m.cnt = rows;
575 genchange.m.maps = malloc(rows*sizeof(struct position_maps));
576 for ( i=0; i<rows; ++i ) {
577 genchange.m.maps[i].current = mappings[cols*i+0].u.md_real;
578 genchange.m.maps[i].desired = mappings[cols*i+2].u.md_real;
579 genchange.m.maps[i].cur_width = mappings[cols*i+1].u.md_real;
580 }
581 /* Order maps */
582 for ( i=0; i<rows; ++i ) for ( j=i+1; j<rows; ++j ) {
583 if ( genchange.m.maps[i].current > genchange.m.maps[j].current ) {
584 struct position_maps temp;
585 temp = genchange.m.maps[i];
586 genchange.m.maps[i] = genchange.m.maps[j];
587 genchange.m.maps[j] = temp;
588 }
589 }
590 } else {
591 genchange.vcounter_scale = GetReal8(ew,CID_VCounterPercent,_("Vertical Counter Scale"),&err)/100.;
592 genchange.vcounter_add = GetReal8(ew,CID_VCounterAdd,_("Vertical Counter Add"),&err);
593 if ( err )
594 return( true );
595 }
596 if ( ed->gc == gc_smallcaps )
597 FVAddSmallCaps( (FontViewBase *) ed->fv, &genchange );
598 else if ( ed->fv!=NULL )
599 FVGenericChange( (FontViewBase *) ed->fv, &genchange );
600 else
601 CVGenericChange( (CharViewBase *) ed->cv, &genchange );
602 free(genchange.glyph_extension);
603 free(genchange.m.maps);
604 free( genchange.extension_for_letters );
605 free( genchange.extension_for_symbols );
606 ed->done = true;
607 }
608 return( true );
609 }
610
611 static GTextInfo stemwidth[] = {
612 { (unichar_t *) N_("Width of Vertical Stems:"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
613 { (unichar_t *) N_("Width/Height of Thick Stems:"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
614 GTEXTINFO_EMPTY
615 };
616 static GTextInfo stemheight[] = {
617 { (unichar_t *) N_("Height of Horizontal Stems:"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
618 { (unichar_t *) N_("Width/Height of Thin Stems:"), NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 0, 0, '\0'},
619 GTEXTINFO_EMPTY
620 };
621
CG_SameAs_Changed(GGadget * g,GEvent * e)622 static int CG_SameAs_Changed(GGadget *g, GEvent *e) {
623
624 if ( e==NULL || (e->type==et_controlevent && e->u.control.subtype == et_radiochanged )) {
625 GWindow ew = GGadgetGetWindow(g);
626 int uniform = GGadgetIsChecked(GWidgetGetControl(ew,CID_StemsUniform));
627 int by_dir = GGadgetIsChecked(GWidgetGetControl(ew,CID_Stems_H_V));
628 int by_width = GGadgetIsChecked(GWidgetGetControl(ew,CID_Stems_by_Width));
629 unichar_t *v_label = by_width ? stemwidth[1].text : stemwidth[0].text;
630 unichar_t *h_label = by_width ? stemheight[1].text : stemheight[0].text;
631
632 GGadgetSetEnabled(GWidgetGetControl(ew,CID_StemWidth), !uniform);
633 GGadgetSetEnabled(GWidgetGetControl(ew,CID_StemWidthAdd), by_dir);
634 GGadgetSetEnabled(GWidgetGetControl(ew,CID_StemThreshold), by_width);
635 if ( uniform ) {
636 GGadgetSetTitle(GWidgetGetControl(ew,CID_StemWidth),
637 _GGadgetGetTitle(GWidgetGetControl(ew,CID_StemHeight)));
638 GGadgetSetTitle(GWidgetGetControl(ew,CID_StemWidthAdd),
639 _GGadgetGetTitle(GWidgetGetControl(ew,CID_StemHeightAdd)));
640 } else if ( by_width ) {
641 GGadgetSetTitle(GWidgetGetControl(ew,CID_StemWidthAdd),
642 _GGadgetGetTitle(GWidgetGetControl(ew,CID_StemHeightAdd)));
643 }
644
645 GGadgetSetTitle8(GWidgetGetControl(ew,CID_StemWidthLabel), (char *) v_label);
646 GGadgetSetTitle8(GWidgetGetControl(ew,CID_StemHeightLabel), (char *) h_label);
647 }
648 return( true );
649 }
650
CG_VStem_Changed(GGadget * g,GEvent * e)651 static int CG_VStem_Changed(GGadget *g, GEvent *e) {
652
653 if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
654 GWindow ew = GGadgetGetWindow(g);
655 if ( GGadgetIsChecked(GWidgetGetControl(ew,CID_StemsUniform))) {
656 GGadgetSetTitle(GWidgetGetControl(ew,CID_StemWidth),
657 _GGadgetGetTitle(GWidgetGetControl(ew,CID_StemHeight)));
658 GGadgetSetTitle(GWidgetGetControl(ew,CID_StemWidthAdd),
659 _GGadgetGetTitle(GWidgetGetControl(ew,CID_StemHeightAdd)));
660
661 } else if ( GGadgetIsChecked(GWidgetGetControl(ew,CID_Stems_by_Width))) {
662 GGadgetSetTitle(GWidgetGetControl(ew,CID_StemWidthAdd),
663 _GGadgetGetTitle(GWidgetGetControl(ew,CID_StemHeightAdd)));
664
665 }
666 }
667 return( true );
668 }
669
CG_CounterSameAs_Changed(GGadget * g,GEvent * e)670 static int CG_CounterSameAs_Changed(GGadget *g, GEvent *e) {
671
672 if ( e==NULL || (e->type==et_controlevent && e->u.control.subtype == et_radiochanged )) {
673 GWindow ew = GGadgetGetWindow(g);
674 int on = GGadgetIsChecked(GWidgetGetControl(ew,CID_Counter_is_SideB));
675 int enabled = GGadgetIsChecked(GWidgetGetControl(ew,CID_Counter_isnt_SideB));
676 GGadgetSetEnabled(GWidgetGetControl(ew,CID_LSBPercent), enabled);
677 GGadgetSetEnabled(GWidgetGetControl(ew,CID_LSBAdd), enabled);
678 GGadgetSetEnabled(GWidgetGetControl(ew,CID_RSBPercent), enabled);
679 GGadgetSetEnabled(GWidgetGetControl(ew,CID_RSBAdd), enabled);
680 if ( on ) {
681 GGadgetSetTitle(GWidgetGetControl(ew,CID_LSBPercent),
682 _GGadgetGetTitle(GWidgetGetControl(ew,CID_CounterPercent)));
683 GGadgetSetTitle(GWidgetGetControl(ew,CID_LSBAdd),
684 _GGadgetGetTitle(GWidgetGetControl(ew,CID_CounterAdd)));
685 GGadgetSetTitle(GWidgetGetControl(ew,CID_RSBPercent),
686 _GGadgetGetTitle(GWidgetGetControl(ew,CID_CounterPercent)));
687 GGadgetSetTitle(GWidgetGetControl(ew,CID_RSBAdd),
688 _GGadgetGetTitle(GWidgetGetControl(ew,CID_CounterAdd)));
689 }
690 }
691 return( true );
692 }
693
CG_Counter_Changed(GGadget * g,GEvent * e)694 static int CG_Counter_Changed(GGadget *g, GEvent *e) {
695
696 if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
697 GWindow ew = GGadgetGetWindow(g);
698 if ( GGadgetIsChecked(GWidgetGetControl(ew,CID_Counter_is_SideB))) {
699 GGadgetSetTitle(GWidgetGetControl(ew,CID_LSBPercent),
700 _GGadgetGetTitle(GWidgetGetControl(ew,CID_CounterPercent)));
701 GGadgetSetTitle(GWidgetGetControl(ew,CID_LSBAdd),
702 _GGadgetGetTitle(GWidgetGetControl(ew,CID_CounterAdd)));
703 GGadgetSetTitle(GWidgetGetControl(ew,CID_RSBPercent),
704 _GGadgetGetTitle(GWidgetGetControl(ew,CID_CounterPercent)));
705 GGadgetSetTitle(GWidgetGetControl(ew,CID_RSBAdd),
706 _GGadgetGetTitle(GWidgetGetControl(ew,CID_CounterAdd)));
707 }
708 }
709 return( true );
710 }
711
CG_UseVCounters(GGadget * g,GEvent * e)712 static int CG_UseVCounters(GGadget *g, GEvent *e) {
713
714 if ( e==NULL || (e->type==et_controlevent && e->u.control.subtype == et_radiochanged )) {
715 GWindow ew = GGadgetGetWindow(g);
716 int on = GGadgetIsChecked(GWidgetGetControl(ew,CID_UseVerticalCounters));
717 GGadgetSetEnabled(GWidgetGetControl(ew,CID_VCounterPercent), on);
718 GGadgetSetEnabled(GWidgetGetControl(ew,CID_VCounterAdd), on);
719 GGadgetSetEnabled(GWidgetGetControl(ew,CID_VerticalScale), !on);
720 GGadgetSetEnabled(GWidgetGetControl(ew,CID_VMappings), !on);
721 }
722 return( true );
723 }
724
CG_VScale_Changed(GGadget * g,GEvent * e)725 static int CG_VScale_Changed(GGadget *g, GEvent *e) {
726
727 if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
728 GWindow ew = GGadgetGetWindow(g);
729 StyleDlg *ed = GDrawGetUserData(ew);
730 int err=0;
731 bigreal scale;
732 GGadget *map = GWidgetGetControl(ew,CID_VMappings);
733 int rows, cols = GMatrixEditGetColCnt(map);
734 struct matrix_data *mappings = GMatrixEditGet(map, &rows);
735 int i;
736
737 scale = GetCalmReal8(ew,CID_VerticalScale,"unused",&err)/100.0;
738 if ( err || scale<=0 || RealNear(ed->scale,scale) )
739 return( true );
740 for ( i=0; i<rows; ++i ) {
741 bigreal offset = mappings[cols*i+2].u.md_real - rint(ed->scale*mappings[cols*i+0].u.md_real);
742 mappings[cols*i+2].u.md_real =
743 rint(scale * mappings[cols*i+0].u.md_real) + offset;
744 }
745 ed->scale = scale;
746 GGadgetRedraw(map);
747 }
748 return( true );
749 }
750
CG_PetiteCapsChange(GGadget * g,GEvent * e)751 static int CG_PetiteCapsChange(GGadget *g, GEvent *e) {
752
753 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
754 GWindow ew = GGadgetGetWindow(g);
755 int petite = GGadgetIsChecked(GWidgetGetControl(ew,CID_PetiteCaps));
756 GGadgetSetTitle8(GWidgetGetControl(ew,CID_Letter_Ext), petite ? "pc" : "sc" );
757 }
758 return( true );
759 }
760
CG_SmallCapSymbols(GGadget * g,GEvent * e)761 static int CG_SmallCapSymbols(GGadget *g, GEvent *e) {
762
763 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
764 GWindow ew = GGadgetGetWindow(g);
765 int on = GGadgetIsChecked(g);
766 GGadgetSetEnabled(GWidgetGetControl(ew,CID_Symbol_Ext), on);
767 }
768 return( true );
769 }
770
ParseBlue(double blues[14],struct psdict * private,char * key)771 static int ParseBlue(double blues[14],struct psdict *private,char *key) {
772 int i;
773 char *val, *end;
774
775 if ( private==NULL )
776 return( 0 );
777 if ( (val = PSDictHasEntry(private,key))==NULL )
778 return( 0 );
779 while ( isspace( *val ) || *val=='[' ) ++val;
780
781 for ( i=0; i<14; ++i ) {
782 while ( isspace( *val )) ++val;
783 if ( *val==']' || *val=='\0' )
784 return( i );
785 blues[i] = strtod(val,&end);
786 if ( end==val ) /* Not a number */
787 return( 0 );
788 val = end;
789 }
790 return( i );
791 }
792
793 static struct col_init mapci[5] = {
794 { me_real, NULL, NULL, NULL, N_("Original Y Position") },
795 { me_real, NULL, NULL, NULL, N_("Extent") },
796 { me_real, NULL, NULL, NULL, N_("Resultant Y Position") },
797 };
MappingMatrixInit(struct matrixinit * mi,SplineFont * sf,double xheight,double capheight,double scale)798 static void MappingMatrixInit(struct matrixinit *mi,SplineFont *sf,
799 double xheight, double capheight, double scale) {
800 struct matrix_data *md;
801 int cnt;
802 double blues[14], others[14];
803 int b=0,o=0,i,j;
804
805 memset(mi,0,sizeof(*mi));
806 mi->col_cnt = 3;
807 mi->col_init = mapci;
808
809 if ( sf->private!=NULL ) {
810 b = ParseBlue(blues,sf->private,"BlueValues");
811 o = ParseBlue(others,sf->private,"OtherBlues");
812 }
813
814 if ( (b>1 && (b&1)==0) || (o>1 && (o&1)==0)) {
815 b>>=1; o>>=1;
816 md = calloc(3*(b+o),sizeof(struct matrix_data));
817 mi->initial_row_cnt = b+o;
818 mi->matrix_data = md;
819
820 for ( i=0; i<o; ++i ) {
821 md[3*i+0].u.md_real = others[2*i+1];
822 md[3*i+1].u.md_real = others[2*i] - others[2*i+1];
823 md[3*i+2].u.md_real = rint(scale*md[3*i+0].u.md_real);
824 }
825 for ( j=0; j<b; ++j ) {
826 if ( j==0 ) {
827 md[3*(i+j)+0].u.md_real = blues[1];
828 md[3*(i+j)+1].u.md_real = blues[0] - blues[1];
829 } else {
830 md[3*(i+j)+0].u.md_real = blues[2*j];
831 md[3*(i+j)+1].u.md_real = blues[2*j+1] - blues[2*j];
832 }
833 md[3*(i+j)+2].u.md_real = rint(scale*md[3*(i+j)+0].u.md_real);
834 }
835 } else if ( xheight==0 && capheight==0 ) {
836 md = calloc(3,sizeof(struct matrix_data));
837 mi->initial_row_cnt = 1;
838 mi->matrix_data = md;
839 } else {
840 cnt = 1; /* For the baseline */
841 if ( xheight!=0 )
842 ++cnt;
843 if ( capheight!=0 )
844 ++cnt;
845 md = calloc(3*cnt,sizeof(struct matrix_data));
846 mi->initial_row_cnt = cnt;
847 mi->matrix_data = md;
848 md[3*0+1].u.md_real = -1;
849 cnt = 1;
850 if ( xheight!=0 ) {
851 md[3*cnt+0].u.md_real = xheight;
852 md[3*cnt+1].u.md_real = 1;
853 md[3*cnt+2].u.md_real = scale*xheight;
854 ++cnt;
855 }
856 if ( capheight!=0 ) {
857 md[3*cnt+0].u.md_real = capheight;
858 md[3*cnt+1].u.md_real = 1;
859 md[3*cnt+2].u.md_real = scale*capheight;
860 ++cnt;
861 }
862 }
863 }
864
GlyphChange_Default(GGadget * g,GEvent * e)865 static int GlyphChange_Default(GGadget *g, GEvent *e) {
866
867 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
868 GWindow ew = GGadgetGetWindow(g);
869 StyleDlg *ed = GDrawGetUserData(ew);
870 enum glyphchange_type gc = ed->gc;
871 bigreal glyph_scale = 1.0, stem_scale=1.0;
872 char glyph_factor[40], stem_factor[40];
873 struct matrixinit mapmi;
874
875 if ( gc==gc_subsuper ) {
876 GGadgetSetTitle8(GWidgetGetControl(ew,CID_Feature),"");
877 GGadgetSetTitle8(GWidgetGetControl(ew,CID_Extension),"");
878 GGadgetSetTitle8(GWidgetGetControl(ew,CID_VerticalOff),"");
879
880 glyph_scale = 2.0/3.0;
881 stem_scale = 3.0/4.0;
882 } else if ( gc == gc_smallcaps ) {
883 GGadgetSetTitle8(GWidgetGetControl(ew,CID_Letter_Ext),"sc");
884 GGadgetSetTitle8(GWidgetGetControl(ew,CID_Symbol_Ext),"taboldstyle");
885 GGadgetSetChecked(GWidgetGetControl(ew,CID_Symbols_Too),false);
886 GGadgetSetChecked(GWidgetGetControl(ew,CID_SmallCaps),true);
887
888 if ( ed->small->xheight!=0 && ed->small->capheight!=0 )
889 glyph_scale = ed->small->xheight/ed->small->capheight;
890 if ( ed->small->lc_stem_width!=0 && ed->small->uc_stem_width!=0 )
891 stem_scale = ed->small->lc_stem_width/ed->small->uc_stem_width;
892 }
893 ed->scale = glyph_scale;
894 sprintf( glyph_factor, "%.2f", (double) (100*glyph_scale) );
895 sprintf( stem_factor , "%.2f", (double) (100* stem_scale) );
896
897 GGadgetSetChecked(GWidgetGetControl(ew,CID_StemsUniform),true);
898 GGadgetSetTitle8(GWidgetGetControl(ew,CID_StemHeight),stem_factor);
899 GGadgetSetTitle8(GWidgetGetControl(ew,CID_StemHeightAdd),"0");
900 GGadgetSetTitle8(GWidgetGetControl(ew,CID_StemWidth),stem_factor);
901 GGadgetSetTitle8(GWidgetGetControl(ew,CID_StemWidthAdd),"0");
902 GGadgetSetChecked(GWidgetGetControl(ew,CID_DStemOn),true);
903
904 GGadgetSetChecked(GWidgetGetControl(ew,CID_Counter_is_SideB),true);
905 GGadgetSetTitle8(GWidgetGetControl(ew,CID_CounterPercent),glyph_factor);
906 GGadgetSetTitle8(GWidgetGetControl(ew,CID_CounterAdd),"0");
907 GGadgetSetTitle8(GWidgetGetControl(ew,CID_LSBPercent),glyph_factor);
908 GGadgetSetTitle8(GWidgetGetControl(ew,CID_LSBAdd),"0");
909 GGadgetSetTitle8(GWidgetGetControl(ew,CID_RSBPercent),glyph_factor);
910 GGadgetSetTitle8(GWidgetGetControl(ew,CID_RSBAdd),"0");
911
912 GGadgetSetChecked(GWidgetGetControl(ew,CID_UseVerticalMappings),true);
913 GGadgetSetTitle8(GWidgetGetControl(ew,CID_VCounterPercent),glyph_factor);
914 GGadgetSetTitle8(GWidgetGetControl(ew,CID_VCounterAdd),"0");
915 GGadgetSetTitle8(GWidgetGetControl(ew,CID_VerticalScale),glyph_factor);
916
917 MappingMatrixInit(&mapmi,
918 ed->sf,
919 gc==gc_smallcaps?0:ed->small->xheight,
920 ed->small->capheight,glyph_scale);
921 GMatrixEditSet(GWidgetGetControl(ew,CID_VMappings),
922 mapmi.matrix_data,mapmi.initial_row_cnt,false);
923
924 CG_SameAs_Changed(GWidgetGetControl(ew,CID_StemsUniform),NULL);
925 CG_CounterSameAs_Changed(GWidgetGetControl(ew,CID_Counter_is_SideB),NULL);
926 CG_UseVCounters(GWidgetGetControl(ew,CID_UseVerticalMappings),NULL);
927 }
928 return( true );
929 }
930
GlyphChangeDlg(FontView * fv,CharView * cv,enum glyphchange_type gc)931 void GlyphChangeDlg(FontView *fv,CharView *cv, enum glyphchange_type gc) {
932 StyleDlg ed;
933 SplineFont *sf = fv!=NULL ? fv->b.sf : cv->b.sc->parent;
934 GRect pos;
935 GWindow gw;
936 GWindowAttrs wattrs;
937 GGadgetCreateData gcd[64], boxes[19], *barray[11], *stemarray[22], *stemtarray[6],
938 *stemarrayhc[20], *stemarrayvc[8], *varrayi[16], *varrays[15],
939 *varrayhc[14], *varrayvc[12], *pcarray[4],
940 *varray[7], *harray[6], *voarray[6], *extarray[7], *exarray[6];
941 GTextInfo label[64];
942 GTabInfo aspects[5];
943 int i,k,l,s, a;
944 struct smallcaps small;
945 struct matrixinit mapmi;
946 bigreal glyph_scale = 1.0, stem_scale=1.0;
947 char glyph_factor[40], stem_factor[40], stem_threshold[10];
948 int layer = fv!=NULL ? fv->b.active_layer : CVLayer((CharViewBase *) cv);
949 static GWindow last_dlg[gc_max] = { NULL };
950 static SplineFont *last_sf[gc_max] = { NULL };
951 static int intldone = false;
952
953 memset(&ed,0,sizeof(ed));
954 ed.fv = fv;
955 ed.cv = cv;
956 ed.sf = sf;
957 ed.small = &small;
958 ed.gc = gc;
959
960 if (!intldone) {
961 intldone = true;
962 for ( i=0; stemwidth[i].text; ++i )
963 stemwidth[i].text = (unichar_t *) _((char *) stemwidth[i].text);
964 for ( i=0; stemheight[i].text; ++i )
965 stemheight[i].text = (unichar_t *) _((char *) stemheight[i].text);
966 }
967
968 SmallCapsFindConstants(&small,sf,layer); /* I want to know the xheight... */
969
970 if ( last_dlg[gc] == NULL || last_sf[gc] != sf ) {
971 if ( last_dlg[gc]!=NULL )
972 GDrawDestroyWindow(last_dlg[gc]);
973
974 memset(&wattrs,0,sizeof(wattrs));
975 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
976 wattrs.event_masks = ~(1<<et_charup);
977 wattrs.restrict_input_to_me = 1;
978 wattrs.undercursor = 1;
979 wattrs.cursor = ct_pointer;
980 wattrs.utf8_window_title = gc==gc_subsuper ? _("Create Subscript/Superscript") :
981 gc==gc_smallcaps ? _("Create Small Caps") :
982 _("Change Glyphs");
983 wattrs.is_dlg = true;
984 pos.x = pos.y = 0;
985 pos.width = 100;
986 pos.height = 100;
987 ed.gw = gw = GDrawCreateTopWindow(NULL,&pos,style_e_h,&ed,&wattrs);
988
989
990 k=l=s=a=0;
991
992 memset(aspects,0,sizeof(aspects));
993 memset(gcd,0,sizeof(gcd));
994 memset(boxes,0,sizeof(boxes));
995 memset(label,0,sizeof(label));
996 memset(stemarray,0,sizeof(stemarray));
997
998 if ( gc==gc_subsuper ) {
999 label[k].text = (unichar_t *) _(
1000 "Unlike most commands this one does not work directly on the\n"
1001 "selected glyphs. Instead, if you select a glyph FontForge will\n"
1002 "create (or reuse) another glyph named by appending the extension\n"
1003 "to the original name, and it will copy a modified version of\n"
1004 "the original glyph into the new one.");
1005 label[k].text_is_1byte = true;
1006 label[k].text_in_resource = true;
1007 gcd[k].gd.label = &label[k];
1008 gcd[k].gd.flags = gg_enabled | gg_visible;
1009 gcd[k++].creator = GLabelCreate;
1010 varrayi[l++] = &gcd[k-1]; varrayi[l++] = NULL;
1011
1012
1013 gcd[k].gd.pos.width = 10; gcd[k].gd.pos.height = 10;
1014 gcd[k].gd.flags = gg_enabled | gg_visible;
1015 gcd[k++].creator = GSpacerCreate;
1016 varrayi[l++] = &gcd[k-1]; varrayi[l++] = NULL;
1017
1018 label[k].text = (unichar_t *) _("Feature Tag:");
1019 label[k].text_is_1byte = true;
1020 label[k].text_in_resource = true;
1021 gcd[k].gd.label = &label[k];
1022 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1023 gcd[k].gd.flags = gg_enabled | gg_visible;
1024 gcd[k++].creator = GLabelCreate;
1025 extarray[0] = &gcd[k-1];
1026
1027 label[k].text = (unichar_t *) "";
1028 label[k].text_is_1byte = true;
1029 gcd[k].gd.label = &label[k];
1030 gcd[k].gd.flags = gg_enabled | gg_visible;
1031 gcd[k].gd.cid = CID_Feature;
1032 gcd[k].gd.u.list = ss_features;
1033 gcd[k].gd.handle_controlevent = SS_Feature_Changed;
1034 gcd[k++].creator = GListFieldCreate;
1035 extarray[1] = &gcd[k-1];
1036
1037 label[k].text = (unichar_t *) _("Glyph Extension:");
1038 label[k].text_is_1byte = true;
1039 label[k].text_in_resource = true;
1040 gcd[k].gd.label = &label[k];
1041 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1042 gcd[k].gd.flags = gg_enabled | gg_visible;
1043 gcd[k++].creator = GLabelCreate;
1044 extarray[2] = &gcd[k-1];
1045
1046 label[k].text = (unichar_t *) "";
1047 label[k].text_is_1byte = true;
1048 gcd[k].gd.label = &label[k];
1049 gcd[k].gd.flags = gg_enabled | gg_visible;
1050 gcd[k].gd.cid = CID_Extension;
1051 gcd[k++].creator = GTextFieldCreate;
1052 extarray[3] = &gcd[k-1]; extarray[4] = NULL;
1053
1054 boxes[2].gd.flags = gg_enabled|gg_visible;
1055 boxes[2].gd.u.boxelements = extarray;
1056 boxes[2].creator = GHBoxCreate;
1057 varrayi[l++] = &boxes[2]; varrayi[l++] = NULL;
1058
1059 label[k].text = (unichar_t *) _("Vertical Offset:");
1060 label[k].text_is_1byte = true;
1061 label[k].text_in_resource = true;
1062 gcd[k].gd.label = &label[k];
1063 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1064 gcd[k].gd.flags = gg_enabled | gg_visible;
1065 gcd[k++].creator = GLabelCreate;
1066 voarray[0] = &gcd[k-1];
1067
1068 label[k].text = (unichar_t *) "0";
1069 label[k].text_is_1byte = true;
1070 gcd[k].gd.label = &label[k];
1071 gcd[k].gd.flags = gg_enabled | gg_visible;
1072 gcd[k].gd.pos.width = 60;
1073 gcd[k].gd.cid = CID_VerticalOff;
1074 gcd[k++].creator = GTextFieldCreate;
1075 voarray[1]= &gcd[k-1]; voarray[2] = GCD_Glue; voarray[3] = NULL;
1076
1077 boxes[3].gd.flags = gg_enabled|gg_visible;
1078 boxes[3].gd.u.boxelements = voarray;
1079 boxes[3].creator = GHBoxCreate;
1080 varrayi[l++] = &boxes[3]; varrayi[l++] = NULL;
1081 varrayi[l++] = GCD_Glue; varrayi[l++] = NULL; varrayi[l++] = NULL;
1082
1083 boxes[4].gd.flags = gg_enabled|gg_visible;
1084 boxes[4].gd.u.boxelements = varrayi;
1085 boxes[4].creator = GHVBoxCreate;
1086
1087 aspects[a].text = (unichar_t *) _("Introduction");
1088 aspects[a].text_is_1byte = true;
1089 aspects[a++].gcd = &boxes[4];
1090
1091 glyph_scale = 2.0/3.0;
1092 stem_scale = 3.0/4.0;
1093 } else if ( gc == gc_smallcaps ) {
1094 label[k].text = (unichar_t *) _(
1095 "Unlike most commands this one does not work directly on the\n"
1096 "selected glyphs. Instead, if you select an \"A\" (or an \"a\")\n"
1097 "FontForge will create (or reuse) a glyph named \"a.sc\", and\n"
1098 "it will copy a modified version of the \"A\" glyph into \"a.sc\".");
1099 label[k].text_is_1byte = true;
1100 label[k].text_in_resource = true;
1101 gcd[k].gd.label = &label[k];
1102 gcd[k].gd.flags = gg_enabled | gg_visible;
1103 gcd[k++].creator = GLabelCreate;
1104 varrayi[l++] = &gcd[k-1]; varrayi[l++] = NULL;
1105
1106 gcd[k].gd.pos.width = 10; gcd[k].gd.pos.height = 10;
1107 gcd[k].gd.flags = gg_enabled | gg_visible;
1108 gcd[k++].creator = GSpacerCreate;
1109 varrayi[l++] = &gcd[k-1]; varrayi[l++] = NULL;
1110
1111 label[k].text = (unichar_t *) _("Small Caps");
1112 label[k].text_is_1byte = true;
1113 label[k].text_in_resource = true;
1114 gcd[k].gd.label = &label[k];
1115 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1116 gcd[k].gd.flags = gg_visible | gg_enabled | gg_cb_on;
1117 gcd[k].gd.handle_controlevent = CG_PetiteCapsChange;
1118 gcd[k].gd.cid = CID_SmallCaps;
1119 gcd[k++].creator = GRadioCreate;
1120 pcarray[0] = &gcd[k-1];
1121
1122 label[k].text = (unichar_t *) _("Petite Caps");
1123 label[k].text_is_1byte = true;
1124 label[k].text_in_resource = true;
1125 gcd[k].gd.label = &label[k];
1126 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1127 gcd[k].gd.flags = gg_visible | gg_enabled ;
1128 gcd[k].gd.handle_controlevent = CG_PetiteCapsChange;
1129 gcd[k].gd.cid = CID_PetiteCaps;
1130 gcd[k++].creator = GRadioCreate;
1131 pcarray[1] = &gcd[k-1]; pcarray[2] = GCD_Glue; pcarray[3] = NULL;
1132
1133 boxes[2].gd.flags = gg_enabled|gg_visible;
1134 boxes[2].gd.u.boxelements = pcarray;
1135 boxes[2].creator = GHBoxCreate;
1136 varrayi[l++] = &boxes[2]; varrayi[l++] = NULL;
1137
1138 label[k].text = (unichar_t *) _("Glyph Extensions");
1139 label[k].text_is_1byte = true;
1140 label[k].text_in_resource = true;
1141 gcd[k].gd.label = &label[k];
1142 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1143 gcd[k].gd.flags = gg_visible | gg_enabled;
1144 gcd[k++].creator = GLabelCreate;
1145 varrayi[l++] = &gcd[k-1]; varrayi[l++] = NULL;
1146
1147 label[k].text = (unichar_t *) _("Letters:");
1148 label[k].text_is_1byte = true;
1149 label[k].text_in_resource = true;
1150 gcd[k].gd.label = &label[k];
1151 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1152 gcd[k].gd.flags = gg_visible | gg_enabled;
1153 gcd[k++].creator = GLabelCreate;
1154
1155 label[k].text = (unichar_t *) "sc";
1156 label[k].text_is_1byte = true;
1157 gcd[k].gd.label = &label[k];
1158 gcd[k].gd.pos.width = 80;
1159 gcd[k].gd.flags = gg_visible | gg_enabled;
1160 gcd[k].gd.cid = CID_Letter_Ext;
1161 gcd[k++].creator = GTextFieldCreate;
1162
1163 label[k].text = (unichar_t *) _("Symbols:");
1164 label[k].text_is_1byte = true;
1165 label[k].text_in_resource = true;
1166 gcd[k].gd.label = &label[k];
1167 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1168 gcd[k].gd.flags = gg_visible | gg_enabled;
1169 gcd[k++].creator = GLabelCreate;
1170
1171 label[k].text = (unichar_t *) "taboldstyle";
1172 label[k].text_is_1byte = true;
1173 gcd[k].gd.label = &label[k];
1174 gcd[k].gd.pos.width = 80;
1175 gcd[k].gd.flags = gg_visible;
1176 gcd[k].gd.cid = CID_Symbol_Ext;
1177 gcd[k++].creator = GTextFieldCreate;
1178 exarray[0] = &gcd[k-4]; exarray[1] = &gcd[k-3]; exarray[2] = &gcd[k-2]; exarray[3] = &gcd[k-1];
1179 exarray[4] = NULL;
1180
1181 boxes[3].gd.flags = gg_enabled|gg_visible;
1182 boxes[3].gd.u.boxelements = exarray;
1183 boxes[3].creator = GHBoxCreate;
1184 varrayi[l++] = &boxes[3]; varrayi[l++] = NULL;
1185
1186 label[k].text = (unichar_t *) _("Create small caps variants for symbols as well as letters");
1187 label[k].text_is_1byte = true;
1188 label[k].text_in_resource = true;
1189 gcd[k].gd.label = &label[k];
1190 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1191 gcd[k].gd.flags = gg_enabled | gg_visible;
1192 gcd[k].gd.handle_controlevent = CG_SmallCapSymbols;
1193 gcd[k].gd.cid = CID_Symbols_Too;
1194 gcd[k++].creator = GCheckBoxCreate;
1195 varrayi[l++] = &gcd[k-1]; varrayi[l++] = NULL;
1196 varrayi[l++] = GCD_Glue; varrayi[l++] = NULL; varrayi[l++] = NULL;
1197
1198 boxes[4].gd.flags = gg_enabled|gg_visible;
1199 boxes[4].gd.u.boxelements = varrayi;
1200 boxes[4].creator = GHVBoxCreate;
1201
1202 aspects[a].text = (unichar_t *) _("Introduction");
1203 aspects[a].text_is_1byte = true;
1204 aspects[a++].gcd = &boxes[4];
1205
1206 if ( small.xheight!=0 && small.capheight!=0 )
1207 glyph_scale = small.xheight/small.capheight;
1208 if ( small.lc_stem_width!=0 && small.uc_stem_width!=0 )
1209 stem_scale = small.lc_stem_width/small.uc_stem_width;
1210 }
1211
1212 l = 0;
1213
1214 ed.scale = glyph_scale;
1215 sprintf( glyph_factor, "%.2f", (double) (100*glyph_scale) );
1216 sprintf( stem_factor , "%.2f", (double) (100* stem_scale) );
1217
1218 label[k].text = (unichar_t *) _("Uniform scaling for stems of any width and direction");
1219 label[k].text_is_1byte = true;
1220 label[k].text_in_resource = true;
1221 gcd[k].gd.label = &label[k];
1222 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1223 gcd[k].gd.flags = gg_enabled | gg_visible | gg_cb_on;
1224 gcd[k].gd.cid = CID_StemsUniform;
1225 gcd[k].gd.handle_controlevent = CG_SameAs_Changed;
1226 gcd[k++].creator = GRadioCreate;
1227 varrays[l++] = &gcd[k-1]; varrays[l++] = NULL;
1228
1229 label[k].text = (unichar_t *) _("Separate ratios for thin and thick stems");
1230 label[k].text_is_1byte = true;
1231 label[k].text_in_resource = true;
1232 gcd[k].gd.label = &label[k];
1233 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1234 gcd[k].gd.flags = gg_enabled | gg_visible;
1235 gcd[k].gd.cid = CID_Stems_by_Width;
1236 gcd[k].gd.handle_controlevent = CG_SameAs_Changed;
1237 gcd[k++].creator = GRadioCreate;
1238 varrays[l++] = &gcd[k-1]; varrays[l++] = NULL;
1239
1240 label[k].text = (unichar_t *) _("Threshold between \"thin\" and \"thick\":");
1241 label[k].text_is_1byte = true;
1242 label[k].text_in_resource = true;
1243 gcd[k].gd.label = &label[k];
1244 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1245 gcd[k].gd.flags = gg_enabled | gg_visible;
1246 gcd[k++].creator = GLabelCreate;
1247 stemtarray[s++] = &gcd[k-1];
1248
1249 sprintf(stem_threshold,"%.0f",GuessStemThreshold(sf));
1250 label[k].text = (unichar_t *) stem_threshold;
1251 label[k].text_is_1byte = true;
1252 gcd[k].gd.label = &label[k];
1253 gcd[k].gd.flags = gg_visible;
1254 gcd[k].gd.cid = CID_StemThreshold;
1255 gcd[k].gd.pos.width = 60;
1256 gcd[k++].creator = GTextFieldCreate;
1257 stemtarray[s++] = &gcd[k-1];
1258
1259 label[k].text = (unichar_t *) _("em-units");
1260 label[k].text_is_1byte = true;
1261 label[k].text_in_resource = true;
1262 gcd[k].gd.label = &label[k];
1263 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1264 gcd[k].gd.flags = gg_enabled | gg_visible;
1265 gcd[k++].creator = GLabelCreate;
1266 stemtarray[s++] = &gcd[k-1];
1267 stemtarray[s++] = NULL;
1268 stemtarray[s++] = NULL;
1269
1270 boxes[6].gd.flags = gg_enabled|gg_visible;
1271 boxes[6].gd.u.boxelements = stemtarray;
1272 boxes[6].creator = GHVBoxCreate;
1273 varrays[l++] = &boxes[6]; varrays[l++] = NULL;
1274
1275 label[k].text = (unichar_t *) _("Separate ratios for horizontal and vertical stems");
1276 label[k].text_is_1byte = true;
1277 label[k].text_in_resource = true;
1278 gcd[k].gd.label = &label[k];
1279 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1280 gcd[k].gd.flags = gg_enabled | gg_visible | gg_rad_continueold;
1281 gcd[k].gd.cid = CID_Stems_H_V;
1282 gcd[k].gd.handle_controlevent = CG_SameAs_Changed;
1283 gcd[k++].creator = GRadioCreate;
1284 varrays[l++] = &gcd[k-1]; varrays[l++] = NULL;
1285
1286 s = 0;
1287 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1288 gcd[k].gd.flags = gg_enabled | gg_visible;
1289 gcd[k].gd.cid = CID_StemHeightLabel;
1290 gcd[k].gd.u.list = stemheight;
1291 gcd[k++].creator = GLabelCreate;
1292 stemarray[s++] = &gcd[k-1];
1293
1294 label[k].text = (unichar_t *) stem_factor;
1295 label[k].text_is_1byte = true;
1296 gcd[k].gd.label = &label[k];
1297 gcd[k].gd.flags = gg_enabled | gg_visible;
1298 gcd[k].gd.cid = CID_StemHeight;
1299 gcd[k].gd.handle_controlevent = CG_VStem_Changed;
1300 gcd[k].gd.pos.width = 60;
1301 gcd[k++].creator = GTextFieldCreate;
1302 stemarray[s++] = &gcd[k-1];
1303
1304 label[k].text = (unichar_t *) _("% +");
1305 label[k].text_is_1byte = true;
1306 label[k].text_in_resource = true;
1307 gcd[k].gd.label = &label[k];
1308 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1309 gcd[k].gd.flags = gg_enabled | gg_visible;
1310 gcd[k++].creator = GLabelCreate;
1311 stemarray[s++] = &gcd[k-1];
1312
1313 label[k].text = (unichar_t *) "0";
1314 label[k].text_is_1byte = true;
1315 gcd[k].gd.label = &label[k];
1316 gcd[k].gd.flags = gg_enabled | gg_visible;
1317 gcd[k].gd.pos.width = 60;
1318 gcd[k].gd.cid = CID_StemHeightAdd;
1319 gcd[k].gd.handle_controlevent = CG_VStem_Changed;
1320 gcd[k++].creator = GTextFieldCreate;
1321 stemarray[s++] = &gcd[k-1];
1322
1323 label[k].text = (unichar_t *) _("em-units");
1324 label[k].text_is_1byte = true;
1325 label[k].text_in_resource = true;
1326 gcd[k].gd.label = &label[k];
1327 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1328 gcd[k].gd.flags = gg_enabled | gg_visible;
1329 gcd[k++].creator = GLabelCreate;
1330 stemarray[s++] = &gcd[k-1];
1331 stemarray[s++] = NULL;
1332
1333 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1334 gcd[k].gd.flags = gg_enabled | gg_visible;
1335 gcd[k].gd.cid = CID_StemWidthLabel;
1336 gcd[k].gd.u.list = stemwidth;
1337 gcd[k++].creator = GLabelCreate;
1338 stemarray[s++] = &gcd[k-1];
1339
1340 label[k].text = (unichar_t *) stem_factor;
1341 label[k].text_is_1byte = true;
1342 gcd[k].gd.label = &label[k];
1343 gcd[k].gd.flags = gg_visible;
1344 gcd[k].gd.cid = CID_StemWidth;
1345 gcd[k].gd.pos.width = 60;
1346 gcd[k++].creator = GTextFieldCreate;
1347 stemarray[s++] = &gcd[k-1];
1348
1349 label[k].text = (unichar_t *) _("% +");
1350 label[k].text_is_1byte = true;
1351 label[k].text_in_resource = true;
1352 gcd[k].gd.label = &label[k];
1353 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1354 gcd[k].gd.flags = gg_enabled | gg_visible;
1355 gcd[k++].creator = GLabelCreate;
1356 stemarray[s++] = &gcd[k-1];
1357
1358 label[k].text = (unichar_t *) "0";
1359 label[k].text_is_1byte = true;
1360 gcd[k].gd.label = &label[k];
1361 gcd[k].gd.flags = gg_visible;
1362 gcd[k].gd.pos.width = 60;
1363 gcd[k].gd.cid = CID_StemWidthAdd;
1364 gcd[k++].creator = GTextFieldCreate;
1365 stemarray[s++] = &gcd[k-1];
1366
1367 label[k].text = (unichar_t *) _("em-units");
1368 label[k].text_is_1byte = true;
1369 label[k].text_in_resource = true;
1370 gcd[k].gd.label = &label[k];
1371 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1372 gcd[k].gd.flags = gg_enabled | gg_visible;
1373 gcd[k++].creator = GLabelCreate;
1374 stemarray[s++] = &gcd[k-1];
1375 stemarray[s++] = NULL;
1376 stemarray[s++] = NULL;
1377
1378 boxes[7].gd.flags = gg_enabled|gg_visible;
1379 boxes[7].gd.u.boxelements = stemarray;
1380 boxes[7].creator = GHVBoxCreate;
1381 varrays[l++] = &boxes[7]; varrays[l++] = NULL;
1382
1383 label[k].text = (unichar_t *) _("Activate diagonal stem processing");
1384 label[k].text_is_1byte = true;
1385 label[k].text_in_resource = true;
1386 gcd[k].gd.label = &label[k];
1387 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1388 gcd[k].gd.flags = gg_enabled | gg_visible | gg_cb_on;
1389 gcd[k].gd.cid = CID_DStemOn;
1390 gcd[k++].creator = GCheckBoxCreate;
1391 varrays[l++] = &gcd[k-1]; varrays[l++] = NULL;
1392 varrays[l++] = GCD_Glue; varrays[l++] = NULL; varrays[l++] = NULL;
1393
1394 boxes[8].gd.flags = gg_enabled|gg_visible;
1395 boxes[8].gd.u.boxelements = varrays;
1396 boxes[8].creator = GHVBoxCreate;
1397
1398 aspects[a].text = (unichar_t *) _("Stems");
1399 aspects[a].text_is_1byte = true;
1400 aspects[a++].gcd = &boxes[8];
1401
1402 l=s=0;
1403
1404 label[k].text = (unichar_t *) _("Retain current advance width, center glyph within that width");
1405 label[k].text_is_1byte = true;
1406 label[k].text_in_resource = true;
1407 gcd[k].gd.label = &label[k];
1408 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1409 gcd[k].gd.flags = gg_enabled | gg_visible;
1410 gcd[k].gd.cid = CID_Counter_SameAdvance;
1411 gcd[k].gd.handle_controlevent = CG_CounterSameAs_Changed;
1412 gcd[k++].creator = GRadioCreate;
1413 varrayhc[l++] = &gcd[k-1]; varrayhc[l++] = NULL;
1414
1415 label[k].text = (unichar_t *) _("Retain current advance width, scale side bearings proportionally");
1416 label[k].text_is_1byte = true;
1417 label[k].text_in_resource = true;
1418 gcd[k].gd.label = &label[k];
1419 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1420 gcd[k].gd.flags = gg_enabled | gg_visible;
1421 gcd[k].gd.cid = CID_Counter_PropAdvance;
1422 gcd[k].gd.handle_controlevent = CG_CounterSameAs_Changed;
1423 gcd[k++].creator = GRadioCreate;
1424 varrayhc[l++] = &gcd[k-1]; varrayhc[l++] = NULL;
1425
1426 label[k].text = (unichar_t *) _("Uniform scaling for horizontal counters and side bearings");
1427 label[k].text_is_1byte = true;
1428 label[k].text_in_resource = true;
1429 gcd[k].gd.label = &label[k];
1430 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1431 gcd[k].gd.flags = gg_enabled | gg_visible | gg_cb_on;
1432 gcd[k].gd.cid = CID_Counter_is_SideB;
1433 gcd[k].gd.handle_controlevent = CG_CounterSameAs_Changed;
1434 gcd[k++].creator = GRadioCreate;
1435 varrayhc[l++] = &gcd[k-1]; varrayhc[l++] = NULL;
1436
1437 label[k].text = (unichar_t *) _("Non uniform scaling for horizontal counters and side bearings");
1438 label[k].text_is_1byte = true;
1439 label[k].text_in_resource = true;
1440 gcd[k].gd.label = &label[k];
1441 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1442 gcd[k].gd.flags = gg_enabled | gg_visible;
1443 gcd[k].gd.cid = CID_Counter_isnt_SideB;
1444 gcd[k].gd.handle_controlevent = CG_CounterSameAs_Changed;
1445 gcd[k++].creator = GRadioCreate;
1446 varrayhc[l++] = &gcd[k-1]; varrayhc[l++] = NULL;
1447
1448 label[k].text = (unichar_t *) _("Counter Size:");
1449 label[k].text_is_1byte = true;
1450 label[k].text_in_resource = true;
1451 gcd[k].gd.label = &label[k];
1452 gcd[k].gd.flags = gg_enabled | gg_visible;
1453 gcd[k++].creator = GLabelCreate;
1454 stemarrayhc[s++] = &gcd[k-1];
1455
1456 label[k].text = (unichar_t *) glyph_factor;
1457 label[k].text_is_1byte = true;
1458 gcd[k].gd.label = &label[k];
1459 gcd[k].gd.flags = gg_enabled | gg_visible;
1460 gcd[k].gd.cid = CID_CounterPercent;
1461 gcd[k].gd.handle_controlevent = CG_Counter_Changed;
1462 gcd[k].gd.pos.width = 60;
1463 gcd[k++].creator = GTextFieldCreate;
1464 stemarrayhc[s++] = &gcd[k-1];
1465
1466 label[k].text = (unichar_t *) _("% +");
1467 label[k].text_is_1byte = true;
1468 label[k].text_in_resource = true;
1469 gcd[k].gd.label = &label[k];
1470 gcd[k].gd.flags = gg_enabled | gg_visible;
1471 gcd[k++].creator = GLabelCreate;
1472 stemarrayhc[s++] = &gcd[k-1];
1473
1474 label[k].text = (unichar_t *) "0";
1475 label[k].text_is_1byte = true;
1476 gcd[k].gd.label = &label[k];
1477 gcd[k].gd.flags = gg_enabled | gg_visible;
1478 gcd[k].gd.pos.width = 60;
1479 gcd[k].gd.cid = CID_CounterAdd;
1480 gcd[k].gd.handle_controlevent = CG_Counter_Changed;
1481 gcd[k++].creator = GTextFieldCreate;
1482 stemarrayhc[s++] = &gcd[k-1];
1483
1484 label[k].text = (unichar_t *) _("em-units");
1485 label[k].text_is_1byte = true;
1486 label[k].text_in_resource = true;
1487 gcd[k].gd.label = &label[k];
1488 gcd[k].gd.flags = gg_enabled | gg_visible;
1489 gcd[k++].creator = GLabelCreate;
1490 stemarrayhc[s++] = &gcd[k-1];
1491 stemarrayhc[s++] = NULL;
1492
1493 label[k].text = (unichar_t *) _("Left Side Bearing:");
1494 label[k].text_is_1byte = true;
1495 label[k].text_in_resource = true;
1496 gcd[k].gd.label = &label[k];
1497 gcd[k].gd.flags = gg_enabled | gg_visible;
1498 gcd[k++].creator = GLabelCreate;
1499 stemarrayhc[s++] = &gcd[k-1];
1500
1501 label[k].text = (unichar_t *) glyph_factor;
1502 label[k].text_is_1byte = true;
1503 gcd[k].gd.label = &label[k];
1504 gcd[k].gd.flags = gg_visible;
1505 gcd[k].gd.cid = CID_LSBPercent;
1506 gcd[k].gd.pos.width = 60;
1507 gcd[k++].creator = GTextFieldCreate;
1508 stemarrayhc[s++] = &gcd[k-1];
1509
1510 label[k].text = (unichar_t *) _("% +");
1511 label[k].text_is_1byte = true;
1512 label[k].text_in_resource = true;
1513 gcd[k].gd.label = &label[k];
1514 gcd[k].gd.flags = gg_enabled | gg_visible;
1515 gcd[k++].creator = GLabelCreate;
1516 stemarrayhc[s++] = &gcd[k-1];
1517
1518 label[k].text = (unichar_t *) "0";
1519 label[k].text_is_1byte = true;
1520 gcd[k].gd.label = &label[k];
1521 gcd[k].gd.flags = gg_visible;
1522 gcd[k].gd.pos.width = 60;
1523 gcd[k].gd.cid = CID_LSBAdd;
1524 gcd[k++].creator = GTextFieldCreate;
1525 stemarrayhc[s++] = &gcd[k-1];
1526
1527 label[k].text = (unichar_t *) _("em-units");
1528 label[k].text_is_1byte = true;
1529 label[k].text_in_resource = true;
1530 gcd[k].gd.label = &label[k];
1531 gcd[k].gd.flags = gg_enabled | gg_visible;
1532 gcd[k++].creator = GLabelCreate;
1533 stemarrayhc[s++] = &gcd[k-1];
1534 stemarrayhc[s++] = NULL;
1535
1536 label[k].text = (unichar_t *) _("Right Side Bearing:");
1537 label[k].text_is_1byte = true;
1538 label[k].text_in_resource = true;
1539 gcd[k].gd.label = &label[k];
1540 gcd[k].gd.flags = gg_enabled | gg_visible;
1541 gcd[k++].creator = GLabelCreate;
1542 stemarrayhc[s++] = &gcd[k-1];
1543
1544 label[k].text = (unichar_t *) glyph_factor;
1545 label[k].text_is_1byte = true;
1546 gcd[k].gd.label = &label[k];
1547 gcd[k].gd.flags = gg_visible;
1548 gcd[k].gd.cid = CID_RSBPercent;
1549 gcd[k].gd.pos.width = 60;
1550 gcd[k++].creator = GTextFieldCreate;
1551 stemarrayhc[s++] = &gcd[k-1];
1552
1553 label[k].text = (unichar_t *) _("% +");
1554 label[k].text_is_1byte = true;
1555 label[k].text_in_resource = true;
1556 gcd[k].gd.label = &label[k];
1557 gcd[k].gd.flags = gg_enabled | gg_visible;
1558 gcd[k++].creator = GLabelCreate;
1559 stemarrayhc[s++] = &gcd[k-1];
1560
1561 label[k].text = (unichar_t *) "0";
1562 label[k].text_is_1byte = true;
1563 gcd[k].gd.label = &label[k];
1564 gcd[k].gd.flags = gg_visible;
1565 gcd[k].gd.pos.width = 60;
1566 gcd[k].gd.cid = CID_RSBAdd;
1567 gcd[k++].creator = GTextFieldCreate;
1568 stemarrayhc[s++] = &gcd[k-1];
1569
1570 label[k].text = (unichar_t *) _("em-units");
1571 label[k].text_is_1byte = true;
1572 label[k].text_in_resource = true;
1573 gcd[k].gd.label = &label[k];
1574 gcd[k].gd.flags = gg_enabled | gg_visible;
1575 gcd[k++].creator = GLabelCreate;
1576 stemarrayhc[s++] = &gcd[k-1];
1577 stemarrayhc[s++] = NULL;
1578 stemarrayhc[s++] = NULL;
1579
1580 boxes[10].gd.flags = gg_enabled|gg_visible;
1581 boxes[10].gd.u.boxelements = stemarrayhc;
1582 boxes[10].creator = GHVBoxCreate;
1583 varrayhc[l++] = &boxes[10]; varrayhc[l++] = NULL;
1584 varrayhc[l++] = GCD_Glue; varrayhc[l++] = NULL; varrayhc[l++] = NULL;
1585
1586 boxes[11].gd.flags = gg_enabled|gg_visible;
1587 boxes[11].gd.u.boxelements = varrayhc;
1588 boxes[11].creator = GHVBoxCreate;
1589
1590 aspects[a].text = (unichar_t *) _("Horizontal");
1591 aspects[a].text_is_1byte = true;
1592 aspects[a++].gcd = &boxes[11];
1593
1594 l=s=0;
1595
1596 label[k].text = (unichar_t *) _("Control Vertical Counters (use for CJK)");
1597 label[k].text_is_1byte = true;
1598 label[k].text_in_resource = true;
1599 gcd[k].gd.label = &label[k];
1600 gcd[k].gd.flags = gg_enabled | gg_visible;
1601 gcd[k].gd.handle_controlevent = CG_UseVCounters;
1602 gcd[k].gd.cid = CID_UseVerticalCounters;
1603 gcd[k++].creator = GRadioCreate;
1604 varrayvc[l++] = &gcd[k-1]; varrayvc[l++] = NULL;
1605
1606 label[k].text = (unichar_t *) _("Vertical Counters:");
1607 label[k].text_is_1byte = true;
1608 label[k].text_in_resource = true;
1609 gcd[k].gd.label = &label[k];
1610 gcd[k].gd.flags = gg_enabled | gg_visible;
1611 gcd[k++].creator = GLabelCreate;
1612 stemarrayvc[s++] = &gcd[k-1];
1613
1614 label[k].text = (unichar_t *) glyph_factor;
1615 label[k].text_is_1byte = true;
1616 gcd[k].gd.label = &label[k];
1617 gcd[k].gd.flags = gg_visible;
1618 gcd[k].gd.cid = CID_VCounterPercent;
1619 gcd[k].gd.pos.width = 60;
1620 gcd[k++].creator = GTextFieldCreate;
1621 stemarrayvc[s++] = &gcd[k-1];
1622
1623 label[k].text = (unichar_t *) _("% +");
1624 label[k].text_is_1byte = true;
1625 label[k].text_in_resource = true;
1626 gcd[k].gd.label = &label[k];
1627 gcd[k].gd.flags = gg_enabled | gg_visible;
1628 gcd[k++].creator = GLabelCreate;
1629 stemarrayvc[s++] = &gcd[k-1];
1630
1631 label[k].text = (unichar_t *) "0";
1632 label[k].text_is_1byte = true;
1633 gcd[k].gd.label = &label[k];
1634 gcd[k].gd.flags = gg_visible;
1635 gcd[k].gd.pos.width = 60;
1636 gcd[k].gd.cid = CID_VCounterAdd;
1637 gcd[k++].creator = GTextFieldCreate;
1638 stemarrayvc[s++] = &gcd[k-1];
1639
1640 label[k].text = (unichar_t *) _("em-units");
1641 label[k].text_is_1byte = true;
1642 label[k].text_in_resource = true;
1643 gcd[k].gd.label = &label[k];
1644 gcd[k].gd.flags = gg_enabled | gg_visible;
1645 gcd[k++].creator = GLabelCreate;
1646 stemarrayvc[s++] = &gcd[k-1];
1647 stemarrayvc[s++] = NULL; stemarrayvc[s++] = NULL;
1648
1649 if ( s > sizeof(stemarrayvc)/sizeof(stemarrayvc[0]) )
1650 IError( "Increase size of stemarrayvc" );
1651
1652 boxes[13].gd.flags = gg_enabled|gg_visible;
1653 boxes[13].gd.u.boxelements = stemarrayvc;
1654 boxes[13].creator = GHBoxCreate;
1655 varrayvc[l++] = &boxes[13]; varrayvc[l++] = NULL;
1656
1657 label[k].text = (unichar_t *) _("Control Vertical Mapping (use for Latin, Greek, Cyrillic)");
1658 label[k].text_is_1byte = true;
1659 label[k].text_in_resource = true;
1660 gcd[k].gd.label = &label[k];
1661 gcd[k].gd.flags = gg_enabled | gg_visible| gg_cb_on | gg_rad_continueold;
1662 gcd[k].gd.popup_msg = _("These mappings may be used to fix certain standard heights.");
1663 gcd[k].gd.cid = CID_UseVerticalMappings;
1664 gcd[k].gd.handle_controlevent = CG_UseVCounters;
1665 gcd[k++].creator = GRadioCreate;
1666 varrayvc[l++] = &gcd[k-1]; varrayvc[l++] = NULL;
1667
1668 s = 0;
1669 label[k].text = (unichar_t *) _("Vertical Scale:");
1670 label[k].text_is_1byte = true;
1671 label[k].text_in_resource = true;
1672 gcd[k].gd.label = &label[k];
1673 gcd[k].gd.flags = gg_enabled | gg_visible;
1674 gcd[k++].creator = GLabelCreate;
1675 harray[s++] = &gcd[k-1];
1676
1677 label[k].text = (unichar_t *) glyph_factor;
1678 label[k].text_is_1byte = true;
1679 gcd[k].gd.label = &label[k];
1680 gcd[k].gd.flags = gg_enabled | gg_visible;
1681 gcd[k].gd.cid = CID_VerticalScale;
1682 gcd[k].gd.pos.width = 60;
1683 gcd[k].gd.handle_controlevent = CG_VScale_Changed;
1684 gcd[k++].creator = GTextFieldCreate;
1685 harray[s++] = &gcd[k-1];
1686
1687 label[k].text = (unichar_t *) _("%");
1688 label[k].text_is_1byte = true;
1689 label[k].text_in_resource = true;
1690 gcd[k].gd.label = &label[k];
1691 gcd[k].gd.flags = gg_enabled | gg_visible;
1692 gcd[k++].creator = GLabelCreate;
1693 harray[s++] = &gcd[k-1]; harray[s++] = GCD_Glue; harray[s++] = NULL;
1694
1695 boxes[14].gd.flags = gg_enabled|gg_visible;
1696 boxes[14].gd.u.boxelements = harray;
1697 boxes[14].creator = GHBoxCreate;
1698 varrayvc[l++] = &boxes[14]; varrayvc[l++] = NULL;
1699
1700
1701 MappingMatrixInit(&mapmi,
1702 sf,
1703 gc==gc_smallcaps?0:small.xheight,
1704 small.capheight,glyph_scale);
1705
1706 gcd[k].gd.flags = gg_enabled | gg_visible;
1707 gcd[k].gd.cid = CID_VMappings;
1708 gcd[k].gd.u.matrix = &mapmi;
1709 gcd[k++].creator = GMatrixEditCreate;
1710 varrayvc[l++] = &gcd[k-1]; varrayvc[l++] = NULL; varrayvc[l++] = NULL;
1711
1712 boxes[15].gd.flags = gg_enabled|gg_visible;
1713 boxes[15].gd.u.boxelements = varrayvc;
1714 boxes[15].creator = GHVBoxCreate;
1715
1716 aspects[a].text = (unichar_t *) _("Vertical");
1717 aspects[a].text_is_1byte = true;
1718 aspects[a++].gcd = &boxes[15];
1719
1720 l=0;
1721
1722 gcd[k].gd.u.tabs = aspects;
1723 gcd[k].gd.flags = gg_visible | gg_enabled | gg_tabset_scroll;
1724 gcd[k].gd.cid = CID_TabSet;
1725 gcd[k++].creator = GTabSetCreate;
1726 varray[l++] = &gcd[k-1]; varray[l++] = NULL;
1727
1728
1729 gcd[k].gd.pos.x = 30-3; gcd[k].gd.pos.y = 5;
1730 gcd[k].gd.pos.width = -1;
1731 gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_default;
1732 label[k].text = (unichar_t *) _("_OK");
1733 label[k].text_is_1byte = true;
1734 label[k].text_in_resource = true;
1735 gcd[k].gd.label = &label[k];
1736 gcd[k].gd.handle_controlevent = GlyphChange_OK;
1737 gcd[k++].creator = GButtonCreate;
1738 barray[0] = GCD_Glue; barray[1] = &gcd[k-1]; barray[2] = GCD_Glue;
1739
1740 gcd[k].gd.flags = gg_visible | gg_enabled;
1741 gcd[k].gd.popup_msg = _("Everything to its default value");
1742 label[k].text = (unichar_t *) _("Reset");
1743 label[k].text_is_1byte = true;
1744 label[k].text_in_resource = true;
1745 gcd[k].gd.label = &label[k];
1746 gcd[k].gd.handle_controlevent = GlyphChange_Default;
1747 gcd[k++].creator = GButtonCreate;
1748 barray[3] = GCD_Glue; barray[4] = &gcd[k-1]; barray[5] = GCD_Glue;
1749
1750 gcd[k].gd.pos.x = -30; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+3;
1751 gcd[k].gd.pos.width = -1;
1752 gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
1753 label[k].text = (unichar_t *) _("_Cancel");
1754 label[k].text_is_1byte = true;
1755 label[k].text_in_resource = true;
1756 gcd[k].gd.label = &label[k];
1757 gcd[k].gd.handle_controlevent = CondenseExtend_Cancel;
1758 gcd[k].creator = GButtonCreate;
1759 barray[6] = GCD_Glue; barray[7] = &gcd[k]; barray[8] = GCD_Glue;
1760 barray[9] = NULL;
1761
1762 boxes[17].gd.flags = gg_enabled|gg_visible;
1763 boxes[17].gd.u.boxelements = barray;
1764 boxes[17].creator = GHBoxCreate;
1765 varray[l++] = &boxes[17]; varray[l++] = NULL; varray[l++] = NULL;
1766
1767 if ( l>=sizeof(varray)/sizeof(varray[0]))
1768 IError("Increase size of varray" );
1769 if ( k>=sizeof(gcd)/sizeof(gcd[0]))
1770 IError("Increase size of gcd" );
1771 if ( k>=sizeof(label)/sizeof(label[0]))
1772 IError("Increase size of label" );
1773
1774 boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
1775 boxes[0].gd.flags = gg_enabled|gg_visible;
1776 boxes[0].gd.u.boxelements = varray;
1777 boxes[0].creator = GHVGroupCreate;
1778
1779 GGadgetsCreate(gw,boxes);
1780 GHVBoxSetExpandableCol(boxes[13].ret,gb_expandglue);
1781 if ( boxes[2].ret!=NULL )
1782 GHVBoxSetExpandableCol(boxes[2].ret,gb_expandglue);
1783 if ( boxes[3].ret!=NULL )
1784 GHVBoxSetExpandableCol(boxes[3].ret,gb_expandglue);
1785 if ( boxes[4].ret!=NULL )
1786 GHVBoxSetExpandableRow(boxes[4].ret,gb_expandglue);
1787 GHVBoxSetExpandableRow(boxes[8].ret,gb_expandglue);
1788 GHVBoxSetExpandableRow(boxes[11].ret,gb_expandglue);
1789 GHVBoxSetExpandableRow(boxes[15].ret,4);
1790 GHVBoxSetExpandableCol(boxes[17].ret,gb_expandgluesame);
1791 GHVBoxSetExpandableRow(boxes[0].ret,0);
1792 GHVBoxFitWindow(boxes[0].ret);
1793 /* if ( gc==gc_subsuper ) */
1794 /* GMatrixEditShowColumn(GWidgetGetControl(gw,CID_VMappings),2,false);*/
1795 last_dlg[gc] = gw;
1796 last_sf[gc] = sf;
1797 } else {
1798 int err = false;
1799 ed.gw = gw = last_dlg[gc];
1800 ed.scale = GetCalmReal8(gw,CID_VerticalScale,"unused",&err)/100.0;
1801 if ( err )
1802 ed.scale = 1;
1803 GDrawSetUserData(last_dlg[gc],&ed);
1804 GDrawSetTransientFor(last_dlg[gc],(GWindow) -1);
1805 }
1806 GDrawSetVisible(gw,true);
1807
1808 while ( !ed.done )
1809 GDrawProcessOneEvent(NULL);
1810 GDrawSetVisible(gw,false);
1811 }
1812
1813 /* ************************************************************************** */
1814 /* ***************************** Embolden Dialog **************************** */
1815 /* ************************************************************************** */
1816
1817 #define CID_EmBdWidth 1001
1818 #define CID_LCG 1002
1819 #define CID_CJK 1003
1820 #define CID_Auto 1004
1821 #define CID_Custom 1005
1822 #define CID_TopZone 1006
1823 #define CID_BottomZone 1007
1824 #define CID_CleanupSelfIntersect 1008
1825 #define CID_TopHint 1009
1826 #define CID_BottomHint 1010
1827 #define CID_Squish 1011
1828 #define CID_Retain 1012
1829 #define CID_CounterAuto 1013
1830 #define CID_SerifHeight 1014
1831 #define CID_SerifHFuzz 1015
1832
1833 static SplineFont *lastsf = NULL;
1834 static enum embolden_type last_type = embolden_auto;
1835 static struct lcg_zones last_zones;
1836 static int last_width;
1837 static int last_overlap = true;
1838
Embolden_OK(GGadget * g,GEvent * e)1839 static int Embolden_OK(GGadget *g, GEvent *e) {
1840 enum embolden_type type;
1841 struct lcg_zones zones;
1842 int err = false;
1843
1844 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1845 GWindow ew = GGadgetGetWindow(g);
1846 StyleDlg *ed = GDrawGetUserData(ew);
1847 memset(&zones,0,sizeof(zones));
1848 err = false;
1849 zones.stroke_width = GetReal8(ew,CID_EmBdWidth,_("Embolden by"),&err);
1850 type = GGadgetIsChecked( GWidgetGetControl(ew,CID_LCG)) ? embolden_lcg :
1851 GGadgetIsChecked( GWidgetGetControl(ew,CID_CJK)) ? embolden_cjk :
1852 GGadgetIsChecked( GWidgetGetControl(ew,CID_Auto)) ? embolden_auto :
1853 embolden_custom;
1854 zones.serif_height = GetReal8(ew,CID_SerifHeight,_("Serif Height"),&err);
1855 zones.serif_fuzz = GetReal8(ew,CID_SerifHFuzz,_("Serif Height Fuzz"),&err);
1856 if ( type == embolden_custom ) {
1857 zones.top_zone = GetReal8(ew,CID_TopZone,_("Top Zone"),&err);
1858 zones.bottom_zone = GetReal8(ew,CID_BottomZone,_("Bottom Zone"),&err);
1859 zones.top_bound = GetReal8(ew,CID_TopHint,_("Top Hint"),&err);
1860 zones.bottom_bound = GetReal8(ew,CID_BottomHint,_("Bottom Hint"),&err);
1861 }
1862 if ( err )
1863 return( true );
1864 zones.counter_type = GGadgetIsChecked( GWidgetGetControl(ew,CID_Squish)) ? ct_squish :
1865 GGadgetIsChecked( GWidgetGetControl(ew,CID_Retain)) ? ct_retain :
1866 ct_auto;
1867
1868 lastsf = ed->sf;
1869 last_type = type;
1870 last_width = zones.stroke_width;
1871 last_overlap = zones.removeoverlap = GGadgetIsChecked( GWidgetGetControl(ew,CID_CleanupSelfIntersect));
1872 if ( type == embolden_custom )
1873 last_zones = zones;
1874
1875 if ( ed->fv!=NULL )
1876 FVEmbolden((FontViewBase *) ed->fv, type, &zones);
1877 else
1878 CVEmbolden((CharViewBase *) ed->cv, type, &zones);
1879 ed->done = true;
1880 }
1881 return( true );
1882 }
1883
Embolden_Cancel(GGadget * g,GEvent * e)1884 static int Embolden_Cancel(GGadget *g, GEvent *e) {
1885 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1886 StyleDlg *ed = GDrawGetUserData(GGadgetGetWindow(g));
1887 ed->done = true;
1888 }
1889 return( true );
1890 }
1891
Embolden_Radio(GGadget * g,GEvent * e)1892 static int Embolden_Radio(GGadget *g, GEvent *e) {
1893 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
1894 StyleDlg *ed = GDrawGetUserData(GGadgetGetWindow(g));
1895 int en;
1896 en = GGadgetIsChecked( GWidgetGetControl(ed->gw,CID_Custom));
1897 GGadgetSetEnabled(GWidgetGetControl(ed->gw,CID_TopZone),en);
1898 GGadgetSetEnabled(GWidgetGetControl(ed->gw,CID_BottomZone),en);
1899 GGadgetSetEnabled(GWidgetGetControl(ed->gw,CID_TopHint),en);
1900 GGadgetSetEnabled(GWidgetGetControl(ed->gw,CID_BottomHint),en);
1901 }
1902 return( true );
1903 }
1904
EmboldenDlg(FontView * fv,CharView * cv)1905 void EmboldenDlg(FontView *fv, CharView *cv) {
1906 StyleDlg ed;
1907 SplineFont *sf = fv!=NULL ? fv->b.sf : cv->b.sc->parent;
1908 BlueData bd;
1909 GRect pos;
1910 GWindow gw;
1911 GWindowAttrs wattrs;
1912 GGadgetCreateData gcd[27], boxes[6], *barray[8], *rarray[6], *carray[6], *hvarray[10][5];
1913 GTextInfo label[27];
1914 int k;
1915 char topzone[40], botzone[40], emb_width[40], tophint[40], bothint[40], serifh[40];
1916
1917 memset(&ed,0,sizeof(ed));
1918 ed.fv = fv;
1919 ed.cv = cv;
1920 ed.sf = sf;
1921 ed.layer = cv==NULL ? fv->b.active_layer : CVLayer((CharViewBase *) cv);
1922
1923 QuickBlues(sf, ed.layer, &bd);
1924
1925 memset(&wattrs,0,sizeof(wattrs));
1926 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
1927 wattrs.event_masks = ~(1<<et_charup);
1928 wattrs.restrict_input_to_me = 1;
1929 wattrs.undercursor = 1;
1930 wattrs.cursor = ct_pointer;
1931 wattrs.utf8_window_title = _("Change Weight");
1932 wattrs.is_dlg = true;
1933 pos.x = pos.y = 0;
1934 pos.width = 100;
1935 pos.height = 100;
1936 ed.gw = gw = GDrawCreateTopWindow(NULL,&pos,style_e_h,&ed,&wattrs);
1937
1938
1939 k=0;
1940
1941 memset(gcd,0,sizeof(gcd));
1942 memset(boxes,0,sizeof(boxes));
1943 memset(label,0,sizeof(label));
1944 label[k].text = (unichar_t *) _("Embolden by:");
1945 label[k].text_is_1byte = true;
1946 label[k].text_in_resource = true;
1947 gcd[k].gd.label = &label[k];
1948 gcd[k].gd.flags = gg_enabled | gg_visible;
1949 gcd[k++].creator = GLabelCreate;
1950 hvarray[0][0] = &gcd[k-1];
1951
1952 sprintf( emb_width, "%d", sf==lastsf ? last_width : (sf->ascent+sf->descent)/20 );
1953 label[k].text = (unichar_t *) emb_width;
1954 label[k].text_is_1byte = true;
1955 gcd[k].gd.label = &label[k];
1956 gcd[k].gd.pos.width = 60;
1957 gcd[k].gd.flags = gg_enabled | gg_visible;
1958 gcd[k].gd.cid = CID_EmBdWidth;
1959 gcd[k++].creator = GNumericFieldCreate;
1960 hvarray[0][1] = &gcd[k-1];
1961
1962 label[k].text = (unichar_t *) _("em units");
1963 label[k].text_is_1byte = true;
1964 label[k].text_in_resource = true;
1965 gcd[k].gd.label = &label[k];
1966 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
1967 gcd[k].gd.flags = gg_enabled | gg_visible;
1968 gcd[k++].creator = GLabelCreate;
1969 hvarray[0][2] = &gcd[k-1];
1970 hvarray[0][3] = GCD_Glue; hvarray[0][4] = NULL;
1971
1972 label[k].text = (unichar_t *) _("_LCG");
1973 gcd[k].gd.popup_msg = _("Embolden as appropriate for Latin, Cyrillic and Greek scripts");
1974 label[k].text_is_1byte = true;
1975 label[k].text_in_resource = true;
1976 gcd[k].gd.label = &label[k];
1977 gcd[k].gd.flags = gg_enabled | gg_visible;
1978 gcd[k].gd.cid = CID_LCG;
1979 gcd[k].gd.handle_controlevent = Embolden_Radio;
1980 gcd[k++].creator = GRadioCreate;
1981 rarray[0] = &gcd[k-1];
1982
1983 label[k].text = (unichar_t *) _("_CJK");
1984 gcd[k].gd.popup_msg = _("Embolden as appropriate for Chinese, Japanese, Korean scripts");
1985 label[k].text_is_1byte = true;
1986 label[k].text_in_resource = true;
1987 gcd[k].gd.label = &label[k];
1988 gcd[k].gd.flags = gg_enabled | gg_visible;
1989 gcd[k].gd.cid = CID_CJK;
1990 gcd[k].gd.handle_controlevent = Embolden_Radio;
1991 gcd[k++].creator = GRadioCreate;
1992 rarray[1] = &gcd[k-1];
1993
1994 label[k].text = (unichar_t *) _("_Auto");
1995 gcd[k].gd.popup_msg = _("Choose the appropriate method depending on the glyph's script");
1996 label[k].text_is_1byte = true;
1997 label[k].text_in_resource = true;
1998 gcd[k].gd.label = &label[k];
1999 gcd[k].gd.flags = gg_enabled | gg_visible;
2000 gcd[k].gd.cid = CID_Auto;
2001 gcd[k].gd.handle_controlevent = Embolden_Radio;
2002 gcd[k++].creator = GRadioCreate;
2003 rarray[2] = &gcd[k-1];
2004
2005 label[k].text = (unichar_t *) _("C_ustom");
2006 gcd[k].gd.popup_msg = _("User controls the emboldening with the next two fields");
2007 label[k].text_is_1byte = true;
2008 label[k].text_in_resource = true;
2009 gcd[k].gd.label = &label[k];
2010 gcd[k].gd.flags = gg_enabled | gg_visible;
2011 gcd[k].gd.cid = CID_Custom;
2012 gcd[k].gd.handle_controlevent = Embolden_Radio;
2013 gcd[k++].creator = GRadioCreate;
2014 rarray[3] = &gcd[k-1]; rarray[4] = GCD_Glue; rarray[5] = NULL;
2015
2016 if ( lastsf!=sf )
2017 gcd[k-4 + embolden_auto].gd.flags |= gg_cb_on;
2018 else
2019 gcd[k-4 + last_type].gd.flags |= gg_cb_on;
2020
2021 boxes[3].gd.flags = gg_enabled|gg_visible;
2022 boxes[3].gd.u.boxelements = rarray;
2023 boxes[3].creator = GHBoxCreate;
2024 hvarray[1][0] = &boxes[3]; hvarray[1][1] = hvarray[1][2] = hvarray[1][3] = GCD_ColSpan; hvarray[1][4] = NULL;
2025
2026 label[k].text = (unichar_t *) _("_Top hint:");
2027 label[k].text_is_1byte = true;
2028 label[k].text_in_resource = true;
2029 gcd[k].gd.label = &label[k];
2030 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
2031 gcd[k].gd.flags = gg_enabled | gg_visible;
2032 gcd[k++].creator = GLabelCreate;
2033 hvarray[2][0] = &gcd[k-1];
2034
2035 sprintf( tophint, "%d", lastsf==sf && last_type==embolden_custom ? last_zones.top_bound :
2036 (int) rint(bd.xheight>0 ? bd.xheight : bd.caph>0 ? 2*bd.caph/3 :
2037 sf->ascent/2 ));
2038 label[k].text = (unichar_t *) tophint;
2039 label[k].text_is_1byte = true;
2040 gcd[k].gd.label = &label[k];
2041 gcd[k].gd.pos.x = 80; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-3;
2042 gcd[k].gd.pos.width = 60;
2043 gcd[k].gd.flags = gg_visible;
2044 gcd[k].gd.cid = CID_TopHint;
2045 gcd[k++].creator = GNumericFieldCreate;
2046 hvarray[2][1] = &gcd[k-1];
2047
2048 label[k].text = (unichar_t *) _("_Zone:");
2049 label[k].text_is_1byte = true;
2050 label[k].text_in_resource = true;
2051 gcd[k].gd.label = &label[k];
2052 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
2053 gcd[k].gd.flags = gg_enabled | gg_visible;
2054 gcd[k++].creator = GLabelCreate;
2055 hvarray[2][2] = &gcd[k-1];
2056
2057 sprintf( topzone, "%d", lastsf==sf && last_type==embolden_custom ? last_zones.top_zone :
2058 (int) rint(bd.xheight>0 ? 2*bd.xheight/3 :
2059 bd.caph>0 ? 2*bd.caph/3 :
2060 (sf->ascent/3)) );
2061 label[k].text = (unichar_t *) topzone;
2062 label[k].text_is_1byte = true;
2063 gcd[k].gd.label = &label[k];
2064 gcd[k].gd.pos.x = 80; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-3;
2065 gcd[k].gd.pos.width = 60;
2066 gcd[k].gd.flags = gg_visible;
2067 gcd[k].gd.cid = CID_TopZone;
2068 gcd[k++].creator = GNumericFieldCreate;
2069 hvarray[2][3] = &gcd[k-1]; hvarray[2][4] = NULL;
2070
2071 label[k].text = (unichar_t *) _("_Bottom hint:");
2072 label[k].text_is_1byte = true;
2073 label[k].text_in_resource = true;
2074 gcd[k].gd.label = &label[k];
2075 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
2076 gcd[k].gd.flags = gg_enabled | gg_visible;
2077 gcd[k++].creator = GLabelCreate;
2078 hvarray[3][0] = &gcd[k-1];
2079
2080 sprintf( bothint, "%d", lastsf==sf && last_type==embolden_custom ? last_zones.bottom_bound :
2081 0 );
2082 label[k].text = (unichar_t *) bothint;
2083 label[k].text_is_1byte = true;
2084 gcd[k].gd.label = &label[k];
2085 gcd[k].gd.pos.x = 80; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-3;
2086 gcd[k].gd.pos.width = 60;
2087 gcd[k].gd.flags = gg_visible;
2088 gcd[k].gd.cid = CID_BottomHint;
2089 gcd[k++].creator = GNumericFieldCreate;
2090 hvarray[3][1] = &gcd[k-1];
2091
2092 label[k].text = (unichar_t *) _("Zone:");
2093 label[k].text_is_1byte = true;
2094 label[k].text_in_resource = true;
2095 gcd[k].gd.label = &label[k];
2096 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
2097 gcd[k].gd.flags = gg_enabled | gg_visible;
2098 gcd[k++].creator = GLabelCreate;
2099 hvarray[3][2] = &gcd[k-1];
2100
2101 sprintf( botzone, "%d", lastsf==sf && last_type==embolden_custom ? last_zones.bottom_zone :
2102 (int) rint(bd.xheight>0 ? bd.xheight/3 :
2103 bd.caph>0 ? bd.caph/3 :
2104 (sf->ascent/4)) );
2105 label[k].text = (unichar_t *) botzone;
2106 label[k].text_is_1byte = true;
2107 gcd[k].gd.label = &label[k];
2108 gcd[k].gd.pos.x = 80; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-3;
2109 gcd[k].gd.pos.width = 60;
2110 gcd[k].gd.flags = gg_visible;
2111 gcd[k].gd.cid = CID_BottomZone;
2112 gcd[k++].creator = GNumericFieldCreate;
2113 hvarray[3][3] = &gcd[k-1]; hvarray[3][4] = NULL;
2114
2115 label[k].text = (unichar_t *) _("Serif Height");
2116 label[k].text_is_1byte = true;
2117 label[k].text_in_resource = true;
2118 gcd[k].gd.label = &label[k];
2119 gcd[k].gd.flags = gg_enabled | gg_visible;
2120 gcd[k].gd.popup_msg = _("Any points this high will be assumed to be on serifs,\nand will remain at that height after processing.\n(So serifs should remain the same size).\n(If you do wish the serifs to grow, set this to 0)");
2121 gcd[k++].creator = GLabelCreate;
2122 hvarray[4][0] = &gcd[k-1];
2123
2124 sprintf( serifh, "%g", SFSerifHeight(sf));
2125 label[k].text = (unichar_t *) serifh;
2126 label[k].text_is_1byte = true;
2127 gcd[k].gd.label = &label[k];
2128 gcd[k].gd.pos.x = 80; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-3;
2129 gcd[k].gd.pos.width = 60;
2130 gcd[k].gd.flags = gg_enabled | gg_visible;
2131 gcd[k].gd.cid = CID_SerifHeight;
2132 gcd[k].gd.popup_msg = gcd[k-1].gd.popup_msg;
2133 gcd[k++].creator = GNumericFieldCreate;
2134 hvarray[4][1] = &gcd[k-1];
2135
2136 label[k].text = (unichar_t *) _("Fuzz");
2137 label[k].text_is_1byte = true;
2138 label[k].text_in_resource = true;
2139 gcd[k].gd.label = &label[k];
2140 gcd[k].gd.flags = gg_enabled | gg_visible;
2141 gcd[k].gd.popup_msg = _("Allow the height match to differ by this much");
2142 gcd[k++].creator = GLabelCreate;
2143 hvarray[4][2] = &gcd[k-1];
2144
2145 label[k].text = (unichar_t *) ".9";
2146 label[k].text_is_1byte = true;
2147 gcd[k].gd.label = &label[k];
2148 gcd[k].gd.pos.x = 80; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y-3;
2149 gcd[k].gd.pos.width = 60;
2150 gcd[k].gd.flags = gg_enabled | gg_visible;
2151 gcd[k].gd.cid = CID_SerifHFuzz;
2152 gcd[k].gd.popup_msg = gcd[k-1].gd.popup_msg;
2153 gcd[k++].creator = GNumericFieldCreate;
2154 hvarray[4][3] = &gcd[k-1];
2155 hvarray[4][4] = NULL;
2156
2157 label[k].text = (unichar_t *) _("Counters:");
2158 gcd[k].gd.popup_msg = _("The simple application of this algorithm will squeeze counters\nThat is not normally seen in bold latin fonts");
2159 label[k].text_is_1byte = true;
2160 label[k].text_in_resource = true;
2161 gcd[k].gd.label = &label[k];
2162 gcd[k].gd.flags = gg_enabled | gg_visible;
2163 gcd[k++].creator = GLabelCreate;
2164 carray[0] = &gcd[k-1];
2165
2166 label[k].text = (unichar_t *) _("Squish");
2167 gcd[k].gd.popup_msg = _("Make the counters narrower");
2168 label[k].text_is_1byte = true;
2169 label[k].text_in_resource = true;
2170 gcd[k].gd.label = &label[k];
2171 gcd[k].gd.flags = gg_enabled | gg_visible;
2172 gcd[k].gd.cid = CID_Squish;
2173 /*gcd[k].gd.handle_controlevent = Embolden_Counter;*/
2174 gcd[k++].creator = GRadioCreate;
2175 carray[1] = &gcd[k-1];
2176
2177 label[k].text = (unichar_t *) _("Retain");
2178 gcd[k].gd.popup_msg = _("Try to insure that the counters are as wide\nafterward as they were before");
2179 label[k].text_is_1byte = true;
2180 label[k].text_in_resource = true;
2181 gcd[k].gd.label = &label[k];
2182 gcd[k].gd.flags = gg_enabled | gg_visible;
2183 gcd[k].gd.cid = CID_Retain;
2184 /*gcd[k].gd.handle_controlevent = Embolden_Counter;*/
2185 gcd[k++].creator = GRadioCreate;
2186 carray[2] = &gcd[k-1];
2187
2188 label[k].text = (unichar_t *) _("Auto");
2189 gcd[k].gd.popup_msg = _("Retain counter size for glyphs using latin algorithm\nSquish them for those using CJK." );
2190 label[k].text_is_1byte = true;
2191 label[k].text_in_resource = true;
2192 gcd[k].gd.label = &label[k];
2193 gcd[k].gd.flags = gg_enabled | gg_visible| gg_cb_on;
2194 gcd[k].gd.cid = CID_CounterAuto;
2195 /* gcd[k].gd.handle_controlevent = Embolden_Counter;*/
2196 gcd[k++].creator = GRadioCreate;
2197 carray[3] = &gcd[k-1];
2198 carray[4] = GCD_Glue; carray[5] = NULL;
2199
2200 boxes[5].gd.flags = gg_enabled|gg_visible;
2201 boxes[5].gd.u.boxelements = carray;
2202 boxes[5].creator = GHBoxCreate;
2203 hvarray[5][0] = &boxes[5]; hvarray[5][1] = hvarray[5][2] = hvarray[5][3] = GCD_ColSpan; hvarray[5][4] = NULL;
2204
2205 label[k].text = (unichar_t *) _("Cleanup Self Intersect");
2206 label[k].text_is_1byte = true;
2207 label[k].text_in_resource = true;
2208 gcd[k].gd.label = &label[k];
2209 gcd[k].gd.flags = gg_enabled | gg_visible| (last_overlap?gg_cb_on:0);
2210 gcd[k].gd.cid = CID_CleanupSelfIntersect;
2211 gcd[k].gd.popup_msg = _("When FontForge detects that an expanded stroke will self-intersect,\nthen setting this option will cause it to try to make things nice\nby removing the intersections");
2212 gcd[k++].creator = GCheckBoxCreate;
2213 hvarray[6][0] = &gcd[k-1]; hvarray[6][1] = hvarray[6][2] = hvarray[6][3] = GCD_ColSpan; hvarray[6][4] = NULL;
2214
2215 hvarray[7][0] = hvarray[7][1] = hvarray[7][2] = hvarray[7][3] = GCD_Glue; hvarray[7][4] = NULL;
2216
2217 gcd[k].gd.pos.x = 30-3; gcd[k].gd.pos.y = 5;
2218 gcd[k].gd.pos.width = -1;
2219 gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_default;
2220 label[k].text = (unichar_t *) _("_OK");
2221 label[k].text_is_1byte = true;
2222 label[k].text_in_resource = true;
2223 gcd[k].gd.label = &label[k];
2224 gcd[k].gd.handle_controlevent = Embolden_OK;
2225 gcd[k++].creator = GButtonCreate;
2226 barray[0] = GCD_Glue; barray[1] = &gcd[k-1]; barray[2] = GCD_Glue;
2227
2228 gcd[k].gd.pos.x = -30; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+3;
2229 gcd[k].gd.pos.width = -1;
2230 gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
2231 label[k].text = (unichar_t *) _("_Cancel");
2232 label[k].text_is_1byte = true;
2233 label[k].text_in_resource = true;
2234 gcd[k].gd.label = &label[k];
2235 gcd[k].gd.handle_controlevent = Embolden_Cancel;
2236 gcd[k].creator = GButtonCreate;
2237 barray[3] = GCD_Glue; barray[4] = &gcd[k]; barray[5] = GCD_Glue;
2238 barray[6] = NULL;
2239
2240 boxes[4].gd.flags = gg_enabled|gg_visible;
2241 boxes[4].gd.u.boxelements = barray;
2242 boxes[4].creator = GHBoxCreate;
2243 hvarray[8][0] = &boxes[4]; hvarray[8][1] = hvarray[8][2] = hvarray[8][3] = GCD_ColSpan; hvarray[8][4] = NULL;
2244 hvarray[9][0] = NULL;
2245
2246 boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
2247 boxes[0].gd.flags = gg_enabled|gg_visible;
2248 boxes[0].gd.u.boxelements = hvarray[0];
2249 boxes[0].creator = GHVGroupCreate;
2250
2251 GGadgetsCreate(gw,boxes);
2252 GHVBoxSetExpandableRow(boxes[0].ret,gb_expandglue);
2253 GHVBoxSetExpandableCol(boxes[3].ret,gb_expandglue);
2254 GHVBoxSetExpandableCol(boxes[4].ret,gb_expandgluesame);
2255 GHVBoxSetExpandableCol(boxes[5].ret,gb_expandglue);
2256 GHVBoxFitWindow(boxes[0].ret);
2257 GDrawSetVisible(gw,true);
2258
2259 while ( !ed.done )
2260 GDrawProcessOneEvent(NULL);
2261 GDrawDestroyWindow(gw);
2262 }
2263
2264 /* ************************************************************************** */
2265 /* ***************************** Oblique Dialog ***************************** */
2266 /* ************************************************************************** */
2267
2268 static ItalicInfo last_ii = {
2269 -13, /* Italic angle (in degrees) */
2270 .95, /* xheight percent */
2271 /* horizontal squash, lsb, stemsize, countersize, rsb */
2272 { .91, .89, .90, .91 }, /* For lower case */
2273 { .91, .93, .93, .91 }, /* For upper case */
2274 { .91, .93, .93, .91 }, /* For things which are neither upper nor lower case */
2275 srf_flat, /* Secondary serifs (initial, medial on "m", descender on "p", "q" */
2276 true, /* Transform bottom serifs */
2277 true, /* Transform serifs at x-height */
2278 false, /* Transform serifs on ascenders */
2279 true, /* Transform serifs on diagonal stems at baseline and x-height */
2280
2281 true, /* Change the shape of an "a" to look like a "d" without ascender */
2282 false, /* Change the shape of "f" so it descends below baseline (straight down no flag at end) */
2283 true, /* Change the shape of "f" so the bottom looks like the top */
2284 true, /* Remove serifs from the bottom of descenders */
2285
2286 true, /* Make the cyrillic "phi" glyph have a top like an "f" */
2287 true, /* Make the cyrillic "i" glyph look like a latin "u" */
2288 true, /* Make the cyrillic "pi" glyph look like a latin "n" */
2289 true, /* Make the cyrillic "te" glyph look like a latin "m" */
2290 true, /* Make the cyrillic "sha" glyph look like a latin "m" rotated 180 */
2291 true, /* Make the cyrillic "dje" glyph look like a latin smallcaps T (not implemented) */
2292 true, /* Make the cyrillic "dzhe" glyph look like a latin "u" (same glyph used for cyrillic "i") */
2293
2294 ITALICINFO_REMAINDER
2295 };
2296
ObliqueDlg(FontView * fv,CharView * cv)2297 void ObliqueDlg(FontView *fv, CharView *cv) {
2298 bigreal temp;
2299 char def[40], *ret, *end;
2300 real transform[6];
2301
2302 sprintf( def, "%g", last_ii.italic_angle );
2303 ret = gwwv_ask_string(_("Oblique Slant..."),def,_("By what angle (in degrees) do you want to slant the font?"));
2304 if ( ret==NULL )
2305 return;
2306 temp = strtod(ret,&end);
2307 if ( *end || temp>90 || temp<-90 ) {
2308 free(ret);
2309 ff_post_error( _("Bad Number"),_("Bad Number") );
2310 return;
2311 }
2312 free(ret);
2313 last_ii.italic_angle = temp;
2314 memset(transform,0,sizeof(transform));
2315 transform[0] = transform[3] = 1;
2316 transform[2] = -tan( last_ii.italic_angle * FF_PI/180.0 );
2317 if ( cv!=NULL ) {
2318 CVPreserveState((CharViewBase *) cv);
2319 CVTransFunc(cv,transform,fvt_dontmovewidth);
2320 CVCharChangedUpdate(&cv->b);
2321 } else {
2322 int i, gid;
2323 SplineChar *sc;
2324
2325 for ( i=0; i<fv->b.map->enccount; ++i ) if ( fv->b.selected[i] &&
2326 (gid = fv->b.map->map[i])!=-1 && (sc=fv->b.sf->glyphs[gid])!=NULL ) {
2327 FVTrans((FontViewBase *) fv,sc,transform,NULL,fvt_dontmovewidth);
2328 }
2329 }
2330 }
2331
2332
2333 /* ************************************************************************** */
2334 /* ********************************* Italic ********************************* */
2335 /* ************************************************************************** */
2336
2337 #define CID_A 1001
2338 #define CID_F 1002
2339 #define CID_F2 1003
2340 #define CID_P 1004
2341 #define CID_Cyrl_I 1011
2342 #define CID_Cyrl_Pi 1012
2343 #define CID_Cyrl_Te 1013
2344 #define CID_Cyrl_Phi 1014
2345 #define CID_Cyrl_Sha 1015
2346 #define CID_Cyrl_Dje 1016
2347 #define CID_Cyrl_Dzhe 1017
2348 #define CID_BottomSerifs 2001
2349 #define CID_XHeightSerifs 2002
2350 #define CID_AscenderSerifs 2003
2351 #define CID_DiagSerifs 2004
2352 #define CID_Flat 2011
2353 #define CID_Slanted 2012
2354 #define CID_PenSlant 2013
2355 #define CID_CompressLSB 3001 /* for lc, 3011 for uc, 3021 for others */
2356 #define CID_CompressStem 3002 /* for lc, 3012 for uc, 3022 for others */
2357 #define CID_CompressCounter 3003 /* for lc, 3013 for uc, 3023 for others */
2358 #define CID_CompressRSB 3004 /* for lc, 3014 for uc, 3024 for others */
2359 #define CID_XHeightPercent 4001
2360 #define CID_ItalicAngle 4002
2361
Ital_Ok(GGadget * g,GEvent * e)2362 static int Ital_Ok(GGadget *g, GEvent *e) {
2363 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
2364 GWindow ew = GGadgetGetWindow(g);
2365 StyleDlg *ed = GDrawGetUserData(ew);
2366 ItalicInfo ii;
2367 int err = false, i;
2368
2369 memset(&ii,0,sizeof(ii));
2370 for ( i=0; i<3; ++i ) {
2371 struct hsquash *hs = &(&ii.lc)[i];
2372 hs->lsb_percent = GetReal8(ew,CID_CompressLSB+i*10,_("LSB Compression Percent"),&err)/100.0;
2373 hs->stem_percent = GetReal8(ew,CID_CompressStem+i*10,_("Stem Compression Percent"),&err)/100.0;
2374 hs->counter_percent = GetReal8(ew,CID_CompressCounter+i*10,_("Counter Compression Percent"),&err)/100.0;
2375 hs->rsb_percent = GetReal8(ew,CID_CompressRSB+i*10,_("RSB Compression Percent"),&err)/100.0;
2376 if ( err )
2377 return( true );
2378 }
2379 ii.xheight_percent = GetReal8(ew,CID_XHeightPercent,_("XHeight Percent"),&err)/100;
2380 ii.italic_angle = GetReal8(ew,CID_ItalicAngle,_("Italic Angle"),&err);
2381 if ( err )
2382 return( true );
2383
2384 ii.secondary_serif = GGadgetIsChecked(GWidgetGetControl(ew,CID_Flat)) ? srf_flat :
2385 GGadgetIsChecked(GWidgetGetControl(ew,CID_Slanted)) ? srf_simpleslant :
2386 srf_complexslant;
2387
2388 ii.transform_bottom_serifs= GGadgetIsChecked(GWidgetGetControl(ew,CID_BottomSerifs));
2389 ii.transform_top_xh_serifs= GGadgetIsChecked(GWidgetGetControl(ew,CID_XHeightSerifs));
2390 ii.transform_top_as_serifs= GGadgetIsChecked(GWidgetGetControl(ew,CID_AscenderSerifs));
2391 ii.transform_diagon_serifs= GGadgetIsChecked(GWidgetGetControl(ew,CID_DiagSerifs));
2392
2393 ii.a_from_d = GGadgetIsChecked(GWidgetGetControl(ew,CID_A));
2394 ii.f_rotate_top = GGadgetIsChecked(GWidgetGetControl(ew,CID_F));
2395 ii.f_long_tail = GGadgetIsChecked(GWidgetGetControl(ew,CID_F2));
2396 ii.pq_deserif = GGadgetIsChecked(GWidgetGetControl(ew,CID_P));
2397 if ( ii.f_rotate_top && ii.f_long_tail ) {
2398 ff_post_error(_("Bad setting"),_("You may not select both variants of 'f'"));
2399 return( true );
2400 }
2401
2402 ii.cyrl_i = GGadgetIsChecked(GWidgetGetControl(ew,CID_Cyrl_I));
2403 ii.cyrl_pi = GGadgetIsChecked(GWidgetGetControl(ew,CID_Cyrl_Pi));
2404 ii.cyrl_te = GGadgetIsChecked(GWidgetGetControl(ew,CID_Cyrl_Te));
2405 ii.cyrl_phi = GGadgetIsChecked(GWidgetGetControl(ew,CID_Cyrl_Phi));
2406 ii.cyrl_sha = GGadgetIsChecked(GWidgetGetControl(ew,CID_Cyrl_Sha));
2407 ii.cyrl_dje = GGadgetIsChecked(GWidgetGetControl(ew,CID_Cyrl_Dje));
2408 ii.cyrl_dzhe = GGadgetIsChecked(GWidgetGetControl(ew,CID_Cyrl_Dzhe));
2409
2410 last_ii = ii;
2411 MakeItalic((FontViewBase *) ed->fv,(CharViewBase *) ed->cv,&ii);
2412 ed->done = true;
2413 }
2414 return( true );
2415 }
2416
ItalicDlg(FontView * fv,CharView * cv)2417 void ItalicDlg(FontView *fv, CharView *cv) {
2418 StyleDlg ed;
2419 SplineFont *sf = fv!=NULL ? fv->b.sf : cv->b.sc->parent;
2420 GRect pos;
2421 GWindow gw;
2422 GWindowAttrs wattrs;
2423 GGadgetCreateData gcd[54], boxes[7], *forms[30], *compress[5][6], *sarray[5],
2424 *iaarray[3][3], *barray[10], *varray[39];
2425 GTextInfo label[54];
2426 int k,f,r,i;
2427 char lsb[3][40], stems[3][40], counters[3][40], rsb[3][40], ia[40], xp[40];
2428
2429 memset(&ed,0,sizeof(ed));
2430 ed.fv = fv;
2431 ed.cv = cv;
2432 ed.sf = sf;
2433
2434 memset(&wattrs,0,sizeof(wattrs));
2435 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
2436 wattrs.event_masks = ~(1<<et_charup);
2437 wattrs.restrict_input_to_me = 1;
2438 wattrs.undercursor = 1;
2439 wattrs.cursor = ct_pointer;
2440 wattrs.utf8_window_title = _("Italic");
2441 wattrs.is_dlg = true;
2442 pos.x = pos.y = 0;
2443 pos.width = 100;
2444 pos.height = 100;
2445 ed.gw = gw = GDrawCreateTopWindow(NULL,&pos,style_e_h,&ed,&wattrs);
2446
2447 k=f=r=0;
2448
2449 memset(gcd,0,sizeof(gcd));
2450 memset(boxes,0,sizeof(boxes));
2451 memset(label,0,sizeof(label));
2452
2453 label[k].image = &GIcon_aItalic;
2454 gcd[k].gd.label = &label[k];
2455 gcd[k].gd.flags = gg_enabled | gg_visible;
2456 if ( last_ii.a_from_d ) gcd[k].gd.flags |= gg_cb_on;
2457 gcd[k].gd.cid = CID_A;
2458 gcd[k++].creator = GCheckBoxCreate;
2459 forms[f++] = &gcd[k-1];
2460
2461 label[k].image = &GIcon_fItalic;
2462 gcd[k].gd.label = &label[k];
2463 gcd[k].gd.flags = gg_enabled | gg_visible;
2464 if ( last_ii.f_rotate_top ) gcd[k].gd.flags |= gg_cb_on;
2465 gcd[k].gd.cid = CID_F;
2466 gcd[k++].creator = GCheckBoxCreate;
2467 forms[f++] = &gcd[k-1];
2468
2469 label[k].image = &GIcon_f2Italic;
2470 gcd[k].gd.label = &label[k];
2471 gcd[k].gd.flags = gg_enabled | gg_visible;
2472 if ( last_ii.f_long_tail ) gcd[k].gd.flags |= gg_cb_on;
2473 gcd[k].gd.cid = CID_F2;
2474 gcd[k++].creator = GCheckBoxCreate;
2475 forms[f++] = &gcd[k-1];
2476 forms[f++] = GCD_Glue; forms[f++] = NULL;
2477
2478 gcd[k].gd.pos.width = 10; gcd[k].gd.pos.height = 10;
2479 gcd[k].gd.flags = gg_enabled | gg_visible;
2480 gcd[k++].creator = GSpacerCreate;
2481 forms[f++] = GCD_Glue;
2482 forms[f++] = GCD_Glue; forms[f++] = GCD_Glue;
2483 forms[f++] = GCD_Glue; forms[f++] = NULL;
2484
2485 label[k].image = &GIcon_u438Italic;
2486 gcd[k].gd.label = &label[k];
2487 gcd[k].gd.flags = gg_enabled | gg_visible;
2488 if ( last_ii.cyrl_i ) gcd[k].gd.flags |= gg_cb_on;
2489 gcd[k].gd.cid = CID_Cyrl_I;
2490 gcd[k++].creator = GCheckBoxCreate;
2491 forms[f++] = &gcd[k-1];
2492
2493 label[k].image = &GIcon_u43fItalic;
2494 gcd[k].gd.label = &label[k];
2495 gcd[k].gd.flags = gg_enabled | gg_visible;
2496 if ( last_ii.cyrl_pi ) gcd[k].gd.flags |= gg_cb_on;
2497 gcd[k].gd.cid = CID_Cyrl_Pi;
2498 gcd[k++].creator = GCheckBoxCreate;
2499 forms[f++] = &gcd[k-1];
2500
2501 label[k].image = &GIcon_u442Italic;
2502 gcd[k].gd.label = &label[k];
2503 gcd[k].gd.flags = gg_enabled | gg_visible;
2504 if ( last_ii.cyrl_te ) gcd[k].gd.flags |= gg_cb_on;
2505 gcd[k].gd.cid = CID_Cyrl_Te;
2506 gcd[k++].creator = GCheckBoxCreate;
2507 forms[f++] = &gcd[k-1];
2508 forms[f++] = GCD_Glue; forms[f++] = NULL;
2509
2510 label[k].image = &GIcon_u444Italic;
2511 gcd[k].gd.label = &label[k];
2512 gcd[k].gd.flags = gg_enabled | gg_visible;
2513 if ( last_ii.cyrl_phi ) gcd[k].gd.flags |= gg_cb_on;
2514 gcd[k].gd.cid = CID_Cyrl_Phi;
2515 gcd[k++].creator = GCheckBoxCreate;
2516 forms[f++] = &gcd[k-1];
2517
2518 label[k].image = &GIcon_u448Italic;
2519 gcd[k].gd.label = &label[k];
2520 gcd[k].gd.flags = gg_enabled | gg_visible;
2521 if ( last_ii.cyrl_sha ) gcd[k].gd.flags |= gg_cb_on;
2522 gcd[k].gd.cid = CID_Cyrl_Sha;
2523 gcd[k++].creator = GCheckBoxCreate;
2524 forms[f++] = &gcd[k-1];
2525
2526 label[k].image = &GIcon_u452Italic;
2527 gcd[k].gd.label = &label[k];
2528 gcd[k].gd.flags = gg_enabled | gg_visible;
2529 if ( last_ii.cyrl_dje ) gcd[k].gd.flags |= gg_cb_on;
2530 gcd[k].gd.cid = CID_Cyrl_Dje;
2531 gcd[k++].creator = GCheckBoxCreate;
2532 forms[f++] = &gcd[k-1];
2533 forms[f++] = GCD_Glue; forms[f++] = NULL;
2534
2535 label[k].image = &GIcon_u45fItalic;
2536 gcd[k].gd.label = &label[k];
2537 gcd[k].gd.flags = gg_enabled | gg_visible;
2538 if ( last_ii.cyrl_dzhe ) gcd[k].gd.flags |= gg_cb_on;
2539 gcd[k].gd.cid = CID_Cyrl_Dzhe;
2540 gcd[k++].creator = GCheckBoxCreate;
2541 forms[f++] = &gcd[k-1];
2542 forms[f++] = GCD_Glue; forms[f++] = GCD_Glue; forms[f++] = GCD_Glue; forms[f++] = NULL;
2543 forms[f++] = NULL;
2544
2545 boxes[2].gd.flags = gg_enabled|gg_visible;
2546 boxes[2].gd.u.boxelements = forms;
2547 boxes[2].creator = GHVBoxCreate;
2548 varray[r++] = &boxes[2]; varray[r++] = NULL;
2549
2550 gcd[k].gd.flags = gg_visible|gg_enabled ;
2551 gcd[k].gd.pos.height = 5; gcd[k].gd.pos.width = 20;
2552 gcd[k++].creator = GSpacerCreate;
2553 varray[r++] = &gcd[k-1]; varray[r++] = NULL;
2554
2555 label[k].text = (unichar_t *) _("Transform baseline serifs");
2556 label[k].text_is_1byte = true;
2557 label[k].text_in_resource = true;
2558 label[k].image_precedes = true;
2559 label[k].image = &GIcon_BottomSerifs;
2560 gcd[k].gd.label = &label[k];
2561 gcd[k].gd.flags = gg_enabled | gg_visible;
2562 if ( last_ii.transform_bottom_serifs ) gcd[k].gd.flags |= gg_cb_on;
2563 gcd[k].gd.cid = CID_BottomSerifs;
2564 gcd[k++].creator = GCheckBoxCreate;
2565 varray[r++] = &gcd[k-1]; varray[r++] = NULL;
2566
2567 label[k].text = (unichar_t *) _("Transform x-height serifs");
2568 label[k].text_is_1byte = true;
2569 label[k].text_in_resource = true;
2570 label[k].image_precedes = true;
2571 label[k].image = &GIcon_TopSerifs;
2572 gcd[k].gd.label = &label[k];
2573 gcd[k].gd.flags = gg_enabled | gg_visible;
2574 if ( last_ii.transform_top_xh_serifs ) gcd[k].gd.flags |= gg_cb_on;
2575 gcd[k].gd.cid = CID_XHeightSerifs;
2576 gcd[k++].creator = GCheckBoxCreate;
2577 varray[r++] = &gcd[k-1]; varray[r++] = NULL;
2578
2579 label[k].text = (unichar_t *) _("Transform ascender serifs");
2580 label[k].text_is_1byte = true;
2581 label[k].text_in_resource = true;
2582 label[k].image_precedes = true;
2583 label[k].image = &GIcon_TopSerifs;
2584 gcd[k].gd.label = &label[k];
2585 gcd[k].gd.flags = gg_enabled | gg_visible;
2586 if ( last_ii.transform_top_as_serifs ) gcd[k].gd.flags |= gg_cb_on;
2587 gcd[k].gd.cid = CID_AscenderSerifs;
2588 gcd[k++].creator = GCheckBoxCreate;
2589 varray[r++] = &gcd[k-1]; varray[r++] = NULL;
2590
2591 label[k].text = (unichar_t *) _("Transform descender serifs");
2592 label[k].text_is_1byte = true;
2593 label[k].text_in_resource = true;
2594 label[k].image_precedes = true;
2595 label[k].image = &GIcon_pItalic;
2596 gcd[k].gd.label = &label[k];
2597 gcd[k].gd.flags = gg_enabled | gg_visible;
2598 if ( last_ii.pq_deserif ) gcd[k].gd.flags |= gg_cb_on;
2599 gcd[k].gd.cid = CID_P;
2600 gcd[k++].creator = GCheckBoxCreate;
2601 varray[r++] = &gcd[k-1]; varray[r++] = NULL;
2602
2603 label[k].text = (unichar_t *) _("Transform diagonal serifs");
2604 label[k].text_is_1byte = true;
2605 label[k].text_in_resource = true;
2606 label[k].image_precedes = true;
2607 label[k].image = &GIcon_DiagSerifs;
2608 gcd[k].gd.label = &label[k];
2609 gcd[k].gd.flags = gg_enabled | gg_visible;
2610 if ( last_ii.transform_diagon_serifs ) gcd[k].gd.flags |= gg_cb_on;
2611 gcd[k].gd.cid = CID_DiagSerifs;
2612 gcd[k++].creator = GCheckBoxCreate;
2613 varray[r++] = &gcd[k-1]; varray[r++] = NULL;
2614
2615 label[k].text = (unichar_t *) _("When serifs are removed (as first two in \"m\"), replace with:");
2616 label[k].text_is_1byte = true;
2617 gcd[k].gd.label = &label[k];
2618 gcd[k].gd.flags = gg_enabled | gg_visible;
2619 gcd[k++].creator = GLabelCreate;
2620 varray[r++] = &gcd[k-1]; varray[r++] = NULL;
2621
2622 label[k].text = (unichar_t *) _("Flat");
2623 label[k].text_is_1byte = true;
2624 label[k].text_in_resource = true;
2625 label[k].image_precedes = true;
2626 label[k].image = &GIcon_FlatSerif;
2627 gcd[k].gd.label = &label[k];
2628 gcd[k].gd.flags = gg_enabled | gg_visible;
2629 if ( last_ii.secondary_serif==srf_flat ) gcd[k].gd.flags |= gg_cb_on;
2630 gcd[k].gd.cid = CID_Flat;
2631 gcd[k++].creator = GRadioCreate;
2632 sarray[0] = &gcd[k-1];
2633
2634 label[k].text = (unichar_t *) _("Slanted");
2635 label[k].text_is_1byte = true;
2636 label[k].text_in_resource = true;
2637 label[k].image_precedes = true;
2638 label[k].image = &GIcon_SlantSerif;
2639 gcd[k].gd.label = &label[k];
2640 gcd[k].gd.flags = gg_enabled | gg_visible;
2641 if ( last_ii.secondary_serif==srf_simpleslant ) gcd[k].gd.flags |= gg_cb_on;
2642 gcd[k].gd.cid = CID_Slanted;
2643 gcd[k++].creator = GRadioCreate;
2644 sarray[1] = &gcd[k-1];
2645
2646 label[k].text = (unichar_t *) _("Pen Slanted");
2647 label[k].text_is_1byte = true;
2648 label[k].text_in_resource = true;
2649 label[k].image_precedes = true;
2650 label[k].image = &GIcon_PenSerif;
2651 gcd[k].gd.label = &label[k];
2652 gcd[k].gd.flags = gg_enabled | gg_visible;
2653 if ( last_ii.secondary_serif==srf_complexslant ) gcd[k].gd.flags |= gg_cb_on;
2654 gcd[k].gd.cid = CID_PenSlant;
2655 gcd[k++].creator = GRadioCreate;
2656 sarray[2] = &gcd[k-1]; sarray[3] = GCD_Glue; sarray[4] = NULL;
2657
2658 boxes[3].gd.flags = gg_enabled|gg_visible;
2659 boxes[3].gd.u.boxelements = sarray;
2660 boxes[3].creator = GHBoxCreate;
2661 varray[r++] = &boxes[3]; varray[r++] = NULL;
2662
2663 gcd[k].gd.flags = gg_visible|gg_enabled ;
2664 gcd[k].gd.pos.height = 5; gcd[k].gd.pos.width = 20;
2665 gcd[k++].creator = GSpacerCreate;
2666 varray[r++] = &gcd[k-1]; varray[r++] = NULL;
2667
2668 label[k].text = (unichar_t *) _("Compress (as a percentage)");
2669 label[k].text_is_1byte = true;
2670 gcd[k].gd.label = &label[k];
2671 gcd[k].gd.flags = gg_enabled | gg_visible;
2672 gcd[k++].creator = GLabelCreate;
2673 varray[r++] = &gcd[k-1]; varray[r++] = NULL;
2674
2675 compress[0][0] = GCD_Glue;
2676
2677 label[k].text = (unichar_t *) _("LSB");
2678 label[k].text_is_1byte = true;
2679 gcd[k].gd.label = &label[k];
2680 gcd[k].gd.flags = gg_enabled | gg_visible;
2681 gcd[k].gd.popup_msg = _("Left Side Bearing");
2682 gcd[k++].creator = GLabelCreate;
2683 compress[0][1] = &gcd[k-1];
2684
2685 label[k].text = (unichar_t *) _("Stems");
2686 label[k].text_is_1byte = true;
2687 gcd[k].gd.label = &label[k];
2688 gcd[k].gd.flags = gg_enabled | gg_visible;
2689 gcd[k++].creator = GLabelCreate;
2690 compress[0][2] = &gcd[k-1];
2691
2692 label[k].text = (unichar_t *) _("Counters");
2693 label[k].text_is_1byte = true;
2694 gcd[k].gd.label = &label[k];
2695 gcd[k].gd.flags = gg_enabled | gg_visible;
2696 gcd[k++].creator = GLabelCreate;
2697 compress[0][3] = &gcd[k-1];
2698
2699 label[k].text = (unichar_t *) _("RSB");
2700 label[k].text_is_1byte = true;
2701 gcd[k].gd.label = &label[k];
2702 gcd[k].gd.flags = gg_enabled | gg_visible;
2703 gcd[k].gd.popup_msg = _("Right Side Bearing");
2704 gcd[k++].creator = GLabelCreate;
2705 compress[0][4] = &gcd[k-1]; compress[0][5] = NULL;
2706
2707 for ( i=0; i<3; ++i ) {
2708 struct hsquash *hs = &(&last_ii.lc)[i];
2709
2710 label[k].text = (unichar_t *) (i==0 ? _("Lower Case") : i==1 ? _("Upper Case") : _("Others"));
2711 label[k].text_is_1byte = true;
2712 gcd[k].gd.label = &label[k];
2713 gcd[k].gd.flags = gg_enabled | gg_visible;
2714 gcd[k++].creator = GLabelCreate;
2715 compress[i+1][0] = &gcd[k-1];
2716
2717 sprintf( lsb[i], "%g", 100.0* hs->lsb_percent );
2718 label[k].text = (unichar_t *) lsb[i];
2719 label[k].text_is_1byte = true;
2720 gcd[k].gd.label = &label[k];
2721 gcd[k].gd.pos.width = 50;
2722 gcd[k].gd.flags = gg_enabled|gg_visible;
2723 gcd[k].gd.cid = CID_CompressLSB+10*i;
2724 gcd[k++].creator = GTextFieldCreate;
2725 compress[i+1][1] = &gcd[k-1];
2726
2727 sprintf( stems[i], "%g", 100.0* hs->stem_percent );
2728 label[k].text = (unichar_t *) stems[i];
2729 label[k].text_is_1byte = true;
2730 gcd[k].gd.label = &label[k];
2731 gcd[k].gd.pos.width = 50;
2732 gcd[k].gd.flags = gg_enabled|gg_visible;
2733 gcd[k].gd.cid = CID_CompressStem+10*i;
2734 gcd[k++].creator = GTextFieldCreate;
2735 compress[i+1][2] = &gcd[k-1];
2736
2737 sprintf( counters[i], "%g", 100.0* hs->counter_percent );
2738 label[k].text = (unichar_t *) counters[i];
2739 label[k].text_is_1byte = true;
2740 gcd[k].gd.label = &label[k];
2741 gcd[k].gd.pos.width = 50;
2742 gcd[k].gd.flags = gg_enabled|gg_visible;
2743 gcd[k].gd.cid = CID_CompressCounter+10*i;
2744 gcd[k++].creator = GTextFieldCreate;
2745 compress[i+1][3] = &gcd[k-1];
2746
2747 sprintf( rsb[i], "%g", 100.0* hs->rsb_percent );
2748 label[k].text = (unichar_t *) rsb[i];
2749 label[k].text_is_1byte = true;
2750 gcd[k].gd.label = &label[k];
2751 gcd[k].gd.pos.width = 50;
2752 gcd[k].gd.flags = gg_enabled|gg_visible;
2753 gcd[k].gd.cid = CID_CompressRSB+10*i;
2754 gcd[k++].creator = GTextFieldCreate;
2755 compress[i+1][4] = &gcd[k-1]; compress[i+1][5] = NULL;
2756 }
2757 compress[i+1][0] = NULL;
2758
2759 boxes[4].gd.flags = gg_enabled|gg_visible;
2760 boxes[4].gd.u.boxelements = compress[0];
2761 boxes[4].creator = GHVBoxCreate;
2762 varray[r++] = &boxes[4]; varray[r++] = NULL;
2763
2764 gcd[k].gd.flags = gg_visible|gg_enabled ;
2765 gcd[k].gd.pos.height = 5; gcd[k].gd.pos.width = 20;
2766 gcd[k++].creator = GSpacerCreate;
2767 varray[r++] = &gcd[k-1]; varray[r++] = NULL;
2768
2769 label[k].text = (unichar_t *) _("XHeight Percent:");
2770 label[k].text_is_1byte = true;
2771 gcd[k].gd.label = &label[k];
2772 gcd[k].gd.flags = gg_enabled | gg_visible;
2773 gcd[k++].creator = GLabelCreate;
2774 iaarray[0][0] = &gcd[k-1];
2775
2776 sprintf( xp, "%g", rint(last_ii.xheight_percent*100) );
2777 label[k].text = (unichar_t *) xp;
2778 label[k].text_is_1byte = true;
2779 gcd[k].gd.label = &label[k];
2780 gcd[k].gd.pos.width = 50;
2781 gcd[k].gd.flags = gg_enabled|gg_visible;
2782 gcd[k].gd.cid = CID_XHeightPercent;
2783 gcd[k].gd.popup_msg = _("Traditionally the x-height of an italic face is slightly less\nthan the x-height of the companion roman");
2784 gcd[k++].creator = GTextFieldCreate;
2785 iaarray[0][1] = &gcd[k-1]; iaarray[0][2] = NULL;
2786
2787 label[k].text = (unichar_t *) _("Italic Angle:");
2788 label[k].text_is_1byte = true;
2789 gcd[k].gd.label = &label[k];
2790 gcd[k].gd.flags = gg_enabled | gg_visible;
2791 gcd[k++].creator = GLabelCreate;
2792 iaarray[1][0] = &gcd[k-1];
2793
2794 sprintf( ia, "%g", last_ii.italic_angle );
2795 label[k].text = (unichar_t *) ia;
2796 label[k].text_is_1byte = true;
2797 gcd[k].gd.label = &label[k];
2798 gcd[k].gd.pos.width = 50;
2799 gcd[k].gd.flags = gg_enabled|gg_visible;
2800 gcd[k].gd.cid = CID_ItalicAngle;
2801 gcd[k++].creator = GTextFieldCreate;
2802 iaarray[1][1] = &gcd[k-1]; iaarray[1][2] = NULL; iaarray[2][0] = NULL;
2803
2804 boxes[5].gd.flags = gg_enabled|gg_visible;
2805 boxes[5].gd.u.boxelements = iaarray[0];
2806 boxes[5].creator = GHVBoxCreate;
2807 varray[r++] = &boxes[5]; varray[r++] = NULL;
2808
2809 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = 17+31+16;
2810 gcd[k].gd.pos.width = 190-10;
2811 gcd[k].gd.flags = gg_enabled|gg_visible;
2812 gcd[k++].creator = GLineCreate;
2813 varray[r++] = &gcd[k-1]; varray[r++] = NULL;
2814
2815 label[k].text = (unichar_t *) U_(
2816 "This italic conversion will be incomplete!\n"
2817 "You will probably want to do manual fixups on e, g, k, and v-z\n"
2818 "And on в, г, д, е, ж, л, м, ц, щ, ъ, ђ\n"
2819 "And on all Greek lower case letters. And maybe everything else.");
2820 label[k].text_is_1byte = true;
2821 gcd[k].gd.label = &label[k];
2822 gcd[k].gd.flags = gg_enabled | gg_visible;
2823 gcd[k++].creator = GLabelCreate;
2824 varray[r++] = &gcd[k-1]; varray[r++] = NULL;
2825
2826 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = 17+31+16;
2827 gcd[k].gd.pos.width = 190-10;
2828 gcd[k].gd.flags = gg_enabled|gg_visible;
2829 gcd[k++].creator = GLineCreate;
2830 varray[r++] = &gcd[k-1]; varray[r++] = NULL;
2831
2832 label[k].text = (unichar_t *) _("_OK");
2833 label[k].text_is_1byte = true;
2834 label[k].text_in_resource = true;
2835 gcd[k].gd.label = &label[k];
2836 gcd[k].gd.flags = gg_enabled|gg_visible|gg_but_default;
2837 gcd[k].gd.handle_controlevent = Ital_Ok;
2838 gcd[k++].creator = GButtonCreate;
2839
2840 label[k].text = (unichar_t *) _("_Cancel");
2841 label[k].text_is_1byte = true;
2842 label[k].text_in_resource = true;
2843 gcd[k].gd.label = &label[k];
2844 gcd[k].gd.flags = gg_enabled|gg_visible|gg_but_cancel;
2845 gcd[k].gd.handle_controlevent = CondenseExtend_Cancel;
2846 gcd[k++].creator = GButtonCreate;
2847
2848 if ( k>sizeof(gcd)/sizeof(gcd[0]) )
2849 IError( "Too many options in Italic Dlg");
2850
2851 barray[0] = GCD_Glue; barray[1] = &gcd[k-2]; barray[2] = GCD_Glue;
2852 barray[3] = GCD_Glue; barray[4] = &gcd[k-1]; barray[5] = GCD_Glue;
2853 barray[6] = NULL;
2854
2855 boxes[6].gd.flags = gg_enabled|gg_visible;
2856 boxes[6].gd.u.boxelements = barray;
2857 boxes[6].creator = GHBoxCreate;
2858 varray[r++] = &boxes[6]; varray[r++] = NULL;
2859 varray[r++] = NULL;
2860 if ( r>sizeof(varray)/sizeof(varray[0]) )
2861 IError( "Too many rows in Italic Dlg");
2862
2863 boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
2864 boxes[0].gd.flags = gg_enabled|gg_visible;
2865 boxes[0].gd.u.boxelements = varray;
2866 boxes[0].creator = GHVGroupCreate;
2867
2868 GGadgetsCreate(gw,boxes);
2869
2870 GHVBoxSetExpandableCol(boxes[2].ret,gb_expandglue);
2871 GHVBoxSetExpandableCol(boxes[3].ret,gb_expandglue);
2872 GHVBoxSetExpandableCol(boxes[5].ret,gb_expandglue);
2873 GHVBoxSetExpandableCol(boxes[6].ret,gb_expandgluesame);
2874 GHVBoxFitWindow(boxes[0].ret);
2875
2876 GDrawSetVisible(gw,true);
2877
2878 while ( !ed.done )
2879 GDrawProcessOneEvent(NULL);
2880
2881 GDrawDestroyWindow(gw);
2882 }
2883
2884 /* ************************************************************************** */
2885 /* ************************* Change XHeight Dialog ************************** */
2886 /* ************************************************************************** */
2887 #define CID_XHeight_Current 1001
2888 #define CID_XHeight_Desired 1002
2889 #define CID_Serif_Height 1003
2890
XHeight_OK(GGadget * g,GEvent * e)2891 static int XHeight_OK(GGadget *g, GEvent *e) {
2892 int err = false;
2893 struct xheightinfo xi;
2894
2895 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
2896 GWindow ew = GGadgetGetWindow(g);
2897 StyleDlg *ed = GDrawGetUserData(ew);
2898 xi.xheight_current = GetReal8(ew,CID_XHeight_Current,_("Current X-Height"),&err);
2899 xi.xheight_desired = GetReal8(ew,CID_XHeight_Desired,_("Desired X-Height"),&err);
2900 xi.serif_height = GetReal8(ew,CID_Serif_Height ,_("Serif Height"),&err);
2901 if ( err )
2902 return( true );
2903
2904 ChangeXHeight( (FontViewBase *) ed->fv, (CharViewBase *) ed->cv, &xi );
2905 ed->done = true;
2906 }
2907 return( true );
2908 }
2909
ChangeXHeightDlg(FontView * fv,CharView * cv)2910 void ChangeXHeightDlg(FontView *fv,CharView *cv) {
2911 StyleDlg ed;
2912 SplineFont *sf = fv!=NULL ? fv->b.sf : cv->b.sc->parent;
2913 GRect pos;
2914 GWindow gw;
2915 GWindowAttrs wattrs;
2916 GGadgetCreateData gcd[31], boxes[7], *barray[8], *hvarray[40];
2917 GTextInfo label[31];
2918 int k;
2919 char xh_c[40], xh_d[40], sh[40];
2920 struct xheightinfo xi;
2921
2922 memset(&ed,0,sizeof(ed));
2923 ed.fv = fv;
2924 ed.cv = cv;
2925 ed.sf = sf;
2926
2927 InitXHeightInfo(sf,fv!=NULL ? fv->b.active_layer: CVLayer((CharViewBase *) cv),&xi);
2928
2929 memset(&wattrs,0,sizeof(wattrs));
2930 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
2931 wattrs.event_masks = ~(1<<et_charup);
2932 wattrs.restrict_input_to_me = 1;
2933 wattrs.undercursor = 1;
2934 wattrs.cursor = ct_pointer;
2935 wattrs.utf8_window_title = _("Change XHeight");
2936 wattrs.is_dlg = true;
2937 pos.x = pos.y = 0;
2938 pos.width = 100;
2939 pos.height = 100;
2940 ed.gw = gw = GDrawCreateTopWindow(NULL,&pos,style_e_h,&ed,&wattrs);
2941
2942
2943 k=0;
2944
2945 memset(gcd,0,sizeof(gcd));
2946 memset(boxes,0,sizeof(boxes));
2947 memset(label,0,sizeof(label));
2948
2949 label[k].text = (unichar_t *) _("Current x-height:");
2950 label[k].text_is_1byte = true;
2951 label[k].text_in_resource = true;
2952 gcd[k].gd.label = &label[k];
2953 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = 0;
2954 gcd[k].gd.flags = gg_visible | gg_enabled ;
2955 gcd[k++].creator = GLabelCreate;
2956
2957 sprintf( xh_c, "%g", rint( xi.xheight_current ));
2958 label[k].text = (unichar_t *) xh_c;
2959 label[k].text_is_1byte = true;
2960 gcd[k].gd.label = &label[k];
2961 gcd[k].gd.flags = gg_visible | gg_enabled;
2962 gcd[k].gd.cid = CID_XHeight_Current;
2963 gcd[k++].creator = GTextFieldCreate;
2964 hvarray[0] = &gcd[k-2]; hvarray[1] = &gcd[k-1]; hvarray[2] = NULL;
2965
2966 label[k].text = (unichar_t *) _("Desired x-height:");
2967 label[k].text_is_1byte = true;
2968 label[k].text_in_resource = true;
2969 gcd[k].gd.label = &label[k];
2970 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
2971 gcd[k].gd.flags = gg_visible | gg_enabled;
2972 gcd[k++].creator = GLabelCreate;
2973
2974 sprintf( xh_d, "%g", rint( xi.xheight_current ));
2975 label[k].text = (unichar_t *) xh_d;
2976 label[k].text_is_1byte = true;
2977 gcd[k].gd.label = &label[k];
2978 gcd[k].gd.flags = gg_visible | gg_enabled;
2979 gcd[k].gd.cid = CID_XHeight_Desired;
2980 gcd[k++].creator = GTextFieldCreate;
2981 hvarray[3] = &gcd[k-2]; hvarray[4] = &gcd[k-1]; hvarray[5] = NULL;
2982
2983 label[k].text = (unichar_t *) _("Serif height:");
2984 label[k].text_is_1byte = true;
2985 label[k].text_in_resource = true;
2986 gcd[k].gd.label = &label[k];
2987 gcd[k].gd.pos.x = 5; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+31;
2988 gcd[k].gd.flags = gg_visible | gg_enabled;
2989 gcd[k++].creator = GLabelCreate;
2990
2991 sprintf( sh, "%g", rint( xi.xheight_desired ));
2992 label[k].text = (unichar_t *) sh;
2993 label[k].text_is_1byte = true;
2994 gcd[k].gd.label = &label[k];
2995 gcd[k].gd.flags = gg_visible | gg_enabled;
2996 gcd[k].gd.cid = CID_Serif_Height;
2997 gcd[k++].creator = GTextFieldCreate;
2998 hvarray[6] = &gcd[k-2]; hvarray[7] = &gcd[k-1]; hvarray[8] = NULL;
2999
3000 gcd[k].gd.pos.x = 30-3; gcd[k].gd.pos.y = 5;
3001 gcd[k].gd.pos.width = -1;
3002 gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_default;
3003 label[k].text = (unichar_t *) _("_OK");
3004 label[k].text_is_1byte = true;
3005 label[k].text_in_resource = true;
3006 gcd[k].gd.label = &label[k];
3007 gcd[k].gd.handle_controlevent = XHeight_OK;
3008 gcd[k++].creator = GButtonCreate;
3009 barray[0] = GCD_Glue; barray[1] = &gcd[k-1]; barray[2] = GCD_Glue;
3010
3011 gcd[k].gd.pos.x = -30; gcd[k].gd.pos.y = gcd[k-1].gd.pos.y+3;
3012 gcd[k].gd.pos.width = -1;
3013 gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
3014 label[k].text = (unichar_t *) _("_Cancel");
3015 label[k].text_is_1byte = true;
3016 label[k].text_in_resource = true;
3017 gcd[k].gd.label = &label[k];
3018 gcd[k].gd.handle_controlevent = CondenseExtend_Cancel;
3019 gcd[k].creator = GButtonCreate;
3020 barray[3] = GCD_Glue; barray[4] = &gcd[k]; barray[5] = GCD_Glue;
3021 barray[6] = NULL;
3022
3023 boxes[3].gd.flags = gg_enabled|gg_visible;
3024 boxes[3].gd.u.boxelements = barray;
3025 boxes[3].creator = GHBoxCreate;
3026 hvarray[9] = &boxes[3]; hvarray[10] = GCD_ColSpan; hvarray[11] = NULL;
3027 hvarray[12] = NULL;
3028
3029 boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
3030 boxes[0].gd.flags = gg_enabled|gg_visible;
3031 boxes[0].gd.u.boxelements = hvarray;
3032 boxes[0].creator = GHVGroupCreate;
3033
3034 GGadgetsCreate(gw,boxes);
3035 GHVBoxSetExpandableCol(boxes[3].ret,gb_expandgluesame);
3036 GHVBoxFitWindow(boxes[0].ret);
3037 GDrawSetVisible(gw,true);
3038
3039 while ( !ed.done )
3040 GDrawProcessOneEvent(NULL);
3041 GDrawDestroyWindow(gw);
3042 }
3043