Line data Source code
1 : /* Copyright (C) 2008-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 "cvundoes.h"
28 : #include "fontforgeui.h"
29 : #include "glyphcomp.h"
30 : #include "splineutil.h"
31 : #include <ustring.h>
32 : #include <gkeysym.h>
33 :
34 : enum l2l_type { l2l_copy, l2l_compare };
35 :
36 : typedef struct l2ld {
37 : GWindow gw;
38 : SplineFont *sf;
39 : CharView *cv;
40 : FontView *fv;
41 : enum l2l_type l2l;
42 : int done;
43 : } L2LDlg;
44 :
45 : #define CID_FromLayer 1000
46 : #define CID_ToLayer 1001
47 : #define CID_ClearOld 1002
48 : #define CID_ErrorBound 1003
49 :
50 0 : static GTextInfo *SFLayerList(SplineFont *sf,int def_layer) {
51 0 : GTextInfo *ret = calloc(sf->layer_cnt+1,sizeof(GTextInfo));
52 : int l;
53 :
54 0 : for ( l=0; l<sf->layer_cnt; ++l ) {
55 0 : ret[l].text = (unichar_t *) copy(sf->layers[l].name);
56 0 : ret[l].text_is_1byte = true;
57 0 : ret[l].userdata = (void *) (intpt) l;
58 : }
59 0 : ret[def_layer].selected = true;
60 0 : return( ret );
61 : }
62 :
63 0 : static void _DoCVCopy(CharView *cv,int from,int to,int clear) {
64 0 : SCCopyLayerToLayer(cv->b.sc,from,to,clear);
65 0 : }
66 :
67 0 : static void RedoRefs(SplineFont *sf,SplineChar *sc,int layer) {
68 : RefChar *refs;
69 :
70 0 : sc->ticked2 = true;
71 0 : for ( refs=sc->layers[layer].refs; refs!=NULL; refs=refs->next ) {
72 0 : if ( refs->sc->ticked && !refs->sc->ticked2 )
73 0 : RedoRefs(sf,refs->sc,layer);
74 0 : SCReinstanciateRefChar(sc,refs,layer);
75 : }
76 0 : }
77 :
78 0 : static void _DoFVCopy(FontView *fv,int from,int to,int clear) {
79 0 : SplineFont *sf = fv->b.sf;
80 : int gid, enc;
81 : SplineChar *sc;
82 :
83 0 : for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( (sc = sf->glyphs[gid])!=NULL ) {
84 0 : sc->ticked = sc->ticked2 = false;
85 : }
86 0 : for ( enc=0 ; enc<fv->b.map->enccount; ++enc ) {
87 0 : if ( fv->b.selected[enc] && (gid=fv->b.map->map[enc])!=-1 &&
88 0 : (sc = sf->glyphs[gid])!=NULL && !sc->ticked ) {
89 0 : SCCopyLayerToLayer(sc,from,to,clear);
90 0 : sc->ticked = true;
91 : }
92 : }
93 0 : for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( (sc = sf->glyphs[gid])!=NULL ) {
94 0 : if ( sc->ticked && !sc->ticked2 )
95 0 : RedoRefs(sf,sc,to);
96 : }
97 0 : }
98 :
99 0 : static void _DoCVCompare(CharView *cv,int from,int to,double errbound) {
100 0 : if ( LayersSimilar(&cv->b.sc->layers[from],&cv->b.sc->layers[to],errbound))
101 0 : ff_post_notice(_("Match"),_("No significant differences found"));
102 : else
103 0 : ff_post_notice(_("Differ"),_("The layers do not match"));
104 0 : }
105 :
106 0 : static void _DoFVCompare(FontView *fv,int from,int to,double errbound) {
107 0 : SplineFont *sf = fv->b.sf;
108 : int gid, enc;
109 : SplineChar *sc;
110 0 : int first=-1;
111 :
112 0 : memset(fv->b.selected,0,fv->b.map->enccount);
113 :
114 0 : for ( enc=0 ; enc<fv->b.map->enccount; ++enc ) {
115 0 : if ( /*fv->b.selected[enc] &&*/ (gid=fv->b.map->map[enc])!=-1 &&
116 0 : (sc = sf->glyphs[gid])!=NULL && !sc->ticked ) {
117 0 : if ( !LayersSimilar(&sc->layers[from],&sc->layers[to],errbound)) {
118 0 : fv->b.selected[enc] = true;
119 0 : if ( first==-1 )
120 0 : first = enc;
121 : }
122 : }
123 : }
124 0 : GDrawRequestExpose(fv->v,NULL,true);
125 0 : if ( first==-1 )
126 0 : ff_post_notice(_("Match"),_("No significant differences found"));
127 : else {
128 0 : ff_post_notice(_("Differ"),_("The layers do not match"));
129 0 : FVScrollToChar(fv,first);
130 0 : fv->end_pos = fv->pressed_pos = first;
131 : /*FVShowInfo(fv);*/
132 : }
133 0 : }
134 :
135 :
136 0 : static int L2L_OK(GGadget *g, GEvent *e) {
137 :
138 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
139 0 : L2LDlg *d = GDrawGetUserData(GGadgetGetWindow(g));
140 : int from, to, clear;
141 0 : int err=0;
142 : double errbound;
143 :
144 0 : from = GGadgetGetFirstListSelectedItem(GWidgetGetControl(d->gw,CID_FromLayer));
145 0 : to = GGadgetGetFirstListSelectedItem(GWidgetGetControl(d->gw,CID_ToLayer));
146 0 : if ( d->l2l==l2l_copy ) {
147 0 : clear = GGadgetIsChecked(GWidgetGetControl(d->gw,CID_ClearOld));
148 0 : if ( d->cv )
149 0 : _DoCVCopy(d->cv,from,to,clear);
150 : else
151 0 : _DoFVCopy(d->fv,from,to,clear);
152 : } else {
153 0 : errbound = GetReal8(d->gw,CID_ErrorBound,_("Error Bound"),&err);
154 0 : if ( err )
155 0 : return( true );
156 0 : if ( d->cv )
157 0 : _DoCVCompare(d->cv,from,to,errbound);
158 : else
159 0 : _DoFVCompare(d->fv,from,to,errbound);
160 : }
161 0 : d->done = true;
162 : }
163 0 : return( true );
164 : }
165 :
166 0 : static int L2L_Cancel(GGadget *g, GEvent *e) {
167 :
168 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
169 0 : L2LDlg *d = GDrawGetUserData(GGadgetGetWindow(g));
170 0 : d->done = true;
171 : }
172 0 : return( true );
173 : }
174 :
175 0 : static int l2l_e_h(GWindow gw, GEvent *event) {
176 :
177 0 : if ( event->type==et_close ) {
178 0 : L2LDlg *d = GDrawGetUserData(gw);
179 0 : d->done = true;
180 0 : } else if ( event->type == et_char ) {
181 0 : return( false );
182 : }
183 0 : return( true );
184 : }
185 :
186 0 : static void Layer2Layer(CharView *cv,FontView *fv,enum l2l_type l2l,int def_layer) {
187 : L2LDlg d;
188 : GRect pos;
189 : GWindow gw;
190 : GWindowAttrs wattrs;
191 : GGadgetCreateData gcd[17], *hvarray[34], *harray[5], *harray2[8], *hvarray2[7], boxes[7];
192 : GTextInfo label[17];
193 : int k,j;
194 :
195 0 : memset(&d,0,sizeof(d));
196 0 : d.cv = cv; d.fv = fv; d.l2l = l2l;
197 0 : if ( cv!=NULL ) d.sf = cv->b.sc->parent;
198 0 : else d.sf = fv->b.sf;
199 :
200 0 : memset(&wattrs,0,sizeof(wattrs));
201 0 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
202 0 : wattrs.event_masks = ~(1<<et_charup);
203 0 : wattrs.restrict_input_to_me = 1;
204 0 : wattrs.undercursor = 1;
205 0 : wattrs.cursor = ct_pointer;
206 0 : wattrs.utf8_window_title = l2l==l2l_copy ? _("Copy Layers") : _("Compare Layers");
207 0 : wattrs.is_dlg = true;
208 0 : pos.x = pos.y = 0;
209 0 : pos.width = GGadgetScale(GDrawPointsToPixels(NULL,170));
210 0 : pos.height = GDrawPointsToPixels(NULL,178);
211 0 : d.gw = gw = GDrawCreateTopWindow(NULL,&pos,l2l_e_h,&d,&wattrs);
212 :
213 0 : memset(&label,0,sizeof(label));
214 0 : memset(&gcd,0,sizeof(gcd));
215 0 : memset(&boxes,0,sizeof(boxes));
216 :
217 0 : k=j=0;
218 0 : label[k].text = (unichar_t *) (l2l==l2l_copy ? _("Copy one layer to another") : _("Compare two layers"));
219 0 : label[k].text_is_1byte = true;
220 0 : gcd[k].gd.label = &label[k];
221 0 : gcd[k].gd.flags = gg_enabled|gg_visible;
222 0 : gcd[k++].creator = GLabelCreate;
223 0 : hvarray[j++] = &gcd[k-1]; hvarray[j++] = NULL;
224 :
225 0 : label[k].text = (unichar_t *) (l2l==l2l_copy ? _("From:") : _("Base:"));
226 0 : label[k].text_is_1byte = true;
227 0 : gcd[k].gd.label = &label[k];
228 0 : gcd[k].gd.flags = gg_enabled|gg_visible;
229 0 : gcd[k++].creator = GLabelCreate;
230 0 : hvarray2[0] = &gcd[k-1];
231 :
232 0 : gcd[k].gd.flags = gg_enabled|gg_visible;
233 0 : gcd[k].gd.cid = CID_FromLayer;
234 0 : gcd[k].gd.u.list = SFLayerList(d.sf,def_layer);
235 0 : gcd[k++].creator = GListButtonCreate;
236 0 : hvarray2[1] = &gcd[k-1]; hvarray2[2] = NULL;
237 :
238 0 : label[k].text = (unichar_t *) (l2l==l2l_copy ? _("To:") : _("Other:"));
239 0 : label[k].text_is_1byte = true;
240 0 : gcd[k].gd.label = &label[k];
241 0 : gcd[k].gd.flags = gg_enabled|gg_visible;
242 0 : gcd[k++].creator = GLabelCreate;
243 0 : hvarray2[3] = &gcd[k-1];
244 :
245 0 : gcd[k].gd.flags = gg_enabled|gg_visible;
246 0 : gcd[k].gd.cid = CID_ToLayer;
247 0 : gcd[k].gd.u.list = SFLayerList(d.sf,def_layer==ly_fore ? ly_back : ly_fore );
248 0 : gcd[k++].creator = GListButtonCreate;
249 0 : hvarray2[4] = &gcd[k-1]; hvarray2[5] = NULL; hvarray2[6] = NULL;
250 :
251 0 : boxes[3].gd.flags = gg_enabled|gg_visible;
252 0 : boxes[3].gd.u.boxelements = hvarray2;
253 0 : boxes[3].creator = GHVBoxCreate;
254 0 : hvarray[j++] = &boxes[3]; hvarray[j++] = NULL;
255 :
256 0 : if ( l2l==l2l_copy ) {
257 0 : label[k].text = (unichar_t *) _("Clear destination layer before copy");
258 0 : label[k].text_is_1byte = true;
259 0 : gcd[k].gd.label = &label[k];
260 0 : gcd[k].gd.cid = CID_ClearOld;
261 0 : gcd[k].gd.flags = gg_enabled|gg_visible|gg_cb_on;
262 0 : gcd[k++].creator = GCheckBoxCreate;
263 0 : hvarray[j++] = &gcd[k-1]; hvarray[j++] = NULL;
264 : } else {
265 0 : label[k].text = (unichar_t *) _("Allow errors of:");
266 0 : label[k].text_is_1byte = true;
267 0 : gcd[k].gd.label = &label[k];
268 0 : gcd[k].gd.flags = gg_enabled|gg_visible;
269 0 : gcd[k++].creator = GLabelCreate;
270 0 : harray[0] = &gcd[k-1];
271 :
272 0 : label[k].text = (unichar_t *) "1";
273 0 : label[k].text_is_1byte = true;
274 0 : gcd[k].gd.pos.width = 50;
275 0 : gcd[k].gd.label = &label[k];
276 0 : gcd[k].gd.flags = gg_enabled|gg_visible;
277 0 : gcd[k].gd.cid = CID_ErrorBound;
278 0 : gcd[k++].creator = GTextFieldCreate;
279 0 : harray[1] = &gcd[k-1];
280 :
281 0 : label[k].text = (unichar_t *) _("em units");
282 0 : label[k].text_is_1byte = true;
283 0 : gcd[k].gd.label = &label[k];
284 0 : gcd[k].gd.flags = gg_enabled|gg_visible;
285 0 : gcd[k++].creator = GLabelCreate;
286 0 : harray[2] = &gcd[k-1]; harray[3] = GCD_Glue; harray[4] = NULL;
287 :
288 0 : boxes[4].gd.flags = gg_enabled|gg_visible;
289 0 : boxes[4].gd.u.boxelements = harray;
290 0 : boxes[4].creator = GHBoxCreate;
291 0 : hvarray[j++] = &boxes[4]; hvarray[j++] = NULL;
292 : }
293 :
294 0 : gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_default;
295 0 : label[k].text = (unichar_t *) _("_OK");
296 0 : label[k].text_is_1byte = true;
297 0 : label[k].text_in_resource = true;
298 0 : gcd[k].gd.label = &label[k];
299 0 : gcd[k].gd.handle_controlevent = L2L_OK;
300 0 : gcd[k++].creator = GButtonCreate;
301 0 : harray2[0] = GCD_Glue; harray2[1] = &gcd[k-1]; harray2[2] = GCD_Glue; harray2[3] = GCD_Glue;
302 :
303 0 : gcd[k].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
304 0 : label[k].text = (unichar_t *) _("_Cancel");
305 0 : label[k].text_is_1byte = true;
306 0 : label[k].text_in_resource = true;
307 0 : gcd[k].gd.label = &label[k];
308 0 : gcd[k].gd.handle_controlevent = L2L_Cancel;
309 0 : gcd[k++].creator = GButtonCreate;
310 0 : harray2[4] = GCD_Glue; harray2[5] = &gcd[k-1]; harray2[6] = GCD_Glue; harray2[7] = NULL;
311 :
312 0 : boxes[2].gd.flags = gg_enabled|gg_visible;
313 0 : boxes[2].gd.u.boxelements = harray2;
314 0 : boxes[2].creator = GHBoxCreate;
315 0 : hvarray[j++] = &boxes[2]; hvarray[j++] = NULL;
316 0 : hvarray[j++] = GCD_Glue; hvarray[j++] = NULL; hvarray[j++] = NULL;
317 :
318 0 : boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
319 0 : boxes[0].gd.flags = gg_enabled|gg_visible;
320 0 : boxes[0].gd.u.boxelements = hvarray;
321 0 : boxes[0].creator = GHVGroupCreate;
322 :
323 0 : GGadgetsCreate(gw,boxes);
324 0 : GHVBoxSetExpandableRow(boxes[0].ret,gb_expandglue);
325 0 : GHVBoxSetExpandableCol(boxes[2].ret,gb_expandgluesame);
326 0 : if ( l2l==l2l_compare )
327 0 : GHVBoxSetExpandableRow(boxes[4].ret,gb_expandglue);
328 :
329 0 : GTextInfoListFree(gcd[2].gd.u.list);
330 0 : GTextInfoListFree(gcd[4].gd.u.list);
331 :
332 0 : GHVBoxFitWindow(boxes[0].ret);
333 :
334 0 : GDrawSetVisible(gw,true);
335 0 : while ( !d.done )
336 0 : GDrawProcessOneEvent(NULL);
337 :
338 0 : GDrawDestroyWindow(gw);
339 0 : }
340 :
341 0 : void CVCopyLayerToLayer(CharView *cv) {
342 0 : Layer2Layer(cv,NULL,l2l_copy,CVLayer((CharViewBase *) cv));
343 0 : }
344 :
345 0 : void FVCopyLayerToLayer(FontView *fv) {
346 0 : Layer2Layer(NULL,fv,l2l_copy,ly_fore);
347 0 : }
348 :
349 0 : void CVCompareLayerToLayer(CharView *cv) {
350 0 : Layer2Layer(cv,NULL,l2l_compare,CVLayer((CharViewBase *) cv));
351 0 : }
352 :
353 0 : void FVCompareLayerToLayer(FontView *fv) {
354 0 : Layer2Layer(NULL,fv,l2l_compare,ly_fore);
355 0 : }
|