diff options
author | Elliot Lee <sopwith@src.gnome.org> | 2000-06-20 20:20:38 +0000 |
---|---|---|
committer | Elliot Lee <sopwith@src.gnome.org> | 2000-06-20 20:20:38 +0000 |
commit | dd7510dccbf51df37e0d02d31f4daed4e52152e6 (patch) | |
tree | 96d9f438ed17642198ac2970af857476056a133b /gdk/linux-fb/gdkdrawable-fb2.c | |
parent | 2eb7985b0bb0542d9c2aa427a8818d9def8ecf80 (diff) | |
download | gtk+-dd7510dccbf51df37e0d02d31f4daed4e52152e6.tar.gz |
*** empty log message ***
Diffstat (limited to 'gdk/linux-fb/gdkdrawable-fb2.c')
-rw-r--r-- | gdk/linux-fb/gdkdrawable-fb2.c | 950 |
1 files changed, 629 insertions, 321 deletions
diff --git a/gdk/linux-fb/gdkdrawable-fb2.c b/gdk/linux-fb/gdkdrawable-fb2.c index 99d158f749..81ef83091a 100644 --- a/gdk/linux-fb/gdkdrawable-fb2.c +++ b/gdk/linux-fb/gdkdrawable-fb2.c @@ -1,11 +1,21 @@ #include "gdkprivate-fb.h" #include "mi.h" -#include <t1lib.h> + +/* #define USE_FTGRAYS */ +#define USE_AA +#include <freetype/ftglyph.h> + +#include <endian.h> +#ifndef __BYTE_ORDER +#error "endian.h needs to #define __BYTE_ORDER" +#endif #ifndef g_alloca #define g_alloca alloca #endif +static void gdk_fb_drawable_set_pixel(GdkDrawable *drawable, GdkGC *gc, int x, int y, GdkColor *spot, gboolean abs_coords); + static void gdk_fb_drawable_destroy (GdkDrawable *drawable); void gdk_fb_draw_rectangle (GdkDrawable *drawable, GdkGC *gc, @@ -42,6 +52,12 @@ static void gdk_fb_draw_text_wc (GdkDrawable *drawable, gint y, const GdkWChar *text, gint text_length); +static void gdk_fb_draw_glyphs(GdkDrawable *drawable, + GdkGC *gc, + PangoFont *font, + gint x, + gint y, + PangoGlyphString *glyphs); void gdk_fb_draw_drawable (GdkDrawable *drawable, GdkGC *gc, GdkPixmap *src, @@ -75,7 +91,8 @@ GdkDrawableClass _gdk_fb_drawable_class = { gdk_fb_draw_drawable, gdk_fb_draw_points, gdk_fb_draw_segments, - gdk_fb_draw_lines + gdk_fb_draw_lines, + gdk_fb_draw_glyphs }; /***************************************************** @@ -184,12 +201,10 @@ gdk_fb_clip_region(GdkDrawable *drawable, GdkGC *gc, gboolean do_clipping) } static void -gdk_fb_fill_span(GdkDrawable *drawable, GdkGC *gc, GdkSegment *cur, guint pixel, GdkVisual *visual) +gdk_fb_fill_span(GdkDrawable *drawable, GdkGC *gc, GdkSegment *cur, GdkColor *color, 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; + GdkColor spot = *color; if(gc && (GDK_GC_FBDATA(gc)->values.clip_mask @@ -218,6 +233,10 @@ gdk_fb_fill_span(GdkDrawable *drawable, GdkGC *gc, GdkSegment *cur, guint pixel, { gint xstep, ystep; gint relx, rely; + GdkFBDrawingContext *dc, dc_data; + dc = &dc_data; + + gdk_fb_drawing_context_init(dc, drawable, gc, FALSE, TRUE); ts = GDK_GC_FBDATA(gc)->values.tile; for(cury = cur->y1; cury < cur->y2; cury += ystep) @@ -243,13 +262,16 @@ gdk_fb_fill_span(GdkDrawable *drawable, GdkGC *gc, GdkSegment *cur, guint pixel, xstep = MIN(GDK_DRAWABLE_P(ts)->width - draww, cur->x2 - relx); - gdk_fb_draw_drawable_2(drawable, gc, ts, + gdk_fb_draw_drawable_3(drawable, gc, ts, + dc, draww, drawh, relx, rely, - xstep, ystep, FALSE, TRUE); + xstep, ystep); } } + gdk_fb_drawing_context_finalize(dc); + return; } else if((GDK_GC_FBDATA(gc)->values.fill == GDK_STIPPLED @@ -262,163 +284,165 @@ gdk_fb_fill_span(GdkDrawable *drawable, GdkGC *gc, GdkSegment *cur, guint pixel, solid_stipple = (GDK_GC_FBDATA(gc)->values.fill == GDK_OPAQUE_STIPPLED); } - switch(depth) + for(cury = cur->y1; cury < cur->y2; cury++) { - case 1: - g_assert(!ts); - for(cury = cur->y1; cury < cur->y2; cury++) + for(curx = cur->x1; curx < cur->x2; curx++) { - 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)]; + int maskx = curx+clipxoff, masky = cury + clipyoff; + guchar foo; - 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++) + if(cmask) { - guchar *ptr = mem + (cury * rowstride) + curx; - int maskx = curx+clipxoff, masky = cury + clipyoff; - guchar foo; + foo = clipmem[masky*mask_rowstride + (maskx >> 3)]; - 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; + if(!(foo & (1 << (maskx % 8)))) + continue; } - } - break; - case 16: - case 24: - case 32: - for(cury = cur->y1; cury < cur->y2; cury++) - { - for(curx = cur->x1; curx < cur->x2; curx++) + if(ts) { - guint *ptr2 = (guint *)(mem + (cury * rowstride) + (curx * (depth >> 3))); - int maskx = curx+clipxoff, masky = cury + clipyoff; - guchar foo; + int wid = GDK_DRAWABLE_P(ts)->width, hih = GDK_DRAWABLE_P(ts)->height; - if(cmask) - { - foo = clipmem[masky*mask_rowstride + (maskx >> 3)]; + maskx = (curx+tsxoff)%wid; + masky = (cury+tsyoff)%hih; + if(maskx < 0) + maskx += wid; + if(masky < 0) + masky += hih; - if(!(foo & (1 << (maskx % 8)))) - continue; + foo = GDK_DRAWABLE_FBDATA(ts)->mem[(maskx >> 3) + GDK_DRAWABLE_FBDATA(ts)->rowstride*masky]; + if(foo & (1 << (maskx % 8))) + { + spot = GDK_GC_FBDATA(gc)->values.foreground; } - - if(ts) + else if(solid_stipple) { - 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; + spot = GDK_GC_FBDATA(gc)->values.background; } - - *ptr2 = (*ptr2 & ~(visual->red_mask|visual->green_mask|visual->blue_mask)) | pixel; + else + continue; } + + gdk_fb_drawable_set_pixel(drawable, gc, curx, cury, &spot, TRUE); } - break; } } else { - switch(depth) + guchar *mem = GDK_DRAWABLE_FBDATA(drawable)->mem, *ptr; + guint rowstride = GDK_DRAWABLE_FBDATA(drawable)->rowstride; + int n; + + switch(GDK_DRAWABLE_P(drawable)->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)); - } - } + { + int fromx = MIN((cur->x1+7)&(~7), cur->x2); + int begn = fromx - cur->x1, begoff = cur->x1 % 8, endn; + guchar begmask, endmask; + int body_end = cur->x2 & ~7; + int body_len = (body_end - fromx)/8; + + begmask = ((1 << (begn + begoff)) - 1) + & ~((1 << (begoff)) - 1); + endn = cur->x2 - body_end; + endmask = (1 << endn) - 1; + + for(cury = cur->y1; cury < cur->y2; cury++) + { + ptr = mem + cury*rowstride + (cur->x1 >> 3); + + if(spot.pixel) + *ptr |= begmask; + else + *ptr &= ~begmask; + + curx = fromx; + + if(curx < cur->x2) + { + ptr = mem + cury*rowstride + (curx >> 3); + memset(ptr, spot.pixel?0xFF:0, body_len); + + if(endn) + { + ptr = mem + cury*rowstride + (body_end >> 3); + if(spot.pixel) + *ptr |= endmask; + else + *ptr &= ~endmask; + } + } + } + } 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); + ptr = mem + cury*rowstride + cur->x1; + memset(ptr, spot.pixel, cur->x2 - cur->x1); } break; - case 16: + { + int i; + n = cur->x2 - cur->x1; + for(cury = cur->y1; cury < cur->y2; cury++) + { + guint16 *p16 = (guint16 *)(mem + cury * rowstride + cur->x1*2); + for(i = 0; i < n; i++) + *(p16++) = spot.pixel; + } + } + break; case 24: + { + guchar redval = spot.red>>8, greenval=spot.green>>8, blueval=spot.blue>>8; + guchar *firstline, *ptr_end; + + if((cur->y2 - cur->y1) <= 0) + break; + + n = (cur->x2 - cur->x1)*3; + + firstline = ptr = mem + cur->y1 * rowstride + cur->x1*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; + } + for(cury = cur->y1 + 1, ptr = mem + cury * rowstride + cur->x1*3; cury < cur->y2; cury++, ptr += rowstride) + { + memcpy(ptr, firstline, n); + } + } + break; case 32: + { + int i; + n = cur->x2 - cur->x1; + for(cury = cur->y1; cury < cur->y2; cury++) + { + guint32 *p32 = (guint32 *)(mem + cury * rowstride + cur->x1*4); + for(i = 0; i < n; i++) + *(p32++) = spot.pixel; + } + } + break; + default: + g_assert_not_reached(); +#if 0 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; + gdk_fb_drawable_set_pixel(drawable, gc, curx, cury, &spot, TRUE); } } +#endif break; } } @@ -430,7 +454,7 @@ gdk_fb_fill_spans(GdkDrawable *drawable, GdkRectangle *rects, int nrects) { int i; - guint pixel; + GdkColor color; GdkRegion *real_clip_region, *tmpreg; GdkRectangle draw_rect, cursor_rect; GdkVisual *visual = gdk_visual_get_system(); @@ -441,12 +465,12 @@ gdk_fb_fill_spans(GdkDrawable *drawable, 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; + if(gc && (GDK_GC_FBDATA(gc)->values_mask | GDK_GC_FOREGROUND)) + color = GDK_GC_FBDATA(gc)->values.foreground; else if(GDK_IS_WINDOW(drawable)) - pixel = GDK_WINDOW_P(drawable)->bg_color.pixel; + color = GDK_WINDOW_P(drawable)->bg_color; else - pixel = 0; + gdk_color_black(GDK_DRAWABLE_P(drawable)->colormap, &color); real_clip_region = gdk_fb_clip_region(drawable, gc, TRUE); @@ -496,11 +520,14 @@ gdk_fb_fill_spans(GdkDrawable *drawable, 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); + { + cur = tmpreg->rects[j]; + gdk_fb_fill_span(drawable, gc, &cur, &color, visual); + } gdk_region_destroy(tmpreg); break; case GDK_OVERLAP_RECTANGLE_IN: - gdk_fb_fill_span(drawable, gc, &cur, pixel, visual); + gdk_fb_fill_span(drawable, gc, &cur, &color, visual); break; default: break; @@ -512,6 +539,230 @@ gdk_fb_fill_spans(GdkDrawable *drawable, gdk_fb_cursor_unhide(); } +typedef enum { GPR_USED_BG, GPR_AA_GRAYVAL, GPR_NONE, GPR_ERR_BOUNDS } GetPixelRet; +static GetPixelRet +gdk_fb_drawable_get_pixel(GdkDrawable *drawable, GdkGC *gc, int x, int y, GdkColor *spot, + gboolean abs_coords, GdkDrawable *bg_relto, GdkDrawable *bgpm) +{ + GetPixelRet retval = GPR_NONE; + guchar *mem = GDK_DRAWABLE_FBDATA(drawable)->mem; + guint rowstride = GDK_DRAWABLE_FBDATA(drawable)->rowstride; + + if(!abs_coords) + { + x += GDK_DRAWABLE_FBDATA(drawable)->abs_x; + y += GDK_DRAWABLE_FBDATA(drawable)->abs_y; + } + + switch(GDK_DRAWABLE_P(drawable)->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; + + if(bgpm) + { + int bgx, bgy; + + bgx = (x - GDK_DRAWABLE_FBDATA(bg_relto)->abs_x) % GDK_DRAWABLE_P(bgpm)->width; + bgy = (y - GDK_DRAWABLE_FBDATA(bg_relto)->abs_y) % GDK_DRAWABLE_P(bgpm)->height; + + gdk_fb_drawable_get_pixel(bgpm, gc, bgx, bgy, spot, FALSE, NULL, NULL); + retval = GPR_USED_BG; + } + else + { + *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 = GDK_DRAWABLE_P(drawable)->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 (__BYTE_ORDER == __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; +} + +static void +gdk_fb_drawable_set_pixel(GdkDrawable *drawable, GdkGC *gc, int x, int y, GdkColor *spot, + gboolean abs_coords) +{ + guchar *mem = GDK_DRAWABLE_FBDATA(drawable)->mem; + guint rowstride = GDK_DRAWABLE_FBDATA(drawable)->rowstride; + + if(!abs_coords) + { + x += GDK_DRAWABLE_FBDATA(drawable)->abs_x; + y += GDK_DRAWABLE_FBDATA(drawable)->abs_y; + } + + switch(GDK_DRAWABLE_P(drawable)->depth) + { + case 1: + { + guchar *foo = mem + (y*rowstride) + (x >> 3); + + if(spot->pixel) + *foo |= (1 << (x % 8)); + else + *foo &= ~(1 << (x % 8)); + } + break; + case 8: + mem[x + y*rowstride] = spot->pixel; + break; + case 16: + { + guint16 *p16 = (guint16 *)&mem[x*2 + y*rowstride]; + *p16 = spot->pixel; + } + break; + case 24: + { + guchar *smem = &mem[x*3 + y*rowstride]; + smem[gdk_display->red_byte] = spot->red >> 8; + smem[gdk_display->green_byte] = spot->green >> 8; + smem[gdk_display->blue_byte] = spot->blue >> 8; + }; + break; + case 32: + { + guint32 *smem = (guint32 *)&mem[x*4 + y*rowstride]; + *smem = spot->pixel; + } + break; + default: + g_assert_not_reached(); + break; + } + +} + +void +gdk_fb_drawing_context_init(GdkFBDrawingContext *dc, + GdkDrawable *drawable, + GdkGC *gc, + gboolean draw_bg, + gboolean do_clipping) +{ + dc->mem = GDK_DRAWABLE_FBDATA(drawable)->mem; + dc->rowstride = GDK_DRAWABLE_FBDATA(drawable)->rowstride; + dc->handle_cursor = FALSE; + dc->bgpm = NULL; + dc->bg_relto = drawable; + dc->draw_bg = draw_bg; + + if(GDK_IS_WINDOW(drawable)) + { + dc->bgpm = GDK_WINDOW_P(drawable)->bg_pixmap; + if(dc->bgpm == GDK_PARENT_RELATIVE_BG) + { + for(; dc->bgpm == GDK_PARENT_RELATIVE_BG && dc->bg_relto; dc->bg_relto = GDK_WINDOW_P(dc->bg_relto)->parent) + dc->bgpm = GDK_WINDOW_P(dc->bg_relto)->bg_pixmap; + } + + if(dc->bgpm == GDK_NO_BG) + dc->bgpm = NULL; + } + dc->clipxoff = - GDK_DRAWABLE_FBDATA(drawable)->abs_x; + dc->clipyoff = - GDK_DRAWABLE_FBDATA(drawable)->abs_y; + + dc->real_clip_region = gdk_fb_clip_region(drawable, gc, do_clipping); + + if(gc) + { + dc->clipxoff -= GDK_GC_FBDATA(gc)->values.clip_x_origin; + dc->clipyoff -= GDK_GC_FBDATA(gc)->values.clip_y_origin; + + if(GDK_GC_FBDATA(gc)->values.clip_mask) + { + dc->clipmem = GDK_DRAWABLE_FBDATA(GDK_GC_FBDATA(gc)->values.clip_mask)->mem; + dc->clip_rowstride = GDK_DRAWABLE_FBDATA(GDK_GC_FBDATA(gc)->values.clip_mask)->rowstride; + } + } + + if(do_clipping) + { + GdkRectangle cursor_rect; + + 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(dc->real_clip_region, &cursor_rect) != GDK_OVERLAP_RECTANGLE_OUT) + { + dc->handle_cursor = TRUE; + gdk_fb_cursor_hide(); + } + } +} + +void +gdk_fb_drawing_context_finalize(GdkFBDrawingContext *dc) +{ + gdk_region_destroy(dc->real_clip_region); + + if(dc->handle_cursor) + gdk_fb_cursor_unhide(); +} + void gdk_fb_draw_drawable_2 (GdkDrawable *drawable, GdkGC *gc, @@ -525,57 +776,58 @@ gdk_fb_draw_drawable_2 (GdkDrawable *drawable, 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; + GdkFBDrawingContext *dc, dc_data; + dc = &dc_data; - 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!"); + gdk_fb_drawing_context_init(dc, drawable, gc, draw_bg, do_clipping); + gdk_fb_draw_drawable_3(drawable, gc, src, dc, xsrc, ysrc, xdest, ydest, width, height); + gdk_fb_drawing_context_finalize(dc); +} + +void +gdk_fb_draw_drawable_3 (GdkDrawable *drawable, + GdkGC *gc, + GdkPixmap *src, + GdkFBDrawingContext *dc, + gint xsrc, + gint ysrc, + gint xdest, + gint ydest, + gint width, + gint height) +{ + GdkRectangle rect; + guchar *srcmem = GDK_DRAWABLE_FBDATA(src)->mem; + int src_x_off, src_y_off; + GdkRegion *tmpreg, *real_clip_region; + int i; 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(!GDK_WINDOW_P(drawable)->mapped) + return; + if(GDK_WINDOW_P(drawable)->input_only) + g_error("Drawing on the evil input-only!"); } 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); + memcpy(srcmem, dc->mem, fbd->rowstride * fbd->lim_y); } - real_clip_region = gdk_fb_clip_region(drawable, gc, do_clipping); + /* Do some magic to avoid creating extra regions unnecessarily */ + tmpreg = dc->real_clip_region; + 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); + real_clip_region = 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; @@ -589,30 +841,6 @@ gdk_fb_draw_drawable_2 (GdkDrawable *drawable, 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++) { @@ -620,16 +848,19 @@ gdk_fb_draw_drawable_2 (GdkDrawable *drawable, int cur_y; if(GDK_DRAWABLE_P(src)->depth == GDK_DRAWABLE_P(drawable)->depth - && GDK_DRAWABLE_P(src)->depth > 1 + && GDK_DRAWABLE_P(src)->depth >= 8 + && GDK_DRAWABLE_P(src)->depth <= 32 && (!gc || !GDK_GC_FBDATA(gc)->values.clip_mask)) { guint depth = GDK_DRAWABLE_P(src)->depth; + guint src_rowstride = GDK_DRAWABLE_FBDATA(src)->rowstride; + int linelen = (cur->x2 - cur->x1)*(depth>>3); for(cur_y = cur->y1; cur_y < cur->y2; cur_y++) { - memcpy(mem + (cur_y * rowstride) + cur->x1*(depth>>3), + memcpy(dc->mem + (cur_y * dc->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)); + linelen); } } else @@ -640,96 +871,118 @@ gdk_fb_draw_drawable_2 (GdkDrawable *drawable, { for(cur_x = cur->x1; cur_x < cur->x2; cur_x++) { - guint pixel; - guint16 *p16; - guint32 *p32; + GdkColor spot; if(gc && GDK_GC_FBDATA(gc)->values.clip_mask) { - int maskx = cur_x+clipxoff, masky = cur_y + clipyoff; + int maskx = cur_x+dc->clipxoff, masky = cur_y + dc->clipyoff; guchar foo; - if(maskx < 0 || masky < 0) - continue; - - foo = clipmem[masky*clip_rowstride + (maskx >> 3)]; + foo = dc->clipmem[masky*dc->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) + switch(gdk_fb_drawable_get_pixel(src, gc, cur_x + src_x_off, cur_y + src_y_off, &spot, TRUE, NULL, NULL)) { - case 1: + case GPR_AA_GRAYVAL: { - guchar *foo = mem + (cur_y*src_rowstride) + (cur_x >> 3); - - if(pixel == GDK_GC_FBDATA(gc)->values.foreground.pixel) - *foo |= (1 << (cur_x % 8)); + GdkColor realspot, fg; + guint graylevel = spot.pixel; + gint tmp; + + if(GDK_DRAWABLE_P(drawable)->depth == 1) + { + if(spot.pixel > 192) + spot = GDK_GC_FBDATA(gc)->values.foreground; + else + spot = GDK_GC_FBDATA(gc)->values.background; + break; + } else - *foo &= ~(1 << (cur_x % 8)); + { + 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_fb_drawable_get_pixel(drawable, gc, cur_x, cur_y, &realspot, TRUE, dc->bg_relto, dc->bgpm)) + { + case GPR_NONE: + case GPR_USED_BG: + 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(GDK_DRAWABLE_P(drawable)->depth) + { + case 8: + if(!gdk_colormap_alloc_color(GDK_DRAWABLE_P(drawable)->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) << (gdk_display->modeinfo.red.offset - 8)) + | ((spot.green & 0xFF00) << (gdk_display->modeinfo.green.offset - 8)) + | ((spot.blue & 0xFF00) << (gdk_display->modeinfo.blue.offset - 8)); + break; + } + } + } } 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; + case GPR_USED_BG: + if(!dc->draw_bg) + continue; break; - case 32: - p32 = (guint32 *)&mem[cur_x*4 + cur_y*rowstride]; - *p32 = pixel; + case GPR_NONE: break; default: g_assert_not_reached(); break; } + + gdk_fb_drawable_set_pixel(drawable, gc, cur_x, cur_y, &spot, GDK_DRAWABLE_P(src)->depth); } } } @@ -737,9 +990,6 @@ gdk_fb_draw_drawable_2 (GdkDrawable *drawable, out: gdk_region_destroy(real_clip_region); - - if(handle_cursor) - gdk_fb_cursor_unhide(); } void @@ -765,33 +1015,7 @@ gdk_fb_draw_text(GdkDrawable *drawable, 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); + g_warning("gdk_fb_draw_text NYI"); } static void @@ -803,19 +1027,7 @@ gdk_fb_draw_text_wc (GdkDrawable *drawable, 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); + g_warning("gdk_fb_draw_text_wc NYI"); } void @@ -831,17 +1043,6 @@ gdk_fb_draw_rectangle (GdkDrawable *drawable, if(filled) { -#if 0 - 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(); - } -#endif - rect.x = x; rect.y = y; rect.width = width; @@ -868,7 +1069,7 @@ static void gdk_fb_draw_points (GdkDrawable *drawable, GdkPoint *points, gint npoints) { - GdkRectangle *rects = alloca(npoints * sizeof(GdkRectangle)); + GdkRectangle *rects = g_alloca(npoints * sizeof(GdkRectangle)); int i; for(i = 0; i < npoints; i++) @@ -916,7 +1117,7 @@ static void gdk_fb_draw_polygon (GdkDrawable *drawable, miFillPolygon(drawable, gc, 0, 0, npoints, points); else { - GdkPoint *realpts = alloca(sizeof(GdkPoint) * (npoints + 1)); + GdkPoint *realpts = g_alloca(sizeof(GdkPoint) * (npoints + 1)); memcpy(realpts, points, sizeof(GdkPoint) * npoints); realpts[npoints] = points[0]; @@ -957,5 +1158,112 @@ static void gdk_fb_draw_segments (GdkDrawable *drawable, void gdk_fb_drawable_clear(GdkDrawable *d) { + extern void + _gdk_windowing_window_clear_area (GdkWindow *window, + gint x, + gint y, + gint width, + gint height); + _gdk_windowing_window_clear_area(d, 0, 0, GDK_DRAWABLE_P(d)->width, GDK_DRAWABLE_P(d)->height); } + +extern FT_Library gdk_fb_ft_lib; + +extern void pango_fb_font_set_size(PangoFont *font); + +static void gdk_fb_draw_glyphs(GdkDrawable *drawable, + GdkGC *gc, + PangoFont *font, + gint x, + gint y, + PangoGlyphString *glyphs) +{ + int i; + GdkPixmapFBData fbd; + GdkDrawablePrivate tmp_foo; + FT_Face ftf; + int xpos; + GdkFBDrawingContext fbdc; + + g_return_if_fail(font); + + gdk_fb_drawing_context_init(&fbdc, drawable, gc, FALSE, TRUE); + + ftf = PANGO_FB_FONT(font)->ftf; + + /* 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; + tmp_foo.window_type = GDK_DRAWABLE_PIXMAP; + + pango_fb_font_set_size(font); + for(i = xpos = 0; i < glyphs->num_glyphs; i++) + { + FT_GlyphSlot g; + FT_Bitmap *renderme; + int this_wid; + + FT_Load_Glyph(ftf, glyphs->glyphs[i].glyph, FT_LOAD_DEFAULT); + g = ftf->glyph; + + if(g->format != ft_glyph_format_bitmap) + { + FT_BitmapGlyph bgy; + int bdepth; +#ifdef USE_AA +#ifdef USE_FTGRAYS + bdepth = 256; +#else + bdepth = 128; +#endif +#else + bdepth = 0; +#endif + + if(FT_Get_Glyph_Bitmap(ftf, glyphs->glyphs[i].glyph, 0, bdepth, NULL, &bgy)) + continue; + + renderme = &bgy->bitmap; + } + else + renderme = &g->bitmap; + + fbd.drawable_data.mem = renderme->buffer; + fbd.drawable_data.rowstride = renderme->pitch; + tmp_foo.width = fbd.drawable_data.lim_x = renderme->width; + tmp_foo.height = fbd.drawable_data.lim_y = renderme->rows; + + switch(renderme->pixel_mode) + { + case ft_pixel_mode_mono: + tmp_foo.depth = 1; + break; + case ft_pixel_mode_grays: +#if defined(USE_FTGRAYS) + tmp_foo.depth = 78; +#else + tmp_foo.depth = 77; +#endif + break; + default: + g_assert_not_reached(); + break; + } + + this_wid = (xpos + glyphs->glyphs[i].geometry.width)/PANGO_SCALE; + gdk_fb_draw_drawable_3(drawable, gc, (GdkDrawable *)&tmp_foo, + &fbdc, + 0, 0, + x + (xpos + glyphs->glyphs[i].geometry.x_offset)/PANGO_SCALE, + y + glyphs->glyphs[i].geometry.y_offset / PANGO_SCALE + + ((-ftf->glyph->metrics.horiBearingY) >> 6), + this_wid, renderme->rows); + + xpos += glyphs->glyphs[i].geometry.width; + } + + gdk_fb_drawing_context_finalize(&fbdc); +} |