emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 921c0a16ce2: Improve the Android last resort font driver


From: Po Lu
Subject: master 921c0a16ce2: Improve the Android last resort font driver
Date: Wed, 13 Sep 2023 22:00:06 -0400 (EDT)

branch: master
commit 921c0a16ce20828043b3a9df3e0fb6c3a4ecbd74
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Improve the Android last resort font driver
    
    * java/org/gnu/emacs/EmacsSdk7FontDriver.java (Sdk7Typeface):
    Rename fileName to familyName and cease attempting to infer a
    style from it.
    (EmacsSdk7FontDriver): Employ preset typefaces rather than
    enumerating each typeface within the system fonts directory.
    (draw): Circumvent kerning difficulties by advancing past each
    character individually.
---
 java/org/gnu/emacs/EmacsSdk7FontDriver.java | 194 ++++++++++------------------
 1 file changed, 71 insertions(+), 123 deletions(-)

diff --git a/java/org/gnu/emacs/EmacsSdk7FontDriver.java 
b/java/org/gnu/emacs/EmacsSdk7FontDriver.java
index 97969585d16..b8aecbe7c2d 100644
--- a/java/org/gnu/emacs/EmacsSdk7FontDriver.java
+++ b/java/org/gnu/emacs/EmacsSdk7FontDriver.java
@@ -31,6 +31,19 @@ import android.graphics.Canvas;
 
 import android.util.Log;
 
+
+
+/* EmacsSdk7FontDriver implements a fallback font driver under
+   Android.  This font driver is enabled when the SFNT font driver (in
+   sfntfont-android.c) proves incapable of locating any fonts, which
+   has hitherto not been observed in practice.
+
+   This font driver does not supply each font installed on the system,
+   in lieu of which it provides a list of fonts for each conceivable
+   style and sub-type of the system's own Typefaces, which arises from
+   Android's absence of suitable APIs for loading individual font
+   files.  */
+
 public class EmacsSdk7FontDriver extends EmacsFontDriver
 {
   private static final String TOFU_STRING = "\uDB3F\uDFFD";
@@ -46,106 +59,26 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver
     public int slant, width, weight, spacing;
 
     public
-    Sdk7Typeface (String fileName, Typeface typeface)
+    Sdk7Typeface (String familyName, Typeface typeface)
     {
       String style, testString;
       int index, measured, i;
       float[] widths;
 
+      /* Initialize the font style fields and create a paint object
+        linked with that typeface.  */
+
       slant = NORMAL;
       weight = REGULAR;
       width = UNSPECIFIED;
       spacing = PROPORTIONAL;
 
       this.typeface = typeface;
+      this.familyName = familyName;
 
       typefacePaint = new Paint ();
       typefacePaint.setAntiAlias (true);
       typefacePaint.setTypeface (typeface);
-
-      /* For the calls to measureText below.  */
-      typefacePaint.setTextSize (10.0f);
-
-      /* Parse the file name into some useful data.  First, strip off
-        the extension.  */
-      fileName = fileName.split ("\\.", 2)[0];
-
-      /* Next, split the file name by dashes.  Everything before the
-        last dash is part of the family name.  */
-      index = fileName.lastIndexOf ("-");
-
-      if (index > 0)
-       {
-         style = fileName.substring (index + 1, fileName.length ());
-         familyName = fileName.substring (0, index);
-
-         /* Look for something describing the weight.  */
-         if (style.contains ("Thin"))
-           weight = THIN;
-         else if (style.contains ("UltraLight"))
-           weight = ULTRA_LIGHT;
-         else if (style.contains ("SemiLight"))
-           weight = SEMI_LIGHT;
-         else if (style.contains ("Light"))
-           weight = LIGHT;
-         else if (style.contains ("Medium"))
-           weight = MEDIUM;
-         else if (style.contains ("SemiBold"))
-           weight = SEMI_BOLD;
-         else if (style.contains ("ExtraBold"))
-           weight = EXTRA_BOLD;
-         else if (style.contains ("Bold"))
-           weight = BOLD;
-         else if (style.contains ("Black"))
-           weight = BLACK;
-         else if (style.contains ("UltraHeavy"))
-           weight = ULTRA_HEAVY;
-
-         /* And the slant.  */
-         if (style.contains ("ReverseOblique"))
-           slant = OBLIQUE;
-         else if (style.contains ("ReverseItalic"))
-           slant = REVERSE_ITALIC;
-         else if (style.contains ("Italic"))
-           slant = ITALIC;
-         else if (style.contains ("Oblique"))
-           slant = OBLIQUE;
-
-         /* Finally, the width.  */
-         if (style.contains ("UltraCondensed"))
-           width = ULTRA_CONDENSED;
-         else if (style.contains ("ExtraCondensed"))
-           width = EXTRA_CONDENSED;
-         else if (style.contains ("SemiCondensed"))
-           width = SEMI_CONDENSED;
-         else if (style.contains ("Condensed"))
-           width = CONDENSED;
-         else if (style.contains ("SemiExpanded"))
-           width = SEMI_EXPANDED;
-         else if (style.contains ("ExtraExpanded"))
-           width = EXTRA_EXPANDED;
-         else if (style.contains ("UltraExpanded"))
-           width = ULTRA_EXPANDED;
-         else if (style.contains ("Expanded"))
-           width = EXPANDED;
-
-         /* Guess the spacing information.  */
-         testString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
-         widths = new float[testString.length ()];
-
-         measured = typefacePaint.getTextWidths (testString,
-                                                 0, testString.length (),
-                                                 widths);
-         spacing = MONO;
-         for (i = 0; i < measured; ++i)
-           {
-             if (i != 0 && widths[i - 1] != widths[i])
-               /* This isn't a monospace font.  */
-               spacing = PROPORTIONAL;
-           }
-       }
-      else
-       familyName = fileName;
     }
 
     @Override
@@ -244,43 +177,42 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver
   EmacsSdk7FontDriver ()
   {
     int i;
-    File systemFontsDirectory, fontFile;
     Typeface typeface;
 
-    systemFontsDirectory = new File ("/system/fonts");
-
-    fontFamilyList = systemFontsDirectory.list ();
-
-    /* If that returned null, replace it with an empty array.  */
-    fontFamilyList = new String[0];
+    typefaceList = new Sdk7Typeface[5];
 
-    typefaceList = new Sdk7Typeface[fontFamilyList.length + 3];
-
-    /* It would be nice to avoid opening each and every font upon
-       startup.  But that doesn't seem to be possible on
-       Android.  */
+    /* Initialize the default monospace and Sans Serif typefaces.
+       Initialize the same typeface with various distinct styles.  */
+    fallbackTypeface = new Sdk7Typeface ("Sans Serif",
+                                        Typeface.DEFAULT);
+    typefaceList[1] = fallbackTypeface;
 
-    for (i = 0; i < fontFamilyList.length; ++i)
-      {
-       fontFile = new File (systemFontsDirectory,
-                            fontFamilyList[i]);
-       typeface = Typeface.createFromFile (fontFile);
-       typefaceList[i] = new Sdk7Typeface (fontFile.getName (),
-                                           typeface);
-      }
+    fallbackTypeface = new Sdk7Typeface ("Sans Serif",
+                                        Typeface.create (Typeface.DEFAULT,
+                                                         Typeface.BOLD));
+    fallbackTypeface.weight = BOLD;
+    typefaceList[2] = fallbackTypeface;
 
-    /* Initialize the default monospace and serif typefaces.  */
-    fallbackTypeface = new Sdk7Typeface ("monospace",
-                                        Typeface.MONOSPACE);
-    typefaceList[fontFamilyList.length] = fallbackTypeface;
+    fallbackTypeface = new Sdk7Typeface ("Sans Serif",
+                                        Typeface.create (Typeface.DEFAULT,
+                                                         Typeface.ITALIC));
+    fallbackTypeface.slant = ITALIC;
+    typefaceList[3] = fallbackTypeface;
+
+    fallbackTypeface
+      = new Sdk7Typeface ("Sans Serif",
+                         Typeface.create (Typeface.DEFAULT,
+                                          Typeface.BOLD_ITALIC));
+    fallbackTypeface.weight = BOLD;
+    fallbackTypeface.slant = ITALIC;
+    typefaceList[4] = fallbackTypeface;
 
     fallbackTypeface = new Sdk7Typeface ("Monospace",
                                         Typeface.MONOSPACE);
-    typefaceList[fontFamilyList.length + 1] = fallbackTypeface;
+    fallbackTypeface.spacing = MONO;
+    typefaceList[0] = fallbackTypeface;
 
-    fallbackTypeface = new Sdk7Typeface ("Sans Serif",
-                                        Typeface.DEFAULT);
-    typefaceList[fontFamilyList.length + 2] = fallbackTypeface;
+    fontFamilyList = new String[] { "Monospace", "Sans Serif", };
   }
 
   private boolean
@@ -491,16 +423,12 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver
   {
     Rect backgroundRect, bounds;
     Sdk7FontObject sdk7FontObject;
-    char[] charsArray;
     int i;
     Canvas canvas;
     Paint paint;
+    char[] array;
 
     sdk7FontObject = (Sdk7FontObject) fontObject;
-    charsArray = new char[chars.length];
-
-    for (i = 0; i < chars.length; ++i)
-      charsArray[i] = (char) chars[i];
 
     backgroundRect = new Rect ();
     backgroundRect.top = y - sdk7FontObject.ascent;
@@ -526,13 +454,33 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver
     paint.setTextSize (sdk7FontObject.pixelSize);
     paint.setTypeface (sdk7FontObject.typeface.typeface);
     paint.setAntiAlias (true);
-    canvas.drawText (charsArray, 0, chars.length, x, y, paint);
+
+    /* Android applies kerning to non-monospaced fonts by default,
+       which brings the dimensions of strings drawn via `drawText' out
+       of agreement with measurements previously provided to redisplay
+       by textExtents.  To avert such disaster, draw each character
+       individually, advancing the origin point by hand.  */
 
     bounds = new Rect ();
-    paint.getTextBounds (charsArray, 0, chars.length, bounds);
-    bounds.offset (x, y);
-    bounds.union (backgroundRect);
-    drawable.damageRect (bounds);
+    array = new char[1];
+
+    for (i = 0; i < chars.length; ++i)
+      {
+       /* Retrieve the text bounds for this character so as to
+          compute the damage rectangle.  */
+       array[0] = (char) chars[i];
+       paint.getTextBounds (array, 0, 1, bounds);
+       bounds.offset (x, y);
+       backgroundRect.union (bounds);
+
+       /* Draw this character.  */
+       canvas.drawText (array, 0, 1, x, y, paint);
+
+       /* Advance the origin point by that much.  */
+       x += paint.measureText ("" + array[0]);
+      }
+
+    drawable.damageRect (backgroundRect);
     paint.setAntiAlias (false);
     return 1;
   }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]