Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307, USA. */
+#include "config.h"
+
+#ifdef HAVE_X11
+
#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
/*** @addtogroup m17nInternal
@{ */
-#include "config.h"
-
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int alt_mask;
int super_mask;
int hyper_mask;
+
+ Atom MULE_BASELINE_OFFSET;
+ Atom AVERAGE_WIDTH;
} MDisplayInfo;
/* Anchor of the chain of MDisplayInfo objects. */
GC scratch_gc;
+ int resy;
+
#ifdef HAVE_XFT2
XftDraw *xft_draw;
#endif
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)
int nfonts;
int i, j;
MFont font;
+ int for_full_width;
plist = mplist_get (font_list, registry);
if (plist)
font_names = XListFonts (disp_info->display, pattern, 0x8000, &nfonts);
if (nfonts == 0)
return plist;
+ {
+ char *reg_name = msymbol_name (registry);
+
+ for_full_width = (strncmp (reg_name, "jis", 3) == 0
+ || strncmp (reg_name, "gb", 2) == 0
+ || strncmp (reg_name, "big5", 4) == 0
+ || strncmp (reg_name, "ksc", 3) == 0);
+ }
names = alloca (sizeof (char *) * nfonts);
memcpy (names, font_names, sizeof (char *) * nfonts);
qsort (names, nfonts, sizeof (char *), font_compare);
sizes[nsizes++] = size;
}
+ font.for_full_width = for_full_width;
font.type = MFONT_TYPE_OBJECT;
font.source = MFONT_SOURCE_X;
MSTRUCT_CALLOC (fontx, MERROR_WIN);
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);
int mdebug_mask = MDEBUG_FONT;
MFont this;
+ 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)
{
for (; rfont; rfont = rfont->next)
return rfont;
}
-
this = *font;
this.size = size;
/* This never fail to generate a valid fontname. */
rfont->font = font;
rfont->driver = &xfont_driver;
rfont->info = x_rfont;
+ {
+ MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
+ unsigned long value;
+
+ 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;
+ rfont->max_advance = xfont->max_bounds.width;
rfont->fontp = xfont;
rfont->next = MPLIST_VAL (frame->realized_font_list);
MPLIST_VAL (frame->realized_font_list) = rfont;
g->descent = xfont->descent;
}
}
+ g->ascent += rfont->baseline_offset;
+ g->descent -= rfont->baseline_offset;
}
}
GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
MGlyph *g;
int i;
+ int baseline_offset;
if (from == to)
return;
+ baseline_offset = rface->rfont->baseline_offset;
if (region)
gc = set_region (rface->frame, gc, region);
XSetFont (display, gc, ((XFontStruct *) rface->rfont->fontp)->fid);
else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
{
XDrawString16 (display, (Window) win, gc,
- x + g->xoff, y + g->yoff, code + (g - from), 1);
+ x + g->xoff, y + g->yoff - baseline_offset,
+ code + (g - from), 1);
x += g->width;
g++;
}
g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
i++, g++)
x += g->width;
- XDrawString16 (display, (Window) win, gc, orig_x, y,
- code + code_idx, i);
+ XDrawString16 (display, (Window) win, gc,
+ orig_x, y - baseline_offset, code + code_idx, i);
}
}
}
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++)
+ {
+ 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;
+ last_family = family;
+
+ MPLIST_DO (p, plist)
+ {
+ MSymbol sym = MPLIST_SYMBOL (p);
+
+ if (sym == family)
+ break;
+ if (strcmp (MSYMBOL_NAME (sym), fam) > 0)
+ {
+ mplist_push (p, Msymbol, family);
+ break;
+ }
+ }
+ if (MPLIST_TAIL_P (p))
+ mplist_push (p, Msymbol, family);
+ }
+ if (font_names)
+ XFreeFontNames (font_names);
+}
+
+static int
+xfont_check_capability (MRealizedFont *rfont, MSymbol capability)
+{
+ /* Currently X font driver doesn't support any capability. */
+ return -1;
+}
+
\f
/* Xft Handler */
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)
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, 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)
{
rfont = (mfont__ft_driver.open) (frame, font, spec, rfont);
if (! rfont)
return NULL;
+ 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;
xft_font = xft_open_font (display, font->file, size / 10, anti_alias);
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;
rfont->info = rfont_xft;
+ 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);
MPLIST_VAL (frame->realized_font_list) = rfont;
XftDrawChange (xft_draw, (Drawable) win);
XftDrawSetClip (xft_draw, (Region) region);
+ y -= rfont->baseline_offset;
glyphs = alloca (sizeof (FT_UInt) * (to - from));
for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
{
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 */
\f
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);
}
#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");
disp_info->auto_display = auto_display;
disp_info->font_list = mplist ();
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);
}
device = (MWDevice *) mplist_value (plist);
if (device->display_info == disp_info
&& device->depth == depth
- && device->cmap == cmap)
+ && device->cmap == cmap
+ && device->screen_num == screen_num)
break;
}
{
unsigned long valuemask = GCForeground;
XGCValues values;
+ double pixels, mm;
M17N_OBJECT (device, free_device, MERROR_WIN);
device->display_info = disp_info;
1, 1, depth);
device->depth = depth;
device->cmap = cmap;
+ pixels = DisplayHeight (display, screen_num);
+ mm = DisplayHeightMM (display, screen_num);
+ device->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
device->realized_face_list = mplist ();
device->realized_font_list = mplist ();
mplist_add (device->realized_font_list, Mt, NULL);
frame->device = device;
frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
+ frame->dpi = device->resy;
frame->driver = &x_driver;
frame->font_driver_list = mplist ();
#ifdef HAVE_XFT2
/* External API */
/*** @addtogroup m17nInputMethodWin */
-/*=*/
+
/*** @{ */
/***en
/*** @} */
+#else /* not HAVE_X11 */
+
+int device_open () { return -1; }
+
+#endif /* not HAVE_X11 */
+
/*
Local Variables:
coding: euc-japan