From ab3e73bed560e274681efc4d903916973dcb246c Mon Sep 17 00:00:00 2001 From: Po Lu Date: Tue, 23 Apr 2024 15:57:45 +0800 Subject: [PATCH] Enable configuring Emacs for "pseudo-grayscale" systems on Android * 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): : 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) : 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 | 25 +++++++++++++++++++--- src/androidfns.c | 19 +++++++++++++++-- src/androidterm.c | 48 ++++++++++++++++++++++++++++++++++++------ src/androidterm.h | 5 +++-- src/image.c | 3 +++ 5 files changed, 86 insertions(+), 14 deletions(-) diff --git a/doc/emacs/android.texi b/doc/emacs/android.texi index 15c5fbcce3a..9e3716894ee 100644 --- a/doc/emacs/android.texi +++ b/doc/emacs/android.texi @@ -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 diff --git a/src/androidfns.c b/src/androidfns.c index 9f7ac8b69b2..b6df7ae0677 100644 --- a/src/androidfns.c +++ b/src/androidfns.c @@ -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, diff --git a/src/androidterm.c b/src/androidterm.c index c920375fdbe..e4f3abdb2d3 100644 --- a/src/androidterm.c +++ b/src/androidterm.c @@ -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; diff --git a/src/androidterm.h b/src/androidterm.h index fd4cc99f641..24eb2c30f12 100644 --- a/src/androidterm.h +++ b/src/androidterm.h @@ -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; diff --git a/src/image.c b/src/image.c index 3028c2e707a..d1faadee968 100644 --- a/src/image.c +++ b/src/image.c @@ -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 *); -- 2.39.5