OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tk/] [generic/] [tkRectOval.c] - Blame information for rev 578

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tkRectOval.c --
3
 *
4
 *      This file implements rectangle and oval items for canvas
5
 *      widgets.
6
 *
7
 * Copyright (c) 1991-1994 The Regents of the University of California.
8
 * Copyright (c) 1994-1996 Sun Microsystems, Inc.
9
 *
10
 * See the file "license.terms" for information on usage and redistribution
11
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12
 *
13
 * RCS: @(#) $Id: tkRectOval.c,v 1.1.1.1 2002-01-16 10:25:52 markom Exp $
14
 */
15
 
16
#include <stdio.h>
17
#include "tk.h"
18
#include "tkInt.h"
19
#include "tkPort.h"
20
 
21
/*
22
 * The structure below defines the record for each rectangle/oval item.
23
 */
24
 
25
typedef struct RectOvalItem  {
26
    Tk_Item header;             /* Generic stuff that's the same for all
27
                                 * types.  MUST BE FIRST IN STRUCTURE. */
28
    double bbox[4];             /* Coordinates of bounding box for rectangle
29
                                 * or oval (x1, y1, x2, y2).  Item includes
30
                                 * x1 and x2 but not y1 and y2. */
31
    int width;                  /* Width of outline. */
32
    XColor *outlineColor;       /* Color for outline. */
33
    XColor *fillColor;          /* Color for filling rectangle/oval. */
34
    Pixmap fillStipple;         /* Stipple bitmap for filling item. */
35
    GC outlineGC;               /* Graphics context for outline. */
36
    GC fillGC;                  /* Graphics context for filling item. */
37
} RectOvalItem;
38
 
39
/*
40
 * Information used for parsing configuration specs:
41
 */
42
 
43
static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,
44
    Tk_CanvasTagsPrintProc, (ClientData) NULL
45
};
46
 
47
static Tk_ConfigSpec configSpecs[] = {
48
    {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,
49
        (char *) NULL, Tk_Offset(RectOvalItem, fillColor), TK_CONFIG_NULL_OK},
50
    {TK_CONFIG_COLOR, "-outline", (char *) NULL, (char *) NULL,
51
        "black", Tk_Offset(RectOvalItem, outlineColor), TK_CONFIG_NULL_OK},
52
    {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,
53
        (char *) NULL, Tk_Offset(RectOvalItem, fillStipple), TK_CONFIG_NULL_OK},
54
    {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
55
        (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
56
    {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
57
        "1", Tk_Offset(RectOvalItem, width), TK_CONFIG_DONT_SET_DEFAULT},
58
    {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
59
        (char *) NULL, 0, 0}
60
};
61
 
62
/*
63
 * Prototypes for procedures defined in this file:
64
 */
65
 
66
static void             ComputeRectOvalBbox _ANSI_ARGS_((Tk_Canvas canvas,
67
                            RectOvalItem *rectOvalPtr));
68
static int              ConfigureRectOval _ANSI_ARGS_((Tcl_Interp *interp,
69
                            Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
70
                            char **argv, int flags));
71
static int              CreateRectOval _ANSI_ARGS_((Tcl_Interp *interp,
72
                            Tk_Canvas canvas, struct Tk_Item *itemPtr,
73
                            int argc, char **argv));
74
static void             DeleteRectOval _ANSI_ARGS_((Tk_Canvas canvas,
75
                            Tk_Item *itemPtr, Display *display));
76
static void             DisplayRectOval _ANSI_ARGS_((Tk_Canvas canvas,
77
                            Tk_Item *itemPtr, Display *display, Drawable dst,
78
                            int x, int y, int width, int height));
79
static int              OvalToArea _ANSI_ARGS_((Tk_Canvas canvas,
80
                            Tk_Item *itemPtr, double *areaPtr));
81
static double           OvalToPoint _ANSI_ARGS_((Tk_Canvas canvas,
82
                            Tk_Item *itemPtr, double *pointPtr));
83
static int              RectOvalCoords _ANSI_ARGS_((Tcl_Interp *interp,
84
                            Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
85
                            char **argv));
86
static int              RectOvalToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
87
                            Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
88
static int              RectToArea _ANSI_ARGS_((Tk_Canvas canvas,
89
                            Tk_Item *itemPtr, double *areaPtr));
90
static double           RectToPoint _ANSI_ARGS_((Tk_Canvas canvas,
91
                            Tk_Item *itemPtr, double *pointPtr));
92
static void             ScaleRectOval _ANSI_ARGS_((Tk_Canvas canvas,
93
                            Tk_Item *itemPtr, double originX, double originY,
94
                            double scaleX, double scaleY));
95
static void             TranslateRectOval _ANSI_ARGS_((Tk_Canvas canvas,
96
                            Tk_Item *itemPtr, double deltaX, double deltaY));
97
 
98
/*
99
 * The structures below defines the rectangle and oval item types
100
 * by means of procedures that can be invoked by generic item code.
101
 */
102
 
103
Tk_ItemType tkRectangleType = {
104
    "rectangle",                        /* name */
105
    sizeof(RectOvalItem),               /* itemSize */
106
    CreateRectOval,                     /* createProc */
107
    configSpecs,                        /* configSpecs */
108
    ConfigureRectOval,                  /* configureProc */
109
    RectOvalCoords,                     /* coordProc */
110
    DeleteRectOval,                     /* deleteProc */
111
    DisplayRectOval,                    /* displayProc */
112
    0,                                   /* alwaysRedraw */
113
    RectToPoint,                        /* pointProc */
114
    RectToArea,                         /* areaProc */
115
    RectOvalToPostscript,               /* postscriptProc */
116
    ScaleRectOval,                      /* scaleProc */
117
    TranslateRectOval,                  /* translateProc */
118
    (Tk_ItemIndexProc *) NULL,          /* indexProc */
119
    (Tk_ItemCursorProc *) NULL,         /* icursorProc */
120
    (Tk_ItemSelectionProc *) NULL,      /* selectionProc */
121
    (Tk_ItemInsertProc *) NULL,         /* insertProc */
122
    (Tk_ItemDCharsProc *) NULL,         /* dTextProc */
123
    (Tk_ItemType *) NULL                /* nextPtr */
124
};
125
 
126
Tk_ItemType tkOvalType = {
127
    "oval",                             /* name */
128
    sizeof(RectOvalItem),               /* itemSize */
129
    CreateRectOval,                     /* createProc */
130
    configSpecs,                        /* configSpecs */
131
    ConfigureRectOval,                  /* configureProc */
132
    RectOvalCoords,                     /* coordProc */
133
    DeleteRectOval,                     /* deleteProc */
134
    DisplayRectOval,                    /* displayProc */
135
    0,                                   /* alwaysRedraw */
136
    OvalToPoint,                        /* pointProc */
137
    OvalToArea,                         /* areaProc */
138
    RectOvalToPostscript,               /* postscriptProc */
139
    ScaleRectOval,                      /* scaleProc */
140
    TranslateRectOval,                  /* translateProc */
141
    (Tk_ItemIndexProc *) NULL,          /* indexProc */
142
    (Tk_ItemCursorProc *) NULL,         /* cursorProc */
143
    (Tk_ItemSelectionProc *) NULL,      /* selectionProc */
144
    (Tk_ItemInsertProc *) NULL,         /* insertProc */
145
    (Tk_ItemDCharsProc *) NULL,         /* dTextProc */
146
    (Tk_ItemType *) NULL                /* nextPtr */
147
};
148
 
149
/*
150
 *--------------------------------------------------------------
151
 *
152
 * CreateRectOval --
153
 *
154
 *      This procedure is invoked to create a new rectangle
155
 *      or oval item in a canvas.
156
 *
157
 * Results:
158
 *      A standard Tcl return value.  If an error occurred in
159
 *      creating the item, then an error message is left in
160
 *      interp->result;  in this case itemPtr is left uninitialized,
161
 *      so it can be safely freed by the caller.
162
 *
163
 * Side effects:
164
 *      A new rectangle or oval item is created.
165
 *
166
 *--------------------------------------------------------------
167
 */
168
 
169
static int
170
CreateRectOval(interp, canvas, itemPtr, argc, argv)
171
    Tcl_Interp *interp;                 /* For error reporting. */
172
    Tk_Canvas canvas;                   /* Canvas to hold new item. */
173
    Tk_Item *itemPtr;                   /* Record to hold new item;  header
174
                                         * has been initialized by caller. */
175
    int argc;                           /* Number of arguments in argv. */
176
    char **argv;                        /* Arguments describing rectangle. */
177
{
178
    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
179
 
180
    if (argc < 4) {
181
        Tcl_AppendResult(interp, "wrong # args: should be \"",
182
                Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
183
                itemPtr->typePtr->name, " x1 y1 x2 y2 ?options?\"",
184
                (char *) NULL);
185
        return TCL_ERROR;
186
    }
187
 
188
    /*
189
     * Carry out initialization that is needed in order to clean
190
     * up after errors during the the remainder of this procedure.
191
     */
192
 
193
    rectOvalPtr->width = 1;
194
    rectOvalPtr->outlineColor = NULL;
195
    rectOvalPtr->fillColor = NULL;
196
    rectOvalPtr->fillStipple = None;
197
    rectOvalPtr->outlineGC = None;
198
    rectOvalPtr->fillGC = None;
199
 
200
    /*
201
     * Process the arguments to fill in the item record.
202
     */
203
 
204
    if ((Tk_CanvasGetCoord(interp, canvas, argv[0],
205
                &rectOvalPtr->bbox[0]) != TCL_OK)
206
            || (Tk_CanvasGetCoord(interp, canvas, argv[1],
207
                &rectOvalPtr->bbox[1]) != TCL_OK)
208
            || (Tk_CanvasGetCoord(interp, canvas, argv[2],
209
                    &rectOvalPtr->bbox[2]) != TCL_OK)
210
            || (Tk_CanvasGetCoord(interp, canvas, argv[3],
211
                    &rectOvalPtr->bbox[3]) != TCL_OK)) {
212
        return TCL_ERROR;
213
    }
214
 
215
    if (ConfigureRectOval(interp, canvas, itemPtr, argc-4, argv+4, 0)
216
            != TCL_OK) {
217
        DeleteRectOval(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
218
        return TCL_ERROR;
219
    }
220
    return TCL_OK;
221
}
222
 
223
/*
224
 *--------------------------------------------------------------
225
 *
226
 * RectOvalCoords --
227
 *
228
 *      This procedure is invoked to process the "coords" widget
229
 *      command on rectangles and ovals.  See the user documentation
230
 *      for details on what it does.
231
 *
232
 * Results:
233
 *      Returns TCL_OK or TCL_ERROR, and sets interp->result.
234
 *
235
 * Side effects:
236
 *      The coordinates for the given item may be changed.
237
 *
238
 *--------------------------------------------------------------
239
 */
240
 
241
static int
242
RectOvalCoords(interp, canvas, itemPtr, argc, argv)
243
    Tcl_Interp *interp;                 /* Used for error reporting. */
244
    Tk_Canvas canvas;                   /* Canvas containing item. */
245
    Tk_Item *itemPtr;                   /* Item whose coordinates are to be
246
                                         * read or modified. */
247
    int argc;                           /* Number of coordinates supplied in
248
                                         * argv. */
249
    char **argv;                        /* Array of coordinates: x1, y1,
250
                                         * x2, y2, ... */
251
{
252
    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
253
    char c0[TCL_DOUBLE_SPACE], c1[TCL_DOUBLE_SPACE];
254
    char c2[TCL_DOUBLE_SPACE], c3[TCL_DOUBLE_SPACE];
255
 
256
    if (argc == 0) {
257
        Tcl_PrintDouble(interp, rectOvalPtr->bbox[0], c0);
258
        Tcl_PrintDouble(interp, rectOvalPtr->bbox[1], c1);
259
        Tcl_PrintDouble(interp, rectOvalPtr->bbox[2], c2);
260
        Tcl_PrintDouble(interp, rectOvalPtr->bbox[3], c3);
261
        Tcl_AppendResult(interp, c0, " ", c1, " ", c2, " ", c3,
262
                (char *) NULL);
263
    } else if (argc == 4) {
264
        if ((Tk_CanvasGetCoord(interp, canvas, argv[0],
265
                    &rectOvalPtr->bbox[0]) != TCL_OK)
266
                || (Tk_CanvasGetCoord(interp, canvas, argv[1],
267
                    &rectOvalPtr->bbox[1]) != TCL_OK)
268
                || (Tk_CanvasGetCoord(interp, canvas, argv[2],
269
                        &rectOvalPtr->bbox[2]) != TCL_OK)
270
                || (Tk_CanvasGetCoord(interp, canvas, argv[3],
271
                        &rectOvalPtr->bbox[3]) != TCL_OK)) {
272
            return TCL_ERROR;
273
        }
274
        ComputeRectOvalBbox(canvas, rectOvalPtr);
275
    } else {
276
        sprintf(interp->result,
277
                "wrong # coordinates: expected 0 or 4, got %d",
278
                argc);
279
        return TCL_ERROR;
280
    }
281
    return TCL_OK;
282
}
283
 
284
/*
285
 *--------------------------------------------------------------
286
 *
287
 * ConfigureRectOval --
288
 *
289
 *      This procedure is invoked to configure various aspects
290
 *      of a rectangle or oval item, such as its border and
291
 *      background colors.
292
 *
293
 * Results:
294
 *      A standard Tcl result code.  If an error occurs, then
295
 *      an error message is left in interp->result.
296
 *
297
 * Side effects:
298
 *      Configuration information, such as colors and stipple
299
 *      patterns, may be set for itemPtr.
300
 *
301
 *--------------------------------------------------------------
302
 */
303
 
304
static int
305
ConfigureRectOval(interp, canvas, itemPtr, argc, argv, flags)
306
    Tcl_Interp *interp;         /* Used for error reporting. */
307
    Tk_Canvas canvas;           /* Canvas containing itemPtr. */
308
    Tk_Item *itemPtr;           /* Rectangle item to reconfigure. */
309
    int argc;                   /* Number of elements in argv.  */
310
    char **argv;                /* Arguments describing things to configure. */
311
    int flags;                  /* Flags to pass to Tk_ConfigureWidget. */
312
{
313
    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
314
    XGCValues gcValues;
315
    GC newGC;
316
    unsigned long mask;
317
    Tk_Window tkwin;
318
 
319
    tkwin = Tk_CanvasTkwin(canvas);
320
    if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, argv,
321
            (char *) rectOvalPtr, flags) != TCL_OK) {
322
        return TCL_ERROR;
323
    }
324
 
325
    /*
326
     * A few of the options require additional processing, such as
327
     * graphics contexts.
328
     */
329
 
330
    if (rectOvalPtr->width < 1) {
331
        rectOvalPtr->width = 1;
332
    }
333
    if (rectOvalPtr->outlineColor == NULL) {
334
        newGC = None;
335
    } else {
336
        gcValues.foreground = rectOvalPtr->outlineColor->pixel;
337
        gcValues.cap_style = CapProjecting;
338
        gcValues.line_width = rectOvalPtr->width;
339
        mask = GCForeground|GCCapStyle|GCLineWidth;
340
        newGC = Tk_GetGCColor(tkwin, mask, &gcValues,
341
                              rectOvalPtr->outlineColor, NULL);
342
    }
343
    if (rectOvalPtr->outlineGC != None) {
344
        Tk_FreeGC(Tk_Display(tkwin), rectOvalPtr->outlineGC);
345
    }
346
    rectOvalPtr->outlineGC = newGC;
347
 
348
    if (rectOvalPtr->fillColor == NULL) {
349
        newGC = None;
350
    } else {
351
        gcValues.foreground = rectOvalPtr->fillColor->pixel;
352
        if (rectOvalPtr->fillStipple != None) {
353
            gcValues.stipple = rectOvalPtr->fillStipple;
354
            gcValues.fill_style = FillStippled;
355
            mask = GCForeground|GCStipple|GCFillStyle;
356
        } else {
357
            mask = GCForeground;
358
        }
359
        newGC = Tk_GetGCColor(tkwin, mask, &gcValues, rectOvalPtr->fillColor,
360
                              NULL);
361
    }
362
    if (rectOvalPtr->fillGC != None) {
363
        Tk_FreeGC(Tk_Display(tkwin), rectOvalPtr->fillGC);
364
    }
365
    rectOvalPtr->fillGC = newGC;
366
    ComputeRectOvalBbox(canvas, rectOvalPtr);
367
 
368
    return TCL_OK;
369
}
370
 
371
/*
372
 *--------------------------------------------------------------
373
 *
374
 * DeleteRectOval --
375
 *
376
 *      This procedure is called to clean up the data structure
377
 *      associated with a rectangle or oval item.
378
 *
379
 * Results:
380
 *      None.
381
 *
382
 * Side effects:
383
 *      Resources associated with itemPtr are released.
384
 *
385
 *--------------------------------------------------------------
386
 */
387
 
388
static void
389
DeleteRectOval(canvas, itemPtr, display)
390
    Tk_Canvas canvas;                   /* Info about overall widget. */
391
    Tk_Item *itemPtr;                   /* Item that is being deleted. */
392
    Display *display;                   /* Display containing window for
393
                                         * canvas. */
394
{
395
    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
396
 
397
    if (rectOvalPtr->outlineColor != NULL) {
398
        Tk_FreeColor(rectOvalPtr->outlineColor);
399
    }
400
    if (rectOvalPtr->fillColor != NULL) {
401
        Tk_FreeColor(rectOvalPtr->fillColor);
402
    }
403
    if (rectOvalPtr->fillStipple != None) {
404
        Tk_FreeBitmap(display, rectOvalPtr->fillStipple);
405
    }
406
    if (rectOvalPtr->outlineGC != None) {
407
        Tk_FreeGC(display, rectOvalPtr->outlineGC);
408
    }
409
    if (rectOvalPtr->fillGC != None) {
410
        Tk_FreeGC(display, rectOvalPtr->fillGC);
411
    }
412
}
413
 
414
/*
415
 *--------------------------------------------------------------
416
 *
417
 * ComputeRectOvalBbox --
418
 *
419
 *      This procedure is invoked to compute the bounding box of
420
 *      all the pixels that may be drawn as part of a rectangle
421
 *      or oval.
422
 *
423
 * Results:
424
 *      None.
425
 *
426
 * Side effects:
427
 *      The fields x1, y1, x2, and y2 are updated in the header
428
 *      for itemPtr.
429
 *
430
 *--------------------------------------------------------------
431
 */
432
 
433
        /* ARGSUSED */
434
static void
435
ComputeRectOvalBbox(canvas, rectOvalPtr)
436
    Tk_Canvas canvas;                   /* Canvas that contains item. */
437
    RectOvalItem *rectOvalPtr;          /* Item whose bbox is to be
438
                                         * recomputed. */
439
{
440
    int bloat, tmp;
441
    double dtmp;
442
 
443
    /*
444
     * Make sure that the first coordinates are the lowest ones.
445
     */
446
 
447
    if (rectOvalPtr->bbox[1] > rectOvalPtr->bbox[3]) {
448
        double tmp;
449
        tmp = rectOvalPtr->bbox[3];
450
        rectOvalPtr->bbox[3] = rectOvalPtr->bbox[1];
451
        rectOvalPtr->bbox[1] = tmp;
452
    }
453
    if (rectOvalPtr->bbox[0] > rectOvalPtr->bbox[2]) {
454
        double tmp;
455
        tmp = rectOvalPtr->bbox[2];
456
        rectOvalPtr->bbox[2] = rectOvalPtr->bbox[0];
457
        rectOvalPtr->bbox[0] = tmp;
458
    }
459
 
460
    if (rectOvalPtr->outlineColor == NULL) {
461
        bloat = 0;
462
    } else {
463
        bloat = (rectOvalPtr->width+1)/2;
464
    }
465
 
466
    /*
467
     * Special note:  the rectangle is always drawn at least 1x1 in
468
     * size, so round up the upper coordinates to be at least 1 unit
469
     * greater than the lower ones.
470
     */
471
 
472
    tmp = (int) ((rectOvalPtr->bbox[0] >= 0) ? rectOvalPtr->bbox[0] + .5
473
            : rectOvalPtr->bbox[0] - .5);
474
    rectOvalPtr->header.x1 = tmp - bloat;
475
    tmp = (int) ((rectOvalPtr->bbox[1] >= 0) ? rectOvalPtr->bbox[1] + .5
476
            : rectOvalPtr->bbox[1] - .5);
477
    rectOvalPtr->header.y1 = tmp - bloat;
478
    dtmp = rectOvalPtr->bbox[2];
479
    if (dtmp < (rectOvalPtr->bbox[0] + 1)) {
480
        dtmp = rectOvalPtr->bbox[0] + 1;
481
    }
482
    tmp = (int) ((dtmp >= 0) ? dtmp + .5 : dtmp - .5);
483
    rectOvalPtr->header.x2 = tmp + bloat;
484
    dtmp = rectOvalPtr->bbox[3];
485
    if (dtmp < (rectOvalPtr->bbox[1] + 1)) {
486
        dtmp = rectOvalPtr->bbox[1] + 1;
487
    }
488
    tmp = (int) ((dtmp >= 0) ? dtmp + .5 : dtmp - .5);
489
    rectOvalPtr->header.y2 = tmp + bloat;
490
}
491
 
492
/*
493
 *--------------------------------------------------------------
494
 *
495
 * DisplayRectOval --
496
 *
497
 *      This procedure is invoked to draw a rectangle or oval
498
 *      item in a given drawable.
499
 *
500
 * Results:
501
 *      None.
502
 *
503
 * Side effects:
504
 *      ItemPtr is drawn in drawable using the transformation
505
 *      information in canvas.
506
 *
507
 *--------------------------------------------------------------
508
 */
509
 
510
static void
511
DisplayRectOval(canvas, itemPtr, display, drawable, x, y, width, height)
512
    Tk_Canvas canvas;                   /* Canvas that contains item. */
513
    Tk_Item *itemPtr;                   /* Item to be displayed. */
514
    Display *display;                   /* Display on which to draw item. */
515
    Drawable drawable;                  /* Pixmap or window in which to draw
516
                                         * item. */
517
    int x, y, width, height;            /* Describes region of canvas that
518
                                         * must be redisplayed (not used). */
519
{
520
    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
521
    short x1, y1, x2, y2;
522
 
523
    /*
524
     * Compute the screen coordinates of the bounding box for the item.
525
     * Make sure that the bbox is at least one pixel large, since some
526
     * X servers will die if it isn't.
527
     */
528
 
529
    Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[0], rectOvalPtr->bbox[1],
530
            &x1, &y1);
531
    Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[2], rectOvalPtr->bbox[3],
532
            &x2, &y2);
533
    if (x2 <= x1) {
534
        x2 = x1+1;
535
    }
536
    if (y2 <= y1) {
537
        y2 = y1+1;
538
    }
539
 
540
    /*
541
     * Display filled part first (if wanted), then outline.  If we're
542
     * stippling, then modify the stipple offset in the GC.  Be sure to
543
     * reset the offset when done, since the GC is supposed to be
544
     * read-only.
545
     */
546
 
547
    if (rectOvalPtr->fillGC != None) {
548
        if (rectOvalPtr->fillStipple != None) {
549
            Tk_CanvasSetStippleOrigin(canvas, rectOvalPtr->fillGC);
550
        }
551
        if (rectOvalPtr->header.typePtr == &tkRectangleType) {
552
            XFillRectangle(display, drawable, rectOvalPtr->fillGC,
553
                    x1, y1, (unsigned int) (x2-x1), (unsigned int) (y2-y1));
554
        } else {
555
            XFillArc(display, drawable, rectOvalPtr->fillGC,
556
                    x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1),
557
                    0, 360*64);
558
        }
559
        if (rectOvalPtr->fillStipple != None) {
560
            XSetTSOrigin(display, rectOvalPtr->fillGC, 0, 0);
561
        }
562
    }
563
    if (rectOvalPtr->outlineGC != None) {
564
        if (rectOvalPtr->header.typePtr == &tkRectangleType) {
565
            XDrawRectangle(display, drawable, rectOvalPtr->outlineGC,
566
                    x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1));
567
        } else {
568
            XDrawArc(display, drawable, rectOvalPtr->outlineGC,
569
                    x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1), 0, 360*64);
570
        }
571
    }
572
}
573
 
574
/*
575
 *--------------------------------------------------------------
576
 *
577
 * RectToPoint --
578
 *
579
 *      Computes the distance from a given point to a given
580
 *      rectangle, in canvas units.
581
 *
582
 * Results:
583
 *      The return value is 0 if the point whose x and y coordinates
584
 *      are coordPtr[0] and coordPtr[1] is inside the rectangle.  If the
585
 *      point isn't inside the rectangle then the return value is the
586
 *      distance from the point to the rectangle.  If itemPtr is filled,
587
 *      then anywhere in the interior is considered "inside"; if
588
 *      itemPtr isn't filled, then "inside" means only the area
589
 *      occupied by the outline.
590
 *
591
 * Side effects:
592
 *      None.
593
 *
594
 *--------------------------------------------------------------
595
 */
596
 
597
        /* ARGSUSED */
598
static double
599
RectToPoint(canvas, itemPtr, pointPtr)
600
    Tk_Canvas canvas;           /* Canvas containing item. */
601
    Tk_Item *itemPtr;           /* Item to check against point. */
602
    double *pointPtr;           /* Pointer to x and y coordinates. */
603
{
604
    RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;
605
    double xDiff, yDiff, x1, y1, x2, y2, inc, tmp;
606
 
607
    /*
608
     * Generate a new larger rectangle that includes the border
609
     * width, if there is one.
610
     */
611
 
612
    x1 = rectPtr->bbox[0];
613
    y1 = rectPtr->bbox[1];
614
    x2 = rectPtr->bbox[2];
615
    y2 = rectPtr->bbox[3];
616
    if (rectPtr->outlineGC != None) {
617
        inc = rectPtr->width/2.0;
618
        x1 -= inc;
619
        y1 -= inc;
620
        x2 += inc;
621
        y2 += inc;
622
    }
623
 
624
    /*
625
     * If the point is inside the rectangle, handle specially:
626
     * distance is 0 if rectangle is filled, otherwise compute
627
     * distance to nearest edge of rectangle and subtract width
628
     * of edge.
629
     */
630
 
631
    if ((pointPtr[0] >= x1) && (pointPtr[0] < x2)
632
                && (pointPtr[1] >= y1) && (pointPtr[1] < y2)) {
633
        if ((rectPtr->fillGC != None) || (rectPtr->outlineGC == None)) {
634
            return 0.0;
635
        }
636
        xDiff = pointPtr[0] - x1;
637
        tmp = x2 - pointPtr[0];
638
        if (tmp < xDiff) {
639
            xDiff = tmp;
640
        }
641
        yDiff = pointPtr[1] - y1;
642
        tmp = y2 - pointPtr[1];
643
        if (tmp < yDiff) {
644
            yDiff = tmp;
645
        }
646
        if (yDiff < xDiff) {
647
            xDiff = yDiff;
648
        }
649
        xDiff -= rectPtr->width;
650
        if (xDiff < 0.0) {
651
            return 0.0;
652
        }
653
        return xDiff;
654
    }
655
 
656
    /*
657
     * Point is outside rectangle.
658
     */
659
 
660
    if (pointPtr[0] < x1) {
661
        xDiff = x1 - pointPtr[0];
662
    } else if (pointPtr[0] > x2)  {
663
        xDiff = pointPtr[0] - x2;
664
    } else {
665
        xDiff = 0;
666
    }
667
 
668
    if (pointPtr[1] < y1) {
669
        yDiff = y1 - pointPtr[1];
670
    } else if (pointPtr[1] > y2)  {
671
        yDiff = pointPtr[1] - y2;
672
    } else {
673
        yDiff = 0;
674
    }
675
 
676
    return hypot(xDiff, yDiff);
677
}
678
 
679
/*
680
 *--------------------------------------------------------------
681
 *
682
 * OvalToPoint --
683
 *
684
 *      Computes the distance from a given point to a given
685
 *      oval, in canvas units.
686
 *
687
 * Results:
688
 *      The return value is 0 if the point whose x and y coordinates
689
 *      are coordPtr[0] and coordPtr[1] is inside the oval.  If the
690
 *      point isn't inside the oval then the return value is the
691
 *      distance from the point to the oval.  If itemPtr is filled,
692
 *      then anywhere in the interior is considered "inside"; if
693
 *      itemPtr isn't filled, then "inside" means only the area
694
 *      occupied by the outline.
695
 *
696
 * Side effects:
697
 *      None.
698
 *
699
 *--------------------------------------------------------------
700
 */
701
 
702
        /* ARGSUSED */
703
static double
704
OvalToPoint(canvas, itemPtr, pointPtr)
705
    Tk_Canvas canvas;           /* Canvas containing item. */
706
    Tk_Item *itemPtr;           /* Item to check against point. */
707
    double *pointPtr;           /* Pointer to x and y coordinates. */
708
{
709
    RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;
710
    double width;
711
    int filled;
712
 
713
    width = ovalPtr->width;
714
    filled = ovalPtr->fillGC != None;
715
    if (ovalPtr->outlineGC == None) {
716
        width = 0.0;
717
        filled = 1;
718
    }
719
    return TkOvalToPoint(ovalPtr->bbox, width, filled, pointPtr);
720
}
721
 
722
/*
723
 *--------------------------------------------------------------
724
 *
725
 * RectToArea --
726
 *
727
 *      This procedure is called to determine whether an item
728
 *      lies entirely inside, entirely outside, or overlapping
729
 *      a given rectangle.
730
 *
731
 * Results:
732
 *      -1 is returned if the item is entirely outside the area
733
 *      given by rectPtr, 0 if it overlaps, and 1 if it is entirely
734
 *      inside the given area.
735
 *
736
 * Side effects:
737
 *      None.
738
 *
739
 *--------------------------------------------------------------
740
 */
741
 
742
        /* ARGSUSED */
743
static int
744
RectToArea(canvas, itemPtr, areaPtr)
745
    Tk_Canvas canvas;           /* Canvas containing item. */
746
    Tk_Item *itemPtr;           /* Item to check against rectangle. */
747
    double *areaPtr;            /* Pointer to array of four coordinates
748
                                 * (x1, y1, x2, y2) describing rectangular
749
                                 * area.  */
750
{
751
    RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;
752
    double halfWidth;
753
 
754
    halfWidth = rectPtr->width/2.0;
755
    if (rectPtr->outlineGC == None) {
756
        halfWidth = 0.0;
757
    }
758
 
759
    if ((areaPtr[2] <= (rectPtr->bbox[0] - halfWidth))
760
            || (areaPtr[0] >= (rectPtr->bbox[2] + halfWidth))
761
            || (areaPtr[3] <= (rectPtr->bbox[1] - halfWidth))
762
            || (areaPtr[1] >= (rectPtr->bbox[3] + halfWidth))) {
763
        return -1;
764
    }
765
    if ((rectPtr->fillGC == None) && (rectPtr->outlineGC != None)
766
            && (areaPtr[0] >= (rectPtr->bbox[0] + halfWidth))
767
            && (areaPtr[1] >= (rectPtr->bbox[1] + halfWidth))
768
            && (areaPtr[2] <= (rectPtr->bbox[2] - halfWidth))
769
            && (areaPtr[3] <= (rectPtr->bbox[3] - halfWidth))) {
770
        return -1;
771
    }
772
    if ((areaPtr[0] <= (rectPtr->bbox[0] - halfWidth))
773
            && (areaPtr[1] <= (rectPtr->bbox[1] - halfWidth))
774
            && (areaPtr[2] >= (rectPtr->bbox[2] + halfWidth))
775
            && (areaPtr[3] >= (rectPtr->bbox[3] + halfWidth))) {
776
        return 1;
777
    }
778
    return 0;
779
}
780
 
781
/*
782
 *--------------------------------------------------------------
783
 *
784
 * OvalToArea --
785
 *
786
 *      This procedure is called to determine whether an item
787
 *      lies entirely inside, entirely outside, or overlapping
788
 *      a given rectangular area.
789
 *
790
 * Results:
791
 *      -1 is returned if the item is entirely outside the area
792
 *      given by rectPtr, 0 if it overlaps, and 1 if it is entirely
793
 *      inside the given area.
794
 *
795
 * Side effects:
796
 *      None.
797
 *
798
 *--------------------------------------------------------------
799
 */
800
 
801
        /* ARGSUSED */
802
static int
803
OvalToArea(canvas, itemPtr, areaPtr)
804
    Tk_Canvas canvas;           /* Canvas containing item. */
805
    Tk_Item *itemPtr;           /* Item to check against oval. */
806
    double *areaPtr;            /* Pointer to array of four coordinates
807
                                 * (x1, y1, x2, y2) describing rectangular
808
                                 * area.  */
809
{
810
    RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;
811
    double oval[4], halfWidth;
812
    int result;
813
 
814
    /*
815
     * Expand the oval to include the width of the outline, if any.
816
     */
817
 
818
    halfWidth = ovalPtr->width/2.0;
819
    if (ovalPtr->outlineGC == None) {
820
        halfWidth = 0.0;
821
    }
822
    oval[0] = ovalPtr->bbox[0] - halfWidth;
823
    oval[1] = ovalPtr->bbox[1] - halfWidth;
824
    oval[2] = ovalPtr->bbox[2] + halfWidth;
825
    oval[3] = ovalPtr->bbox[3] + halfWidth;
826
 
827
    result = TkOvalToArea(oval, areaPtr);
828
 
829
    /*
830
     * If the rectangle appears to overlap the oval and the oval
831
     * isn't filled, do one more check to see if perhaps all four
832
     * of the rectangle's corners are totally inside the oval's
833
     * unfilled center, in which case we should return "outside".
834
     */
835
 
836
    if ((result == 0) && (ovalPtr->outlineGC != None)
837
            && (ovalPtr->fillGC == None)) {
838
        double centerX, centerY, width, height;
839
        double xDelta1, yDelta1, xDelta2, yDelta2;
840
 
841
        centerX = (ovalPtr->bbox[0] + ovalPtr->bbox[2])/2.0;
842
        centerY = (ovalPtr->bbox[1] + ovalPtr->bbox[3])/2.0;
843
        width = (ovalPtr->bbox[2] - ovalPtr->bbox[0])/2.0 - halfWidth;
844
        height = (ovalPtr->bbox[3] - ovalPtr->bbox[1])/2.0 - halfWidth;
845
        xDelta1 = (areaPtr[0] - centerX)/width;
846
        xDelta1 *= xDelta1;
847
        yDelta1 = (areaPtr[1] - centerY)/height;
848
        yDelta1 *= yDelta1;
849
        xDelta2 = (areaPtr[2] - centerX)/width;
850
        xDelta2 *= xDelta2;
851
        yDelta2 = (areaPtr[3] - centerY)/height;
852
        yDelta2 *= yDelta2;
853
        if (((xDelta1 + yDelta1) < 1.0)
854
                && ((xDelta1 + yDelta2) < 1.0)
855
                && ((xDelta2 + yDelta1) < 1.0)
856
                && ((xDelta2 + yDelta2) < 1.0)) {
857
            return -1;
858
        }
859
    }
860
    return result;
861
}
862
 
863
/*
864
 *--------------------------------------------------------------
865
 *
866
 * ScaleRectOval --
867
 *
868
 *      This procedure is invoked to rescale a rectangle or oval
869
 *      item.
870
 *
871
 * Results:
872
 *      None.
873
 *
874
 * Side effects:
875
 *      The rectangle or oval referred to by itemPtr is rescaled
876
 *      so that the following transformation is applied to all
877
 *      point coordinates:
878
 *              x' = originX + scaleX*(x-originX)
879
 *              y' = originY + scaleY*(y-originY)
880
 *
881
 *--------------------------------------------------------------
882
 */
883
 
884
static void
885
ScaleRectOval(canvas, itemPtr, originX, originY, scaleX, scaleY)
886
    Tk_Canvas canvas;                   /* Canvas containing rectangle. */
887
    Tk_Item *itemPtr;                   /* Rectangle to be scaled. */
888
    double originX, originY;            /* Origin about which to scale rect. */
889
    double scaleX;                      /* Amount to scale in X direction. */
890
    double scaleY;                      /* Amount to scale in Y direction. */
891
{
892
    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
893
 
894
    rectOvalPtr->bbox[0] = originX + scaleX*(rectOvalPtr->bbox[0] - originX);
895
    rectOvalPtr->bbox[1] = originY + scaleY*(rectOvalPtr->bbox[1] - originY);
896
    rectOvalPtr->bbox[2] = originX + scaleX*(rectOvalPtr->bbox[2] - originX);
897
    rectOvalPtr->bbox[3] = originY + scaleY*(rectOvalPtr->bbox[3] - originY);
898
    ComputeRectOvalBbox(canvas, rectOvalPtr);
899
}
900
 
901
/*
902
 *--------------------------------------------------------------
903
 *
904
 * TranslateRectOval --
905
 *
906
 *      This procedure is called to move a rectangle or oval by a
907
 *      given amount.
908
 *
909
 * Results:
910
 *      None.
911
 *
912
 * Side effects:
913
 *      The position of the rectangle or oval is offset by
914
 *      (xDelta, yDelta), and the bounding box is updated in the
915
 *      generic part of the item structure.
916
 *
917
 *--------------------------------------------------------------
918
 */
919
 
920
static void
921
TranslateRectOval(canvas, itemPtr, deltaX, deltaY)
922
    Tk_Canvas canvas;                   /* Canvas containing item. */
923
    Tk_Item *itemPtr;                   /* Item that is being moved. */
924
    double deltaX, deltaY;              /* Amount by which item is to be
925
                                         * moved. */
926
{
927
    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
928
 
929
    rectOvalPtr->bbox[0] += deltaX;
930
    rectOvalPtr->bbox[1] += deltaY;
931
    rectOvalPtr->bbox[2] += deltaX;
932
    rectOvalPtr->bbox[3] += deltaY;
933
    ComputeRectOvalBbox(canvas, rectOvalPtr);
934
}
935
 
936
/*
937
 *--------------------------------------------------------------
938
 *
939
 * RectOvalToPostscript --
940
 *
941
 *      This procedure is called to generate Postscript for
942
 *      rectangle and oval items.
943
 *
944
 * Results:
945
 *      The return value is a standard Tcl result.  If an error
946
 *      occurs in generating Postscript then an error message is
947
 *      left in interp->result, replacing whatever used to be there.
948
 *      If no error occurs, then Postscript for the rectangle is
949
 *      appended to the result.
950
 *
951
 * Side effects:
952
 *      None.
953
 *
954
 *--------------------------------------------------------------
955
 */
956
 
957
static int
958
RectOvalToPostscript(interp, canvas, itemPtr, prepass)
959
    Tcl_Interp *interp;                 /* Interpreter for error reporting. */
960
    Tk_Canvas canvas;                   /* Information about overall canvas. */
961
    Tk_Item *itemPtr;                   /* Item for which Postscript is
962
                                         * wanted. */
963
    int prepass;                        /* 1 means this is a prepass to
964
                                         * collect font information;  0 means
965
                                         * final Postscript is being created. */
966
{
967
    char pathCmd[500], string[100];
968
    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
969
    double y1, y2;
970
 
971
    y1 = Tk_CanvasPsY(canvas, rectOvalPtr->bbox[1]);
972
    y2 = Tk_CanvasPsY(canvas, rectOvalPtr->bbox[3]);
973
 
974
    /*
975
     * Generate a string that creates a path for the rectangle or oval.
976
     * This is the only part of the procedure's code that is type-
977
     * specific.
978
     */
979
 
980
 
981
    if (rectOvalPtr->header.typePtr == &tkRectangleType) {
982
        sprintf(pathCmd, "%.15g %.15g moveto %.15g 0 rlineto 0 %.15g rlineto %.15g 0 rlineto closepath\n",
983
                rectOvalPtr->bbox[0], y1,
984
                rectOvalPtr->bbox[2]-rectOvalPtr->bbox[0], y2-y1,
985
                rectOvalPtr->bbox[0]-rectOvalPtr->bbox[2]);
986
    } else {
987
        sprintf(pathCmd, "matrix currentmatrix\n%.15g %.15g translate %.15g %.15g scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n",
988
                (rectOvalPtr->bbox[0] + rectOvalPtr->bbox[2])/2, (y1 + y2)/2,
989
                (rectOvalPtr->bbox[2] - rectOvalPtr->bbox[0])/2, (y1 - y2)/2);
990
    }
991
 
992
    /*
993
     * First draw the filled area of the rectangle.
994
     */
995
 
996
    if (rectOvalPtr->fillColor != NULL) {
997
        Tcl_AppendResult(interp, pathCmd, (char *) NULL);
998
        if (Tk_CanvasPsColor(interp, canvas, rectOvalPtr->fillColor)
999
                != TCL_OK) {
1000
            return TCL_ERROR;
1001
        }
1002
        if (rectOvalPtr->fillStipple != None) {
1003
            Tcl_AppendResult(interp, "clip ", (char *) NULL);
1004
            if (Tk_CanvasPsStipple(interp, canvas, rectOvalPtr->fillStipple)
1005
                    != TCL_OK) {
1006
                return TCL_ERROR;
1007
            }
1008
            if (rectOvalPtr->outlineColor != NULL) {
1009
                Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL);
1010
            }
1011
        } else {
1012
            Tcl_AppendResult(interp, "fill\n", (char *) NULL);
1013
        }
1014
    }
1015
 
1016
    /*
1017
     * Now draw the outline, if there is one.
1018
     */
1019
 
1020
    if (rectOvalPtr->outlineColor != NULL) {
1021
        Tcl_AppendResult(interp, pathCmd, (char *) NULL);
1022
        sprintf(string, "%d setlinewidth", rectOvalPtr->width);
1023
        Tcl_AppendResult(interp, string,
1024
                " 0 setlinejoin 2 setlinecap\n", (char *) NULL);
1025
        if (Tk_CanvasPsColor(interp, canvas, rectOvalPtr->outlineColor)
1026
                != TCL_OK) {
1027
            return TCL_ERROR;
1028
        }
1029
        Tcl_AppendResult(interp, "stroke\n", (char *) NULL);
1030
    }
1031
    return TCL_OK;
1032
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.