]> git.eshelyaron.com Git - emacs.git/commitdiff
Enable configuring Emacs for "pseudo-grayscale" systems on Android
authorPo Lu <luangruo@yahoo.com>
Tue, 23 Apr 2024 07:57:45 +0000 (15:57 +0800)
committerEshel Yaron <me@eshelyaron.com>
Tue, 23 Apr 2024 10:14:00 +0000 (12:14 +0200)
* doc/emacs/android.texi (Android Windowing): Document how to
configure Emacs for monochrome displays.

* src/androidfns.c (Fx_display_visual_class): Return
Qstatic_gray when n_planes is smaller than 24.
(Fandroid_get_connection): Set n_planes by the value of
android_display_planes.
(syms_of_androidfns): <Qstatic_gray>: New function.

* src/androidterm.c (android_alloc_nearest_color): Allocate
monochrome colors similarly to the X server.
(android_query_colors): Fix typos.
(android_draw_fringe_bitmap): Create bitmaps of n_image_planes
depth.
(android_term_init): Initialize n_image_planes to 24.
(syms_of_androidterm) <android_display_planes>: New variable.

* src/androidterm.h (struct android_display_info): New field
`n_image_planes'.

* src/image.c (n_planes) [HAVE_ANDROID]: Define to
n_image_planes.

(cherry picked from commit cd7456e00d719d32c203c71b4e23c98b0c4e1967)

doc/emacs/android.texi
src/androidfns.c
src/androidterm.c
src/androidterm.h
src/image.c

index 15c5fbcce3aec96f7024b7a6fb920f5239d5c023..9e3716894ee7c78471b848b967b37b6ad73db308 100644 (file)
@@ -827,7 +827,7 @@ example, the permission to access contacts may be useful for EUDC.
 applications as maximized or full-screen, and, in the general case, only
 one window can be displayed at a time.  On larger devices, the system
 permits simultaneously tiling up to four windows on the screen, though
-in emulators or installations configured for ``desktop'' system stacks
+in emulators or installations configured for ``desktop'' systems stacks
 freely resizable windows as other desktop window managers do.
 
   Windows, or, in system nomenclature, activities, do not exist
@@ -1002,12 +1002,31 @@ customized through altering the variable
 @code{android-keyboard-bell-duration} to any value between @code{10}
 and @code{1000}.
 
+@vindex android-display-planes
+@cindex visual class, Android
+@cindex display color space, Android
+  Color-related characteristics of the display are not automatically
+detectable on Android, so the variable @code{android-display-planes}
+should be configured to a suitable value if Emacs is to realize faces
+and images in a manner consistent with the true visual attributes of a
+grayscale or monochrome display: to @code{8} for the former class of
+display, and @code{1} for the latter, which will, respectively, force
+all colors to be rendered in 256 grays, or in monochrome.  As this
+variable is processed at the time the display connection is established,
+customizations will not take effect unless they be performed from
+@code{early-init.el} (@pxref{Early Init File}).
+
+  The value of this variable does not affect anti-aliasing in the font
+driver, as monochrome displays nevertheless expect Emacs to provide
+antialiased text, which they receive after it is processed into bitmap
+data by the display driver.
+
 @node Android Fonts
 @section Font Backends and Selection under Android
 @cindex fonts, android
 
-  Emacs supports two font backends under Android: they are
-respectively named @code{sfnt-android} and @code{android}.
+  Emacs supports two font backends under Android: they are respectively
+named @code{sfnt-android} and @code{android}.
 
   Upon startup, Emacs enumerates all the TrueType format fonts in the
 directories @file{/system/fonts} and @file{/product/fonts}, and the
index 9f7ac8b69b263a94a87cfacbc25452b886dc5094..b6df7ae0677d46f3fea1a9cc93d3b423ab66709d 100644 (file)
@@ -1345,7 +1345,12 @@ DEFUN ("x-display-visual-class", Fx_display_visual_class,
        doc: /* SKIP: real doc in xfns.c.  */)
   (Lisp_Object terminal)
 {
-  check_android_display_info (terminal);
+  struct android_display_info *dpyinfo;
+
+  dpyinfo = check_android_display_info (terminal);
+
+  if (dpyinfo->n_planes < 24)
+    return Qstatic_gray;
 
   return Qtrue_color;
 }
@@ -1805,7 +1810,16 @@ Android, so there is no equivalent of `x-open-connection'.  */)
   terminal = Qnil;
 
   if (x_display_list)
-    XSETTERMINAL (terminal, x_display_list->terminal);
+    {
+      XSETTERMINAL (terminal, x_display_list->terminal);
+
+      /* Update the display's bit depth from
+        `android_display_planes'.  */
+      x_display_list->n_planes
+       = (android_display_planes > 8
+          ? 24 : (android_display_planes > 1
+                  ? android_display_planes : 1));
+    }
 
   return terminal;
 #endif
@@ -3479,6 +3493,7 @@ syms_of_androidfns (void)
 {
   /* Miscellaneous symbols used by some functions here.  */
   DEFSYM (Qtrue_color, "true-color");
+  DEFSYM (Qstatic_gray, "static-color");
   DEFSYM (Qwhen_mapped, "when-mapped");
 
   DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape,
index c920375fdbe4c8b912ed204c9ec6f46e1bc5c282..e4f3abdb2d307306308602c64651ac373536e637 100644 (file)
@@ -1964,10 +1964,33 @@ android_parse_color (struct frame *f, const char *color_name,
 bool
 android_alloc_nearest_color (struct frame *f, Emacs_Color *color)
 {
+  unsigned int ntsc;
+
   gamma_correct (f, color);
-  color->pixel = RGB_TO_ULONG (color->red / 256,
-                              color->green / 256,
-                              color->blue / 256);
+
+  if (FRAME_DISPLAY_INFO (f)->n_planes == 1)
+    {
+      /* Black and white.  I think this is the luminance formula applied
+        by the X server on generic monochrome framebuffers.  */
+      color->pixel = ((((30l * color->red
+                        + 59l * color->green
+                        + 11l * color->blue) >> 8)
+                      >= (((1 << 8) -1) * 50))
+                     ? 0xffffff : 0);
+    }
+  else if (FRAME_DISPLAY_INFO (f)->n_planes <= 8)
+    {
+      /* 256 grays.  */
+      ntsc = min (255, ((color->red * 0.299
+                        + color->green * 0.587
+                        + color->blue * 0.114)
+                       / 256));
+      color->pixel = RGB_TO_ULONG (ntsc, ntsc, ntsc);
+    }
+  else
+    color->pixel = RGB_TO_ULONG (color->red / 256,
+                                color->green / 256,
+                                color->blue / 256);
 
   return true;
 }
@@ -1980,8 +2003,8 @@ android_query_colors (struct frame *f, Emacs_Color *colors, int ncolors)
   for (i = 0; i < ncolors; ++i)
     {
       colors[i].red = RED_FROM_ULONG (colors[i].pixel) * 257;
-      colors[i].green = RED_FROM_ULONG (colors[i].pixel) * 257;
-      colors[i].blue = RED_FROM_ULONG (colors[i].pixel) * 257;
+      colors[i].green = GREEN_FROM_ULONG (colors[i].pixel) * 257;
+      colors[i].blue = BLUE_FROM_ULONG (colors[i].pixel) * 257;
     }
 }
 
@@ -2630,7 +2653,7 @@ android_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
       clipmask = ANDROID_NONE;
       background = face->background;
       cursor_pixel = f->output_data.android->cursor_pixel;
-      depth = FRAME_DISPLAY_INFO (f)->n_planes;
+      depth = FRAME_DISPLAY_INFO (f)->n_image_planes;
 
       /* Intersect the destination rectangle with that of the row.
         Setting a clip mask overrides the clip rectangles provided by
@@ -6504,8 +6527,8 @@ android_term_init (void)
   terminal = android_create_terminal (dpyinfo);
   terminal->kboard = allocate_kboard (Qandroid);
   terminal->kboard->reference_count++;
-
   dpyinfo->n_planes = 24;
+  dpyinfo->n_image_planes = 24;
 
   /* This function should only be called once at startup.  */
   eassert (!x_display_list);
@@ -6702,6 +6725,17 @@ Emacs is running on.  */);
     doc: /* Name of the developer of the running version of Android.  */);
   Vandroid_build_manufacturer = Qnil;
 
+  DEFVAR_INT ("android-display-planes", android_display_planes,
+    doc: /* Depth and visual class of the display.
+This variable controls the visual class and depth of the display, which
+cannot be detected on Android.  The default value of 24, and values from
+there to 8 represent a TrueColor display providing 24 planes, values
+between 8 and 1 StaticGray displays providing that many planes, and 1 or
+lower monochrome displays with a single plane.  Modifications to this
+variable must be completed before the window system is initialized, in,
+for instance, `early-init.el', or they will be of no effect.  */);
+  android_display_planes = 24;
+
   DEFVAR_LISP ("x-ctrl-keysym", Vx_ctrl_keysym,
     doc: /* SKIP: real doc in xterm.c.  */);
   Vx_ctrl_keysym = Qnil;
index fd4cc99f641efbb7ddd4e2251a21b3838721427c..24eb2c30f12913cc12e2310479cdd60ce48e726b 100644 (file)
@@ -77,8 +77,9 @@ struct android_display_info
   /* Mouse highlight information.  */
   Mouse_HLInfo mouse_highlight;
 
-  /* Number of planes on this screen.  Always 24.  */
-  int n_planes;
+  /* Number of planes on this screen, and the same for the purposes of
+     image processing.  */
+  int n_planes, n_image_planes;
 
   /* Mask of things causing the mouse to be grabbed.  */
   int grabbed;
index 3028c2e707a47abb3aac7bb8a586224a788f4348..d1faadee9687e24e1297c6dfdee8d323d32dd6e7 100644 (file)
@@ -198,6 +198,9 @@ typedef android_pixmap Pixmap;
 #define GREEN16_FROM_ULONG(color)      (GREEN_FROM_ULONG (color) * 0x101)
 #define BLUE16_FROM_ULONG(color)       (BLUE_FROM_ULONG (color) * 0x101)
 
+/* DPYINFO->n_planes is unsuitable for this file, because it accepts
+   values that may not be supported for pixmap creation.  */
+#define n_planes n_image_planes
 #endif
 
 static void image_disable_image (struct frame *, struct image *);