mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-26 13:41:07 +00:00
5b4c8afa7e
* gdk/gdktypes.h: Add new type GdkSpan * docs/reference/gdk/gdk-sections.txt, docs/reference/gdk/tmpl/regions.sgml, gdk/gdkregion-generic.c, gdk/gdkregion.h: Implement and document gdk_region_spans_intersect_foreach. * gdk/linux-fb/Makefile.am, gdk/linux-fb/gdkrender-fb.c: Add new file gdkrender-fb.c which contains all core rendering code. Add gdk_fb_fill_rectangle_generic (old rectangle code) and gdk_fb_fill_rectangle_simple_16, gdk_fb_fill_rectangle_simple_32 (optimized rectangle fillers). * gdk/linux-fb/gdkdrawable-fb2.c: Move all rendering code to gdkrender-fb.c. Change from using GdkRectangles and GdkSegments for spans to GdkSpan. Use the new span intersection functions in gdk_fb_fill_spans. gdk_fb_draw_rectangle() clips filled rectangles and calls gc->fill_rectangle with the result. gdk_fb_fill_spans() gets extra argument "sorted". * gdk/linux-fb/gdkevents-fb.c: Remove unused includes and defines. New function gdk_fb_get_time() to get correct time for events. * gdk/linux-fb/gdkinput-ps2.c: Use gdk method of generating multiple-clicks (gdk_event_button_generate) Make sure to set the time of all events. * gdk/linux-fb/gdkmain-fb.c: Use gdk_fb_get_time (). * gdk/linux-fb/gdkprivate-fb.h: New virtual GC calls: fill_span & fill_rectangle. Export gdk_fb_get_time(). gdk_fb_fill_spans() gets extra argument "sorted". * gdk/linux-fb/mi*.c: Use GdkSpan instead of GdkRectangle. Pass correct sorted to gdk_fb_fill_spans. (sorted value taken from XFree 4 source)
261 lines
7.7 KiB
C
261 lines
7.7 KiB
C
/***********************************************************
|
||
|
||
Copyright 1987, 1998 The Open Group
|
||
|
||
All Rights Reserved.
|
||
|
||
The above copyright notice and this permission notice shall be included in
|
||
all copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
||
Except as contained in this notice, the name of The Open Group shall not be
|
||
used in advertising or otherwise to promote the sale, use or other dealings
|
||
in this Software without prior written authorization from The Open Group.
|
||
|
||
|
||
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
|
||
|
||
All Rights Reserved
|
||
|
||
Permission to use, copy, modify, and distribute this software and its
|
||
documentation for any purpose and without fee is hereby granted,
|
||
provided that the above copyright notice appear in all copies and that
|
||
both that copyright notice and this permission notice appear in
|
||
supporting documentation, and that the name of Digital not be
|
||
used in advertising or publicity pertaining to distribution of the
|
||
software without specific, written prior permission.
|
||
|
||
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
|
||
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||
SOFTWARE.
|
||
|
||
******************************************************************/
|
||
/* $TOG: mifpolycon.c /main/13 1998/02/09 14:47:05 kaleb $ */
|
||
#include <math.h>
|
||
#include "mi.h"
|
||
#include "mifpoly.h"
|
||
|
||
static int GetFPolyYBounds();
|
||
|
||
#ifdef ICEILTEMPDECL
|
||
ICEILTEMPDECL
|
||
#endif
|
||
|
||
/*
|
||
* Written by Todd Newman; April. 1987.
|
||
*
|
||
* Fill a convex polygon. If the given polygon
|
||
* is not convex, then the result is undefined.
|
||
* The algorithm is to order the edges from smallest
|
||
* y to largest by partitioning the array into a left
|
||
* edge list and a right edge list. The algorithm used
|
||
* to traverse each edge is digital differencing analyzer
|
||
* line algorithm with y as the major axis. There's some funny linear
|
||
* interpolation involved because of the subpixel postioning.
|
||
*/
|
||
void
|
||
miFillSppPoly(GdkDrawable *dst, GdkGC *pgc, int count, SppPointPtr ptsIn, int xTrans, int yTrans, double xFtrans, double yFtrans)
|
||
#if 0
|
||
GdkDrawable* dst;
|
||
GdkGC* pgc;
|
||
int count; /* number of points */
|
||
SppPointPtr ptsIn; /* the points */
|
||
int xTrans, yTrans; /* Translate each point by this */
|
||
double xFtrans, yFtrans; /* translate before conversion
|
||
by this amount. This provides
|
||
a mechanism to match rounding
|
||
errors with any shape that must
|
||
meet the polygon exactly.
|
||
*/
|
||
#endif
|
||
{
|
||
double xl, xr, /* x vals of left and right edges */
|
||
ml, /* left edge slope */
|
||
mr, /* right edge slope */
|
||
dy, /* delta y */
|
||
i; /* loop counter */
|
||
int y, /* current scanline */
|
||
j,
|
||
imin, /* index of vertex with smallest y */
|
||
ymin, /* y-extents of polygon */
|
||
ymax,
|
||
*Marked; /* set if this vertex has been used */
|
||
register int left, right, /* indices to first endpoints */
|
||
nextleft,
|
||
nextright; /* indices to second endpoints */
|
||
GdkSpan* ptsOut,
|
||
*FirstPoint; /* output buffer */
|
||
|
||
imin = GetFPolyYBounds(ptsIn, count, yFtrans, &ymin, &ymax);
|
||
|
||
y = ymax - ymin + 1;
|
||
if ((count < 3) || (y <= 0))
|
||
return;
|
||
ptsOut = FirstPoint = (GdkSpan*)ALLOCATE_LOCAL(sizeof(GdkSpan) * y);
|
||
Marked = (int *) ALLOCATE_LOCAL(sizeof(int) * count);
|
||
|
||
if(!ptsOut || !Marked)
|
||
{
|
||
if (Marked) DEALLOCATE_LOCAL(Marked);
|
||
if (ptsOut) DEALLOCATE_LOCAL(ptsOut);
|
||
return;
|
||
}
|
||
|
||
for(j = 0; j < count; j++)
|
||
Marked[j] = 0;
|
||
nextleft = nextright = imin;
|
||
Marked[imin] = -1;
|
||
y = ICEIL(ptsIn[nextleft].y + yFtrans);
|
||
|
||
/*
|
||
* loop through all edges of the polygon
|
||
*/
|
||
do
|
||
{
|
||
/* add a left edge if we need to */
|
||
if ((y > (ptsIn[nextleft].y + yFtrans) ||
|
||
ISEQUAL(y, ptsIn[nextleft].y + yFtrans)) &&
|
||
Marked[nextleft] != 1)
|
||
{
|
||
Marked[nextleft]++;
|
||
left = nextleft++;
|
||
|
||
/* find the next edge, considering the end conditions */
|
||
if (nextleft >= count)
|
||
nextleft = 0;
|
||
|
||
/* now compute the starting point and slope */
|
||
dy = ptsIn[nextleft].y - ptsIn[left].y;
|
||
if (dy != 0.0)
|
||
{
|
||
ml = (ptsIn[nextleft].x - ptsIn[left].x) / dy;
|
||
dy = y - (ptsIn[left].y + yFtrans);
|
||
xl = (ptsIn[left].x + xFtrans) + ml * MAX(dy, 0);
|
||
}
|
||
}
|
||
|
||
/* add a right edge if we need to */
|
||
if ((y > ptsIn[nextright].y + yFtrans) ||
|
||
(ISEQUAL(y, ptsIn[nextright].y + yFtrans)
|
||
&& Marked[nextright] != 1))
|
||
{
|
||
Marked[nextright]++;
|
||
right = nextright--;
|
||
|
||
/* find the next edge, considering the end conditions */
|
||
if (nextright < 0)
|
||
nextright = count - 1;
|
||
|
||
/* now compute the starting point and slope */
|
||
dy = ptsIn[nextright].y - ptsIn[right].y;
|
||
if (dy != 0.0)
|
||
{
|
||
mr = (ptsIn[nextright].x - ptsIn[right].x) / dy;
|
||
dy = y - (ptsIn[right].y + yFtrans);
|
||
xr = (ptsIn[right].x + xFtrans) + mr * MAX(dy, 0);
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
* generate scans to fill while we still have
|
||
* a right edge as well as a left edge.
|
||
*/
|
||
i = (MIN(ptsIn[nextleft].y, ptsIn[nextright].y) + yFtrans) - y;
|
||
|
||
if (i < EPSILON)
|
||
{
|
||
if(Marked[nextleft] && Marked[nextright])
|
||
{
|
||
/* Arrgh, we're trapped! (no more points)
|
||
* Out, we've got to get out of here before this decadence saps
|
||
* our will completely! */
|
||
break;
|
||
}
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
j = (int) i;
|
||
if(!j)
|
||
j++;
|
||
}
|
||
while (j > 0)
|
||
{
|
||
int cxl, cxr;
|
||
|
||
ptsOut->y = (y) + yTrans;
|
||
|
||
cxl = ICEIL(xl);
|
||
cxr = ICEIL(xr);
|
||
/* reverse the edges if necessary */
|
||
if (xl < xr)
|
||
{
|
||
ptsOut->width = cxr - cxl;
|
||
(ptsOut++)->x = cxl + xTrans;
|
||
}
|
||
else
|
||
{
|
||
ptsOut->width = cxl - cxr;
|
||
(ptsOut++)->x = cxr + xTrans;
|
||
}
|
||
y++;
|
||
|
||
/* increment down the edges */
|
||
xl += ml;
|
||
xr += mr;
|
||
j--;
|
||
}
|
||
} while (y <= ymax);
|
||
|
||
/* Finally, fill the spans we've collected */
|
||
gdk_fb_fill_spans(dst, pgc, FirstPoint, ptsOut-FirstPoint, TRUE);
|
||
DEALLOCATE_LOCAL(Marked);
|
||
DEALLOCATE_LOCAL(FirstPoint);
|
||
}
|
||
|
||
|
||
/* Find the index of the point with the smallest y.also return the
|
||
* smallest and largest y */
|
||
static
|
||
int
|
||
GetFPolyYBounds(pts, n, yFtrans, by, ty)
|
||
register SppPointPtr pts;
|
||
int n;
|
||
double yFtrans;
|
||
int *by, *ty;
|
||
{
|
||
register SppPointPtr ptMin;
|
||
double ymin, ymax;
|
||
SppPointPtr ptsStart = pts;
|
||
|
||
ptMin = pts;
|
||
ymin = ymax = (pts++)->y;
|
||
|
||
while (--n > 0) {
|
||
if (pts->y < ymin)
|
||
{
|
||
ptMin = pts;
|
||
ymin = pts->y;
|
||
}
|
||
if(pts->y > ymax)
|
||
ymax = pts->y;
|
||
|
||
pts++;
|
||
}
|
||
|
||
*by = ICEIL(ymin + yFtrans);
|
||
*ty = ICEIL(ymax + yFtrans - 1);
|
||
return(ptMin-ptsStart);
|
||
}
|