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
28 #include <fontforge-config.h>
29
30 #include "cvundoes.h"
31 #include "fontforgeui.h"
32 #include "fvfonts.h"
33 #include "gkeysym.h"
34 #include "splinestroke.h"
35 #include "splineutil.h"
36 #include "splineutil2.h"
37 #include "splineoverlap.h"
38 #include "ustring.h"
39 #include "utype.h"
40
41 #include <assert.h>
42 #include <math.h>
43
44 extern GDevEventMask input_em[];
45 extern const int input_em_cnt;
46
47 #define CID_ButtCap 1001
48 #define CID_RoundCap 1002
49 #define CID_NibCap 1003
50 #define CID_BevelJoin 1004
51 #define CID_NibJoin 1005
52 #define CID_MiterJoin 1006
53 #define CID_Width 1007
54 #define CID_MinorAxis 1008
55 #define CID_PenAngle 1009
56 #define CID_Circle 1010
57 #define CID_Calligraphic 1011
58 #define CID_Convex 1012
59 #define CID_JoinLimitVal 1013
60 #define CID_JoinLimitLen 1014
61 #define CID_JoinLimitRel 1015
62 #define CID_JoinLimitTxt 1016
63 #define CID_MinorAxisTxt 1017
64 /* For Kanou (& me) */
65 #define CID_RmInternal 1019
66 #define CID_RmExternal 1020
67 #define CID_RmOvLayer 1021
68 #define CID_Apply 1022
69 #define CID_Nib 1023
70 #define CID_WidthTxt 1024
71 #define CID_TopBox 1025
72 #define CID_RmOvContour 1027
73 #define CID_RmOvNone 1028
74 #define CID_Simplify 1029
75 #define CID_Extrema 1030
76 #define CID_MiterClipJoin 1031
77 #define CID_ArcsJoin 1032
78 #define CID_BevelCap 1033
79 #define CID_ExtendCapVal 1034
80 #define CID_ExtendCapLen 1035
81 #define CID_ExtendCapRel 1036
82 #define CID_ExtendCapTxt 1037
83 #define CID_AccTar 1038
84 #define CID_RoundJoin 1039
85 #define CID_AlText 1040
86 #define CID_AlAuto 1041
87 #define CID_AlSVG2 1042
88 #define CID_AlRatio 1043
89
90 /* For freehand */
91 #define CID_CenterLine 1050
92
93 /* Used in other structures and tools */
94 #define CID_SquareCap 1051
95 #define CID_LineJoinTxt 1053
96 #define CID_LineCapTxt 1054
97
CVStrokeIt(void * _cv,StrokeInfo * si,int justapply)98 static void CVStrokeIt(void *_cv, StrokeInfo *si, int justapply) {
99 CharView *cv = _cv;
100 int anypoints;
101 SplineSet *spl, *prev, *head=NULL, *cur, *snext;
102
103 if ( cv->b.layerheads[cv->b.drawmode]->undoes!=NULL &&
104 cv->b.layerheads[cv->b.drawmode]->undoes->undotype==ut_tstate )
105 CVDoUndo(&cv->b);
106
107 if ( justapply )
108 CVPreserveTState(cv);
109 else
110 CVPreserveState(&cv->b);
111 if ( CVAnySel(cv,&anypoints,NULL,NULL,NULL) && anypoints ) {
112 prev = NULL;
113 for ( spl= cv->b.layerheads[cv->b.drawmode]->splines; spl!=NULL; spl = snext ) {
114 snext = spl->next;
115 spl->next = NULL;
116 if ( PointListIsSelected(spl)) {
117 cur = SplineSetStroke(spl,si,cv->b.layerheads[cv->b.drawmode]->order2);
118 SplinePointListSelect(cur, true);
119 SplinePointListMDFree(cv->b.sc,spl);
120 } else
121 cur = spl;
122 if ( cur!=NULL ) {
123 if ( prev==NULL )
124 prev = cv->b.layerheads[cv->b.drawmode]->splines = cur;
125 else
126 prev->next = cur;
127 while ( prev->next )
128 prev=prev->next;
129 }
130 }
131 if ( si->rmov==srmov_layer )
132 cv->b.layerheads[cv->b.drawmode]->splines = SplineSetRemoveOverlap(cv->b.sc,
133 cv->b.layerheads[cv->b.drawmode]->splines, over_rmselected);
134 } else {
135 head = SplineSetStroke(cv->b.layerheads[cv->b.drawmode]->splines,si,
136 cv->b.layerheads[cv->b.drawmode]->order2);
137 SplinePointListsFree( cv->b.layerheads[cv->b.drawmode]->splines );
138 cv->b.layerheads[cv->b.drawmode]->splines = head;
139 }
140 SCClearSelPt(cv->b.sc);
141 CVCharChangedUpdate(&cv->b);
142 }
143
_Stroke_OK(StrokeDlg * sd,int isapply)144 static int _Stroke_OK(StrokeDlg *sd,int isapply) {
145 StrokeInfo *si, apply_si;
146 int err;
147 GWindow sw = sd->gw;
148 GGadget *clg;
149 const char *msg;
150
151 assert( sd->si!=NULL );
152 if ( isapply )
153 si = InitializeStrokeInfo(&apply_si);
154 else
155 si = sd->si;
156 err = false;
157
158 si->stroke_type = si_round;
159 if ( GGadgetIsChecked( GWidgetGetControl(sw,CID_Calligraphic)) )
160 si->stroke_type = si_calligraphic;
161 else if ( GGadgetIsChecked( GWidgetGetControl(sw,CID_Convex)) )
162 si->stroke_type = si_nib;
163 else if ( (clg=GWidgetGetControl(sw,CID_CenterLine))!=NULL
164 && GGadgetIsChecked(clg) )
165 si->stroke_type = si_centerline;
166 if ( si->stroke_type==si_nib ) {
167 si->nib = sd->sc_stroke.layers[ly_fore].splines;
168 if ( sd->sc_stroke.layers[ly_fore].refs != NULL ) {
169 ff_post_error(_("No References"),_("No references allowed in a pen."));
170 err = true;
171 } else if ( si->nib==NULL ) {
172 ff_post_error(_("Nothing specified"),_("Please draw a convex polygon in the drawing area."));
173 err = true;
174 } else {
175 SplineSet *ss;
176 SplinePointListSelect(si->nib, false);
177 for ( ss=si->nib ; ss!=NULL && !err; ss=ss->next ) {
178 enum ShapeType pt = NibIsValid(ss);
179 if ( pt!=Shape_Convex ) {
180 GDrawRequestExpose(sd->cv_stroke.v,NULL,false);
181 ff_post_error(_("Nib shape not valid"), NibShapeTypeMsg(pt));
182 err = true;
183 }
184 }
185 }
186 if (!err)
187 GDrawRequestExpose(sd->cv_stroke.v,NULL,false);
188 } else {
189 si->width = GetReal8(sw,CID_Width,_("Stroke _Width:"),&err);
190 if ( si->width==0 && ( si->stroke_type==si_round
191 || si->stroke_type==si_calligraphic )) {
192 ff_post_error(_("Bad Value"), _("Stroke width cannot be zero"));
193 err = true;
194 }
195 if ( si->width<0 )
196 si->width = -si->width;
197 si->height = GetReal8(sw,CID_MinorAxis,_("Minor A_xis:"),&err);
198 if ( si->height<0 )
199 si->height = -si->height;
200 }
201 si->penangle = GetReal8(sw,CID_PenAngle,_("Pen _Angle:"),&err);
202 if ( si->penangle>180 || si->penangle < -180 ) {
203 si->penangle = fmod(si->penangle,360);
204 if ( si->penangle>180 )
205 si->penangle -= 360;
206 else if ( si->penangle<-180 )
207 si->penangle += 360;
208 }
209 si->penangle *= FF_PI/180;
210 si->cap = GGadgetIsChecked( GWidgetGetControl(sw,CID_ButtCap))?lc_butt:
211 GGadgetIsChecked( GWidgetGetControl(sw,CID_BevelCap))?lc_bevel:
212 GGadgetIsChecked( GWidgetGetControl(sw,CID_RoundCap))?lc_round:
213 lc_nib;
214 si->join = GGadgetIsChecked( GWidgetGetControl(sw,CID_BevelJoin))?lj_bevel:
215 GGadgetIsChecked( GWidgetGetControl(sw,CID_MiterJoin))?lj_miter:
216 GGadgetIsChecked( GWidgetGetControl(sw,CID_MiterClipJoin))?lj_miterclip:
217 GGadgetIsChecked( GWidgetGetControl(sw,CID_RoundJoin))?lj_round:
218 GGadgetIsChecked( GWidgetGetControl(sw,CID_ArcsJoin))?lj_arcs:
219 lj_nib;
220 si->rmov = GGadgetIsChecked( GWidgetGetControl(sw,CID_RmOvNone))?srmov_none:
221 GGadgetIsChecked( GWidgetGetControl(sw,CID_RmOvContour))?srmov_contour:
222 srmov_layer;
223 si->al = GGadgetIsChecked( GWidgetGetControl(sw,CID_AlSVG2))?sal_svg2:
224 GGadgetIsChecked( GWidgetGetControl(sw,CID_AlRatio))?sal_ratio:
225 sal_auto;
226 si->removeinternal = GGadgetIsChecked( GWidgetGetControl(sw,CID_RmInternal));
227 si->removeexternal = GGadgetIsChecked( GWidgetGetControl(sw,CID_RmExternal));
228 si->simplify = GGadgetIsChecked( GWidgetGetControl(sw,CID_Simplify));
229 si->extrema = GGadgetIsChecked( GWidgetGetControl(sw,CID_Extrema));
230 si->joinlimit = GetReal8(sw,CID_JoinLimitVal,_("Join Limit:"),&err);
231 si->jlrelative = GGadgetIsChecked( GWidgetGetControl(sw,CID_JoinLimitLen))
232 ? false : true;
233 si->extendcap = GetReal8(sw,CID_ExtendCapVal,_("Extend Cap:"),&err);
234 si->ecrelative = GGadgetIsChecked( GWidgetGetControl(sw,CID_ExtendCapRel))
235 ? true : false;
236 si->accuracy_target = GetReal8(sw,CID_AccTar,_("Accuracy Target:"),&err);
237 if ( si->removeinternal && si->removeexternal ) {
238 ff_post_error(_("Bad Value"),_("Removing both the internal and the external contours makes no sense"));
239 err = true;
240 }
241 if ( err )
242 return( true );
243 if ( sd->strokeit!=NULL )
244 (sd->strokeit)(sd->cv,si,isapply);
245 sd->done = !isapply;
246 return( true );
247 }
248
Stroke_OK(GGadget * g,GEvent * e)249 static int Stroke_OK(GGadget *g, GEvent *e) {
250
251 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
252 GWindow sw = GGadgetGetWindow(g);
253 StrokeDlg *sd = (StrokeDlg *) ((CharViewBase *) GDrawGetUserData(sw))->container;
254 return( _Stroke_OK(sd,GGadgetGetCid(g) == CID_Apply));
255 }
256 return( true );
257 }
258
_Stroke_Cancel(StrokeDlg * sd)259 static void _Stroke_Cancel(StrokeDlg *sd ) {
260 if ( sd->strokeit==CVStrokeIt && sd->cv->b.layerheads[sd->cv->b.drawmode]->undoes!=NULL &&
261 sd->cv->b.layerheads[sd->cv->b.drawmode]->undoes->undotype==ut_tstate )
262 CVDoUndo(&sd->cv->b);
263 sd->done = -1;
264 }
265
Stroke_Cancel(GGadget * g,GEvent * e)266 static int Stroke_Cancel(GGadget *g, GEvent *e) {
267 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
268 StrokeDlg *sd = (StrokeDlg *) ((CharViewBase *) GDrawGetUserData(GGadgetGetWindow(g)))->container;
269 _Stroke_Cancel(sd);
270 }
271 return( true );
272 }
273
Stroke_ShowNib(StrokeDlg * sd)274 static void Stroke_ShowNib(StrokeDlg *sd) {
275 SplineSet *ss;
276 real transform[6];
277 double angle,c,s, width, height;
278 int err=0;
279
280 SplinePointListsFree(sd->dummy_sf.grid.splines);
281 sd->dummy_sf.grid.splines = NULL;
282 if ( GGadgetIsChecked(GWidgetGetControl(sd->gw,CID_Convex)) ) {
283 if ( sd->sc_stroke.layers[ly_fore].splines==NULL ) {
284 sd->sc_stroke.layers[ly_fore].splines = sd->old_convex;
285 sd->old_convex = NULL;
286 }
287 } else {
288 if ( sd->old_convex==NULL ) {
289 sd->old_convex = sd->sc_stroke.layers[ly_fore].splines;
290 sd->sc_stroke.layers[ly_fore].splines = NULL;
291 }
292 }
293 if ( GGadgetIsChecked(GWidgetGetControl(sd->gw,CID_Circle)) ||
294 GGadgetIsChecked(GWidgetGetControl(sd->gw,CID_Calligraphic)) ) {
295 // UnitShape(1) presumably returns a square for this line's benefit.
296 ss = UnitShape( GGadgetIsChecked(GWidgetGetControl(sd->gw,CID_Calligraphic)) );
297 memset(transform,0,sizeof(transform));
298 width = GetCalmReal8(sd->gw,CID_Width,"",&err);
299 height = GetCalmReal8(sd->gw,CID_MinorAxis,"",&err);
300 angle = GetCalmReal8(sd->gw,CID_PenAngle,"",&err)*FF_PI/180;
301 c = cos(angle); s=sin(angle);
302 transform[0] = transform[3] = c;
303 transform[1] = s; transform[2] = -s;
304 transform[0] *= width/2;
305 transform[1] *= width/2;
306 transform[2] *= height/2;
307 transform[3] *= height/2;
308 SplinePointListTransform(ss,transform,tpt_AllPoints);
309 sd->dummy_sf.grid.splines = ss;
310 }
311 GDrawRequestExpose(sd->cv_stroke.v,NULL,false);
312 }
313
StrokeSetup(StrokeDlg * sd,enum si_type stroke_type)314 static void StrokeSetup(StrokeDlg *sd, enum si_type stroke_type) {
315
316 sd->dontexpand = ( stroke_type==si_centerline );
317
318 GGadgetSetEnabled(GWidgetGetControl(sd->gw,CID_WidthTxt ), stroke_type==si_round || stroke_type==si_calligraphic);
319 GGadgetSetEnabled(GWidgetGetControl(sd->gw,CID_Width ), stroke_type==si_round || stroke_type==si_calligraphic);
320 GGadgetSetEnabled(GWidgetGetControl(sd->gw,CID_MinorAxisTxt), stroke_type==si_round || stroke_type==si_calligraphic);
321 GGadgetSetEnabled(GWidgetGetControl(sd->gw,CID_MinorAxis ), stroke_type==si_round || stroke_type==si_calligraphic);
322 }
323
Stroke_TextChanged(GGadget * g,GEvent * e)324 static int Stroke_TextChanged(GGadget *g, GEvent *e) {
325 if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
326 StrokeDlg *sd = (StrokeDlg *) ((CharViewBase *) GDrawGetUserData(GGadgetGetWindow(g)))->container;
327 Stroke_ShowNib(sd);
328 }
329 return( true );
330 }
331
Stroke_CenterLine(GGadget * g,GEvent * e)332 static int Stroke_CenterLine(GGadget *g, GEvent *e) {
333 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
334 StrokeDlg *sd = (StrokeDlg *) ((CharViewBase *) GDrawGetUserData(GGadgetGetWindow(g)))->container;
335 StrokeSetup(sd,si_centerline);
336 Stroke_ShowNib(sd);
337 }
338 return( true );
339 }
340
Stroke_Calligraphic(GGadget * g,GEvent * e)341 static int Stroke_Calligraphic(GGadget *g, GEvent *e) {
342 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
343 StrokeDlg *sd = (StrokeDlg *) ((CharViewBase *) GDrawGetUserData(GGadgetGetWindow(g)))->container;
344 StrokeSetup(sd,si_calligraphic);
345 Stroke_ShowNib(sd);
346 }
347 return( true );
348 }
349
Stroke_Stroke(GGadget * g,GEvent * e)350 static int Stroke_Stroke(GGadget *g, GEvent *e) {
351 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
352 StrokeDlg *sd = (StrokeDlg *) ((CharViewBase *) GDrawGetUserData(GGadgetGetWindow(g)))->container;
353 StrokeSetup(sd,si_round);
354 Stroke_ShowNib(sd);
355 }
356 return( true );
357 }
358
Stroke_Convex(GGadget * g,GEvent * e)359 static int Stroke_Convex(GGadget *g, GEvent *e) {
360 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
361 StrokeDlg *sd = (StrokeDlg *) ((CharViewBase *) GDrawGetUserData(GGadgetGetWindow(g)))->container;
362 StrokeSetup(sd,si_nib);
363 Stroke_ShowNib(sd);
364 }
365 return( true );
366 }
367
JoinSetup(StrokeDlg * sd,int type)368 static void JoinSetup(StrokeDlg *sd, int type) {
369 GGadgetSetEnabled(GWidgetGetControl(sd->gw,CID_JoinLimitTxt ), type>0);
370 GGadgetSetEnabled(GWidgetGetControl(sd->gw,CID_JoinLimitVal ), type>0);
371 GGadgetSetEnabled(GWidgetGetControl(sd->gw,CID_JoinLimitLen ), type>0);
372 GGadgetSetEnabled(GWidgetGetControl(sd->gw,CID_JoinLimitRel ), type>0);
373 GGadgetSetEnabled(GWidgetGetControl(sd->gw,CID_AlText ), type==2);
374 GGadgetSetEnabled(GWidgetGetControl(sd->gw,CID_AlAuto ), type==2);
375 GGadgetSetEnabled(GWidgetGetControl(sd->gw,CID_AlSVG2 ), type==2);
376 GGadgetSetEnabled(GWidgetGetControl(sd->gw,CID_AlRatio ), type==2);
377 }
378
Join_Arcs(GGadget * g,GEvent * e)379 static int Join_Arcs(GGadget *g, GEvent *e) {
380 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
381 StrokeDlg *sd = (StrokeDlg *) ((CharViewBase *) GDrawGetUserData(GGadgetGetWindow(g)))->container;
382 JoinSetup(sd,2);
383 }
384 return( true );
385 }
386
Join_Miter(GGadget * g,GEvent * e)387 static int Join_Miter(GGadget *g, GEvent *e) {
388 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
389 StrokeDlg *sd = (StrokeDlg *) ((CharViewBase *) GDrawGetUserData(GGadgetGetWindow(g)))->container;
390 JoinSetup(sd,1);
391 }
392 return( true );
393 }
394
Join_Other(GGadget * g,GEvent * e)395 static int Join_Other(GGadget *g, GEvent *e) {
396 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
397 StrokeDlg *sd = (StrokeDlg *) ((CharViewBase *) GDrawGetUserData(GGadgetGetWindow(g)))->container;
398 JoinSetup(sd,0);
399 }
400 return( true );
401 }
402
ExtendSetup(StrokeDlg * sd,int enabled)403 static void ExtendSetup(StrokeDlg *sd, int enabled) {
404 GGadgetSetEnabled(GWidgetGetControl(sd->gw,CID_ExtendCapTxt ), enabled);
405 GGadgetSetEnabled(GWidgetGetControl(sd->gw,CID_ExtendCapVal ), enabled);
406 GGadgetSetEnabled(GWidgetGetControl(sd->gw,CID_ExtendCapLen ), enabled);
407 GGadgetSetEnabled(GWidgetGetControl(sd->gw,CID_ExtendCapRel ), enabled);
408 }
409
Cap_Extendable(GGadget * g,GEvent * e)410 static int Cap_Extendable(GGadget *g, GEvent *e) {
411 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
412 StrokeDlg *sd = (StrokeDlg *) ((CharViewBase *) GDrawGetUserData(GGadgetGetWindow(g)))->container;
413 ExtendSetup(sd,1);
414 }
415 return( true );
416 }
417
Cap_Other(GGadget * g,GEvent * e)418 static int Cap_Other(GGadget *g, GEvent *e) {
419 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
420 StrokeDlg *sd = (StrokeDlg *) ((CharViewBase *) GDrawGetUserData(GGadgetGetWindow(g)))->container;
421 ExtendSetup(sd,0);
422 }
423 return( true );
424 }
425
Stroke_SubResize(StrokeDlg * sd,GEvent * event)426 static void Stroke_SubResize(StrokeDlg *sd, GEvent *event) {
427 int width, height;
428
429 if ( !event->u.resize.sized )
430 return;
431
432 width = event->u.resize.size.width;
433 height = event->u.resize.size.height;
434 if ( width!=sd->cv_width || height!=sd->cv_height ) {
435 sd->cv_width = width; sd->cv_height = height;
436 GDrawResize(sd->cv_stroke.gw,width,height);
437 }
438
439 GDrawSync(NULL);
440 GDrawProcessPendingEvents(NULL);
441 }
442
Stroke_Draw(StrokeDlg * sd,GWindow pixmap,GEvent * event)443 static void Stroke_Draw(StrokeDlg *sd, GWindow pixmap, GEvent *event) {
444 GRect r,pos;
445
446 GGadgetGetSize(GWidgetGetControl(sd->gw,CID_Nib),&pos);
447 r.x = pos.x-1; r.y = pos.y-1;
448 r.width = pos.width+1; r.height = pos.height+1;
449 GDrawDrawRect(pixmap,&r,0);
450 }
451
Stroke_MakeActive(StrokeDlg * sd,CharView * cv)452 static void Stroke_MakeActive(StrokeDlg *sd,CharView *cv) {
453
454 if ( sd==NULL )
455 return;
456 cv->inactive = false;
457 GDrawSetUserData(sd->gw,cv);
458 GDrawRequestExpose(cv->v,NULL,false);
459 GDrawRequestExpose(sd->gw,NULL,false);
460 }
461
Stroke_Char(StrokeDlg * sd,GEvent * event)462 static void Stroke_Char(StrokeDlg *sd, GEvent *event) {
463
464 if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
465 help("ui/menus/elementmenu.html", "#elementmenu-expand");
466 return;
467 } else if ( event->u.chr.keysym == GK_Return ) {
468 _Stroke_OK(sd,false);
469 return;
470 } else if ( event->u.chr.keysym == GK_Escape ) {
471 _Stroke_Cancel(sd);
472 return;
473 }
474
475 CVChar((&sd->cv_stroke),event);
476 }
477
Stroke_DoClose(struct cvcontainer * cvc)478 static void Stroke_DoClose(struct cvcontainer *cvc) {
479 StrokeDlg *sd = (StrokeDlg *) cvc;
480
481 {
482 SplineChar *msc = &sd->sc_stroke;
483 SplinePointListsFree(msc->layers[0].splines);
484 SplinePointListsFree(msc->layers[1].splines);
485 free( msc->layers );
486 }
487
488 sd->done = -1;
489 }
490
stroke_sub_e_h(GWindow gw,GEvent * event)491 static int stroke_sub_e_h(GWindow gw, GEvent *event) {
492 StrokeDlg *sd = (StrokeDlg *) ((CharViewBase *) GDrawGetUserData(gw))->container;
493
494 switch ( event->type ) {
495 case et_resize:
496 if ( event->u.resize.sized )
497 Stroke_SubResize(sd,event);
498 break;
499 case et_char:
500 Stroke_Char(sd,event);
501 break;
502 case et_mouseup: case et_mousedown: case et_mousemove:
503 return( false );
504 break;
505 }
506 return( true );
507 }
508
Stroke_Can_Navigate(struct cvcontainer * cvc,enum nav_type type)509 static int Stroke_Can_Navigate(struct cvcontainer *cvc, enum nav_type type) {
510 return( false );
511 }
512
Stroke_Can_Open(struct cvcontainer * cvc)513 static int Stroke_Can_Open(struct cvcontainer *cvc) {
514 return( false );
515 }
516
SF_Of_Stroke(struct cvcontainer * foo)517 static SplineFont *SF_Of_Stroke(struct cvcontainer *foo) {
518 return( NULL );
519 }
520
521 struct cvcontainer_funcs stroke_funcs = {
522 cvc_stroke,
523 (void (*) (struct cvcontainer *cvc,CharViewBase *cv)) Stroke_MakeActive,
524 (void (*) (struct cvcontainer *cvc,void *)) Stroke_Char,
525 Stroke_Can_Navigate,
526 NULL,
527 Stroke_Can_Open,
528 Stroke_DoClose,
529 SF_Of_Stroke
530 };
531
532
StrokeInit(StrokeDlg * sd)533 static void StrokeInit(StrokeDlg *sd) {
534 real transform[6];
535
536 sd->base.funcs = &stroke_funcs;
537
538 {
539 SplineChar *msc = (&sd->sc_stroke);
540 CharView *mcv = (&sd->cv_stroke);
541 msc->orig_pos = 0;
542 msc->unicodeenc = -1;
543 msc->name = "Nib";
544 msc->parent = &sd->dummy_sf;
545 msc->layer_cnt = 2;
546 msc->layers = calloc(2,sizeof(Layer));
547 msc->width = 200;
548 LayerDefault(&msc->layers[0]);
549 LayerDefault(&msc->layers[1]);
550 sd->chars[0] = msc;
551
552 mcv->b.sc = msc;
553 mcv->b.layerheads[dm_fore] = &msc->layers[ly_fore];
554 mcv->b.layerheads[dm_back] = &msc->layers[ly_back];
555 mcv->b.layerheads[dm_grid] = &sd->dummy_sf.grid;
556 mcv->b.drawmode = dm_fore;
557 mcv->b.container = (struct cvcontainer *) sd;
558 mcv->inactive = false;
559 }
560 sd->dummy_sf.glyphs = sd->chars;
561 sd->dummy_sf.glyphcnt = sd->dummy_sf.glyphmax = 1;
562 sd->dummy_sf.pfminfo.fstype = -1;
563 sd->dummy_sf.pfminfo.stylemap = -1;
564 sd->dummy_sf.fontname = sd->dummy_sf.fullname = sd->dummy_sf.familyname = "dummy";
565 sd->dummy_sf.weight = "Medium";
566 sd->dummy_sf.origname = "dummy";
567 sd->dummy_sf.ascent = 200;
568 sd->dummy_sf.descent = 200;
569 sd->dummy_sf.layers = sd->layerinfo;
570 sd->dummy_sf.layer_cnt = 2;
571 sd->layerinfo[ly_back].order2 = false;
572 sd->layerinfo[ly_back].name = _("Back");
573 sd->layerinfo[ly_fore].order2 = false;
574 sd->layerinfo[ly_fore].name = _("Fore");
575 sd->dummy_sf.grid.order2 = false;
576 sd->dummy_sf.anchor = NULL;
577
578 sd->dummy_sf.fv = (FontViewBase *) &sd->dummy_fv;
579 sd->dummy_fv.b.active_layer = ly_fore;
580 sd->dummy_fv.b.sf = &sd->dummy_sf;
581 sd->dummy_fv.b.selected = sd->sel;
582 sd->dummy_fv.cbw = sd->dummy_fv.cbh = default_fv_font_size+1;
583 sd->dummy_fv.magnify = 1;
584
585 sd->dummy_fv.b.map = &sd->dummy_map;
586 sd->dummy_map.map = sd->map;
587 sd->dummy_map.backmap = sd->backmap;
588 sd->dummy_map.enccount = sd->dummy_map.encmax = sd->dummy_map.backmax = 1;
589 sd->dummy_map.enc = &custom;
590
591 }
592
stroke_e_h(GWindow gw,GEvent * event)593 static int stroke_e_h(GWindow gw, GEvent *event) {
594 StrokeDlg *sd = (StrokeDlg *) ((CharViewBase *) GDrawGetUserData(gw))->container;
595 switch (event->type) {
596 case et_expose:
597 Stroke_Draw(sd, gw, event);
598 break;
599 case et_close:
600 sd->done = -1;
601 break;
602 case et_destroy:
603 sd->gw = NULL; // some flag to indicate that we're finally gone
604 break;
605 case et_char:
606 if (event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help) {
607 help("ui/menus/elementmenu.html", "#elementmenu-expand");
608 return true;
609 }
610 return false;
611 case et_map:
612 if (event->u.map.is_visible) {
613 /* Above palettes */
614 GDrawRaise(gw);
615 }
616 break;
617 default:
618 break;
619 }
620 return true;
621 }
622
623 #define SD_Width 400
624 #define SD_Height 400
625 #define FH_Height (SD_Height+75)
626
MakeStrokeDlg(void * cv,void (* strokeit)(void *,StrokeInfo *,int),StrokeInfo * si,int apply)627 static void MakeStrokeDlg(void *cv, void (*strokeit)(void *,StrokeInfo *,int),
628 StrokeInfo *si, int apply) {
629 StrokeDlg sd;
630 GRect pos;
631 GWindow gw;
632 GWindowAttrs wattrs;
633 SplineSet *nib_bk = NULL;
634 GGadgetCreateData gcd[54], boxes[7], *buttons[13], *mainarray[11][2],
635 *radoptarray[4][9], *split[13][6], *checkarray[5],
636 *jlexarray[3][8];
637 GTextInfo label[54];
638 int i, gcdoff, mi, sp, tfpos[6];
639 char anglebuf[20], ecbuf[20], jlbuf[20], accbuf[20];
640 char widthbuf[20], axisbuf[20];
641
642 assert( si!=NULL );
643
644 memset(&sd, 0, sizeof(sd));
645 sd.si = si;
646 if ( si->nib!=NULL ) {
647 sd.old_convex = si->nib;
648 nib_bk = SplinePointListCopy(si->nib);
649 si->nib=NULL;
650 }
651
652 {
653 StrokeInit(&sd);
654 memset(&wattrs,0,sizeof(wattrs));
655 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
656 wattrs.event_masks = ~(1<<et_charup);
657 wattrs.restrict_input_to_me = 1;
658 wattrs.undercursor = 1;
659 wattrs.cursor = ct_pointer;
660 wattrs.utf8_window_title = strokeit!=NULL ? _("Expand Stroke") :
661 /* GT: This does not mean the program, but freehand drawing */
662 _("Freehand");
663 wattrs.is_dlg = true;
664 pos.x = pos.y = 0;
665 pos.width = GGadgetScale(GDrawPointsToPixels(NULL,SD_Width));
666 pos.height = GDrawPointsToPixels(NULL,strokeit!=NULL ? SD_Height : FH_Height);
667 sd.gw = gw = GDrawCreateTopWindow(NULL,&pos,stroke_e_h,&sd.cv_stroke,&wattrs);
668 GDrawSetWindowTypeName(gw, "CharView"); // For hotkeys
669 GDrawRequestDeviceEvents(gw,input_em_cnt,input_em);
670
671 memset(&label,0,sizeof(label));
672 memset(&gcd,0,sizeof(gcd));
673 memset(&boxes,0,sizeof(boxes));
674 memset(&split,0,sizeof(split));
675 memset(&jlexarray,0,sizeof(jlexarray));
676 memset(&radoptarray,0,sizeof(radoptarray));
677 gcdoff = mi = sp = 0;
678
679 gcd[gcdoff].gd.flags = gg_visible|gg_enabled ; /* This space is for the menubar */
680 gcd[gcdoff].gd.pos.height = 18; gcd[gcdoff].gd.pos.width = 20;
681 gcd[gcdoff++].creator = GSpacerCreate;
682 mainarray[mi][0] = &gcd[gcdoff-1]; mainarray[mi++][1] = NULL;
683
684 gcd[gcdoff].gd.pos.width = gcd[gcdoff].gd.pos.height = 200;
685 gcd[gcdoff].gd.flags = gg_visible | gg_enabled;
686 gcd[gcdoff].gd.cid = CID_Nib;
687 gcd[gcdoff].gd.u.drawable_e_h = stroke_sub_e_h;
688 gcd[gcdoff++].creator = GDrawableCreate;
689 split[sp][0] = &gcd[gcdoff-1];
690
691 label[gcdoff].text = (unichar_t *) _("Nib Type:");
692 label[gcdoff].text_is_1byte = true;
693 label[gcdoff].text_in_resource = true;
694 gcd[gcdoff].gd.label = &label[gcdoff];
695 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
696 gcd[gcdoff++].creator = GLabelCreate;
697 split[sp][1] = GCD_HPad10; split[sp][2] = &gcd[gcdoff-1];
698
699 label[gcdoff].text = (unichar_t *) _("_Circular (Elliptical)");
700 label[gcdoff].text_is_1byte = true;
701 label[gcdoff].text_in_resource = true;
702 gcd[gcdoff].gd.label = &label[gcdoff];
703 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->stroke_type==si_round? gg_cb_on : 0);
704 gcd[gcdoff].gd.u.radiogroup = 1;
705 gcd[gcdoff].gd.cid = CID_Circle;
706 gcd[gcdoff].gd.handle_controlevent = Stroke_Stroke;
707 gcd[gcdoff++].creator = GRadioCreate;
708 split[sp][3] = &gcd[gcdoff-1]; split[sp][4] = GCD_ColSpan;
709 split[sp++][5] = NULL;
710
711 label[gcdoff].text = (unichar_t *) _("Ca_lligraphic (Rectangular)");
712 label[gcdoff].text_is_1byte = true;
713 label[gcdoff].text_in_resource = true;
714 gcd[gcdoff].gd.label = &label[gcdoff];
715 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->stroke_type == si_calligraphic ? gg_cb_on : 0);
716 gcd[gcdoff].gd.u.radiogroup = 1;
717 gcd[gcdoff].gd.cid = CID_Calligraphic;
718 gcd[gcdoff].gd.handle_controlevent = Stroke_Calligraphic;
719 gcd[gcdoff++].creator = GRadioCreate;
720 split[sp][0] = GCD_RowSpan;
721 split[sp][1] = GCD_HPad10; split[sp][2] = GCD_Glue;
722 split[sp][3] = &gcd[gcdoff-1]; split[sp][4] = GCD_ColSpan;
723 split[sp++][5] = NULL;
724
725 label[gcdoff].text = (unichar_t *) _("Conve_x (Polygonal)");
726 label[gcdoff].text_is_1byte = true;
727 label[gcdoff].text_in_resource = true;
728 gcd[gcdoff].gd.label = &label[gcdoff];
729 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->stroke_type == si_nib ? gg_cb_on : 0);
730 gcd[gcdoff].gd.u.radiogroup = 1;
731 gcd[gcdoff].gd.cid = CID_Convex;
732 gcd[gcdoff].gd.handle_controlevent = Stroke_Convex;
733 gcd[gcdoff++].creator = GRadioCreate;
734 split[sp][0] = GCD_RowSpan;
735 split[sp][1] = GCD_HPad10; split[sp][2] = GCD_Glue;
736 split[sp][3] = &gcd[gcdoff-1]; split[sp][4] = GCD_ColSpan;
737 split[sp++][5] = NULL;
738
739 if ( strokeit==NULL ) {
740 label[gcdoff].text = (unichar_t *) _("_Don't Expand");
741 label[gcdoff].text_is_1byte = true;
742 label[gcdoff].text_in_resource = true;
743 gcd[gcdoff].gd.label = &label[gcdoff];
744 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->stroke_type==si_centerline ? gg_cb_on : 0 );
745 gcd[gcdoff].gd.u.radiogroup = 1;
746 gcd[gcdoff].gd.cid = CID_CenterLine;
747 gcd[gcdoff].gd.handle_controlevent = Stroke_CenterLine;
748 gcd[gcdoff++].creator = GRadioCreate;
749 split[sp][0] = GCD_RowSpan;
750 split[sp][1] = GCD_HPad10; split[sp][2] = GCD_Glue;
751 split[sp][3] = &gcd[gcdoff-1]; split[sp][4] = GCD_ColSpan;
752 split[sp++][5] = NULL;
753 }
754
755 label[gcdoff].text = (unichar_t *) _("Major Axis (_Width):");
756 label[gcdoff].text_is_1byte = true;
757 label[gcdoff].text_in_resource = true;
758 gcd[gcdoff].gd.label = &label[gcdoff];
759 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
760 gcd[gcdoff].gd.cid = CID_WidthTxt;
761 gcd[gcdoff++].creator = GLabelCreate;
762 split[sp][0] = GCD_RowSpan;
763 split[sp][1] = GCD_HPad10; split[sp][2] = &gcd[gcdoff-1];
764 split[sp][3] = GCD_ColSpan;
765
766 sprintf( widthbuf, "%g", (double) (si->width) );
767 label[gcdoff].text = (unichar_t *) widthbuf;
768 label[gcdoff].text_is_1byte = true;
769 gcd[gcdoff].gd.pos.width = 50;
770 gcd[gcdoff].gd.label = &label[gcdoff];
771 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
772 gcd[gcdoff].gd.cid = CID_Width;
773 gcd[gcdoff].gd.handle_controlevent = Stroke_TextChanged;
774 tfpos[0] = gcdoff;
775 gcd[gcdoff++].creator = GTextFieldCreate;
776 split[sp][4] = &gcd[gcdoff-1];
777 split[sp++][5] = NULL;
778
779 label[gcdoff].text = (unichar_t *) _("Minor Axis (_Height):");
780 label[gcdoff].text_is_1byte = true;
781 label[gcdoff].text_in_resource = true;
782 gcd[gcdoff].gd.label = &label[gcdoff];
783 gcd[gcdoff].gd.flags = gg_visible | gg_enabled;
784 gcd[gcdoff].gd.cid = CID_MinorAxisTxt;
785 gcd[gcdoff++].creator = GLabelCreate;
786 split[sp][0] = GCD_RowSpan;
787 split[sp][1] = GCD_HPad10; split[sp][2] = &gcd[gcdoff-1];
788 split[sp][3] = GCD_ColSpan;
789
790 sprintf( axisbuf, "%g", (double) (si->height) );
791 label[gcdoff].text = (unichar_t *) axisbuf;
792 label[gcdoff].text_is_1byte = true;
793 gcd[gcdoff].gd.pos.width = 50;
794 gcd[gcdoff].gd.label = &label[gcdoff];
795 gcd[gcdoff].gd.flags = gg_visible | gg_enabled;
796 gcd[gcdoff].gd.cid = CID_MinorAxis;
797 gcd[gcdoff].gd.handle_controlevent = Stroke_TextChanged;
798 gcd[gcdoff].gd.popup_msg = _(
799 "A calligraphic pen or an elliptical pen has two widths\n"
800 "(which may be the same, giving a circular or square pen,\n"
801 "or different giving an eliptical or rectangular pen).");
802 tfpos[1] = gcdoff;
803 gcd[gcdoff++].creator = GTextFieldCreate;
804 split[sp][4] = &gcd[gcdoff-1];
805 split[sp++][5] = NULL;
806
807 label[gcdoff].text = (unichar_t *) _("Ni_b Angle:");
808 label[gcdoff].text_is_1byte = true;
809 label[gcdoff].text_in_resource = true;
810 gcd[gcdoff].gd.label = &label[gcdoff];
811 gcd[gcdoff].gd.flags = gg_visible | gg_enabled;
812 gcd[gcdoff++].creator = GLabelCreate;
813 split[sp][0] = GCD_RowSpan;
814 split[sp][1] = GCD_HPad10; split[sp][2] = &gcd[gcdoff-1];
815 split[sp][3] = GCD_ColSpan;
816
817 sprintf( anglebuf, "%g", (double) (si->penangle*180/FF_PI) );
818 label[gcdoff].text = (unichar_t *) anglebuf;
819 label[gcdoff].text_is_1byte = true;
820 gcd[gcdoff].gd.pos.width = 50;
821 gcd[gcdoff].gd.label = &label[gcdoff];
822 gcd[gcdoff].gd.flags = gg_visible | gg_enabled;
823 gcd[gcdoff].gd.cid = CID_PenAngle;
824 gcd[gcdoff].gd.handle_controlevent = Stroke_TextChanged;
825 gcd[gcdoff].gd.popup_msg = _(
826 "A Convex nib will also be rotated by this amount\n"
827 "although this is not displayed in the dialog.");
828 tfpos[2] = gcdoff;
829 gcd[gcdoff++].creator = GTextFieldCreate;
830 split[sp][4] = &gcd[gcdoff-1];
831 split[sp++][5] = NULL;
832
833 label[gcdoff].text = (unichar_t *) _("Line Cap:");
834 label[gcdoff].text_is_1byte = true;
835 gcd[gcdoff].gd.label = &label[gcdoff];
836 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
837 gcd[gcdoff++].creator = GLabelCreate;
838 split[sp][0] = GCD_RowSpan;
839 split[sp][1] = GCD_HPad10; split[sp][2] = &gcd[gcdoff-1];
840
841 label[gcdoff].text = (unichar_t *) _("_Nib");
842 label[gcdoff].text_is_1byte = true;
843 label[gcdoff].text_in_resource = true;
844 gcd[gcdoff].gd.label = &label[gcdoff];
845 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->cap==lc_nib?gg_cb_on:0);
846 gcd[gcdoff].gd.cid = CID_NibCap;
847 gcd[gcdoff].gd.handle_controlevent = Cap_Other;
848 gcd[gcdoff++].creator = GRadioCreate;
849 split[sp][3] = &gcd[gcdoff-1];
850
851 // label[gcdoff].image = &GIcon_squarecap;
852 label[gcdoff].text = (unichar_t *) _("_Butt");
853 label[gcdoff].text_is_1byte = true;
854 label[gcdoff].text_in_resource = true;
855 label[gcdoff].image = &GIcon_buttcap;
856 gcd[gcdoff].gd.mnemonic = 'q';
857 gcd[gcdoff].gd.label = &label[gcdoff];
858 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->cap==lc_butt?gg_cb_on:0);
859 gcd[gcdoff].gd.cid = CID_ButtCap;
860 gcd[gcdoff].gd.handle_controlevent = Cap_Extendable;
861 gcd[gcdoff++].creator = GRadioCreate;
862 split[sp][4] = &gcd[gcdoff-1];
863 split[sp++][5] = NULL;
864
865 label[gcdoff].text = (unichar_t *) _("_Round");
866 label[gcdoff].text_is_1byte = true;
867 label[gcdoff].text_in_resource = true;
868 label[gcdoff].image = &GIcon_roundcap;
869 gcd[gcdoff].gd.mnemonic = 'R';
870 gcd[gcdoff].gd.label = &label[gcdoff];
871 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->cap==lc_round?gg_cb_on:0);
872 gcd[gcdoff].gd.cid = CID_RoundCap;
873 gcd[gcdoff].gd.handle_controlevent = Cap_Extendable;
874 gcd[gcdoff++].creator = GRadioCreate;
875 split[sp][0] = GCD_RowSpan;
876 split[sp][1] = GCD_HPad10; split[sp][2] = GCD_Glue;
877 split[sp][3] = &gcd[gcdoff-1];
878
879 label[gcdoff].text = (unichar_t *) _("Be_vel");
880 label[gcdoff].text_is_1byte = true;
881 label[gcdoff].text_in_resource = true;
882 // label[gcdoff].image = &GIcon_roundcap;
883 gcd[gcdoff].gd.label = &label[gcdoff];
884 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->cap==lc_bevel?gg_cb_on:0);
885 gcd[gcdoff].gd.cid = CID_BevelCap;
886 gcd[gcdoff].gd.handle_controlevent = Cap_Other;
887 gcd[gcdoff++].creator = GRadioCreate;
888 split[sp][4] = &gcd[gcdoff-1];
889 split[sp++][5] = NULL;
890
891 label[gcdoff].text = (unichar_t *) _("Line Join:");
892 label[gcdoff].text_is_1byte = true;
893 label[gcdoff].text_in_resource = true;
894 gcd[gcdoff].gd.label = &label[gcdoff];
895 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
896 gcd[gcdoff++].creator = GLabelCreate;
897 split[sp][0] = GCD_RowSpan;
898 split[sp][1] = GCD_HPad10; split[sp][2] = &gcd[gcdoff-1];
899
900 label[gcdoff].text = (unichar_t *) _("Ni_b");
901 label[gcdoff].text_is_1byte = true;
902 label[gcdoff].text_in_resource = true;
903 gcd[gcdoff].gd.label = &label[gcdoff];
904 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->join==lj_nib?gg_cb_on:0);
905 gcd[gcdoff].gd.cid = CID_NibJoin;
906 gcd[gcdoff].gd.handle_controlevent = Join_Other;
907 gcd[gcdoff++].creator = GRadioCreate;
908 split[sp][3] = &gcd[gcdoff-1];
909
910 label[gcdoff].text = (unichar_t *) _("B_evel");
911 label[gcdoff].text_is_1byte = true;
912 label[gcdoff].text_in_resource = true;
913 label[gcdoff].image = &GIcon_beveljoin;
914 gcd[gcdoff].gd.label = &label[gcdoff];
915 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->join==lj_bevel?gg_cb_on:0);
916 gcd[gcdoff].gd.cid = CID_BevelJoin;
917 gcd[gcdoff].gd.handle_controlevent = Join_Other;
918 gcd[gcdoff++].creator = GRadioCreate;
919 split[sp][4] = &gcd[gcdoff-1];
920 split[sp++][5] = NULL;
921
922 label[gcdoff].text = (unichar_t *) _("Round");
923 label[gcdoff].text_is_1byte = true;
924 label[gcdoff].text_in_resource = true;
925 gcd[gcdoff].gd.label = &label[gcdoff];
926 gcd[gcdoff].gd.flags = gg_visible | gg_enabled | (si->join==lj_round?gg_cb_on:0);
927 gcd[gcdoff].gd.cid = CID_RoundJoin;
928 gcd[gcdoff].gd.handle_controlevent = Join_Other;
929 gcd[gcdoff++].creator = GRadioCreate;
930 split[sp][0] = GCD_RowSpan;
931 split[sp][1] = GCD_HPad10; split[sp][2] = GCD_Glue;
932 split[sp][3] = &gcd[gcdoff-1];
933
934 label[gcdoff].text = (unichar_t *) _("Arcs");
935 label[gcdoff].text_is_1byte = true;
936 label[gcdoff].text_in_resource = true;
937 gcd[gcdoff].gd.label = &label[gcdoff];
938 gcd[gcdoff].gd.flags = gg_visible | gg_enabled | (si->join==lj_arcs?gg_cb_on:0);
939 gcd[gcdoff].gd.cid = CID_ArcsJoin;
940 gcd[gcdoff].gd.handle_controlevent = Join_Arcs;
941 gcd[gcdoff++].creator = GRadioCreate;
942 split[sp][4] = &gcd[gcdoff-1];
943 split[sp++][5] = NULL;
944
945 label[gcdoff].text = (unichar_t *) _("_Miter");
946 label[gcdoff].text_is_1byte = true;
947 label[gcdoff].text_in_resource = true;
948 label[gcdoff].image = &GIcon_miterjoin;
949 gcd[gcdoff].gd.label = &label[gcdoff];
950 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->join==lj_miter?gg_cb_on:0);
951 gcd[gcdoff].gd.cid = CID_MiterJoin;
952 gcd[gcdoff].gd.handle_controlevent = Join_Miter;
953 gcd[gcdoff++].creator = GRadioCreate;
954 split[sp][0] = GCD_RowSpan;
955 split[sp][1] = GCD_HPad10; split[sp][2] = GCD_Glue;
956 split[sp][3] = &gcd[gcdoff-1];
957
958 label[gcdoff].text = (unichar_t *) _("Miter Cli_p");
959 label[gcdoff].text_is_1byte = true;
960 label[gcdoff].text_in_resource = true;
961 gcd[gcdoff].gd.label = &label[gcdoff];
962 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->join==lj_miterclip?gg_cb_on:0);
963 gcd[gcdoff].gd.cid = CID_MiterClipJoin;
964 gcd[gcdoff].gd.handle_controlevent = Join_Miter;
965 gcd[gcdoff++].creator = GRadioCreate;
966 split[sp][4] = &gcd[gcdoff-1];
967 split[sp++][5] = NULL;
968 split[sp][0] = NULL;
969
970 boxes[2].gd.flags = gg_enabled|gg_visible;
971 boxes[2].gd.u.boxelements = split[0];
972 boxes[2].creator = GHVGroupCreate;
973 mainarray[mi][0] = &boxes[2]; mainarray[mi++][1] = NULL;
974
975 gcd[gcdoff].gd.flags = gg_enabled|gg_visible;
976 gcd[gcdoff++].creator = GLineCreate;
977 mainarray[mi][0] = &gcd[gcdoff-1]; mainarray[mi++][1] = NULL;
978
979 label[gcdoff].text = (unichar_t *) _("_Join Limit:");
980 label[gcdoff].text_is_1byte = true;
981 label[gcdoff].text_in_resource = true;
982 gcd[gcdoff].gd.label = &label[gcdoff];
983 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
984 gcd[gcdoff].gd.cid = CID_JoinLimitTxt;
985 gcd[gcdoff++].creator = GLabelCreate;
986 jlexarray[0][0] = &gcd[gcdoff-1];
987
988 sprintf( jlbuf, "%g", (double) (si->joinlimit) );
989 label[gcdoff].text = (unichar_t *) jlbuf;
990 label[gcdoff].text_is_1byte = true;
991 gcd[gcdoff].gd.pos.width = 50;
992 gcd[gcdoff].gd.label = &label[gcdoff];
993 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
994 gcd[gcdoff].gd.cid = CID_JoinLimitVal;
995 gcd[gcdoff].gd.handle_controlevent = Stroke_TextChanged;
996 tfpos[3] = gcdoff;
997 gcd[gcdoff++].creator = GTextFieldCreate;
998 jlexarray[0][1] = &gcd[gcdoff-1];
999
1000 label[gcdoff].text = (unichar_t *) _("as _Length");
1001 label[gcdoff].text_is_1byte = true;
1002 label[gcdoff].text_in_resource = true;
1003 gcd[gcdoff].gd.label = &label[gcdoff];
1004 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (!si->jlrelative?gg_cb_on:0);
1005 gcd[gcdoff].gd.cid = CID_JoinLimitLen;
1006 gcd[gcdoff++].creator = GRadioCreate;
1007 jlexarray[0][2] = &gcd[gcdoff-1];
1008
1009 label[gcdoff].text = (unichar_t *) _("* Nib _Span");
1010 label[gcdoff].text_is_1byte = true;
1011 label[gcdoff].text_in_resource = true;
1012 gcd[gcdoff].gd.label = &label[gcdoff];
1013 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->jlrelative?gg_cb_on:0);
1014 gcd[gcdoff].gd.cid = CID_JoinLimitRel;
1015 gcd[gcdoff++].creator = GRadioCreate;
1016 jlexarray[0][3] = &gcd[gcdoff-1];
1017 jlexarray[0][4] = GCD_Glue;
1018
1019 label[gcdoff].text = (unichar_t *) _("Accuracy _Target:");
1020 label[gcdoff].text_is_1byte = true;
1021 label[gcdoff].text_in_resource = true;
1022 gcd[gcdoff].gd.label = &label[gcdoff];
1023 gcd[gcdoff].gd.flags = gg_visible | gg_enabled;
1024 gcd[gcdoff++].creator = GLabelCreate;
1025 jlexarray[0][5] = &gcd[gcdoff-1];
1026
1027 sprintf( accbuf, "%g", (double) (si->accuracy_target) );
1028 label[gcdoff].text = (unichar_t *) accbuf;
1029 label[gcdoff].text_is_1byte = true;
1030 gcd[gcdoff].gd.pos.width = 50;
1031 gcd[gcdoff].gd.label = &label[gcdoff];
1032 gcd[gcdoff].gd.flags = gg_visible | gg_enabled;
1033 gcd[gcdoff].gd.cid = CID_AccTar;
1034 gcd[gcdoff].gd.handle_controlevent = Stroke_TextChanged;
1035 gcd[gcdoff].gd.popup_msg = _(
1036 "The stroke algorithm will attempt to be (at least)\n"
1037 "this accurate, but there may be exceptions.");
1038 tfpos[5] = gcdoff;
1039 gcd[gcdoff++].creator = GTextFieldCreate;
1040 jlexarray[0][6] = &gcd[gcdoff-1]; jlexarray[0][7] = NULL;
1041
1042 label[gcdoff].text = (unichar_t *) _("_Extend Cap:");
1043 label[gcdoff].text_is_1byte = true;
1044 label[gcdoff].text_in_resource = true;
1045 gcd[gcdoff].gd.label = &label[gcdoff];
1046 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
1047 gcd[gcdoff].gd.cid = CID_ExtendCapTxt;
1048 gcd[gcdoff++].creator = GLabelCreate;
1049 jlexarray[1][0] = &gcd[gcdoff-1];
1050
1051 sprintf( ecbuf, "%g", (double) (si->extendcap) );
1052 label[gcdoff].text = (unichar_t *) ecbuf;
1053 label[gcdoff].text_is_1byte = true;
1054 gcd[gcdoff].gd.pos.width = 50;
1055 gcd[gcdoff].gd.label = &label[gcdoff];
1056 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
1057 gcd[gcdoff].gd.cid = CID_ExtendCapVal;
1058 gcd[gcdoff].gd.handle_controlevent = Stroke_TextChanged;
1059 tfpos[4] = gcdoff;
1060 gcd[gcdoff++].creator = GTextFieldCreate;
1061 jlexarray[1][1] = &gcd[gcdoff-1];
1062
1063 label[gcdoff].text = (unichar_t *) _("as Len_gth");
1064 label[gcdoff].text_is_1byte = true;
1065 label[gcdoff].text_in_resource = true;
1066 gcd[gcdoff].gd.label = &label[gcdoff];
1067 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (!si->ecrelative?gg_cb_on:0);
1068 gcd[gcdoff].gd.cid = CID_ExtendCapLen;
1069 gcd[gcdoff++].creator = GRadioCreate;
1070 jlexarray[1][2] = &gcd[gcdoff-1];
1071
1072 label[gcdoff].text = (unichar_t *) _("* Cap Widt_h");
1073 label[gcdoff].text_is_1byte = true;
1074 label[gcdoff].text_in_resource = true;
1075 gcd[gcdoff].gd.label = &label[gcdoff];
1076 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->ecrelative?gg_cb_on:0);
1077 gcd[gcdoff].gd.cid = CID_ExtendCapRel;
1078 gcd[gcdoff++].creator = GRadioCreate;
1079 jlexarray[1][3] = &gcd[gcdoff-1];
1080 jlexarray[1][4] = GCD_Glue; jlexarray[1][5] = GCD_Glue;
1081 jlexarray[1][6] = GCD_Glue; jlexarray[1][7] = NULL;
1082 jlexarray[2][0] = NULL;
1083
1084 boxes[3].gd.flags = gg_enabled|gg_visible;
1085 boxes[3].gd.u.boxelements = jlexarray[0];
1086 boxes[3].creator = GHVBoxCreate;
1087 mainarray[mi][0] = &boxes[3]; mainarray[mi++][1] = NULL;
1088
1089 gcd[gcdoff].gd.flags = gg_enabled|gg_visible;
1090 gcd[gcdoff++].creator = GLineCreate;
1091 mainarray[mi][0] = &gcd[gcdoff-1]; mainarray[mi++][1] = NULL;
1092
1093 label[gcdoff].text = (unichar_t *) _("Remove Overlap:");
1094 label[gcdoff].text_is_1byte = true;
1095 label[gcdoff].text_in_resource = true;
1096 gcd[gcdoff].gd.label = &label[gcdoff];
1097 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
1098 gcd[gcdoff++].creator = GLabelCreate;
1099 radoptarray[0][0] = &gcd[gcdoff-1]; radoptarray[0][1] = GCD_Glue;
1100
1101 label[gcdoff].text = (unichar_t *) _("By La_yer");
1102 label[gcdoff].text_is_1byte = true;
1103 label[gcdoff].text_in_resource = true;
1104 gcd[gcdoff].gd.label = &label[gcdoff];
1105 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->rmov==srmov_layer?gg_cb_on:0);
1106 gcd[gcdoff].gd.cid = CID_RmOvLayer;
1107 gcd[gcdoff++].creator = GRadioCreate;
1108 radoptarray[0][2] = &gcd[gcdoff-1]; radoptarray[0][3] = GCD_Glue;
1109
1110 label[gcdoff].text = (unichar_t *) _("By Con_tour");
1111 label[gcdoff].text_is_1byte = true;
1112 label[gcdoff].text_in_resource = true;
1113 gcd[gcdoff].gd.label = &label[gcdoff];
1114 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->rmov==srmov_contour?gg_cb_on:0);
1115 gcd[gcdoff].gd.cid = CID_RmOvContour;
1116 gcd[gcdoff++].creator = GRadioCreate;
1117 radoptarray[0][4] = &gcd[gcdoff-1]; radoptarray[0][5] = GCD_Glue;
1118
1119 label[gcdoff].text = (unichar_t *) _("N_one (Debug)");
1120 label[gcdoff].text_is_1byte = true;
1121 label[gcdoff].text_in_resource = true;
1122 gcd[gcdoff].gd.label = &label[gcdoff];
1123 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->rmov==srmov_none?gg_cb_on:0);
1124 gcd[gcdoff].gd.cid = CID_RmOvNone;
1125 gcd[gcdoff++].creator = GRadioCreate;
1126 radoptarray[0][6] = &gcd[gcdoff-1]; radoptarray[0][7] = GCD_Glue;
1127 radoptarray[0][8] = NULL;
1128
1129 label[gcdoff].text = (unichar_t *) _("Contours (from closed):");
1130 label[gcdoff].text_is_1byte = true;
1131 label[gcdoff].text_in_resource = true;
1132 gcd[gcdoff].gd.label = &label[gcdoff];
1133 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
1134 gcd[gcdoff++].creator = GLabelCreate;
1135 radoptarray[1][0] = &gcd[gcdoff-1]; radoptarray[1][1] = GCD_Glue;
1136
1137 label[gcdoff].text = (unichar_t *) _("Both");
1138 label[gcdoff].text_is_1byte = true;
1139 label[gcdoff].text_in_resource = true;
1140 gcd[gcdoff].gd.label = &label[gcdoff];
1141 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | ((!si->removeinternal && !si->removeexternal)?gg_cb_on:0);
1142 gcd[gcdoff++].creator = GRadioCreate;
1143 radoptarray[1][2] = &gcd[gcdoff-1]; radoptarray[1][3] = GCD_Glue;
1144
1145 label[gcdoff].text = (unichar_t *) _("External Only");
1146 label[gcdoff].text_is_1byte = true;
1147 label[gcdoff].text_in_resource = true;
1148 gcd[gcdoff].gd.label = &label[gcdoff];
1149 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->removeinternal?gg_cb_on:0);
1150 gcd[gcdoff].gd.cid = CID_RmInternal;
1151 gcd[gcdoff++].creator = GRadioCreate;
1152 radoptarray[1][4] = &gcd[gcdoff-1]; radoptarray[1][5] = GCD_Glue;
1153
1154 label[gcdoff].text = (unichar_t *) _("Internal Only");
1155 label[gcdoff].text_is_1byte = true;
1156 label[gcdoff].text_in_resource = true;
1157 gcd[gcdoff].gd.label = &label[gcdoff];
1158 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->removeexternal?gg_cb_on:0);
1159 gcd[gcdoff].gd.cid = CID_RmExternal;
1160 gcd[gcdoff++].creator = GRadioCreate;
1161 radoptarray[1][6] = &gcd[gcdoff-1]; radoptarray[1][7] = GCD_Glue;
1162 radoptarray[1][8] = NULL;
1163
1164 label[gcdoff].text = (unichar_t *) _("Arcs Clip:");
1165 label[gcdoff].text_is_1byte = true;
1166 label[gcdoff].text_in_resource = true;
1167 gcd[gcdoff].gd.label = &label[gcdoff];
1168 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
1169 gcd[gcdoff].gd.cid = CID_AlText;
1170 gcd[gcdoff++].creator = GLabelCreate;
1171 radoptarray[2][0] = &gcd[gcdoff-1]; radoptarray[2][1] = GCD_Glue;
1172
1173 label[gcdoff].text = (unichar_t *) _("Auto");
1174 label[gcdoff].text_is_1byte = true;
1175 label[gcdoff].text_in_resource = true;
1176 gcd[gcdoff].gd.label = &label[gcdoff];
1177 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->al==sal_auto?gg_cb_on:0);
1178 gcd[gcdoff].gd.cid = CID_AlAuto;
1179 gcd[gcdoff++].creator = GRadioCreate;
1180 radoptarray[2][2] = &gcd[gcdoff-1]; radoptarray[2][3] = GCD_Glue;
1181
1182 label[gcdoff].text = (unichar_t *) _("SVG 2");
1183 label[gcdoff].text_is_1byte = true;
1184 label[gcdoff].text_in_resource = true;
1185 gcd[gcdoff].gd.label = &label[gcdoff];
1186 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->al==sal_svg2?gg_cb_on:0);
1187 gcd[gcdoff].gd.cid = CID_AlSVG2;
1188 gcd[gcdoff++].creator = GRadioCreate;
1189 radoptarray[2][4] = &gcd[gcdoff-1]; radoptarray[2][5] = GCD_Glue;
1190
1191 label[gcdoff].text = (unichar_t *) _("Ratio");
1192 label[gcdoff].text_is_1byte = true;
1193 label[gcdoff].text_in_resource = true;
1194 gcd[gcdoff].gd.label = &label[gcdoff];
1195 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->al==sal_ratio?gg_cb_on:0);
1196 gcd[gcdoff].gd.cid = CID_AlRatio;
1197 gcd[gcdoff++].creator = GRadioCreate;
1198 radoptarray[2][6] = &gcd[gcdoff-1]; radoptarray[2][7] = GCD_Glue;
1199 radoptarray[2][8] = NULL; radoptarray[3][0] = NULL;
1200
1201 boxes[4].gd.flags = gg_enabled|gg_visible;
1202 boxes[4].gd.u.boxelements = radoptarray[0];
1203 boxes[4].creator = GHVBoxCreate;
1204 mainarray[mi][0] = &boxes[4]; mainarray[mi++][1] = NULL;
1205
1206 label[gcdoff].text = (unichar_t *) _("S_implify");
1207 label[gcdoff].text_is_1byte = true;
1208 label[gcdoff].text_in_resource = true;
1209 gcd[gcdoff].gd.label = &label[gcdoff];
1210 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->simplify?gg_cb_on:0);
1211 gcd[gcdoff].gd.cid = CID_Simplify;
1212 gcd[gcdoff++].creator = GCheckBoxCreate;
1213 checkarray[0] = &gcd[gcdoff-1]; checkarray[1] = GCD_Glue;
1214
1215 label[gcdoff].text = (unichar_t *) _("A_dd Extrema");
1216 label[gcdoff].text_is_1byte = true;
1217 label[gcdoff].text_in_resource = true;
1218 gcd[gcdoff].gd.label = &label[gcdoff];
1219 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (si->extrema?gg_cb_on:0);
1220 gcd[gcdoff].gd.cid = CID_Extrema;
1221 gcd[gcdoff++].creator = GCheckBoxCreate;
1222 checkarray[2] = &gcd[gcdoff-1]; checkarray[3] = GCD_Glue;
1223 checkarray[4] = NULL;
1224
1225 boxes[5].gd.flags = gg_enabled|gg_visible;
1226 boxes[5].gd.u.boxelements = checkarray;
1227 boxes[5].creator = GHBoxCreate;
1228 mainarray[mi][0] = &boxes[5]; mainarray[mi++][1] = NULL;
1229
1230 gcd[gcdoff].gd.flags = gg_visible | gg_enabled | gg_but_default;
1231 label[gcdoff].text = (unichar_t *) _("_OK");
1232 label[gcdoff].text_is_1byte = true;
1233 label[gcdoff].text_in_resource = true;
1234 gcd[gcdoff].gd.label = &label[gcdoff];
1235 gcd[gcdoff].gd.handle_controlevent = Stroke_OK;
1236 gcd[gcdoff++].creator = GButtonCreate;
1237 buttons[0] = GCD_Glue; buttons[1] = &gcd[gcdoff-1]; buttons[2] = GCD_Glue; buttons[3] = GCD_Glue;
1238
1239 gcd[gcdoff].gd.flags = gg_visible | gg_enabled;
1240 label[gcdoff].text = (unichar_t *) _("_Apply");
1241 label[gcdoff].text_is_1byte = true;
1242 label[gcdoff].text_in_resource = true;
1243 gcd[gcdoff].gd.label = &label[gcdoff];
1244 gcd[gcdoff].gd.handle_controlevent = Stroke_OK;
1245 gcd[gcdoff].gd.cid = CID_Apply;
1246 gcd[gcdoff++].creator = GButtonCreate;
1247 buttons[4] = GCD_Glue; buttons[5] = &gcd[gcdoff-1]; buttons[6] = GCD_Glue; buttons[7] = GCD_Glue;
1248
1249 gcd[gcdoff].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
1250 label[gcdoff].text = (unichar_t *) _("_Cancel");
1251 label[gcdoff].text_is_1byte = true;
1252 label[gcdoff].text_in_resource = true;
1253 gcd[gcdoff].gd.label = &label[gcdoff];
1254 gcd[gcdoff].gd.handle_controlevent = Stroke_Cancel;
1255 gcd[gcdoff].creator = GButtonCreate;
1256 buttons[8] = GCD_Glue; buttons[9] = &gcd[gcdoff]; buttons[10] = GCD_Glue;
1257 buttons[11] = NULL;
1258
1259 boxes[6].gd.flags = gg_enabled|gg_visible;
1260 boxes[6].gd.u.boxelements = buttons;
1261 boxes[6].creator = GHBoxCreate;
1262 mainarray[mi][0] = &boxes[6]; mainarray[mi++][1] = NULL;
1263 mainarray[mi][0] = GCD_Glue; mainarray[mi++][1] = NULL;
1264 mainarray[mi][0] = NULL;
1265
1266 boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
1267 boxes[0].gd.flags = gg_enabled|gg_visible;
1268 boxes[0].gd.u.boxelements = mainarray[0];
1269 boxes[0].gd.cid = CID_TopBox;
1270 boxes[0].creator = GHVGroupCreate;
1271
1272 GGadgetsCreate(gw,boxes);
1273 GHVBoxSetExpandableRow(boxes[0].ret,1);
1274 GHVBoxSetExpandableCol(boxes[2].ret,0);
1275 for (i=3; i<=5; ++i) {
1276 GHVBoxSetExpandableCol(boxes[i].ret,gb_expandglue);
1277 }
1278 GHVBoxSetExpandableCol(boxes[6].ret,gb_expandgluesame);
1279 for (i=0; i<6; ++i)
1280 GGadgetSetSkipUnQualifiedHotkeyProcessing(gcd[tfpos[i]].ret, 1);
1281
1282 StrokeCharViewInits(&sd,CID_Nib);
1283 sd.cv_stroke.showfore = true;
1284 sd.cv_stroke.showgrids = true;
1285 }
1286
1287 Stroke_MakeActive(&sd,&sd.cv_stroke);
1288 Stroke_ShowNib(&sd);
1289
1290 sd.cv = cv;
1291 sd.strokeit = strokeit;
1292 sd.done = false;
1293 sd.up[0] = sd.up[1] = true;
1294
1295 GWidgetHidePalettes();
1296 GWidgetIndicateFocusGadget(GWidgetGetControl(sd.gw,CID_Width));
1297
1298 StrokeSetup(&sd,si->stroke_type);
1299 JoinSetup(&sd,si->join==lj_arcs?2:((si->join==lj_miterclip||si->join==lj_miter)?1:0));
1300 ExtendSetup(&sd,si->cap==lc_butt||si->cap==lc_round);
1301
1302 GGadgetSetVisible(GWidgetGetControl(sd.gw,CID_Apply), apply);
1303 GWidgetToDesiredSize(sd.gw);
1304
1305 GDrawSetVisible(sd.gw,true);
1306 while ( !sd.done )
1307 GDrawProcessOneEvent(NULL);
1308
1309 CVPalettesHideIfMine(&sd.cv_stroke);
1310 GDrawDestroyWindow(sd.gw);
1311
1312 do {
1313 GDrawSync(NULL);
1314 GDrawProcessPendingEvents(NULL);
1315 } while (sd.gw != NULL);
1316
1317 if ( sd.done==1 && si->stroke_type!=si_nib ) {
1318 assert( si->nib==NULL );
1319 // Return the edited nib in this case
1320 si->nib = sd.old_convex;
1321 sd.old_convex = NULL;
1322 SplinePointListFree(nib_bk);
1323 } else if ( sd.done==1 ) {
1324 SplinePointListFree(nib_bk);
1325 } else {
1326 assert( si->nib==NULL );
1327 si->nib = nib_bk;
1328 SplinePointListFree(sd.old_convex);
1329 }
1330 }
1331
CVStroke(CharView * cv)1332 void CVStroke(CharView *cv) {
1333 if ( cv->b.layerheads[cv->b.drawmode]->splines==NULL )
1334 return;
1335 MakeStrokeDlg(cv, CVStrokeIt, CVStrokeInfo(), true);
1336 }
1337
FVStroke(FontView * fv)1338 void FVStroke(FontView *fv) {
1339 MakeStrokeDlg(fv, FVStrokeItScript, CVStrokeInfo(), false);
1340 }
1341
FreeHandStrokeDlg(StrokeInfo * si)1342 void FreeHandStrokeDlg(StrokeInfo *si) {
1343 MakeStrokeDlg(NULL,NULL,si,false);
1344 }
1345
1346 /* ************************************************************************** */
1347 /* ****************************** Layer Dialog ****************************** */
1348 /* ************************************************************************** */
1349 #define LY_Width 300
1350 #define LY_Height 336
1351
1352 #define CID_FillColor 2001
1353 #define CID_FillCInherit 2002
1354 #define CID_FillOpacity 2003
1355 #define CID_FillOInherit 2004
1356 #define CID_StrokeColor 2005
1357 #define CID_StrokeCInherit 2006
1358 #define CID_StrokeOpacity 2007
1359 #define CID_StrokeOInherit 2008
1360 #define CID_StrokeWInherit 2009
1361 #define CID_Trans 2010
1362 #define CID_InheritCap 2011
1363 #define CID_InheritJoin 2012
1364 #define CID_Fill 2013
1365 #define CID_Dashes 2014
1366 #define CID_DashesTxt 2015
1367 #define CID_DashesInherit 2016
1368 #define CID_Stroke 2017
1369
1370 #define CID_FillGradAdd 2100
1371 #define CID_FillGradEdit 2101
1372 #define CID_FillGradDelete 2102
1373 #define CID_StrokeGradAdd 2110
1374 #define CID_StrokeGradEdit 2111
1375 #define CID_StrokeGradDelete 2112
1376
1377 #define CID_FillPatAdd 2200
1378 #define CID_FillPatEdit 2201
1379 #define CID_FillPatDelete 2202
1380 #define CID_StrokePatAdd 2210
1381 #define CID_StrokePatEdit 2211
1382 #define CID_StrokePatDelete 2212
1383
1384 struct layer_dlg {
1385 int done;
1386 int ok;
1387 Layer *layer;
1388 SplineFont *sf;
1389 GWindow gw;
1390 struct gradient *fillgrad, *strokegrad;
1391 struct pattern *fillpat, *strokepat;
1392
1393 int pat_done;
1394 struct pattern *curpat;
1395 };
1396
1397 #define CID_Gradient 1001
1398 #define CID_Stops 1002
1399 #define CID_Pad 1003
1400 #define CID_Repeat 1004
1401 #define CID_Reflect 1005
1402 #define CID_Linear 1006
1403 #define CID_Radial 1007
1404 #define CID_GradStops 1008
1405
GDDSubResize(GradientDlg * gdd,GEvent * event)1406 static void GDDSubResize(GradientDlg *gdd, GEvent *event) {
1407 int width, height;
1408
1409 if ( !event->u.resize.sized )
1410 return;
1411
1412 width = event->u.resize.size.width;
1413 height = event->u.resize.size.height;
1414 if ( width!=gdd->cv_width || height!=gdd->cv_height ) {
1415 gdd->cv_width = width; gdd->cv_height = height;
1416 GDrawResize(gdd->cv_grad.gw,width,height);
1417 }
1418
1419 GDrawSync(NULL);
1420 GDrawProcessPendingEvents(NULL);
1421 }
1422
GDDDraw(GradientDlg * gdd,GWindow pixmap,GEvent * event)1423 static void GDDDraw(GradientDlg *gdd, GWindow pixmap, GEvent *event) {
1424 GRect r,pos;
1425
1426 GGadgetGetSize(GWidgetGetControl(gdd->gw,CID_Gradient),&pos);
1427 r.x = pos.x-1; r.y = pos.y-1;
1428 r.width = pos.width+1; r.height = pos.height+1;
1429 GDrawDrawRect(pixmap,&r,0);
1430 }
1431
GDDMakeActive(GradientDlg * gdd,CharView * cv)1432 static void GDDMakeActive(GradientDlg *gdd,CharView *cv) {
1433
1434 if ( gdd==NULL )
1435 return;
1436 cv->inactive = false;
1437 GDrawSetUserData(gdd->gw,cv);
1438 GDrawRequestExpose(cv->v,NULL,false);
1439 GDrawRequestExpose(gdd->gw,NULL,false);
1440 }
1441
GDDChar(GradientDlg * gdd,GEvent * event)1442 static void GDDChar(GradientDlg *gdd, GEvent *event) {
1443 CVChar((&gdd->cv_grad),event);
1444 }
1445
GDD_DoClose(struct cvcontainer * cvc)1446 static void GDD_DoClose(struct cvcontainer *cvc) {
1447 GradientDlg *gdd = (GradientDlg *) cvc;
1448
1449 {
1450 SplineChar *msc = &gdd->sc_grad;
1451 SplinePointListsFree(msc->layers[0].splines);
1452 SplinePointListsFree(msc->layers[1].splines);
1453 free( msc->layers );
1454 }
1455
1456 gdd->done = true;
1457 }
1458
gdd_sub_e_h(GWindow gw,GEvent * event)1459 static int gdd_sub_e_h(GWindow gw, GEvent *event) {
1460 GradientDlg *gdd = (GradientDlg *) ((CharViewBase *) GDrawGetUserData(gw))->container;
1461
1462 switch ( event->type ) {
1463 case et_resize:
1464 if ( event->u.resize.sized )
1465 GDDSubResize(gdd,event);
1466 break;
1467 case et_char:
1468 GDDChar(gdd,event);
1469 break;
1470 case et_mouseup: case et_mousedown: case et_mousemove:
1471 return( false );
1472 break;
1473 }
1474 return( true );
1475 }
1476
gdd_e_h(GWindow gw,GEvent * event)1477 static int gdd_e_h(GWindow gw, GEvent *event) {
1478 GradientDlg *gdd = (GradientDlg *) ((CharViewBase *) GDrawGetUserData(gw))->container;
1479
1480 switch ( event->type ) {
1481 case et_expose:
1482 GDDDraw(gdd, gw, event);
1483 break;
1484 case et_char:
1485 GDDChar(gdd,event);
1486 break;
1487 case et_close:
1488 GDD_DoClose((struct cvcontainer *) gdd);
1489 break;
1490 case et_create:
1491 break;
1492 case et_map:
1493 {
1494 CharView *cv = (&gdd->cv_grad);
1495 if ( !cv->inactive ) {
1496 if ( event->u.map.is_visible )
1497 CVPaletteActivate(cv);
1498 else
1499 CVPalettesHideIfMine(cv);
1500 }
1501 }
1502 /* gdd->isvisible = event->u.map.is_visible; */
1503 break;
1504 }
1505 return( true );
1506 }
1507
Gradient_Cancel(GGadget * g,GEvent * e)1508 static int Gradient_Cancel(GGadget *g, GEvent *e) {
1509 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1510 GradientDlg *gdd = (GradientDlg *) (((CharViewBase *) GDrawGetUserData(GGadgetGetWindow(g)))->container);
1511 GDD_DoClose(&gdd->base);
1512 }
1513 return( true );
1514 }
1515
orderstops(const void * _md1,const void * _md2)1516 static int orderstops(const void *_md1, const void *_md2) {
1517 const struct matrix_data *md1 = _md1, *md2 = _md2;
1518
1519 if ( md1->u.md_real>md2->u.md_real )
1520 return( 1 );
1521 else if ( md1->u.md_real==md2->u.md_real )
1522 return( 0 );
1523 else
1524 return( -1 );
1525 }
1526
Gradient_OK(GGadget * g,GEvent * e)1527 static int Gradient_OK(GGadget *g, GEvent *e) {
1528 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1529 GradientDlg *gdd = (GradientDlg *) (((CharViewBase *) GDrawGetUserData(GGadgetGetWindow(g)))->container);
1530 struct gradient *gradient = gdd->active;
1531 BasePoint start, end, offset;
1532 real radius;
1533 int pad, linear;
1534 SplineSet *ss, *ss2;
1535 int i, rows, cols = GMatrixEditGetColCnt(GWidgetGetControl(gdd->gw,CID_GradStops));
1536 struct matrix_data *md = GMatrixEditGet(GWidgetGetControl(gdd->gw,CID_GradStops), &rows);
1537
1538 if ( rows<2 ) {
1539 ff_post_error(_("Bad Gradient"),_("There must be at least 2 gradient stops"));
1540 return( true );
1541 }
1542 for ( i=0; i<rows; ++i ) {
1543 if ( md[cols*i+0].u.md_real<0 || md[cols*i+0].u.md_real>100.0 ) {
1544 ff_post_error(_("Bad Gradient"),_("Bad offset on line %d, must be between 0% and 100%."), i );
1545 return( true );
1546 }
1547 if ( md[cols*i+1].u.md_ival<0 || md[cols*i+1].u.md_ival>0xffffff ) {
1548 ff_post_error(_("Bad Gradient"),_("Bad color on line %d, must be between 000000 and ffffff."), i );
1549 return( true );
1550 }
1551 if ( md[cols*i+2].u.md_real<0 || md[cols*i+2].u.md_real>1.0 ) {
1552 ff_post_error(_("Bad Gradient"),_("Bad opacity on line %d, must be between 0.0 and 1.0."), i );
1553 return( true );
1554 }
1555 }
1556
1557 linear = GGadgetIsChecked(GWidgetGetControl(gdd->gw,CID_Linear));
1558 if ( GGadgetIsChecked(GWidgetGetControl(gdd->gw,CID_Pad)) )
1559 pad = sm_pad;
1560 else if ( GGadgetIsChecked(GWidgetGetControl(gdd->gw,CID_Repeat)) )
1561 pad = sm_repeat;
1562 else
1563 pad = sm_reflect;
1564 ss = gdd->sc_grad.layers[ly_fore].splines;
1565 if ( ss==NULL || gdd->sc_grad.layers[ly_fore].refs!=NULL ||
1566 (linear && ss->next!=NULL) ||
1567 (!linear && ss->next!=NULL && ss->next->next!=NULL)) {
1568 ff_post_error(_("Bad Gradient"),_("You must draw a line"));
1569 return( true );
1570 }
1571 ss2 = NULL;
1572 if ( !linear && ss->next!=NULL ) {
1573 if ( ss->first->next==NULL ) {
1574 ss2 = ss;
1575 ss = ss2->next;
1576 } else {
1577 ss2 = ss->next;
1578 if ( ss2->first->next!=NULL ) {
1579 ff_post_error(_("Bad Gradient"),_("You must draw a line, with at most one additional point"));
1580 return( true );
1581 }
1582 }
1583 }
1584 if ( (ss->first->next==NULL || ss->first==ss->last ||
1585 ss->first->next->to->next!=NULL ) ||
1586 !ss->first->next->islinear ) {
1587 ff_post_error(_("Bad Gradient"),_("You must draw a line"));
1588 return( true );
1589 }
1590
1591 if ( linear ) {
1592 start = ss->first->me;
1593 end = ss->last->me;
1594 radius = 0;
1595 } else {
1596 end = ss->first->me;
1597 offset.x = ss->last->me.x-end.x;
1598 offset.y = ss->last->me.y-end.y;
1599 radius = sqrt(offset.x*offset.x + offset.y*offset.y);
1600 if ( ss2!=NULL )
1601 start = ss2->first->me;
1602 else
1603 start = end;
1604 }
1605 if ( gradient==NULL )
1606 gdd->active = gradient = chunkalloc(sizeof(struct gradient));
1607 gradient->start = start;
1608 gradient->stop = end;
1609 gradient->radius = radius;
1610 gradient->sm = pad;
1611
1612 /* Stops must be stored in ascending order */
1613 qsort(md,rows,cols*sizeof(struct matrix_data),orderstops);
1614 gradient->grad_stops = realloc(gradient->grad_stops,rows*sizeof(struct grad_stops));
1615 gradient->stop_cnt = rows;
1616 for ( i=0; i<rows; ++i ) {
1617 gradient->grad_stops[i].offset = md[cols*i+0].u.md_real/100.0;
1618 gradient->grad_stops[i].col = md[cols*i+1].u.md_ival;
1619 gradient->grad_stops[i].opacity = md[cols*i+2].u.md_real;
1620 }
1621
1622 GDD_DoClose(&gdd->base);
1623 gdd->oked = true;
1624 }
1625 return( true );
1626 }
1627
GDD_Can_Navigate(struct cvcontainer * cvc,enum nav_type type)1628 static int GDD_Can_Navigate(struct cvcontainer *cvc, enum nav_type type) {
1629 return( false );
1630 }
1631
GDD_Can_Open(struct cvcontainer * cvc)1632 static int GDD_Can_Open(struct cvcontainer *cvc) {
1633 return( false );
1634 }
1635
SF_Of_GDD(struct cvcontainer * foo)1636 static SplineFont *SF_Of_GDD(struct cvcontainer *foo) {
1637 return( NULL );
1638 }
1639
1640 struct cvcontainer_funcs gradient_funcs = {
1641 cvc_gradient,
1642 (void (*) (struct cvcontainer *cvc,CharViewBase *cv)) GDDMakeActive,
1643 (void (*) (struct cvcontainer *cvc,void *)) GDDChar,
1644 GDD_Can_Navigate,
1645 NULL,
1646 GDD_Can_Open,
1647 GDD_DoClose,
1648 SF_Of_GDD
1649 };
1650
1651
GDDInit(GradientDlg * gdd,SplineFont * sf,Layer * ly,struct gradient * grad)1652 static void GDDInit(GradientDlg *gdd,SplineFont *sf,Layer *ly,struct gradient *grad) {
1653
1654 memset(gdd,0,sizeof(*gdd));
1655 gdd->base.funcs = &gradient_funcs;
1656
1657 {
1658 SplineChar *msc = (&gdd->sc_grad);
1659 CharView *mcv = (&gdd->cv_grad);
1660 msc->orig_pos = 0;
1661 msc->unicodeenc = -1;
1662 msc->name = "Gradient";
1663 msc->parent = &gdd->dummy_sf;
1664 msc->layer_cnt = 2;
1665 msc->layers = calloc(2,sizeof(Layer));
1666 LayerDefault(&msc->layers[0]);
1667 LayerDefault(&msc->layers[1]);
1668 gdd->chars[0] = msc;
1669
1670 mcv->b.sc = msc;
1671 mcv->b.layerheads[dm_fore] = &msc->layers[ly_fore];
1672 mcv->b.layerheads[dm_back] = &msc->layers[ly_back];
1673 mcv->b.layerheads[dm_grid] = &gdd->dummy_sf.grid;
1674 mcv->b.drawmode = dm_fore;
1675 mcv->b.container = (struct cvcontainer *) gdd;
1676 mcv->inactive = false;
1677 }
1678 gdd->dummy_sf.glyphs = gdd->chars;
1679 gdd->dummy_sf.glyphcnt = gdd->dummy_sf.glyphmax = 1;
1680 gdd->dummy_sf.pfminfo.fstype = -1;
1681 gdd->dummy_sf.pfminfo.stylemap = -1;
1682 gdd->dummy_sf.fontname = gdd->dummy_sf.fullname = gdd->dummy_sf.familyname = "dummy";
1683 gdd->dummy_sf.weight = "Medium";
1684 gdd->dummy_sf.origname = "dummy";
1685 gdd->dummy_sf.ascent = sf->ascent;
1686 gdd->dummy_sf.descent = sf->descent;
1687 gdd->dummy_sf.layers = gdd->layerinfo;
1688 gdd->dummy_sf.layer_cnt = 2;
1689 gdd->layerinfo[ly_back].order2 = sf->layers[ly_back].order2;
1690 gdd->layerinfo[ly_back].name = _("Back");
1691 gdd->layerinfo[ly_fore].order2 = sf->layers[ly_fore].order2;
1692 gdd->layerinfo[ly_fore].name = _("Fore");
1693 gdd->dummy_sf.grid.order2 = sf->grid.order2;
1694 gdd->dummy_sf.anchor = NULL;
1695
1696 gdd->dummy_sf.fv = (FontViewBase *) &gdd->dummy_fv;
1697 gdd->dummy_fv.b.active_layer = ly_fore;
1698 gdd->dummy_fv.b.sf = &gdd->dummy_sf;
1699 gdd->dummy_fv.b.selected = gdd->sel;
1700 gdd->dummy_fv.cbw = gdd->dummy_fv.cbh = default_fv_font_size+1;
1701 gdd->dummy_fv.magnify = 1;
1702
1703 gdd->dummy_fv.b.map = &gdd->dummy_map;
1704 gdd->dummy_map.map = gdd->map;
1705 gdd->dummy_map.backmap = gdd->backmap;
1706 gdd->dummy_map.enccount = gdd->dummy_map.encmax = gdd->dummy_map.backmax = 1;
1707 gdd->dummy_map.enc = &custom;
1708
1709 if ( grad!=NULL ) {
1710 SplineSet *ss1, *ss2;
1711 SplinePoint *sp1, *sp2, *sp3;
1712 ss1 = chunkalloc(sizeof(SplineSet));
1713 sp2 = SplinePointCreate(grad->stop.x,grad->stop.y);
1714 if ( grad->radius==0 ) {
1715 sp1 = SplinePointCreate(grad->start.x,grad->start.y);
1716 SplineMake(sp1,sp2,sf->layers[ly_fore].order2);
1717 ss1->first = sp1; ss1->last = sp2;
1718 } else {
1719 sp3 = SplinePointCreate(grad->start.x+grad->radius,grad->start.y);
1720 SplineMake(sp2,sp3,sf->layers[ly_fore].order2);
1721 ss1->first = sp2; ss1->last = sp3;
1722 if ( grad->start.x!=grad->stop.x || grad->start.y!=grad->stop.y ) {
1723 ss2 = chunkalloc(sizeof(SplineSet));
1724 sp1 = SplinePointCreate(grad->start.x,grad->start.y);
1725 ss2->first = ss2->last = sp1;
1726 ss1->next = ss2;
1727 }
1728 }
1729 gdd->sc_grad.layers[ly_fore].splines = ss1;
1730 }
1731
1732 gdd->sc_grad.layers[ly_back]. splines = SplinePointListCopy( LayerAllSplines(ly));
1733 LayerUnAllSplines(ly);
1734 }
1735
1736 static struct col_init stopci[] = {
1737 { me_real , NULL, NULL, NULL, N_("Offset %") },
1738 { me_hex, NULL, NULL, NULL, N_("Color") },
1739 { me_real, NULL, NULL, NULL, N_("Opacity") }
1740 };
1741
Grad_CanDelete(GGadget * g,int row)1742 static int Grad_CanDelete(GGadget *g,int row) {
1743 int rows;
1744 struct matrix_data *md = GMatrixEditGet(g, &rows);
1745 if ( md==NULL )
1746 return( false );
1747
1748 /* There must always be at least two entries in the table */
1749 return( rows>2 );
1750 }
1751
Grad_NewRow(GGadget * g,int row)1752 static void Grad_NewRow(GGadget *g,int row) {
1753 int rows;
1754 struct matrix_data *md = GMatrixEditGet(g, &rows);
1755 if ( md==NULL )
1756 return;
1757
1758 md[3*row+2].u.md_real = 1.0;
1759 }
1760
StopMatrixInit(struct matrixinit * mi,struct gradient * grad)1761 static void StopMatrixInit(struct matrixinit *mi,struct gradient *grad) {
1762 int i;
1763 struct matrix_data *md;
1764
1765 memset(mi,0,sizeof(*mi));
1766 mi->col_cnt = 3;
1767 mi->col_init = stopci;
1768
1769 if ( grad==NULL ) {
1770 md = calloc(2*mi->col_cnt,sizeof(struct matrix_data));
1771 md[3*0+0].u.md_real = 0;
1772 md[3*0+1].u.md_ival = 0x000000;
1773 md[3*0+2].u.md_real = 1;
1774 md[3*1+0].u.md_real = 100;
1775 md[3*1+1].u.md_ival = 0xffffff;
1776 md[3*1+2].u.md_real = 1;
1777 mi->initial_row_cnt = 2;
1778 } else {
1779 md = calloc(3*grad->stop_cnt,sizeof(struct matrix_data));
1780 for ( i=0; i<grad->stop_cnt; ++i ) {
1781 md[3*i+0].u.md_real = grad->grad_stops[i].offset*100.0;
1782 md[3*i+1].u.md_ival = grad->grad_stops[i].col;
1783 md[3*i+2].u.md_real = grad->grad_stops[i].opacity;
1784 }
1785 mi->initial_row_cnt = grad->stop_cnt;
1786 }
1787 mi->matrix_data = md;
1788
1789 mi->initrow = Grad_NewRow;
1790 mi->candelete = Grad_CanDelete;
1791 }
1792
GradientEdit(struct layer_dlg * ld,struct gradient * active)1793 static struct gradient *GradientEdit(struct layer_dlg *ld,struct gradient *active) {
1794 GradientDlg gdd;
1795 GRect pos;
1796 GWindow gw;
1797 GWindowAttrs wattrs;
1798 GGadgetCreateData gcd[14], boxes[5], *harray[8], *varray[10],
1799 *rharray[5], *gtarray[5];
1800 GTextInfo label[14];
1801 int j,k;
1802 struct matrixinit stopmi;
1803
1804 GDDInit( &gdd,ld->sf,ld->layer,active );
1805 gdd.active = active;
1806
1807 memset(&wattrs,0,sizeof(wattrs));
1808 wattrs.mask = wam_events|wam_cursor|wam_isdlg|wam_restrict|wam_undercursor|wam_utf8_wtitle;
1809 wattrs.is_dlg = true;
1810 wattrs.restrict_input_to_me = 1;
1811 wattrs.undercursor = 1;
1812 wattrs.event_masks = -1;
1813 wattrs.cursor = ct_pointer;
1814 wattrs.utf8_window_title = _("Gradient");
1815 pos.width = 600;
1816 pos.height = 300;
1817 gdd.gw = gw = GDrawCreateTopWindow(NULL,&pos,gdd_e_h,&gdd.cv_grad,&wattrs);
1818
1819 memset(&label,0,sizeof(label));
1820 memset(&gcd,0,sizeof(gcd));
1821 memset(&boxes,0,sizeof(boxes));
1822
1823 k = j = 0;
1824 gcd[k].gd.flags = gg_visible|gg_enabled ; /* This space is for the menubar */
1825 gcd[k].gd.pos.height = 18; gcd[k].gd.pos.width = 20;
1826 gcd[k++].creator = GSpacerCreate;
1827 varray[j++] = &gcd[k-1];
1828
1829 label[k].text = (unichar_t *) _(
1830 " A linear gradient is represented by a line drawn\n"
1831 "from its start point to its end point.\n"
1832 " A radial gradient is represented by a line drawn\n"
1833 "from its center whose length is the ultimate radius.\n"
1834 "If there is a single additional point, that point\n"
1835 "represents the gradient's focus, if omitted the focus\n"
1836 "is the same as the radius." );
1837 label[k].text_is_1byte = true;
1838 gcd[k].gd.label = &label[k];
1839 gcd[k].gd.flags = gg_enabled | gg_visible;
1840 gcd[k++].creator = GLabelCreate;
1841 varray[j++] = &gcd[k-1];
1842
1843 gcd[k].gd.flags = gg_visible | gg_enabled;
1844 label[k].text = (unichar_t *) _("Linear");
1845 label[k].text_is_1byte = true;
1846 label[k].text_in_resource = true;
1847 gcd[k].gd.label = &label[k];
1848 gcd[k].gd.popup_msg = _(
1849 "The gradient will be a linear gradient,\n"
1850 "With the color change happening along\n"
1851 "the line drawn in the view" );
1852 gcd[k].gd.cid = CID_Linear;
1853 gcd[k++].creator = GRadioCreate;
1854 gtarray[0] = &gcd[k-1];
1855
1856 gcd[k].gd.flags = gg_visible | gg_enabled;
1857 label[k].text = (unichar_t *) _("Radial");
1858 label[k].text_is_1byte = true;
1859 label[k].text_in_resource = true;
1860 gcd[k].gd.label = &label[k];
1861 gcd[k].gd.popup_msg = _(
1862 "The gradient will be a radial gradient,\n"
1863 "With the color change happening in circles\n"
1864 "starting at the focus (if specified) and\n"
1865 "extending outward until it reaches the\n"
1866 "specified radius." );
1867 gcd[k].gd.cid = CID_Radial;
1868 gcd[k++].creator = GRadioCreate;
1869 gtarray[1] = &gcd[k-1]; gtarray[2] = GCD_Glue; gtarray[3] = NULL;
1870
1871 boxes[4].gd.flags = gg_enabled|gg_visible;
1872 boxes[4].gd.u.boxelements = gtarray;
1873 boxes[4].creator = GHBoxCreate;
1874 varray[j++] = &boxes[4];
1875
1876 gcd[k].gd.pos.width = gcd[k].gd.pos.height = 200;
1877 gcd[k].gd.flags = gg_visible | gg_enabled;
1878 gcd[k].gd.cid = CID_Gradient;
1879 gcd[k].gd.u.drawable_e_h = gdd_sub_e_h;
1880 gcd[k++].creator = GDrawableCreate;
1881 varray[j++] = &gcd[k-1];
1882
1883 gcd[k].gd.flags = gg_visible | gg_enabled;
1884 label[k].text = (unichar_t *) _("_Pad");
1885 label[k].text_is_1byte = true;
1886 label[k].text_in_resource = true;
1887 gcd[k].gd.label = &label[k];
1888 gcd[k].gd.popup_msg = _("Beyond the endpoints, the gradient takes on the color at the end-points\n"
1889 "This does not work for PostScript linear gradients");
1890 gcd[k].gd.cid = CID_Pad;
1891 gcd[k++].creator = GRadioCreate;
1892 rharray[0] = &gcd[k-1];
1893
1894 gcd[k].gd.flags = gg_visible | gg_enabled;
1895 label[k].text = (unichar_t *) _("Repeat");
1896 label[k].text_is_1byte = true;
1897 label[k].text_in_resource = true;
1898 gcd[k].gd.label = &label[k];
1899 gcd[k].gd.popup_msg = _("Beyond the endpoints the gradient repeats itself\n"
1900 "This does not work for PostScript gradients." );
1901 gcd[k].gd.cid = CID_Repeat;
1902 gcd[k++].creator = GRadioCreate;
1903 rharray[1] = &gcd[k-1];
1904
1905 gcd[k].gd.flags = gg_visible | gg_enabled;
1906 label[k].text = (unichar_t *) _("Reflect");
1907 label[k].text_is_1byte = true;
1908 label[k].text_in_resource = true;
1909 gcd[k].gd.label = &label[k];
1910 gcd[k].gd.popup_msg = _("Beyond the endpoint the gradient repeats itself, but reflected.\n"
1911 "This does not work for PostScript gradients");
1912 gcd[k].gd.cid = CID_Reflect;
1913 gcd[k++].creator = GRadioCreate;
1914 rharray[2] = &gcd[k-1];
1915 rharray[3] = GCD_Glue; rharray[4] = NULL;
1916
1917 boxes[2].gd.flags = gg_enabled|gg_visible;
1918 boxes[2].gd.u.boxelements = rharray;
1919 boxes[2].creator = GHBoxCreate;
1920 varray[j++] = &boxes[2];
1921
1922 label[k].text = (unichar_t *) _(
1923 "Specify the color (& opacity) at stop points\n"
1924 "along the line drawn above. The offset is a\n"
1925 "percentage of the distance from the start to\n"
1926 "the end of the line. The color is a 6 (hex)\n"
1927 "digit number expressing an RGB color.");
1928 label[k].text_is_1byte = true;
1929 gcd[k].gd.label = &label[k];
1930 gcd[k].gd.flags = gg_enabled | gg_visible;
1931 gcd[k++].creator = GLabelCreate;
1932 varray[j++] = &gcd[k-1];
1933
1934 StopMatrixInit(&stopmi,active);
1935
1936 gcd[k].gd.pos.width = 300; gcd[k].gd.pos.height = 200;
1937 gcd[k].gd.flags = gg_enabled | gg_visible;
1938 gcd[k].gd.cid = CID_GradStops;
1939 gcd[k].gd.u.matrix = &stopmi;
1940 gcd[k++].creator = GMatrixEditCreate;
1941 varray[j++] = &gcd[k-1];
1942
1943 label[k].text = (unichar_t *) _("_OK");
1944 label[k].text_is_1byte = true;
1945 label[k].text_in_resource = true;
1946 gcd[k].gd.label = &label[k];
1947 gcd[k].gd.flags = gg_enabled|gg_visible|gg_but_default;
1948 gcd[k].gd.handle_controlevent = Gradient_OK;
1949 gcd[k++].creator = GButtonCreate;
1950
1951 label[k].text = (unichar_t *) _("_Cancel");
1952 label[k].text_is_1byte = true;
1953 label[k].text_in_resource = true;
1954 gcd[k].gd.label = &label[k];
1955 gcd[k].gd.flags = gg_enabled|gg_visible|gg_but_cancel;
1956 gcd[k].gd.handle_controlevent = Gradient_Cancel;
1957 gcd[k++].creator = GButtonCreate;
1958
1959 harray[0] = GCD_Glue; harray[1] = &gcd[k-2]; harray[2] = GCD_Glue;
1960 harray[3] = GCD_Glue; harray[4] = &gcd[k-1]; harray[5] = GCD_Glue;
1961 harray[6] = NULL;
1962
1963 boxes[3].gd.flags = gg_enabled|gg_visible;
1964 boxes[3].gd.u.boxelements = harray;
1965 boxes[3].creator = GHBoxCreate;
1966 varray[j++] = &boxes[3];
1967 varray[j] = NULL;
1968
1969 boxes[0].gd.flags = gg_enabled|gg_visible;
1970 boxes[0].gd.u.boxelements = varray;
1971 boxes[0].creator = GVBoxCreate;
1972
1973 GGadgetsCreate(gw,boxes);
1974
1975 GDDCharViewInits(&gdd,CID_Gradient);
1976
1977 GHVBoxSetExpandableRow(boxes[0].ret,3);
1978 GHVBoxSetExpandableCol(boxes[2].ret,gb_expandgluesame);
1979 GHVBoxSetExpandableRow(boxes[3].ret,gb_expandgluesame);
1980 GGadgetResize(boxes[0].ret,pos.width,pos.height);
1981
1982 if ( active!=NULL ) {
1983 GGadgetSetChecked(GWidgetGetControl(gw,CID_Linear),active->radius==0);
1984 GGadgetSetChecked(GWidgetGetControl(gw,CID_Radial),active->radius!=0);
1985 GGadgetSetChecked(GWidgetGetControl(gw,CID_Pad),active->sm==sm_pad);
1986 GGadgetSetChecked(GWidgetGetControl(gw,CID_Reflect),active->sm==sm_reflect);
1987 GGadgetSetChecked(GWidgetGetControl(gw,CID_Repeat),active->sm==sm_repeat);
1988 } else {
1989 GGadgetSetChecked(GWidgetGetControl(gw,CID_Linear),true);
1990 GGadgetSetChecked(GWidgetGetControl(gw,CID_Pad),true);
1991 }
1992
1993 GDDMakeActive(&gdd,&gdd.cv_grad);
1994
1995 GDrawResize(gw,400,768); /* Force a resize event */
1996
1997 GDrawSetVisible(gdd.gw,true);
1998
1999 while ( !gdd.done )
2000 GDrawProcessOneEvent(NULL);
2001
2002 {
2003 CharView *cv = &gdd.cv_grad;
2004 if ( cv->backimgs!=NULL ) {
2005 GDrawDestroyWindow(cv->backimgs);
2006 cv->backimgs = NULL;
2007 }
2008 CVPalettesHideIfMine(cv);
2009 }
2010 GDrawDestroyWindow(gdd.gw);
2011 /* Now because the cv of the nested window is on the stack, we need to */
2012 /* handle its destruction HERE while that stack location still makes */
2013 /* sense. Can't do it in whoever calls us */
2014 GDrawSync(NULL);
2015 GDrawProcessPendingEvents(NULL);
2016 GDrawSync(NULL);
2017 GDrawProcessPendingEvents(NULL);
2018 return( gdd.active );
2019 }
2020
Layer_GradSet(struct layer_dlg * ld)2021 static void Layer_GradSet(struct layer_dlg *ld) {
2022 GGadgetSetEnabled(GWidgetGetControl(ld->gw,CID_FillGradAdd),ld->fillgrad==NULL);
2023 GGadgetSetEnabled(GWidgetGetControl(ld->gw,CID_FillGradEdit),ld->fillgrad!=NULL);
2024 GGadgetSetEnabled(GWidgetGetControl(ld->gw,CID_FillGradDelete),ld->fillgrad!=NULL);
2025 GGadgetSetEnabled(GWidgetGetControl(ld->gw,CID_StrokeGradAdd),ld->strokegrad==NULL);
2026 GGadgetSetEnabled(GWidgetGetControl(ld->gw,CID_StrokeGradEdit),ld->strokegrad!=NULL);
2027 GGadgetSetEnabled(GWidgetGetControl(ld->gw,CID_StrokeGradDelete),ld->strokegrad!=NULL);
2028 }
2029
Layer_FillGradDelete(GGadget * g,GEvent * e)2030 static int Layer_FillGradDelete(GGadget *g, GEvent *e) {
2031
2032 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
2033 struct layer_dlg *ld = GDrawGetUserData(GGadgetGetWindow(g));
2034 GradientFree(ld->fillgrad);
2035 ld->fillgrad=NULL;
2036 Layer_GradSet(ld);
2037 }
2038 return( true );
2039 }
2040
Layer_FillGradAddEdit(GGadget * g,GEvent * e)2041 static int Layer_FillGradAddEdit(GGadget *g, GEvent *e) {
2042
2043 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
2044 struct layer_dlg *ld = GDrawGetUserData(GGadgetGetWindow(g));
2045 ld->fillgrad = GradientEdit(ld,ld->fillgrad);
2046 Layer_GradSet(ld);
2047 }
2048 return( true );
2049 }
2050
Layer_StrokeGradDelete(GGadget * g,GEvent * e)2051 static int Layer_StrokeGradDelete(GGadget *g, GEvent *e) {
2052
2053 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
2054 struct layer_dlg *ld = GDrawGetUserData(GGadgetGetWindow(g));
2055 GradientFree(ld->strokegrad);
2056 ld->strokegrad=NULL;
2057 Layer_GradSet(ld);
2058 }
2059 return( true );
2060 }
2061
Layer_StrokeGradAddEdit(GGadget * g,GEvent * e)2062 static int Layer_StrokeGradAddEdit(GGadget *g, GEvent *e) {
2063
2064 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
2065 struct layer_dlg *ld = GDrawGetUserData(GGadgetGetWindow(g));
2066 ld->strokegrad = GradientEdit(ld,ld->strokegrad);
2067 Layer_GradSet(ld);
2068 }
2069 return( true );
2070 }
2071
2072 #define CID_PatternName 1001
2073 #define CID_Skew 1002
2074 #define CID_Rotate 1003
2075 #define CID_TransX 1004
2076 #define CID_TransY 1005
2077 #define CID_Transform 1006
2078 #define CID_Aspect 1007
2079 #define CID_TWidth 1008
2080 #define CID_THeight 1009
2081
Pat_WidthChanged(GGadget * g,GEvent * e)2082 static int Pat_WidthChanged(GGadget *g, GEvent *e) {
2083
2084 if ( e->type==et_controlevent &&
2085 (e->u.control.subtype == et_textchanged ||
2086 e->u.control.subtype == et_radiochanged)) {
2087 GWindow gw = GGadgetGetWindow(g);
2088 struct layer_dlg *ld = GDrawGetUserData(gw);
2089 char *name = GGadgetGetTitle8(GWidgetGetControl(gw,CID_PatternName));
2090 SplineChar *patternsc = SFGetChar(ld->sf,-1,name);
2091 DBounds b;
2092 int err = false;
2093 real height, width;
2094 char buffer[50];
2095
2096 free(name);
2097 if ( patternsc==NULL )
2098 return( true );
2099 if ( !GGadgetIsChecked(GWidgetGetControl(gw,CID_Aspect)))
2100 return( true );
2101 width = GetCalmReal8(gw,CID_TWidth,_("Width"),&err);
2102 if ( err )
2103 return( true );
2104 PatternSCBounds(patternsc,&b);
2105 height = width * (b.maxy - b.miny)/(b.maxx - b.minx);
2106 sprintf( buffer, "%g", (double) height );
2107 GGadgetSetTitle8(GWidgetGetControl(gw,CID_THeight), buffer);
2108 }
2109 return( true );
2110 }
2111
Pat_HeightChanged(GGadget * g,GEvent * e)2112 static int Pat_HeightChanged(GGadget *g, GEvent *e) {
2113
2114 if ( e->type==et_controlevent && e->u.control.subtype == et_textchanged ) {
2115 GWindow gw = GGadgetGetWindow(g);
2116 struct layer_dlg *ld = GDrawGetUserData(gw);
2117 char *name = GGadgetGetTitle8(GWidgetGetControl(gw,CID_PatternName));
2118 SplineChar *patternsc = SFGetChar(ld->sf,-1,name);
2119 DBounds b;
2120 int err = false;
2121 real height, width;
2122 char buffer[50];
2123
2124 free(name);
2125 if ( patternsc==NULL )
2126 return( true );
2127 if ( !GGadgetIsChecked(GWidgetGetControl(gw,CID_Aspect)))
2128 return( true );
2129 height = GetCalmReal8(gw,CID_THeight,_("Height"),&err);
2130 if ( err )
2131 return( true );
2132 PatternSCBounds(patternsc,&b);
2133 width = height * (b.maxx - b.minx)/(b.maxy - b.miny);
2134 sprintf( buffer, "%g", (double) width );
2135 GGadgetSetTitle8(GWidgetGetControl(gw,CID_TWidth), buffer);
2136 }
2137 return( true );
2138 }
2139
Pat_TransformChanged(GGadget * g,GEvent * e)2140 static int Pat_TransformChanged(GGadget *g, GEvent *e) {
2141
2142 if ( e==NULL ||
2143 (e->type==et_controlevent && e->u.control.subtype == et_textchanged )) {
2144 GWindow gw = GGadgetGetWindow(g);
2145 double trans[6];
2146 char *name = GGadgetGetTitle8(g);
2147 double c, s, t;
2148 char buffer[50];
2149
2150 if ( sscanf( name, "[%lg %lg %lg %lg %lg %lg]", &trans[0], &trans[1], &trans[2],
2151 &trans[3], &trans[4], &trans[5])!=6 ) {
2152 free(name );
2153 return( true );
2154 }
2155 free(name );
2156
2157 c = trans[0]; s = trans[1];
2158 if ( c!=0 )
2159 t = (trans[2]+s)/c;
2160 else if ( s!=0 )
2161 t = (trans[3]-c)/s;
2162 else
2163 t = 9999;
2164 if ( RealWithin(c*c+s*s,1,.005) && RealWithin(t*c-s,trans[2],.01) && RealWithin(t*s+c,trans[3],.01)) {
2165 double skew = atan(t)*180/FF_PI;
2166 double rot = atan2(s,c)*180/FF_PI;
2167 sprintf( buffer, "%g", skew );
2168 GGadgetSetTitle8(GWidgetGetControl(gw,CID_Skew), buffer);
2169 sprintf( buffer, "%g", rot );
2170 GGadgetSetTitle8(GWidgetGetControl(gw,CID_Rotate), buffer);
2171 sprintf( buffer, "%g", trans[4] );
2172 GGadgetSetTitle8(GWidgetGetControl(gw,CID_TransX), buffer);
2173 sprintf( buffer, "%g", trans[5] );
2174 GGadgetSetTitle8(GWidgetGetControl(gw,CID_TransY), buffer);
2175 } else {
2176 GGadgetSetTitle8(GWidgetGetControl(gw,CID_Skew), "");
2177 GGadgetSetTitle8(GWidgetGetControl(gw,CID_Rotate), "");
2178 GGadgetSetTitle8(GWidgetGetControl(gw,CID_TransX), "");
2179 GGadgetSetTitle8(GWidgetGetControl(gw,CID_TransY), "");
2180 }
2181 }
2182 return( true );
2183 }
2184
Pat_AnglesChanged(GGadget * g,GEvent * e)2185 static int Pat_AnglesChanged(GGadget *g, GEvent *e) {
2186
2187 if ( e==NULL ||
2188 (e->type==et_controlevent && e->u.control.subtype == et_textchanged )) {
2189 GWindow gw = GGadgetGetWindow(g);
2190 double rotate, skew, x, y;
2191 double c, s, t;
2192 char buffer[340];
2193 int err=false;
2194
2195 skew = GetCalmReal8(gw,CID_Skew,_("Skew"),&err)*FF_PI/180;
2196 rotate = GetCalmReal8(gw,CID_Rotate,_("Rotate"),&err)*FF_PI/180;
2197 x = GetCalmReal8(gw,CID_TransX,_("Translation in X"),&err);
2198 y = GetCalmReal8(gw,CID_TransY,_("Translation in Y"),&err);
2199 if ( err )
2200 return( true );
2201 t = tan(skew);
2202 c = cos(rotate); s = sin(rotate);
2203 sprintf( buffer, "[%g %g %g %g %g %g]", c, s, t*c-s, t*s+c, x, y );
2204 GGadgetSetTitle8(GWidgetGetControl(gw,CID_Transform),buffer );
2205 }
2206 return( true );
2207 }
2208
Pat_GlyphNameCompletion(GGadget * t,int from_tab)2209 static unichar_t **Pat_GlyphNameCompletion(GGadget *t,int from_tab) {
2210 struct layer_dlg *ld = GDrawGetUserData(GGadgetGetWindow(t));
2211
2212 return( SFGlyphNameCompletion(ld->sf,t,from_tab,false));
2213 }
2214
Pat_OK(GGadget * g,GEvent * e)2215 static int Pat_OK(GGadget *g, GEvent *e) {
2216 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
2217 GWindow gw = GGadgetGetWindow(g);
2218 struct layer_dlg *ld = GDrawGetUserData(gw);
2219 char *transstring = GGadgetGetTitle8(GWidgetGetControl(gw,CID_Transform));
2220 char *name;
2221 double width, height;
2222 double trans[6];
2223 int i;
2224 SplineChar *patternsc;
2225 int err;
2226
2227 if ( sscanf( transstring, "[%lg %lg %lg %lg %lg %lg]", &trans[0], &trans[1], &trans[2],
2228 &trans[3], &trans[4], &trans[5])!=6 ) {
2229 free( transstring );
2230 ff_post_error(_("Bad Transformation matrix"),_("Bad Transformation matrix"));
2231 return( true );
2232 }
2233 free(transstring);
2234
2235 name = GGadgetGetTitle8(GWidgetGetControl(gw,CID_PatternName));
2236 patternsc = SFGetChar(ld->sf,-1,name);
2237 if ( patternsc==NULL ) {
2238 ff_post_error(_("No Glyph"),_("This font does not contain a glyph named \"%.40s\""), name);
2239 free(name);
2240 return( true );
2241 }
2242
2243 err = false;
2244 width = GetReal8(gw,CID_TWidth,_("Width"),&err);
2245 height = GetReal8(gw,CID_THeight,_("Height"),&err);
2246 if ( err )
2247 return( true );
2248
2249 if ( ld->curpat == NULL )
2250 ld->curpat = chunkalloc(sizeof(struct pattern));
2251 free( ld->curpat->pattern );
2252 ld->curpat->pattern = name;
2253 for ( i=0; i<6; ++i )
2254 ld->curpat->transform[i] = trans[i];
2255 ld->curpat->width = width;
2256 ld->curpat->height = height;
2257 ld->pat_done = true;
2258 }
2259 return( true );
2260 }
2261
Pat_Cancel(GGadget * g,GEvent * e)2262 static int Pat_Cancel(GGadget *g, GEvent *e) {
2263 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
2264 GWindow gw = GGadgetGetWindow(g);
2265 struct layer_dlg *ld = GDrawGetUserData(gw);
2266 ld->pat_done = true;
2267 }
2268 return( true );
2269 }
2270
pat_e_h(GWindow gw,GEvent * event)2271 static int pat_e_h(GWindow gw, GEvent *event) {
2272 struct layer_dlg *ld = GDrawGetUserData(gw);
2273
2274 switch ( event->type ) {
2275 case et_char:
2276 return( false );
2277 break;
2278 case et_close:
2279 ld->pat_done = true;
2280 break;
2281 }
2282 return( true );
2283 }
2284
PatternEdit(struct layer_dlg * ld,struct pattern * active)2285 static struct pattern *PatternEdit(struct layer_dlg *ld,struct pattern *active) {
2286 GRect pos;
2287 GWindow gw;
2288 GWindowAttrs wattrs;
2289 GGadgetCreateData gcd[25], boxes[5], *harray[8], *varray[10],
2290 *hvarray[42];
2291 GTextInfo label[25];
2292 int j,k;
2293 char *name;
2294 char width[50], height[50], transform[340];
2295 int aspect_fixed = true;
2296
2297 ld->pat_done = false;
2298 ld->curpat = active;
2299
2300 name = "";
2301 width[0] = height[0] = '\0';
2302 strcpy(transform,"[1 0 0 1 0 0]");
2303 aspect_fixed = true;
2304 if ( active!=NULL ) {
2305 SplineChar *patternsc = SFGetChar(ld->sf,-1,active->pattern);
2306 name = active->pattern;
2307 sprintf( width, "%g", (double) active->width );
2308 sprintf( height, "%g", (double) active->height );
2309 sprintf( transform, "[%g %g %g %g %g %g]",
2310 (double) active->transform[0], (double) active->transform[1],
2311 (double) active->transform[2], (double) active->transform[3],
2312 (double) active->transform[4], (double) active->transform[5]);
2313 if ( patternsc!=NULL ) {
2314 DBounds b;
2315 PatternSCBounds(patternsc,&b);
2316 aspect_fixed = RealNear(active->width*(b.maxy-b.miny),active->height*(b.maxx-b.minx));
2317 }
2318 }
2319
2320 memset(&wattrs,0,sizeof(wattrs));
2321 wattrs.mask = wam_events|wam_cursor|wam_isdlg|wam_restrict|wam_undercursor|wam_utf8_wtitle;
2322 wattrs.is_dlg = true;
2323 wattrs.restrict_input_to_me = 1;
2324 wattrs.undercursor = 1;
2325 wattrs.event_masks = -1;
2326 wattrs.cursor = ct_pointer;
2327 wattrs.utf8_window_title = _("Tile Pattern");
2328 pos.width = 600;
2329 pos.height = 300;
2330 gw = GDrawCreateTopWindow(NULL,&pos,pat_e_h,ld,&wattrs);
2331
2332 memset(&label,0,sizeof(label));
2333 memset(&gcd,0,sizeof(gcd));
2334 memset(&boxes,0,sizeof(boxes));
2335
2336 k = j = 0;
2337
2338 label[k].text = (unichar_t *) _(
2339 "The pattern itself should be drawn in another glyph\n"
2340 "of the current font. Specify a glyph name:");
2341 label[k].text_is_1byte = true;
2342 gcd[k].gd.label = &label[k];
2343 gcd[k].gd.flags = gg_enabled | gg_visible;
2344 gcd[k++].creator = GLabelCreate;
2345 varray[j++] = &gcd[k-1];
2346
2347 label[k].text = (unichar_t *) name;
2348 label[k].text_is_1byte = true;
2349 gcd[k].gd.label = &label[k];
2350 gcd[k].gd.flags = gg_enabled|gg_visible;
2351 gcd[k].gd.handle_controlevent = Pat_WidthChanged; /* That will make sure the aspect ratio stays correct */
2352 gcd[k].gd.cid = CID_PatternName;
2353 gcd[k++].creator = GTextCompletionCreate;
2354 varray[j++] = &gcd[k-1];
2355
2356 gcd[k].gd.flags = gg_visible | gg_enabled;
2357 if ( aspect_fixed )
2358 gcd[k].gd.flags |= gg_cb_on;
2359 label[k].text = (unichar_t *) _("Aspect Ratio same as Tile Glyph");
2360 label[k].text_is_1byte = true;
2361 label[k].text_in_resource = true;
2362 gcd[k].gd.label = &label[k];
2363 gcd[k].gd.cid = CID_Aspect;
2364 gcd[k].gd.handle_controlevent = Pat_WidthChanged; /* That will make sure the aspect ratio stays correct */
2365 gcd[k++].creator = GCheckBoxCreate;
2366 varray[j++] = &gcd[k-1];
2367
2368 label[k].text = (unichar_t *) _("Width:");
2369 label[k].text_is_1byte = true;
2370 gcd[k].gd.label = &label[k];
2371 gcd[k].gd.flags = gg_enabled | gg_visible;
2372 gcd[k++].creator = GLabelCreate;
2373 hvarray[0] = &gcd[k-1];
2374
2375 label[k].text = (unichar_t *) width;
2376 label[k].text_is_1byte = true;
2377 gcd[k].gd.label = &label[k];
2378 gcd[k].gd.flags = gg_enabled|gg_visible;
2379 gcd[k].gd.handle_controlevent = Pat_WidthChanged;
2380 gcd[k].gd.cid = CID_TWidth;
2381 gcd[k++].creator = GTextFieldCreate;
2382 hvarray[1] = &gcd[k-1]; hvarray[2] = GCD_Glue; hvarray[3] = NULL;
2383
2384 label[k].text = (unichar_t *) _("Height:");
2385 label[k].text_is_1byte = true;
2386 gcd[k].gd.label = &label[k];
2387 gcd[k].gd.flags = gg_enabled | gg_visible;
2388 gcd[k++].creator = GLabelCreate;
2389 hvarray[4] = &gcd[k-1];
2390
2391 label[k].text = (unichar_t *) height;
2392 label[k].text_is_1byte = true;
2393 gcd[k].gd.label = &label[k];
2394 gcd[k].gd.flags = gg_enabled|gg_visible;
2395 gcd[k].gd.handle_controlevent = Pat_HeightChanged;
2396 gcd[k].gd.cid = CID_THeight;
2397 gcd[k++].creator = GTextFieldCreate;
2398 hvarray[5] = &gcd[k-1]; hvarray[6] = GCD_Glue; hvarray[7] = NULL;
2399
2400 gcd[k].gd.flags = gg_enabled | gg_visible;
2401 gcd[k++].creator = GLineCreate;
2402 hvarray[8] = &gcd[k-1];
2403 hvarray[9] = GCD_ColSpan; hvarray[10] = GCD_Glue; hvarray[11] = NULL;
2404
2405 label[k].text = (unichar_t *) _("Rotate:");
2406 label[k].text_is_1byte = true;
2407 gcd[k].gd.label = &label[k];
2408 gcd[k].gd.flags = gg_enabled | gg_visible;
2409 gcd[k++].creator = GLabelCreate;
2410 hvarray[12] = &gcd[k-1];
2411
2412 gcd[k].gd.flags = gg_enabled|gg_visible;
2413 gcd[k].gd.handle_controlevent = Pat_AnglesChanged;
2414 gcd[k].gd.cid = CID_Rotate;
2415 gcd[k++].creator = GTextFieldCreate;
2416 hvarray[13] = &gcd[k-1]; hvarray[14] = GCD_Glue; hvarray[15] = NULL;
2417
2418 label[k].text = (unichar_t *) _("Skew:");
2419 label[k].text_is_1byte = true;
2420 gcd[k].gd.label = &label[k];
2421 gcd[k].gd.flags = gg_enabled | gg_visible;
2422 gcd[k++].creator = GLabelCreate;
2423 hvarray[16] = &gcd[k-1];
2424
2425 gcd[k].gd.flags = gg_enabled|gg_visible;
2426 gcd[k].gd.handle_controlevent = Pat_AnglesChanged;
2427 gcd[k].gd.cid = CID_Skew;
2428 gcd[k++].creator = GTextFieldCreate;
2429 hvarray[17] = &gcd[k-1]; hvarray[18] = GCD_Glue; hvarray[19] = NULL;
2430
2431 label[k].text = (unichar_t *) _("Translate By");
2432 label[k].text_is_1byte = true;
2433 gcd[k].gd.label = &label[k];
2434 gcd[k].gd.flags = gg_enabled | gg_visible;
2435 gcd[k++].creator = GLabelCreate;
2436 hvarray[20] = &gcd[k-1];
2437 hvarray[21] = GCD_ColSpan; hvarray[22] = GCD_Glue; hvarray[23] = NULL;
2438
2439 label[k].text = (unichar_t *) _("X:");
2440 label[k].text_is_1byte = true;
2441 gcd[k].gd.label = &label[k];
2442 gcd[k].gd.flags = gg_enabled | gg_visible;
2443 gcd[k++].creator = GLabelCreate;
2444 hvarray[24] = &gcd[k-1];
2445
2446 gcd[k].gd.flags = gg_enabled|gg_visible;
2447 gcd[k].gd.handle_controlevent = Pat_AnglesChanged;
2448 gcd[k].gd.cid = CID_TransX;
2449 gcd[k++].creator = GTextFieldCreate;
2450 hvarray[25] = &gcd[k-1]; hvarray[26] = GCD_Glue; hvarray[27] = NULL;
2451
2452 label[k].text = (unichar_t *) _("Y:");
2453 label[k].text_is_1byte = true;
2454 gcd[k].gd.label = &label[k];
2455 gcd[k].gd.flags = gg_enabled | gg_visible;
2456 gcd[k++].creator = GLabelCreate;
2457 hvarray[28] = &gcd[k-1];
2458
2459 gcd[k].gd.flags = gg_enabled|gg_visible;
2460 gcd[k].gd.handle_controlevent = Pat_AnglesChanged;
2461 gcd[k].gd.cid = CID_TransY;
2462 gcd[k++].creator = GTextFieldCreate;
2463 hvarray[29] = &gcd[k-1]; hvarray[30] = GCD_Glue; hvarray[31] = NULL;
2464
2465 gcd[k].gd.flags = gg_enabled | gg_visible;
2466 gcd[k++].creator = GLineCreate;
2467 hvarray[32] = &gcd[k-1];
2468 hvarray[33] = GCD_ColSpan; hvarray[34] = GCD_Glue; hvarray[35] = NULL;
2469
2470 label[k].text = (unichar_t *) _("Transform:");
2471 label[k].text_is_1byte = true;
2472 gcd[k].gd.label = &label[k];
2473 gcd[k].gd.flags = gg_enabled | gg_visible;
2474 gcd[k++].creator = GLabelCreate;
2475 hvarray[36] = &gcd[k-1];
2476
2477 label[k].text = (unichar_t *) transform;
2478 label[k].text_is_1byte = true;
2479 gcd[k].gd.label = &label[k];
2480 gcd[k].gd.flags = gg_enabled|gg_visible;
2481 gcd[k].gd.handle_controlevent = Pat_TransformChanged;
2482 gcd[k].gd.cid = CID_Transform;
2483 gcd[k++].creator = GTextFieldCreate;
2484 hvarray[37] = &gcd[k-1]; hvarray[38] = GCD_ColSpan; hvarray[39] = NULL;
2485 hvarray[40] = NULL;
2486
2487 boxes[2].gd.flags = gg_enabled|gg_visible;
2488 boxes[2].gd.u.boxelements = hvarray;
2489 boxes[2].creator = GHVBoxCreate;
2490 varray[j++] = &boxes[2];
2491
2492 label[k].text = (unichar_t *) _("_OK");
2493 label[k].text_is_1byte = true;
2494 label[k].text_in_resource = true;
2495 gcd[k].gd.label = &label[k];
2496 gcd[k].gd.flags = gg_enabled|gg_visible|gg_but_default;
2497 gcd[k].gd.handle_controlevent = Pat_OK;
2498 gcd[k++].creator = GButtonCreate;
2499
2500 label[k].text = (unichar_t *) _("_Cancel");
2501 label[k].text_is_1byte = true;
2502 label[k].text_in_resource = true;
2503 gcd[k].gd.label = &label[k];
2504 gcd[k].gd.flags = gg_enabled|gg_visible|gg_but_cancel;
2505 gcd[k].gd.handle_controlevent = Pat_Cancel;
2506 gcd[k++].creator = GButtonCreate;
2507
2508 harray[0] = GCD_Glue; harray[1] = &gcd[k-2]; harray[2] = GCD_Glue;
2509 harray[3] = GCD_Glue; harray[4] = &gcd[k-1]; harray[5] = GCD_Glue;
2510 harray[6] = NULL;
2511
2512 boxes[3].gd.flags = gg_enabled|gg_visible;
2513 boxes[3].gd.u.boxelements = harray;
2514 boxes[3].creator = GHBoxCreate;
2515 varray[j++] = &boxes[3];
2516 varray[j++] = GCD_Glue;
2517 varray[j] = NULL;
2518
2519 boxes[0].gd.flags = gg_enabled|gg_visible;
2520 boxes[0].gd.u.boxelements = varray;
2521 boxes[0].creator = GVBoxCreate;
2522
2523 GGadgetsCreate(gw,boxes);
2524
2525 GHVBoxSetExpandableRow(boxes[0].ret,gb_expandglue);
2526 GHVBoxSetExpandableCol(boxes[2].ret,2);
2527 GHVBoxSetExpandableRow(boxes[3].ret,gb_expandgluesame);
2528 GHVBoxFitWindow(boxes[0].ret);
2529
2530
2531 Pat_TransformChanged(GWidgetGetControl(gw,CID_Transform),NULL);
2532 GCompletionFieldSetCompletion(gcd[1].ret,Pat_GlyphNameCompletion);
2533
2534 GDrawSetVisible(gw,true);
2535
2536 while ( !ld->pat_done )
2537 GDrawProcessOneEvent(NULL);
2538
2539 GDrawDestroyWindow(gw);
2540 return( ld->curpat );
2541 }
2542
Layer_PatSet(struct layer_dlg * ld)2543 static void Layer_PatSet(struct layer_dlg *ld) {
2544 GGadgetSetEnabled(GWidgetGetControl(ld->gw,CID_FillPatAdd),ld->fillpat==NULL);
2545 GGadgetSetEnabled(GWidgetGetControl(ld->gw,CID_FillPatEdit),ld->fillpat!=NULL);
2546 GGadgetSetEnabled(GWidgetGetControl(ld->gw,CID_FillPatDelete),ld->fillpat!=NULL);
2547 GGadgetSetEnabled(GWidgetGetControl(ld->gw,CID_StrokePatAdd),ld->strokepat==NULL);
2548 GGadgetSetEnabled(GWidgetGetControl(ld->gw,CID_StrokePatEdit),ld->strokepat!=NULL);
2549 GGadgetSetEnabled(GWidgetGetControl(ld->gw,CID_StrokePatDelete),ld->strokepat!=NULL);
2550 }
2551
Layer_FillPatDelete(GGadget * g,GEvent * e)2552 static int Layer_FillPatDelete(GGadget *g, GEvent *e) {
2553
2554 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
2555 struct layer_dlg *ld = GDrawGetUserData(GGadgetGetWindow(g));
2556 PatternFree(ld->fillpat);
2557 ld->fillpat=NULL;
2558 Layer_PatSet(ld);
2559 }
2560 return( true );
2561 }
2562
Layer_FillPatAddEdit(GGadget * g,GEvent * e)2563 static int Layer_FillPatAddEdit(GGadget *g, GEvent *e) {
2564
2565 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
2566 struct layer_dlg *ld = GDrawGetUserData(GGadgetGetWindow(g));
2567 ld->fillpat = PatternEdit(ld,ld->fillpat);
2568 Layer_PatSet(ld);
2569 }
2570 return( true );
2571 }
2572
Layer_StrokePatDelete(GGadget * g,GEvent * e)2573 static int Layer_StrokePatDelete(GGadget *g, GEvent *e) {
2574
2575 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
2576 struct layer_dlg *ld = GDrawGetUserData(GGadgetGetWindow(g));
2577 PatternFree(ld->strokepat);
2578 ld->strokepat=NULL;
2579 Layer_PatSet(ld);
2580 }
2581 return( true );
2582 }
2583
Layer_StrokePatAddEdit(GGadget * g,GEvent * e)2584 static int Layer_StrokePatAddEdit(GGadget *g, GEvent *e) {
2585
2586 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
2587 struct layer_dlg *ld = GDrawGetUserData(GGadgetGetWindow(g));
2588 ld->strokepat = PatternEdit(ld,ld->strokepat);
2589 Layer_PatSet(ld);
2590 }
2591 return( true );
2592 }
2593
getcol(GGadget * g,int * err)2594 static uint32 getcol(GGadget *g,int *err) {
2595 const unichar_t *ret=_GGadgetGetTitle(g);
2596 unichar_t *end;
2597 uint32 col = COLOR_INHERITED;
2598
2599 if ( *ret=='#' ) ++ret;
2600 col = u_strtol(ret,&end,16);
2601 if ( col<0 || col>0xffffff || *end!='\0' ) {
2602 *err = true;
2603 ff_post_error(_("Bad Color"),_("Bad Color"));
2604 }
2605 return( col );
2606 }
2607
Layer_OK(GGadget * g,GEvent * e)2608 static int Layer_OK(GGadget *g, GEvent *e) {
2609
2610 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
2611 GWindow gw = GGadgetGetWindow(g);
2612 struct layer_dlg *ld = GDrawGetUserData(GGadgetGetWindow(g));
2613 Layer temp;
2614 int err=false;
2615 const unichar_t *ret;
2616 unichar_t *end, *end2;
2617 int i;
2618
2619 LayerDefault(&temp);
2620 temp.dofill = GGadgetIsChecked(GWidgetGetControl(gw,CID_Fill));
2621 temp.dostroke = GGadgetIsChecked(GWidgetGetControl(gw,CID_Stroke));
2622 if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_FillCInherit)) )
2623 temp.fill_brush.col = COLOR_INHERITED;
2624 else
2625 temp.fill_brush.col = getcol(GWidgetGetControl(gw,CID_FillColor),&err);
2626 if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_FillOInherit)) )
2627 temp.fill_brush.opacity = -1;
2628 else
2629 temp.fill_brush.opacity = GetReal8(gw,CID_FillOpacity,_("Opacity:"),&err);
2630
2631 if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_StrokeCInherit)) )
2632 temp.stroke_pen.brush.col = COLOR_INHERITED;
2633 else
2634 temp.stroke_pen.brush.col = getcol(GWidgetGetControl(gw,CID_StrokeColor),&err);
2635 if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_StrokeOInherit)) )
2636 temp.stroke_pen.brush.opacity = -1;
2637 else
2638 temp.stroke_pen.brush.opacity = GetReal8(gw,CID_StrokeOpacity,_("Opacity:"),&err);
2639 if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_StrokeWInherit)) )
2640 temp.stroke_pen.width = WIDTH_INHERITED;
2641 else
2642 temp.stroke_pen.width = GetReal8(gw,CID_Width,_("_Width"),&err);
2643 if ( err )
2644 return( true );
2645
2646 ret = _GGadgetGetTitle(GWidgetGetControl(gw,CID_Trans));
2647 while ( *ret==' ' || *ret=='[' ) ++ret;
2648 temp.stroke_pen.trans[0] = u_strtod(ret,&end);
2649 temp.stroke_pen.trans[1] = u_strtod(end,&end);
2650 temp.stroke_pen.trans[2] = u_strtod(end,&end);
2651 temp.stroke_pen.trans[3] = u_strtod(end,&end2);
2652 for ( ret = end2 ; *ret==' ' || *ret==']' ; ++ret );
2653 if ( end2==end || *ret!='\0' || temp.stroke_pen.trans[0] ==0 || temp.stroke_pen.trans[3]==0 ) {
2654 ff_post_error(_("Bad Transformation Matrix"),_("Bad Transformation Matrix"));
2655 return( true );
2656 }
2657 if ( GGadgetIsChecked(GWidgetGetControl(gw,CID_DashesInherit)) ) {
2658 temp.stroke_pen.dashes[0] = 0; temp.stroke_pen.dashes[1] = DASH_INHERITED;
2659 } else {
2660 ret = _GGadgetGetTitle(GWidgetGetControl(gw,CID_Dashes));
2661 while ( *ret==' ' || *ret=='[' ) ++ret;
2662 for ( i=0; ; ++i ) {
2663 long val = u_strtol(ret,&end,10);
2664 if ( *end=='\0' )
2665 break;
2666 if ( val<0 || val>255 ) {
2667 ff_post_error(_("Bad dash list"),_("Value out of range"));
2668 return( true );
2669 } else if ( *end!=' ' ) {
2670 ff_post_error(_("Bad dash list"),_("Bad Number"));
2671 return( true );
2672 } else if ( i>=DASH_MAX ) {
2673 ff_post_error(_("Bad dash list"),_("Too many dashes (at most %d allowed)"), DASH_MAX);
2674 return( true );
2675 }
2676 temp.stroke_pen.dashes[i] = val;
2677 ret = end;
2678 while ( *ret==' ' ) ++ret;
2679 }
2680 if ( i<DASH_MAX ) temp.stroke_pen.dashes[i] = 0;
2681 }
2682 temp.stroke_pen.linecap =
2683 GGadgetIsChecked(GWidgetGetControl(gw,CID_ButtCap))?lc_butt:
2684 GGadgetIsChecked(GWidgetGetControl(gw,CID_RoundCap))?lc_round:
2685 GGadgetIsChecked(GWidgetGetControl(gw,CID_SquareCap))?lc_square:
2686 lc_inherited;
2687 temp.stroke_pen.linejoin =
2688 GGadgetIsChecked(GWidgetGetControl(gw,CID_BevelJoin))?lj_bevel:
2689 GGadgetIsChecked(GWidgetGetControl(gw,CID_RoundJoin))?lj_round:
2690 GGadgetIsChecked(GWidgetGetControl(gw,CID_MiterJoin))?lj_miter:
2691 lj_inherited;
2692
2693 GradientFree(ld->layer->fill_brush.gradient);
2694 PatternFree(ld->layer->fill_brush.pattern);
2695 GradientFree(ld->layer->stroke_pen.brush.gradient);
2696 PatternFree(ld->layer->stroke_pen.brush.pattern);
2697
2698 ld->done = ld->ok = true;
2699 ld->layer->stroke_pen = temp.stroke_pen;
2700 ld->layer->fill_brush = temp.fill_brush;
2701 ld->layer->dofill = temp.dofill;
2702 ld->layer->dostroke = temp.dostroke;
2703 ld->layer->fillfirst = temp.fillfirst;
2704
2705 ld->layer->fill_brush.gradient = ld->fillgrad;
2706 ld->layer->stroke_pen.brush.gradient = ld->strokegrad;
2707 ld->layer->fill_brush.pattern = ld->fillpat;
2708 ld->layer->stroke_pen.brush.pattern = ld->strokepat;
2709 }
2710 return( true );
2711 }
2712
Layer_Cancel(GGadget * g,GEvent * e)2713 static int Layer_Cancel(GGadget *g, GEvent *e) {
2714 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
2715 struct layer_dlg *ld = GDrawGetUserData(GGadgetGetWindow(g));
2716 ld->done = true;
2717 }
2718 return( true );
2719 }
2720
Layer_Inherit(GGadget * g,GEvent * e)2721 static int Layer_Inherit(GGadget *g, GEvent *e) {
2722 if ( e->type==et_controlevent && e->u.control.subtype == et_radiochanged ) {
2723 GWindow gw = GGadgetGetWindow(g);
2724 int cid = (intpt) GGadgetGetUserData(g);
2725 GGadgetSetEnabled(GWidgetGetControl(gw,cid),
2726 !GGadgetIsChecked(g));
2727 }
2728 return( true );
2729 }
2730
Layer_DoColorWheel(GGadget * g,GEvent * e)2731 static int Layer_DoColorWheel(GGadget *g, GEvent *e) {
2732 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
2733 GWindow gw = GGadgetGetWindow(g);
2734 int cid = (intpt) GGadgetGetUserData(g);
2735 GGadget *tf = GWidgetGetControl(gw,cid);
2736 if ( GGadgetIsEnabled(tf)) {
2737 char *pt, *text = GGadgetGetTitle8(tf);
2738 char buf[12];
2739 Color val;
2740 struct hslrgb col;
2741 pt = text;
2742 while ( isspace(*pt)) ++pt;
2743 if ( *pt=='0' && (pt[1]=='x' || pt[1]=='X')) pt += 2;
2744 else if ( *pt=='#' ) ++pt;
2745 val = strtoul(pt,NULL,16);
2746 gColor2Hslrgb(&col,val);
2747 col = GWidgetColor(_("Pick a color"),&col,NULL);
2748 if ( col.rgb ) {
2749 val = gHslrgb2Color(&col);
2750 sprintf(buf,"#%06x", val );
2751 GGadgetSetTitle8(tf,buf);
2752 }
2753 }
2754 }
2755 return( true );
2756 }
2757
layer_e_h(GWindow gw,GEvent * event)2758 static int layer_e_h(GWindow gw, GEvent *event) {
2759 if ( event->type==et_close ) {
2760 struct layer_dlg *ld = GDrawGetUserData(gw);
2761 ld->done = true;
2762 } else if ( event->type == et_char ) {
2763 if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
2764 help("ui/dialogs/multilayer.html", "#multilayer-layer");
2765 return( true );
2766 }
2767 return( false );
2768 }
2769 return( true );
2770 }
2771
LayerDialog(Layer * layer,SplineFont * sf)2772 int LayerDialog(Layer *layer,SplineFont *sf) {
2773 GRect pos;
2774 GWindow gw;
2775 GWindowAttrs wattrs;
2776 GGadgetCreateData gcd[62], boxes[12];
2777 GGadgetCreateData *barray[10], *varray[4], *fhvarray[22], *shvarray[46],
2778 *lcarray[6], *ljarray[6], *fgarray[5], *fparray[5], *sgarray[5],
2779 *sparray[5];
2780 GTextInfo label[62];
2781 struct layer_dlg ld;
2782 int yoff=0;
2783 int gcdoff, fill_gcd, stroke_gcd, k, j;
2784 char widthbuf[20], fcol[12], scol[12], fopac[30], sopac[30], transbuf[150],
2785 dashbuf[60];
2786 int i;
2787 char *pt;
2788
2789 memset(&ld,0,sizeof(ld));
2790 ld.layer = layer;
2791 ld.sf = sf;
2792
2793 memset(&wattrs,0,sizeof(wattrs));
2794 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
2795 wattrs.event_masks = ~(1<<et_charup);
2796 wattrs.restrict_input_to_me = 1;
2797 wattrs.undercursor = 1;
2798 wattrs.cursor = ct_pointer;
2799 wattrs.utf8_window_title = _("Layer");
2800 wattrs.is_dlg = true;
2801 pos.x = pos.y = 0;
2802 pos.width = GGadgetScale(GDrawPointsToPixels(NULL,LY_Width));
2803 pos.height = GDrawPointsToPixels(NULL,LY_Height);
2804 ld.gw = gw = GDrawCreateTopWindow(NULL,&pos,layer_e_h,&ld,&wattrs);
2805
2806 ld.fillgrad = GradientCopy(layer->fill_brush.gradient,NULL);
2807 ld.strokegrad = GradientCopy(layer->stroke_pen.brush.gradient,NULL);
2808 ld.fillpat = PatternCopy(layer->fill_brush.pattern,NULL);
2809 ld.strokepat = PatternCopy(layer->stroke_pen.brush.pattern,NULL);
2810
2811 memset(&label,0,sizeof(label));
2812 memset(&gcd,0,sizeof(gcd));
2813 memset(&boxes,0,sizeof(boxes));
2814
2815 gcdoff = k = 0;
2816
2817 label[gcdoff].text = (unichar_t *) _("Fi_ll");
2818 label[gcdoff].text_is_1byte = true;
2819 label[gcdoff].text_in_resource = true;
2820 gcd[gcdoff].gd.label = &label[gcdoff];
2821 gcd[gcdoff].gd.pos.x = 5; gcd[gcdoff].gd.pos.y = 5+yoff;
2822 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (layer->dofill? gg_cb_on : 0);
2823 gcd[gcdoff].gd.cid = CID_Fill;
2824 gcd[gcdoff++].creator = GCheckBoxCreate;
2825
2826 fill_gcd = gcdoff;
2827
2828 label[gcdoff].text = (unichar_t *) _("Color:");
2829 label[gcdoff].text_is_1byte = true;
2830 gcd[gcdoff].gd.label = &label[gcdoff];
2831 gcd[gcdoff].gd.pos.x = 5; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y+12;
2832 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
2833 gcd[gcdoff++].creator = GLabelCreate;
2834 fhvarray[k++] = &gcd[gcdoff-1];
2835
2836 sprintf( fcol, "#%06x", layer->fill_brush.col );
2837 label[gcdoff].text = (unichar_t *) fcol;
2838 label[gcdoff].text_is_1byte = true;
2839 if ( layer->fill_brush.col==COLOR_INHERITED )
2840 gcd[gcdoff].gd.flags = gg_visible;
2841 else {
2842 gcd[gcdoff].gd.label = &label[gcdoff];
2843 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
2844 }
2845 gcd[gcdoff].gd.pos.x = 80; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y-3;
2846 gcd[gcdoff].gd.pos.width = 80;
2847 gcd[gcdoff].gd.cid = CID_FillColor;
2848 gcd[gcdoff++].creator = GTextFieldCreate;
2849 fhvarray[k++] = &gcd[gcdoff-1];
2850
2851 label[gcdoff].text = (unichar_t *) _("Inherited");
2852 label[gcdoff].text_is_1byte = true;
2853 gcd[gcdoff].gd.label = &label[gcdoff];
2854 gcd[gcdoff].gd.pos.x = 165; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y+2;
2855 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (layer->fill_brush.col==COLOR_INHERITED? gg_cb_on : 0);
2856 gcd[gcdoff].data = (void *) CID_FillColor;
2857 gcd[gcdoff].gd.cid = CID_FillCInherit;
2858 gcd[gcdoff].gd.handle_controlevent = Layer_Inherit;
2859 gcd[gcdoff++].creator = GCheckBoxCreate;
2860 fhvarray[k++] = &gcd[gcdoff-1];
2861
2862 label[gcdoff].image = GGadgetImageCache("colorwheel.png");
2863 gcd[gcdoff].gd.label = &label[gcdoff];
2864 gcd[gcdoff].gd.flags = gg_enabled|gg_visible;
2865 gcd[gcdoff].data = (void *) CID_FillColor;
2866 gcd[gcdoff].gd.handle_controlevent = Layer_DoColorWheel;
2867 gcd[gcdoff++].creator = GButtonCreate;
2868 fhvarray[k++] = &gcd[gcdoff-1];
2869 fhvarray[k++] = NULL;
2870
2871 label[gcdoff].text = (unichar_t *) _("Opacity:");
2872 label[gcdoff].text_is_1byte = true;
2873 gcd[gcdoff].gd.label = &label[gcdoff];
2874 gcd[gcdoff].gd.pos.x = 5; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y+25;
2875 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
2876 gcd[gcdoff++].creator = GLabelCreate;
2877 fhvarray[k++] = &gcd[gcdoff-1];
2878
2879 sprintf( fopac, "%g", layer->fill_brush.opacity );
2880 label[gcdoff].text = (unichar_t *) fopac;
2881 label[gcdoff].text_is_1byte = true;
2882 if ( layer->fill_brush.opacity<0 )
2883 gcd[gcdoff].gd.flags = gg_visible;
2884 else {
2885 gcd[gcdoff].gd.label = &label[gcdoff];
2886 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
2887 }
2888 gcd[gcdoff].gd.pos.x = 80; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y-3;
2889 gcd[gcdoff].gd.pos.width = 80;
2890 gcd[gcdoff].gd.cid = CID_FillOpacity;
2891 gcd[gcdoff++].creator = GTextFieldCreate;
2892 fhvarray[k++] = &gcd[gcdoff-1];
2893
2894 label[gcdoff].text = (unichar_t *) _("Inherited");
2895 label[gcdoff].text_is_1byte = true;
2896 gcd[gcdoff].gd.label = &label[gcdoff];
2897 gcd[gcdoff].gd.pos.x = 165; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y+2;
2898 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (layer->fill_brush.opacity<0? gg_cb_on : 0);
2899 gcd[gcdoff].data = (void *) CID_FillOpacity;
2900 gcd[gcdoff].gd.cid = CID_FillOInherit;
2901 gcd[gcdoff].gd.handle_controlevent = Layer_Inherit;
2902 gcd[gcdoff++].creator = GCheckBoxCreate;
2903 fhvarray[k++] = &gcd[gcdoff-1];
2904 fhvarray[k++] = GCD_Glue;
2905 fhvarray[k++] = NULL;
2906
2907 label[gcdoff].text = (unichar_t *) _("Gradient:");
2908 label[gcdoff].text_is_1byte = true;
2909 gcd[gcdoff].gd.label = &label[gcdoff];
2910 gcd[gcdoff].gd.pos.x = 5; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y+25;
2911 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
2912 gcd[gcdoff++].creator = GLabelCreate;
2913 fhvarray[k++] = &gcd[gcdoff-1];
2914
2915 gcd[gcdoff].gd.flags = layer->fill_brush.gradient==NULL ? (gg_visible | gg_enabled) : gg_visible;
2916 label[gcdoff].text = (unichar_t *) _("Add");
2917 label[gcdoff].text_is_1byte = true;
2918 label[gcdoff].text_in_resource = true;
2919 gcd[gcdoff].gd.label = &label[gcdoff];
2920 gcd[gcdoff].gd.handle_controlevent = Layer_FillGradAddEdit;
2921 gcd[gcdoff].gd.cid = CID_FillGradAdd;
2922 gcd[gcdoff++].creator = GButtonCreate;
2923 fgarray[0] = &gcd[gcdoff-1];
2924
2925 gcd[gcdoff].gd.flags = layer->fill_brush.gradient!=NULL ? (gg_visible | gg_enabled) : gg_visible;
2926 label[gcdoff].text = (unichar_t *) _("Edit");
2927 label[gcdoff].text_is_1byte = true;
2928 label[gcdoff].text_in_resource = true;
2929 gcd[gcdoff].gd.label = &label[gcdoff];
2930 gcd[gcdoff].gd.handle_controlevent = Layer_FillGradAddEdit;
2931 gcd[gcdoff].gd.cid = CID_FillGradEdit;
2932 gcd[gcdoff++].creator = GButtonCreate;
2933 fgarray[1] = &gcd[gcdoff-1];
2934
2935 gcd[gcdoff].gd.flags = layer->fill_brush.gradient!=NULL ? (gg_visible | gg_enabled) : gg_visible;
2936 label[gcdoff].text = (unichar_t *) _("Delete");
2937 label[gcdoff].text_is_1byte = true;
2938 label[gcdoff].text_in_resource = true;
2939 gcd[gcdoff].gd.label = &label[gcdoff];
2940 gcd[gcdoff].gd.handle_controlevent = Layer_FillGradDelete;
2941 gcd[gcdoff].gd.cid = CID_FillGradDelete;
2942 gcd[gcdoff++].creator = GButtonCreate;
2943 fgarray[2] = &gcd[gcdoff-1];
2944 fgarray[3] = GCD_Glue;
2945 fgarray[4] = NULL;
2946
2947 boxes[7].gd.flags = gg_enabled|gg_visible;
2948 boxes[7].gd.u.boxelements = fgarray;
2949 boxes[7].creator = GHBoxCreate;
2950 fhvarray[k++] = &boxes[7];
2951 fhvarray[k++] = GCD_ColSpan;
2952 fhvarray[k++] = GCD_Glue;
2953 fhvarray[k++] = NULL;
2954
2955 label[gcdoff].text = (unichar_t *) _("Pattern:");
2956 label[gcdoff].text_is_1byte = true;
2957 gcd[gcdoff].gd.label = &label[gcdoff];
2958 gcd[gcdoff].gd.pos.x = 5; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y+25;
2959 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
2960 gcd[gcdoff++].creator = GLabelCreate;
2961 fhvarray[k++] = &gcd[gcdoff-1];
2962
2963 gcd[gcdoff].gd.flags = layer->fill_brush.pattern==NULL ? (gg_visible | gg_enabled) : gg_visible;
2964 label[gcdoff].text = (unichar_t *) _("Add");
2965 label[gcdoff].text_is_1byte = true;
2966 label[gcdoff].text_in_resource = true;
2967 gcd[gcdoff].gd.label = &label[gcdoff];
2968 gcd[gcdoff].gd.handle_controlevent = Layer_FillPatAddEdit;
2969 gcd[gcdoff].gd.cid = CID_FillPatAdd;
2970 gcd[gcdoff++].creator = GButtonCreate;
2971 fparray[0] = &gcd[gcdoff-1];
2972
2973 gcd[gcdoff].gd.flags = layer->fill_brush.pattern!=NULL ? (gg_visible | gg_enabled) : gg_visible;
2974 label[gcdoff].text = (unichar_t *) _("Edit");
2975 label[gcdoff].text_is_1byte = true;
2976 label[gcdoff].text_in_resource = true;
2977 gcd[gcdoff].gd.label = &label[gcdoff];
2978 gcd[gcdoff].gd.handle_controlevent = Layer_FillPatAddEdit;
2979 gcd[gcdoff].gd.cid = CID_FillPatEdit;
2980 gcd[gcdoff++].creator = GButtonCreate;
2981 fparray[1] = &gcd[gcdoff-1];
2982
2983 gcd[gcdoff].gd.flags = layer->fill_brush.pattern!=NULL ? (gg_visible | gg_enabled) : gg_visible;
2984 label[gcdoff].text = (unichar_t *) _("Delete");
2985 label[gcdoff].text_is_1byte = true;
2986 label[gcdoff].text_in_resource = true;
2987 gcd[gcdoff].gd.label = &label[gcdoff];
2988 gcd[gcdoff].gd.handle_controlevent = Layer_FillPatDelete;
2989 gcd[gcdoff].gd.cid = CID_FillPatDelete;
2990 gcd[gcdoff++].creator = GButtonCreate;
2991 fparray[2] = &gcd[gcdoff-1];
2992 fparray[3] = GCD_Glue;
2993 fparray[4] = NULL;
2994
2995 boxes[8].gd.flags = gg_enabled|gg_visible;
2996 boxes[8].gd.u.boxelements = fparray;
2997 boxes[8].creator = GHBoxCreate;
2998 fhvarray[k++] = &boxes[8];
2999 fhvarray[k++] = GCD_ColSpan;
3000 fhvarray[k++] = GCD_Glue;
3001 fhvarray[k++] = NULL;
3002 fhvarray[k++] = NULL;
3003
3004
3005 boxes[2].gd.pos.x = boxes[2].gd.pos.y = 2;
3006 boxes[2].gd.flags = gg_enabled|gg_visible;
3007 boxes[2].gd.u.boxelements = fhvarray;
3008 boxes[2].gd.label = (GTextInfo *) &gcd[fill_gcd-1];
3009 boxes[2].creator = GHVGroupCreate;
3010
3011 label[gcdoff].text = (unichar_t *) _("Stroke");
3012 label[gcdoff].text_is_1byte = true;
3013 gcd[gcdoff].gd.mnemonic = 'S';
3014 gcd[gcdoff].gd.label = &label[gcdoff];
3015 gcd[gcdoff].gd.pos.x = 5; gcd[gcdoff].gd.pos.y = gcd[fill_gcd].gd.pos.y+gcd[fill_gcd].gd.pos.height+4;
3016 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (layer->dostroke? gg_cb_on : 0);
3017 gcd[gcdoff].gd.cid = CID_Stroke;
3018 gcd[gcdoff++].creator = GCheckBoxCreate;
3019
3020 stroke_gcd = gcdoff;
3021 k = 0;
3022
3023 label[gcdoff].text = (unichar_t *) _("Color:");
3024 label[gcdoff].text_is_1byte = true;
3025 gcd[gcdoff].gd.label = &label[gcdoff];
3026 gcd[gcdoff].gd.pos.x = 5; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y+12;
3027 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
3028 gcd[gcdoff++].creator = GLabelCreate;
3029 shvarray[k++] = &gcd[gcdoff-1];
3030
3031 sprintf( scol, "#%06x", layer->stroke_pen.brush.col );
3032 label[gcdoff].text = (unichar_t *) scol;
3033 label[gcdoff].text_is_1byte = true;
3034 if ( layer->stroke_pen.brush.col==COLOR_INHERITED )
3035 gcd[gcdoff].gd.flags = gg_visible;
3036 else {
3037 gcd[gcdoff].gd.label = &label[gcdoff];
3038 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
3039 }
3040 gcd[gcdoff].gd.pos.x = 80; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y-3;
3041 gcd[gcdoff].gd.pos.width = 80;
3042 gcd[gcdoff].gd.cid = CID_StrokeColor;
3043 gcd[gcdoff++].creator = GTextFieldCreate;
3044 shvarray[k++] = &gcd[gcdoff-1];
3045
3046 label[gcdoff].text = (unichar_t *) _("Inherited");
3047 label[gcdoff].text_is_1byte = true;
3048 gcd[gcdoff].gd.label = &label[gcdoff];
3049 gcd[gcdoff].gd.pos.x = 165; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y+2;
3050 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (layer->stroke_pen.brush.col==COLOR_INHERITED? gg_cb_on : 0);
3051 gcd[gcdoff].data = (void *) CID_StrokeColor;
3052 gcd[gcdoff].gd.cid = CID_StrokeCInherit;
3053 gcd[gcdoff].gd.handle_controlevent = Layer_Inherit;
3054 gcd[gcdoff++].creator = GCheckBoxCreate;
3055 shvarray[k++] = &gcd[gcdoff-1];
3056
3057 label[gcdoff].image = GGadgetImageCache("colorwheel.png");
3058 gcd[gcdoff].gd.label = &label[gcdoff];
3059 gcd[gcdoff].gd.flags = gg_enabled|gg_visible;
3060 gcd[gcdoff].data = (void *) CID_StrokeColor;
3061 gcd[gcdoff].gd.handle_controlevent = Layer_DoColorWheel;
3062 gcd[gcdoff++].creator = GButtonCreate;
3063 shvarray[k++] = &gcd[gcdoff-1];
3064 shvarray[k++] = NULL;
3065
3066 label[gcdoff].text = (unichar_t *) _("Opacity:");
3067 label[gcdoff].text_is_1byte = true;
3068 gcd[gcdoff].gd.mnemonic = 'W';
3069 gcd[gcdoff].gd.label = &label[gcdoff];
3070 gcd[gcdoff].gd.pos.x = 5; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y+25;
3071 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
3072 gcd[gcdoff++].creator = GLabelCreate;
3073 shvarray[k++] = &gcd[gcdoff-1];
3074
3075 sprintf( sopac, "%g", layer->stroke_pen.brush.opacity );
3076 label[gcdoff].text = (unichar_t *) sopac;
3077 label[gcdoff].text_is_1byte = true;
3078 if ( layer->stroke_pen.brush.opacity<0 )
3079 gcd[gcdoff].gd.flags = gg_visible;
3080 else {
3081 gcd[gcdoff].gd.label = &label[gcdoff];
3082 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
3083 }
3084 gcd[gcdoff].gd.pos.x = 80; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y-3;
3085 gcd[gcdoff].gd.pos.width = 80;
3086 gcd[gcdoff].gd.cid = CID_StrokeOpacity;
3087 gcd[gcdoff++].creator = GTextFieldCreate;
3088 shvarray[k++] = &gcd[gcdoff-1];
3089
3090 label[gcdoff].text = (unichar_t *) _("Inherited");
3091 label[gcdoff].text_is_1byte = true;
3092 gcd[gcdoff].gd.label = &label[gcdoff];
3093 gcd[gcdoff].gd.pos.x = 165; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y+2;
3094 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (layer->stroke_pen.brush.opacity<0? gg_cb_on : 0);
3095 gcd[gcdoff].data = (void *) CID_StrokeOpacity;
3096 gcd[gcdoff].gd.cid = CID_StrokeOInherit;
3097 gcd[gcdoff].gd.handle_controlevent = Layer_Inherit;
3098 gcd[gcdoff++].creator = GCheckBoxCreate;
3099 shvarray[k++] = &gcd[gcdoff-1];
3100 shvarray[k++] = GCD_Glue;
3101 shvarray[k++] = NULL;
3102
3103 label[gcdoff].text = (unichar_t *) _("Gradient:");
3104 label[gcdoff].text_is_1byte = true;
3105 gcd[gcdoff].gd.label = &label[gcdoff];
3106 gcd[gcdoff].gd.pos.x = 5; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y+25;
3107 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
3108 gcd[gcdoff++].creator = GLabelCreate;
3109 shvarray[k++] = &gcd[gcdoff-1];
3110
3111 gcd[gcdoff].gd.flags = layer->stroke_pen.brush.gradient==NULL ? (gg_visible | gg_enabled) : gg_visible;
3112 label[gcdoff].text = (unichar_t *) _("Add");
3113 label[gcdoff].text_is_1byte = true;
3114 label[gcdoff].text_in_resource = true;
3115 gcd[gcdoff].gd.label = &label[gcdoff];
3116 gcd[gcdoff].gd.handle_controlevent = Layer_StrokeGradAddEdit;
3117 gcd[gcdoff].gd.cid = CID_StrokeGradAdd;
3118 gcd[gcdoff++].creator = GButtonCreate;
3119 sgarray[0] = &gcd[gcdoff-1];
3120
3121 gcd[gcdoff].gd.flags = layer->stroke_pen.brush.gradient!=NULL ? (gg_visible | gg_enabled) : gg_visible;
3122 label[gcdoff].text = (unichar_t *) _("Edit");
3123 label[gcdoff].text_is_1byte = true;
3124 label[gcdoff].text_in_resource = true;
3125 gcd[gcdoff].gd.label = &label[gcdoff];
3126 gcd[gcdoff].gd.handle_controlevent = Layer_StrokeGradAddEdit;
3127 gcd[gcdoff].gd.cid = CID_StrokeGradEdit;
3128 gcd[gcdoff++].creator = GButtonCreate;
3129 sgarray[1] = &gcd[gcdoff-1];
3130
3131 gcd[gcdoff].gd.flags = layer->stroke_pen.brush.gradient!=NULL ? (gg_visible | gg_enabled) : gg_visible;
3132 label[gcdoff].text = (unichar_t *) _("Delete");
3133 label[gcdoff].text_is_1byte = true;
3134 label[gcdoff].text_in_resource = true;
3135 gcd[gcdoff].gd.label = &label[gcdoff];
3136 gcd[gcdoff].gd.handle_controlevent = Layer_StrokeGradDelete;
3137 gcd[gcdoff].gd.cid = CID_StrokeGradDelete;
3138 gcd[gcdoff++].creator = GButtonCreate;
3139 sgarray[2] = &gcd[gcdoff-1];
3140 sgarray[3] = GCD_Glue;
3141 sgarray[4] = NULL;
3142
3143 boxes[9].gd.flags = gg_enabled|gg_visible;
3144 boxes[9].gd.u.boxelements = sgarray;
3145 boxes[9].creator = GHBoxCreate;
3146 shvarray[k++] = &boxes[9];
3147 shvarray[k++] = GCD_ColSpan;
3148 shvarray[k++] = GCD_Glue;
3149 shvarray[k++] = NULL;
3150
3151 label[gcdoff].text = (unichar_t *) _("Pattern:");
3152 label[gcdoff].text_is_1byte = true;
3153 gcd[gcdoff].gd.label = &label[gcdoff];
3154 gcd[gcdoff].gd.pos.x = 5; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y+25;
3155 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
3156 gcd[gcdoff++].creator = GLabelCreate;
3157 shvarray[k++] = &gcd[gcdoff-1];
3158
3159 gcd[gcdoff].gd.flags = layer->stroke_pen.brush.pattern==NULL ? (gg_visible | gg_enabled) : gg_visible;
3160 label[gcdoff].text = (unichar_t *) _("Add");
3161 label[gcdoff].text_is_1byte = true;
3162 label[gcdoff].text_in_resource = true;
3163 gcd[gcdoff].gd.label = &label[gcdoff];
3164 gcd[gcdoff].gd.handle_controlevent = Layer_StrokePatAddEdit;
3165 gcd[gcdoff].gd.cid = CID_StrokePatAdd;
3166 gcd[gcdoff++].creator = GButtonCreate;
3167 sparray[0] = &gcd[gcdoff-1];
3168
3169 gcd[gcdoff].gd.flags = layer->stroke_pen.brush.pattern!=NULL ? (gg_visible | gg_enabled) : gg_visible;
3170 label[gcdoff].text = (unichar_t *) _("Edit");
3171 label[gcdoff].text_is_1byte = true;
3172 label[gcdoff].text_in_resource = true;
3173 gcd[gcdoff].gd.label = &label[gcdoff];
3174 gcd[gcdoff].gd.handle_controlevent = Layer_StrokePatAddEdit;
3175 gcd[gcdoff].gd.cid = CID_StrokePatEdit;
3176 gcd[gcdoff++].creator = GButtonCreate;
3177 sparray[1] = &gcd[gcdoff-1];
3178
3179 gcd[gcdoff].gd.flags = layer->stroke_pen.brush.pattern!=NULL ? (gg_visible | gg_enabled) : gg_visible;
3180 label[gcdoff].text = (unichar_t *) _("Delete");
3181 label[gcdoff].text_is_1byte = true;
3182 label[gcdoff].text_in_resource = true;
3183 gcd[gcdoff].gd.label = &label[gcdoff];
3184 gcd[gcdoff].gd.handle_controlevent = Layer_StrokePatDelete;
3185 gcd[gcdoff].gd.cid = CID_StrokePatDelete;
3186 gcd[gcdoff++].creator = GButtonCreate;
3187 sparray[2] = &gcd[gcdoff-1];
3188 sparray[3] = GCD_Glue;
3189 sparray[4] = NULL;
3190
3191 boxes[10].gd.flags = gg_enabled|gg_visible;
3192 boxes[10].gd.u.boxelements = sparray;
3193 boxes[10].creator = GHBoxCreate;
3194 shvarray[k++] = &boxes[10];
3195 shvarray[k++] = GCD_ColSpan;
3196 shvarray[k++] = GCD_Glue;
3197 shvarray[k++] = NULL;
3198
3199 label[gcdoff].text = (unichar_t *) _("Stroke _Width:");
3200 label[gcdoff].text_is_1byte = true;
3201 label[gcdoff].text_in_resource = true;
3202 gcd[gcdoff].gd.label = &label[gcdoff];
3203 gcd[gcdoff].gd.label = &label[gcdoff];
3204 gcd[gcdoff].gd.pos.x = 5; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y+26;
3205 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
3206 gcd[gcdoff].gd.cid = CID_WidthTxt;
3207 gcd[gcdoff++].creator = GLabelCreate;
3208 shvarray[k++] = &gcd[gcdoff-1];
3209
3210 sprintf( widthbuf, "%g", layer->stroke_pen.width );
3211 label[gcdoff].text = (unichar_t *) widthbuf;
3212 label[gcdoff].text_is_1byte = true;
3213 if ( layer->stroke_pen.width==WIDTH_INHERITED )
3214 gcd[gcdoff].gd.flags = gg_visible;
3215 else {
3216 gcd[gcdoff].gd.label = &label[gcdoff];
3217 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
3218 }
3219 gcd[gcdoff].gd.pos.x = 80; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y-3;
3220 gcd[gcdoff].gd.pos.width = 80;
3221 gcd[gcdoff].gd.cid = CID_Width;
3222 gcd[gcdoff++].creator = GTextFieldCreate;
3223 shvarray[k++] = &gcd[gcdoff-1];
3224
3225 label[gcdoff].text = (unichar_t *) _("Inherited");
3226 label[gcdoff].text_is_1byte = true;
3227 gcd[gcdoff].gd.label = &label[gcdoff];
3228 gcd[gcdoff].gd.pos.x = 165; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y+2;
3229 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (layer->stroke_pen.width==WIDTH_INHERITED? gg_cb_on : 0);
3230 gcd[gcdoff].data = (void *) CID_Width;
3231 gcd[gcdoff].gd.cid = CID_StrokeWInherit;
3232 gcd[gcdoff].gd.handle_controlevent = Layer_Inherit;
3233 gcd[gcdoff++].creator = GCheckBoxCreate;
3234 shvarray[k++] = &gcd[gcdoff-1];
3235 shvarray[k++] = GCD_Glue;
3236 shvarray[k++] = NULL;
3237
3238 label[gcdoff].text = (unichar_t *) _("Dashes");
3239 label[gcdoff].text_is_1byte = true;
3240 gcd[gcdoff].gd.label = &label[gcdoff];
3241 gcd[gcdoff].gd.pos.x = 5; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y+26;
3242 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
3243 gcd[gcdoff].gd.cid = CID_DashesTxt;
3244 gcd[gcdoff].gd.popup_msg = _("This specifies the dash pattern for a line.\nLeave this field blank for a solid line.\nOtherwise specify a list of up to 8 integers\n(between 0 and 255) which give the dash pattern\nin em-units. So \"10 10\" will draw the first\n10 units of a line, leave the next 10 blank,\ndraw the next 10, and so on.");
3245 gcd[gcdoff++].creator = GLabelCreate;
3246 shvarray[k++] = &gcd[gcdoff-1];
3247
3248 pt = dashbuf; dashbuf[0] = '\0';
3249 for ( i=0; i<DASH_MAX && layer->stroke_pen.dashes[i]!=0; ++i ) {
3250 sprintf( pt, "%d ", layer->stroke_pen.dashes[i]);
3251 pt += strlen(pt);
3252 }
3253 if ( pt>dashbuf ) pt[-1] = '\0';
3254 label[gcdoff].text = (unichar_t *) dashbuf;
3255 label[gcdoff].text_is_1byte = true;
3256 if ( layer->stroke_pen.dashes[0]==0 && layer->stroke_pen.dashes[1]==DASH_INHERITED )
3257 gcd[gcdoff].gd.flags = gg_visible;
3258 else {
3259 gcd[gcdoff].gd.label = &label[gcdoff];
3260 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
3261 }
3262 gcd[gcdoff].gd.pos.x = 80; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y-3;
3263 gcd[gcdoff].gd.pos.width = 80;
3264 gcd[gcdoff].gd.cid = CID_Dashes;
3265 gcd[gcdoff++].creator = GTextFieldCreate;
3266 shvarray[k++] = &gcd[gcdoff-1];
3267
3268 label[gcdoff].text = (unichar_t *) _("Inherited");
3269 label[gcdoff].text_is_1byte = true;
3270 gcd[gcdoff].gd.label = &label[gcdoff];
3271 gcd[gcdoff].gd.pos.x = 165; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y+2;
3272 if ( layer->stroke_pen.dashes[0]==0 && layer->stroke_pen.dashes[1]==DASH_INHERITED )
3273 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | gg_cb_on;
3274 else
3275 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
3276 gcd[gcdoff].data = (void *) CID_Dashes;
3277 gcd[gcdoff].gd.cid = CID_DashesInherit;
3278 gcd[gcdoff].gd.handle_controlevent = Layer_Inherit;
3279 gcd[gcdoff].gd.popup_msg = _("This specifies the dash pattern for a line.\nLeave this field blank for a solid line.\nOtherwise specify a list of up to 8 integers\n(between 0 and 255) which give the dash pattern\nin em-units. So \"10 10\" will draw the first\n10 units of a line, leave the next 10 blank,\ndraw the next 10, and so on.");
3280 gcd[gcdoff++].creator = GCheckBoxCreate;
3281 shvarray[k++] = &gcd[gcdoff-1];
3282 shvarray[k++] = GCD_Glue;
3283 shvarray[k++] = NULL;
3284
3285 label[gcdoff].text = (unichar_t *) _("_Transform Pen:");
3286 label[gcdoff].text_in_resource = true;
3287 label[gcdoff].text_is_1byte = true;
3288 gcd[gcdoff].gd.label = &label[gcdoff];
3289 gcd[gcdoff].gd.pos.x = 5; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y+25;
3290 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
3291 gcd[gcdoff++].creator = GLabelCreate;
3292 shvarray[k++] = &gcd[gcdoff-1];
3293
3294 sprintf( transbuf, "[%.4g %.4g %.4g %.4g]", (double) layer->stroke_pen.trans[0],
3295 (double) layer->stroke_pen.trans[1], (double) layer->stroke_pen.trans[2],
3296 (double) layer->stroke_pen.trans[3]);
3297 label[gcdoff].text = (unichar_t *) transbuf;
3298 label[gcdoff].text_is_1byte = true;
3299 gcd[gcdoff].gd.label = &label[gcdoff];
3300 gcd[gcdoff].gd.pos.x = 80; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y-3;
3301 gcd[gcdoff].gd.pos.width = 210;
3302 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
3303 gcd[gcdoff].gd.cid = CID_Trans;
3304 gcd[gcdoff++].creator = GTextFieldCreate;
3305 shvarray[k++] = &gcd[gcdoff-1];
3306 shvarray[k++] = GCD_ColSpan;
3307 shvarray[k++] = GCD_ColSpan;
3308 shvarray[k++] = NULL;
3309
3310 j = 0;
3311 label[gcdoff].text = (unichar_t *) _("Line Cap");
3312 label[gcdoff].text_is_1byte = true;
3313 gcd[gcdoff].gd.label = &label[gcdoff];
3314 gcd[gcdoff].gd.pos.x = 10; gcd[gcdoff].gd.pos.y = gcd[gcdoff-2].gd.pos.y+20;
3315 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
3316 gcd[gcdoff].gd.cid = CID_LineCapTxt;
3317 gcd[gcdoff++].creator = GLabelCreate;
3318
3319 label[gcdoff].text = (unichar_t *) _("_Butt");
3320 label[gcdoff].text_is_1byte = true;
3321 label[gcdoff].text_in_resource = true;
3322 label[gcdoff].image = &GIcon_buttcap;
3323 gcd[gcdoff].gd.mnemonic = 'B';
3324 gcd[gcdoff].gd.label = &label[gcdoff];
3325 gcd[gcdoff].gd.pos.x = 15; gcd[gcdoff].gd.pos.y = gcd[gcdoff-2].gd.pos.y+12;
3326 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (layer->stroke_pen.linecap==lc_butt?gg_cb_on:0);
3327 gcd[gcdoff].gd.cid = CID_ButtCap;
3328 gcd[gcdoff++].creator = GRadioCreate;
3329 lcarray[j++] = &gcd[gcdoff-1];
3330
3331 label[gcdoff].text = (unichar_t *) _("_Round");
3332 label[gcdoff].text_is_1byte = true;
3333 label[gcdoff].text_in_resource = true;
3334 label[gcdoff].image = &GIcon_roundcap;
3335 gcd[gcdoff].gd.mnemonic = 'R';
3336 gcd[gcdoff].gd.label = &label[gcdoff];
3337 gcd[gcdoff].gd.pos.x = 80; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y;
3338 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (layer->stroke_pen.linecap==lc_round?gg_cb_on:0);
3339 gcd[gcdoff].gd.cid = CID_RoundCap;
3340 gcd[gcdoff++].creator = GRadioCreate;
3341 lcarray[j++] = &gcd[gcdoff-1];
3342
3343 label[gcdoff].text = (unichar_t *) _("S_quare");
3344 label[gcdoff].text_is_1byte = true;
3345 label[gcdoff].text_in_resource = true;
3346 label[gcdoff].image = &GIcon_squarecap;
3347 gcd[gcdoff].gd.mnemonic = 'q';
3348 gcd[gcdoff].gd.label = &label[gcdoff];
3349 gcd[gcdoff].gd.pos.x = 150; gcd[gcdoff].gd.pos.y = gcd[gcdoff-2].gd.pos.y;
3350 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (layer->stroke_pen.linecap==lc_square?gg_cb_on:0);
3351 gcd[gcdoff].gd.cid = CID_SquareCap;
3352 gcd[gcdoff++].creator = GRadioCreate;
3353 lcarray[j++] = &gcd[gcdoff-1];
3354
3355 label[gcdoff].text = (unichar_t *) _("Inherited");
3356 label[gcdoff].text_is_1byte = true;
3357 gcd[gcdoff].gd.label = &label[gcdoff];
3358 gcd[gcdoff].gd.pos.x = 220; gcd[gcdoff].gd.pos.y = gcd[gcdoff-2].gd.pos.y;
3359 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (layer->stroke_pen.linecap==lc_inherited?gg_cb_on:0);
3360 gcd[gcdoff].gd.cid = CID_InheritCap;
3361 gcd[gcdoff++].creator = GRadioCreate;
3362 lcarray[j++] = &gcd[gcdoff-1];
3363 lcarray[j++] = NULL;
3364 lcarray[j++] = NULL;
3365
3366 boxes[3].gd.pos.x = boxes[3].gd.pos.y = 2;
3367 boxes[3].gd.flags = gg_enabled|gg_visible;
3368 boxes[3].gd.u.boxelements = lcarray;
3369 boxes[3].gd.label = (GTextInfo *) &gcd[gcdoff-5];
3370 boxes[3].creator = GHVGroupCreate;
3371 shvarray[k++] = &boxes[3];
3372 shvarray[k++] = GCD_ColSpan;
3373 shvarray[k++] = GCD_ColSpan;
3374 shvarray[k++] = GCD_ColSpan;
3375 shvarray[k++] = NULL;
3376
3377 j=0;
3378 label[gcdoff].text = (unichar_t *) _("Line Join");
3379 label[gcdoff].text_is_1byte = true;
3380 gcd[gcdoff].gd.label = &label[gcdoff];
3381 gcd[gcdoff].gd.pos.x = gcd[gcdoff-6].gd.pos.x; gcd[gcdoff].gd.pos.y = gcd[gcdoff-3].gd.pos.y+25;
3382 gcd[gcdoff].gd.flags = gg_enabled | gg_visible;
3383 gcd[gcdoff].gd.cid = CID_LineJoinTxt;
3384 gcd[gcdoff++].creator = GLabelCreate;
3385
3386 label[gcdoff].text = (unichar_t *) _("_Miter");
3387 label[gcdoff].text_is_1byte = true;
3388 label[gcdoff].text_in_resource = true;
3389 label[gcdoff].image = &GIcon_miterjoin;
3390 gcd[gcdoff].gd.mnemonic = 'M';
3391 gcd[gcdoff].gd.label = &label[gcdoff];
3392 gcd[gcdoff].gd.pos.x = gcd[gcdoff-6].gd.pos.x; gcd[gcdoff].gd.pos.y = gcd[gcdoff-2].gd.pos.y+12;
3393 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (layer->stroke_pen.linejoin==lj_miter?gg_cb_on:0);
3394 gcd[gcdoff].gd.cid = CID_MiterJoin;
3395 gcd[gcdoff++].creator = GRadioCreate;
3396 ljarray[j++] = &gcd[gcdoff-1];
3397
3398 label[gcdoff].text = (unichar_t *) _("Ro_und");
3399 label[gcdoff].text_is_1byte = true;
3400 label[gcdoff].text_in_resource = true;
3401 label[gcdoff].image = &GIcon_roundjoin;
3402 gcd[gcdoff].gd.mnemonic = 'u';
3403 gcd[gcdoff].gd.label = &label[gcdoff];
3404 gcd[gcdoff].gd.pos.x = gcd[gcdoff-6].gd.pos.x; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y;
3405 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (layer->stroke_pen.linejoin==lj_round?gg_cb_on:0);
3406 gcd[gcdoff].gd.cid = CID_RoundJoin;
3407 gcd[gcdoff++].creator = GRadioCreate;
3408 ljarray[j++] = &gcd[gcdoff-1];
3409
3410 label[gcdoff].text = (unichar_t *) _("Be_vel");
3411 label[gcdoff].text_is_1byte = true;
3412 label[gcdoff].text_in_resource = true;
3413 label[gcdoff].image = &GIcon_beveljoin;
3414 gcd[gcdoff].gd.mnemonic = 'v';
3415 gcd[gcdoff].gd.label = &label[gcdoff];
3416 gcd[gcdoff].gd.pos.x = gcd[gcdoff-6].gd.pos.x; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y;
3417 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (layer->stroke_pen.linejoin==lj_bevel?gg_cb_on:0);
3418 gcd[gcdoff].gd.cid = CID_BevelJoin;
3419 gcd[gcdoff++].creator = GRadioCreate;
3420 ljarray[j++] = &gcd[gcdoff-1];
3421
3422 label[gcdoff].text = (unichar_t *) _("Inherited");
3423 label[gcdoff].text_is_1byte = true;
3424 gcd[gcdoff].gd.mnemonic = 'q';
3425 gcd[gcdoff].gd.label = &label[gcdoff];
3426 gcd[gcdoff].gd.pos.x = 220; gcd[gcdoff].gd.pos.y = gcd[gcdoff-2].gd.pos.y;
3427 gcd[gcdoff].gd.flags = gg_enabled | gg_visible | (layer->stroke_pen.linejoin==lj_inherited?gg_cb_on:0);
3428 gcd[gcdoff].gd.cid = CID_InheritCap;
3429 gcd[gcdoff++].creator = GRadioCreate;
3430 ljarray[j++] = &gcd[gcdoff-1];
3431 ljarray[j++] = NULL;
3432 ljarray[j++] = NULL;
3433
3434 boxes[4].gd.pos.x = boxes[4].gd.pos.y = 2;
3435 boxes[4].gd.flags = gg_enabled|gg_visible;
3436 boxes[4].gd.u.boxelements = ljarray;
3437 boxes[4].gd.label = (GTextInfo *) &gcd[gcdoff-5];
3438 boxes[4].creator = GHVGroupCreate;
3439 shvarray[k++] = &boxes[4];
3440 shvarray[k++] = GCD_ColSpan;
3441 shvarray[k++] = GCD_ColSpan;
3442 shvarray[k++] = NULL;
3443 shvarray[k++] = NULL;
3444
3445 boxes[5].gd.pos.x = boxes[5].gd.pos.y = 2;
3446 boxes[5].gd.flags = gg_enabled|gg_visible;
3447 boxes[5].gd.u.boxelements = shvarray;
3448 boxes[5].gd.label = (GTextInfo *) &gcd[stroke_gcd-1];
3449 boxes[5].creator = GHVGroupCreate;
3450
3451
3452 gcd[gcdoff].gd.pos.x = 30-3; gcd[gcdoff].gd.pos.y = LY_Height-30-3;
3453 gcd[gcdoff].gd.pos.width = -1;
3454 gcd[gcdoff].gd.flags = gg_visible | gg_enabled | gg_but_default;
3455 label[gcdoff].text = (unichar_t *) _("_OK");
3456 label[gcdoff].text_is_1byte = true;
3457 label[gcdoff].text_in_resource = true;
3458 gcd[gcdoff].gd.label = &label[gcdoff];
3459 gcd[gcdoff].gd.handle_controlevent = Layer_OK;
3460 gcd[gcdoff++].creator = GButtonCreate;
3461 barray[0] = GCD_Glue; barray[1] = &gcd[gcdoff-1]; barray[2] = GCD_Glue; barray[3] = GCD_Glue;
3462
3463 gcd[gcdoff].gd.pos.x = -30; gcd[gcdoff].gd.pos.y = gcd[gcdoff-1].gd.pos.y+3;
3464 gcd[gcdoff].gd.pos.width = -1;
3465 gcd[gcdoff].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
3466 label[gcdoff].text = (unichar_t *) _("_Cancel");
3467 label[gcdoff].text_is_1byte = true;
3468 label[gcdoff].text_in_resource = true;
3469 gcd[gcdoff].gd.label = &label[gcdoff];
3470 gcd[gcdoff].gd.handle_controlevent = Layer_Cancel;
3471 gcd[gcdoff++].creator = GButtonCreate;
3472 barray[4] = GCD_Glue; barray[5] = &gcd[gcdoff-1]; barray[6] = GCD_Glue; barray[7] = NULL;
3473
3474 boxes[6].gd.flags = gg_enabled|gg_visible;
3475 boxes[6].gd.u.boxelements = barray;
3476 boxes[6].creator = GHBoxCreate;
3477
3478 varray[0] = &boxes[2]; varray[1] = &boxes[5]; varray[2] = &boxes[6]; varray[3] = NULL;
3479
3480 boxes[0].gd.flags = gg_enabled|gg_visible;
3481 boxes[0].gd.u.boxelements = varray;
3482 boxes[0].creator = GVBoxCreate;
3483
3484 GGadgetsCreate(gw,boxes);
3485 GHVBoxSetExpandableCol(boxes[2].ret,2);
3486 GHVBoxSetExpandableCol(boxes[5].ret,2);
3487 GHVBoxSetExpandableCol(boxes[6].ret,gb_expandgluesame);
3488 GHVBoxSetExpandableCol(boxes[7].ret,gb_expandgluesame);
3489 GHVBoxSetExpandableCol(boxes[8].ret,gb_expandgluesame);
3490 GHVBoxSetExpandableCol(boxes[9].ret,gb_expandgluesame);
3491 GHVBoxSetExpandableCol(boxes[10].ret,gb_expandgluesame);
3492 GHVBoxFitWindow(boxes[0].ret);
3493
3494 GWidgetHidePalettes();
3495 /*GWidgetIndicateFocusGadget(GWidgetGetControl(ld.gw,CID_Width));*/
3496 GDrawSetVisible(ld.gw,true);
3497 while ( !ld.done )
3498 GDrawProcessOneEvent(NULL);
3499 GDrawDestroyWindow(ld.gw);
3500 if ( !ld.ok ) {
3501 GradientFree(ld.fillgrad);
3502 GradientFree(ld.strokegrad);
3503 PatternFree(ld.fillpat);
3504 PatternFree(ld.strokepat);
3505 }
3506 return( ld.ok );
3507 }
3508