Mercurial > emacs
changeset 92409:8171649adf8a
(Quniscribe, QCformat): New symbols.
(syms_of_w32font): Define them.
(w32font_has_char): Indicate uncertainty.
(w32font_encode_char): Encode as glyph point. Make static.
(recompute_cached_metrics): New function.
(w32font_open_internal): Use it. Set font to use glyph points
initially. Set format based on type of font.
(w32font_text_extents, w32font_draw): Optionally use glyph points.
(w32_enumfont_pattern_entity): Accept backend arg. Set type based
on it. Set format based on information available here.
(add_font_entity_to_list): Identify backend based on opentype_only.
author | Jason Rumney <jasonr@gnu.org> |
---|---|
date | Mon, 03 Mar 2008 00:31:18 +0000 |
parents | a371504924ef |
children | 9fb51b883c0c |
files | src/w32font.c |
diffstat | 1 files changed, 169 insertions(+), 48 deletions(-) [+] |
line wrap: on
line diff
--- a/src/w32font.c Mon Mar 03 00:31:03 2008 +0000 +++ b/src/w32font.c Mon Mar 03 00:31:18 2008 +0000 @@ -45,6 +45,8 @@ 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; @@ -78,9 +80,7 @@ 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)); @@ -117,12 +117,9 @@ 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) @@ -263,20 +260,74 @@ 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. @@ -308,6 +359,7 @@ { GLYPHMETRICS gm; MAT2 transform; + struct w32font_info *w32_font = (struct w32font_info *) font; /* Set transform to the identity matrix. */ bzero (&transform, sizeof (transform)); @@ -320,11 +372,11 @@ 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) @@ -346,8 +398,11 @@ 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; @@ -362,6 +417,20 @@ } 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; } @@ -449,8 +518,11 @@ 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); @@ -709,34 +781,12 @@ 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)); @@ -790,7 +840,20 @@ 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; @@ -859,20 +922,22 @@ /* 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); @@ -939,6 +1004,24 @@ 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; } @@ -1166,7 +1249,9 @@ 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); } @@ -1615,6 +1700,40 @@ 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 */ @@ -1650,6 +1769,8 @@ syms_of_w32font () { DEFSYM (Qgdi, "gdi"); + DEFSYM (Quniscribe, "uniscribe"); + DEFSYM (QCformat, ":format"); /* Generic font families. */ DEFSYM (Qmonospace, "monospace");