changeset 93598:6b92cdd67bfb

(Qbalinese, Qbuginese, Qbuhid, Qcuneiform, Qcypriot) (Qdeseret, Qglagolitic, Qgothic, Qhanunoo, Qkharoshthi) (Qlimbu, Qlinear_b, Qold_italic, Qold_persian, Qosmanya) (Qphags_pa, Qphoenician, Qshavian, Qsyloti_nagri) (Qtagalog, Qtagbanwa, Qtai_le, Qtifinagh, Qugaritic) (Qphonetic): New symbols. (syms_of_w32font): Initialize them. (font_supported_scripts): Use them. (w32font_list_family): List all charsets. (w32font_text_extents, recompute_cached_metrics): Fix metric calculations. (w32_enumfont_pattern_entity): Make full_type a DWORD. Give opentype fonts their own format. (font_matches_spec): New arguments backend and logfont. Handle :otf spec for uniscribe backend. (add_font_entity_to_list): Match truetype fonts in uniscribe backend. (fill_in_logfont): Use DEFAULT_CHARSET when charset not supplied.
author Jason Rumney <jasonr@gnu.org>
date Thu, 03 Apr 2008 13:10:57 +0000
parents 0dac12128e1c
children a67af10a545c
files src/w32font.c
diffstat 1 files changed, 134 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/src/w32font.c	Thu Apr 03 12:37:44 2008 +0000
+++ b/src/w32font.c	Thu Apr 03 13:10:57 2008 +0000
@@ -55,7 +55,7 @@
 static Lisp_Object Qraster, Qoutline, Qunknown;
 
 /* antialiasing  */
-extern Lisp_Object QCantialias; /* defined in font.c  */
+extern Lisp_Object QCantialias, QCotf, QClanguage; /* defined in font.c  */
 extern Lisp_Object Qnone; /* reuse from w32fns.c  */
 static Lisp_Object Qstandard, Qsubpixel, Qnatural;
 
@@ -70,6 +70,14 @@
 static Lisp_Object Qideographic_description, Qcjk_misc, Qkana, Qbopomofo;
 static Lisp_Object Qkanbun, Qyi, Qbyzantine_musical_symbol;
 static Lisp_Object Qmusical_symbol, Qmathematical;
+/* Not defined in characters.el, but referenced in fontset.el.  */
+static Lisp_Object Qbalinese, Qbuginese, Qbuhid, Qcuneiform, Qcypriot;
+static Lisp_Object Qdeseret, Qglagolitic, Qgothic, Qhanunoo, Qkharoshthi;
+static Lisp_Object Qlimbu, Qlinear_b, Qold_italic, Qold_persian, Qosmanya;
+static Lisp_Object Qphags_pa, Qphoenician, Qshavian, Qsyloti_nagri;
+static Lisp_Object Qtagalog, Qtagbanwa, Qtai_le, Qtifinagh, Qugaritic;
+/* Only defined here, but useful for distinguishing IPA capable fonts.  */
+static Lisp_Object Qphonetic;
 
 /* Font spacing symbols - defined in font.c.  */
 extern Lisp_Object Qc, Qp, Qm;
@@ -180,6 +188,7 @@
   FRAME_PTR f = XFRAME (frame);
 
   bzero (&font_match_pattern, sizeof (font_match_pattern));
+  font_match_pattern.lfCharSet = DEFAULT_CHARSET;
 
   dc = get_frame_dc (f);
 
@@ -385,8 +394,8 @@
               if (char_metric->width == 0)
                 break;
 
-              metrics->lbearing = max (metrics->lbearing,
-                                       char_metric->lbearing - metrics->width);
+              metrics->lbearing = min (metrics->lbearing,
+                                       metrics->width + char_metric->lbearing);
               metrics->rbearing = max (metrics->rbearing,
                                        metrics->width + char_metric->rbearing);
               metrics->width += char_metric->width;
@@ -410,12 +419,13 @@
                   int new_val = metrics->width + gm.gmBlackBoxX
                     + gm.gmptGlyphOrigin.x;
                   metrics->rbearing = max (metrics->rbearing, new_val);
-                  new_val = -gm.gmptGlyphOrigin.x - metrics->width;
-                  metrics->lbearing = max (metrics->lbearing, new_val);
+                  new_val = metrics->width + gm.gmptGlyphOrigin.x;
+                  metrics->lbearing = min (metrics->lbearing, new_val);
                   metrics->width += gm.gmCellIncX;
-                  new_val = -gm.gmptGlyphOrigin.y;
+                  new_val = gm.gmBlackBoxY;
                   metrics->ascent = max (metrics->ascent, new_val);
-                  new_val = gm.gmBlackBoxY + gm.gmptGlyphOrigin.y;
+                  new_val = (gm.gmCellIncY - gm.gmptGlyphOrigin.y
+			     - gm.gmBlackBoxY);
                   metrics->descent = max (metrics->descent, new_val);
                 }
               else
@@ -454,6 +464,9 @@
         }
     }
 
+  /* For non-truetype fonts, GetGlyphOutlineW is not supported, so
+     fallback on other methods that will at least give some of the metric
+     information.  */
   for (i = 0; i < nglyphs; i++)
     {
       if (code[i] < 0x10000)
@@ -477,6 +490,8 @@
       total_width = size.cx;
     }
 
+  /* On 95/98/ME, only some unicode functions are available, so fallback
+     on doing a dummy draw to find the total width.  */
   if (!total_width)
     {
       RECT rect;
@@ -486,6 +501,7 @@
       total_width = rect.right;
     }
 
+  /* Give our best estimate of the metrics, based on what we know.  */
   if (metrics)
     {
       metrics->width = total_width;
@@ -937,7 +953,7 @@
   Lisp_Object entity, tem;
   LOGFONT *lf = (LOGFONT*) logical_font;
   BYTE generic_type;
-  BYTE full_type = physical_font->ntmTm.ntmFlags;
+  DWORD full_type = physical_font->ntmTm.ntmFlags;
 
   entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil);
 
@@ -1013,12 +1029,14 @@
      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)
+  if (EQ (backend, Quniscribe) && (full_type & NTMFLAGS_OPENTYPE))
+    tem = intern ("opentype");
+  else if (font_type & TRUETYPE_FONTTYPE)
     tem = intern ("truetype");
+  else if (full_type & NTM_PS_OPENTYPE)
+    tem = intern ("postscript");
   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
@@ -1070,10 +1088,12 @@
 }
 
 static int
-font_matches_spec (type, font, spec)
+font_matches_spec (type, font, spec, backend, logfont)
      DWORD type;
      NEWTEXTMETRICEX *font;
      Lisp_Object spec;
+     Lisp_Object backend;
+     LOGFONT *logfont;
 {
   Lisp_Object extra, val;
 
@@ -1210,10 +1230,22 @@
                         return 0;
                     }
                   else
-                    /* Other scripts unlikely to be handled.  */
+                    /* Other scripts unlikely to be handled by non-truetype
+		       fonts.  */
                     return 0;
                 }
             }
+          else if (EQ (key, QCotf) && CONSP (val))
+	    {
+	      /* OTF features only supported by the uniscribe backend.  */
+	      if (EQ (backend, Quniscribe))
+		{
+		  if (!uniscribe_check_otf (logfont, val))
+		    return 0;
+		}
+	      else
+		return 0;
+	    }
         }
     }
   return 1;
@@ -1260,12 +1292,15 @@
 {
   struct font_callback_data *match_data
     = (struct font_callback_data *) lParam;
+  Lisp_Object backend = match_data->opentype_only ? Quniscribe : Qgdi;
 
   if ((!match_data->opentype_only
-       || (physical_font->ntmTm.ntmFlags & NTMFLAGS_OPENTYPE))
+       || (physical_font->ntmTm.ntmFlags & NTMFLAGS_OPENTYPE)
+       || (font_type & TRUETYPE_FONTTYPE))
       && logfonts_match (&logical_font->elfLogFont, &match_data->pattern)
       && font_matches_spec (font_type, physical_font,
-                            match_data->orig_font_spec)
+                            match_data->orig_font_spec, backend,
+			    &logical_font->elfLogFont)
       && w32font_coverage_ok (&physical_font->ntmFontSig,
                               match_data->pattern.lfCharSet)
       /* Avoid substitutions involving raster fonts (eg Helv -> MS Sans Serif)
@@ -1283,8 +1318,7 @@
         = w32_enumfont_pattern_entity (match_data->frame, logical_font,
                                        physical_font, font_type,
                                        &match_data->pattern,
-                                       match_data->opentype_only
-                                         ? Quniscribe : Qgdi);
+                                       backend);
       if (!NILP (entity))
         match_data->list = Fcons (entity, match_data->list);
     }
@@ -1401,6 +1435,8 @@
   tmp = AREF (font_spec, FONT_REGISTRY_INDEX);
   if (! NILP (tmp))
     logfont->lfCharSet = registry_to_w32_charset (tmp);
+  else
+    logfont->lfCharSet = DEFAULT_CHARSET;
 
   /* Out Precision  */
 
@@ -1602,8 +1638,12 @@
       || (subranges[2] & (mask2)) || (subranges[3] & (mask3))) \
     supported = Fcons ((sym), supported)
 
-  SUBRANGE (0, Qlatin); /* There are many others... */
-
+  SUBRANGE (0, Qlatin);
+  /* The following count as latin too, ASCII should be present in these fonts,
+     so don't need to mark them separately.  */
+  /* 1: Latin-1 supplement, 2: Latin Extended A, 3: Latin Extended B.  */
+  SUBRANGE (4, Qphonetic);
+  /* 5: Spacing and tone modifiers, 6: Combining Diacriticals.  */
   SUBRANGE (7, Qgreek);
   SUBRANGE (8, Qcoptic);
   SUBRANGE (9, Qcyrillic);
@@ -1623,15 +1663,28 @@
   SUBRANGE (24, Qthai);
   SUBRANGE (25, Qlao);
   SUBRANGE (26, Qgeorgian);
-
+  SUBRANGE (27, Qbalinese);
+  /* 28: Hangul Jamo.  */
+  /* 29: Latin Extended, 30: Greek Extended, 31: Punctuation.  */
+  /* 32-47: Symbols (defined below).  */
   SUBRANGE (48, Qcjk_misc);
+  /* Match either 49: katakana or 50: hiragana for kana.  */
+  MASK_ANY (0, 0x00060000, 0, 0, Qkana);
   SUBRANGE (51, Qbopomofo);
-  SUBRANGE (54, Qkanbun); /* Is this right?  */
+  /* 52: Compatibility Jamo */
+  SUBRANGE (53, Qphags_pa);
+  /* 54: Enclosed CJK letters and months, 55: CJK Compatibility.  */
   SUBRANGE (56, Qhangul);
-
+  /* 57: Surrogates.  */
+  SUBRANGE (58, Qphoenician);
   SUBRANGE (59, Qhan); /* There are others, but this is the main one.  */
-  SUBRANGE (59, Qideographic_description); /* Windows lumps this in  */
-
+  SUBRANGE (59, Qideographic_description); /* Windows lumps this in.  */
+  SUBRANGE (59, Qkanbun); /* And this.  */
+  /* 60: Private use, 61: CJK strokes and compatibility.  */
+  /* 62: Alphabetic Presentation, 63: Arabic Presentation A.  */
+  /* 64: Combining half marks, 65: Vertical and CJK compatibility.  */
+  /* 66: Small forms, 67: Arabic Presentation B, 68: Half and Full width.  */
+  /* 69: Specials.  */
   SUBRANGE (70, Qtibetan);
   SUBRANGE (71, Qsyriac);
   SUBRANGE (72, Qthaana);
@@ -1646,19 +1699,42 @@
   SUBRANGE (81, Qmongolian);
   SUBRANGE (82, Qbraille);
   SUBRANGE (83, Qyi);
-
+  SUBRANGE (84, Qbuhid);
+  SUBRANGE (84, Qhanunoo);
+  SUBRANGE (84, Qtagalog);
+  SUBRANGE (84, Qtagbanwa);
+  SUBRANGE (85, Qold_italic);
+  SUBRANGE (86, Qgothic);
+  SUBRANGE (87, Qdeseret);
   SUBRANGE (88, Qbyzantine_musical_symbol);
   SUBRANGE (88, Qmusical_symbol); /* Windows doesn't distinguish these.  */
-
   SUBRANGE (89, Qmathematical);
-
-  /* Match either katakana or hiragana for kana.  */
-  MASK_ANY (0, 0x00060000, 0, 0, Qkana);
+  /* 90: Private use, 91: Variation selectors, 92: Tags.  */
+  SUBRANGE (93, Qlimbu);
+  SUBRANGE (94, Qtai_le);
+  /* 95: New Tai Le */
+  SUBRANGE (90, Qbuginese);
+  SUBRANGE (97, Qglagolitic);
+  SUBRANGE (98, Qtifinagh);
+  /* 99: Yijing Hexagrams.  */
+  SUBRANGE (100, Qsyloti_nagri);
+  SUBRANGE (101, Qlinear_b);
+  /* 102: Ancient Greek Numbers.  */
+  SUBRANGE (103, Qugaritic);
+  SUBRANGE (104, Qold_persian);
+  SUBRANGE (105, Qshavian);
+  SUBRANGE (106, Qosmanya);
+  SUBRANGE (107, Qcypriot);
+  SUBRANGE (108, Qkharoshthi);
+  /* 109: Tai Xuan Jing.  */
+  SUBRANGE (110, Qcuneiform);
+  /* 111: Counting Rods.  */
 
   /* There isn't really a main symbol range, so include symbol if any
      relevant range is set.  */
   MASK_ANY (0x8000000, 0x0000FFFF, 0, 0, Qsymbol);
 
+  /* Missing: Tai Viet (U+AA80) and Cham (U+AA00) .  */
 #undef SUBRANGE
 #undef MASK_ANY
 
@@ -1763,11 +1839,12 @@
       if (GetGlyphOutlineW (dc, i, options, &gm, 0, NULL, &transform)
           != GDI_ERROR)
         {
-          char_metric->lbearing = -gm.gmptGlyphOrigin.x;
+          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;
+          char_metric->ascent = gm.gmBlackBoxY;
+          char_metric->descent = (gm.gmCellIncY - gm.gmptGlyphOrigin.y
+				  - gm.gmBlackBoxY);
         }
       else
         char_metric->width = 0;
@@ -1879,6 +1956,31 @@
   DEFSYM (Qbyzantine_musical_symbol, "byzantine-musical-symbol");
   DEFSYM (Qmusical_symbol, "musical-symbol");
   DEFSYM (Qmathematical, "mathematical");
+  DEFSYM (Qphonetic, "phonetic");
+  DEFSYM (Qbalinese, "balinese");
+  DEFSYM (Qbuginese, "buginese");
+  DEFSYM (Qbuhid, "buhid");
+  DEFSYM (Qcuneiform, "cuneiform");
+  DEFSYM (Qcypriot, "cypriot");
+  DEFSYM (Qdeseret, "deseret");
+  DEFSYM (Qglagolitic, "glagolitic");
+  DEFSYM (Qgothic, "gothic");
+  DEFSYM (Qhanunoo, "hanunoo");
+  DEFSYM (Qkharoshthi, "kharoshthi");
+  DEFSYM (Qlimbu, "limbu");
+  DEFSYM (Qlinear_b, "linear_b");
+  DEFSYM (Qold_italic, "old_italic");
+  DEFSYM (Qold_persian, "old_persian");
+  DEFSYM (Qosmanya, "osmanya");
+  DEFSYM (Qphags_pa, "phags-pa");
+  DEFSYM (Qphoenician, "phoenician");
+  DEFSYM (Qshavian, "shavian");
+  DEFSYM (Qsyloti_nagri, "syloti_nagri");
+  DEFSYM (Qtagalog, "tagalog");
+  DEFSYM (Qtagbanwa, "tagbanwa");
+  DEFSYM (Qtai_le, "tai_le");
+  DEFSYM (Qtifinagh, "tifinagh");
+  DEFSYM (Qugaritic, "ugaritic");
 
   w32font_driver.type = Qgdi;
   register_font_driver (&w32font_driver, NULL);