This source file includes following definitions.
- android_init_font_driver
- android_init_font_spec
- android_init_font_metrics
- android_init_integer
- android_init_font_object
- androidfont_get_cache
- androidfont_check_init
- androidfont_from_lisp
- androidfont_from_java
- androidfont_list
- androidfont_match
- androidfont_draw
- androidfont_open_font
- androidfont_close_font
- androidfont_has_char
- androidfont_encode_char
- androidfont_cache_text_extents
- androidfont_check_cached_extents
- androidfont_text_extents
- androidfont_list_family
- syms_of_androidfont_for_pdumper
- syms_of_androidfont
- init_androidfont
- android_finalize_font_entity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #include <config.h>
25
26 #include "lisp.h"
27 #include "dispextern.h"
28 #include "composite.h"
29 #include "blockinput.h"
30 #include "charset.h"
31 #include "frame.h"
32 #include "window.h"
33 #include "fontset.h"
34 #include "androidterm.h"
35 #include "character.h"
36 #include "coding.h"
37 #include "font.h"
38 #include "termchar.h"
39 #include "pdumper.h"
40 #include "android.h"
41
42 #ifndef ANDROID_STUBIFY
43
44 #include <android/log.h>
45
46 struct android_emacs_font_driver
47 {
48 jclass class;
49 jmethodID list;
50 jmethodID match;
51 jmethodID list_families;
52 jmethodID open_font;
53 jmethodID has_char;
54 jmethodID text_extents;
55 jmethodID encode_char;
56 jmethodID draw;
57
58
59 jmethodID create_font_driver;
60 };
61
62 struct android_emacs_font_spec
63 {
64 jclass class;
65 jfieldID foundry;
66 jfieldID family;
67 jfieldID adstyle;
68 jfieldID registry;
69 jfieldID width;
70 jfieldID weight;
71 jfieldID slant;
72 jfieldID size;
73 jfieldID spacing;
74 jfieldID avgwidth;
75 jfieldID dpi;
76 };
77
78 struct android_emacs_font_metrics
79 {
80 jclass class;
81 jfieldID lbearing;
82 jfieldID rbearing;
83 jfieldID width;
84 jfieldID ascent;
85 jfieldID descent;
86 };
87
88 struct android_emacs_font_object
89 {
90 jclass class;
91 jfieldID min_width;
92 jfieldID max_width;
93 jfieldID pixel_size;
94 jfieldID height;
95 jfieldID space_width;
96 jfieldID average_width;
97 jfieldID ascent;
98 jfieldID descent;
99 jfieldID underline_thickness;
100 jfieldID underline_position;
101 jfieldID baseline_offset;
102 jfieldID relative_compose;
103 jfieldID default_ascent;
104 jfieldID encoding_charset;
105 jfieldID repertory_charset;
106 };
107
108 struct android_integer
109 {
110 jclass class;
111 jmethodID constructor;
112 jmethodID int_value;
113 };
114
115 struct androidfont_info
116 {
117
118 struct font font;
119
120
121 jobject object;
122
123
124 struct font_metrics **metrics;
125 };
126
127 struct androidfont_entity
128 {
129
130 struct font_entity font;
131
132
133 jobject object;
134 };
135
136
137
138
139 struct android_emacs_font_driver font_driver_class;
140
141
142
143
144 struct android_emacs_font_spec font_spec_class;
145
146
147
148 struct android_integer integer_class;
149
150
151
152
153 struct android_emacs_font_metrics font_metrics_class;
154
155
156
157
158 struct android_emacs_font_object font_object_class;
159
160
161
162 static Lisp_Object font_cache;
163
164
165
166 static jobject font_driver;
167
168
169
170
171
172
173 static void
174 android_init_font_driver (void)
175 {
176 jclass old;
177
178 font_driver_class.class
179 = (*android_java_env)->FindClass (android_java_env,
180 "org/gnu/emacs/EmacsFontDriver");
181 eassert (font_driver_class.class);
182
183 old = font_driver_class.class;
184 font_driver_class.class
185 = (jclass) (*android_java_env)->NewGlobalRef (android_java_env,
186 (jobject) old);
187 ANDROID_DELETE_LOCAL_REF (old);
188
189 if (!font_driver_class.class)
190 emacs_abort ();
191
192 #define FIND_METHOD(c_name, name, signature) \
193 font_driver_class.c_name \
194 = (*android_java_env)->GetMethodID (android_java_env, \
195 font_driver_class.class, \
196 name, signature); \
197 eassert (font_driver_class.c_name);
198
199 FIND_METHOD (list, "list", "(Lorg/gnu/emacs/EmacsFontDriver$FontSpec;)"
200 "[Lorg/gnu/emacs/EmacsFontDriver$FontEntity;");
201 FIND_METHOD (match, "match", "(Lorg/gnu/emacs/EmacsFontDriver$FontSpec;)"
202 "Lorg/gnu/emacs/EmacsFontDriver$FontEntity;");
203 FIND_METHOD (list_families, "listFamilies", "()[Ljava/lang/String;");
204 FIND_METHOD (open_font, "openFont", "(Lorg/gnu/emacs/EmacsFontDriver$Font"
205 "Entity;I)Lorg/gnu/emacs/EmacsFontDriver$FontObject;");
206 FIND_METHOD (has_char, "hasChar", "(Lorg/gnu/emacs/EmacsFontDriver$Font"
207 "Spec;C)I");
208 FIND_METHOD (text_extents, "textExtents", "(Lorg/gnu/emacs/EmacsFontDriver"
209 "$FontObject;[ILorg/gnu/emacs/EmacsFontDriver$FontMetrics;)V");
210 FIND_METHOD (encode_char, "encodeChar", "(Lorg/gnu/emacs/EmacsFontDriver"
211 "$FontObject;C)I");
212 FIND_METHOD (draw, "draw", "(Lorg/gnu/emacs/EmacsFontDriver$FontObject;"
213 "Lorg/gnu/emacs/EmacsGC;Lorg/gnu/emacs/EmacsDrawable;[IIIIZ)I");
214
215 font_driver_class.create_font_driver
216 = (*android_java_env)->GetStaticMethodID (android_java_env,
217 font_driver_class.class,
218 "createFontDriver",
219 "()Lorg/gnu/emacs/"
220 "EmacsFontDriver;");
221 eassert (font_driver_class.create_font_driver);
222 #undef FIND_METHOD
223 }
224
225
226
227
228
229 static void
230 android_init_font_spec (void)
231 {
232 jclass old;
233
234 font_spec_class.class
235 = (*android_java_env)->FindClass (android_java_env,
236 "org/gnu/emacs/EmacsFontDriver"
237 "$FontSpec");
238 eassert (font_spec_class.class);
239
240 old = font_spec_class.class;
241 font_spec_class.class
242 = (jclass) (*android_java_env)->NewGlobalRef (android_java_env,
243 (jobject) old);
244 ANDROID_DELETE_LOCAL_REF (old);
245
246 if (!font_spec_class.class)
247 emacs_abort ();
248
249 #define FIND_FIELD(c_name, name, signature) \
250 font_spec_class.c_name \
251 = (*android_java_env)->GetFieldID (android_java_env, \
252 font_spec_class.class, \
253 name, signature); \
254 eassert (font_spec_class.c_name);
255
256 FIND_FIELD (foundry, "foundry", "Ljava/lang/String;");
257 FIND_FIELD (family, "family", "Ljava/lang/String;");
258 FIND_FIELD (adstyle, "adstyle", "Ljava/lang/String;");
259 FIND_FIELD (registry, "registry", "Ljava/lang/String;");
260 FIND_FIELD (width, "width", "Ljava/lang/Integer;");
261 FIND_FIELD (weight, "weight", "Ljava/lang/Integer;");
262 FIND_FIELD (slant, "slant", "Ljava/lang/Integer;");
263 FIND_FIELD (size, "size", "Ljava/lang/Integer;");
264 FIND_FIELD (spacing, "spacing", "Ljava/lang/Integer;");
265 FIND_FIELD (avgwidth, "avgwidth", "Ljava/lang/Integer;");
266 FIND_FIELD (dpi, "dpi", "Ljava/lang/Integer;");
267 #undef FIND_FIELD
268 }
269
270 static void
271 android_init_font_metrics (void)
272 {
273 jclass old;
274
275 font_metrics_class.class
276 = (*android_java_env)->FindClass (android_java_env,
277 "org/gnu/emacs/EmacsFontDriver"
278 "$FontMetrics");
279 eassert (font_metrics_class.class);
280
281 old = font_metrics_class.class;
282 font_metrics_class.class
283 = (jclass) (*android_java_env)->NewGlobalRef (android_java_env,
284 (jobject) old);
285 ANDROID_DELETE_LOCAL_REF (old);
286
287 if (!font_metrics_class.class)
288 emacs_abort ();
289
290 #define FIND_FIELD(c_name, name, signature) \
291 font_metrics_class.c_name \
292 = (*android_java_env)->GetFieldID (android_java_env, \
293 font_metrics_class.class, \
294 name, signature); \
295 eassert (font_metrics_class.c_name);
296
297 FIND_FIELD (lbearing, "lbearing", "S");
298 FIND_FIELD (rbearing, "rbearing", "S");
299 FIND_FIELD (width, "width", "S");
300 FIND_FIELD (ascent, "ascent", "S");
301 FIND_FIELD (descent, "descent", "S");
302 #undef FIND_FIELD
303 }
304
305 static void
306 android_init_integer (void)
307 {
308 jclass old;
309
310 integer_class.class
311 = (*android_java_env)->FindClass (android_java_env,
312 "java/lang/Integer");
313 eassert (integer_class.class);
314
315 old = integer_class.class;
316 integer_class.class
317 = (jclass) (*android_java_env)->NewGlobalRef (android_java_env,
318 (jobject) old);
319 ANDROID_DELETE_LOCAL_REF (old);
320
321 if (!integer_class.class)
322 emacs_abort ();
323
324 #define FIND_METHOD(c_name, name, signature) \
325 integer_class.c_name \
326 = (*android_java_env)->GetMethodID (android_java_env, \
327 integer_class.class, \
328 name, signature); \
329 eassert (integer_class.c_name);
330
331 FIND_METHOD (constructor, "<init>", "(I)V");
332 FIND_METHOD (int_value, "intValue", "()I");
333 #undef FIND_METHOD
334 }
335
336 static void
337 android_init_font_object (void)
338 {
339 jclass old;
340
341 font_object_class.class
342 = (*android_java_env)->FindClass (android_java_env,
343 "org/gnu/emacs/EmacsFontDriver"
344 "$FontObject");
345 eassert (font_object_class.class);
346
347 old = font_object_class.class;
348 font_object_class.class
349 = (jclass) (*android_java_env)->NewGlobalRef (android_java_env,
350 (jobject) old);
351 ANDROID_DELETE_LOCAL_REF (old);
352
353 if (!font_object_class.class)
354 emacs_abort ();
355
356 #define FIND_FIELD(c_name, name, signature) \
357 font_object_class.c_name \
358 = (*android_java_env)->GetFieldID (android_java_env, \
359 font_object_class.class, \
360 name, signature); \
361 eassert (font_object_class.c_name);
362
363 FIND_FIELD (min_width, "minWidth", "I");
364 FIND_FIELD (max_width, "maxWidth", "I");
365 FIND_FIELD (pixel_size, "pixelSize", "I");
366 FIND_FIELD (height, "height", "I");
367 FIND_FIELD (space_width, "spaceWidth", "I");
368 FIND_FIELD (average_width, "averageWidth", "I");
369 FIND_FIELD (ascent, "ascent", "I");
370 FIND_FIELD (descent, "descent", "I");
371 FIND_FIELD (underline_thickness, "underlineThickness", "I");
372 FIND_FIELD (underline_position, "underlinePosition", "I");
373 FIND_FIELD (baseline_offset, "baselineOffset", "I");
374 FIND_FIELD (relative_compose, "relativeCompose", "I");
375 FIND_FIELD (default_ascent, "defaultAscent", "I");
376 FIND_FIELD (encoding_charset, "encodingCharset", "I");
377 FIND_FIELD (repertory_charset, "repertoryCharset", "I");
378 #undef FIND_FIELD
379 }
380
381 static Lisp_Object
382 androidfont_get_cache (struct frame *frame)
383 {
384 return font_cache;
385 }
386
387
388
389
390
391
392 static void
393 androidfont_check_init (void)
394 {
395 jmethodID method;
396 jobject old;
397
398 if (font_driver)
399 return;
400
401
402
403 __android_log_print (ANDROID_LOG_WARN, __func__,
404 "The Android font driver is being used."
405 " Please investigate why this is so.");
406
407 method = font_driver_class.create_font_driver;
408
409
410 font_driver
411 = (*android_java_env)->CallStaticObjectMethod (android_java_env,
412 font_driver_class.class,
413 method);
414 android_exception_check ();
415
416 old = font_driver;
417 font_driver
418 = (*android_java_env)->NewGlobalRef (android_java_env, font_driver);
419 ANDROID_DELETE_LOCAL_REF (old);
420 }
421
422
423
424
425 static jobject
426 androidfont_from_lisp (Lisp_Object font)
427 {
428 jobject spec, integer;
429 jstring string;
430 Lisp_Object tem;
431
432 spec = (*android_java_env)->AllocObject (android_java_env,
433 font_spec_class.class);
434 android_exception_check ();
435
436 #define DO_SYMBOL_FIELD(field, index) \
437 tem = AREF (font, index); \
438 if (SYMBOLP (tem)) \
439 { \
440
441 \
442 string = (*android_java_env)->NewStringUTF (android_java_env, \
443 SSDATA (SYMBOL_NAME (tem))); \
444 android_exception_check_1 (spec); \
445 \
446 (*android_java_env)->SetObjectField (android_java_env, spec, \
447 font_spec_class.field, \
448 string); \
449 ANDROID_DELETE_LOCAL_REF (string); \
450 } \
451
452 DO_SYMBOL_FIELD (foundry, FONT_FOUNDRY_INDEX);
453 DO_SYMBOL_FIELD (family, FONT_FAMILY_INDEX);
454 DO_SYMBOL_FIELD (adstyle, FONT_ADSTYLE_INDEX);
455 DO_SYMBOL_FIELD (registry, FONT_REGISTRY_INDEX);
456
457 #undef DO_SYMBOL_FIELD
458
459 #define DO_CARDINAL_FIELD(field, value) \
460 if (value != -1) \
461 { \
462 integer = (*android_java_env)->NewObject (android_java_env, \
463 integer_class.class, \
464 integer_class.constructor, \
465 (jint) value); \
466 android_exception_check_1 (spec); \
467 \
468 (*android_java_env)->SetObjectField (android_java_env, spec, \
469 font_spec_class.field, \
470 integer); \
471 ANDROID_DELETE_LOCAL_REF (integer); \
472 }
473
474 DO_CARDINAL_FIELD (width, FONT_WIDTH_NUMERIC (font));
475 DO_CARDINAL_FIELD (weight, FONT_WEIGHT_NUMERIC (font));
476 DO_CARDINAL_FIELD (slant, FONT_SLANT_NUMERIC (font));
477 DO_CARDINAL_FIELD (size, (FIXNUMP (AREF (font, FONT_SIZE_INDEX))
478 ? XFIXNUM (AREF (font, FONT_SIZE_INDEX))
479 : -1));
480 DO_CARDINAL_FIELD (spacing, (FIXNUMP (AREF (font, FONT_SPACING_INDEX))
481 ? XFIXNUM (AREF (font, FONT_SPACING_INDEX))
482 : -1));
483 DO_CARDINAL_FIELD (avgwidth, (FIXNUMP (AREF (font, FONT_AVGWIDTH_INDEX))
484 ? XFIXNUM (AREF (font, FONT_AVGWIDTH_INDEX))
485 : -1));
486 DO_CARDINAL_FIELD (dpi, (FIXNUMP (AREF (font, FONT_DPI_INDEX))
487 ? XFIXNUM (AREF (font, FONT_DPI_INDEX))
488 : -1));
489
490 #undef DO_CARDINAL_FIELD
491
492 return spec;
493 }
494
495 static void
496 androidfont_from_java (jobject spec, Lisp_Object entity)
497 {
498 jobject tem;
499 jint value;
500 const char *string;
501
502 #define DO_SYMBOL_FIELD(field, index) \
503 tem = (*android_java_env)->GetObjectField (android_java_env, \
504 spec, \
505 font_spec_class.field); \
506 if (tem) \
507 { \
508 string = (*android_java_env)->GetStringUTFChars (android_java_env, \
509 tem, NULL); \
510 if (!string) \
511 memory_full (0); \
512 ASET (entity, index, intern (string)); \
513 (*android_java_env)->ReleaseStringUTFChars (android_java_env, \
514 tem, string); \
515 ANDROID_DELETE_LOCAL_REF (tem); \
516 }
517
518 DO_SYMBOL_FIELD (foundry, FONT_FOUNDRY_INDEX);
519 DO_SYMBOL_FIELD (family, FONT_FAMILY_INDEX);
520 DO_SYMBOL_FIELD (adstyle, FONT_ADSTYLE_INDEX);
521 DO_SYMBOL_FIELD (registry, FONT_REGISTRY_INDEX);
522
523 #undef DO_SYMBOL_FIELD
524 #define DO_CARDINAL_FIELD(field, index, is_style) \
525 tem = (*android_java_env)->GetObjectField (android_java_env, \
526 spec, \
527 font_spec_class.field); \
528 if (tem) \
529 { \
530 value \
531 = (*android_java_env)->CallIntMethod (android_java_env, \
532 tem, \
533 integer_class.int_value); \
534 if (!is_style) \
535 ASET (entity, index, make_fixnum (value)); \
536 else \
537 FONT_SET_STYLE (entity, index, make_fixnum (value)); \
538 ANDROID_DELETE_LOCAL_REF (tem); \
539 }
540
541 DO_CARDINAL_FIELD (width, FONT_WIDTH_INDEX, true);
542 DO_CARDINAL_FIELD (weight, FONT_WEIGHT_INDEX, true);
543 DO_CARDINAL_FIELD (slant, FONT_SLANT_INDEX, true);
544 DO_CARDINAL_FIELD (size, FONT_SIZE_INDEX, false);
545 DO_CARDINAL_FIELD (spacing, FONT_SPACING_INDEX, false);
546 DO_CARDINAL_FIELD (avgwidth, FONT_AVGWIDTH_INDEX, false);
547 DO_CARDINAL_FIELD (dpi, FONT_DPI_INDEX, false);
548
549 #undef DO_CARDINAL_FIELD
550 }
551
552
553
554
555 static Lisp_Object
556 androidfont_list (struct frame *f, Lisp_Object font_spec)
557 {
558 jobject spec, array, tem;
559 jarray entities;
560 jsize i, size;
561 Lisp_Object value, entity;
562 struct androidfont_entity *info;
563
564
565 androidfont_check_init ();
566
567 spec = androidfont_from_lisp (font_spec);
568 array = (*android_java_env)->CallObjectMethod (android_java_env,
569 font_driver,
570 font_driver_class.list,
571 spec);
572 android_exception_check_1 (spec);
573 ANDROID_DELETE_LOCAL_REF (spec);
574
575 entities = (jarray) array;
576 size = (*android_java_env)->GetArrayLength (android_java_env,
577 entities);
578 value = Qnil;
579
580 for (i = 0; i < size; ++i)
581 {
582 entity = font_make_entity_android (VECSIZE (struct androidfont_entity));
583 info = (struct androidfont_entity *) XFONT_ENTITY (entity);
584
585
586
587 ASET (entity, FONT_TYPE_INDEX, Qandroid);
588
589
590
591 info->object = NULL;
592
593 tem = (*android_java_env)->GetObjectArrayElement (android_java_env,
594 entities, i);
595 androidfont_from_java (tem, entity);
596
597
598 info->object = (*android_java_env)->NewGlobalRef (android_java_env,
599 (jobject) tem);
600 android_exception_check_2 (tem, entities);
601 ANDROID_DELETE_LOCAL_REF (tem);
602
603 value = Fcons (entity, value);
604 }
605
606 ANDROID_DELETE_LOCAL_REF (entities);
607 return Fnreverse (value);
608 }
609
610 static Lisp_Object
611 androidfont_match (struct frame *f, Lisp_Object font_spec)
612 {
613 jobject spec, result;
614 Lisp_Object entity;
615 struct androidfont_entity *info;
616
617
618 androidfont_check_init ();
619
620 spec = androidfont_from_lisp (font_spec);
621 result = (*android_java_env)->CallObjectMethod (android_java_env,
622 font_driver,
623 font_driver_class.match,
624 spec);
625 android_exception_check_1 (spec);
626 ANDROID_DELETE_LOCAL_REF (spec);
627
628 entity = font_make_entity_android (VECSIZE (struct androidfont_entity));
629 info = (struct androidfont_entity *) XFONT_ENTITY (entity);
630
631
632
633 ASET (entity, FONT_TYPE_INDEX, Qandroid);
634
635 info->object = NULL;
636 androidfont_from_java (result, entity);
637 info->object = (*android_java_env)->NewGlobalRef (android_java_env,
638 (jobject) result);
639 android_exception_check_1 (result);
640 ANDROID_DELETE_LOCAL_REF (result);
641
642 return entity;
643 }
644
645 static int
646 androidfont_draw (struct glyph_string *s, int from, int to,
647 int x, int y, bool with_background)
648 {
649 struct androidfont_info *info;
650 jarray chars;
651 int rc;
652 jobject gcontext, drawable;
653
654
655 androidfont_check_init ();
656
657 verify (sizeof (unsigned int) == sizeof (jint));
658 info = (struct androidfont_info *) s->font;
659
660 gcontext = android_resolve_handle (s->gc->gcontext,
661 ANDROID_HANDLE_GCONTEXT);
662 drawable = android_resolve_handle (FRAME_ANDROID_DRAWABLE (s->f),
663 ANDROID_HANDLE_WINDOW);
664 chars = (*android_java_env)->NewIntArray (android_java_env,
665 to - from);
666 android_exception_check ();
667
668 (*android_java_env)->SetIntArrayRegion (android_java_env, chars,
669 0, to - from,
670 (jint *) s->char2b + from);
671
672 info = (struct androidfont_info *) s->font;
673 prepare_face_for_display (s->f, s->face);
674
675 rc = (*android_java_env)->CallIntMethod (android_java_env,
676 font_driver,
677 font_driver_class.draw,
678 info->object,
679 gcontext, drawable,
680 chars, (jint) x, (jint) y,
681 (jint) s->width,
682 (jboolean) with_background);
683 android_exception_check_1 (chars);
684 ANDROID_DELETE_LOCAL_REF (chars);
685
686 return rc;
687 }
688
689 static Lisp_Object
690 androidfont_open_font (struct frame *f, Lisp_Object font_entity,
691 int pixel_size)
692 {
693 struct androidfont_info *font_info;
694 struct androidfont_entity *entity;
695 struct font *font;
696 Lisp_Object font_object;
697 jobject old;
698 jint value;
699
700
701 androidfont_check_init ();
702
703 if (XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX)) != 0)
704 pixel_size = XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX));
705 else if (pixel_size == 0)
706 {
707
708
709
710 if (FRAME_FONT (f))
711 pixel_size = FRAME_FONT (f)->pixel_size;
712 else
713 pixel_size = 12;
714 }
715
716 entity = (struct androidfont_entity *) XFONT_ENTITY (font_entity);
717
718 block_input ();
719 font_object = font_make_object (VECSIZE (struct androidfont_info),
720 font_entity, pixel_size);
721 ASET (font_object, FONT_TYPE_INDEX, Qandroid);
722 font_info = (struct androidfont_info *) XFONT_OBJECT (font_object);
723 font = &font_info->font;
724 font->driver = &androidfont_driver;
725
726
727
728 font_info->object = NULL;
729 font_info->metrics = NULL;
730 unblock_input ();
731
732 font_info->object
733 = (*android_java_env)->CallObjectMethod (android_java_env,
734 font_driver,
735 font_driver_class.open_font,
736 entity->object,
737 (jint) pixel_size);
738 android_exception_check ();
739
740 old = font_info->object;
741 font_info->object
742 = (*android_java_env)->NewGlobalRef (android_java_env, old);
743 android_exception_check_1 (old);
744 ANDROID_DELETE_LOCAL_REF (old);
745
746 if (!font_info->object)
747 return Qnil;
748
749
750 androidfont_from_java (font_info->object, font_object);
751
752
753 #define DO_CARDINAL_FIELD(field) \
754 value \
755 = (*android_java_env)->GetIntField (android_java_env, \
756 font_info->object, \
757 font_object_class.field); \
758 font->field = value;
759
760 DO_CARDINAL_FIELD (min_width);
761 DO_CARDINAL_FIELD (max_width);
762 DO_CARDINAL_FIELD (pixel_size);
763 DO_CARDINAL_FIELD (height);
764 DO_CARDINAL_FIELD (space_width);
765 DO_CARDINAL_FIELD (average_width);
766 DO_CARDINAL_FIELD (ascent);
767 DO_CARDINAL_FIELD (descent);
768 DO_CARDINAL_FIELD (underline_thickness);
769 DO_CARDINAL_FIELD (underline_position);
770 DO_CARDINAL_FIELD (baseline_offset);
771 DO_CARDINAL_FIELD (relative_compose);
772 DO_CARDINAL_FIELD (default_ascent);
773 DO_CARDINAL_FIELD (encoding_charset);
774 DO_CARDINAL_FIELD (repertory_charset);
775
776 #undef DO_CARDINAL_FIELD
777
778
779 font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil);
780
781 return font_object;
782 }
783
784 static void
785 androidfont_close_font (struct font *font)
786 {
787 struct androidfont_info *info;
788 int i;
789
790
791 androidfont_check_init ();
792
793 info = (struct androidfont_info *) font;
794
795
796
797 if (info->metrics)
798 {
799 for (i = 0; i < 256; ++i)
800 xfree (info->metrics[i]);
801 xfree (info->metrics);
802 }
803
804 info->metrics = NULL;
805
806
807
808
809
810
811
812 if (!info->object)
813 return;
814
815 (*android_java_env)->DeleteGlobalRef (android_java_env,
816 info->object);
817 info->object = NULL;
818 }
819
820 static int
821 androidfont_has_char (Lisp_Object font, int c)
822 {
823 struct androidfont_info *info;
824 struct androidfont_entity *entity;
825
826
827 androidfont_check_init ();
828
829 if (FONT_ENTITY_P (font))
830 {
831 entity = (struct androidfont_entity *) XFONT_ENTITY (font);
832
833 return (*android_java_env)->CallIntMethod (android_java_env,
834 font_driver,
835 font_driver_class.has_char,
836 entity->object, (jint) c);
837 }
838 else
839 {
840 info = (struct androidfont_info *) XFONT_OBJECT (font);
841
842 return (*android_java_env)->CallIntMethod (android_java_env,
843 font_driver,
844 font_driver_class.has_char,
845 info->object, (jint) c);
846 }
847 }
848
849 static unsigned
850 androidfont_encode_char (struct font *font, int c)
851 {
852 struct androidfont_info *info;
853
854
855 androidfont_check_init ();
856
857 info = (struct androidfont_info *) font;
858
859 return (*android_java_env)->CallIntMethod (android_java_env,
860 font_driver,
861 font_driver_class.encode_char,
862 info->object, (jchar) c);
863 }
864
865 static void
866 androidfont_cache_text_extents (struct androidfont_info *info,
867 unsigned int glyph,
868 struct font_metrics *metrics)
869 {
870 int i;
871
872
873 if (glyph >= 256 * 256)
874 return;
875
876 if (!info->metrics)
877 info->metrics = xzalloc (256 * sizeof *info->metrics);
878
879 if (!info->metrics[glyph / 256])
880 {
881 info->metrics[glyph / 256]
882 = xnmalloc (256, sizeof **info->metrics);
883
884
885
886 for (i = 0; i < 256; ++i)
887 info->metrics[glyph / 256][i].lbearing = SHRT_MAX;
888 }
889
890
891 info->metrics[glyph / 256][glyph % 256] = *metrics;
892 }
893
894 static bool
895 androidfont_check_cached_extents (struct androidfont_info *info,
896 unsigned int glyph,
897 struct font_metrics *metrics)
898 {
899 if (info->metrics && info->metrics[glyph / 256]
900 && info->metrics[glyph / 256][glyph % 256].lbearing != SHRT_MAX)
901 {
902 *metrics = info->metrics[glyph / 256][glyph % 256];
903 return true;
904 }
905
906 return false;
907 }
908
909 static void
910 androidfont_text_extents (struct font *font, const unsigned int *code,
911 int nglyphs, struct font_metrics *metrics)
912 {
913 struct androidfont_info *info;
914 jarray codepoint_array;
915 jobject metrics_object;
916 short value;
917
918
919 androidfont_check_init ();
920
921 info = (struct androidfont_info *) font;
922
923 if (nglyphs == 1
924 && androidfont_check_cached_extents (info, *code, metrics))
925 return;
926
927
928 codepoint_array
929 = (*android_java_env)->NewIntArray (android_java_env,
930 nglyphs);
931 if (!codepoint_array)
932 {
933 (*android_java_env)->ExceptionClear (android_java_env);
934 memory_full (0);
935 }
936
937 verify (sizeof (unsigned int) == sizeof (jint));
938
939
940 (*android_java_env)->SetIntArrayRegion (android_java_env,
941 codepoint_array,
942 0, nglyphs,
943 (jint *) code);
944
945 metrics_object
946 = (*android_java_env)->AllocObject (android_java_env,
947 font_metrics_class.class);
948
949 (*android_java_env)->CallVoidMethod (android_java_env,
950 font_driver,
951 font_driver_class.text_extents,
952 info->object, codepoint_array,
953 metrics_object);
954
955 if ((*android_java_env)->ExceptionCheck (android_java_env))
956 {
957 (*android_java_env)->ExceptionClear (android_java_env);
958 ANDROID_DELETE_LOCAL_REF (metrics_object);
959 ANDROID_DELETE_LOCAL_REF (codepoint_array);
960 memory_full (0);
961 }
962
963 #define DO_CARDINAL_FIELD(field) \
964 value \
965 = (*android_java_env)->GetShortField (android_java_env, \
966 metrics_object, \
967 font_metrics_class.field); \
968 metrics->field = value;
969
970 DO_CARDINAL_FIELD (lbearing);
971 DO_CARDINAL_FIELD (rbearing);
972 DO_CARDINAL_FIELD (width);
973 DO_CARDINAL_FIELD (ascent);
974 DO_CARDINAL_FIELD (descent);
975
976 #undef DO_CARDINAL_FIELD
977
978 ANDROID_DELETE_LOCAL_REF (metrics_object);
979 ANDROID_DELETE_LOCAL_REF (codepoint_array);
980
981
982
983
984
985 if (nglyphs == 1)
986 androidfont_cache_text_extents (info, *code, metrics);
987 }
988
989 static Lisp_Object
990 androidfont_list_family (struct frame *f)
991 {
992 Lisp_Object families;
993 jarray family_array;
994 jobject string;
995 jsize i, length;
996 const char *family;
997
998
999
1000
1001
1002
1003 if (!font_driver)
1004 return Qnil;
1005
1006 family_array
1007 = (*android_java_env)->CallObjectMethod (android_java_env,
1008 font_driver,
1009 font_driver_class.list_families);
1010 android_exception_check ();
1011
1012 length = (*android_java_env)->GetArrayLength (android_java_env,
1013 family_array);
1014 families = Qnil;
1015
1016 for (i = 0; i < length; ++i)
1017 {
1018 string = (*android_java_env)->GetObjectArrayElement (android_java_env,
1019 family_array, i);
1020 family = (*android_java_env)->GetStringUTFChars (android_java_env,
1021 (jstring) string, NULL);
1022
1023 if (!family)
1024 {
1025 ANDROID_DELETE_LOCAL_REF (string);
1026 ANDROID_DELETE_LOCAL_REF (family_array);
1027 }
1028
1029 families = Fcons (build_string_from_utf8 (string), families);
1030 (*android_java_env)->ReleaseStringUTFChars (android_java_env,
1031 (jstring) string,
1032 family);
1033 ANDROID_DELETE_LOCAL_REF (string);
1034 }
1035
1036 ANDROID_DELETE_LOCAL_REF (family_array);
1037 return Fnreverse (families);
1038 }
1039
1040 struct font_driver androidfont_driver =
1041 {
1042 .type = LISPSYM_INITIALLY (Qandroid),
1043 .case_sensitive = true,
1044 .get_cache = androidfont_get_cache,
1045 .list = androidfont_list,
1046 .match = androidfont_match,
1047 .draw = androidfont_draw,
1048 .open_font = androidfont_open_font,
1049 .close_font = androidfont_close_font,
1050 .has_char = androidfont_has_char,
1051 .encode_char = androidfont_encode_char,
1052 .text_extents = androidfont_text_extents,
1053 .list_family = androidfont_list_family,
1054 };
1055
1056 static void
1057 syms_of_androidfont_for_pdumper (void)
1058 {
1059 register_font_driver (&androidfont_driver, NULL);
1060 }
1061
1062 void
1063 syms_of_androidfont (void)
1064 {
1065 DEFSYM (Qfontsize, "fontsize");
1066
1067 pdumper_do_now_and_after_load (syms_of_androidfont_for_pdumper);
1068
1069 font_cache = list (Qnil);
1070 staticpro (&font_cache);
1071 }
1072
1073 void
1074 init_androidfont (void)
1075 {
1076 if (!android_init_gui)
1077 return;
1078
1079 android_init_font_driver ();
1080 android_init_font_spec ();
1081 android_init_font_metrics ();
1082 android_init_font_object ();
1083 android_init_integer ();
1084
1085
1086
1087 }
1088
1089 void
1090 android_finalize_font_entity (struct font_entity *entity)
1091 {
1092 struct androidfont_entity *info;
1093
1094 info = (struct androidfont_entity *) entity;
1095
1096 if (info->object)
1097 (*android_java_env)->DeleteGlobalRef (android_java_env,
1098 info->object);
1099
1100
1101 info->object = NULL;
1102 }
1103
1104 #endif