diff options
| author | Po Lu | 2023-01-16 19:50:02 +0800 |
|---|---|---|
| committer | Po Lu | 2023-01-16 19:50:02 +0800 |
| commit | ad59d8986aee4498c0427449e024341d1a195a2d (patch) | |
| tree | da8ee046484e48cd991cb484ecc960a7432c91de /src | |
| parent | da9ae10636b84b88e9eb9c827b03cdaabd1611d1 (diff) | |
| download | emacs-ad59d8986aee4498c0427449e024341d1a195a2d.tar.gz emacs-ad59d8986aee4498c0427449e024341d1a195a2d.zip | |
Update Android port
* doc/emacs/android.texi (Android, Android Environment): Improve
documentation.
* doc/lispref/commands.texi (Touchscreen Events): Document
changes to touchscreen support.
* doc/lispref/display.texi (Defining Faces, Window Systems):
* doc/lispref/frames.texi (Frame Layout, Font and Color
Parameters):
* doc/lispref/os.texi (System Environment): Document Android in
various places.
* java/org/gnu/emacs/EmacsWindow.java (figureChange): Fix crash.
* lisp/loadup.el: ("touch-screen"): Load touch-screen.el.
* lisp/pixel-scroll.el: Autoload two functions.
* lisp/term/android-win.el: Add require 'touch-screen.
* lisp/touch-screen.el (touch-screen-current-tool)
(touch-screen-current-timer, touch-screen-delay)
(touch-screen-relative-xy, touch-screen-handle-scroll)
(touch-screen-handle-timeout, touch-screen-handle-point-update)
(touch-screen-handle-point-up, touch-screen-handle-touch)
(global-map, touch-screen): New file.
* src/android.c (android_run_debug_thread): Fix build on 64 bit
systems.
(JNICALL, android_put_pixel): Likewise.
(android_transform_coordinates, android_four_corners_bilinear)
(android_fetch_pixel_bilinear, android_project_image_bilinear)
(android_fetch_pixel_nearest_24, android_fetch_pixel_nearest_1)
(android_project_image_nearest): New functions.
* src/androidgui.h (struct android_transform): New structure.
* src/androidterm.c (android_note_mouse_movement): Remove
obsolete TODO.
(android_get_scale_factor): New function.
(android_draw_underwave): Scale underwave correctly.
* src/dispextern.h: Support native image transforms on Android.
* src/image.c (matrix_identity, matrix_rotate)
(matrix_mirror_horizontal, matrix_translate): New functions.
(image_set_transform): Implement native image transforms on
Android.
(Fimage_transforms_p): Implement on Android.
* src/keyboard.c (make_lispy_event, syms_of_keyboard): Handle
touch screen- menu bar events.
* src/sfnt.c: Fix typo in comment.
* src/sfntfont-android.c (sfntfont_android_blend, U255TO256)
(sfntfont_android_put_glyphs): Avoid redundant swizzling.
* src/sfntfont.c (sfntfont_lookup_char): Fix build on 64 bit
systems.
Diffstat (limited to 'src')
| -rw-r--r-- | src/android.c | 282 | ||||
| -rw-r--r-- | src/androidgui.h | 19 | ||||
| -rw-r--r-- | src/androidterm.c | 28 | ||||
| -rw-r--r-- | src/dispextern.h | 5 | ||||
| -rw-r--r-- | src/image.c | 310 | ||||
| -rw-r--r-- | src/keyboard.c | 70 | ||||
| -rw-r--r-- | src/sfnt.c | 2 | ||||
| -rw-r--r-- | src/sfntfont-android.c | 55 | ||||
| -rw-r--r-- | src/sfntfont.c | 2 |
9 files changed, 715 insertions, 58 deletions
diff --git a/src/android.c b/src/android.c index 3a965286460..9b15ea9f15a 100644 --- a/src/android.c +++ b/src/android.c | |||
| @@ -25,9 +25,11 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 25 | #include <signal.h> | 25 | #include <signal.h> |
| 26 | #include <semaphore.h> | 26 | #include <semaphore.h> |
| 27 | #include <dlfcn.h> | 27 | #include <dlfcn.h> |
| 28 | #include <errno.h> | ||
| 28 | 29 | ||
| 29 | #include <sys/stat.h> | 30 | #include <sys/stat.h> |
| 30 | #include <sys/mman.h> | 31 | #include <sys/mman.h> |
| 32 | #include <sys/param.h> | ||
| 31 | 33 | ||
| 32 | #include <assert.h> | 34 | #include <assert.h> |
| 33 | 35 | ||
| @@ -513,7 +515,7 @@ android_run_debug_thread (void *data) | |||
| 513 | char *line; | 515 | char *line; |
| 514 | size_t n; | 516 | size_t n; |
| 515 | 517 | ||
| 516 | fd = (int) data; | 518 | fd = (int) (intptr_t) data; |
| 517 | file = fdopen (fd, "r"); | 519 | file = fdopen (fd, "r"); |
| 518 | 520 | ||
| 519 | if (!file) | 521 | if (!file) |
| @@ -958,7 +960,7 @@ NATIVE_NAME (setEmacsParams) (JNIEnv *env, jobject object, | |||
| 958 | close (pipefd[1]); | 960 | close (pipefd[1]); |
| 959 | 961 | ||
| 960 | if (pthread_create (&thread, NULL, android_run_debug_thread, | 962 | if (pthread_create (&thread, NULL, android_run_debug_thread, |
| 961 | (void *) pipefd[0])) | 963 | (void *) (intptr_t) pipefd[0])) |
| 962 | emacs_abort (); | 964 | emacs_abort (); |
| 963 | 965 | ||
| 964 | /* Now set the path to the site load directory. */ | 966 | /* Now set the path to the site load directory. */ |
| @@ -2829,6 +2831,7 @@ android_put_pixel (struct android_image *ximg, int x, int y, | |||
| 2829 | { | 2831 | { |
| 2830 | char *byte, *word; | 2832 | char *byte, *word; |
| 2831 | unsigned int r, g, b; | 2833 | unsigned int r, g, b; |
| 2834 | unsigned int pixel_int; | ||
| 2832 | 2835 | ||
| 2833 | /* Ignore out-of-bounds accesses. */ | 2836 | /* Ignore out-of-bounds accesses. */ |
| 2834 | 2837 | ||
| @@ -2859,7 +2862,8 @@ android_put_pixel (struct android_image *ximg, int x, int y, | |||
| 2859 | b = pixel & 0x000000ff; | 2862 | b = pixel & 0x000000ff; |
| 2860 | pixel = (r >> 16) | g | (b << 16) | 0xff000000; | 2863 | pixel = (r >> 16) | g | (b << 16) | 0xff000000; |
| 2861 | 2864 | ||
| 2862 | memcpy (word, &pixel, sizeof pixel); | 2865 | pixel_int = pixel; |
| 2866 | memcpy (word, &pixel_int, sizeof pixel_int); | ||
| 2863 | break; | 2867 | break; |
| 2864 | } | 2868 | } |
| 2865 | } | 2869 | } |
| @@ -3734,6 +3738,262 @@ android_exception_check (void) | |||
| 3734 | } | 3738 | } |
| 3735 | } | 3739 | } |
| 3736 | 3740 | ||
| 3741 | |||
| 3742 | |||
| 3743 | /* Native image transforms. */ | ||
| 3744 | |||
| 3745 | /* Transform the coordinates X and Y by the specified affine | ||
| 3746 | transformation MATRIX. Place the result in *XOUT and *YOUT. */ | ||
| 3747 | |||
| 3748 | static void | ||
| 3749 | android_transform_coordinates (int x, int y, | ||
| 3750 | struct android_transform *transform, | ||
| 3751 | float *xout, float *yout) | ||
| 3752 | { | ||
| 3753 | /* Apply the specified affine transformation. | ||
| 3754 | A transform looks like: | ||
| 3755 | |||
| 3756 | M1 M2 M3 X | ||
| 3757 | M4 M5 M6 * Y | ||
| 3758 | |||
| 3759 | = | ||
| 3760 | |||
| 3761 | M1*X + M2*Y + M3*1 = X1 | ||
| 3762 | M4*X + M5*Y + M6*1 = Y1 | ||
| 3763 | |||
| 3764 | (In most transforms, there is another row at the bottom for | ||
| 3765 | mathematical reasons. Since Z1 is always 1.0, the row is simply | ||
| 3766 | implied to be 0 0 1, because 0 * x + 0 * y + 1 * 1 = 1.0. See | ||
| 3767 | the definition of matrix3x3 in image.c for some more explanations | ||
| 3768 | about this.) */ | ||
| 3769 | |||
| 3770 | *xout = transform->m1 * x + transform->m2 * y + transform->m3; | ||
| 3771 | *yout = transform->m4 * x + transform->m5 * y + transform->m6; | ||
| 3772 | } | ||
| 3773 | |||
| 3774 | /* Return the interpolation of the four pixels TL, TR, BL, and BR, | ||
| 3775 | according to the weights DISTX and DISTY. */ | ||
| 3776 | |||
| 3777 | static unsigned int | ||
| 3778 | android_four_corners_bilinear (unsigned int tl, unsigned int tr, | ||
| 3779 | unsigned int bl, unsigned int br, | ||
| 3780 | int distx, int disty) | ||
| 3781 | { | ||
| 3782 | int distxy, distxiy, distixy, distixiy; | ||
| 3783 | uint32_t f, r; | ||
| 3784 | |||
| 3785 | distxy = distx * disty; | ||
| 3786 | distxiy = (distx << 8) - distxy; | ||
| 3787 | distixy = (disty << 8) - distxy; | ||
| 3788 | distixiy = (256 * 256 - (disty << 8) | ||
| 3789 | - (distx << 8) + distxy); | ||
| 3790 | |||
| 3791 | /* Red */ | ||
| 3792 | r = ((tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy | ||
| 3793 | + (bl & 0x000000ff) * distixy + (br & 0x000000ff) * distxy); | ||
| 3794 | |||
| 3795 | /* Green */ | ||
| 3796 | f = ((tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy | ||
| 3797 | + (bl & 0x0000ff00) * distixy + (br & 0x0000ff00) * distxy); | ||
| 3798 | r |= f & 0xff000000; | ||
| 3799 | |||
| 3800 | /* Now do the upper two components. */ | ||
| 3801 | tl >>= 16; | ||
| 3802 | tr >>= 16; | ||
| 3803 | bl >>= 16; | ||
| 3804 | br >>= 16; | ||
| 3805 | r >>= 16; | ||
| 3806 | |||
| 3807 | /* Blue */ | ||
| 3808 | f = ((tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy | ||
| 3809 | + (bl & 0x000000ff) * distixy + (br & 0x000000ff) * distxy); | ||
| 3810 | r |= f & 0x00ff0000; | ||
| 3811 | |||
| 3812 | /* Alpha */ | ||
| 3813 | f = ((tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy | ||
| 3814 | + (bl & 0x0000ff00) * distixy + (br & 0x0000ff00) * distxy); | ||
| 3815 | r |= f & 0xff000000; | ||
| 3816 | |||
| 3817 | return r; | ||
| 3818 | } | ||
| 3819 | |||
| 3820 | /* Return the interpolation of the four pixels closest to at X, Y in | ||
| 3821 | IMAGE, according to weights in both axes computed from X and Y. | ||
| 3822 | IMAGE must be depth 24, or the behavior is undefined. */ | ||
| 3823 | |||
| 3824 | static unsigned int | ||
| 3825 | android_fetch_pixel_bilinear (struct android_image *image, | ||
| 3826 | float x, float y) | ||
| 3827 | { | ||
| 3828 | int x1, y1, x2, y2; | ||
| 3829 | float distx, disty; | ||
| 3830 | unsigned int top_left, top_right; | ||
| 3831 | unsigned int bottom_left, bottom_right; | ||
| 3832 | char *word; | ||
| 3833 | |||
| 3834 | /* Compute the four closest corners to X and Y. */ | ||
| 3835 | x1 = (int) x; | ||
| 3836 | x2 = x1 + 1; | ||
| 3837 | y1 = (int) y; | ||
| 3838 | y2 = y1 + 1; | ||
| 3839 | |||
| 3840 | /* Make sure all four corners are within range. */ | ||
| 3841 | x1 = MAX (0, MIN (image->width - 1, x1)); | ||
| 3842 | y1 = MAX (0, MIN (image->height - 1, y1)); | ||
| 3843 | x2 = MAX (0, MIN (image->width - 1, x2)); | ||
| 3844 | y2 = MAX (0, MIN (image->height - 1, y2)); | ||
| 3845 | |||
| 3846 | /* Compute the X and Y biases. These are numbers between 0f and | ||
| 3847 | 1f. */ | ||
| 3848 | distx = x - x1; | ||
| 3849 | disty = y - y1; | ||
| 3850 | |||
| 3851 | /* Fetch the four closest pixels. */ | ||
| 3852 | word = image->data + y1 * image->bytes_per_line + x1 * 4; | ||
| 3853 | memcpy (&top_left, word, sizeof top_left); | ||
| 3854 | word = image->data + y1 * image->bytes_per_line + x2 * 4; | ||
| 3855 | memcpy (&top_right, word, sizeof top_right); | ||
| 3856 | word = image->data + y2 * image->bytes_per_line + x1 * 4; | ||
| 3857 | memcpy (&bottom_left, word, sizeof bottom_left); | ||
| 3858 | word = image->data + y2 * image->bytes_per_line + x2 * 4; | ||
| 3859 | memcpy (&bottom_right, word, sizeof bottom_right); | ||
| 3860 | |||
| 3861 | /* Do the interpolation. */ | ||
| 3862 | return android_four_corners_bilinear (top_left, top_right, bottom_left, | ||
| 3863 | bottom_right, distx * 256, | ||
| 3864 | disty * 256); | ||
| 3865 | } | ||
| 3866 | |||
| 3867 | /* Transform the depth 24 image IMAGE by the 3x2 affine transformation | ||
| 3868 | matrix MATRIX utilizing a bilinear filter. Place the result in | ||
| 3869 | OUT. The matrix maps from the coordinate space of OUT to | ||
| 3870 | IMAGE. */ | ||
| 3871 | |||
| 3872 | void | ||
| 3873 | android_project_image_bilinear (struct android_image *image, | ||
| 3874 | struct android_image *out, | ||
| 3875 | struct android_transform *transform) | ||
| 3876 | { | ||
| 3877 | int x, y; | ||
| 3878 | unsigned int pixel; | ||
| 3879 | float xout, yout; | ||
| 3880 | char *word; | ||
| 3881 | |||
| 3882 | /* Loop through each pixel in OUT. Transform it by TRANSFORM, then | ||
| 3883 | interpolate it to IMAGE, and place the result back in OUT. */ | ||
| 3884 | |||
| 3885 | for (y = 0; y < out->height; ++y) | ||
| 3886 | { | ||
| 3887 | for (x = 0; x < out->width; ++x) | ||
| 3888 | { | ||
| 3889 | /* Transform the coordinates by TRANSFORM. */ | ||
| 3890 | android_transform_coordinates (x, y, transform, | ||
| 3891 | &xout, &yout); | ||
| 3892 | |||
| 3893 | /* Interpolate back to IMAGE. */ | ||
| 3894 | pixel = android_fetch_pixel_bilinear (image, xout, yout); | ||
| 3895 | |||
| 3896 | /* Put the pixel back in OUT. */ | ||
| 3897 | word = out->data + y * out->bytes_per_line + x * 4; | ||
| 3898 | memcpy (word, &pixel, sizeof pixel); | ||
| 3899 | } | ||
| 3900 | } | ||
| 3901 | } | ||
| 3902 | |||
| 3903 | /* Return the interpolation of X, Y to IMAGE, a depth 24 image. */ | ||
| 3904 | |||
| 3905 | static unsigned int | ||
| 3906 | android_fetch_pixel_nearest_24 (struct android_image *image, float x, | ||
| 3907 | float y) | ||
| 3908 | { | ||
| 3909 | int x1, y1; | ||
| 3910 | char *word; | ||
| 3911 | unsigned int pixel; | ||
| 3912 | |||
| 3913 | x1 = MAX (0, MIN (image->width - 1, (int) roundf (x))); | ||
| 3914 | y1 = MAX (0, MIN (image->height - 1, (int) roundf (y))); | ||
| 3915 | |||
| 3916 | word = image->data + y1 * image->bytes_per_line + x1 * 4; | ||
| 3917 | memcpy (&pixel, word, sizeof pixel); | ||
| 3918 | |||
| 3919 | return pixel; | ||
| 3920 | } | ||
| 3921 | |||
| 3922 | /* Return the interpolation of X, Y to IMAGE, a depth 1 image. */ | ||
| 3923 | |||
| 3924 | static unsigned int | ||
| 3925 | android_fetch_pixel_nearest_1 (struct android_image *image, float x, | ||
| 3926 | float y) | ||
| 3927 | { | ||
| 3928 | int x1, y1; | ||
| 3929 | char *byte; | ||
| 3930 | |||
| 3931 | x1 = MAX (0, MIN (image->width - 1, (int) roundf (x))); | ||
| 3932 | y1 = MAX (0, MIN (image->height - 1, (int) roundf (y))); | ||
| 3933 | |||
| 3934 | byte = image->data + y1 * image->bytes_per_line; | ||
| 3935 | return (byte[x1 / 8] & (1 << x1 % 8)) ? 1 : 0; | ||
| 3936 | } | ||
| 3937 | |||
| 3938 | /* Transform the depth 24 or 1 image IMAGE by the 3x2 affine | ||
| 3939 | transformation matrix MATRIX. Place the result in OUT. The matrix | ||
| 3940 | maps from the coordinate space of OUT to IMAGE. Use a | ||
| 3941 | nearest-neighbor filter. */ | ||
| 3942 | |||
| 3943 | void | ||
| 3944 | android_project_image_nearest (struct android_image *image, | ||
| 3945 | struct android_image *out, | ||
| 3946 | struct android_transform *transform) | ||
| 3947 | { | ||
| 3948 | int x, y; | ||
| 3949 | unsigned int pixel; | ||
| 3950 | float xout, yout; | ||
| 3951 | char *word, *byte; | ||
| 3952 | |||
| 3953 | if (image->depth == 1) | ||
| 3954 | { | ||
| 3955 | for (y = 0; y < out->height; ++y) | ||
| 3956 | { | ||
| 3957 | for (x = 0; x < out->width; ++x) | ||
| 3958 | { | ||
| 3959 | /* Transform the coordinates by TRANSFORM. */ | ||
| 3960 | android_transform_coordinates (x, y, transform, | ||
| 3961 | &xout, &yout); | ||
| 3962 | |||
| 3963 | /* Interpolate back to IMAGE. */ | ||
| 3964 | pixel = android_fetch_pixel_nearest_1 (image, xout, yout); | ||
| 3965 | |||
| 3966 | /* Put the pixel back in OUT. */ | ||
| 3967 | byte = out->data + y * out->bytes_per_line + x / 8; | ||
| 3968 | |||
| 3969 | if (pixel) | ||
| 3970 | *byte |= (1 << x % 8); | ||
| 3971 | else | ||
| 3972 | *byte &= ~(1 << x % 8); | ||
| 3973 | } | ||
| 3974 | } | ||
| 3975 | |||
| 3976 | return; | ||
| 3977 | } | ||
| 3978 | |||
| 3979 | for (y = 0; y < out->height; ++y) | ||
| 3980 | { | ||
| 3981 | for (x = 0; x < out->width; ++x) | ||
| 3982 | { | ||
| 3983 | /* Transform the coordinates by TRANSFORM. */ | ||
| 3984 | android_transform_coordinates (x, y, transform, | ||
| 3985 | &xout, &yout); | ||
| 3986 | |||
| 3987 | /* Interpolate back to IMAGE. */ | ||
| 3988 | pixel = android_fetch_pixel_nearest_24 (image, xout, yout); | ||
| 3989 | |||
| 3990 | /* Put the pixel back in OUT. */ | ||
| 3991 | word = out->data + y * out->bytes_per_line + x * 4; | ||
| 3992 | memcpy (word, &pixel, sizeof pixel); | ||
| 3993 | } | ||
| 3994 | } | ||
| 3995 | } | ||
| 3996 | |||
| 3737 | #else /* ANDROID_STUBIFY */ | 3997 | #else /* ANDROID_STUBIFY */ |
| 3738 | 3998 | ||
| 3739 | /* X emulation functions for Android. */ | 3999 | /* X emulation functions for Android. */ |
| @@ -3793,4 +4053,20 @@ android_put_image (android_pixmap pixmap, | |||
| 3793 | emacs_abort (); | 4053 | emacs_abort (); |
| 3794 | } | 4054 | } |
| 3795 | 4055 | ||
| 4056 | void | ||
| 4057 | android_project_image_bilinear (struct android_image *image, | ||
| 4058 | struct android_image *out, | ||
| 4059 | struct android_transform *transform) | ||
| 4060 | { | ||
| 4061 | emacs_abort (); | ||
| 4062 | } | ||
| 4063 | |||
| 4064 | void | ||
| 4065 | android_project_image_nearest (struct android_image *image, | ||
| 4066 | struct android_image *out, | ||
| 4067 | struct android_transform *transform) | ||
| 4068 | { | ||
| 4069 | emacs_abort (); | ||
| 4070 | } | ||
| 4071 | |||
| 3796 | #endif | 4072 | #endif |
diff --git a/src/androidgui.h b/src/androidgui.h index 9df5b073a7c..1f28c18ff34 100644 --- a/src/androidgui.h +++ b/src/androidgui.h | |||
| @@ -542,6 +542,25 @@ extern struct android_image *android_get_image (android_drawable, | |||
| 542 | enum android_image_format); | 542 | enum android_image_format); |
| 543 | extern void android_put_image (android_pixmap, struct android_image *); | 543 | extern void android_put_image (android_pixmap, struct android_image *); |
| 544 | 544 | ||
| 545 | |||
| 546 | /* Native image transforms. */ | ||
| 547 | |||
| 548 | /* 3x2 matrix describing a projective transform. See | ||
| 549 | android_transform_coordinates for details. */ | ||
| 550 | |||
| 551 | struct android_transform | ||
| 552 | { | ||
| 553 | float m1, m2, m3; | ||
| 554 | float m4, m5, m6; | ||
| 555 | }; | ||
| 556 | |||
| 557 | extern void android_project_image_bilinear (struct android_image *, | ||
| 558 | struct android_image *, | ||
| 559 | struct android_transform *); | ||
| 560 | extern void android_project_image_nearest (struct android_image *, | ||
| 561 | struct android_image *, | ||
| 562 | struct android_transform *); | ||
| 563 | |||
| 545 | 564 | ||
| 546 | 565 | ||
| 547 | /* X emulation stuff also needed while building stubs. */ | 566 | /* X emulation stuff also needed while building stubs. */ |
diff --git a/src/androidterm.c b/src/androidterm.c index 6f452a52d85..cc2da279bb3 100644 --- a/src/androidterm.c +++ b/src/androidterm.c | |||
| @@ -417,8 +417,6 @@ android_note_mouse_movement (struct frame *frame, | |||
| 417 | || event->y < r->y || event->y >= r->y + r->height) | 417 | || event->y < r->y || event->y >= r->y + r->height) |
| 418 | { | 418 | { |
| 419 | frame->mouse_moved = true; | 419 | frame->mouse_moved = true; |
| 420 | /* TODO | ||
| 421 | dpyinfo->last_mouse_scroll_bar = NULL; */ | ||
| 422 | note_mouse_highlight (frame, event->x, event->y); | 420 | note_mouse_highlight (frame, event->x, event->y); |
| 423 | /* Remember which glyph we're now on. */ | 421 | /* Remember which glyph we're now on. */ |
| 424 | remember_mouse_glyph (frame, event->x, event->y, r); | 422 | remember_mouse_glyph (frame, event->x, event->y, r); |
| @@ -2960,9 +2958,33 @@ android_draw_stretch_glyph_string (struct glyph_string *s) | |||
| 2960 | } | 2958 | } |
| 2961 | 2959 | ||
| 2962 | static void | 2960 | static void |
| 2961 | android_get_scale_factor (int *scale_x, int *scale_y) | ||
| 2962 | { | ||
| 2963 | /* This is 96 everywhere else, but 160 on Android. */ | ||
| 2964 | const int base_res = 160; | ||
| 2965 | struct android_display_info *dpyinfo; | ||
| 2966 | |||
| 2967 | dpyinfo = x_display_list; | ||
| 2968 | *scale_x = *scale_y = 1; | ||
| 2969 | |||
| 2970 | if (dpyinfo) | ||
| 2971 | { | ||
| 2972 | if (dpyinfo->resx > base_res) | ||
| 2973 | *scale_x = floor (dpyinfo->resx / base_res); | ||
| 2974 | if (dpyinfo->resy > base_res) | ||
| 2975 | *scale_y = floor (dpyinfo->resy / base_res); | ||
| 2976 | } | ||
| 2977 | } | ||
| 2978 | |||
| 2979 | static void | ||
| 2963 | android_draw_underwave (struct glyph_string *s, int decoration_width) | 2980 | android_draw_underwave (struct glyph_string *s, int decoration_width) |
| 2964 | { | 2981 | { |
| 2965 | int wave_height = 3, wave_length = 2; | 2982 | int scale_x, scale_y; |
| 2983 | |||
| 2984 | android_get_scale_factor (&scale_x, &scale_y); | ||
| 2985 | |||
| 2986 | int wave_height = 3 * scale_y, wave_length = 2 * scale_x; | ||
| 2987 | |||
| 2966 | int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax; | 2988 | int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax; |
| 2967 | bool odd; | 2989 | bool odd; |
| 2968 | struct android_rectangle wave_clip, string_clip, final_clip; | 2990 | struct android_rectangle wave_clip, string_clip, final_clip; |
diff --git a/src/dispextern.h b/src/dispextern.h index 2ceed53813e..bc3556114c5 100644 --- a/src/dispextern.h +++ b/src/dispextern.h | |||
| @@ -3098,8 +3098,9 @@ struct redisplay_interface | |||
| 3098 | 3098 | ||
| 3099 | #ifdef HAVE_WINDOW_SYSTEM | 3099 | #ifdef HAVE_WINDOW_SYSTEM |
| 3100 | 3100 | ||
| 3101 | # if (defined USE_CAIRO || defined HAVE_XRENDER \ | 3101 | # if (defined USE_CAIRO || defined HAVE_XRENDER \ |
| 3102 | || defined HAVE_NS || defined HAVE_NTGUI || defined HAVE_HAIKU) | 3102 | || defined HAVE_NS || defined HAVE_NTGUI || defined HAVE_HAIKU \ |
| 3103 | || defined HAVE_ANDROID) | ||
| 3103 | # define HAVE_NATIVE_TRANSFORMS | 3104 | # define HAVE_NATIVE_TRANSFORMS |
| 3104 | # endif | 3105 | # endif |
| 3105 | 3106 | ||
diff --git a/src/image.c b/src/image.c index 364ddd96e31..16618f49f1e 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -2631,11 +2631,11 @@ compute_image_size (double width, double height, | |||
| 2631 | finally move the origin back to the top left of the image, which | 2631 | finally move the origin back to the top left of the image, which |
| 2632 | may now be a different corner. | 2632 | may now be a different corner. |
| 2633 | 2633 | ||
| 2634 | Note that different GUI backends (X, Cairo, w32, NS, Haiku) want | 2634 | Note that different GUI backends (X, Cairo, w32, NS, Haiku, |
| 2635 | the transform matrix defined as transform from the original image | 2635 | Android) want the transform matrix defined as transform from the |
| 2636 | to the transformed image, while others want the matrix to describe | 2636 | original image to the transformed image, while others want the |
| 2637 | the transform of the space, which boils down to inverting the | 2637 | matrix to describe the transform of the space, which boils down to |
| 2638 | matrix. | 2638 | inverting the matrix. |
| 2639 | 2639 | ||
| 2640 | It's possible to pre-calculate the matrix multiplications and just | 2640 | It's possible to pre-calculate the matrix multiplications and just |
| 2641 | generate one transform matrix that will do everything we need in a | 2641 | generate one transform matrix that will do everything we need in a |
| @@ -2677,6 +2677,96 @@ compute_image_rotation (struct image *img, double *rotation) | |||
| 2677 | *rotation = XFIXNUM (reduced_angle); | 2677 | *rotation = XFIXNUM (reduced_angle); |
| 2678 | } | 2678 | } |
| 2679 | 2679 | ||
| 2680 | #ifdef HAVE_ANDROID | ||
| 2681 | |||
| 2682 | static void | ||
| 2683 | matrix_identity (matrix3x3 matrix) | ||
| 2684 | { | ||
| 2685 | memset (matrix, 0, sizeof (matrix3x3)); | ||
| 2686 | |||
| 2687 | matrix[0][0] = 1.0; | ||
| 2688 | matrix[1][1] = 1.0; | ||
| 2689 | matrix[2][2] = 1.0; | ||
| 2690 | } | ||
| 2691 | |||
| 2692 | /* Translate the matrix TRANSFORM to X, Y, and then perform clockwise | ||
| 2693 | rotation by the given angle THETA in radians and translate back. | ||
| 2694 | As the transform is being performed in a coordinate system where Y | ||
| 2695 | grows downwards, the given angle describes a clockwise | ||
| 2696 | rotation. */ | ||
| 2697 | |||
| 2698 | static void | ||
| 2699 | matrix_rotate (matrix3x3 transform, double theta, double x, double y) | ||
| 2700 | { | ||
| 2701 | matrix3x3 temp, copy; | ||
| 2702 | |||
| 2703 | /* 1. Translate the matrix so X and Y are in the center. */ | ||
| 2704 | |||
| 2705 | matrix_identity (temp); | ||
| 2706 | memcpy (copy, transform, sizeof copy); | ||
| 2707 | |||
| 2708 | temp[0][2] = x; | ||
| 2709 | temp[1][2] = y; | ||
| 2710 | |||
| 2711 | matrix3x3_mult (copy, temp, transform); | ||
| 2712 | matrix_identity (temp); | ||
| 2713 | memcpy (copy, transform, sizeof copy); | ||
| 2714 | |||
| 2715 | /* 2. Rotate the matrix counter-clockwise, assuming a coordinate | ||
| 2716 | system where Y grows downwards. */ | ||
| 2717 | |||
| 2718 | temp[0][0] = cos (theta); | ||
| 2719 | temp[0][1] = -sin (theta); | ||
| 2720 | temp[1][0] = sinf (theta); | ||
| 2721 | temp[1][1] = cosf (theta); | ||
| 2722 | |||
| 2723 | matrix3x3_mult (copy, temp, transform); | ||
| 2724 | matrix_identity (temp); | ||
| 2725 | memcpy (copy, transform, sizeof copy); | ||
| 2726 | |||
| 2727 | /* 3. Translate back. */ | ||
| 2728 | |||
| 2729 | temp[0][2] = -x; | ||
| 2730 | temp[1][2] = -y; | ||
| 2731 | |||
| 2732 | matrix3x3_mult (copy, temp, transform); | ||
| 2733 | } | ||
| 2734 | |||
| 2735 | /* Scale the matrix TRANSFORM by -1, and then apply a TX of width, in | ||
| 2736 | effect flipping the image horizontally. */ | ||
| 2737 | |||
| 2738 | static void | ||
| 2739 | matrix_mirror_horizontal (matrix3x3 transform, double width) | ||
| 2740 | { | ||
| 2741 | matrix3x3 temp, copy; | ||
| 2742 | |||
| 2743 | matrix_identity (temp); | ||
| 2744 | memcpy (copy, transform, sizeof copy); | ||
| 2745 | |||
| 2746 | temp[0][0] = -1.0f; | ||
| 2747 | temp[0][2] = width; | ||
| 2748 | |||
| 2749 | matrix3x3_mult (copy, temp, transform); | ||
| 2750 | } | ||
| 2751 | |||
| 2752 | static void | ||
| 2753 | matrix_translate (matrix3x3 transform, float tx, float ty) | ||
| 2754 | { | ||
| 2755 | matrix3x3 temp, copy; | ||
| 2756 | |||
| 2757 | matrix_identity (temp); | ||
| 2758 | memcpy (copy, transform, sizeof copy); | ||
| 2759 | |||
| 2760 | /* Set the tx and ty. */ | ||
| 2761 | temp[0][2] = tx; | ||
| 2762 | temp[1][2] = ty; | ||
| 2763 | |||
| 2764 | /* Multiply it with the transform. */ | ||
| 2765 | matrix3x3_mult (copy, temp, transform); | ||
| 2766 | } | ||
| 2767 | |||
| 2768 | #endif | ||
| 2769 | |||
| 2680 | static void | 2770 | static void |
| 2681 | image_set_transform (struct frame *f, struct image *img) | 2771 | image_set_transform (struct frame *f, struct image *img) |
| 2682 | { | 2772 | { |
| @@ -2696,6 +2786,14 @@ image_set_transform (struct frame *f, struct image *img) | |||
| 2696 | memcpy (&img->transform, identity, sizeof identity); | 2786 | memcpy (&img->transform, identity, sizeof identity); |
| 2697 | #endif | 2787 | #endif |
| 2698 | 2788 | ||
| 2789 | #if defined HAVE_ANDROID | ||
| 2790 | matrix3x3 identity = { | ||
| 2791 | { 1, 0, 0 }, | ||
| 2792 | { 0, 1, 0 }, | ||
| 2793 | { 0, 0, 1 }, | ||
| 2794 | }; | ||
| 2795 | #endif | ||
| 2796 | |||
| 2699 | # if (defined HAVE_IMAGEMAGICK \ | 2797 | # if (defined HAVE_IMAGEMAGICK \ |
| 2700 | && !defined DONT_CREATE_TRANSFORMED_IMAGEMAGICK_IMAGE) | 2798 | && !defined DONT_CREATE_TRANSFORMED_IMAGEMAGICK_IMAGE) |
| 2701 | /* ImageMagick images already have the correct transform. */ | 2799 | /* ImageMagick images already have the correct transform. */ |
| @@ -2733,7 +2831,8 @@ image_set_transform (struct frame *f, struct image *img) | |||
| 2733 | /* Determine flipping. */ | 2831 | /* Determine flipping. */ |
| 2734 | flip = !NILP (image_spec_value (img->spec, QCflip, NULL)); | 2832 | flip = !NILP (image_spec_value (img->spec, QCflip, NULL)); |
| 2735 | 2833 | ||
| 2736 | # if defined USE_CAIRO || defined HAVE_XRENDER || defined HAVE_NS || defined HAVE_HAIKU | 2834 | # if defined USE_CAIRO || defined HAVE_XRENDER || defined HAVE_NS || defined HAVE_HAIKU \ |
| 2835 | || defined HAVE_ANDROID | ||
| 2737 | /* We want scale up operations to use a nearest neighbor filter to | 2836 | /* We want scale up operations to use a nearest neighbor filter to |
| 2738 | show real pixels instead of munging them, but scale down | 2837 | show real pixels instead of munging them, but scale down |
| 2739 | operations to use a blended filter, to avoid aliasing and the like. | 2838 | operations to use a blended filter, to avoid aliasing and the like. |
| @@ -2755,7 +2854,7 @@ image_set_transform (struct frame *f, struct image *img) | |||
| 2755 | 2854 | ||
| 2756 | matrix3x3 matrix | 2855 | matrix3x3 matrix |
| 2757 | = { | 2856 | = { |
| 2758 | # if defined USE_CAIRO || defined HAVE_XRENDER | 2857 | # if defined USE_CAIRO || defined HAVE_XRENDER || defined HAVE_ANDROID |
| 2759 | [0][0] = (!IEEE_FLOATING_POINT && width == 0 ? DBL_MAX | 2858 | [0][0] = (!IEEE_FLOATING_POINT && width == 0 ? DBL_MAX |
| 2760 | : img->width / (double) width), | 2859 | : img->width / (double) width), |
| 2761 | [1][1] = (!IEEE_FLOATING_POINT && height == 0 ? DBL_MAX | 2860 | [1][1] = (!IEEE_FLOATING_POINT && height == 0 ? DBL_MAX |
| @@ -2778,7 +2877,7 @@ image_set_transform (struct frame *f, struct image *img) | |||
| 2778 | 2877 | ||
| 2779 | /* Haiku needs this, since the transformation is done on the basis | 2878 | /* Haiku needs this, since the transformation is done on the basis |
| 2780 | of the view, and not the image. */ | 2879 | of the view, and not the image. */ |
| 2781 | #ifdef HAVE_HAIKU | 2880 | #if defined HAVE_HAIKU |
| 2782 | int extra_tx, extra_ty; | 2881 | int extra_tx, extra_ty; |
| 2783 | 2882 | ||
| 2784 | extra_tx = 0; | 2883 | extra_tx = 0; |
| @@ -2789,8 +2888,9 @@ image_set_transform (struct frame *f, struct image *img) | |||
| 2789 | rotate_flag = 0; | 2888 | rotate_flag = 0; |
| 2790 | else | 2889 | else |
| 2791 | { | 2890 | { |
| 2792 | # if (defined USE_CAIRO || defined HAVE_XRENDER \ | 2891 | #ifndef HAVE_ANDROID |
| 2793 | || defined HAVE_NTGUI || defined HAVE_NS \ | 2892 | # if (defined USE_CAIRO || defined HAVE_XRENDER \ |
| 2893 | || defined HAVE_NTGUI || defined HAVE_NS \ | ||
| 2794 | || defined HAVE_HAIKU) | 2894 | || defined HAVE_HAIKU) |
| 2795 | int cos_r, sin_r; | 2895 | int cos_r, sin_r; |
| 2796 | if (rotation == 0) | 2896 | if (rotation == 0) |
| @@ -2817,7 +2917,7 @@ image_set_transform (struct frame *f, struct image *img) | |||
| 2817 | sin_r = 1; | 2917 | sin_r = 1; |
| 2818 | rotate_flag = 1; | 2918 | rotate_flag = 1; |
| 2819 | 2919 | ||
| 2820 | #ifdef HAVE_HAIKU | 2920 | #if defined HAVE_HAIKU |
| 2821 | if (!flip) | 2921 | if (!flip) |
| 2822 | extra_ty = height; | 2922 | extra_ty = height; |
| 2823 | extra_tx = 0; | 2923 | extra_tx = 0; |
| @@ -2853,7 +2953,7 @@ image_set_transform (struct frame *f, struct image *img) | |||
| 2853 | 2953 | ||
| 2854 | if (0 < rotate_flag) | 2954 | if (0 < rotate_flag) |
| 2855 | { | 2955 | { |
| 2856 | # if defined USE_CAIRO || defined HAVE_XRENDER | 2956 | # if defined USE_CAIRO || defined HAVE_XRENDER || defined HAVE_ANDROID |
| 2857 | /* 1. Translate so (0, 0) is in the center of the image. */ | 2957 | /* 1. Translate so (0, 0) is in the center of the image. */ |
| 2858 | matrix3x3 t | 2958 | matrix3x3 t |
| 2859 | = { [0][0] = 1, | 2959 | = { [0][0] = 1, |
| @@ -2904,6 +3004,93 @@ image_set_transform (struct frame *f, struct image *img) | |||
| 2904 | img->height = height; | 3004 | img->height = height; |
| 2905 | } | 3005 | } |
| 2906 | # endif | 3006 | # endif |
| 3007 | #else | ||
| 3008 | /* Calculate the inverse transform from the destination to the | ||
| 3009 | source. The matrix is currently identity with scale | ||
| 3010 | applied. | ||
| 3011 | |||
| 3012 | This code makes more sense to me than what lies above. But | ||
| 3013 | I'm not touching what works. */ | ||
| 3014 | |||
| 3015 | if (rotation != 0 && rotation != 90 | ||
| 3016 | && rotation != 180 && rotation != 270) | ||
| 3017 | { | ||
| 3018 | rotate_flag = 0; | ||
| 3019 | goto bail; | ||
| 3020 | } | ||
| 3021 | |||
| 3022 | rotate_flag = 1; | ||
| 3023 | |||
| 3024 | switch ((int) rotation + (flip ? 1 : 0)) | ||
| 3025 | { | ||
| 3026 | case 0: | ||
| 3027 | break; | ||
| 3028 | |||
| 3029 | case 90: | ||
| 3030 | /* Rotate the image 90 degrees clockwise. IOW, rotate the | ||
| 3031 | destination by 90 degrees counterclockwise, which is 270 | ||
| 3032 | degrees clockwise. */ | ||
| 3033 | matrix_rotate (matrix, M_PI * 1.5, 0, 0); | ||
| 3034 | matrix_translate (matrix, -height, 0); | ||
| 3035 | break; | ||
| 3036 | |||
| 3037 | case 180: | ||
| 3038 | /* Apply clockwise 180 degree rotation around the | ||
| 3039 | center. */ | ||
| 3040 | matrix_rotate (matrix, M_PI, width / 2.0, height / 2.0); | ||
| 3041 | break; | ||
| 3042 | |||
| 3043 | case 270: | ||
| 3044 | /* Apply 270 degree counterclockwise rotation to the | ||
| 3045 | destination, which is 90 degrees clockwise. */ | ||
| 3046 | matrix_rotate (matrix, M_PI * 0.5, 0, 0); | ||
| 3047 | matrix_translate (matrix, 0, -width); | ||
| 3048 | break; | ||
| 3049 | |||
| 3050 | case 1: | ||
| 3051 | /* Flipped. Apply horizontal flip. */ | ||
| 3052 | matrix_mirror_horizontal (matrix, width); | ||
| 3053 | break; | ||
| 3054 | |||
| 3055 | case 91: | ||
| 3056 | /* Apply a flip but otherwise treat this the same as 90. */ | ||
| 3057 | matrix_rotate (matrix, M_PI * 1.5, 0, 0); | ||
| 3058 | matrix_translate (matrix, -height, 0); | ||
| 3059 | matrix_mirror_horizontal (matrix, height); | ||
| 3060 | break; | ||
| 3061 | |||
| 3062 | case 181: | ||
| 3063 | /* Flipped 180 degrees. Apply a flip and treat this the | ||
| 3064 | same as 180. */ | ||
| 3065 | matrix_rotate (matrix, M_PI, width / 2.0, height / 2.0); | ||
| 3066 | matrix_mirror_horizontal (matrix, width); | ||
| 3067 | break; | ||
| 3068 | |||
| 3069 | case 271: | ||
| 3070 | /* Flipped 270 degrees. Apply a flip and treat this the | ||
| 3071 | same as 270. */ | ||
| 3072 | matrix_rotate (matrix, M_PI * 0.5, 0, 0); | ||
| 3073 | matrix_translate (matrix, 0, -width); | ||
| 3074 | matrix_mirror_horizontal (matrix, height); | ||
| 3075 | break; | ||
| 3076 | } | ||
| 3077 | |||
| 3078 | /* Now set img->width and img->height. Flip them if the | ||
| 3079 | rotation being applied requires so. */ | ||
| 3080 | |||
| 3081 | if (rotation != 270 && rotation != 90) | ||
| 3082 | { | ||
| 3083 | img->width = width; | ||
| 3084 | img->height = height; | ||
| 3085 | } | ||
| 3086 | else | ||
| 3087 | { | ||
| 3088 | img->height = width; | ||
| 3089 | img->width = height; | ||
| 3090 | } | ||
| 3091 | bail: | ||
| 3092 | ; | ||
| 3093 | #endif | ||
| 2907 | } | 3094 | } |
| 2908 | 3095 | ||
| 2909 | if (rotate_flag < 0) | 3096 | if (rotate_flag < 0) |
| @@ -2968,6 +3155,103 @@ image_set_transform (struct frame *f, struct image *img) | |||
| 2968 | img->transform[0][2] = extra_tx; | 3155 | img->transform[0][2] = extra_tx; |
| 2969 | img->transform[1][2] = extra_ty; | 3156 | img->transform[1][2] = extra_ty; |
| 2970 | } | 3157 | } |
| 3158 | # elif defined HAVE_ANDROID | ||
| 3159 | /* Create a new image of the right size, then turn it into a pixmap | ||
| 3160 | and set that as img->pixmap. Destroy img->mask for now (this is | ||
| 3161 | not right.) */ | ||
| 3162 | |||
| 3163 | struct android_image *transformed_image, *image; | ||
| 3164 | struct android_transform transform; | ||
| 3165 | |||
| 3166 | /* If there is no transform, simply return. */ | ||
| 3167 | if (!memcmp (&matrix, &identity, sizeof matrix)) | ||
| 3168 | return; | ||
| 3169 | |||
| 3170 | /* First, get the source image. */ | ||
| 3171 | image = image_get_x_image (f, img, false); | ||
| 3172 | |||
| 3173 | /* Make the transformed image. */ | ||
| 3174 | transformed_image = android_create_image (image->depth, | ||
| 3175 | ANDROID_Z_PIXMAP, | ||
| 3176 | NULL, img->width, | ||
| 3177 | img->height); | ||
| 3178 | |||
| 3179 | /* Allocate memory for that image. */ | ||
| 3180 | transformed_image->data | ||
| 3181 | = xmalloc (transformed_image->bytes_per_line | ||
| 3182 | * transformed_image->height); | ||
| 3183 | |||
| 3184 | /* Do the transform. */ | ||
| 3185 | transform.m1 = matrix[0][0]; | ||
| 3186 | transform.m2 = matrix[0][1]; | ||
| 3187 | transform.m3 = matrix[0][2]; | ||
| 3188 | transform.m4 = matrix[1][0]; | ||
| 3189 | transform.m5 = matrix[1][1]; | ||
| 3190 | transform.m6 = matrix[1][2]; | ||
| 3191 | |||
| 3192 | if (image->depth == 24 && smoothing) | ||
| 3193 | android_project_image_bilinear (image, transformed_image, | ||
| 3194 | &transform); | ||
| 3195 | else | ||
| 3196 | android_project_image_nearest (image, transformed_image, | ||
| 3197 | &transform); | ||
| 3198 | |||
| 3199 | image_unget_x_image (img, false, image); | ||
| 3200 | |||
| 3201 | /* Now replace the image. */ | ||
| 3202 | |||
| 3203 | if (img->ximg) | ||
| 3204 | image_destroy_x_image (img->ximg); | ||
| 3205 | |||
| 3206 | img->ximg = transformed_image; | ||
| 3207 | |||
| 3208 | #ifndef ANDROID_STUBIFY | ||
| 3209 | /* Then replace the pixmap. */ | ||
| 3210 | android_free_pixmap (img->pixmap); | ||
| 3211 | |||
| 3212 | /* In case android_create_pixmap signals. */ | ||
| 3213 | img->pixmap = ANDROID_NONE; | ||
| 3214 | img->pixmap = android_create_pixmap (img->width, img->height, | ||
| 3215 | transformed_image->depth); | ||
| 3216 | android_put_image (img->pixmap, transformed_image); | ||
| 3217 | #else | ||
| 3218 | emacs_abort (); | ||
| 3219 | #endif | ||
| 3220 | |||
| 3221 | /* Now, transform the mask. The mask should be depth 1, and is | ||
| 3222 | always transformed using a nearest neighbor filter. */ | ||
| 3223 | |||
| 3224 | if (img->mask_img || img->mask) | ||
| 3225 | { | ||
| 3226 | image = image_get_x_image (f, img, true); | ||
| 3227 | transformed_image = android_create_image (1, ANDROID_Z_PIXMAP, | ||
| 3228 | NULL, img->width, | ||
| 3229 | img->height); | ||
| 3230 | transformed_image->data | ||
| 3231 | = xmalloc (transformed_image->bytes_per_line | ||
| 3232 | * transformed_image->height); | ||
| 3233 | android_project_image_nearest (image, transformed_image, | ||
| 3234 | &transform); | ||
| 3235 | image_unget_x_image (img, false, image); | ||
| 3236 | |||
| 3237 | /* Now replace the image. */ | ||
| 3238 | |||
| 3239 | if (img->mask_img) | ||
| 3240 | image_destroy_x_image (img->mask_img); | ||
| 3241 | |||
| 3242 | img->mask_img = transformed_image; | ||
| 3243 | |||
| 3244 | #ifndef ANDROID_STUBIFY | ||
| 3245 | if (img->mask) | ||
| 3246 | android_free_pixmap (img->mask); | ||
| 3247 | |||
| 3248 | img->mask = ANDROID_NONE; | ||
| 3249 | img->mask = android_create_pixmap (img->width, img->height, 1); | ||
| 3250 | android_put_image (img->mask, transformed_image); | ||
| 3251 | #endif | ||
| 3252 | } | ||
| 3253 | |||
| 3254 | /* Done! */ | ||
| 2971 | #endif | 3255 | #endif |
| 2972 | } | 3256 | } |
| 2973 | 3257 | ||
| @@ -12087,7 +12371,7 @@ The list of capabilities can include one or more of the following: | |||
| 12087 | { | 12371 | { |
| 12088 | #ifdef HAVE_NATIVE_TRANSFORMS | 12372 | #ifdef HAVE_NATIVE_TRANSFORMS |
| 12089 | # if defined HAVE_IMAGEMAGICK || defined (USE_CAIRO) || defined (HAVE_NS) \ | 12373 | # if defined HAVE_IMAGEMAGICK || defined (USE_CAIRO) || defined (HAVE_NS) \ |
| 12090 | || defined (HAVE_HAIKU) | 12374 | || defined (HAVE_HAIKU) | defined HAVE_ANDROID |
| 12091 | return list2 (Qscale, Qrotate90); | 12375 | return list2 (Qscale, Qrotate90); |
| 12092 | # elif defined (HAVE_X_WINDOWS) && defined (HAVE_XRENDER) | 12376 | # elif defined (HAVE_X_WINDOWS) && defined (HAVE_XRENDER) |
| 12093 | if (FRAME_DISPLAY_INFO (f)->xrender_supported_p) | 12377 | if (FRAME_DISPLAY_INFO (f)->xrender_supported_p) |
diff --git a/src/keyboard.c b/src/keyboard.c index 78637ef4f15..306fea354e2 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -339,6 +339,10 @@ static struct timespec timer_last_idleness_start_time; | |||
| 339 | static Lisp_Object virtual_core_pointer_name; | 339 | static Lisp_Object virtual_core_pointer_name; |
| 340 | static Lisp_Object virtual_core_keyboard_name; | 340 | static Lisp_Object virtual_core_keyboard_name; |
| 341 | 341 | ||
| 342 | /* If not nil, ID of the last TOUCHSCREEN_END_EVENT to land on the | ||
| 343 | menu bar. */ | ||
| 344 | static Lisp_Object menu_bar_touch_id; | ||
| 345 | |||
| 342 | 346 | ||
| 343 | /* Global variable declarations. */ | 347 | /* Global variable declarations. */ |
| 344 | 348 | ||
| @@ -6445,11 +6449,74 @@ make_lispy_event (struct input_event *event) | |||
| 6445 | { | 6449 | { |
| 6446 | Lisp_Object x, y, id, position; | 6450 | Lisp_Object x, y, id, position; |
| 6447 | struct frame *f = XFRAME (event->frame_or_window); | 6451 | struct frame *f = XFRAME (event->frame_or_window); |
| 6452 | #if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR | ||
| 6453 | int column, row, dummy; | ||
| 6454 | #endif | ||
| 6448 | 6455 | ||
| 6449 | id = event->arg; | 6456 | id = event->arg; |
| 6450 | x = event->x; | 6457 | x = event->x; |
| 6451 | y = event->y; | 6458 | y = event->y; |
| 6452 | 6459 | ||
| 6460 | #if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR | ||
| 6461 | if (event->kind == TOUCHSCREEN_BEGIN_EVENT | ||
| 6462 | && coords_in_menu_bar_window (f, XFIXNUM (x), XFIXNUM (y))) | ||
| 6463 | { | ||
| 6464 | /* If the tap began in the menu bar window, then save the | ||
| 6465 | id. */ | ||
| 6466 | menu_bar_touch_id = id; | ||
| 6467 | return Qnil; | ||
| 6468 | } | ||
| 6469 | else if (event->kind == TOUCHSCREEN_END_EVENT | ||
| 6470 | && EQ (menu_bar_touch_id, id)) | ||
| 6471 | { | ||
| 6472 | /* This touch should activate the menu bar. Generate the | ||
| 6473 | menu bar event. */ | ||
| 6474 | menu_bar_touch_id = Qnil; | ||
| 6475 | |||
| 6476 | if (f->menu_bar_window) | ||
| 6477 | { | ||
| 6478 | x_y_to_hpos_vpos (XWINDOW (f->menu_bar_window), XFIXNUM (x), | ||
| 6479 | XFIXNUM (y), &column, &row, NULL, NULL, | ||
| 6480 | &dummy); | ||
| 6481 | |||
| 6482 | if (row >= 0 && row < FRAME_MENU_BAR_LINES (f)) | ||
| 6483 | { | ||
| 6484 | Lisp_Object items, item; | ||
| 6485 | |||
| 6486 | /* Find the menu bar item under `column'. */ | ||
| 6487 | item = Qnil; | ||
| 6488 | items = FRAME_MENU_BAR_ITEMS (f); | ||
| 6489 | for (i = 0; i < ASIZE (items); i += 4) | ||
| 6490 | { | ||
| 6491 | Lisp_Object pos, string; | ||
| 6492 | string = AREF (items, i + 1); | ||
| 6493 | pos = AREF (items, i + 3); | ||
| 6494 | if (NILP (string)) | ||
| 6495 | break; | ||
| 6496 | if (column >= XFIXNUM (pos) | ||
| 6497 | && column < XFIXNUM (pos) + SCHARS (string)) | ||
| 6498 | { | ||
| 6499 | item = AREF (items, i); | ||
| 6500 | break; | ||
| 6501 | } | ||
| 6502 | } | ||
| 6503 | |||
| 6504 | /* ELisp manual 2.4b says (x y) are window | ||
| 6505 | relative but code says they are | ||
| 6506 | frame-relative. */ | ||
| 6507 | position = list4 (event->frame_or_window, | ||
| 6508 | Qmenu_bar, | ||
| 6509 | Fcons (event->x, event->y), | ||
| 6510 | INT_TO_INTEGER (event->timestamp)); | ||
| 6511 | |||
| 6512 | return list2 (item, position); | ||
| 6513 | } | ||
| 6514 | } | ||
| 6515 | |||
| 6516 | return Qnil; | ||
| 6517 | } | ||
| 6518 | #endif | ||
| 6519 | |||
| 6453 | position = make_lispy_position (f, x, y, event->timestamp); | 6520 | position = make_lispy_position (f, x, y, event->timestamp); |
| 6454 | 6521 | ||
| 6455 | return list2 (((event->kind | 6522 | return list2 (((event->kind |
| @@ -12462,6 +12529,9 @@ syms_of_keyboard (void) | |||
| 12462 | virtual_core_keyboard_name = Qnil; | 12529 | virtual_core_keyboard_name = Qnil; |
| 12463 | staticpro (&virtual_core_keyboard_name); | 12530 | staticpro (&virtual_core_keyboard_name); |
| 12464 | 12531 | ||
| 12532 | menu_bar_touch_id = Qnil; | ||
| 12533 | staticpro (&menu_bar_touch_id); | ||
| 12534 | |||
| 12465 | defsubr (&Scurrent_idle_time); | 12535 | defsubr (&Scurrent_idle_time); |
| 12466 | defsubr (&Sevent_symbol_parse_modifiers); | 12536 | defsubr (&Sevent_symbol_parse_modifiers); |
| 12467 | defsubr (&Sevent_convert_list); | 12537 | defsubr (&Sevent_convert_list); |
diff --git a/src/sfnt.c b/src/sfnt.c index 9b6c421212a..09fda82382b 100644 --- a/src/sfnt.c +++ b/src/sfnt.c | |||
| @@ -3436,7 +3436,7 @@ sfnt_compare_edges (const void *a, const void *b) | |||
| 3436 | that now overlap with Y, keeping them sorted by X. Poly those | 3436 | that now overlap with Y, keeping them sorted by X. Poly those |
| 3437 | edges through SPAN_FUNC. Then, move upwards by SFNT_POLY_STEP, | 3437 | edges through SPAN_FUNC. Then, move upwards by SFNT_POLY_STEP, |
| 3438 | remove edges that no longer apply, and interpolate the remaining | 3438 | remove edges that no longer apply, and interpolate the remaining |
| 3439 | edge's X coordinates. Repeat until all the edges have been polyed. | 3439 | edges' X coordinates. Repeat until all the edges have been polyed. |
| 3440 | 3440 | ||
| 3441 | Or alternatively, think of this as such: each edge is actually a | 3441 | Or alternatively, think of this as such: each edge is actually a |
| 3442 | vector from its bottom position towards its top most position. | 3442 | vector from its bottom position towards its top most position. |
diff --git a/src/sfntfont-android.c b/src/sfntfont-android.c index 01bfdbaaf58..cddb3fd40f3 100644 --- a/src/sfntfont-android.c +++ b/src/sfntfont-android.c | |||
| @@ -73,48 +73,22 @@ sfntfont_android_mul8x2 (unsigned int a8, unsigned int b32) | |||
| 73 | return (i + ((i >> 8) & 0xff00ff)) >> 8 & 0xff00ff; | 73 | return (i + ((i >> 8) & 0xff00ff)) >> 8 & 0xff00ff; |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | /* Blend two pixels SRC and DST without utilizing any control flow. | ||
| 77 | SRC must be in premultiplied ARGB8888 format, and DST must be in | ||
| 78 | premultiplied ABGR8888 format. Value is in premultiplied ABGR8888 | ||
| 79 | format. */ | ||
| 80 | |||
| 81 | static unsigned int | ||
| 82 | sfntfont_android_blend (unsigned int src, unsigned int dst) | ||
| 83 | { | ||
| 84 | unsigned int a, br_part, ag_part, src_rb, both; | ||
| 85 | |||
| 86 | a = (src >> 24); | ||
| 87 | br_part = sfntfont_android_mul8x2 (255 - a, dst); | ||
| 88 | ag_part = sfntfont_android_mul8x2 (255 - a, dst >> 8) << 8; | ||
| 89 | |||
| 90 | both = ag_part | br_part; | ||
| 91 | |||
| 92 | /* Swizzle src. */ | ||
| 93 | src_rb = src & 0x00ff00ff; | ||
| 94 | src = src & ~0x00ff00ff; | ||
| 95 | src |= (src_rb >> 16 | src_rb << 16); | ||
| 96 | |||
| 97 | /* This addition need not be saturating because both has already | ||
| 98 | been multiplied by 255 - a. */ | ||
| 99 | return both + src; | ||
| 100 | } | ||
| 101 | |||
| 102 | #define U255TO256(x) ((unsigned short) (x) + ((x) >> 7)) | 76 | #define U255TO256(x) ((unsigned short) (x) + ((x) >> 7)) |
| 103 | 77 | ||
| 104 | /* Blend two pixels SRC and DST without utilizing any control flow. | 78 | /* Blend two pixels SRC and DST without utilizing any control flow. |
| 105 | Both SRC and DST are expected to be in premultiplied ARGB8888 | 79 | Both SRC and DST are expected to be in premultiplied ABGB8888 |
| 106 | format. Value is returned in premultiplied ARGB8888 format. */ | 80 | format. Value is returned in premultiplied ARGB8888 format. */ |
| 107 | 81 | ||
| 108 | static unsigned int | 82 | static unsigned int |
| 109 | sfntfont_android_blendrgb (unsigned int src, unsigned int dst) | 83 | sfntfont_android_blend (unsigned int src, unsigned int dst) |
| 110 | { | 84 | { |
| 111 | unsigned int a, rb_part, ag_part, both; | 85 | unsigned int a, br_part, ag_part, both; |
| 112 | 86 | ||
| 113 | a = (src >> 24); | 87 | a = (src >> 24); |
| 114 | rb_part = sfntfont_android_mul8x2 (255 - a, dst); | 88 | br_part = sfntfont_android_mul8x2 (255 - a, dst); |
| 115 | ag_part = sfntfont_android_mul8x2 (255 - a, dst >> 8) << 8; | 89 | ag_part = sfntfont_android_mul8x2 (255 - a, dst >> 8) << 8; |
| 116 | 90 | ||
| 117 | both = ag_part | rb_part; | 91 | both = ag_part | br_part; |
| 118 | 92 | ||
| 119 | /* This addition need not be saturating because both has already | 93 | /* This addition need not be saturating because both has already |
| 120 | been multiplied by 255 - a. */ | 94 | been multiplied by 255 - a. */ |
| @@ -210,6 +184,7 @@ sfntfont_android_put_glyphs (struct glyph_string *s, int from, | |||
| 210 | jobject bitmap; | 184 | jobject bitmap; |
| 211 | int left, top, temp_y; | 185 | int left, top, temp_y; |
| 212 | unsigned int prod, raster_y; | 186 | unsigned int prod, raster_y; |
| 187 | unsigned long foreground, back_pixel, rb; | ||
| 213 | 188 | ||
| 214 | if (!s->gc->num_clip_rects) | 189 | if (!s->gc->num_clip_rects) |
| 215 | /* Clip region is empty. */ | 190 | /* Clip region is empty. */ |
| @@ -219,6 +194,17 @@ sfntfont_android_put_glyphs (struct glyph_string *s, int from, | |||
| 219 | /* Nothing to draw. */ | 194 | /* Nothing to draw. */ |
| 220 | return; | 195 | return; |
| 221 | 196 | ||
| 197 | /* Swizzle the foreground and background in s->gc into BGR, then add | ||
| 198 | an alpha channel. */ | ||
| 199 | foreground = s->gc->foreground; | ||
| 200 | back_pixel = s->gc->background; | ||
| 201 | rb = foreground & 0x00ff00ff; | ||
| 202 | foreground &= ~0x00ff00ff; | ||
| 203 | foreground |= rb >> 16 | rb << 16 | 0xff000000; | ||
| 204 | rb = back_pixel & 0x00ff00ff; | ||
| 205 | back_pixel &= ~0x00ff00ff; | ||
| 206 | back_pixel |= rb >> 16 | rb << 16 | 0xff000000; | ||
| 207 | |||
| 222 | USE_SAFE_ALLOCA; | 208 | USE_SAFE_ALLOCA; |
| 223 | 209 | ||
| 224 | prepare_face_for_display (s->f, s->face); | 210 | prepare_face_for_display (s->f, s->face); |
| @@ -294,7 +280,7 @@ sfntfont_android_put_glyphs (struct glyph_string *s, int from, | |||
| 294 | + stride * temp_y); | 280 | + stride * temp_y); |
| 295 | 281 | ||
| 296 | for (x = background.x; x < background.x + background.width; ++x) | 282 | for (x = background.x; x < background.x + background.width; ++x) |
| 297 | row[x] = s->gc->background | 0xff000000; | 283 | row[x] = back_pixel; |
| 298 | } | 284 | } |
| 299 | } | 285 | } |
| 300 | 286 | ||
| @@ -327,10 +313,9 @@ sfntfont_android_put_glyphs (struct glyph_string *s, int from, | |||
| 327 | { | 313 | { |
| 328 | prod | 314 | prod |
| 329 | = sfntfont_android_scale32 (U255TO256 (raster_row[x]), | 315 | = sfntfont_android_scale32 (U255TO256 (raster_row[x]), |
| 330 | (s->gc->foreground | 316 | foreground); |
| 331 | | 0xff000000)); | ||
| 332 | row[left + x] | 317 | row[left + x] |
| 333 | = sfntfont_android_blendrgb (prod, row[left + x]); | 318 | = sfntfont_android_blend (prod, row[left + x]); |
| 334 | } | 319 | } |
| 335 | } | 320 | } |
| 336 | } | 321 | } |
diff --git a/src/sfntfont.c b/src/sfntfont.c index 25cea59f6a7..56977622211 100644 --- a/src/sfntfont.c +++ b/src/sfntfont.c | |||
| @@ -860,7 +860,7 @@ sfntfont_lookup_char (struct sfnt_font_desc *desc, Lisp_Object character, | |||
| 860 | /* Emacs missing charsets? */ | 860 | /* Emacs missing charsets? */ |
| 861 | return false; | 861 | return false; |
| 862 | 862 | ||
| 863 | font_character = ENCODE_CHAR (charset, XFIXNUM (character)); | 863 | font_character = ENCODE_CHAR (charset, (int) XFIXNUM (character)); |
| 864 | 864 | ||
| 865 | if (font_character == CHARSET_INVALID_CODE (charset)) | 865 | if (font_character == CHARSET_INVALID_CODE (charset)) |
| 866 | return false; | 866 | return false; |