From 81b778b62f74aff7afc1a09312862c4a3a8e4a99 Mon Sep 17 00:00:00 2001 From: handa Date: Thu, 18 Mar 2004 08:20:27 +0000 Subject: [PATCH] *** empty log message *** --- example/ChangeLog | 10 +- example/medit.c | 103 +++++--- src/ChangeLog | 105 +++++++- src/draw.c | 50 ++-- src/face.c | 43 ++-- src/face.h | 13 - src/font-flt.c | 9 +- src/font-ft.c | 195 ++++++++++---- src/font.c | 59 ++++- src/font.h | 12 +- src/fontset.c | 29 +-- src/input-gui.c | 20 +- src/internal-gui.h | 27 +- src/m17n-X.c | 727 ++++++++++++++++++++++++++++------------------------ src/m17n-gui.c | 5 +- src/m17n-gui.h | 4 + 16 files changed, 870 insertions(+), 541 deletions(-) diff --git a/example/ChangeLog b/example/ChangeLog index b00eb49..83201e6 100644 --- a/example/ChangeLog +++ b/example/ChangeLog @@ -1,4 +1,12 @@ -2004-03-12 Kenichi Handa +2004-03-17 Kenichi Handa + + * medit.c (update_selection): Fix for the case that the selected + region is expanded to the opposite direction. + (ButtonMoveProc): Likewise. + (main): Use alloca instead of malloc for allocating menu names. + Free several memory areas and GCs. Set control.anti_alias to 1. + +2004-03-12 Kenichi Handa * medit.c (input_status_control): New variable. (input_status): Use input_status_control. diff --git a/example/medit.c b/example/medit.c index cacfbcf..e4c4a97 100644 --- a/example/medit.c +++ b/example/medit.c @@ -328,8 +328,8 @@ redraw (int y0, int y1, int clear, int scroll_bar) if (clear) CLEAR_AREA (0, y0, win_width, y1 - y0); - /* Find a line closest to y0. The lihe is a cursor line if the - cursor is at the position above Y0, otherwise the top line. */ + /* Find a line closest to y0. It is a cursor line if the cursor is + Y0, otherwise the top line. */ if (y0 >= cur.y0) line = &cur; else @@ -498,28 +498,28 @@ update_selection () if (from < top.from) { - GLYPH_INFO (bol (from, 0), from, info); - sel_start.ascent = -info.this.y; - sel_start.from = info.line_from; - sel_start.to = info.line_to; - TEXT_EXTENTS (from, top.from, rect); - sel_start.y0 = - rect.height; - sel_start.y1 = sel_start.y0 + info.this.height; + int pos = bol (from, 0); + + TEXT_EXTENTS (pos, top.from, rect); + sel_start.y0 = top.y0 - rect.height; + sel_start.ascent = - rect.y; + GLYPH_INFO (pos, from, info); + if (pos < info.line_from) + sel_start.y0 += - rect.y + info.y + info.this.y; } else { GLYPH_INFO (top.from, from, info); sel_start.y0 = top.ascent + info.y + info.this.y; - sel_start.y1 = sel_start.y0 + info.this.height; - sel_start.ascent = -info.this.y; - sel_start.from = info.line_from; - sel_start.to = info.line_to; } + sel_start.ascent = -info.this.y; + sel_start.y1 = sel_start.y0 + info.this.height; + sel_start.from = info.line_from; + sel_start.to = info.line_to; if (to <= sel_start.to) { sel_end = sel_start; - to = bol (to - 1, 1) - 1; if (to >= sel_end.to) { GLYPH_INFO (sel_start.from, to, info); @@ -529,7 +529,6 @@ update_selection () } else { - to = bol (to - 1, 1) - 1; GLYPH_INFO (sel_start.from, to, info); sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.this.y; sel_end.y1 = sel_end.y0 + info.this.height; @@ -1143,25 +1142,61 @@ ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num) if (cursor.from == from) { - /* Start position of selection changed. */ - select_region (pos, to); - if (pos > from) - /* Shrunken. Previous selection face must be cleared. */ - redraw (start_y0, sel_start.y1, 1, 0); + /* Starting position changed. */ + if (pos <= from) + { + /* Enlarged. We can simply overdraw. */ + select_region (pos, to); + redraw (sel_start.y0, start_y1, 0, 0); + } + else if (pos < to) + { + /* Shrunken. Previous selection face must be cleared. */ + select_region (pos, to); + redraw (start_y0, sel_start.y1, 1, 0); + } + else if (pos == to) + { + /* Shrunken to zero. */ + XtDisownSelection (w, XA_PRIMARY, CurrentTime); + mtext_detach_property (selection); + redraw (start_y0, end_y1, 1, 0); + } else - /* Enlarged. We can simply overdraw. */ - redraw (sel_start.y0, start_y1, 0, 0); + { + /* Full update is necessary. */ + select_region (to, pos); + redraw (start_y0, sel_end.y1, 1, 0); + } } else { - /* End position of selection changed. */ - select_region (from, pos); - if (pos < to) - /* Shrunken. Previous selection face must be cleared. */ - redraw (sel_end.y0, end_y1, 1, 0); + /* Ending position changed. */ + if (pos < from) + { + /* Full update is necessary. */ + select_region (pos, from); + redraw (sel_start.y0, end_y1, 1, 0); + } + else if (pos == from) + { + /* Shrunken to zero. */ + XtDisownSelection (w, XA_PRIMARY, CurrentTime); + mtext_detach_property (selection); + redraw (start_y0, end_y1, 1, 0); + } + else if (pos < to) + { + /* Shrunken. Previous selection face must be cleared. */ + select_region (from, pos); + redraw (sel_end.y0, end_y1, 1, 0); + } else - /* Enlarged. We can simply overdraw. */ - redraw (end_y0, sel_end.y1, 0, 0); + { + /* Enlarged. We can simply overdraw. */ + select_region (from, pos); + redraw (end_y0, sel_end.y1, 0, 0); + } } } else @@ -2585,7 +2620,7 @@ main (int argc, char **argv) for (i = 0; i < 11; i++) if (plist[i]) { - char *name = malloc (9); + char *name = alloca (9); sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1); if (i == 10) @@ -2652,6 +2687,7 @@ main (int argc, char **argv) memset (&control, 0, sizeof control); control.two_dimensional = 1; control.enable_bidi = 1; + control.anti_alias = 1; control.min_line_ascent = font_ascent; control.min_line_descent = font_descent; control.max_line_width = win_width; @@ -2675,7 +2711,6 @@ main (int argc, char **argv) for (i = 0; i < num_input_methods; i++) minput_close_im (input_method_table[i]); m17n_object_unref (frame); - m17n_object_unref (mt); m17n_object_unref (face_xxx_large); m17n_object_unref (face_box); @@ -2693,7 +2728,13 @@ main (int argc, char **argv) M17N_FINI (); free (fontset_name); + free (filename); + free (input_method_table); + free (InputMethodMenus); + XFreeGC (display, mono_gc); + XFreeGC (display, mono_gc_inv); + XFreeGC (display, gc_inv); XtUninstallTranslations (form); XtUninstallTranslations (TextWidget); XtDestroyWidget (ShellWidget); diff --git a/src/ChangeLog b/src/ChangeLog index 1c53be1..a033bd1 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,4 +1,105 @@ -2004-03-16 Kenichi Handa +2004-03-18 Kenichi Handa + + * draw.c (Mdepth): New variable. + (visual_order): Delete unused local var `pos'. + (compose_glyph_string): Fix for the case that gstring->glyphs is + realloced. Stop generating glyphs at TO. Fix handling of + control charaters. + (layout_glyphs): Get metrics of all glyphs in advance. Set + lbearing and rbearing of base of composition glyph correctly. + Handle left-overhang glyphs correctly. + (alloc_gstring): New arg frame. Set gstring->anti_alias. Caller + changed. + (dump_combining_code): Change the defualt off_x character to ".". + (mdraw__init): Initialize Mdepth. + + * face.c (work_gstring): New variable + (mface__init): Initialize work_gstring. + (mface__fini): Free work_gstring.glyphs. + (mface__realize): Don't handle videomode property here. Adjusted + for the change of mfont__get_metric. + (mface__for_chars): Adjusted for the change of mfont__get_metric. + + * face.h (enum face_gc): Moved to m17n-X.c. + + * font.h (struct MFontDriver): Arguments of find_metric changed. + (mfont__select): Prototype adjusted. + (mfont__get_metric): Likewise. + (mfont__ft_drive_otf): Likewise. + (mfont__flt_run): Likewise. + + * font.c (mfont__select): New argument layouter. If layouter is + different in the registered font, make a new copy of realized + font. + (mfont__get_metric): Argument changed. Get metrics of multiple + glyphs. + (mfont_find): Call mfont__select with layouter as Mnil. + + * font-flt.c (FontLayoutContext): New member rfont. + (run_otf): Adjusted for the change of mfont__ft_drive_otf. + (mfont__flt_run): Argument changed. Initialize ctx.rfont. + + * font-ft.c (ft_find_metric): Arguments changed. Get metrics of + multiple glyphs. + (NUM_POINTS): New macro. + (MPointTable): New type. + (ft_render): Use mwin__draw_points instead of mwin__draw_bitmap. + (mfont__ft_drive_otf): New argument rfont. + + * fontset.c (realize_font_group): Adjusted for the changed of + mfont__select. + (check_fontset_element): This function deleted. + + * input-gui.c (adjust_window_and_draw): Locate a preedit window + off the parent window if the preedit text is zero length. + + * internal-gui.h (struct MFrame): New members foreground, + background, videomode, font. + (struct MGlyphString): New member anti_alias. + (MDrawPoint): New type. + (mwin__draw_bitmap): Prototype deleted. + (mwin__draw_points): Prototype added. + + * m17n-gui.h (MDrawControl): New member anti_alias. + + * m17n-gui.c (free_frame): Free frame->font. + (mframe): Set the fontset of frame->face to the default fontset. + + * m17n-X.c (RGB_GC): New type. + (enum gc_index): Renamed from enum face_gc. Member names changed. + (GCInfo): New typel + (struct MWDevice): Members foreground and background deleted. New + member scratch_gc, gc_list. + (DEFAULT_FONT, FALLBACK_FONT): New macros. + (free_device): Free GCs in device->gc_list. + (get_rgb_gc): New function. + (get_gc): Renamed and argument changed from get_color. + (get_gc_for_anti_alias): New function. + (xfont_find_metric): Arguments changed. Get metrics of multiple + glyphs. + (set_region): Argument changed. Caller changed. + (xfont_render): Allways set a font in gc. + (x_error_handler, x_io_error_handler): Define only if + X_SET_ERROR_HANDLER is defined. + (mwin__open_device): Create device->scratch_gc. Set members + foreground, background, and videomode of frame. Call + XSetErrorHandler and XSetIOErrorHandler only if + X_SET_ERROR_HANDLER is defined. + (struct gc_list): Deleted. + (REGISTER_GC, UNREGISTER_GC): These macros deleted. + (mwin__realize_face): Adjusted for the change of the format of + rface->info and the charge of set_region. + (mwin__free_realized_face, mwin__fill_space, mwin__draw_hline) + (mwin__draw_box): Likewise. + (mwin__draw_bitmap): This function deleted. + (mwin__draw_points): New function. + (mwin__verify_region): Adjusted for the change of the format of + rface->info and the charge of set_region. + (mwin__create_window): Inherit backgound pixel from parent. + (mwin__dump_gc): Adjusted for the change of the format of + rface->info. + +2004-03-16 Kenichi Handa * m17n-X.c (mwin__parse_event): Fix handling of modifier keys. @@ -17,7 +118,7 @@ * input-gui.c (win_create_ic): Enable bidi in status control. - * draw.c (visual_order): Avoid re-ordering only combining glyphs. + * draw.c (visual_order): Avoid re-ordering of combining glyphs only. 2004-03-09 Kenichi Handa diff --git a/src/draw.c b/src/draw.c index 869a709..aee3180 100644 --- a/src/draw.c +++ b/src/draw.c @@ -79,6 +79,8 @@ static MSymbol Mlatin, Minherited; /* Special categories */ static MSymbol McatCc, McatCf; +static MSymbol Mdepth; + /* Glyph-string composer. */ @@ -169,7 +171,6 @@ visual_order (MGlyphString *gstring) { int j = indices[i]; int k = idx[j]; - int pos = glyphs[k].pos; glyphs[k].bidi_level = levels[j]; #ifdef HAVE_FRIBIDI @@ -236,6 +237,7 @@ compose_glyph_string (MFrame *frame, MText *mt, int from, int to, int non_ascii_found; int size = gstring->control.fixed_width; int i, limit; + int last; MLIST_RESET (gstring); gstring->from = from; @@ -251,7 +253,7 @@ compose_glyph_string (MFrame *frame, MText *mt, int from, int to, APPEND_GLYPH (gstring, g_tmp); stop = face_change = charset_change = language_change = pos = from; - g = gstring->glyphs + gstring->used; + last = 0; non_ascii_found = 0; while (1) { @@ -279,13 +281,15 @@ compose_glyph_string (MFrame *frame, MText *mt, int from, int to, this_script = script; } - if (pos == stop || script != this_script || g->type != g_tmp.type) + if (pos == stop || script != this_script + || MGLYPH (last)->type != g_tmp.type) { + g = MGLYPH (last); if (non_ascii_found && g->type == GLYPH_CHAR) while (g < gstring->glyphs + gstring->used) g = mface__for_chars (script, language, charset, g, gstring->glyphs + gstring->used, size); - g = gstring->glyphs + gstring->used; + last = gstring->used; non_ascii_found = 0; script = this_script; if (pos == to) @@ -312,7 +316,9 @@ compose_glyph_string (MFrame *frame, MText *mt, int from, int to, language, charset, size) : default_rface); } - stop = language_change; + stop = to; + if (stop > language_change) + stop = language_change; if (stop > charset_change) stop = charset_change; if (face_change < stop) @@ -328,12 +334,12 @@ compose_glyph_string (MFrame *frame, MText *mt, int from, int to, non_ascii_found = 1; else if (g_tmp.type == GLYPH_CHAR && (c <= 32 || c == 127)) { - g_tmp.c = '^'; + g_tmp.code = '^'; APPEND_GLYPH (gstring, g_tmp); if (c < ' ') - g_tmp.c += 0x40; + g_tmp.code = g_tmp.c + 0x40; else - g_tmp.c = '?'; + g_tmp.code = '?'; } APPEND_GLYPH (gstring, g_tmp); if (c == '\n' @@ -385,9 +391,7 @@ compose_glyph_string (MFrame *frame, MText *mt, int from, int to, i++, g++) if (g->rface->rfont != this->rface->rfont) g->code = code; - i = mfont__flt_run (gstring, start, i, - this->rface->rfont->layouter, - this->rface->ascii_rface); + i = mfont__flt_run (gstring, start, i, this->rface); } else { @@ -482,6 +486,8 @@ layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to) g_physical_descent = gstring->physical_descent; g_width = g_lbearing = g_rbearing = 0; + mfont__get_metric (gstring, from, to); + while (g < last_g) { MGlyph *base = g++; @@ -489,7 +495,6 @@ layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to) int size = rfont->font.property[MFONT_SIZE]; int width, lbearing, rbearing; - mfont__get_metric (rfont, base); if (g == last_g || ! g->combining_code) { /* No combining. */ @@ -549,7 +554,6 @@ layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to) else if (end < g->to) end = g->to; - mfont__get_metric (rfont, g); g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x; if (g->xoff < left) left = g->xoff; @@ -580,6 +584,8 @@ layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to) base->ascent = - top; base->descent = bottom; + base->lbearing = lbearing; + base->rbearing = rbearing; if (left < - base->width) { base->xoff = - base->width - left; @@ -1138,7 +1144,8 @@ render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width, rect.x += rect.width; if (rect.x < x + width) { - while (g != gend && x + width - gend[-1].width >= rect.x) + while (g != gend + && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x)) { width -= (--gend)->width; while (! gend->enabled && g != gend) @@ -1354,7 +1361,8 @@ free_gstring (void *object) static MGlyphString scratch_gstring; static MGlyphString * -alloc_gstring (MText *mt, int pos, MDrawControl *control, int line, int y) +alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control, + int line, int y) { MGlyphString *gstring; @@ -1377,6 +1385,10 @@ alloc_gstring (MText *mt, int pos, MDrawControl *control, int line, int y) (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit)); else gstring->width_limit = control->max_line_width; + gstring->anti_alias = control->anti_alias; + if (gstring->anti_alias + && (unsigned) mwin__device_get_prop (frame->device, Mdepth) < 8) + gstring->anti_alias = 0; return gstring; } @@ -1502,7 +1514,7 @@ get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control) beg = pos; end = to; } - gstring = alloc_gstring (mt, beg, control, line, y); + gstring = alloc_gstring (frame, mt, beg, control, line, y); compose_glyph_string (frame, mt, beg, end, gstring); layout_glyph_string (frame, gstring); end = gstring->to; @@ -1516,7 +1528,8 @@ get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control) while (gst->to < end) { line++, y += gst->height; - gst->next = alloc_gstring (mt, gst->from, control, line, y); + gst->next = alloc_gstring (frame, mt, gst->from, control, + line, y); gst->next->top = gstring; compose_glyph_string (frame, mt, gst->to, end, gst->next); gst = gst->next; @@ -1638,7 +1651,7 @@ dump_combining_code (int code) else if (off_y < 0) sprintf (work + 2, "%d", off_y); else if (off_x == 0) - sprintf (work + 2, "-"); + sprintf (work + 2, "."); p = work + strlen (work); if (off_x > 0) sprintf (p, ">%d", off_x); @@ -1692,6 +1705,7 @@ mdraw__init () McatCc = msymbol ("Cc"); McatCf = msymbol ("Cf"); + Mdepth = msymbol ("depth"); MbidiR = msymbol ("R"); MbidiAL = msymbol ("AL"); diff --git a/src/face.c b/src/face.c index e1a2bc5..7c7df8b 100644 --- a/src/face.c +++ b/src/face.c @@ -386,6 +386,8 @@ deserialize_face (MPlist *plist) return face; } +static MGlyphString work_gstring; + /* Internal API */ @@ -515,6 +517,11 @@ mface__init () mface_yellow->property[MFACE_FOREGROUND] = (void *) msymbol ("yellow"); mface_magenta = mface (); mface_magenta->property[MFACE_FOREGROUND] = (void *) msymbol ("magenta"); + + work_gstring.glyphs = malloc (sizeof (MGlyph) * 2); + work_gstring.size = 2; + work_gstring.used = 0; + work_gstring.inc = 1; return 0; } @@ -544,6 +551,8 @@ mface__fini () M17N_OBJECT_UNREF (mface_cyan); M17N_OBJECT_UNREF (mface_yellow); M17N_OBJECT_UNREF (mface_magenta); + free (work_gstring.glyphs); + mdebug__report_object ("Face", &face_table); } @@ -585,15 +594,6 @@ mface__realize (MFrame *frame, MFace **faces, int num, merged_face.property[MFACE_SIZE] = (void *) font_size; } - if ((MSymbol) merged_face.property[MFACE_VIDEOMODE] == Mreverse) - { - MSymbol foreground = (MSymbol) merged_face.property[MFACE_FOREGROUND]; - MSymbol background = (MSymbol) merged_face.property[MFACE_BACKGROUND]; - - merged_face.property[MFACE_FOREGROUND] = background; - merged_face.property[MFACE_BACKGROUND] = foreground; - } - rface = find_realized_face (frame, &merged_face, NULL); if (rface && rface->tick == tick) return rface->ascii_rface; @@ -617,12 +617,14 @@ mface__realize (MFrame *frame, MFace **faces, int num, { rface->rfont = rfont; g.otf_encoded = 0; - mfont__get_metric (rfont, &g); - rface->space_width = g.width; - g.code = MCHAR_INVALID_CODE; - mfont__get_metric (rface->rfont, &g); - rface->ascent = g.ascent; - rface->descent = g.descent; + work_gstring.glyphs[0] = g; + work_gstring.glyphs[0].rface = rface; + work_gstring.glyphs[1].code = MCHAR_INVALID_CODE; + work_gstring.glyphs[1].rface = rface; + mfont__get_metric (&work_gstring, 0, 2); + rface->space_width = work_gstring.glyphs[0].width; + rface->ascent = work_gstring.glyphs[1].ascent; + rface->descent = work_gstring.glyphs[1].descent; } else { @@ -673,12 +675,11 @@ mface__for_chars (MSymbol script, MSymbol language, MSymbol charset, *rface = *from_g->rface->ascii_rface; rface->rfont = rfont; { - MGlyph tmp; - - tmp.code = MCHAR_INVALID_CODE; - mfont__get_metric (rfont, &tmp); - rface->ascent = tmp.ascent; - rface->descent = tmp.descent; + work_gstring.glyphs[0].code = MCHAR_INVALID_CODE; + work_gstring.glyphs[0].rface = rface; + mfont__get_metric (&work_gstring, 0, 1); + rface->ascent = work_gstring.glyphs[0].ascent; + rface->descent = work_gstring.glyphs[0].descent; } mwin__realize_face (rface); mplist_add (from_g->rface->frame->realized_face_list, Mt, rface); diff --git a/src/face.h b/src/face.h index 9ab1d16..a174631 100644 --- a/src/face.h +++ b/src/face.h @@ -67,19 +67,6 @@ struct MFace }; -enum face_gc - { - MFACE_GC_NORMAL, - MFACE_GC_INVERSE, - MFACE_GC_SCRATCH, - MFACE_GC_HLINE, - MFACE_GC_BOX_TOP, - MFACE_GC_BOX_BOTTOM, - MFACE_GC_BOX_LEFT, - MFACE_GC_BOX_RIGHT, - MFACE_GCS - }; - /** A realized face is registered in MFrame->face_list, thus it does not have to be a managed object. */ diff --git a/src/font-flt.c b/src/font-flt.c index b93c5c4..b49e97d 100644 --- a/src/font-flt.c +++ b/src/font-flt.c @@ -912,6 +912,7 @@ typedef struct int cluster_end_pos; int combining_code; int left_padding; + MRealizedFont *rfont; } FontLayoutContext; static int run_command (int depth, @@ -1069,7 +1070,7 @@ run_otf (int depth, #ifdef HAVE_OTF int gidx = gstring->used; - to = mfont__ft_drive_otf (gstring, from, to, + to = mfont__ft_drive_otf (gstring, from, to, ctx->rfont, otf_cmd->script, otf_cmd->langsys, otf_cmd->gsub_features, otf_cmd->gpos_features); if (gidx < gstring->used) @@ -1256,8 +1257,7 @@ mfont__flt_encode_char (MSymbol layouter_name, int c) } int -mfont__flt_run (MGlyphString *gstring, int from, int to, - MSymbol layouter_name, MRealizedFace *ascii_rface) +mfont__flt_run (MGlyphString *gstring, int from, int to, MRealizedFace *rface) { int stage_idx = 0; int gidx; @@ -1266,7 +1266,9 @@ mfont__flt_run (MGlyphString *gstring, int from, int to, MCharTable *table; int encoded_len; int match_indices[NMATCH]; + MSymbol layouter_name = rface->rfont->layouter; MFontLayoutTable *layouter = get_font_layout_table (layouter_name); + MRealizedFace *ascii_rface = rface->ascii_rface; FontLayoutStage *stage; int from_pos, to_pos; MGlyph dummy; @@ -1284,6 +1286,7 @@ mfont__flt_run (MGlyphString *gstring, int from, int to, /* Setup CTX. */ memset (&ctx, 0, sizeof ctx); + ctx.rfont = rface->rfont; table = MPLIST_VAL (layouter); layouter = MPLIST_NEXT (layouter); stage = (FontLayoutStage *) MPLIST_VAL (layouter); diff --git a/src/font-ft.c b/src/font-ft.c index 98a54ea..8878356 100644 --- a/src/font-ft.c +++ b/src/font-ft.c @@ -261,7 +261,7 @@ build_font_list () static MRealizedFont *ft_select (MFrame *, MFont *, MFont *, int); static int ft_open (MRealizedFont *); static void ft_close (MRealizedFont *); -static void ft_find_metric (MRealizedFont *, MGlyph *); +static void ft_find_metric (MRealizedFont *, MGlyphString *, int, int); static unsigned ft_encode_char (MRealizedFont *, int, unsigned); static void ft_render (MDrawWindow, int, int, MGlyphString *, MGlyph *, MGlyph *, int, MDrawRegion); @@ -400,39 +400,54 @@ ft_close (MRealizedFont *rfont) /* The FreeType font driver function FIND_METRIC. */ static void -ft_find_metric (MRealizedFont *rfont, MGlyph *g) +ft_find_metric (MRealizedFont *rfont, MGlyphString *gstring, + int from, int to) { MFTInfo *ft_info = (MFTInfo *) rfont->info; FT_Face ft_face = ft_info->ft_face; + MGlyph *g = MGLYPH (from), *gend = MGLYPH (to); + FT_Int32 load_flags = FT_LOAD_RENDER; - if (g->code == MCHAR_INVALID_CODE) + if (! gstring->anti_alias) { - unsigned unitsPerEm = ft_face->units_per_EM; - int size = rfont->font.property[MFONT_SIZE] / 10; - - g->lbearing = 0; - g->rbearing = ft_face->max_advance_width * size / unitsPerEm; - g->width = ft_face->max_advance_width * size / unitsPerEm; - g->ascent = ft_face->ascender * size / unitsPerEm; - g->descent = (- ft_face->descender) * size / unitsPerEm; +#ifdef FT_LOAD_TARGET_MONO + load_flags |= FT_LOAD_TARGET_MONO; +#else + load_flags |= FT_LOAD_MONOCHROME; +#endif } - else - { - FT_Glyph_Metrics *metrics; - FT_UInt code; - if (g->otf_encoded) - code = g->code; + for (; g != gend; g++) + { + if (g->code == MCHAR_INVALID_CODE) + { + unsigned unitsPerEm = ft_face->units_per_EM; + int size = rfont->font.property[MFONT_SIZE] / 10; + + g->lbearing = 0; + g->rbearing = ft_face->max_advance_width * size / unitsPerEm; + g->width = ft_face->max_advance_width * size / unitsPerEm; + g->ascent = ft_face->ascender * size / unitsPerEm; + g->descent = (- ft_face->descender) * size / unitsPerEm; + } else - code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code); + { + FT_Glyph_Metrics *metrics; + FT_UInt code; - FT_Load_Glyph (ft_face, code, FT_LOAD_RENDER | FT_LOAD_MONOCHROME); - metrics = &ft_face->glyph->metrics; - g->lbearing = metrics->horiBearingX >> 6; - g->rbearing = (metrics->horiBearingX + metrics->width) >> 6; - g->width = metrics->horiAdvance >> 6; - g->ascent = metrics->horiBearingY >> 6; - g->descent = (metrics->height - metrics->horiBearingY) >> 6; + if (g->otf_encoded) + code = g->code; + else + code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code); + + FT_Load_Glyph (ft_face, code, FT_LOAD_RENDER); + metrics = &ft_face->glyph->metrics; + g->lbearing = (metrics->horiBearingX >> 6); + g->rbearing = (metrics->horiBearingX + metrics->width) >> 6; + g->width = metrics->horiAdvance >> 6; + g->ascent = metrics->horiBearingY >> 6; + g->descent = (metrics->height - metrics->horiBearingY) >> 6; + } } } @@ -464,56 +479,127 @@ ft_encode_char (MRealizedFont *rfont, int c, unsigned ignored) /* The FreeType font driver function RENDER. */ +#define NUM_POINTS 0x1000 + +typedef struct { + MDrawPoint points[NUM_POINTS]; + MDrawPoint *p; +} MPointTable; + static void ft_render (MDrawWindow win, int x, int y, MGlyphString *gstring, MGlyph *from, MGlyph *to, int reverse, MDrawRegion region) { - MRealizedFace *rface; - MFrame *frame; + MRealizedFace *rface = from->rface; + MFrame *frame = rface->frame; MFTInfo *ft_info; FT_Face ft_face = NULL; + FT_Int32 load_flags = FT_LOAD_RENDER; MGlyph *g; + int i, j; + MPointTable point_table[8]; if (from == to) return; + if (! gstring->anti_alias) + { +#ifdef FT_LOAD_TARGET_MONO + load_flags |= FT_LOAD_TARGET_MONO; +#else + load_flags |= FT_LOAD_MONOCHROME; +#endif + } + /* It is assured that the all glyphs in the current range use the same realized face. */ - rface = from->rface; - frame = rface->frame; ft_info = (MFTInfo *) rface->rfont->info; ft_face = ft_info->ft_face; - g = from; - while (g < to) + for (i = 0; i < 8; i++) + point_table[i].p = point_table[i].points; + + for (g = from; g < to; x += g++->width) { - if (g->type == GLYPH_CHAR) - { - FT_UInt code; + FT_UInt code; + unsigned char *bmp; + int intensity; + MPointTable *ptable; + int xoff, yoff; - if (g->otf_encoded) - code = g->code; - else - code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code); -#ifdef FT_LOAD_TARGET_MONO - FT_Load_Glyph (ft_face, code, FT_LOAD_RENDER | FT_LOAD_TARGET_MONO); -#else - FT_Render_Glyph (ft_face->glyph, FT_LOAD_RENDER | FT_LOAD_MONOCHROME); -#endif - mwin__draw_bitmap (frame, win, rface, reverse, - x + ft_face->glyph->bitmap_left + g->xoff, - y - ft_face->glyph->bitmap_top + g->yoff, - ft_face->glyph->bitmap.width, - ft_face->glyph->bitmap.rows, - ft_face->glyph->bitmap.pitch, - ft_face->glyph->bitmap.buffer, - region); + if (g->otf_encoded) + code = g->code; + else + code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code); + FT_Load_Glyph (ft_face, code, load_flags); + yoff = y - ft_face->glyph->bitmap_top + g->yoff; + bmp = ft_face->glyph->bitmap.buffer; + if (gstring->anti_alias) + for (i = 0; i < ft_face->glyph->bitmap.rows; + i++, bmp += ft_face->glyph->bitmap.pitch, yoff++) + { + xoff = x + ft_face->glyph->bitmap_left + g->xoff; + for (j = 0; j < ft_face->glyph->bitmap.width; j++, xoff++) + { + intensity = bmp[j] >> 5; + if (intensity) + { + ptable = point_table + intensity; + ptable->p->x = xoff; + ptable->p->y = yoff; + ptable->p++; + if (ptable->p - ptable->points == NUM_POINTS) + { + mwin__draw_points (frame, win, rface, + reverse ? 7 - intensity : intensity, + ptable->points, NUM_POINTS, region); + ptable->p = ptable->points; + } + } + } + } + else + for (i = 0; i < ft_face->glyph->bitmap.rows; + i++, bmp += ft_face->glyph->bitmap.pitch, yoff++) + { + xoff = x + ft_face->glyph->bitmap_left + g->xoff; + for (j = 0; j < ft_face->glyph->bitmap.width; j++, xoff++) + { + intensity = bmp[j / 8] & (1 << (7 - (j % 8))); + if (intensity) + { + ptable = point_table; + ptable->p->x = xoff; + ptable->p->y = yoff; + ptable->p++; + if (ptable->p - ptable->points == NUM_POINTS) + { + mwin__draw_points (frame, win, rface, + reverse ? 0 : 7, + ptable->points, NUM_POINTS, region); + ptable->p = ptable->points; + } + } + } } - x += g++->width; } - return; + if (gstring->anti_alias) + { + for (i = 1; i < 8; i++) + if (point_table[i].p != point_table[i].points) + mwin__draw_points (frame, win, rface, reverse ? 7 - i : i, + point_table[i].points, + point_table[i].p - point_table[i].points, region); + } + else + { + if (point_table[0].p != point_table[0].points) + mwin__draw_points (frame, win, rface, reverse ? 0 : 7, + point_table[0].points, + point_table[0].p - point_table[0].points, region); + } } @@ -579,6 +665,7 @@ mfont__ft_fini () int mfont__ft_drive_otf (MGlyphString *gstring, int from, int to, + MRealizedFont *rfont, MSymbol script, MSymbol langsys, MSymbol gsub_features, MSymbol gpos_features) { @@ -598,7 +685,7 @@ mfont__ft_drive_otf (MGlyphString *gstring, int from, int to, if (len == 0) return from; - ft_info = (MFTInfo *) gstring->glyphs[from].rface->rfont->info; + ft_info = (MFTInfo *) rfont->info; if (ft_info->otf_flag < 0) goto simple_copy; otf = ft_info->otf; diff --git a/src/font.c b/src/font.c index 645f8e8..fa39508 100644 --- a/src/font.c +++ b/src/font.c @@ -776,11 +776,12 @@ mfont__set_spec_from_plist (MFont *spec, MPlist *plist) } MRealizedFont * -mfont__select (MFrame *frame, MFont *spec, MFont *request, int limited_size) +mfont__select (MFrame *frame, MFont *spec, MFont *request, int limited_size, + MSymbol layouter) { MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY); MPlist *realized_font_list; - MRealizedFont *best_font[MFONT_TYPE_MAX]; + MRealizedFont *best_font[MFONT_TYPE_MAX], *best; int best_index; int i; int mdebug_mask = MDEBUG_FONT; @@ -790,15 +791,29 @@ mfont__select (MFrame *frame, MFont *spec, MFont *request, int limited_size) MPLIST_DO (realized_font_list, frame->realized_font_list) { - MRealizedFont *best = MPLIST_VAL (realized_font_list); - + best = MPLIST_VAL (realized_font_list); if (MPLIST_KEY (realized_font_list) == registry && ! memcmp (&best->spec, spec, sizeof (MFont)) && ! memcmp (&best->request, request, sizeof (MFont))) - return best; + { + if (best->layouter != layouter) + { + MRealizedFont *copy; + + MSTRUCT_MALLOC (copy, MERROR_FONT); + *copy = *best; + copy->layouter = layouter; + if (copy->info) + M17N_OBJECT_REF (copy->info); + mplist_add (frame->realized_font_list, registry, copy); + best = copy; + } + return best; + } } MDEBUG_PUSH_TIME (); + best = NULL; best_index = -1; for (i = 0; i < MFONT_TYPE_MAX; i++) { @@ -809,13 +824,13 @@ mfont__select (MFrame *frame, MFont *spec, MFont *request, int limited_size) : NULL); if (best_font[i] && (best_index < 0 - || best_font[best_index]->score > best_font[i]->score)) + || best_font[best_index]->score < best_font[i]->score)) best_index = i; } for (i = 0; i < MFONT_TYPE_MAX; i++) { if (i == best_index) - mplist_add (frame->realized_font_list, registry, best_font[i]); + best = best_font[i]; else if (best_font[i]) free (best_font[i]); } @@ -830,18 +845,21 @@ mfont__select (MFrame *frame, MFont *spec, MFont *request, int limited_size) font.property[i] = request->property[i]; gen_font_name (buf2, &font); - if (best_index >= 0) + if (best) MDEBUG_PRINT_TIME ("FONT", (stderr, " to select <%s> from <%s>.", - gen_font_name (buf1, - &best_font[best_index]->font), + gen_font_name (buf1, &best->font), buf2)); else MDEBUG_PRINT_TIME ("FONT", (stderr, " to fail to find <%s>.", buf2)); MDEBUG_POP_TIME (); } - return (best_index >= 0 ? best_font[best_index] : NULL); + if (! best) + return NULL; + best->layouter = layouter; + mplist_add (frame->realized_font_list, registry, best); + return best; } @@ -957,9 +975,22 @@ mfont__encode_char (MRealizedFont *rfont, int c) } void -mfont__get_metric (MRealizedFont *rfont, MGlyph *g) +mfont__get_metric (MGlyphString *gstring, int from, int to) { - (rfont->driver->find_metric) (rfont, g); + MGlyph *from_g = MGLYPH (from), *to_g = MGLYPH (to), *g; + MRealizedFont *rfont = from_g->rface->rfont; + + for (g = from_g; g != to_g; g++) + if (g->rface->rfont != rfont) + { + int idx = GLYPH_INDEX (g); + + (rfont->driver->find_metric) (rfont, gstring, from, idx); + from_g = g; + rfont = g->rface->rfont; + from = idx; + } + (rfont->driver->find_metric) (rfont, gstring, from, GLYPH_INDEX (g)); } @@ -1542,7 +1573,7 @@ mfont_find (MFrame *frame, MFont *spec, int *score, int limited_size) MFONT_INIT (&spec_copy); spec_copy.property[MFONT_REGISTRY] = spec->property[MFONT_REGISTRY]; - rfont = mfont__select (frame, &spec_copy, spec, limited_size); + rfont = mfont__select (frame, &spec_copy, spec, limited_size, Mnil); if (!rfont) return NULL; if (score) diff --git a/src/font.h b/src/font.h index 6c77228..b96e11c 100644 --- a/src/font.h +++ b/src/font.h @@ -169,7 +169,9 @@ struct MFontDriver /** Close a font specified by RFONT. */ void (*close) (MRealizedFont *rfont); - void (*find_metric) (MRealizedFont *rfont, MGlyph *g); + /** Set metrics of glyphs in GSTRING from FROM to TO. */ + void (*find_metric) (MRealizedFont *rfont, MGlyphString *gstring, + int from, int to); /** Encode C into the glyph code the font. CODE is a code point of C in rfont->encoder->encoding_charset. If the font has no glyph @@ -202,6 +204,7 @@ extern int mfont__ft_init (); extern void mfont__ft_fini (); extern int mfont__ft_drive_otf (MGlyphString *gstring, int from, int to, + MRealizedFont *rfont, MSymbol script, MSymbol langsys, MSymbol gsub_features, MSymbol gpos_features); extern int mfont__ft_decode_otf (MGlyph *g); @@ -227,13 +230,14 @@ extern int mfont__encodable_p (MRealizedFont *rfont, MSymbol layouter_name, extern unsigned mfont__encode_char (MRealizedFont *rfont, int c); extern MRealizedFont *mfont__select (MFrame *frame, MFont *spec, - MFont *request, int limitted_size); + MFont *request, int limitted_size, + MSymbol layouter); extern int mfont__open (MRealizedFont *rfont); extern void mfont__close (MRealizedFont *rfont); -extern void mfont__get_metric (MRealizedFont *rfont, MGlyph *g); +extern void mfont__get_metric (MGlyphString *gstring, int from, int to); extern void mfont__set_property (MFont *font, enum MFontProperty key, MSymbol val); @@ -248,6 +252,6 @@ extern void mfont__set_spec (MFont *font, extern unsigned mfont__flt_encode_char (MSymbol layouter_name, int c); extern int mfont__flt_run (MGlyphString *gstring, int from, int to, - MSymbol layouter_name, MRealizedFace *ascii_rface); + MRealizedFace *rface); #endif /* _M17N_FONT_H_ */ diff --git a/src/fontset.c b/src/fontset.c index af938ae..6f922ec 100644 --- a/src/fontset.c +++ b/src/fontset.c @@ -307,14 +307,13 @@ realize_font_group (MFrame *frame, MFont *request, MPlist *font_group, mplist_set (font_group, Mnil, NULL); MPLIST_DO (pl, plist) { + MSymbol layouter = MPLIST_KEY (pl); MRealizedFont *rfont = mfont__select (frame, MPLIST_VAL (pl), request, - size); + size, + layouter == Mt ? Mnil : layouter); if (rfont) { - rfont->layouter = MPLIST_KEY (pl); - if (rfont->layouter == Mt) - rfont->layouter = Mnil; MPLIST_DO (p, font_group) if (((MRealizedFont *) (MPLIST_VAL (p)))->score > rfont->score) break; @@ -323,28 +322,6 @@ realize_font_group (MFrame *frame, MFont *request, MPlist *font_group, } } -int -check_fontset_element (MFrame *frame, MPlist *element, MGlyph *g, int size) -{ - MRealizedFont *rfont = (MRealizedFont *) MPLIST_VAL (element); - - if (! rfont) - /* We have already failed to select this font. */ - return 0; - if (! rfont->frame) - { - rfont = mfont__select (frame, &rfont->spec, &rfont->request, size); - free (MPLIST_VAL (element)); - MPLIST_VAL (element) = rfont; - if (! rfont) - /* No font matches this spec. */ - return 0; - } - - g->code = mfont__encode_char (rfont, g->c); - return (g->code != MCHAR_INVALID_CODE); -} - /* Internal API */ diff --git a/src/input-gui.c b/src/input-gui.c index 52f589b..b9a32f9 100644 --- a/src/input-gui.c +++ b/src/input-gui.c @@ -221,16 +221,24 @@ adjust_window_and_draw (MFrame *frame, MInputContext *ic, MText *mt, int type) physical.x = win_ic_info->client.geometry.width - physical.width; if (type == 0) { - if (y0 > - ic->spot.ascent) + if (len <= 1) { - physical.height += y0 + ic->spot.ascent; - y0 = - ic->spot.ascent; + physical.height = physical.width = 1; + physical.x = physical.y = -1; } - if (y1 < ic->spot.descent) + else { - physical.height += ic->spot.descent - y1; + if (y0 > - ic->spot.ascent) + { + physical.height += y0 + ic->spot.ascent; + y0 = - ic->spot.ascent; + } + if (y1 < ic->spot.descent) + { + physical.height += ic->spot.descent - y1; + } + physical.y = yoff + ic->spot.y + y0; } - physical.y = yoff + ic->spot.y + y0; } else if (type == 1) { diff --git a/src/internal-gui.h b/src/internal-gui.h index c50d936..656bfb6 100644 --- a/src/internal-gui.h +++ b/src/internal-gui.h @@ -41,6 +41,10 @@ struct MFrame with the frame. */ MWDevice *device; + MSymbol foreground, background, videomode; + + MFont *font; + /** The default face of the frame. */ MFace *face; @@ -77,7 +81,7 @@ enum glyph_type GLYPH_TYPE_MAX }; -struct MGlyph +typedef struct { int pos, to; int c; @@ -93,9 +97,7 @@ struct MGlyph unsigned bidi_level : 6; enum glyph_type type : 3; int combining_code; -}; - -typedef struct MGlyph MGlyph; +} MGlyph; struct MGlyphString { @@ -113,6 +115,10 @@ struct MGlyphString /* Members to keep temporary data while layouting. */ short sub_width, sub_lbearing, sub_rbearing; + /* Copied for .anti_alias but never set if the frame's + depth is less than 8. */ + unsigned anti_alias : 1; + MDrawControl control; MDrawRegion region; @@ -182,6 +188,11 @@ typedef struct MGlyphString MGlyphString; typedef struct MFontDriver MFontDriver; +typedef struct +{ + short x, y; +} MDrawPoint; + extern int mfont__init (); extern void mfont__fini (); @@ -229,11 +240,9 @@ extern void mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyph *g, int x, int y, int width, MDrawRegion region); -extern void mwin__draw_bitmap (MFrame *frame, MDrawWindow win, - MRealizedFace *rface, int reverse, - int x, int y, - int width, int height, int row_bytes, - unsigned char *bmp, +extern void mwin__draw_points (MFrame *frame, MDrawWindow win, + MRealizedFace *rface, + int intensity, MDrawPoint *points, int num, MDrawRegion region); extern MDrawRegion mwin__region_from_rect (MDrawMetric *rect); diff --git a/src/m17n-X.c b/src/m17n-X.c index 28654c5..c821e72 100644 --- a/src/m17n-X.c +++ b/src/m17n-X.c @@ -84,6 +84,35 @@ typedef struct /* Anchor of the chain of MDisplayInfo objects. */ static MPlist *display_info_list; + +/* Color value and the corresponding GC. */ +typedef struct +{ + unsigned int rgb; /* (red << 16) | (green << 8) | blue */ + GC gc; +} RGB_GC; + +enum gc_index + { + GC_INVERSE, + GC_NORMAL = GC_INVERSE + 7, + GC_HLINE, + GC_BOX_TOP, + GC_BOX_BOTTOM, + GC_BOX_LEFT, + GC_BOX_RIGHT, + GC_MAX + }; + +typedef struct +{ + int rgb_fore; + int rgb_back; + /* The first 8 elements are indexed by an intensity for + anti-aliasing. The 2nd to 7th are created on demand. */ + GC gc[GC_MAX]; +} GCInfo; + struct MWDevice { /* Common header for the m17n object. */ @@ -99,7 +128,7 @@ struct MWDevice Colormap cmap; - unsigned long foreground, background; + GC scratch_gc; /** List of pointers to realized faces on the frame. */ MPlist *realized_face_list; @@ -107,6 +136,8 @@ struct MWDevice /** List of pointers to realized fontsets on the frame. */ MPlist *realized_fontset_list; + /** List of XColors vs GCs on the frame. */ + MPlist *gc_list; }; static MPlist *device_list; @@ -116,6 +147,17 @@ static MSymbol M_iso8859_1, M_iso10646_1; #define FRAME_DISPLAY(frame) (frame->device->display_info->display) #define FRAME_SCREEN(frame) (frame->device->screen_num) +#define DEFAULT_FONT "-misc-fixed-medium-r-normal--*-120-*-*-*-*-iso8859-1" +#define FALLBACK_FONT "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1" + +typedef struct +{ + String font; + String foreground; + String background; + Boolean reverse_video; +} AppData, *AppDataPtr; + static void free_display_info (void *object) { @@ -182,6 +224,15 @@ free_device (void *object) mface__free_realized ((MRealizedFace *) mplist_value (plist)); M17N_OBJECT_UNREF (device->realized_face_list); + MPLIST_DO (plist, device->gc_list) + { + XFreeGC (device->display_info->display, + ((RGB_GC *) MPLIST_VAL (plist))->gc); + free (MPLIST_VAL (plist)); + } + M17N_OBJECT_UNREF (device->gc_list); + XFreeGC (device->display_info->display, device->scratch_gc); + XFreePixmap (device->display_info->display, device->drawable); M17N_OBJECT_UNREF (device->display_info); free (object); @@ -238,22 +289,102 @@ find_modifier_bits (MDisplayInfo *disp_info) XFreeModifiermap (mods); } -static unsigned long -get_color (Display *display, Colormap cmap, - MSymbol color_name, MSymbol default_name, - unsigned long default_pixel) +static RGB_GC * +get_rgb_gc (MWDevice *device, XColor *xcolor) +{ + int rgb = (((xcolor->red >> 8) << 16) | ((xcolor->green >> 8) << 8) + | (xcolor->blue >> 8)); + MPlist *plist; + RGB_GC *rgb_gc; + unsigned long valuemask = GCForeground; + XGCValues values; + + MPLIST_DO (plist, device->gc_list) + { + rgb_gc = MPLIST_VAL (plist); + + if (rgb_gc->rgb == rgb) + return rgb_gc; + if (rgb_gc->rgb > rgb) + break; + } + + if (! XAllocColor (device->display_info->display, device->cmap, xcolor)) + return NULL; + + rgb_gc = malloc (sizeof (RGB_GC)); + rgb_gc->rgb = rgb; + values.foreground = xcolor->pixel; + rgb_gc->gc = XCreateGC (device->display_info->display, + device->drawable, valuemask, &values); + mplist_push (plist, Mt, rgb_gc); + return rgb_gc; +} + +static GC +get_gc (MFrame *frame, MSymbol color, int for_foreground, int *rgb_ret) { - XColor exact_def; + MWDevice *device = frame->device; + XColor xcolor; + RGB_GC *rgb_gc; - if (XParseColor (display, cmap, msymbol_name (color_name), &exact_def) - && XAllocColor (display, cmap, &exact_def)) - return exact_def.pixel; + if (color == Mnil) + { + if (frame->rface) + goto no_color; + color = for_foreground ? frame->foreground : frame->background; + } + if (! XParseColor (FRAME_DISPLAY (frame), device->cmap, + msymbol_name (color), &xcolor)) + goto no_color; + rgb_gc = get_rgb_gc (device, &xcolor); + if (! rgb_gc) + goto no_color; + if (rgb_ret) + *rgb_ret = rgb_gc->rgb; + return rgb_gc->gc; + + no_color: + { + GCInfo *info = frame->rface->info; + GC gc; + int rgb; + + if (for_foreground) + rgb = info->rgb_fore, gc = info->gc[GC_NORMAL]; + else + rgb = info->rgb_back, gc = info->gc[GC_INVERSE]; + if (rgb_ret) + *rgb_ret = rgb; + return gc; + } +} - if (XParseColor (display, cmap, msymbol_name (default_name), &exact_def) - && XAllocColor (display, cmap, &exact_def)) - return exact_def.pixel; +static GC +get_gc_for_anti_alias (MWDevice *device, GCInfo *info, int intensity) +{ + int rgb_fore, rgb_back; + XColor xcolor; + RGB_GC *rgb_gc; + GC gc; - return default_pixel; + if (info->gc[intensity]) + return info->gc[intensity]; + + rgb_fore = info->rgb_fore, rgb_back = info->rgb_back; + xcolor.red = ((((rgb_fore & 0xFF0000) >> 16) * intensity + + ((rgb_back & 0xFF0000) >> 16) * (7 - intensity)) / 7) << 8; + xcolor.green = ((((rgb_fore & 0xFF00) >> 8) * intensity + + ((rgb_back & 0xFF00) >> 8) * (7 - intensity)) / 7) << 8; + xcolor.blue = (((rgb_fore & 0xFF) * intensity + + (rgb_back & 0xFF) * (7 - intensity)) / 7) << 8; + rgb_gc = get_rgb_gc (device, &xcolor); + if (rgb_gc) + gc = rgb_gc->gc; + else + gc =get_gc_for_anti_alias (device, info, + intensity < 4 ? intensity - 1 : intensity + 1); + return (info->gc[intensity] = gc); } @@ -447,7 +578,7 @@ build_font_list (MFrame *frame, MSymbol family, MSymbol registry, static MRealizedFont *xfont_select (MFrame *, MFont *, MFont *, int); static int xfont_open (MRealizedFont *); static void xfont_close (MRealizedFont *); -static void xfont_find_metric (MRealizedFont *, MGlyph *); +static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int); static unsigned xfont_encode_char (MRealizedFont *, int, unsigned); static void xfont_render (MDrawWindow, int, int, MGlyphString *, MGlyph *, MGlyph *, int, MDrawRegion); @@ -598,68 +729,73 @@ xfont_close (MRealizedFont *rfont) /* The X font driver function FIND_METRIC. */ static void -xfont_find_metric (MRealizedFont *rfont, MGlyph *g) +xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring, + int from, int to) { - XCharStruct *pcm = NULL; MXFontInfo *xfont = (MXFontInfo *) rfont->info; XFontStruct *f = xfont->f; - int byte1, byte2; + MGlyph *g = MGLYPH (from), *gend = MGLYPH (to); - if (g->code == MCHAR_INVALID_CODE) + for (; g != gend; g++) { - g->lbearing = f->max_bounds.lbearing; - g->rbearing = f->max_bounds.rbearing; - g->width = f->max_bounds.width; - g->ascent = f->ascent; - g->descent = f->descent; - return; - } - - byte1 = g->code >> 8; - byte2 = g->code & 0xFF; - - if (f->per_char != NULL) - { - if (f->min_byte1 == 0 && f->max_byte1 == 0) + if (g->code == MCHAR_INVALID_CODE) { - if (byte1 == 0 - && byte2 >= f->min_char_or_byte2 - && byte2 <= f->max_char_or_byte2) - pcm = f->per_char + byte2 - f->min_char_or_byte2; + g->lbearing = f->max_bounds.lbearing; + g->rbearing = f->max_bounds.rbearing; + g->width = f->max_bounds.width; + g->ascent = f->ascent; + g->descent = f->descent; } else { - if (byte1 >= f->min_byte1 - && byte1 <= f->max_byte1 - && byte2 >= f->min_char_or_byte2 - && byte2 <= f->max_char_or_byte2) + int byte1 = g->code >> 8, byte2 = g->code & 0xFF; + XCharStruct *pcm = NULL; + + if (f->per_char != NULL) { - pcm = (f->per_char - + ((f->max_char_or_byte2-f->min_char_or_byte2 + 1) - * (byte1 - f->min_byte1)) - + (byte2 - f->min_char_or_byte2)); + if (f->min_byte1 == 0 && f->max_byte1 == 0) + { + if (byte1 == 0 + && byte2 >= f->min_char_or_byte2 + && byte2 <= f->max_char_or_byte2) + pcm = f->per_char + byte2 - f->min_char_or_byte2; + } + else + { + if (byte1 >= f->min_byte1 + && byte1 <= f->max_byte1 + && byte2 >= f->min_char_or_byte2 + && byte2 <= f->max_char_or_byte2) + { + pcm = (f->per_char + + ((f->max_char_or_byte2-f->min_char_or_byte2 + 1) + * (byte1 - f->min_byte1)) + + (byte2 - f->min_char_or_byte2)); + } + } } - } - } - if (pcm) - { - g->lbearing = pcm->lbearing; - g->rbearing = pcm->rbearing; - g->width = pcm->width; - g->ascent = pcm->ascent; - g->descent = pcm->descent; - } - else - { - /* If the per_char pointer is null, all glyphs between the first - and last character indexes inclusive have the same - information, as given by both min_bounds and max_bounds. */ - g->lbearing = 0; - g->rbearing = f->max_bounds.width; - g->width = f->max_bounds.width; - g->ascent = f->ascent; - g->descent = f->descent; + if (pcm) + { + g->lbearing = pcm->lbearing; + g->rbearing = pcm->rbearing; + g->width = pcm->width; + g->ascent = pcm->ascent; + g->descent = pcm->descent; + } + else + { + /* If the per_char pointer is null, all glyphs between + the first and last character indexes inclusive have + the same information, as given by both min_bounds and + max_bounds. */ + g->lbearing = 0; + g->rbearing = f->max_bounds.width; + g->width = f->max_bounds.width; + g->ascent = f->ascent; + g->descent = f->descent; + } + } } } @@ -717,16 +853,14 @@ xfont_encode_char (MRealizedFont *rfont, int c, unsigned code) } static GC -set_region (Display *display, MRealizedFace *rface, GC gc, MDrawRegion region) +set_region (MFrame *frame, GC gc, MDrawRegion region) { - GC gc1; - XRectangle xrect; + unsigned long valuemask = GCForeground; - XClipBox (region, &xrect); - gc1 = ((GC *) rface->info)[MFACE_GC_SCRATCH]; - XCopyGC (display, gc, GCFont | GCForeground | GCBackground, gc1); - XSetRegion (display, gc1, region); - return gc1; + XCopyGC (FRAME_DISPLAY (frame), gc, valuemask, + frame->device->scratch_gc); + XSetRegion (FRAME_DISPLAY (frame), frame->device->scratch_gc, region); + return frame->device->scratch_gc; } /* The X font driver function RENDER. */ @@ -738,8 +872,7 @@ xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring, MRealizedFace *rface = from->rface; Display *display; XChar2b *code; - GC *gcs = rface->info; - GC gc = gcs[reverse ? MFACE_GC_INVERSE : MFACE_GC_NORMAL]; + GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL]; MGlyph *g; int i; @@ -751,7 +884,8 @@ xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring, display = FRAME_DISPLAY (rface->frame); if (region) - gc = set_region (display, rface, gc, region); + gc = set_region (rface->frame, gc, region); + XSetFont (display, gc, ((MXFontInfo *) (rface->rfont->info))->f->fid); if (from->code == MCHAR_INVALID_CODE) { @@ -1017,7 +1151,7 @@ xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt) -#if 1 +#ifdef X_SET_ERROR_HANDLER static int x_error_handler (Display *display, XErrorEvent *error) { @@ -1064,15 +1198,6 @@ mwin__fini () M17N_OBJECT_UNREF (device_list); } -typedef struct -{ - String font; - String foreground; - String background; - Boolean reverse_video; -} AppData, *AppDataPtr; - - int mwin__parse_font_name (char *name, MFont *font) { @@ -1155,6 +1280,7 @@ mwin__open_device (MFrame *frame, MPlist *param) XWindowAttributes attr; unsigned depth = 0; MPlist *plist; + AppData app_data; if (param) for (plist = param; (key = mplist_key (plist)) != Mnil; @@ -1253,6 +1379,9 @@ mwin__open_device (MFrame *frame, MPlist *param) M17N_OBJECT_REF (device); else { + unsigned long valuemask = GCForeground; + XGCValues values; + M17N_OBJECT (device, free_device, MERROR_WIN); device->display_info = disp_info; device->screen_num = screen_num; @@ -1264,8 +1393,10 @@ mwin__open_device (MFrame *frame, MPlist *param) device->cmap = cmap; device->realized_face_list = mplist (); device->realized_fontset_list = mplist (); - device->foreground = BlackPixel (display, screen_num); - device->background = WhitePixel (display, screen_num); + device->gc_list = mplist (); + values.foreground = BlackPixel (display, screen_num); + device->scratch_gc = XCreateGC (display, device->drawable, + valuemask, &values); } frame->realized_font_list = disp_info->realized_font_list; @@ -1274,11 +1405,9 @@ mwin__open_device (MFrame *frame, MPlist *param) if (widget) { - AppData app_data; XtResource resources[] = { { XtNfont, XtCFont, XtRString, sizeof (String), - XtOffset (AppDataPtr, font), XtRString, - "-misc-fixed-medium-r-normal--*-120-*-*-*-*-iso8859-1" }, + XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT }, { XtNforeground, XtCForeground, XtRString, sizeof (String), XtOffset (AppDataPtr, foreground), XtRString, "black" }, { XtNbackground, XtCBackground, XtRString, sizeof (String), @@ -1286,62 +1415,60 @@ mwin__open_device (MFrame *frame, MPlist *param) { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean), XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE } }; - MFace *face = NULL; - MFont font; - char **names; - int nfonts; XtGetApplicationResources (widget, &app_data, resources, XtNumber (resources), NULL, 0); - names = XListFonts (display, app_data.font, 1, &nfonts); - if (nfonts == 1) - { - if (mwin__parse_font_name (names[0], &font) >= 0) - face = mface_from_font (&font); - else - { - /* The font name does not conform to XLFD. Try to open the - font and get XA_FONT property. */ - XFontStruct *xfont = XLoadQueryFont (display, names[0]); + frame->foreground = msymbol (app_data.foreground); + frame->background = msymbol (app_data.background); + frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal; + } + else + { + app_data.font = DEFAULT_FONT; + frame->foreground = msymbol ("black"); + frame->background = msymbol ("white"); + frame->videomode = Mnormal; + } - if (xfont) - { - unsigned long value; - char *name; + frame->font = mfont (); + { + int nfonts; + char **names = XListFonts (display, app_data.font, 1, &nfonts); - if (XGetFontProperty (xfont, XA_FONT, &value) - && (name = ((char *) - XGetAtomName (display, (Atom) value)))) - { - if (mwin__parse_font_name (name, &font) >= 0) - face = mface_from_font (&font); - } - XFreeFont (display, xfont); - } - } - XFreeFontNames (names); - } + if (nfonts > 0) + { + if (mwin__parse_font_name (names[0], frame->font) < 0) + { + /* The font name does not conform to XLFD. Try to open the + font and get XA_FONT property. */ + XFontStruct *xfont = XLoadQueryFont (display, names[0]); + + nfonts = 0; + if (xfont) + { + unsigned long value; + char *name; + + if (XGetFontProperty (xfont, XA_FONT, &value) + && (name = ((char *) + XGetAtomName (display, (Atom) value)))) + { + if (mwin__parse_font_name (name, frame->font) >= 0) + nfonts = 1; + } + XFreeFont (display, xfont); + } + } + XFreeFontNames (names); + } + if (! nfonts) + mwin__parse_font_name (FALLBACK_FONT, frame->font); + } - if (app_data.reverse_video == True) - { - if (! face) - face = mface (); - mface_put_prop (face, Mvideomode, Mreverse); - } - if (face) - { - mplist_push (param, Mface, face); - M17N_OBJECT_UNREF (face); - } - device->foreground - = get_color (display, cmap, msymbol (app_data.foreground), Mnil, - device->foreground); - device->background - = get_color (display, cmap, msymbol (app_data.background), Mnil, - device->background); - } +#ifdef X_SET_ERROR_HANDLER XSetErrorHandler (x_error_handler); - /* XSetIOErrorHandler (x_io_error_handler); */ + XSetIOErrorHandler (x_io_error_handler); +#endif return device; } @@ -1367,155 +1494,77 @@ mwin__device_get_prop (MWDevice *device, MSymbol key) return NULL; } -struct { - int size, inc, used; - GC *gc_table; -} gc_list; - -#define REGISTER_GC(gc) \ - do { \ - if (! gc_list.size) \ - MLIST_INIT1 (&gc_list, gc_table, 100); \ - MLIST_APPEND1 (&gc_list, gc_table, gc, MERROR_WIN); \ - } while (0) - - -#define UNREGISTER_GC(gc) \ - do { \ - int j; \ - for (j = 0; j < gc_list.used; j++) \ - if (gc_list.gc_table[j] == gc) \ - gc_list.gc_table[j] = (GC) NULL; \ - } while (0) - - void mwin__realize_face (MRealizedFace *rface) { - MFrame *frame = rface->frame; - MWDevice *device = frame->device; - Display *display = FRAME_DISPLAY (frame); - XGCValues values; - int mask = GCForeground | GCBackground; - MSymbol foreground = rface->face.property[MFACE_FOREGROUND]; - MSymbol background = rface->face.property[MFACE_BACKGROUND]; - MFaceHLineProp *hline = rface->hline; - MFaceBoxProp *box = rface->box; - MFaceHookFunc func = (MFaceHookFunc) rface->face.property[MFACE_HOOK_FUNC]; - MSymbol default_foreground - = (MSymbol) mface_get_prop (frame->face, Mforeground); - MSymbol default_background - = (MSymbol) mface_get_prop (frame->face, Mbackground); - GC *gcs; - unsigned long pixel; - - MTABLE_CALLOC (gcs, MFACE_GCS, MERROR_WIN); - - values.foreground = get_color (display, device->cmap, foreground, - default_foreground, device->foreground); - values.background = get_color (display, device->cmap, background, - default_background, device->background); - if (rface->face.property[MFACE_VIDEOMODE] == Mreverse) - pixel = values.foreground, - values.foreground = values.background, - values.background = pixel; - - if (rface->rfont - && rface->rfont->font.property[MFONT_TYPE] - 1 == MFONT_TYPE_WIN) + MFrame *frame; + MSymbol foreground, background, videomode; + MFaceHLineProp *hline; + MFaceBoxProp *box; + MFaceHookFunc func; + GCInfo *info; + + if (rface != rface->ascii_rface) { - values.font = ((MXFontInfo *) (rface->rfont->info))->f->fid; - mask |= GCFont; + rface->info = rface->ascii_rface->info; + return; } - gcs[MFACE_GC_NORMAL] = XCreateGC (display, device->drawable, mask, &values); - REGISTER_GC (gcs[MFACE_GC_NORMAL]); - - gcs[MFACE_GC_SCRATCH] = XCreateGC (display, device->drawable, mask, &values); - REGISTER_GC (gcs[MFACE_GC_SCRATCH]); - - pixel = values.foreground; - values.foreground = values.background; - values.background = pixel; - gcs[MFACE_GC_INVERSE] = XCreateGC (display, device->drawable, mask, &values); - REGISTER_GC (gcs[MFACE_GC_INVERSE]); - values.background = values.foreground; - values.foreground = pixel; + frame = rface->frame; + MSTRUCT_CALLOC (info, MERROR_WIN); - mask &= ~GCFont; + foreground = rface->face.property[MFACE_FOREGROUND]; + background = rface->face.property[MFACE_BACKGROUND]; + videomode = rface->face.property[MFACE_VIDEOMODE]; + if (! videomode) + videomode = frame->videomode; + if (videomode != Mreverse) + { + info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore); + info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back); + } + else + { + info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore); + info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back); + } - if (rface == rface->ascii_rface) + hline = rface->hline; + if (hline) { - /* This realized face is for ASCII. Setup GCs for hline and - box. */ - if (hline && hline->color != foreground) - { - values.foreground - = get_color (display, device->cmap, hline->color, - default_foreground, device->foreground); - gcs[MFACE_GC_HLINE] - = XCreateGC (display, device->drawable, mask, &values); - REGISTER_GC (gcs[MFACE_GC_HLINE]); - values.foreground = pixel; - } + if (hline->color) + info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL); + else + info->gc[GC_HLINE] = info->gc[GC_NORMAL]; + } - if (box) - { - if (box->color_top) - { - values.foreground - = get_color (display, device->cmap, box->color_top, - default_foreground, device->foreground); - gcs[MFACE_GC_BOX_TOP] - = XCreateGC (display, device->drawable, mask, &values); - REGISTER_GC (gcs[MFACE_GC_BOX_TOP]); - } + box = rface->box; + if (box) + { + if (box->color_top) + info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL); + else + info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL]; - if (box->color_left - && box->color_left != box->color_top) - { - values.foreground - = get_color (display, device->cmap, box->color_left, - default_foreground, device->foreground); - gcs[MFACE_GC_BOX_LEFT] - = XCreateGC (display, device->drawable, mask, &values); - REGISTER_GC (gcs[MFACE_GC_BOX_LEFT]); - } + if (box->color_left && box->color_left != box->color_top) + info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL); + else + info->gc[GC_BOX_LEFT] = info->gc[GC_NORMAL]; - if (box->color_right - && box->color_right != box->color_top) - { - values.foreground - = get_color (display, device->cmap, box->color_right, - default_foreground, device->foreground); - gcs[MFACE_GC_BOX_RIGHT] - = XCreateGC (display, device->drawable, mask, &values); - REGISTER_GC (gcs[MFACE_GC_BOX_RIGHT]); - } + if (box->color_bottom && box->color_bottom != box->color_top) + info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL); + else + info->gc[GC_BOX_BOTTOM] = info->gc[GC_NORMAL]; - if (box->color_bottom - && box->color_bottom != box->color_top) - { - values.foreground - = get_color (display, device->cmap, box->color_bottom, - default_foreground, device->foreground); - gcs[MFACE_GC_BOX_BOTTOM] - = XCreateGC (display, device->drawable, mask, &values); - REGISTER_GC (gcs[MFACE_GC_BOX_BOTTOM]); - } - } + if (box->color_right && box->color_right != box->color_top) + info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL); + else + info->gc[GC_BOX_RIGHT] = info->gc[GC_NORMAL]; } - else - { - /* This realized face is not for ASCII. GCs for hline and box - are shared with that of the corresponding ASCII face. */ - GC *ascii_gcs = rface->ascii_rface->info; - int i; - for (i = MFACE_GC_HLINE; i < MFACE_GCS; i++) - gcs[i] = ascii_gcs[i]; - } + rface->info = info; - rface->info = gcs; + func = (MFaceHookFunc) rface->face.property[MFACE_HOOK_FUNC]; if (func) (func) (&(rface->face), rface->info, rface->face.property[MFACE_HOOK_ARG]); } @@ -1524,18 +1573,8 @@ mwin__realize_face (MRealizedFace *rface) void mwin__free_realized_face (MRealizedFace *rface) { - GC *gcs = rface->info; - enum face_gc limit - = rface == rface->ascii_rface ? MFACE_GCS : MFACE_GC_HLINE; - int i; - - for (i = 0; i < limit; i++) - if (gcs[i]) - { - UNREGISTER_GC (gcs[i]); - XFreeGC (FRAME_DISPLAY (rface->frame), gcs[i]); - } - free (gcs); + if (rface == rface->ascii_rface) + free (rface->info); } @@ -1544,11 +1583,10 @@ mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface, int reverse, int x, int y, int width, int height, MDrawRegion region) { - GC *gcs = rface->info; - GC gc = gcs[reverse ? MFACE_GC_NORMAL : MFACE_GC_INVERSE]; + GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE]; if (region) - gc = set_region (FRAME_DISPLAY (frame), rface, gc, region); + gc = set_region (frame, gc, region); XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc, x, y, width, height); @@ -1561,8 +1599,8 @@ mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring, int x, int y, int width, MDrawRegion region) { enum MFaceHLineType type = rface->hline->type; - GC *gcs = rface->info; - GC gc; + GCInfo *info = rface->info; + GC gc = gc = info->gc[GC_HLINE]; int i; y = (type == MFACE_HLINE_BOTTOM @@ -1572,15 +1610,8 @@ mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring, : type == MFACE_HLINE_STRIKE_THROUGH ? y - ((gstring->ascent + gstring->descent) / 2) : y - gstring->text_ascent); - if (reverse) - gc = gcs[MFACE_GC_INVERSE]; - else if (gcs[MFACE_GC_HLINE]) - gc = gcs[MFACE_GC_HLINE]; - else - gc = gcs[MFACE_GC_NORMAL]; - if (region) - gc = set_region (FRAME_DISPLAY (frame), rface, gc, region); + gc = set_region (frame, gc, region); for (i = 0; i < rface->hline->width; i++) XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc, @@ -1595,7 +1626,7 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring, Display *display = FRAME_DISPLAY (frame); MRealizedFace *rface = g->rface; MFaceBoxProp *box = rface->box; - GC *gcs = rface->info; + GCInfo *info = rface->info; GC gc_top, gc_left, gc_right, gc_btm; int y0, y1; int i; @@ -1605,14 +1636,13 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring, y1 = y + (gstring->text_descent + rface->box->inner_vmargin + rface->box->width - 1); - gc_top = gcs[MFACE_GC_BOX_TOP]; - if (! gc_top) - gc_top = gcs[MFACE_GC_NORMAL]; + gc_top = info->gc[GC_BOX_TOP]; if (region) - gc_top = set_region (FRAME_DISPLAY (frame), rface, gc_top, region); - gc_btm = gcs[MFACE_GC_BOX_BOTTOM]; - if (! gc_btm) + gc_top = set_region (frame, gc_top, region); + if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM]) gc_btm = gc_top; + else + gc_btm = info->gc[GC_BOX_BOTTOM]; if (g->type == GLYPH_BOX) { @@ -1628,19 +1658,22 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring, XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i); /* Draw the bottom side. */ - if (region) - gc_btm = set_region (display, rface, gc_btm, region); + if (region && gc_btm != gc_top) + gc_btm = set_region (frame, gc_btm, region); for (i = 0; i < box->width; i++) XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i); if (g->left_padding > 0) { /* Draw the left side. */ - gc_left = gcs[MFACE_GC_BOX_LEFT]; - if (! gc_left) + if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP]) gc_left = gc_top; - else if (region) - gc_left = set_region (display, rface, gc_left, region); + else + { + gc_left = info->gc[GC_BOX_LEFT]; + if (region) + gc_left = set_region (frame, gc_left, region); + } for (i = 0; i < rface->box->width; i++) XDrawLine (display, (Window) win, gc_left, x0 + i, y0 + i, x0 + i, y1 - i); @@ -1648,11 +1681,14 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring, else { /* Draw the right side. */ - gc_right = gcs[MFACE_GC_BOX_RIGHT]; - if (! gc_right) + if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP]) gc_right = gc_top; - else if (region) - gc_right = set_region (display, rface, gc_right, region); + else + { + gc_right = info->gc[GC_BOX_RIGHT]; + if (region) + gc_right = set_region (frame, gc_right, region); + } for (i = 0; i < rface->box->width; i++) XDrawLine (display, (Window) win, gc_right, x1 - i, y0 + i, x1 - i, y1 - i); @@ -1666,8 +1702,8 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring, x, y0 + i, x + width - 1, y0 + i); /* Draw the bottom side. */ - if (region) - gc_btm = set_region (display, rface, gc_btm, region); + if (region && gc_btm != gc_top) + gc_btm = set_region (frame, gc_btm, region); for (i = 0; i < box->width; i++) XDrawLine (display, (Window) win, gc_btm, x, y1 - i, x + width - 1, y1 - i); @@ -1675,6 +1711,7 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring, } +#if 0 void mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface, int reverse, int x, int y, @@ -1683,17 +1720,35 @@ mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface, { Display *display = FRAME_DISPLAY (frame); int i, j; - GC *gcs = rface->info; - GC gc = gcs[reverse ? MFACE_GC_INVERSE : MFACE_GC_NORMAL]; + GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL]; if (region) - gc = set_region (FRAME_DISPLAY (frame), rface, gc, region); + gc = set_region (frame, gc, region); for (i = 0; i < height; i++, bmp += row_bytes) for (j = 0; j < width; j++) if (bmp[j / 8] & (1 << (7 - (j % 8)))) XDrawPoint (display, (Window) win, gc, x + j, y + i); } +#endif + +void +mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface, + int intensity, MDrawPoint *points, int num, + MDrawRegion region) +{ + GCInfo *info = rface->info; + GC gc; + + if (! (gc = info->gc[intensity])) + gc = info->gc[intensity] = get_gc_for_anti_alias (frame->device, info, + intensity); + if (region) + gc = set_region (frame, gc, region); + + XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc, + (XPoint *) points, num, CoordModeOrigin); +} MDrawRegion @@ -1781,35 +1836,31 @@ mwin__dump_region (MDrawRegion region) void mwin__verify_region (MFrame *frame, MDrawRegion region) { - set_region (FRAME_DISPLAY (frame), frame->rface, - ((GC *) frame->rface->info)[MFACE_GC_NORMAL], region); + set_region (frame, ((GCInfo *) frame->rface->info)->gc[GC_NORMAL], region); } MDrawWindow mwin__create_window (MFrame *frame, MDrawWindow parent) { - MWDevice *device = frame->device; Display *display = FRAME_DISPLAY (frame); - int screen = FRAME_SCREEN (frame); Window win; XWMHints wm_hints = { InputHint, False }; XClassHint class_hints = { "M17N-IM", "m17n-im" }; - XSetWindowAttributes attrs; + XWindowAttributes win_attrs; + XSetWindowAttributes set_attrs; unsigned long mask; - MSymbol background = mface_get_prop (frame->face, Mbackground); - - attrs.background_pixel = get_color (display, device->cmap, - background, background, - WhitePixel (display, screen)); - attrs.backing_store = Always; - attrs.override_redirect = True; - attrs.save_under = True; - mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder; + if (! parent) - parent = (MDrawWindow) RootWindow (display, screen); + parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame)); + XGetWindowAttributes (display, (Window) parent, &win_attrs); + set_attrs.background_pixel = win_attrs.backing_pixel; + set_attrs.backing_store = Always; + set_attrs.override_redirect = True; + set_attrs.save_under = True; + mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder; win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0, CopyFromParent, InputOutput, CopyFromParent, - mask, &attrs); + mask, &set_attrs); XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0, NULL, &wm_hints, &class_hints); XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask); @@ -2034,12 +2085,12 @@ mwin__dump_gc (MFrame *frame, MRealizedFace *rface) unsigned long valuemask = GCForeground | GCBackground | GCClipMask; XGCValues values; Display *display = FRAME_DISPLAY (frame); - GC *gcs = rface->info; + GCInfo *info = rface->info; int i; - for (i = 0; i <= MFACE_GC_SCRATCH; i++) + for (i = 0; i <= GC_INVERSE; i++) { - XGetGCValues (display, gcs[i], valuemask, &values); + XGetGCValues (display, info->gc[i], valuemask, &values); fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i, values.foreground, values.background); fprintf (stderr, "\n"); diff --git a/src/m17n-gui.c b/src/m17n-gui.c index 2c3c011..a56873f 100644 --- a/src/m17n-gui.c +++ b/src/m17n-gui.c @@ -76,6 +76,7 @@ free_frame (void *object) M17N_OBJECT_UNREF (frame->face); mwin__close_device ((MFrame *) object); + free (frame->font); free (object); } @@ -313,7 +314,9 @@ mframe (MPlist *plist) MERROR (MERROR_WIN, NULL); } - frame->face = mface_copy (mface__default); + frame->face = mface_from_font (frame->font); + frame->face->property[MFACE_FONTSET] = mfontset (NULL); + M17N_OBJECT_REF (mface__default->property[MFACE_FONTSET]); if (plist) for (; (key = mplist_key (plist)) != Mnil; plist = mplist_next (plist)) if (key == Mface) diff --git a/src/m17n-gui.h b/src/m17n-gui.h index ba9adf6..9be293e 100644 --- a/src/m17n-gui.h +++ b/src/m17n-gui.h @@ -438,6 +438,10 @@ typedef struct implemented. */ unsigned fixed_width : 1; + /***en If nonzero, draw glyphs with anti-aliasing if a backend font + driver supports it. */ + unsigned anti_alias : 1; + /***en If nonzero, the values are minimum line ascent and descent pixels. */ unsigned int min_line_ascent; -- 1.7.10.4