# HG changeset patch # User Kenichi Handa # Date 1195448769 0 # Node ID 5ed0717083a1f1d5d1b018feb6d904a838499840 # Parent 6da57551efb7ef1e88fe48473f14d01d7157407e (ftxfont_get_gcs): Renamed from ftxfont_create_gcs. Argument changed. Cache GCs in the per-frame data. (struct ftxfont_frame_data): New struct. (ftxfont_draw_bitmap): New arg gc_fore and flush. (ftxfont_prepare_face, ftxfont_done_face): Delete them. (ftxfont_draw): Get GCs by ftxfont_get_gcs. Reflect s->clip in GCs. (ftxfont_end_for_frame): New function. (syms_of_ftxfont): Set ftxfont_driver.end_for_frame. diff -r 6da57551efb7 -r 5ed0717083a1 src/ftxfont.c --- a/src/ftxfont.c Mon Nov 19 05:02:49 2007 +0000 +++ b/src/ftxfont.c Mon Nov 19 05:06:09 2007 +0000 @@ -40,43 +40,88 @@ static Lisp_Object Qftx; /* Prototypes for helper function. */ -static int ftxfont_create_gcs P_ ((FRAME_PTR, GC *, - unsigned long, unsigned long)); -static int ftxfont_draw_bitmap P_ ((FRAME_PTR, GC *, struct font *, unsigned, - int, int, XPoint *, int, int *n)); +static GC *ftxfont_get_gcs P_ ((FRAME_PTR, unsigned long, unsigned long)); +static int ftxfont_draw_bitmap P_ ((FRAME_PTR, GC, GC *, struct font *, + unsigned, int, int, XPoint *, int, int *, + int)); static void ftxfont_draw_backgrond P_ ((FRAME_PTR, struct font *, GC, int, int, int)); static Font ftxfont_default_fid P_ ((FRAME_PTR)); -/* Create 6 GCs for antialiasing by interpolating colors FOREGROUND - and BACKGROUND. GCS[0] is closest to BACKGROUND, and GCS[5] is - closest to FOREGROUND. */ +struct ftxfont_frame_data +{ + /* Background and foreground colors. */ + XColor colors[2]; + /* GCs interporationg the above colors. gcs[0] is for a color + closest to BACKGROUND, and gcs[5] is for a color closest to + FOREGROUND. */ + GC gcs[6]; + struct ftxfont_frame_data *next; +}; -static int -ftxfont_create_gcs (f, gcs, foreground, background) + +/* Return an array of 6 GCs for antialiasing. */ + +static GC * +ftxfont_get_gcs (f, foreground, background) FRAME_PTR f; - GC *gcs; unsigned long foreground, background; { - XColor colors[3]; + XColor color; XGCValues xgcv; int i; + struct ftxfont_frame_data *data = font_get_frame_data (f, &ftxfont_driver); + struct ftxfont_frame_data *prev = NULL, *this = NULL, *new; - colors[0].pixel = foreground; - colors[1].pixel = background; + if (data) + { + for (this = data; this; prev = this, this = this->next) + { + if (this->colors[0].pixel < background) + continue; + if (this->colors[0].pixel > background) + break; + if (this->colors[1].pixel < foreground) + continue; + if (this->colors[1].pixel > foreground) + break; + return this->gcs; + } + } + + new = malloc (sizeof (struct ftxfont_frame_data)); + if (! new) + return NULL; + new->next = this; + if (prev) + { + prev->next = new; + } + else if (font_put_frame_data (f, &ftxfont_driver, new) < 0) + { + free (new); + return NULL; + } + + new->colors[0].pixel = background; + new->colors[1].pixel = foreground; BLOCK_INPUT; - XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, 2); + XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), new->colors, 2); for (i = 1; i < 7; i++) { - colors[2].red = (colors[0].red * i + colors[1].red * (8 - i)) / 8; - colors[2].green = (colors[0].green * i + colors[1].green * (8 - i)) / 8; - colors[2].blue = (colors[0].blue * i + colors[1].blue * (8 - i)) / 8; - if (! x_alloc_nearest_color (f, FRAME_X_COLORMAP (f), &colors[2])) + /* Interpolate colors linearly. Any better algorithm? */ + color.red + = (new->colors[1].red * i + new->colors[0].red * (8 - i)) / 8; + color.green + = (new->colors[1].green * i + new->colors[0].green * (8 - i)) / 8; + color.blue + = (new->colors[1].blue * i + new->colors[0].blue * (8 - i)) / 8; + if (! x_alloc_nearest_color (f, FRAME_X_COLORMAP (f), &color)) break; - xgcv.foreground = colors[2].pixel; - gcs[i - 1] = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - GCForeground, &xgcv); + xgcv.foreground = color.pixel; + new->gcs[i - 1] = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + GCForeground, &xgcv); } UNBLOCK_INPUT; @@ -84,22 +129,28 @@ { BLOCK_INPUT; for (i--; i >= 0; i--) - XFreeGC (FRAME_X_DISPLAY (f), gcs[i]); + XFreeGC (FRAME_X_DISPLAY (f), new->gcs[i]); UNBLOCK_INPUT; - return -1; + if (prev) + prev->next = new->next; + else if (data) + font_put_frame_data (f, &ftxfont_driver, new->next); + free (new); + return NULL; } - return 0; + return new->gcs; } static int -ftxfont_draw_bitmap (f, gc, font, code, x, y, p, size, n) +ftxfont_draw_bitmap (f, gc_fore, gcs, font, code, x, y, p, size, n, flush) FRAME_PTR f; - GC *gc; + GC gc_fore, *gcs; struct font *font; unsigned code; int x, y; XPoint *p; int size, *n; + int flush; { struct font_bitmap bitmap; unsigned char *b; @@ -107,29 +158,38 @@ if (ftfont_driver.get_bitmap (font, code, &bitmap, size > 0x100 ? 1 : 8) < 0) return 0; - for (i = 0, b = bitmap.buffer; i < bitmap.rows; - i++, b += bitmap.pitch) + if (size > 0x100) { - if (size > 0x100) + for (i = 0, b = bitmap.buffer; i < bitmap.rows; + i++, b += bitmap.pitch) { for (j = 0; j < bitmap.width; j++) if (b[j / 8] & (1 << (7 - (j % 8)))) { p[n[0]].x = x + bitmap.left + j; p[n[0]].y = y - bitmap.top + i; - if (++n[0] == 0x400) + if (++n[0] == size) { XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - gc[0], p, size, CoordModeOrigin); + gc_fore, p, size, CoordModeOrigin); n[0] = 0; } } } - else + if (flush && n[0] > 0) + XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + gc_fore, p, n[0], CoordModeOrigin); + } + else + { + for (i = 0, b = bitmap.buffer; i < bitmap.rows; + i++, b += bitmap.pitch) { for (j = 0; j < bitmap.width; j++) { - int idx = (b[j] >> 5) - 1; + int idx = (bitmap.bits_per_pixel == 1 + ? ((b[j / 8] & (1 << (7 - (j % 8)))) ? 6 : -1) + : (b[j] >> 5) - 1); if (idx >= 0) { @@ -137,15 +197,26 @@ pp[n[idx]].x = x + bitmap.left + j; pp[n[idx]].y = y - bitmap.top + i; - if (++(n[idx]) == 0x100) + if (++(n[idx]) == size) { XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - gc[idx], pp, size, CoordModeOrigin); + idx == 6 ? gc_fore : gcs[idx], pp, size, + CoordModeOrigin); n[idx] = 0; } } } } + if (flush) + { + for (i = 0; i < 6; i++) + if (n[i] > 0) + XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + gcs[i], p + 0x100 * i, n[i], CoordModeOrigin); + if (n[6] > 0) + XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + gc_fore, p + 0x600, n[6], CoordModeOrigin); + } } if (ftfont_driver.free_bitmap) @@ -199,9 +270,6 @@ static Lisp_Object ftxfont_match P_ ((Lisp_Object, Lisp_Object)); static struct font *ftxfont_open P_ ((FRAME_PTR, Lisp_Object, int)); static void ftxfont_close P_ ((FRAME_PTR, struct font *)); -static int ftxfont_prepare_face (FRAME_PTR, struct face *); -static void ftxfont_done_face (FRAME_PTR, struct face *); - static int ftxfont_draw P_ ((struct glyph_string *, int, int, int, int, int)); struct font_driver ftxfont_driver; @@ -296,51 +364,6 @@ } static int -ftxfont_prepare_face (f, face) - FRAME_PTR f; - struct face *face; -{ - struct font *font = (struct font *) face->font_info; - GC gcs[6]; - int i; - - face->extra = NULL; - - if (! font->scalable) - return 0; - - if (ftxfont_create_gcs (f, gcs, face->foreground, face->background) < 0) - /* Give up antialiasing. */ - return 0; - - face->extra = malloc (sizeof (GC) * 7); - if (! face->extra) - return -1; - for (i = 0; i < 6; i++) - ((GC *) face->extra)[i] = gcs[i]; - ((GC *) face->extra)[i] = face->gc; - return 0; -} - -static void -ftxfont_done_face (f, face) - FRAME_PTR f; - struct face *face; -{ - if (face->extra) - { - int i; - - BLOCK_INPUT; - for (i = 0; i < 6; i++) - XFreeGC (FRAME_X_DISPLAY (f), ((GC *) face->extra)[i]); - UNBLOCK_INPUT; - free (face->extra); - face->extra = NULL; - } -} - -static int ftxfont_draw (s, from, to, x, y, with_background) struct glyph_string *s; int from, to, x, y, with_background; @@ -358,7 +381,6 @@ n[0] = n[1] = n[2] = n[3] = n[4] = n[5] = n[6] = 0; BLOCK_INPUT; - if (with_background) ftxfont_draw_backgrond (f, font, s->gc, x, y, s->width); code = alloca (sizeof (unsigned) * len); @@ -366,46 +388,40 @@ code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8) | XCHAR2B_BYTE2 (s->char2b + from + i)); - gcs = face->extra; - if (gcs && face->gc != s->gc) + if (face->gc == s->gc) { - /* We are drawing for cursor or for mouse highlighting, and - can't use the prepared GCs. */ + gcs = ftxfont_get_gcs (f, face->foreground, face->background); + } + else + { XGCValues xgcv; unsigned long mask = GCForeground | GCBackground; - gcs = alloca (sizeof (GC) * 7); XGetGCValues (FRAME_X_DISPLAY (f), s->gc, mask, &xgcv); - if (ftxfont_create_gcs (f, gcs, xgcv.foreground, xgcv.background) < 0) - gcs = NULL; - gcs[6] = s->gc; + gcs = ftxfont_get_gcs (f, xgcv.foreground, xgcv.background); } - if (! gcs) + if (gcs) { - /* We are drawing with a bitmap font which doesn't use - antialiasing. */ + if (s->num_clips) + for (i = 0; i < 6; i++) + XSetClipRectangles (FRAME_X_DISPLAY (f), gcs[i], 0, 0, + s->clip, s->num_clips, Unsorted); + for (i = 0; i < len; i++) - x += ftxfont_draw_bitmap (f, &s->gc, font, code[i], x, y, - p, 0x700, n); - if (n[0] > 0) - XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - s->gc, p, n[0], CoordModeOrigin); + x += ftxfont_draw_bitmap (f, s->gc, gcs, font, code[i], x, y, + p, 0x100, n, i + 1 == len); + if (s->num_clips) + for (i = 0; i < 6; i++) + XSetClipMask (FRAME_X_DISPLAY (f), gcs[i], None); } else { - /* We are drawing with a scalable font which use - antialiasing. */ + /* We can't draw with antialiasing. + s->gc should already have a proper clipping setting. */ for (i = 0; i < len; i++) - x += ftxfont_draw_bitmap (f, gcs, font, code[i], x, y, - p, 0x100, n); - for (i = 0; i < 7; i++) - if (n[i] > 0) - XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - gcs[i], p + 0x100 * i, n[i], CoordModeOrigin); - if (face->gc != s->gc) - for (i = 0; i < 6; i++) - XFreeGC (FRAME_X_DISPLAY (f), gcs[i]); + x += ftxfont_draw_bitmap (f, s->gc, NULL, font, code[i], x, y, + p, 0x700, n, i + 1 == len); } UNBLOCK_INPUT; @@ -413,6 +429,27 @@ return len; } +static int +ftxfont_end_for_frame (f) + FRAME_PTR f; +{ + struct ftxfont_frame_data *data = font_get_frame_data (f, &ftxfont_driver); + + BLOCK_INPUT; + while (data) + { + struct ftxfont_frame_data *next = data->next; + int i; + + for (i = 0; i < 7; i++) + XFreeGC (FRAME_X_DISPLAY (f), data->gcs[i]); + free (data); + data = next; + } + UNBLOCK_INPUT; + return 0; +} + void @@ -426,10 +463,8 @@ ftxfont_driver.match = ftxfont_match; ftxfont_driver.open = ftxfont_open; ftxfont_driver.close = ftxfont_close; - ftxfont_driver.prepare_face = ftxfont_prepare_face; - ftxfont_driver.done_face = ftxfont_done_face; ftxfont_driver.draw = ftxfont_draw; - + ftxfont_driver.end_for_frame = ftxfont_end_for_frame; register_font_driver (&ftxfont_driver, NULL); }