summaryrefslogtreecommitdiff
path: root/src/ftfont.c
diff options
context:
space:
mode:
authorKenichi Handa <handa@m17n.org>2009-04-13 12:33:13 +0000
committerKenichi Handa <handa@m17n.org>2009-04-13 12:33:13 +0000
commit99c4d65db7400d28b56494fd3671471a43acb76d (patch)
treebad63641cc7d73546acf172a390c6960db4572bf /src/ftfont.c
parent7395a3b3278acf50a66294d2f799a9e62b146b2d (diff)
downloademacs-99c4d65db7400d28b56494fd3671471a43acb76d.tar.gz
emacs-99c4d65db7400d28b56494fd3671471a43acb76d.tar.bz2
emacs-99c4d65db7400d28b56494fd3671471a43acb76d.zip
(Qja, Qko): New variables.
(fc_charset_table): Delete uniquifier data for iso8859-1. (ftfont_get_latin1_charset): New function. (get_adstyle_property): New function. (ftfont_pattern_entity): Set FONT_ADSTYLE_INDEX of entity for bitmap fonts. (ftfont_lookup_cache): Handle the case that KEY is a font-entity. Delete iso-8859-1 range from the charset of fonts whose adstyle is `ko' or `ja'. (ftfont_get_fc_charset): Call ftfont_lookup_cache with ENTITY. (ftfont_get_charset): For iso8859-1, call ftfont_get_latin1_charset. (ftfont_list): Don't refuse a font spec with non-nil `adstyle' property. (ftfont_open): Call ftfont_lookup_cache with ENTITY. (syms_of_ftfont): DEFSYM Qja and Qko.
Diffstat (limited to 'src/ftfont.c')
-rw-r--r--src/ftfont.c199
1 files changed, 162 insertions, 37 deletions
diff --git a/src/ftfont.c b/src/ftfont.c
index 0be985e30f2..6865478bd20 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -43,6 +43,9 @@ Lisp_Object Qfreetype;
/* Fontconfig's generic families and their aliases. */
static Lisp_Object Qmonospace, Qsans_serif, Qserif, Qmono, Qsans, Qsans__serif;
+/* Special ADSTYLE properties to avoid fonts used for Latin characters. */
+static Lisp_Object Qja, Qko;
+
/* Flag to tell if FcInit is already called or not. */
static int fc_initialized;
@@ -92,7 +95,7 @@ static struct
/* set on demand */
FcCharSet *fc_charset;
} fc_charset_table[] =
- { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
+ { { "iso8859-1", { } }, /* ftfont_get_latin1_charset handles it. */
{ "iso8859-2", { 0x00A0, 0x010E }},
{ "iso8859-3", { 0x00A0, 0x0108 }},
{ "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
@@ -132,8 +135,71 @@ static struct
{ NULL }
};
+/* Return a FcCharSet for iso8859-1 from fc_charset_table[0]. If the
+ charset is not yet ready, create it. */
+static FcCharSet *
+ftfont_get_latin1_charset ()
+{
+ FcCharSet *cs;
+ FcChar32 c;
+
+ if (fc_charset_table[0].fc_charset)
+ return fc_charset_table[0].fc_charset;
+ cs = FcCharSetCreate ();
+ if (! cs)
+ return NULL;
+ for (c = 33; c <= 0xFF; c++)
+ {
+ FcCharSetAddChar (cs, c);
+ if (c == 0x7E)
+ c = 0xA0;
+ }
+ fc_charset_table[0].fc_charset = cs;
+ return cs;
+}
+
extern Lisp_Object Qc, Qm, Qp, Qd;
+/* Dirty hack for handing ADSTYLE property.
+
+ Fontconfig (actually the underlying FreeType) gives such ADSTYLE
+ font property of PCF/BDF fonts in FC_STYLE. And, "Bold",
+ "Oblique", "Italic", or any non-normal SWIDTH property names
+ (e.g. SemiCondensed) are appended. In addition, if there's no
+ ADSTYLE property nor non-normal WEIGHT/SLANT/SWIDTH properties,
+ "Regular" is used for FC_STYLE (see the function
+ pcf_interpret_style in src/pcf/pcfread.c of FreeType).
+
+ Unfortunately this behavior is not documented, so the following
+ code may fail if FreeType changes the behavior in the future. */
+
+static Lisp_Object
+get_adstyle_property (FcPattern *p)
+{
+ char *str, *end;
+ Lisp_Object adstyle;
+
+ if (FcPatternGetString (p, FC_STYLE, 0, (FcChar8 **) &str) != FcResultMatch)
+ return Qnil;
+ for (end = str; *end && *end != ' '; end++);
+ if (*end)
+ {
+ char *p = alloca (end - str + 1);
+ memcpy (p, str, end - str);
+ p[end - str] = '\0';
+ str = p;
+ }
+ if (xstrcasecmp (str, "Regular") == 0
+ || xstrcasecmp (str, "Bold") == 0
+ || xstrcasecmp (str, "Oblique") == 0
+ || xstrcasecmp (str, "Italic") == 0)
+ return Qnil;
+ adstyle = font_intern_prop (str, end - str, 0);
+ if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0)
+ return Qnil;
+ return adstyle;
+}
+
static Lisp_Object
ftfont_pattern_entity (p, extra)
FcPattern *p;
@@ -176,7 +242,14 @@ ftfont_pattern_entity (p, extra)
FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, make_number (numeric));
}
if (FcPatternGetDouble (p, FC_PIXEL_SIZE, 0, &dbl) == FcResultMatch)
- ASET (entity, FONT_SIZE_INDEX, make_number (dbl));
+ {
+ Lisp_Object adstyle;
+
+ ASET (entity, FONT_SIZE_INDEX, make_number (dbl));
+ /* As this font has PIXEL_SIZE property, parhaps this is a BDF
+ or PCF font. */
+ ASET (entity, FONT_ADSTYLE_INDEX, get_adstyle_property (p));
+ }
else
ASET (entity, FONT_SIZE_INDEX, make_number (0));
if (FcPatternGetInteger (p, FC_SPACING, 0, &numeric) == FcResultMatch)
@@ -265,9 +338,19 @@ ftfont_lookup_cache (key, for_face)
Lisp_Object key;
int for_face;
{
- Lisp_Object cache, val;
+ Lisp_Object cache, val, entity;
struct ftfont_cache_data *cache_data;
+ if (FONT_ENTITY_P (key))
+ {
+ entity = key;
+ val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
+ xassert (CONSP (val));
+ key = XCDR (val);
+ }
+ else
+ entity = Qnil;
+
cache = assoc_no_quit (key, ft_face_cache);
if (NILP (cache))
{
@@ -301,25 +384,56 @@ ftfont_lookup_cache (key, for_face)
}
else
{
- FcPattern *pat;
- FcFontSet *fontset;
- FcObjectSet *objset;
- FcCharSet *charset;
+ FcPattern *pat = NULL;
+ FcFontSet *fontset = NULL;
+ FcObjectSet *objset = NULL;
+ FcCharSet *charset = NULL;
pat = FcPatternBuild (0, FC_FILE, FcTypeString, (FcChar8 *) filename,
FC_INDEX, FcTypeInteger, index, NULL);
- objset = FcObjectSetBuild (FC_CHARSET, NULL);
+ if (! pat)
+ goto finish;
+ objset = FcObjectSetBuild (FC_CHARSET, FC_STYLE, NULL);
+ if (! objset)
+ goto finish;
fontset = FcFontList (NULL, pat, objset);
- if (fontset && fontset->nfont > 0
- && (FcPatternGetCharSet (fontset->fonts[0], FC_CHARSET, 0,
+ if (! fontset)
+ goto finish;
+ if (fontset && fontset->nfont > 0)
+ {
+ if (FcPatternGetCharSet (fontset->fonts[0], FC_CHARSET, 0,
&charset)
- == FcResultMatch))
- cache_data->fc_charset = FcCharSetCopy (charset);
+ == FcResultMatch)
+ {
+ /* Dirty hack. Fonts of "ja" and "ko" adstyle are
+ not suitable for Latin characters. */
+ if (! NILP (entity)
+ && (EQ (AREF (entity, FONT_ADSTYLE_INDEX), Qja)
+ || EQ (AREF (entity, FONT_ADSTYLE_INDEX), Qko)))
+ {
+ FcCharSet *latin1 = ftfont_get_latin1_charset ();
+
+ if (! latin1)
+ goto finish;
+ cache_data->fc_charset = FcCharSetSubtract (charset,
+ latin1);
+ }
+ else
+ cache_data->fc_charset = FcCharSetCopy (charset);
+ }
+ else
+ cache_data->fc_charset = FcCharSetCreate ();
+ }
else
cache_data->fc_charset = FcCharSetCreate ();
- FcFontSetDestroy (fontset);
- FcObjectSetDestroy (objset);
- FcPatternDestroy (pat);
+
+ finish:
+ if (fontset)
+ FcFontSetDestroy (fontset);
+ if (objset)
+ FcObjectSetDestroy (objset);
+ if (pat)
+ FcPatternDestroy (pat);
}
}
return cache;
@@ -332,10 +446,7 @@ ftfont_get_fc_charset (entity)
Lisp_Object val, cache;
struct ftfont_cache_data *cache_data;
- val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
- xassert (CONSP (val));
- val = XCDR (val);
- cache = ftfont_lookup_cache (val, 0);
+ cache = ftfont_lookup_cache (entity, 0);
val = XCDR (cache);
cache_data = XSAVE_VALUE (val)->pointer;
return cache_data->fc_charset;
@@ -470,18 +581,23 @@ ftfont_get_charset (registry)
return -1;
if (! fc_charset_table[i].fc_charset)
{
- FcCharSet *charset = FcCharSetCreate ();
- int *uniquifier = fc_charset_table[i].uniquifier;
+ if (i == 0)
+ ftfont_get_latin1_charset ();
+ else
+ {
+ FcCharSet *charset = FcCharSetCreate ();
+ int *uniquifier = fc_charset_table[i].uniquifier;
- if (! charset)
- return -1;
- for (j = 0; uniquifier[j]; j++)
- if (! FcCharSetAddChar (charset, uniquifier[j]))
- {
- FcCharSetDestroy (charset);
+ if (! charset)
return -1;
- }
- fc_charset_table[i].fc_charset = charset;
+ for (j = 0; uniquifier[j]; j++)
+ if (! FcCharSetAddChar (charset, uniquifier[j]))
+ {
+ FcCharSetDestroy (charset);
+ return -1;
+ }
+ fc_charset_table[i].fc_charset = charset;
+ }
}
return i;
}
@@ -602,10 +718,6 @@ ftfont_spec_pattern (spec, otlayout, otspec)
Lisp_Object registry;
int fc_charset_idx;
- if (! NILP (AREF (spec, FONT_ADSTYLE_INDEX))
- && SBYTES (SYMBOL_NAME (AREF (spec, FONT_ADSTYLE_INDEX))) > 0)
- /* Fontconfig doesn't support adstyle property. */
- return NULL;
if ((n = FONT_SLANT_NUMERIC (spec)) >= 0
&& n < 100)
/* Fontconfig doesn't support reverse-italic/obligue. */
@@ -752,7 +864,7 @@ static Lisp_Object
ftfont_list (frame, spec)
Lisp_Object frame, spec;
{
- Lisp_Object val = Qnil, family;
+ Lisp_Object val = Qnil, family, adstyle;
int i;
FcPattern *pattern;
FcFontSet *fontset = NULL;
@@ -800,10 +912,12 @@ ftfont_list (frame, spec)
goto err;
}
}
-
+ adstyle = AREF (spec, FONT_ADSTYLE_INDEX);
+ if (! NILP (adstyle) && SBYTES (SYMBOL_NAME (adstyle)) == 0)
+ adstyle = Qnil;
objset = FcObjectSetBuild (FC_FOUNDRY, FC_FAMILY, FC_WEIGHT, FC_SLANT,
FC_WIDTH, FC_PIXEL_SIZE, FC_SPACING, FC_SCALABLE,
- FC_FILE, FC_INDEX,
+ FC_STYLE, FC_FILE, FC_INDEX,
#ifdef FC_CAPABILITY
FC_CAPABILITY,
#endif /* FC_CAPABILITY */
@@ -908,6 +1022,15 @@ ftfont_list (frame, spec)
if (j == ASIZE (chars))
continue;
}
+ if (! NILP (adstyle))
+ {
+ Lisp_Object this_adstyle = get_adstyle_property (fontset->fonts[i]);
+
+ if (NILP (this_adstyle)
+ || xstrcasecmp (SDATA (SYMBOL_NAME (adstyle)),
+ SDATA (SYMBOL_NAME (this_adstyle))) != 0)
+ continue;
+ }
entity = ftfont_pattern_entity (fontset->fonts[i],
AREF (spec, FONT_EXTRA_INDEX));
if (! NILP (entity))
@@ -1046,7 +1169,7 @@ ftfont_open (f, entity, pixel_size)
if (! CONSP (val))
return Qnil;
val = XCDR (val);
- cache = ftfont_lookup_cache (val, 1);
+ cache = ftfont_lookup_cache (entity, 1);
if (NILP (cache))
return Qnil;
filename = XCAR (val);
@@ -2091,6 +2214,8 @@ syms_of_ftfont ()
DEFSYM (Qmono, "mono");
DEFSYM (Qsans, "sans");
DEFSYM (Qsans__serif, "sans serif");
+ DEFSYM (Qja, "ja");
+ DEFSYM (Qko, "ko");
staticpro (&freetype_font_cache);
freetype_font_cache = Fcons (Qt, Qnil);