]> Pileus Git - ~andy/gtk/blob - gdk/linux-fb/mizerline.c
implement maximize for linux-fb
[~andy/gtk] / gdk / linux-fb / mizerline.c
1 /* $XFree86: xc/programs/Xserver/mi/mizerline.c,v 3.4 1999/10/14 04:43:16 dawes Exp $ */
2 /***********************************************************
3
4 Copyright 1987, 1998  The Open Group
5
6 All Rights Reserved.
7
8 The above copyright notice and this permission notice shall be included in
9 all copies or substantial portions of the Software.
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
14 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
15 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
18 Except as contained in this notice, the name of The Open Group shall not be
19 used in advertising or otherwise to promote the sale, use or other dealings
20 in this Software without prior written authorization from The Open Group.
21
22
23 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
24
25                         All Rights Reserved
26
27 Permission to use, copy, modify, and distribute this software and its 
28 documentation for any purpose and without fee is hereby granted, 
29 provided that the above copyright notice appear in all copies and that
30 both that copyright notice and this permission notice appear in 
31 supporting documentation, and that the name of Digital not be
32 used in advertising or publicity pertaining to distribution of the
33 software without specific, written prior permission.  
34
35 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
36 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
37 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
38 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
39 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
40 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
41 SOFTWARE.
42
43 ******************************************************************/
44 /* $TOG: mizerline.c /main/18 1998/02/09 14:49:45 kaleb $ */
45
46 #include "mi.h"
47 #include "miline.h"
48
49 /* Draw lineSolid, fillStyle-independent zero width lines.
50  *
51  * Must keep X and Y coordinates in "ints" at least until after they're
52  * translated and clipped to accomodate CoordModePrevious lines with very
53  * large coordinates.
54  *
55  * Draws the same pixels regardless of sign(dx) or sign(dy).
56  *
57  * Ken Whaley
58  *
59  */
60
61 /* largest positive value that can fit into a component of a point.
62  * Assumes that the point structure is {type x, y;} where type is
63  * a signed type.
64  */
65 #define MAX_COORDINATE ((1 << (((sizeof(GdkPoint) >> 1) << 3) - 1)) - 1)
66
67 #define MI_OUTPUT_POINT(xx, yy)\
68 {\
69     if ( !new_span && yy == current_y)\
70     {\
71         if (xx < spans->x)\
72             spans->x = xx;\
73         spans->width++; \
74     }\
75     else\
76     {\
77         ++Nspans;\
78         ++spans;\
79         spans->x = xx;\
80         spans->y = yy;\
81         spans->width = 1; \
82         current_y = yy;\
83         new_span = FALSE;\
84     }\
85 }
86
87 void
88 miZeroLine(pDraw, pGC, mode, npt, pptInit)
89     GdkDrawable* pDraw;
90     GdkGC*      pGC;
91     int         mode;           /* Origin or Previous */
92     int         npt;            /* number of points */
93     GdkPoint* pptInit;
94 {
95     int Nspans, current_y = 0;
96     GdkPoint* ppt; 
97     GdkSpan* pspanInit, *spans;
98     int list_len;
99     int xleft, ytop, xright, ybottom;
100     int new_x1, new_y1, new_x2, new_y2;
101     int x = 0, y = 0, x1, y1, x2, y2, xstart, ystart;
102     int oc1, oc2;
103     int result;
104     int pt1_clipped, pt2_clipped = 0;
105     gboolean new_span;
106     int signdx, signdy;
107     int clipdx, clipdy;
108     int width, height;
109     int adx, ady;
110     int octant;
111     unsigned int bias = miGetZeroLineBias();
112     int e, e1, e2, e3;  /* Bresenham error terms */
113     int length;         /* length of lines == # of pixels on major axis */
114
115     xleft   = 0;
116     ytop    = 0;
117     xright  = GDK_DRAWABLE_FBDATA(pDraw)->width - 1;
118     ybottom = GDK_DRAWABLE_FBDATA(pDraw)->height - 1;
119
120     /* it doesn't matter whether we're in drawable or screen coordinates,
121      * FillSpans simply cannot take starting coordinates outside of the
122      * range of a GdkPoint component.
123      */
124
125     /* since we're clipping to the drawable's boundaries & coordinate
126      * space boundaries, we're guaranteed that the larger of width/height
127      * is the longest span we'll need to output
128      */
129     width = xright - xleft + 1;
130     height = ybottom - ytop + 1;
131     list_len = (height >= width) ? height : width;
132     pspanInit = (GdkSpan*)ALLOCATE_LOCAL(list_len * sizeof(GdkSpan));
133     if (!pspanInit)
134         return;
135
136     Nspans = 0;
137     new_span = TRUE;
138     spans  = pspanInit - 1;
139     ppt = pptInit;
140
141     xstart = ppt->x;
142     ystart = ppt->y;
143     
144     /* x2, y2, oc2 copied to x1, y1, oc1 at top of loop to simplify
145      * iteration logic
146      */
147     x2 = xstart;
148     y2 = ystart;
149     oc2 = 0;
150     MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom);
151
152     while (--npt > 0)
153     {
154         if (Nspans > 0)
155           gdk_fb_fill_spans(pDraw, pGC, pspanInit, Nspans, FALSE);
156         Nspans = 0;
157         new_span = TRUE;
158         spans  = pspanInit - 1;
159
160         x1  = x2;
161         y1  = y2;
162         oc1 = oc2;
163         ++ppt;
164
165         x2 = ppt->x;
166         y2 = ppt->y;
167
168         oc2 = 0;
169         MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom);
170
171         CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant);
172
173         if (adx > ady)
174         {
175             e1 = ady << 1;
176             e2 = e1 - (adx << 1);
177             e  = e1 - adx;
178             length  = adx;      /* don't draw endpoint in main loop */
179
180             FIXUP_ERROR(e, octant, bias);
181
182             new_x1 = x1;
183             new_y1 = y1;
184             new_x2 = x2;
185             new_y2 = y2;
186             pt1_clipped = 0;
187             pt2_clipped = 0;
188
189             if ((oc1 | oc2) != 0)
190             {
191                 result = miZeroClipLine(xleft, ytop, xright, ybottom,
192                                         &new_x1, &new_y1, &new_x2, &new_y2,
193                                         adx, ady,
194                                         &pt1_clipped, &pt2_clipped,
195                                         octant, bias, oc1, oc2);
196                 if (result == -1)
197                     continue;
198
199                 length = abs(new_x2 - new_x1);
200
201                 /* if we've clipped the endpoint, always draw the full length
202                  * of the segment, because then the capstyle doesn't matter 
203                  */
204                 if (pt2_clipped)
205                     length++;
206
207                 if (pt1_clipped)
208                 {
209                     /* must calculate new error terms */
210                     clipdx = abs(new_x1 - x1);
211                     clipdy = abs(new_y1 - y1);
212                     e += (clipdy * e2) + ((clipdx - clipdy) * e1);
213                 }
214             }
215
216             /* draw the segment */
217
218             x = new_x1;
219             y = new_y1;
220             
221             e3 = e2 - e1;
222             e  = e - e1;
223
224             while (length--)
225             {
226                 MI_OUTPUT_POINT(x, y);
227                 e += e1;
228                 if (e >= 0)
229                 {
230                     y += signdy;
231                     e += e3;
232                 }
233                 x += signdx;
234             }
235         }
236         else    /* Y major line */
237         {
238             e1 = adx << 1;
239             e2 = e1 - (ady << 1);
240             e  = e1 - ady;
241             length  = ady;      /* don't draw endpoint in main loop */
242
243             SetYMajorOctant(octant);
244             FIXUP_ERROR(e, octant, bias);
245
246             new_x1 = x1;
247             new_y1 = y1;
248             new_x2 = x2;
249             new_y2 = y2;
250             pt1_clipped = 0;
251             pt2_clipped = 0;
252
253             if ((oc1 | oc2) != 0)
254             {
255                 result = miZeroClipLine(xleft, ytop, xright, ybottom,
256                                         &new_x1, &new_y1, &new_x2, &new_y2,
257                                         adx, ady,
258                                         &pt1_clipped, &pt2_clipped,
259                                         octant, bias, oc1, oc2);
260                 if (result == -1)
261                     continue;
262
263                 length = abs(new_y2 - new_y1);
264
265                 /* if we've clipped the endpoint, always draw the full length
266                  * of the segment, because then the capstyle doesn't matter 
267                  */
268                 if (pt2_clipped)
269                     length++;
270
271                 if (pt1_clipped)
272                 {
273                     /* must calculate new error terms */
274                     clipdx = abs(new_x1 - x1);
275                     clipdy = abs(new_y1 - y1);
276                     e += (clipdx * e2) + ((clipdy - clipdx) * e1);
277                 }
278             }
279
280             /* draw the segment */
281
282             x = new_x1;
283             y = new_y1;
284
285             e3 = e2 - e1;
286             e  = e - e1;
287
288             while (length--)
289             {
290                 MI_OUTPUT_POINT(x, y);
291                 e += e1;
292                 if (e >= 0)
293                 {
294                     x += signdx;
295                     e += e3;
296                 }
297                 y += signdy;
298             }
299         }
300     }
301
302     /* only do the capnotlast check on the last segment
303      * and only if the endpoint wasn't clipped.  And then, if the last
304      * point is the same as the first point, do not draw it, unless the
305      * line is degenerate
306      */
307     if ( (! pt2_clipped) && (GDK_GC_FBDATA(pGC)->values.cap_style != GDK_CAP_NOT_LAST) &&
308                 (((xstart != x2) || (ystart != y2)) || (ppt == pptInit + 1)))
309     {
310         MI_OUTPUT_POINT(x, y);
311     }    
312
313     if (Nspans > 0)
314       gdk_fb_fill_spans(pDraw, pGC, pspanInit, Nspans, FALSE);
315
316     DEALLOCATE_LOCAL(pspanInit);
317 }
318
319 void
320 miZeroDashLine(dst, pgc, mode, nptInit, pptInit)
321 GdkDrawable* dst;
322 GdkGC* pgc;
323 int mode;
324 int nptInit;            /* number of points in polyline */
325 GdkPoint *pptInit;      /* points in the polyline */
326 {
327     /* XXX kludge until real zero-width dash code is written */
328     GDK_GC_FBDATA(pgc)->values.line_width = 1;
329     miWideDash (dst, pgc, mode, nptInit, pptInit);
330     GDK_GC_FBDATA(pgc)->values.line_width = 0;
331 }