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