X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fm17n-X.c;h=80cbeb37f1c294e1eaeb766ea76368f561af1af3;hb=6ac495c3a791ab71a4fb0a19b2d9f88f77efb558;hp=f45473b2906219a29472cf7b65c1ff3e722d98d9;hpb=fe49a883d776eabe5aa538e9a7c0a108f6796f2a;p=m17n%2Fm17n-lib.git diff --git a/src/m17n-X.c b/src/m17n-X.c index f45473b..80cbeb3 100644 --- a/src/m17n-X.c +++ b/src/m17n-X.c @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with the m17n library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 02111-1307, USA. */ #include "config.h" @@ -59,26 +59,6 @@ #include "fontset.h" #include "face.h" -typedef struct _MFontX MFontX; - -struct _MFontX -{ - /* Record a font of the smallest pixel size. */ - MFont core; - /* Nth bit tells the existence of a font of size N + 5. So this is - for 5..36 pixel size fonts. Usually this covers all sizes. */ - unsigned int size5_36; - /* Fonts of (size < 5 || size > 36) are listed here (except for a - scalable whose size is 0). */ - MFontX *next; -}; - -/* S must satisfy the condition (S >= 5 && S < 36). */ - -#define SET_SIZE(FONTX, S) ((FONTX)->size5_36 |= (1 << ((S) - 5))) - -#define HAVE_SIZE(FONTX, S) ((FONTX)->size5_36 & (1 << ((S) - 5))) - typedef struct { /* Common header for the m17n object. */ @@ -92,7 +72,7 @@ typedef struct /** List of available X-core fonts on the display. Keys are registries and values are plists whose keys are families and - values are pointers to MFontX. */ + values are pointers to MFont. */ MPlist *font_list; /** Nonzero means that already contains all available @@ -106,6 +86,7 @@ typedef struct int hyper_mask; Atom MULE_BASELINE_OFFSET; + Atom AVERAGE_WIDTH; } MDisplayInfo; /* Anchor of the chain of MDisplayInfo objects. */ @@ -210,15 +191,7 @@ free_display_info (void *object) MPLIST_DO (plist, disp_info->font_list) { MPLIST_DO (pl, MPLIST_VAL (plist)) - { - MFontX *fontx, *next; - - for (fontx = MPLIST_VAL (pl); fontx; fontx = next) - { - next = fontx->next; - free (fontx); - } - } + free (MPLIST_VAL (pl)); M17N_OBJECT_UNREF (MPLIST_VAL (plist)); } M17N_OBJECT_UNREF (disp_info->font_list); @@ -442,12 +415,13 @@ static unsigned xfont_encode_char (MFrame *, MFont *, MFont *, unsigned); static void xfont_render (MDrawWindow, int, int, MGlyphString *, MGlyph *, MGlyph *, int, MDrawRegion); static int xfont_list (MFrame *, MPlist *, MFont *, int); - +static void xfont_list_family_names (MFrame *, MPlist *); +static int xfont_check_capability (MRealizedFont *rfont, MSymbol capability); static MFontDriver xfont_driver = { xfont_select, xfont_open, xfont_find_metric, xfont_has_char, xfont_encode_char, - xfont_render, xfont_list }; + xfont_render, xfont_list, xfont_list_family_names, xfont_check_capability }; static int font_compare (const void *p1, const void *p2) @@ -471,7 +445,7 @@ xfont_registry_list (MFrame *frame, MSymbol registry) plist = mplist_get (font_list, registry); if (plist) return plist; - plist = mplist (); + p = plist = mplist (); mplist_add (font_list, registry, plist); sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s", msymbol_name (registry)); font_names = XListFonts (disp_info->display, pattern, 0x8000, &nfonts); @@ -489,24 +463,20 @@ xfont_registry_list (MFrame *frame, MSymbol registry) memcpy (names, font_names, sizeof (char *) * nfonts); qsort (names, nfonts, sizeof (char *), font_compare); MFONT_INIT (&font); - for (i = 0, p = NULL; i < nfonts; i++) + for (i = 0; i < nfonts; i++) if (mfont__parse_name_into_font (names[i], Mx, &font) == 0 - && (font.size >= 50 || font.property[MFONT_RESY] == 0)) + && (font.size > 0 || font.property[MFONT_RESY] == 0)) { MSymbol family = FONT_PROPERTY (&font, MFONT_FAMILY); - MFontX *fontx, *fontx2; + MFont *fontx; unsigned sizes[256]; int nsizes = 0; - int size, smallest; + int limit; + int size, normal_size; char *base_end; int base_len; int fields; - if (p && MPLIST_KEY (p) != family) - p = mplist_find_by_key (plist, family); - if (! p) - p = mplist_push (plist, family, NULL); - /* Calculate how many bytes to compare to detect fonts of the same base name. */ for (base_end = names[i], fields = 0; *base_end; base_end++) @@ -515,44 +485,44 @@ xfont_registry_list (MFrame *frame, MSymbol registry) break; base_len = base_end - names[i] + 1; - size = smallest = font.size / 10; + size = font.size / 10; sizes[nsizes++] = size; - for (j = i + 1; j < nfonts && ! strncmp (names[i], names[j], base_len); + normal_size = (size >= 6 && size <= 29); + limit = (i + 256 < nfonts ? i + 256 : nfonts); + for (j = i + 1; j < limit && ! memcmp (names[i], names[j], base_len); i = j++) if (mfont__parse_name_into_font (names[j], Mx, &font) == 0 - && (font.size >= 50 || font.property[MFONT_RESY] == 0)) + && (font.size > 0 || font.property[MFONT_RESY] == 0)) { size = font.size / 10; - if (size < smallest) - smallest = size; - if (nsizes < 256) - sizes[nsizes++] = size; + sizes[nsizes++] = size; + normal_size |= (size >= 6 && size <= 29); } font.for_full_width = for_full_width; font.type = MFONT_TYPE_OBJECT; font.source = MFONT_SOURCE_X; - MSTRUCT_CALLOC (fontx, MERROR_WIN); - fontx->core = font; - fontx->core.size = smallest * 10; - fontx->next = MPLIST_VAL (p); - MPLIST_VAL (p) = fontx; - if (smallest > 0) - for (j = 0; j < nsizes; j++) + if (normal_size) + { + MSTRUCT_CALLOC (fontx, MERROR_WIN); + *fontx = font; + fontx->multiple_sizes = 1; + fontx->size = 0; + for (j = 0; j < nsizes; j++) + if (sizes[j] >= 6 && sizes[j] <= 29) + fontx->size |= 1 << (sizes[j] - 6); + p = mplist_add (p, family, fontx); + } + for (j = 0; j < nsizes; j++) + if (sizes[j] < 6 || sizes[j] > 29) { - if (sizes[j] <= 36) - { - if (sizes[j] != smallest) - SET_SIZE (fontx, sizes[j]); - } - else - { - MSTRUCT_CALLOC (fontx2, MERROR_WIN); - fontx2->core = font; - fontx2->core.size = sizes[j] * 10; - fontx2->next = MPLIST_VAL (p); - MPLIST_VAL (p) = fontx2; - } + MSTRUCT_CALLOC (fontx, MERROR_WIN); + *fontx = font; + fontx->multiple_sizes = 0; + fontx->size = sizes[j] * 10; + if (sizes[j] == 0) + fontx->property[MFONT_RESY] = 0; + p = mplist_add (p, family, fontx); } } XFreeFontNames (font_names); @@ -623,7 +593,7 @@ close_xfont (void *object) static MRealizedFont * xfont_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont) { - int size = spec->size; + int size; MRealizedFontX *x_rfont; char *name; Display *display = FRAME_DISPLAY (frame); @@ -631,6 +601,41 @@ xfont_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont) int mdebug_mask = MDEBUG_FONT; MFont this; + size = spec->size; + if (size) + { + int ratio = mfont_resize_ratio (font); + + if (ratio != 100) + size = size * ratio / 100; + } + else + size = 120; + + if (font->size) + { + /* non-scalable font */ + if (font->multiple_sizes) + { + int i; + + if (size < 60) + size = 60; + else if (size > 290) + size = 290; + for (i = size / 10 - 6; i >= 0; i--) + if (font->size & (1 << i)) + break; + if (i == 0) + for (i = size / 10 - 5; i < 24; i++) + if (font->size & (1 << i)) + break; + size = (i + 6) * 10; + } + else + size = font->size; + } + if (rfont) { for (; rfont; rfont = rfont->next) @@ -639,6 +644,7 @@ xfont_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont) } this = *font; + this.multiple_sizes = 0; this.size = size; /* This never fail to generate a valid fontname. */ name = mfont_unparse_name (&this, Mx); @@ -670,6 +676,9 @@ xfont_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont) rfont->baseline_offset = (XGetFontProperty (xfont, disp_info->MULE_BASELINE_OFFSET, &value) ? (int) value : 0); + rfont->average_width + = (XGetFontProperty (xfont, disp_info->AVERAGE_WIDTH, &value) + ? (int) value / 10 : 0); } rfont->ascent = xfont->ascent + rfont->baseline_offset; rfont->descent = xfont->descent - rfont->baseline_offset; @@ -777,11 +786,9 @@ xfont_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code) rfont = (MRealizedFont *) font; else if (font->type == MFONT_TYPE_OBJECT) { - int size = spec->size; - for (rfont = MPLIST_VAL (frame->realized_font_list); rfont; rfont = rfont->next) - if (rfont->font == font && rfont->spec.size == size) + if (rfont->font == font) break; if (! rfont) { @@ -930,62 +937,86 @@ xfont_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum) xfont_registry_list (frame, registry); MPLIST_DO (pl, disp_info->font_list) + if (registry == Mnil || registry == MPLIST_KEY (pl)) + { + MPLIST_DO (p, MPLIST_VAL (pl)) + if (family == Mnil || family == MPLIST_KEY (p)) + { + MFont *fontx = MPLIST_VAL (p); + + if (! font || (mfont__match_p (fontx, font, MFONT_REGISTRY))) + { + if (fontx->size != 0 && size) + { + if (fontx->multiple_sizes) + { + if (size < 60 || size > 290 + || ! (fontx->size & (1 << (size / 10 - 6)))) + continue; + } + else if (fontx->size != size) + continue; + } + mplist_push (plist, MPLIST_KEY (p), fontx); + num++; + if (maxnum > 0 && maxnum == num) + goto done; + } + } + } + + done: + MDEBUG_PRINT1 (" %d found\n", num); + return num; +} + +static void +xfont_list_family_names (MFrame *frame, MPlist *plist) +{ + MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info; + char **font_names; + int i, nfonts; + MSymbol last_family = Mnil; + + font_names = XListFonts (disp_info->display, + "-*-*-*-*-*-*-*-*-*-*-*-*-*-*", 0x8000, &nfonts); + for (i = 0; i < nfonts; i++) { - if (registry != Mnil && registry != MPLIST_KEY (pl)) + MSymbol family; + char foundry[256], fam[256]; + MPlist *p; + + if (sscanf (font_names[i], "-%s-%s-", foundry, fam) < 2) + continue; + family = msymbol (fam); + if (family == last_family) continue; - MPLIST_DO (p, MPLIST_VAL (pl)) + last_family = family; + + MPLIST_DO (p, plist) { - MFontX *fontx; - - if (family != Mnil && family != MPLIST_KEY (p)) - continue; - for (fontx = MPLIST_VAL (p); fontx; fontx = fontx->next) - if (! font - || (mfont__match_p (&fontx->core, font, MFONT_REGISTRY))) - { - if (fontx->core.size == size - || fontx->core.size == 0) - { - mplist_push (plist, MPLIST_KEY (p), fontx); - num++; - } - else if (size == 0 - || (size <= 360 && HAVE_SIZE (fontx, (size / 10)))) - { - unsigned size5_36 = fontx->size5_36; - MFontX *fontx2; - int i; - - fontx->size5_36 = 0; - for (i = fontx->core.size / 10; i <= 36; i++) - if (size5_36 & (1 << (i - 5))) - { - MSTRUCT_CALLOC (fontx2, MERROR_WIN); - fontx2->core = fontx->core; - fontx2->core.size = i * 10; - fontx2->next = fontx->next; - fontx->next = fontx2; - fontx = fontx2; - if ((size == 0 || size == fontx->core.size) - && (maxnum == 0 || num < maxnum)) - { - mplist_push (plist, MPLIST_KEY (p), fontx); - num++; - } - } - } - if (maxnum > 0 && maxnum == num) - break; - } - if (maxnum > 0 && maxnum == num) + MSymbol sym = MPLIST_SYMBOL (p); + + if (sym == family) break; + if (strcmp (MSYMBOL_NAME (sym), fam) > 0) + { + mplist_push (p, Msymbol, family); + break; + } } - if (maxnum > 0 && maxnum == num) - break; + if (MPLIST_TAIL_P (p)) + mplist_push (p, Msymbol, family); } + if (font_names) + XFreeFontNames (font_names); +} - MDEBUG_PRINT1 (" %d found\n", num); - return num; +static int +xfont_check_capability (MRealizedFont *rfont, MSymbol capability) +{ + /* Currently X font driver doesn't support any capability. */ + return -1; } @@ -996,10 +1027,10 @@ xfont_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum) typedef struct { M17NObject control; + FT_Face ft_face; /* This must be the 2nd member. */ Display *display; XftFont *font_aa; XftFont *font_no_aa; - FT_Face ft_face; /* Pointer to MRealizedFontFT */ void *info; } MRealizedFontXft; @@ -1013,10 +1044,13 @@ static unsigned xft_encode_char (MFrame *frame, MFont *font, MFont *spec, static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int); static void xft_render (MDrawWindow, int, int, MGlyphString *, MGlyph *, MGlyph *, int, MDrawRegion); +static int xft_check_capability (MRealizedFont *rfont, MSymbol capability); -MFontDriver xft_driver = +static MFontDriver xft_driver = { NULL, xft_open, - xft_find_metric, xft_has_char, xft_encode_char, xft_render, NULL }; + xft_find_metric, xft_has_char, xft_encode_char, xft_render, NULL, NULL, + xft_check_capability + }; static void close_xft (void *object) @@ -1056,9 +1090,21 @@ xft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont) FT_Face ft_face; MRealizedFontXft *rfont_xft; FcBool anti_alias = FRAME_DEVICE (frame)->depth > 1 ? FcTrue : FcFalse; - double size = font->size ? font->size : spec->size; + int size; XftFont *xft_font; - int ascent, descent, max_advance, baseline_offset; + int ascent, descent, max_advance, average_width, baseline_offset; + + if (font->size) + /* non-scalable font */ + size = font->size; + else if (spec->size) + { + int ratio = mfont_resize_ratio (font); + + size = ratio == 100 ? spec->size : spec->size * ratio / 100; + } + else + size = 120; if (rfont) { @@ -1083,6 +1129,7 @@ xft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont) ascent = rfont->ascent; descent = rfont->descent; max_advance = rfont->max_advance; + average_width = rfont->average_width; baseline_offset = rfont->baseline_offset; spec = &rfont->spec; ft_face = rfont->fontp; @@ -1100,6 +1147,7 @@ xft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont) M17N_OBJECT_REF (rfont->info); MSTRUCT_CALLOC (rfont, MERROR_FONT_X); rfont->spec = *spec; + rfont->spec.size = size; rfont->frame = frame; rfont->font = font; rfont->driver = &xft_driver; @@ -1107,6 +1155,7 @@ xft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont) rfont->ascent = ascent; rfont->descent = descent; rfont->max_advance = max_advance; + rfont->average_width = average_width; rfont->baseline_offset = baseline_offset; rfont->fontp = xft_font; rfont->next = MPLIST_VAL (frame->realized_font_list); @@ -1264,6 +1313,18 @@ xft_render (MDrawWindow win, int x, int y, XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs); } +static int +xft_check_capability (MRealizedFont *rfont, MSymbol capability) +{ + MRealizedFontXft *rfont_xft = rfont->info; + int result; + + rfont->info = rfont_xft->info; + result = mfont__ft_driver.check_capability (rfont, capability); + rfont->info = rfont_xft; + return result; +} + #endif /* HAVE_XFT2 */ @@ -1710,6 +1771,12 @@ mwin__create_window (MFrame *frame, MDrawWindow parent) static void mwin__destroy_window (MFrame *frame, MDrawWindow win) { +#ifdef HAVE_XFT2 + XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw; + + if (XftDrawDrawable (xft_draw) == (Drawable) win) + XftDrawChange (xft_draw, FRAME_DEVICE (frame)->drawable); +#endif /* HAVE_XFT2 */ XDestroyWindow (FRAME_DISPLAY (frame), (Window) win); } @@ -1859,7 +1926,7 @@ mwin__parse_event (MFrame *frame, void *arg, int *modifiers) int len; char buf[512]; KeySym keysym; - MSymbol key = Mnil; + MSymbol key; *modifiers = 0; if (event->xany.type != KeyPress @@ -1869,26 +1936,17 @@ mwin__parse_event (MFrame *frame, void *arg, int *modifiers) len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL); if (len > 1) return Mnil; - if (len == 1) + if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R) + return Mnil; + if (len == 1 && keysym >= XK_space && keysym <= XK_asciitilde) { int c = keysym; - if (c < XK_space || c > XK_asciitilde) - c = buf[0]; - if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask) - *modifiers |= MINPUT_KEY_SHIFT_MODIFIER; - if (((XKeyEvent *) event)->state & ControlMask) - { - if (c >= 'a' && c <= 'z') - c += 'A' - 'a'; - if (c >= ' ' && c < 127) - *modifiers |= MINPUT_KEY_CONTROL_MODIFIER; - } key = minput__char_to_key (c); + if (c == ' ' && ((XKeyEvent *) event)->state & ShiftMask) + *modifiers |= MINPUT_KEY_SHIFT_MODIFIER; } - else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R) - return Mnil; - if (key == Mnil) + else { char *str = XKeysymToString (keysym); @@ -1897,9 +1955,9 @@ mwin__parse_event (MFrame *frame, void *arg, int *modifiers) key = msymbol (str); if (((XKeyEvent *) event)->state & ShiftMask) *modifiers |= MINPUT_KEY_SHIFT_MODIFIER; - if (((XKeyEvent *) event)->state & ControlMask) - *modifiers |= MINPUT_KEY_CONTROL_MODIFIER; } + if (((XKeyEvent *) event)->state & ControlMask) + *modifiers |= MINPUT_KEY_CONTROL_MODIFIER; if (((XKeyEvent *) event)->state & disp_info->meta_mask) *modifiers |= MINPUT_KEY_META_MODIFIER; if (((XKeyEvent *) event)->state & disp_info->alt_mask) @@ -1972,6 +2030,7 @@ device_init () #ifdef HAVE_XFT2 xft_driver.select = mfont__ft_driver.select; xft_driver.list = mfont__ft_driver.list; + xft_driver.list_family_names = mfont__ft_driver.list_family_names; #endif Mxim = msymbol ("xim"); @@ -2130,6 +2189,8 @@ device_open (MFrame *frame, MPlist *param) find_modifier_bits (disp_info); disp_info->MULE_BASELINE_OFFSET = XInternAtom (display, "_MULE_BASELINE_OFFSET", False); + disp_info->AVERAGE_WIDTH + = XInternAtom (display, "AVERAGE_WIDTH", False); mplist_add (display_info_list, Mt, disp_info); }