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