extern struct font_driver w32font_driver;
Lisp_Object Qgdi;
+Lisp_Object Quniscribe;
+static Lisp_Object QCformat;
static Lisp_Object Qmonospace, Qsansserif, Qmono, Qsans, Qsans_serif;
static Lisp_Object Qserif, Qscript, Qdecorative;
static Lisp_Object Qraster, Qoutline, Qunknown;
static Lisp_Object font_supported_scripts P_ ((FONTSIGNATURE * sig));
static int w32font_full_name P_ ((LOGFONT * font, Lisp_Object font_obj,
int pixel_size, char *name, int nbytes));
-
-/* From old font code in w32fns.c */
-char * w32_to_x_charset P_ ((int charset, char * matching));
+static void recompute_cached_metrics P_ ((HDC dc, struct font * font));
static Lisp_Object w32_registry P_ ((LONG w32_charset));
style variations if the font name is not specified. */
static void list_all_matching_fonts P_ ((struct font_callback_data *match));
+/* From old font code in w32fns.c */
+char * w32_to_x_charset P_ ((int charset, char * matching));
-/* MingW headers only define this when _WIN32_WINNT >= 0x0500, but we
- target older versions. */
-#ifndef GGI_MARK_NONEXISTING_GLYPHS
-#define GGI_MARK_NONEXISTING_GLYPHS 1
-#endif
static int
memq_no_quit (elt, list)
script = CHAR_TABLE_REF (Vchar_script_table, c);
- return (memq_no_quit (script, supported_scripts)) ? 1 : 0;
+ return (memq_no_quit (script, supported_scripts)) ? -1 : 0;
}
/* w32 implementation of encode_char for font backend.
Return a glyph code of FONT for characer C (Unicode code point).
If FONT doesn't have such a glyph, return FONT_INVALID_CODE. */
-unsigned
+static unsigned
w32font_encode_char (font, c)
struct font *font;
int c;
{
- /* Avoid unneccesary conversion - all the Win32 APIs will take a unicode
- character. */
- return c;
+ struct frame *f;
+ HDC dc;
+ HFONT old_font;
+ DWORD retval;
+ GCP_RESULTSW result;
+ wchar_t in[2];
+ wchar_t out[2];
+ int len;
+ struct w32font_info *w32_font = (struct w32font_info *) font;
+
+ /* If glyph indexing is not working for this font, just return the
+ unicode code-point. */
+ if (!w32_font->glyph_idx)
+ return c;
+
+ if (c > 0xFFFF)
+ {
+ /* TODO: Encode as surrogate pair and lookup the glyph. */
+ return FONT_INVALID_CODE;
+ }
+ else
+ {
+ in[0] = (wchar_t) c;
+ len = 1;
+ }
+
+ bzero (&result, sizeof (result));
+ result.lStructSize = sizeof (result);
+ result.lpGlyphs = out;
+ result.nGlyphs = 2;
+
+ f = XFRAME (selected_frame);
+
+ dc = get_frame_dc (f);
+ old_font = SelectObject (dc, ((W32FontStruct *) (font->font.font))->hfont);
+
+ retval = GetCharacterPlacementW (dc, in, len, 0, &result, 0);
+
+ SelectObject (dc, old_font);
+ release_frame_dc (f, dc);
+
+ if (retval)
+ {
+ if (result.nGlyphs != 1 || !result.lpGlyphs[0])
+ return FONT_INVALID_CODE;
+ return result.lpGlyphs[0];
+ }
+ else
+ {
+ int i;
+ /* Mark this font as not supporting glyph indices. This can happen
+ on Windows9x, and maybe with non-Truetype fonts on NT etc. */
+ w32_font->glyph_idx = 0;
+ recompute_cached_metrics (dc, font);
+
+ return c;
+ }
}
/* w32 implementation of text_extents for font backend.
{
GLYPHMETRICS gm;
MAT2 transform;
+ struct w32font_info *w32_font = (struct w32font_info *) font;
/* Set transform to the identity matrix. */
bzero (&transform, sizeof (transform));
for (i = 0; i < nglyphs; i++)
{
- if (*(code + i) < 128 && *(code + i) > 32)
+ if (*(code + i) < 128)
{
/* Use cached metrics for ASCII. */
struct font_metrics *char_metric
- = &((struct w32font_info *)font)->ascii_metrics[*(code+i)-32];
+ = &w32_font->ascii_metrics[*(code+i)];
/* If we couldn't get metrics when caching, use fallback. */
if (char_metric->width == 0)
old_font = SelectObject (dc, ((W32FontStruct *)
(font->font.font))->hfont);
}
- if (GetGlyphOutlineW (dc, *(code + i), GGO_METRICS, &gm, 0,
- NULL, &transform) != GDI_ERROR)
+ if (GetGlyphOutlineW (dc, *(code + i),
+ GGO_METRICS
+ | w32_font->glyph_idx
+ ? GGO_GLYPH_INDEX : 0,
+ &gm, 0, NULL, &transform) != GDI_ERROR)
{
int new_val = metrics->width + gm.gmBlackBoxX
+ gm.gmptGlyphOrigin.x;
}
else
{
+ if (w32_font->glyph_idx)
+ {
+ /* Disable glyph indexing for this font, as we can't
+ handle the metrics. Abort this run, our recovery
+ strategies rely on having unicode code points here.
+ This will cause a glitch in display, but in practice,
+ any problems should be caught when initialising the
+ metrics cache. */
+ w32_font->glyph_idx = 0;
+ recompute_cached_metrics (dc, font);
+ SelectObject (dc, old_font);
+ release_frame_dc (f, dc);
+ return 0;
+ }
/* Rely on an estimate based on the overall font metrics. */
break;
}
struct glyph_string *s;
int from, to, x, y, with_background;
{
- UINT options = 0;
+ UINT options;
HRGN orig_clip;
+ struct w32font_info *w32font = (struct w32font_info *) s->face->font_info;
+
+ options = w32font->glyph_idx;
/* Save clip region for later restoration. */
GetClipRgn(s->hdc, orig_clip);
GetTextMetrics (dc, &w32_font->metrics);
/* Cache ASCII metrics. */
- {
- GLYPHMETRICS gm;
- MAT2 transform;
- int i;
-
- bzero (&transform, sizeof (transform));
- transform.eM11.value = 1;
- transform.eM22.value = 1;
-
- for (i = 0; i < 96; i++)
- {
- struct font_metrics* char_metric = &w32_font->ascii_metrics[i];
-
- if (GetGlyphOutlineW (dc, i + 32, GGO_METRICS, &gm, 0,
- NULL, &transform) != GDI_ERROR)
- {
- char_metric->lbearing = -gm.gmptGlyphOrigin.x;
- char_metric->rbearing = gm.gmBlackBoxX + gm.gmptGlyphOrigin.x;
- char_metric->width = gm.gmCellIncX;
- char_metric->ascent = -gm.gmptGlyphOrigin.y;
- char_metric->descent = gm.gmBlackBoxY + gm.gmptGlyphOrigin.y;
- }
- else
- char_metric->width = 0;
- }
- }
+ recompute_cached_metrics (dc, font);
SelectObject (dc, old_font);
release_frame_dc (f, dc);
+
+ w32_font->glyph_idx = ETO_GLYPH_INDEX;
+
/* W32FontStruct - we should get rid of this, and use the w32font_info
struct for any W32 specific fields. font->font.font can then be hfont. */
font->font.font = xmalloc (sizeof (W32FontStruct));
font->entity = font_entity;
font->pixel_size = size;
font->driver = &w32font_driver;
- font->format = Qgdi;
+ /* Use format cached during list, as the information we have access to
+ here is incomplete. */
+ extra = AREF (font_entity, FONT_EXTRA_INDEX);
+ if (CONSP (extra))
+ {
+ val = assq_no_quit (QCformat, extra);
+ if (CONSP (val))
+ font->format = XCDR (val);
+ else
+ font->format = Qunknown;
+ }
+ else
+ font->format = Qunknown;
+
font->file_name = NULL;
font->encoding_charset = -1;
font->repertory_charset = -1;
/* Convert an enumerated Windows font to an Emacs font entity. */
static Lisp_Object
w32_enumfont_pattern_entity (frame, logical_font, physical_font,
- font_type, requested_font)
+ font_type, requested_font, backend)
Lisp_Object frame;
ENUMLOGFONTEX *logical_font;
NEWTEXTMETRICEX *physical_font;
DWORD font_type;
LOGFONT *requested_font;
+ Lisp_Object backend;
{
Lisp_Object entity, tem;
LOGFONT *lf = (LOGFONT*) logical_font;
BYTE generic_type;
+ BYTE full_type = physical_font->ntmTm.ntmFlags;
entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil);
- ASET (entity, FONT_TYPE_INDEX, Qgdi);
+ ASET (entity, FONT_TYPE_INDEX, backend);
ASET (entity, FONT_FRAME_INDEX, frame);
ASET (entity, FONT_REGISTRY_INDEX, w32_registry (lf->lfCharSet));
ASET (entity, FONT_OBJLIST_INDEX, Qnil);
font_supported_scripts (&physical_font->ntmFontSig));
}
+ /* This information is not fully available when opening fonts, so
+ save it here. Only Windows 2000 and later return information
+ about opentype and type1 fonts, so need a fallback for detecting
+ truetype so that this information is not any worse than we could
+ have obtained later. */
+ if (full_type & NTM_TT_OPENTYPE || font_type & TRUETYPE_FONTTYPE)
+ tem = intern ("truetype");
+ else if (full_type & NTM_TYPE1)
+ tem = intern ("type1");
+ else if (full_type & NTM_PS_OPENTYPE)
+ tem = intern ("postscript");
+ else if (font_type & RASTER_FONTTYPE)
+ tem = intern ("w32bitmap");
+ else
+ tem = intern ("w32vector");
+
+ font_put_extra (entity, QCformat, tem);
+
return entity;
}
Lisp_Object entity
= w32_enumfont_pattern_entity (match_data->frame, logical_font,
physical_font, font_type,
- &match_data->pattern);
+ &match_data->pattern,
+ match_data->opentype_only
+ ? Quniscribe : Qgdi);
if (!NILP (entity))
match_data->list = Fcons (entity, match_data->list);
}
return (p - name);
}
+
+static void
+recompute_cached_metrics (dc, font)
+ HDC dc;
+ struct font *font;
+{
+ GLYPHMETRICS gm;
+ MAT2 transform;
+ int i;
+ struct w32font_info *w32_font;
+
+ bzero (&transform, sizeof (transform));
+ transform.eM11.value = 1;
+ transform.eM22.value = 1;
+
+ for (i = 0; i < 128; i++)
+ {
+ struct font_metrics* char_metric = &w32_font->ascii_metrics[i];
+
+ if (GetGlyphOutlineW (dc, i + 32, GGO_METRICS
+ | w32_font->glyph_idx ? GGO_GLYPH_INDEX : 0,
+ &gm, 0, NULL, &transform) != GDI_ERROR)
+ {
+ char_metric->lbearing = -gm.gmptGlyphOrigin.x;
+ char_metric->rbearing = gm.gmBlackBoxX + gm.gmptGlyphOrigin.x;
+ char_metric->width = gm.gmCellIncX;
+ char_metric->ascent = -gm.gmptGlyphOrigin.y;
+ char_metric->descent = gm.gmBlackBoxY + gm.gmptGlyphOrigin.y;
+ }
+ else
+ char_metric->width = 0;
+ }
+}
+
struct font_driver w32font_driver =
{
0, /* Qgdi */
syms_of_w32font ()
{
DEFSYM (Qgdi, "gdi");
+ DEFSYM (Quniscribe, "uniscribe");
+ DEFSYM (QCformat, ":format");
/* Generic font families. */
DEFSYM (Qmonospace, "monospace");