X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fm17n-X.c;h=469b8963cf73995141fb8e0a146588305f7f7daf;hb=9e2820bc75b5631b7b8a34c709f537716299bf0f;hp=dbaf6f23e37cfb76dba0178c33a9ba3a28891eab;hpb=2d49a014ebb8a4a5e16d07d21a7af2ab7b16b962;p=m17n%2Fm17n-lib.git diff --git a/src/m17n-X.c b/src/m17n-X.c index dbaf6f2..469b896 100644 --- a/src/m17n-X.c +++ b/src/m17n-X.c @@ -58,11 +58,16 @@ typedef struct { MFont core; - unsigned int sizes[2]; + /* Nth bit tells the existence of a font of size (N+1). + core.property[MFONT_SIZE] holds the smallest size. */ + unsigned int sizes; + /* If sizes is not 0, smallest and largest sizes. */ + unsigned short smallest, largest; } MXFont; -#define SET_SIZE(xfont, s) ((xfont)->sizes[(s) / 32] |= (1 << ((s) & 0x1F))) -#define HAVE_SIZE(xfont, s) ((xfont)->sizes[(s) / 32] & (1 << ((s) & 0x1F))) +/* S must satisfy the condition (S > 0 && S <= 32). */ +#define SET_SIZE(sizes, s) ((sizes) |= (1 << ((s) - 1))) +#define HAVE_SIZE(sizes, s) ((sizes) & (1 << ((s) - 1))) typedef struct { int size, inc, used; @@ -453,7 +458,6 @@ xfont_registry_list (MFrame *frame, MSymbol registry) int nfonts; int i, j; MXFont font; - MXFontList *xfont_table; MFont *bfont = NULL; plist = mplist_get (font_list, registry); @@ -474,42 +478,87 @@ xfont_registry_list (MFrame *frame, MSymbol registry) || font.core.property[MFONT_RESY] == 0)) { MSymbol family = FONT_PROPERTY ((MFont *) &font, MFONT_FAMILY); - int size = font.core.property[MFONT_SIZE] / 10; + MXFontList *xfont_table; + int sizes[256]; + int sizes_idx = 0; + int size, smallest, largest; + int have_scalable; + unsigned int size_bits = 0; char *base_end; int base_len; int fields; - font.sizes[0] = font.sizes[1] = 0; - SET_SIZE (&font, size); - - /* Handle fonts of the same base. */ + if (p && MPLIST_KEY (p) != family) + p = mplist_find_by_key (plist, family); + if (p) + xfont_table = MPLIST_VAL (p); + else + { + p = plist; + MSTRUCT_MALLOC (xfont_table, MERROR_WIN); + MLIST_INIT1 (xfont_table, fonts, 4); + mplist_push (p, family, xfont_table); + } + + /* 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++) if (*base_end == '-' && ++fields == 7 /* PIXEL_SIZE */) break; - base_len = base_end - names[i]; + base_len = base_end - names[i] + 1; + + size = font.core.property[MFONT_SIZE] / 10; + have_scalable = size == 0; + sizes[sizes_idx++] = size; for (j = i + 1; j < nfonts && ! strncmp (names[i], names[j], base_len); i = j++) if (mfont__parse_name_into_font (names[j], Mx, (MFont *) &font) == 0 && (font.core.property[MFONT_SIZE] > 0 || font.core.property[MFONT_RESY] == 0)) { + int k; + size = font.core.property[MFONT_SIZE] / 10; - SET_SIZE (&font, size); + if (! have_scalable) + have_scalable = size == 0; + for (k = 0; k < sizes_idx && sizes[k] != size; k++); + if (k == sizes_idx && sizes_idx < 256) + sizes[sizes_idx++] = size; } - if (p && MPLIST_KEY (p) != family) - p = mplist_find_by_key (plist, family); - if (p) - xfont_table = MPLIST_VAL (p); - else + for (j = 0, smallest = 0; j < sizes_idx; j++) { - p = plist; - MSTRUCT_MALLOC (xfont_table, MERROR_WIN); - MLIST_INIT1 (xfont_table, fonts, 4); - mplist_push (p, family, xfont_table); + size = sizes[j]; + if (size <= 32) + { + if (size != 0) + { + if (smallest == 0) + smallest = largest = size; + else if (size < smallest) + smallest = size; + else if (size > largest) + largest = size; + SET_SIZE (size_bits, size); + } + } + else + { + font.core.property[MFONT_SIZE] = size * 10; + font.sizes = 0; + MLIST_APPEND1 (xfont_table, fonts, font, MERROR_WIN); + } + } + + if (size_bits || have_scalable == 1) + { + font.sizes = size_bits; + font.smallest = smallest; + font.largest = largest; + font.core.property[MFONT_SIZE] = have_scalable ? 0 : smallest * 10; + MLIST_APPEND1 (xfont_table, fonts, font, MERROR_WIN); } - MLIST_APPEND1 (xfont_table, fonts, font, MERROR_WIN); if (! bfont || (font.core.property[MFONT_FOUNDRY] != bfont->property[MFONT_FOUNDRY]) @@ -555,16 +604,16 @@ typedef struct /* The X font driver function SELECT. */ static MRealizedFont * -xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size){ - +xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size) +{ MSymbol family = FONT_PROPERTY (spec, MFONT_FAMILY); MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY); - int requested_size = request->property[MFONT_SIZE]; + int requested_size = request->property[MFONT_SIZE] / 10; MRealizedFont *rfont; MPlist *plist; int i; MFont *best_font; - int best_score, score; + int best_size, best_score, score; if (registry == Mnil || ! strchr (MSYMBOL_NAME (registry), '-')) @@ -574,8 +623,6 @@ xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size){ if (MPLIST_TAIL_P (plist)) return NULL; best_score = -1, best_font = NULL; - if (family == Mnil) - family = FONT_PROPERTY (request, MFONT_FAMILY); MPLIST_DO (plist, plist) { if (family == Mnil || family == MPLIST_KEY (plist)) @@ -586,42 +633,46 @@ xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size){ { MXFont *xfont = xfont_table->fonts + i; MFont *font = (MFont *) xfont; - int size = requested_size / 10, s0, s1; - - for (s0 = size; s0 > 0 && ! HAVE_SIZE (xfont, s0); s0--); - if (s0 * 10 == requested_size) - /* Exact size match. */ - ; - else if (xfont->sizes[0] & 1) - /* Scalable font. */ + unsigned int sizes = xfont->sizes; + int orig_size = font->property[MFONT_SIZE]; + int size; + + if (sizes == 0) + size = orig_size / 10; + else if (requested_size < xfont->smallest) + size = orig_size == 0 ? 0 : xfont->smallest; + else if (requested_size > xfont->largest) + size = orig_size == 0 ? 0 : xfont->largest; + else if (HAVE_SIZE (sizes, requested_size)) + size = requested_size; + else if (orig_size == 0) size = 0; - else if (limited_size) - /* We can't use a larger font. */ - continue; - else if (s0 == 0) - { - for (s0 = size + 1; s0 < 64 && ! HAVE_SIZE (xfont, s0); s0++); - if (s0 == 64) - continue; - size = s0; - } else { - for (s1 = size + (size - s0) - 1; - s1 > size && HAVE_SIZE (xfont, s1); s1++); - size = (s1 > size ? s1 : s0); + for (size = requested_size - 1; + size > xfont->smallest && ! HAVE_SIZE (sizes, size); + size--); + if (! limited_size) + { + int s; + for (s = requested_size; + s < xfont->largest && ! HAVE_SIZE (sizes, s); + s++); + if (s - requested_size < requested_size - size) + size = s; + } } font->property[MFONT_SIZE] = size * 10; - - if ((score = mfont__score (font, spec, request, - limited_size)) >= 0 - && (best_score < 0 || score < best_score)) - { - best_score = score; - best_font = (MFont *) (xfont_table->fonts + i); - if (best_score == 0) - break; - } + score = mfont__score (font, spec, request, limited_size); + font->property[MFONT_SIZE] = orig_size; + if (score >= 0 && (best_score < 0 || score < best_score)) + { + best_size = size * 10; + best_score = score; + best_font = (MFont *) (xfont_table->fonts + i); + if (best_score == 0) + break; + } } if (best_score == 0) break; @@ -635,8 +686,10 @@ xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size){ rfont->spec = *spec; rfont->request = *request; rfont->font = *best_font; - if (best_font->property[MFONT_SIZE] == 0) + if (best_size == 0) rfont->font.property[MFONT_SIZE] = request->property[MFONT_SIZE]; + else + rfont->font.property[MFONT_SIZE] = best_size; rfont->score = best_score; return rfont; } @@ -1899,7 +1952,7 @@ device_open (MFrame *frame, MPlist *param) MPlist *plist; AppData app_data; MFace *face; - int use_xfont = 1, use_freetype = 1; + int use_xfont = 0, use_freetype = 0, use_xft = 0; for (plist = param; (key = mplist_key (plist)) != Mnil; plist = mplist_next (plist)) @@ -1921,14 +1974,22 @@ device_open (MFrame *frame, MPlist *param) MSymbol val = MPLIST_SYMBOL (plist); if (val == Mx) - use_freetype = 0; + use_xfont = 1; #ifdef HAVE_FREETYPE else if (val == Mfreetype) - use_xfont = 0; + use_freetype = 1; +#ifdef HAVE_XFT2 + else if (val == Mxft) + use_xft = 1; +#endif #endif } } + /* If none of them is specified, use all of them. */ + if (! use_xfont && ! use_freetype && ! use_xft) + use_xfont = use_freetype = use_xft = 1; + if (widget) { display = XtDisplay (widget); @@ -2036,15 +2097,20 @@ device_open (MFrame *frame, MPlist *param) frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT; frame->driver = &x_driver; frame->font_driver_list = mplist (); - if (use_xfont) - mplist_add (frame->font_driver_list, Mx, &xfont_driver); #ifdef HAVE_XFT2 - if (use_freetype) - mplist_add (frame->font_driver_list, Mfreetype, &xft_driver); -#elif HAVE_FREETYPE + if (use_xft) + { + mplist_add (frame->font_driver_list, Mfreetype, &xft_driver); + use_freetype = 0; + } +#endif /* HAVE_XFT2 */ +#ifdef HAVE_FREETYPE if (use_freetype) mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver); -#endif +#endif /* HAVE_FREETYPE */ + if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list)) + mplist_push (frame->font_driver_list, Mx, &xfont_driver); + frame->realized_font_list = device->realized_font_list; frame->realized_face_list = device->realized_face_list; frame->realized_fontset_list = device->realized_fontset_list; @@ -2077,18 +2143,20 @@ device_open (MFrame *frame, MPlist *param) } { - int nfonts; - char **names = XListFonts (display, app_data.font, 1, &nfonts); + int nfonts, i; + /* Try at least 32 fonts to obtain a non-autoscaled font. */ + char **names = XListFonts (display, app_data.font, 32, &nfonts); + MFont *font = NULL; - if (nfonts > 0) + for (i = 0; ! font && i < nfonts; i++) { - if (! (frame->font = mfont_parse_name (names[0], Mx))) + font = mfont_parse_name (names[i], Mx); + if (!font) { /* The font name does not conform to XLFD. Try to open the font and get XA_FONT property. */ - XFontStruct *xfont = XLoadQueryFont (display, names[0]); + XFontStruct *xfont = XLoadQueryFont (display, names[i]); - nfonts = 0; if (xfont) { unsigned long value; @@ -2097,17 +2165,20 @@ device_open (MFrame *frame, MPlist *param) if (XGetFontProperty (xfont, XA_FONT, &value) && (name = ((char *) XGetAtomName (display, (Atom) value)))) - { - if ((frame->font = mfont_parse_name (name, Mx))) - nfonts = 1; - } + font = mfont_parse_name (name, Mx); XFreeFont (display, xfont); } } - XFreeFontNames (names); + if (font && + font->property[MFONT_SIZE] == 0 && font->property[MFONT_RESY] > 0) + { + free (font); + font = NULL; + } } - if (! nfonts) - frame->font = mfont_parse_name (FALLBACK_FONT, Mx); + if (nfonts) + XFreeFontNames (names); + frame->font = font ? font : mfont_parse_name (FALLBACK_FONT, Mx); } face = mface_from_font (frame->font); @@ -2382,31 +2453,27 @@ x_io_error_handler (Display *display) /***ja @brief XIMÍÑÆþÎϥɥ饤¥Ð. - ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã - ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸ - ¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£ + ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã¥ÉÍѤǤ¢¤ê¡¢ + XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£ ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£ - #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ - ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£ + #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim + ¤Ç¤¢¤ëÆþÎϥ᥽¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£ - ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø - ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ + ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ + ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ - ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM ¤Ø¤Î¥Ý - ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò - »²¾È¡£ + ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM + ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò»²¾È¡£ - ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC ¤Ø¤Î - ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ - ¤ò»²¾È¡£ + ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC + ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ¤ò»²¾È¡£ - ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿ - ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£ + ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent + ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£ ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter () - ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì - ¤ë¡£ */ + ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì¤ë¡£ */ MInputDriver minput_xim_driver = { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,