diff options
| author | Po Lu | 2023-03-13 09:58:52 +0800 |
|---|---|---|
| committer | Po Lu | 2023-03-13 09:58:52 +0800 |
| commit | c3524b15aa77b309f325fcb806fe9e9c91c4e99e (patch) | |
| tree | 2498b189ef6a68d1969e97dcd44097056d5bf74d /src | |
| parent | a517c24697d080475e2d531c8ce1d433aa44a9c6 (diff) | |
| download | emacs-c3524b15aa77b309f325fcb806fe9e9c91c4e99e.tar.gz emacs-c3524b15aa77b309f325fcb806fe9e9c91c4e99e.zip | |
Update Android port
* src/image.c (image_create_bitmap_from_file, image_find_image_fd)
(close_android_fd, slurp_file): Return and use `struct
android_fd_or_asset' on Android.
(xbm_load, xpm_load, pbm_load, png_load_body, jpeg_load_body)
(webp_load, svg_load): Adjust accordingly.
Diffstat (limited to 'src')
| -rw-r--r-- | src/image.c | 107 |
1 files changed, 91 insertions, 16 deletions
diff --git a/src/image.c b/src/image.c index a244b23ecd2..dc45a2d2419 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -652,9 +652,19 @@ image_create_bitmap_from_data (struct frame *f, char *bits, | |||
| 652 | return id; | 652 | return id; |
| 653 | } | 653 | } |
| 654 | 654 | ||
| 655 | #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY | ||
| 656 | #include "android.h" | ||
| 657 | |||
| 658 | /* This abstraction allows directly loading images from assets without | ||
| 659 | copying them to a file descriptor first. */ | ||
| 660 | typedef struct android_fd_or_asset image_fd; | ||
| 661 | #else /* !defined HAVE_ANDROID || defined ANDROID_STUBIFY */ | ||
| 662 | typedef int image_fd; | ||
| 663 | #endif /* defined HAVE_ANDROID && !defined ANDROID_STUBIFY */ | ||
| 664 | |||
| 655 | #if defined HAVE_HAIKU || defined HAVE_NS || defined HAVE_ANDROID | 665 | #if defined HAVE_HAIKU || defined HAVE_NS || defined HAVE_ANDROID |
| 656 | static char *slurp_file (int, ptrdiff_t *); | 666 | static char *slurp_file (image_fd, ptrdiff_t *); |
| 657 | static Lisp_Object image_find_image_fd (Lisp_Object, int *); | 667 | static Lisp_Object image_find_image_fd (Lisp_Object, image_fd *); |
| 658 | static bool xbm_read_bitmap_data (struct frame *, char *, char *, | 668 | static bool xbm_read_bitmap_data (struct frame *, char *, char *, |
| 659 | int *, int *, char **, bool); | 669 | int *, int *, char **, bool); |
| 660 | #endif | 670 | #endif |
| @@ -877,7 +887,8 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) | |||
| 877 | emacs_abort (); | 887 | emacs_abort (); |
| 878 | #else | 888 | #else |
| 879 | ptrdiff_t id, size; | 889 | ptrdiff_t id, size; |
| 880 | int fd, width, height, rc; | 890 | int width, height, rc; |
| 891 | image_fd fd; | ||
| 881 | char *contents, *data; | 892 | char *contents, *data; |
| 882 | Lisp_Object found; | 893 | Lisp_Object found; |
| 883 | android_pixmap bitmap; | 894 | android_pixmap bitmap; |
| @@ -4135,10 +4146,11 @@ image_unget_x_image (struct image *img, bool mask_p, Emacs_Pix_Container ximg) | |||
| 4135 | PFD is null, do not open the file. */ | 4146 | PFD is null, do not open the file. */ |
| 4136 | 4147 | ||
| 4137 | static Lisp_Object | 4148 | static Lisp_Object |
| 4138 | image_find_image_fd (Lisp_Object file, int *pfd) | 4149 | image_find_image_fd (Lisp_Object file, image_fd *pfd) |
| 4139 | { | 4150 | { |
| 4140 | Lisp_Object file_found, search_path; | 4151 | Lisp_Object file_found, search_path; |
| 4141 | int fd; | 4152 | int fd; |
| 4153 | void *platform; | ||
| 4142 | 4154 | ||
| 4143 | /* TODO I think this should use something like image-load-path | 4155 | /* TODO I think this should use something like image-load-path |
| 4144 | instead. Unfortunately, that can contain non-string elements. */ | 4156 | instead. Unfortunately, that can contain non-string elements. */ |
| @@ -4147,9 +4159,10 @@ image_find_image_fd (Lisp_Object file, int *pfd) | |||
| 4147 | Vx_bitmap_file_path); | 4159 | Vx_bitmap_file_path); |
| 4148 | 4160 | ||
| 4149 | /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */ | 4161 | /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */ |
| 4162 | platform = NULL; | ||
| 4150 | fd = openp (search_path, file, Qnil, &file_found, | 4163 | fd = openp (search_path, file, Qnil, &file_found, |
| 4151 | pfd ? Qt : make_fixnum (R_OK), false, false, | 4164 | pfd ? Qt : make_fixnum (R_OK), false, false, |
| 4152 | NULL); | 4165 | pfd ? &platform : NULL); |
| 4153 | if (fd == -2) | 4166 | if (fd == -2) |
| 4154 | { | 4167 | { |
| 4155 | /* The file exists locally, but has a file name handler. | 4168 | /* The file exists locally, but has a file name handler. |
| @@ -4159,10 +4172,23 @@ image_find_image_fd (Lisp_Object file, int *pfd) | |||
| 4159 | Lisp_Object encoded_name = ENCODE_FILE (file_found); | 4172 | Lisp_Object encoded_name = ENCODE_FILE (file_found); |
| 4160 | fd = emacs_open (SSDATA (encoded_name), O_RDONLY, 0); | 4173 | fd = emacs_open (SSDATA (encoded_name), O_RDONLY, 0); |
| 4161 | } | 4174 | } |
| 4162 | else if (fd < 0) | 4175 | /* FD is -3 if PLATFORM is set to a valid asset file descriptor on |
| 4176 | Android. */ | ||
| 4177 | else if (fd < 0 && fd != -3) | ||
| 4163 | return Qnil; | 4178 | return Qnil; |
| 4179 | |||
| 4180 | #if !defined HAVE_ANDROID || defined ANDROID_STUBIFY | ||
| 4164 | if (pfd) | 4181 | if (pfd) |
| 4165 | *pfd = fd; | 4182 | *pfd = fd; |
| 4183 | #else | ||
| 4184 | /* Construct an asset file descriptor. */ | ||
| 4185 | |||
| 4186 | if (pfd) | ||
| 4187 | { | ||
| 4188 | pfd->fd = fd; | ||
| 4189 | pfd->asset = platform; | ||
| 4190 | } | ||
| 4191 | #endif | ||
| 4166 | return file_found; | 4192 | return file_found; |
| 4167 | } | 4193 | } |
| 4168 | 4194 | ||
| @@ -4176,14 +4202,25 @@ image_find_image_file (Lisp_Object file) | |||
| 4176 | return image_find_image_fd (file, 0); | 4202 | return image_find_image_fd (file, 0); |
| 4177 | } | 4203 | } |
| 4178 | 4204 | ||
| 4205 | #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY | ||
| 4206 | |||
| 4207 | static void | ||
| 4208 | close_android_fd (void *ptr) | ||
| 4209 | { | ||
| 4210 | android_close_asset (*(struct android_fd_or_asset *) ptr); | ||
| 4211 | } | ||
| 4212 | |||
| 4213 | #endif | ||
| 4214 | |||
| 4179 | /* Read FILE into memory. Value is a pointer to a buffer allocated | 4215 | /* Read FILE into memory. Value is a pointer to a buffer allocated |
| 4180 | with xmalloc holding FILE's contents. Value is null if an error | 4216 | with xmalloc holding FILE's contents. Value is null if an error |
| 4181 | occurred. FD is a file descriptor open for reading FILE. Set | 4217 | occurred. FD is a file descriptor open for reading FILE. Set |
| 4182 | *SIZE to the size of the file. */ | 4218 | *SIZE to the size of the file. */ |
| 4183 | 4219 | ||
| 4184 | static char * | 4220 | static char * |
| 4185 | slurp_file (int fd, ptrdiff_t *size) | 4221 | slurp_file (image_fd fd, ptrdiff_t *size) |
| 4186 | { | 4222 | { |
| 4223 | #if !defined HAVE_ANDROID || defined ANDROID_STUBIFY | ||
| 4187 | FILE *fp = fdopen (fd, "rb"); | 4224 | FILE *fp = fdopen (fd, "rb"); |
| 4188 | 4225 | ||
| 4189 | char *buf = NULL; | 4226 | char *buf = NULL; |
| @@ -4212,6 +4249,39 @@ slurp_file (int fd, ptrdiff_t *size) | |||
| 4212 | 4249 | ||
| 4213 | unbind_to (count, Qnil); | 4250 | unbind_to (count, Qnil); |
| 4214 | } | 4251 | } |
| 4252 | #else | ||
| 4253 | char *buf; | ||
| 4254 | struct stat st; | ||
| 4255 | specpdl_ref count; | ||
| 4256 | |||
| 4257 | if (!android_asset_fstat (fd, &st) | ||
| 4258 | && (0 <= st.st_size | ||
| 4259 | && st.st_size < min (PTRDIFF_MAX, SIZE_MAX))) | ||
| 4260 | { | ||
| 4261 | count = SPECPDL_INDEX (); | ||
| 4262 | record_unwind_protect_ptr (close_android_fd, &fd); | ||
| 4263 | buf = xmalloc (st.st_size + 1); | ||
| 4264 | |||
| 4265 | /* Read one byte past the end of the file. That allows | ||
| 4266 | detecting if the file grows as it is being read. */ | ||
| 4267 | |||
| 4268 | if (android_asset_read (fd, buf, | ||
| 4269 | st.st_size + 1) == st.st_size) | ||
| 4270 | *size = st.st_size; | ||
| 4271 | else | ||
| 4272 | { | ||
| 4273 | xfree (buf); | ||
| 4274 | buf = NULL; | ||
| 4275 | } | ||
| 4276 | |||
| 4277 | unbind_to (count, Qnil); | ||
| 4278 | } | ||
| 4279 | else | ||
| 4280 | { | ||
| 4281 | buf = NULL; | ||
| 4282 | android_close_asset (fd); | ||
| 4283 | } | ||
| 4284 | #endif | ||
| 4215 | 4285 | ||
| 4216 | return buf; | 4286 | return buf; |
| 4217 | } | 4287 | } |
| @@ -4934,7 +5004,7 @@ xbm_load (struct frame *f, struct image *img) | |||
| 4934 | file_name = image_spec_value (img->spec, QCfile, NULL); | 5004 | file_name = image_spec_value (img->spec, QCfile, NULL); |
| 4935 | if (STRINGP (file_name)) | 5005 | if (STRINGP (file_name)) |
| 4936 | { | 5006 | { |
| 4937 | int fd; | 5007 | image_fd fd; |
| 4938 | Lisp_Object file = image_find_image_fd (file_name, &fd); | 5008 | Lisp_Object file = image_find_image_fd (file_name, &fd); |
| 4939 | if (!STRINGP (file)) | 5009 | if (!STRINGP (file)) |
| 4940 | { | 5010 | { |
| @@ -6230,7 +6300,7 @@ xpm_load (struct frame *f, | |||
| 6230 | file_name = image_spec_value (img->spec, QCfile, NULL); | 6300 | file_name = image_spec_value (img->spec, QCfile, NULL); |
| 6231 | if (STRINGP (file_name)) | 6301 | if (STRINGP (file_name)) |
| 6232 | { | 6302 | { |
| 6233 | int fd; | 6303 | image_fd fd; |
| 6234 | Lisp_Object file = image_find_image_fd (file_name, &fd); | 6304 | Lisp_Object file = image_find_image_fd (file_name, &fd); |
| 6235 | if (!STRINGP (file)) | 6305 | if (!STRINGP (file)) |
| 6236 | { | 6306 | { |
| @@ -7259,7 +7329,7 @@ pbm_load (struct frame *f, struct image *img) | |||
| 7259 | 7329 | ||
| 7260 | if (STRINGP (specified_file)) | 7330 | if (STRINGP (specified_file)) |
| 7261 | { | 7331 | { |
| 7262 | int fd; | 7332 | image_fd fd; |
| 7263 | Lisp_Object file = image_find_image_fd (specified_file, &fd); | 7333 | Lisp_Object file = image_find_image_fd (specified_file, &fd); |
| 7264 | if (!STRINGP (file)) | 7334 | if (!STRINGP (file)) |
| 7265 | { | 7335 | { |
| @@ -7927,8 +7997,11 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) | |||
| 7927 | if (NILP (specified_data)) | 7997 | if (NILP (specified_data)) |
| 7928 | { | 7998 | { |
| 7929 | int fd; | 7999 | int fd; |
| 7930 | Lisp_Object file = image_find_image_fd (specified_file, &fd); | 8000 | Lisp_Object file = image_find_image_file (specified_file); |
| 7931 | if (!STRINGP (file)) | 8001 | |
| 8002 | if (!STRINGP (file) | ||
| 8003 | || (fd = emacs_open (SSDATA (ENCODE_FILE (file)), | ||
| 8004 | O_RDONLY, 0)) < 0) | ||
| 7932 | { | 8005 | { |
| 7933 | image_error ("Cannot find image file `%s'", specified_file); | 8006 | image_error ("Cannot find image file `%s'", specified_file); |
| 7934 | return 0; | 8007 | return 0; |
| @@ -8655,8 +8728,10 @@ jpeg_load_body (struct frame *f, struct image *img, | |||
| 8655 | if (NILP (specified_data)) | 8728 | if (NILP (specified_data)) |
| 8656 | { | 8729 | { |
| 8657 | int fd; | 8730 | int fd; |
| 8658 | Lisp_Object file = image_find_image_fd (specified_file, &fd); | 8731 | Lisp_Object file = image_find_image_file (specified_file); |
| 8659 | if (!STRINGP (file)) | 8732 | if (!STRINGP (file) |
| 8733 | || (fd = emacs_open (SSDATA (ENCODE_FILE (file)), | ||
| 8734 | O_RDONLY, 0)) < 0) | ||
| 8660 | { | 8735 | { |
| 8661 | image_error ("Cannot find image file `%s'", specified_file); | 8736 | image_error ("Cannot find image file `%s'", specified_file); |
| 8662 | return 0; | 8737 | return 0; |
| @@ -10153,7 +10228,7 @@ webp_load (struct frame *f, struct image *img) | |||
| 10153 | 10228 | ||
| 10154 | if (NILP (specified_data)) | 10229 | if (NILP (specified_data)) |
| 10155 | { | 10230 | { |
| 10156 | int fd; | 10231 | image_fd fd; |
| 10157 | file = image_find_image_fd (specified_file, &fd); | 10232 | file = image_find_image_fd (specified_file, &fd); |
| 10158 | if (!STRINGP (file)) | 10233 | if (!STRINGP (file)) |
| 10159 | { | 10234 | { |
| @@ -11552,7 +11627,7 @@ svg_load (struct frame *f, struct image *img) | |||
| 11552 | base_uri = image_spec_value (img->spec, QCbase_uri, NULL); | 11627 | base_uri = image_spec_value (img->spec, QCbase_uri, NULL); |
| 11553 | if (STRINGP (file_name)) | 11628 | if (STRINGP (file_name)) |
| 11554 | { | 11629 | { |
| 11555 | int fd; | 11630 | image_fd fd; |
| 11556 | Lisp_Object file = image_find_image_fd (file_name, &fd); | 11631 | Lisp_Object file = image_find_image_fd (file_name, &fd); |
| 11557 | if (!STRINGP (file)) | 11632 | if (!STRINGP (file)) |
| 11558 | { | 11633 | { |