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

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [generic/] [tkCanvArc.c] - Blame information for rev 1780

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

Line No. Rev Author Line
1 578 markom
/*
2
 * tkCanvArc.c --
3
 *
4
 *      This file implements arc items for canvas widgets.
5
 *
6
 * Copyright (c) 1992-1994 The Regents of the University of California.
7
 * Copyright (c) 1994-1995 Sun Microsystems, Inc.
8
 *
9
 * See the file "license.terms" for information on usage and redistribution
10
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11
 *
12
 * RCS: @(#) $Id: tkCanvArc.c,v 1.1.1.1 2002-01-16 10:25:50 markom Exp $
13
 */
14
 
15
#include <stdio.h>
16
#include "tkPort.h"
17
#include "tkInt.h"
18
 
19
/*
20
 * The structure below defines the record for each arc item.
21
 */
22
 
23
typedef struct ArcItem  {
24
    Tk_Item header;             /* Generic stuff that's the same for all
25
                                 * types.  MUST BE FIRST IN STRUCTURE. */
26
    double bbox[4];             /* Coordinates (x1, y1, x2, y2) of bounding
27
                                 * box for oval of which arc is a piece. */
28
    double start;               /* Angle at which arc begins, in degrees
29
                                 * between 0 and 360. */
30
    double extent;              /* Extent of arc (angular distance from
31
                                 * start to end of arc) in degrees between
32
                                 * -360 and 360. */
33
    double *outlinePtr;         /* Points to (x,y) coordinates for points
34
                                 * that define one or two closed polygons
35
                                 * representing the portion of the outline
36
                                 * that isn't part of the arc (the V-shape
37
                                 * for a pie slice or a line-like segment
38
                                 * for a chord).  Malloc'ed. */
39
    int numOutlinePoints;       /* Number of points at outlinePtr.  Zero
40
                                 * means no space allocated. */
41
    int width;                  /* Width of outline (in pixels). */
42
    XColor *outlineColor;       /* Color for outline.  NULL means don't
43
                                 * draw outline. */
44
    XColor *fillColor;          /* Color for filling arc (used for drawing
45
                                 * outline too when style is "arc").  NULL
46
                                 * means don't fill arc. */
47
    Pixmap fillStipple;         /* Stipple bitmap for filling item. */
48
    Pixmap outlineStipple;      /* Stipple bitmap for outline. */
49
    Tk_Uid style;               /* How to draw arc: arc, chord, or pieslice. */
50
    GC outlineGC;               /* Graphics context for outline. */
51
    GC fillGC;                  /* Graphics context for filling item. */
52
    double center1[2];          /* Coordinates of center of arc outline at
53
                                 * start (see ComputeArcOutline). */
54
    double center2[2];          /* Coordinates of center of arc outline at
55
                                 * start+extent (see ComputeArcOutline). */
56
} ArcItem;
57
 
58
/*
59
 * The definitions below define the sizes of the polygons used to
60
 * display outline information for various styles of arcs:
61
 */
62
 
63
#define CHORD_OUTLINE_PTS       7
64
#define PIE_OUTLINE1_PTS        6
65
#define PIE_OUTLINE2_PTS        7
66
 
67
/*
68
 * Information used for parsing configuration specs:
69
 */
70
 
71
static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,
72
    Tk_CanvasTagsPrintProc, (ClientData) NULL
73
};
74
 
75
static Tk_ConfigSpec configSpecs[] = {
76
    {TK_CONFIG_DOUBLE, "-extent", (char *) NULL, (char *) NULL,
77
        "90", Tk_Offset(ArcItem, extent), TK_CONFIG_DONT_SET_DEFAULT},
78
    {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,
79
        (char *) NULL, Tk_Offset(ArcItem, fillColor), TK_CONFIG_NULL_OK},
80
    {TK_CONFIG_COLOR, "-outline", (char *) NULL, (char *) NULL,
81
        "black", Tk_Offset(ArcItem, outlineColor), TK_CONFIG_NULL_OK},
82
    {TK_CONFIG_BITMAP, "-outlinestipple", (char *) NULL, (char *) NULL,
83
        (char *) NULL, Tk_Offset(ArcItem, outlineStipple), TK_CONFIG_NULL_OK},
84
    {TK_CONFIG_DOUBLE, "-start", (char *) NULL, (char *) NULL,
85
        "0", Tk_Offset(ArcItem, start), TK_CONFIG_DONT_SET_DEFAULT},
86
    {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,
87
        (char *) NULL, Tk_Offset(ArcItem, fillStipple), TK_CONFIG_NULL_OK},
88
    {TK_CONFIG_UID, "-style", (char *) NULL, (char *) NULL,
89
        "pieslice", Tk_Offset(ArcItem, style), TK_CONFIG_DONT_SET_DEFAULT},
90
    {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
91
        (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
92
    {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
93
        "1", Tk_Offset(ArcItem, width), TK_CONFIG_DONT_SET_DEFAULT},
94
    {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
95
        (char *) NULL, 0, 0}
96
};
97
 
98
/*
99
 * Prototypes for procedures defined in this file:
100
 */
101
 
102
static void             ComputeArcBbox _ANSI_ARGS_((Tk_Canvas canvas,
103
                            ArcItem *arcPtr));
104
static int              ConfigureArc _ANSI_ARGS_((Tcl_Interp *interp,
105
                            Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
106
                            char **argv, int flags));
107
static int              CreateArc _ANSI_ARGS_((Tcl_Interp *interp,
108
                            Tk_Canvas canvas, struct Tk_Item *itemPtr,
109
                            int argc, char **argv));
110
static void             DeleteArc _ANSI_ARGS_((Tk_Canvas canvas,
111
                            Tk_Item *itemPtr, Display *display));
112
static void             DisplayArc _ANSI_ARGS_((Tk_Canvas canvas,
113
                            Tk_Item *itemPtr, Display *display, Drawable dst,
114
                            int x, int y, int width, int height));
115
static int              ArcCoords _ANSI_ARGS_((Tcl_Interp *interp,
116
                            Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
117
                            char **argv));
118
static int              ArcToArea _ANSI_ARGS_((Tk_Canvas canvas,
119
                            Tk_Item *itemPtr, double *rectPtr));
120
static double           ArcToPoint _ANSI_ARGS_((Tk_Canvas canvas,
121
                            Tk_Item *itemPtr, double *coordPtr));
122
static int              ArcToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
123
                            Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
124
static void             ScaleArc _ANSI_ARGS_((Tk_Canvas canvas,
125
                            Tk_Item *itemPtr, double originX, double originY,
126
                            double scaleX, double scaleY));
127
static void             TranslateArc _ANSI_ARGS_((Tk_Canvas canvas,
128
                            Tk_Item *itemPtr, double deltaX, double deltaY));
129
static int              AngleInRange _ANSI_ARGS_((double x, double y,
130
                            double start, double extent));
131
static void             ComputeArcOutline _ANSI_ARGS_((ArcItem *arcPtr));
132
static int              HorizLineToArc _ANSI_ARGS_((double x1, double x2,
133
                            double y, double rx, double ry,
134
                            double start, double extent));
135
static int              VertLineToArc _ANSI_ARGS_((double x, double y1,
136
                            double y2, double rx, double ry,
137
                            double start, double extent));
138
 
139
/*
140
 * The structures below defines the arc item types by means of procedures
141
 * that can be invoked by generic item code.
142
 */
143
 
144
Tk_ItemType tkArcType = {
145
    "arc",                              /* name */
146
    sizeof(ArcItem),                    /* itemSize */
147
    CreateArc,                          /* createProc */
148
    configSpecs,                        /* configSpecs */
149
    ConfigureArc,                       /* configureProc */
150
    ArcCoords,                          /* coordProc */
151
    DeleteArc,                          /* deleteProc */
152
    DisplayArc,                         /* displayProc */
153
    0,                                   /* alwaysRedraw */
154
    ArcToPoint,                         /* pointProc */
155
    ArcToArea,                          /* areaProc */
156
    ArcToPostscript,                    /* postscriptProc */
157
    ScaleArc,                           /* scaleProc */
158
    TranslateArc,                       /* translateProc */
159
    (Tk_ItemIndexProc *) NULL,          /* indexProc */
160
    (Tk_ItemCursorProc *) NULL,         /* icursorProc */
161
    (Tk_ItemSelectionProc *) NULL,      /* selectionProc */
162
    (Tk_ItemInsertProc *) NULL,         /* insertProc */
163
    (Tk_ItemDCharsProc *) NULL,         /* dTextProc */
164
    (Tk_ItemType *) NULL                /* nextPtr */
165
};
166
 
167
#ifndef PI
168
#    define PI 3.14159265358979323846
169
#endif
170
 
171
/*
172
 * The uid's below comprise the legal values for the "-style"
173
 * option for arcs.
174
 */
175
 
176
static Tk_Uid arcUid =  NULL;
177
static Tk_Uid chordUid =  NULL;
178
static Tk_Uid pieSliceUid = NULL;
179
 
180
/*
181
 *--------------------------------------------------------------
182
 *
183
 * CreateArc --
184
 *
185
 *      This procedure is invoked to create a new arc item in
186
 *      a canvas.
187
 *
188
 * Results:
189
 *      A standard Tcl return value.  If an error occurred in
190
 *      creating the item, then an error message is left in
191
 *      interp->result;  in this case itemPtr is
192
 *      left uninitialized, so it can be safely freed by the
193
 *      caller.
194
 *
195
 * Side effects:
196
 *      A new arc item is created.
197
 *
198
 *--------------------------------------------------------------
199
 */
200
 
201
static int
202
CreateArc(interp, canvas, itemPtr, argc, argv)
203
    Tcl_Interp *interp;                 /* Interpreter for error reporting. */
204
    Tk_Canvas canvas;                   /* Canvas to hold new item. */
205
    Tk_Item *itemPtr;                   /* Record to hold new item;  header
206
                                         * has been initialized by caller. */
207
    int argc;                           /* Number of arguments in argv. */
208
    char **argv;                        /* Arguments describing arc. */
209
{
210
    ArcItem *arcPtr = (ArcItem *) itemPtr;
211
 
212
    if (argc < 4) {
213
        Tcl_AppendResult(interp, "wrong # args: should be \"",
214
                Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
215
                itemPtr->typePtr->name, " x1 y1 x2 y2 ?options?\"",
216
                (char *) NULL);
217
        return TCL_ERROR;
218
    }
219
 
220
    /*
221
     * Carry out once-only initialization.
222
     */
223
 
224
    if (arcUid == NULL) {
225
        arcUid = Tk_GetUid("arc");
226
        chordUid = Tk_GetUid("chord");
227
        pieSliceUid = Tk_GetUid("pieslice");
228
    }
229
 
230
    /*
231
     * Carry out initialization that is needed in order to clean
232
     * up after errors during the the remainder of this procedure.
233
     */
234
 
235
    arcPtr->start = 0;
236
    arcPtr->extent = 90;
237
    arcPtr->outlinePtr = NULL;
238
    arcPtr->numOutlinePoints = 0;
239
    arcPtr->width = 1;
240
    arcPtr->outlineColor = NULL;
241
    arcPtr->fillColor = NULL;
242
    arcPtr->fillStipple = None;
243
    arcPtr->outlineStipple = None;
244
    arcPtr->style = pieSliceUid;
245
    arcPtr->outlineGC = None;
246
    arcPtr->fillGC = None;
247
 
248
    /*
249
     * Process the arguments to fill in the item record.
250
     */
251
 
252
    if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &arcPtr->bbox[0]) != TCL_OK)
253
            || (Tk_CanvasGetCoord(interp, canvas, argv[1],
254
                &arcPtr->bbox[1]) != TCL_OK)
255
            || (Tk_CanvasGetCoord(interp, canvas, argv[2],
256
                    &arcPtr->bbox[2]) != TCL_OK)
257
            || (Tk_CanvasGetCoord(interp, canvas, argv[3],
258
                    &arcPtr->bbox[3]) != TCL_OK)) {
259
        return TCL_ERROR;
260
    }
261
 
262
    if (ConfigureArc(interp, canvas, itemPtr, argc-4, argv+4, 0) != TCL_OK) {
263
        DeleteArc(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
264
        return TCL_ERROR;
265
    }
266
    return TCL_OK;
267
}
268
 
269
/*
270
 *--------------------------------------------------------------
271
 *
272
 * ArcCoords --
273
 *
274
 *      This procedure is invoked to process the "coords" widget
275
 *      command on arcs.  See the user documentation for details
276
 *      on what it does.
277
 *
278
 * Results:
279
 *      Returns TCL_OK or TCL_ERROR, and sets interp->result.
280
 *
281
 * Side effects:
282
 *      The coordinates for the given item may be changed.
283
 *
284
 *--------------------------------------------------------------
285
 */
286
 
287
static int
288
ArcCoords(interp, canvas, itemPtr, argc, argv)
289
    Tcl_Interp *interp;                 /* Used for error reporting. */
290
    Tk_Canvas canvas;                   /* Canvas containing item. */
291
    Tk_Item *itemPtr;                   /* Item whose coordinates are to be
292
                                         * read or modified. */
293
    int argc;                           /* Number of coordinates supplied in
294
                                         * argv. */
295
    char **argv;                        /* Array of coordinates: x1, y1,
296
                                         * x2, y2, ... */
297
{
298
    ArcItem *arcPtr = (ArcItem *) itemPtr;
299
    char c0[TCL_DOUBLE_SPACE], c1[TCL_DOUBLE_SPACE];
300
    char c2[TCL_DOUBLE_SPACE], c3[TCL_DOUBLE_SPACE];
301
 
302
    if (argc == 0) {
303
        Tcl_PrintDouble(interp, arcPtr->bbox[0], c0);
304
        Tcl_PrintDouble(interp, arcPtr->bbox[1], c1);
305
        Tcl_PrintDouble(interp, arcPtr->bbox[2], c2);
306
        Tcl_PrintDouble(interp, arcPtr->bbox[3], c3);
307
        Tcl_AppendResult(interp, c0, " ", c1, " ", c2, " ", c3,
308
                (char *) NULL);
309
    } else if (argc == 4) {
310
        if ((Tk_CanvasGetCoord(interp, canvas, argv[0],
311
                    &arcPtr->bbox[0]) != TCL_OK)
312
                || (Tk_CanvasGetCoord(interp, canvas, argv[1],
313
                    &arcPtr->bbox[1]) != TCL_OK)
314
                || (Tk_CanvasGetCoord(interp, canvas, argv[2],
315
                        &arcPtr->bbox[2]) != TCL_OK)
316
                || (Tk_CanvasGetCoord(interp, canvas, argv[3],
317
                        &arcPtr->bbox[3]) != TCL_OK)) {
318
            return TCL_ERROR;
319
        }
320
        ComputeArcBbox(canvas, arcPtr);
321
    } else {
322
        sprintf(interp->result,
323
                "wrong # coordinates: expected 0 or 4, got %d",
324
                argc);
325
        return TCL_ERROR;
326
    }
327
    return TCL_OK;
328
}
329
 
330
/*
331
 *--------------------------------------------------------------
332
 *
333
 * ConfigureArc --
334
 *
335
 *      This procedure is invoked to configure various aspects
336
 *      of a arc item, such as its outline and fill colors.
337
 *
338
 * Results:
339
 *      A standard Tcl result code.  If an error occurs, then
340
 *      an error message is left in interp->result.
341
 *
342
 * Side effects:
343
 *      Configuration information, such as colors and stipple
344
 *      patterns, may be set for itemPtr.
345
 *
346
 *--------------------------------------------------------------
347
 */
348
 
349
static int
350
ConfigureArc(interp, canvas, itemPtr, argc, argv, flags)
351
    Tcl_Interp *interp;         /* Used for error reporting. */
352
    Tk_Canvas canvas;           /* Canvas containing itemPtr. */
353
    Tk_Item *itemPtr;           /* Arc item to reconfigure. */
354
    int argc;                   /* Number of elements in argv.  */
355
    char **argv;                /* Arguments describing things to configure. */
356
    int flags;                  /* Flags to pass to Tk_ConfigureWidget. */
357
{
358
    ArcItem *arcPtr = (ArcItem *) itemPtr;
359
    XGCValues gcValues;
360
    GC newGC;
361
    unsigned long mask;
362
    int i;
363
    Tk_Window tkwin;
364
 
365
    tkwin = Tk_CanvasTkwin(canvas);
366
    if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, argv,
367
            (char *) arcPtr, flags) != TCL_OK) {
368
        return TCL_ERROR;
369
    }
370
 
371
    /*
372
     * A few of the options require additional processing, such as
373
     * style and graphics contexts.
374
     */
375
 
376
    i = (int) (arcPtr->start/360.0);
377
    arcPtr->start -= i*360.0;
378
    if (arcPtr->start < 0) {
379
        arcPtr->start += 360.0;
380
    }
381
    i = (int) (arcPtr->extent/360.0);
382
    arcPtr->extent -= i*360.0;
383
 
384
    if ((arcPtr->style != arcUid) && (arcPtr->style != chordUid)
385
            && (arcPtr->style != pieSliceUid)) {
386
        Tcl_AppendResult(interp, "bad -style option \"",
387
                arcPtr->style, "\": must be arc, chord, or pieslice",
388
                (char *) NULL);
389
        arcPtr->style = pieSliceUid;
390
        return TCL_ERROR;
391
    }
392
 
393
    if (arcPtr->width < 0) {
394
        arcPtr->width = 1;
395
    }
396
    if (arcPtr->outlineColor == NULL) {
397
        newGC = None;
398
    } else {
399
        gcValues.foreground = arcPtr->outlineColor->pixel;
400
        gcValues.cap_style = CapButt;
401
        gcValues.line_width = arcPtr->width;
402
        mask = GCForeground|GCCapStyle|GCLineWidth;
403
        if (arcPtr->outlineStipple != None) {
404
            gcValues.stipple = arcPtr->outlineStipple;
405
            gcValues.fill_style = FillStippled;
406
            mask |= GCStipple|GCFillStyle;
407
        }
408
        newGC = Tk_GetGCColor(tkwin, mask, &gcValues, arcPtr->outlineColor,
409
                              NULL);
410
    }
411
    if (arcPtr->outlineGC != None) {
412
        Tk_FreeGC(Tk_Display(tkwin), arcPtr->outlineGC);
413
    }
414
    arcPtr->outlineGC = newGC;
415
 
416
    if ((arcPtr->fillColor == NULL) || (arcPtr->style == arcUid)) {
417
        newGC = None;
418
    } else {
419
        gcValues.foreground = arcPtr->fillColor->pixel;
420
        if (arcPtr->style == chordUid) {
421
            gcValues.arc_mode = ArcChord;
422
        } else {
423
            gcValues.arc_mode = ArcPieSlice;
424
        }
425
        mask = GCForeground|GCArcMode;
426
        if (arcPtr->fillStipple != None) {
427
            gcValues.stipple = arcPtr->fillStipple;
428
            gcValues.fill_style = FillStippled;
429
            mask |= GCStipple|GCFillStyle;
430
        }
431
        newGC = Tk_GetGCColor(tkwin, mask, &gcValues, arcPtr->fillColor, NULL);
432
    }
433
    if (arcPtr->fillGC != None) {
434
        Tk_FreeGC(Tk_Display(tkwin), arcPtr->fillGC);
435
    }
436
    arcPtr->fillGC = newGC;
437
 
438
    ComputeArcBbox(canvas, arcPtr);
439
    return TCL_OK;
440
}
441
 
442
/*
443
 *--------------------------------------------------------------
444
 *
445
 * DeleteArc --
446
 *
447
 *      This procedure is called to clean up the data structure
448
 *      associated with a arc item.
449
 *
450
 * Results:
451
 *      None.
452
 *
453
 * Side effects:
454
 *      Resources associated with itemPtr are released.
455
 *
456
 *--------------------------------------------------------------
457
 */
458
 
459
static void
460
DeleteArc(canvas, itemPtr, display)
461
    Tk_Canvas canvas;                   /* Info about overall canvas. */
462
    Tk_Item *itemPtr;                   /* Item that is being deleted. */
463
    Display *display;                   /* Display containing window for
464
                                         * canvas. */
465
{
466
    ArcItem *arcPtr = (ArcItem *) itemPtr;
467
 
468
    if (arcPtr->numOutlinePoints != 0) {
469
        ckfree((char *) arcPtr->outlinePtr);
470
    }
471
    if (arcPtr->outlineColor != NULL) {
472
        Tk_FreeColor(arcPtr->outlineColor);
473
    }
474
    if (arcPtr->fillColor != NULL) {
475
        Tk_FreeColor(arcPtr->fillColor);
476
    }
477
    if (arcPtr->fillStipple != None) {
478
        Tk_FreeBitmap(display, arcPtr->fillStipple);
479
    }
480
    if (arcPtr->outlineStipple != None) {
481
        Tk_FreeBitmap(display, arcPtr->outlineStipple);
482
    }
483
    if (arcPtr->outlineGC != None) {
484
        Tk_FreeGC(display, arcPtr->outlineGC);
485
    }
486
    if (arcPtr->fillGC != None) {
487
        Tk_FreeGC(display, arcPtr->fillGC);
488
    }
489
}
490
 
491
/*
492
 *--------------------------------------------------------------
493
 *
494
 * ComputeArcBbox --
495
 *
496
 *      This procedure is invoked to compute the bounding box of
497
 *      all the pixels that may be drawn as part of an arc.
498
 *
499
 * Results:
500
 *      None.
501
 *
502
 * Side effects:
503
 *      The fields x1, y1, x2, and y2 are updated in the header
504
 *      for itemPtr.
505
 *
506
 *--------------------------------------------------------------
507
 */
508
 
509
        /* ARGSUSED */
510
static void
511
ComputeArcBbox(canvas, arcPtr)
512
    Tk_Canvas canvas;                   /* Canvas that contains item. */
513
    ArcItem *arcPtr;                    /* Item whose bbox is to be
514
                                         * recomputed. */
515
{
516
    double tmp, center[2], point[2];
517
 
518
    /*
519
     * Make sure that the first coordinates are the lowest ones.
520
     */
521
 
522
    if (arcPtr->bbox[1] > arcPtr->bbox[3]) {
523
        double tmp;
524
        tmp = arcPtr->bbox[3];
525
        arcPtr->bbox[3] = arcPtr->bbox[1];
526
        arcPtr->bbox[1] = tmp;
527
    }
528
    if (arcPtr->bbox[0] > arcPtr->bbox[2]) {
529
        double tmp;
530
        tmp = arcPtr->bbox[2];
531
        arcPtr->bbox[2] = arcPtr->bbox[0];
532
        arcPtr->bbox[0] = tmp;
533
    }
534
 
535
    ComputeArcOutline(arcPtr);
536
 
537
    /*
538
     * To compute the bounding box, start with the the bbox formed
539
     * by the two endpoints of the arc.  Then add in the center of
540
     * the arc's oval (if relevant) and the 3-o'clock, 6-o'clock,
541
     * 9-o'clock, and 12-o'clock positions, if they are relevant.
542
     */
543
 
544
    arcPtr->header.x1 = arcPtr->header.x2 = (int) arcPtr->center1[0];
545
    arcPtr->header.y1 = arcPtr->header.y2 = (int) arcPtr->center1[1];
546
    TkIncludePoint((Tk_Item *) arcPtr, arcPtr->center2);
547
    center[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2;
548
    center[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2;
549
    if (arcPtr->style == pieSliceUid) {
550
        TkIncludePoint((Tk_Item *) arcPtr, center);
551
    }
552
 
553
    tmp = -arcPtr->start;
554
    if (tmp < 0) {
555
        tmp += 360.0;
556
    }
557
    if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
558
        point[0] = arcPtr->bbox[2];
559
        point[1] = center[1];
560
        TkIncludePoint((Tk_Item *) arcPtr, point);
561
    }
562
    tmp = 90.0 - arcPtr->start;
563
    if (tmp < 0) {
564
        tmp += 360.0;
565
    }
566
    if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
567
        point[0] = center[0];
568
        point[1] = arcPtr->bbox[1];
569
        TkIncludePoint((Tk_Item *) arcPtr, point);
570
    }
571
    tmp = 180.0 - arcPtr->start;
572
    if (tmp < 0) {
573
        tmp += 360.0;
574
    }
575
    if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
576
        point[0] = arcPtr->bbox[0];
577
        point[1] = center[1];
578
        TkIncludePoint((Tk_Item *) arcPtr, point);
579
    }
580
    tmp = 270.0 - arcPtr->start;
581
    if (tmp < 0) {
582
        tmp += 360.0;
583
    }
584
    if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
585
        point[0] = center[0];
586
        point[1] = arcPtr->bbox[3];
587
        TkIncludePoint((Tk_Item *) arcPtr, point);
588
    }
589
 
590
    /*
591
     * Lastly, expand by the width of the arc (if the arc's outline is
592
     * being drawn) and add one extra pixel just for safety.
593
     */
594
 
595
    if (arcPtr->outlineColor == NULL) {
596
        tmp = 1;
597
    } else {
598
        tmp = (arcPtr->width + 1)/2 + 1;
599
    }
600
    arcPtr->header.x1 -= (int) tmp;
601
    arcPtr->header.y1 -= (int) tmp;
602
    arcPtr->header.x2 += (int) tmp;
603
    arcPtr->header.y2 += (int) tmp;
604
}
605
 
606
/*
607
 *--------------------------------------------------------------
608
 *
609
 * DisplayArc --
610
 *
611
 *      This procedure is invoked to draw an arc item in a given
612
 *      drawable.
613
 *
614
 * Results:
615
 *      None.
616
 *
617
 * Side effects:
618
 *      ItemPtr is drawn in drawable using the transformation
619
 *      information in canvas.
620
 *
621
 *--------------------------------------------------------------
622
 */
623
 
624
static void
625
DisplayArc(canvas, itemPtr, display, drawable, x, y, width, height)
626
    Tk_Canvas canvas;                   /* Canvas that contains item. */
627
    Tk_Item *itemPtr;                   /* Item to be displayed. */
628
    Display *display;                   /* Display on which to draw item. */
629
    Drawable drawable;                  /* Pixmap or window in which to draw
630
                                         * item. */
631
    int x, y, width, height;            /* Describes region of canvas that
632
                                         * must be redisplayed (not used). */
633
{
634
    ArcItem *arcPtr = (ArcItem *) itemPtr;
635
    short x1, y1, x2, y2;
636
    int start, extent;
637
 
638
    /*
639
     * Compute the screen coordinates of the bounding box for the item,
640
     * plus integer values for the angles.
641
     */
642
 
643
    Tk_CanvasDrawableCoords(canvas, arcPtr->bbox[0], arcPtr->bbox[1],
644
            &x1, &y1);
645
    Tk_CanvasDrawableCoords(canvas, arcPtr->bbox[2], arcPtr->bbox[3],
646
            &x2, &y2);
647
    if (x2 <= x1) {
648
        x2 = x1+1;
649
    }
650
    if (y2 <= y1) {
651
        y2 = y1+1;
652
    }
653
    start = (int) ((64*arcPtr->start) + 0.5);
654
    extent = (int) ((64*arcPtr->extent) + 0.5);
655
 
656
    /*
657
     * Display filled arc first (if wanted), then outline.  If the extent
658
     * is zero then don't invoke XFillArc or XDrawArc, since this causes
659
     * some window servers to crash and should be a no-op anyway.
660
     */
661
 
662
    if ((arcPtr->fillGC != None) && (extent != 0)) {
663
        if (arcPtr->fillStipple != None) {
664
            Tk_CanvasSetStippleOrigin(canvas, arcPtr->fillGC);
665
        }
666
        XFillArc(display, drawable, arcPtr->fillGC, x1, y1, (unsigned) (x2-x1),
667
                (unsigned) (y2-y1), start, extent);
668
        if (arcPtr->fillStipple != None) {
669
            XSetTSOrigin(display, arcPtr->fillGC, 0, 0);
670
        }
671
    }
672
    if (arcPtr->outlineGC != None) {
673
        if (arcPtr->outlineStipple != None) {
674
            Tk_CanvasSetStippleOrigin(canvas, arcPtr->outlineGC);
675
        }
676
        if (extent != 0) {
677
            XDrawArc(display, drawable, arcPtr->outlineGC, x1, y1,
678
                    (unsigned) (x2-x1), (unsigned) (y2-y1), start, extent);
679
        }
680
 
681
        /*
682
         * If the outline width is very thin, don't use polygons to draw
683
         * the linear parts of the outline (this often results in nothing
684
         * being displayed); just draw lines instead.
685
         */
686
 
687
        if (arcPtr->width <= 2) {
688
            Tk_CanvasDrawableCoords(canvas, arcPtr->center1[0],
689
                    arcPtr->center1[1], &x1, &y1);
690
            Tk_CanvasDrawableCoords(canvas, arcPtr->center2[0],
691
                    arcPtr->center2[1], &x2, &y2);
692
 
693
            if (arcPtr->style == chordUid) {
694
                XDrawLine(display, drawable, arcPtr->outlineGC,
695
                        x1, y1, x2, y2);
696
            } else if (arcPtr->style == pieSliceUid) {
697
                short cx, cy;
698
 
699
                Tk_CanvasDrawableCoords(canvas,
700
                        (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0,
701
                        (arcPtr->bbox[1] + arcPtr->bbox[3])/2.0, &cx, &cy);
702
                XDrawLine(display, drawable, arcPtr->outlineGC,
703
                        cx, cy, x1, y1);
704
                XDrawLine(display, drawable, arcPtr->outlineGC,
705
                        cx, cy, x2, y2);
706
            }
707
        } else {
708
            if (arcPtr->style == chordUid) {
709
                TkFillPolygon(canvas, arcPtr->outlinePtr, CHORD_OUTLINE_PTS,
710
                        display, drawable, arcPtr->outlineGC, None);
711
            } else if (arcPtr->style == pieSliceUid) {
712
                TkFillPolygon(canvas, arcPtr->outlinePtr, PIE_OUTLINE1_PTS,
713
                        display, drawable, arcPtr->outlineGC, None);
714
                TkFillPolygon(canvas, arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS,
715
                        PIE_OUTLINE2_PTS, display, drawable, arcPtr->outlineGC,
716
                        None);
717
            }
718
        }
719
        if (arcPtr->outlineStipple != None) {
720
            XSetTSOrigin(display, arcPtr->outlineGC, 0, 0);
721
        }
722
    }
723
}
724
 
725
/*
726
 *--------------------------------------------------------------
727
 *
728
 * ArcToPoint --
729
 *
730
 *      Computes the distance from a given point to a given
731
 *      arc, in canvas units.
732
 *
733
 * Results:
734
 *      The return value is 0 if the point whose x and y coordinates
735
 *      are coordPtr[0] and coordPtr[1] is inside the arc.  If the
736
 *      point isn't inside the arc then the return value is the
737
 *      distance from the point to the arc.  If itemPtr is filled,
738
 *      then anywhere in the interior is considered "inside"; if
739
 *      itemPtr isn't filled, then "inside" means only the area
740
 *      occupied by the outline.
741
 *
742
 * Side effects:
743
 *      None.
744
 *
745
 *--------------------------------------------------------------
746
 */
747
 
748
        /* ARGSUSED */
749
static double
750
ArcToPoint(canvas, itemPtr, pointPtr)
751
    Tk_Canvas canvas;           /* Canvas containing item. */
752
    Tk_Item *itemPtr;           /* Item to check against point. */
753
    double *pointPtr;           /* Pointer to x and y coordinates. */
754
{
755
    ArcItem *arcPtr = (ArcItem *) itemPtr;
756
    double vertex[2], pointAngle, diff, dist, newDist;
757
    double poly[8], polyDist, width, t1, t2;
758
    int filled, angleInRange;
759
 
760
    /*
761
     * See if the point is within the angular range of the arc.
762
     * Remember, X angles are backwards from the way we'd normally
763
     * think of them.  Also, compensate for any eccentricity of
764
     * the oval.
765
     */
766
 
767
    vertex[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0;
768
    vertex[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2.0;
769
    t1 = (pointPtr[1] - vertex[1])/(arcPtr->bbox[3] - arcPtr->bbox[1]);
770
    t2 = (pointPtr[0] - vertex[0])/(arcPtr->bbox[2] - arcPtr->bbox[0]);
771
    if ((t1 == 0.0) && (t2 == 0.0)) {
772
        pointAngle = 0;
773
    } else {
774
        pointAngle = -atan2(t1, t2)*180/PI;
775
    }
776
    diff = pointAngle - arcPtr->start;
777
    diff -= ((int) (diff/360.0) * 360.0);
778
    if (diff < 0) {
779
        diff += 360.0;
780
    }
781
    angleInRange = (diff <= arcPtr->extent) ||
782
            ((arcPtr->extent < 0) && ((diff - 360.0) >= arcPtr->extent));
783
 
784
    /*
785
     * Now perform different tests depending on what kind of arc
786
     * we're dealing with.
787
     */
788
 
789
    if (arcPtr->style == arcUid) {
790
        if (angleInRange) {
791
            return TkOvalToPoint(arcPtr->bbox, (double) arcPtr->width,
792
                    0, pointPtr);
793
        }
794
        dist = hypot(pointPtr[0] - arcPtr->center1[0],
795
                pointPtr[1] - arcPtr->center1[1]);
796
        newDist = hypot(pointPtr[0] - arcPtr->center2[0],
797
                pointPtr[1] - arcPtr->center2[1]);
798
        if (newDist < dist) {
799
            return newDist;
800
        }
801
        return dist;
802
    }
803
 
804
    if ((arcPtr->fillGC != None) || (arcPtr->outlineGC == None)) {
805
        filled = 1;
806
    } else {
807
        filled = 0;
808
    }
809
    if (arcPtr->outlineGC == None) {
810
        width = 0.0;
811
    } else {
812
        width = arcPtr->width;
813
    }
814
 
815
    if (arcPtr->style == pieSliceUid) {
816
        if (width > 1.0) {
817
            dist = TkPolygonToPoint(arcPtr->outlinePtr, PIE_OUTLINE1_PTS,
818
                    pointPtr);
819
            newDist = TkPolygonToPoint(arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS,
820
                        PIE_OUTLINE2_PTS, pointPtr);
821
        } else {
822
            dist = TkLineToPoint(vertex, arcPtr->center1, pointPtr);
823
            newDist = TkLineToPoint(vertex, arcPtr->center2, pointPtr);
824
        }
825
        if (newDist < dist) {
826
            dist = newDist;
827
        }
828
        if (angleInRange) {
829
            newDist = TkOvalToPoint(arcPtr->bbox, width, filled, pointPtr);
830
            if (newDist < dist) {
831
                dist = newDist;
832
            }
833
        }
834
        return dist;
835
    }
836
 
837
    /*
838
     * This is a chord-style arc.  We have to deal specially with the
839
     * triangular piece that represents the difference between a
840
     * chord-style arc and a pie-slice arc (for small angles this piece
841
     * is excluded here where it would be included for pie slices;
842
     * for large angles the piece is included here but would be
843
     * excluded for pie slices).
844
     */
845
 
846
    if (width > 1.0) {
847
        dist = TkPolygonToPoint(arcPtr->outlinePtr, CHORD_OUTLINE_PTS,
848
                    pointPtr);
849
    } else {
850
        dist = TkLineToPoint(arcPtr->center1, arcPtr->center2, pointPtr);
851
    }
852
    poly[0] = poly[6] = vertex[0];
853
    poly[1] = poly[7] = vertex[1];
854
    poly[2] = arcPtr->center1[0];
855
    poly[3] = arcPtr->center1[1];
856
    poly[4] = arcPtr->center2[0];
857
    poly[5] = arcPtr->center2[1];
858
    polyDist = TkPolygonToPoint(poly, 4, pointPtr);
859
    if (angleInRange) {
860
        if ((arcPtr->extent < -180.0) || (arcPtr->extent > 180.0)
861
                || (polyDist > 0.0)) {
862
            newDist = TkOvalToPoint(arcPtr->bbox, width, filled, pointPtr);
863
            if (newDist < dist) {
864
                dist = newDist;
865
            }
866
        }
867
    } else {
868
        if ((arcPtr->extent < -180.0) || (arcPtr->extent > 180.0)) {
869
            if (filled && (polyDist < dist)) {
870
                dist = polyDist;
871
            }
872
        }
873
    }
874
    return dist;
875
}
876
 
877
/*
878
 *--------------------------------------------------------------
879
 *
880
 * ArcToArea --
881
 *
882
 *      This procedure is called to determine whether an item
883
 *      lies entirely inside, entirely outside, or overlapping
884
 *      a given area.
885
 *
886
 * Results:
887
 *      -1 is returned if the item is entirely outside the area
888
 *      given by rectPtr, 0 if it overlaps, and 1 if it is entirely
889
 *      inside the given area.
890
 *
891
 * Side effects:
892
 *      None.
893
 *
894
 *--------------------------------------------------------------
895
 */
896
 
897
        /* ARGSUSED */
898
static int
899
ArcToArea(canvas, itemPtr, rectPtr)
900
    Tk_Canvas canvas;           /* Canvas containing item. */
901
    Tk_Item *itemPtr;           /* Item to check against arc. */
902
    double *rectPtr;            /* Pointer to array of four coordinates
903
                                 * (x1, y1, x2, y2) describing rectangular
904
                                 * area.  */
905
{
906
    ArcItem *arcPtr = (ArcItem *) itemPtr;
907
    double rx, ry;              /* Radii for transformed oval:  these define
908
                                 * an oval centered at the origin. */
909
    double tRect[4];            /* Transformed version of x1, y1, x2, y2,
910
                                 * for coord. system where arc is centered
911
                                 * on the origin. */
912
    double center[2], width, angle, tmp;
913
    double points[20], *pointPtr;
914
    int numPoints, filled;
915
    int inside;                 /* Non-zero means every test so far suggests
916
                                 * that arc is inside rectangle.  0 means
917
                                 * every test so far shows arc to be outside
918
                                 * of rectangle. */
919
    int newInside;
920
 
921
    if ((arcPtr->fillGC != None) || (arcPtr->outlineGC == None)) {
922
        filled = 1;
923
    } else {
924
        filled = 0;
925
    }
926
    if (arcPtr->outlineGC == None) {
927
        width = 0.0;
928
    } else {
929
        width = arcPtr->width;
930
    }
931
 
932
    /*
933
     * Transform both the arc and the rectangle so that the arc's oval
934
     * is centered on the origin.
935
     */
936
 
937
    center[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0;
938
    center[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2.0;
939
    tRect[0] = rectPtr[0] - center[0];
940
    tRect[1] = rectPtr[1] - center[1];
941
    tRect[2] = rectPtr[2] - center[0];
942
    tRect[3] = rectPtr[3] - center[1];
943
    rx = arcPtr->bbox[2] - center[0] + width/2.0;
944
    ry = arcPtr->bbox[3] - center[1] + width/2.0;
945
 
946
    /*
947
     * Find the extreme points of the arc and see whether these are all
948
     * inside the rectangle (in which case we're done), partly in and
949
     * partly out (in which case we're done), or all outside (in which
950
     * case we have more work to do).  The extreme points include the
951
     * following, which are checked in order:
952
     *
953
     * 1. The outside points of the arc, corresponding to start and
954
     *    extent.
955
     * 2. The center of the arc (but only in pie-slice mode).
956
     * 3. The 12, 3, 6, and 9-o'clock positions (but only if the arc
957
     *    includes those angles).
958
     */
959
 
960
    pointPtr = points;
961
    angle = -arcPtr->start*(PI/180.0);
962
    pointPtr[0] = rx*cos(angle);
963
    pointPtr[1] = ry*sin(angle);
964
    angle += -arcPtr->extent*(PI/180.0);
965
    pointPtr[2] = rx*cos(angle);
966
    pointPtr[3] = ry*sin(angle);
967
    numPoints = 2;
968
    pointPtr += 4;
969
 
970
    if ((arcPtr->style == pieSliceUid) && (arcPtr->extent < 180.0)) {
971
        pointPtr[0] = 0.0;
972
        pointPtr[1] = 0.0;
973
        numPoints++;
974
        pointPtr += 2;
975
    }
976
 
977
    tmp = -arcPtr->start;
978
    if (tmp < 0) {
979
        tmp += 360.0;
980
    }
981
    if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
982
        pointPtr[0] = rx;
983
        pointPtr[1] = 0.0;
984
        numPoints++;
985
        pointPtr += 2;
986
    }
987
    tmp = 90.0 - arcPtr->start;
988
    if (tmp < 0) {
989
        tmp += 360.0;
990
    }
991
    if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
992
        pointPtr[0] = 0.0;
993
        pointPtr[1] = -ry;
994
        numPoints++;
995
        pointPtr += 2;
996
    }
997
    tmp = 180.0 - arcPtr->start;
998
    if (tmp < 0) {
999
        tmp += 360.0;
1000
    }
1001
    if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
1002
        pointPtr[0] = -rx;
1003
        pointPtr[1] = 0.0;
1004
        numPoints++;
1005
        pointPtr += 2;
1006
    }
1007
    tmp = 270.0 - arcPtr->start;
1008
    if (tmp < 0) {
1009
        tmp += 360.0;
1010
    }
1011
    if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
1012
        pointPtr[0] = 0.0;
1013
        pointPtr[1] = ry;
1014
        numPoints++;
1015
    }
1016
 
1017
    /*
1018
     * Now that we've located the extreme points, loop through them all
1019
     * to see which are inside the rectangle.
1020
     */
1021
 
1022
    inside = (points[0] > tRect[0]) && (points[0] < tRect[2])
1023
            && (points[1] > tRect[1]) && (points[1] < tRect[3]);
1024
    for (pointPtr = points+2; numPoints > 1; pointPtr += 2, numPoints--) {
1025
        newInside = (pointPtr[0] > tRect[0]) && (pointPtr[0] < tRect[2])
1026
                && (pointPtr[1] > tRect[1]) && (pointPtr[1] < tRect[3]);
1027
        if (newInside != inside) {
1028
            return 0;
1029
        }
1030
    }
1031
 
1032
    if (inside) {
1033
        return 1;
1034
    }
1035
 
1036
    /*
1037
     * So far, oval appears to be outside rectangle, but can't yet tell
1038
     * for sure.  Next, test each of the four sides of the rectangle
1039
     * against the bounding region for the arc.  If any intersections
1040
     * are found, then return "overlapping".  First, test against the
1041
     * polygon(s) forming the sides of a chord or pie-slice.
1042
     */
1043
 
1044
    if (arcPtr->style == pieSliceUid) {
1045
        if (width >= 1.0) {
1046
            if (TkPolygonToArea(arcPtr->outlinePtr, PIE_OUTLINE1_PTS,
1047
                    rectPtr) != -1)  {
1048
                return 0;
1049
            }
1050
            if (TkPolygonToArea(arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS,
1051
                    PIE_OUTLINE2_PTS, rectPtr) != -1) {
1052
                return 0;
1053
            }
1054
        } else {
1055
            if ((TkLineToArea(center, arcPtr->center1, rectPtr) != -1) ||
1056
                    (TkLineToArea(center, arcPtr->center2, rectPtr) != -1)) {
1057
                return 0;
1058
            }
1059
        }
1060
    } else if (arcPtr->style == chordUid) {
1061
        if (width >= 1.0) {
1062
            if (TkPolygonToArea(arcPtr->outlinePtr, CHORD_OUTLINE_PTS,
1063
                    rectPtr) != -1) {
1064
                return 0;
1065
            }
1066
        } else {
1067
            if (TkLineToArea(arcPtr->center1, arcPtr->center2,
1068
                    rectPtr) != -1) {
1069
                return 0;
1070
            }
1071
        }
1072
    }
1073
 
1074
    /*
1075
     * Next check for overlap between each of the four sides and the
1076
     * outer perimiter of the arc.  If the arc isn't filled, then also
1077
     * check the inner perimeter of the arc.
1078
     */
1079
 
1080
    if (HorizLineToArc(tRect[0], tRect[2], tRect[1], rx, ry, arcPtr->start,
1081
                arcPtr->extent)
1082
            || HorizLineToArc(tRect[0], tRect[2], tRect[3], rx, ry,
1083
                arcPtr->start, arcPtr->extent)
1084
            || VertLineToArc(tRect[0], tRect[1], tRect[3], rx, ry,
1085
                arcPtr->start, arcPtr->extent)
1086
            || VertLineToArc(tRect[2], tRect[1], tRect[3], rx, ry,
1087
                arcPtr->start, arcPtr->extent)) {
1088
        return 0;
1089
    }
1090
    if ((width > 1.0) && !filled) {
1091
        rx -= width;
1092
        ry -= width;
1093
        if (HorizLineToArc(tRect[0], tRect[2], tRect[1], rx, ry, arcPtr->start,
1094
                    arcPtr->extent)
1095
                || HorizLineToArc(tRect[0], tRect[2], tRect[3], rx, ry,
1096
                    arcPtr->start, arcPtr->extent)
1097
                || VertLineToArc(tRect[0], tRect[1], tRect[3], rx, ry,
1098
                    arcPtr->start, arcPtr->extent)
1099
                || VertLineToArc(tRect[2], tRect[1], tRect[3], rx, ry,
1100
                    arcPtr->start, arcPtr->extent)) {
1101
            return 0;
1102
        }
1103
    }
1104
 
1105
    /*
1106
     * The arc still appears to be totally disjoint from the rectangle,
1107
     * but it's also possible that the rectangle is totally inside the arc.
1108
     * Do one last check, which is to check one point of the rectangle
1109
     * to see if it's inside the arc.  If it is, we've got overlap.  If
1110
     * it isn't, the arc's really outside the rectangle.
1111
     */
1112
 
1113
    if (ArcToPoint(canvas, itemPtr, rectPtr) == 0.0) {
1114
        return 0;
1115
    }
1116
    return -1;
1117
}
1118
 
1119
/*
1120
 *--------------------------------------------------------------
1121
 *
1122
 * ScaleArc --
1123
 *
1124
 *      This procedure is invoked to rescale an arc item.
1125
 *
1126
 * Results:
1127
 *      None.
1128
 *
1129
 * Side effects:
1130
 *      The arc referred to by itemPtr is rescaled so that the
1131
 *      following transformation is applied to all point
1132
 *      coordinates:
1133
 *              x' = originX + scaleX*(x-originX)
1134
 *              y' = originY + scaleY*(y-originY)
1135
 *
1136
 *--------------------------------------------------------------
1137
 */
1138
 
1139
static void
1140
ScaleArc(canvas, itemPtr, originX, originY, scaleX, scaleY)
1141
    Tk_Canvas canvas;                   /* Canvas containing arc. */
1142
    Tk_Item *itemPtr;                   /* Arc to be scaled. */
1143
    double originX, originY;            /* Origin about which to scale rect. */
1144
    double scaleX;                      /* Amount to scale in X direction. */
1145
    double scaleY;                      /* Amount to scale in Y direction. */
1146
{
1147
    ArcItem *arcPtr = (ArcItem *) itemPtr;
1148
 
1149
    arcPtr->bbox[0] = originX + scaleX*(arcPtr->bbox[0] - originX);
1150
    arcPtr->bbox[1] = originY + scaleY*(arcPtr->bbox[1] - originY);
1151
    arcPtr->bbox[2] = originX + scaleX*(arcPtr->bbox[2] - originX);
1152
    arcPtr->bbox[3] = originY + scaleY*(arcPtr->bbox[3] - originY);
1153
    ComputeArcBbox(canvas, arcPtr);
1154
}
1155
 
1156
/*
1157
 *--------------------------------------------------------------
1158
 *
1159
 * TranslateArc --
1160
 *
1161
 *      This procedure is called to move an arc by a given amount.
1162
 *
1163
 * Results:
1164
 *      None.
1165
 *
1166
 * Side effects:
1167
 *      The position of the arc is offset by (xDelta, yDelta), and
1168
 *      the bounding box is updated in the generic part of the item
1169
 *      structure.
1170
 *
1171
 *--------------------------------------------------------------
1172
 */
1173
 
1174
static void
1175
TranslateArc(canvas, itemPtr, deltaX, deltaY)
1176
    Tk_Canvas canvas;                   /* Canvas containing item. */
1177
    Tk_Item *itemPtr;                   /* Item that is being moved. */
1178
    double deltaX, deltaY;              /* Amount by which item is to be
1179
                                         * moved. */
1180
{
1181
    ArcItem *arcPtr = (ArcItem *) itemPtr;
1182
 
1183
    arcPtr->bbox[0] += deltaX;
1184
    arcPtr->bbox[1] += deltaY;
1185
    arcPtr->bbox[2] += deltaX;
1186
    arcPtr->bbox[3] += deltaY;
1187
    ComputeArcBbox(canvas, arcPtr);
1188
}
1189
 
1190
/*
1191
 *--------------------------------------------------------------
1192
 *
1193
 * ComputeArcOutline --
1194
 *
1195
 *      This procedure creates a polygon describing everything in
1196
 *      the outline for an arc except what's in the curved part.
1197
 *      For a "pie slice" arc this is a V-shaped chunk, and for
1198
 *      a "chord" arc this is a linear chunk (with cutaway corners).
1199
 *      For "arc" arcs, this stuff isn't relevant.
1200
 *
1201
 * Results:
1202
 *      None.
1203
 *
1204
 * Side effects:
1205
 *      The information at arcPtr->outlinePtr gets modified, and
1206
 *      storage for arcPtr->outlinePtr may be allocated or freed.
1207
 *
1208
 *--------------------------------------------------------------
1209
 */
1210
 
1211
static void
1212
ComputeArcOutline(arcPtr)
1213
    ArcItem *arcPtr;                    /* Information about arc. */
1214
{
1215
    double sin1, cos1, sin2, cos2, angle, halfWidth;
1216
    double boxWidth, boxHeight;
1217
    double vertex[2], corner1[2], corner2[2];
1218
    double *outlinePtr;
1219
 
1220
    /*
1221
     * Make sure that the outlinePtr array is large enough to hold
1222
     * either a chord or pie-slice outline.
1223
     */
1224
 
1225
    if (arcPtr->numOutlinePoints == 0) {
1226
        arcPtr->outlinePtr = (double *) ckalloc((unsigned)
1227
                (26 * sizeof(double)));
1228
        arcPtr->numOutlinePoints = 22;
1229
    }
1230
    outlinePtr = arcPtr->outlinePtr;
1231
 
1232
    /*
1233
     * First compute the two points that lie at the centers of
1234
     * the ends of the curved arc segment, which are marked with
1235
     * X's in the figure below:
1236
     *
1237
     *
1238
     *                            * * *
1239
     *                        *          *
1240
     *                     *      * *      *
1241
     *                   *    *         *    *
1242
     *                  *   *             *   *
1243
     *                   X *               * X
1244
     *
1245
     * The code is tricky because the arc can be ovular in shape.
1246
     * It computes the position for a unit circle, and then
1247
     * scales to fit the shape of the arc's bounding box.
1248
     *
1249
     * Also, watch out because angles go counter-clockwise like you
1250
     * might expect, but the y-coordinate system is inverted.  To
1251
     * handle this, just negate the angles in all the computations.
1252
     */
1253
 
1254
    boxWidth = arcPtr->bbox[2] - arcPtr->bbox[0];
1255
    boxHeight = arcPtr->bbox[3] - arcPtr->bbox[1];
1256
    angle = -arcPtr->start*PI/180.0;
1257
    sin1 = sin(angle);
1258
    cos1 = cos(angle);
1259
    angle -= arcPtr->extent*PI/180.0;
1260
    sin2 = sin(angle);
1261
    cos2 = cos(angle);
1262
    vertex[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0;
1263
    vertex[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2.0;
1264
    arcPtr->center1[0] = vertex[0] + cos1*boxWidth/2.0;
1265
    arcPtr->center1[1] = vertex[1] + sin1*boxHeight/2.0;
1266
    arcPtr->center2[0] = vertex[0] + cos2*boxWidth/2.0;
1267
    arcPtr->center2[1] = vertex[1] + sin2*boxHeight/2.0;
1268
 
1269
    /*
1270
     * Next compute the "outermost corners" of the arc, which are
1271
     * marked with X's in the figure below:
1272
     *
1273
     *                            * * *
1274
     *                        *          *
1275
     *                     *      * *      *
1276
     *                   *    *         *    *
1277
     *                  X   *             *   X
1278
     *                     *               *
1279
     *
1280
     * The code below is tricky because it has to handle eccentricity
1281
     * in the shape of the oval.  The key in the code below is to
1282
     * realize that the slope of the line from arcPtr->center1 to corner1
1283
     * is (boxWidth*sin1)/(boxHeight*cos1), and similarly for arcPtr->center2
1284
     * and corner2.  These formulas can be computed from the formula for
1285
     * the oval.
1286
     */
1287
 
1288
    halfWidth = arcPtr->width/2.0;
1289
    if (((boxWidth*sin1) == 0.0) && ((boxHeight*cos1) == 0.0)) {
1290
        angle = 0.0;
1291
    } else {
1292
        angle = atan2(boxWidth*sin1, boxHeight*cos1);
1293
    }
1294
    corner1[0] = arcPtr->center1[0] + cos(angle)*halfWidth;
1295
    corner1[1] = arcPtr->center1[1] + sin(angle)*halfWidth;
1296
    if (((boxWidth*sin2) == 0.0) && ((boxHeight*cos2) == 0.0)) {
1297
        angle = 0.0;
1298
    } else {
1299
        angle = atan2(boxWidth*sin2, boxHeight*cos2);
1300
    }
1301
    corner2[0] = arcPtr->center2[0] + cos(angle)*halfWidth;
1302
    corner2[1] = arcPtr->center2[1] + sin(angle)*halfWidth;
1303
 
1304
    /*
1305
     * For a chord outline, generate a six-sided polygon with three
1306
     * points for each end of the chord.  The first and third points
1307
     * for each end are butt points generated on either side of the
1308
     * center point.  The second point is the corner point.
1309
     */
1310
 
1311
    if (arcPtr->style == chordUid) {
1312
        outlinePtr[0] = outlinePtr[12] = corner1[0];
1313
        outlinePtr[1] = outlinePtr[13] = corner1[1];
1314
        TkGetButtPoints(arcPtr->center2, arcPtr->center1,
1315
                (double) arcPtr->width, 0, outlinePtr+10, outlinePtr+2);
1316
        outlinePtr[4] = arcPtr->center2[0] + outlinePtr[2]
1317
                - arcPtr->center1[0];
1318
        outlinePtr[5] = arcPtr->center2[1] + outlinePtr[3]
1319
                - arcPtr->center1[1];
1320
        outlinePtr[6] = corner2[0];
1321
        outlinePtr[7] = corner2[1];
1322
        outlinePtr[8] = arcPtr->center2[0] + outlinePtr[10]
1323
                - arcPtr->center1[0];
1324
        outlinePtr[9] = arcPtr->center2[1] + outlinePtr[11]
1325
                - arcPtr->center1[1];
1326
    } else if (arcPtr->style == pieSliceUid) {
1327
        /*
1328
         * For pie slices, generate two polygons, one for each side
1329
         * of the pie slice.  The first arm has a shape like this,
1330
         * where the center of the oval is X, arcPtr->center1 is at Y, and
1331
         * corner1 is at Z:
1332
         *
1333
         *       _____________________
1334
         *      |                     \
1335
         *      |                      \
1336
         *      X                    Y  Z
1337
         *      |                      /
1338
         *      |_____________________/
1339
         *
1340
         */
1341
 
1342
        TkGetButtPoints(arcPtr->center1, vertex, (double) arcPtr->width, 0,
1343
                outlinePtr, outlinePtr+2);
1344
        outlinePtr[4] = arcPtr->center1[0] + outlinePtr[2] - vertex[0];
1345
        outlinePtr[5] = arcPtr->center1[1] + outlinePtr[3] - vertex[1];
1346
        outlinePtr[6] = corner1[0];
1347
        outlinePtr[7] = corner1[1];
1348
        outlinePtr[8] = arcPtr->center1[0] + outlinePtr[0] - vertex[0];
1349
        outlinePtr[9] = arcPtr->center1[1] + outlinePtr[1] - vertex[1];
1350
        outlinePtr[10] = outlinePtr[0];
1351
        outlinePtr[11] = outlinePtr[1];
1352
 
1353
        /*
1354
         * The second arm has a shape like this:
1355
         *
1356
         *
1357
         *         ______________________
1358
         *        /                       \
1359
         *       /                         \
1360
         *      Z  Y                    X  /
1361
         *       \                        /
1362
         *        \______________________/
1363
         *
1364
         * Similar to above X is the center of the oval/circle, Y is
1365
         * arcPtr->center2, and Z is corner2.  The extra jog out to the left
1366
         * of X is needed in or to produce a butted joint with the
1367
         * first arm;  the corner to the right of X is one of the
1368
         * first two points of the first arm, depending on extent.
1369
         */
1370
 
1371
        TkGetButtPoints(arcPtr->center2, vertex, (double) arcPtr->width, 0,
1372
                outlinePtr+12, outlinePtr+16);
1373
        if ((arcPtr->extent > 180) ||
1374
                ((arcPtr->extent < 0) && (arcPtr->extent > -180))) {
1375
            outlinePtr[14] = outlinePtr[0];
1376
            outlinePtr[15] = outlinePtr[1];
1377
        } else {
1378
            outlinePtr[14] = outlinePtr[2];
1379
            outlinePtr[15] = outlinePtr[3];
1380
        }
1381
        outlinePtr[18] = arcPtr->center2[0] + outlinePtr[16] - vertex[0];
1382
        outlinePtr[19] = arcPtr->center2[1] + outlinePtr[17] - vertex[1];
1383
        outlinePtr[20] = corner2[0];
1384
        outlinePtr[21] = corner2[1];
1385
        outlinePtr[22] = arcPtr->center2[0] + outlinePtr[12] - vertex[0];
1386
        outlinePtr[23] = arcPtr->center2[1] + outlinePtr[13] - vertex[1];
1387
        outlinePtr[24] = outlinePtr[12];
1388
        outlinePtr[25] = outlinePtr[13];
1389
    }
1390
}
1391
 
1392
/*
1393
 *--------------------------------------------------------------
1394
 *
1395
 * HorizLineToArc --
1396
 *
1397
 *      Determines whether a horizontal line segment intersects
1398
 *      a given arc.
1399
 *
1400
 * Results:
1401
 *      The return value is 1 if the given line intersects the
1402
 *      infinitely-thin arc section defined by rx, ry, start,
1403
 *      and extent, and 0 otherwise.  Only the perimeter of the
1404
 *      arc is checked: interior areas (e.g. pie-slice or chord)
1405
 *      are not checked.
1406
 *
1407
 * Side effects:
1408
 *      None.
1409
 *
1410
 *--------------------------------------------------------------
1411
 */
1412
 
1413
static int
1414
HorizLineToArc(x1, x2, y, rx, ry, start, extent)
1415
    double x1, x2;              /* X-coords of endpoints of line segment.
1416
                                 * X1 must be <= x2. */
1417
    double y;                   /* Y-coordinate of line segment. */
1418
    double rx, ry;              /* These x- and y-radii define an oval
1419
                                 * centered at the origin. */
1420
    double start, extent;       /* Angles that define extent of arc, in
1421
                                 * the standard fashion for this module. */
1422
{
1423
    double tmp;
1424
    double tx, ty;              /* Coordinates of intersection point in
1425
                                 * transformed coordinate system. */
1426
    double x;
1427
 
1428
    /*
1429
     * Compute the x-coordinate of one possible intersection point
1430
     * between the arc and the line.  Use a transformed coordinate
1431
     * system where the oval is a unit circle centered at the origin.
1432
     * Then scale back to get actual x-coordinate.
1433
     */
1434
 
1435
    ty = y/ry;
1436
    tmp = 1 - ty*ty;
1437
    if (tmp < 0) {
1438
        return 0;
1439
    }
1440
    tx = sqrt(tmp);
1441
    x = tx*rx;
1442
 
1443
    /*
1444
     * Test both intersection points.
1445
     */
1446
 
1447
    if ((x >= x1) && (x <= x2) && AngleInRange(tx, ty, start, extent)) {
1448
        return 1;
1449
    }
1450
    if ((-x >= x1) && (-x <= x2) && AngleInRange(-tx, ty, start, extent)) {
1451
        return 1;
1452
    }
1453
    return 0;
1454
}
1455
 
1456
/*
1457
 *--------------------------------------------------------------
1458
 *
1459
 * VertLineToArc --
1460
 *
1461
 *      Determines whether a vertical line segment intersects
1462
 *      a given arc.
1463
 *
1464
 * Results:
1465
 *      The return value is 1 if the given line intersects the
1466
 *      infinitely-thin arc section defined by rx, ry, start,
1467
 *      and extent, and 0 otherwise.  Only the perimeter of the
1468
 *      arc is checked: interior areas (e.g. pie-slice or chord)
1469
 *      are not checked.
1470
 *
1471
 * Side effects:
1472
 *      None.
1473
 *
1474
 *--------------------------------------------------------------
1475
 */
1476
 
1477
static int
1478
VertLineToArc(x, y1, y2, rx, ry, start, extent)
1479
    double x;                   /* X-coordinate of line segment. */
1480
    double y1, y2;              /* Y-coords of endpoints of line segment.
1481
                                 * Y1 must be <= y2. */
1482
    double rx, ry;              /* These x- and y-radii define an oval
1483
                                 * centered at the origin. */
1484
    double start, extent;       /* Angles that define extent of arc, in
1485
                                 * the standard fashion for this module. */
1486
{
1487
    double tmp;
1488
    double tx, ty;              /* Coordinates of intersection point in
1489
                                 * transformed coordinate system. */
1490
    double y;
1491
 
1492
    /*
1493
     * Compute the y-coordinate of one possible intersection point
1494
     * between the arc and the line.  Use a transformed coordinate
1495
     * system where the oval is a unit circle centered at the origin.
1496
     * Then scale back to get actual y-coordinate.
1497
     */
1498
 
1499
    tx = x/rx;
1500
    tmp = 1 - tx*tx;
1501
    if (tmp < 0) {
1502
        return 0;
1503
    }
1504
    ty = sqrt(tmp);
1505
    y = ty*ry;
1506
 
1507
    /*
1508
     * Test both intersection points.
1509
     */
1510
 
1511
    if ((y > y1) && (y < y2) && AngleInRange(tx, ty, start, extent)) {
1512
        return 1;
1513
    }
1514
    if ((-y > y1) && (-y < y2) && AngleInRange(tx, -ty, start, extent)) {
1515
        return 1;
1516
    }
1517
    return 0;
1518
}
1519
 
1520
/*
1521
 *--------------------------------------------------------------
1522
 *
1523
 * AngleInRange --
1524
 *
1525
 *      Determine whether the angle from the origin to a given
1526
 *      point is within a given range.
1527
 *
1528
 * Results:
1529
 *      The return value is 1 if the angle from (0,0) to (x,y)
1530
 *      is in the range given by start and extent, where angles
1531
 *      are interpreted in the standard way for ovals (meaning
1532
 *      backwards from normal interpretation).  Otherwise the
1533
 *      return value is 0.
1534
 *
1535
 * Side effects:
1536
 *      None.
1537
 *
1538
 *--------------------------------------------------------------
1539
 */
1540
 
1541
static int
1542
AngleInRange(x, y, start, extent)
1543
    double x, y;                /* Coordinate of point;  angle measured
1544
                                 * from origin to here, relative to x-axis. */
1545
    double start;               /* First angle, degrees, >=0, <=360. */
1546
    double extent;              /* Size of arc in degrees >=-360, <=360. */
1547
{
1548
    double diff;
1549
 
1550
    if ((x == 0.0) && (y == 0.0)) {
1551
        return 1;
1552
    }
1553
    diff = -atan2(y, x);
1554
    diff = diff*(180.0/PI) - start;
1555
    while (diff > 360.0) {
1556
        diff -= 360.0;
1557
    }
1558
    while (diff < 0.0) {
1559
        diff += 360.0;
1560
    }
1561
    if (extent >= 0) {
1562
        return diff <= extent;
1563
    }
1564
    return (diff-360.0) >= extent;
1565
}
1566
 
1567
/*
1568
 *--------------------------------------------------------------
1569
 *
1570
 * ArcToPostscript --
1571
 *
1572
 *      This procedure is called to generate Postscript for
1573
 *      arc items.
1574
 *
1575
 * Results:
1576
 *      The return value is a standard Tcl result.  If an error
1577
 *      occurs in generating Postscript then an error message is
1578
 *      left in interp->result, replacing whatever used
1579
 *      to be there.  If no error occurs, then Postscript for the
1580
 *      item is appended to the result.
1581
 *
1582
 * Side effects:
1583
 *      None.
1584
 *
1585
 *--------------------------------------------------------------
1586
 */
1587
 
1588
static int
1589
ArcToPostscript(interp, canvas, itemPtr, prepass)
1590
    Tcl_Interp *interp;                 /* Leave Postscript or error message
1591
                                         * here. */
1592
    Tk_Canvas canvas;                   /* Information about overall canvas. */
1593
    Tk_Item *itemPtr;                   /* Item for which Postscript is
1594
                                         * wanted. */
1595
    int prepass;                        /* 1 means this is a prepass to
1596
                                         * collect font information;  0 means
1597
                                         * final Postscript is being created. */
1598
{
1599
    ArcItem *arcPtr = (ArcItem *) itemPtr;
1600
    char buffer[400];
1601
    double y1, y2, ang1, ang2;
1602
 
1603
    y1 = Tk_CanvasPsY(canvas, arcPtr->bbox[1]);
1604
    y2 = Tk_CanvasPsY(canvas, arcPtr->bbox[3]);
1605
    ang1 = arcPtr->start;
1606
    ang2 = ang1 + arcPtr->extent;
1607
    if (ang2 < ang1) {
1608
        ang1 = ang2;
1609
        ang2 = arcPtr->start;
1610
    }
1611
 
1612
    /*
1613
     * If the arc is filled, output Postscript for the interior region
1614
     * of the arc.
1615
     */
1616
 
1617
    if (arcPtr->fillGC != None) {
1618
        sprintf(buffer, "matrix currentmatrix\n%.15g %.15g translate %.15g %.15g scale\n",
1619
                (arcPtr->bbox[0] + arcPtr->bbox[2])/2, (y1 + y2)/2,
1620
                (arcPtr->bbox[2] - arcPtr->bbox[0])/2, (y1 - y2)/2);
1621
        Tcl_AppendResult(interp, buffer, (char *) NULL);
1622
        if (arcPtr->style == chordUid) {
1623
            sprintf(buffer, "0 0 1 %.15g %.15g arc closepath\nsetmatrix\n",
1624
                    ang1, ang2);
1625
        } else {
1626
            sprintf(buffer,
1627
                    "0 0 moveto 0 0 1 %.15g %.15g arc closepath\nsetmatrix\n",
1628
                    ang1, ang2);
1629
        }
1630
        Tcl_AppendResult(interp, buffer, (char *) NULL);
1631
        if (Tk_CanvasPsColor(interp, canvas, arcPtr->fillColor) != TCL_OK) {
1632
            return TCL_ERROR;
1633
        };
1634
        if (arcPtr->fillStipple != None) {
1635
            Tcl_AppendResult(interp, "clip ", (char *) NULL);
1636
            if (Tk_CanvasPsStipple(interp, canvas, arcPtr->fillStipple)
1637
                    != TCL_OK) {
1638
                return TCL_ERROR;
1639
            }
1640
            if (arcPtr->outlineGC != None) {
1641
                Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL);
1642
            }
1643
        } else {
1644
            Tcl_AppendResult(interp, "fill\n", (char *) NULL);
1645
        }
1646
    }
1647
 
1648
    /*
1649
     * If there's an outline for the arc, draw it.
1650
     */
1651
 
1652
    if (arcPtr->outlineGC != None) {
1653
        sprintf(buffer, "matrix currentmatrix\n%.15g %.15g translate %.15g %.15g scale\n",
1654
                (arcPtr->bbox[0] + arcPtr->bbox[2])/2, (y1 + y2)/2,
1655
                (arcPtr->bbox[2] - arcPtr->bbox[0])/2, (y1 - y2)/2);
1656
        Tcl_AppendResult(interp, buffer, (char *) NULL);
1657
        sprintf(buffer, "0 0 1 %.15g %.15g arc\nsetmatrix\n", ang1, ang2);
1658
        Tcl_AppendResult(interp, buffer, (char *) NULL);
1659
        sprintf(buffer, "%d setlinewidth\n0 setlinecap\n", arcPtr->width);
1660
        Tcl_AppendResult(interp, buffer, (char *) NULL);
1661
        if (Tk_CanvasPsColor(interp, canvas, arcPtr->outlineColor)
1662
                != TCL_OK) {
1663
            return TCL_ERROR;
1664
        }
1665
        if (arcPtr->outlineStipple != None) {
1666
            Tcl_AppendResult(interp, "StrokeClip ", (char *) NULL);
1667
            if (Tk_CanvasPsStipple(interp, canvas,
1668
                    arcPtr->outlineStipple) != TCL_OK) {
1669
                return TCL_ERROR;
1670
            }
1671
        } else {
1672
            Tcl_AppendResult(interp, "stroke\n", (char *) NULL);
1673
        }
1674
        if (arcPtr->style != arcUid) {
1675
            Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL);
1676
            if (arcPtr->style == chordUid) {
1677
                Tk_CanvasPsPath(interp, canvas, arcPtr->outlinePtr,
1678
                        CHORD_OUTLINE_PTS);
1679
            } else {
1680
                Tk_CanvasPsPath(interp, canvas, arcPtr->outlinePtr,
1681
                        PIE_OUTLINE1_PTS);
1682
                if (Tk_CanvasPsColor(interp, canvas, arcPtr->outlineColor)
1683
                        != TCL_OK) {
1684
                    return TCL_ERROR;
1685
                }
1686
                if (arcPtr->outlineStipple != None) {
1687
                    Tcl_AppendResult(interp, "clip ", (char *) NULL);
1688
                    if (Tk_CanvasPsStipple(interp, canvas,
1689
                            arcPtr->outlineStipple) != TCL_OK) {
1690
                        return TCL_ERROR;
1691
                    }
1692
                } else {
1693
                    Tcl_AppendResult(interp, "fill\n", (char *) NULL);
1694
                }
1695
                Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL);
1696
                Tk_CanvasPsPath(interp, canvas,
1697
                        arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS,
1698
                        PIE_OUTLINE2_PTS);
1699
            }
1700
            if (Tk_CanvasPsColor(interp, canvas, arcPtr->outlineColor)
1701
                    != TCL_OK) {
1702
                return TCL_ERROR;
1703
            }
1704
            if (arcPtr->outlineStipple != None) {
1705
                Tcl_AppendResult(interp, "clip ", (char *) NULL);
1706
                if (Tk_CanvasPsStipple(interp, canvas,
1707
                        arcPtr->outlineStipple) != TCL_OK) {
1708
                    return TCL_ERROR;
1709
                }
1710
            } else {
1711
                Tcl_AppendResult(interp, "fill\n", (char *) NULL);
1712
            }
1713
        }
1714
    }
1715
 
1716
    return TCL_OK;
1717
}

powered by: WebSVN 2.1.0

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