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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [mw/] [src/] [engine/] [devclip1.c] - Blame information for rev 1773

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

Line No. Rev Author Line
1 673 markom
/*
2
 * Copyright (c) 1999 Greg Haerr <greg@censoft.com>
3
 * Copyright (c) 1991 David I. Bell
4
 * Permission is granted to use, distribute, or modify this source,
5
 * provided that this copyright notice remains intact.
6
 *
7
 * Device-independent routines to determine clipping regions.
8
 */
9
#include "device.h"
10
 
11
/* Clip cache rectangle information.
12
 * After calling GdClipPoint, this rectangle is guaranteed to contain the
13
 * specified point (among others), and all points in the rectangle are
14
 * plottable or not according to the value of clipresult.
15
 */
16
MWCOORD clipminx;               /* minimum x value of cache rectangle */
17
MWCOORD clipminy;               /* minimum y value of cache rectangle */
18
MWCOORD clipmaxx;               /* maximum x value of cache rectangle */
19
MWCOORD clipmaxy;               /* maximum y value of cache rectangle */
20
 
21
static MWBOOL   clipresult;     /* whether clip rectangle is plottable */
22
int     clipcount;              /* number of clip rectangles */
23
MWCLIPRECT cliprects[MAX_CLIPRECTS];    /* clip rectangles */
24
 
25
/*
26
 * Set an array of clip rectangles for future drawing actions.
27
 * Each pixel will be drawn only if lies in one or more of the specified
28
 * clip rectangles.  As a special case, specifying no rectangles implies
29
 * clipping is for the complete screen.  All clip rectangles are modified
30
 * if necessary to lie within the device area.  Call only after device
31
 * has been initialized.
32
 */
33
void
34
GdSetClipRects(PSD psd,int count, MWCLIPRECT *table)
35
{
36
  register MWCLIPRECT *rp;              /* current rectangle */
37
 
38
  /* If there are no clip rectangles, then default to the full device area. */
39
  if (count <= 0) {
40
        clipminx = 0;
41
        clipminy = 0;
42
        clipmaxx = psd->xvirtres - 1;
43
        clipmaxy = psd->yvirtres - 1;
44
        clipcount = 0;
45
        clipresult = TRUE;
46
        return;
47
  }
48
 
49
  /* Copy the clip table to our own static array, modifying each
50
   * rectangle as necesary to fit within the device area.  If the clip
51
   * rectangle lies entirely outside of the device area, then skip it.
52
   */
53
  rp = cliprects;
54
  clipcount = 0;
55
  if (count > MAX_CLIPRECTS) count = MAX_CLIPRECTS;
56
  while (count-- > 0) {
57
        *rp = *table++;
58
        if (rp->x < 0) {
59
                rp->width += rp->x;
60
                rp->x = 0;
61
        }
62
        if (rp->y < 0) {
63
                rp->height += rp->y;
64
                rp->y = 0;
65
        }
66
        if ((rp->x >= psd->xvirtres) || (rp->width <= 0) ||
67
            (rp->y >= psd->yvirtres) || (rp->height <= 0))
68
                continue;
69
        if (rp->x + rp->width > psd->xvirtres)
70
                rp->width = psd->xvirtres - rp->x;
71
        if (rp->y + rp->height > psd->yvirtres)
72
                rp->height = psd->yvirtres - rp->y;
73
        rp++;
74
        clipcount++;
75
  }
76
 
77
  /* If there were no surviving clip rectangles, then set the clip
78
   * cache to prevent all drawing.
79
   */
80
  if (clipcount == 0) {
81
        clipminx = MIN_MWCOORD;
82
        clipminy = MIN_MWCOORD;
83
        clipmaxx = MAX_MWCOORD;
84
        clipmaxy = MAX_MWCOORD;
85
        clipresult = FALSE;
86
        return;
87
  }
88
 
89
  /* There was at least one valid clip rectangle. Default the clip
90
   * cache to be the first clip rectangle.
91
   */
92
  clipminx = cliprects[0].x;
93
  clipminy = cliprects[0].y;
94
  clipmaxx = clipminx + cliprects[0].width - 1;
95
  clipmaxy = clipminy + cliprects[0].height - 1;
96
  clipresult = TRUE;
97
}
98
 
99
 
100
/* Check a point against the list of clip rectangles.
101
 * Returns TRUE if the point is within one or more rectangles and thus
102
 * can be plotted, or FALSE if the point is not within any rectangle and
103
 * thus cannot be plotted.  Also remembers the coordinates of a clip cache
104
 * rectangle containing the specified point such that every point in the
105
 * rectangle would give the same result.  By examining this clip cache
106
 * rectangle after a call to this routine, the caller can efficiently
107
 * check many nearby points without needing any further calls.  If the
108
 * point lies within the cursor, then the cursor is removed.
109
 */
110
MWBOOL
111
GdClipPoint(PSD psd,MWCOORD x,MWCOORD y)
112
{
113
  int count;
114
  MWCLIPRECT *rp;
115
  MWCOORD temp;
116
 
117
  /* First see whether the point lies within the current clip cache
118
   * rectangle.  If so, then we already know the result.
119
   */
120
  if ((x >= clipminx) && (x <= clipmaxx) &&
121
      (y >= clipminy) && (y <= clipmaxy)) {
122
        if (clipresult) GdCheckCursor(psd, x, y, x, y);
123
        return clipresult;
124
  }
125
 
126
  /* If the point is outside of the screen area, then it is not
127
   * plottable, and the clip cache rectangle is the whole half-plane
128
   * outside of the screen area.
129
   */
130
  if (x < 0) {
131
        clipminx = MIN_MWCOORD;
132
        clipmaxx = -1;
133
        clipminy = MIN_MWCOORD;
134
        clipmaxy = MAX_MWCOORD;
135
        clipresult = FALSE;
136
        return FALSE;
137
  }
138
  if (y < 0) {
139
        clipminx = MIN_MWCOORD;
140
        clipmaxx = MAX_MWCOORD;
141
        clipminy = MIN_MWCOORD;
142
        clipmaxy = -1;
143
        clipresult = FALSE;
144
        return FALSE;
145
  }
146
  if (x >= psd->xvirtres) {
147
        clipminx = psd->xvirtres;
148
        clipmaxx = MAX_MWCOORD;
149
        clipminy = MIN_MWCOORD;
150
        clipmaxy = MAX_MWCOORD;
151
        clipresult = FALSE;
152
        return FALSE;
153
  }
154
  if (y >= psd->yvirtres) {
155
        clipminx = MIN_MWCOORD;
156
        clipmaxx = MAX_MWCOORD;
157
        clipminy = psd->yvirtres;
158
        clipmaxy = MAX_MWCOORD;
159
        clipresult = FALSE;
160
        return FALSE;
161
  }
162
 
163
  /* The point is within the screen area. If there are no clip
164
   * rectangles, then the point is plottable and the rectangle is the
165
   * whole screen.
166
   */
167
  count = clipcount;
168
  if (count <= 0) {
169
        clipminx = 0;
170
        clipmaxx = psd->xvirtres - 1;
171
        clipminy = 0;
172
        clipmaxy = psd->yvirtres - 1;
173
        clipresult = TRUE;
174
        GdCheckCursor(psd, x, y, x, y);
175
        return TRUE;
176
  }
177
 
178
  /* We need to scan the list of clip rectangles to calculate a new
179
   * clip cache rectangle containing this point, and the result. First
180
   * see if the point lies within any of the clip rectangles. If so,
181
   * then it is plottable and use that clip rectangle as the cache
182
   * rectangle.  This is not necessarily the best result, but works ok
183
   * and is fast.
184
   */
185
  for (rp = cliprects; count-- > 0; rp++) {
186
        if ((x >= rp->x) && (y >= rp->y) && (x < rp->x + rp->width)
187
            && (y < rp->y + rp->height)) {
188
                clipminx = rp->x;
189
                clipminy = rp->y;
190
                clipmaxx = rp->x + rp->width - 1;
191
                clipmaxy = rp->y + rp->height - 1;
192
                clipresult = TRUE;
193
                GdCheckCursor(psd, x, y, x, y);
194
                return TRUE;
195
        }
196
  }
197
 
198
  /* The point is not plottable. Scan the clip rectangles again to
199
   * determine a rectangle containing more non-plottable points.
200
   * Simply pick the largest rectangle whose area doesn't contain any
201
   * of the same coordinates as appropriate sides of the clip
202
   * rectangles.  This is not necessarily the best result, but works ok
203
   * and is fast.
204
   */
205
  clipminx = MIN_MWCOORD;
206
  clipminy = MIN_MWCOORD;
207
  clipmaxx = MAX_MWCOORD;
208
  clipmaxy = MAX_MWCOORD;
209
  count = clipcount;
210
  for (rp = cliprects; count-- > 0; rp++) {
211
        if ((x < rp->x) && (rp->x <= clipmaxx)) clipmaxx = rp->x - 1;
212
        temp = rp->x + rp->width - 1;
213
        if ((x > temp) && (temp >= clipminx)) clipminx = temp + 1;
214
        if ((y < rp->y) && (rp->y <= clipmaxy)) clipmaxy = rp->y - 1;
215
        temp = rp->y + rp->height - 1;
216
        if ((y > temp) && (temp >= clipminy)) clipminy = temp + 1;
217
  }
218
  clipresult = FALSE;
219
  return FALSE;
220
}
221
 
222
 
223
/* Check the area determined by the specified pair of points against the
224
 * list of clip rectangles.  The area will either be totally visible,
225
 * totally visible, or possibly partially visible.  This routine updates
226
 * the clip cache rectangle, and returns one of the following values:
227
 *      CLIP_VISIBLE            The whole rectangle is visible
228
 *      CLIP_INVISIBLE          The whole rectangle is invisible
229
 *      CLIP_PARTIAL            The rectangle may be partially visible
230
 * In the case that the area is totally visible, the cursor is removed
231
 * if it overlaps the clip area.
232
 */
233
int
234
GdClipArea(PSD psd,MWCOORD x1, MWCOORD y1, MWCOORD x2, MWCOORD y2)
235
{
236
  if ((x1 < clipminx) || (x1 > clipmaxx) ||
237
      (y1 < clipminy) || (y1 > clipmaxy))
238
        GdClipPoint(psd, x1, y1);
239
 
240
  if ((x2 >= clipminx) && (x2 <= clipmaxx) &&
241
      (y2 >= clipminy) && (y2 <= clipmaxy)) {
242
        if (!clipresult) return CLIP_INVISIBLE;
243
        GdCheckCursor(psd, x1, y1, x2, y2);
244
        return CLIP_VISIBLE;
245
  }
246
  return CLIP_PARTIAL;
247
}

powered by: WebSVN 2.1.0

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