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): <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.
This commit is contained in:
Po Lu 2024-04-23 15:57:45 +08:00
parent b9c191d690
commit cd7456e00d
5 changed files with 86 additions and 14 deletions

View 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

View 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,

View 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;

View 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;

View 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 *);