This source file includes following definitions.
- MessageReceived
- hash_string
- cache_font_object_data
- lookup_font_object_data
- font_object_has_chars
- estimate_font_ascii
- BFont_close
- BFont_metrics
- BFont_have_char_p
- BFont_have_char_block
- BFont_char_bounds
- BFont_nchar_bounds
- font_style_to_flags
- font_check_wanted_chars
- font_check_one_of
- font_check_language
- font_family_style_matches_p
- haiku_font_fill_pattern
- haiku_font_pattern_free
- BFont_find
- be_open_font_at_index
- BFont_open_pattern
- BFont_populate_fixed_family
- BFont_populate_plain_family
- be_list_font_families
- be_init_font_data
- be_evict_font_cache
- be_font_style_to_flags
- be_find_font_indices
- be_set_font_antialiasing
- be_send_font_settings
- be_listen_font_settings
- be_lock_font_defaults
- be_unlock_font_defaults
- be_get_font_default
- be_get_font_size
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <config.h>
20
21 #include <Font.h>
22 #include <Rect.h>
23 #include <AffineTransform.h>
24 #include <FindDirectory.h>
25 #include <Path.h>
26 #include <File.h>
27 #include <Message.h>
28 #include <OS.h>
29 #include <Locker.h>
30 #include <NodeMonitor.h>
31 #include <Looper.h>
32
33 #include <cstring>
34 #include <cmath>
35
36 #include "haiku_support.h"
37
38
39
40 struct font_object_cache_bucket
41 {
42 struct font_object_cache_bucket *next;
43 unsigned int hash;
44
45 BFont *font_object;
46 };
47
48 static struct font_object_cache_bucket *font_object_cache[2048];
49
50
51 static char *fixed_family, *fixed_style;
52
53
54 static char *default_family, *default_style;
55
56
57 static float default_size, fixed_size;
58
59
60 static BLocker default_locker;
61
62
63
64
65
66
67 static int language_code_points[MAX_LANGUAGE][3] =
68 {
69 {20154, 20754, 22996},
70 {51312, 49440, 44544},
71 {26085, 26412, 12371},
72 };
73
74 static void be_send_font_settings (void);
75
76
77 class EmacsFontMonitorLooper : public BLooper
78 {
79 void
80 MessageReceived (BMessage *msg)
81 {
82 int32 opcode;
83
84 if (msg->what != B_NODE_MONITOR)
85 return;
86
87 if (msg->FindInt32 ("opcode", &opcode) != B_OK)
88 return;
89
90 if (opcode != B_STAT_CHANGED)
91 return;
92
93
94
95 snooze (10000);
96
97
98 be_send_font_settings ();
99 }
100 };
101
102 static unsigned int
103 hash_string (const char *name_or_style)
104 {
105 unsigned int i;
106
107 i = 3323198485ul;
108 for (; *name_or_style; ++name_or_style)
109 {
110 i ^= *name_or_style;
111 i *= 0x5bd1e995;
112 i ^= i >> 15;
113 }
114 return i;
115 }
116
117 static struct font_object_cache_bucket *
118 cache_font_object_data (const char *family, const char *style,
119 BFont *font_object)
120 {
121 uint32_t hash;
122 struct font_object_cache_bucket *bucket, *next;
123
124 hash = hash_string (family) ^ hash_string (style);
125 bucket = font_object_cache[hash % 2048];
126
127 for (next = bucket; next; next = next->next)
128 {
129 if (next->hash == hash)
130 {
131 delete next->font_object;
132 next->font_object = font_object;
133
134 return next;
135 }
136 }
137
138 next = new struct font_object_cache_bucket;
139 next->font_object = font_object;
140 next->hash = hash;
141 next->next = bucket;
142 font_object_cache[hash % 2048] = next;
143 return next;
144 }
145
146 static struct font_object_cache_bucket *
147 lookup_font_object_data (const char *family, const char *style)
148 {
149 uint32_t hash;
150 struct font_object_cache_bucket *bucket, *next;
151
152 hash = hash_string (family) ^ hash_string (style);
153 bucket = font_object_cache[hash % 2048];
154
155 for (next = bucket; next; next = next->next)
156 {
157 if (next->hash == hash)
158 return next;
159 }
160
161 return NULL;
162 }
163
164 static bool
165 font_object_has_chars (struct font_object_cache_bucket *cached,
166 int *chars, int nchars, bool just_one_of)
167 {
168 int i;
169
170 for (i = 0; i < nchars; ++i)
171 {
172 if (just_one_of
173 && cached->font_object->IncludesBlock (chars[i],
174 chars[i]))
175 return true;
176
177 if (!just_one_of
178 && !cached->font_object->IncludesBlock (chars[i],
179 chars[i]))
180 return false;
181 }
182
183 return !just_one_of;
184 }
185
186 static void
187 estimate_font_ascii (BFont *font, int *max_width,
188 int *min_width, int *avg_width)
189 {
190 char ch[2];
191 bool tems[1];
192 int total = 0;
193 int count = 0;
194 int min = 0;
195 int max = 0;
196
197 std::memset (ch, 0, sizeof ch);
198 for (ch[0] = 32; ch[0] < 127; ++ch[0])
199 {
200 tems[0] = false;
201 font->GetHasGlyphs (ch, 1, tems);
202 if (tems[0])
203 {
204 int w = font->StringWidth (ch);
205 ++count;
206 total += w;
207
208 if (!min || min > w)
209 min = w;
210 if (max < w)
211 max = w;
212 }
213 }
214
215 *min_width = min;
216 *max_width = max;
217
218 if (count)
219 *avg_width = total / count;
220 else
221 *avg_width = 0;
222 }
223
224 void
225 BFont_close (void *font)
226 {
227 if (font != (void *) be_fixed_font &&
228 font != (void *) be_plain_font &&
229 font != (void *) be_bold_font)
230 delete (BFont *) font;
231 }
232
233 void
234 BFont_metrics (void *font, int *px_size, int *min_width, int *max_width,
235 int *avg_width, int *height, int *space_width, int *ascent,
236 int *descent, int *underline_position, int *underline_thickness)
237 {
238 BFont *ft = (BFont *) font;
239 struct font_height fheight;
240 bool have_space_p;
241
242 char atem[1];
243 bool otem[1];
244
245 ft->GetHeight (&fheight);
246 atem[0] = ' ';
247 otem[0] = false;
248 ft->GetHasGlyphs (atem, 1, otem);
249 have_space_p = otem[0];
250
251 estimate_font_ascii (ft, max_width, min_width, avg_width);
252 *ascent = std::lrint (fheight.ascent);
253 *descent = std::lrint (fheight.descent);
254 *height = *ascent + *descent;
255
256 *space_width = have_space_p ? ft->StringWidth (" ") : 0;
257
258 *px_size = std::lrint (ft->Size ());
259 *underline_position = 0;
260 *underline_thickness = 0;
261 }
262
263
264 int
265 BFont_have_char_p (void *font, int32_t chr)
266 {
267 BFont *ft = (BFont *) font;
268 return ft->IncludesBlock (chr, chr);
269 }
270
271
272 int
273 BFont_have_char_block (void *font, int32_t beg, int32_t end)
274 {
275 BFont *ft = (BFont *) font;
276 return ft->IncludesBlock (beg, end);
277 }
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301 void
302 BFont_char_bounds (void *font, const char *mb_str, int *advance,
303 int *lb, int *rb)
304 {
305 BFont *ft = (BFont *) font;
306 edge_info edge_info;
307 float size, escapement;
308 size = ft->Size ();
309
310 ft->GetEdges (mb_str, 1, &edge_info);
311 ft->GetEscapements (mb_str, 1, &escapement);
312 *advance = std::lrint (escapement * size);
313 *lb = std::lrint (edge_info.left * size);
314 *rb = *advance + std::lrint (edge_info.right * size);
315 }
316
317
318 void
319 BFont_nchar_bounds (void *font, const char *mb_str, int *advance,
320 int *lb, int *rb, int32_t n)
321 {
322 BFont *ft = (BFont *) font;
323 edge_info edge_info[n];
324 float size;
325 float escapement[n];
326
327 size = ft->Size ();
328
329 ft->GetEdges (mb_str, n, edge_info);
330 ft->GetEscapements (mb_str, n, (float *) escapement);
331
332 for (int32_t i = 0; i < n; ++i)
333 {
334 advance[i] = std::lrint (escapement[i] * size);
335 lb[i] = advance[i] - std::lrint (edge_info[i].left * size);
336 rb[i] = advance[i] + std::lrint (edge_info[i].right * size);
337 }
338 }
339
340 static void
341 font_style_to_flags (const char *style_string,
342 struct haiku_font_pattern *pattern)
343 {
344 char *style;
345 char *token;
346 int tok = 0;
347
348 style = strdup (style_string);
349
350 if (!style)
351 return;
352
353 pattern->weight = NO_WEIGHT;
354 pattern->width = NO_WIDTH;
355 pattern->slant = NO_SLANT;
356
357 while ((token = std::strtok (!tok ? style : NULL, " ")) && tok < 3)
358 {
359 if (token && !strcmp (token, "Thin"))
360 pattern->weight = HAIKU_THIN;
361 else if (token && (!strcmp (token, "UltraLight")
362 || !strcmp (token, "ExtraLight")))
363 pattern->weight = HAIKU_EXTRALIGHT;
364 else if (token && !strcmp (token, "Light"))
365 pattern->weight = HAIKU_LIGHT;
366 else if (token && !strcmp (token, "SemiLight"))
367 pattern->weight = HAIKU_SEMI_LIGHT;
368 else if (token && !strcmp (token, "Regular"))
369 {
370 if (pattern->slant == NO_SLANT)
371 pattern->slant = SLANT_REGULAR;
372
373 if (pattern->width == NO_WIDTH)
374 pattern->width = NORMAL_WIDTH;
375
376 if (pattern->weight == NO_WEIGHT)
377 pattern->weight = HAIKU_REGULAR;
378 }
379 else if (token && (!strcmp (token, "SemiBold")
380
381 || !strcmp (token, "Semibold")))
382 pattern->weight = HAIKU_SEMI_BOLD;
383 else if (token && !strcmp (token, "Bold"))
384 pattern->weight = HAIKU_BOLD;
385 else if (token && (!strcmp (token, "ExtraBold")
386
387 || !strcmp (token, "Extrabold")
388 || !strcmp (token, "UltraBold")))
389 pattern->weight = HAIKU_EXTRA_BOLD;
390 else if (token && !strcmp (token, "Book"))
391 pattern->weight = HAIKU_BOOK;
392 else if (token && !strcmp (token, "Heavy"))
393 pattern->weight = HAIKU_HEAVY;
394 else if (token && !strcmp (token, "UltraHeavy"))
395 pattern->weight = HAIKU_ULTRA_HEAVY;
396 else if (token && !strcmp (token, "Black"))
397 pattern->weight = HAIKU_BLACK;
398 else if (token && !strcmp (token, "Medium"))
399 pattern->weight = HAIKU_MEDIUM;
400 else if (token && !strcmp (token, "Oblique"))
401 pattern->slant = SLANT_OBLIQUE;
402 else if (token && !strcmp (token, "Italic"))
403 pattern->slant = SLANT_ITALIC;
404 else if (token && !strcmp (token, "UltraCondensed"))
405 pattern->width = ULTRA_CONDENSED;
406 else if (token && !strcmp (token, "ExtraCondensed"))
407 pattern->width = EXTRA_CONDENSED;
408 else if (token && !strcmp (token, "Condensed"))
409 pattern->width = CONDENSED;
410 else if (token && !strcmp (token, "SemiCondensed"))
411 pattern->width = SEMI_CONDENSED;
412 else if (token && !strcmp (token, "SemiExpanded"))
413 pattern->width = SEMI_EXPANDED;
414 else if (token && !strcmp (token, "Expanded"))
415 pattern->width = EXPANDED;
416 else if (token && !strcmp (token, "ExtraExpanded"))
417 pattern->width = EXTRA_EXPANDED;
418 else if (token && !strcmp (token, "UltraExpanded"))
419 pattern->width = ULTRA_EXPANDED;
420 else
421 {
422 tok = 1000;
423 break;
424 }
425 tok++;
426 }
427
428 if (pattern->weight != NO_WEIGHT)
429 pattern->specified |= FSPEC_WEIGHT;
430 if (pattern->slant != NO_SLANT)
431 pattern->specified |= FSPEC_SLANT;
432 if (pattern->width != NO_WIDTH)
433 pattern->specified |= FSPEC_WIDTH;
434
435 if (tok > 3)
436 {
437 pattern->specified &= ~FSPEC_SLANT;
438 pattern->specified &= ~FSPEC_WEIGHT;
439 pattern->specified &= ~FSPEC_WIDTH;
440 pattern->specified |= FSPEC_STYLE;
441 std::strncpy ((char *) &pattern->style,
442 style_string,
443 sizeof pattern->style - 1);
444 pattern->style[sizeof pattern->style - 1] = '\0';
445 }
446
447 free (style);
448 }
449
450 static bool
451 font_check_wanted_chars (struct haiku_font_pattern *pattern, font_family family,
452 char *style)
453 {
454 BFont *ft;
455 static struct font_object_cache_bucket *cached;
456 unicode_block wanted_block;
457
458 cached = lookup_font_object_data (family, style);
459 if (cached)
460 ft = cached->font_object;
461 else
462 {
463 ft = new BFont;
464
465 if (ft->SetFamilyAndStyle (family, style) != B_OK)
466 {
467 delete ft;
468 return false;
469 }
470
471 cached = cache_font_object_data (family, style, ft);
472 }
473
474 return font_object_has_chars (cached, pattern->wanted_chars,
475 pattern->want_chars_len, false);
476 }
477
478 static bool
479 font_check_one_of (struct haiku_font_pattern *pattern, font_family family,
480 char *style)
481 {
482 BFont *ft;
483 static struct font_object_cache_bucket *cached;
484 unicode_block wanted_block;
485
486 cached = lookup_font_object_data (family, style);
487 if (cached)
488 ft = cached->font_object;
489 else
490 {
491 ft = new BFont;
492
493 if (ft->SetFamilyAndStyle (family, style) != B_OK)
494 {
495 delete ft;
496 return false;
497 }
498
499 cached = cache_font_object_data (family, style, ft);
500 }
501
502 return font_object_has_chars (cached, pattern->need_one_of,
503 pattern->need_one_of_len, true);
504 }
505
506 static bool
507 font_check_language (struct haiku_font_pattern *pattern, font_family family,
508 char *style)
509 {
510 BFont *ft;
511 static struct font_object_cache_bucket *cached;
512
513 cached = lookup_font_object_data (family, style);
514 if (cached)
515 ft = cached->font_object;
516 else
517 {
518 ft = new BFont;
519
520 if (ft->SetFamilyAndStyle (family, style) != B_OK)
521 {
522 delete ft;
523 return false;
524 }
525
526 cached = cache_font_object_data (family, style, ft);
527 }
528
529 if (pattern->language == MAX_LANGUAGE)
530 return false;
531
532 return font_object_has_chars (cached, language_code_points[pattern->language],
533 3, false);
534 }
535
536 static bool
537 font_family_style_matches_p (font_family family, char *style, uint32_t flags,
538 struct haiku_font_pattern *pattern,
539 int ignore_flags_p = 0)
540 {
541 struct haiku_font_pattern m;
542 m.specified = 0;
543
544 if (style)
545 font_style_to_flags (style, &m);
546
547 if ((pattern->specified & FSPEC_FAMILY)
548 && strcmp ((char *) &pattern->family, family))
549 return false;
550
551 if (!ignore_flags_p && (pattern->specified & FSPEC_SPACING)
552 && !(pattern->mono_spacing_p) != !(flags & B_IS_FIXED))
553 return false;
554
555 if (pattern->specified & FSPEC_STYLE)
556 return style && !strcmp (style, pattern->style);
557
558
559 else if (m.specified & FSPEC_STYLE)
560 return false;
561
562 if ((pattern->specified & FSPEC_WEIGHT)
563 && (pattern->weight
564 != ((m.specified & FSPEC_WEIGHT) ? m.weight : HAIKU_REGULAR)))
565 return false;
566
567 if ((pattern->specified & FSPEC_SLANT)
568 && (pattern->slant
569 != (m.specified & FSPEC_SLANT
570 ? m.slant : SLANT_REGULAR)))
571 return false;
572
573 if ((pattern->specified & FSPEC_WANTED)
574 && !font_check_wanted_chars (pattern, family, style))
575 return false;
576
577 if ((pattern->specified & FSPEC_WIDTH)
578 && (pattern->width
579 != (m.specified & FSPEC_WIDTH
580 ? m.width : NORMAL_WIDTH)))
581 return false;
582
583 if ((pattern->specified & FSPEC_NEED_ONE_OF)
584 && !font_check_one_of (pattern, family, style))
585 return false;
586
587 if ((pattern->specified & FSPEC_LANGUAGE)
588 && !font_check_language (pattern, family, style))
589 return false;
590
591 return true;
592 }
593
594 static void
595 haiku_font_fill_pattern (struct haiku_font_pattern *pattern,
596 font_family family, char *style,
597 uint32_t flags)
598 {
599 if (style)
600 font_style_to_flags (style, pattern);
601
602 pattern->specified |= FSPEC_FAMILY;
603 std::strncpy (pattern->family, family,
604 sizeof pattern->family - 1);
605 pattern->family[sizeof pattern->family - 1] = '\0';
606 pattern->specified |= FSPEC_SPACING;
607 pattern->mono_spacing_p = flags & B_IS_FIXED;
608 }
609
610
611 void
612 haiku_font_pattern_free (struct haiku_font_pattern *pt)
613 {
614 struct haiku_font_pattern *tem = pt;
615 while (tem)
616 {
617 struct haiku_font_pattern *t = tem;
618 tem = t->next;
619 delete t;
620 }
621 }
622
623
624 struct haiku_font_pattern *
625 BFont_find (struct haiku_font_pattern *pt)
626 {
627 struct haiku_font_pattern *r = NULL;
628 font_family name;
629 font_style sname;
630 uint32 flags;
631 int sty_count, fam_count, si, fi;
632 struct haiku_font_pattern *p, *head, *n;
633 bool oblique_seen_p;
634
635 fam_count = count_font_families ();
636
637 for (fi = 0; fi < fam_count; ++fi)
638 {
639 if (get_font_family (fi, &name, &flags) == B_OK)
640 {
641 sty_count = count_font_styles (name);
642 if (!sty_count
643 && font_family_style_matches_p (name, NULL, flags, pt))
644 {
645 p = new struct haiku_font_pattern;
646 p->specified = 0;
647 p->oblique_seen_p = 1;
648 haiku_font_fill_pattern (p, name, NULL, flags);
649 p->next = r;
650 if (p->next)
651 p->next->last = p;
652 p->last = NULL;
653 p->next_family = r;
654 r = p;
655
656 if (pt->specified & FSPEC_ANTIALIAS)
657 {
658 p->specified |= FSPEC_ANTIALIAS;
659 p->use_antialiasing = pt->use_antialiasing;
660 }
661 }
662 else if (sty_count)
663 {
664 for (si = 0; si < sty_count; ++si)
665 {
666 oblique_seen_p = 0;
667 head = r;
668 p = NULL;
669
670 if (get_font_style (name, si, &sname, &flags) == B_OK)
671 {
672 if (font_family_style_matches_p (name, (char *) &sname, flags, pt))
673 {
674 p = new struct haiku_font_pattern;
675 p->specified = 0;
676 haiku_font_fill_pattern (p, name, (char *) &sname, flags);
677
678
679
680
681
682 p->specified |= FSPEC_INDICES;
683 p->family_index = fi;
684 p->style_index = si;
685
686 if (pt->specified & FSPEC_ANTIALIAS)
687 {
688 p->specified |= FSPEC_ANTIALIAS;
689 p->use_antialiasing = pt->use_antialiasing;
690 }
691
692 if (p->specified & FSPEC_SLANT
693 && (p->slant == SLANT_OBLIQUE
694 || p->slant == SLANT_ITALIC))
695 oblique_seen_p = 1;
696
697 p->next = r;
698 if (p->next)
699 p->next->last = p;
700 r = p;
701 p->next_family = head;
702 }
703 }
704
705 if (p)
706 p->last = NULL;
707
708 for (; head; head = head->last)
709 head->oblique_seen_p = oblique_seen_p;
710 }
711 }
712 }
713 }
714
715
716
717
718
719 if (!(pt->specified & FSPEC_SLANT))
720 {
721
722 for (p = r; p;)
723 {
724 if (!p->oblique_seen_p)
725 {
726 n = new haiku_font_pattern;
727 *n = *p;
728
729 n->slant = SLANT_OBLIQUE;
730
731
732
733 n->specified &= ~FSPEC_INDICES;
734 p->next = n;
735 p = p->next_family;
736 }
737 else
738 p = p->next_family;
739 }
740 }
741
742 return r;
743 }
744
745
746
747
748 void *
749 be_open_font_at_index (int family, int style, float size)
750 {
751 font_family family_name;
752 font_style style_name;
753 uint32 flags;
754 status_t rc;
755 BFont *font;
756
757 rc = get_font_family (family, &family_name, &flags);
758
759 if (rc != B_OK)
760 return NULL;
761
762 rc = get_font_style (family_name, style, &style_name, &flags);
763
764 if (rc != B_OK)
765 return NULL;
766
767 font = new BFont;
768
769 rc = font->SetFamilyAndStyle (family_name, style_name);
770
771 if (rc != B_OK)
772 {
773 delete font;
774 return NULL;
775 }
776
777 font->SetSize (size);
778 font->SetEncoding (B_UNICODE_UTF8);
779 font->SetSpacing (B_BITMAP_SPACING);
780 return font;
781 }
782
783
784
785 int
786 BFont_open_pattern (struct haiku_font_pattern *pat, void **font, float size)
787 {
788 int sty_count, si, code;
789 font_family name;
790 font_style sname;
791 BFont *ft;
792 uint32 flags = 0;
793 struct haiku_font_pattern copy;
794
795 if (!(pat->specified & FSPEC_FAMILY))
796 return 1;
797
798 strncpy (name, pat->family, sizeof name - 1);
799 name[sizeof name - 1] = '\0';
800
801 sty_count = count_font_styles (name);
802
803 if (!sty_count
804 && font_family_style_matches_p (name, NULL, flags, pat, 1))
805 {
806 ft = new BFont;
807 ft->SetSize (size);
808 ft->SetEncoding (B_UNICODE_UTF8);
809 ft->SetSpacing (B_BITMAP_SPACING);
810
811 if (ft->SetFamilyAndStyle (name, NULL) != B_OK)
812 {
813 delete ft;
814 return 1;
815 }
816 *font = (void *) ft;
817 return 0;
818 }
819 else if (sty_count)
820 {
821 for (si = 0; si < sty_count; ++si)
822 {
823 if (get_font_style (name, si, &sname, &flags) == B_OK
824 && font_family_style_matches_p (name, (char *) &sname,
825 flags, pat))
826 {
827 ft = new BFont;
828 ft->SetSize (size);
829 ft->SetEncoding (B_UNICODE_UTF8);
830 ft->SetSpacing (B_BITMAP_SPACING);
831
832 if (ft->SetFamilyAndStyle (name, sname) != B_OK)
833 {
834 delete ft;
835 return 1;
836 }
837
838 *font = (void *) ft;
839 return 0;
840 }
841 }
842 }
843
844 if (pat->specified & FSPEC_SLANT && pat->slant == SLANT_OBLIQUE)
845 {
846 copy = *pat;
847 copy.slant = SLANT_REGULAR;
848 code = BFont_open_pattern (©, font, size);
849
850 if (code)
851 return code;
852
853 ft = (BFont *) *font;
854
855
856
857 ft->SetFace (B_ITALIC_FACE);
858 return 0;
859 }
860
861 return 1;
862 }
863
864
865 void
866 BFont_populate_fixed_family (struct haiku_font_pattern *ptn)
867 {
868 font_family f;
869 font_style s;
870 be_fixed_font->GetFamilyAndStyle (&f, &s);
871
872 ptn->specified |= FSPEC_FAMILY;
873 strncpy (ptn->family, f, sizeof ptn->family - 1);
874 ptn->family[sizeof ptn->family - 1] = '\0';
875 }
876
877 void
878 BFont_populate_plain_family (struct haiku_font_pattern *ptn)
879 {
880 font_family f;
881 font_style s;
882 be_plain_font->GetFamilyAndStyle (&f, &s);
883
884 ptn->specified |= FSPEC_FAMILY;
885 strncpy (ptn->family, f, sizeof ptn->family - 1);
886 ptn->family[sizeof ptn->family - 1] = '\0';
887 }
888
889 haiku_font_family_or_style *
890 be_list_font_families (size_t *length)
891 {
892 int32 families = count_font_families ();
893 haiku_font_family_or_style *array;
894 int32 idx;
895 uint32 flags;
896
897 array = (haiku_font_family_or_style *) malloc (sizeof *array * families);
898
899 if (!array)
900 return NULL;
901
902 for (idx = 0; idx < families; ++idx)
903 {
904 if (get_font_family (idx, &array[idx], &flags) != B_OK)
905 array[idx][0] = '\0';
906 }
907
908 *length = families;
909
910 return array;
911 }
912
913 void
914 be_init_font_data (void)
915 {
916 memset (&font_object_cache, 0, sizeof font_object_cache);
917 }
918
919
920
921 void
922 be_evict_font_cache (void)
923 {
924 struct font_object_cache_bucket *bucket, *last;
925 int i;
926
927 for (i = 0; i < 2048; ++i)
928 {
929 bucket = font_object_cache[i];
930
931 while (bucket)
932 {
933 last = bucket;
934 bucket = bucket->next;
935 delete last->font_object;
936 delete last;
937 }
938
939 font_object_cache[i] = NULL;
940 }
941 }
942
943 void
944 be_font_style_to_flags (const char *style, struct haiku_font_pattern *pattern)
945 {
946 pattern->specified = 0;
947
948 font_style_to_flags (style, pattern);
949 }
950
951 int
952 be_find_font_indices (struct haiku_font_pattern *pattern,
953 int *family_index, int *style_index)
954 {
955 int32 i, j, n_families, n_styles;
956 font_family family;
957 font_style style;
958 uint32 flags;
959
960 n_families = count_font_families ();
961
962 for (i = 0; i < n_families; ++i)
963 {
964 if (get_font_family (i, &family, &flags) == B_OK)
965 {
966 n_styles = count_font_styles (family);
967
968 for (j = 0; j < n_styles; ++j)
969 {
970 if (get_font_style (family, j, &style, &flags) == B_OK
971 && font_family_style_matches_p (family, style,
972 flags, pattern))
973 {
974 *family_index = i;
975 *style_index = j;
976
977 return 0;
978 }
979 }
980 }
981 }
982
983 return 1;
984 }
985
986 void
987 be_set_font_antialiasing (void *font, bool antialias_p)
988 {
989 BFont *font_object;
990
991 font_object = (BFont *) font;
992 font_object->SetFlags (antialias_p
993 ? B_FORCE_ANTIALIASING
994 : B_DISABLE_ANTIALIASING);
995 }
996
997 static void
998 be_send_font_settings (void)
999 {
1000 struct haiku_font_change_event rq;
1001 BFile file;
1002 BPath path;
1003 status_t rc;
1004 BMessage message;
1005 font_family family;
1006 font_style style;
1007 const char *new_family, *new_style;
1008 float new_size;
1009
1010 rc = find_directory (B_USER_SETTINGS_DIRECTORY, &path);
1011
1012 if (rc < B_OK)
1013 return;
1014
1015 rc = path.Append ("system/app_server/fonts");
1016
1017 if (rc < B_OK)
1018 return;
1019
1020 if (file.SetTo (path.Path (), B_READ_ONLY) != B_OK)
1021 return;
1022
1023 if (message.Unflatten (&file) != B_OK)
1024 return;
1025
1026
1027 if (!default_locker.Lock ())
1028 gui_abort ("Failed to lock font data locker");
1029
1030
1031 be_fixed_font->GetFamilyAndStyle (&family, &style);
1032 default_size = be_fixed_font->Size ();
1033
1034
1035 new_family = message.GetString ("fixed family", family);
1036 new_style = message.GetString ("fixed style", style);
1037 new_size = message.GetFloat ("fixed size", default_size);
1038
1039
1040
1041
1042 if (!fixed_family || !fixed_style
1043 || new_size != fixed_size
1044 || strcmp (new_family, fixed_family)
1045 || strcmp (new_style, fixed_style))
1046 {
1047 memset (&rq, 0, sizeof rq);
1048 strncpy (rq.new_family, (char *) new_family,
1049 sizeof rq.new_family - 1);
1050 strncpy (rq.new_style, (char *) new_style,
1051 sizeof rq.new_style - 1);
1052 rq.new_size = new_size;
1053 rq.what = FIXED_FAMILY;
1054
1055 haiku_write (FONT_CHANGE_EVENT, &rq);
1056 }
1057
1058 if (fixed_family)
1059 free (fixed_family);
1060
1061 if (fixed_style)
1062 free (fixed_style);
1063
1064 fixed_family = strdup (new_family);
1065 fixed_style = strdup (new_style);
1066 fixed_size = new_size;
1067
1068
1069 be_plain_font->GetFamilyAndStyle (&family, &style);
1070 default_size = be_plain_font->Size ();
1071
1072
1073 new_family = message.GetString ("plain family", family);
1074 new_style = message.GetString ("plain style", style);
1075 new_size = message.GetFloat ("plain style", default_size);
1076
1077 if (!default_family || !default_style
1078 || new_size != default_size
1079 || strcmp (new_family, default_family)
1080 || strcmp (new_style, default_style))
1081 {
1082 memset (&rq, 0, sizeof rq);
1083 strncpy (rq.new_family, (char *) new_family,
1084 sizeof rq.new_family - 1);
1085 strncpy (rq.new_style, (char *) new_style,
1086 sizeof rq.new_style - 1);
1087 rq.new_size = new_size;
1088 rq.what = DEFAULT_FAMILY;
1089
1090 haiku_write (FONT_CHANGE_EVENT, &rq);
1091 }
1092
1093 if (default_family)
1094 free (default_family);
1095
1096 if (default_style)
1097 free (default_style);
1098
1099 default_family = strdup (new_family);
1100 default_style = strdup (new_style);
1101 default_size = new_size;
1102
1103 default_locker.Unlock ();
1104 }
1105
1106
1107
1108
1109
1110
1111 void
1112 be_listen_font_settings (void)
1113 {
1114 BPath path;
1115 status_t rc;
1116 BNode node;
1117 node_ref node_ref;
1118 EmacsFontMonitorLooper *looper;
1119 font_family family;
1120 font_style style;
1121
1122
1123 be_fixed_font->GetFamilyAndStyle (&family, &style);
1124 fixed_family = strdup (family);
1125 fixed_style = strdup (style);
1126 fixed_size = be_fixed_font->Size ();
1127
1128 be_plain_font->GetFamilyAndStyle (&family, &style);
1129 default_family = strdup (family);
1130 default_style = strdup (style);
1131 default_size = be_plain_font->Size ();
1132
1133 rc = find_directory (B_USER_SETTINGS_DIRECTORY, &path);
1134
1135 if (rc < B_OK)
1136 return;
1137
1138 rc = path.Append ("system/app_server/fonts");
1139
1140 if (rc < B_OK)
1141 return;
1142
1143 rc = node.SetTo (path.Path ());
1144
1145 if (rc < B_OK)
1146 return;
1147
1148 if (node.GetNodeRef (&node_ref) < B_OK)
1149 return;
1150
1151 looper = new EmacsFontMonitorLooper;
1152
1153 if (watch_node (&node_ref, B_WATCH_STAT, looper) < B_OK)
1154 {
1155 delete looper;
1156 return;
1157 }
1158
1159 looper->Run ();
1160 }
1161
1162 bool
1163 be_lock_font_defaults (void)
1164 {
1165 return default_locker.Lock ();
1166 }
1167
1168 void
1169 be_unlock_font_defaults (void)
1170 {
1171 return default_locker.Unlock ();
1172 }
1173
1174 const char *
1175 be_get_font_default (enum haiku_what_font what)
1176 {
1177 switch (what)
1178 {
1179 case FIXED_FAMILY:
1180 return fixed_family;
1181
1182 case FIXED_STYLE:
1183 return fixed_style;
1184
1185 case DEFAULT_FAMILY:
1186 return default_family;
1187
1188 case DEFAULT_STYLE:
1189 return default_style;
1190 }
1191
1192 return NULL;
1193 }
1194
1195 int
1196 be_get_font_size (enum haiku_what_font what)
1197 {
1198 switch (what)
1199 {
1200 case FIXED_FAMILY:
1201 return fixed_size;
1202
1203 case DEFAULT_FAMILY:
1204 return default_size;
1205
1206 default:
1207 return 0;
1208 }
1209 }