This source file includes following definitions.
- sfntfont_android_scale32
- sfntfont_android_mul8x2
- sfntfont_android_blend
- sfntfont_android_u255to256
- sfntfont_android_over_8888_1
- sfntfont_android_over_8888
- sfntfont_android_composite_bitmap
- sfntfont_android_union_boxes
- sfntfont_android_put_glyphs
- sfntfont_android_shrink_scanline_buffer
- sfntfont_android_get_cache
- DEFUN
- syms_of_sfntfont_android_for_pdumper
- init_sfntfont_android
- syms_of_sfntfont_android
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21 #include <dirent.h>
22 #include <string.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25
26 #ifdef __aarch64__
27 #include <arm_neon.h>
28 #endif
29
30 #include <android/api-level.h>
31 #include <android/log.h>
32
33 #include "androidterm.h"
34 #include "sfntfont.h"
35 #include "pdumper.h"
36 #include "blockinput.h"
37 #include "android.h"
38
39
40
41 struct sfntfont_android_scanline_buffer
42 {
43
44 size_t buffer_size;
45
46
47 void *buffer_data;
48 };
49
50
51 static char *system_font_directories[] =
52 {
53 (char *) "/system/fonts",
54 (char *) "/product/fonts",
55
56 (char[PATH_MAX]) { },
57 };
58
59
60 static Lisp_Object font_cache;
61
62
63 static struct sfntfont_android_scanline_buffer scanline_buffer;
64
65
66
67 static size_t max_scanline_buffer_size;
68
69
70
71
72
73
74 #ifndef __aarch64__
75
76 #define GET_SCANLINE_BUFFER(buffer, height, stride) \
77 do \
78 { \
79 size_t _size; \
80 \
81 if (INT_MULTIPLY_WRAPV (height, stride, &_size)) \
82 memory_full (SIZE_MAX); \
83 \
84 if (_size < MAX_ALLOCA) \
85 (buffer) = alloca (_size); \
86 else \
87 { \
88 if (_size > scanline_buffer.buffer_size) \
89 { \
90 (buffer) \
91 = scanline_buffer.buffer_data \
92 = xrealloc (scanline_buffer.buffer_data, \
93 _size); \
94 scanline_buffer.buffer_size = _size; \
95 } \
96 else if (_size <= scanline_buffer.buffer_size) \
97 (buffer) = scanline_buffer.buffer_data; \
98 \
99 else \
100 emacs_abort (); \
101 \
102 max_scanline_buffer_size \
103 = max (_size, max_scanline_buffer_size); \
104 } \
105 } while (false);
106
107 #else
108
109 #define GET_SCANLINE_BUFFER(buffer, height, stride) \
110 do \
111 { \
112 size_t _size; \
113 void *_temp; \
114 \
115 if (INT_MULTIPLY_WRAPV (height, stride, &_size)) \
116 memory_full (SIZE_MAX); \
117 \
118 if (_size > scanline_buffer.buffer_size) \
119 { \
120 if (posix_memalign (&_temp, 16, _size)) \
121 memory_full (_size); \
122 free (scanline_buffer.buffer_data); \
123 (buffer) \
124 = scanline_buffer.buffer_data \
125 = _temp; \
126 scanline_buffer.buffer_size = _size; \
127 } \
128 else if (_size <= scanline_buffer.buffer_size) \
129 (buffer) = scanline_buffer.buffer_data; \
130 \
131 else \
132 emacs_abort (); \
133 \
134 max_scanline_buffer_size \
135 = max (_size, max_scanline_buffer_size); \
136 } while (false);
137
138 #endif
139
140
141
142
143
144
145
146
147 static unsigned int
148 sfntfont_android_scale32 (unsigned int scale, unsigned int p)
149 {
150 uint32_t ag, rb;
151 uint32_t scaled_ag, scaled_rb;
152
153 ag = (p & 0xFF00FF00) >> 8;
154 rb = (p & 0x00FF00FF);
155
156 scaled_ag = (scale * ag) & 0xFF00FF00;
157 scaled_rb = (scale * rb) >> 8 & 0x00FF00FF;
158
159 return scaled_ag | scaled_rb;
160 }
161
162 static unsigned int
163 sfntfont_android_mul8x2 (unsigned int a8, unsigned int b32)
164 {
165 unsigned int i;
166
167 b32 &= 0xff00ff;
168 i = a8 * b32 + 0x800080;
169
170 return (i + ((i >> 8) & 0xff00ff)) >> 8 & 0xff00ff;
171 }
172
173 #define U255TO256(x) ((unsigned short) (x) + ((x) >> 7))
174
175
176
177
178
179 static unsigned int
180 sfntfont_android_blend (unsigned int src, unsigned int dst)
181 {
182 unsigned int a, br_part, ag_part, both;
183
184 a = (src >> 24);
185 br_part = sfntfont_android_mul8x2 (255 - a, dst);
186 ag_part = sfntfont_android_mul8x2 (255 - a, dst >> 8) << 8;
187
188 both = ag_part | br_part;
189
190
191
192 return both + src;
193 }
194
195 #ifdef __aarch64__
196
197
198
199 static uint16x8_t
200 sfntfont_android_u255to256 (uint8x8_t in)
201 {
202 return vaddl_u8 (vshr_n_u8 (in, 7), in);
203 }
204
205
206
207
208 static void
209 sfntfont_android_over_8888_1 (unsigned int *src, unsigned int *dst)
210 {
211 uint8x8_t alpha;
212 uint16x8_t alpha_c16, v1, v3, v4;
213 uint8x8_t b, g, r, a, v2, v5;
214 uint8x8x4_t _src, _dst;
215
216
217
218
219
220 _src = vld4_u8 ((const uint8_t *) src);
221 _dst = vld4_u8 ((const uint8_t *) dst);
222
223
224 v4 = vdupq_n_u16 (256);
225 v5 = vdup_n_u8 (0);
226
227
228 alpha = _src.val[3];
229
230
231 alpha_c16 = sfntfont_android_u255to256 (alpha);
232 alpha_c16 = vsubq_u16 (v4, alpha_c16);
233
234
235 v1 = vaddl_u8 (_dst.val[2], v5);
236 v2 = _src.val[2];
237 v3 = vmulq_u16 (v1, alpha_c16);
238 b = vqadd_u8 (v2, vshrn_n_u16 (v3, 8));
239
240 v1 = vaddl_u8 (_dst.val[1], v5);
241 v2 = _src.val[1];
242 v3 = vmulq_u16 (v1, alpha_c16);
243 g = vqadd_u8 (v2, vshrn_n_u16 (v3, 8));
244
245 v1 = vaddl_u8 (_dst.val[0], v5);
246 v2 = _src.val[0];
247 v3 = vmulq_u16 (v1, alpha_c16);
248 r = vqadd_u8 (v2, vshrn_n_u16 (v3, 8));
249
250 #if 0
251
252 v1 = vaddl_u8 (_dst.val[3], v5);
253 v2 = _src.val[3];
254 v3 = vmulq_u16 (v1, alpha_c16);
255 a = vqadd_u8 (v2, vshrn_n_u16 (v3, 8));
256 #else
257
258
259 a = vdup_n_u8 (255);
260 #endif
261
262
263 _dst.val[0] = r;
264 _dst.val[1] = g;
265 _dst.val[2] = b;
266 _dst.val[3] = a;
267 vst4_u8 ((uint8_t *) dst, _dst);
268 }
269
270
271
272
273
274
275
276
277
278 static int
279 sfntfont_android_over_8888 (unsigned int *src, unsigned int *dst,
280 unsigned int *max, unsigned int *x)
281 {
282 size_t i;
283 ptrdiff_t how_much;
284 void *s, *d;
285
286
287 how_much = (max - src) & ~7;
288
289
290 if (!how_much)
291 return 1;
292
293
294
295
296 *x += how_much;
297
298 for (i = 0; i < how_much; i += 8)
299 {
300 s = (src + i);
301 d = (dst + i);
302
303 sfntfont_android_over_8888_1 (s, d);
304 }
305
306 return 0;
307 }
308
309 #endif
310
311
312
313
314
315 static void
316 sfntfont_android_composite_bitmap (unsigned char *restrict buffer,
317 size_t stride,
318 unsigned char *restrict dest,
319 AndroidBitmapInfo *bitmap_info,
320 struct android_rectangle *text_rectangle,
321 struct android_rectangle *rect)
322 {
323 unsigned int *src_row;
324 unsigned int *dst_row;
325 unsigned int i, src_y, x, src_x, max_x, dst_x;
326 #ifdef __aarch64__
327 unsigned int lim_x;
328 #endif
329
330 if ((intptr_t) dest & 3 || bitmap_info->stride & 3)
331
332
333 emacs_abort ();
334 else
335 {
336 for (i = 0; i < rect->height; ++i)
337 {
338 if (i + rect->y >= bitmap_info->height)
339
340 return;
341
342 src_y = i + (rect->y - text_rectangle->y);
343
344 if (src_y > text_rectangle->height)
345
346 return;
347
348 src_row = (unsigned int *) ((buffer + src_y * stride));
349 dst_row = (unsigned int *) (dest + ((i + rect->y)
350 * bitmap_info->stride));
351
352
353 max_x = min (rect->width, bitmap_info->width - rect->x);
354
355
356 for (x = 0; x < max_x; ++x)
357 {
358 src_x = x + (rect->x - text_rectangle->x);
359 dst_x = x + rect->x;
360
361 #ifdef __aarch64__
362
363 lim_x = max_x + (rect->x - text_rectangle->x);
364
365 if (!sfntfont_android_over_8888 (src_row + src_x,
366 dst_row + dst_x,
367 src_row + lim_x,
368 &x))
369 {
370
371
372 x--;
373 continue;
374 }
375 #endif
376 dst_row[dst_x]
377 = sfntfont_android_blend (src_row[src_x],
378 dst_row[dst_x]);
379 }
380 }
381 }
382 }
383
384
385
386
387 static void
388 sfntfont_android_union_boxes (struct gui_box a, struct gui_box b,
389 struct gui_box *result)
390 {
391 result->x1 = min (a.x1, b.x1);
392 result->y1 = min (a.y1, b.y1);
393 result->x2 = max (a.x2, b.x2);
394 result->y2 = max (a.y2, b.y2);
395 }
396
397
398
399
400
401
402 static void
403 sfntfont_android_put_glyphs (struct glyph_string *s, int from,
404 int to, int x, int y, bool with_background,
405 struct sfnt_raster **rasters,
406 int *x_coords)
407 {
408 struct android_rectangle background, text_rectangle, rect;
409 struct gui_box text, character;
410 unsigned int *buffer, *row;
411 unsigned char *restrict raster_row;
412 size_t stride, i;
413 AndroidBitmapInfo bitmap_info;
414 unsigned char *bitmap_data;
415 jobject bitmap;
416 int left, top, temp_y;
417 unsigned int prod, raster_y;
418 unsigned long foreground, back_pixel, rb;
419
420 if (!s->gc->num_clip_rects)
421
422 return;
423
424 if (from == to)
425
426 return;
427
428
429
430 foreground = s->gc->foreground;
431 back_pixel = s->gc->background;
432 rb = foreground & 0x00ff00ff;
433 foreground &= ~0x00ff00ff;
434 foreground |= rb >> 16 | rb << 16 | 0xff000000;
435 rb = back_pixel & 0x00ff00ff;
436 back_pixel &= ~0x00ff00ff;
437 back_pixel |= rb >> 16 | rb << 16 | 0xff000000;
438
439 prepare_face_for_display (s->f, s->face);
440
441
442
443 memset (&background, 0, sizeof background);
444
445 if (with_background)
446 {
447 background.x = x;
448 background.y = y - FONT_BASE (s->font);
449 background.width = s->width;
450 background.height = FONT_HEIGHT (s->font);
451 }
452
453
454
455 if (rasters[0])
456 {
457 text.x1 = x_coords[0] + rasters[0]->offx;
458 text.x2 = text.x1 + rasters[0]->width;
459 text.y1 = y - rasters[0]->height - rasters[0]->offy;
460 text.y2 = y - rasters[0]->offy;
461 }
462 else
463 memset (&text, 0, sizeof text);
464
465 for (i = 1; i < to - from; ++i)
466 {
467
468
469 if (!rasters[i])
470 continue;
471
472 character.x1 = x_coords[i] + rasters[i]->offx;
473 character.x2 = character.x1 + rasters[i]->width;
474 character.y1 = y - rasters[i]->height - rasters[i]->offy;
475 character.y2 = y - rasters[i]->offy;
476
477 sfntfont_android_union_boxes (text, character, &text);
478 }
479
480
481 text_rectangle.x = text.x1;
482 text_rectangle.y = text.y1;
483 text_rectangle.width = text.x2 - text.x1;
484 text_rectangle.height = text.y2 - text.y1;
485 gui_union_rectangles (&background, &text_rectangle,
486 &text_rectangle);
487
488
489
490 #ifndef __aarch64__
491 stride = ((text_rectangle.width * sizeof *buffer) + 7) & ~7;
492 #else
493 stride = ((text_rectangle.width * sizeof *buffer) + 15) & ~15;
494 #endif
495 GET_SCANLINE_BUFFER (buffer, text_rectangle.height, stride);
496
497
498
499
500 if (!with_background || memcmp (&background, &text_rectangle,
501 sizeof text_rectangle))
502 memset (buffer, 0, text_rectangle.height * stride);
503
504 if (with_background)
505 {
506
507
508
509 background.x = background.x - text_rectangle.x;
510 background.y = background.y - text_rectangle.y;
511 eassert (background.x >= 0 && background.y >= 0);
512
513 for (temp_y = background.y; (temp_y
514 < (background.y
515 + background.height));
516 ++temp_y)
517 {
518 row = (unsigned int *) ((unsigned char *) buffer
519 + stride * temp_y);
520
521 for (x = background.x; x < background.x + background.width; ++x)
522 row[x] = back_pixel;
523 }
524 }
525
526
527 for (i = 0; i < to - from; ++i)
528 {
529 if (!rasters[i])
530 continue;
531
532
533
534 left = x_coords[i] + rasters[i]->offx - text_rectangle.x;
535
536
537
538 top = (y - (rasters[i]->height + rasters[i]->offy)
539 - text_rectangle.y);
540 eassert (left >= 0 && top >= 0);
541
542
543
544
545 for (raster_y = 0; raster_y < rasters[i]->height; ++raster_y)
546 {
547 row = (unsigned int *) ((unsigned char *) buffer
548 + stride * (raster_y + top));
549 raster_row = &rasters[i]->cells[raster_y * rasters[i]->stride];
550
551 for (x = 0; x < rasters[i]->width; ++x)
552 {
553 prod
554 = sfntfont_android_scale32 (U255TO256 (raster_row[x]),
555 foreground);
556 row[left + x]
557 = sfntfont_android_blend (prod, row[left + x]);
558 }
559 }
560 }
561
562
563 bitmap_data = android_lock_bitmap (FRAME_ANDROID_DRAWABLE (s->f),
564 &bitmap_info, &bitmap);
565
566
567
568 if (!bitmap_data)
569 return;
570
571
572 eassert (bitmap_info.format == ANDROID_BITMAP_FORMAT_RGBA_8888);
573
574 if (s->gc->num_clip_rects > 0)
575 {
576 for (i = 0; i < s->gc->num_clip_rects; ++i)
577 {
578 if (!gui_intersect_rectangles (&s->gc->clip_rects[i],
579 &text_rectangle, &rect))
580
581 continue;
582
583
584 sfntfont_android_composite_bitmap ((unsigned char *) buffer,
585 stride, bitmap_data,
586 &bitmap_info,
587 &text_rectangle, &rect);
588 }
589 }
590 else
591 sfntfont_android_composite_bitmap ((unsigned char *) buffer,
592 stride, bitmap_data,
593 &bitmap_info,
594 &text_rectangle,
595 &text_rectangle);
596
597
598 AndroidBitmap_unlockPixels (android_java_env, bitmap);
599 ANDROID_DELETE_LOCAL_REF (bitmap);
600
601
602 android_damage_window (FRAME_ANDROID_DRAWABLE (s->f),
603 &text_rectangle);
604
605 #undef MAX_ALLOCA
606 }
607
608
609
610
611
612
613
614
615 void
616 sfntfont_android_shrink_scanline_buffer (void)
617 {
618 if (!max_scanline_buffer_size)
619 return;
620
621 if (max_scanline_buffer_size
622 < scanline_buffer.buffer_size / 2)
623 {
624 scanline_buffer.buffer_size
625 = max_scanline_buffer_size;
626 scanline_buffer.buffer_data
627 = xrealloc (scanline_buffer.buffer_data,
628 max_scanline_buffer_size);
629 }
630
631 max_scanline_buffer_size = 0;
632 }
633
634
635
636
637
638
639
640 static Lisp_Object
641 sfntfont_android_get_cache (struct frame *f)
642 {
643 return font_cache;
644 }
645
646
647 const struct font_driver android_sfntfont_driver =
648 {
649 .type = LISPSYM_INITIALLY (Qsfnt_android),
650 .case_sensitive = true,
651 .get_cache = sfntfont_android_get_cache,
652 .list = sfntfont_list,
653 .match = sfntfont_match,
654 .draw = sfntfont_draw,
655 .open_font = sfntfont_open,
656 .close_font = sfntfont_close,
657 .encode_char = sfntfont_encode_char,
658 .text_extents = sfntfont_text_extents,
659 .list_family = sfntfont_list_family,
660 .get_variation_glyphs = sfntfont_get_variation_glyphs,
661
662 #ifdef HAVE_HARFBUZZ
663
664
665 .begin_hb_font = sfntfont_begin_hb_font,
666 .combining_capability = hbfont_combining_capability,
667 .shape = hbfont_shape,
668 .otf_capability = hbfont_otf_capability,
669 #endif
670 };
671
672
673
674
675
676
677 DEFUN ("android-enumerate-fonts", Fandroid_enumerate_fonts,
678 Sandroid_enumerate_fonts, 0, 0, 0,
679 doc:
680
681
682
683 )
684 (void)
685 {
686 DIR *dir;
687 int i;
688 struct dirent *dirent;
689 char name[PATH_MAX * 2];
690 static bool enumerated;
691
692 if (enumerated)
693 error ("Fonts have already been enumerated");
694 enumerated = true;
695
696 block_input ();
697
698
699
700 for (i = 0; i < ARRAYELTS (system_font_directories); ++i)
701 {
702 dir = opendir (system_font_directories[i]);
703
704 __android_log_print (ANDROID_LOG_VERBOSE, __func__,
705 "Loading fonts from: %s",
706 system_font_directories[i]);
707
708 if (!dir)
709 continue;
710
711 while ((dirent = readdir (dir)))
712 {
713
714
715
716 if ((strstr (dirent->d_name, ".ttf")
717 || strstr (dirent->d_name, ".ttc"))
718
719 && (i != 0 || strcmp (dirent->d_name,
720 "RobotoStatic-Regular.ttf")))
721 {
722 sprintf (name, "%s/%s", system_font_directories[i],
723 dirent->d_name);
724 sfnt_enum_font (name);
725 }
726 }
727
728 closedir (dir);
729 }
730
731 unblock_input ();
732
733 return Qnil;
734 }
735
736
737
738 static void
739 syms_of_sfntfont_android_for_pdumper (void)
740 {
741 init_sfntfont_vendor (Qsfnt_android, &android_sfntfont_driver,
742 sfntfont_android_put_glyphs);
743 register_font_driver (&android_sfntfont_driver, NULL);
744 }
745
746 void
747 init_sfntfont_android (void)
748 {
749 if (!android_init_gui)
750 return;
751
752
753
754 if (android_get_current_api_level () >= 15)
755 Vsfnt_default_family_alist
756 = list3 (Fcons (build_string ("Monospace"),
757 build_string ("Droid Sans Mono")),
758
759
760 Fcons (build_string ("Monospace Serif"),
761 build_string ("Droid Sans Mono")),
762 Fcons (build_string ("Sans Serif"),
763 build_string ("Roboto")));
764 else
765 Vsfnt_default_family_alist
766 = list3 (Fcons (build_string ("Monospace"),
767 build_string ("Droid Sans Mono")),
768 Fcons (build_string ("Monospace Serif"),
769 build_string ("Droid Sans Mono")),
770 Fcons (build_string ("Sans Serif"),
771 build_string ("Droid Sans")));
772
773
774
775 snprintf (system_font_directories[2], PATH_MAX, "%s/fonts",
776 android_get_home_directory ());
777 }
778
779 void
780 syms_of_sfntfont_android (void)
781 {
782 DEFSYM (Qsfnt_android, "sfnt-android");
783 DEFSYM (Qandroid_enumerate_fonts, "android-enumerate-fonts");
784 Fput (Qandroid, Qfont_driver_superseded_by, Qsfnt_android);
785
786 font_cache = list (Qnil);
787 staticpro (&font_cache);
788
789 defsubr (&Sandroid_enumerate_fonts);
790
791 pdumper_do_now_and_after_load (syms_of_sfntfont_android_for_pdumper);
792 }