gtk/gdk/linux-fb/gdkrender-fb.c
Alexander Larsson 1c805555ce Huge GtkFB patch with lots of small bugfixes and initial selections implementation.
2000-11-23  Alexander Larsson  <alexl@redhat.com>

	* gdk/linux-fb/gdkselection-fb.c:
	Initial selection implementation.

	* gtk/gtkselection.c:
	if GDK_WINDOWING_FB defined, include linux-fb/gdkfb.h and look up
	requestor in gtk_selection_request.

	* gdk/linux-fb/gdkfb.h, gdk/linux-fb/gdkglobals-fb.c:
	Added gdk_selection_property atom.

	* gdk/linux-fb/gdkprivate-fb.h:
	Export _gdk_selection_window_destroyed.
	Removed mask_off_x/y from GdkCursorPrivateFB.
	Removed hbearing, added top, left to PangoFBGlyphInfo.

	* gdk/linux-fb/gdkwindow-fb.c (_gdk_windowing_window_destroy):
	Call _gdk_selection_window_destroyed
	(_gdk_windowing_window_init): Don't call gdk_cursor_new() before
	the root window has been created.
	(static_dx_hack, static_dy_hack, compare_draw_rects,
	gdk_fb_window_move_resize): Remove unnecessary sort of rectangles
	in region. They are already sorted. Instead just traverse them in
	reverse if draw_direction < 0.

	* gdk/linux-fb/gdkinput-ps2.c (send_button_event):
	Double-clicks must be sent after the normal button_press.
	(gdk_fb_cursor_unhide): Remove usage of mask_off_x/y. Clean up.

	* gdk/linux-fb/gdkgeometry-fb.c (gdk_window_scroll):
	Pass _gdk_fb_screen_gc instead of NULL.

	* gdk/linux-fb/gdkmain-fb.c (_gdk_windowing_init_check):
	Initialize gdk_selection_property.
	(gdk_event_make): Remove unused code.

	* gdk/linux-fb/gdkcursor-fb.c:
	Make the pixmap for the cursor the same size as the mask. Also remove
	the mask_off_x/y fields in GdkCursorPrivateFB and combine
	_gdk_cursor_new_from_pixmap() and gdk_cursor_new_from_pixmap()
	Now the whole cursor is visible.

	* gdk/linux-fb/gdkdrawable-fb2.c (gdk_fb_draw_drawable_3):
	Fix bug where xdest+height instead of ydest+height was used
	to calculate if the source and dest overlapped. This fixes the
	redraw bug when the main window in testgtk was scrolled when
	partially covered by a tall window.
	Copy rectangles in region in order depending on draw_direction.
	Also moved the draw_direction flipping of start_y and end_y into
	the gc functions, as this might not be what all of them want.
	(gdk_fb_draw_lines): Support dashed lines.
	(gdk_fb_draw_glyphs): Clean up glyph placement. Also fix positioning
	so that the text is positioned correctly (was 1 pixel high).

	gdk/linux-fb/gdkgc-fb.c:
	Initialize cap_style to GTK_CAP_BUTT. This fixes a problem where
	all lines were drawn a pixel to short. Also checked the default of
	the rest of the values, and they're the same as X now.

	* gdk/linux-fb/gdkpango-fb.c (pango_fb_font_get_glyph_info):
	Clean up pixel positioning of the glyphs. Just use bgy->top and
	bgy->left. Also used PANGO_PIXEL where appropriate and added 0.5
	to all divisions to get correct rounding behaviour.

	* gdk/linux-fb/gdkrender-fb.c (gdk_fb_draw_drawable_generic,
	gdk_fb_draw_drawable_memmove, gdk_fb_draw_drawable_aa_24):
	Moved start_y/end_y flip into draw_drawable implementations.
	Flip also x rendering when draw_direction < 0.
	Remove unneccesary multiply with draw_direction.
2000-11-25 15:44:35 +00:00

1197 lines
29 KiB
C

#include "gdkprivate-fb.h"
#include <string.h>
/*
* Reading pixel values from a generic drawable.
*/
static GetPixelRet
gdk_fb_drawable_get_color (GdkDrawable *drawable,
GdkGC *gc,
int x,
int y,
GdkColor *spot)
{
GetPixelRet retval = GPR_NONE;
GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
guchar *mem = private->mem;
guint rowstride = private->rowstride;
switch (private->depth)
{
case 1:
{
guchar foo = mem[(x >> 3) + y * rowstride];
if (foo & (1 << (x % 8)))
*spot = GDK_GC_FBDATA (gc)->values.foreground;
else
{
retval = GPR_USED_BG;
*spot = GDK_GC_FBDATA (gc)->values.background;
}
}
break;
case 71:
if (mem[x + y * rowstride])
*spot = GDK_GC_FBDATA (gc)->values.foreground;
else
*spot = GDK_GC_FBDATA (gc)->values.background;
break;
case 77:
retval = GPR_AA_GRAYVAL;
spot->pixel = mem[x + y * rowstride] << 1;
spot->red = spot->green = spot->blue = spot->pixel << 8;
break;
case 78: /* AA mode */
retval = GPR_AA_GRAYVAL;
spot->pixel = mem[x + y * rowstride];
spot->red = spot->green = spot->blue = spot->pixel << 8;
break;
case 8:
spot->pixel = mem[x + y * rowstride];
*spot = private->colormap->colors[spot->pixel];
break;
case 16:
{
guint16 val16 = *((guint16 *)&mem[x*2 + y*rowstride]);
spot->red = (((1<<gdk_display->modeinfo.red.length) - 1) & (val16 >> gdk_display->modeinfo.red.offset)) << (16 - gdk_display->modeinfo.red.length);
spot->green = (((1<<gdk_display->modeinfo.green.length) - 1) & (val16 >> gdk_display->modeinfo.green.offset)) << (16 - gdk_display->modeinfo.green.length);
spot->blue = (((1<<gdk_display->modeinfo.blue.length) - 1) & (val16 >> gdk_display->modeinfo.blue.offset)) << (16 - gdk_display->modeinfo.blue.length);
spot->pixel = val16;
}
break;
case 24:
{
guchar *smem = &mem[x*3 + y*rowstride];
spot->red = smem[gdk_display->red_byte] << 8;
spot->green = smem[gdk_display->green_byte] << 8;
spot->blue = smem[gdk_display->blue_byte] << 8;
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
spot->pixel = (smem[0]<<16)|(smem[1]<<8)|smem[2];
#else
spot->pixel = smem[0]|(smem[1]<<8)|(smem[2]<<16);
#endif
}
break;
case 32:
{
guchar *smem = &mem[x*4 + y*rowstride];
spot->red = smem[gdk_display->red_byte] << 8;
spot->green = smem[gdk_display->green_byte] << 8;
spot->blue = smem[gdk_display->blue_byte] << 8;
spot->pixel = *(guint32 *)smem;
}
break;
}
return retval;
}
/*************************************
* gc->get_color() implementations
*************************************/
static GetPixelRet
gdk_fb_get_color_1 (GdkDrawable *drawable,
GdkGC *gc,
int x,
int y,
GdkColor *color)
{
GetPixelRet retval = GPR_NONE;
GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
guchar *mem = private->mem;
guint rowstride = private->rowstride;
guchar foo;
g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
foo = mem[(x >> 3) + y * rowstride];
if (foo & (1 << (x % 8)))
*color = GDK_GC_FBDATA (gc)->values.foreground;
else
{
retval = GPR_USED_BG;
*color = GDK_GC_FBDATA (gc)->values.background;
}
return retval;
}
static GetPixelRet
gdk_fb_get_color_8 (GdkDrawable *drawable,
GdkGC *gc,
int x,
int y,
GdkColor *color)
{
GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
guchar *mem = private->mem;
guint rowstride = private->rowstride;
gint pixel;
g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
pixel = mem[x + y * rowstride];
*color = private->colormap->colors[pixel];
return GPR_NONE;
}
static GetPixelRet
gdk_fb_get_color_16 (GdkDrawable *drawable,
GdkGC *gc,
int x,
int y,
GdkColor *color)
{
GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
guchar *mem = private->mem;
guint rowstride = private->rowstride;
guint16 val16;
g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
val16 = *((guint16 *)&mem[x*2 + y*rowstride]);
color->red = (((1<<gdk_display->modeinfo.red.length) - 1) & (val16 >> gdk_display->modeinfo.red.offset)) << (16 - gdk_display->modeinfo.red.length);
color->green = (((1<<gdk_display->modeinfo.green.length) - 1) & (val16 >> gdk_display->modeinfo.green.offset)) << (16 - gdk_display->modeinfo.green.length);
color->blue = (((1<<gdk_display->modeinfo.blue.length) - 1) & (val16 >> gdk_display->modeinfo.blue.offset)) << (16 - gdk_display->modeinfo.blue.length);
color->pixel = val16;
return GPR_NONE;
}
static GetPixelRet
gdk_fb_get_color_24 (GdkDrawable *drawable,
GdkGC *gc,
int x,
int y,
GdkColor *color)
{
GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
guchar *mem = private->mem;
guint rowstride = private->rowstride;
guchar *smem;
g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
smem = &mem[x*3 + y*rowstride];
color->red = smem[gdk_display->red_byte] << 8;
color->green = smem[gdk_display->green_byte] << 8;
color->blue = smem[gdk_display->blue_byte] << 8;
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
color->pixel = (smem[0]<<16)|(smem[1]<<8)|smem[2];
#else
color->pixel = smem[0]|(smem[1]<<8)|(smem[2]<<16);
#endif
return GPR_NONE;
}
static GetPixelRet
gdk_fb_get_color_32 (GdkDrawable *drawable,
GdkGC *gc,
int x,
int y,
GdkColor *color)
{
GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
guchar *mem = private->mem;
guint rowstride = private->rowstride;
guchar *smem;
g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
smem = &mem[x*4 + y*rowstride];
color->red = smem[gdk_display->red_byte] << 8;
color->green = smem[gdk_display->green_byte] << 8;
color->blue = smem[gdk_display->blue_byte] << 8;
color->pixel = *(guint32 *)smem;
return GPR_NONE;
}
/*************************************
* gc->set_pixel() implementations
*************************************/
static void
gdk_fb_set_pixel_1(GdkDrawable *drawable,
GdkGC *gc,
int x,
int y,
gulong pixel)
{
GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
guchar *mem = private->mem;
guint rowstride = private->rowstride;
guchar *ptr;
g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
ptr = mem + (y*rowstride) + (x >> 3);
if (pixel)
*ptr |= (1 << (x % 8));
else
*ptr &= ~(1 << (x % 8));
}
static void
gdk_fb_set_pixel_8(GdkDrawable *drawable,
GdkGC *gc,
int x,
int y,
gulong pixel)
{
GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
guchar *mem = private->mem;
guint rowstride = private->rowstride;
g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
mem[x + y*rowstride] = pixel;
}
static void
gdk_fb_set_pixel_16(GdkDrawable *drawable,
GdkGC *gc,
int x,
int y,
gulong pixel)
{
GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
guchar *mem = private->mem;
guint rowstride = private->rowstride;
guint16 *ptr;
g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
ptr = (guint16 *)&mem[x*2 + y*rowstride];
*ptr = pixel;
}
static void
gdk_fb_set_pixel_24(GdkDrawable *drawable,
GdkGC *gc,
int x,
int y,
gulong pixel)
{
GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
guchar *mem = private->mem;
guint rowstride = private->rowstride;
guchar *smem;
g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
smem = &mem[x*3 + y*rowstride];
smem[0] = pixel & 0xff;
smem[1] = (pixel >> 8) & 0xff;
smem[2] = (pixel >> 16) & 0xff;
}
static void
gdk_fb_set_pixel_32(GdkDrawable *drawable,
GdkGC *gc,
int x,
int y,
gulong pixel)
{
GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
guchar *mem = private->mem;
guint rowstride = private->rowstride;
guint32 *smem;
g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
smem = (guint32 *)&mem[x*4 + y*rowstride];
*smem = pixel;
}
/*************************************
* gc->fill_span() implementations
*************************************/
static void
gdk_fb_fill_span_generic (GdkDrawable *drawable,
GdkGC *gc,
GdkSpan *span,
GdkColor *color)
{
int curx;
GdkColor spot = *color;
GdkGCFBData *gc_private;
GdkDrawableFBData *private;
gint left, right, y;
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;
GdkDrawableFBData *ts_private;
gboolean solid_stipple;
GdkFunction func;
private = GDK_DRAWABLE_FBDATA (drawable);
gc_private = GDK_GC_FBDATA (gc);
g_assert (gc);
y = span->y;
left = span->x;
right = span->x + span->width;
func = gc_private->values.function;
cmask = gc_private->values.clip_mask;
clipxoff = clipyoff = tsxoff = tsyoff = 0;
mask_rowstride = 0;
solid_stipple = FALSE;
clipmem = NULL;
if (cmask)
{
GdkDrawableFBData *cmask_private;
cmask_private = GDK_DRAWABLE_IMPL_FBDATA (cmask);
clipmem = cmask_private->mem;
clipxoff = cmask_private->abs_x - gc_private->values.clip_x_origin - private->abs_x;
clipyoff = cmask_private->abs_y - gc_private->values.clip_y_origin - private->abs_y;
mask_rowstride = cmask_private->rowstride;
}
if (gc_private->values.fill == GDK_TILED &&
gc_private->values.tile)
{
gint xstep;
gint relx, rely;
int drawh;
GdkFBDrawingContext *dc, dc_data;
dc = &dc_data;
gdk_fb_drawing_context_init (dc, drawable, gc, FALSE, TRUE);
ts = gc_private->values.tile;
ts_private = GDK_DRAWABLE_IMPL_FBDATA (ts);
rely = y - private->abs_y;
drawh = (rely + gc_private->values.ts_y_origin) % ts_private->height;
if (drawh < 0)
drawh += GDK_DRAWABLE_FBDATA (ts)->height;
for (curx = left; curx < right; curx += xstep)
{
int draww;
relx = curx - private->abs_x;
draww = (relx + gc_private->values.ts_x_origin) % ts_private->width;
if (draww < 0)
draww += ts_private->width;
xstep = MIN (ts_private->width - draww, right - relx);
gdk_fb_draw_drawable_3 (drawable, gc, GDK_DRAWABLE_IMPL (ts),
dc,
draww, drawh,
relx, rely,
xstep, 1);
}
gdk_fb_drawing_context_finalize (dc);
return;
}
else if ((gc_private->values.fill == GDK_STIPPLED ||
gc_private->values.fill == GDK_OPAQUE_STIPPLED) &&
gc_private->values.stipple)
{
ts = gc_private->values.stipple;
tsxoff = GDK_DRAWABLE_FBDATA (ts)->abs_x - gc_private->values.ts_x_origin - private->abs_x;
tsyoff = GDK_DRAWABLE_FBDATA (ts)->abs_y - gc_private->values.ts_y_origin - private->abs_y;
solid_stipple = (gc_private->values.fill == GDK_OPAQUE_STIPPLED);
}
for (curx = left; curx < right; curx++)
{
int maskx = curx+clipxoff, masky = y + clipyoff;
guchar foo;
if (cmask)
{
foo = clipmem[masky*mask_rowstride + (maskx >> 3)];
if (!(foo & (1 << (maskx % 8))))
continue;
}
if (func == GDK_INVERT)
{
(gc_private->get_color) (drawable, gc, curx, y, &spot);
spot.pixel = ~spot.pixel;
spot.red = ~spot.red;
spot.green = ~spot.green;
spot.blue = ~spot.blue;
}
else if (ts)
{
int wid, hih;
ts_private = GDK_DRAWABLE_IMPL_FBDATA (ts);
wid = ts_private->width;
hih = ts_private->height;
maskx = (curx+tsxoff)%wid;
masky = (y+tsyoff)%hih;
if (maskx < 0)
maskx += wid;
if (masky < 0)
masky += hih;
foo = ts_private->mem[(maskx >> 3) + ts_private->rowstride*masky];
if (foo & (1 << (maskx % 8)))
{
spot = gc_private->values.foreground;
}
else if (solid_stipple)
{
spot = gc_private->values.background;
}
else
continue;
}
(gc_private->set_pixel) (drawable, gc, curx, y, spot.pixel);
}
}
static void
gdk_fb_fill_span_simple_1 (GdkDrawable *drawable,
GdkGC *gc,
GdkSpan *span,
GdkColor *color)
{
int curx;
GdkGCFBData *gc_private;
GdkDrawableFBData *private;
guchar *mem, *ptr;
guint rowstride;
gint left, right, y;
private = GDK_DRAWABLE_FBDATA (drawable);
gc_private = GDK_GC_FBDATA (gc);
g_assert (gc);
g_assert (!gc_private->values.clip_mask &&
!gc_private->values.tile &&
!gc_private->values.stipple &&
gc_private->values.function != GDK_INVERT);
y = span->y;
left = span->x;
right = span->x + span->width;
mem = private->mem;
rowstride = private->rowstride;
{
int fromx = MIN ((left+7)&(~7), right);
int begn = fromx - left, begoff = left % 8, endn;
guchar begmask, endmask;
int body_end = right & ~7;
int body_len = (body_end - fromx)/8;
begmask = ((1 << (begn + begoff)) - 1)
& ~((1 << (begoff)) - 1);
endn = right - body_end;
endmask = (1 << endn) - 1;
ptr = mem + y*rowstride + (left >> 3);
if (color->pixel)
*ptr |= begmask;
else
*ptr &= ~begmask;
curx = fromx;
if (curx < right)
{
ptr = mem + y*rowstride + (curx >> 3);
memset (ptr, color->pixel?0xFF:0, body_len);
if (endn)
{
ptr = mem + y*rowstride + (body_end >> 3);
if (color->pixel)
*ptr |= endmask;
else
*ptr &= ~endmask;
}
}
}
}
static void
gdk_fb_fill_span_simple_8 (GdkDrawable *drawable,
GdkGC *gc,
GdkSpan *span,
GdkColor *color)
{
GdkGCFBData *gc_private;
GdkDrawableFBData *private;
guchar *mem, *ptr;
guint rowstride;
private = GDK_DRAWABLE_FBDATA (drawable);
gc_private = GDK_GC_FBDATA (gc);
g_assert (gc);
g_assert (!gc_private->values.clip_mask &&
!gc_private->values.tile &&
!gc_private->values.stipple &&
gc_private->values.function != GDK_INVERT);
mem = private->mem;
rowstride = private->rowstride;
ptr = mem + span->y*rowstride + span->x;
memset (ptr, color->pixel, span->width);
}
static void
gdk_fb_fill_span_simple_16 (GdkDrawable *drawable,
GdkGC *gc,
GdkSpan *span,
GdkColor *color)
{
GdkGCFBData *gc_private;
GdkDrawableFBData *private;
guchar *mem;
guint rowstride;
guint16 *p16;
int n;
int i;
private = GDK_DRAWABLE_FBDATA (drawable);
gc_private = GDK_GC_FBDATA (gc);
g_assert (gc);
g_assert (!gc_private->values.clip_mask &&
!gc_private->values.tile &&
!gc_private->values.stipple &&
gc_private->values.function != GDK_INVERT);
mem = private->mem;
rowstride = private->rowstride;
n = span->width;
p16 = (guint16 *)(mem + span->y * rowstride + span->x*2);
for (i = 0; i < n; i++)
*(p16++) = color->pixel;
}
static void
gdk_fb_fill_span_simple_24 (GdkDrawable *drawable,
GdkGC *gc,
GdkSpan *span,
GdkColor *color)
{
GdkGCFBData *gc_private;
GdkDrawableFBData *private;
guchar *mem, *ptr;
guint rowstride;
int n;
guchar redval, greenval, blueval;
guchar *firstline, *ptr_end;
private = GDK_DRAWABLE_FBDATA (drawable);
gc_private = GDK_GC_FBDATA (gc);
g_assert (gc);
g_assert (!gc_private->values.clip_mask &&
!gc_private->values.tile &&
!gc_private->values.stipple &&
gc_private->values.function != GDK_INVERT);
mem = private->mem;
rowstride = private->rowstride;
redval = color->red>>8;
greenval = color->green>>8;
blueval = color->blue>>8;
n = span->width*3;
firstline = ptr = mem + span->y * rowstride + span->x*3;
ptr_end = ptr+n;
while (ptr < ptr_end)
{
ptr[gdk_display->red_byte] = redval;
ptr[gdk_display->green_byte] = greenval;
ptr[gdk_display->blue_byte] = blueval;
ptr += 3;
}
}
static void
gdk_fb_fill_span_simple_32 (GdkDrawable *drawable,
GdkGC *gc,
GdkSpan *span,
GdkColor *color)
{
GdkGCFBData *gc_private;
GdkDrawableFBData *private;
guchar *mem;
guint rowstride;
guint32 *p32;
int n;
int i;
private = GDK_DRAWABLE_FBDATA (drawable);
gc_private = GDK_GC_FBDATA (gc);
g_assert (gc);
g_assert (!gc_private->values.clip_mask &&
!gc_private->values.tile &&
!gc_private->values.stipple &&
gc_private->values.function != GDK_INVERT);
mem = private->mem;
rowstride = private->rowstride;
n = span->width;
p32 = (guint32 *)(mem + span->y * rowstride + span->x*4);
for (i = 0; i < n; i++)
*(p32++) = color->pixel;
}
/*************************************
* gc->draw_drawable() implementations
*************************************/
static void
gdk_fb_draw_drawable_generic (GdkDrawable *drawable,
GdkGC *gc,
GdkPixmap *src,
GdkFBDrawingContext *dc,
gint start_y,
gint end_y,
gint start_x,
gint end_x,
gint src_x_off,
gint src_y_off,
gint draw_direction)
{
GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
int cur_x, cur_y;
if (draw_direction < 0)
{
int tmp;
tmp = start_y;
start_y = end_y;
end_y = tmp;
start_y--;
end_y--;
tmp = start_x;
start_x = end_x;
end_x = tmp;
start_x--;
end_x--;
}
for (cur_y = start_y; cur_y != end_y; cur_y+=draw_direction)
{
for (cur_x = start_x; cur_x != end_x; cur_x+=draw_direction)
{
GdkColor spot;
if (GDK_GC_FBDATA(gc)->values.clip_mask)
{
int maskx = cur_x + dc->clipxoff, masky = cur_y + dc->clipyoff;
guchar foo;
foo = dc->clipmem[masky*dc->clip_rowstride + (maskx >> 3)];
if (!(foo & (1 << (maskx % 8))))
continue;
}
switch (gdk_fb_drawable_get_color (src, gc, cur_x + src_x_off, cur_y + src_y_off, &spot))
{
case GPR_AA_GRAYVAL:
{
GdkColor realspot, fg;
guint graylevel = spot.pixel;
gint tmp;
if (private->depth == 1)
{
if (spot.pixel > 192)
spot = GDK_GC_FBDATA (gc)->values.foreground;
else
spot = GDK_GC_FBDATA (gc)->values.background;
break;
}
else
{
if (graylevel >= 254)
{
spot = GDK_GC_FBDATA (gc)->values.foreground;
}
else if (graylevel <= 2)
{
if (!dc->draw_bg)
continue;
spot = GDK_GC_FBDATA (gc)->values.background;
}
else
{
switch ((GDK_GC_FBDATA (gc)->get_color) (drawable, gc, cur_x, cur_y, &realspot))
{
case GPR_USED_BG:
{
int bgx, bgy;
bgx = (cur_x - GDK_DRAWABLE_IMPL_FBDATA (dc->bg_relto)->abs_x) % GDK_DRAWABLE_IMPL_FBDATA (dc->bgpm)->width + private->abs_x;
bgy = (cur_y - GDK_DRAWABLE_IMPL_FBDATA (dc->bg_relto)->abs_y) % GDK_DRAWABLE_IMPL_FBDATA (dc->bgpm)->height + private->abs_y;
gdk_fb_drawable_get_color (dc->bgpm, gc, bgx, bgy, &realspot);
}
break;
case GPR_NONE:
break;
default:
g_assert_not_reached ();
break;
}
fg = GDK_GC_FBDATA (gc)->values.foreground;
/* Now figure out what 'spot' should actually look like */
fg.red >>= 8;
fg.green >>= 8;
fg.blue >>= 8;
realspot.red >>= 8;
realspot.green >>= 8;
realspot.blue >>= 8;
tmp = (fg.red - realspot.red) * graylevel;
spot.red = realspot.red + ((tmp + (tmp >> 8) + 0x80) >> 8);
spot.red <<= 8;
tmp = (fg.green - realspot.green) * graylevel;
spot.green = realspot.green + ((tmp + (tmp >> 8) + 0x80) >> 8);
spot.green <<= 8;
tmp = (fg.blue - realspot.blue) * graylevel;
spot.blue = realspot.blue + ((tmp + (tmp >> 8) + 0x80) >> 8);
spot.blue <<= 8;
/* Now find the pixel for this thingie */
switch (private->depth)
{
case 8:
if (!gdk_colormap_alloc_color (private->colormap, &spot, FALSE, TRUE))
{
g_error ("Can't allocate AA color!");
}
break;
case 16:
spot.pixel = (spot.red >> (16 - gdk_display->modeinfo.red.length)) << gdk_display->modeinfo.red.offset;
spot.pixel |= (spot.green >> (16 - gdk_display->modeinfo.green.length)) << gdk_display->modeinfo.green.offset;
spot.pixel |= (spot.blue >> (16 - gdk_display->modeinfo.blue.length)) << gdk_display->modeinfo.blue.offset;
break;
case 24:
case 32:
spot.pixel = ((spot.red & 0xFF00) >> 8 << (gdk_display->modeinfo.red.offset))
| ((spot.green & 0xFF00) >> 8 << (gdk_display->modeinfo.green.offset))
| ((spot.blue & 0xFF00) >> 8 << (gdk_display->modeinfo.blue.offset));
break;
}
}
}
}
break;
case GPR_USED_BG:
if (!dc->draw_bg)
continue;
break;
case GPR_NONE:
break;
default:
g_assert_not_reached ();
break;
}
(GDK_GC_FBDATA (gc)->set_pixel) (drawable, gc, cur_x, cur_y, spot.pixel);
}
}
}
void
gdk_fb_draw_drawable_memmove (GdkDrawable *drawable,
GdkGC *gc,
GdkPixmap *src,
GdkFBDrawingContext *dc,
gint start_y,
gint end_y,
gint start_x,
gint end_x,
gint src_x_off,
gint src_y_off,
gint draw_direction)
{
GdkDrawableFBData *src_private = GDK_DRAWABLE_FBDATA (src);
guint depth = src_private->depth;
guint src_rowstride = src_private->rowstride;
guchar *srcmem = src_private->mem;
int linelen = (end_x - start_x)*(depth>>3);
gint cur_y;
if (draw_direction < 0)
{
int tmp;
tmp = start_y;
start_y = end_y;
end_y = tmp;
start_y--;
end_y--;
}
for(cur_y = start_y; cur_y != end_y; cur_y += draw_direction)
{
memmove (dc->mem + (cur_y * dc->rowstride) + start_x*(depth>>3),
srcmem + ((cur_y + src_y_off)*src_rowstride) + (start_x + src_x_off)*(depth>>3),
linelen);
}
}
static void
gdk_fb_draw_drawable_aa_24 (GdkDrawable *drawable,
GdkGC *gc,
GdkPixmap *src,
GdkFBDrawingContext *dc,
gint start_y,
gint end_y,
gint start_x,
gint end_x,
gint src_x_off,
gint src_y_off,
gint draw_direction)
{
GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
int x, y;
GdkGCFBData *gc_private;
guchar *dmem = private->mem;
guint dst_rowstride = private->rowstride;
guchar *smem = GDK_DRAWABLE_FBDATA (src)->mem;
guint src_rowstride = GDK_DRAWABLE_FBDATA (src)->rowstride;
guchar *dst;
guint grayval;
gint r, g, b, tmp;
GdkColor fg;
gint fg_r, fg_g, fg_b;
gc_private = GDK_GC_FBDATA (gc);
fg = GDK_GC_FBDATA (gc)->values.foreground;
fg_r = fg.red >> 8;
fg_g = fg.green >> 8;
fg_b = fg.blue >> 8;
if (draw_direction < 0)
{
int tmp;
tmp = start_y;
start_y = end_y;
end_y = tmp;
start_y--;
end_y--;
tmp = start_x;
start_x = end_x;
end_x = tmp;
start_x--;
end_x--;
}
for (y = start_y; y != end_y; y+=draw_direction)
{
for (x = start_x; x != end_x; x+=draw_direction)
{
grayval = smem[x + src_x_off + (y + src_y_off) * src_rowstride];
if ((grayval <= 2) && (!dc->draw_bg))
continue;
dst = &dmem[x*3 + y*dst_rowstride];
if (grayval >= 254)
{
dst[gdk_display->red_byte] = fg_r;
dst[gdk_display->green_byte] = fg_g;
dst[gdk_display->blue_byte] = fg_b;
}
else if (grayval <= 2)
{
dst[gdk_display->red_byte] = GDK_GC_FBDATA (gc)->values.background.red >> 8;
dst[gdk_display->green_byte] = GDK_GC_FBDATA (gc)->values.background.green >> 8;
dst[gdk_display->blue_byte] = GDK_GC_FBDATA (gc)->values.background.blue >> 8;
}
else
{
r = dst[gdk_display->red_byte];
tmp = (fg_r - r) * (gint)grayval;
r = r + ((tmp + (tmp >> 8) + 0x80) >> 8);
dst[gdk_display->red_byte] = r;
g = dst[gdk_display->green_byte];
tmp = (fg_g - g) * (gint)grayval;
g = g + ((tmp + (tmp >> 8) + 0x80) >> 8);
dst[gdk_display->green_byte] = g;
b = dst[gdk_display->blue_byte];
tmp = (fg_b - b) * (gint)grayval;
b = b + ((tmp + (tmp >> 8) + 0x80) >> 8);
dst[gdk_display->blue_byte] = b;
}
}
}
}
/*************************************
* gc->fill_rectangle() implementations
*************************************/
void
gdk_fb_fill_rectangle_generic (GdkDrawable *drawable,
GdkGC *gc,
GdkRectangle *rect,
GdkColor *color)
{
GdkDrawableFBData *private;
GdkSpan *spans;
int i;
private = GDK_DRAWABLE_FBDATA (drawable);
spans = g_new (GdkSpan, rect->height);
for (i=0;i<rect->height;i++)
{
spans[i].x = rect->x - private->abs_x;
spans[i].y = rect->y+i - private->abs_y;
spans[i].width = rect->width;
}
gdk_fb_fill_spans (drawable, gc, spans, rect->height, TRUE);
g_free (spans);
}
void
gdk_fb_fill_rectangle_simple_16 (GdkDrawable *drawable,
GdkGC *gc,
GdkRectangle *rect,
GdkColor *color)
{
GdkGCFBData *gc_private;
GdkDrawableFBData *private;
guchar *ptr;
guint rowstride;
int n;
gboolean extra;
int i;
guint32 pixel;
gint height;
private = GDK_DRAWABLE_FBDATA (drawable);
gc_private = GDK_GC_FBDATA (gc);
rowstride = private->rowstride - rect->width*2;
ptr = (guchar *)private->mem + rect->y * private->rowstride + rect->x*2;
extra = rect->width&1;
n = rect->width>>1;
pixel = (color->pixel << 16) | color->pixel;
height = rect->height;
while (height>0)
{
i = n;
while (i>0)
{
*(guint32 *)ptr = pixel;
ptr += 4;
i--;
}
if (extra)
{
*(guint16 *)ptr = color->pixel;
ptr += 2;
}
ptr += rowstride;
height--;
}
}
void
gdk_fb_fill_rectangle_simple_32 (GdkDrawable *drawable,
GdkGC *gc,
GdkRectangle *rect,
GdkColor *color)
{
GdkGCFBData *gc_private;
GdkDrawableFBData *private;
guchar *ptr;
guint rowstride;
int n;
int i;
guint32 pixel;
gint height;
private = GDK_DRAWABLE_FBDATA (drawable);
gc_private = GDK_GC_FBDATA (gc);
rowstride = private->rowstride - rect->width*4;
ptr = (guchar *)private->mem + rect->y * private->rowstride + rect->x*4;
n = rect->width;
pixel = color->pixel;
height = rect->height;
while (height>0)
{
i = n;
while (i>0)
{
*(guint32 *)ptr = pixel;
ptr += 4;
i--;
}
ptr += rowstride;
height--;
}
}
/*************************************
* GC state calculation
*************************************/
void
_gdk_fb_gc_calc_state (GdkGC *gc,
GdkGCValuesMask changed)
{
GdkGCFBData *gc_private;
int i;
gc_private = GDK_GC_FBDATA (gc);
gc_private->fill_span = gdk_fb_fill_span_generic;
gc_private->fill_rectangle = gdk_fb_fill_rectangle_generic;
for (i=0;i<GDK_NUM_FB_SRCBPP;i++)
gc_private->draw_drawable[i] = gdk_fb_draw_drawable_generic;
if (changed & _GDK_FB_GC_DEPTH)
switch (gc_private->depth)
{
case 1:
gc_private->set_pixel = gdk_fb_set_pixel_1;
gc_private->get_color = gdk_fb_get_color_1;
break;
case 8:
gc_private->set_pixel = gdk_fb_set_pixel_8;
gc_private->get_color = gdk_fb_get_color_8;
break;
case 16:
gc_private->set_pixel = gdk_fb_set_pixel_16;
gc_private->get_color = gdk_fb_get_color_16;
break;
case 24:
gc_private->set_pixel = gdk_fb_set_pixel_24;
gc_private->get_color = gdk_fb_get_color_24;
break;
case 32:
gc_private->set_pixel = gdk_fb_set_pixel_32;
gc_private->get_color = gdk_fb_get_color_32;
break;
default:
g_assert_not_reached ();
break;
}
if (!gc_private->values.clip_mask)
{
switch (gc_private->depth)
{
case 8:
gc_private->draw_drawable[GDK_FB_SRC_BPP_8] = gdk_fb_draw_drawable_memmove;
break;
case 16:
gc_private->draw_drawable[GDK_FB_SRC_BPP_16] = gdk_fb_draw_drawable_memmove;
break;
case 24:
gc_private->draw_drawable[GDK_FB_SRC_BPP_8_AA_GRAYVAL] = gdk_fb_draw_drawable_aa_24;
gc_private->draw_drawable[GDK_FB_SRC_BPP_24] = gdk_fb_draw_drawable_memmove;
break;
case 32:
gc_private->draw_drawable[GDK_FB_SRC_BPP_32] = gdk_fb_draw_drawable_memmove;
break;
}
}
if (!gc_private->values.clip_mask &&
!gc_private->values.tile &&
!gc_private->values.stipple &&
gc_private->values.function != GDK_INVERT)
{
switch (gc_private->depth)
{
case 1:
gc_private->fill_span = gdk_fb_fill_span_simple_1;
break;
case 8:
gc_private->fill_span = gdk_fb_fill_span_simple_8;
break;
case 16:
gc_private->fill_span = gdk_fb_fill_span_simple_16;
gc_private->fill_rectangle = gdk_fb_fill_rectangle_simple_16;
break;
case 24:
gc_private->fill_span = gdk_fb_fill_span_simple_24;
break;
case 32:
gc_private->fill_span = gdk_fb_fill_span_simple_32;
gc_private->fill_rectangle = gdk_fb_fill_rectangle_simple_32;
break;
default:
g_assert_not_reached ();
break;
}
}
}