Line data Source code
1 : /* Copyright (C) 2000-2012 by George Williams */
2 : /*
3 : * Redistribution and use in source and binary forms, with or without
4 : * modification, are permitted provided that the following conditions are met:
5 :
6 : * Redistributions of source code must retain the above copyright notice, this
7 : * list of conditions and the following disclaimer.
8 :
9 : * Redistributions in binary form must reproduce the above copyright notice,
10 : * this list of conditions and the following disclaimer in the documentation
11 : * and/or other materials provided with the distribution.
12 :
13 : * The name of the author may not be used to endorse or promote products
14 : * derived from this software without specific prior written permission.
15 :
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 : * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 : * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 : #include "fontforgeui.h"
28 : #include "fvfonts.h"
29 : #include "splineutil.h"
30 : #include "ustring.h"
31 : #include "utype.h"
32 : #include "gfile.h"
33 : #include "chardata.h"
34 :
35 0 : static void MergeAskFilename(FontView *fv,int preserveCrossFontKerning) {
36 0 : char *filename = GetPostScriptFontName(NULL,true);
37 : SplineFont *sf;
38 : char *eod, *fpt, *file, *full;
39 :
40 0 : if ( filename==NULL )
41 0 : return;
42 0 : eod = strrchr(filename,'/');
43 0 : *eod = '\0';
44 0 : file = eod+1;
45 : do {
46 0 : fpt = strstr(file,"; ");
47 0 : if ( fpt!=NULL ) *fpt = '\0';
48 0 : full = malloc(strlen(filename)+1+strlen(file)+1);
49 0 : strcpy(full,filename); strcat(full,"/"); strcat(full,file);
50 0 : sf = LoadSplineFont(full,0);
51 0 : if ( sf!=NULL && sf->fv==NULL )
52 0 : EncMapFree(sf->map);
53 0 : free(full);
54 0 : if ( sf==NULL )
55 : /* Do Nothing */;
56 0 : else if ( sf->fv==(FontViewBase *) fv )
57 0 : ff_post_error(_("Merging Problem"),_("Merging a font with itself achieves nothing"));
58 : else {
59 0 : if ( preserveCrossFontKerning==-1 ) {
60 : char *buts[4];
61 : int ret;
62 0 : buts[0] = _("_Yes"); buts[1] = _("_No"); buts[2] = _("_Cancel"); buts[3]=NULL;
63 0 : ret = gwwv_ask(_("Kerning"),(const char **) buts,0,2,
64 0 : _("Do you want to retain kerning information from the selected font\nwhen one of the glyphs being kerned will come from the base font?"));
65 0 : if ( ret==2 ) {
66 0 : free(filename);
67 0 : return;
68 : }
69 0 : preserveCrossFontKerning = ret==0;
70 : }
71 0 : MergeFont((FontViewBase *) fv,sf,preserveCrossFontKerning);
72 : }
73 0 : file = fpt+2;
74 0 : } while ( fpt!=NULL );
75 0 : free(filename);
76 : }
77 :
78 0 : GTextInfo *BuildFontList(FontView *except) {
79 : FontView *fv;
80 0 : int cnt=0;
81 : GTextInfo *tf;
82 :
83 0 : for ( fv=fv_list; fv!=NULL; fv = (FontView *) (fv->b.next) )
84 0 : ++cnt;
85 0 : tf = calloc(cnt+3,sizeof(GTextInfo));
86 0 : for ( fv=fv_list, cnt=0; fv!=NULL; fv = (FontView *) (fv->b.next) ) if ( fv!=except ) {
87 0 : tf[cnt].fg = tf[cnt].bg = COLOR_DEFAULT;
88 0 : tf[cnt].text = (unichar_t *) fv->b.sf->fontname;
89 0 : tf[cnt].text_is_1byte = true;
90 0 : ++cnt;
91 : }
92 0 : tf[cnt++].line = true;
93 0 : tf[cnt].fg = tf[cnt].bg = COLOR_DEFAULT;
94 0 : tf[cnt].text_is_1byte = true;
95 0 : tf[cnt++].text = (unichar_t *) _("Other ...");
96 0 : return( tf );
97 : }
98 :
99 0 : void TFFree(GTextInfo *tf) {
100 : /*
101 : int i;
102 :
103 : for ( i=0; tf[i].text!=NULL || tf[i].line ; ++i )
104 : if ( !tf[i].text_in_resource )
105 : free( tf[i].text );
106 : */
107 0 : free(tf);
108 0 : }
109 :
110 : struct mf_data {
111 : int done;
112 : FontView *fv;
113 : GGadget *other;
114 : GGadget *amount;
115 : };
116 : #define CID_Preserve 1001
117 :
118 0 : static int MF_OK(GGadget *g, GEvent *e) {
119 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
120 0 : GWindow gw = GGadgetGetWindow(g);
121 0 : struct mf_data *d = GDrawGetUserData(gw);
122 0 : int i, index = GGadgetGetFirstListSelectedItem(d->other);
123 0 : int preserve = GGadgetIsChecked(GWidgetGetControl(gw,CID_Preserve));
124 : FontView *fv;
125 0 : for ( i=0, fv=fv_list; fv!=NULL; fv=(FontView *) (fv->b.next) ) {
126 0 : if ( fv==d->fv )
127 0 : continue;
128 0 : if ( i==index )
129 0 : break;
130 0 : ++i;
131 : }
132 0 : if ( fv==NULL )
133 0 : MergeAskFilename(d->fv,preserve);
134 : else
135 0 : MergeFont((FontViewBase *) d->fv,fv->b.sf,preserve);
136 0 : d->done = true;
137 : }
138 0 : return( true );
139 : }
140 :
141 0 : static int MF_Cancel(GGadget *g, GEvent *e) {
142 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
143 0 : GWindow gw = GGadgetGetWindow(g);
144 0 : struct mf_data *d = GDrawGetUserData(gw);
145 0 : d->done = true;
146 : }
147 0 : return( true );
148 : }
149 :
150 0 : static int mv_e_h(GWindow gw, GEvent *event) {
151 0 : if ( event->type==et_close ) {
152 0 : struct mf_data *d = GDrawGetUserData(gw);
153 0 : d->done = true;
154 0 : } else if ( event->type == et_char ) {
155 0 : return( false );
156 : }
157 0 : return( true );
158 : }
159 :
160 0 : void FVMergeFonts(FontView *fv) {
161 : GRect pos;
162 : GWindow gw;
163 : GWindowAttrs wattrs;
164 : GGadgetCreateData gcd[7], *varray[9], *barray[8], boxes[4];
165 : GTextInfo label[7];
166 : struct mf_data d;
167 : char buffer[80];
168 :
169 : /* If there's only one font loaded, then it's the current one, and there's*/
170 : /* no point asking the user if s/he wants to merge any of the loaded */
171 : /* fonts, go directly to searching the disk */
172 0 : if ( fv_list==fv && fv_list->b.next==NULL )
173 0 : MergeAskFilename(fv,-1);
174 : else {
175 0 : memset(&wattrs,0,sizeof(wattrs));
176 0 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict|wam_isdlg;
177 0 : wattrs.event_masks = ~(1<<et_charup);
178 0 : wattrs.restrict_input_to_me = 1;
179 0 : wattrs.is_dlg = 1;
180 0 : wattrs.undercursor = 1;
181 0 : wattrs.cursor = ct_pointer;
182 0 : wattrs.utf8_window_title = _("Merge Fonts");
183 0 : pos.x = pos.y = 0;
184 0 : pos.width = GGadgetScale(GDrawPointsToPixels(NULL,150));
185 0 : pos.height = GDrawPointsToPixels(NULL,88);
186 0 : gw = GDrawCreateTopWindow(NULL,&pos,mv_e_h,&d,&wattrs);
187 :
188 0 : memset(&label,0,sizeof(label));
189 0 : memset(&gcd,0,sizeof(gcd));
190 0 : memset(&boxes,0,sizeof(boxes));
191 :
192 0 : sprintf( buffer, _("Font to merge into %.20s"), fv->b.sf->fontname );
193 0 : label[0].text = (unichar_t *) buffer;
194 0 : label[0].text_is_1byte = true;
195 0 : gcd[0].gd.label = &label[0];
196 0 : gcd[0].gd.pos.x = 12; gcd[0].gd.pos.y = 6;
197 0 : gcd[0].gd.flags = gg_visible | gg_enabled;
198 0 : gcd[0].creator = GLabelCreate;
199 0 : varray[0] = &gcd[0]; varray[1] = NULL;
200 :
201 0 : gcd[1].gd.pos.x = 15; gcd[1].gd.pos.y = 21;
202 0 : gcd[1].gd.pos.width = 120;
203 0 : gcd[1].gd.flags = gg_visible | gg_enabled;
204 0 : gcd[1].gd.u.list = BuildFontList(fv);
205 0 : gcd[1].gd.label = &gcd[1].gd.u.list[0];
206 0 : gcd[1].gd.u.list[0].selected = true;
207 0 : gcd[1].creator = GListButtonCreate;
208 0 : varray[2] = &gcd[1]; varray[3] = NULL;
209 :
210 0 : label[2].text = (unichar_t *) _("Preserve cross-font kerning");
211 0 : label[2].text_is_1byte = true;
212 0 : gcd[2].gd.label = &label[2];
213 0 : gcd[2].gd.pos.x = 12; gcd[2].gd.pos.y = 6;
214 0 : gcd[2].gd.flags = gg_visible | gg_enabled | gg_cb_on;
215 0 : gcd[2].gd.cid = CID_Preserve;
216 0 : gcd[2].creator = GCheckBoxCreate;
217 0 : varray[4] = &gcd[2]; varray[5] = NULL;
218 :
219 0 : gcd[3].gd.pos.x = 15-3; gcd[3].gd.pos.y = 55-3;
220 0 : gcd[3].gd.pos.width = -1; gcd[3].gd.pos.height = 0;
221 0 : gcd[3].gd.flags = gg_visible | gg_enabled | gg_but_default;
222 0 : label[3].text = (unichar_t *) _("_OK");
223 0 : label[3].text_is_1byte = true;
224 0 : label[3].text_in_resource = true;
225 0 : gcd[3].gd.mnemonic = 'O';
226 0 : gcd[3].gd.label = &label[3];
227 0 : gcd[3].gd.handle_controlevent = MF_OK;
228 0 : gcd[3].creator = GButtonCreate;
229 :
230 0 : gcd[4].gd.pos.x = -15; gcd[4].gd.pos.y = 55;
231 0 : gcd[4].gd.pos.width = -1; gcd[4].gd.pos.height = 0;
232 0 : gcd[4].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
233 0 : label[4].text = (unichar_t *) _("_Cancel");
234 0 : label[4].text_is_1byte = true;
235 0 : label[4].text_in_resource = true;
236 0 : gcd[4].gd.label = &label[4];
237 0 : gcd[4].gd.mnemonic = 'C';
238 0 : gcd[4].gd.handle_controlevent = MF_Cancel;
239 0 : gcd[4].creator = GButtonCreate;
240 0 : barray[0] = barray[2] = barray[3] = barray[4] = barray[6] = GCD_Glue; barray[7] = NULL;
241 0 : barray[1] = &gcd[3]; barray[5] = &gcd[4];
242 :
243 0 : boxes[2].gd.flags = gg_enabled|gg_visible;
244 0 : boxes[2].gd.u.boxelements = barray;
245 0 : boxes[2].creator = GHBoxCreate;
246 0 : varray[6] = &boxes[2]; varray[7] = NULL;
247 0 : varray[8] = NULL;
248 :
249 0 : boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
250 0 : boxes[0].gd.flags = gg_enabled|gg_visible;
251 0 : boxes[0].gd.u.boxelements = varray;
252 0 : boxes[0].creator = GHVGroupCreate;
253 :
254 0 : GGadgetsCreate(gw,boxes);
255 0 : GHVBoxSetExpandableCol(boxes[2].ret,gb_expandgluesame);
256 0 : GHVBoxFitWindow(boxes[0].ret);
257 :
258 0 : memset(&d,'\0',sizeof(d));
259 0 : d.other = gcd[1].ret;
260 0 : d.fv = fv;
261 :
262 0 : GWidgetHidePalettes();
263 0 : GDrawSetVisible(gw,true);
264 0 : while ( !d.done )
265 0 : GDrawProcessOneEvent(NULL);
266 0 : GDrawDestroyWindow(gw);
267 0 : TFFree(gcd[1].gd.u.list);
268 : }
269 0 : }
270 :
271 : /******************************************************************************/
272 : /* *************************** Font Interpolation *************************** */
273 : /******************************************************************************/
274 :
275 0 : static void InterAskFilename(FontView *fv, real amount) {
276 0 : char *filename = GetPostScriptFontName(NULL,false);
277 : SplineFont *sf;
278 :
279 0 : if ( filename==NULL )
280 0 : return;
281 0 : sf = LoadSplineFont(filename,0);
282 0 : if ( sf!=NULL && sf->fv==NULL )
283 0 : EncMapFree(sf->map);
284 0 : free(filename);
285 0 : if ( sf==NULL )
286 0 : return;
287 0 : FontViewCreate(InterpolateFont(fv->b.sf,sf,amount,fv->b.map->enc),false);
288 : }
289 :
290 : #define CID_Amount 1000
291 : static double last_amount=50;
292 :
293 0 : static int IF_OK(GGadget *g, GEvent *e) {
294 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
295 0 : GWindow gw = GGadgetGetWindow(g);
296 0 : struct mf_data *d = GDrawGetUserData(gw);
297 0 : int i, index = GGadgetGetFirstListSelectedItem(d->other);
298 : FontView *fv;
299 0 : int err=false;
300 : real amount;
301 :
302 0 : amount = GetReal8(gw,CID_Amount, _("Amount"),&err);
303 0 : if ( err )
304 0 : return( true );
305 0 : last_amount = amount;
306 0 : for ( i=0, fv=fv_list; fv!=NULL; fv=(FontView *) (fv->b.next) ) {
307 0 : if ( fv==d->fv )
308 0 : continue;
309 0 : if ( i==index )
310 0 : break;
311 0 : ++i;
312 : }
313 0 : if ( fv==NULL )
314 0 : InterAskFilename(d->fv,last_amount/100.0);
315 : else
316 0 : FontViewCreate(InterpolateFont(d->fv->b.sf,fv->b.sf,last_amount/100.0,d->fv->b.map->enc),false);
317 0 : d->done = true;
318 : }
319 0 : return( true );
320 : }
321 :
322 0 : void FVInterpolateFonts(FontView *fv) {
323 : GRect pos;
324 : GWindow gw;
325 : GWindowAttrs wattrs;
326 : GGadgetCreateData gcd[8];
327 : GTextInfo label[8];
328 : struct mf_data d;
329 : char buffer[80]; char buf2[30];
330 :
331 0 : memset(&wattrs,0,sizeof(wattrs));
332 0 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict|wam_isdlg;
333 0 : wattrs.event_masks = ~(1<<et_charup);
334 0 : wattrs.restrict_input_to_me = 1;
335 0 : wattrs.is_dlg = 1;
336 0 : wattrs.undercursor = 1;
337 0 : wattrs.cursor = ct_pointer;
338 0 : wattrs.utf8_window_title = _("Interpolate Fonts");
339 0 : pos.x = pos.y = 0;
340 0 : pos.width = GGadgetScale(GDrawPointsToPixels(NULL,200));
341 0 : pos.height = GDrawPointsToPixels(NULL,118);
342 0 : gw = GDrawCreateTopWindow(NULL,&pos,mv_e_h,&d,&wattrs);
343 :
344 0 : memset(&label,0,sizeof(label));
345 0 : memset(&gcd,0,sizeof(gcd));
346 :
347 0 : sprintf( buffer, _("Interpolating between %.20s and:"), fv->b.sf->fontname );
348 0 : label[0].text = (unichar_t *) buffer;
349 0 : label[0].text_is_1byte = true;
350 0 : gcd[0].gd.label = &label[0];
351 0 : gcd[0].gd.pos.x = 12; gcd[0].gd.pos.y = 6;
352 0 : gcd[0].gd.flags = gg_visible | gg_enabled;
353 0 : gcd[0].creator = GLabelCreate;
354 :
355 0 : gcd[1].gd.pos.x = 20; gcd[1].gd.pos.y = 21;
356 0 : gcd[1].gd.pos.width = 110;
357 0 : gcd[1].gd.flags = gg_visible | gg_enabled;
358 0 : gcd[1].gd.u.list = BuildFontList(fv);
359 0 : if ( gcd[1].gd.u.list[0].text!=NULL ) {
360 0 : gcd[1].gd.label = &gcd[1].gd.u.list[0];
361 0 : gcd[1].gd.u.list[0].selected = true;
362 : } else {
363 0 : gcd[1].gd.label = &gcd[1].gd.u.list[1];
364 0 : gcd[1].gd.u.list[1].selected = true;
365 0 : gcd[1].gd.flags = gg_visible;
366 : }
367 0 : gcd[1].creator = GListButtonCreate;
368 :
369 0 : sprintf( buf2, "%g", last_amount );
370 0 : label[2].text = (unichar_t *) buf2;
371 0 : label[2].text_is_1byte = true;
372 0 : gcd[2].gd.pos.x = 20; gcd[2].gd.pos.y = 51;
373 0 : gcd[2].gd.pos.width = 40;
374 0 : gcd[2].gd.flags = gg_visible | gg_enabled;
375 0 : gcd[2].gd.label = &label[2];
376 0 : gcd[2].gd.cid = CID_Amount;
377 0 : gcd[2].creator = GTextFieldCreate;
378 :
379 0 : gcd[3].gd.pos.x = 5; gcd[3].gd.pos.y = 51+6;
380 0 : gcd[3].gd.flags = gg_visible | gg_enabled;
381 : /* GT: The dialog looks like: */
382 : /* GT: Interpolating between <fontname> and: */
383 : /* GT: <list of possible fonts> */
384 : /* GT: by <50>% */
385 : /* GT: So "by" means how much to interpolate. */
386 0 : label[3].text = (unichar_t *) _("by");
387 0 : label[3].text_is_1byte = true;
388 0 : gcd[3].gd.label = &label[3];
389 0 : gcd[3].creator = GLabelCreate;
390 :
391 0 : gcd[4].gd.pos.x = 20+40+3; gcd[4].gd.pos.y = 51+6;
392 0 : gcd[4].gd.flags = gg_visible | gg_enabled;
393 0 : label[4].text = (unichar_t *) "%";
394 0 : label[4].text_is_1byte = true;
395 0 : gcd[4].gd.label = &label[4];
396 0 : gcd[4].creator = GLabelCreate;
397 :
398 0 : gcd[5].gd.pos.x = 15-3; gcd[5].gd.pos.y = 85-3;
399 0 : gcd[5].gd.pos.width = -1; gcd[5].gd.pos.height = 0;
400 0 : gcd[5].gd.flags = gg_visible | gg_enabled | gg_but_default;
401 0 : label[5].text = (unichar_t *) _("_OK");
402 0 : label[5].text_is_1byte = true;
403 0 : label[5].text_in_resource = true;
404 0 : gcd[5].gd.mnemonic = 'O';
405 0 : gcd[5].gd.label = &label[5];
406 0 : gcd[5].gd.handle_controlevent = IF_OK;
407 0 : gcd[5].creator = GButtonCreate;
408 :
409 0 : gcd[6].gd.pos.x = -15; gcd[6].gd.pos.y = 85;
410 0 : gcd[6].gd.pos.width = -1; gcd[6].gd.pos.height = 0;
411 0 : gcd[6].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
412 0 : label[6].text = (unichar_t *) _("_Cancel");
413 0 : label[6].text_is_1byte = true;
414 0 : label[6].text_in_resource = true;
415 0 : gcd[6].gd.label = &label[6];
416 0 : gcd[6].gd.mnemonic = 'C';
417 0 : gcd[6].gd.handle_controlevent = MF_Cancel;
418 0 : gcd[6].creator = GButtonCreate;
419 :
420 0 : GGadgetsCreate(gw,gcd);
421 :
422 0 : memset(&d,'\0',sizeof(d));
423 0 : d.other = gcd[1].ret;
424 0 : d.fv = fv;
425 :
426 0 : GWidgetHidePalettes();
427 0 : GDrawSetVisible(gw,true);
428 0 : while ( !d.done )
429 0 : GDrawProcessOneEvent(NULL);
430 0 : GDrawDestroyWindow(gw);
431 0 : TFFree(gcd[1].gd.u.list);
432 0 : }
|