/* xfaces.c -- "Face" primitives.
- Copyright (C) 1993, 1994, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
- Free Software Foundation.
+ Copyright (C) 1993, 1994, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Emacs.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* New face implementation by Gerd Moellmann <gerd@gnu.org>. */
#include "window.h"
#include "intervals.h"
+#ifdef HAVE_WINDOW_SYSTEM
+#ifdef USE_FONT_BACKEND
+#include "font.h"
+#endif /* USE_FONT_BACKEND */
+#endif /* HAVE_WINDOW_SYSTEM */
+
#ifdef HAVE_X_WINDOWS
/* Compensate for a bug in Xos.h on some systems, on which it requires
#define UNSPECIFIEDP(ATTR) EQ ((ATTR), Qunspecified)
+/* Non-zero if face attribute ATTR is `ignore-defface'. */
+
+#define IGNORE_DEFFACE_P(ATTR) EQ ((ATTR), Qignore_defface)
+
/* Value is the number of elements of VECTOR. */
#define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
Lisp_Object Qreleased_button, Qpressed_button;
Lisp_Object QCstyle, QCcolor, QCline_width;
Lisp_Object Qunspecified;
+Lisp_Object Qignore_defface;
char unspecified_fg[] = "unspecified-fg", unspecified_bg[] = "unspecified-bg";
int, struct named_merge_point *));
static int set_lface_from_font_name P_ ((struct frame *, Lisp_Object,
Lisp_Object, int, int));
+static void set_lface_from_font_and_fontset P_ ((struct frame *, Lisp_Object,
+ Lisp_Object, int, int));
static Lisp_Object lface_from_face_name P_ ((struct frame *, Lisp_Object, int));
static struct face *make_realized_face P_ ((Lisp_Object *));
static char *best_matching_font P_ ((struct frame *, Lisp_Object *,
#ifdef MAC_OS
/* Mac OS emulation of GCs */
-extern XGCValues *XCreateGC (void *, Window, unsigned long, XGCValues *);
-
static INLINE GC
x_create_gc (f, mask, xgcv)
struct frame *f;
XGCValues *xgcv;
{
GC gc;
+ BLOCK_INPUT;
gc = XCreateGC (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), mask, xgcv);
+ UNBLOCK_INPUT;
+ IF_DEBUG (++ngcs);
return gc;
}
struct frame *f;
GC gc;
{
+ BLOCK_INPUT;
+ IF_DEBUG (xassert (--ngcs >= 0));
XFreeGC (FRAME_MAC_DISPLAY (f), gc);
+ UNBLOCK_INPUT;
}
#endif /* MAC_OS */
unsigned char *p = s;
for (p = s; *p; ++p)
- *p = tolower (*p);
+ /* On Mac OS X 10.3, tolower also converts non-ASCII characters
+ for some locales. */
+ if (isascii (*p))
+ *p = tolower (*p);
return s;
}
{
struct x_display_info *dpyinfo;
+#ifdef USE_FONT_BACKEND
+ if (! enable_font_backend)
+#endif /* USE_FONT_BACKEND */
/* Fonts are common for frames on one display, i.e. on
one X screen. */
for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
char *font_name;
int needs_overstrike;
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend)
+ abort ();
+#endif /* USE_FONT_BACKEND */
face->font_info_id = -1;
face->font = NULL;
face->font_name = NULL;
/* Return non-zero if COLOR_NAME is a shade of gray (or white or
- black) on frame F. The algorithm is taken from 20.2 faces.el. */
+ black) on frame F.
+
+ The criterion implemented here is not a terribly sophisticated one. */
static int
face_color_gray_p (f, color_name)
int gray_p;
if (defined_color (f, color_name, &color, 0))
- gray_p = ((abs (color.red - color.green)
- < max (color.red, color.green) / 20)
- && (abs (color.green - color.blue)
- < max (color.green, color.blue) / 20)
- && (abs (color.blue - color.red)
- < max (color.blue, color.red) / 20));
+ gray_p = (/* Any color sufficiently close to black counts as grey. */
+ (color.red < 5000 && color.green < 5000 && color.blue < 5000)
+ ||
+ ((abs (color.red - color.green)
+ < max (color.red, color.green) / 20)
+ && (abs (color.green - color.blue)
+ < max (color.green, color.blue) / 20)
+ && (abs (color.blue - color.red)
+ < max (color.blue, color.red) / 20)));
else
gray_p = 0;
#ifdef HAVE_WINDOW_SYSTEM
+#ifdef USE_FONT_BACKEND
+static INLINE Lisp_Object
+face_symbolic_value (table, dim, font_prop)
+ struct table_entry *table;
+ int dim;
+ Lisp_Object font_prop;
+{
+ struct table_entry *p;
+ char *s = SDATA (SYMBOL_NAME (font_prop));
+ int low, mid, high, cmp;
+
+ low = 0;
+ high = dim - 1;
+
+ while (low <= high)
+ {
+ mid = (low + high) / 2;
+ cmp = strcmp (table[mid].name, s);
+
+ if (cmp < 0)
+ low = mid + 1;
+ else if (cmp > 0)
+ high = mid - 1;
+ else
+ return *table[mid].symbol;
+ }
+
+ return Qnil;
+}
+
+static INLINE Lisp_Object
+face_symbolic_weight (weight)
+ Lisp_Object weight;
+{
+ return face_symbolic_value (weight_table, DIM (weight_table), weight);
+}
+
+static INLINE Lisp_Object
+face_symbolic_slant (slant)
+ Lisp_Object slant;
+{
+ return face_symbolic_value (slant_table, DIM (slant_table), slant);
+}
+
+static INLINE Lisp_Object
+face_symbolic_swidth (width)
+ Lisp_Object width;
+{
+ return face_symbolic_value (swidth_table, DIM (swidth_table), width);
+}
+#endif /* USE_FONT_BACKEND */
+
Lisp_Object
split_font_name_into_vector (fontname)
Lisp_Object fontname;
Lisp_Object *attrs;
{
xassert (UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
+ || IGNORE_DEFFACE_P (attrs[LFACE_FAMILY_INDEX])
|| STRINGP (attrs[LFACE_FAMILY_INDEX]));
xassert (UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
+ || IGNORE_DEFFACE_P (attrs[LFACE_SWIDTH_INDEX])
|| SYMBOLP (attrs[LFACE_SWIDTH_INDEX]));
xassert (UNSPECIFIEDP (attrs[LFACE_AVGWIDTH_INDEX])
+ || IGNORE_DEFFACE_P (attrs[LFACE_AVGWIDTH_INDEX])
|| INTEGERP (attrs[LFACE_AVGWIDTH_INDEX]));
xassert (UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
+ || IGNORE_DEFFACE_P (attrs[LFACE_HEIGHT_INDEX])
|| INTEGERP (attrs[LFACE_HEIGHT_INDEX])
|| FLOATP (attrs[LFACE_HEIGHT_INDEX])
|| FUNCTIONP (attrs[LFACE_HEIGHT_INDEX]));
xassert (UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX])
+ || IGNORE_DEFFACE_P (attrs[LFACE_WEIGHT_INDEX])
|| SYMBOLP (attrs[LFACE_WEIGHT_INDEX]));
xassert (UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX])
+ || IGNORE_DEFFACE_P (attrs[LFACE_SLANT_INDEX])
|| SYMBOLP (attrs[LFACE_SLANT_INDEX]));
xassert (UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX])
+ || IGNORE_DEFFACE_P (attrs[LFACE_UNDERLINE_INDEX])
|| SYMBOLP (attrs[LFACE_UNDERLINE_INDEX])
|| STRINGP (attrs[LFACE_UNDERLINE_INDEX]));
xassert (UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
+ || IGNORE_DEFFACE_P (attrs[LFACE_OVERLINE_INDEX])
|| SYMBOLP (attrs[LFACE_OVERLINE_INDEX])
|| STRINGP (attrs[LFACE_OVERLINE_INDEX]));
xassert (UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX])
+ || IGNORE_DEFFACE_P (attrs[LFACE_STRIKE_THROUGH_INDEX])
|| SYMBOLP (attrs[LFACE_STRIKE_THROUGH_INDEX])
|| STRINGP (attrs[LFACE_STRIKE_THROUGH_INDEX]));
xassert (UNSPECIFIEDP (attrs[LFACE_BOX_INDEX])
+ || IGNORE_DEFFACE_P (attrs[LFACE_BOX_INDEX])
|| SYMBOLP (attrs[LFACE_BOX_INDEX])
|| STRINGP (attrs[LFACE_BOX_INDEX])
|| INTEGERP (attrs[LFACE_BOX_INDEX])
|| CONSP (attrs[LFACE_BOX_INDEX]));
xassert (UNSPECIFIEDP (attrs[LFACE_INVERSE_INDEX])
+ || IGNORE_DEFFACE_P (attrs[LFACE_INVERSE_INDEX])
|| SYMBOLP (attrs[LFACE_INVERSE_INDEX]));
xassert (UNSPECIFIEDP (attrs[LFACE_FOREGROUND_INDEX])
+ || IGNORE_DEFFACE_P (attrs[LFACE_FOREGROUND_INDEX])
|| STRINGP (attrs[LFACE_FOREGROUND_INDEX]));
xassert (UNSPECIFIEDP (attrs[LFACE_BACKGROUND_INDEX])
+ || IGNORE_DEFFACE_P (attrs[LFACE_BACKGROUND_INDEX])
|| STRINGP (attrs[LFACE_BACKGROUND_INDEX]));
xassert (UNSPECIFIEDP (attrs[LFACE_INHERIT_INDEX])
+ || IGNORE_DEFFACE_P (attrs[LFACE_INHERIT_INDEX])
|| NILP (attrs[LFACE_INHERIT_INDEX])
|| SYMBOLP (attrs[LFACE_INHERIT_INDEX])
|| CONSP (attrs[LFACE_INHERIT_INDEX]));
#ifdef HAVE_WINDOW_SYSTEM
xassert (UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
+ || IGNORE_DEFFACE_P (attrs[LFACE_STIPPLE_INDEX])
|| SYMBOLP (attrs[LFACE_STIPPLE_INDEX])
|| !NILP (Fbitmap_spec_p (attrs[LFACE_STIPPLE_INDEX])));
xassert (UNSPECIFIEDP (attrs[LFACE_FONT_INDEX])
+ || IGNORE_DEFFACE_P (attrs[LFACE_FONT_INDEX])
|| NILP (attrs[LFACE_FONT_INDEX])
+#ifdef USE_FONT_BACKEND
+ || FONT_OBJECT_P (attrs[LFACE_FONT_INDEX])
+#endif /* USE_FONT_BACKEND */
|| STRINGP (attrs[LFACE_FONT_INDEX]));
xassert (UNSPECIFIEDP (attrs[LFACE_FONTSET_INDEX])
|| STRINGP (attrs[LFACE_FONTSET_INDEX]));
for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
if (i != LFACE_FONT_INDEX && i != LFACE_INHERIT_INDEX
&& i != LFACE_AVGWIDTH_INDEX && i != LFACE_FONTSET_INDEX)
- if (UNSPECIFIEDP (attrs[i])
+ if ((UNSPECIFIEDP (attrs[i]) || IGNORE_DEFFACE_P (attrs[i]))
#ifdef MAC_OS
/* MAC_TODO: No stipple support on Mac OS yet, this index is
always unspecified. */
/* If FONTNAME is actually a fontset name, get ASCII font name of it. */
fontset = fs_query_fontset (fontname, 0);
+
if (fontset > 0)
font_name = SDATA (fontset_ascii (fontset));
else if (fontset == 0)
return 1;
}
+#ifdef USE_FONT_BACKEND
+/* Set font-related attributes of Lisp face LFACE from FONT-OBJECT and
+ FONTSET. If FORCE_P is zero, set only unspecified attributes of
+ LFACE. The exceptions are `font' and `fontset' attributes. They
+ are set regardless of FORCE_P. */
+
+static void
+set_lface_from_font_and_fontset (f, lface, font_object, fontset, force_p)
+ struct frame *f;
+ Lisp_Object lface, font_object;
+ int fontset;
+ int force_p;
+{
+ struct font *font = XSAVE_VALUE (font_object)->pointer;
+ Lisp_Object entity = font->entity;
+ Lisp_Object val;
+
+ /* Set attributes only if unspecified, otherwise face defaults for
+ new frames would never take effect. If the font doesn't have a
+ specific property, set a normal value for that. */
+
+ if (force_p || UNSPECIFIEDP (LFACE_FAMILY (lface)))
+ {
+ Lisp_Object foundry = AREF (entity, FONT_FOUNDRY_INDEX);
+ Lisp_Object family = AREF (entity, FONT_FAMILY_INDEX);
+
+ if (! NILP (foundry))
+ {
+ if (! NILP (family))
+ val = concat3 (SYMBOL_NAME (foundry), build_string ("-"),
+ SYMBOL_NAME (family));
+ else
+ val = concat2 (SYMBOL_NAME (foundry), build_string ("-*"));
+ }
+ else
+ {
+ if (! NILP (family))
+ val = SYMBOL_NAME (family);
+ else
+ val = build_string ("*");
+ }
+ LFACE_FAMILY (lface) = val;
+ }
+
+ if (force_p || UNSPECIFIEDP (LFACE_HEIGHT (lface)))
+ {
+ int pt = pixel_point_size (f, font->pixel_size * 10);
+
+ xassert (pt > 0);
+ LFACE_HEIGHT (lface) = make_number (pt);
+ }
+
+ if (force_p || UNSPECIFIEDP (LFACE_AVGWIDTH (lface)))
+ LFACE_AVGWIDTH (lface) = make_number (font->font.average_width);
+
+ if (force_p || UNSPECIFIEDP (LFACE_WEIGHT (lface)))
+ {
+ Lisp_Object weight = font_symbolic_weight (entity);
+
+ val = NILP (weight) ? Qnormal : face_symbolic_weight (weight);
+ LFACE_WEIGHT (lface) = ! NILP (val) ? val : weight;
+ }
+ if (force_p || UNSPECIFIEDP (LFACE_SLANT (lface)))
+ {
+ Lisp_Object slant = font_symbolic_slant (entity);
+
+ val = NILP (slant) ? Qnormal : face_symbolic_slant (slant);
+ LFACE_SLANT (lface) = ! NILP (val) ? val : slant;
+ }
+ if (force_p || UNSPECIFIEDP (LFACE_SWIDTH (lface)))
+ {
+ Lisp_Object width = font_symbolic_width (entity);
+
+ val = NILP (width) ? Qnormal : face_symbolic_swidth (width);
+ LFACE_SWIDTH (lface) = ! NILP (val) ? val : width;
+ }
+
+ LFACE_FONT (lface) = font_object;
+ LFACE_FONTSET (lface) = fontset_name (fontset);
+}
+#endif /* USE_FONT_BACKEND */
+
#endif /* HAVE_WINDOW_SYSTEM */
DEFUN ("internal-lisp-face-p", Finternal_lisp_face_p,
Sinternal_lisp_face_p, 1, 2, 0,
doc: /* Return non-nil if FACE names a face.
-If optional second parameter FRAME is non-nil, check for the
+If optional second argument FRAME is non-nil, check for the
existence of a frame-local face with name FACE on that frame.
Otherwise check for the existence of a global face. */)
(face, frame)
/* Set lface to the Lisp attribute vector of FACE. */
if (EQ (frame, Qt))
- lface = lface_from_face_name (NULL, face, 1);
+ {
+ lface = lface_from_face_name (NULL, face, 1);
+
+ /* When updating face-new-frame-defaults, we put :ignore-defface
+ where the caller wants `unspecified'. This forces the frame
+ defaults to ignore the defface value. Otherwise, the defface
+ will take effect, which is generally not what is intended.
+ The value of that attribute will be inherited from some other
+ face during face merging. See internal_merge_in_global_face. */
+ if (UNSPECIFIEDP (value))
+ value = Qignore_defface;
+ }
else
{
if (NILP (frame))
if (EQ (attr, QCfamily))
{
- if (!UNSPECIFIEDP (value))
+ if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
{
CHECK_STRING (value);
if (SCHARS (value) == 0)
}
else if (EQ (attr, QCheight))
{
- if (!UNSPECIFIEDP (value))
+ if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
{
Lisp_Object test;
}
else if (EQ (attr, QCweight))
{
- if (!UNSPECIFIEDP (value))
+ if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
{
CHECK_SYMBOL (value);
if (face_numeric_weight (value) < 0)
}
else if (EQ (attr, QCslant))
{
- if (!UNSPECIFIEDP (value))
+ if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
{
CHECK_SYMBOL (value);
if (face_numeric_slant (value) < 0)
}
else if (EQ (attr, QCunderline))
{
- if (!UNSPECIFIEDP (value))
+ if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
if ((SYMBOLP (value)
&& !EQ (value, Qt)
&& !EQ (value, Qnil))
}
else if (EQ (attr, QCoverline))
{
- if (!UNSPECIFIEDP (value))
+ if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
if ((SYMBOLP (value)
&& !EQ (value, Qt)
&& !EQ (value, Qnil))
}
else if (EQ (attr, QCstrike_through))
{
- if (!UNSPECIFIEDP (value))
+ if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
if ((SYMBOLP (value)
&& !EQ (value, Qt)
&& !EQ (value, Qnil))
if (EQ (value, Qt))
value = make_number (1);
- if (UNSPECIFIEDP (value))
+ if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value))
valid_p = 1;
else if (NILP (value))
valid_p = 1;
else if (EQ (attr, QCinverse_video)
|| EQ (attr, QCreverse_video))
{
- if (!UNSPECIFIEDP (value))
+ if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
{
CHECK_SYMBOL (value);
if (!EQ (value, Qt) && !NILP (value))
}
else if (EQ (attr, QCforeground))
{
- if (!UNSPECIFIEDP (value))
+ if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
{
/* Don't check for valid color names here because it depends
on the frame (display) whether the color will be valid
}
else if (EQ (attr, QCbackground))
{
- if (!UNSPECIFIEDP (value))
+ if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
{
/* Don't check for valid color names here because it depends
on the frame (display) whether the color will be valid
else if (EQ (attr, QCstipple))
{
#ifdef HAVE_X_WINDOWS
- if (!UNSPECIFIEDP (value)
+ if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)
&& !NILP (value)
&& NILP (Fbitmap_spec_p (value)))
signal_error ("Invalid stipple attribute", value);
}
else if (EQ (attr, QCwidth))
{
- if (!UNSPECIFIEDP (value))
+ if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
{
CHECK_SYMBOL (value);
if (face_numeric_swidth (value) < 0)
else
f = check_x_frame (frame);
- if (!UNSPECIFIEDP (value))
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend
+ && !UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
+ {
+ int fontset;
+
+ if (EQ (attr, QCfontset))
+ {
+ Lisp_Object fontset_name = Fquery_fontset (value, Qnil);
+
+ if (NILP (fontset_name))
+ signal_error ("Invalid fontset name", value);
+ LFACE_FONTSET (lface) = value;
+ }
+ else
+ {
+ Lisp_Object font_object;
+
+ if (FONT_OBJECT_P (value))
+ {
+ font_object = value;
+ fontset = FRAME_FONTSET (f);
+ }
+ else
+ {
+ CHECK_STRING (value);
+
+ fontset = fs_query_fontset (value, 0);
+ if (fontset >= 0)
+ value = fontset_ascii (fontset);
+ else
+ fontset = FRAME_FONTSET (f);
+ font_object = font_open_by_name (f, SDATA (value));
+ if (NILP (font_object))
+ signal_error ("Invalid font", value);
+ }
+ set_lface_from_font_and_fontset (f, lface, font_object,
+ fontset, 1);
+ }
+ }
+ else
+#endif /* USE_FONT_BACKEND */
+ if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
{
CHECK_STRING (value);
signal_error ("Invalid face attribute name", attr);
if (font_related_attr_p
- && !UNSPECIFIEDP (value))
+ && !UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
/* If a font-related attribute other than QCfont is specified, the
original `font' attribute nor that of default face is useless
to determine a new font. Thus, we set it to nil so that font
++windows_or_buffers_changed;
}
- if (!UNSPECIFIEDP (value)
+ if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)
&& NILP (Fequal (old_value, value)))
{
Lisp_Object param;
if (STRINGP (LFACE_FONT (lface)))
font_name = LFACE_FONT (lface);
+#ifdef USE_FONT_BACKEND
+ else if (enable_font_backend)
+ {
+ /* We set FONT_NAME to a font-object. */
+ if (FONT_OBJECT_P (LFACE_FONT (lface)))
+ font_name = LFACE_FONT (lface);
+ else
+ {
+ font_name = font_find_for_lface (f, &AREF (lface, 0), Qnil);
+ if (NILP (font_name))
+ error ("No font matches the specified attribute");
+ font_name = font_open_for_lface (f, &AREF (lface, 0), font_name);
+ if (NILP (font_name))
+ error ("No font matches the specified attribute");
+ }
+ }
+#endif
else
{
/* Choose a font name that reflects LFACE's attributes and has
if (SYMBOLP (boolean_value))
value = boolean_value;
}
- else if (EQ (attr, QCbox))
+ else if (EQ (attr, QCbox) || EQ (attr, QCinherit))
value = Fcar (Fread_from_string (value, Qnil, Qnil));
return Finternal_set_lisp_face_attribute (face, attr, value, frame);
#ifdef USE_MOTIF
const char *suffix = "List";
Bool motif = True;
+#else
+#if defined HAVE_X_I18N
+
+ const char *suffix = "Set";
#else
const char *suffix = "";
+#endif
Bool motif = False;
#endif
#if defined HAVE_X_I18N
(attribute, value)
Lisp_Object attribute, value;
{
- if (EQ (value, Qunspecified))
+ if (EQ (value, Qunspecified) || (EQ (value, Qignore_defface)))
return Qt;
else if (EQ (attribute, QCheight))
return INTEGERP (value) ? Qnil : Qt;
(attribute, value1, value2)
Lisp_Object attribute, value1, value2;
{
- if (EQ (value1, Qunspecified))
+ if (EQ (value1, Qunspecified) || EQ (value1, Qignore_defface))
return value2;
else if (EQ (attribute, QCheight))
return merge_face_heights (value1, value2, value1);
else
signal_error ("Invalid face attribute name", keyword);
+ if (IGNORE_DEFFACE_P (value))
+ return Qunspecified;
+
return value;
}
gvec = XVECTOR (global_lface)->contents;
for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
if (! UNSPECIFIEDP (gvec[i]))
- lvec[i] = gvec[i];
+ {
+ if (IGNORE_DEFFACE_P (gvec[i]))
+ lvec[i] = Qunspecified;
+ else
+ lvec[i] = gvec[i];
+ }
return Qnil;
}
free_face_fontset (f, face);
if (face->gc)
{
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend && face->font_info)
+ font_done_for_face (f, face);
+#endif /* USE_FONT_BACKEND */
x_free_gc (f, face->gc);
face->gc = 0;
}
}
#endif
face->gc = x_create_gc (f, mask, &xgcv);
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend && face->font)
+ font_prepare_for_face (f, face);
+#endif /* USE_FONT_BACKEND */
UNBLOCK_INPUT;
}
#endif /* HAVE_WINDOW_SYSTEM */
struct face *face = c->faces_by_id[i];
if (face && face->gc)
{
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend && face->font_info)
+ font_done_for_face (c->f, face);
+#endif /* USE_FONT_BACKEND */
x_free_gc (c->f, face->gc);
face->gc = 0;
}
return face->id;
}
+
+#ifdef USE_FONT_BACKEND
+int
+face_for_font (f, font, base_face)
+ struct frame *f;
+ struct font *font;
+ struct face *base_face;
+{
+ struct face_cache *cache = FRAME_FACE_CACHE (f);
+ unsigned hash;
+ int i;
+ struct face *face;
+
+ xassert (cache != NULL);
+ base_face = base_face->ascii_face;
+ hash = lface_hash (base_face->lface);
+ i = hash % FACE_CACHE_BUCKETS_SIZE;
+
+ for (face = cache->buckets[i]; face; face = face->next)
+ {
+ if (face->ascii_face == face)
+ continue;
+ if (face->ascii_face == base_face
+ && face->font_info == (struct font_info *) font)
+ return face->id;
+ }
+
+ /* If not found, realize a new face. */
+ face = realize_non_ascii_face (f, -1, base_face);
+ face->font = font->font.font;
+ face->font_info = (struct font_info *) font;
+ face->font_info_id = 0;
+ face->font_name = font->font.full_name;
+ return face->id;
+}
+#endif /* USE_FONT_BACKEND */
+
#endif /* HAVE_WINDOW_SYSTEM */
/* Return the face id of the realized face for named face SYMBOL on
free_all_realized_faces (Qnil);
}
+#ifdef USE_FONT_BACKEND
+ font_update_sort_order (font_sort_order);
+#endif /* USE_FONT_BACKEND */
+
return Qnil;
}
{
int i;
+ /* Any font is better than no font. */
+ if (! font1)
+ return 0;
+ if (! font2)
+ return 1;
+
for (i = 0; i < DIM (font_sort_order); ++i)
{
int xlfd_idx = font_sort_order[i];
if (needs_overstrike)
*needs_overstrike = 0;
- /* Start with the first non-scalable font in the list. */
- for (i = 0; i < nfonts; ++i)
- if (!font_scalable_p (fonts + i))
- break;
+ best = NULL;
/* Find the best match among the non-scalable fonts. */
- if (i < nfonts)
- {
- best = fonts + i;
-
- for (i = 1; i < nfonts; ++i)
- if (!font_scalable_p (fonts + i)
- && better_font_p (specified, fonts + i, best, 1, avgwidth))
- {
- best = fonts + i;
+ for (i = 0; i < nfonts; ++i)
+ if (!font_scalable_p (fonts + i)
+ && better_font_p (specified, fonts + i, best, 1, avgwidth))
+ {
+ best = fonts + i;
- exact_p = exact_face_match_p (specified, best, avgwidth);
- if (exact_p)
- break;
- }
- }
- else
- best = NULL;
+ exact_p = exact_face_match_p (specified, best, avgwidth);
+ if (exact_p)
+ break;
+ }
/* Unless we found an exact match among non-scalable fonts, see if
we can find a better match among scalable fonts. */
for (i = 0; i < nfonts; ++i)
if (font_scalable_p (fonts + i))
{
- if (best == NULL
- || better_font_p (specified, fonts + i, best, 0, 0)
+ if (better_font_p (specified, fonts + i, best, 0, 0)
|| (!non_scalable_has_exact_height_p
&& !better_font_p (specified, best, fonts + i, 0, 0)))
{
best = fonts + i;
}
}
+ }
- if (needs_overstrike)
- {
- enum xlfd_weight want_weight = specified[XLFD_WEIGHT];
- enum xlfd_weight got_weight = best->numeric[XLFD_WEIGHT];
+ /* We should have found SOME font. */
+ if (best == NULL)
+ abort ();
- if (want_weight > XLFD_WEIGHT_MEDIUM && want_weight > got_weight)
- {
- /* We want a bold font, but didn't get one; try to use
- overstriking instead to simulate bold-face. However,
- don't overstrike an already-bold fontn unless the
- desired weight grossly exceeds the available weight. */
- if (got_weight > XLFD_WEIGHT_MEDIUM)
- *needs_overstrike = (got_weight - want_weight) > 2;
- else
- *needs_overstrike = 1;
- }
+ if (! exact_p && needs_overstrike)
+ {
+ enum xlfd_weight want_weight = specified[XLFD_WEIGHT];
+ enum xlfd_weight got_weight = best->numeric[XLFD_WEIGHT];
+
+ if (want_weight > XLFD_WEIGHT_MEDIUM && want_weight > got_weight)
+ {
+ /* We want a bold font, but didn't get one; try to use
+ overstriking instead to simulate bold-face. However,
+ don't overstrike an already-bold fontn unless the
+ desired weight grossly exceeds the available weight. */
+ if (got_weight > XLFD_WEIGHT_MEDIUM)
+ *needs_overstrike = (got_weight - want_weight) > 2;
+ else
+ *needs_overstrike = 1;
}
}
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (f))
{
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend)
+ {
+ frame_font = font_find_object (FRAME_FONT_OBJECT (f));
+ xassert (FONT_OBJECT_P (frame_font));
+ set_lface_from_font_and_fontset (f, lface, frame_font,
+ FRAME_FONTSET (f),
+ f->default_face_done_p);
+ }
+ else
+ {
+#endif /* USE_FONT_BACKEND */
/* Set frame_font to the value of the `font' frame parameter. */
frame_font = Fassq (Qfont, f->param_alist);
xassert (CONSP (frame_font) && STRINGP (XCDR (frame_font)));
frame_font = XCDR (frame_font);
set_lface_from_font_name (f, lface, frame_font,
f->default_face_done_p, 1);
+#ifdef USE_FONT_BACKEND
+ }
+#endif /* USE_FONT_BACKEND */
f->default_face_done_p = 1;
}
#endif /* HAVE_WINDOW_SYSTEM */
check_lface (lface);
bcopy (XVECTOR (lface)->contents, attrs, sizeof attrs);
face = realize_face (c, attrs, DEFAULT_FACE_ID);
+
+#ifdef HAVE_WINDOW_SYSTEM
+#ifdef HAVE_X_WINDOWS
+ if (face->font != FRAME_FONT (f))
+ /* As the font specified for the frame was not acceptable as a
+ font for the default face (perhaps because auto-scaled fonts
+ are rejected), we must adjust the frame font. */
+ x_set_font (f, build_string (face->font_name), Qnil);
+#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
return 1;
}
{
face->font = default_face->font;
face->font_info_id = default_face->font_info_id;
+#ifdef USE_FONT_BACKEND
+ face->font_info = default_face->font_info;
+#endif /* USE_FONT_BACKEND */
face->font_name = default_face->font_name;
face->fontset
= make_fontset_for_ascii_face (f, default_face->fontset, face);
fontset = default_face->fontset;
if (fontset == -1)
abort ();
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend)
+ font_load_for_face (f, face);
+ else
+#endif /* USE_FONT_BACKEND */
load_face_font (f, face);
- face->fontset = make_fontset_for_ascii_face (f, fontset, face);
+ if (face->font)
+ face->fontset = make_fontset_for_ascii_face (f, fontset, face);
+ else
+ face->fontset = -1;
}
/* Load colors, and set remaining attributes. */
staticpro (&Qforeground_color);
Qunspecified = intern ("unspecified");
staticpro (&Qunspecified);
+ Qignore_defface = intern (":ignore-defface");
+ staticpro (&Qignore_defface);
Qface_alias = intern ("face-alias");
staticpro (&Qface_alias);