mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-10 19:00:08 +00:00
Put it into CVS.
Put it into CVS.
This commit is contained in:
parent
85e7a89b13
commit
c496211676
8
gdk/linux-fb/.cvsignore
Normal file
8
gdk/linux-fb/.cvsignore
Normal file
@ -0,0 +1,8 @@
|
||||
*.lo
|
||||
Makefile
|
||||
Makefile.in
|
||||
.deps
|
||||
_libs
|
||||
.libs
|
||||
libgdk-x11.la
|
||||
gxid
|
61
gdk/linux-fb/Makefile.am
Normal file
61
gdk/linux-fb/Makefile.am
Normal file
@ -0,0 +1,61 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
INCLUDES = @STRIP_BEGIN@ \
|
||||
-DG_LOG_DOMAIN=\"Gdk\" \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_srcdir)/gdk \
|
||||
-I$(top_builddir)/gdk \
|
||||
@GTK_DEBUG_FLAGS@ \
|
||||
@GTK_XIM_FLAGS@ \
|
||||
@GTK_LOCALE_FLAGS@ \
|
||||
@GLIB_CFLAGS@ \
|
||||
@STRIP_END@
|
||||
|
||||
LDFLAGS = @STRIP_BEGIN@ \
|
||||
@GLIB_LIBS@ \
|
||||
-L/gnome2/lib \
|
||||
-lt1 \
|
||||
-lm \
|
||||
@STRIP_END@
|
||||
|
||||
lib_LTLIBRARIES = libgdk-fb.la
|
||||
noinst_PROGRAMS=test-fb
|
||||
|
||||
test_fb_LDFLAGS=../libgdk.la libgdk-fb.la
|
||||
|
||||
libgdk_fb_la_SOURCES = \
|
||||
gdkcolor-fb.c \
|
||||
gdkcursor-fb.c \
|
||||
gdkdnd-fb.c \
|
||||
gdkdrawable-fb2.c \
|
||||
gdkfont-fb.c \
|
||||
gdkgc-fb.c \
|
||||
gdkgeometry-fb.c \
|
||||
gdkglobals-fb.c \
|
||||
gdkim-fb.c \
|
||||
gdkimage-fb.c \
|
||||
gdkinput.c \
|
||||
gdkmain-fb.c \
|
||||
gdkpixmap-fb.c \
|
||||
gdkproperty-fb.c \
|
||||
gdkpolyreg-generic.c \
|
||||
gdkregion-generic.c \
|
||||
gdkselection-fb.c \
|
||||
gdkvisual-fb.c \
|
||||
gdkwindow-fb.c \
|
||||
gdkx.h \
|
||||
gdkprivate-fb.h \
|
||||
gdkinputprivate.h \
|
||||
gdkinput-ps2.c \
|
||||
gdkevents-fb.c \
|
||||
miarc.c \
|
||||
midash.c \
|
||||
mifillarc.c \
|
||||
mifpolycon.c \
|
||||
mipoly.c \
|
||||
mipolygen.c \
|
||||
mipolyutil.c \
|
||||
miwideline.c \
|
||||
mizerclip.c \
|
||||
mizerline.c \
|
||||
mispans.c
|
3
gdk/linux-fb/TODO
Normal file
3
gdk/linux-fb/TODO
Normal file
@ -0,0 +1,3 @@
|
||||
. Fix CTree
|
||||
. DnD?
|
||||
. All the standard X cursors
|
759
gdk/linux-fb/gdkcolor-fb.c
Normal file
759
gdk/linux-fb/gdkcolor-fb.c
Normal file
@ -0,0 +1,759 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "gdkcolor.h"
|
||||
#include "gdkprivate-fb.h"
|
||||
|
||||
static gint gdk_colormap_match_color (GdkColormap *cmap,
|
||||
GdkColor *color,
|
||||
const gchar *available);
|
||||
GdkColormap*
|
||||
gdk_colormap_new (GdkVisual *visual,
|
||||
gint private_cmap)
|
||||
{
|
||||
GdkColormap *colormap;
|
||||
GdkColormapPrivateFB *private;
|
||||
GdkFBDisplay *fbd;
|
||||
int i;
|
||||
|
||||
g_return_val_if_fail (visual != NULL, NULL);
|
||||
|
||||
private = g_new (GdkColormapPrivateFB, 1);
|
||||
colormap = (GdkColormap*) private;
|
||||
|
||||
private->base.visual = visual;
|
||||
private->base.ref_count = 1;
|
||||
fbd = gdk_display;
|
||||
|
||||
private->hash = NULL;
|
||||
|
||||
colormap->size = visual->colormap_size;
|
||||
colormap->colors = NULL;
|
||||
|
||||
switch (visual->type)
|
||||
{
|
||||
case GDK_VISUAL_STATIC_GRAY:
|
||||
case GDK_VISUAL_STATIC_COLOR:
|
||||
case GDK_VISUAL_GRAYSCALE:
|
||||
case GDK_VISUAL_PSEUDO_COLOR:
|
||||
private->info = g_new0 (GdkColorInfo, colormap->size);
|
||||
colormap->colors = g_new (GdkColor, colormap->size);
|
||||
|
||||
private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
|
||||
(GCompareFunc) gdk_color_equal);
|
||||
|
||||
if (private_cmap)
|
||||
{
|
||||
guint16 red[256], green[256], blue[256];
|
||||
struct fb_cmap fbc = {0, 256};
|
||||
|
||||
fbc.red = red;
|
||||
fbc.green = green;
|
||||
fbc.blue = blue;
|
||||
|
||||
if(ioctl(fbd->fd, FBIOGETCMAP, &fbc))
|
||||
g_error("ioctl(FBIOGETCMAP) failed");
|
||||
|
||||
for (i = 0; i < colormap->size; i++)
|
||||
{
|
||||
colormap->colors[i].pixel = i;
|
||||
colormap->colors[i].red = red[i];
|
||||
colormap->colors[i].green = green[i];
|
||||
colormap->colors[i].blue = blue[i];
|
||||
}
|
||||
|
||||
gdk_colormap_change (colormap, colormap->size);
|
||||
}
|
||||
break;
|
||||
|
||||
case GDK_VISUAL_DIRECT_COLOR:
|
||||
g_error("NYI");
|
||||
#if 0
|
||||
colormap->colors = g_new (GdkColor, colormap->size);
|
||||
|
||||
size = 1 << visual->red_prec;
|
||||
for (i = 0; i < size; i++)
|
||||
colormap->colors[i].red = i * 65535 / (size - 1);
|
||||
|
||||
size = 1 << visual->green_prec;
|
||||
for (i = 0; i < size; i++)
|
||||
colormap->colors[i].green = i * 65535 / (size - 1);
|
||||
|
||||
size = 1 << visual->blue_prec;
|
||||
for (i = 0; i < size; i++)
|
||||
colormap->colors[i].blue = i * 65535 / (size - 1);
|
||||
|
||||
gdk_colormap_change (colormap, colormap->size);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
|
||||
case GDK_VISUAL_TRUE_COLOR:
|
||||
break;
|
||||
}
|
||||
|
||||
return colormap;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_colormap_real_destroy (GdkColormap *colormap)
|
||||
{
|
||||
GdkColormapPrivateFB *private = (GdkColormapPrivateFB*) colormap;
|
||||
|
||||
if (private->hash)
|
||||
g_hash_table_destroy (private->hash);
|
||||
|
||||
g_free (private->info);
|
||||
g_free (colormap->colors);
|
||||
g_free (colormap);
|
||||
}
|
||||
|
||||
#define MIN_SYNC_TIME 2
|
||||
|
||||
void
|
||||
gdk_colormap_sync (GdkColormap *colormap,
|
||||
gboolean force)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
GdkColormap*
|
||||
gdk_colormap_get_system (void)
|
||||
{
|
||||
static GdkColormap *colormap = NULL;
|
||||
|
||||
if (!colormap)
|
||||
{
|
||||
guint16 red[256], green[256], blue[256];
|
||||
struct fb_cmap fbc = {0, 256};
|
||||
int i, r, g, b;
|
||||
GdkVisual *visual = gdk_visual_get_system();
|
||||
|
||||
if(visual->type == GDK_VISUAL_GRAYSCALE
|
||||
|| visual->type == GDK_VISUAL_PSEUDO_COLOR)
|
||||
{
|
||||
fbc.red = red;
|
||||
fbc.green = green;
|
||||
fbc.blue = blue;
|
||||
switch(visual->type)
|
||||
{
|
||||
case GDK_VISUAL_GRAYSCALE:
|
||||
for(i = 0; i < 256; i++)
|
||||
red[i] = green[i] = blue[i] = i << 8;
|
||||
i--;
|
||||
red[i] = green[i] = blue[i] = 65535; /* Make it a true white */
|
||||
break;
|
||||
case GDK_VISUAL_PSEUDO_COLOR:
|
||||
/* Color cube stolen from gdkrgb upon advice from Owen */
|
||||
for(i = r = 0; r < 6; r++)
|
||||
for(g = 0; g < 6; g++)
|
||||
for(b = 0; b < 6; b++)
|
||||
{
|
||||
red[i] = r * 65535 / 5;
|
||||
green[i] = g * 65535 / 5;
|
||||
blue[i] = b * 65535 / 5;
|
||||
i++;
|
||||
}
|
||||
g_assert(i == 216);
|
||||
|
||||
/* Fill in remaining space with grays */
|
||||
for(i = 216; i < 256; i++)
|
||||
{
|
||||
red[i] = green[i] = blue[i] =
|
||||
(i - 216) * 40;
|
||||
}
|
||||
/* Real white */
|
||||
red[255] = green[255] = blue[255] = 65535;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ioctl(gdk_display->fd, FBIOPUTCMAP, &fbc);
|
||||
}
|
||||
|
||||
colormap = gdk_colormap_new(visual, TRUE);
|
||||
}
|
||||
|
||||
return colormap;
|
||||
}
|
||||
|
||||
gint
|
||||
gdk_colormap_get_system_size (void)
|
||||
{
|
||||
return 1 << (gdk_display->modeinfo.bits_per_pixel);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_colormap_change (GdkColormap *colormap,
|
||||
gint ncolors)
|
||||
{
|
||||
guint16 red[256], green[256], blue[256];
|
||||
struct fb_cmap fbc = {0,256};
|
||||
GdkColormapPrivateFB *private;
|
||||
int i;
|
||||
|
||||
g_return_if_fail (colormap != NULL);
|
||||
|
||||
fbc.red = red;
|
||||
fbc.green = green;
|
||||
fbc.blue = blue;
|
||||
|
||||
private = (GdkColormapPrivateFB*) colormap;
|
||||
switch (private->base.visual->type)
|
||||
{
|
||||
case GDK_VISUAL_GRAYSCALE:
|
||||
for(i = 0; i < ncolors; i++)
|
||||
{
|
||||
red[i] = green[i] = blue[i] =
|
||||
(colormap->colors[i].red +
|
||||
colormap->colors[i].green +
|
||||
colormap->colors[i].blue)/3;
|
||||
}
|
||||
ioctl(gdk_display->fd, FBIOPUTCMAP, &fbc);
|
||||
break;
|
||||
|
||||
case GDK_VISUAL_PSEUDO_COLOR:
|
||||
for (i = 0; i < ncolors; i++)
|
||||
{
|
||||
red[i] = colormap->colors[i].red;
|
||||
green[i] = colormap->colors[i].green;
|
||||
blue[i] = colormap->colors[i].blue;
|
||||
}
|
||||
ioctl(gdk_display->fd, FBIOPUTCMAP, &fbc);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_color_parse (const gchar *spec,
|
||||
GdkColor *color)
|
||||
{
|
||||
char aline[512];
|
||||
FILE *fh;
|
||||
|
||||
g_return_val_if_fail(spec, FALSE);
|
||||
g_return_val_if_fail(color, FALSE);
|
||||
|
||||
if(spec[0] == '#')
|
||||
{
|
||||
if(strlen(spec) == 7)
|
||||
{
|
||||
guint num;
|
||||
|
||||
sscanf(spec + 1, "%x", &num);
|
||||
color->red = (num & 0xFF0000) >> 8;
|
||||
color->green = (num & 0xFF00);
|
||||
color->blue = (num & 0xFF) << 8;
|
||||
}
|
||||
else if(strlen(spec) == 13)
|
||||
{
|
||||
char s1[5], s2[5], s3[5];
|
||||
g_snprintf(s1, sizeof(s1), spec + 1);
|
||||
g_snprintf(s2, sizeof(s2), spec + 5);
|
||||
g_snprintf(s3, sizeof(s3), spec + 9);
|
||||
|
||||
if(!sscanf(s1, "%hx", &color->red))
|
||||
g_error("sscanf failed");
|
||||
if(!sscanf(s2, "%hx", &color->green))
|
||||
g_error("sscanf failed");
|
||||
if(!sscanf(s3, "%hx", &color->blue))
|
||||
g_error("sscanf failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning("Couldn't parse color specifier `%s'", spec);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
fh = fopen("/usr/lib/X11/rgb.txt", "r");
|
||||
if(!fh)
|
||||
return FALSE;
|
||||
|
||||
while(fgets(aline, sizeof(aline), fh))
|
||||
{
|
||||
int red, green, blue;
|
||||
char *ctmp;
|
||||
|
||||
g_strstrip(aline);
|
||||
if(!aline[0] || aline[0] == '#' || aline[0] == '!')
|
||||
continue;
|
||||
|
||||
ctmp = strtok(aline, " \t");
|
||||
if(!ctmp)
|
||||
continue;
|
||||
red = atoi(ctmp);
|
||||
|
||||
ctmp = strtok(NULL, " \t");
|
||||
if(!ctmp)
|
||||
continue;
|
||||
green = atoi(ctmp);
|
||||
|
||||
ctmp = strtok(NULL, " \t");
|
||||
if(!ctmp)
|
||||
continue;
|
||||
blue = atoi(ctmp);
|
||||
|
||||
ctmp = strtok(NULL, " \t");
|
||||
if(!ctmp || strcmp(ctmp, spec))
|
||||
continue;
|
||||
|
||||
color->red = red << 8;
|
||||
color->green = green << 8;
|
||||
color->blue = blue << 8;
|
||||
return TRUE;
|
||||
}
|
||||
fclose(fh);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_colormap_free_colors (GdkColormap *colormap,
|
||||
GdkColor *colors,
|
||||
gint ncolors)
|
||||
{
|
||||
GdkColormapPrivateFB *private;
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (colormap != NULL);
|
||||
g_return_if_fail (colors != NULL);
|
||||
|
||||
private = (GdkColormapPrivateFB*) colormap;
|
||||
|
||||
if ((private->base.visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
|
||||
(private->base.visual->type != GDK_VISUAL_GRAYSCALE))
|
||||
return;
|
||||
|
||||
for (i=0; i<ncolors; i++)
|
||||
{
|
||||
gulong pixel = colors[i].pixel;
|
||||
|
||||
if (private->info[pixel].ref_count)
|
||||
{
|
||||
private->info[pixel].ref_count--;
|
||||
|
||||
if (private->info[pixel].ref_count == 0)
|
||||
{
|
||||
if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
|
||||
g_hash_table_remove (private->hash, &colormap->colors[pixel]);
|
||||
private->info[pixel].flags = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************
|
||||
* Color allocation *
|
||||
********************/
|
||||
|
||||
/* Try to allocate a single color using XAllocColor. If it succeeds,
|
||||
* cache the result in our colormap, and store in ret.
|
||||
*/
|
||||
static gboolean
|
||||
gdk_colormap_alloc1 (GdkColormap *colormap,
|
||||
GdkColor *color,
|
||||
GdkColor *ret)
|
||||
{
|
||||
GdkColormapPrivateFB *private;
|
||||
int i;
|
||||
|
||||
private = (GdkColormapPrivateFB*) colormap;
|
||||
|
||||
if(private->base.visual->type != GDK_VISUAL_GRAYSCALE
|
||||
&& private->base.visual->type != GDK_VISUAL_PSEUDO_COLOR)
|
||||
return FALSE;
|
||||
|
||||
*ret = *color;
|
||||
if(!color->red && !color->green && !color->blue) /* black */
|
||||
{
|
||||
ret->pixel = 0;
|
||||
private->info[ret->pixel].ref_count++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if(color->red == 65535 && color->green == 65535 && color->blue == 65535) /* white */
|
||||
{
|
||||
ret->pixel = 255;
|
||||
private->info[ret->pixel].ref_count++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
for(i = 1; i < (colormap->size - 1); i++)
|
||||
{
|
||||
if(!private->info[i].ref_count)
|
||||
{
|
||||
guint16 red = color->red, green = color->green, blue = color->blue;
|
||||
struct fb_cmap fbc;
|
||||
fbc.len = 1;
|
||||
fbc.start = i;
|
||||
fbc.red = &red;
|
||||
fbc.green = &green;
|
||||
fbc.blue = &blue;
|
||||
|
||||
ioctl(gdk_display->fd, FBIOPUTCMAP, &fbc);
|
||||
|
||||
ret->pixel = i;
|
||||
colormap->colors[ret->pixel] = *ret;
|
||||
private->info[ret->pixel].ref_count = 1;
|
||||
g_hash_table_insert (private->hash,
|
||||
&colormap->colors[ret->pixel],
|
||||
&colormap->colors[ret->pixel]);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gint
|
||||
gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
|
||||
GdkColor *colors,
|
||||
gint ncolors,
|
||||
gboolean writeable,
|
||||
gboolean best_match,
|
||||
gboolean *success)
|
||||
{
|
||||
GdkColormapPrivateFB *private;
|
||||
gint i, index;
|
||||
gint nremaining = 0;
|
||||
gint nfailed = 0;
|
||||
|
||||
private = (GdkColormapPrivateFB*) colormap;
|
||||
index = -1;
|
||||
|
||||
for (i=0; i<ncolors; i++)
|
||||
{
|
||||
if (!success[i])
|
||||
{
|
||||
if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i]))
|
||||
success[i] = TRUE;
|
||||
else
|
||||
nremaining++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (nremaining > 0 && best_match)
|
||||
{
|
||||
gchar *available = g_new (gchar, colormap->size);
|
||||
|
||||
for (i = 0; i < colormap->size; i++)
|
||||
available[i] = ((private->info[i].ref_count == 0) ||
|
||||
!(private->info[i].flags && GDK_COLOR_WRITEABLE));
|
||||
|
||||
while (nremaining > 0)
|
||||
{
|
||||
for (i=0; i<ncolors; i++)
|
||||
{
|
||||
if (!success[i])
|
||||
{
|
||||
index = gdk_colormap_match_color (colormap, &colors[i], available);
|
||||
if (index != -1)
|
||||
{
|
||||
if (private->info[index].ref_count)
|
||||
{
|
||||
private->info[index].ref_count++;
|
||||
colors[i] = colormap->colors[index];
|
||||
success[i] = TRUE;
|
||||
nremaining--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gdk_colormap_alloc1 (colormap,
|
||||
&colormap->colors[index],
|
||||
&colors[i]))
|
||||
{
|
||||
success[i] = TRUE;
|
||||
nremaining--;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
available[index] = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nfailed++;
|
||||
nremaining--;
|
||||
success[i] = 2; /* flag as permanent failure */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
g_free (available);
|
||||
}
|
||||
|
||||
/* Change back the values we flagged as permanent failures */
|
||||
if (nfailed > 0)
|
||||
{
|
||||
for (i=0; i<ncolors; i++)
|
||||
if (success[i] == 2)
|
||||
success[i] = FALSE;
|
||||
nremaining = nfailed;
|
||||
}
|
||||
|
||||
return (ncolors - nremaining);
|
||||
}
|
||||
|
||||
static gint
|
||||
gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap,
|
||||
GdkColor *colors,
|
||||
gint ncolors,
|
||||
gboolean writeable,
|
||||
gboolean best_match,
|
||||
gboolean *success)
|
||||
{
|
||||
GdkColormapPrivateFB *private;
|
||||
GdkColor *lookup_color;
|
||||
gint i;
|
||||
gint nremaining = 0;
|
||||
|
||||
private = (GdkColormapPrivateFB*) colormap;
|
||||
|
||||
/* Check for an exact match among previously allocated colors */
|
||||
|
||||
for (i=0; i<ncolors; i++)
|
||||
{
|
||||
if (!success[i])
|
||||
{
|
||||
lookup_color = g_hash_table_lookup (private->hash, &colors[i]);
|
||||
if (lookup_color)
|
||||
{
|
||||
private->info[lookup_color->pixel].ref_count++;
|
||||
colors[i].pixel = lookup_color->pixel;
|
||||
success[i] = TRUE;
|
||||
}
|
||||
else
|
||||
nremaining++;
|
||||
}
|
||||
}
|
||||
|
||||
/* If that failed, we try to allocate a new color, or approxmiate
|
||||
* with what we can get if best_match is TRUE.
|
||||
*/
|
||||
if (nremaining > 0)
|
||||
return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
gint
|
||||
gdk_colormap_alloc_colors (GdkColormap *colormap,
|
||||
GdkColor *colors,
|
||||
gint ncolors,
|
||||
gboolean writeable,
|
||||
gboolean best_match,
|
||||
gboolean *success)
|
||||
{
|
||||
GdkColormapPrivateFB *private;
|
||||
GdkVisual *visual;
|
||||
gint i;
|
||||
gint nremaining = 0;
|
||||
|
||||
g_return_val_if_fail (colormap != NULL, FALSE);
|
||||
g_return_val_if_fail (colors != NULL, FALSE);
|
||||
|
||||
private = (GdkColormapPrivateFB*) colormap;
|
||||
|
||||
for (i=0; i<ncolors; i++)
|
||||
success[i] = FALSE;
|
||||
|
||||
switch (private->base.visual->type)
|
||||
{
|
||||
case GDK_VISUAL_PSEUDO_COLOR:
|
||||
case GDK_VISUAL_GRAYSCALE:
|
||||
case GDK_VISUAL_STATIC_GRAY:
|
||||
case GDK_VISUAL_STATIC_COLOR:
|
||||
return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors,
|
||||
writeable, best_match, success);
|
||||
break;
|
||||
|
||||
case GDK_VISUAL_DIRECT_COLOR:
|
||||
case GDK_VISUAL_TRUE_COLOR:
|
||||
visual = private->base.visual;
|
||||
|
||||
for (i=0; i<ncolors; i++)
|
||||
{
|
||||
colors[i].pixel = (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
|
||||
((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
|
||||
((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift));
|
||||
success[i] = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return nremaining;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_color_change (GdkColormap *colormap,
|
||||
GdkColor *color)
|
||||
{
|
||||
GdkColormapPrivateFB *private;
|
||||
struct fb_cmap fbc = {0, 1};
|
||||
|
||||
g_return_val_if_fail (colormap != NULL, FALSE);
|
||||
g_return_val_if_fail (color != NULL, FALSE);
|
||||
|
||||
private = (GdkColormapPrivateFB*) colormap;
|
||||
|
||||
switch(private->base.visual->type)
|
||||
{
|
||||
case GDK_VISUAL_GRAYSCALE:
|
||||
color->red = color->green = color->blue = (color->red + color->green + color->blue)/3;
|
||||
|
||||
case GDK_VISUAL_PSEUDO_COLOR:
|
||||
fbc.start = color->pixel;
|
||||
fbc.red = &color->red;
|
||||
fbc.green = &color->green;
|
||||
fbc.blue = &color->blue;
|
||||
ioctl(gdk_display->fd, FBIOPUTCMAP, &fbc);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gint
|
||||
gdk_colormap_match_color (GdkColormap *cmap,
|
||||
GdkColor *color,
|
||||
const gchar *available)
|
||||
{
|
||||
GdkColor *colors;
|
||||
guint sum, max;
|
||||
gint rdiff, gdiff, bdiff;
|
||||
gint i, index;
|
||||
|
||||
g_return_val_if_fail (cmap != NULL, 0);
|
||||
g_return_val_if_fail (color != NULL, 0);
|
||||
|
||||
colors = cmap->colors;
|
||||
max = 3 * (65536);
|
||||
index = -1;
|
||||
|
||||
for (i = 0; i < cmap->size; i++)
|
||||
{
|
||||
if ((!available) || (available && available[i]))
|
||||
{
|
||||
rdiff = (color->red - colors[i].red);
|
||||
gdiff = (color->green - colors[i].green);
|
||||
bdiff = (color->blue - colors[i].blue);
|
||||
|
||||
sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
|
||||
|
||||
if (sum < max)
|
||||
{
|
||||
index = i;
|
||||
max = sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
gint gdk_colors_alloc (GdkColormap *colormap,
|
||||
gboolean contiguous,
|
||||
gulong *planes,
|
||||
gint nplanes,
|
||||
gulong *pixels,
|
||||
gint npixels)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_colors_free (GdkColormap *colormap,
|
||||
gulong *pixels,
|
||||
gint npixels,
|
||||
gulong planes)
|
||||
{
|
||||
}
|
||||
|
||||
gulong
|
||||
gdk_color_context_get_pixel(GdkColorContext *cc,
|
||||
gushort red,
|
||||
gushort green,
|
||||
gushort blue,
|
||||
gint *failed)
|
||||
{
|
||||
g_error("NYI");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
GdkColorContext *
|
||||
gdk_color_context_new(GdkVisual *visual,
|
||||
GdkColormap *colormap)
|
||||
{
|
||||
g_error("NYI");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GdkColorContext *
|
||||
gdk_color_context_new_mono(GdkVisual *visual,
|
||||
GdkColormap *colormap)
|
||||
{
|
||||
g_error("NYI");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_color_context_free(GdkColorContext *cc)
|
||||
{
|
||||
g_error("NYI");
|
||||
}
|
||||
|
||||
gint
|
||||
gdk_color_context_query_color(GdkColorContext *cc,
|
||||
GdkColor *color)
|
||||
{
|
||||
g_error("NYI");
|
||||
|
||||
return 0;
|
||||
}
|
81
gdk/linux-fb/gdkcursor-fb.c
Normal file
81
gdk/linux-fb/gdkcursor-fb.c
Normal file
@ -0,0 +1,81 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include "gdkfb.h"
|
||||
#include "gdkprivate-fb.h"
|
||||
#include "gdkcursor.h"
|
||||
|
||||
GdkCursor*
|
||||
gdk_cursor_new (GdkCursorType cursor_type)
|
||||
{
|
||||
GdkCursorPrivateFB *private;
|
||||
GdkCursor *cursor;
|
||||
|
||||
return NULL;
|
||||
|
||||
private = g_new0(GdkCursorPrivateFB, 1);
|
||||
cursor = (GdkCursor*) private;
|
||||
cursor->type = cursor_type;
|
||||
cursor->ref_count = 1;
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
GdkCursor*
|
||||
gdk_cursor_new_from_pixmap (GdkPixmap *source,
|
||||
GdkPixmap *mask,
|
||||
GdkColor *fg,
|
||||
GdkColor *bg,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
GdkCursorPrivateFB *private;
|
||||
GdkCursor *cursor;
|
||||
|
||||
g_return_val_if_fail (source != NULL, NULL);
|
||||
|
||||
private = g_new (GdkCursorPrivateFB, 1);
|
||||
cursor = (GdkCursor *) private;
|
||||
cursor->type = GDK_CURSOR_IS_PIXMAP;
|
||||
cursor->ref_count = 1;
|
||||
private->cursor = gdk_pixmap_ref(source);
|
||||
private->mask = gdk_pixmap_ref(mask);
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_cursor_destroy (GdkCursor *cursor)
|
||||
{
|
||||
GdkCursorPrivateFB *private;
|
||||
|
||||
g_return_if_fail (cursor != NULL);
|
||||
g_return_if_fail (cursor->ref_count == 0);
|
||||
|
||||
private = (GdkCursorPrivateFB *) cursor;
|
||||
|
||||
g_free (private);
|
||||
}
|
264
gdk/linux-fb/gdkdnd-fb.c
Normal file
264
gdk/linux-fb/gdkdnd-fb.c
Normal file
@ -0,0 +1,264 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1999 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "gdk.h" /* For gdk_flush() */
|
||||
#include "gdkdnd.h"
|
||||
#include "gdkproperty.h"
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkprivate-fb.h"
|
||||
|
||||
typedef struct _GdkDragContextPrivate GdkDragContextPrivate;
|
||||
|
||||
typedef enum {
|
||||
GDK_DRAG_STATUS_DRAG,
|
||||
GDK_DRAG_STATUS_MOTION_WAIT,
|
||||
GDK_DRAG_STATUS_ACTION_WAIT,
|
||||
GDK_DRAG_STATUS_DROP
|
||||
} GtkDragStatus;
|
||||
|
||||
/* Structure that holds information about a drag in progress.
|
||||
* this is used on both source and destination sides.
|
||||
*/
|
||||
struct _GdkDragContextPrivate {
|
||||
GdkDragContext context;
|
||||
|
||||
guint ref_count;
|
||||
};
|
||||
|
||||
/* Drag Contexts */
|
||||
|
||||
static GList *contexts;
|
||||
|
||||
GdkDragContext *
|
||||
gdk_drag_context_new (void)
|
||||
{
|
||||
GdkDragContextPrivate *result;
|
||||
|
||||
result = g_new0 (GdkDragContextPrivate, 1);
|
||||
|
||||
result->ref_count = 1;
|
||||
|
||||
contexts = g_list_prepend (contexts, result);
|
||||
|
||||
return (GdkDragContext *)result;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drag_context_ref (GdkDragContext *context)
|
||||
{
|
||||
g_return_if_fail (context != NULL);
|
||||
|
||||
((GdkDragContextPrivate *)context)->ref_count++;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drag_context_unref (GdkDragContext *context)
|
||||
{
|
||||
GdkDragContextPrivate *private = (GdkDragContextPrivate *)context;
|
||||
|
||||
g_return_if_fail (context != NULL);
|
||||
g_return_if_fail (private->ref_count > 0);
|
||||
|
||||
private->ref_count--;
|
||||
|
||||
if (private->ref_count == 0)
|
||||
{
|
||||
g_dataset_destroy (private);
|
||||
|
||||
g_list_free (context->targets);
|
||||
|
||||
if (context->source_window)
|
||||
{
|
||||
#if 0
|
||||
if ((context->protocol == GDK_DRAG_PROTO_XDND) &&
|
||||
!context->is_source)
|
||||
xdnd_manage_source_filter (context, context->source_window, FALSE);
|
||||
#endif
|
||||
|
||||
gdk_window_unref (context->source_window);
|
||||
}
|
||||
|
||||
if (context->dest_window)
|
||||
gdk_window_unref (context->dest_window);
|
||||
|
||||
#if 0
|
||||
if (private->window_cache)
|
||||
gdk_window_cache_destroy (private->window_cache);
|
||||
#endif
|
||||
|
||||
contexts = g_list_remove (contexts, private);
|
||||
g_free (private);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
************************** Public API ***********************
|
||||
*************************************************************/
|
||||
|
||||
void
|
||||
gdk_dnd_init (void)
|
||||
{
|
||||
}
|
||||
|
||||
/* Source side */
|
||||
|
||||
static void
|
||||
gdk_drag_do_leave (GdkDragContext *context, guint32 time) G_GNUC_UNUSED;
|
||||
|
||||
static void
|
||||
gdk_drag_do_leave (GdkDragContext *context, guint32 time)
|
||||
{
|
||||
}
|
||||
|
||||
GdkDragContext *
|
||||
gdk_drag_begin (GdkWindow *window,
|
||||
GList *targets)
|
||||
{
|
||||
GList *tmp_list;
|
||||
GdkDragContext *new_context;
|
||||
|
||||
g_return_val_if_fail (window != NULL, NULL);
|
||||
|
||||
new_context = gdk_drag_context_new ();
|
||||
new_context->is_source = TRUE;
|
||||
new_context->source_window = window;
|
||||
gdk_window_ref (window);
|
||||
|
||||
tmp_list = g_list_last (targets);
|
||||
new_context->targets = NULL;
|
||||
while (tmp_list)
|
||||
{
|
||||
new_context->targets = g_list_prepend (new_context->targets,
|
||||
tmp_list->data);
|
||||
tmp_list = tmp_list->prev;
|
||||
}
|
||||
|
||||
new_context->actions = 0;
|
||||
|
||||
return new_context;
|
||||
}
|
||||
|
||||
guint32
|
||||
gdk_drag_get_protocol (guint32 xid,
|
||||
GdkDragProtocol *protocol)
|
||||
{
|
||||
*protocol = GDK_DRAG_PROTO_NONE;
|
||||
return GDK_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drag_find_window (GdkDragContext *context,
|
||||
GdkWindow *drag_window,
|
||||
gint x_root,
|
||||
gint y_root,
|
||||
GdkWindow **dest_window,
|
||||
GdkDragProtocol *protocol)
|
||||
{
|
||||
g_return_if_fail (context != NULL);
|
||||
|
||||
*dest_window = gdk_window_get_pointer(NULL, &x_root, &y_root, NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_drag_motion (GdkDragContext *context,
|
||||
GdkWindow *dest_window,
|
||||
GdkDragProtocol protocol,
|
||||
gint x_root,
|
||||
gint y_root,
|
||||
GdkDragAction suggested_action,
|
||||
GdkDragAction possible_actions,
|
||||
guint32 time)
|
||||
{
|
||||
g_return_val_if_fail (context != NULL, FALSE);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drag_drop (GdkDragContext *context,
|
||||
guint32 time)
|
||||
{
|
||||
g_return_if_fail (context != NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drag_abort (GdkDragContext *context,
|
||||
guint32 time)
|
||||
{
|
||||
g_return_if_fail (context != NULL);
|
||||
}
|
||||
|
||||
/* Destination side */
|
||||
|
||||
void
|
||||
gdk_drag_status (GdkDragContext *context,
|
||||
GdkDragAction action,
|
||||
guint32 time)
|
||||
{
|
||||
g_return_if_fail (context != NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drop_reply (GdkDragContext *context,
|
||||
gboolean ok,
|
||||
guint32 time)
|
||||
{
|
||||
g_return_if_fail (context != NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drop_finish (GdkDragContext *context,
|
||||
gboolean success,
|
||||
guint32 time)
|
||||
{
|
||||
g_return_if_fail (context != NULL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gdk_window_register_dnd (GdkWindow *window)
|
||||
{
|
||||
g_return_if_fail (window != NULL);
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* gdk_drag_get_selection:
|
||||
* Returns the selection atom for the current source window
|
||||
* arguments:
|
||||
*
|
||||
* results:
|
||||
*************************************************************/
|
||||
|
||||
GdkAtom
|
||||
gdk_drag_get_selection (GdkDragContext *context)
|
||||
{
|
||||
g_return_val_if_fail (context != NULL, GDK_NONE);
|
||||
|
||||
return GDK_NONE;
|
||||
}
|
||||
|
959
gdk/linux-fb/gdkdrawable-fb2.c
Normal file
959
gdk/linux-fb/gdkdrawable-fb2.c
Normal file
@ -0,0 +1,959 @@
|
||||
#include "gdkprivate-fb.h"
|
||||
#include "mi.h"
|
||||
#include <t1lib.h>
|
||||
|
||||
#ifndef g_alloca
|
||||
#define g_alloca alloca
|
||||
#endif
|
||||
|
||||
static void gdk_fb_drawable_destroy (GdkDrawable *drawable);
|
||||
void gdk_fb_draw_rectangle (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
gint filled,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height);
|
||||
static void gdk_fb_draw_arc (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
gint filled,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height,
|
||||
gint angle1,
|
||||
gint angle2);
|
||||
static void gdk_fb_draw_polygon (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
gint filled,
|
||||
GdkPoint *points,
|
||||
gint npoints);
|
||||
static void gdk_fb_draw_text (GdkDrawable *drawable,
|
||||
GdkFont *font,
|
||||
GdkGC *gc,
|
||||
gint x,
|
||||
gint y,
|
||||
const gchar *text,
|
||||
gint text_length);
|
||||
static void gdk_fb_draw_text_wc (GdkDrawable *drawable,
|
||||
GdkFont *font,
|
||||
GdkGC *gc,
|
||||
gint x,
|
||||
gint y,
|
||||
const GdkWChar *text,
|
||||
gint text_length);
|
||||
void gdk_fb_draw_drawable (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
GdkPixmap *src,
|
||||
gint xsrc,
|
||||
gint ysrc,
|
||||
gint xdest,
|
||||
gint ydest,
|
||||
gint width,
|
||||
gint height);
|
||||
static void gdk_fb_draw_points (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
GdkPoint *points,
|
||||
gint npoints);
|
||||
static void gdk_fb_draw_segments (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
GdkSegment *segs,
|
||||
gint nsegs);
|
||||
static void gdk_fb_draw_lines (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
GdkPoint *points,
|
||||
gint npoints);
|
||||
|
||||
GdkDrawableClass _gdk_fb_drawable_class = {
|
||||
gdk_fb_drawable_destroy,
|
||||
(gpointer)_gdk_fb_gc_new,
|
||||
gdk_fb_draw_rectangle,
|
||||
gdk_fb_draw_arc,
|
||||
gdk_fb_draw_polygon,
|
||||
gdk_fb_draw_text,
|
||||
gdk_fb_draw_text_wc,
|
||||
gdk_fb_draw_drawable,
|
||||
gdk_fb_draw_points,
|
||||
gdk_fb_draw_segments,
|
||||
gdk_fb_draw_lines
|
||||
};
|
||||
|
||||
/*****************************************************
|
||||
* FB specific implementations of generic functions *
|
||||
*****************************************************/
|
||||
|
||||
GdkColormap*
|
||||
gdk_drawable_get_colormap (GdkDrawable *drawable)
|
||||
{
|
||||
GdkColormap *retval = GDK_DRAWABLE_P(drawable)->colormap;
|
||||
|
||||
if(!retval)
|
||||
retval = gdk_colormap_get_system();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_drawable_set_colormap (GdkDrawable *drawable,
|
||||
GdkColormap *colormap)
|
||||
{
|
||||
GdkColormap *old_cmap;
|
||||
old_cmap = GDK_DRAWABLE_P(drawable)->colormap;
|
||||
GDK_DRAWABLE_P(drawable)->colormap = gdk_colormap_ref(colormap);
|
||||
gdk_colormap_unref(old_cmap);
|
||||
}
|
||||
|
||||
/* Drawing
|
||||
*/
|
||||
static void
|
||||
gdk_fb_drawable_destroy (GdkDrawable *drawable)
|
||||
{
|
||||
}
|
||||
|
||||
static GdkRegion *
|
||||
gdk_fb_clip_region(GdkDrawable *drawable, GdkGC *gc, gboolean do_clipping)
|
||||
{
|
||||
GdkRectangle draw_rect;
|
||||
GdkRegion *real_clip_region, *tmpreg;
|
||||
|
||||
g_assert(!GDK_IS_WINDOW(drawable) || !GDK_WINDOW_P(drawable)->input_only);
|
||||
|
||||
draw_rect.x = GDK_DRAWABLE_FBDATA(drawable)->llim_x;
|
||||
draw_rect.y = GDK_DRAWABLE_FBDATA(drawable)->llim_y;
|
||||
draw_rect.width = GDK_DRAWABLE_FBDATA(drawable)->lim_x - draw_rect.x;
|
||||
draw_rect.height = GDK_DRAWABLE_FBDATA(drawable)->lim_y - draw_rect.y;
|
||||
real_clip_region = gdk_region_rectangle(&draw_rect);
|
||||
|
||||
if(do_clipping && GDK_IS_WINDOW(drawable) && GDK_WINDOW_P(drawable)->mapped && !GDK_WINDOW_P(drawable)->input_only)
|
||||
{
|
||||
GdkWindow *parentwin, *lastwin;
|
||||
|
||||
for(parentwin = lastwin = ((GdkWindow *)drawable);
|
||||
parentwin; lastwin = parentwin, parentwin = GDK_WINDOW_P(parentwin)->parent)
|
||||
{
|
||||
GList *cur;
|
||||
|
||||
for(cur = GDK_WINDOW_P(parentwin)->children; cur && cur->data != lastwin; cur = cur->next)
|
||||
{
|
||||
if(!GDK_WINDOW_P(cur->data)->mapped || GDK_WINDOW_P(cur->data)->input_only)
|
||||
continue;
|
||||
|
||||
draw_rect.x = GDK_DRAWABLE_FBDATA(cur->data)->llim_x;
|
||||
draw_rect.y = GDK_DRAWABLE_FBDATA(cur->data)->llim_y;
|
||||
draw_rect.width = GDK_DRAWABLE_FBDATA(cur->data)->lim_x - draw_rect.x;
|
||||
draw_rect.height = GDK_DRAWABLE_FBDATA(cur->data)->lim_y - draw_rect.y;
|
||||
|
||||
tmpreg = gdk_region_rectangle(&draw_rect);
|
||||
gdk_region_subtract(real_clip_region, tmpreg);
|
||||
gdk_region_destroy(tmpreg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(gc)
|
||||
{
|
||||
if(GDK_GC_FBDATA(gc)->clip_region)
|
||||
{
|
||||
tmpreg = gdk_region_copy(GDK_GC_FBDATA(gc)->clip_region);
|
||||
gdk_region_offset(tmpreg, GDK_DRAWABLE_FBDATA(drawable)->abs_x + GDK_GC_P(gc)->clip_x_origin,
|
||||
GDK_DRAWABLE_FBDATA(drawable)->abs_y + GDK_GC_P(gc)->clip_y_origin);
|
||||
gdk_region_intersect(real_clip_region, tmpreg);
|
||||
gdk_region_destroy(tmpreg);
|
||||
}
|
||||
|
||||
if(GDK_GC_FBDATA(gc)->values.clip_mask)
|
||||
{
|
||||
GdkDrawable *cmask = GDK_GC_FBDATA(gc)->values.clip_mask;
|
||||
|
||||
g_assert(GDK_DRAWABLE_P(cmask)->depth == 1);
|
||||
g_assert(GDK_DRAWABLE_FBDATA(cmask)->abs_x == 0
|
||||
&& GDK_DRAWABLE_FBDATA(cmask)->abs_y == 0);
|
||||
|
||||
draw_rect.x = GDK_DRAWABLE_FBDATA(drawable)->abs_x + GDK_DRAWABLE_FBDATA(cmask)->llim_x + GDK_GC_FBDATA(gc)->values.clip_x_origin;
|
||||
draw_rect.y = GDK_DRAWABLE_FBDATA(drawable)->abs_y + GDK_DRAWABLE_FBDATA(cmask)->llim_y + GDK_GC_FBDATA(gc)->values.clip_y_origin;
|
||||
draw_rect.width = GDK_DRAWABLE_P(cmask)->width;
|
||||
draw_rect.height = GDK_DRAWABLE_P(cmask)->height;
|
||||
|
||||
tmpreg = gdk_region_rectangle(&draw_rect);
|
||||
gdk_region_intersect(real_clip_region, tmpreg);
|
||||
gdk_region_destroy(tmpreg);
|
||||
}
|
||||
}
|
||||
|
||||
return real_clip_region;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_fb_fill_span(GdkDrawable *drawable, GdkGC *gc, GdkSegment *cur, guint pixel, GdkVisual *visual)
|
||||
{
|
||||
int curx, cury;
|
||||
guchar *mem = GDK_DRAWABLE_FBDATA(drawable)->mem;
|
||||
guint rowstride = GDK_DRAWABLE_FBDATA(drawable)->rowstride;
|
||||
guint depth = GDK_DRAWABLE_P(drawable)->depth;
|
||||
|
||||
if(gc
|
||||
&& (GDK_GC_FBDATA(gc)->values.clip_mask
|
||||
|| GDK_GC_FBDATA(gc)->values.tile
|
||||
|| GDK_GC_FBDATA(gc)->values.stipple))
|
||||
{
|
||||
int clipxoff, clipyoff; /* Amounts to add to curx & cury to get x & y in clip mask */
|
||||
int tsxoff, tsyoff;
|
||||
GdkDrawable *cmask;
|
||||
guchar *clipmem;
|
||||
guint mask_rowstride;
|
||||
GdkPixmap *ts = NULL;
|
||||
gboolean solid_stipple;
|
||||
|
||||
cmask = GDK_GC_FBDATA(gc)->values.clip_mask;
|
||||
if(cmask)
|
||||
{
|
||||
clipmem = GDK_DRAWABLE_FBDATA(cmask)->mem;
|
||||
clipxoff = GDK_DRAWABLE_FBDATA(cmask)->abs_x - GDK_GC_FBDATA(gc)->values.clip_x_origin - GDK_DRAWABLE_FBDATA(drawable)->abs_x;
|
||||
clipyoff = GDK_DRAWABLE_FBDATA(cmask)->abs_y - GDK_GC_FBDATA(gc)->values.clip_y_origin - GDK_DRAWABLE_FBDATA(drawable)->abs_y;
|
||||
mask_rowstride = GDK_DRAWABLE_FBDATA(cmask)->rowstride;
|
||||
}
|
||||
|
||||
if(GDK_GC_FBDATA(gc)->values.fill == GDK_TILED
|
||||
&& GDK_GC_FBDATA(gc)->values.tile)
|
||||
{
|
||||
gint xstep, ystep;
|
||||
gint relx, rely;
|
||||
|
||||
ts = GDK_GC_FBDATA(gc)->values.tile;
|
||||
for(cury = cur->y1; cury < cur->y2; cury += ystep)
|
||||
{
|
||||
int drawh;
|
||||
|
||||
rely = cury - GDK_DRAWABLE_FBDATA(drawable)->abs_y;
|
||||
drawh = (rely + GDK_GC_FBDATA(gc)->values.ts_y_origin) % GDK_DRAWABLE_P(ts)->height;
|
||||
if(drawh < 0)
|
||||
drawh += GDK_DRAWABLE_P(ts)->height;
|
||||
|
||||
ystep = MIN(GDK_DRAWABLE_P(ts)->height - drawh, cur->y2 - rely);
|
||||
|
||||
for(curx = cur->x1; curx < cur->x2; curx += xstep)
|
||||
{
|
||||
int draww;
|
||||
|
||||
relx = curx - GDK_DRAWABLE_FBDATA(drawable)->abs_x;
|
||||
|
||||
draww = (relx + GDK_GC_FBDATA(gc)->values.ts_x_origin) % GDK_DRAWABLE_P(ts)->width;
|
||||
if(draww < 0)
|
||||
draww += GDK_DRAWABLE_P(ts)->width;
|
||||
|
||||
xstep = MIN(GDK_DRAWABLE_P(ts)->width - draww, cur->x2 - relx);
|
||||
|
||||
gdk_fb_draw_drawable_2(drawable, gc, ts,
|
||||
draww, drawh,
|
||||
relx, rely,
|
||||
xstep, ystep, FALSE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else if((GDK_GC_FBDATA(gc)->values.fill == GDK_STIPPLED
|
||||
|| GDK_GC_FBDATA(gc)->values.fill == GDK_OPAQUE_STIPPLED)
|
||||
&& GDK_GC_FBDATA(gc)->values.stipple)
|
||||
{
|
||||
ts = GDK_GC_FBDATA(gc)->values.stipple;
|
||||
tsxoff = GDK_DRAWABLE_FBDATA(ts)->abs_x - GDK_GC_FBDATA(gc)->values.ts_x_origin - GDK_DRAWABLE_FBDATA(drawable)->abs_x;
|
||||
tsyoff = GDK_DRAWABLE_FBDATA(ts)->abs_y - GDK_GC_FBDATA(gc)->values.ts_y_origin - GDK_DRAWABLE_FBDATA(drawable)->abs_y;
|
||||
solid_stipple = (GDK_GC_FBDATA(gc)->values.fill == GDK_OPAQUE_STIPPLED);
|
||||
}
|
||||
|
||||
switch(depth)
|
||||
{
|
||||
case 1:
|
||||
g_assert(!ts);
|
||||
for(cury = cur->y1; cury < cur->y2; cury++)
|
||||
{
|
||||
for(curx = cur->x1; curx < cur->x2; curx++)
|
||||
{
|
||||
guchar *ptr = mem + (cury * rowstride) + (curx >> 3);
|
||||
int maskx = curx+clipxoff, masky = cury + clipyoff;
|
||||
guchar foo;
|
||||
|
||||
if(cmask)
|
||||
{
|
||||
foo = clipmem[masky*mask_rowstride + (maskx >> 3)];
|
||||
|
||||
if(!(foo & (1 << (maskx % 8))))
|
||||
continue;
|
||||
}
|
||||
|
||||
*ptr |= (1 << (curx % 8));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
for(cury = cur->y1; cury < cur->y2; cury++)
|
||||
{
|
||||
for(curx = cur->x1; curx < cur->x2; curx++)
|
||||
{
|
||||
guchar *ptr = mem + (cury * rowstride) + curx;
|
||||
int maskx = curx+clipxoff, masky = cury + clipyoff;
|
||||
guchar foo;
|
||||
|
||||
if(cmask)
|
||||
{
|
||||
foo = clipmem[masky*mask_rowstride + (maskx >> 3)];
|
||||
|
||||
if(!(foo & (1 << (maskx % 8))))
|
||||
continue;
|
||||
}
|
||||
|
||||
if(ts)
|
||||
{
|
||||
int wid = GDK_DRAWABLE_P(ts)->width, hih = GDK_DRAWABLE_P(ts)->height;
|
||||
maskx = (curx+tsxoff)%wid;
|
||||
masky = (cury+tsyoff)%hih;
|
||||
if(maskx < 0)
|
||||
maskx += wid;
|
||||
if(masky < 0)
|
||||
masky += hih;
|
||||
|
||||
foo = GDK_DRAWABLE_FBDATA(ts)->mem[(maskx >> 3) + GDK_DRAWABLE_FBDATA(ts)->rowstride*masky];
|
||||
if(foo & (1 << (maskx % 8)))
|
||||
{
|
||||
pixel = GDK_GC_FBDATA(gc)->values.foreground.pixel;
|
||||
}
|
||||
else if(solid_stipple)
|
||||
{
|
||||
pixel = GDK_GC_FBDATA(gc)->values.background.pixel;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
*ptr = pixel;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 16:
|
||||
case 24:
|
||||
case 32:
|
||||
for(cury = cur->y1; cury < cur->y2; cury++)
|
||||
{
|
||||
for(curx = cur->x1; curx < cur->x2; curx++)
|
||||
{
|
||||
guint *ptr2 = (guint *)(mem + (cury * rowstride) + (curx * (depth >> 3)));
|
||||
int maskx = curx+clipxoff, masky = cury + clipyoff;
|
||||
guchar foo;
|
||||
|
||||
if(cmask)
|
||||
{
|
||||
foo = clipmem[masky*mask_rowstride + (maskx >> 3)];
|
||||
|
||||
if(!(foo & (1 << (maskx % 8))))
|
||||
continue;
|
||||
}
|
||||
|
||||
if(ts)
|
||||
{
|
||||
int wid = GDK_DRAWABLE_P(ts)->width, hih = GDK_DRAWABLE_P(ts)->height;
|
||||
|
||||
maskx = (curx+tsxoff)%wid;
|
||||
masky = (cury+tsyoff)%hih;
|
||||
if(maskx < 0)
|
||||
maskx += wid;
|
||||
if(masky < 0)
|
||||
masky += hih;
|
||||
|
||||
foo = GDK_DRAWABLE_FBDATA(ts)->mem[(maskx >> 3) + GDK_DRAWABLE_FBDATA(ts)->rowstride*masky];
|
||||
if(foo & (1 << (maskx % 8)))
|
||||
{
|
||||
pixel = GDK_GC_FBDATA(gc)->values.foreground.pixel;
|
||||
}
|
||||
else if(solid_stipple)
|
||||
{
|
||||
pixel = GDK_GC_FBDATA(gc)->values.background.pixel;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
*ptr2 = (*ptr2 & ~(visual->red_mask|visual->green_mask|visual->blue_mask)) | pixel;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(depth)
|
||||
{
|
||||
case 1:
|
||||
for(cury = cur->y1; cury < cur->y2; cury++)
|
||||
{
|
||||
for(curx = cur->x1; curx < cur->x2; curx++)
|
||||
{
|
||||
guchar *ptr = mem + (cury * rowstride) + (curx >> 3);
|
||||
|
||||
if(pixel)
|
||||
*ptr |= (1 << (curx % 8));
|
||||
else
|
||||
*ptr &= ~(1 << (curx % 8));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 8:
|
||||
for(cury = cur->y1; cury < cur->y2; cury++)
|
||||
{
|
||||
guchar *ptr = mem + (cury * rowstride) + cur->x1;
|
||||
memset(ptr, pixel, cur->x2 - cur->x1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 16:
|
||||
case 24:
|
||||
case 32:
|
||||
for(cury = cur->y1; cury < cur->y2; cury++)
|
||||
{
|
||||
for(curx = cur->x1; curx < cur->x2; curx++)
|
||||
{
|
||||
guint *ptr2 = (guint *)(mem + (cury * rowstride) + (curx * (depth >> 3)));
|
||||
|
||||
*ptr2 = (*ptr2 & ~(visual->red_mask|visual->green_mask|visual->blue_mask)) | pixel;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gdk_fb_fill_spans(GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
GdkRectangle *rects, int nrects)
|
||||
{
|
||||
int i;
|
||||
guint pixel;
|
||||
GdkRegion *real_clip_region, *tmpreg;
|
||||
GdkRectangle draw_rect, cursor_rect;
|
||||
GdkVisual *visual = gdk_visual_get_system();
|
||||
gboolean handle_cursor = FALSE;
|
||||
|
||||
if(GDK_IS_WINDOW(drawable) && !GDK_WINDOW_P(drawable)->mapped)
|
||||
return;
|
||||
if(GDK_IS_WINDOW(drawable) && GDK_WINDOW_P(drawable)->input_only)
|
||||
g_error("Drawing on the evil input-only!");
|
||||
|
||||
if(gc)
|
||||
pixel = GDK_GC_FBDATA(gc)->values.foreground.pixel;
|
||||
else if(GDK_IS_WINDOW(drawable))
|
||||
pixel = GDK_WINDOW_P(drawable)->bg_color.pixel;
|
||||
else
|
||||
pixel = 0;
|
||||
|
||||
real_clip_region = gdk_fb_clip_region(drawable, gc, TRUE);
|
||||
|
||||
gdk_fb_get_cursor_rect(&cursor_rect);
|
||||
if(GDK_DRAWABLE_FBDATA(drawable)->mem == GDK_DRAWABLE_FBDATA(gdk_parent_root)->mem
|
||||
&& cursor_rect.x >= 0
|
||||
&& gdk_region_rect_in(real_clip_region, &cursor_rect) != GDK_OVERLAP_RECTANGLE_OUT)
|
||||
{
|
||||
handle_cursor = TRUE;
|
||||
gdk_fb_cursor_hide();
|
||||
}
|
||||
|
||||
for(i = 0; i < nrects; i++)
|
||||
{
|
||||
GdkSegment cur;
|
||||
int j;
|
||||
|
||||
cur.x1 = rects[i].x;
|
||||
cur.y1 = rects[i].y;
|
||||
cur.x2 = cur.x1 + rects[i].width;
|
||||
cur.y2 = cur.y1 + rects[i].height;
|
||||
g_assert(cur.x2 >= cur.x1);
|
||||
g_assert(cur.y2 >= cur.y1);
|
||||
|
||||
cur.x1 += GDK_DRAWABLE_FBDATA(drawable)->abs_x;
|
||||
cur.x1 = MAX(cur.x1, GDK_DRAWABLE_FBDATA(drawable)->llim_x);
|
||||
|
||||
cur.x2 += GDK_DRAWABLE_FBDATA(drawable)->abs_x;
|
||||
cur.x2 = MIN(cur.x2, GDK_DRAWABLE_FBDATA(drawable)->lim_x);
|
||||
cur.x1 = MIN(cur.x1, cur.x2);
|
||||
|
||||
cur.y1 += GDK_DRAWABLE_FBDATA(drawable)->abs_y;
|
||||
cur.y1 = MAX(cur.y1, GDK_DRAWABLE_FBDATA(drawable)->llim_y);
|
||||
|
||||
cur.y2 += GDK_DRAWABLE_FBDATA(drawable)->abs_y;
|
||||
cur.y2 = MIN(cur.y2, GDK_DRAWABLE_FBDATA(drawable)->lim_y);
|
||||
cur.y1 = MIN(cur.y1, cur.y2);
|
||||
|
||||
draw_rect.x = cur.x1;
|
||||
draw_rect.y = cur.y1;
|
||||
draw_rect.width = cur.x2 - cur.x1;
|
||||
draw_rect.height = cur.y2 - cur.y1;
|
||||
|
||||
switch(gdk_region_rect_in(real_clip_region, &draw_rect))
|
||||
{
|
||||
case GDK_OVERLAP_RECTANGLE_PART:
|
||||
tmpreg = gdk_region_rectangle(&draw_rect);
|
||||
gdk_region_intersect(tmpreg, real_clip_region);
|
||||
for(j = 0; j < tmpreg->numRects; j++)
|
||||
gdk_fb_fill_span(drawable, gc, &tmpreg->rects[j], pixel, visual);
|
||||
gdk_region_destroy(tmpreg);
|
||||
break;
|
||||
case GDK_OVERLAP_RECTANGLE_IN:
|
||||
gdk_fb_fill_span(drawable, gc, &cur, pixel, visual);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gdk_region_destroy(real_clip_region);
|
||||
if(handle_cursor)
|
||||
gdk_fb_cursor_unhide();
|
||||
}
|
||||
|
||||
void
|
||||
gdk_fb_draw_drawable_2 (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
GdkPixmap *src,
|
||||
gint xsrc,
|
||||
gint ysrc,
|
||||
gint xdest,
|
||||
gint ydest,
|
||||
gint width,
|
||||
gint height,
|
||||
gboolean draw_bg,
|
||||
gboolean do_clipping)
|
||||
{
|
||||
GdkRegion *real_clip_region, *tmpreg;
|
||||
GdkRectangle rect, cursor_rect;
|
||||
int i;
|
||||
int src_x_off, src_y_off;
|
||||
int clipxoff, clipyoff;
|
||||
guchar *mem = GDK_DRAWABLE_FBDATA(drawable)->mem, *srcmem = GDK_DRAWABLE_FBDATA(src)->mem;
|
||||
guchar *clipmem;
|
||||
guint rowstride = GDK_DRAWABLE_FBDATA(drawable)->rowstride, src_rowstride = GDK_DRAWABLE_FBDATA(src)->rowstride;
|
||||
guint clip_rowstride;
|
||||
GdkDrawableFBData *fbd;
|
||||
gboolean handle_cursor = FALSE;
|
||||
GdkPixmap *bgpm = NULL;
|
||||
GdkWindow *bg_relto = drawable;
|
||||
|
||||
if(GDK_IS_WINDOW(drawable) && !GDK_WINDOW_P(drawable)->mapped)
|
||||
return;
|
||||
if(GDK_IS_WINDOW(drawable) && GDK_WINDOW_P(drawable)->input_only)
|
||||
g_error("Drawing on the evil input-only!");
|
||||
|
||||
if(GDK_IS_WINDOW(drawable))
|
||||
{
|
||||
bgpm = GDK_WINDOW_P(drawable)->bg_pixmap;
|
||||
if(bgpm == GDK_PARENT_RELATIVE_BG)
|
||||
{
|
||||
for(; bgpm == GDK_PARENT_RELATIVE_BG && bg_relto; bg_relto = GDK_WINDOW_P(bg_relto)->parent)
|
||||
bgpm = GDK_WINDOW_P(bg_relto)->bg_pixmap;
|
||||
}
|
||||
|
||||
if(bgpm == GDK_NO_BG)
|
||||
bgpm = NULL;
|
||||
|
||||
if(bgpm)
|
||||
g_assert(GDK_DRAWABLE_P(bgpm)->depth == 8);
|
||||
}
|
||||
|
||||
if(drawable == src)
|
||||
{
|
||||
GdkDrawableFBData *fbd = GDK_DRAWABLE_FBDATA(src);
|
||||
/* One lame hack deserves another ;-) */
|
||||
srcmem = g_alloca(fbd->rowstride * fbd->lim_y);
|
||||
memcpy(srcmem, mem, fbd->rowstride * fbd->lim_y);
|
||||
}
|
||||
|
||||
real_clip_region = gdk_fb_clip_region(drawable, gc, do_clipping);
|
||||
rect.x = xdest + GDK_DRAWABLE_FBDATA(drawable)->abs_x;
|
||||
rect.y = ydest + GDK_DRAWABLE_FBDATA(drawable)->abs_y;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
tmpreg = gdk_region_rectangle(&rect);
|
||||
gdk_region_intersect(real_clip_region, tmpreg);
|
||||
gdk_region_destroy(tmpreg);
|
||||
|
||||
rect.x = xdest + GDK_DRAWABLE_FBDATA(drawable)->abs_x;
|
||||
rect.y = ydest + GDK_DRAWABLE_FBDATA(drawable)->abs_y;
|
||||
rect.width = MAX(GDK_DRAWABLE_P(src)->width - xsrc, 0);
|
||||
rect.height = MAX(GDK_DRAWABLE_P(src)->height - ysrc, 0);
|
||||
if(!rect.width || !rect.height)
|
||||
goto out;
|
||||
tmpreg = gdk_region_rectangle(&rect);
|
||||
gdk_region_intersect(real_clip_region, tmpreg);
|
||||
gdk_region_destroy(tmpreg);
|
||||
|
||||
src_x_off = (GDK_DRAWABLE_FBDATA(src)->abs_x + xsrc) - (GDK_DRAWABLE_FBDATA(drawable)->abs_x + xdest);
|
||||
src_y_off = (GDK_DRAWABLE_FBDATA(src)->abs_y + ysrc) - (GDK_DRAWABLE_FBDATA(drawable)->abs_y + ydest);
|
||||
clipxoff = - GDK_DRAWABLE_FBDATA(drawable)->abs_x;
|
||||
clipyoff = - GDK_DRAWABLE_FBDATA(drawable)->abs_y;
|
||||
if(gc)
|
||||
{
|
||||
clipxoff -= GDK_GC_FBDATA(gc)->values.clip_x_origin;
|
||||
clipyoff -= GDK_GC_FBDATA(gc)->values.clip_y_origin;
|
||||
|
||||
if(GDK_GC_FBDATA(gc)->values.clip_mask)
|
||||
{
|
||||
fbd = GDK_DRAWABLE_FBDATA(GDK_GC_FBDATA(gc)->values.clip_mask);
|
||||
clipmem = GDK_DRAWABLE_FBDATA(GDK_GC_FBDATA(gc)->values.clip_mask)->mem;
|
||||
clip_rowstride = GDK_DRAWABLE_FBDATA(GDK_GC_FBDATA(gc)->values.clip_mask)->rowstride;
|
||||
}
|
||||
}
|
||||
|
||||
gdk_fb_get_cursor_rect(&cursor_rect);
|
||||
if(do_clipping
|
||||
&& GDK_DRAWABLE_FBDATA(drawable)->mem == GDK_DRAWABLE_FBDATA(gdk_parent_root)->mem
|
||||
&& cursor_rect.x >= 0
|
||||
&& gdk_region_rect_in(real_clip_region, &cursor_rect) != GDK_OVERLAP_RECTANGLE_OUT)
|
||||
{
|
||||
handle_cursor = TRUE;
|
||||
gdk_fb_cursor_hide();
|
||||
}
|
||||
|
||||
for(i = 0; i < real_clip_region->numRects; i++)
|
||||
{
|
||||
GdkRegionBox *cur = &real_clip_region->rects[i];
|
||||
int cur_y;
|
||||
|
||||
if(GDK_DRAWABLE_P(src)->depth == GDK_DRAWABLE_P(drawable)->depth
|
||||
&& GDK_DRAWABLE_P(src)->depth > 1
|
||||
&& (!gc || !GDK_GC_FBDATA(gc)->values.clip_mask))
|
||||
{
|
||||
guint depth = GDK_DRAWABLE_P(src)->depth;
|
||||
|
||||
for(cur_y = cur->y1; cur_y < cur->y2; cur_y++)
|
||||
{
|
||||
memcpy(mem + (cur_y * rowstride) + cur->x1*(depth>>3),
|
||||
srcmem + ((cur_y + src_y_off)*src_rowstride) + (cur->x1 + src_x_off)*(depth>>3),
|
||||
(cur->x2 - cur->x1)*(depth>>3));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int cur_x;
|
||||
|
||||
for(cur_y = cur->y1; cur_y < cur->y2; cur_y++)
|
||||
{
|
||||
for(cur_x = cur->x1; cur_x < cur->x2; cur_x++)
|
||||
{
|
||||
guint pixel;
|
||||
guint16 *p16;
|
||||
guint32 *p32;
|
||||
|
||||
if(gc && GDK_GC_FBDATA(gc)->values.clip_mask)
|
||||
{
|
||||
int maskx = cur_x+clipxoff, masky = cur_y + clipyoff;
|
||||
guchar foo;
|
||||
|
||||
if(maskx < 0 || masky < 0)
|
||||
continue;
|
||||
|
||||
foo = clipmem[masky*clip_rowstride + (maskx >> 3)];
|
||||
|
||||
if(!(foo & (1 << (maskx % 8))))
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(GDK_DRAWABLE_P(src)->depth)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
guchar foo = srcmem[((cur_x + src_x_off) >> 3) + ((cur_y + src_y_off)*src_rowstride)];
|
||||
|
||||
if(foo & (1 << ((cur_x + src_x_off) % 8))) {
|
||||
pixel = GDK_GC_FBDATA(gc)->values.foreground.pixel;
|
||||
} else if(draw_bg) {
|
||||
if(bgpm)
|
||||
{
|
||||
int bgx, bgy;
|
||||
|
||||
bgx = (cur_x - GDK_DRAWABLE_FBDATA(bg_relto)->abs_x) % GDK_DRAWABLE_P(bgpm)->width;
|
||||
bgy = (cur_y - GDK_DRAWABLE_FBDATA(bg_relto)->abs_y) % GDK_DRAWABLE_P(bgpm)->height;
|
||||
|
||||
pixel = GDK_DRAWABLE_FBDATA(bgpm)->mem[bgx + bgy * GDK_DRAWABLE_FBDATA(bgpm)->rowstride];
|
||||
}
|
||||
else
|
||||
pixel = GDK_GC_FBDATA(gc)->values.background.pixel;
|
||||
} else
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
pixel = srcmem[(cur_x + src_x_off) + ((cur_y + src_y_off)*src_rowstride)];
|
||||
break;
|
||||
case 16:
|
||||
pixel = *(guint16 *)(srcmem + (cur_x + src_x_off)*2 + ((cur_y + src_y_off)*src_rowstride));
|
||||
break;
|
||||
case 24:
|
||||
pixel = 0x00FFFFFF & *(guint32 *)(srcmem + (cur_x + src_x_off)*3 + ((cur_y + src_y_off)*src_rowstride));
|
||||
break;
|
||||
case 32:
|
||||
pixel = *(guint32 *)(srcmem + (cur_x + src_x_off)*4 + ((cur_y + src_y_off)*src_rowstride));
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
|
||||
switch(GDK_DRAWABLE_P(drawable)->depth)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
guchar *foo = mem + (cur_y*src_rowstride) + (cur_x >> 3);
|
||||
|
||||
if(pixel == GDK_GC_FBDATA(gc)->values.foreground.pixel)
|
||||
*foo |= (1 << (cur_x % 8));
|
||||
else
|
||||
*foo &= ~(1 << (cur_x % 8));
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
mem[cur_x + cur_y*rowstride] = pixel;
|
||||
break;
|
||||
case 16:
|
||||
p16 = (guint16 *)&mem[cur_x*2 + cur_y*rowstride];
|
||||
*p16 = pixel;
|
||||
break;
|
||||
case 24:
|
||||
p32 = (guint32 *)&mem[cur_x*3 + cur_y*rowstride];
|
||||
*p32 = (*p32 & 0xFF000000) | pixel;
|
||||
break;
|
||||
case 32:
|
||||
p32 = (guint32 *)&mem[cur_x*4 + cur_y*rowstride];
|
||||
*p32 = pixel;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
gdk_region_destroy(real_clip_region);
|
||||
|
||||
if(handle_cursor)
|
||||
gdk_fb_cursor_unhide();
|
||||
}
|
||||
|
||||
void
|
||||
gdk_fb_draw_drawable (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
GdkPixmap *src,
|
||||
gint xsrc,
|
||||
gint ysrc,
|
||||
gint xdest,
|
||||
gint ydest,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
gdk_fb_draw_drawable_2(drawable, gc, src, xsrc, ysrc, xdest, ydest, width, height, TRUE, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_fb_draw_text(GdkDrawable *drawable,
|
||||
GdkFont *font,
|
||||
GdkGC *gc,
|
||||
gint x,
|
||||
gint y,
|
||||
const gchar *text,
|
||||
gint text_length)
|
||||
{
|
||||
GLYPH *g;
|
||||
GdkDrawablePrivate tmp_pixmap;
|
||||
GdkDrawableFBData fbd;
|
||||
|
||||
if(GDK_IS_WINDOW(drawable) && !GDK_WINDOW_P(drawable)->mapped)
|
||||
return;
|
||||
|
||||
y -= font->ascent; /* y is relative to baseline, we want it relative to top left corner */
|
||||
|
||||
g = T1_SetString(GDK_FONT_FB(font)->t1_font_id, (char *)text, text_length, 0, T1_KERNING, GDK_FONT_FB(font)->size,
|
||||
NULL);
|
||||
g_assert(g);
|
||||
|
||||
tmp_pixmap.window_type = GDK_DRAWABLE_PIXMAP;
|
||||
tmp_pixmap.width = (g->metrics.rightSideBearing - g->metrics.leftSideBearing);
|
||||
tmp_pixmap.height = (g->metrics.ascent - g->metrics.descent);
|
||||
tmp_pixmap.depth = 1;
|
||||
|
||||
fbd.mem = g->bits;
|
||||
fbd.abs_x = fbd.abs_y = fbd.llim_x = fbd.llim_y = 0;
|
||||
fbd.lim_x = tmp_pixmap.width;
|
||||
fbd.lim_y = tmp_pixmap.height;
|
||||
fbd.rowstride = (tmp_pixmap.width + 7) / 8;
|
||||
tmp_pixmap.klass_data = &fbd;
|
||||
tmp_pixmap.klass = &_gdk_fb_drawable_class;
|
||||
|
||||
gdk_fb_draw_drawable_2(drawable, gc, (GdkPixmap *)&tmp_pixmap, 0, 0, x, y, tmp_pixmap.width, tmp_pixmap.height, FALSE, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_fb_draw_text_wc (GdkDrawable *drawable,
|
||||
GdkFont *font,
|
||||
GdkGC *gc,
|
||||
gint x,
|
||||
gint y,
|
||||
const GdkWChar *text,
|
||||
gint text_length)
|
||||
{
|
||||
char *realbuf;
|
||||
int i;
|
||||
|
||||
if(GDK_IS_WINDOW(drawable) && (!GDK_WINDOW_P(drawable)->mapped || GDK_WINDOW_P(drawable)->input_only))
|
||||
return;
|
||||
|
||||
/* A hack, a hack, a pretty little hack */
|
||||
realbuf = alloca(text_length + 1);
|
||||
for(i = 0; i < text_length; i++)
|
||||
realbuf[i] = text[i];
|
||||
realbuf[i] = 0;
|
||||
|
||||
gdk_fb_draw_text(drawable, font, gc, x, y, realbuf, text_length);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_fb_draw_rectangle (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
gint filled,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
GdkRectangle rect;
|
||||
|
||||
if(filled)
|
||||
{
|
||||
static volatile int print_rect = 0;
|
||||
|
||||
if(print_rect)
|
||||
{
|
||||
fprintf(debug_out, "[%d, %d] +[%d, %d]\n", x, y, width, height);
|
||||
if(y < 0)
|
||||
G_BREAKPOINT();
|
||||
}
|
||||
|
||||
rect.x = x;
|
||||
rect.y = y;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
gdk_fb_fill_spans(drawable, gc, &rect, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
GdkPoint pts[5];
|
||||
pts[0].x = pts[4].x = x;
|
||||
pts[0].y = pts[4].y = y;
|
||||
pts[1].x = x + width;
|
||||
pts[1].y = y;
|
||||
pts[2].x = x + width;
|
||||
pts[2].y = y + height;
|
||||
pts[3].x = x;
|
||||
pts[3].y = y + height;
|
||||
gdk_fb_draw_lines(drawable, gc, pts, 5);
|
||||
}
|
||||
}
|
||||
|
||||
static void gdk_fb_draw_points (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
GdkPoint *points,
|
||||
gint npoints)
|
||||
{
|
||||
GdkRectangle *rects = alloca(npoints * sizeof(GdkRectangle));
|
||||
int i;
|
||||
|
||||
for(i = 0; i < npoints; i++)
|
||||
{
|
||||
rects[i].x = points[i].x;
|
||||
rects[i].y = points[i].y;
|
||||
rects[i].width = rects[i].height = 1;
|
||||
}
|
||||
|
||||
gdk_fb_fill_spans(drawable, gc, rects, npoints);
|
||||
}
|
||||
|
||||
static void gdk_fb_draw_arc (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
gint filled,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height,
|
||||
gint angle1,
|
||||
gint angle2)
|
||||
{
|
||||
miArc arc;
|
||||
|
||||
arc.x = x;
|
||||
arc.y = y;
|
||||
arc.width = width;
|
||||
arc.height = height;
|
||||
arc.angle1 = angle1;
|
||||
arc.angle2 = angle2;
|
||||
|
||||
if(filled)
|
||||
miPolyFillArc(drawable, gc, 1, &arc);
|
||||
else
|
||||
miPolyArc(drawable, gc, 1, &arc);
|
||||
}
|
||||
|
||||
static void gdk_fb_draw_polygon (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
gint filled,
|
||||
GdkPoint *points,
|
||||
gint npoints)
|
||||
{
|
||||
if(filled)
|
||||
miFillPolygon(drawable, gc, 0, 0, npoints, points);
|
||||
else
|
||||
{
|
||||
GdkPoint *realpts = alloca(sizeof(GdkPoint) * (npoints + 1));
|
||||
|
||||
memcpy(realpts, points, sizeof(GdkPoint) * npoints);
|
||||
realpts[npoints] = points[0];
|
||||
gdk_fb_draw_lines(drawable, gc, points, npoints);
|
||||
}
|
||||
}
|
||||
|
||||
static void gdk_fb_draw_lines (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
GdkPoint *points,
|
||||
gint npoints)
|
||||
{
|
||||
if(GDK_GC_FBDATA(gc)->values.line_width > 0)
|
||||
miWideLine(drawable, gc, 0, npoints, points);
|
||||
else
|
||||
miZeroLine(drawable, gc, 0, npoints, points);
|
||||
}
|
||||
|
||||
static void gdk_fb_draw_segments (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
GdkSegment *segs,
|
||||
gint nsegs)
|
||||
{
|
||||
GdkPoint pts[2];
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nsegs; i++)
|
||||
{
|
||||
pts[0].x = segs[i].x1;
|
||||
pts[0].y = segs[i].y1;
|
||||
pts[1].x = segs[i].x2;
|
||||
pts[1].y = segs[i].y2;
|
||||
|
||||
gdk_fb_draw_lines(drawable, gc, pts, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gdk_fb_drawable_clear(GdkDrawable *d)
|
||||
{
|
||||
_gdk_windowing_window_clear_area(d, 0, 0, GDK_DRAWABLE_P(d)->width, GDK_DRAWABLE_P(d)->height);
|
||||
}
|
209
gdk/linux-fb/gdkevents-fb.c
Normal file
209
gdk/linux-fb/gdkevents-fb.c
Normal file
@ -0,0 +1,209 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include "gdk.h"
|
||||
#include "gdkprivate-fb.h"
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkfb.h"
|
||||
|
||||
#include "gdkkeysyms.h"
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
# if STDC_HEADERS
|
||||
# include <string.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef struct _GdkIOClosure GdkIOClosure;
|
||||
typedef struct _GdkEventPrivate GdkEventPrivate;
|
||||
|
||||
#define DOUBLE_CLICK_TIME 250
|
||||
#define TRIPLE_CLICK_TIME 500
|
||||
#define DOUBLE_CLICK_DIST 5
|
||||
#define TRIPLE_CLICK_DIST 5
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* Following flag is set for events on the event queue during
|
||||
* translation and cleared afterwards.
|
||||
*/
|
||||
GDK_EVENT_PENDING = 1 << 0
|
||||
} GdkEventFlags;
|
||||
|
||||
struct _GdkIOClosure
|
||||
{
|
||||
GdkInputFunction function;
|
||||
GdkInputCondition condition;
|
||||
GdkDestroyNotify notify;
|
||||
gpointer data;
|
||||
};
|
||||
|
||||
struct _GdkEventPrivate
|
||||
{
|
||||
GdkEvent event;
|
||||
guint flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* Private function declarations
|
||||
*/
|
||||
|
||||
/* Private variable declarations
|
||||
*/
|
||||
|
||||
#if 0
|
||||
static GList *client_filters; /* Filters for client messages */
|
||||
|
||||
static GSourceFuncs event_funcs = {
|
||||
gdk_event_prepare,
|
||||
gdk_event_check,
|
||||
gdk_event_dispatch,
|
||||
(GDestroyNotify)g_free
|
||||
};
|
||||
#endif
|
||||
|
||||
/*********************************************
|
||||
* Functions for maintaining the event queue *
|
||||
*********************************************/
|
||||
|
||||
void
|
||||
gdk_events_init (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
* gdk_events_pending
|
||||
*
|
||||
* Returns if events are pending on the queue.
|
||||
*
|
||||
* Arguments:
|
||||
*
|
||||
* Results:
|
||||
* Returns TRUE if events are pending
|
||||
*
|
||||
* Side effects:
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
gboolean
|
||||
gdk_events_pending (void)
|
||||
{
|
||||
return gdk_event_queue_find_first()?TRUE:FALSE;
|
||||
}
|
||||
|
||||
GdkEvent*
|
||||
gdk_event_get_graphics_expose (GdkWindow *window)
|
||||
{
|
||||
g_return_val_if_fail (window != NULL, NULL);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_events_queue (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static gint handler_tag = 0;
|
||||
|
||||
static gboolean
|
||||
dispatch_events(gpointer data)
|
||||
{
|
||||
GdkEvent *event;
|
||||
|
||||
GDK_THREADS_ENTER();
|
||||
|
||||
while((event = gdk_event_unqueue()))
|
||||
{
|
||||
if(event->type == GDK_EXPOSE
|
||||
&& event->expose.window == gdk_parent_root)
|
||||
gdk_fb_drawable_clear(event->expose.window);
|
||||
else if(gdk_event_func)
|
||||
(*gdk_event_func)(event, gdk_event_data);
|
||||
gdk_event_free(event);
|
||||
}
|
||||
|
||||
GDK_THREADS_LEAVE();
|
||||
if(event && !handler_tag)
|
||||
handler_tag = g_idle_add_full(G_PRIORITY_HIGH_IDLE, dispatch_events, NULL, NULL);
|
||||
else if(!event && handler_tag)
|
||||
{
|
||||
g_source_remove(handler_tag);
|
||||
handler_tag = 0;
|
||||
}
|
||||
|
||||
return handler_tag?TRUE:FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_event_queue_changed(GList *queue)
|
||||
{
|
||||
if(queue && !handler_tag)
|
||||
handler_tag = g_idle_add_full(G_PRIORITY_HIGH_IDLE, dispatch_events, NULL, NULL);
|
||||
else if(!queue && handler_tag)
|
||||
{
|
||||
g_source_remove(handler_tag);
|
||||
handler_tag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
* gdk_flush
|
||||
*
|
||||
* Flushes the Xlib output buffer and then waits
|
||||
* until all requests have been received and processed
|
||||
* by the X server. The only real use for this function
|
||||
* is in dealing with XShm.
|
||||
*
|
||||
* Arguments:
|
||||
*
|
||||
* Results:
|
||||
*
|
||||
* Side effects:
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
gdk_flush (void)
|
||||
{
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_event_send_client_message (GdkEvent *event, guint32 xid)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void gdk_event_send_clientmessage_toall (GdkEvent *sev)
|
||||
{
|
||||
}
|
18
gdk/linux-fb/gdkfb.h
Normal file
18
gdk/linux-fb/gdkfb.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef GDKFB_H
|
||||
#define GDKFB_H 1
|
||||
|
||||
#include "gdk/gdkprivate.h"
|
||||
|
||||
typedef struct _GdkFBDisplay GdkFBDisplay;
|
||||
typedef struct _GdkFBWindow GdkFBWindow;
|
||||
|
||||
extern GdkFBWindow *gdk_root_window;
|
||||
extern GdkFBDisplay *gdk_display;
|
||||
|
||||
#define GDK_ROOT_WINDOW() gdk_root_window
|
||||
#define GDK_ROOT_PARENT() ((GdkWindow *)gdk_parent_root)
|
||||
#define GDK_DISPLAY() gdk_display
|
||||
|
||||
extern const char *gdk_progclass;
|
||||
|
||||
#endif /* GDKFB_H */
|
328
gdk/linux-fb/gdkfont-fb.c
Normal file
328
gdk/linux-fb/gdkfont-fb.c
Normal file
@ -0,0 +1,328 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include <t1lib.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include "gdkfont.h"
|
||||
#include "gdkprivate-fb.h"
|
||||
|
||||
static GHashTable *font_name_hash = NULL;
|
||||
static GHashTable *fontset_name_hash = NULL;
|
||||
|
||||
static void
|
||||
gdk_font_hash_insert (GdkFontType type, GdkFont *font, const gchar *font_name)
|
||||
{
|
||||
GdkFontPrivateFB *private = (GdkFontPrivateFB *)font;
|
||||
GHashTable **hashp = (type == GDK_FONT_FONT) ?
|
||||
&font_name_hash : &fontset_name_hash;
|
||||
|
||||
if (!*hashp)
|
||||
*hashp = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
|
||||
private->names = g_slist_prepend (private->names, g_strdup (font_name));
|
||||
g_hash_table_insert (*hashp, private->names->data, font);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_font_hash_remove (GdkFontType type, GdkFont *font)
|
||||
{
|
||||
GdkFontPrivateFB *private = (GdkFontPrivateFB *)font;
|
||||
GSList *tmp_list;
|
||||
GHashTable *hash = (type == GDK_FONT_FONT) ?
|
||||
font_name_hash : fontset_name_hash;
|
||||
|
||||
tmp_list = private->names;
|
||||
while (tmp_list)
|
||||
{
|
||||
g_hash_table_remove (hash, tmp_list->data);
|
||||
g_free (tmp_list->data);
|
||||
|
||||
tmp_list = tmp_list->next;
|
||||
}
|
||||
|
||||
g_slist_free (private->names);
|
||||
private->names = NULL;
|
||||
}
|
||||
|
||||
static GdkFont *
|
||||
gdk_font_hash_lookup (GdkFontType type, const gchar *font_name)
|
||||
{
|
||||
GdkFont *result;
|
||||
GHashTable *hash = (type == GDK_FONT_FONT) ?
|
||||
font_name_hash : fontset_name_hash;
|
||||
|
||||
if (!hash)
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
result = g_hash_table_lookup (hash, font_name);
|
||||
if (result)
|
||||
gdk_font_ref (result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
GdkFont*
|
||||
gdk_font_load (const gchar *font_name)
|
||||
{
|
||||
GdkFont *font;
|
||||
GdkFontPrivateFB *private;
|
||||
|
||||
g_return_val_if_fail (font_name != NULL, NULL);
|
||||
|
||||
font = gdk_font_hash_lookup (GDK_FONT_FONTSET, font_name);
|
||||
if (font)
|
||||
return font;
|
||||
|
||||
{
|
||||
char **pieces;
|
||||
BBox bb;
|
||||
|
||||
private = g_new0 (GdkFontPrivateFB, 1);
|
||||
private->base.ref_count = 1;
|
||||
private->names = NULL;
|
||||
|
||||
pieces = g_strsplit(font_name, "-", 2);
|
||||
if(pieces[1])
|
||||
{
|
||||
private->size = atof(pieces[1]);
|
||||
private->t1_font_id = T1_AddFont(pieces[0]);
|
||||
}
|
||||
else
|
||||
private->t1_font_id = T1_AddFont((char *)font_name);
|
||||
g_strfreev(pieces);
|
||||
|
||||
T1_LoadFont(private->t1_font_id);
|
||||
CreateNewFontSize(private->t1_font_id, private->size, FALSE);
|
||||
|
||||
font = (GdkFont*) private;
|
||||
font->type = GDK_FONT_FONTSET;
|
||||
|
||||
bb = T1_GetFontBBox(private->t1_font_id);
|
||||
|
||||
font->ascent = ((double)bb.ury) / 1000.0 * private->size;
|
||||
font->descent = ((double)bb.lly) / -1000.0 * private->size;
|
||||
}
|
||||
|
||||
gdk_font_hash_insert (GDK_FONT_FONTSET, font, font_name);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
GdkFont*
|
||||
gdk_fontset_load (const gchar *fontset_name)
|
||||
{
|
||||
return gdk_font_load(fontset_name);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_font_destroy (GdkFont *font)
|
||||
{
|
||||
gdk_font_hash_remove (font->type, font);
|
||||
|
||||
switch (font->type)
|
||||
{
|
||||
case GDK_FONT_FONT:
|
||||
break;
|
||||
case GDK_FONT_FONTSET:
|
||||
break;
|
||||
default:
|
||||
g_error ("unknown font type.");
|
||||
break;
|
||||
}
|
||||
g_free (font);
|
||||
}
|
||||
|
||||
gint
|
||||
_gdk_font_strlen (GdkFont *font,
|
||||
const gchar *str)
|
||||
{
|
||||
GdkFontPrivateFB *font_private;
|
||||
gint length = 0;
|
||||
|
||||
g_return_val_if_fail (font != NULL, -1);
|
||||
g_return_val_if_fail (str != NULL, -1);
|
||||
|
||||
font_private = (GdkFontPrivateFB*) font;
|
||||
|
||||
if (font->type == GDK_FONT_FONT)
|
||||
{
|
||||
guint16 *string_2b = (guint16 *)str;
|
||||
|
||||
while (*(string_2b++))
|
||||
length++;
|
||||
}
|
||||
else if (font->type == GDK_FONT_FONTSET)
|
||||
{
|
||||
length = strlen (str);
|
||||
}
|
||||
else
|
||||
g_error("undefined font type\n");
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
gint
|
||||
gdk_font_id (const GdkFont *font)
|
||||
{
|
||||
const GdkFontPrivateFB *font_private;
|
||||
|
||||
g_return_val_if_fail (font != NULL, 0);
|
||||
|
||||
font_private = (const GdkFontPrivateFB*) font;
|
||||
|
||||
if (font->type == GDK_FONT_FONT)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
gint
|
||||
gdk_font_equal (const GdkFont *fonta,
|
||||
const GdkFont *fontb)
|
||||
{
|
||||
const GdkFontPrivateFB *privatea;
|
||||
const GdkFontPrivateFB *privateb;
|
||||
|
||||
g_return_val_if_fail (fonta != NULL, FALSE);
|
||||
g_return_val_if_fail (fontb != NULL, FALSE);
|
||||
|
||||
privatea = (const GdkFontPrivateFB*) fonta;
|
||||
privateb = (const GdkFontPrivateFB*) fontb;
|
||||
|
||||
if(fonta == fontb)
|
||||
return TRUE;
|
||||
if(privatea->t1_font_id == privateb->t1_font_id
|
||||
&& privatea->size == privateb->size)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gint
|
||||
gdk_text_width (GdkFont *font,
|
||||
const gchar *text,
|
||||
gint text_length)
|
||||
{
|
||||
GdkFontPrivateFB *private;
|
||||
gint width;
|
||||
double n;
|
||||
|
||||
g_return_val_if_fail (font != NULL, -1);
|
||||
g_return_val_if_fail (text != NULL, -1);
|
||||
|
||||
private = (GdkFontPrivateFB*) font;
|
||||
|
||||
switch (font->type)
|
||||
{
|
||||
case GDK_FONT_FONT:
|
||||
case GDK_FONT_FONTSET:
|
||||
n = private->size / 1000.0;
|
||||
n *= T1_GetStringWidth(private->t1_font_id, (char *)text, text_length, 0, T1_KERNING);
|
||||
width = ceil(n);
|
||||
break;
|
||||
default:
|
||||
width = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
gint
|
||||
gdk_text_width_wc (GdkFont *font,
|
||||
const GdkWChar *text,
|
||||
gint text_length)
|
||||
{
|
||||
char *realstr;
|
||||
int i;
|
||||
|
||||
realstr = alloca(text_length + 1);
|
||||
for(i = 0; i < text_length; i++)
|
||||
realstr[i] = text[i];
|
||||
realstr[i] = '\0';
|
||||
|
||||
return gdk_text_width(font, realstr, text_length);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_text_extents (GdkFont *font,
|
||||
const gchar *text,
|
||||
gint text_length,
|
||||
gint *lbearing,
|
||||
gint *rbearing,
|
||||
gint *width,
|
||||
gint *ascent,
|
||||
gint *descent)
|
||||
{
|
||||
GdkFontPrivateFB *private;
|
||||
METRICSINFO mi;
|
||||
|
||||
g_return_if_fail (font != NULL);
|
||||
g_return_if_fail (text != NULL);
|
||||
|
||||
private = (GdkFontPrivateFB*) font;
|
||||
|
||||
mi = T1_GetMetricsInfo(private->t1_font_id, (char *)text, text_length, 0, T1_KERNING);
|
||||
|
||||
if(ascent)
|
||||
*ascent = ((double)mi.bbox.ury) / 1000.0 * private->size;
|
||||
if(descent)
|
||||
*descent = ((double)mi.bbox.lly) / -1000.0 * private->size;
|
||||
if(width)
|
||||
*width = ((double)mi.width) / 1000.0 * private->size;
|
||||
if(lbearing)
|
||||
*lbearing = ((double)mi.bbox.llx) / 1000.0 * private->size;
|
||||
if(rbearing)
|
||||
*rbearing = ((double)mi.bbox.urx) / 1000.0 * private->size;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_text_extents_wc (GdkFont *font,
|
||||
const GdkWChar *text,
|
||||
gint text_length,
|
||||
gint *lbearing,
|
||||
gint *rbearing,
|
||||
gint *width,
|
||||
gint *ascent,
|
||||
gint *descent)
|
||||
{
|
||||
char *realstr;
|
||||
int i;
|
||||
|
||||
realstr = alloca(text_length + 1);
|
||||
for(i = 0; i < text_length; i++)
|
||||
realstr[i] = text[i];
|
||||
realstr[i] = '\0';
|
||||
|
||||
return gdk_text_extents(font, realstr, text_length, lbearing, rbearing, width, ascent, descent);
|
||||
}
|
308
gdk/linux-fb/gdkgc-fb.c
Normal file
308
gdk/linux-fb/gdkgc-fb.c
Normal file
@ -0,0 +1,308 @@
|
||||
#include "gdkprivate-fb.h"
|
||||
#include "gdkgc.h"
|
||||
#include "gdkfb.h"
|
||||
#include "gdkregion-generic.h"
|
||||
|
||||
typedef enum {
|
||||
GDK_GC_DIRTY_CLIP = 1 << 0,
|
||||
GDK_GC_DIRTY_TS = 1 << 1
|
||||
} GdkGCDirtyValues;
|
||||
|
||||
static void gdk_fb_gc_destroy (GdkGC *gc);
|
||||
static void gdk_fb_gc_get_values (GdkGC *gc,
|
||||
GdkGCValues *values);
|
||||
static void gdk_fb_gc_set_values (GdkGC *gc,
|
||||
GdkGCValues *values,
|
||||
GdkGCValuesMask values_mask);
|
||||
static void gdk_fb_gc_set_dashes (GdkGC *gc,
|
||||
gint dash_offset,
|
||||
gchar dash_list[],
|
||||
gint n);
|
||||
|
||||
static GdkGCClass gdk_fb_gc_class = {
|
||||
gdk_fb_gc_destroy,
|
||||
gdk_fb_gc_get_values,
|
||||
gdk_fb_gc_set_values,
|
||||
gdk_fb_gc_set_dashes
|
||||
};
|
||||
|
||||
GdkGC *
|
||||
_gdk_fb_gc_new (GdkDrawable *drawable,
|
||||
GdkGCValues *values,
|
||||
GdkGCValuesMask values_mask)
|
||||
{
|
||||
GdkGC *gc;
|
||||
GdkGCPrivate *private;
|
||||
GdkGCFBData *data;
|
||||
|
||||
gc = gdk_gc_alloc ();
|
||||
private = (GdkGCPrivate *)gc;
|
||||
|
||||
private->klass = &gdk_fb_gc_class;
|
||||
private->klass_data = data = g_new0 (GdkGCFBData, 1);
|
||||
data->values.foreground.pixel = 255;
|
||||
data->values.foreground.red = data->values.foreground.green = data->values.foreground.blue = 65535;
|
||||
|
||||
gdk_fb_gc_set_values(gc, values, values_mask);
|
||||
|
||||
return gc;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_fb_gc_destroy (GdkGC *gc)
|
||||
{
|
||||
if (GDK_GC_FBDATA (gc)->clip_region)
|
||||
gdk_region_destroy (GDK_GC_FBDATA (gc)->clip_region);
|
||||
|
||||
g_free (GDK_GC_FBDATA (gc));
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_fb_gc_get_values (GdkGC *gc,
|
||||
GdkGCValues *values)
|
||||
{
|
||||
*values = GDK_GC_FBDATA(gc)->values;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gdk_fb_gc_set_values (GdkGC *gc,
|
||||
GdkGCValues *values,
|
||||
GdkGCValuesMask values_mask)
|
||||
{
|
||||
GdkPixmap *oldpm;
|
||||
GdkFont *oldf;
|
||||
|
||||
if(values_mask & GDK_GC_FOREGROUND)
|
||||
{
|
||||
GDK_GC_FBDATA(gc)->values.foreground = values->foreground;
|
||||
GDK_GC_FBDATA(gc)->values_mask |= GDK_GC_FOREGROUND;
|
||||
}
|
||||
|
||||
if(values_mask & GDK_GC_BACKGROUND)
|
||||
{
|
||||
GDK_GC_FBDATA(gc)->values.background = values->background;
|
||||
GDK_GC_FBDATA(gc)->values_mask |= GDK_GC_BACKGROUND;
|
||||
}
|
||||
|
||||
if(values_mask & GDK_GC_FONT)
|
||||
{
|
||||
oldf = GDK_GC_FBDATA(gc)->values.font;
|
||||
GDK_GC_FBDATA(gc)->values.font = gdk_font_ref(values->font);
|
||||
GDK_GC_FBDATA(gc)->values_mask |= GDK_GC_FONT;
|
||||
if(oldf)
|
||||
gdk_font_unref(oldf);
|
||||
}
|
||||
|
||||
if(values_mask & GDK_GC_FUNCTION)
|
||||
{
|
||||
GDK_GC_FBDATA(gc)->values.function = values->function;
|
||||
GDK_GC_FBDATA(gc)->values_mask |= GDK_GC_FUNCTION;
|
||||
}
|
||||
|
||||
if(values_mask & GDK_GC_FILL)
|
||||
{
|
||||
GDK_GC_FBDATA(gc)->values.fill = values->fill;
|
||||
GDK_GC_FBDATA(gc)->values_mask |= GDK_GC_FILL;
|
||||
}
|
||||
|
||||
if(values_mask & GDK_GC_TILE)
|
||||
{
|
||||
oldpm = GDK_GC_FBDATA(gc)->values.tile;
|
||||
if(values->tile)
|
||||
g_assert(GDK_DRAWABLE_P(values->tile)->depth == 8);
|
||||
|
||||
GDK_GC_FBDATA(gc)->values.tile = values->tile?gdk_pixmap_ref(values->tile):NULL;
|
||||
GDK_GC_FBDATA(gc)->values_mask |= GDK_GC_TILE;
|
||||
if(oldpm)
|
||||
gdk_pixmap_unref(oldpm);
|
||||
}
|
||||
|
||||
if(values_mask & GDK_GC_STIPPLE)
|
||||
{
|
||||
oldpm = GDK_GC_FBDATA(gc)->values.stipple;
|
||||
if(values->stipple)
|
||||
g_assert(GDK_DRAWABLE_P(values->stipple)->depth == 1);
|
||||
GDK_GC_FBDATA(gc)->values.stipple = values->stipple?gdk_pixmap_ref(values->stipple):NULL;
|
||||
GDK_GC_FBDATA(gc)->values_mask |= GDK_GC_STIPPLE;
|
||||
if(oldpm)
|
||||
gdk_pixmap_unref(oldpm);
|
||||
}
|
||||
|
||||
if(values_mask & GDK_GC_CLIP_MASK)
|
||||
{
|
||||
oldpm = GDK_GC_FBDATA(gc)->values.clip_mask;
|
||||
|
||||
GDK_GC_FBDATA(gc)->values.clip_mask = values->clip_mask?gdk_pixmap_ref(values->clip_mask):NULL;
|
||||
GDK_GC_FBDATA(gc)->values_mask |= GDK_GC_CLIP_MASK;
|
||||
if(oldpm)
|
||||
gdk_pixmap_unref(oldpm);
|
||||
}
|
||||
|
||||
if(values_mask & GDK_GC_SUBWINDOW)
|
||||
{
|
||||
GDK_GC_FBDATA(gc)->values.subwindow_mode = values->subwindow_mode;
|
||||
GDK_GC_FBDATA(gc)->values_mask |= GDK_GC_SUBWINDOW;
|
||||
}
|
||||
|
||||
if(values_mask & GDK_GC_TS_X_ORIGIN)
|
||||
{
|
||||
GDK_GC_FBDATA(gc)->values.ts_x_origin = values->ts_x_origin;
|
||||
GDK_GC_FBDATA(gc)->values_mask |= GDK_GC_TS_X_ORIGIN;
|
||||
}
|
||||
|
||||
if(values_mask & GDK_GC_TS_Y_ORIGIN)
|
||||
{
|
||||
GDK_GC_FBDATA(gc)->values.ts_y_origin = values->ts_y_origin;
|
||||
GDK_GC_FBDATA(gc)->values_mask |= GDK_GC_TS_Y_ORIGIN;
|
||||
}
|
||||
|
||||
if(values_mask & GDK_GC_CLIP_X_ORIGIN)
|
||||
{
|
||||
GDK_GC_FBDATA(gc)->values.clip_x_origin = GDK_GC_P(gc)->clip_x_origin = values->clip_x_origin;
|
||||
GDK_GC_FBDATA(gc)->values_mask |= GDK_GC_CLIP_X_ORIGIN;
|
||||
}
|
||||
|
||||
if(values_mask & GDK_GC_CLIP_Y_ORIGIN)
|
||||
{
|
||||
GDK_GC_FBDATA(gc)->values.clip_y_origin = GDK_GC_P(gc)->clip_y_origin = values->clip_y_origin;
|
||||
GDK_GC_FBDATA(gc)->values_mask |= GDK_GC_CLIP_Y_ORIGIN;
|
||||
}
|
||||
|
||||
if(values_mask & GDK_GC_EXPOSURES)
|
||||
{
|
||||
GDK_GC_FBDATA(gc)->values.graphics_exposures = values->graphics_exposures;
|
||||
GDK_GC_FBDATA(gc)->values_mask |= GDK_GC_EXPOSURES;
|
||||
}
|
||||
|
||||
if(values_mask & GDK_GC_LINE_WIDTH)
|
||||
{
|
||||
GDK_GC_FBDATA(gc)->values.line_width = values->line_width;
|
||||
GDK_GC_FBDATA(gc)->values_mask |= GDK_GC_LINE_WIDTH;
|
||||
}
|
||||
|
||||
if(values_mask & GDK_GC_LINE_STYLE)
|
||||
{
|
||||
GDK_GC_FBDATA(gc)->values.line_style = values->line_style;
|
||||
GDK_GC_FBDATA(gc)->values_mask |= GDK_GC_LINE_STYLE;
|
||||
}
|
||||
|
||||
if(values_mask & GDK_GC_CAP_STYLE)
|
||||
{
|
||||
GDK_GC_FBDATA(gc)->values.cap_style = values->cap_style;
|
||||
GDK_GC_FBDATA(gc)->values_mask |= GDK_GC_CAP_STYLE;
|
||||
}
|
||||
|
||||
if(values_mask & GDK_GC_JOIN_STYLE)
|
||||
{
|
||||
GDK_GC_FBDATA(gc)->values.join_style = values->join_style;
|
||||
GDK_GC_FBDATA(gc)->values_mask |= GDK_GC_JOIN_STYLE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_fb_gc_set_dashes (GdkGC *gc,
|
||||
gint dash_offset,
|
||||
gchar dash_list[],
|
||||
gint n)
|
||||
{
|
||||
GDK_GC_FBDATA(gc)->dash_offset = dash_offset;
|
||||
GDK_GC_FBDATA(gc)->dash_list_len = n;
|
||||
if(n)
|
||||
{
|
||||
GDK_GC_FBDATA(gc)->dash_list = g_realloc(GDK_GC_FBDATA(gc)->dash_list, n);
|
||||
memcpy(GDK_GC_FBDATA(gc)->dash_list, dash_list, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free(GDK_GC_FBDATA(gc)->dash_list);
|
||||
GDK_GC_FBDATA(gc)->dash_list = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gdk_gc_set_clip_rectangle (GdkGC *gc,
|
||||
GdkRectangle *rectangle)
|
||||
{
|
||||
GdkGCPrivate *private = (GdkGCPrivate *)gc;
|
||||
GdkGCFBData *data;
|
||||
|
||||
g_return_if_fail (gc != NULL);
|
||||
|
||||
data = GDK_GC_FBDATA (gc);
|
||||
|
||||
if (data->clip_region)
|
||||
{
|
||||
gdk_region_destroy (data->clip_region);
|
||||
data->clip_region = NULL;
|
||||
}
|
||||
|
||||
if (rectangle)
|
||||
data->clip_region = gdk_region_rectangle (rectangle);
|
||||
|
||||
private->clip_x_origin = 0;
|
||||
private->clip_y_origin = 0;
|
||||
data->values.clip_x_origin = 0;
|
||||
data->values.clip_y_origin = 0;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_gc_set_clip_region (GdkGC *gc,
|
||||
GdkRegion *region)
|
||||
{
|
||||
GdkGCPrivate *private = (GdkGCPrivate *)gc;
|
||||
GdkGCFBData *data;
|
||||
|
||||
g_return_if_fail (gc != NULL);
|
||||
|
||||
data = GDK_GC_FBDATA (gc);
|
||||
|
||||
if(region == data->clip_region)
|
||||
return;
|
||||
|
||||
if (data->clip_region)
|
||||
{
|
||||
gdk_region_destroy (data->clip_region);
|
||||
data->clip_region = NULL;
|
||||
}
|
||||
|
||||
if (region)
|
||||
data->clip_region = gdk_region_copy (region);
|
||||
|
||||
private->clip_x_origin = 0;
|
||||
private->clip_y_origin = 0;
|
||||
data->values.clip_x_origin = 0;
|
||||
data->values.clip_y_origin = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gdk_gc_copy (GdkGC *dst_gc, GdkGC *src_gc)
|
||||
{
|
||||
g_return_if_fail (dst_gc != NULL);
|
||||
g_return_if_fail (src_gc != NULL);
|
||||
|
||||
if(GDK_GC_FBDATA(dst_gc)->clip_region)
|
||||
gdk_region_destroy(GDK_GC_FBDATA(dst_gc)->clip_region);
|
||||
|
||||
if(GDK_GC_FBDATA(dst_gc)->values_mask & GDK_GC_FONT)
|
||||
gdk_font_unref(GDK_GC_FBDATA(dst_gc)->values.font);
|
||||
if(GDK_GC_FBDATA(dst_gc)->values_mask & GDK_GC_TILE)
|
||||
gdk_pixmap_unref(GDK_GC_FBDATA(dst_gc)->values.tile);
|
||||
if(GDK_GC_FBDATA(dst_gc)->values_mask & GDK_GC_STIPPLE)
|
||||
gdk_pixmap_unref(GDK_GC_FBDATA(dst_gc)->values.stipple);
|
||||
if(GDK_GC_FBDATA(dst_gc)->values_mask & GDK_GC_CLIP_MASK)
|
||||
gdk_pixmap_unref(GDK_GC_FBDATA(dst_gc)->values.clip_mask);
|
||||
|
||||
*dst_gc = *src_gc;
|
||||
if(GDK_GC_FBDATA(dst_gc)->values_mask & GDK_GC_FONT)
|
||||
gdk_font_ref(GDK_GC_FBDATA(dst_gc)->values.font);
|
||||
if(GDK_GC_FBDATA(dst_gc)->values_mask & GDK_GC_TILE)
|
||||
gdk_pixmap_ref(GDK_GC_FBDATA(dst_gc)->values.tile);
|
||||
if(GDK_GC_FBDATA(dst_gc)->values_mask & GDK_GC_STIPPLE)
|
||||
gdk_pixmap_ref(GDK_GC_FBDATA(dst_gc)->values.stipple);
|
||||
if(GDK_GC_FBDATA(dst_gc)->values_mask & GDK_GC_CLIP_MASK)
|
||||
gdk_pixmap_ref(GDK_GC_FBDATA(dst_gc)->values.clip_mask);
|
||||
if(GDK_GC_FBDATA(dst_gc)->clip_region)
|
||||
GDK_GC_FBDATA(dst_gc)->clip_region = gdk_region_copy(GDK_GC_FBDATA(dst_gc)->clip_region);
|
||||
}
|
0
gdk/linux-fb/gdkgeometry-fb.c
Normal file
0
gdk/linux-fb/gdkgeometry-fb.c
Normal file
41
gdk/linux-fb/gdkglobals-fb.c
Normal file
41
gdk/linux-fb/gdkglobals-fb.c
Normal file
@ -0,0 +1,41 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "gdktypes.h"
|
||||
#include "gdkprivate-fb.h"
|
||||
#include "config.h"
|
||||
|
||||
const gchar *gdk_progclass = "none";
|
||||
gboolean gdk_null_window_warnings = TRUE;
|
||||
|
||||
GdkWindow *_gdk_fb_pointer_grab_window, *_gdk_fb_keyboard_grab_window, *_gdk_fb_pointer_grab_confine = NULL;
|
||||
GdkEventMask _gdk_fb_pointer_grab_events, _gdk_fb_keyboard_grab_events;
|
||||
|
||||
GdkFBWindow *gdk_root_window = NULL;
|
||||
GdkFBDisplay *gdk_display = NULL;
|
||||
GdkCursor *_gdk_fb_pointer_grab_cursor;
|
242
gdk/linux-fb/gdkim-fb.c
Normal file
242
gdk/linux-fb/gdkim-fb.c
Normal file
@ -0,0 +1,242 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include "gdki18n.h"
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkprivate-fb.h"
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
# if STDC_HEADERS
|
||||
# include <string.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
/* If this variable is FALSE, it indicates that we should
|
||||
* avoid trying to use multibyte conversion functions and
|
||||
* assume everything is 1-byte per character
|
||||
*/
|
||||
static gboolean gdk_use_mb;
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
* gdk_set_locale
|
||||
*
|
||||
* Arguments:
|
||||
*
|
||||
* Results:
|
||||
*
|
||||
* Side effects:
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
gchar*
|
||||
gdk_set_locale (void)
|
||||
{
|
||||
wchar_t result;
|
||||
gchar *current_locale;
|
||||
|
||||
gdk_use_mb = FALSE;
|
||||
|
||||
if (!setlocale (LC_ALL,""))
|
||||
g_warning ("locale not supported by C library");
|
||||
|
||||
current_locale = setlocale (LC_ALL, NULL);
|
||||
|
||||
if ((strcmp (current_locale, "C")) && (strcmp (current_locale, "POSIX")))
|
||||
{
|
||||
gdk_use_mb = TRUE;
|
||||
|
||||
#ifndef X_LOCALE
|
||||
/* Detect GNU libc, where mb == UTF8. Not useful unless it's
|
||||
* really a UTF8 locale. The below still probably will
|
||||
* screw up on Greek, Cyrillic, etc, encoded as UTF8.
|
||||
*/
|
||||
|
||||
if ((MB_CUR_MAX == 2) &&
|
||||
(mbstowcs (&result, "\xdd\xa5", 1) > 0) &&
|
||||
result == 0x765)
|
||||
{
|
||||
if ((strlen (current_locale) < 4) ||
|
||||
g_strcasecmp (current_locale + strlen(current_locale) - 4, "utf8"))
|
||||
gdk_use_mb = FALSE;
|
||||
}
|
||||
#endif /* X_LOCALE */
|
||||
}
|
||||
|
||||
GDK_NOTE (MISC,
|
||||
g_message ("%s multi-byte string functions.",
|
||||
gdk_use_mb ? "Using" : "Not using"));
|
||||
|
||||
return current_locale;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_im_begin (GdkIC *ic, GdkWindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
gdk_im_end (void)
|
||||
{
|
||||
}
|
||||
|
||||
GdkIMStyle
|
||||
gdk_im_decide_style (GdkIMStyle supported_style)
|
||||
{
|
||||
return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
|
||||
}
|
||||
|
||||
GdkIMStyle
|
||||
gdk_im_set_best_style (GdkIMStyle style)
|
||||
{
|
||||
return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
|
||||
}
|
||||
|
||||
gint
|
||||
gdk_im_ready (void)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gint
|
||||
gdk_im_open(void)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_im_close(void)
|
||||
{
|
||||
}
|
||||
|
||||
GdkIC *
|
||||
gdk_ic_new (GdkICAttr *attr, GdkICAttributesType mask)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_ic_destroy (GdkIC *ic)
|
||||
{
|
||||
}
|
||||
|
||||
GdkIMStyle
|
||||
gdk_ic_get_style (GdkIC *ic)
|
||||
{
|
||||
return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_ic_set_values (GdkIC *ic, ...)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
gdk_ic_get_values (GdkIC *ic, ...)
|
||||
{
|
||||
}
|
||||
|
||||
GdkICAttributesType
|
||||
gdk_ic_set_attr (GdkIC *ic, GdkICAttr *attr, GdkICAttributesType mask)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
GdkICAttributesType
|
||||
gdk_ic_get_attr (GdkIC *ic, GdkICAttr *attr, GdkICAttributesType mask)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
GdkEventMask
|
||||
gdk_ic_get_events (GdkIC *ic)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* gdk_wcstombs
|
||||
*
|
||||
* Returns a multi-byte string converted from the specified array
|
||||
* of wide characters. The string is newly allocated. The array of
|
||||
* wide characters must be null-terminated. If the conversion is
|
||||
* failed, it returns NULL.
|
||||
*/
|
||||
gchar *
|
||||
gdk_wcstombs (const GdkWChar *src)
|
||||
{
|
||||
gchar *mbstr;
|
||||
|
||||
gint length = 0;
|
||||
gint i;
|
||||
|
||||
while (src[length] != 0)
|
||||
length++;
|
||||
|
||||
mbstr = g_new (gchar, length + 1);
|
||||
|
||||
for (i=0; i<length+1; i++)
|
||||
mbstr[i] = src[i];
|
||||
|
||||
return mbstr;
|
||||
}
|
||||
|
||||
/*
|
||||
* gdk_mbstowcs
|
||||
*
|
||||
* Converts the specified string into wide characters, and, returns the
|
||||
* number of wide characters written. The string 'src' must be
|
||||
* null-terminated. If the conversion is failed, it returns -1.
|
||||
*/
|
||||
gint
|
||||
gdk_mbstowcs (GdkWChar *dest, const gchar *src, gint dest_max)
|
||||
{
|
||||
gint i;
|
||||
|
||||
for (i=0; i<dest_max && src[i]; i++)
|
||||
dest[i] = src[i];
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_ic_cleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
GdkICAttr* gdk_ic_attr_new (void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_ic_attr_destroy (GdkICAttr *attr)
|
||||
{
|
||||
}
|
268
gdk/linux-fb/gdkimage-fb.c
Normal file
268
gdk/linux-fb/gdkimage-fb.c
Normal file
@ -0,0 +1,268 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "gdk.h"
|
||||
#include "gdkimage.h"
|
||||
#include "gdkprivate.h"
|
||||
#include "gdkprivate-fb.h"
|
||||
|
||||
struct _GdkImagePrivateFB
|
||||
{
|
||||
GdkImagePrivate base;
|
||||
};
|
||||
|
||||
static void gdk_fb_image_destroy (GdkImage *image);
|
||||
static void gdk_image_put_normal (GdkImage *image,
|
||||
GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
gint xsrc,
|
||||
gint ysrc,
|
||||
gint xdest,
|
||||
gint ydest,
|
||||
gint width,
|
||||
gint height);
|
||||
|
||||
static GdkImageClass image_class_normal = {
|
||||
gdk_fb_image_destroy,
|
||||
gdk_image_put_normal
|
||||
};
|
||||
|
||||
GdkImage *
|
||||
gdk_image_new_bitmap(GdkVisual *visual, gpointer data, gint w, gint h)
|
||||
{
|
||||
GdkImage *image;
|
||||
GdkImagePrivateFB *private;
|
||||
|
||||
private = g_new(GdkImagePrivateFB, 1);
|
||||
image = (GdkImage *) private;
|
||||
private->base.ref_count = 1;
|
||||
private->base.klass = &image_class_normal;
|
||||
image->type = GDK_IMAGE_NORMAL;
|
||||
image->visual = visual;
|
||||
image->width = w;
|
||||
image->height = h;
|
||||
image->depth = 1;
|
||||
|
||||
image->byte_order = 1 /* MSBFirst */;
|
||||
image->mem = g_malloc(w * h / 8);
|
||||
image->bpp = 1;
|
||||
image->bpl = (w+7)/8;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_image_init (void)
|
||||
{
|
||||
}
|
||||
|
||||
GdkImage*
|
||||
gdk_image_new (GdkImageType type,
|
||||
GdkVisual *visual,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
GdkImage *image;
|
||||
GdkImagePrivateFB *private;
|
||||
|
||||
private = g_new (GdkImagePrivateFB, 1);
|
||||
image = (GdkImage*) private;
|
||||
|
||||
private->base.ref_count = 1;
|
||||
|
||||
image->type = 0;
|
||||
image->visual = visual;
|
||||
image->width = width;
|
||||
image->height = height;
|
||||
image->depth = visual->depth;
|
||||
|
||||
private->base.klass = &image_class_normal;
|
||||
|
||||
if (image)
|
||||
{
|
||||
image->byte_order = 0;
|
||||
image->mem = g_malloc(width * height * (image->depth >> 3));
|
||||
image->bpp = image->depth;
|
||||
image->bpl = (width * image->depth + 7)/8;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
GdkImage*
|
||||
gdk_image_get (GdkWindow *window,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
GdkImage *image;
|
||||
GdkImagePrivateFB *private;
|
||||
gint bits_per_pixel = GDK_DRAWABLE_P(gdk_parent_root)->depth;
|
||||
GdkDrawableFBData fbd;
|
||||
GdkDrawablePrivate tmp_foo;
|
||||
|
||||
g_return_val_if_fail (window != NULL, NULL);
|
||||
|
||||
if (GDK_DRAWABLE_DESTROYED (window))
|
||||
return NULL;
|
||||
|
||||
private = g_new (GdkImagePrivateFB, 1);
|
||||
image = (GdkImage*) private;
|
||||
|
||||
private->base.ref_count = 1;
|
||||
private->base.klass = &image_class_normal;
|
||||
|
||||
image->type = GDK_IMAGE_NORMAL;
|
||||
image->visual = gdk_window_get_visual (window);
|
||||
image->width = width;
|
||||
image->height = height;
|
||||
image->depth = bits_per_pixel;
|
||||
|
||||
if (bits_per_pixel <= 8)
|
||||
image->bpp = 1;
|
||||
else if (bits_per_pixel <= 16)
|
||||
image->bpp = 2;
|
||||
else if (bits_per_pixel <= 24)
|
||||
image->bpp = 3;
|
||||
else
|
||||
image->bpp = 4;
|
||||
image->byte_order = 1;
|
||||
image->bpl = (image->width * image->bpp + 7)/8;
|
||||
image->mem = g_malloc(image->bpl * image->height);
|
||||
|
||||
/* Fake its existence as a pixmap */
|
||||
memset(&tmp_foo, 0, sizeof(tmp_foo));
|
||||
memset(&fbd, 0, sizeof(fbd));
|
||||
tmp_foo.klass = &_gdk_fb_drawable_class;
|
||||
tmp_foo.klass_data = &fbd;
|
||||
fbd.mem = image->mem;
|
||||
fbd.rowstride = image->bpl;
|
||||
tmp_foo.width = fbd.lim_x = image->width;
|
||||
tmp_foo.height = fbd.lim_y = image->height;
|
||||
tmp_foo.depth = image->depth;
|
||||
|
||||
gdk_fb_draw_drawable((GdkPixmap *)&tmp_foo, NULL, window, x, y, 0, 0, width, height);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
guint32
|
||||
gdk_image_get_pixel (GdkImage *image,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
GdkImagePrivateFB *private;
|
||||
|
||||
g_return_val_if_fail (image != NULL, 0);
|
||||
|
||||
private = (GdkImagePrivateFB *) image;
|
||||
|
||||
g_assert(image->depth == 8);
|
||||
|
||||
return ((guchar *)image->mem)[x + y * image->bpl];
|
||||
}
|
||||
|
||||
void
|
||||
gdk_image_put_pixel (GdkImage *image,
|
||||
gint x,
|
||||
gint y,
|
||||
guint32 pixel)
|
||||
{
|
||||
GdkImagePrivateFB *private;
|
||||
|
||||
g_return_if_fail (image != NULL);
|
||||
|
||||
private = (GdkImagePrivateFB *) image;
|
||||
g_assert(image->depth == 8);
|
||||
|
||||
((guchar *)image->mem)[x + y * image->bpl] = pixel;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_fb_image_destroy (GdkImage *image)
|
||||
{
|
||||
GdkImagePrivateFB *private;
|
||||
|
||||
g_return_if_fail (image != NULL);
|
||||
|
||||
private = (GdkImagePrivateFB*) image;
|
||||
|
||||
g_free(image->mem); image->mem = NULL;
|
||||
|
||||
g_free (image);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_image_put_normal (GdkImage *image,
|
||||
GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
gint xsrc,
|
||||
gint ysrc,
|
||||
gint xdest,
|
||||
gint ydest,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
GdkImagePrivateFB *image_private;
|
||||
GdkDrawableFBData fbd;
|
||||
GdkDrawablePrivate tmp_foo;
|
||||
|
||||
g_return_if_fail (drawable != NULL);
|
||||
g_return_if_fail (image != NULL);
|
||||
g_return_if_fail (gc != NULL);
|
||||
|
||||
if (GDK_DRAWABLE_DESTROYED (drawable))
|
||||
return;
|
||||
|
||||
image_private = (GdkImagePrivateFB*) image;
|
||||
|
||||
g_return_if_fail (image->type == GDK_IMAGE_NORMAL);
|
||||
|
||||
/* Fake its existence as a pixmap */
|
||||
memset(&tmp_foo, 0, sizeof(tmp_foo));
|
||||
memset(&fbd, 0, sizeof(fbd));
|
||||
tmp_foo.klass = &_gdk_fb_drawable_class;
|
||||
tmp_foo.klass_data = &fbd;
|
||||
fbd.mem = image->mem;
|
||||
fbd.rowstride = image->bpl;
|
||||
tmp_foo.width = fbd.lim_x = image->width;
|
||||
tmp_foo.height = fbd.lim_y = image->height;
|
||||
tmp_foo.depth = image->depth;
|
||||
|
||||
gdk_fb_draw_drawable(drawable, gc, (GdkPixmap *)&tmp_foo, xsrc, ysrc, xdest, ydest, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_image_exit(void)
|
||||
{
|
||||
}
|
79
gdk/linux-fb/gdkinput-none.c
Normal file
79
gdk/linux-fb/gdkinput-none.c
Normal file
@ -0,0 +1,79 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "gdkinputprivate.h"
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
static void gdk_input_none_get_pointer (GdkWindow *window,
|
||||
guint32 deviceid,
|
||||
gdouble *x,
|
||||
gdouble *y,
|
||||
gdouble *pressure,
|
||||
gdouble *xtilt,
|
||||
gdouble *ytilt,
|
||||
GdkModifierType *mask);
|
||||
|
||||
void
|
||||
gdk_input_init (void)
|
||||
{
|
||||
gdk_input_vtable.set_mode = NULL;
|
||||
gdk_input_vtable.set_axes = NULL;
|
||||
gdk_input_vtable.set_key = NULL;
|
||||
gdk_input_vtable.motion_events = NULL;
|
||||
gdk_input_vtable.get_pointer = gdk_input_none_get_pointer;
|
||||
gdk_input_vtable.grab_pointer = NULL;
|
||||
gdk_input_vtable.ungrab_pointer = NULL;
|
||||
gdk_input_vtable.configure_event = NULL;
|
||||
gdk_input_vtable.enter_event = NULL;
|
||||
gdk_input_vtable.other_event = NULL;
|
||||
gdk_input_vtable.window_none_event = NULL;
|
||||
gdk_input_vtable.enable_window = NULL;
|
||||
gdk_input_vtable.disable_window = NULL;
|
||||
|
||||
gdk_input_devices = g_list_append (NULL, (GdkDeviceInfo *) &gdk_input_core_info);
|
||||
|
||||
gdk_input_ignore_core = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_input_none_get_pointer (GdkWindow *window,
|
||||
guint32 deviceid,
|
||||
gdouble *x,
|
||||
gdouble *y,
|
||||
gdouble *pressure,
|
||||
gdouble *xtilt,
|
||||
gdouble *ytilt,
|
||||
GdkModifierType *mask)
|
||||
{
|
||||
gint x_int, y_int;
|
||||
|
||||
gdk_window_get_pointer (window, &x_int, &y_int, mask);
|
||||
|
||||
if (x) *x = x_int;
|
||||
if (y) *y = y_int;
|
||||
if (pressure) *pressure = 0.5;
|
||||
if (xtilt) *xtilt = 0;
|
||||
if (ytilt) *ytilt = 0;
|
||||
}
|
1096
gdk/linux-fb/gdkinput-ps2.c
Normal file
1096
gdk/linux-fb/gdkinput-ps2.c
Normal file
File diff suppressed because it is too large
Load Diff
290
gdk/linux-fb/gdkinput.c
Normal file
290
gdk/linux-fb/gdkinput.c
Normal file
@ -0,0 +1,290 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkfb.h"
|
||||
#include "gdkinput.h"
|
||||
#include "gdkprivate.h"
|
||||
#include "gdkinputprivate.h"
|
||||
|
||||
static const GdkAxisUse gdk_input_core_axes[] = { GDK_AXIS_X, GDK_AXIS_Y };
|
||||
|
||||
const GdkDeviceInfo gdk_input_core_info =
|
||||
{
|
||||
GDK_CORE_POINTER,
|
||||
"Core Pointer",
|
||||
GDK_SOURCE_MOUSE,
|
||||
GDK_MODE_SCREEN,
|
||||
TRUE,
|
||||
2,
|
||||
gdk_input_core_axes
|
||||
};
|
||||
|
||||
/* Global variables */
|
||||
|
||||
GdkInputVTable gdk_input_vtable;
|
||||
/* information about network port and host for gxid daemon */
|
||||
gchar *gdk_input_gxid_host;
|
||||
gint gdk_input_gxid_port;
|
||||
gint gdk_input_ignore_core;
|
||||
|
||||
GList *gdk_input_devices;
|
||||
GList *gdk_input_windows;
|
||||
|
||||
GList *
|
||||
gdk_input_list_devices (void)
|
||||
{
|
||||
return gdk_input_devices;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_input_set_source (guint32 deviceid, GdkInputSource source)
|
||||
{
|
||||
GdkDevicePrivate *gdkdev = gdk_input_find_device(deviceid);
|
||||
g_return_if_fail (gdkdev != NULL);
|
||||
|
||||
gdkdev->info.source = source;
|
||||
}
|
||||
|
||||
gint
|
||||
gdk_input_set_mode (guint32 deviceid, GdkInputMode mode)
|
||||
{
|
||||
if (deviceid == GDK_CORE_POINTER)
|
||||
return FALSE;
|
||||
|
||||
if (gdk_input_vtable.set_mode)
|
||||
return gdk_input_vtable.set_mode(deviceid,mode);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_input_set_axes (guint32 deviceid, GdkAxisUse *axes)
|
||||
{
|
||||
if (deviceid != GDK_CORE_POINTER && gdk_input_vtable.set_axes)
|
||||
gdk_input_vtable.set_axes (deviceid, axes);
|
||||
}
|
||||
|
||||
void gdk_input_set_key (guint32 deviceid,
|
||||
guint index,
|
||||
guint keyval,
|
||||
GdkModifierType modifiers)
|
||||
{
|
||||
if (deviceid != GDK_CORE_POINTER && gdk_input_vtable.set_key)
|
||||
gdk_input_vtable.set_key (deviceid, index, keyval, modifiers);
|
||||
}
|
||||
|
||||
GdkTimeCoord *
|
||||
gdk_input_motion_events (GdkWindow *window,
|
||||
guint32 deviceid,
|
||||
guint32 start,
|
||||
guint32 stop,
|
||||
gint *nevents_return)
|
||||
{
|
||||
g_return_val_if_fail (window != NULL, NULL);
|
||||
g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
|
||||
|
||||
*nevents_return = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gint
|
||||
gdk_input_enable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
|
||||
{
|
||||
if (gdk_input_vtable.enable_window)
|
||||
return gdk_input_vtable.enable_window (window, gdkdev);
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gint
|
||||
gdk_input_disable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
|
||||
{
|
||||
if (gdk_input_vtable.disable_window)
|
||||
return gdk_input_vtable.disable_window(window,gdkdev);
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
GdkInputWindow *
|
||||
gdk_input_window_find(GdkWindow *window)
|
||||
{
|
||||
GList *tmp_list;
|
||||
|
||||
for (tmp_list=gdk_input_windows; tmp_list; tmp_list=tmp_list->next)
|
||||
if (((GdkInputWindow *)(tmp_list->data))->window == window)
|
||||
return (GdkInputWindow *)(tmp_list->data);
|
||||
|
||||
return NULL; /* Not found */
|
||||
}
|
||||
|
||||
/* FIXME: this routine currently needs to be called between creation
|
||||
and the corresponding configure event (because it doesn't get the
|
||||
root_relative_geometry). This should work with
|
||||
gtk_window_set_extension_events, but will likely fail in other
|
||||
cases */
|
||||
|
||||
void
|
||||
gdk_input_set_extension_events (GdkWindow *window, gint mask,
|
||||
GdkExtensionMode mode)
|
||||
{
|
||||
GdkWindowPrivate *window_private;
|
||||
GList *tmp_list;
|
||||
GdkInputWindow *iw;
|
||||
|
||||
g_return_if_fail (window != NULL);
|
||||
g_return_if_fail (GDK_IS_WINDOW (window));
|
||||
|
||||
window_private = (GdkWindowPrivate*) window;
|
||||
if (GDK_DRAWABLE_DESTROYED (window))
|
||||
return;
|
||||
|
||||
if (mode == GDK_EXTENSION_EVENTS_NONE)
|
||||
mask = 0;
|
||||
|
||||
if (mask != 0)
|
||||
{
|
||||
iw = g_new(GdkInputWindow,1);
|
||||
|
||||
iw->window = window;
|
||||
iw->mode = mode;
|
||||
|
||||
iw->obscuring = NULL;
|
||||
iw->num_obscuring = 0;
|
||||
iw->grabbed = FALSE;
|
||||
|
||||
gdk_input_windows = g_list_append(gdk_input_windows,iw);
|
||||
window_private->extension_events = mask;
|
||||
|
||||
/* Add enter window events to the event mask */
|
||||
/* FIXME, this is not needed for XINPUT_NONE */
|
||||
gdk_window_set_events (window,
|
||||
gdk_window_get_events (window) |
|
||||
GDK_ENTER_NOTIFY_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
iw = gdk_input_window_find (window);
|
||||
if (iw)
|
||||
{
|
||||
gdk_input_windows = g_list_remove(gdk_input_windows,iw);
|
||||
g_free(iw);
|
||||
}
|
||||
|
||||
window_private->extension_events = 0;
|
||||
}
|
||||
|
||||
for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
|
||||
{
|
||||
GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
|
||||
|
||||
if (gdkdev->info.deviceid != GDK_CORE_POINTER)
|
||||
{
|
||||
if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED
|
||||
&& (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL))
|
||||
gdk_input_enable_window(window,gdkdev);
|
||||
else
|
||||
gdk_input_disable_window(window,gdkdev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gdk_input_window_destroy (GdkWindow *window)
|
||||
{
|
||||
GdkInputWindow *input_window;
|
||||
|
||||
input_window = gdk_input_window_find (window);
|
||||
g_return_if_fail (input_window != NULL);
|
||||
|
||||
gdk_input_windows = g_list_remove (gdk_input_windows,input_window);
|
||||
g_free(input_window);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_input_exit (void)
|
||||
{
|
||||
GList *tmp_list;
|
||||
GdkDevicePrivate *gdkdev;
|
||||
|
||||
for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
|
||||
{
|
||||
gdkdev = (GdkDevicePrivate *)(tmp_list->data);
|
||||
if (gdkdev->info.deviceid != GDK_CORE_POINTER)
|
||||
{
|
||||
gdk_input_set_mode(gdkdev->info.deviceid,GDK_MODE_DISABLED);
|
||||
|
||||
g_free(gdkdev->info.name);
|
||||
#ifndef XINPUT_NONE
|
||||
g_free(gdkdev->axes);
|
||||
#endif
|
||||
g_free(gdkdev->info.axes);
|
||||
g_free(gdkdev->info.keys);
|
||||
g_free(gdkdev);
|
||||
}
|
||||
}
|
||||
|
||||
g_list_free(gdk_input_devices);
|
||||
|
||||
for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
|
||||
{
|
||||
g_free(tmp_list->data);
|
||||
}
|
||||
g_list_free(gdk_input_windows);
|
||||
}
|
||||
|
||||
GdkDevicePrivate *
|
||||
gdk_input_find_device(guint32 id)
|
||||
{
|
||||
GList *tmp_list = gdk_input_devices;
|
||||
GdkDevicePrivate *gdkdev;
|
||||
while (tmp_list)
|
||||
{
|
||||
gdkdev = (GdkDevicePrivate *)(tmp_list->data);
|
||||
if (gdkdev->info.deviceid == id)
|
||||
return gdkdev;
|
||||
tmp_list = tmp_list->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_input_window_get_pointer (GdkWindow *window,
|
||||
guint32 deviceid,
|
||||
gdouble *x,
|
||||
gdouble *y,
|
||||
gdouble *pressure,
|
||||
gdouble *xtilt,
|
||||
gdouble *ytilt,
|
||||
GdkModifierType *mask)
|
||||
{
|
||||
if (gdk_input_vtable.get_pointer)
|
||||
gdk_input_vtable.get_pointer (window, deviceid, x, y, pressure,
|
||||
xtilt, ytilt, mask);
|
||||
}
|
222
gdk/linux-fb/gdkinputprivate.h
Normal file
222
gdk/linux-fb/gdkinputprivate.h
Normal file
@ -0,0 +1,222 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_INPUTPRIVATE_H__
|
||||
#define __GDK_INPUTPRIVATE_H__
|
||||
|
||||
#include "config.h"
|
||||
#include "gdkinput.h"
|
||||
#include "gdkevents.h"
|
||||
#include "gdkfb.h"
|
||||
|
||||
typedef struct _GdkAxisInfo GdkAxisInfo;
|
||||
typedef struct _GdkInputVTable GdkInputVTable;
|
||||
typedef struct _GdkDevicePrivate GdkDevicePrivate;
|
||||
typedef struct _GdkInputWindow GdkInputWindow;
|
||||
|
||||
struct _GdkInputVTable {
|
||||
gint (*set_mode) (guint32 deviceid, GdkInputMode mode);
|
||||
void (*set_axes) (guint32 deviceid, GdkAxisUse *axes);
|
||||
void (*set_key) (guint32 deviceid,
|
||||
guint index,
|
||||
guint keyval,
|
||||
GdkModifierType modifiers);
|
||||
|
||||
GdkTimeCoord* (*motion_events) (GdkWindow *window,
|
||||
guint32 deviceid,
|
||||
guint32 start,
|
||||
guint32 stop,
|
||||
gint *nevents_return);
|
||||
void (*get_pointer) (GdkWindow *window,
|
||||
guint32 deviceid,
|
||||
gdouble *x,
|
||||
gdouble *y,
|
||||
gdouble *pressure,
|
||||
gdouble *xtilt,
|
||||
gdouble *ytilt,
|
||||
GdkModifierType *mask);
|
||||
gint (*grab_pointer) (GdkWindow * window,
|
||||
gint owner_events,
|
||||
GdkEventMask event_mask,
|
||||
GdkWindow * confine_to,
|
||||
guint32 time);
|
||||
void (*ungrab_pointer) (guint32 time);
|
||||
|
||||
void (*configure_event) (GdkEventConfigure *event, GdkWindow *window);
|
||||
void (*enter_event) (GdkEventCrossing *event, GdkWindow *window);
|
||||
gint (*other_event) (GdkEvent *event, GdkWindow *window);
|
||||
/* Handle an unidentified event. Returns TRUE if handled, FALSE
|
||||
otherwise */
|
||||
gint (*window_none_event) (GdkEvent *event);
|
||||
gint (*enable_window) (GdkWindow *window, GdkDevicePrivate *gdkdev);
|
||||
gint (*disable_window) (GdkWindow *window, GdkDevicePrivate *gdkdev);
|
||||
};
|
||||
|
||||
/* information about a device axis */
|
||||
struct _GdkAxisInfo
|
||||
{
|
||||
/* reported x resolution */
|
||||
gint xresolution;
|
||||
|
||||
/* reported x minimum/maximum values */
|
||||
gint xmin_value, xmax_value;
|
||||
|
||||
/* calibrated resolution (for aspect ration) - only relative values
|
||||
between axes used */
|
||||
gint resolution;
|
||||
|
||||
/* calibrated minimum/maximum values */
|
||||
gint min_value, max_value;
|
||||
};
|
||||
|
||||
#define GDK_INPUT_NUM_EVENTC 6
|
||||
|
||||
struct _GdkDevicePrivate {
|
||||
GdkDeviceInfo info;
|
||||
|
||||
#ifndef XINPUT_NONE
|
||||
/* information about the axes */
|
||||
GdkAxisInfo *axes;
|
||||
|
||||
/* reverse lookup on axis use type */
|
||||
gint axis_for_use[GDK_AXIS_LAST];
|
||||
|
||||
/* Information about XInput device */
|
||||
XDevice *xdevice;
|
||||
|
||||
/* minimum key code for device */
|
||||
gint min_keycode;
|
||||
|
||||
int buttonpress_type, buttonrelease_type, keypress_type,
|
||||
keyrelease_type, motionnotify_type, proximityin_type,
|
||||
proximityout_type, changenotify_type;
|
||||
|
||||
/* true if we need to select a different set of events, but
|
||||
can't because this is the core pointer */
|
||||
gint needs_update;
|
||||
|
||||
/* Mask of buttons (used for button grabs) */
|
||||
gint button_state;
|
||||
|
||||
/* true if we've claimed the device as active. (used only for XINPUT_GXI) */
|
||||
gint claimed;
|
||||
#endif /* !XINPUT_NONE */
|
||||
};
|
||||
|
||||
struct _GdkInputWindow
|
||||
{
|
||||
/* gdk window */
|
||||
GdkWindow *window;
|
||||
|
||||
/* Extension mode (GDK_EXTENSION_EVENTS_ALL/CURSOR) */
|
||||
GdkExtensionMode mode;
|
||||
|
||||
/* position relative to root window */
|
||||
gint root_x;
|
||||
gint root_y;
|
||||
|
||||
/* rectangles relative to window of windows obscuring this one */
|
||||
GdkRectangle *obscuring;
|
||||
gint num_obscuring;
|
||||
|
||||
/* Is there a pointer grab for this window ? */
|
||||
gint grabbed;
|
||||
};
|
||||
|
||||
/* Global data */
|
||||
|
||||
extern const GdkDeviceInfo gdk_input_core_info;
|
||||
extern GList *gdk_input_devices;
|
||||
extern GList *gdk_input_windows;
|
||||
|
||||
extern GdkInputVTable gdk_input_vtable;
|
||||
/* information about network port and host for gxid daemon */
|
||||
extern gchar *gdk_input_gxid_host;
|
||||
extern gint gdk_input_gxid_port;
|
||||
extern gint gdk_input_ignore_core;
|
||||
|
||||
/* Function declarations */
|
||||
|
||||
GdkDevicePrivate * gdk_input_find_device (guint32 id);
|
||||
GdkInputWindow * gdk_input_window_find (GdkWindow *window);
|
||||
void gdk_input_window_destroy (GdkWindow *window);
|
||||
void gdk_input_init (void);
|
||||
void gdk_input_exit (void);
|
||||
gint gdk_input_enable_window (GdkWindow *window,
|
||||
GdkDevicePrivate *gdkdev);
|
||||
gint gdk_input_disable_window (GdkWindow *window,
|
||||
GdkDevicePrivate *gdkdev);
|
||||
|
||||
#ifndef XINPUT_NONE
|
||||
|
||||
#define GDK_MAX_DEVICE_CLASSES 13
|
||||
|
||||
gint gdk_input_common_init (gint include_core);
|
||||
void gdk_input_get_root_relative_geometry (Display *dpy,
|
||||
Window w,
|
||||
int *x_ret,
|
||||
int *y_ret,
|
||||
int *width_ret,
|
||||
int *height_ret);
|
||||
void gdk_input_common_find_events (GdkWindow *window,
|
||||
GdkDevicePrivate *gdkdev,
|
||||
gint mask,
|
||||
XEventClass *classes,
|
||||
int *num_classes);
|
||||
void gdk_input_common_select_events (GdkWindow *window,
|
||||
GdkDevicePrivate *gdkdev);
|
||||
gint gdk_input_common_other_event (GdkEvent *event,
|
||||
XEvent *xevent,
|
||||
GdkInputWindow *input_window,
|
||||
GdkDevicePrivate *gdkdev);
|
||||
void gdk_input_common_get_pointer (GdkWindow *window,
|
||||
guint32 deviceid,
|
||||
gdouble *x,
|
||||
gdouble *y,
|
||||
gdouble *pressure,
|
||||
gdouble *xtilt,
|
||||
gdouble *ytilt,
|
||||
GdkModifierType *mask);
|
||||
void gdk_input_common_set_key (guint32 deviceid,
|
||||
guint index,
|
||||
guint keyval,
|
||||
GdkModifierType modifiers);
|
||||
void gdk_input_common_set_axes (guint32 deviceid,
|
||||
GdkAxisUse *axes);
|
||||
GdkTimeCoord * gdk_input_common_motion_events (GdkWindow *window,
|
||||
guint32 deviceid,
|
||||
guint32 start,
|
||||
guint32 stop,
|
||||
gint *nevents_return);
|
||||
|
||||
#endif /* !XINPUT_NONE */
|
||||
|
||||
GdkDevicePrivate *gdk_input_find_device (guint32 id);
|
||||
GdkInputWindow *gdk_input_window_find (GdkWindow *window);
|
||||
void gdk_input_window_destroy (GdkWindow *window);
|
||||
void gdk_input_exit (void);
|
||||
|
||||
#endif /* __GDK_INPUTPRIVATE_H__ */
|
575
gdk/linux-fb/gdkmain-fb.c
Normal file
575
gdk/linux-fb/gdkmain-fb.c
Normal file
@ -0,0 +1,575 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <t1lib.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "gdk.h"
|
||||
|
||||
#include "gdkprivate-fb.h"
|
||||
#include "gdkinternals.h"
|
||||
|
||||
/*
|
||||
* Private function declarations
|
||||
*/
|
||||
|
||||
#ifndef HAVE_XCONVERTCASE
|
||||
static void gdkx_XConvertCase (KeySym symbol,
|
||||
KeySym *lower,
|
||||
KeySym *upper);
|
||||
#define XConvertCase gdkx_XConvertCase
|
||||
#endif
|
||||
|
||||
/* Private variable declarations
|
||||
*/
|
||||
static int gdk_initialized = 0; /* 1 if the library is initialized,
|
||||
* 0 otherwise.
|
||||
*/
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
static const GDebugKey gdk_debug_keys[] = {
|
||||
{"misc", GDK_DEBUG_MISC},
|
||||
{"events", GDK_DEBUG_EVENTS},
|
||||
};
|
||||
|
||||
static const int gdk_ndebug_keys = sizeof(gdk_debug_keys)/sizeof(GDebugKey);
|
||||
|
||||
#endif /* G_ENABLE_DEBUG */
|
||||
|
||||
GdkArgDesc _gdk_windowing_args[] = {
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static GdkFBDisplay *
|
||||
gdk_fb_display_new(const char *filename)
|
||||
{
|
||||
int fd, n;
|
||||
GdkFBDisplay *retval;
|
||||
guint16 red[256], green[256], blue[256];
|
||||
struct fb_cmap cmap;
|
||||
|
||||
fd = open(filename, O_RDWR);
|
||||
if(fd < 0)
|
||||
return NULL;
|
||||
|
||||
retval = g_new0(GdkFBDisplay, 1);
|
||||
retval->fd = fd;
|
||||
n = ioctl(fd, FBIOGET_FSCREENINFO, &retval->sinfo);
|
||||
n |= ioctl(fd, FBIOGET_VSCREENINFO, &retval->modeinfo);
|
||||
g_assert(!n);
|
||||
|
||||
retval->fbmem = mmap(NULL, retval->sinfo.smem_len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
g_assert(retval->fbmem != MAP_FAILED);
|
||||
|
||||
for(n = 0; n < 16; n++)
|
||||
red[n] = green[n] = blue[n] = n << 12;
|
||||
for(n = 16; n < 256; n++)
|
||||
red[n] = green[n] = blue[n] = n << 8;
|
||||
cmap.red = red; cmap.green = green; cmap.blue = blue; cmap.len = 256; cmap.start = 0;
|
||||
ioctl(fd, FBIOPUTCMAP, &cmap);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_fb_display_destroy(GdkFBDisplay *fbd)
|
||||
{
|
||||
munmap(fbd->fbmem, fbd->sinfo.smem_len);
|
||||
g_free(fbd);
|
||||
}
|
||||
|
||||
extern void keyboard_init(void);
|
||||
|
||||
gboolean
|
||||
_gdk_windowing_init_check (int argc, char **argv)
|
||||
{
|
||||
if(gdk_initialized)
|
||||
return TRUE;
|
||||
|
||||
keyboard_init();
|
||||
gdk_display = gdk_fb_display_new("/dev/fb");
|
||||
|
||||
if(!gdk_display)
|
||||
return FALSE;
|
||||
|
||||
T1_InitLib(NO_LOGFILE|IGNORE_FONTDATABASE);
|
||||
T1_AASetBitsPerPixel(gdk_display->modeinfo.bits_per_pixel);
|
||||
|
||||
gdk_initialized = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
* gdk_pointer_grab
|
||||
*
|
||||
* Grabs the pointer to a specific window
|
||||
*
|
||||
* Arguments:
|
||||
* "window" is the window which will receive the grab
|
||||
* "owner_events" specifies whether events will be reported as is,
|
||||
* or relative to "window"
|
||||
* "event_mask" masks only interesting events
|
||||
* "confine_to" limits the cursor movement to the specified window
|
||||
* "cursor" changes the cursor for the duration of the grab
|
||||
* "time" specifies the time
|
||||
*
|
||||
* Results:
|
||||
*
|
||||
* Side effects:
|
||||
* requires a corresponding call to gdk_pointer_ungrab
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
gint
|
||||
gdk_pointer_grab (GdkWindow * window,
|
||||
gint owner_events,
|
||||
GdkEventMask event_mask,
|
||||
GdkWindow * confine_to,
|
||||
GdkCursor * cursor,
|
||||
guint32 time)
|
||||
{
|
||||
g_return_val_if_fail (window != NULL, 0);
|
||||
g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
|
||||
g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
|
||||
|
||||
if(_gdk_fb_pointer_grab_window)
|
||||
return 1;
|
||||
|
||||
if(!owner_events)
|
||||
_gdk_fb_pointer_grab_window = gdk_window_ref(window);
|
||||
|
||||
_gdk_fb_pointer_grab_confine = confine_to?gdk_window_ref(confine_to):NULL;
|
||||
_gdk_fb_pointer_grab_events = event_mask;
|
||||
_gdk_fb_pointer_grab_cursor = cursor?gdk_cursor_ref(cursor):NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
* gdk_pointer_ungrab
|
||||
*
|
||||
* Releases any pointer grab
|
||||
*
|
||||
* Arguments:
|
||||
*
|
||||
* Results:
|
||||
*
|
||||
* Side effects:
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
gdk_pointer_ungrab (guint32 time)
|
||||
{
|
||||
if(_gdk_fb_pointer_grab_window)
|
||||
gdk_window_unref(_gdk_fb_pointer_grab_window);
|
||||
_gdk_fb_pointer_grab_window = NULL;
|
||||
|
||||
if(_gdk_fb_pointer_grab_confine)
|
||||
gdk_window_unref(_gdk_fb_pointer_grab_confine);
|
||||
_gdk_fb_pointer_grab_confine = NULL;
|
||||
|
||||
if(_gdk_fb_pointer_grab_cursor)
|
||||
gdk_cursor_unref(_gdk_fb_pointer_grab_cursor);
|
||||
_gdk_fb_pointer_grab_cursor = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
* gdk_pointer_is_grabbed
|
||||
*
|
||||
* Tell wether there is an active x pointer grab in effect
|
||||
*
|
||||
* Arguments:
|
||||
*
|
||||
* Results:
|
||||
*
|
||||
* Side effects:
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
gint
|
||||
gdk_pointer_is_grabbed (void)
|
||||
{
|
||||
return _gdk_fb_pointer_grab_window != NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
* gdk_keyboard_grab
|
||||
*
|
||||
* Grabs the keyboard to a specific window
|
||||
*
|
||||
* Arguments:
|
||||
* "window" is the window which will receive the grab
|
||||
* "owner_events" specifies whether events will be reported as is,
|
||||
* or relative to "window"
|
||||
* "time" specifies the time
|
||||
*
|
||||
* Results:
|
||||
*
|
||||
* Side effects:
|
||||
* requires a corresponding call to gdk_keyboard_ungrab
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
gint
|
||||
gdk_keyboard_grab (GdkWindow * window,
|
||||
gint owner_events,
|
||||
guint32 time)
|
||||
{
|
||||
g_return_val_if_fail (window != NULL, 0);
|
||||
g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
|
||||
|
||||
if(_gdk_fb_pointer_grab_window)
|
||||
gdk_keyboard_ungrab(time);
|
||||
|
||||
if(!owner_events)
|
||||
_gdk_fb_keyboard_grab_window = gdk_window_ref(window);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
* gdk_keyboard_ungrab
|
||||
*
|
||||
* Releases any keyboard grab
|
||||
*
|
||||
* Arguments:
|
||||
*
|
||||
* Results:
|
||||
*
|
||||
* Side effects:
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
gdk_keyboard_ungrab (guint32 time)
|
||||
{
|
||||
if(_gdk_fb_keyboard_grab_window)
|
||||
gdk_window_unref(_gdk_fb_keyboard_grab_window);
|
||||
_gdk_fb_keyboard_grab_window = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
* gdk_screen_width
|
||||
*
|
||||
* Return the width of the screen.
|
||||
*
|
||||
* Arguments:
|
||||
*
|
||||
* Results:
|
||||
*
|
||||
* Side effects:
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
gint
|
||||
gdk_screen_width (void)
|
||||
{
|
||||
return gdk_display->modeinfo.xres;
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
* gdk_screen_height
|
||||
*
|
||||
* Return the height of the screen.
|
||||
*
|
||||
* Arguments:
|
||||
*
|
||||
* Results:
|
||||
*
|
||||
* Side effects:
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
gint
|
||||
gdk_screen_height (void)
|
||||
{
|
||||
return gdk_display->modeinfo.yres;
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
* gdk_screen_width_mm
|
||||
*
|
||||
* Return the width of the screen in millimeters.
|
||||
*
|
||||
* Arguments:
|
||||
*
|
||||
* Results:
|
||||
*
|
||||
* Side effects:
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
gint
|
||||
gdk_screen_width_mm (void)
|
||||
{
|
||||
return 0.5 + gdk_screen_width () * (25.4 / 72.);
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
* gdk_screen_height
|
||||
*
|
||||
* Return the height of the screen in millimeters.
|
||||
*
|
||||
* Arguments:
|
||||
*
|
||||
* Results:
|
||||
*
|
||||
* Side effects:
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
gint
|
||||
gdk_screen_height_mm (void)
|
||||
{
|
||||
return 0.5 + gdk_screen_height () * (25.4 / 72.);
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
* gdk_set_sm_client_id
|
||||
*
|
||||
* Set the SM_CLIENT_ID property on the WM_CLIENT_LEADER window
|
||||
* so that the window manager can save our state using the
|
||||
* X11R6 ICCCM session management protocol. A NULL value should
|
||||
* be set following disconnection from the session manager to
|
||||
* remove the SM_CLIENT_ID property.
|
||||
*
|
||||
* Arguments:
|
||||
*
|
||||
* "sm_client_id" specifies the client id assigned to us by the
|
||||
* session manager or NULL to remove the property.
|
||||
*
|
||||
* Results:
|
||||
*
|
||||
* Side effects:
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
gdk_set_sm_client_id (const gchar* sm_client_id)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
gdk_key_repeat_disable (void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
gdk_key_repeat_restore (void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gdk_beep (void)
|
||||
{
|
||||
}
|
||||
|
||||
extern void keyboard_shutdown(void);
|
||||
|
||||
void
|
||||
gdk_windowing_exit (void)
|
||||
{
|
||||
gdk_fb_display_destroy(gdk_display); gdk_display = NULL;
|
||||
|
||||
T1_CloseLib();
|
||||
|
||||
keyboard_shutdown();
|
||||
}
|
||||
|
||||
gchar*
|
||||
gdk_keyval_name (guint keyval)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
guint
|
||||
gdk_keyval_from_name (const gchar *keyval_name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gdk_keyval_convert_case (guint symbol,
|
||||
guint *lower,
|
||||
guint *upper)
|
||||
{
|
||||
if(symbol >= 'a' && symbol <= 'z')
|
||||
symbol = toupper(symbol);
|
||||
|
||||
if(upper)
|
||||
*upper = symbol;
|
||||
|
||||
if(lower)
|
||||
*lower = symbol;
|
||||
}
|
||||
|
||||
gchar *
|
||||
gdk_get_display(void)
|
||||
{
|
||||
return g_strdup("/dev/fb0");
|
||||
}
|
||||
|
||||
/* utils */
|
||||
GdkEvent *
|
||||
gdk_event_make(GdkWindow *window, GdkEventType type, gboolean append_to_queue)
|
||||
{
|
||||
static const guint type_masks[] = {
|
||||
GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE = 0, */
|
||||
GDK_STRUCTURE_MASK, /* GDK_DESTROY = 1, */
|
||||
GDK_EXPOSURE_MASK, /* GDK_EXPOSE = 2, */
|
||||
GDK_POINTER_MOTION_MASK|GDK_BUTTON_MOTION_MASK, /* GDK_MOTION_NOTIFY = 3, */
|
||||
GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS = 4, */
|
||||
GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS = 5, */
|
||||
GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS = 6, */
|
||||
GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE = 7, */
|
||||
GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS = 8, */
|
||||
GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE = 9, */
|
||||
GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY = 10, */
|
||||
GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY = 11, */
|
||||
GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE = 12, */
|
||||
GDK_STRUCTURE_MASK, /* GDK_CONFIGURE = 13, */
|
||||
GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP = 14, */
|
||||
GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP = 15, */
|
||||
GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY = 16, */
|
||||
GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR = 17, */
|
||||
GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST = 18, */
|
||||
GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY = 19, */
|
||||
GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN = 20, */
|
||||
GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT = 21, */
|
||||
GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER = 22, */
|
||||
GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE = 23, */
|
||||
GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION = 24, */
|
||||
GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS = 25, */
|
||||
GDK_ALL_EVENTS_MASK, /* GDK_DROP_START = 26, */
|
||||
GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED = 27, */
|
||||
GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT = 28, */
|
||||
GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29, */
|
||||
GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE = 30, */
|
||||
GDK_SCROLL_MASK /* GDK_SCROLL = 31 */
|
||||
};
|
||||
|
||||
if(GDK_WINDOW_FBDATA(window)->event_mask & type_masks[type])
|
||||
{
|
||||
GdkEvent *event = gdk_event_new();
|
||||
guint32 the_time = g_latest_time.tv_sec;
|
||||
|
||||
event->any.type = type;
|
||||
event->any.window = gdk_window_ref(window);
|
||||
switch(type)
|
||||
{
|
||||
case GDK_MOTION_NOTIFY:
|
||||
event->motion.time = the_time;
|
||||
break;
|
||||
case GDK_BUTTON_PRESS:
|
||||
case GDK_2BUTTON_PRESS:
|
||||
case GDK_3BUTTON_PRESS:
|
||||
case GDK_BUTTON_RELEASE:
|
||||
event->button.time = the_time;
|
||||
break;
|
||||
case GDK_KEY_PRESS:
|
||||
case GDK_KEY_RELEASE:
|
||||
event->key.time = the_time;
|
||||
break;
|
||||
case GDK_ENTER_NOTIFY:
|
||||
case GDK_LEAVE_NOTIFY:
|
||||
event->crossing.time = the_time;
|
||||
break;
|
||||
|
||||
case GDK_PROPERTY_NOTIFY:
|
||||
event->property.time = the_time;
|
||||
break;
|
||||
|
||||
case GDK_SELECTION_CLEAR:
|
||||
case GDK_SELECTION_REQUEST:
|
||||
case GDK_SELECTION_NOTIFY:
|
||||
event->selection.time = the_time;
|
||||
break;
|
||||
case GDK_PROXIMITY_IN:
|
||||
case GDK_PROXIMITY_OUT:
|
||||
event->proximity.time = the_time;
|
||||
break;
|
||||
case GDK_DRAG_ENTER:
|
||||
case GDK_DRAG_LEAVE:
|
||||
case GDK_DRAG_MOTION:
|
||||
case GDK_DRAG_STATUS:
|
||||
case GDK_DROP_START:
|
||||
case GDK_DROP_FINISHED:
|
||||
event->dnd.time = the_time;
|
||||
break;
|
||||
|
||||
case GDK_FOCUS_CHANGE:
|
||||
case GDK_CONFIGURE:
|
||||
case GDK_MAP:
|
||||
case GDK_UNMAP:
|
||||
case GDK_CLIENT_EVENT:
|
||||
case GDK_VISIBILITY_NOTIFY:
|
||||
case GDK_NO_EXPOSE:
|
||||
case GDK_SCROLL:
|
||||
case GDK_DELETE:
|
||||
case GDK_DESTROY:
|
||||
case GDK_EXPOSE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(append_to_queue)
|
||||
gdk_event_queue_append(event);
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
768
gdk/linux-fb/gdkpixmap-fb.c
Normal file
768
gdk/linux-fb/gdkpixmap-fb.c
Normal file
@ -0,0 +1,768 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
/* Needed for SEEK_END in SunOS */
|
||||
#include <unistd.h>
|
||||
|
||||
#include "gdkpixmap.h"
|
||||
#include "gdkfb.h"
|
||||
#include "gdkprivate-fb.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gchar *color_string;
|
||||
GdkColor color;
|
||||
gint transparent;
|
||||
} _GdkPixmapColor;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint ncolors;
|
||||
GdkColormap *colormap;
|
||||
gulong pixels[1];
|
||||
} _GdkPixmapInfo;
|
||||
|
||||
static void
|
||||
gdk_fb_pixmap_destroy (GdkPixmap *pixmap)
|
||||
{
|
||||
g_free (GDK_DRAWABLE_FBDATA(pixmap)->mem);
|
||||
g_free (GDK_DRAWABLE_FBDATA (pixmap));
|
||||
}
|
||||
|
||||
static GdkDrawable *
|
||||
gdk_fb_pixmap_alloc (void)
|
||||
{
|
||||
GdkDrawable *drawable;
|
||||
GdkDrawablePrivate *private;
|
||||
|
||||
static GdkDrawableClass klass;
|
||||
static gboolean initialized = FALSE;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
initialized = TRUE;
|
||||
|
||||
klass = _gdk_fb_drawable_class;
|
||||
klass.destroy = gdk_fb_pixmap_destroy;
|
||||
}
|
||||
|
||||
drawable = gdk_drawable_alloc ();
|
||||
private = (GdkDrawablePrivate *)drawable;
|
||||
|
||||
private->klass = &klass;
|
||||
private->klass_data = g_new0 (GdkDrawableFBData, 1);
|
||||
private->window_type = GDK_DRAWABLE_PIXMAP;
|
||||
private->colormap = gdk_colormap_ref(gdk_colormap_get_system());
|
||||
|
||||
return drawable;
|
||||
}
|
||||
|
||||
GdkPixmap*
|
||||
gdk_pixmap_new (GdkWindow *window,
|
||||
gint width,
|
||||
gint height,
|
||||
gint depth)
|
||||
{
|
||||
GdkPixmap *pixmap;
|
||||
GdkDrawablePrivate *private;
|
||||
|
||||
g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
|
||||
g_return_val_if_fail ((window != NULL) || (depth != -1), NULL);
|
||||
g_return_val_if_fail ((width != 0) && (height != 0), NULL);
|
||||
|
||||
if (!window)
|
||||
window = gdk_parent_root;
|
||||
|
||||
if (GDK_DRAWABLE_DESTROYED (window))
|
||||
return NULL;
|
||||
|
||||
if (depth == -1)
|
||||
depth = gdk_drawable_get_visual (window)->depth;
|
||||
|
||||
pixmap = gdk_fb_pixmap_alloc ();
|
||||
private = (GdkDrawablePrivate *)pixmap;
|
||||
|
||||
GDK_DRAWABLE_FBDATA(pixmap)->mem = g_malloc(((width * depth + 7) / 8) * height);
|
||||
GDK_DRAWABLE_FBDATA(pixmap)->rowstride = (width * depth + 7) / 8; /* Round up to nearest whole byte */
|
||||
GDK_DRAWABLE_FBDATA(pixmap)->lim_x = width;
|
||||
GDK_DRAWABLE_FBDATA(pixmap)->lim_y = height;
|
||||
private->width = width;
|
||||
private->height = height;
|
||||
private->depth = depth;
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
GdkPixmap *
|
||||
gdk_bitmap_create_from_data (GdkWindow *window,
|
||||
const gchar *data,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
GdkPixmap *pixmap;
|
||||
|
||||
g_return_val_if_fail (data != NULL, NULL);
|
||||
g_return_val_if_fail ((width != 0) && (height != 0), NULL);
|
||||
g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
|
||||
|
||||
if (!window)
|
||||
window = gdk_parent_root;
|
||||
|
||||
if (GDK_DRAWABLE_DESTROYED (window))
|
||||
return NULL;
|
||||
|
||||
pixmap = gdk_pixmap_new(window, width, height, 1);
|
||||
|
||||
memcpy(GDK_DRAWABLE_FBDATA(pixmap)->mem, data, ((width + 7) / 8) * height);
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
GdkPixmap*
|
||||
gdk_pixmap_create_from_data (GdkWindow *window,
|
||||
const gchar *data,
|
||||
gint width,
|
||||
gint height,
|
||||
gint depth,
|
||||
GdkColor *fg,
|
||||
GdkColor *bg)
|
||||
{
|
||||
GdkPixmap *pixmap;
|
||||
GdkDrawablePrivate *private;
|
||||
|
||||
g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
|
||||
g_return_val_if_fail (data != NULL, NULL);
|
||||
g_return_val_if_fail (fg != NULL, NULL);
|
||||
g_return_val_if_fail (bg != NULL, NULL);
|
||||
g_return_val_if_fail ((window != NULL) || (depth != -1), NULL);
|
||||
g_return_val_if_fail ((width != 0) && (height != 0), NULL);
|
||||
|
||||
if (!window)
|
||||
window = gdk_parent_root;
|
||||
|
||||
if (GDK_DRAWABLE_DESTROYED (window))
|
||||
return NULL;
|
||||
|
||||
if (depth == -1)
|
||||
depth = gdk_drawable_get_visual (window)->depth;
|
||||
|
||||
pixmap = gdk_pixmap_new(window, width, height, depth);
|
||||
|
||||
private = (GdkDrawablePrivate *)pixmap;
|
||||
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
static gint
|
||||
gdk_pixmap_seek_string (FILE *infile,
|
||||
const gchar *str,
|
||||
gint skip_comments)
|
||||
{
|
||||
char instr[1024];
|
||||
|
||||
while (!feof (infile))
|
||||
{
|
||||
fscanf (infile, "%1023s", instr);
|
||||
if (skip_comments == TRUE && strcmp (instr, "/*") == 0)
|
||||
{
|
||||
fscanf (infile, "%1023s", instr);
|
||||
while (!feof (infile) && strcmp (instr, "*/") != 0)
|
||||
fscanf (infile, "%1023s", instr);
|
||||
fscanf(infile, "%1023s", instr);
|
||||
}
|
||||
if (strcmp (instr, str)==0)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gint
|
||||
gdk_pixmap_seek_char (FILE *infile,
|
||||
gchar c)
|
||||
{
|
||||
gint b, oldb;
|
||||
|
||||
while ((b = getc(infile)) != EOF)
|
||||
{
|
||||
if (c != b && b == '/')
|
||||
{
|
||||
b = getc (infile);
|
||||
if (b == EOF)
|
||||
return FALSE;
|
||||
else if (b == '*') /* we have a comment */
|
||||
{
|
||||
b = -1;
|
||||
do
|
||||
{
|
||||
oldb = b;
|
||||
b = getc (infile);
|
||||
if (b == EOF)
|
||||
return FALSE;
|
||||
}
|
||||
while (!(oldb == '*' && b == '/'));
|
||||
}
|
||||
}
|
||||
else if (c == b)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gint
|
||||
gdk_pixmap_read_string (FILE *infile,
|
||||
gchar **buffer,
|
||||
guint *buffer_size)
|
||||
{
|
||||
gint c;
|
||||
guint cnt = 0, bufsiz, ret = FALSE;
|
||||
gchar *buf;
|
||||
|
||||
buf = *buffer;
|
||||
bufsiz = *buffer_size;
|
||||
if (buf == NULL)
|
||||
{
|
||||
bufsiz = 10 * sizeof (gchar);
|
||||
buf = g_new(gchar, bufsiz);
|
||||
}
|
||||
|
||||
do
|
||||
c = getc (infile);
|
||||
while (c != EOF && c != '"');
|
||||
|
||||
if (c != '"')
|
||||
goto out;
|
||||
|
||||
while ((c = getc(infile)) != EOF)
|
||||
{
|
||||
if (cnt == bufsiz)
|
||||
{
|
||||
guint new_size = bufsiz * 2;
|
||||
if (new_size > bufsiz)
|
||||
bufsiz = new_size;
|
||||
else
|
||||
goto out;
|
||||
|
||||
buf = (gchar *) g_realloc (buf, bufsiz);
|
||||
buf[bufsiz-1] = '\0';
|
||||
}
|
||||
|
||||
if (c != '"')
|
||||
buf[cnt++] = c;
|
||||
else
|
||||
{
|
||||
buf[cnt] = 0;
|
||||
ret = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
buf[bufsiz-1] = '\0'; /* ensure null termination for errors */
|
||||
*buffer = buf;
|
||||
*buffer_size = bufsiz;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
gdk_pixmap_skip_whitespaces (gchar *buffer)
|
||||
{
|
||||
gint32 index = 0;
|
||||
|
||||
while (buffer[index] != 0 && (buffer[index] == 0x20 || buffer[index] == 0x09))
|
||||
index++;
|
||||
|
||||
return &buffer[index];
|
||||
}
|
||||
|
||||
static gchar*
|
||||
gdk_pixmap_skip_string (gchar *buffer)
|
||||
{
|
||||
gint32 index = 0;
|
||||
|
||||
while (buffer[index] != 0 && buffer[index] != 0x20 && buffer[index] != 0x09)
|
||||
index++;
|
||||
|
||||
return &buffer[index];
|
||||
}
|
||||
|
||||
/* Xlib crashed once at a color name lengths around 125 */
|
||||
#define MAX_COLOR_LEN 120
|
||||
|
||||
static gchar*
|
||||
gdk_pixmap_extract_color (gchar *buffer)
|
||||
{
|
||||
gint counter, numnames;
|
||||
gchar *ptr = NULL, ch, temp[128];
|
||||
gchar color[MAX_COLOR_LEN], *retcol;
|
||||
gint space;
|
||||
|
||||
counter = 0;
|
||||
while (ptr == NULL)
|
||||
{
|
||||
if (buffer[counter] == 'c')
|
||||
{
|
||||
ch = buffer[counter + 1];
|
||||
if (ch == 0x20 || ch == 0x09)
|
||||
ptr = &buffer[counter + 1];
|
||||
}
|
||||
else if (buffer[counter] == 0)
|
||||
return NULL;
|
||||
|
||||
counter++;
|
||||
}
|
||||
|
||||
ptr = gdk_pixmap_skip_whitespaces (ptr);
|
||||
|
||||
if (ptr[0] == 0)
|
||||
return NULL;
|
||||
else if (ptr[0] == '#')
|
||||
{
|
||||
counter = 1;
|
||||
while (ptr[counter] != 0 &&
|
||||
((ptr[counter] >= '0' && ptr[counter] <= '9') ||
|
||||
(ptr[counter] >= 'a' && ptr[counter] <= 'f') ||
|
||||
(ptr[counter] >= 'A' && ptr[counter] <= 'F')))
|
||||
counter++;
|
||||
|
||||
retcol = g_new (gchar, counter+1);
|
||||
strncpy (retcol, ptr, counter);
|
||||
|
||||
retcol[counter] = 0;
|
||||
|
||||
return retcol;
|
||||
}
|
||||
|
||||
color[0] = 0;
|
||||
numnames = 0;
|
||||
|
||||
space = MAX_COLOR_LEN - 1;
|
||||
while (space > 0)
|
||||
{
|
||||
sscanf (ptr, "%127s", temp);
|
||||
|
||||
if (((gint)ptr[0] == 0) ||
|
||||
(strcmp ("s", temp) == 0) || (strcmp ("m", temp) == 0) ||
|
||||
(strcmp ("g", temp) == 0) || (strcmp ("g4", temp) == 0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (numnames > 0)
|
||||
{
|
||||
space -= 1;
|
||||
strcat (color, " ");
|
||||
}
|
||||
strncat (color, temp, space);
|
||||
space -= MIN (space, strlen (temp));
|
||||
ptr = gdk_pixmap_skip_string (ptr);
|
||||
ptr = gdk_pixmap_skip_whitespaces (ptr);
|
||||
numnames++;
|
||||
}
|
||||
}
|
||||
|
||||
retcol = g_strdup (color);
|
||||
return retcol;
|
||||
}
|
||||
|
||||
|
||||
enum buffer_op
|
||||
{
|
||||
op_header,
|
||||
op_cmap,
|
||||
op_body
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
gdk_xpm_destroy_notify (gpointer data)
|
||||
{
|
||||
_GdkPixmapInfo *info = (_GdkPixmapInfo *)data;
|
||||
GdkColor color;
|
||||
int i;
|
||||
|
||||
for (i=0; i<info->ncolors; i++)
|
||||
{
|
||||
color.pixel = info->pixels[i];
|
||||
gdk_colormap_free_colors (info->colormap, &color, 1);
|
||||
}
|
||||
|
||||
gdk_colormap_unref (info->colormap);
|
||||
g_free (info);
|
||||
}
|
||||
|
||||
static GdkPixmap *
|
||||
_gdk_pixmap_create_from_xpm (GdkWindow *window,
|
||||
GdkColormap *colormap,
|
||||
GdkBitmap **mask,
|
||||
GdkColor *transparent_color,
|
||||
gchar * (*get_buf) (enum buffer_op op,
|
||||
gpointer handle),
|
||||
gpointer handle)
|
||||
{
|
||||
GdkPixmap *pixmap = NULL;
|
||||
GdkImage *image = NULL;
|
||||
GdkVisual *visual;
|
||||
GdkGC *gc = NULL;
|
||||
GdkColor tmp_color;
|
||||
gint width, height, num_cols, cpp, n, ns, cnt, xcnt, ycnt, wbytes;
|
||||
gchar *buffer, pixel_str[32];
|
||||
gchar *name_buf;
|
||||
_GdkPixmapColor *color = NULL, *fallbackcolor = NULL;
|
||||
_GdkPixmapColor *colors = NULL;
|
||||
gulong index;
|
||||
GHashTable *color_hash = NULL;
|
||||
_GdkPixmapInfo *color_info = NULL;
|
||||
|
||||
if ((window == NULL) && (colormap == NULL))
|
||||
g_warning ("Creating pixmap from xpm with NULL window and colormap");
|
||||
|
||||
if (window == NULL)
|
||||
window = gdk_parent_root;
|
||||
|
||||
if (colormap == NULL)
|
||||
{
|
||||
colormap = gdk_drawable_get_colormap (window);
|
||||
visual = gdk_drawable_get_visual (window);
|
||||
}
|
||||
else
|
||||
visual = ((GdkColormapPrivate *)colormap)->visual;
|
||||
|
||||
buffer = (*get_buf) (op_header, handle);
|
||||
if (buffer == NULL)
|
||||
return NULL;
|
||||
|
||||
sscanf (buffer,"%d %d %d %d", &width, &height, &num_cols, &cpp);
|
||||
if (cpp >= 32)
|
||||
{
|
||||
g_warning ("Pixmap has more than 31 characters per color\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
color_hash = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
|
||||
if (transparent_color == NULL)
|
||||
{
|
||||
gdk_color_white (colormap, &tmp_color);
|
||||
transparent_color = &tmp_color;
|
||||
}
|
||||
|
||||
/* For pseudo-color and grayscale visuals, we have to remember
|
||||
* the colors we allocated, so we can free them later.
|
||||
*/
|
||||
if ((visual->type == GDK_VISUAL_PSEUDO_COLOR) ||
|
||||
(visual->type == GDK_VISUAL_GRAYSCALE))
|
||||
{
|
||||
color_info = g_malloc (sizeof (_GdkPixmapInfo) +
|
||||
sizeof(gulong) * (num_cols - 1));
|
||||
color_info->ncolors = num_cols;
|
||||
color_info->colormap = colormap;
|
||||
gdk_colormap_ref (colormap);
|
||||
}
|
||||
|
||||
name_buf = g_new (gchar, num_cols * (cpp+1));
|
||||
colors = g_new (_GdkPixmapColor, num_cols);
|
||||
|
||||
for (cnt = 0; cnt < num_cols; cnt++)
|
||||
{
|
||||
gchar *color_name;
|
||||
|
||||
buffer = (*get_buf) (op_cmap, handle);
|
||||
if (buffer == NULL)
|
||||
goto error;
|
||||
|
||||
color = &colors[cnt];
|
||||
color->color_string = &name_buf [cnt * (cpp + 1)];
|
||||
strncpy (color->color_string, buffer, cpp);
|
||||
color->color_string[cpp] = 0;
|
||||
buffer += strlen (color->color_string);
|
||||
color->transparent = FALSE;
|
||||
|
||||
color_name = gdk_pixmap_extract_color (buffer);
|
||||
|
||||
if (color_name == NULL || g_strcasecmp (color_name, "None") == 0 ||
|
||||
gdk_color_parse (color_name, &color->color) == FALSE)
|
||||
{
|
||||
color->color = *transparent_color;
|
||||
color->transparent = TRUE;
|
||||
}
|
||||
|
||||
g_free (color_name);
|
||||
|
||||
/* FIXME: The remaining slowness appears to happen in this
|
||||
function. */
|
||||
gdk_color_alloc (colormap, &color->color);
|
||||
|
||||
if (color_info)
|
||||
color_info->pixels[cnt] = color->color.pixel;
|
||||
|
||||
g_hash_table_insert (color_hash, color->color_string, color);
|
||||
if (cnt == 0)
|
||||
fallbackcolor = color;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
image = gdk_image_new (GDK_IMAGE_FASTEST, visual, width, height);
|
||||
|
||||
if (mask)
|
||||
{
|
||||
/* The pixmap mask is just a bits pattern.
|
||||
* Color 0 is used for background and 1 for foreground.
|
||||
* We don't care about the colormap, we just need 0 and 1.
|
||||
*/
|
||||
GdkColor mask_pattern;
|
||||
|
||||
*mask = gdk_pixmap_new (window, width, height, 1);
|
||||
gc = gdk_gc_new (*mask);
|
||||
|
||||
mask_pattern.pixel = 0;
|
||||
gdk_gc_set_foreground (gc, &mask_pattern);
|
||||
gdk_draw_rectangle (*mask, gc, TRUE, 0, 0, width, height);
|
||||
|
||||
mask_pattern.pixel = 255;
|
||||
gdk_gc_set_foreground (gc, &mask_pattern);
|
||||
}
|
||||
|
||||
wbytes = width * cpp;
|
||||
for (ycnt = 0; ycnt < height; ycnt++)
|
||||
{
|
||||
buffer = (*get_buf) (op_body, handle);
|
||||
|
||||
/* FIXME: this slows things down a little - it could be
|
||||
* integrated into the strncpy below, perhaps. OTOH, strlen
|
||||
* is fast.
|
||||
*/
|
||||
if ((buffer == NULL) || strlen (buffer) < wbytes)
|
||||
continue;
|
||||
|
||||
for (n = 0, cnt = 0, xcnt = 0; n < wbytes; n += cpp, xcnt++)
|
||||
{
|
||||
strncpy (pixel_str, &buffer[n], cpp);
|
||||
pixel_str[cpp] = 0;
|
||||
ns = 0;
|
||||
|
||||
color = g_hash_table_lookup (color_hash, pixel_str);
|
||||
|
||||
if (!color) /* screwed up XPM file */
|
||||
color = fallbackcolor;
|
||||
|
||||
gdk_image_put_pixel (image, xcnt, ycnt, color->color.pixel);
|
||||
|
||||
if (mask && color->transparent)
|
||||
{
|
||||
if (cnt < xcnt)
|
||||
gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
|
||||
cnt = xcnt + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (mask && (cnt < xcnt))
|
||||
gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
|
||||
}
|
||||
|
||||
error:
|
||||
|
||||
if (mask)
|
||||
gdk_gc_unref (gc);
|
||||
|
||||
if (image != NULL)
|
||||
{
|
||||
pixmap = gdk_pixmap_new (window, width, height, visual->depth);
|
||||
|
||||
if (color_info)
|
||||
gdk_drawable_set_data (pixmap, "gdk-xpm", color_info,
|
||||
gdk_xpm_destroy_notify);
|
||||
|
||||
gc = gdk_gc_new (pixmap);
|
||||
gdk_gc_set_foreground (gc, transparent_color);
|
||||
gdk_draw_image (pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
|
||||
gdk_gc_unref (gc);
|
||||
gdk_image_unref (image);
|
||||
|
||||
#if 0
|
||||
g_print("%dx%d\n", width, height);
|
||||
for(y = 0; y < height; y++)
|
||||
{
|
||||
for(x = 0; x < width; x++)
|
||||
{
|
||||
guchar foo = GDK_DRAWABLE_FBDATA(pixmap)->mem[(x + GDK_DRAWABLE_FBDATA(pixmap)->rowstride * y];
|
||||
if(foo == 0)
|
||||
g_print("o");
|
||||
else if(foo == 255)
|
||||
g_print("w");
|
||||
else if(foo == transparent_color->pixel)
|
||||
g_print(" ");
|
||||
else
|
||||
g_print(".");
|
||||
}
|
||||
g_print("\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (color_info)
|
||||
gdk_xpm_destroy_notify (color_info);
|
||||
|
||||
if (color_hash != NULL)
|
||||
g_hash_table_destroy (color_hash);
|
||||
|
||||
if (colors != NULL)
|
||||
g_free (colors);
|
||||
|
||||
if (name_buf != NULL)
|
||||
g_free (name_buf);
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
|
||||
struct file_handle
|
||||
{
|
||||
FILE *infile;
|
||||
gchar *buffer;
|
||||
guint buffer_size;
|
||||
};
|
||||
|
||||
|
||||
static gchar *
|
||||
file_buffer (enum buffer_op op, gpointer handle)
|
||||
{
|
||||
struct file_handle *h = handle;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case op_header:
|
||||
if (gdk_pixmap_seek_string (h->infile, "XPM", FALSE) != TRUE)
|
||||
break;
|
||||
|
||||
if (gdk_pixmap_seek_char (h->infile,'{') != TRUE)
|
||||
break;
|
||||
/* Fall through to the next gdk_pixmap_seek_char. */
|
||||
|
||||
case op_cmap:
|
||||
gdk_pixmap_seek_char (h->infile, '"');
|
||||
fseek (h->infile, -1, SEEK_CUR);
|
||||
/* Fall through to the gdk_pixmap_read_string. */
|
||||
|
||||
case op_body:
|
||||
gdk_pixmap_read_string (h->infile, &h->buffer, &h->buffer_size);
|
||||
return h->buffer;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
GdkPixmap*
|
||||
gdk_pixmap_colormap_create_from_xpm (GdkWindow *window,
|
||||
GdkColormap *colormap,
|
||||
GdkBitmap **mask,
|
||||
GdkColor *transparent_color,
|
||||
const gchar *filename)
|
||||
{
|
||||
struct file_handle h;
|
||||
GdkPixmap *pixmap = NULL;
|
||||
|
||||
memset (&h, 0, sizeof (h));
|
||||
h.infile = fopen (filename, "rb");
|
||||
if (h.infile != NULL)
|
||||
{
|
||||
pixmap = _gdk_pixmap_create_from_xpm (window, colormap, mask,
|
||||
transparent_color,
|
||||
file_buffer, &h);
|
||||
fclose (h.infile);
|
||||
g_free (h.buffer);
|
||||
}
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
GdkPixmap*
|
||||
gdk_pixmap_create_from_xpm (GdkWindow *window,
|
||||
GdkBitmap **mask,
|
||||
GdkColor *transparent_color,
|
||||
const gchar *filename)
|
||||
{
|
||||
return gdk_pixmap_colormap_create_from_xpm (window, NULL, mask,
|
||||
transparent_color, filename);
|
||||
}
|
||||
|
||||
|
||||
struct mem_handle
|
||||
{
|
||||
gchar **data;
|
||||
int offset;
|
||||
};
|
||||
|
||||
|
||||
static gchar *
|
||||
mem_buffer (enum buffer_op op, gpointer handle)
|
||||
{
|
||||
struct mem_handle *h = handle;
|
||||
switch (op)
|
||||
{
|
||||
case op_header:
|
||||
case op_cmap:
|
||||
case op_body:
|
||||
if (h->data[h->offset])
|
||||
return h->data[h->offset ++];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
GdkPixmap*
|
||||
gdk_pixmap_colormap_create_from_xpm_d (GdkWindow *window,
|
||||
GdkColormap *colormap,
|
||||
GdkBitmap **mask,
|
||||
GdkColor *transparent_color,
|
||||
gchar **data)
|
||||
{
|
||||
struct mem_handle h;
|
||||
GdkPixmap *pixmap = NULL;
|
||||
|
||||
memset (&h, 0, sizeof (h));
|
||||
h.data = data;
|
||||
pixmap = _gdk_pixmap_create_from_xpm (window, colormap, mask,
|
||||
transparent_color,
|
||||
mem_buffer, &h);
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
|
||||
GdkPixmap*
|
||||
gdk_pixmap_create_from_xpm_d (GdkWindow *window,
|
||||
GdkBitmap **mask,
|
||||
GdkColor *transparent_color,
|
||||
gchar **data)
|
||||
{
|
||||
return gdk_pixmap_colormap_create_from_xpm_d (window, NULL, mask,
|
||||
transparent_color, data);
|
||||
}
|
291
gdk/linux-fb/gdkpoly-generic.h
Normal file
291
gdk/linux-fb/gdkpoly-generic.h
Normal file
@ -0,0 +1,291 @@
|
||||
/* $TOG: poly.h /main/5 1998/02/06 17:47:27 kaleb $ */
|
||||
/************************************************************************
|
||||
|
||||
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.
|
||||
|
||||
************************************************************************/
|
||||
|
||||
/*
|
||||
* This file contains a few macros to help track
|
||||
* the edge of a filled object. The object is assumed
|
||||
* to be filled in scanline order, and thus the
|
||||
* algorithm used is an extension of Bresenham's line
|
||||
* drawing algorithm which assumes that y is always the
|
||||
* major axis.
|
||||
* Since these pieces of code are the same for any filled shape,
|
||||
* it is more convenient to gather the library in one
|
||||
* place, but since these pieces of code are also in
|
||||
* the inner loops of output primitives, procedure call
|
||||
* overhead is out of the question.
|
||||
* See the author for a derivation if needed.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* In scan converting polygons, we want to choose those pixels
|
||||
* which are inside the polygon. Thus, we add .5 to the starting
|
||||
* x coordinate for both left and right edges. Now we choose the
|
||||
* first pixel which is inside the pgon for the left edge and the
|
||||
* first pixel which is outside the pgon for the right edge.
|
||||
* Draw the left pixel, but not the right.
|
||||
*
|
||||
* How to add .5 to the starting x coordinate:
|
||||
* If the edge is moving to the right, then subtract dy from the
|
||||
* error term from the general form of the algorithm.
|
||||
* If the edge is moving to the left, then add dy to the error term.
|
||||
*
|
||||
* The reason for the difference between edges moving to the left
|
||||
* and edges moving to the right is simple: If an edge is moving
|
||||
* to the right, then we want the algorithm to flip immediately.
|
||||
* If it is moving to the left, then we don't want it to flip until
|
||||
* we traverse an entire pixel.
|
||||
*/
|
||||
#define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \
|
||||
int dx; /* local storage */ \
|
||||
\
|
||||
/* \
|
||||
* if the edge is horizontal, then it is ignored \
|
||||
* and assumed not to be processed. Otherwise, do this stuff. \
|
||||
*/ \
|
||||
if ((dy) != 0) { \
|
||||
xStart = (x1); \
|
||||
dx = (x2) - xStart; \
|
||||
if (dx < 0) { \
|
||||
m = dx / (dy); \
|
||||
m1 = m - 1; \
|
||||
incr1 = -2 * dx + 2 * (dy) * m1; \
|
||||
incr2 = -2 * dx + 2 * (dy) * m; \
|
||||
d = 2 * m * (dy) - 2 * dx - 2 * (dy); \
|
||||
} else { \
|
||||
m = dx / (dy); \
|
||||
m1 = m + 1; \
|
||||
incr1 = 2 * dx - 2 * (dy) * m1; \
|
||||
incr2 = 2 * dx - 2 * (dy) * m; \
|
||||
d = -2 * m * (dy) + 2 * dx; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \
|
||||
if (m1 > 0) { \
|
||||
if (d > 0) { \
|
||||
minval += m1; \
|
||||
d += incr1; \
|
||||
} \
|
||||
else { \
|
||||
minval += m; \
|
||||
d += incr2; \
|
||||
} \
|
||||
} else {\
|
||||
if (d >= 0) { \
|
||||
minval += m1; \
|
||||
d += incr1; \
|
||||
} \
|
||||
else { \
|
||||
minval += m; \
|
||||
d += incr2; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This structure contains all of the information needed
|
||||
* to run the bresenham algorithm.
|
||||
* The variables may be hardcoded into the declarations
|
||||
* instead of using this structure to make use of
|
||||
* register declarations.
|
||||
*/
|
||||
typedef struct {
|
||||
int minor_axis; /* minor axis */
|
||||
int d; /* decision variable */
|
||||
int m, m1; /* slope and slope+1 */
|
||||
int incr1, incr2; /* error increments */
|
||||
} BRESINFO;
|
||||
|
||||
|
||||
#define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \
|
||||
BRESINITPGON(dmaj, min1, min2, bres.minor_axis, bres.d, \
|
||||
bres.m, bres.m1, bres.incr1, bres.incr2)
|
||||
|
||||
#define BRESINCRPGONSTRUCT(bres) \
|
||||
BRESINCRPGON(bres.d, bres.minor_axis, bres.m, bres.m1, bres.incr1, bres.incr2)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* These are the data structures needed to scan
|
||||
* convert regions. Two different scan conversion
|
||||
* methods are available -- the even-odd method, and
|
||||
* the winding number method.
|
||||
* The even-odd rule states that a point is inside
|
||||
* the polygon if a ray drawn from that point in any
|
||||
* direction will pass through an odd number of
|
||||
* path segments.
|
||||
* By the winding number rule, a point is decided
|
||||
* to be inside the polygon if a ray drawn from that
|
||||
* point in any direction passes through a different
|
||||
* number of clockwise and counter-clockwise path
|
||||
* segments.
|
||||
*
|
||||
* These data structures are adapted somewhat from
|
||||
* the algorithm in (Foley/Van Dam) for scan converting
|
||||
* polygons.
|
||||
* The basic algorithm is to start at the top (smallest y)
|
||||
* of the polygon, stepping down to the bottom of
|
||||
* the polygon by incrementing the y coordinate. We
|
||||
* keep a list of edges which the current scanline crosses,
|
||||
* sorted by x. This list is called the Active Edge Table (AET)
|
||||
* As we change the y-coordinate, we update each entry in
|
||||
* in the active edge table to reflect the edges new xcoord.
|
||||
* This list must be sorted at each scanline in case
|
||||
* two edges intersect.
|
||||
* We also keep a data structure known as the Edge Table (ET),
|
||||
* which keeps track of all the edges which the current
|
||||
* scanline has not yet reached. The ET is basically a
|
||||
* list of ScanLineList structures containing a list of
|
||||
* edges which are entered at a given scanline. There is one
|
||||
* ScanLineList per scanline at which an edge is entered.
|
||||
* When we enter a new edge, we move it from the ET to the AET.
|
||||
*
|
||||
* From the AET, we can implement the even-odd rule as in
|
||||
* (Foley/Van Dam).
|
||||
* The winding number rule is a little trickier. We also
|
||||
* keep the EdgeTableEntries in the AET linked by the
|
||||
* nextWETE (winding EdgeTableEntry) link. This allows
|
||||
* the edges to be linked just as before for updating
|
||||
* purposes, but only uses the edges linked by the nextWETE
|
||||
* link as edges representing spans of the polygon to
|
||||
* drawn (as with the even-odd rule).
|
||||
*/
|
||||
|
||||
/*
|
||||
* for the winding number rule
|
||||
*/
|
||||
#define CLOCKWISE 1
|
||||
#define COUNTERCLOCKWISE -1
|
||||
|
||||
typedef struct _EdgeTableEntry {
|
||||
int ymax; /* ycoord at which we exit this edge. */
|
||||
BRESINFO bres; /* Bresenham info to run the edge */
|
||||
struct _EdgeTableEntry *next; /* next in the list */
|
||||
struct _EdgeTableEntry *back; /* for insertion sort */
|
||||
struct _EdgeTableEntry *nextWETE; /* for winding num rule */
|
||||
int ClockWise; /* flag for winding number rule */
|
||||
} EdgeTableEntry;
|
||||
|
||||
|
||||
typedef struct _ScanLineList{
|
||||
int scanline; /* the scanline represented */
|
||||
EdgeTableEntry *edgelist; /* header node */
|
||||
struct _ScanLineList *next; /* next in the list */
|
||||
} ScanLineList;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int ymax; /* ymax for the polygon */
|
||||
int ymin; /* ymin for the polygon */
|
||||
ScanLineList scanlines; /* header node */
|
||||
} EdgeTable;
|
||||
|
||||
|
||||
/*
|
||||
* Here is a struct to help with storage allocation
|
||||
* so we can allocate a big chunk at a time, and then take
|
||||
* pieces from this heap when we need to.
|
||||
*/
|
||||
#define SLLSPERBLOCK 25
|
||||
|
||||
typedef struct _ScanLineListBlock {
|
||||
ScanLineList SLLs[SLLSPERBLOCK];
|
||||
struct _ScanLineListBlock *next;
|
||||
} ScanLineListBlock;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* a few macros for the inner loops of the fill code where
|
||||
* performance considerations don't allow a procedure call.
|
||||
*
|
||||
* Evaluate the given edge at the given scanline.
|
||||
* If the edge has expired, then we leave it and fix up
|
||||
* the active edge table; otherwise, we increment the
|
||||
* x value to be ready for the next scanline.
|
||||
* The winding number rule is in effect, so we must notify
|
||||
* the caller when the edge has been removed so he
|
||||
* can reorder the Winding Active Edge Table.
|
||||
*/
|
||||
#define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \
|
||||
if (pAET->ymax == y) { /* leaving this edge */ \
|
||||
pPrevAET->next = pAET->next; \
|
||||
pAET = pPrevAET->next; \
|
||||
fixWAET = 1; \
|
||||
if (pAET) \
|
||||
pAET->back = pPrevAET; \
|
||||
} \
|
||||
else { \
|
||||
BRESINCRPGONSTRUCT(pAET->bres); \
|
||||
pPrevAET = pAET; \
|
||||
pAET = pAET->next; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Evaluate the given edge at the given scanline.
|
||||
* If the edge has expired, then we leave it and fix up
|
||||
* the active edge table; otherwise, we increment the
|
||||
* x value to be ready for the next scanline.
|
||||
* The even-odd rule is in effect.
|
||||
*/
|
||||
#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \
|
||||
if (pAET->ymax == y) { /* leaving this edge */ \
|
||||
pPrevAET->next = pAET->next; \
|
||||
pAET = pPrevAET->next; \
|
||||
if (pAET) \
|
||||
pAET->back = pPrevAET; \
|
||||
} \
|
||||
else { \
|
||||
BRESINCRPGONSTRUCT(pAET->bres); \
|
||||
pPrevAET = pAET; \
|
||||
pAET = pAET->next; \
|
||||
} \
|
||||
}
|
616
gdk/linux-fb/gdkpolyreg-generic.c
Normal file
616
gdk/linux-fb/gdkpolyreg-generic.c
Normal file
@ -0,0 +1,616 @@
|
||||
/* $TOG: PolyReg.c /main/15 1998/02/06 17:47:08 kaleb $ */
|
||||
/************************************************************************
|
||||
|
||||
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.
|
||||
|
||||
************************************************************************/
|
||||
/* $XFree86: xc/lib/X11/PolyReg.c,v 1.4 1998/10/03 08:41:21 dawes Exp $ */
|
||||
|
||||
#define LARGE_COORDINATE 1000000
|
||||
#define SMALL_COORDINATE -LARGE_COORDINATE
|
||||
|
||||
#include <gdkregion.h>
|
||||
#include "gdkregion-generic.h"
|
||||
#include "gdkpoly-generic.h"
|
||||
|
||||
/*
|
||||
* InsertEdgeInET
|
||||
*
|
||||
* Insert the given edge into the edge table.
|
||||
* First we must find the correct bucket in the
|
||||
* Edge table, then find the right slot in the
|
||||
* bucket. Finally, we can insert it.
|
||||
*
|
||||
*/
|
||||
static void
|
||||
InsertEdgeInET(ET, ETE, scanline, SLLBlock, iSLLBlock)
|
||||
EdgeTable *ET;
|
||||
EdgeTableEntry *ETE;
|
||||
int scanline;
|
||||
ScanLineListBlock **SLLBlock;
|
||||
int *iSLLBlock;
|
||||
{
|
||||
EdgeTableEntry *start, *prev;
|
||||
ScanLineList *pSLL, *pPrevSLL;
|
||||
ScanLineListBlock *tmpSLLBlock;
|
||||
|
||||
/*
|
||||
* find the right bucket to put the edge into
|
||||
*/
|
||||
pPrevSLL = &ET->scanlines;
|
||||
pSLL = pPrevSLL->next;
|
||||
while (pSLL && (pSLL->scanline < scanline))
|
||||
{
|
||||
pPrevSLL = pSLL;
|
||||
pSLL = pSLL->next;
|
||||
}
|
||||
|
||||
/*
|
||||
* reassign pSLL (pointer to ScanLineList) if necessary
|
||||
*/
|
||||
if ((!pSLL) || (pSLL->scanline > scanline))
|
||||
{
|
||||
if (*iSLLBlock > SLLSPERBLOCK-1)
|
||||
{
|
||||
tmpSLLBlock =
|
||||
(ScanLineListBlock *)g_malloc(sizeof(ScanLineListBlock));
|
||||
(*SLLBlock)->next = tmpSLLBlock;
|
||||
tmpSLLBlock->next = (ScanLineListBlock *)NULL;
|
||||
*SLLBlock = tmpSLLBlock;
|
||||
*iSLLBlock = 0;
|
||||
}
|
||||
pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
|
||||
|
||||
pSLL->next = pPrevSLL->next;
|
||||
pSLL->edgelist = (EdgeTableEntry *)NULL;
|
||||
pPrevSLL->next = pSLL;
|
||||
}
|
||||
pSLL->scanline = scanline;
|
||||
|
||||
/*
|
||||
* now insert the edge in the right bucket
|
||||
*/
|
||||
prev = (EdgeTableEntry *)NULL;
|
||||
start = pSLL->edgelist;
|
||||
while (start && (start->bres.minor_axis < ETE->bres.minor_axis))
|
||||
{
|
||||
prev = start;
|
||||
start = start->next;
|
||||
}
|
||||
ETE->next = start;
|
||||
|
||||
if (prev)
|
||||
prev->next = ETE;
|
||||
else
|
||||
pSLL->edgelist = ETE;
|
||||
}
|
||||
|
||||
/*
|
||||
* CreateEdgeTable
|
||||
*
|
||||
* This routine creates the edge table for
|
||||
* scan converting polygons.
|
||||
* The Edge Table (ET) looks like:
|
||||
*
|
||||
* EdgeTable
|
||||
* --------
|
||||
* | ymax | ScanLineLists
|
||||
* |scanline|-->------------>-------------->...
|
||||
* -------- |scanline| |scanline|
|
||||
* |edgelist| |edgelist|
|
||||
* --------- ---------
|
||||
* | |
|
||||
* | |
|
||||
* V V
|
||||
* list of ETEs list of ETEs
|
||||
*
|
||||
* where ETE is an EdgeTableEntry data structure,
|
||||
* and there is one ScanLineList per scanline at
|
||||
* which an edge is initially entered.
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
CreateETandAET(count, pts, ET, AET, pETEs, pSLLBlock)
|
||||
int count;
|
||||
GdkPoint *pts;
|
||||
EdgeTable *ET;
|
||||
EdgeTableEntry *AET;
|
||||
EdgeTableEntry *pETEs;
|
||||
ScanLineListBlock *pSLLBlock;
|
||||
{
|
||||
GdkPoint *top, *bottom;
|
||||
GdkPoint *PrevPt, *CurrPt;
|
||||
int iSLLBlock = 0;
|
||||
int dy;
|
||||
|
||||
if (count < 2) return;
|
||||
|
||||
/*
|
||||
* initialize the Active Edge Table
|
||||
*/
|
||||
AET->next = (EdgeTableEntry *)NULL;
|
||||
AET->back = (EdgeTableEntry *)NULL;
|
||||
AET->nextWETE = (EdgeTableEntry *)NULL;
|
||||
AET->bres.minor_axis = SMALL_COORDINATE;
|
||||
|
||||
/*
|
||||
* initialize the Edge Table.
|
||||
*/
|
||||
ET->scanlines.next = (ScanLineList *)NULL;
|
||||
ET->ymax = SMALL_COORDINATE;
|
||||
ET->ymin = LARGE_COORDINATE;
|
||||
pSLLBlock->next = (ScanLineListBlock *)NULL;
|
||||
|
||||
PrevPt = &pts[count-1];
|
||||
|
||||
/*
|
||||
* for each vertex in the array of points.
|
||||
* In this loop we are dealing with two vertices at
|
||||
* a time -- these make up one edge of the polygon.
|
||||
*/
|
||||
while (count--)
|
||||
{
|
||||
CurrPt = pts++;
|
||||
|
||||
/*
|
||||
* find out which point is above and which is below.
|
||||
*/
|
||||
if (PrevPt->y > CurrPt->y)
|
||||
{
|
||||
bottom = PrevPt, top = CurrPt;
|
||||
pETEs->ClockWise = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bottom = CurrPt, top = PrevPt;
|
||||
pETEs->ClockWise = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* don't add horizontal edges to the Edge table.
|
||||
*/
|
||||
if (bottom->y != top->y)
|
||||
{
|
||||
pETEs->ymax = bottom->y-1; /* -1 so we don't get last scanline */
|
||||
|
||||
/*
|
||||
* initialize integer edge algorithm
|
||||
*/
|
||||
dy = bottom->y - top->y;
|
||||
BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres);
|
||||
|
||||
InsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock);
|
||||
|
||||
if (PrevPt->y > ET->ymax)
|
||||
ET->ymax = PrevPt->y;
|
||||
if (PrevPt->y < ET->ymin)
|
||||
ET->ymin = PrevPt->y;
|
||||
pETEs++;
|
||||
}
|
||||
|
||||
PrevPt = CurrPt;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* loadAET
|
||||
*
|
||||
* This routine moves EdgeTableEntries from the
|
||||
* EdgeTable into the Active Edge Table,
|
||||
* leaving them sorted by smaller x coordinate.
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
loadAET(AET, ETEs)
|
||||
EdgeTableEntry *AET, *ETEs;
|
||||
{
|
||||
EdgeTableEntry *pPrevAET;
|
||||
EdgeTableEntry *tmp;
|
||||
|
||||
pPrevAET = AET;
|
||||
AET = AET->next;
|
||||
while (ETEs)
|
||||
{
|
||||
while (AET && (AET->bres.minor_axis < ETEs->bres.minor_axis))
|
||||
{
|
||||
pPrevAET = AET;
|
||||
AET = AET->next;
|
||||
}
|
||||
tmp = ETEs->next;
|
||||
ETEs->next = AET;
|
||||
if (AET)
|
||||
AET->back = ETEs;
|
||||
ETEs->back = pPrevAET;
|
||||
pPrevAET->next = ETEs;
|
||||
pPrevAET = ETEs;
|
||||
|
||||
ETEs = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* computeWAET
|
||||
*
|
||||
* This routine links the AET by the
|
||||
* nextWETE (winding EdgeTableEntry) link for
|
||||
* use by the winding number rule. The final
|
||||
* Active Edge Table (AET) might look something
|
||||
* like:
|
||||
*
|
||||
* AET
|
||||
* ---------- --------- ---------
|
||||
* |ymax | |ymax | |ymax |
|
||||
* | ... | |... | |... |
|
||||
* |next |->|next |->|next |->...
|
||||
* |nextWETE| |nextWETE| |nextWETE|
|
||||
* --------- --------- ^--------
|
||||
* | | |
|
||||
* V-------------------> V---> ...
|
||||
*
|
||||
*/
|
||||
static void
|
||||
computeWAET(AET)
|
||||
EdgeTableEntry *AET;
|
||||
{
|
||||
EdgeTableEntry *pWETE;
|
||||
int inside = 1;
|
||||
int isInside = 0;
|
||||
|
||||
AET->nextWETE = (EdgeTableEntry *)NULL;
|
||||
pWETE = AET;
|
||||
AET = AET->next;
|
||||
while (AET)
|
||||
{
|
||||
if (AET->ClockWise)
|
||||
isInside++;
|
||||
else
|
||||
isInside--;
|
||||
|
||||
if ((!inside && !isInside) ||
|
||||
( inside && isInside))
|
||||
{
|
||||
pWETE->nextWETE = AET;
|
||||
pWETE = AET;
|
||||
inside = !inside;
|
||||
}
|
||||
AET = AET->next;
|
||||
}
|
||||
pWETE->nextWETE = (EdgeTableEntry *)NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* InsertionSort
|
||||
*
|
||||
* Just a simple insertion sort using
|
||||
* pointers and back pointers to sort the Active
|
||||
* Edge Table.
|
||||
*
|
||||
*/
|
||||
|
||||
static int
|
||||
InsertionSort(AET)
|
||||
EdgeTableEntry *AET;
|
||||
{
|
||||
EdgeTableEntry *pETEchase;
|
||||
EdgeTableEntry *pETEinsert;
|
||||
EdgeTableEntry *pETEchaseBackTMP;
|
||||
int changed = 0;
|
||||
|
||||
AET = AET->next;
|
||||
while (AET)
|
||||
{
|
||||
pETEinsert = AET;
|
||||
pETEchase = AET;
|
||||
while (pETEchase->back->bres.minor_axis > AET->bres.minor_axis)
|
||||
pETEchase = pETEchase->back;
|
||||
|
||||
AET = AET->next;
|
||||
if (pETEchase != pETEinsert)
|
||||
{
|
||||
pETEchaseBackTMP = pETEchase->back;
|
||||
pETEinsert->back->next = AET;
|
||||
if (AET)
|
||||
AET->back = pETEinsert->back;
|
||||
pETEinsert->next = pETEchase;
|
||||
pETEchase->back->next = pETEinsert;
|
||||
pETEchase->back = pETEinsert;
|
||||
pETEinsert->back = pETEchaseBackTMP;
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
return(changed);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up our act.
|
||||
*/
|
||||
static void
|
||||
FreeStorage(pSLLBlock)
|
||||
ScanLineListBlock *pSLLBlock;
|
||||
{
|
||||
ScanLineListBlock *tmpSLLBlock;
|
||||
|
||||
while (pSLLBlock)
|
||||
{
|
||||
tmpSLLBlock = pSLLBlock->next;
|
||||
g_free (pSLLBlock);
|
||||
pSLLBlock = tmpSLLBlock;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create an array of rectangles from a list of points.
|
||||
* If indeed these things (POINTS, RECTS) are the same,
|
||||
* then this proc is still needed, because it allocates
|
||||
* storage for the array, which was allocated on the
|
||||
* stack by the calling procedure.
|
||||
*
|
||||
*/
|
||||
static int PtsToRegion(numFullPtBlocks, iCurPtBlock, FirstPtBlock, reg)
|
||||
int numFullPtBlocks, iCurPtBlock;
|
||||
POINTBLOCK *FirstPtBlock;
|
||||
GdkRegion *reg;
|
||||
{
|
||||
GdkRegionBox *rects;
|
||||
GdkPoint *pts;
|
||||
POINTBLOCK *CurPtBlock;
|
||||
int i;
|
||||
GdkRegionBox *extents;
|
||||
int numRects;
|
||||
|
||||
extents = ®->extents;
|
||||
|
||||
numRects = ((numFullPtBlocks * NUMPTSTOBUFFER) + iCurPtBlock) >> 1;
|
||||
|
||||
reg->rects = g_renew (GdkRegionBox, reg->rects, numRects);
|
||||
|
||||
reg->size = numRects;
|
||||
CurPtBlock = FirstPtBlock;
|
||||
rects = reg->rects - 1;
|
||||
numRects = 0;
|
||||
extents->x1 = G_MAXSHORT, extents->x2 = G_MINSHORT;
|
||||
|
||||
for ( ; numFullPtBlocks >= 0; numFullPtBlocks--) {
|
||||
/* the loop uses 2 points per iteration */
|
||||
i = NUMPTSTOBUFFER >> 1;
|
||||
if (!numFullPtBlocks)
|
||||
i = iCurPtBlock >> 1;
|
||||
for (pts = CurPtBlock->pts; i--; pts += 2) {
|
||||
if (pts->x == pts[1].x)
|
||||
continue;
|
||||
if (numRects && pts->x == rects->x1 && pts->y == rects->y2 &&
|
||||
pts[1].x == rects->x2 &&
|
||||
(numRects == 1 || rects[-1].y1 != rects->y1) &&
|
||||
(i && pts[2].y > pts[1].y)) {
|
||||
rects->y2 = pts[1].y + 1;
|
||||
continue;
|
||||
}
|
||||
numRects++;
|
||||
rects++;
|
||||
rects->x1 = pts->x; rects->y1 = pts->y;
|
||||
rects->x2 = pts[1].x; rects->y2 = pts[1].y + 1;
|
||||
if (rects->x1 < extents->x1)
|
||||
extents->x1 = rects->x1;
|
||||
if (rects->x2 > extents->x2)
|
||||
extents->x2 = rects->x2;
|
||||
}
|
||||
CurPtBlock = CurPtBlock->next;
|
||||
}
|
||||
|
||||
if (numRects) {
|
||||
extents->y1 = reg->rects->y1;
|
||||
extents->y2 = rects->y2;
|
||||
} else {
|
||||
extents->x1 = 0;
|
||||
extents->y1 = 0;
|
||||
extents->x2 = 0;
|
||||
extents->y2 = 0;
|
||||
}
|
||||
reg->numRects = numRects;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* polytoregion
|
||||
*
|
||||
* Scan converts a polygon by returning a run-length
|
||||
* encoding of the resultant bitmap -- the run-length
|
||||
* encoding is in the form of an array of rectangles.
|
||||
*/
|
||||
GdkRegion *
|
||||
gdk_region_polygon(GdkPoint *Pts, gint Count, GdkFillRule rule)
|
||||
{
|
||||
GdkRegion *region;
|
||||
EdgeTableEntry *pAET; /* Active Edge Table */
|
||||
int y; /* current scanline */
|
||||
int iPts = 0; /* number of pts in buffer */
|
||||
EdgeTableEntry *pWETE; /* Winding Edge Table Entry*/
|
||||
ScanLineList *pSLL; /* current scanLineList */
|
||||
GdkPoint *pts; /* output buffer */
|
||||
EdgeTableEntry *pPrevAET; /* ptr to previous AET */
|
||||
EdgeTable ET; /* header node for ET */
|
||||
EdgeTableEntry AET; /* header node for AET */
|
||||
EdgeTableEntry *pETEs; /* EdgeTableEntries pool */
|
||||
ScanLineListBlock SLLBlock; /* header for scanlinelist */
|
||||
int fixWAET = FALSE;
|
||||
POINTBLOCK FirstPtBlock, *curPtBlock; /* PtBlock buffers */
|
||||
POINTBLOCK *tmpPtBlock;
|
||||
int numFullPtBlocks = 0;
|
||||
|
||||
region = gdk_region_new ();
|
||||
|
||||
/* special case a rectangle */
|
||||
pts = Pts;
|
||||
if (((Count == 4) ||
|
||||
((Count == 5) && (pts[4].x == pts[0].x) && (pts[4].y == pts[0].y))) &&
|
||||
(((pts[0].y == pts[1].y) &&
|
||||
(pts[1].x == pts[2].x) &&
|
||||
(pts[2].y == pts[3].y) &&
|
||||
(pts[3].x == pts[0].x)) ||
|
||||
((pts[0].x == pts[1].x) &&
|
||||
(pts[1].y == pts[2].y) &&
|
||||
(pts[2].x == pts[3].x) &&
|
||||
(pts[3].y == pts[0].y)))) {
|
||||
region->extents.x1 = MIN(pts[0].x, pts[2].x);
|
||||
region->extents.y1 = MIN(pts[0].y, pts[2].y);
|
||||
region->extents.x2 = MAX(pts[0].x, pts[2].x);
|
||||
region->extents.y2 = MAX(pts[0].y, pts[2].y);
|
||||
if ((region->extents.x1 != region->extents.x2) &&
|
||||
(region->extents.y1 != region->extents.y2)) {
|
||||
region->numRects = 1;
|
||||
*(region->rects) = region->extents;
|
||||
}
|
||||
return(region);
|
||||
}
|
||||
|
||||
pETEs = g_new (EdgeTableEntry, Count);
|
||||
|
||||
pts = FirstPtBlock.pts;
|
||||
CreateETandAET(Count, Pts, &ET, &AET, pETEs, &SLLBlock);
|
||||
pSLL = ET.scanlines.next;
|
||||
curPtBlock = &FirstPtBlock;
|
||||
|
||||
if (rule == GDK_EVEN_ODD_RULE) {
|
||||
/*
|
||||
* for each scanline
|
||||
*/
|
||||
for (y = ET.ymin; y < ET.ymax; y++) {
|
||||
/*
|
||||
* Add a new edge to the active edge table when we
|
||||
* get to the next edge.
|
||||
*/
|
||||
if (pSLL != NULL && y == pSLL->scanline) {
|
||||
loadAET(&AET, pSLL->edgelist);
|
||||
pSLL = pSLL->next;
|
||||
}
|
||||
pPrevAET = &AET;
|
||||
pAET = AET.next;
|
||||
|
||||
/*
|
||||
* for each active edge
|
||||
*/
|
||||
while (pAET) {
|
||||
pts->x = pAET->bres.minor_axis, pts->y = y;
|
||||
pts++, iPts++;
|
||||
|
||||
/*
|
||||
* send out the buffer
|
||||
*/
|
||||
if (iPts == NUMPTSTOBUFFER) {
|
||||
tmpPtBlock = (POINTBLOCK *)g_malloc(sizeof(POINTBLOCK));
|
||||
curPtBlock->next = tmpPtBlock;
|
||||
curPtBlock = tmpPtBlock;
|
||||
pts = curPtBlock->pts;
|
||||
numFullPtBlocks++;
|
||||
iPts = 0;
|
||||
}
|
||||
EVALUATEEDGEEVENODD(pAET, pPrevAET, y);
|
||||
}
|
||||
(void) InsertionSort(&AET);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* for each scanline
|
||||
*/
|
||||
for (y = ET.ymin; y < ET.ymax; y++) {
|
||||
/*
|
||||
* Add a new edge to the active edge table when we
|
||||
* get to the next edge.
|
||||
*/
|
||||
if (pSLL != NULL && y == pSLL->scanline) {
|
||||
loadAET(&AET, pSLL->edgelist);
|
||||
computeWAET(&AET);
|
||||
pSLL = pSLL->next;
|
||||
}
|
||||
pPrevAET = &AET;
|
||||
pAET = AET.next;
|
||||
pWETE = pAET;
|
||||
|
||||
/*
|
||||
* for each active edge
|
||||
*/
|
||||
while (pAET) {
|
||||
/*
|
||||
* add to the buffer only those edges that
|
||||
* are in the Winding active edge table.
|
||||
*/
|
||||
if (pWETE == pAET) {
|
||||
pts->x = pAET->bres.minor_axis, pts->y = y;
|
||||
pts++, iPts++;
|
||||
|
||||
/*
|
||||
* send out the buffer
|
||||
*/
|
||||
if (iPts == NUMPTSTOBUFFER) {
|
||||
tmpPtBlock = (POINTBLOCK *)g_malloc(sizeof(POINTBLOCK));
|
||||
curPtBlock->next = tmpPtBlock;
|
||||
curPtBlock = tmpPtBlock;
|
||||
pts = curPtBlock->pts;
|
||||
numFullPtBlocks++; iPts = 0;
|
||||
}
|
||||
pWETE = pWETE->nextWETE;
|
||||
}
|
||||
EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET);
|
||||
}
|
||||
|
||||
/*
|
||||
* recompute the winding active edge table if
|
||||
* we just resorted or have exited an edge.
|
||||
*/
|
||||
if (InsertionSort(&AET) || fixWAET) {
|
||||
computeWAET(&AET);
|
||||
fixWAET = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
FreeStorage(SLLBlock.next);
|
||||
(void) PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
|
||||
for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
|
||||
tmpPtBlock = curPtBlock->next;
|
||||
g_free (curPtBlock);
|
||||
curPtBlock = tmpPtBlock;
|
||||
}
|
||||
g_free (pETEs);
|
||||
return(region);
|
||||
}
|
194
gdk/linux-fb/gdkprivate-fb.h
Normal file
194
gdk/linux-fb/gdkprivate-fb.h
Normal file
@ -0,0 +1,194 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Private uninstalled header defining things local to X windowing code
|
||||
*/
|
||||
|
||||
#ifndef __GDK_PRIVATE_FB_H__
|
||||
#define __GDK_PRIVATE_FB_H__
|
||||
|
||||
#include <gdk/gdkprivate.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include "gdkfb.h"
|
||||
#include "gdkregion-generic.h"
|
||||
#include <linux/fb.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define GDK_DRAWABLE_FBDATA(win) ((GdkDrawableFBData *)(((GdkDrawablePrivate*)(win))->klass_data))
|
||||
#define GDK_PIXMAP_FBDATA(win) ((GdkPixmapFBData *)(((GdkDrawablePrivate*)(win))->klass_data))
|
||||
#define GDK_WINDOW_FBDATA(win) ((GdkWindowFBData *)(((GdkDrawablePrivate*)(win))->klass_data))
|
||||
#define GDK_FONT_FB(f) ((GdkFontPrivateFB *)(f))
|
||||
#define GDK_CURSOR_FB(c) ((GdkCursorPrivateFB *)(c))
|
||||
|
||||
typedef struct _GdkDrawableFBData GdkDrawableFBData;
|
||||
typedef struct _GdkWindowFBData GdkWindowFBData;
|
||||
|
||||
struct _GdkDrawableFBData
|
||||
{
|
||||
guchar *mem;
|
||||
|
||||
gint abs_x, abs_y, lim_x, lim_y, llim_x, llim_y; /* computed values */
|
||||
|
||||
guint rowstride;
|
||||
};
|
||||
|
||||
struct _GdkPixmapFBData
|
||||
{
|
||||
GdkDrawableFBData drawable_data;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
gulong length;
|
||||
GdkAtom type;
|
||||
gint format;
|
||||
guchar data[1];
|
||||
} GdkWindowProperty;
|
||||
|
||||
struct _GdkWindowFBData
|
||||
{
|
||||
GdkDrawableFBData drawable_data;
|
||||
GdkCursor *cursor;
|
||||
GHashTable *properties;
|
||||
|
||||
GdkEventMask event_mask;
|
||||
gint level;
|
||||
gboolean realized : 1;
|
||||
};
|
||||
|
||||
struct _GdkFBDisplay
|
||||
{
|
||||
int fd;
|
||||
guchar *fbmem;
|
||||
gpointer active_cmap;
|
||||
gulong mem_len;
|
||||
struct fb_fix_screeninfo sinfo;
|
||||
struct fb_var_screeninfo modeinfo;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GdkVisual base;
|
||||
} GdkVisualPrivateFB;
|
||||
|
||||
typedef struct {
|
||||
GdkColormapPrivate base;
|
||||
|
||||
GHashTable *hash;
|
||||
GdkColorInfo *info;
|
||||
guint sync_tag;
|
||||
} GdkColormapPrivateFB;
|
||||
|
||||
typedef struct {
|
||||
GdkCursor base;
|
||||
GdkPixmap *cursor, *mask;
|
||||
} GdkCursorPrivateFB;
|
||||
|
||||
typedef struct {
|
||||
GdkFontPrivate base;
|
||||
|
||||
int t1_font_id;
|
||||
double size;
|
||||
GSList *names;
|
||||
} GdkFontPrivateFB;
|
||||
|
||||
typedef struct {
|
||||
GdkImagePrivate base;
|
||||
} GdkImagePrivateFB;
|
||||
|
||||
#define GDK_GC_FBDATA(x) ((GdkGCFBData *)((GdkGCPrivate *)x)->klass_data)
|
||||
typedef struct {
|
||||
GdkRegion *clip_region;
|
||||
gchar *dash_list;
|
||||
GdkGCValuesMask values_mask;
|
||||
GdkGCValues values;
|
||||
gint dash_offset;
|
||||
gushort dash_list_len;
|
||||
guchar depth, alu;
|
||||
} GdkGCFBData;
|
||||
|
||||
GdkGC * _gdk_fb_gc_new (GdkDrawable *drawable,
|
||||
GdkGCValues *values,
|
||||
GdkGCValuesMask values_mask);
|
||||
|
||||
/* Routines from gdkgeometry-fb.c */
|
||||
|
||||
void _gdk_window_init_position (GdkWindow *window);
|
||||
void _gdk_window_move_resize_child (GdkWindow *window,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height);
|
||||
void _gdk_window_process_expose (GdkWindow *window,
|
||||
gulong serial,
|
||||
GdkRectangle *area);
|
||||
GdkGC *_gdk_fb_gc_new(GdkDrawable *drawable, GdkGCValues *values, GdkGCValuesMask values_mask);
|
||||
|
||||
void gdk_fb_drawable_clear(GdkDrawable *drawable);
|
||||
void gdk_fb_draw_drawable (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
GdkPixmap *src,
|
||||
gint xsrc,
|
||||
gint ysrc,
|
||||
gint xdest,
|
||||
gint ydest,
|
||||
gint width,
|
||||
gint height);
|
||||
void gdk_fb_draw_drawable_2 (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
GdkPixmap *src,
|
||||
gint xsrc,
|
||||
gint ysrc,
|
||||
gint xdest,
|
||||
gint ydest,
|
||||
gint width,
|
||||
gint height,
|
||||
gboolean draw_bg,
|
||||
gboolean do_clipping);
|
||||
void gdk_fb_draw_rectangle (GdkDrawable *drawable,
|
||||
GdkGC *gc,
|
||||
gint filled,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height);
|
||||
void gdk_fb_fill_spans(GdkDrawable *drawable, GdkGC *gc, GdkRectangle *rects, int nrects);
|
||||
|
||||
extern GdkWindow *_gdk_fb_pointer_grab_window, *_gdk_fb_keyboard_grab_window, *_gdk_fb_pointer_grab_confine;
|
||||
extern GdkEventMask _gdk_fb_pointer_grab_events, _gdk_fb_keyboard_grab_events;
|
||||
extern GdkCursor *_gdk_fb_pointer_grab_cursor;
|
||||
extern GdkFBDisplay *gdk_display;
|
||||
extern GdkDrawableClass _gdk_fb_drawable_class;
|
||||
extern FILE *debug_out;
|
||||
GdkEvent *gdk_event_make(GdkWindow *window, GdkEventType type, gboolean append_to_queue);
|
||||
|
||||
void gdk_fb_get_cursor_rect(GdkRectangle *rect);
|
||||
void gdk_fb_cursor_unhide(void);
|
||||
void gdk_fb_cursor_hide(void);
|
||||
void gdk_fb_redraw_all(void);
|
||||
|
||||
void gdk_input_ps2_get_mouseinfo(gint *x, gint *y, GdkModifierType *mask);
|
||||
|
||||
#endif /* __GDK_PRIVATE_FB_H__ */
|
204
gdk/linux-fb/gdkproperty-fb.c
Normal file
204
gdk/linux-fb/gdkproperty-fb.c
Normal file
@ -0,0 +1,204 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "gdkfb.h"
|
||||
#include "gdkproperty.h"
|
||||
#include "gdkprivate.h"
|
||||
#include "gdkprivate-fb.h"
|
||||
|
||||
GdkAtom
|
||||
gdk_atom_intern (const gchar *atom_name,
|
||||
gboolean only_if_exists)
|
||||
{
|
||||
g_return_val_if_fail (atom_name != NULL, GDK_NONE);
|
||||
|
||||
return g_quark_from_string(atom_name);
|
||||
}
|
||||
|
||||
gchar*
|
||||
gdk_atom_name (GdkAtom atom)
|
||||
{
|
||||
return g_quark_to_string(atom);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_property_delete_2 (GdkWindow *window,
|
||||
GdkAtom property,
|
||||
GdkWindowProperty *prop)
|
||||
{
|
||||
GdkWindowFBData *fbd = GDK_WINDOW_FBDATA(window);
|
||||
GdkEvent *event;
|
||||
|
||||
g_hash_table_remove(fbd->properties, GUINT_TO_POINTER(property));
|
||||
g_free(prop);
|
||||
|
||||
event = gdk_event_make(window, GDK_PROPERTY_NOTIFY, TRUE);
|
||||
if(event)
|
||||
{
|
||||
event->property.atom = property;
|
||||
event->property.state = GDK_PROPERTY_DELETE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gdk_property_delete (GdkWindow *window,
|
||||
GdkAtom property)
|
||||
{
|
||||
GdkWindowFBData *fbd = GDK_WINDOW_FBDATA(window);
|
||||
GdkWindowProperty *prop;
|
||||
|
||||
g_return_if_fail (window != NULL);
|
||||
g_return_if_fail (GDK_IS_WINDOW (window));
|
||||
|
||||
if(!fbd->properties)
|
||||
return;
|
||||
|
||||
prop = g_hash_table_lookup(fbd->properties, GUINT_TO_POINTER(property));
|
||||
if(!prop)
|
||||
return;
|
||||
|
||||
gdk_property_delete_2(window, property, prop);
|
||||
}
|
||||
|
||||
gint
|
||||
gdk_property_get (GdkWindow *window,
|
||||
GdkAtom property,
|
||||
GdkAtom type,
|
||||
gulong offset,
|
||||
gulong length,
|
||||
gint pdelete,
|
||||
GdkAtom *actual_property_type,
|
||||
gint *actual_format_type,
|
||||
gint *actual_length,
|
||||
guchar **data)
|
||||
{
|
||||
GdkWindowFBData *fbd = GDK_WINDOW_FBDATA(window);
|
||||
GdkWindowProperty *prop;
|
||||
int nbytes;
|
||||
|
||||
g_return_val_if_fail (window != NULL, FALSE);
|
||||
g_return_val_if_fail (data != NULL, FALSE);
|
||||
g_return_val_if_fail (actual_length != NULL, FALSE);
|
||||
g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
|
||||
|
||||
if(!fbd->properties)
|
||||
return FALSE;
|
||||
|
||||
prop = g_hash_table_lookup(fbd->properties, GUINT_TO_POINTER(property));
|
||||
if(!prop)
|
||||
return FALSE;
|
||||
|
||||
nbytes = (offset + length * (prop->format >> 3)) - prop->length;
|
||||
nbytes = MAX(nbytes, 0);
|
||||
if(nbytes > 0)
|
||||
{
|
||||
*data = g_malloc(nbytes+1);
|
||||
memcpy(data, prop->data + offset, nbytes);
|
||||
(*data)[nbytes] = 0;
|
||||
}
|
||||
else
|
||||
*data = NULL;
|
||||
*actual_length = nbytes / (prop->format >> 3);
|
||||
*actual_property_type = prop->type;
|
||||
*actual_format_type = prop->format;
|
||||
|
||||
if(pdelete)
|
||||
gdk_property_delete_2(window, property, prop);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_property_change (GdkWindow *window,
|
||||
GdkAtom property,
|
||||
GdkAtom type,
|
||||
gint format,
|
||||
GdkPropMode mode,
|
||||
const guchar *data,
|
||||
gint nelements)
|
||||
{
|
||||
GdkWindowFBData *fbd = GDK_WINDOW_FBDATA(window);
|
||||
GdkWindowProperty *prop, *new_prop;
|
||||
int new_size;
|
||||
GdkEvent *event;
|
||||
|
||||
g_return_if_fail (window != NULL);
|
||||
g_return_if_fail (GDK_IS_WINDOW (window));
|
||||
|
||||
if(!fbd->properties)
|
||||
fbd->properties = g_hash_table_new(NULL, NULL);
|
||||
|
||||
prop = g_hash_table_lookup(fbd->properties, GUINT_TO_POINTER(property));
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case GDK_PROP_MODE_REPLACE:
|
||||
new_size = nelements * (format >> 3);
|
||||
break;
|
||||
case GDK_PROP_MODE_PREPEND:
|
||||
case GDK_PROP_MODE_APPEND:
|
||||
new_size = nelements * (format >> 3);
|
||||
if(prop)
|
||||
new_size += prop->length;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
new_prop = g_malloc(G_STRUCT_OFFSET(GdkWindowProperty, data) + new_size);
|
||||
new_prop->length = new_size;
|
||||
new_prop->type = type;
|
||||
new_prop->format = format;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case GDK_PROP_MODE_REPLACE:
|
||||
memcpy(new_prop->data, data, new_size);
|
||||
break;
|
||||
case GDK_PROP_MODE_APPEND:
|
||||
if(prop)
|
||||
memcpy(new_prop->data, prop->data, prop->length);
|
||||
memcpy(new_prop->data + prop->length, data, (nelements * (format >> 3)));
|
||||
break;
|
||||
case GDK_PROP_MODE_PREPEND:
|
||||
memcpy(new_prop->data, data, (nelements * (format >> 3)));
|
||||
if(prop)
|
||||
memcpy(new_prop->data + (nelements * (format >> 3)), prop->data, prop->length);
|
||||
break;
|
||||
}
|
||||
|
||||
g_hash_table_insert(fbd->properties, GUINT_TO_POINTER(property), new_prop);
|
||||
g_free(prop);
|
||||
|
||||
event = gdk_event_make(window, GDK_PROPERTY_NOTIFY, TRUE);
|
||||
if(event)
|
||||
{
|
||||
event->property.atom = property;
|
||||
event->property.state = GDK_PROPERTY_NEW_VALUE;
|
||||
}
|
||||
}
|
1505
gdk/linux-fb/gdkregion-generic.c
Normal file
1505
gdk/linux-fb/gdkregion-generic.c
Normal file
File diff suppressed because it is too large
Load Diff
162
gdk/linux-fb/gdkregion-generic.h
Normal file
162
gdk/linux-fb/gdkregion-generic.h
Normal file
@ -0,0 +1,162 @@
|
||||
/* $TOG: region.h /main/9 1998/02/06 17:50:30 kaleb $ */
|
||||
/************************************************************************
|
||||
|
||||
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.
|
||||
|
||||
************************************************************************/
|
||||
|
||||
#ifndef __GDK_REGION_GENERIC_H__
|
||||
#define __GDK_REGION_GENERIC_H__
|
||||
|
||||
typedef GdkSegment GdkRegionBox;
|
||||
|
||||
/*
|
||||
* clip region
|
||||
*/
|
||||
|
||||
struct _GdkRegion
|
||||
{
|
||||
long size;
|
||||
long numRects;
|
||||
GdkRegionBox *rects;
|
||||
GdkRegionBox extents;
|
||||
};
|
||||
|
||||
/* 1 if two BOXs overlap.
|
||||
* 0 if two BOXs do not overlap.
|
||||
* Remember, x2 and y2 are not in the region
|
||||
*/
|
||||
#define EXTENTCHECK(r1, r2) \
|
||||
((r1)->x2 > (r2)->x1 && \
|
||||
(r1)->x1 < (r2)->x2 && \
|
||||
(r1)->y2 > (r2)->y1 && \
|
||||
(r1)->y1 < (r2)->y2)
|
||||
|
||||
/*
|
||||
* update region extents
|
||||
*/
|
||||
#define EXTENTS(r,idRect){\
|
||||
if((r)->x1 < (idRect)->extents.x1)\
|
||||
(idRect)->extents.x1 = (r)->x1;\
|
||||
if((r)->y1 < (idRect)->extents.y1)\
|
||||
(idRect)->extents.y1 = (r)->y1;\
|
||||
if((r)->x2 > (idRect)->extents.x2)\
|
||||
(idRect)->extents.x2 = (r)->x2;\
|
||||
if((r)->y2 > (idRect)->extents.y2)\
|
||||
(idRect)->extents.y2 = (r)->y2;\
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if there is enough memory in the present region.
|
||||
*/
|
||||
#define MEMCHECK(reg, rect, firstrect){ \
|
||||
if ((reg)->numRects >= ((reg)->size - 1)) { \
|
||||
(firstrect) = g_renew (GdkRegionBox, (firstrect), 2 * (reg)->size); \
|
||||
(reg)->size *= 2; \
|
||||
(rect) = &(firstrect)[(reg)->numRects]; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* this routine checks to see if the previous rectangle is the same
|
||||
* or subsumes the new rectangle to add.
|
||||
*/
|
||||
|
||||
#define CHECK_PREVIOUS(Reg, R, Rx1, Ry1, Rx2, Ry2)\
|
||||
(!(((Reg)->numRects > 0)&&\
|
||||
((R-1)->y1 == (Ry1)) &&\
|
||||
((R-1)->y2 == (Ry2)) &&\
|
||||
((R-1)->x1 <= (Rx1)) &&\
|
||||
((R-1)->x2 >= (Rx2))))
|
||||
|
||||
/* add a rectangle to the given Region */
|
||||
#define ADDRECT(reg, r, rx1, ry1, rx2, ry2){\
|
||||
if (((rx1) < (rx2)) && ((ry1) < (ry2)) &&\
|
||||
CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\
|
||||
(r)->x1 = (rx1);\
|
||||
(r)->y1 = (ry1);\
|
||||
(r)->x2 = (rx2);\
|
||||
(r)->y2 = (ry2);\
|
||||
EXTENTS((r), (reg));\
|
||||
(reg)->numRects++;\
|
||||
(r)++;\
|
||||
}\
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* add a rectangle to the given Region */
|
||||
#define ADDRECTNOX(reg, r, rx1, ry1, rx2, ry2){\
|
||||
if ((rx1 < rx2) && (ry1 < ry2) &&\
|
||||
CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\
|
||||
(r)->x1 = (rx1);\
|
||||
(r)->y1 = (ry1);\
|
||||
(r)->x2 = (rx2);\
|
||||
(r)->y2 = (ry2);\
|
||||
(reg)->numRects++;\
|
||||
(r)++;\
|
||||
}\
|
||||
}
|
||||
|
||||
#define EMPTY_REGION(pReg) pReg->numRects = 0
|
||||
|
||||
#define REGION_NOT_EMPTY(pReg) pReg->numRects
|
||||
|
||||
#define INBOX(r, x, y) \
|
||||
( ( ((r).x2 > x)) && \
|
||||
( ((r).x1 <= x)) && \
|
||||
( ((r).y2 > y)) && \
|
||||
( ((r).y1 <= y)) )
|
||||
|
||||
/*
|
||||
* number of points to buffer before sending them off
|
||||
* to scanlines() : Must be an even number
|
||||
*/
|
||||
#define NUMPTSTOBUFFER 200
|
||||
|
||||
/*
|
||||
* used to allocate buffers for points and link
|
||||
* the buffers together
|
||||
*/
|
||||
typedef struct _POINTBLOCK {
|
||||
GdkPoint pts[NUMPTSTOBUFFER];
|
||||
struct _POINTBLOCK *next;
|
||||
} POINTBLOCK;
|
||||
|
||||
#endif /* __GDK_REGION_GENERIC_H__ */
|
104
gdk/linux-fb/gdkselection-fb.c
Normal file
104
gdk/linux-fb/gdkselection-fb.c
Normal file
@ -0,0 +1,104 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "gdkproperty.h"
|
||||
#include "gdkselection.h"
|
||||
#include "gdkprivate.h"
|
||||
#include "gdkprivate-fb.h"
|
||||
|
||||
|
||||
gint
|
||||
gdk_selection_owner_set (GdkWindow *owner,
|
||||
GdkAtom selection,
|
||||
guint32 time,
|
||||
gint send_event)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GdkWindow*
|
||||
gdk_selection_owner_get (GdkAtom selection)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_selection_convert (GdkWindow *requestor,
|
||||
GdkAtom selection,
|
||||
GdkAtom target,
|
||||
guint32 time)
|
||||
{
|
||||
}
|
||||
|
||||
gint
|
||||
gdk_selection_property_get (GdkWindow *requestor,
|
||||
guchar **data,
|
||||
GdkAtom *ret_type,
|
||||
gint *ret_format)
|
||||
{
|
||||
g_return_val_if_fail (requestor != NULL, 0);
|
||||
g_return_val_if_fail (GDK_IS_WINDOW (requestor), 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gdk_selection_send_notify (guint32 requestor,
|
||||
GdkAtom selection,
|
||||
GdkAtom target,
|
||||
GdkAtom property,
|
||||
guint32 time)
|
||||
{
|
||||
}
|
||||
|
||||
gint
|
||||
gdk_text_property_to_text_list (GdkAtom encoding, gint format,
|
||||
const guchar *text, gint length,
|
||||
gchar ***list)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_free_text_list (gchar **list)
|
||||
{
|
||||
g_return_if_fail (list != NULL);
|
||||
}
|
||||
|
||||
gint
|
||||
gdk_string_to_compound_text (const gchar *str,
|
||||
GdkAtom *encoding, gint *format,
|
||||
guchar **ctext, gint *length)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gdk_free_compound_text (guchar *ctext)
|
||||
{
|
||||
}
|
180
gdk/linux-fb/gdkvisual-fb.c
Normal file
180
gdk/linux-fb/gdkvisual-fb.c
Normal file
@ -0,0 +1,180 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include "gdkvisual.h"
|
||||
#include "gdkprivate-fb.h"
|
||||
#include "gdkinternals.h"
|
||||
#include <endian.h>
|
||||
|
||||
static GdkVisual *system_visual = NULL;
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
|
||||
#if 0
|
||||
static const gchar* visual_names[] =
|
||||
{
|
||||
"static gray",
|
||||
"grayscale",
|
||||
"static color",
|
||||
"pseudo color",
|
||||
"true color",
|
||||
"direct color",
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* G_ENABLE_DEBUG */
|
||||
|
||||
void
|
||||
gdk_visual_init (void)
|
||||
{
|
||||
system_visual = g_new0(GdkVisual, 1);
|
||||
|
||||
system_visual->depth = system_visual->bits_per_rgb = gdk_display->modeinfo.bits_per_pixel;
|
||||
system_visual->byte_order = GDK_LSB_FIRST;
|
||||
system_visual->colormap_size = 0;
|
||||
|
||||
switch(gdk_display->sinfo.visual)
|
||||
{
|
||||
case FB_VISUAL_PSEUDOCOLOR:
|
||||
system_visual->colormap_size = 1 << gdk_display->modeinfo.bits_per_pixel;
|
||||
system_visual->type = GDK_VISUAL_PSEUDO_COLOR;
|
||||
break;
|
||||
case FB_VISUAL_DIRECTCOLOR:
|
||||
system_visual->colormap_size = 1 << gdk_display->modeinfo.bits_per_pixel;
|
||||
system_visual->type = GDK_VISUAL_DIRECT_COLOR;
|
||||
case FB_VISUAL_TRUECOLOR:
|
||||
if(gdk_display->sinfo.visual == GDK_VISUAL_TRUE_COLOR)
|
||||
system_visual->type = GDK_VISUAL_TRUE_COLOR;
|
||||
|
||||
system_visual->red_prec = MIN(system_visual->depth / 3, 8);
|
||||
system_visual->red_shift = 0;
|
||||
system_visual->red_mask = ((1 << (system_visual->red_prec + 1)) - 1) << system_visual->red_shift;
|
||||
|
||||
system_visual->green_shift = system_visual->red_prec;
|
||||
system_visual->green_prec = MIN(system_visual->depth / 3, 8);
|
||||
system_visual->green_mask = ((1 << (system_visual->green_prec + 1)) - 1) << system_visual->green_shift;
|
||||
|
||||
system_visual->blue_shift = system_visual->green_prec + system_visual->green_shift;
|
||||
system_visual->blue_prec = MIN(system_visual->depth / 3, 8);
|
||||
system_visual->blue_mask = ((1 << (system_visual->blue_prec + 1)) - 1) << system_visual->blue_shift;
|
||||
break;
|
||||
case FB_VISUAL_STATIC_PSEUDOCOLOR:
|
||||
system_visual->type = GDK_VISUAL_STATIC_COLOR;
|
||||
system_visual->colormap_size = 1 << gdk_display->modeinfo.bits_per_pixel;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GdkVisual*
|
||||
gdk_visual_ref (GdkVisual *visual)
|
||||
{
|
||||
return visual;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_visual_unref (GdkVisual *visual)
|
||||
{
|
||||
}
|
||||
|
||||
gint
|
||||
gdk_visual_get_best_depth (void)
|
||||
{
|
||||
return system_visual->depth;
|
||||
}
|
||||
|
||||
GdkVisualType
|
||||
gdk_visual_get_best_type (void)
|
||||
{
|
||||
return system_visual->type;
|
||||
}
|
||||
|
||||
GdkVisual*
|
||||
gdk_visual_get_system (void)
|
||||
{
|
||||
return system_visual;
|
||||
}
|
||||
|
||||
GdkVisual*
|
||||
gdk_visual_get_best (void)
|
||||
{
|
||||
return system_visual;
|
||||
}
|
||||
|
||||
GdkVisual*
|
||||
gdk_visual_get_best_with_depth (gint depth)
|
||||
{
|
||||
if(system_visual->depth != depth)
|
||||
return NULL;
|
||||
|
||||
return system_visual;
|
||||
}
|
||||
|
||||
GdkVisual*
|
||||
gdk_visual_get_best_with_type (GdkVisualType visual_type)
|
||||
{
|
||||
if(system_visual->type != visual_type)
|
||||
return NULL;
|
||||
|
||||
return system_visual;
|
||||
}
|
||||
|
||||
GdkVisual*
|
||||
gdk_visual_get_best_with_both (gint depth,
|
||||
GdkVisualType visual_type)
|
||||
{
|
||||
if(system_visual->depth != depth)
|
||||
return NULL;
|
||||
|
||||
if(system_visual->type != visual_type)
|
||||
return NULL;
|
||||
|
||||
return system_visual;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_query_depths (gint **depths,
|
||||
gint *count)
|
||||
{
|
||||
*count = 1;
|
||||
*depths = &system_visual->depth;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_query_visual_types (GdkVisualType **visual_types,
|
||||
gint *count)
|
||||
{
|
||||
*count = 1;
|
||||
*visual_types = &system_visual->type;
|
||||
}
|
||||
|
||||
GList*
|
||||
gdk_list_visuals (void)
|
||||
{
|
||||
return g_list_append(NULL, gdk_visual_get_system());
|
||||
}
|
1372
gdk/linux-fb/gdkwindow-fb.c
Normal file
1372
gdk/linux-fb/gdkwindow-fb.c
Normal file
File diff suppressed because it is too large
Load Diff
21
gdk/linux-fb/mi.h
Normal file
21
gdk/linux-fb/mi.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef MI_H
|
||||
#define MI_H 1
|
||||
|
||||
#include "mitypes.h"
|
||||
#include "mistruct.h"
|
||||
#include "mifpoly.h"
|
||||
#include "mifillarc.h"
|
||||
#include "mipoly.h"
|
||||
|
||||
void miPolyArc(GdkDrawable *pDraw, GdkGC *pGC, int narcs, miArc *parcs);
|
||||
void miPolyFillArc(GdkDrawable *pDraw, GdkGC *pGC, int narcs, miArc *parcs);
|
||||
void miFillPolygon(GdkDrawable *dst, GdkGC *pgc, int shape, int mode, int count, GdkPoint *pPts);
|
||||
|
||||
miDashPtr miDashLine(int npt, GdkPoint *ppt, unsigned int nDash, unsigned char *pDash, unsigned int offset, int *pnseg);
|
||||
void miZeroLine(GdkDrawable *pDraw, GdkGC *pGC, int mode, int npt, GdkPoint *pptInit);
|
||||
void miZeroDashLine(GdkDrawable *dst, GdkGC *pgc, int mode, int nptInit, GdkPoint *pptInit);
|
||||
void miStepDash (int dist, int *pDashIndex, unsigned char *pDash, int numInDashList, int *pDashOffset);
|
||||
void miWideDash (GdkDrawable *pDrawable, GdkGC *pGC, int mode, int npt, GdkPoint *pPts);
|
||||
void miWideLine (GdkDrawable *pDrawable, GdkGC *pGC, int mode, int npt, GdkPoint *pPts);
|
||||
|
||||
#endif
|
3569
gdk/linux-fb/miarc.c
Normal file
3569
gdk/linux-fb/miarc.c
Normal file
File diff suppressed because it is too large
Load Diff
309
gdk/linux-fb/midash.c
Normal file
309
gdk/linux-fb/midash.c
Normal file
@ -0,0 +1,309 @@
|
||||
/***********************************************************
|
||||
|
||||
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: midash.c /main/14 1998/02/09 14:46:34 kaleb $ */
|
||||
|
||||
#include "mi.h"
|
||||
|
||||
static miDashPtr CheckDashStorage();
|
||||
|
||||
/* return a list of DashRec. there will be an extra
|
||||
entry at the end holding the last point of the polyline.
|
||||
this means that the code that actually draws dashes can
|
||||
get a pair of points for every dash. only the point in the last
|
||||
dash record is useful; the other fields are not used.
|
||||
nseg is the number of segments, not the number of points.
|
||||
|
||||
example:
|
||||
|
||||
dash1.start
|
||||
dash2.start
|
||||
dash3.start
|
||||
last-point
|
||||
|
||||
defines a list of segments
|
||||
(dash1.pt, dash2.pt)
|
||||
(dash2.pt, dash3.pt)
|
||||
(dash3.pt, last-point)
|
||||
and nseg == 3.
|
||||
|
||||
NOTE:
|
||||
EVEN_DASH == ~ODD_DASH
|
||||
|
||||
NOTE ALSO:
|
||||
miDashLines may return 0 segments, going from pt[0] to pt[0] with one dash.
|
||||
*/
|
||||
|
||||
enum { EVEN_DASH=0, ODD_DASH=1 };
|
||||
|
||||
#define sign(x) ((x)>0)?1:( ((x)<0)?-1:0 )
|
||||
|
||||
miDashPtr
|
||||
miDashLine(npt, ppt, nDash, pDash, offset, pnseg)
|
||||
int npt;
|
||||
GdkPoint* ppt;
|
||||
unsigned int nDash;
|
||||
unsigned char *pDash;
|
||||
unsigned int offset;
|
||||
int *pnseg;
|
||||
{
|
||||
GdkPoint pt1, pt2;
|
||||
int lenCur; /* npt used from this dash */
|
||||
int lenMax; /* npt in this dash */
|
||||
int iDash = 0; /* index of current dash */
|
||||
int which; /* EVEN_DASH or ODD_DASH */
|
||||
miDashPtr pseg; /* list of dash segments */
|
||||
miDashPtr psegBase; /* start of list */
|
||||
int nseg = 0; /* number of dashes so far */
|
||||
int nsegMax = 0; /* num segs we can fit in this list */
|
||||
|
||||
int x, y, len;
|
||||
int adx, ady, signdx, signdy;
|
||||
int du, dv, e1, e2, e, base_e = 0;
|
||||
|
||||
lenCur = offset;
|
||||
which = EVEN_DASH;
|
||||
while(lenCur >= pDash[iDash])
|
||||
{
|
||||
lenCur -= pDash[iDash];
|
||||
iDash++;
|
||||
if (iDash >= nDash)
|
||||
iDash = 0;
|
||||
which = ~which;
|
||||
}
|
||||
lenMax = pDash[iDash];
|
||||
|
||||
psegBase = (miDashPtr)NULL;
|
||||
pt2 = ppt[0]; /* just in case there is only one point */
|
||||
|
||||
while(--npt)
|
||||
{
|
||||
if (PtEqual(ppt[0], ppt[1]))
|
||||
{
|
||||
ppt++;
|
||||
continue; /* no duplicated points in polyline */
|
||||
}
|
||||
pt1 = *ppt++;
|
||||
pt2 = *ppt;
|
||||
|
||||
adx = pt2.x - pt1.x;
|
||||
ady = pt2.y - pt1.y;
|
||||
signdx = sign(adx);
|
||||
signdy = sign(ady);
|
||||
adx = abs(adx);
|
||||
ady = abs(ady);
|
||||
|
||||
if (adx > ady)
|
||||
{
|
||||
du = adx;
|
||||
dv = ady;
|
||||
len = adx;
|
||||
}
|
||||
else
|
||||
{
|
||||
du = ady;
|
||||
dv = adx;
|
||||
len = ady;
|
||||
}
|
||||
|
||||
e1 = dv * 2;
|
||||
e2 = e1 - 2*du;
|
||||
e = e1 - du;
|
||||
x = pt1.x;
|
||||
y = pt1.y;
|
||||
|
||||
nseg++;
|
||||
pseg = CheckDashStorage(&psegBase, nseg, &nsegMax);
|
||||
if (!pseg)
|
||||
return (miDashPtr)NULL;
|
||||
pseg->pt = pt1;
|
||||
pseg->e1 = e1;
|
||||
pseg->e2 = e2;
|
||||
base_e = pseg->e = e;
|
||||
pseg->which = which;
|
||||
pseg->newLine = 1;
|
||||
|
||||
while (len--)
|
||||
{
|
||||
if (adx > ady)
|
||||
{
|
||||
/* X_AXIS */
|
||||
if (((signdx > 0) && (e < 0)) ||
|
||||
((signdx <=0) && (e <=0))
|
||||
)
|
||||
{
|
||||
e += e1;
|
||||
}
|
||||
else
|
||||
{
|
||||
y += signdy;
|
||||
e += e2;
|
||||
}
|
||||
x += signdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Y_AXIS */
|
||||
if (((signdx > 0) && (e < 0)) ||
|
||||
((signdx <=0) && (e <=0))
|
||||
)
|
||||
{
|
||||
e +=e1;
|
||||
}
|
||||
else
|
||||
{
|
||||
x += signdx;
|
||||
e += e2;
|
||||
}
|
||||
y += signdy;
|
||||
}
|
||||
|
||||
lenCur++;
|
||||
if (lenCur >= lenMax && (len || npt <= 1))
|
||||
{
|
||||
nseg++;
|
||||
pseg = CheckDashStorage(&psegBase, nseg, &nsegMax);
|
||||
if (!pseg)
|
||||
return (miDashPtr)NULL;
|
||||
pseg->pt.x = x;
|
||||
pseg->pt.y = y;
|
||||
pseg->e1 = e1;
|
||||
pseg->e2 = e2;
|
||||
pseg->e = e;
|
||||
which = ~which;
|
||||
pseg->which = which;
|
||||
pseg->newLine = 0;
|
||||
|
||||
/* move on to next dash */
|
||||
iDash++;
|
||||
if (iDash >= nDash)
|
||||
iDash = 0;
|
||||
lenMax = pDash[iDash];
|
||||
lenCur = 0;
|
||||
}
|
||||
} /* while len-- */
|
||||
} /* while --npt */
|
||||
|
||||
if (lenCur == 0 && nseg != 0)
|
||||
{
|
||||
nseg--;
|
||||
which = ~which;
|
||||
}
|
||||
*pnseg = nseg;
|
||||
pseg = CheckDashStorage(&psegBase, nseg+1, &nsegMax);
|
||||
if (!pseg)
|
||||
return (miDashPtr)NULL;
|
||||
pseg->pt = pt2;
|
||||
pseg->e = base_e;
|
||||
pseg->which = which;
|
||||
pseg->newLine = 0;
|
||||
return psegBase;
|
||||
}
|
||||
|
||||
|
||||
#define NSEGDELTA 16
|
||||
|
||||
/* returns a pointer to the pseg[nseg-1], growing the storage as
|
||||
necessary. this interface seems unnecessarily cumbersome.
|
||||
|
||||
*/
|
||||
|
||||
static
|
||||
miDashPtr
|
||||
CheckDashStorage(ppseg, nseg, pnsegMax)
|
||||
miDashPtr *ppseg; /* base pointer */
|
||||
int nseg; /* number of segment we want to write to */
|
||||
int *pnsegMax; /* size (in segments) of list so far */
|
||||
{
|
||||
if (nseg > *pnsegMax)
|
||||
{
|
||||
miDashPtr newppseg;
|
||||
|
||||
*pnsegMax += NSEGDELTA;
|
||||
newppseg = (miDashPtr)g_realloc(*ppseg,
|
||||
(*pnsegMax)*sizeof(miDashRec));
|
||||
if (!newppseg)
|
||||
{
|
||||
g_free(*ppseg);
|
||||
return (miDashPtr)NULL;
|
||||
}
|
||||
*ppseg = newppseg;
|
||||
}
|
||||
return(*ppseg+(nseg-1));
|
||||
}
|
||||
|
||||
void
|
||||
miStepDash (dist, pDashIndex, pDash, numInDashList, pDashOffset)
|
||||
int dist; /* distance to step */
|
||||
int *pDashIndex; /* current dash */
|
||||
unsigned char *pDash; /* dash list */
|
||||
int numInDashList; /* total length of dash list */
|
||||
int *pDashOffset; /* offset into current dash */
|
||||
{
|
||||
int dashIndex, dashOffset;
|
||||
int totallen;
|
||||
int i;
|
||||
|
||||
dashIndex = *pDashIndex;
|
||||
dashOffset = *pDashOffset;
|
||||
if (dist < pDash[dashIndex] - dashOffset)
|
||||
{
|
||||
*pDashOffset = dashOffset + dist;
|
||||
return;
|
||||
}
|
||||
dist -= pDash[dashIndex] - dashOffset;
|
||||
if (++dashIndex == numInDashList)
|
||||
dashIndex = 0;
|
||||
totallen = 0;
|
||||
for (i = 0; i < numInDashList; i++)
|
||||
totallen += pDash[i];
|
||||
if (totallen <= dist)
|
||||
dist = dist % totallen;
|
||||
while (dist >= pDash[dashIndex])
|
||||
{
|
||||
dist -= pDash[dashIndex];
|
||||
if (++dashIndex == numInDashList)
|
||||
dashIndex = 0;
|
||||
}
|
||||
*pDashIndex = dashIndex;
|
||||
*pDashOffset = dist;
|
||||
}
|
743
gdk/linux-fb/mifillarc.c
Normal file
743
gdk/linux-fb/mifillarc.c
Normal file
@ -0,0 +1,743 @@
|
||||
/* $XFree86: xc/programs/Xserver/mi/mifillarc.c,v 3.4 1999/04/11 13:11:20 dawes Exp $ */
|
||||
/************************************************************
|
||||
|
||||
Copyright 1989, 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.
|
||||
|
||||
Author: Bob Scheifler, MIT X Consortium
|
||||
|
||||
********************************************************/
|
||||
|
||||
/* $TOG: mifillarc.c /main/20 1998/02/09 14:46:52 kaleb $ */
|
||||
|
||||
#include <math.h>
|
||||
#include "mi.h"
|
||||
#include "mifillarc.h"
|
||||
#include "gdkprivate-fb.h"
|
||||
|
||||
#define QUADRANT (90 * 64)
|
||||
#define HALFCIRCLE (180 * 64)
|
||||
#define QUADRANT3 (270 * 64)
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#define Dsin(d) sin((double)d*(M_PI/11520.0))
|
||||
#define Dcos(d) cos((double)d*(M_PI/11520.0))
|
||||
|
||||
void
|
||||
miFillArcSetup(arc, info)
|
||||
register miArc *arc;
|
||||
register miFillArcRec *info;
|
||||
{
|
||||
info->y = arc->height >> 1;
|
||||
info->dy = arc->height & 1;
|
||||
info->yorg = arc->y + info->y;
|
||||
info->dx = arc->width & 1;
|
||||
info->xorg = arc->x + (arc->width >> 1) + info->dx;
|
||||
info->dx = 1 - info->dx;
|
||||
if (arc->width == arc->height)
|
||||
{
|
||||
/* (2x - 2xorg)^2 = d^2 - (2y - 2yorg)^2 */
|
||||
/* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */
|
||||
info->ym = 8;
|
||||
info->xm = 8;
|
||||
info->yk = info->y << 3;
|
||||
if (!info->dx)
|
||||
{
|
||||
info->xk = 0;
|
||||
info->e = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
info->y++;
|
||||
info->yk += 4;
|
||||
info->xk = -4;
|
||||
info->e = - (info->y << 3);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */
|
||||
/* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */
|
||||
info->ym = (arc->width * arc->width) << 3;
|
||||
info->xm = (arc->height * arc->height) << 3;
|
||||
info->yk = info->y * info->ym;
|
||||
if (!info->dy)
|
||||
info->yk -= info->ym >> 1;
|
||||
if (!info->dx)
|
||||
{
|
||||
info->xk = 0;
|
||||
info->e = - (info->xm >> 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
info->y++;
|
||||
info->yk += info->ym;
|
||||
info->xk = -(info->xm >> 1);
|
||||
info->e = info->xk - info->yk;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
miFillArcDSetup(arc, info)
|
||||
register miArc *arc;
|
||||
register miFillArcDRec *info;
|
||||
{
|
||||
/* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */
|
||||
/* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */
|
||||
info->y = arc->height >> 1;
|
||||
info->dy = arc->height & 1;
|
||||
info->yorg = arc->y + info->y;
|
||||
info->dx = arc->width & 1;
|
||||
info->xorg = arc->x + (arc->width >> 1) + info->dx;
|
||||
info->dx = 1 - info->dx;
|
||||
info->ym = ((double)arc->width) * (arc->width * 8);
|
||||
info->xm = ((double)arc->height) * (arc->height * 8);
|
||||
info->yk = info->y * info->ym;
|
||||
if (!info->dy)
|
||||
info->yk -= info->ym / 2.0;
|
||||
if (!info->dx)
|
||||
{
|
||||
info->xk = 0;
|
||||
info->e = - (info->xm / 8.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
info->y++;
|
||||
info->yk += info->ym;
|
||||
info->xk = -info->xm / 2.0;
|
||||
info->e = info->xk - info->yk;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
miGetArcEdge(arc, edge, k, top, left)
|
||||
register miArc *arc;
|
||||
register miSliceEdgePtr edge;
|
||||
int k;
|
||||
gboolean top, left;
|
||||
{
|
||||
register int xady, y;
|
||||
|
||||
y = arc->height >> 1;
|
||||
if (!(arc->width & 1))
|
||||
y++;
|
||||
if (!top)
|
||||
{
|
||||
y = -y;
|
||||
if (arc->height & 1)
|
||||
y--;
|
||||
}
|
||||
xady = k + y * edge->dx;
|
||||
if (xady <= 0)
|
||||
edge->x = - ((-xady) / edge->dy + 1);
|
||||
else
|
||||
edge->x = (xady - 1) / edge->dy;
|
||||
edge->e = xady - edge->x * edge->dy;
|
||||
if ((top && (edge->dx < 0)) || (!top && (edge->dx > 0)))
|
||||
edge->e = edge->dy - edge->e + 1;
|
||||
if (left)
|
||||
edge->x++;
|
||||
edge->x += arc->x + (arc->width >> 1);
|
||||
if (edge->dx > 0)
|
||||
{
|
||||
edge->deltax = 1;
|
||||
edge->stepx = edge->dx / edge->dy;
|
||||
edge->dx = edge->dx % edge->dy;
|
||||
}
|
||||
else
|
||||
{
|
||||
edge->deltax = -1;
|
||||
edge->stepx = - ((-edge->dx) / edge->dy);
|
||||
edge->dx = (-edge->dx) % edge->dy;
|
||||
}
|
||||
if (!top)
|
||||
{
|
||||
edge->deltax = -edge->deltax;
|
||||
edge->stepx = -edge->stepx;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
miEllipseAngleToSlope (angle, width, height, dxp, dyp, d_dxp, d_dyp)
|
||||
int angle;
|
||||
int width;
|
||||
int height;
|
||||
int *dxp;
|
||||
int *dyp;
|
||||
double *d_dxp;
|
||||
double *d_dyp;
|
||||
{
|
||||
int dx, dy;
|
||||
double d_dx, d_dy, scale;
|
||||
gboolean negative_dx, negative_dy;
|
||||
|
||||
switch (angle) {
|
||||
case 0:
|
||||
*dxp = -1;
|
||||
*dyp = 0;
|
||||
if (d_dxp) {
|
||||
*d_dxp = width / 2.0;
|
||||
*d_dyp = 0;
|
||||
}
|
||||
break;
|
||||
case QUADRANT:
|
||||
*dxp = 0;
|
||||
*dyp = 1;
|
||||
if (d_dxp) {
|
||||
*d_dxp = 0;
|
||||
*d_dyp = - height / 2.0;
|
||||
}
|
||||
break;
|
||||
case HALFCIRCLE:
|
||||
*dxp = 1;
|
||||
*dyp = 0;
|
||||
if (d_dxp) {
|
||||
*d_dxp = - width / 2.0;
|
||||
*d_dyp = 0;
|
||||
}
|
||||
break;
|
||||
case QUADRANT3:
|
||||
*dxp = 0;
|
||||
*dyp = -1;
|
||||
if (d_dxp) {
|
||||
*d_dxp = 0;
|
||||
*d_dyp = height / 2.0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
d_dx = Dcos(angle) * width;
|
||||
d_dy = Dsin(angle) * height;
|
||||
if (d_dxp) {
|
||||
*d_dxp = d_dx / 2.0;
|
||||
*d_dyp = - d_dy / 2.0;
|
||||
}
|
||||
negative_dx = FALSE;
|
||||
if (d_dx < 0.0)
|
||||
{
|
||||
d_dx = -d_dx;
|
||||
negative_dx = TRUE;
|
||||
}
|
||||
negative_dy = FALSE;
|
||||
if (d_dy < 0.0)
|
||||
{
|
||||
d_dy = -d_dy;
|
||||
negative_dy = TRUE;
|
||||
}
|
||||
scale = d_dx;
|
||||
if (d_dy > d_dx)
|
||||
scale = d_dy;
|
||||
dx = floor ((d_dx * 32768) / scale + 0.5);
|
||||
if (negative_dx)
|
||||
dx = -dx;
|
||||
*dxp = dx;
|
||||
dy = floor ((d_dy * 32768) / scale + 0.5);
|
||||
if (negative_dy)
|
||||
dy = -dy;
|
||||
*dyp = dy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
miGetPieEdge(arc, angle, edge, top, left)
|
||||
register miArc *arc;
|
||||
register int angle;
|
||||
register miSliceEdgePtr edge;
|
||||
gboolean top, left;
|
||||
{
|
||||
register int k;
|
||||
int dx, dy;
|
||||
|
||||
miEllipseAngleToSlope (angle, arc->width, arc->height, &dx, &dy, 0, 0);
|
||||
|
||||
if (dy == 0)
|
||||
{
|
||||
edge->x = left ? -65536 : 65536;
|
||||
edge->stepx = 0;
|
||||
edge->e = 0;
|
||||
edge->dx = -1;
|
||||
return;
|
||||
}
|
||||
if (dx == 0)
|
||||
{
|
||||
edge->x = arc->x + (arc->width >> 1);
|
||||
if (left && (arc->width & 1))
|
||||
edge->x++;
|
||||
else if (!left && !(arc->width & 1))
|
||||
edge->x--;
|
||||
edge->stepx = 0;
|
||||
edge->e = 0;
|
||||
edge->dx = -1;
|
||||
return;
|
||||
}
|
||||
if (dy < 0) {
|
||||
dx = -dx;
|
||||
dy = -dy;
|
||||
}
|
||||
k = (arc->height & 1) ? dx : 0;
|
||||
if (arc->width & 1)
|
||||
k += dy;
|
||||
edge->dx = dx << 1;
|
||||
edge->dy = dy << 1;
|
||||
miGetArcEdge(arc, edge, k, top, left);
|
||||
}
|
||||
|
||||
void
|
||||
miFillArcSliceSetup(arc, slice, pGC)
|
||||
register miArc *arc;
|
||||
register miArcSliceRec *slice;
|
||||
GdkGC* pGC;
|
||||
{
|
||||
register int angle1, angle2;
|
||||
|
||||
angle1 = arc->angle1;
|
||||
if (arc->angle2 < 0)
|
||||
{
|
||||
angle2 = angle1;
|
||||
angle1 += arc->angle2;
|
||||
}
|
||||
else
|
||||
angle2 = angle1 + arc->angle2;
|
||||
while (angle1 < 0)
|
||||
angle1 += FULLCIRCLE;
|
||||
while (angle1 >= FULLCIRCLE)
|
||||
angle1 -= FULLCIRCLE;
|
||||
while (angle2 < 0)
|
||||
angle2 += FULLCIRCLE;
|
||||
while (angle2 >= FULLCIRCLE)
|
||||
angle2 -= FULLCIRCLE;
|
||||
slice->min_top_y = 0;
|
||||
slice->max_top_y = arc->height >> 1;
|
||||
slice->min_bot_y = 1 - (arc->height & 1);
|
||||
slice->max_bot_y = slice->max_top_y - 1;
|
||||
slice->flip_top = FALSE;
|
||||
slice->flip_bot = FALSE;
|
||||
if (0 /* pGC->arcMode == ArcPieSlice */)
|
||||
{
|
||||
slice->edge1_top = (angle1 < HALFCIRCLE);
|
||||
slice->edge2_top = (angle2 <= HALFCIRCLE);
|
||||
if ((angle2 == 0) || (angle1 == HALFCIRCLE))
|
||||
{
|
||||
if (angle2 ? slice->edge2_top : slice->edge1_top)
|
||||
slice->min_top_y = slice->min_bot_y;
|
||||
else
|
||||
slice->min_top_y = arc->height;
|
||||
slice->min_bot_y = 0;
|
||||
}
|
||||
else if ((angle1 == 0) || (angle2 == HALFCIRCLE))
|
||||
{
|
||||
slice->min_top_y = slice->min_bot_y;
|
||||
if (angle1 ? slice->edge1_top : slice->edge2_top)
|
||||
slice->min_bot_y = arc->height;
|
||||
else
|
||||
slice->min_bot_y = 0;
|
||||
}
|
||||
else if (slice->edge1_top == slice->edge2_top)
|
||||
{
|
||||
if (angle2 < angle1)
|
||||
{
|
||||
slice->flip_top = slice->edge1_top;
|
||||
slice->flip_bot = !slice->edge1_top;
|
||||
}
|
||||
else if (slice->edge1_top)
|
||||
{
|
||||
slice->min_top_y = 1;
|
||||
slice->min_bot_y = arc->height;
|
||||
}
|
||||
else
|
||||
{
|
||||
slice->min_bot_y = 0;
|
||||
slice->min_top_y = arc->height;
|
||||
}
|
||||
}
|
||||
miGetPieEdge(arc, angle1, &slice->edge1,
|
||||
slice->edge1_top, !slice->edge1_top);
|
||||
miGetPieEdge(arc, angle2, &slice->edge2,
|
||||
slice->edge2_top, slice->edge2_top);
|
||||
}
|
||||
else
|
||||
{
|
||||
double w2, h2, x1, y1, x2, y2, dx, dy, scale;
|
||||
int signdx, signdy, y, k;
|
||||
gboolean isInt1 = TRUE, isInt2 = TRUE;
|
||||
|
||||
w2 = (double)arc->width / 2.0;
|
||||
h2 = (double)arc->height / 2.0;
|
||||
if ((angle1 == 0) || (angle1 == HALFCIRCLE))
|
||||
{
|
||||
x1 = angle1 ? -w2 : w2;
|
||||
y1 = 0.0;
|
||||
}
|
||||
else if ((angle1 == QUADRANT) || (angle1 == QUADRANT3))
|
||||
{
|
||||
x1 = 0.0;
|
||||
y1 = (angle1 == QUADRANT) ? h2 : -h2;
|
||||
}
|
||||
else
|
||||
{
|
||||
isInt1 = FALSE;
|
||||
x1 = Dcos(angle1) * w2;
|
||||
y1 = Dsin(angle1) * h2;
|
||||
}
|
||||
if ((angle2 == 0) || (angle2 == HALFCIRCLE))
|
||||
{
|
||||
x2 = angle2 ? -w2 : w2;
|
||||
y2 = 0.0;
|
||||
}
|
||||
else if ((angle2 == QUADRANT) || (angle2 == QUADRANT3))
|
||||
{
|
||||
x2 = 0.0;
|
||||
y2 = (angle2 == QUADRANT) ? h2 : -h2;
|
||||
}
|
||||
else
|
||||
{
|
||||
isInt2 = FALSE;
|
||||
x2 = Dcos(angle2) * w2;
|
||||
y2 = Dsin(angle2) * h2;
|
||||
}
|
||||
dx = x2 - x1;
|
||||
dy = y2 - y1;
|
||||
if (arc->height & 1)
|
||||
{
|
||||
y1 -= 0.5;
|
||||
y2 -= 0.5;
|
||||
}
|
||||
if (arc->width & 1)
|
||||
{
|
||||
x1 += 0.5;
|
||||
x2 += 0.5;
|
||||
}
|
||||
if (dy < 0.0)
|
||||
{
|
||||
dy = -dy;
|
||||
signdy = -1;
|
||||
}
|
||||
else
|
||||
signdy = 1;
|
||||
if (dx < 0.0)
|
||||
{
|
||||
dx = -dx;
|
||||
signdx = -1;
|
||||
}
|
||||
else
|
||||
signdx = 1;
|
||||
if (isInt1 && isInt2)
|
||||
{
|
||||
slice->edge1.dx = dx * 2;
|
||||
slice->edge1.dy = dy * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale = (dx > dy) ? dx : dy;
|
||||
slice->edge1.dx = floor((dx * 32768) / scale + .5);
|
||||
slice->edge1.dy = floor((dy * 32768) / scale + .5);
|
||||
}
|
||||
if (!slice->edge1.dy)
|
||||
{
|
||||
if (signdx < 0)
|
||||
{
|
||||
y = floor(y1 + 1.0);
|
||||
if (y >= 0)
|
||||
{
|
||||
slice->min_top_y = y;
|
||||
slice->min_bot_y = arc->height;
|
||||
}
|
||||
else
|
||||
{
|
||||
slice->max_bot_y = -y - (arc->height & 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
y = floor(y1);
|
||||
if (y >= 0)
|
||||
slice->max_top_y = y;
|
||||
else
|
||||
{
|
||||
slice->min_top_y = arc->height;
|
||||
slice->min_bot_y = -y - (arc->height & 1);
|
||||
}
|
||||
}
|
||||
slice->edge1_top = TRUE;
|
||||
slice->edge1.x = 65536;
|
||||
slice->edge1.stepx = 0;
|
||||
slice->edge1.e = 0;
|
||||
slice->edge1.dx = -1;
|
||||
slice->edge2 = slice->edge1;
|
||||
slice->edge2_top = FALSE;
|
||||
}
|
||||
else if (!slice->edge1.dx)
|
||||
{
|
||||
if (signdy < 0)
|
||||
x1 -= 1.0;
|
||||
slice->edge1.x = ceil(x1);
|
||||
slice->edge1_top = signdy < 0;
|
||||
slice->edge1.x += arc->x + (arc->width >> 1);
|
||||
slice->edge1.stepx = 0;
|
||||
slice->edge1.e = 0;
|
||||
slice->edge1.dx = -1;
|
||||
slice->edge2_top = !slice->edge1_top;
|
||||
slice->edge2 = slice->edge1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (signdx < 0)
|
||||
slice->edge1.dx = -slice->edge1.dx;
|
||||
if (signdy < 0)
|
||||
slice->edge1.dx = -slice->edge1.dx;
|
||||
k = ceil(((x1 + x2) * slice->edge1.dy - (y1 + y2) * slice->edge1.dx) / 2.0);
|
||||
slice->edge2.dx = slice->edge1.dx;
|
||||
slice->edge2.dy = slice->edge1.dy;
|
||||
slice->edge1_top = signdy < 0;
|
||||
slice->edge2_top = !slice->edge1_top;
|
||||
miGetArcEdge(arc, &slice->edge1, k,
|
||||
slice->edge1_top, !slice->edge1_top);
|
||||
miGetArcEdge(arc, &slice->edge2, k,
|
||||
slice->edge2_top, slice->edge2_top);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define ADDSPANS() \
|
||||
pts->x = xorg - x; \
|
||||
pts->y = yorg - y; \
|
||||
pts->width = slw; \
|
||||
pts->height = 1; \
|
||||
pts++; \
|
||||
if (miFillArcLower(slw)) \
|
||||
{ \
|
||||
pts->x = xorg - x; \
|
||||
pts->y = yorg + y + dy; \
|
||||
pts->width = slw; \
|
||||
pts->height = 1; \
|
||||
pts++; \
|
||||
}
|
||||
|
||||
static void
|
||||
miFillEllipseI(pDraw, pGC, arc)
|
||||
GdkDrawable* pDraw;
|
||||
GdkGC* pGC;
|
||||
miArc *arc;
|
||||
{
|
||||
register int x, y, e;
|
||||
int yk, xk, ym, xm, dx, dy, xorg, yorg;
|
||||
int slw;
|
||||
miFillArcRec info;
|
||||
GdkRectangle* points;
|
||||
register GdkRectangle* pts;
|
||||
|
||||
points = (GdkRectangle*)ALLOCATE_LOCAL(sizeof(GdkRectangle) * arc->height);
|
||||
if (!points)
|
||||
return;
|
||||
miFillArcSetup(arc, &info);
|
||||
MIFILLARCSETUP();
|
||||
pts = points;
|
||||
while (y > 0)
|
||||
{
|
||||
MIFILLARCSTEP(slw);
|
||||
ADDSPANS();
|
||||
}
|
||||
gdk_fb_fill_spans(pDraw, pGC, points, pts - points);
|
||||
|
||||
DEALLOCATE_LOCAL(points);
|
||||
}
|
||||
|
||||
static void
|
||||
miFillEllipseD(pDraw, pGC, arc)
|
||||
GdkDrawable* pDraw;
|
||||
GdkGC* pGC;
|
||||
miArc *arc;
|
||||
{
|
||||
register int x, y;
|
||||
int xorg, yorg, dx, dy, slw;
|
||||
double e, yk, xk, ym, xm;
|
||||
miFillArcDRec info;
|
||||
GdkRectangle* points;
|
||||
register GdkRectangle* pts;
|
||||
|
||||
points = (GdkRectangle*)ALLOCATE_LOCAL(sizeof(GdkRectangle) * arc->height);
|
||||
if (!points)
|
||||
return;
|
||||
miFillArcDSetup(arc, &info);
|
||||
MIFILLARCSETUP();
|
||||
pts = points;
|
||||
while (y > 0)
|
||||
{
|
||||
MIFILLARCSTEP(slw);
|
||||
ADDSPANS();
|
||||
}
|
||||
gdk_fb_fill_spans(pDraw, pGC, points, pts - points);
|
||||
DEALLOCATE_LOCAL(points);
|
||||
}
|
||||
|
||||
#define ADDSPAN(l,r) \
|
||||
if (r >= l) \
|
||||
{ \
|
||||
pts->x = l; \
|
||||
pts->y = ya; \
|
||||
pts->width = r - l + 1; \
|
||||
pts->height = 1; \
|
||||
pts++; \
|
||||
}
|
||||
|
||||
#define ADDSLICESPANS(flip) \
|
||||
if (!flip) \
|
||||
{ \
|
||||
ADDSPAN(xl, xr); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
xc = xorg - x; \
|
||||
ADDSPAN(xc, xr); \
|
||||
xc += slw - 1; \
|
||||
ADDSPAN(xl, xc); \
|
||||
}
|
||||
|
||||
static void
|
||||
miFillArcSliceI(pDraw, pGC, arc)
|
||||
GdkDrawable* pDraw;
|
||||
GdkGC* pGC;
|
||||
miArc *arc;
|
||||
{
|
||||
int yk, xk, ym, xm, dx, dy, xorg, yorg, slw;
|
||||
register int x, y, e;
|
||||
miFillArcRec info;
|
||||
miArcSliceRec slice;
|
||||
int ya, xl, xr, xc;
|
||||
GdkRectangle* points;
|
||||
register GdkRectangle* pts;
|
||||
|
||||
miFillArcSetup(arc, &info);
|
||||
miFillArcSliceSetup(arc, &slice, pGC);
|
||||
MIFILLARCSETUP();
|
||||
slw = arc->height;
|
||||
if (slice.flip_top || slice.flip_bot)
|
||||
slw += (arc->height >> 1) + 1;
|
||||
points = (GdkRectangle*)ALLOCATE_LOCAL(sizeof(GdkRectangle) * slw);
|
||||
if (!points)
|
||||
return;
|
||||
pts = points;
|
||||
while (y > 0)
|
||||
{
|
||||
MIFILLARCSTEP(slw);
|
||||
MIARCSLICESTEP(slice.edge1);
|
||||
MIARCSLICESTEP(slice.edge2);
|
||||
if (miFillSliceUpper(slice))
|
||||
{
|
||||
ya = yorg - y;
|
||||
MIARCSLICEUPPER(xl, xr, slice, slw);
|
||||
ADDSLICESPANS(slice.flip_top);
|
||||
}
|
||||
if (miFillSliceLower(slice))
|
||||
{
|
||||
ya = yorg + y + dy;
|
||||
MIARCSLICELOWER(xl, xr, slice, slw);
|
||||
ADDSLICESPANS(slice.flip_bot);
|
||||
}
|
||||
}
|
||||
|
||||
gdk_fb_fill_spans(pDraw, pGC, points, pts - points);
|
||||
DEALLOCATE_LOCAL(points);
|
||||
}
|
||||
|
||||
static void
|
||||
miFillArcSliceD(pDraw, pGC, arc)
|
||||
GdkDrawable* pDraw;
|
||||
GdkGC* pGC;
|
||||
miArc *arc;
|
||||
{
|
||||
register int x, y;
|
||||
int dx, dy, xorg, yorg, slw;
|
||||
double e, yk, xk, ym, xm;
|
||||
miFillArcDRec info;
|
||||
miArcSliceRec slice;
|
||||
int ya, xl, xr, xc;
|
||||
GdkRectangle* points;
|
||||
register GdkRectangle* pts;
|
||||
|
||||
miFillArcDSetup(arc, &info);
|
||||
miFillArcSliceSetup(arc, &slice, pGC);
|
||||
MIFILLARCSETUP();
|
||||
slw = arc->height;
|
||||
if (slice.flip_top || slice.flip_bot)
|
||||
slw += (arc->height >> 1) + 1;
|
||||
points = (GdkRectangle*)ALLOCATE_LOCAL(sizeof(GdkRectangle) * slw);
|
||||
if (!points)
|
||||
return;
|
||||
pts = points;
|
||||
while (y > 0)
|
||||
{
|
||||
MIFILLARCSTEP(slw);
|
||||
MIARCSLICESTEP(slice.edge1);
|
||||
MIARCSLICESTEP(slice.edge2);
|
||||
if (miFillSliceUpper(slice))
|
||||
{
|
||||
ya = yorg - y;
|
||||
MIARCSLICEUPPER(xl, xr, slice, slw);
|
||||
ADDSLICESPANS(slice.flip_top);
|
||||
}
|
||||
if (miFillSliceLower(slice))
|
||||
{
|
||||
ya = yorg + y + dy;
|
||||
MIARCSLICELOWER(xl, xr, slice, slw);
|
||||
ADDSLICESPANS(slice.flip_bot);
|
||||
}
|
||||
}
|
||||
gdk_fb_fill_spans(pDraw, pGC, points, pts - points);
|
||||
|
||||
DEALLOCATE_LOCAL(points);
|
||||
}
|
||||
|
||||
/* MIPOLYFILLARC -- The public entry for the PolyFillArc request.
|
||||
* Since we don't have to worry about overlapping segments, we can just
|
||||
* fill each arc as it comes.
|
||||
*/
|
||||
void
|
||||
miPolyFillArc(pDraw, pGC, narcs, parcs)
|
||||
GdkDrawable* pDraw;
|
||||
GdkGC* pGC;
|
||||
int narcs;
|
||||
miArc *parcs;
|
||||
{
|
||||
register int i;
|
||||
register miArc *arc;
|
||||
|
||||
for(i = narcs, arc = parcs; --i >= 0; arc++)
|
||||
{
|
||||
if (miFillArcEmpty(arc))
|
||||
continue;;
|
||||
if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE))
|
||||
{
|
||||
if (miCanFillArc(arc))
|
||||
miFillEllipseI(pDraw, pGC, arc);
|
||||
else
|
||||
miFillEllipseD(pDraw, pGC, arc);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (miCanFillArc(arc))
|
||||
miFillArcSliceI(pDraw, pGC, arc);
|
||||
else
|
||||
miFillArcSliceD(pDraw, pGC, arc);
|
||||
}
|
||||
}
|
||||
}
|
224
gdk/linux-fb/mifillarc.h
Normal file
224
gdk/linux-fb/mifillarc.h
Normal file
@ -0,0 +1,224 @@
|
||||
/* $XFree86: xc/programs/Xserver/mi/mifillarc.h,v 3.3 1998/10/04 09:39:27 dawes Exp $ */
|
||||
/************************************************************
|
||||
|
||||
Copyright 1989, 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.
|
||||
|
||||
********************************************************/
|
||||
|
||||
/* $TOG: mifillarc.h /main/11 1998/02/09 14:46:57 kaleb $ */
|
||||
|
||||
#ifndef MIFILLARC_H
|
||||
#define MIFILLARC_H 1
|
||||
|
||||
#define FULLCIRCLE (360 * 64)
|
||||
|
||||
typedef struct _miFillArc {
|
||||
int xorg, yorg;
|
||||
int y;
|
||||
int dx, dy;
|
||||
int e;
|
||||
int ym, yk, xm, xk;
|
||||
} miFillArcRec;
|
||||
|
||||
/* could use 64-bit integers */
|
||||
typedef struct _miFillArcD {
|
||||
int xorg, yorg;
|
||||
int y;
|
||||
int dx, dy;
|
||||
double e;
|
||||
double ym, yk, xm, xk;
|
||||
} miFillArcDRec;
|
||||
|
||||
#define miFillArcEmpty(arc) (!(arc)->angle2 || \
|
||||
!(arc)->width || !(arc)->height || \
|
||||
(((arc)->width == 1) && ((arc)->height & 1)))
|
||||
|
||||
#define miCanFillArc(arc) (((arc)->width == (arc)->height) || \
|
||||
(((arc)->width <= 800) && ((arc)->height <= 800)))
|
||||
|
||||
#define MIFILLARCSETUP() \
|
||||
x = 0; \
|
||||
y = info.y; \
|
||||
e = info.e; \
|
||||
xk = info.xk; \
|
||||
xm = info.xm; \
|
||||
yk = info.yk; \
|
||||
ym = info.ym; \
|
||||
dx = info.dx; \
|
||||
dy = info.dy; \
|
||||
xorg = info.xorg; \
|
||||
yorg = info.yorg
|
||||
|
||||
#define MIFILLARCSTEP(slw) \
|
||||
e += yk; \
|
||||
while (e >= 0) \
|
||||
{ \
|
||||
x++; \
|
||||
xk -= xm; \
|
||||
e += xk; \
|
||||
} \
|
||||
y--; \
|
||||
yk -= ym; \
|
||||
slw = (x << 1) + dx; \
|
||||
if ((e == xk) && (slw > 1)) \
|
||||
slw--
|
||||
|
||||
#define MIFILLCIRCSTEP(slw) MIFILLARCSTEP(slw)
|
||||
#define MIFILLELLSTEP(slw) MIFILLARCSTEP(slw)
|
||||
|
||||
#define miFillArcLower(slw) (((y + dy) != 0) && ((slw > 1) || (e != xk)))
|
||||
|
||||
typedef struct _miSliceEdge {
|
||||
int x;
|
||||
int stepx;
|
||||
int deltax;
|
||||
int e;
|
||||
int dy;
|
||||
int dx;
|
||||
} miSliceEdgeRec, *miSliceEdgePtr;
|
||||
|
||||
typedef struct _miArcSlice {
|
||||
miSliceEdgeRec edge1, edge2;
|
||||
int min_top_y, max_top_y;
|
||||
int min_bot_y, max_bot_y;
|
||||
gboolean edge1_top, edge2_top;
|
||||
gboolean flip_top, flip_bot;
|
||||
} miArcSliceRec;
|
||||
|
||||
#define MIARCSLICESTEP(edge) \
|
||||
edge.x -= edge.stepx; \
|
||||
edge.e -= edge.dx; \
|
||||
if (edge.e <= 0) \
|
||||
{ \
|
||||
edge.x -= edge.deltax; \
|
||||
edge.e += edge.dy; \
|
||||
}
|
||||
|
||||
#define miFillSliceUpper(slice) \
|
||||
((y >= slice.min_top_y) && (y <= slice.max_top_y))
|
||||
|
||||
#define miFillSliceLower(slice) \
|
||||
((y >= slice.min_bot_y) && (y <= slice.max_bot_y))
|
||||
|
||||
#define MIARCSLICEUPPER(xl,xr,slice,slw) \
|
||||
xl = xorg - x; \
|
||||
xr = xl + slw - 1; \
|
||||
if (slice.edge1_top && (slice.edge1.x < xr)) \
|
||||
xr = slice.edge1.x; \
|
||||
if (slice.edge2_top && (slice.edge2.x > xl)) \
|
||||
xl = slice.edge2.x;
|
||||
|
||||
#define MIARCSLICELOWER(xl,xr,slice,slw) \
|
||||
xl = xorg - x; \
|
||||
xr = xl + slw - 1; \
|
||||
if (!slice.edge1_top && (slice.edge1.x > xl)) \
|
||||
xl = slice.edge1.x; \
|
||||
if (!slice.edge2_top && (slice.edge2.x < xr)) \
|
||||
xr = slice.edge2.x;
|
||||
|
||||
#define MIWIDEARCSETUP(x,y,dy,slw,e,xk,xm,yk,ym) \
|
||||
x = 0; \
|
||||
y = slw >> 1; \
|
||||
yk = y << 3; \
|
||||
xm = 8; \
|
||||
ym = 8; \
|
||||
if (dy) \
|
||||
{ \
|
||||
xk = 0; \
|
||||
if (slw & 1) \
|
||||
e = -1; \
|
||||
else \
|
||||
e = -(y << 2) - 2; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
y++; \
|
||||
yk += 4; \
|
||||
xk = -4; \
|
||||
if (slw & 1) \
|
||||
e = -(y << 2) - 3; \
|
||||
else \
|
||||
e = - (y << 3); \
|
||||
}
|
||||
|
||||
#define MIFILLINARCSTEP(slw) \
|
||||
ine += inyk; \
|
||||
while (ine >= 0) \
|
||||
{ \
|
||||
inx++; \
|
||||
inxk -= inxm; \
|
||||
ine += inxk; \
|
||||
} \
|
||||
iny--; \
|
||||
inyk -= inym; \
|
||||
slw = (inx << 1) + dx; \
|
||||
if ((ine == inxk) && (slw > 1)) \
|
||||
slw--
|
||||
|
||||
#define miFillInArcLower(slw) (((iny + dy) != 0) && \
|
||||
((slw > 1) || (ine != inxk)))
|
||||
|
||||
extern int miFreeArcCache(
|
||||
#if NeedFunctionPrototypes
|
||||
gpointer /*data*/,
|
||||
guint /*id*/
|
||||
#endif
|
||||
);
|
||||
|
||||
extern struct finalSpan *realAllocSpan(
|
||||
#if NeedFunctionPrototypes
|
||||
void
|
||||
#endif
|
||||
);
|
||||
|
||||
extern void miFillArcSetup(
|
||||
#if NeedFunctionPrototypes
|
||||
miArc * /*arc*/,
|
||||
miFillArcRec * /*info*/
|
||||
#endif
|
||||
);
|
||||
|
||||
extern void miFillArcDSetup(
|
||||
#if NeedFunctionPrototypes
|
||||
miArc * /*arc*/,
|
||||
miFillArcDRec * /*info*/
|
||||
#endif
|
||||
);
|
||||
|
||||
extern void miEllipseAngleToSlope(
|
||||
#if NeedFunctionPrototypes
|
||||
int /*angle*/,
|
||||
int /*width*/,
|
||||
int /*height*/,
|
||||
int * /*dxp*/,
|
||||
int * /*dyp*/,
|
||||
double * /*d_dxp*/,
|
||||
double * /*d_dyp*/
|
||||
#endif
|
||||
);
|
||||
|
||||
extern void miFillArcSliceSetup(
|
||||
#if NeedFunctionPrototypes
|
||||
miArc * /*arc*/,
|
||||
miArcSliceRec * /*slice*/,
|
||||
GdkGC* /*pGC*/
|
||||
#endif
|
||||
);
|
||||
|
||||
#endif
|
112
gdk/linux-fb/mifpoly.h
Normal file
112
gdk/linux-fb/mifpoly.h
Normal file
@ -0,0 +1,112 @@
|
||||
/* $TOG: mifpoly.h /main/10 1998/02/09 14:47:09 kaleb $ */
|
||||
/***********************************************************
|
||||
|
||||
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.
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MIFPOLY_H
|
||||
#define MIFPOLY_H 1
|
||||
|
||||
#define EPSILON 0.000001
|
||||
#define ISEQUAL(a,b) (fabs((a) - (b)) <= EPSILON)
|
||||
#define UNEQUAL(a,b) (fabs((a) - (b)) > EPSILON)
|
||||
#define WITHINHALF(a, b) (((a) - (b) > 0.0) ? (a) - (b) < 0.5 : \
|
||||
(b) - (a) <= 0.5)
|
||||
#define ROUNDTOINT(x) ((int) (((x) > 0.0) ? ((x) + 0.5) : ((x) - 0.5)))
|
||||
#define ISZERO(x) (fabs((x)) <= EPSILON)
|
||||
#define PTISEQUAL(a,b) (ISEQUAL(a.x,b.x) && ISEQUAL(a.y,b.y))
|
||||
#define PTUNEQUAL(a,b) (UNEQUAL(a.x,b.x) || UNEQUAL(a.y,b.y))
|
||||
#define PtEqual(a, b) (((a).x == (b).x) && ((a).y == (b).y))
|
||||
|
||||
#define NotEnd 0
|
||||
#define FirstEnd 1
|
||||
#define SecondEnd 2
|
||||
|
||||
#define SQSECANT 108.856472512142 /* 1/sin^2(11/2) - for 11o miter cutoff */
|
||||
#define D2SECANT 5.21671526231167 /* 1/2*sin(11/2) - max extension per width */
|
||||
|
||||
#ifndef ICIEL
|
||||
#ifdef NOINLINEICEIL
|
||||
#define ICEIL(x) ((int)ceil(x))
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
#define ICEIL ICIEL
|
||||
static __inline int ICEIL(x)
|
||||
double x;
|
||||
{
|
||||
int _cTmp = x;
|
||||
return ((x == _cTmp) || (x < 0.0)) ? _cTmp : _cTmp+1;
|
||||
}
|
||||
#else
|
||||
#define ICEIL(x) ((((x) == (_cTmp = (x))) || ((x) < 0.0)) ? _cTmp : _cTmp+1)
|
||||
#define ICEILTEMPDECL static int _cTmp;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Point with sub-pixel positioning. In this case we use doubles, but
|
||||
* see mifpolycon.c for other suggestions
|
||||
*/
|
||||
typedef struct _SppPoint {
|
||||
double x, y;
|
||||
} SppPointRec, *SppPointPtr;
|
||||
|
||||
typedef struct _SppArc {
|
||||
double x, y, width, height;
|
||||
double angle1, angle2;
|
||||
} SppArcRec, *SppArcPtr;
|
||||
|
||||
/* mifpolycon.c */
|
||||
|
||||
extern void miFillSppPoly(
|
||||
#if NeedFunctionPrototypes
|
||||
GdkDrawable* /*dst*/,
|
||||
GdkGC* /*pgc*/,
|
||||
int /*count*/,
|
||||
SppPointPtr /*ptsIn*/,
|
||||
int /*xTrans*/,
|
||||
int /*yTrans*/,
|
||||
double /*xFtrans*/,
|
||||
double /*yFtrans*/
|
||||
#endif
|
||||
);
|
||||
|
||||
#endif /* MIFPOLY_H */
|
261
gdk/linux-fb/mifpolycon.c
Normal file
261
gdk/linux-fb/mifpolycon.c
Normal file
@ -0,0 +1,261 @@
|
||||
/***********************************************************
|
||||
|
||||
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 */
|
||||
GdkRectangle* ptsOut,
|
||||
*FirstPoint; /* output buffer */
|
||||
|
||||
imin = GetFPolyYBounds(ptsIn, count, yFtrans, &ymin, &ymax);
|
||||
|
||||
y = ymax - ymin + 1;
|
||||
if ((count < 3) || (y <= 0))
|
||||
return;
|
||||
ptsOut = FirstPoint = (GdkRectangle*)ALLOCATE_LOCAL(sizeof(GdkRectangle) * 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);
|
||||
ptsOut->height = 1;
|
||||
/* 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);
|
||||
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);
|
||||
}
|
177
gdk/linux-fb/miline.h
Normal file
177
gdk/linux-fb/miline.h
Normal file
@ -0,0 +1,177 @@
|
||||
/* $TOG: miline.h /main/7 1998/02/09 14:47:30 kaleb $ */
|
||||
|
||||
/*
|
||||
|
||||
Copyright 1994, 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.
|
||||
|
||||
*/
|
||||
/* $XFree86: xc/programs/Xserver/mi/miline.h,v 1.4 1999/10/13 22:33:11 dawes Exp $ */
|
||||
|
||||
#ifndef MILINE_H
|
||||
|
||||
/*
|
||||
* Public definitions used for configuring basic pixelization aspects
|
||||
* of the sample implementation line-drawing routines provided in
|
||||
* {mfb,mi,cfb*} at run-time.
|
||||
*/
|
||||
|
||||
#define XDECREASING 4
|
||||
#define YDECREASING 2
|
||||
#define YMAJOR 1
|
||||
|
||||
#define OCTANT1 (1 << (YDECREASING))
|
||||
#define OCTANT2 (1 << (YDECREASING|YMAJOR))
|
||||
#define OCTANT3 (1 << (XDECREASING|YDECREASING|YMAJOR))
|
||||
#define OCTANT4 (1 << (XDECREASING|YDECREASING))
|
||||
#define OCTANT5 (1 << (XDECREASING))
|
||||
#define OCTANT6 (1 << (XDECREASING|YMAJOR))
|
||||
#define OCTANT7 (1 << (YMAJOR))
|
||||
#define OCTANT8 (1 << (0))
|
||||
|
||||
#define XMAJOROCTANTS (OCTANT1 | OCTANT4 | OCTANT5 | OCTANT8)
|
||||
|
||||
#define DEFAULTZEROLINEBIAS (OCTANT2 | OCTANT3 | OCTANT4 | OCTANT5)
|
||||
|
||||
/*
|
||||
* Devices can configure the rendering of routines in mi, mfb, and cfb*
|
||||
* by specifying a thin line bias to be applied to a particular screen
|
||||
* using the following function. The bias parameter is an OR'ing of
|
||||
* the appropriate OCTANT constants defined above to indicate which
|
||||
* octants to bias a line to prefer an axial step when the Bresenham
|
||||
* error term is exactly zero. The octants are mapped as follows:
|
||||
*
|
||||
* \ | /
|
||||
* \ 3 | 2 /
|
||||
* \ | /
|
||||
* 4 \ | / 1
|
||||
* \|/
|
||||
* -----------
|
||||
* /|\
|
||||
* 5 / | \ 8
|
||||
* / | \
|
||||
* / 6 | 7 \
|
||||
* / | \
|
||||
*
|
||||
* For more information, see "Ambiguities in Incremental Line Rastering,"
|
||||
* Jack E. Bresenham, IEEE CG&A, May 1987.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
extern void miSetZeroLineBias(
|
||||
#if NeedFunctionPrototypes
|
||||
ScreenPtr /* pScreen */,
|
||||
unsigned int /* bias */
|
||||
#endif
|
||||
);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Private definitions needed for drawing thin (zero width) lines
|
||||
* Used by the mi, mfb, and all cfb* components.
|
||||
*/
|
||||
|
||||
#define X_AXIS 0
|
||||
#define Y_AXIS 1
|
||||
|
||||
#define OUT_LEFT 0x08
|
||||
#define OUT_RIGHT 0x04
|
||||
#define OUT_ABOVE 0x02
|
||||
#define OUT_BELOW 0x01
|
||||
|
||||
#define OUTCODES(_result, _x, _y, _pbox) \
|
||||
if ( (_x) < (_pbox)->x1) (_result) |= OUT_LEFT; \
|
||||
else if ( (_x) >= (_pbox)->x2) (_result) |= OUT_RIGHT; \
|
||||
if ( (_y) < (_pbox)->y1) (_result) |= OUT_ABOVE; \
|
||||
else if ( (_y) >= (_pbox)->y2) (_result) |= OUT_BELOW;
|
||||
|
||||
#define MIOUTCODES(outcode, x, y, xmin, ymin, xmax, ymax) \
|
||||
{\
|
||||
if (x < xmin) outcode |= OUT_LEFT;\
|
||||
if (x > xmax) outcode |= OUT_RIGHT;\
|
||||
if (y < ymin) outcode |= OUT_ABOVE;\
|
||||
if (y > ymax) outcode |= OUT_BELOW;\
|
||||
}
|
||||
|
||||
#define SWAPINT(i, j) \
|
||||
{ register int _t = i; i = j; j = _t; }
|
||||
|
||||
#define SWAPPT(i, j) \
|
||||
{ GdkPoint _t; _t = i; i = j; j = _t; }
|
||||
|
||||
#define SWAPINT_PAIR(x1, y1, x2, y2)\
|
||||
{ int t = x1; x1 = x2; x2 = t;\
|
||||
t = y1; y1 = y2; y2 = t;\
|
||||
}
|
||||
|
||||
#if 0
|
||||
#define miGetZeroLineBias(_pScreen) \
|
||||
((miZeroLineScreenIndex < 0) ? \
|
||||
0 : ((_pScreen)->devPrivates[miZeroLineScreenIndex].uval))
|
||||
#endif
|
||||
#define miGetZeroLineBias() DEFAULTZEROLINEBIAS
|
||||
|
||||
#define CalcLineDeltas(_x1,_y1,_x2,_y2,_adx,_ady,_sx,_sy,_SX,_SY,_octant) \
|
||||
(_octant) = 0; \
|
||||
(_sx) = (_SX); \
|
||||
if (((_adx) = (_x2) - (_x1)) < 0) { \
|
||||
(_adx) = -(_adx); \
|
||||
(_sx = -(_sx)); \
|
||||
(_octant) |= XDECREASING; \
|
||||
} \
|
||||
(_sy) = (_SY); \
|
||||
if (((_ady) = (_y2) - (_y1)) < 0) { \
|
||||
(_ady) = -(_ady); \
|
||||
(_sy = -(_sy)); \
|
||||
(_octant) |= YDECREASING; \
|
||||
}
|
||||
|
||||
#define SetYMajorOctant(_octant) ((_octant) |= YMAJOR)
|
||||
|
||||
#define FIXUP_ERROR(_e, _octant, _bias) \
|
||||
(_e) -= (((_bias) >> (_octant)) & 1)
|
||||
|
||||
#define IsXMajorOctant(_octant) (!((_octant) & YMAJOR))
|
||||
#define IsYMajorOctant(_octant) ((_octant) & YMAJOR)
|
||||
#define IsXDecreasingOctant(_octant) ((_octant) & XDECREASING)
|
||||
#define IsYDecreasingOctant(_octant) ((_octant) & YDECREASING)
|
||||
|
||||
extern int miZeroLineScreenIndex;
|
||||
|
||||
extern int miZeroClipLine(
|
||||
#if NeedFunctionPrototypes
|
||||
int /*xmin*/,
|
||||
int /*ymin*/,
|
||||
int /*xmax*/,
|
||||
int /*ymax*/,
|
||||
int * /*new_x1*/,
|
||||
int * /*new_y1*/,
|
||||
int * /*new_x2*/,
|
||||
int * /*new_y2*/,
|
||||
unsigned int /*adx*/,
|
||||
unsigned int /*ady*/,
|
||||
int * /*pt1_clipped*/,
|
||||
int * /*pt2_clipped*/,
|
||||
int /*octant*/,
|
||||
unsigned int /*bias*/,
|
||||
int /*oc1*/,
|
||||
int /*oc2*/
|
||||
#endif
|
||||
);
|
||||
|
||||
#endif /* MILINE_H */
|
77
gdk/linux-fb/mipoly.c
Normal file
77
gdk/linux-fb/mipoly.c
Normal file
@ -0,0 +1,77 @@
|
||||
/***********************************************************
|
||||
|
||||
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: mipoly.c /main/5 1998/02/09 14:48:16 kaleb $ */
|
||||
/*
|
||||
* mipoly.c
|
||||
*
|
||||
* Written by Brian Kelleher; June 1986
|
||||
*
|
||||
* Draw polygons. This routine translates the point by the
|
||||
* origin if pGC->miTranslate is non-zero, and calls
|
||||
* to the appropriate routine to actually scan convert the
|
||||
* polygon.
|
||||
*/
|
||||
#include "mi.h"
|
||||
|
||||
extern gboolean miFillGeneralPoly(
|
||||
#if NeedFunctionPrototypes
|
||||
GdkDrawable* /*dst*/,
|
||||
GdkGC* /*pgc*/,
|
||||
int /*count*/,
|
||||
GdkPoint* /*ptsIn*/
|
||||
#endif
|
||||
);
|
||||
|
||||
void
|
||||
miFillPolygon(dst, pgc, shape, mode, count, pPts)
|
||||
GdkDrawable* dst;
|
||||
register GdkGC* pgc;
|
||||
int shape, mode;
|
||||
register int count;
|
||||
GdkPoint* pPts;
|
||||
{
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
miFillGeneralPoly(dst, pgc, count, pPts);
|
||||
}
|
230
gdk/linux-fb/mipoly.h
Normal file
230
gdk/linux-fb/mipoly.h
Normal file
@ -0,0 +1,230 @@
|
||||
/* $TOG: mipoly.h /main/6 1998/02/09 14:48:20 kaleb $ */
|
||||
/*
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MIPOLY_H
|
||||
#define MIPOLY_H
|
||||
|
||||
#include "miscanfill.h"
|
||||
|
||||
/*
|
||||
* fill.h
|
||||
*
|
||||
* Created by Brian Kelleher; Oct 1985
|
||||
*
|
||||
* Include file for filled polygon routines.
|
||||
*
|
||||
* These are the data structures needed to scan
|
||||
* convert regions. Two different scan conversion
|
||||
* methods are available -- the even-odd method, and
|
||||
* the winding number method.
|
||||
* The even-odd rule states that a point is inside
|
||||
* the polygon if a ray drawn from that point in any
|
||||
* direction will pass through an odd number of
|
||||
* path segments.
|
||||
* By the winding number rule, a point is decided
|
||||
* to be inside the polygon if a ray drawn from that
|
||||
* point in any direction passes through a different
|
||||
* number of clockwise and counter-clockwise path
|
||||
* segments.
|
||||
*
|
||||
* These data structures are adapted somewhat from
|
||||
* the algorithm in (Foley/Van Dam) for scan converting
|
||||
* polygons.
|
||||
* The basic algorithm is to start at the top (smallest y)
|
||||
* of the polygon, stepping down to the bottom of
|
||||
* the polygon by incrementing the y coordinate. We
|
||||
* keep a list of edges which the current scanline crosses,
|
||||
* sorted by x. This list is called the Active Edge Table (AET)
|
||||
* As we change the y-coordinate, we update each entry in
|
||||
* in the active edge table to reflect the edges new xcoord.
|
||||
* This list must be sorted at each scanline in case
|
||||
* two edges intersect.
|
||||
* We also keep a data structure known as the Edge Table (ET),
|
||||
* which keeps track of all the edges which the current
|
||||
* scanline has not yet reached. The ET is basically a
|
||||
* list of ScanLineList structures containing a list of
|
||||
* edges which are entered at a given scanline. There is one
|
||||
* ScanLineList per scanline at which an edge is entered.
|
||||
* When we enter a new edge, we move it from the ET to the AET.
|
||||
*
|
||||
* From the AET, we can implement the even-odd rule as in
|
||||
* (Foley/Van Dam).
|
||||
* The winding number rule is a little trickier. We also
|
||||
* keep the EdgeTableEntries in the AET linked by the
|
||||
* nextWETE (winding EdgeTableEntry) link. This allows
|
||||
* the edges to be linked just as before for updating
|
||||
* purposes, but only uses the edges linked by the nextWETE
|
||||
* link as edges representing spans of the polygon to
|
||||
* drawn (as with the even-odd rule).
|
||||
*/
|
||||
|
||||
/*
|
||||
* for the winding number rule
|
||||
*/
|
||||
#define CLOCKWISE 1
|
||||
#define COUNTERCLOCKWISE -1
|
||||
|
||||
typedef struct _EdgeTableEntry {
|
||||
int ymax; /* ycoord at which we exit this edge. */
|
||||
BRESINFO bres; /* Bresenham info to run the edge */
|
||||
struct _EdgeTableEntry *next; /* next in the list */
|
||||
struct _EdgeTableEntry *back; /* for insertion sort */
|
||||
struct _EdgeTableEntry *nextWETE; /* for winding num rule */
|
||||
int ClockWise; /* flag for winding number rule */
|
||||
} EdgeTableEntry;
|
||||
|
||||
|
||||
typedef struct _ScanLineList{
|
||||
int scanline; /* the scanline represented */
|
||||
EdgeTableEntry *edgelist; /* header node */
|
||||
struct _ScanLineList *next; /* next in the list */
|
||||
} ScanLineList;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int ymax; /* ymax for the polygon */
|
||||
int ymin; /* ymin for the polygon */
|
||||
ScanLineList scanlines; /* header node */
|
||||
} EdgeTable;
|
||||
|
||||
|
||||
/*
|
||||
* Here is a struct to help with storage allocation
|
||||
* so we can allocate a big chunk at a time, and then take
|
||||
* pieces from this heap when we need to.
|
||||
*/
|
||||
#define SLLSPERBLOCK 25
|
||||
|
||||
typedef struct _ScanLineListBlock {
|
||||
ScanLineList SLLs[SLLSPERBLOCK];
|
||||
struct _ScanLineListBlock *next;
|
||||
} ScanLineListBlock;
|
||||
|
||||
/*
|
||||
* number of points to buffer before sending them off
|
||||
* to scanlines() : Must be an even number
|
||||
*/
|
||||
#define NUMPTSTOBUFFER 200
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* a few macros for the inner loops of the fill code where
|
||||
* performance considerations don't allow a procedure call.
|
||||
*
|
||||
* Evaluate the given edge at the given scanline.
|
||||
* If the edge has expired, then we leave it and fix up
|
||||
* the active edge table; otherwise, we increment the
|
||||
* x value to be ready for the next scanline.
|
||||
* The winding number rule is in effect, so we must notify
|
||||
* the caller when the edge has been removed so he
|
||||
* can reorder the Winding Active Edge Table.
|
||||
*/
|
||||
#define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \
|
||||
if (pAET->ymax == y) { /* leaving this edge */ \
|
||||
pPrevAET->next = pAET->next; \
|
||||
pAET = pPrevAET->next; \
|
||||
fixWAET = 1; \
|
||||
if (pAET) \
|
||||
pAET->back = pPrevAET; \
|
||||
} \
|
||||
else { \
|
||||
BRESINCRPGONSTRUCT(pAET->bres); \
|
||||
pPrevAET = pAET; \
|
||||
pAET = pAET->next; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Evaluate the given edge at the given scanline.
|
||||
* If the edge has expired, then we leave it and fix up
|
||||
* the active edge table; otherwise, we increment the
|
||||
* x value to be ready for the next scanline.
|
||||
* The even-odd rule is in effect.
|
||||
*/
|
||||
#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \
|
||||
if (pAET->ymax == y) { /* leaving this edge */ \
|
||||
pPrevAET->next = pAET->next; \
|
||||
pAET = pPrevAET->next; \
|
||||
if (pAET) \
|
||||
pAET->back = pPrevAET; \
|
||||
} \
|
||||
else { \
|
||||
BRESINCRPGONSTRUCT(pAET->bres); \
|
||||
pPrevAET = pAET; \
|
||||
pAET = pAET->next; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* mipolyutil.c */
|
||||
|
||||
extern gboolean miInsertEdgeInET(
|
||||
#if NeedFunctionPrototypes
|
||||
EdgeTable * /*ET*/,
|
||||
EdgeTableEntry * /*ETE*/,
|
||||
int /*scanline*/,
|
||||
ScanLineListBlock ** /*SLLBlock*/,
|
||||
int * /*iSLLBlock*/
|
||||
#endif
|
||||
);
|
||||
|
||||
extern gboolean miCreateETandAET(
|
||||
#if NeedFunctionPrototypes
|
||||
int /*count*/,
|
||||
GdkPoint* /*pts*/,
|
||||
EdgeTable * /*ET*/,
|
||||
EdgeTableEntry * /*AET*/,
|
||||
EdgeTableEntry * /*pETEs*/,
|
||||
ScanLineListBlock * /*pSLLBlock*/
|
||||
#endif
|
||||
);
|
||||
|
||||
extern void miloadAET(
|
||||
#if NeedFunctionPrototypes
|
||||
EdgeTableEntry * /*AET*/,
|
||||
EdgeTableEntry * /*ETEs*/
|
||||
#endif
|
||||
);
|
||||
|
||||
extern void micomputeWAET(
|
||||
#if NeedFunctionPrototypes
|
||||
EdgeTableEntry * /*AET*/
|
||||
#endif
|
||||
);
|
||||
|
||||
extern int miInsertionSort(
|
||||
#if NeedFunctionPrototypes
|
||||
EdgeTableEntry * /*AET*/
|
||||
#endif
|
||||
);
|
||||
|
||||
extern void miFreeStorage(
|
||||
#if NeedFunctionPrototypes
|
||||
ScanLineListBlock * /*pSLLBlock*/
|
||||
#endif
|
||||
);
|
||||
|
||||
#endif
|
214
gdk/linux-fb/mipolygen.c
Normal file
214
gdk/linux-fb/mipolygen.c
Normal file
@ -0,0 +1,214 @@
|
||||
/***********************************************************
|
||||
|
||||
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: mipolygen.c /main/9 1998/02/09 14:47:51 kaleb $ */
|
||||
#include "mi.h"
|
||||
#include "mipoly.h"
|
||||
|
||||
/*
|
||||
*
|
||||
* Written by Brian Kelleher; Oct. 1985
|
||||
*
|
||||
* Routine to fill a polygon. Two fill rules are
|
||||
* supported: frWINDING and frEVENODD.
|
||||
*
|
||||
* See fillpoly.h for a complete description of the algorithm.
|
||||
*/
|
||||
|
||||
gboolean
|
||||
miFillGeneralPoly(dst, pgc, count, ptsIn)
|
||||
GdkDrawable* dst;
|
||||
GdkGC* pgc;
|
||||
int count; /* number of points */
|
||||
GdkPoint* ptsIn; /* the points */
|
||||
{
|
||||
register EdgeTableEntry *pAET; /* the Active Edge Table */
|
||||
register int y; /* the current scanline */
|
||||
register int nPts = 0; /* number of pts in buffer */
|
||||
register EdgeTableEntry *pWETE; /* Winding Edge Table */
|
||||
register ScanLineList *pSLL; /* Current ScanLineList */
|
||||
register GdkRectangle* ptsOut; /* ptr to output buffers */
|
||||
GdkRectangle FirstPoint[NUMPTSTOBUFFER]; /* the output buffers */
|
||||
EdgeTableEntry *pPrevAET; /* previous AET entry */
|
||||
EdgeTable ET; /* Edge Table header node */
|
||||
EdgeTableEntry AET; /* Active ET header node */
|
||||
EdgeTableEntry *pETEs; /* Edge Table Entries buff */
|
||||
ScanLineListBlock SLLBlock; /* header for ScanLineList */
|
||||
int fixWAET = 0;
|
||||
|
||||
if (count < 3)
|
||||
return(TRUE);
|
||||
|
||||
if(!(pETEs = (EdgeTableEntry *)
|
||||
ALLOCATE_LOCAL(sizeof(EdgeTableEntry) * count)))
|
||||
return(FALSE);
|
||||
ptsOut = FirstPoint;
|
||||
if (!miCreateETandAET(count, ptsIn, &ET, &AET, pETEs, &SLLBlock))
|
||||
{
|
||||
DEALLOCATE_LOCAL(pETEs);
|
||||
return(FALSE);
|
||||
}
|
||||
pSLL = ET.scanlines.next;
|
||||
|
||||
if (0 /* pgc->fillRule == EvenOddRule */)
|
||||
{
|
||||
/*
|
||||
* for each scanline
|
||||
*/
|
||||
for (y = ET.ymin; y < ET.ymax; y++)
|
||||
{
|
||||
/*
|
||||
* Add a new edge to the active edge table when we
|
||||
* get to the next edge.
|
||||
*/
|
||||
if (pSLL && y == pSLL->scanline)
|
||||
{
|
||||
miloadAET(&AET, pSLL->edgelist);
|
||||
pSLL = pSLL->next;
|
||||
}
|
||||
pPrevAET = &AET;
|
||||
pAET = AET.next;
|
||||
|
||||
/*
|
||||
* for each active edge
|
||||
*/
|
||||
while (pAET)
|
||||
{
|
||||
ptsOut->x = pAET->bres.minor;
|
||||
ptsOut->width = pAET->next->bres.minor - pAET->bres.minor;
|
||||
ptsOut->height = 1;
|
||||
ptsOut++->y = y;
|
||||
nPts++;
|
||||
|
||||
/*
|
||||
* send out the buffer when its full
|
||||
*/
|
||||
if (nPts == NUMPTSTOBUFFER)
|
||||
{
|
||||
gdk_fb_fill_spans(dst, pgc, FirstPoint, nPts);
|
||||
ptsOut = FirstPoint;
|
||||
nPts = 0;
|
||||
}
|
||||
EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
|
||||
EVALUATEEDGEEVENODD(pAET, pPrevAET, y);
|
||||
}
|
||||
miInsertionSort(&AET);
|
||||
}
|
||||
}
|
||||
else /* default to WindingNumber */
|
||||
{
|
||||
/*
|
||||
* for each scanline
|
||||
*/
|
||||
for (y = ET.ymin; y < ET.ymax; y++)
|
||||
{
|
||||
/*
|
||||
* Add a new edge to the active edge table when we
|
||||
* get to the next edge.
|
||||
*/
|
||||
if (pSLL && y == pSLL->scanline)
|
||||
{
|
||||
miloadAET(&AET, pSLL->edgelist);
|
||||
micomputeWAET(&AET);
|
||||
pSLL = pSLL->next;
|
||||
}
|
||||
pPrevAET = &AET;
|
||||
pAET = AET.next;
|
||||
pWETE = pAET;
|
||||
|
||||
/*
|
||||
* for each active edge
|
||||
*/
|
||||
while (pAET)
|
||||
{
|
||||
/*
|
||||
* if the next edge in the active edge table is
|
||||
* also the next edge in the winding active edge
|
||||
* table.
|
||||
*/
|
||||
if (pWETE == pAET)
|
||||
{
|
||||
ptsOut->x = pAET->bres.minor;
|
||||
ptsOut->width = pAET->nextWETE->bres.minor - pAET->bres.minor;
|
||||
ptsOut->height = 1;
|
||||
ptsOut++->y = y;
|
||||
nPts++;
|
||||
|
||||
/*
|
||||
* send out the buffer
|
||||
*/
|
||||
if (nPts == NUMPTSTOBUFFER)
|
||||
{
|
||||
gdk_fb_fill_spans(dst, pgc, FirstPoint, nPts);
|
||||
ptsOut = FirstPoint;
|
||||
nPts = 0;
|
||||
}
|
||||
|
||||
pWETE = pWETE->nextWETE;
|
||||
while (pWETE != pAET)
|
||||
EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET);
|
||||
pWETE = pWETE->nextWETE;
|
||||
}
|
||||
EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET);
|
||||
}
|
||||
|
||||
/*
|
||||
* reevaluate the Winding active edge table if we
|
||||
* just had to resort it or if we just exited an edge.
|
||||
*/
|
||||
if (miInsertionSort(&AET) || fixWAET)
|
||||
{
|
||||
micomputeWAET(&AET);
|
||||
fixWAET = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get any spans that we missed by buffering
|
||||
*/
|
||||
if(nPts > 0)
|
||||
gdk_fb_fill_spans(dst, pgc, FirstPoint, nPts);
|
||||
DEALLOCATE_LOCAL(pETEs);
|
||||
miFreeStorage(SLLBlock.next);
|
||||
return(TRUE);
|
||||
}
|
392
gdk/linux-fb/mipolyutil.c
Normal file
392
gdk/linux-fb/mipolyutil.c
Normal file
@ -0,0 +1,392 @@
|
||||
/* $XFree86: xc/programs/Xserver/mi/mipolyutil.c,v 1.7 1998/10/04 09:39:31 dawes Exp $ */
|
||||
/***********************************************************
|
||||
|
||||
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: mipolyutil.c /main/6 1998/02/09 14:48:12 kaleb $ */
|
||||
#include <limits.h>
|
||||
#include "mi.h"
|
||||
#include "miscanfill.h"
|
||||
#include "mipoly.h"
|
||||
|
||||
/*
|
||||
* fillUtils.c
|
||||
*
|
||||
* Written by Brian Kelleher; Oct. 1985
|
||||
*
|
||||
* This module contains all of the utility functions
|
||||
* needed to scan convert a polygon.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* InsertEdgeInET
|
||||
*
|
||||
* Insert the given edge into the edge table.
|
||||
* First we must find the correct bucket in the
|
||||
* Edge table, then find the right slot in the
|
||||
* bucket. Finally, we can insert it.
|
||||
*
|
||||
*/
|
||||
gboolean
|
||||
miInsertEdgeInET(ET, ETE, scanline, SLLBlock, iSLLBlock)
|
||||
EdgeTable *ET;
|
||||
EdgeTableEntry *ETE;
|
||||
int scanline;
|
||||
ScanLineListBlock **SLLBlock;
|
||||
int *iSLLBlock;
|
||||
{
|
||||
register EdgeTableEntry *start, *prev;
|
||||
register ScanLineList *pSLL, *pPrevSLL;
|
||||
ScanLineListBlock *tmpSLLBlock;
|
||||
|
||||
/*
|
||||
* find the right bucket to put the edge into
|
||||
*/
|
||||
pPrevSLL = &ET->scanlines;
|
||||
pSLL = pPrevSLL->next;
|
||||
while (pSLL && (pSLL->scanline < scanline))
|
||||
{
|
||||
pPrevSLL = pSLL;
|
||||
pSLL = pSLL->next;
|
||||
}
|
||||
|
||||
/*
|
||||
* reassign pSLL (pointer to ScanLineList) if necessary
|
||||
*/
|
||||
if ((!pSLL) || (pSLL->scanline > scanline))
|
||||
{
|
||||
if (*iSLLBlock > SLLSPERBLOCK-1)
|
||||
{
|
||||
tmpSLLBlock =
|
||||
(ScanLineListBlock *)g_malloc(sizeof(ScanLineListBlock));
|
||||
if (!tmpSLLBlock)
|
||||
return FALSE;
|
||||
(*SLLBlock)->next = tmpSLLBlock;
|
||||
tmpSLLBlock->next = (ScanLineListBlock *)NULL;
|
||||
*SLLBlock = tmpSLLBlock;
|
||||
*iSLLBlock = 0;
|
||||
}
|
||||
pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
|
||||
|
||||
pSLL->next = pPrevSLL->next;
|
||||
pSLL->edgelist = (EdgeTableEntry *)NULL;
|
||||
pPrevSLL->next = pSLL;
|
||||
}
|
||||
pSLL->scanline = scanline;
|
||||
|
||||
/*
|
||||
* now insert the edge in the right bucket
|
||||
*/
|
||||
prev = (EdgeTableEntry *)NULL;
|
||||
start = pSLL->edgelist;
|
||||
while (start && (start->bres.minor < ETE->bres.minor))
|
||||
{
|
||||
prev = start;
|
||||
start = start->next;
|
||||
}
|
||||
ETE->next = start;
|
||||
|
||||
if (prev)
|
||||
prev->next = ETE;
|
||||
else
|
||||
pSLL->edgelist = ETE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* CreateEdgeTable
|
||||
*
|
||||
* This routine creates the edge table for
|
||||
* scan converting polygons.
|
||||
* The Edge Table (ET) looks like:
|
||||
*
|
||||
* EdgeTable
|
||||
* --------
|
||||
* | ymax | ScanLineLists
|
||||
* |scanline|-->------------>-------------->...
|
||||
* -------- |scanline| |scanline|
|
||||
* |edgelist| |edgelist|
|
||||
* --------- ---------
|
||||
* | |
|
||||
* | |
|
||||
* V V
|
||||
* list of ETEs list of ETEs
|
||||
*
|
||||
* where ETE is an EdgeTableEntry data structure,
|
||||
* and there is one ScanLineList per scanline at
|
||||
* which an edge is initially entered.
|
||||
*
|
||||
*/
|
||||
|
||||
gboolean
|
||||
miCreateETandAET(count, pts, ET, AET, pETEs, pSLLBlock)
|
||||
register int count;
|
||||
register GdkPoint* pts;
|
||||
EdgeTable *ET;
|
||||
EdgeTableEntry *AET;
|
||||
register EdgeTableEntry *pETEs;
|
||||
ScanLineListBlock *pSLLBlock;
|
||||
{
|
||||
register GdkPoint* top, *bottom;
|
||||
register GdkPoint* PrevPt, *CurrPt;
|
||||
int iSLLBlock = 0;
|
||||
|
||||
int dy;
|
||||
|
||||
if (count < 2) return TRUE;
|
||||
|
||||
/*
|
||||
* initialize the Active Edge Table
|
||||
*/
|
||||
AET->next = (EdgeTableEntry *)NULL;
|
||||
AET->back = (EdgeTableEntry *)NULL;
|
||||
AET->nextWETE = (EdgeTableEntry *)NULL;
|
||||
AET->bres.minor = INT_MIN;
|
||||
|
||||
/*
|
||||
* initialize the Edge Table.
|
||||
*/
|
||||
ET->scanlines.next = (ScanLineList *)NULL;
|
||||
ET->ymax = INT_MIN;
|
||||
ET->ymin = INT_MAX;
|
||||
pSLLBlock->next = (ScanLineListBlock *)NULL;
|
||||
|
||||
PrevPt = &pts[count-1];
|
||||
|
||||
/*
|
||||
* for each vertex in the array of points.
|
||||
* In this loop we are dealing with two vertices at
|
||||
* a time -- these make up one edge of the polygon.
|
||||
*/
|
||||
while (count--)
|
||||
{
|
||||
CurrPt = pts++;
|
||||
|
||||
/*
|
||||
* find out which point is above and which is below.
|
||||
*/
|
||||
if (PrevPt->y > CurrPt->y)
|
||||
{
|
||||
bottom = PrevPt, top = CurrPt;
|
||||
pETEs->ClockWise = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bottom = CurrPt, top = PrevPt;
|
||||
pETEs->ClockWise = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* don't add horizontal edges to the Edge table.
|
||||
*/
|
||||
if (bottom->y != top->y)
|
||||
{
|
||||
pETEs->ymax = bottom->y-1; /* -1 so we don't get last scanline */
|
||||
|
||||
/*
|
||||
* initialize integer edge algorithm
|
||||
*/
|
||||
dy = bottom->y - top->y;
|
||||
BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres);
|
||||
|
||||
if (!miInsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock))
|
||||
{
|
||||
miFreeStorage(pSLLBlock->next);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ET->ymax = MAX(ET->ymax, PrevPt->y);
|
||||
ET->ymin = MIN(ET->ymin, PrevPt->y);
|
||||
pETEs++;
|
||||
}
|
||||
|
||||
PrevPt = CurrPt;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* loadAET
|
||||
*
|
||||
* This routine moves EdgeTableEntries from the
|
||||
* EdgeTable into the Active Edge Table,
|
||||
* leaving them sorted by smaller x coordinate.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
miloadAET(AET, ETEs)
|
||||
register EdgeTableEntry *AET, *ETEs;
|
||||
{
|
||||
register EdgeTableEntry *pPrevAET;
|
||||
register EdgeTableEntry *tmp;
|
||||
|
||||
pPrevAET = AET;
|
||||
AET = AET->next;
|
||||
while (ETEs)
|
||||
{
|
||||
while (AET && (AET->bres.minor < ETEs->bres.minor))
|
||||
{
|
||||
pPrevAET = AET;
|
||||
AET = AET->next;
|
||||
}
|
||||
tmp = ETEs->next;
|
||||
ETEs->next = AET;
|
||||
if (AET)
|
||||
AET->back = ETEs;
|
||||
ETEs->back = pPrevAET;
|
||||
pPrevAET->next = ETEs;
|
||||
pPrevAET = ETEs;
|
||||
|
||||
ETEs = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* computeWAET
|
||||
*
|
||||
* This routine links the AET by the
|
||||
* nextWETE (winding EdgeTableEntry) link for
|
||||
* use by the winding number rule. The final
|
||||
* Active Edge Table (AET) might look something
|
||||
* like:
|
||||
*
|
||||
* AET
|
||||
* ---------- --------- ---------
|
||||
* |ymax | |ymax | |ymax |
|
||||
* | ... | |... | |... |
|
||||
* |next |->|next |->|next |->...
|
||||
* |nextWETE| |nextWETE| |nextWETE|
|
||||
* --------- --------- ^--------
|
||||
* | | |
|
||||
* V-------------------> V---> ...
|
||||
*
|
||||
*/
|
||||
void
|
||||
micomputeWAET(AET)
|
||||
register EdgeTableEntry *AET;
|
||||
{
|
||||
register EdgeTableEntry *pWETE;
|
||||
register int inside = 1;
|
||||
register int isInside = 0;
|
||||
|
||||
AET->nextWETE = (EdgeTableEntry *)NULL;
|
||||
pWETE = AET;
|
||||
AET = AET->next;
|
||||
while (AET)
|
||||
{
|
||||
if (AET->ClockWise)
|
||||
isInside++;
|
||||
else
|
||||
isInside--;
|
||||
|
||||
if ((!inside && !isInside) ||
|
||||
( inside && isInside))
|
||||
{
|
||||
pWETE->nextWETE = AET;
|
||||
pWETE = AET;
|
||||
inside = !inside;
|
||||
}
|
||||
AET = AET->next;
|
||||
}
|
||||
pWETE->nextWETE = (EdgeTableEntry *)NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* InsertionSort
|
||||
*
|
||||
* Just a simple insertion sort using
|
||||
* pointers and back pointers to sort the Active
|
||||
* Edge Table.
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
miInsertionSort(AET)
|
||||
register EdgeTableEntry *AET;
|
||||
{
|
||||
register EdgeTableEntry *pETEchase;
|
||||
register EdgeTableEntry *pETEinsert;
|
||||
register EdgeTableEntry *pETEchaseBackTMP;
|
||||
register int changed = 0;
|
||||
|
||||
AET = AET->next;
|
||||
while (AET)
|
||||
{
|
||||
pETEinsert = AET;
|
||||
pETEchase = AET;
|
||||
while (pETEchase->back->bres.minor > AET->bres.minor)
|
||||
pETEchase = pETEchase->back;
|
||||
|
||||
AET = AET->next;
|
||||
if (pETEchase != pETEinsert)
|
||||
{
|
||||
pETEchaseBackTMP = pETEchase->back;
|
||||
pETEinsert->back->next = AET;
|
||||
if (AET)
|
||||
AET->back = pETEinsert->back;
|
||||
pETEinsert->next = pETEchase;
|
||||
pETEchase->back->next = pETEinsert;
|
||||
pETEchase->back = pETEinsert;
|
||||
pETEinsert->back = pETEchaseBackTMP;
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
return(changed);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up our act.
|
||||
*/
|
||||
void
|
||||
miFreeStorage(pSLLBlock)
|
||||
register ScanLineListBlock *pSLLBlock;
|
||||
{
|
||||
register ScanLineListBlock *tmpSLLBlock;
|
||||
|
||||
while (pSLLBlock)
|
||||
{
|
||||
tmpSLLBlock = pSLLBlock->next;
|
||||
g_free(pSLLBlock);
|
||||
pSLLBlock = tmpSLLBlock;
|
||||
}
|
||||
}
|
139
gdk/linux-fb/miscanfill.h
Normal file
139
gdk/linux-fb/miscanfill.h
Normal file
@ -0,0 +1,139 @@
|
||||
/* $TOG: miscanfill.h /main/6 1998/02/09 14:48:35 kaleb $ */
|
||||
/*
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SCANFILLINCLUDED
|
||||
#define SCANFILLINCLUDED
|
||||
/*
|
||||
* scanfill.h
|
||||
*
|
||||
* Written by Brian Kelleher; Jan 1985
|
||||
*
|
||||
* This file contains a few macros to help track
|
||||
* the edge of a filled object. The object is assumed
|
||||
* to be filled in scanline order, and thus the
|
||||
* algorithm used is an extension of Bresenham's line
|
||||
* drawing algorithm which assumes that y is always the
|
||||
* major axis.
|
||||
* Since these pieces of code are the same for any filled shape,
|
||||
* it is more convenient to gather the library in one
|
||||
* place, but since these pieces of code are also in
|
||||
* the inner loops of output primitives, procedure call
|
||||
* overhead is out of the question.
|
||||
* See the author for a derivation if needed.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* In scan converting polygons, we want to choose those pixels
|
||||
* which are inside the polygon. Thus, we add .5 to the starting
|
||||
* x coordinate for both left and right edges. Now we choose the
|
||||
* first pixel which is inside the pgon for the left edge and the
|
||||
* first pixel which is outside the pgon for the right edge.
|
||||
* Draw the left pixel, but not the right.
|
||||
*
|
||||
* How to add .5 to the starting x coordinate:
|
||||
* If the edge is moving to the right, then subtract dy from the
|
||||
* error term from the general form of the algorithm.
|
||||
* If the edge is moving to the left, then add dy to the error term.
|
||||
*
|
||||
* The reason for the difference between edges moving to the left
|
||||
* and edges moving to the right is simple: If an edge is moving
|
||||
* to the right, then we want the algorithm to flip immediately.
|
||||
* If it is moving to the left, then we don't want it to flip until
|
||||
* we traverse an entire pixel.
|
||||
*/
|
||||
#define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \
|
||||
int dx; /* local storage */ \
|
||||
\
|
||||
/* \
|
||||
* if the edge is horizontal, then it is ignored \
|
||||
* and assumed not to be processed. Otherwise, do this stuff. \
|
||||
*/ \
|
||||
if ((dy) != 0) { \
|
||||
xStart = (x1); \
|
||||
dx = (x2) - xStart; \
|
||||
if (dx < 0) { \
|
||||
m = dx / (dy); \
|
||||
m1 = m - 1; \
|
||||
incr1 = -2 * dx + 2 * (dy) * m1; \
|
||||
incr2 = -2 * dx + 2 * (dy) * m; \
|
||||
d = 2 * m * (dy) - 2 * dx - 2 * (dy); \
|
||||
} else { \
|
||||
m = dx / (dy); \
|
||||
m1 = m + 1; \
|
||||
incr1 = 2 * dx - 2 * (dy) * m1; \
|
||||
incr2 = 2 * dx - 2 * (dy) * m; \
|
||||
d = -2 * m * (dy) + 2 * dx; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \
|
||||
if (m1 > 0) { \
|
||||
if (d > 0) { \
|
||||
minval += m1; \
|
||||
d += incr1; \
|
||||
} \
|
||||
else { \
|
||||
minval += m; \
|
||||
d += incr2; \
|
||||
} \
|
||||
} else {\
|
||||
if (d >= 0) { \
|
||||
minval += m1; \
|
||||
d += incr1; \
|
||||
} \
|
||||
else { \
|
||||
minval += m; \
|
||||
d += incr2; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This structure contains all of the information needed
|
||||
* to run the bresenham algorithm.
|
||||
* The variables may be hardcoded into the declarations
|
||||
* instead of using this structure to make use of
|
||||
* register declarations.
|
||||
*/
|
||||
typedef struct {
|
||||
int minor; /* minor axis */
|
||||
int d; /* decision variable */
|
||||
int m, m1; /* slope and slope+1 */
|
||||
int incr1, incr2; /* error increments */
|
||||
} BRESINFO;
|
||||
|
||||
|
||||
#define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \
|
||||
BRESINITPGON(dmaj, min1, min2, bres.minor, bres.d, \
|
||||
bres.m, bres.m1, bres.incr1, bres.incr2)
|
||||
|
||||
#define BRESINCRPGONSTRUCT(bres) \
|
||||
BRESINCRPGON(bres.d, bres.minor, bres.m, bres.m1, bres.incr1, bres.incr2)
|
||||
|
||||
|
||||
#endif
|
507
gdk/linux-fb/mispans.c
Normal file
507
gdk/linux-fb/mispans.c
Normal file
@ -0,0 +1,507 @@
|
||||
/* $XFree86: xc/programs/Xserver/mi/mispans.c,v 3.1 1998/10/04 09:39:33 dawes Exp $ */
|
||||
/***********************************************************
|
||||
|
||||
Copyright 1989, 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 1989 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: mispans.c /main/7 1998/02/09 14:48:44 kaleb $ */
|
||||
|
||||
#include "mi.h"
|
||||
#include "mispans.h"
|
||||
#include <string.h> /* for memmove */
|
||||
|
||||
/*
|
||||
|
||||
These routines maintain lists of Spans, in order to implement the
|
||||
``touch-each-pixel-once'' rules of wide lines and arcs.
|
||||
|
||||
Written by Joel McCormack, Summer 1989.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
void miInitSpanGroup(spanGroup)
|
||||
SpanGroup *spanGroup;
|
||||
{
|
||||
spanGroup->size = 0;
|
||||
spanGroup->count = 0;
|
||||
spanGroup->group = NULL;
|
||||
spanGroup->ymin = SHRT_MAX;
|
||||
spanGroup->ymax = SHRT_MIN;
|
||||
} /* InitSpanGroup */
|
||||
|
||||
#define YMIN(spans) (spans->points[0].y)
|
||||
#define YMAX(spans) (spans->points[spans->count-1].y)
|
||||
|
||||
void miSubtractSpans (spanGroup, sub)
|
||||
SpanGroup *spanGroup;
|
||||
Spans *sub;
|
||||
{
|
||||
int i, subCount, spansCount;
|
||||
int ymin, ymax, xmin, xmax;
|
||||
Spans *spans;
|
||||
GdkRectangle* subPt, *spansPt;
|
||||
int extra;
|
||||
|
||||
ymin = YMIN(sub);
|
||||
ymax = YMAX(sub);
|
||||
spans = spanGroup->group;
|
||||
for (i = spanGroup->count; i; i--, spans++) {
|
||||
if (YMIN(spans) <= ymax && ymin <= YMAX(spans)) {
|
||||
subCount = sub->count;
|
||||
subPt = sub->points;
|
||||
spansCount = spans->count;
|
||||
spansPt = spans->points;
|
||||
extra = 0;
|
||||
for (;;)
|
||||
{
|
||||
while (spansCount && spansPt->y < subPt->y)
|
||||
{
|
||||
spansPt++; spansCount--;
|
||||
}
|
||||
if (!spansCount)
|
||||
break;
|
||||
while (subCount && subPt->y < spansPt->y)
|
||||
{
|
||||
subPt++; subCount--;
|
||||
}
|
||||
if (!subCount)
|
||||
break;
|
||||
if (subPt->y == spansPt->y)
|
||||
{
|
||||
xmin = subPt->x;
|
||||
xmax = xmin + subPt->width;
|
||||
if (xmin >= (spansPt->x + spansPt->width) || spansPt->x >= xmax)
|
||||
{
|
||||
;
|
||||
}
|
||||
else if (xmin <= spansPt->x)
|
||||
{
|
||||
if (xmax >= (spansPt->x + spansPt->width))
|
||||
{
|
||||
g_memmove (spansPt, spansPt + 1, sizeof *spansPt * (spansCount - 1));
|
||||
spansPt--;
|
||||
spans->count--;
|
||||
extra++;
|
||||
}
|
||||
else
|
||||
{
|
||||
spansPt->width -= xmax - spansPt->x;
|
||||
spansPt->x = xmax;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (xmax >= (spansPt->x + spansPt->width))
|
||||
{
|
||||
spansPt->width = xmin - spansPt->x;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!extra) {
|
||||
GdkRectangle* newPt;
|
||||
|
||||
#define EXTRA 8
|
||||
newPt = (GdkRectangle*) g_realloc (spans->points, (spans->count + EXTRA) * sizeof (GdkRectangle));
|
||||
if (!newPt)
|
||||
break;
|
||||
spansPt = newPt + (spansPt - spans->points);
|
||||
spans->points = newPt;
|
||||
extra = EXTRA;
|
||||
}
|
||||
g_memmove (spansPt + 1, spansPt, sizeof *spansPt * (spansCount));
|
||||
spans->count++;
|
||||
extra--;
|
||||
spansPt->width = xmin - spansPt->x;
|
||||
spansPt->height = 1;
|
||||
spansPt++;
|
||||
spansPt->width -= xmax - spansPt->x;
|
||||
spansPt->height = 1;
|
||||
spansPt->x = xmax;
|
||||
}
|
||||
}
|
||||
}
|
||||
spansPt++; spansCount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void miAppendSpans(spanGroup, otherGroup, spans)
|
||||
SpanGroup *spanGroup;
|
||||
SpanGroup *otherGroup;
|
||||
Spans *spans;
|
||||
{
|
||||
register int ymin, ymax;
|
||||
register int spansCount;
|
||||
|
||||
spansCount = spans->count;
|
||||
if (spansCount > 0) {
|
||||
if (spanGroup->size == spanGroup->count) {
|
||||
spanGroup->size = (spanGroup->size + 8) * 2;
|
||||
spanGroup->group = (Spans *)
|
||||
g_realloc(spanGroup->group, sizeof(Spans) * spanGroup->size);
|
||||
}
|
||||
|
||||
spanGroup->group[spanGroup->count] = *spans;
|
||||
(spanGroup->count)++;
|
||||
ymin = spans->points[0].y;
|
||||
if (ymin < spanGroup->ymin) spanGroup->ymin = ymin;
|
||||
ymax = spans->points[spansCount - 1].y;
|
||||
if (ymax > spanGroup->ymax) spanGroup->ymax = ymax;
|
||||
if (otherGroup &&
|
||||
otherGroup->ymin < ymax &&
|
||||
ymin < otherGroup->ymax)
|
||||
{
|
||||
miSubtractSpans (otherGroup, spans);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free (spans->points);
|
||||
}
|
||||
} /* AppendSpans */
|
||||
|
||||
void miFreeSpanGroup(spanGroup)
|
||||
SpanGroup *spanGroup;
|
||||
{
|
||||
if (spanGroup->group != NULL) g_free(spanGroup->group);
|
||||
}
|
||||
|
||||
static void QuickSortSpansX(points, numSpans)
|
||||
register GdkRectangle points[];
|
||||
register int numSpans;
|
||||
{
|
||||
register int x;
|
||||
register int i, j, m;
|
||||
register GdkRectangle* r;
|
||||
|
||||
/* Always called with numSpans > 1 */
|
||||
/* Sorts only by x, as all y should be the same */
|
||||
|
||||
#define ExchangeSpans(a, b) \
|
||||
{ \
|
||||
GdkRectangle tpt; \
|
||||
\
|
||||
tpt = points[a]; points[a] = points[b]; points[b] = tpt; \
|
||||
}
|
||||
|
||||
do {
|
||||
if (numSpans < 9) {
|
||||
/* Do insertion sort */
|
||||
register int xprev;
|
||||
|
||||
xprev = points[0].x;
|
||||
i = 1;
|
||||
do { /* while i != numSpans */
|
||||
x = points[i].x;
|
||||
if (xprev > x) {
|
||||
/* points[i] is out of order. Move into proper location. */
|
||||
GdkRectangle tpt;
|
||||
int k;
|
||||
|
||||
for (j = 0; x >= points[j].x; j++) {}
|
||||
tpt = points[i];
|
||||
for (k = i; k != j; k--) {
|
||||
points[k] = points[k-1];
|
||||
}
|
||||
points[j] = tpt;
|
||||
x = points[i].x;
|
||||
} /* if out of order */
|
||||
xprev = x;
|
||||
i++;
|
||||
} while (i != numSpans);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Choose partition element, stick in location 0 */
|
||||
m = numSpans / 2;
|
||||
if (points[m].x > points[0].x) ExchangeSpans(m, 0);
|
||||
if (points[m].x > points[numSpans-1].x) ExchangeSpans(m, numSpans-1);
|
||||
if (points[m].x > points[0].x) ExchangeSpans(m, 0);
|
||||
x = points[0].x;
|
||||
|
||||
/* Partition array */
|
||||
i = 0;
|
||||
j = numSpans;
|
||||
do {
|
||||
r = &(points[i]);
|
||||
do {
|
||||
r++;
|
||||
i++;
|
||||
} while (i != numSpans && r->x < x);
|
||||
r = &(points[j]);
|
||||
do {
|
||||
r--;
|
||||
j--;
|
||||
} while (x < r->x);
|
||||
if (i < j) ExchangeSpans(i, j);
|
||||
} while (i < j);
|
||||
|
||||
/* Move partition element back to middle */
|
||||
ExchangeSpans(0, j);
|
||||
|
||||
/* Recurse */
|
||||
if (numSpans-j-1 > 1)
|
||||
QuickSortSpansX(&points[j+1], numSpans-j-1);
|
||||
numSpans = j;
|
||||
} while (numSpans > 1);
|
||||
} /* QuickSortSpans */
|
||||
|
||||
|
||||
static int UniquifySpansX(spans, newPoints, newWidths)
|
||||
Spans *spans;
|
||||
register GdkRectangle *newPoints;
|
||||
{
|
||||
register int newx1, newx2, oldpt, i, y;
|
||||
GdkRectangle *oldPoints, *startNewPoints = newPoints;
|
||||
|
||||
/* Always called with numSpans > 1 */
|
||||
/* Uniquify the spans, and stash them into newPoints and newWidths. Return the
|
||||
number of unique spans. */
|
||||
|
||||
|
||||
oldPoints = spans->points;
|
||||
|
||||
y = oldPoints->y;
|
||||
newx1 = oldPoints->x;
|
||||
newx2 = newx1 + oldPoints->width;
|
||||
|
||||
for (i = spans->count-1; i != 0; i--) {
|
||||
oldPoints++;
|
||||
oldpt = oldPoints->x;
|
||||
if (oldpt > newx2) {
|
||||
/* Write current span, start a new one */
|
||||
newPoints->x = newx1;
|
||||
newPoints->y = y;
|
||||
newPoints->width = newx2 - newx1;
|
||||
newPoints->height = 1;
|
||||
newPoints++;
|
||||
newx1 = oldpt;
|
||||
newx2 = oldpt + oldPoints->width;
|
||||
} else {
|
||||
/* extend current span, if old extends beyond new */
|
||||
oldpt = oldpt + oldPoints->width;
|
||||
if (oldpt > newx2) newx2 = oldpt;
|
||||
}
|
||||
} /* for */
|
||||
|
||||
/* Write final span */
|
||||
newPoints->x = newx1;
|
||||
newPoints->width = newx2 - newx1;
|
||||
newPoints->height = 1;
|
||||
newPoints->y = y;
|
||||
|
||||
return (newPoints - startNewPoints) + 1;
|
||||
} /* UniquifySpansX */
|
||||
|
||||
void
|
||||
miDisposeSpanGroup (spanGroup)
|
||||
SpanGroup *spanGroup;
|
||||
{
|
||||
int i;
|
||||
Spans *spans;
|
||||
|
||||
for (i = 0; i < spanGroup->count; i++)
|
||||
{
|
||||
spans = spanGroup->group + i;
|
||||
g_free (spans->points);
|
||||
}
|
||||
}
|
||||
|
||||
void miFillUniqueSpanGroup(pDraw, pGC, spanGroup)
|
||||
GdkDrawable* pDraw;
|
||||
GdkGC* pGC;
|
||||
SpanGroup *spanGroup;
|
||||
{
|
||||
register int i;
|
||||
register Spans *spans;
|
||||
register Spans *yspans;
|
||||
register int *ysizes;
|
||||
register int ymin, ylength;
|
||||
|
||||
/* Outgoing spans for one big call to FillSpans */
|
||||
register GdkRectangle* points;
|
||||
register int count;
|
||||
|
||||
if (spanGroup->count == 0) return;
|
||||
|
||||
if (spanGroup->count == 1) {
|
||||
/* Already should be sorted, unique */
|
||||
spans = spanGroup->group;
|
||||
gdk_fb_fill_spans(pDraw, pGC, spans->points, spans->count);
|
||||
g_free(spans->points);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Yuck. Gross. Radix sort into y buckets, then sort x and uniquify */
|
||||
/* This seems to be the fastest thing to do. I've tried sorting on
|
||||
both x and y at the same time rather than creating into all those
|
||||
y buckets, but it was somewhat slower. */
|
||||
|
||||
ymin = spanGroup->ymin;
|
||||
ylength = spanGroup->ymax - ymin + 1;
|
||||
|
||||
/* Allocate Spans for y buckets */
|
||||
yspans = (Spans *) g_malloc(ylength * sizeof(Spans));
|
||||
ysizes = (int *) g_malloc(ylength * sizeof (int));
|
||||
|
||||
if (!yspans || !ysizes)
|
||||
{
|
||||
if (yspans)
|
||||
g_free (yspans);
|
||||
if (ysizes)
|
||||
g_free (ysizes);
|
||||
miDisposeSpanGroup (spanGroup);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i != ylength; i++) {
|
||||
ysizes[i] = 0;
|
||||
yspans[i].count = 0;
|
||||
yspans[i].points = NULL;
|
||||
}
|
||||
|
||||
/* Go through every single span and put it into the correct bucket */
|
||||
count = 0;
|
||||
for (i = 0, spans = spanGroup->group;
|
||||
i != spanGroup->count;
|
||||
i++, spans++) {
|
||||
int index;
|
||||
int j;
|
||||
|
||||
for (j = 0, points = spans->points;
|
||||
j != spans->count;
|
||||
j++, points++) {
|
||||
index = points->y - ymin;
|
||||
if (index >= 0 && index < ylength) {
|
||||
Spans *newspans = &(yspans[index]);
|
||||
if (newspans->count == ysizes[index]) {
|
||||
GdkRectangle* newpoints;
|
||||
ysizes[index] = (ysizes[index] + 8) * 2;
|
||||
newpoints = (GdkRectangle*) g_realloc(
|
||||
newspans->points,
|
||||
ysizes[index] * sizeof(GdkRectangle));
|
||||
if (!newpoints)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ylength; i++)
|
||||
{
|
||||
g_free (yspans[i].points);
|
||||
}
|
||||
g_free (yspans);
|
||||
g_free (ysizes);
|
||||
miDisposeSpanGroup (spanGroup);
|
||||
return;
|
||||
}
|
||||
newspans->points = newpoints;
|
||||
}
|
||||
newspans->points[newspans->count] = *points;
|
||||
(newspans->count)++;
|
||||
} /* if y value of span in range */
|
||||
} /* for j through spans */
|
||||
count += spans->count;
|
||||
g_free(spans->points);
|
||||
spans->points = NULL;
|
||||
} /* for i thorough Spans */
|
||||
|
||||
/* Now sort by x and uniquify each bucket into the final array */
|
||||
points = (GdkRectangle*) g_malloc(count * sizeof(GdkRectangle));
|
||||
if (!points)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ylength; i++)
|
||||
{
|
||||
g_free (yspans[i].points);
|
||||
}
|
||||
g_free (yspans);
|
||||
g_free (ysizes);
|
||||
if (points)
|
||||
g_free (points);
|
||||
return;
|
||||
}
|
||||
count = 0;
|
||||
for (i = 0; i != ylength; i++) {
|
||||
int ycount = yspans[i].count;
|
||||
if (ycount > 0) {
|
||||
if (ycount > 1) {
|
||||
QuickSortSpansX(yspans[i].points, ycount);
|
||||
count += UniquifySpansX
|
||||
(&(yspans[i]), &(points[count]));
|
||||
} else {
|
||||
points[count] = yspans[i].points[0];
|
||||
count++;
|
||||
}
|
||||
g_free(yspans[i].points);
|
||||
}
|
||||
}
|
||||
|
||||
gdk_fb_fill_spans(pDraw, pGC, points, count);
|
||||
g_free(points);
|
||||
g_free(yspans);
|
||||
g_free(ysizes); /* use (DE)ALLOCATE_LOCAL for these? */
|
||||
}
|
||||
|
||||
spanGroup->count = 0;
|
||||
spanGroup->ymin = SHRT_MAX;
|
||||
spanGroup->ymax = SHRT_MIN;
|
||||
}
|
||||
|
||||
|
||||
void miFillSpanGroup(pDraw, pGC, spanGroup)
|
||||
GdkDrawable* pDraw;
|
||||
GdkGC* pGC;
|
||||
SpanGroup *spanGroup;
|
||||
{
|
||||
register int i;
|
||||
register Spans *spans;
|
||||
|
||||
for (i = 0, spans = spanGroup->group; i != spanGroup->count; i++, spans++) {
|
||||
gdk_fb_fill_spans(pDraw, pGC, spans->points, spans->count);
|
||||
g_free(spans->points);
|
||||
}
|
||||
|
||||
spanGroup->count = 0;
|
||||
spanGroup->ymin = SHRT_MAX;
|
||||
spanGroup->ymax = SHRT_MIN;
|
||||
} /* FillSpanGroup */
|
127
gdk/linux-fb/mispans.h
Normal file
127
gdk/linux-fb/mispans.h
Normal file
@ -0,0 +1,127 @@
|
||||
/***********************************************************
|
||||
|
||||
Copyright 1989, 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 1989 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: mispans.h /main/5 1998/02/09 14:48:48 kaleb $ */
|
||||
|
||||
typedef struct {
|
||||
int count; /* number of spans */
|
||||
GdkRectangle* points; /* pointer to list of start points */
|
||||
} Spans;
|
||||
|
||||
typedef struct {
|
||||
int size; /* Total number of *Spans allocated */
|
||||
int count; /* Number of *Spans actually in group */
|
||||
Spans *group; /* List of Spans */
|
||||
int ymin, ymax; /* Min, max y values encountered */
|
||||
} SpanGroup;
|
||||
|
||||
/* Initialize SpanGroup. MUST BE DONE before use. */
|
||||
extern void miInitSpanGroup(
|
||||
#if NeedFunctionPrototypes
|
||||
SpanGroup * /*spanGroup*/
|
||||
#endif
|
||||
);
|
||||
|
||||
/* Add a Spans to a SpanGroup. The spans MUST BE in y-sorted order */
|
||||
extern void miAppendSpans(
|
||||
#if NeedFunctionPrototypes
|
||||
SpanGroup * /*spanGroup*/,
|
||||
SpanGroup * /*otherGroup*/,
|
||||
Spans * /*spans*/
|
||||
#endif
|
||||
);
|
||||
|
||||
/* Paint a span group, possibly with some overlap */
|
||||
extern void miFillSpanGroup(
|
||||
#if NeedFunctionPrototypes
|
||||
GdkDrawable* /*pDraw*/,
|
||||
GdkGC* /*pGC*/,
|
||||
SpanGroup * /*spanGroup*/
|
||||
#endif
|
||||
);
|
||||
|
||||
/* Paint a span group, insuring that each pixel is painted at most once */
|
||||
extern void miFillUniqueSpanGroup(
|
||||
#if NeedFunctionPrototypes
|
||||
GdkDrawable* /*pDraw*/,
|
||||
GdkGC* /*pGC*/,
|
||||
SpanGroup * /*spanGroup*/
|
||||
#endif
|
||||
);
|
||||
|
||||
/* Free up data in a span group. MUST BE DONE or you'll suffer memory leaks */
|
||||
extern void miFreeSpanGroup(
|
||||
#if NeedFunctionPrototypes
|
||||
SpanGroup * /*spanGroup*/
|
||||
#endif
|
||||
);
|
||||
|
||||
extern void miSubtractSpans(
|
||||
#if NeedFunctionPrototypes
|
||||
SpanGroup * /*spanGroup*/,
|
||||
Spans * /*sub*/
|
||||
#endif
|
||||
);
|
||||
|
||||
extern void miDisposeSpanGroup(
|
||||
#if NeedFunctionPrototypes
|
||||
SpanGroup * /*spanGroup*/
|
||||
#endif
|
||||
);
|
||||
|
||||
extern int miClipSpans(
|
||||
#if NeedFunctionPrototypes
|
||||
GdkRegion* /*prgnDst*/,
|
||||
GdkPoint* /*ppt*/,
|
||||
int * /*pwidth*/,
|
||||
int /*nspans*/,
|
||||
GdkPoint* /*pptNew*/,
|
||||
int * /*pwidthNew*/,
|
||||
int /*fSorted*/
|
||||
#endif
|
||||
);
|
||||
|
||||
/* Rops which must use span groups */
|
||||
#define miSpansCarefulRop(rop) (((rop) & 0xc) == 0x8 || ((rop) & 0x3) == 0x2)
|
||||
#define miSpansEasyRop(rop) (!miSpansCarefulRop(rop))
|
||||
|
58
gdk/linux-fb/mistruct.h
Normal file
58
gdk/linux-fb/mistruct.h
Normal file
@ -0,0 +1,58 @@
|
||||
/* $TOG: mistruct.h /main/4 1998/02/09 14:49:07 kaleb $ */
|
||||
/***********************************************************
|
||||
|
||||
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.
|
||||
|
||||
******************************************************************/
|
||||
#ifndef MISTRUCT_H
|
||||
#define MISTRUCT_H
|
||||
|
||||
#include "mitypes.h"
|
||||
|
||||
/* information about dashes */
|
||||
typedef struct _miDash {
|
||||
GdkPoint pt;
|
||||
int e1, e2; /* keep these, so we don't have to do it again */
|
||||
int e; /* bresenham error term for this point on line */
|
||||
int which;
|
||||
int newLine;/* 0 if part of same original line as previous dash */
|
||||
} miDashRec;
|
||||
|
||||
#endif /* MISTRUCT_H */
|
486
gdk/linux-fb/mitypes.h
Normal file
486
gdk/linux-fb/mitypes.h
Normal file
@ -0,0 +1,486 @@
|
||||
#ifndef MITYPES_H
|
||||
#define MITYPES_H
|
||||
|
||||
#include <alloca.h>
|
||||
|
||||
#define ALLOCATE_LOCAL(size) alloca((int)(size))
|
||||
#define DEALLOCATE_LOCAL(ptr) /* as nothing */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdkfb.h>
|
||||
#include <gdkprivate-fb.h>
|
||||
#include <gdkregion-generic.h>
|
||||
|
||||
typedef struct _miDash *miDashPtr;
|
||||
|
||||
#define CT_NONE 0
|
||||
#define CT_PIXMAP 1
|
||||
#define CT_REGION 2
|
||||
#define CT_UNSORTED 6
|
||||
#define CT_YSORTED 10
|
||||
#define CT_YXSORTED 14
|
||||
#define CT_YXBANDED 18
|
||||
|
||||
struct _GdkGCFuncs {
|
||||
void (* ValidateGC)(
|
||||
GdkGC* /*pGC*/,
|
||||
unsigned long /*stateChanges*/,
|
||||
GdkDrawable* /*pDrawable*/
|
||||
);
|
||||
|
||||
void (* ChangeGC)(
|
||||
GdkGC* /*pGC*/,
|
||||
unsigned long /*mask*/
|
||||
);
|
||||
|
||||
void (* CopyGC)(
|
||||
GdkGC* /*pGCSrc*/,
|
||||
unsigned long /*mask*/,
|
||||
GdkGC* /*pGCDst*/
|
||||
);
|
||||
|
||||
void (* DestroyGC)(
|
||||
GdkGC* /*pGC*/
|
||||
);
|
||||
|
||||
void (* ChangeClip)(
|
||||
GdkGC* /*pGC*/,
|
||||
int /*type*/,
|
||||
gpointer /*pvalue*/,
|
||||
int /*nrects*/
|
||||
);
|
||||
void (* DestroyClip)(
|
||||
GdkGC* /*pGC*/
|
||||
);
|
||||
|
||||
void (* CopyClip)(
|
||||
GdkGC* /*pgcDst*/,
|
||||
GdkGC* /*pgcSrc*/
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
typedef union {
|
||||
guint32 val;
|
||||
gpointer ptr;
|
||||
} ChangeGCVal, *ChangeGCValPtr;
|
||||
|
||||
#define PixmapBytePad(w, d) (w)
|
||||
#define BitmapBytePad(w) (w)
|
||||
|
||||
#if 0
|
||||
typedef struct _PaddingInfo {
|
||||
int padRoundUp; /* pixels per pad unit - 1 */
|
||||
int padPixelsLog2; /* log 2 (pixels per pad unit) */
|
||||
int padBytesLog2; /* log 2 (bytes per pad unit) */
|
||||
int notPower2; /* bitsPerPixel not a power of 2 */
|
||||
int bytesPerPixel; /* only set when notPower2 is TRUE */
|
||||
} PaddingInfo;
|
||||
extern PaddingInfo PixmapWidthPaddingInfo[];
|
||||
|
||||
#define PixmapWidthInPadUnits(w, d) \
|
||||
(PixmapWidthPaddingInfo[d].notPower2 ? \
|
||||
(((int)(w) * PixmapWidthPaddingInfo[d].bytesPerPixel + \
|
||||
PixmapWidthPaddingInfo[d].bytesPerPixel) >> \
|
||||
PixmapWidthPaddingInfo[d].padBytesLog2) : \
|
||||
((int)((w) + PixmapWidthPaddingInfo[d].padRoundUp) >> \
|
||||
PixmapWidthPaddingInfo[d].padPixelsLog2))
|
||||
|
||||
#define PixmapBytePad(w, d) \
|
||||
(PixmapWidthInPadUnits(w, d) << PixmapWidthPaddingInfo[d].padBytesLog2)
|
||||
|
||||
#define BitmapBytePad(w) \
|
||||
(((int)((w) + BITMAP_SCANLINE_PAD - 1) >> LOG2_BITMAP_PAD) << LOG2_BYTES_PER_SCANLINE_PAD)
|
||||
|
||||
typedef struct _GdkDrawable GdkPixmap, *GdkPixmap*;
|
||||
typedef struct _GdkDrawable GdkDrawable, *GdkDrawable*;
|
||||
typedef struct _GdkGCOps GdkGCOps;
|
||||
typedef struct _Region Region, *GdkRegion*;
|
||||
|
||||
#define EVEN_DASH 0
|
||||
#define ODD_DASH ~0
|
||||
|
||||
typedef struct _GdkPoint {
|
||||
gint16 x, y;
|
||||
} GdkPoint, *GdkPoint*;
|
||||
|
||||
typedef struct _GdkGC {
|
||||
unsigned char depth;
|
||||
unsigned char alu;
|
||||
unsigned short line_width;
|
||||
unsigned short dashOffset;
|
||||
unsigned short numInDashList;
|
||||
unsigned char *dash;
|
||||
unsigned int lineStyle : 2;
|
||||
unsigned int capStyle : 2;
|
||||
unsigned int joinStyle : 2;
|
||||
unsigned int fillStyle : 2;
|
||||
unsigned int fillRule : 1;
|
||||
unsigned int arcMode : 1;
|
||||
unsigned int subWindowMode : 1;
|
||||
unsigned int graphicsExposures : 1;
|
||||
unsigned int clientClipType : 2; /* CT_<kind> */
|
||||
unsigned int miTranslate:1; /* should mi things translate? */
|
||||
unsigned int tileIsPixel:1; /* tile is solid pixel */
|
||||
unsigned int fExpose:1; /* Call exposure handling */
|
||||
unsigned int freeCompClip:1; /* Free composite clip */
|
||||
unsigned int unused:14; /* see comment above */
|
||||
unsigned long planemask;
|
||||
unsigned long fgPixel;
|
||||
unsigned long bgPixel;
|
||||
/*
|
||||
* alas -- both tile and stipple must be here as they
|
||||
* are independently specifiable
|
||||
*/
|
||||
/* PixUnion tile;
|
||||
GdkPixmap* stipple;*/
|
||||
GdkPoint patOrg; /* origin for (tile, stipple) */
|
||||
struct _Font *font;
|
||||
GdkPoint clipOrg;
|
||||
GdkPoint lastWinOrg; /* position of window last validated */
|
||||
gpointer clientClip;
|
||||
unsigned long stateChanges; /* masked with GC_<kind> */
|
||||
unsigned long serialNumber;
|
||||
/* GCFuncs *funcs; */
|
||||
GdkGCOps *ops;
|
||||
} GdkGC, *GdkGC*;
|
||||
|
||||
struct _GdkDrawable {
|
||||
unsigned char type; /* DRAWABLE_<type> */
|
||||
unsigned char depth;
|
||||
unsigned char bitsPerPixel;
|
||||
short x; /* window: screen absolute, pixmap: 0 */
|
||||
short y; /* window: screen absolute, pixmap: 0 */
|
||||
unsigned short width;
|
||||
unsigned short height;
|
||||
unsigned long serialNumber;
|
||||
|
||||
guchar *buffer;
|
||||
int rowStride;
|
||||
};
|
||||
|
||||
typedef struct _GdkSegment {
|
||||
gint16 x1, y1, x2, y2;
|
||||
} GdkSegment;
|
||||
|
||||
typedef struct _GdkRectangle {
|
||||
gint16 x, y;
|
||||
guint16 width, height;
|
||||
} GdkRectangle, *GdkRectangle*;
|
||||
|
||||
typedef struct _Box {
|
||||
short x1, y1, x2, y2;
|
||||
} BoxRec, *BoxPtr;
|
||||
|
||||
/*
|
||||
* graphics operations invoked through a GC
|
||||
*/
|
||||
|
||||
/* graphics functions, as in GC.alu */
|
||||
|
||||
#define GDK_CLEAR 0x0 /* 0 */
|
||||
#define GDK_AND 0x1 /* src AND dst */
|
||||
#define GDK_AND_REVERSE 0x2 /* src AND NOT dst */
|
||||
#define GDK_COPY 0x3 /* src */
|
||||
#define GDK_AND_INVERT 0x4 /* NOT src AND dst */
|
||||
#define GDK_NOOP 0x5 /* dst */
|
||||
#define GDK_XOR 0x6 /* src XOR dst */
|
||||
#define GDK_OR 0x7 /* src OR dst */
|
||||
#define GDK_NOR 0x8 /* NOT src AND NOT dst */
|
||||
#define GDK_EQUIV 0x9 /* NOT src XOR dst */
|
||||
#define GDK_INVERT 0xa /* NOT dst */
|
||||
#define GDK_OR_REVERSE 0xb /* src OR NOT dst */
|
||||
#define GDK_COPY_INVERT 0xc /* NOT src */
|
||||
#define GDK_OR_INVERT 0xd /* NOT src OR dst */
|
||||
#define GDK_NAND 0xe /* NOT src OR NOT dst */
|
||||
#define GDK_SET 0xf /* 1 */
|
||||
|
||||
/* CoordinateMode for drawing routines */
|
||||
|
||||
#define CoordModeOrigin 0 /* relative to the origin */
|
||||
#define CoordModePrevious 1 /* relative to previous point */
|
||||
|
||||
/* Polygon shapes */
|
||||
|
||||
#define Complex 0 /* paths may intersect */
|
||||
#define Nonconvex 1 /* no paths intersect, but not convex */
|
||||
#define Convex 2 /* wholly convex */
|
||||
|
||||
/* LineStyle */
|
||||
|
||||
#define GDK_LINE_SOLID 0
|
||||
#define GDK_LINE_ON_OFF_DASH 1
|
||||
#define GDK_LINE_DOUBLE_DASH 2
|
||||
|
||||
/* capStyle */
|
||||
|
||||
#define GDK_CAP_NOT_LAST 0
|
||||
#define GDK_CAP_BUTT 1
|
||||
#define GDK_CAP_ROUND 2
|
||||
#define GDK_CAP_PROJECTING 3
|
||||
|
||||
/* joinStyle */
|
||||
|
||||
#define GDK_JOIN_MITER 0
|
||||
#define GDK_JOIN_ROUND 1
|
||||
#define GDK_JOIN_BEVEL 2
|
||||
|
||||
/* Arc modes for PolyFillArc */
|
||||
|
||||
#define ArcChord 0 /* join endpoints of arc */
|
||||
#define ArcPieSlice 1 /* join endpoints to center of arc */
|
||||
|
||||
/* fillRule */
|
||||
|
||||
#define EvenOddRule 0
|
||||
#define WindingRule 1
|
||||
|
||||
/* fillStyle */
|
||||
|
||||
#define GDK_SOLID 0
|
||||
#define GDK_TILED 1
|
||||
#define GDK_STIPPLED 2
|
||||
#define GDK_OPAQUE_STIPPLED 3
|
||||
|
||||
typedef enum { Linear8Bit, TwoD8Bit, Linear16Bit, TwoD16Bit } FontEncoding;
|
||||
|
||||
#define MININT G_MININT
|
||||
#define MAXINT G_MAXINT
|
||||
#define MINSHORT G_MINSHORT
|
||||
#define MAXSHORT G_MAXSHORT
|
||||
|
||||
/* GC components: masks used in CreateGC, CopyGC, ChangeGC, OR'ed into
|
||||
GC.stateChanges */
|
||||
|
||||
#define GDK_GC_FUNCTION (1L<<0)
|
||||
#define GCPlaneMask (1L<<1)
|
||||
#define GDK_GC_FOREGROUND (1L<<2)
|
||||
#define GDK_GC_BACKGROUND (1L<<3)
|
||||
#define GDK_GC_LINE_WIDTH (1L<<4)
|
||||
#define GCLineStyle (1L<<5)
|
||||
#define GDK_GC_CAP_STYLE (1L<<6)
|
||||
#define GDK_GC_JOIN_STYLE (1L<<7)
|
||||
#define GDK_GC_FILL_STYLE (1L<<8)
|
||||
#define GCFillRule (1L<<9)
|
||||
#define GCTile (1L<<10)
|
||||
#define GDK_GC_STIPPLE (1L<<11)
|
||||
#define GDK_GC_TS_X_ORIGIN (1L<<12)
|
||||
#define GDK_GC_TS_Y_ORIGIN (1L<<13)
|
||||
#define GCFont (1L<<14)
|
||||
#define GCSubwindowMode (1L<<15)
|
||||
#define GCGraphicsExposures (1L<<16)
|
||||
#define GCClipXOrigin (1L<<17)
|
||||
#define GCClipYOrigin (1L<<18)
|
||||
#define GCClipMask (1L<<19)
|
||||
#define GCDashOffset (1L<<20)
|
||||
#define GCDashList (1L<<21)
|
||||
#define GCArcMode (1L<<22)
|
||||
|
||||
/* types for Drawable */
|
||||
|
||||
#define GDK_WINDOW_CHILD 0
|
||||
#define GDK_DRAWABLE_PIXMAP 1
|
||||
#define GDK_WINDOW_FOREIGN 2
|
||||
#define GDK_WINDOW_TEMP 3
|
||||
|
||||
#endif
|
||||
|
||||
typedef GdkSegment BoxRec, *BoxPtr;
|
||||
|
||||
typedef struct _miArc {
|
||||
gint16 x, y;
|
||||
guint16 width, height;
|
||||
gint16 angle1, angle2;
|
||||
} miArc;
|
||||
|
||||
struct _GdkGCOps {
|
||||
void (* FillSpans)(
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
int /*nInit*/,
|
||||
GdkPoint* /*pptInit*/,
|
||||
int * /*pwidthInit*/,
|
||||
int /*fSorted*/
|
||||
);
|
||||
|
||||
void (* SetSpans)(
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
char * /*psrc*/,
|
||||
GdkPoint* /*ppt*/,
|
||||
int * /*pwidth*/,
|
||||
int /*nspans*/,
|
||||
int /*fSorted*/
|
||||
);
|
||||
|
||||
void (* PutImage)(
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
int /*depth*/,
|
||||
int /*x*/,
|
||||
int /*y*/,
|
||||
int /*w*/,
|
||||
int /*h*/,
|
||||
int /*leftPad*/,
|
||||
int /*format*/,
|
||||
char * /*pBits*/
|
||||
);
|
||||
|
||||
GdkRegion* (* CopyArea)(
|
||||
GdkDrawable* /*pSrc*/,
|
||||
GdkDrawable* /*pDst*/,
|
||||
GdkGC* /*pGC*/,
|
||||
int /*srcx*/,
|
||||
int /*srcy*/,
|
||||
int /*w*/,
|
||||
int /*h*/,
|
||||
int /*dstx*/,
|
||||
int /*dsty*/
|
||||
);
|
||||
|
||||
GdkRegion* (* CopyPlane)(
|
||||
GdkDrawable* /*pSrcDrawable*/,
|
||||
GdkDrawable* /*pDstDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
int /*srcx*/,
|
||||
int /*srcy*/,
|
||||
int /*width*/,
|
||||
int /*height*/,
|
||||
int /*dstx*/,
|
||||
int /*dsty*/,
|
||||
unsigned long /*bitPlane*/
|
||||
);
|
||||
void (* PolyPoint)(
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
int /*mode*/,
|
||||
int /*npt*/,
|
||||
GdkPoint* /*pptInit*/
|
||||
);
|
||||
|
||||
void (* Polylines)(
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
int /*mode*/,
|
||||
int /*npt*/,
|
||||
GdkPoint* /*pptInit*/
|
||||
);
|
||||
|
||||
void (* PolySegment)(
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
int /*nseg*/,
|
||||
GdkSegment * /*pSegs*/
|
||||
);
|
||||
|
||||
void (* PolyRectangle)(
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
int /*nrects*/,
|
||||
GdkRectangle * /*pRects*/
|
||||
);
|
||||
|
||||
void (* PolyArc)(
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
int /*narcs*/,
|
||||
miArc * /*parcs*/
|
||||
);
|
||||
|
||||
void (* FillPolygon)(
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
int /*shape*/,
|
||||
int /*mode*/,
|
||||
int /*count*/,
|
||||
GdkPoint* /*pPts*/
|
||||
);
|
||||
|
||||
void (* PolyFillRect)(
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
int /*nrectFill*/,
|
||||
GdkRectangle * /*prectInit*/
|
||||
);
|
||||
|
||||
void (* PolyFillArc)(
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
int /*narcs*/,
|
||||
miArc * /*parcs*/
|
||||
);
|
||||
|
||||
#if 0
|
||||
int (* PolyText8)(
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
int /*x*/,
|
||||
int /*y*/,
|
||||
int /*count*/,
|
||||
char * /*chars*/
|
||||
);
|
||||
|
||||
int (* PolyText16)(
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
int /*x*/,
|
||||
int /*y*/,
|
||||
int /*count*/,
|
||||
unsigned short * /*chars*/
|
||||
);
|
||||
|
||||
void (* ImageText8)(
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
int /*x*/,
|
||||
int /*y*/,
|
||||
int /*count*/,
|
||||
char * /*chars*/
|
||||
);
|
||||
|
||||
void (* ImageText16)(
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
int /*x*/,
|
||||
int /*y*/,
|
||||
int /*count*/,
|
||||
unsigned short * /*chars*/
|
||||
);
|
||||
|
||||
void (* ImageGlyphBlt)(
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
int /*x*/,
|
||||
int /*y*/,
|
||||
unsigned int /*nglyph*/,
|
||||
CharInfoPtr * /*ppci*/,
|
||||
pointer /*pglyphBase*/
|
||||
);
|
||||
|
||||
void (* PolyGlyphBlt)(
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
int /*x*/,
|
||||
int /*y*/,
|
||||
unsigned int /*nglyph*/,
|
||||
CharInfoPtr * /*ppci*/,
|
||||
pointer /*pglyphBase*/
|
||||
);
|
||||
#endif
|
||||
|
||||
void (* PushPixels)(
|
||||
GdkGC* /*pGC*/,
|
||||
GdkPixmap* /*pBitMap*/,
|
||||
GdkDrawable* /*pDst*/,
|
||||
int /*w*/,
|
||||
int /*h*/,
|
||||
int /*x*/,
|
||||
int /*y*/
|
||||
);
|
||||
};
|
||||
|
||||
#define SCRRIGHT(x, n) ((x)>>(n))
|
||||
|
||||
#endif /* MITYPES_H */
|
2108
gdk/linux-fb/miwideline.c
Normal file
2108
gdk/linux-fb/miwideline.c
Normal file
File diff suppressed because it is too large
Load Diff
254
gdk/linux-fb/miwideline.h
Normal file
254
gdk/linux-fb/miwideline.h
Normal file
@ -0,0 +1,254 @@
|
||||
/* $TOG: miwideline.h /main/12 1998/02/09 14:49:26 kaleb $ */
|
||||
/*
|
||||
|
||||
Copyright 1988, 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.
|
||||
|
||||
*/
|
||||
/* $XFree86: xc/programs/Xserver/mi/miwideline.h,v 1.7 1998/10/04 09:39:35 dawes Exp $ */
|
||||
|
||||
/* Author: Keith Packard, MIT X Consortium */
|
||||
|
||||
#ifndef MI_WIDELINE_H
|
||||
#define MI_WIDELINE_H 1
|
||||
|
||||
#include "mispans.h"
|
||||
|
||||
/*
|
||||
* interface data to span-merging polygon filler
|
||||
*/
|
||||
|
||||
typedef struct _SpanData {
|
||||
SpanGroup fgGroup, bgGroup;
|
||||
} SpanDataRec, *SpanDataPtr;
|
||||
|
||||
#define AppendSpanGroup(pGC, pixel, spanPtr, spanData) { \
|
||||
SpanGroup *group, *othergroup = NULL; \
|
||||
if (pixel->pixel == GDK_GC_FBDATA(pGC)->values.foreground.pixel) \
|
||||
{ \
|
||||
group = &spanData->fgGroup; \
|
||||
if (GDK_GC_FBDATA(pGC)->values.line_style == GDK_LINE_DOUBLE_DASH) \
|
||||
othergroup = &spanData->bgGroup; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
group = &spanData->bgGroup; \
|
||||
othergroup = &spanData->fgGroup; \
|
||||
} \
|
||||
miAppendSpans (group, othergroup, spanPtr); \
|
||||
}
|
||||
|
||||
/*
|
||||
* Polygon edge description for integer wide-line routines
|
||||
*/
|
||||
|
||||
typedef struct _PolyEdge {
|
||||
int height; /* number of scanlines to process */
|
||||
int x; /* starting x coordinate */
|
||||
int stepx; /* fixed integral dx */
|
||||
int signdx; /* variable dx sign */
|
||||
int e; /* initial error term */
|
||||
int dy;
|
||||
int dx;
|
||||
} PolyEdgeRec, *PolyEdgePtr;
|
||||
|
||||
#define SQSECANT 108.856472512142 /* 1/sin^2(11/2) - miter limit constant */
|
||||
|
||||
/*
|
||||
* types for general polygon routines
|
||||
*/
|
||||
|
||||
typedef struct _PolyVertex {
|
||||
double x, y;
|
||||
} PolyVertexRec, *PolyVertexPtr;
|
||||
|
||||
typedef struct _PolySlope {
|
||||
int dx, dy;
|
||||
double k; /* x0 * dy - y0 * dx */
|
||||
} PolySlopeRec, *PolySlopePtr;
|
||||
|
||||
/*
|
||||
* Line face description for caps/joins
|
||||
*/
|
||||
|
||||
typedef struct _LineFace {
|
||||
double xa, ya;
|
||||
int dx, dy;
|
||||
int x, y;
|
||||
double k;
|
||||
} LineFaceRec, *LineFacePtr;
|
||||
|
||||
/*
|
||||
* macros for polygon fillers
|
||||
*/
|
||||
|
||||
#define MIPOLYRELOADLEFT if (!left_height && left_count) { \
|
||||
left_height = left->height; \
|
||||
left_x = left->x; \
|
||||
left_stepx = left->stepx; \
|
||||
left_signdx = left->signdx; \
|
||||
left_e = left->e; \
|
||||
left_dy = left->dy; \
|
||||
left_dx = left->dx; \
|
||||
--left_count; \
|
||||
++left; \
|
||||
}
|
||||
|
||||
#define MIPOLYRELOADRIGHT if (!right_height && right_count) { \
|
||||
right_height = right->height; \
|
||||
right_x = right->x; \
|
||||
right_stepx = right->stepx; \
|
||||
right_signdx = right->signdx; \
|
||||
right_e = right->e; \
|
||||
right_dy = right->dy; \
|
||||
right_dx = right->dx; \
|
||||
--right_count; \
|
||||
++right; \
|
||||
}
|
||||
|
||||
#define MIPOLYSTEPLEFT left_x += left_stepx; \
|
||||
left_e += left_dx; \
|
||||
if (left_e > 0) \
|
||||
{ \
|
||||
left_x += left_signdx; \
|
||||
left_e -= left_dy; \
|
||||
}
|
||||
|
||||
#define MIPOLYSTEPRIGHT right_x += right_stepx; \
|
||||
right_e += right_dx; \
|
||||
if (right_e > 0) \
|
||||
{ \
|
||||
right_x += right_signdx; \
|
||||
right_e -= right_dy; \
|
||||
}
|
||||
|
||||
#define MILINESETPIXEL(pDrawable, pGC, pixel, oldPixel) { \
|
||||
oldPixel = GDK_GC_FBDATA(pGC)->values.foreground; \
|
||||
if (pixel->pixel != oldPixel.pixel) { \
|
||||
gdk_gc_set_foreground(pGC, pixel); \
|
||||
} \
|
||||
}
|
||||
#define MILINERESETPIXEL(pDrawable, pGC, pixel, oldPixel) { \
|
||||
if (pixel->pixel != oldPixel.pixel) { \
|
||||
gdk_gc_set_foreground(pGC, &oldPixel); \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifndef ICEIL
|
||||
#ifdef NOINLINEICEIL
|
||||
#define ICEIL(x) ((int)ceil(x))
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
#define ICEIL ICIEL
|
||||
static __inline int ICEIL(x)
|
||||
double x;
|
||||
{
|
||||
int _cTmp = x;
|
||||
return ((x == _cTmp) || (x < 0.0)) ? _cTmp : _cTmp+1;
|
||||
}
|
||||
#else
|
||||
#define ICEIL(x) ((((x) == (_cTmp = (x))) || ((x) < 0.0)) ? _cTmp : _cTmp+1)
|
||||
#define ICEILTEMPDECL static int _cTmp;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern void miFillPolyHelper(
|
||||
#if NeedFunctionPrototypes
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
GdkColor * /*pixel*/,
|
||||
SpanDataPtr /*spanData*/,
|
||||
int /*y*/,
|
||||
int /*overall_height*/,
|
||||
PolyEdgePtr /*left*/,
|
||||
PolyEdgePtr /*right*/,
|
||||
int /*left_count*/,
|
||||
int /*right_count*/
|
||||
#endif
|
||||
);
|
||||
extern int miRoundJoinFace(
|
||||
#if NeedFunctionPrototypes
|
||||
LineFacePtr /*face*/,
|
||||
PolyEdgePtr /*edge*/,
|
||||
gboolean * /*leftEdge*/
|
||||
#endif
|
||||
);
|
||||
|
||||
extern void miRoundJoinClip(
|
||||
#if NeedFunctionPrototypes
|
||||
LineFacePtr /*pLeft*/,
|
||||
LineFacePtr /*pRight*/,
|
||||
PolyEdgePtr /*edge1*/,
|
||||
PolyEdgePtr /*edge2*/,
|
||||
int * /*y1*/,
|
||||
int * /*y2*/,
|
||||
gboolean * /*left1*/,
|
||||
gboolean * /*left2*/
|
||||
#endif
|
||||
);
|
||||
|
||||
extern int miRoundCapClip(
|
||||
#if NeedFunctionPrototypes
|
||||
LineFacePtr /*face*/,
|
||||
gboolean /*isInt*/,
|
||||
PolyEdgePtr /*edge*/,
|
||||
gboolean * /*leftEdge*/
|
||||
#endif
|
||||
);
|
||||
|
||||
extern void miLineProjectingCap(
|
||||
#if NeedFunctionPrototypes
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
GdkColor * /*pixel*/,
|
||||
SpanDataPtr /*spanData*/,
|
||||
LineFacePtr /*face*/,
|
||||
gboolean /*isLeft*/,
|
||||
double /*xorg*/,
|
||||
double /*yorg*/,
|
||||
gboolean /*isInt*/
|
||||
#endif
|
||||
);
|
||||
|
||||
extern SpanDataPtr miSetupSpanData(
|
||||
#if NeedFunctionPrototypes
|
||||
GdkGC* /*pGC*/,
|
||||
SpanDataPtr /*spanData*/,
|
||||
int /*npt*/
|
||||
#endif
|
||||
);
|
||||
|
||||
extern void miCleanupSpanData(
|
||||
#if NeedFunctionPrototypes
|
||||
GdkDrawable* /*pDrawable*/,
|
||||
GdkGC* /*pGC*/,
|
||||
SpanDataPtr /*spanData*/
|
||||
#endif
|
||||
);
|
||||
|
||||
extern int miPolyBuildEdge(double x0, double y0, double k, int dx, int dy,
|
||||
int xi, int yi, int left, PolyEdgePtr edge);
|
||||
extern int miPolyBuildPoly(PolyVertexPtr vertices, PolySlopePtr slopes,
|
||||
int count, int xi, int yi, PolyEdgePtr left,
|
||||
PolyEdgePtr right, int *pnleft, int *pnright,
|
||||
int *h);
|
||||
|
||||
#endif
|
622
gdk/linux-fb/mizerclip.c
Normal file
622
gdk/linux-fb/mizerclip.c
Normal file
@ -0,0 +1,622 @@
|
||||
/* $XFree86: xc/programs/Xserver/mi/mizerclip.c,v 1.1 1999/10/13 22:33:13 dawes Exp $ */
|
||||
/***********************************************************
|
||||
|
||||
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.
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "mi.h"
|
||||
#include "miline.h"
|
||||
|
||||
/*
|
||||
|
||||
The bresenham error equation used in the mi/mfb/cfb line routines is:
|
||||
|
||||
e = error
|
||||
dx = difference in raw X coordinates
|
||||
dy = difference in raw Y coordinates
|
||||
M = # of steps in X direction
|
||||
N = # of steps in Y direction
|
||||
B = 0 to prefer diagonal steps in a given octant,
|
||||
1 to prefer axial steps in a given octant
|
||||
|
||||
For X major lines:
|
||||
e = 2Mdy - 2Ndx - dx - B
|
||||
-2dx <= e < 0
|
||||
|
||||
For Y major lines:
|
||||
e = 2Ndx - 2Mdy - dy - B
|
||||
-2dy <= e < 0
|
||||
|
||||
At the start of the line, we have taken 0 X steps and 0 Y steps,
|
||||
so M = 0 and N = 0:
|
||||
|
||||
X major e = 2Mdy - 2Ndx - dx - B
|
||||
= -dx - B
|
||||
|
||||
Y major e = 2Ndx - 2Mdy - dy - B
|
||||
= -dy - B
|
||||
|
||||
At the end of the line, we have taken dx X steps and dy Y steps,
|
||||
so M = dx and N = dy:
|
||||
|
||||
X major e = 2Mdy - 2Ndx - dx - B
|
||||
= 2dxdy - 2dydx - dx - B
|
||||
= -dx - B
|
||||
Y major e = 2Ndx - 2Mdy - dy - B
|
||||
= 2dydx - 2dxdy - dy - B
|
||||
= -dy - B
|
||||
|
||||
Thus, the error term is the same at the start and end of the line.
|
||||
|
||||
Let us consider clipping an X coordinate. There are 4 cases which
|
||||
represent the two independent cases of clipping the start vs. the
|
||||
end of the line and an X major vs. a Y major line. In any of these
|
||||
cases, we know the number of X steps (M) and we wish to find the
|
||||
number of Y steps (N). Thus, we will solve our error term equation.
|
||||
If we are clipping the start of the line, we will find the smallest
|
||||
N that satisfies our error term inequality. If we are clipping the
|
||||
end of the line, we will find the largest number of Y steps that
|
||||
satisfies the inequality. In that case, since we are representing
|
||||
the Y steps as (dy - N), we will actually want to solve for the
|
||||
smallest N in that equation.
|
||||
|
||||
Case 1: X major, starting X coordinate moved by M steps
|
||||
|
||||
-2dx <= 2Mdy - 2Ndx - dx - B < 0
|
||||
2Ndx <= 2Mdy - dx - B + 2dx 2Ndx > 2Mdy - dx - B
|
||||
2Ndx <= 2Mdy + dx - B N > (2Mdy - dx - B) / 2dx
|
||||
N <= (2Mdy + dx - B) / 2dx
|
||||
|
||||
Since we are trying to find the smallest N that satisfies these
|
||||
equations, we should use the > inequality to find the smallest:
|
||||
|
||||
N = floor((2Mdy - dx - B) / 2dx) + 1
|
||||
= floor((2Mdy - dx - B + 2dx) / 2dx)
|
||||
= floor((2Mdy + dx - B) / 2dx)
|
||||
|
||||
Case 1b: X major, ending X coordinate moved to M steps
|
||||
|
||||
Same derivations as Case 1, but we want the largest N that satisfies
|
||||
the equations, so we use the <= inequality:
|
||||
|
||||
N = floor((2Mdy + dx - B) / 2dx)
|
||||
|
||||
Case 2: X major, ending X coordinate moved by M steps
|
||||
|
||||
-2dx <= 2(dx - M)dy - 2(dy - N)dx - dx - B < 0
|
||||
-2dx <= 2dxdy - 2Mdy - 2dxdy + 2Ndx - dx - B < 0
|
||||
-2dx <= 2Ndx - 2Mdy - dx - B < 0
|
||||
2Ndx >= 2Mdy + dx + B - 2dx 2Ndx < 2Mdy + dx + B
|
||||
2Ndx >= 2Mdy - dx + B N < (2Mdy + dx + B) / 2dx
|
||||
N >= (2Mdy - dx + B) / 2dx
|
||||
|
||||
Since we are trying to find the highest number of Y steps that
|
||||
satisfies these equations, we need to find the smallest N, so
|
||||
we should use the >= inequality to find the smallest:
|
||||
|
||||
N = ceiling((2Mdy - dx + B) / 2dx)
|
||||
= floor((2Mdy - dx + B + 2dx - 1) / 2dx)
|
||||
= floor((2Mdy + dx + B - 1) / 2dx)
|
||||
|
||||
Case 2b: X major, starting X coordinate moved to M steps from end
|
||||
|
||||
Same derivations as Case 2, but we want the smallest number of Y
|
||||
steps, so we want the highest N, so we use the < inequality:
|
||||
|
||||
N = ceiling((2Mdy + dx + B) / 2dx) - 1
|
||||
= floor((2Mdy + dx + B + 2dx - 1) / 2dx) - 1
|
||||
= floor((2Mdy + dx + B + 2dx - 1 - 2dx) / 2dx)
|
||||
= floor((2Mdy + dx + B - 1) / 2dx)
|
||||
|
||||
Case 3: Y major, starting X coordinate moved by M steps
|
||||
|
||||
-2dy <= 2Ndx - 2Mdy - dy - B < 0
|
||||
2Ndx >= 2Mdy + dy + B - 2dy 2Ndx < 2Mdy + dy + B
|
||||
2Ndx >= 2Mdy - dy + B N < (2Mdy + dy + B) / 2dx
|
||||
N >= (2Mdy - dy + B) / 2dx
|
||||
|
||||
Since we are trying to find the smallest N that satisfies these
|
||||
equations, we should use the >= inequality to find the smallest:
|
||||
|
||||
N = ceiling((2Mdy - dy + B) / 2dx)
|
||||
= floor((2Mdy - dy + B + 2dx - 1) / 2dx)
|
||||
= floor((2Mdy - dy + B - 1) / 2dx) + 1
|
||||
|
||||
Case 3b: Y major, ending X coordinate moved to M steps
|
||||
|
||||
Same derivations as Case 3, but we want the largest N that satisfies
|
||||
the equations, so we use the < inequality:
|
||||
|
||||
N = ceiling((2Mdy + dy + B) / 2dx) - 1
|
||||
= floor((2Mdy + dy + B + 2dx - 1) / 2dx) - 1
|
||||
= floor((2Mdy + dy + B + 2dx - 1 - 2dx) / 2dx)
|
||||
= floor((2Mdy + dy + B - 1) / 2dx)
|
||||
|
||||
Case 4: Y major, ending X coordinate moved by M steps
|
||||
|
||||
-2dy <= 2(dy - N)dx - 2(dx - M)dy - dy - B < 0
|
||||
-2dy <= 2dxdy - 2Ndx - 2dxdy + 2Mdy - dy - B < 0
|
||||
-2dy <= 2Mdy - 2Ndx - dy - B < 0
|
||||
2Ndx <= 2Mdy - dy - B + 2dy 2Ndx > 2Mdy - dy - B
|
||||
2Ndx <= 2Mdy + dy - B N > (2Mdy - dy - B) / 2dx
|
||||
N <= (2Mdy + dy - B) / 2dx
|
||||
|
||||
Since we are trying to find the highest number of Y steps that
|
||||
satisfies these equations, we need to find the smallest N, so
|
||||
we should use the > inequality to find the smallest:
|
||||
|
||||
N = floor((2Mdy - dy - B) / 2dx) + 1
|
||||
|
||||
Case 4b: Y major, starting X coordinate moved to M steps from end
|
||||
|
||||
Same analysis as Case 4, but we want the smallest number of Y steps
|
||||
which means the largest N, so we use the <= inequality:
|
||||
|
||||
N = floor((2Mdy + dy - B) / 2dx)
|
||||
|
||||
Now let's try the Y coordinates, we have the same 4 cases.
|
||||
|
||||
Case 5: X major, starting Y coordinate moved by N steps
|
||||
|
||||
-2dx <= 2Mdy - 2Ndx - dx - B < 0
|
||||
2Mdy >= 2Ndx + dx + B - 2dx 2Mdy < 2Ndx + dx + B
|
||||
2Mdy >= 2Ndx - dx + B M < (2Ndx + dx + B) / 2dy
|
||||
M >= (2Ndx - dx + B) / 2dy
|
||||
|
||||
Since we are trying to find the smallest M, we use the >= inequality:
|
||||
|
||||
M = ceiling((2Ndx - dx + B) / 2dy)
|
||||
= floor((2Ndx - dx + B + 2dy - 1) / 2dy)
|
||||
= floor((2Ndx - dx + B - 1) / 2dy) + 1
|
||||
|
||||
Case 5b: X major, ending Y coordinate moved to N steps
|
||||
|
||||
Same derivations as Case 5, but we want the largest M that satisfies
|
||||
the equations, so we use the < inequality:
|
||||
|
||||
M = ceiling((2Ndx + dx + B) / 2dy) - 1
|
||||
= floor((2Ndx + dx + B + 2dy - 1) / 2dy) - 1
|
||||
= floor((2Ndx + dx + B + 2dy - 1 - 2dy) / 2dy)
|
||||
= floor((2Ndx + dx + B - 1) / 2dy)
|
||||
|
||||
Case 6: X major, ending Y coordinate moved by N steps
|
||||
|
||||
-2dx <= 2(dx - M)dy - 2(dy - N)dx - dx - B < 0
|
||||
-2dx <= 2dxdy - 2Mdy - 2dxdy + 2Ndx - dx - B < 0
|
||||
-2dx <= 2Ndx - 2Mdy - dx - B < 0
|
||||
2Mdy <= 2Ndx - dx - B + 2dx 2Mdy > 2Ndx - dx - B
|
||||
2Mdy <= 2Ndx + dx - B M > (2Ndx - dx - B) / 2dy
|
||||
M <= (2Ndx + dx - B) / 2dy
|
||||
|
||||
Largest # of X steps means smallest M, so use the > inequality:
|
||||
|
||||
M = floor((2Ndx - dx - B) / 2dy) + 1
|
||||
|
||||
Case 6b: X major, starting Y coordinate moved to N steps from end
|
||||
|
||||
Same derivations as Case 6, but we want the smallest # of X steps
|
||||
which means the largest M, so use the <= inequality:
|
||||
|
||||
M = floor((2Ndx + dx - B) / 2dy)
|
||||
|
||||
Case 7: Y major, starting Y coordinate moved by N steps
|
||||
|
||||
-2dy <= 2Ndx - 2Mdy - dy - B < 0
|
||||
2Mdy <= 2Ndx - dy - B + 2dy 2Mdy > 2Ndx - dy - B
|
||||
2Mdy <= 2Ndx + dy - B M > (2Ndx - dy - B) / 2dy
|
||||
M <= (2Ndx + dy - B) / 2dy
|
||||
|
||||
To find the smallest M, use the > inequality:
|
||||
|
||||
M = floor((2Ndx - dy - B) / 2dy) + 1
|
||||
= floor((2Ndx - dy - B + 2dy) / 2dy)
|
||||
= floor((2Ndx + dy - B) / 2dy)
|
||||
|
||||
Case 7b: Y major, ending Y coordinate moved to N steps
|
||||
|
||||
Same derivations as Case 7, but we want the largest M that satisfies
|
||||
the equations, so use the <= inequality:
|
||||
|
||||
M = floor((2Ndx + dy - B) / 2dy)
|
||||
|
||||
Case 8: Y major, ending Y coordinate moved by N steps
|
||||
|
||||
-2dy <= 2(dy - N)dx - 2(dx - M)dy - dy - B < 0
|
||||
-2dy <= 2dxdy - 2Ndx - 2dxdy + 2Mdy - dy - B < 0
|
||||
-2dy <= 2Mdy - 2Ndx - dy - B < 0
|
||||
2Mdy >= 2Ndx + dy + B - 2dy 2Mdy < 2Ndx + dy + B
|
||||
2Mdy >= 2Ndx - dy + B M < (2Ndx + dy + B) / 2dy
|
||||
M >= (2Ndx - dy + B) / 2dy
|
||||
|
||||
To find the highest X steps, find the smallest M, use the >= inequality:
|
||||
|
||||
M = ceiling((2Ndx - dy + B) / 2dy)
|
||||
= floor((2Ndx - dy + B + 2dy - 1) / 2dy)
|
||||
= floor((2Ndx + dy + B - 1) / 2dy)
|
||||
|
||||
Case 8b: Y major, starting Y coordinate moved to N steps from the end
|
||||
|
||||
Same derivations as Case 8, but we want to find the smallest # of X
|
||||
steps which means the largest M, so we use the < inequality:
|
||||
|
||||
M = ceiling((2Ndx + dy + B) / 2dy) - 1
|
||||
= floor((2Ndx + dy + B + 2dy - 1) / 2dy) - 1
|
||||
= floor((2Ndx + dy + B + 2dy - 1 - 2dy) / 2dy)
|
||||
= floor((2Ndx + dy + B - 1) / 2dy)
|
||||
|
||||
So, our equations are:
|
||||
|
||||
1: X major move x1 to x1+M floor((2Mdy + dx - B) / 2dx)
|
||||
1b: X major move x2 to x1+M floor((2Mdy + dx - B) / 2dx)
|
||||
2: X major move x2 to x2-M floor((2Mdy + dx + B - 1) / 2dx)
|
||||
2b: X major move x1 to x2-M floor((2Mdy + dx + B - 1) / 2dx)
|
||||
|
||||
3: Y major move x1 to x1+M floor((2Mdy - dy + B - 1) / 2dx) + 1
|
||||
3b: Y major move x2 to x1+M floor((2Mdy + dy + B - 1) / 2dx)
|
||||
4: Y major move x2 to x2-M floor((2Mdy - dy - B) / 2dx) + 1
|
||||
4b: Y major move x1 to x2-M floor((2Mdy + dy - B) / 2dx)
|
||||
|
||||
5: X major move y1 to y1+N floor((2Ndx - dx + B - 1) / 2dy) + 1
|
||||
5b: X major move y2 to y1+N floor((2Ndx + dx + B - 1) / 2dy)
|
||||
6: X major move y2 to y2-N floor((2Ndx - dx - B) / 2dy) + 1
|
||||
6b: X major move y1 to y2-N floor((2Ndx + dx - B) / 2dy)
|
||||
|
||||
7: Y major move y1 to y1+N floor((2Ndx + dy - B) / 2dy)
|
||||
7b: Y major move y2 to y1+N floor((2Ndx + dy - B) / 2dy)
|
||||
8: Y major move y2 to y2-N floor((2Ndx + dy + B - 1) / 2dy)
|
||||
8b: Y major move y1 to y2-N floor((2Ndx + dy + B - 1) / 2dy)
|
||||
|
||||
We have the following constraints on all of the above terms:
|
||||
|
||||
0 < M,N <= 2^15 2^15 can be imposed by miZeroClipLine
|
||||
0 <= dx/dy <= 2^16 - 1
|
||||
0 <= B <= 1
|
||||
|
||||
The floor in all of the above equations can be accomplished with a
|
||||
simple C divide operation provided that both numerator and denominator
|
||||
are positive.
|
||||
|
||||
Since dx,dy >= 0 and since moving an X coordinate implies that dx != 0
|
||||
and moving a Y coordinate implies dy != 0, we know that the denominators
|
||||
are all > 0.
|
||||
|
||||
For all lines, (-B) and (B-1) are both either 0 or -1, depending on the
|
||||
bias. Thus, we have to show that the 2MNdxy +/- dxy terms are all >= 1
|
||||
or > 0 to prove that the numerators are positive (or zero).
|
||||
|
||||
For X Major lines we know that dx > 0 and since 2Mdy is >= 0 due to the
|
||||
constraints, the first four equations all have numerators >= 0.
|
||||
|
||||
For the second four equations, M > 0, so 2Mdy >= 2dy so (2Mdy - dy) >= dy
|
||||
So (2Mdy - dy) > 0, since they are Y major lines. Also, (2Mdy + dy) >= 3dy
|
||||
or (2Mdy + dy) > 0. So all of their numerators are >= 0.
|
||||
|
||||
For the third set of four equations, N > 0, so 2Ndx >= 2dx so (2Ndx - dx)
|
||||
>= dx > 0. Similarly (2Ndx + dx) >= 3dx > 0. So all numerators >= 0.
|
||||
|
||||
For the fourth set of equations, dy > 0 and 2Ndx >= 0, so all numerators
|
||||
are > 0.
|
||||
|
||||
To consider overflow, consider the case of 2 * M,N * dx,dy + dx,dy. This
|
||||
is bounded <= 2 * 2^15 * (2^16 - 1) + (2^16 - 1)
|
||||
<= 2^16 * (2^16 - 1) + (2^16 - 1)
|
||||
<= 2^32 - 2^16 + 2^16 - 1
|
||||
<= 2^32 - 1
|
||||
Since the (-B) and (B-1) terms are all 0 or -1, the maximum value of
|
||||
the numerator is therefore (2^32 - 1), which does not overflow an unsigned
|
||||
32 bit variable.
|
||||
|
||||
*/
|
||||
|
||||
/* Bit codes for the terms of the 16 clipping equations defined below. */
|
||||
|
||||
#define T_2NDX (1 << 0)
|
||||
#define T_2MDY (0) /* implicit term */
|
||||
#define T_DXNOTY (1 << 1)
|
||||
#define T_DYNOTX (0) /* implicit term */
|
||||
#define T_SUBDXORY (1 << 2)
|
||||
#define T_ADDDX (T_DXNOTY) /* composite term */
|
||||
#define T_SUBDX (T_DXNOTY | T_SUBDXORY) /* composite term */
|
||||
#define T_ADDDY (T_DYNOTX) /* composite term */
|
||||
#define T_SUBDY (T_DYNOTX | T_SUBDXORY) /* composite term */
|
||||
#define T_BIASSUBONE (1 << 3)
|
||||
#define T_SUBBIAS (0) /* implicit term */
|
||||
#define T_DIV2DX (1 << 4)
|
||||
#define T_DIV2DY (0) /* implicit term */
|
||||
#define T_ADDONE (1 << 5)
|
||||
|
||||
/* Bit masks defining the 16 equations used in miZeroClipLine. */
|
||||
|
||||
#define EQN1 (T_2MDY | T_ADDDX | T_SUBBIAS | T_DIV2DX)
|
||||
#define EQN1B (T_2MDY | T_ADDDX | T_SUBBIAS | T_DIV2DX)
|
||||
#define EQN2 (T_2MDY | T_ADDDX | T_BIASSUBONE | T_DIV2DX)
|
||||
#define EQN2B (T_2MDY | T_ADDDX | T_BIASSUBONE | T_DIV2DX)
|
||||
|
||||
#define EQN3 (T_2MDY | T_SUBDY | T_BIASSUBONE | T_DIV2DX | T_ADDONE)
|
||||
#define EQN3B (T_2MDY | T_ADDDY | T_BIASSUBONE | T_DIV2DX)
|
||||
#define EQN4 (T_2MDY | T_SUBDY | T_SUBBIAS | T_DIV2DX | T_ADDONE)
|
||||
#define EQN4B (T_2MDY | T_ADDDY | T_SUBBIAS | T_DIV2DX)
|
||||
|
||||
#define EQN5 (T_2NDX | T_SUBDX | T_BIASSUBONE | T_DIV2DY | T_ADDONE)
|
||||
#define EQN5B (T_2NDX | T_ADDDX | T_BIASSUBONE | T_DIV2DY)
|
||||
#define EQN6 (T_2NDX | T_SUBDX | T_SUBBIAS | T_DIV2DY | T_ADDONE)
|
||||
#define EQN6B (T_2NDX | T_ADDDX | T_SUBBIAS | T_DIV2DY)
|
||||
|
||||
#define EQN7 (T_2NDX | T_ADDDY | T_SUBBIAS | T_DIV2DY)
|
||||
#define EQN7B (T_2NDX | T_ADDDY | T_SUBBIAS | T_DIV2DY)
|
||||
#define EQN8 (T_2NDX | T_ADDDY | T_BIASSUBONE | T_DIV2DY)
|
||||
#define EQN8B (T_2NDX | T_ADDDY | T_BIASSUBONE | T_DIV2DY)
|
||||
|
||||
/* miZeroClipLine
|
||||
*
|
||||
* returns: 1 for partially clipped line
|
||||
* -1 for completely clipped line
|
||||
*
|
||||
*/
|
||||
int
|
||||
miZeroClipLine(xmin, ymin, xmax, ymax,
|
||||
new_x1, new_y1, new_x2, new_y2,
|
||||
adx, ady,
|
||||
pt1_clipped, pt2_clipped, octant, bias, oc1, oc2)
|
||||
int xmin, ymin, xmax, ymax;
|
||||
int *new_x1, *new_y1, *new_x2, *new_y2;
|
||||
int *pt1_clipped, *pt2_clipped;
|
||||
unsigned int adx, ady;
|
||||
int octant;
|
||||
unsigned int bias;
|
||||
int oc1, oc2;
|
||||
{
|
||||
int swapped = 0;
|
||||
int clipDone = 0;
|
||||
guint32 utmp;
|
||||
int clip1, clip2;
|
||||
int x1, y1, x2, y2;
|
||||
int x1_orig, y1_orig, x2_orig, y2_orig;
|
||||
int xmajor;
|
||||
int negslope, anchorval;
|
||||
unsigned int eqn;
|
||||
|
||||
x1 = x1_orig = *new_x1;
|
||||
y1 = y1_orig = *new_y1;
|
||||
x2 = x2_orig = *new_x2;
|
||||
y2 = y2_orig = *new_y2;
|
||||
|
||||
clip1 = 0;
|
||||
clip2 = 0;
|
||||
|
||||
xmajor = IsXMajorOctant(octant);
|
||||
bias = ((bias >> octant) & 1);
|
||||
|
||||
while (1)
|
||||
{
|
||||
if ((oc1 & oc2) != 0) /* trivial reject */
|
||||
{
|
||||
clipDone = -1;
|
||||
clip1 = oc1;
|
||||
clip2 = oc2;
|
||||
break;
|
||||
}
|
||||
else if ((oc1 | oc2) == 0) /* trivial accept */
|
||||
{
|
||||
clipDone = 1;
|
||||
if (swapped)
|
||||
{
|
||||
SWAPINT_PAIR(x1, y1, x2, y2);
|
||||
SWAPINT(clip1, clip2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else /* have to clip */
|
||||
{
|
||||
/* only clip one point at a time */
|
||||
if (oc1 == 0)
|
||||
{
|
||||
SWAPINT_PAIR(x1, y1, x2, y2);
|
||||
SWAPINT_PAIR(x1_orig, y1_orig, x2_orig, y2_orig);
|
||||
SWAPINT(oc1, oc2);
|
||||
SWAPINT(clip1, clip2);
|
||||
swapped = !swapped;
|
||||
}
|
||||
|
||||
clip1 |= oc1;
|
||||
if (oc1 & OUT_LEFT)
|
||||
{
|
||||
negslope = IsYDecreasingOctant(octant);
|
||||
utmp = xmin - x1_orig;
|
||||
if (utmp <= 32767) /* clip based on near endpt */
|
||||
{
|
||||
if (xmajor)
|
||||
eqn = (swapped) ? EQN2 : EQN1;
|
||||
else
|
||||
eqn = (swapped) ? EQN4 : EQN3;
|
||||
anchorval = y1_orig;
|
||||
}
|
||||
else /* clip based on far endpt */
|
||||
{
|
||||
utmp = x2_orig - xmin;
|
||||
if (xmajor)
|
||||
eqn = (swapped) ? EQN1B : EQN2B;
|
||||
else
|
||||
eqn = (swapped) ? EQN3B : EQN4B;
|
||||
anchorval = y2_orig;
|
||||
negslope = !negslope;
|
||||
}
|
||||
x1 = xmin;
|
||||
}
|
||||
else if (oc1 & OUT_ABOVE)
|
||||
{
|
||||
negslope = IsXDecreasingOctant(octant);
|
||||
utmp = ymin - y1_orig;
|
||||
if (utmp <= 32767) /* clip based on near endpt */
|
||||
{
|
||||
if (xmajor)
|
||||
eqn = (swapped) ? EQN6 : EQN5;
|
||||
else
|
||||
eqn = (swapped) ? EQN8 : EQN7;
|
||||
anchorval = x1_orig;
|
||||
}
|
||||
else /* clip based on far endpt */
|
||||
{
|
||||
utmp = y2_orig - ymin;
|
||||
if (xmajor)
|
||||
eqn = (swapped) ? EQN5B : EQN6B;
|
||||
else
|
||||
eqn = (swapped) ? EQN7B : EQN8B;
|
||||
anchorval = x2_orig;
|
||||
negslope = !negslope;
|
||||
}
|
||||
y1 = ymin;
|
||||
}
|
||||
else if (oc1 & OUT_RIGHT)
|
||||
{
|
||||
negslope = IsYDecreasingOctant(octant);
|
||||
utmp = x1_orig - xmax;
|
||||
if (utmp <= 32767) /* clip based on near endpt */
|
||||
{
|
||||
if (xmajor)
|
||||
eqn = (swapped) ? EQN2 : EQN1;
|
||||
else
|
||||
eqn = (swapped) ? EQN4 : EQN3;
|
||||
anchorval = y1_orig;
|
||||
}
|
||||
else /* clip based on far endpt */
|
||||
{
|
||||
/*
|
||||
* Technically since the equations can handle
|
||||
* utmp == 32768, this overflow code isn't
|
||||
* needed since X11 protocol can't generate
|
||||
* a line which goes more than 32768 pixels
|
||||
* to the right of a clip rectangle.
|
||||
*/
|
||||
utmp = xmax - x2_orig;
|
||||
if (xmajor)
|
||||
eqn = (swapped) ? EQN1B : EQN2B;
|
||||
else
|
||||
eqn = (swapped) ? EQN3B : EQN4B;
|
||||
anchorval = y2_orig;
|
||||
negslope = !negslope;
|
||||
}
|
||||
x1 = xmax;
|
||||
}
|
||||
else if (oc1 & OUT_BELOW)
|
||||
{
|
||||
negslope = IsXDecreasingOctant(octant);
|
||||
utmp = y1_orig - ymax;
|
||||
if (utmp <= 32767) /* clip based on near endpt */
|
||||
{
|
||||
if (xmajor)
|
||||
eqn = (swapped) ? EQN6 : EQN5;
|
||||
else
|
||||
eqn = (swapped) ? EQN8 : EQN7;
|
||||
anchorval = x1_orig;
|
||||
}
|
||||
else /* clip based on far endpt */
|
||||
{
|
||||
/*
|
||||
* Technically since the equations can handle
|
||||
* utmp == 32768, this overflow code isn't
|
||||
* needed since X11 protocol can't generate
|
||||
* a line which goes more than 32768 pixels
|
||||
* below the bottom of a clip rectangle.
|
||||
*/
|
||||
utmp = ymax - y2_orig;
|
||||
if (xmajor)
|
||||
eqn = (swapped) ? EQN5B : EQN6B;
|
||||
else
|
||||
eqn = (swapped) ? EQN7B : EQN8B;
|
||||
anchorval = x2_orig;
|
||||
negslope = !negslope;
|
||||
}
|
||||
y1 = ymax;
|
||||
}
|
||||
|
||||
if (swapped)
|
||||
negslope = !negslope;
|
||||
|
||||
utmp <<= 1; /* utmp = 2N or 2M */
|
||||
if (eqn & T_2NDX)
|
||||
utmp = (utmp * adx);
|
||||
else /* (eqn & T_2MDY) */
|
||||
utmp = (utmp * ady);
|
||||
if (eqn & T_DXNOTY)
|
||||
if (eqn & T_SUBDXORY)
|
||||
utmp -= adx;
|
||||
else
|
||||
utmp += adx;
|
||||
else /* (eqn & T_DYNOTX) */
|
||||
if (eqn & T_SUBDXORY)
|
||||
utmp -= ady;
|
||||
else
|
||||
utmp += ady;
|
||||
if (eqn & T_BIASSUBONE)
|
||||
utmp += bias - 1;
|
||||
else /* (eqn & T_SUBBIAS) */
|
||||
utmp -= bias;
|
||||
if (eqn & T_DIV2DX)
|
||||
utmp /= (adx << 1);
|
||||
else /* (eqn & T_DIV2DY) */
|
||||
utmp /= (ady << 1);
|
||||
if (eqn & T_ADDONE)
|
||||
utmp++;
|
||||
|
||||
if (negslope)
|
||||
utmp = -utmp;
|
||||
|
||||
if (eqn & T_2NDX) /* We are calculating X steps */
|
||||
x1 = anchorval + utmp;
|
||||
else /* else, Y steps */
|
||||
y1 = anchorval + utmp;
|
||||
|
||||
oc1 = 0;
|
||||
MIOUTCODES(oc1, x1, y1, xmin, ymin, xmax, ymax);
|
||||
}
|
||||
}
|
||||
|
||||
*new_x1 = x1;
|
||||
*new_y1 = y1;
|
||||
*new_x2 = x2;
|
||||
*new_y2 = y2;
|
||||
|
||||
*pt1_clipped = clip1;
|
||||
*pt2_clipped = clip2;
|
||||
|
||||
return clipDone;
|
||||
}
|
332
gdk/linux-fb/mizerline.c
Normal file
332
gdk/linux-fb/mizerline.c
Normal file
@ -0,0 +1,332 @@
|
||||
/* $XFree86: xc/programs/Xserver/mi/mizerline.c,v 3.4 1999/10/14 04:43:16 dawes Exp $ */
|
||||
/***********************************************************
|
||||
|
||||
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: mizerline.c /main/18 1998/02/09 14:49:45 kaleb $ */
|
||||
|
||||
#include "mi.h"
|
||||
#include "miline.h"
|
||||
|
||||
/* Draw lineSolid, fillStyle-independent zero width lines.
|
||||
*
|
||||
* Must keep X and Y coordinates in "ints" at least until after they're
|
||||
* translated and clipped to accomodate CoordModePrevious lines with very
|
||||
* large coordinates.
|
||||
*
|
||||
* Draws the same pixels regardless of sign(dx) or sign(dy).
|
||||
*
|
||||
* Ken Whaley
|
||||
*
|
||||
*/
|
||||
|
||||
/* largest positive value that can fit into a component of a point.
|
||||
* Assumes that the point structure is {type x, y;} where type is
|
||||
* a signed type.
|
||||
*/
|
||||
#define MAX_COORDINATE ((1 << (((sizeof(GdkPoint) >> 1) << 3) - 1)) - 1)
|
||||
|
||||
#define MI_OUTPUT_POINT(xx, yy)\
|
||||
{\
|
||||
if ( !new_span && yy == current_y)\
|
||||
{\
|
||||
if (xx < spans->x)\
|
||||
spans->x = xx;\
|
||||
spans->width++; \
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
++Nspans;\
|
||||
++spans;\
|
||||
spans->x = xx;\
|
||||
spans->y = yy;\
|
||||
spans->width = 1; \
|
||||
spans->height = 1; \
|
||||
current_y = yy;\
|
||||
new_span = FALSE;\
|
||||
}\
|
||||
}
|
||||
|
||||
void
|
||||
miZeroLine(pDraw, pGC, mode, npt, pptInit)
|
||||
GdkDrawable* pDraw;
|
||||
GdkGC* pGC;
|
||||
int mode; /* Origin or Previous */
|
||||
int npt; /* number of points */
|
||||
GdkPoint* pptInit;
|
||||
{
|
||||
int Nspans, current_y;
|
||||
GdkPoint* ppt;
|
||||
GdkRectangle* pspanInit, *spans;
|
||||
int list_len;
|
||||
int xleft, ytop, xright, ybottom;
|
||||
int new_x1, new_y1, new_x2, new_y2;
|
||||
int x, y, x1, y1, x2, y2, xstart, ystart;
|
||||
int oc1, oc2;
|
||||
int result;
|
||||
int pt1_clipped, pt2_clipped = 0;
|
||||
gboolean new_span;
|
||||
int signdx, signdy;
|
||||
int clipdx, clipdy;
|
||||
int width, height;
|
||||
int adx, ady;
|
||||
int octant;
|
||||
unsigned int bias = miGetZeroLineBias();
|
||||
int e, e1, e2, e3; /* Bresenham error terms */
|
||||
int length; /* length of lines == # of pixels on major axis */
|
||||
|
||||
xleft = 0;
|
||||
ytop = 0;
|
||||
xright = GDK_DRAWABLE_P(pDraw)->width - 1;
|
||||
ybottom = GDK_DRAWABLE_P(pDraw)->height - 1;
|
||||
|
||||
/* it doesn't matter whether we're in drawable or screen coordinates,
|
||||
* FillSpans simply cannot take starting coordinates outside of the
|
||||
* range of a GdkPoint component.
|
||||
*/
|
||||
|
||||
/* since we're clipping to the drawable's boundaries & coordinate
|
||||
* space boundaries, we're guaranteed that the larger of width/height
|
||||
* is the longest span we'll need to output
|
||||
*/
|
||||
width = xright - xleft + 1;
|
||||
height = ybottom - ytop + 1;
|
||||
list_len = (height >= width) ? height : width;
|
||||
pspanInit = (GdkRectangle*)ALLOCATE_LOCAL(list_len * sizeof(GdkRectangle));
|
||||
if (!pspanInit)
|
||||
return;
|
||||
|
||||
Nspans = 0;
|
||||
new_span = TRUE;
|
||||
spans = pspanInit - 1;
|
||||
ppt = pptInit;
|
||||
|
||||
xstart = ppt->x;
|
||||
ystart = ppt->y;
|
||||
|
||||
/* x2, y2, oc2 copied to x1, y1, oc1 at top of loop to simplify
|
||||
* iteration logic
|
||||
*/
|
||||
x2 = xstart;
|
||||
y2 = ystart;
|
||||
oc2 = 0;
|
||||
MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom);
|
||||
|
||||
while (--npt > 0)
|
||||
{
|
||||
if (Nspans > 0)
|
||||
gdk_fb_fill_spans(pDraw, pGC, pspanInit, Nspans);
|
||||
Nspans = 0;
|
||||
new_span = TRUE;
|
||||
spans = pspanInit - 1;
|
||||
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
oc1 = oc2;
|
||||
++ppt;
|
||||
|
||||
x2 = ppt->x;
|
||||
y2 = ppt->y;
|
||||
|
||||
oc2 = 0;
|
||||
MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom);
|
||||
|
||||
CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant);
|
||||
|
||||
if (adx > ady)
|
||||
{
|
||||
e1 = ady << 1;
|
||||
e2 = e1 - (adx << 1);
|
||||
e = e1 - adx;
|
||||
length = adx; /* don't draw endpoint in main loop */
|
||||
|
||||
FIXUP_ERROR(e, octant, bias);
|
||||
|
||||
new_x1 = x1;
|
||||
new_y1 = y1;
|
||||
new_x2 = x2;
|
||||
new_y2 = y2;
|
||||
pt1_clipped = 0;
|
||||
pt2_clipped = 0;
|
||||
|
||||
if ((oc1 | oc2) != 0)
|
||||
{
|
||||
result = miZeroClipLine(xleft, ytop, xright, ybottom,
|
||||
&new_x1, &new_y1, &new_x2, &new_y2,
|
||||
adx, ady,
|
||||
&pt1_clipped, &pt2_clipped,
|
||||
octant, bias, oc1, oc2);
|
||||
if (result == -1)
|
||||
continue;
|
||||
|
||||
length = abs(new_x2 - new_x1);
|
||||
|
||||
/* if we've clipped the endpoint, always draw the full length
|
||||
* of the segment, because then the capstyle doesn't matter
|
||||
*/
|
||||
if (pt2_clipped)
|
||||
length++;
|
||||
|
||||
if (pt1_clipped)
|
||||
{
|
||||
/* must calculate new error terms */
|
||||
clipdx = abs(new_x1 - x1);
|
||||
clipdy = abs(new_y1 - y1);
|
||||
e += (clipdy * e2) + ((clipdx - clipdy) * e1);
|
||||
}
|
||||
}
|
||||
|
||||
/* draw the segment */
|
||||
|
||||
x = new_x1;
|
||||
y = new_y1;
|
||||
|
||||
e3 = e2 - e1;
|
||||
e = e - e1;
|
||||
|
||||
while (length--)
|
||||
{
|
||||
MI_OUTPUT_POINT(x, y);
|
||||
e += e1;
|
||||
if (e >= 0)
|
||||
{
|
||||
y += signdy;
|
||||
e += e3;
|
||||
}
|
||||
x += signdx;
|
||||
}
|
||||
}
|
||||
else /* Y major line */
|
||||
{
|
||||
e1 = adx << 1;
|
||||
e2 = e1 - (ady << 1);
|
||||
e = e1 - ady;
|
||||
length = ady; /* don't draw endpoint in main loop */
|
||||
|
||||
SetYMajorOctant(octant);
|
||||
FIXUP_ERROR(e, octant, bias);
|
||||
|
||||
new_x1 = x1;
|
||||
new_y1 = y1;
|
||||
new_x2 = x2;
|
||||
new_y2 = y2;
|
||||
pt1_clipped = 0;
|
||||
pt2_clipped = 0;
|
||||
|
||||
if ((oc1 | oc2) != 0)
|
||||
{
|
||||
result = miZeroClipLine(xleft, ytop, xright, ybottom,
|
||||
&new_x1, &new_y1, &new_x2, &new_y2,
|
||||
adx, ady,
|
||||
&pt1_clipped, &pt2_clipped,
|
||||
octant, bias, oc1, oc2);
|
||||
if (result == -1)
|
||||
continue;
|
||||
|
||||
length = abs(new_y2 - new_y1);
|
||||
|
||||
/* if we've clipped the endpoint, always draw the full length
|
||||
* of the segment, because then the capstyle doesn't matter
|
||||
*/
|
||||
if (pt2_clipped)
|
||||
length++;
|
||||
|
||||
if (pt1_clipped)
|
||||
{
|
||||
/* must calculate new error terms */
|
||||
clipdx = abs(new_x1 - x1);
|
||||
clipdy = abs(new_y1 - y1);
|
||||
e += (clipdx * e2) + ((clipdy - clipdx) * e1);
|
||||
}
|
||||
}
|
||||
|
||||
/* draw the segment */
|
||||
|
||||
x = new_x1;
|
||||
y = new_y1;
|
||||
|
||||
e3 = e2 - e1;
|
||||
e = e - e1;
|
||||
|
||||
while (length--)
|
||||
{
|
||||
MI_OUTPUT_POINT(x, y);
|
||||
e += e1;
|
||||
if (e >= 0)
|
||||
{
|
||||
x += signdx;
|
||||
e += e3;
|
||||
}
|
||||
y += signdy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* only do the capnotlast check on the last segment
|
||||
* and only if the endpoint wasn't clipped. And then, if the last
|
||||
* point is the same as the first point, do not draw it, unless the
|
||||
* line is degenerate
|
||||
*/
|
||||
if ( (! pt2_clipped) && (GDK_GC_FBDATA(pGC)->values.cap_style != GDK_CAP_NOT_LAST) &&
|
||||
(((xstart != x2) || (ystart != y2)) || (ppt == pptInit + 1)))
|
||||
{
|
||||
MI_OUTPUT_POINT(x, y);
|
||||
}
|
||||
|
||||
if (Nspans > 0)
|
||||
gdk_fb_fill_spans(pDraw, pGC, pspanInit, Nspans);
|
||||
|
||||
DEALLOCATE_LOCAL(pspanInit);
|
||||
}
|
||||
|
||||
void
|
||||
miZeroDashLine(dst, pgc, mode, nptInit, pptInit)
|
||||
GdkDrawable* dst;
|
||||
GdkGC* pgc;
|
||||
int mode;
|
||||
int nptInit; /* number of points in polyline */
|
||||
GdkPoint *pptInit; /* points in the polyline */
|
||||
{
|
||||
/* XXX kludge until real zero-width dash code is written */
|
||||
GDK_GC_FBDATA(pgc)->values.line_width = 1;
|
||||
miWideDash (dst, pgc, mode, nptInit, pptInit);
|
||||
GDK_GC_FBDATA(pgc)->values.line_width = 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user