b311480e |
1 | // Copyright (c) 1999-2012 OPEN CASCADE SAS |
2 | // |
3 | // The content of this file is subject to the Open CASCADE Technology Public |
4 | // License Version 6.5 (the "License"). You may not use the content of this file |
5 | // except in compliance with the License. Please obtain a copy of the License |
6 | // at http://www.opencascade.org and read it completely before using this file. |
7 | // |
8 | // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its |
9 | // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. |
10 | // |
11 | // The Original Code and all software distributed under the License is |
12 | // distributed on an "AS IS" basis, without warranty of any kind, and the |
13 | // Initial Developer hereby disclaims all such warranties, including without |
14 | // limitation, any warranties of merchantability, fitness for a particular |
15 | // purpose or non-infringement. Please see the License for the specific terms |
16 | // and conditions governing the rights and limitations under the License. |
17 | |
7fd59977 |
18 | |
19 | #define S3593 /*GG_130398 |
b311480e |
20 | OPTIMISATION MFT |
7fd59977 |
21 | Activer le clipping de maniere optionnelle |
22 | */ |
23 | |
24 | #include <Xw_Extension.h> |
25 | |
26 | /* ifdef then trace on */ |
27 | #ifdef TRACE |
28 | #define TRACE_DRAW_SEGMENT |
29 | #endif |
30 | |
31 | static XW_EXT_SEGMENT *pseglist ; |
32 | static int BeginSegments = False ; |
33 | |
34 | /* |
35 | STATUS Xw_draw_segment (awindow,x1,y1,x2,y2): |
36 | XW_EXT_WINDOW *awindow |
37 | float x1,y1 First point Coordinates defined in User Space |
38 | float x2,y2 Second point Coordinates defined in User Space |
39 | |
40 | Display segment in current QG set by set_line_attrib . |
41 | Note that segments can be buffered depending of the DisplayMode context |
42 | and Flush at Xw_flush time . |
43 | |
44 | returns SUCCESS always |
45 | |
46 | */ |
47 | |
48 | #ifdef XW_PROTOTYPE |
49 | XW_STATUS Xw_draw_segment (void* awindow,float x1,float y1,float x2,float y2) |
50 | #else |
51 | XW_STATUS Xw_draw_segment (awindow,x1,y1,x2,y2) |
52 | void *awindow; |
53 | float x1,y1,x2,y2 ; |
54 | #endif /*XW_PROTOTYPE*/ |
55 | { |
56 | XW_EXT_WINDOW *pwindow = (XW_EXT_WINDOW*)awindow; |
57 | XW_EXT_BUFFER *pbuffer ; |
58 | int status ; |
59 | int nseg,bindex; |
60 | int ix1,iy1,ix2,iy2 ; |
61 | |
62 | if( !Xw_isdefine_window(pwindow) ) { |
63 | /*ERROR*Bad EXT_WINDOW Address*/ |
64 | Xw_set_error(24,"Xw_draw_segment",pwindow) ; |
65 | return (XW_ERROR) ; |
66 | } |
67 | |
68 | bindex = _BINDEX ; |
69 | pbuffer = &_BUFFER(bindex) ; |
70 | for( pseglist = pbuffer->pseglist ; pseglist ; |
71 | pseglist = (XW_EXT_SEGMENT*)pseglist->link ) { |
72 | if( pseglist->nseg < MAXSEGMENTS ) break ; |
73 | } |
74 | |
75 | if( !pseglist ) { |
76 | pseglist = Xw_add_segment_structure(pbuffer) ; |
77 | } |
78 | |
79 | |
80 | if( !pseglist ) return XW_ERROR ; |
81 | |
82 | //OCC186 |
83 | ix1 = PXPOINT(x1, pwindow->xratio) ; |
84 | iy1 = PYPOINT(y1, pwindow->attributes.height, pwindow->yratio) ; |
85 | ix2 = PXPOINT(x2, pwindow->xratio) ; |
86 | iy2 = PYPOINT(y2, pwindow->attributes.height, pwindow->yratio) ; |
87 | //OCC186 |
88 | |
89 | nseg = pseglist->nseg ; |
90 | |
91 | #ifdef S3593 |
92 | if( pwindow->clipflag ) { |
93 | #endif |
94 | status = Xw_clip_segment(pwindow,ix1,iy1,ix2,iy2, |
95 | &pseglist->rsegments[nseg]); |
96 | if( status < 0 ) return (XW_SUCCESS); |
97 | #ifdef S3593 |
98 | } else { |
99 | pseglist->rsegments[nseg].x1 = ix1 ; |
100 | pseglist->rsegments[nseg].y1 = iy1 ; |
101 | pseglist->rsegments[nseg].x2 = ix2 ; |
102 | pseglist->rsegments[nseg].y2 = iy2 ; |
103 | } |
104 | #endif |
105 | pseglist->nseg++ ; |
106 | |
107 | if( bindex > 0 ) { |
108 | pbuffer->isempty = False ; |
109 | if( ix1 < ix2 ) { |
110 | pbuffer->rxmin = min(pbuffer->rxmin,ix1) ; |
111 | pbuffer->rxmax = max(pbuffer->rxmax,ix2) ; |
112 | } else { |
113 | pbuffer->rxmin = min(pbuffer->rxmin,ix2) ; |
114 | pbuffer->rxmax = max(pbuffer->rxmax,ix1) ; |
115 | } |
116 | if( iy1 < iy2 ) { |
117 | pbuffer->rymin = min(pbuffer->rymin,iy1) ; |
118 | pbuffer->rymax = max(pbuffer->rymax,iy2) ; |
119 | } else { |
120 | pbuffer->rymin = min(pbuffer->rymin,iy2) ; |
121 | pbuffer->rymax = max(pbuffer->rymax,iy1) ; |
122 | } |
123 | } else if( !BeginSegments ) { |
124 | int index = pwindow->lineindex ; |
125 | Xw_draw_pixel_segments(pwindow,pseglist,pwindow->qgline[index].gc) ; |
126 | pseglist->nseg = 0 ; |
127 | } |
128 | |
129 | #ifdef TRACE_DRAW_SEGMENT |
130 | if( Xw_get_trace() > 2 ) { |
131 | printf(" Xw_draw_segment(%lx,%f,%f,%f,%f\n",(long ) pwindow,x1,y1,x2,y2) ; |
132 | } |
133 | #endif |
134 | |
135 | return (XW_SUCCESS); |
136 | } |
137 | |
138 | #ifdef XW_PROTOTYPE |
139 | void Xw_draw_pixel_segments(XW_EXT_WINDOW* pwindow,XW_EXT_SEGMENT *pseglist,GC gc) |
140 | #else |
141 | void Xw_draw_pixel_segments(pwindow,pseglist,gc) |
142 | XW_EXT_WINDOW *pwindow; |
143 | XW_EXT_SEGMENT *pseglist; |
144 | GC gc ; |
145 | #endif /*XW_PROTOTYPE*/ |
146 | { |
147 | |
148 | if( pseglist->isupdated ) { |
149 | XDrawSegments(_DISPLAY,_DRAWABLE,gc, |
150 | pseglist->usegments,pseglist->nseg) ; |
151 | } else { |
152 | XDrawSegments(_DISPLAY,_DRAWABLE,gc, |
153 | pseglist->rsegments,pseglist->nseg) ; |
154 | } |
155 | |
156 | #ifdef TRACE_DRAW_SEGMENT |
157 | if( Xw_get_trace() > 2 ) { |
158 | printf(" %d = Xw_draw_pixel_segments(%lx,%lx,%lx\n",pseglist->nseg,(long ) pwindow,(long ) pseglist,(long ) gc) ; |
159 | } |
160 | #endif |
161 | } |
162 | |
163 | /* |
164 | STATUS Xw_begin_segments (awindow,nsegment): |
165 | XW_EXT_WINDOW *awindow |
166 | int nsegment Not used |
167 | |
168 | |
169 | Begin a set of segments which must be filled by Xw_draw_segment and |
170 | closed by Xw_close_segments |
171 | |
172 | returns ERROR if bad extended window address |
173 | returns SUCCESS if successful |
174 | |
175 | */ |
176 | |
177 | #ifdef XW_PROTOTYPE |
178 | XW_STATUS Xw_begin_segments(void* awindow,int nsegment) |
179 | #else |
180 | XW_STATUS Xw_begin_segments(awindow,nsegment) |
181 | void *awindow ; |
182 | int nsegment ; |
183 | #endif /*XW_PROTOTYPE*/ |
184 | { |
185 | XW_EXT_WINDOW *pwindow = (XW_EXT_WINDOW*)awindow ; |
186 | |
187 | if( !Xw_isdefine_window(pwindow) ) { |
188 | /*ERROR*Bad EXT_WINDOW Address*/ |
189 | Xw_set_error(24,"Xw_begin_segments",pwindow) ; |
190 | return (XW_ERROR) ; |
191 | } |
192 | |
193 | if( BeginSegments ) Xw_close_segments(pwindow); |
194 | |
195 | BeginSegments = True; |
196 | |
197 | #ifdef TRACE_DRAW_LINE |
198 | if( Xw_get_trace() > 2 ) { |
199 | printf(" Xw_begin_segments(%x,%d)\n",pwindow,nsegment) ; |
200 | } |
201 | #endif |
202 | return (XW_SUCCESS) ; |
203 | } |
204 | |
205 | /* |
206 | STATUS Xw_close_segments (awindow): |
207 | XW_EXT_WINDOW *awindow |
208 | |
209 | Close the set of segments |
210 | |
211 | returns ERROR if bad extended window address |
212 | returns SUCCESS successful |
213 | |
214 | */ |
215 | |
216 | #ifdef XW_PROTOTYPE |
217 | XW_STATUS Xw_close_segments(void* awindow) |
218 | #else |
219 | XW_STATUS Xw_close_segments(awindow) |
220 | void *awindow ; |
221 | #endif /*XW_PROTOTYPE*/ |
222 | { |
223 | XW_EXT_WINDOW *pwindow = (XW_EXT_WINDOW*)awindow ; |
224 | XW_EXT_BUFFER *pbuffer ; |
225 | int bindex ; |
226 | |
227 | bindex = _BINDEX ; |
228 | pbuffer = &_BUFFER(bindex) ; |
229 | if( BeginSegments && !bindex ) { |
230 | int index = pwindow->lineindex ; |
231 | for( pseglist = pbuffer->pseglist ; pseglist ; |
232 | pseglist = (XW_EXT_SEGMENT*)pseglist->link ) { |
233 | if( pseglist->nseg ) { |
234 | Xw_draw_pixel_segments(pwindow,pseglist, |
235 | pwindow->qgline[index].gc) ; |
236 | pseglist->nseg = 0 ; |
237 | } else break ; |
238 | } |
239 | } |
240 | |
241 | BeginSegments = False; |
242 | |
243 | #ifdef TRACE_DRAW_SEGMENT |
244 | if( Xw_get_trace() > 2 ) { |
245 | printf(" Xw_close_segments(%lx)\n",(long ) pwindow) ; |
246 | } |
247 | #endif |
248 | return (XW_SUCCESS) ; |
249 | } |
250 | |
251 | #ifdef XW_PROTOTYPE |
252 | XW_EXT_SEGMENT* Xw_add_segment_structure(XW_EXT_BUFFER* pbuflist ) |
253 | #else |
254 | XW_EXT_SEGMENT* Xw_add_segment_structure(pbuflist ) |
255 | XW_EXT_BUFFER *pbuflist ; |
256 | #endif /*XW_PROTOTYPE*/ |
257 | /* |
258 | Create and Insert at end one Extended segment structure in the |
259 | segment List |
260 | |
261 | returns Extended segment address if successful |
262 | or NULL if Bad Allocation |
263 | */ |
264 | { |
265 | XW_EXT_SEGMENT *pseg ; |
266 | |
267 | pseg = (XW_EXT_SEGMENT*) Xw_malloc(sizeof(XW_EXT_SEGMENT)) ; |
268 | if( pseg ) { |
269 | pseg->link = pbuflist->pseglist ; |
270 | pseg->isupdated = False ; |
271 | pseg->nseg = 0 ; |
272 | pbuflist->pseglist = pseg ; |
273 | } else { |
274 | /*ERROR*EXT_SEGMENT Allocation failed*/ |
275 | Xw_set_error(35,"Xw_add_segment_structure",NULL) ; |
276 | } |
277 | |
278 | return (pseg) ; |
279 | } |
280 | |
281 | #ifdef XW_PROTOTYPE |
282 | XW_STATUS Xw_del_segment_structure(XW_EXT_BUFFER* pbuflist) |
283 | #else |
284 | XW_STATUS Xw_del_segment_structure(pbuflist) |
285 | XW_EXT_BUFFER *pbuflist ; |
286 | #endif /*XW_PROTOTYPE*/ |
287 | /* |
288 | Remove ALL Extended segment structure in the |
289 | segment List |
290 | |
291 | SUCCESS always |
292 | */ |
293 | { |
294 | XW_EXT_SEGMENT *pseg,*qseg ; |
295 | |
296 | for( pseg = pbuflist->pseglist ; pseg ; pseg = qseg ) { |
297 | qseg = (XW_EXT_SEGMENT*)pseg->link ; |
298 | Xw_free(pseg) ; |
299 | } |
300 | pbuflist->pseglist = NULL ; |
301 | |
302 | return (XW_SUCCESS) ; |
303 | } |
304 | |
305 | #define MINXCOORD -32768 |
306 | #define MAXXCOORD 32767 |
307 | #define MINYCOORD -32768 |
308 | #define MAXYCOORD 32767 |
309 | |
310 | #ifdef XW_PROTOTYPE |
311 | int Xw_clip_segment (XW_EXT_WINDOW* pwindow,int x1,int y1,int x2,int y2,XSegment* pseg) |
312 | #else |
313 | int Xw_clip_segment (pwindow,x1,y1,x2,y2,pseg) |
314 | XW_EXT_WINDOW *pwindow; |
315 | int x1,y1,x2,y2; |
316 | XSegment *pseg; |
317 | #endif /*XW_PROTOTYPE*/ |
318 | /* |
319 | Clip a segment when one coord is < MINCOORD or > MAXCOORD. |
320 | Returns the clipped segment and a clip bit-mask status : |
321 | |
322 | 0 Nothing is clipped |
323 | 1 X first point is clipped on MAX |
324 | 2 X first point is clipped on MIN |
325 | 4 Y first point is clipped on MAX |
326 | 8 Y first point is clipped on MIN |
327 | 16 X second point is clipped on MAX |
328 | 32 X second point is clipped on MIN |
329 | 64 Y second point is clipped on MAX |
330 | 128 Y second point is clipped on MIN |
331 | -1 segment is out of space. |
332 | */ |
333 | { |
334 | int xx1 = x1,yy1 = y1,xx2 = x2,yy2 = y2; |
335 | int status = 0; |
336 | |
337 | if( xx1 > MAXXCOORD ) { |
338 | if( xx2 < MAXXCOORD ) { |
339 | float rap = (float)(yy2 - yy1)/(xx2 - xx1); |
340 | yy1 += (int)((MAXXCOORD - xx1) * rap); |
341 | xx1 = MAXXCOORD; |
342 | status |= 1; |
343 | } else return -1; |
344 | } else if( xx1 < MINXCOORD ) { |
345 | if( xx2 > MINXCOORD ) { |
346 | float rap = (float)(yy2 - yy1)/(xx2 - xx1); |
347 | yy1 += (int)((MINXCOORD - xx1) * rap); |
348 | xx1 = MINXCOORD; |
349 | status |= 2; |
350 | } else return -1; |
351 | } |
352 | |
353 | if( yy1 > MAXYCOORD ) { |
354 | if( yy2 < MAXYCOORD ) { |
355 | float rap = (float)(xx2 - xx1)/(yy2 - yy1); |
356 | xx1 += (int)((MAXYCOORD - yy1) * rap); |
357 | yy1 = MAXYCOORD; |
358 | status |= 4; |
359 | } else return -1; |
360 | } else if( yy1 < MINYCOORD ) { |
361 | if( yy2 > MINYCOORD ) { |
362 | float rap = (float)(xx2 - xx1)/(yy2 - yy1); |
363 | xx1 += (int)((MINYCOORD - yy1) * rap); |
364 | yy1 = MINYCOORD; |
365 | status |= 8; |
366 | } else return -1; |
367 | } |
368 | |
369 | if( xx2 > MAXXCOORD ) { |
370 | float rap = (float)(yy2 - yy1)/(xx2 - xx1); |
371 | yy2 = yy1 + (int)((MAXXCOORD - xx1) * rap); |
372 | xx2 = MAXXCOORD; |
373 | status |= 16; |
374 | } else if( xx2 < MINXCOORD ) { |
375 | float rap = (float)(yy2 - yy1)/(xx2 - xx1); |
376 | yy2 = yy1 + (int)((MINXCOORD - xx1) * rap); |
377 | xx2 = MINXCOORD; |
378 | status |= 32; |
379 | } |
380 | |
381 | if( yy2 > MAXYCOORD ) { |
382 | float rap = (float)(xx2 - xx1)/(yy2 - yy1); |
383 | xx2 = xx1 + (int)((MAXYCOORD - yy1) * rap); |
384 | yy2 = MAXYCOORD; |
385 | status |= 64; |
386 | } else if( yy2 < MINYCOORD ) { |
387 | float rap = (float)(xx2 - xx1)/(yy2 - yy1); |
388 | xx2 = xx1 + (int)((MINYCOORD - yy1) * rap); |
389 | yy2 = MINYCOORD; |
390 | status |= 128; |
391 | } |
392 | |
393 | pseg->x1 = xx1; |
394 | pseg->y1 = yy1; |
395 | pseg->x2 = xx2; |
396 | pseg->y2 = yy2; |
397 | |
398 | return status; |
399 | } |