~ubuntu-branches/ubuntu/karmic/m17n-lib/karmic

« back to all changes in this revision

Viewing changes to src/font-ft.c

  • Committer: Bazaar Package Importer
  • Author(s): Harshula Jayasuriya
  • Date: 2008-04-04 23:15:32 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20080404231532-pys1hr3eq0qv0fcx
Tags: 1.3.4-2
libm17n-dev Depends on libxml2-dev and libthai-dev. (Closes: #473957)

Show diffs side-by-side

added added

removed removed

Lines of Context:
44
44
#ifdef HAVE_FREETYPE
45
45
 
46
46
#ifdef HAVE_FTBDF_H
47
 
#include <freetype/ftbdf.h>
 
47
#include FT_BDF_H
48
48
#endif
49
49
 
50
50
static int mdebug_mask = MDEBUG_FONT;
51
51
 
52
52
#ifdef HAVE_FONTCONFIG
 
53
#include <fontconfig/fcfreetype.h>
 
54
 
53
55
static FcConfig *fc_config;
54
56
static MSymbol Mgeneric_family;
55
57
#endif  /* HAVE_FONTCONFIG */
68
70
typedef struct
69
71
{
70
72
  MFont font;
71
 
  MPlist *lang;
72
73
#ifdef HAVE_OTF
73
74
  /* NULL if not yet opened.  invalid_otf if not OTF.  */
74
75
  OTF *otf;
82
83
typedef struct
83
84
{
84
85
  M17NObject control;
85
 
  FT_Face ft_face;
 
86
  FT_Face ft_face;              /* This must be the 2nd member. */
86
87
  MPlist *charmap_list;
 
88
  int face_encapsulated;
87
89
} MRealizedFontFT;
88
90
 
89
91
typedef struct
140
142
  } while (0)
141
143
 
142
144
 
 
145
static MPlist *ft_list_family (MSymbol, int);
 
146
 
143
147
static void
144
148
free_ft_rfont (void *object)
145
149
{
146
150
  MRealizedFontFT *ft_rfont = object;
147
151
 
148
 
  M17N_OBJECT_UNREF (ft_rfont->charmap_list);
149
 
  FT_Done_Face (ft_rfont->ft_face);
 
152
  if (! ft_rfont->face_encapsulated)
 
153
    {
 
154
      M17N_OBJECT_UNREF (ft_rfont->charmap_list);
 
155
      FT_Done_Face (ft_rfont->ft_face);
 
156
    }
150
157
  free (ft_rfont);
151
158
}
152
159
 
153
160
static void
154
161
free_ft_info (MFontFT *ft_info)
155
162
{
156
 
  M17N_OBJECT_UNREF (ft_info->lang);
157
163
#ifdef HAVE_OTF
158
164
  if (ft_info->otf && ft_info->otf != invalid_otf)
159
165
    OTF_close (ft_info->otf);
160
166
#endif /* HAVE_OTF */
 
167
#ifdef HAVE_FONTCONFIG
 
168
  if (ft_info->langset)
 
169
    FcLangSetDestroy (ft_info->langset);
 
170
  if (ft_info->charset)
 
171
    FcCharSetDestroy (ft_info->charset);
 
172
#endif  /* HAVE_FONTCONFIG */
161
173
  free (ft_info);
162
174
}
163
175
 
224
236
  return plist;
225
237
}
226
238
 
 
239
static MFontFT *
 
240
ft_gen_font (FT_Face ft_face)
 
241
{
 
242
  MFontFT *ft_info;
 
243
  MFont *font;
 
244
  char *buf;
 
245
  int bufsize = 0;
 
246
  char *stylename;
 
247
  MSymbol family;
 
248
  int size;
 
249
 
 
250
  if (FT_IS_SCALABLE (ft_face))
 
251
    size = ft_face->size->metrics.y_ppem;
 
252
  else if (ft_face->num_fixed_sizes == 0)
 
253
    return NULL;
 
254
  else
 
255
    size = ft_face->available_sizes[0].height;
 
256
 
 
257
  MSTRUCT_CALLOC (ft_info, MERROR_FONT_FT);
 
258
  font = &ft_info->font;
 
259
  STRDUP_LOWER (buf, bufsize, ft_face->family_name);
 
260
  family = msymbol (buf);
 
261
  mfont__set_property (font, MFONT_FAMILY, family);
 
262
  mfont__set_property (font, MFONT_WEIGHT, Mmedium);
 
263
  mfont__set_property (font, MFONT_STYLE, Mr);
 
264
  mfont__set_property (font, MFONT_STRETCH, Mnormal);
 
265
  mfont__set_property (font, MFONT_ADSTYLE, Mnull);
 
266
  mfont__set_property (font, MFONT_REGISTRY, Municode_bmp);
 
267
  font->size = size * 10;
 
268
  font->type = MFONT_TYPE_OBJECT;
 
269
  font->source = MFONT_SOURCE_FT;
 
270
  font->file = NULL;
 
271
 
 
272
  stylename = ft_face->style_name;
 
273
  while (*stylename)
 
274
    {
 
275
      int i;
 
276
 
 
277
      for (i = 0; i < ft_to_prop_size; i++)
 
278
        if (! strncasecmp (ft_to_prop[i].ft_style, stylename,
 
279
                           ft_to_prop[i].len))
 
280
          {
 
281
            mfont__set_property (font, ft_to_prop[i].prop,
 
282
                                 msymbol (ft_to_prop[i].val));
 
283
            stylename += ft_to_prop[i].len;
 
284
            break;
 
285
          }
 
286
      if (i == ft_to_prop_size)
 
287
        {
 
288
          char *p1 = stylename + 1;
 
289
          MSymbol sym;
 
290
 
 
291
          while (*p1 >= 'a' && *p1 <= 'z') p1++;
 
292
          sym = msymbol__with_len (stylename, p1 - stylename);
 
293
          for (i = MFONT_WEIGHT; i <= MFONT_STRETCH; i++)
 
294
            if (msymbol_get (sym, mfont__property_table[i].property))
 
295
              {
 
296
                mfont__set_property (font, i, sym);
 
297
                break;
 
298
              }
 
299
          stylename = p1;
 
300
        }
 
301
      while (*stylename && ! isalpha (*stylename))
 
302
        stylename++;
 
303
    }
 
304
  return ft_info;
 
305
}
 
306
 
227
307
#ifdef HAVE_FONTCONFIG
228
308
 
229
309
typedef struct
344
424
}
345
425
 
346
426
static void
347
 
fc_parse_pattern (FcPattern *pat, char *family, MFont *font)
 
427
fc_parse_pattern (FcPattern *pat, char *family, MFontFT *ft_info)
348
428
{
349
429
  FcChar8 *str;
350
430
  int val;
353
433
  int bufsize = 0;
354
434
  MSymbol sym;
355
435
  FcLangSet *ls;
 
436
  FcCharSet *cs;
 
437
  MFont *font = &ft_info->font;
356
438
 
357
439
  MFONT_INIT (font);
358
440
  if (FcPatternGetString (pat, FC_FOUNDRY, 0, &str) == FcResultMatch)
388
470
          || FcLangSetHasLang (ls, (FcChar8 *) "zh") != FcLangDifferentLang
389
471
          || FcLangSetHasLang (ls, (FcChar8 *) "ko") != FcLangDifferentLang)
390
472
        font->for_full_width = 1;
 
473
      ft_info->langset = FcLangSetCopy (ls);
391
474
    }
 
475
  if (FcPatternGetCharSet (pat, FC_CHARSET, 0, &cs) == FcResultMatch)
 
476
    ft_info->charset = FcCharSetCopy (cs);
392
477
 
393
478
  mfont__set_property (font, MFONT_REGISTRY, Municode_bmp);
394
479
  font->type = MFONT_TYPE_SPEC;
406
491
  MFontFT *ft_info;
407
492
 
408
493
  MSTRUCT_CALLOC (ft_info, MERROR_FONT_FT);
409
 
  fc_parse_pattern (pat, family, &ft_info->font);
 
494
  fc_parse_pattern (pat, family, ft_info);
410
495
  ft_info->font.type = MFONT_TYPE_OBJECT;
411
496
  return ft_info;
412
497
}
413
498
 
 
499
static void
 
500
fc_init_font_list (void)
 
501
{
 
502
  FcPattern *pattern = FcPatternCreate ();
 
503
  FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, NULL);
 
504
  FcFontSet *fs = FcFontList (fc_config, pattern, os);
 
505
  MPlist *plist = mplist ();
 
506
  char *buf;
 
507
  int bufsize = 0;
 
508
  int i;
 
509
 
 
510
  ft_font_list = plist;
 
511
  for (i = 0; i < fs->nfont; i++)
 
512
    {
 
513
      char *fam;
 
514
 
 
515
      if (FcPatternGetString (fs->fonts[i], FC_FAMILY, 0,
 
516
                              (FcChar8 **) &fam) != FcResultMatch)
 
517
        continue;
 
518
      STRDUP_LOWER (buf, bufsize, fam);
 
519
      plist = mplist_add (plist, msymbol (buf), NULL);
 
520
    }
 
521
  FcFontSetDestroy (fs);
 
522
  FcObjectSetDestroy (os);
 
523
  FcPatternDestroy (pattern);
 
524
}
 
525
 
 
526
static MPlist *
 
527
fc_list_pattern (FcPattern *pattern)
 
528
{
 
529
  FcObjectSet *os = NULL;
 
530
  FcFontSet *fs = NULL;
 
531
  MSymbol last_family = Mnil;
 
532
  MPlist *plist = NULL, *pl = NULL;
 
533
  char *buf;
 
534
  int bufsize = 0;
 
535
  int i;
 
536
 
 
537
  if (! (os = FcObjectSetBuild (FC_FAMILY, FC_FILE, NULL)))
 
538
    goto err;
 
539
  if (! (fs = FcFontList (fc_config, pattern, os)))
 
540
    goto err;
 
541
 
 
542
  for (i = 0; i < fs->nfont; i++)
 
543
    {
 
544
      MSymbol family, file;
 
545
      char *fam, *filename;
 
546
      MFontFT *ft_info;
 
547
 
 
548
      if (FcPatternGetString (fs->fonts[i], FC_FAMILY, 0,
 
549
                              (FcChar8 **) &fam) != FcResultMatch)
 
550
        continue;
 
551
      if (FcPatternGetString (fs->fonts[i], FC_FILE, 0,
 
552
                              (FcChar8 **) &filename) != FcResultMatch)
 
553
        continue;
 
554
      STRDUP_LOWER (buf, bufsize, fam);
 
555
      family = msymbol (buf);
 
556
      file = msymbol (filename);
 
557
      if (family != last_family)
 
558
        {
 
559
          pl = MPLIST_PLIST (ft_list_family (family, 0));
 
560
          last_family = family;
 
561
        }
 
562
      ft_info = mplist_get (pl, file);
 
563
      if (ft_info)
 
564
        {
 
565
          if (! plist)
 
566
            plist = mplist ();
 
567
          mplist_add (plist, family, ft_info);
 
568
        }
 
569
    }
 
570
 
 
571
 err:
 
572
  if (fs) FcFontSetDestroy (fs);
 
573
  if (os) FcObjectSetDestroy (os);
 
574
  return plist;
 
575
}
 
576
 
 
577
/* Return FcCharSet object built from CHAR_LIST or MT.  In the latter
 
578
   case, it is assured that the M-text contains at least one
 
579
   character.  */
 
580
 
 
581
static FcCharSet *
 
582
fc_build_charset (MPlist *char_list, MText *mt)
 
583
{
 
584
  FcCharSet *cs = FcCharSetCreate ();
 
585
 
 
586
  if (! cs)
 
587
    return NULL;
 
588
  if (char_list)
 
589
    {
 
590
      for (; ! MPLIST_TAIL_P (char_list); char_list = MPLIST_NEXT (char_list))
 
591
        if (! FcCharSetAddChar (cs, (FcChar32) MPLIST_INTEGER (char_list)))
 
592
          {
 
593
            FcCharSetDestroy (cs);
 
594
            return NULL;
 
595
          }
 
596
    }
 
597
  else
 
598
    {
 
599
      int i;
 
600
 
 
601
      for (i = mtext_nchars (mt) - 1; i >= 0; i--)
 
602
        if (! FcCharSetAddChar (cs, (FcChar32) mtext_ref_char (mt, i)))
 
603
          {
 
604
            FcCharSetDestroy (cs);
 
605
            return NULL;
 
606
          }
 
607
      if (mtext_nchars (mt) > 0
 
608
          && (mt = mtext_get_prop (mt, 0, Mtext)))
 
609
        for (i = mtext_nchars (mt) - 1; i >= 0; i--)
 
610
          if (! FcCharSetAddChar (cs, (FcChar32) mtext_ref_char (mt, i)))
 
611
            {
 
612
              FcCharSetDestroy (cs);
 
613
              return NULL;
 
614
            }
 
615
      }
 
616
  return cs;
 
617
}
 
618
 
414
619
#else   /* not HAVE_FONTCONFIG */
415
620
 
416
621
static MPlist *
429
634
 
430
635
  if (FT_New_Face (ft_library, filename, 0, &ft_face) != 0)
431
636
    return NULL;
432
 
  if (! FT_IS_SCALABLE (ft_face))
433
 
    {
434
 
      int reject;
435
 
#ifdef HAVE_FTBDF_H
436
 
      BDF_PropertyRec prop;
437
 
 
438
 
      reject = FT_Get_BDF_Property (ft_face, "PIXEL_SIZE", &prop) == 0;
439
 
      size = prop.u.integer * 10;
440
 
#else  /* not HAVE_FTBDF_H */
441
 
      reject = 1;
442
 
#endif  /* not HAVE_FTBDF_H */
443
 
      if (reject)
444
 
        {
445
 
          FT_Done_Face (ft_face);
446
 
          return NULL;
447
 
        }
448
 
    }
449
 
 
450
 
  MSTRUCT_CALLOC (ft_info, MERROR_FONT_FT);
 
637
  ft_info = ft_gen_font (ft_face);
 
638
  FT_Done_Face (ft_face);
 
639
  if (! ft_inf)
 
640
    return NULL;
 
641
 
451
642
  font = &ft_info->font;
452
 
  STRDUP_LOWER (buf, bufsize, ft_face->family_name);
453
 
  family = msymbol (buf);
454
 
  mfont__set_property (font, MFONT_FAMILY, family);
455
 
  mfont__set_property (font, MFONT_WEIGHT, Mmedium);
456
 
  mfont__set_property (font, MFONT_STYLE, Mr);
457
 
  mfont__set_property (font, MFONT_STRETCH, Mnormal);
458
 
  mfont__set_property (font, MFONT_ADSTYLE, Mnull);
459
 
  mfont__set_property (font, MFONT_REGISTRY, Municode_bmp);
460
 
  font->type = MFONT_TYPE_OBJECT;
461
 
  font->source = MFONT_SOURCE_FT;
462
 
  font->size = size;
463
643
  font->file = msymbol (filename);
464
644
 
465
 
  stylename = ft_face->style_name;
466
 
  while (*stylename)
467
 
    {
468
 
      for (i = 0; i < ft_to_prop_size; i++)
469
 
        if (! strncasecmp (ft_to_prop[i].ft_style, stylename,
470
 
                           ft_to_prop[i].len))
471
 
          {
472
 
            mfont__set_property (font, ft_to_prop[i].prop,
473
 
                                 msymbol (ft_to_prop[i].val));
474
 
            stylename += ft_to_prop[i].len;
475
 
            break;
476
 
          }
477
 
      if (i == ft_to_prop_size)
478
 
        {
479
 
          char *p1 = stylename + 1;
480
 
          MSymbol sym;
481
 
 
482
 
          while (*p1 >= 'a' && *p1 <= 'z') p1++;
483
 
          sym = msymbol__with_len (stylename, p1 - stylename);
484
 
          for (i = MFONT_WEIGHT; i <= MFONT_STRETCH; i++)
485
 
            if (msymbol_get (sym, mfont__property_table[i].property))
486
 
              {
487
 
                mfont__set_property (font, i, sym);
488
 
                break;
489
 
              }
490
 
          stylename = p1;
491
 
        }
492
 
      while (*stylename && ! isalpha (*stylename))
493
 
        stylename++;
494
 
    }
495
 
 
496
 
  FT_Done_Face (ft_face);
497
 
 
498
645
  plist = mplist_find_by_key (ft_font_list, family);
499
646
  if (plist)
500
647
    mplist_push (MPLIST_PLIST (plist), font->file, ft_info);
507
654
  return plist;
508
655
}
509
656
 
 
657
static void
 
658
ft_init_font_list (void)
 
659
{
 
660
  MPlist *plist;
 
661
  struct stat buf;
 
662
  char *pathname;
 
663
  char *path;
 
664
  USE_SAFE_ALLOCA;
 
665
 
 
666
  ft_font_list = mplist ();
 
667
  MPLIST_DO (plist, mfont_freetype_path)
 
668
    if (MPLIST_STRING_P (plist)
 
669
        && (pathname = MPLIST_STRING (plist))
 
670
        && stat (pathname, &buf) == 0)
 
671
      {
 
672
        if (S_ISREG (buf.st_mode))
 
673
          ft_add_font (pathname);
 
674
        else if (S_ISDIR (buf.st_mode))
 
675
          {
 
676
            DIR *dir = opendir (pathname);
 
677
 
 
678
            if (dir)
 
679
              {
 
680
                int len = strlen (pathname);
 
681
                struct dirent *dp;
 
682
 
 
683
                while ((dp = readdir (dir)) != NULL)
 
684
                  {
 
685
                    SAFE_ALLOCA (path, len + strlen (dp->d_name) + 2);
 
686
                    strcpy (path, pathname);
 
687
                    path[len] =  '/';
 
688
                    strcpy (path + len + 1, dp->d_name);
 
689
                    ft_add_font (path);
 
690
                  }
 
691
                closedir (dir);
 
692
              }
 
693
          }
 
694
      }
 
695
  SAFE_FREE (path);
 
696
}
 
697
 
 
698
/* Return 1 iff the font pointed by FT_INFO has all characters in
 
699
   CHAR_LIST.  */
 
700
 
 
701
static int
 
702
ft_has_char_list_p (MFontFT *ft_info, MPlist *char_list)
 
703
{
 
704
  FT_Face ft_face;
 
705
  MPlist *cl;
 
706
 
 
707
  if (FT_New_Face (ft_library, MSYMBOL_NAME (ft_info->font.file), 0, &ft_face))
 
708
    return 0;
 
709
  MPLIST_DO (cl, char_list)
 
710
    if (FT_Get_Char_Index (ft_face, (FT_ULong) MPLIST_INTEGER (cl)) == 0)
 
711
      break;
 
712
  FT_Done_Face (ft_face);
 
713
  return MPLIST_TAIL_P (cl);
 
714
}
 
715
 
 
716
/* Return ((FAMILY . FONT) ...) where FONT is a pointer to MFontFT
 
717
   that supports characters in CHAR_LIST or MT.  One of CHAR_LIST or
 
718
   MT must be NULL.  */
 
719
 
 
720
static MPlist *
 
721
ft_list_char_list (MPlist *char_list, MText *mt)
 
722
{
 
723
  MPlist *plist = NULL, *pl, *p;
 
724
 
 
725
  if (! ft_font_list)
 
726
    ft_list_family (Mnil, 0);
 
727
 
 
728
  if (mt)
 
729
    {
 
730
      int len = mtext_nchars (mt);
 
731
      MText *extra = mtext_get_prop (mt, 0, Mtext);
 
732
      int total_len = len + (extra ? mtext_nchars (extra) : 0);
 
733
      int i;
 
734
 
 
735
      char_list = mplist ();
 
736
      for (i = 0; i < total_len; i++)
 
737
        {
 
738
          int c = (i < len ? mtext_ref_char (mt, i)
 
739
                   : mtext_ref_char (extra, i - len));
 
740
 
 
741
          if (! mplist_find_by_value (char_list, (void *) c))
 
742
            mplist_push (char_list, Minteger, (void *) c);
 
743
        }
 
744
    }
 
745
 
 
746
  MPLIST_DO (pl, ft_font_list)
 
747
    {
 
748
      MPLIST_DO (p, MPLIST_PLIST (pl))
 
749
        {
 
750
          MFontFT *ft_info = MPLIST_VAL (p);
 
751
 
 
752
          if (ft_has_char_list_p (ft_info, char_list))
 
753
            {
 
754
              MSymbol family = mfont_get_prop (&ft_info->font, Mfamily);
 
755
 
 
756
              if (! plist)
 
757
                plist = mplist ();
 
758
              mplist_push (plist, family, ft_info);
 
759
            }
 
760
        }
 
761
    }
 
762
  if (mt)
 
763
    M17N_OBJECT_UNREF (char_list);
 
764
  return plist;
 
765
}
510
766
#endif  /* not HAVE_FONTCONFIG */
511
767
 
512
768
 
574
830
          pattern = FcPatternCreate ();
575
831
          FcPatternAddString (pattern, FC_FAMILY, (FcChar8 *) fam);
576
832
          os = FcObjectSetBuild (FC_FOUNDRY, FC_WEIGHT, FC_SLANT, FC_WIDTH,
577
 
                                 FC_PIXEL_SIZE, FC_LANG, FC_FILE, NULL);
 
833
                                 FC_PIXEL_SIZE, FC_LANG, FC_CHARSET, FC_FILE,
 
834
                                 NULL);
578
835
          fs = FcFontList (fc_config, pattern, os);
579
836
          p = pl = mplist ();
580
837
          for (i = 0; i < fs->nfont; i++)
669
926
 
670
927
  if (! all_fonts_scaned)
671
928
    {
672
 
      MPlist *plist;
673
 
      struct stat buf;
674
 
      char *pathname;
675
 
      char *path;
676
 
      USE_SAFE_ALLOCA;
677
 
 
678
 
      ft_font_list = mplist ();
679
 
      MPLIST_DO (plist, mfont_freetype_path)
680
 
        if (MPLIST_STRING_P (plist)
681
 
            && (pathname = MPLIST_STRING (plist))
682
 
            && stat (pathname, &buf) == 0)
683
 
          {
684
 
            if (S_ISREG (buf.st_mode))
685
 
              ft_add_font (pathname);
686
 
            else if (S_ISDIR (buf.st_mode))
687
 
              {
688
 
                DIR *dir = opendir (pathname);
689
 
 
690
 
                if (dir)
691
 
                  {
692
 
                    int len = strlen (pathname);
693
 
                    struct dirent *dp;
694
 
 
695
 
                    while ((dp = readdir (dir)) != NULL)
696
 
                      {
697
 
                        SAFE_ALLOCA (path, len + strlen (dp->d_name) + 2);
698
 
                        strcpy (path, pathname);
699
 
                        path[len] =  '/';
700
 
                        strcpy (path + len + 1, dp->d_name);
701
 
                        ft_add_font (path);
702
 
                      }
703
 
                    closedir (dir);
704
 
                  }
705
 
              }
706
 
          }
707
 
      SAFE_FREE (path);
 
929
      ft_init_font_list ();
708
930
      all_fonts_scaned = 1;
709
931
    }
710
932
  if (family == Mnil)
725
947
{
726
948
  MPlist *plist = NULL;
727
949
  MText *mt;
728
 
  int step;
729
950
 
730
951
  if (! ft_language_list)
731
952
    ft_language_list = mplist ();
732
953
  else if ((plist = mplist_find_by_key (ft_language_list, language)))
733
954
    return (MPLIST_VAL (plist) ? MPLIST_PLIST (plist) : NULL);
734
955
 
 
956
  mt = mlanguage_text (language);
 
957
 
735
958
#ifdef HAVE_FONTCONFIG
736
 
  for (step = 0; step < 2; step++)
737
 
    {
738
 
      FcPattern *pattern = NULL;
739
 
      FcObjectSet *os = NULL;
740
 
      FcFontSet *fs = NULL;
741
 
      char *buf;
742
 
      int bufsize = 0;
743
 
      int i;
744
 
 
745
 
      if (! (pattern = FcPatternCreate ())
746
 
          || ! (os = FcObjectSetBuild (FC_FAMILY, FC_FILE, NULL)))
747
 
        goto err;
748
 
      if (step == 0)
749
 
        {
750
 
          FcLangSet *ls = FcLangSetCreate ();
751
 
 
752
 
          if (! ls)
753
 
            goto err;
754
 
          if (FcLangSetAdd (ls, (FcChar8 *) MSYMBOL_NAME (language))
755
 
              && FcPatternAddLangSet (pattern, FC_LANG, ls))
756
 
            fs = FcFontList (fc_config, pattern, os);
757
 
          FcLangSetDestroy (ls);
758
 
          if (! fs)
759
 
            goto err;
760
 
        }
761
 
      else
762
 
        {
763
 
          FcCharSet *cs;
764
 
 
765
 
          if (! (mt = msymbol_get (language, Mtext)))
766
 
            break;
767
 
          if (! (cs = FcCharSetCreate ()))
768
 
            goto err;
769
 
          for (i = mtext_nchars (mt) - 1; i >= 0; i--)
770
 
            if (! FcCharSetAddChar (cs, (FcChar32) mtext_ref_char (mt, i)))
771
 
              break;
772
 
          if (i < 0
773
 
              && (mt = mtext_get_prop (mt, 0, Mtext)))
774
 
            for (i = mtext_nchars (mt) - 1; i >= 0; i--)
775
 
              if (! FcCharSetAddChar (cs, (FcChar32) mtext_ref_char (mt, i)))
776
 
                break;
777
 
          if (i < 0)
778
 
            {
779
 
              if (FcPatternAddCharSet (pattern, FC_CHARSET, cs))
780
 
                fs = FcFontList (fc_config, pattern, os);
781
 
            }
782
 
          FcCharSetDestroy (cs);
783
 
          if (! fs)
784
 
            goto err;
785
 
        }
786
 
 
787
 
      for (i = 0; i < fs->nfont; i++)
788
 
        {
789
 
          MSymbol family, file;
790
 
          char *fam, *filename;
791
 
          MPlist *pl;
792
 
          MFontFT *ft_info;
793
 
 
794
 
          if (FcPatternGetString (fs->fonts[i], FC_FAMILY, 0,
795
 
                                  (FcChar8 **) &fam) != FcResultMatch)
796
 
            continue;
797
 
          if (FcPatternGetString (fs->fonts[i], FC_FILE, 0,
798
 
                                  (FcChar8 **) &filename) != FcResultMatch)
799
 
            continue;
800
 
          STRDUP_LOWER (buf, bufsize, fam);
801
 
          family = msymbol (buf);
802
 
          file = msymbol (filename);
803
 
          pl = MPLIST_PLIST (ft_list_family (family, 0));
804
 
          ft_info = mplist_get (pl, file);
805
 
          if (ft_info)
806
 
            {
807
 
              if (! plist)
808
 
                plist = mplist ();
809
 
              mplist_add (plist, family, ft_info);
810
 
            }
811
 
        }
812
 
      FcFontSetDestroy (fs);
813
 
      FcObjectSetDestroy (os);
814
 
      FcPatternDestroy (pattern);
815
 
      if (language == msymbol ("en"))
816
 
        break;
817
 
      continue;
818
 
 
819
 
    err:
820
 
      if (os)
821
 
        FcObjectSetDestroy (os);
822
 
      if (pattern)
823
 
        FcPatternDestroy (pattern);
824
 
      MEMORY_FULL (MERROR_FONT_FT);
825
 
      return NULL;
826
 
    }
 
959
  {
 
960
    FcPattern *pattern = NULL;
 
961
    FcCharSet *cs = NULL;
 
962
    FcLangSet *ls = NULL;
 
963
 
 
964
    if (! (pattern = FcPatternCreate ()))
 
965
      goto err;
 
966
 
 
967
    if (mt && mtext_nchars (mt) > 0)
 
968
      {
 
969
        cs = fc_build_charset (NULL, mt);       
 
970
        if (cs && ! FcPatternAddCharSet (pattern, FC_CHARSET, cs))
 
971
          goto err;
 
972
      }
 
973
    else
 
974
      {
 
975
        if (! (ls = FcLangSetCreate ()))
 
976
          goto err;
 
977
        if (! FcLangSetAdd (ls, (FcChar8 *) MSYMBOL_NAME (language))
 
978
            || ! FcPatternAddLangSet (pattern, FC_LANG, ls))
 
979
          goto err;
 
980
      }
 
981
 
 
982
    plist = fc_list_pattern (pattern);
 
983
  err:
 
984
    if (cs) FcCharSetDestroy (cs);
 
985
    if (ls) FcLangSetDestroy (ls);
 
986
    if (pattern) FcPatternDestroy (pattern);
 
987
  }
 
988
#else   /* not HAVE_FONTCONFIG */
 
989
  if (mt && mtext_nchars (mt) > 0)
 
990
    plist = ft_list_char_list (NULL, mt);
 
991
#endif  /* not HAVE_FONTCONFIG */
827
992
 
828
993
  mplist_push (ft_language_list, language, plist);
829
994
  return plist;
830
 
 
831
 
#else   /* not HAVE_FONTCONFIG */
832
 
  
833
 
  if ((mt = msymbol_get (language, Mtext)))
834
 
    {
835
 
      MText *extra = mtext_get_prop (mt, 0, Mtext);
836
 
      MPlist *pl, *p;
837
 
      int len = mtext_nchars (mt);
838
 
      int extra_len = extra ? mtext_nchars (extra) : 0;
839
 
      int i;
840
 
 
841
 
      if (! ft_font_list)
842
 
        ft_list_family (Mnil, 0);
843
 
      MPLIST_DO (pl, ft_font_list)
844
 
        {
845
 
          MPLIST_DO (p, MPLIST_PLIST (pl))
846
 
            {
847
 
              MFontFT *ft_info = MPLIST_VAL (p);
848
 
              MSymbol family; 
849
 
              FT_Face ft_face;
850
 
 
851
 
              if (FT_New_Face (ft_library, MSYMBOL_NAME (ft_info->font.file),
852
 
                               0, &ft_face) != 0)
853
 
                continue;
854
 
              for (i = len - 1; i >= 0; i--)
855
 
                if (FT_Get_Char_Index (ft_face, 
856
 
                                       (FT_ULong) mtext_ref_char (mt, i)) == 0)
857
 
                  break;
858
 
              if (i < 0 && extra_len > 0)
859
 
                for (i = extra_len - 1; i >= 0; i--)
860
 
                  if (FT_Get_Char_Index (ft_face, 
861
 
                                         (FT_ULong) mtext_ref_char (extra, i)) == 0)
862
 
                    break;
863
 
              FT_Done_Face (ft_face);
864
 
              if (i >= 0)
865
 
                continue;
866
 
              if (! plist)
867
 
                plist = mplist ();
868
 
              family = mfont_get_prop (&ft_info->font, Mfamily);
869
 
              mplist_push (plist, family, ft_info);
870
 
            }
871
 
        }
872
 
    }
873
 
  return plist;
874
 
#endif  /* not HAVE_FONTCONFIG */
875
995
}
876
996
 
877
997
static MPlist *
878
998
ft_list_script (MSymbol script)
879
999
{
880
1000
  MPlist *plist = NULL;
881
 
  MPlist *language_list, *pl;
 
1001
  MPlist *char_list;
882
1002
 
883
1003
  if (! ft_script_list)
884
1004
    ft_script_list = mplist ();
885
1005
  else if ((plist = mplist_find_by_key (ft_script_list, script)))
886
1006
    return (MPLIST_VAL (plist) ? MPLIST_PLIST (plist) : NULL);
887
1007
 
888
 
  language_list = mlanguage__list (script);
889
 
  MPLIST_DO (pl, language_list)
 
1008
  char_list = mscript__char_list (script);
 
1009
 
 
1010
#ifdef HAVE_FONTCONFIG
 
1011
  if (char_list)
890
1012
    {
891
 
      MSymbol language = MPLIST_VAL (pl) ? MPLIST_SYMBOL (pl) : MPLIST_KEY (pl);
892
 
      MPlist *p = ft_list_language (language);
893
 
      MSymbol family;
 
1013
      FcPattern *pattern = NULL;
 
1014
      FcCharSet *cs;
894
1015
 
895
 
      if (! p)
896
 
        continue;
897
 
      if (! plist)
898
 
        plist = mplist ();
899
 
      MPLIST_DO (p, p)
900
 
        {
901
 
          family = MPLIST_KEY (p);
902
 
          if (! mplist_find_by_value (plist, MPLIST_VAL (p)))
903
 
            mplist_add (plist, family, MPLIST_VAL (p));
904
 
        }
 
1016
      if (! (pattern = FcPatternCreate ()))
 
1017
        goto err;
 
1018
      cs = fc_build_charset (char_list, NULL);
 
1019
      if (cs && ! FcPatternAddCharSet (pattern, FC_CHARSET, cs))
 
1020
          goto err;
 
1021
      plist = fc_list_pattern (pattern);
 
1022
    err:
 
1023
      if (cs) FcCharSetDestroy (cs);
 
1024
      if (pattern) FcPatternDestroy (pattern);
905
1025
    }
 
1026
#else  /* not HAVE_FONTCONFIG */
 
1027
  if (char_list)
 
1028
    plist = ft_list_char_list (char_list, NULL);
 
1029
#endif  /* not HAVE_FONTCONFIG */
 
1030
 
906
1031
  mplist_push (ft_script_list, script, plist);
907
 
  M17N_OBJECT_UNREF (language_list);
908
1032
  return (plist);
909
1033
}
910
1034
 
911
1035
static int
912
 
ft_check_otf (MFontFT *ft_info, MFontCapability *cap)
 
1036
ft_check_otf (MFontFT *ft_info, MFontCapability *cap, FT_Face ft_face)
913
1037
{
914
1038
#ifdef HAVE_OTF
915
1039
  if (ft_info->otf == invalid_otf)
916
1040
    return -1;
917
1041
  if (! ft_info->otf)
918
1042
    {
919
 
      ft_info->otf = OTF_open (MSYMBOL_NAME (ft_info->font.file));
 
1043
#if (LIBOTF_MAJOR_VERSION > 0 || LIBOTF_MINOR_VERSION > 9 || LIBOTF_RELEASE_NUMBER > 4)
 
1044
      if (ft_face)
 
1045
        ft_info->otf = OTF_open_ft_face (ft_face);
 
1046
      else
 
1047
#endif
 
1048
        ft_info->otf = OTF_open (MSYMBOL_NAME (ft_info->font.file));
920
1049
      if (! ft_info->otf)
921
1050
        {
922
1051
          ft_info->otf = invalid_otf;
946
1075
}
947
1076
 
948
1077
static int
949
 
ft_check_lang (MFontFT *ft_info, MFontCapability *cap)
 
1078
ft_check_language (MFontFT *ft_info, MSymbol language, FT_Face ft_face)
950
1079
{
951
 
#ifdef HAVE_FONTCONFIG
952
 
  MPlist *plist;
953
1080
  MText *mt;
954
 
  int i, j;
955
 
 
956
 
  for (i = 0; cap->lang[i] != Mnil; i++)
957
 
    {
958
 
      if (ft_info->lang
959
 
          && (plist = mplist_find_by_key (ft_info->lang, cap->lang[i])))
960
 
        {
961
 
          if (MPLIST_VAL (plist))
962
 
            return 0;
963
 
          continue;
964
 
        }
965
 
 
966
 
      if (! ft_info->langset)
967
 
        {
968
 
          FcPattern *pat = FcPatternBuild (NULL, FC_FILE, FcTypeString,
969
 
                                           MSYMBOL_NAME (ft_info->font.file),
970
 
                                           NULL);
971
 
          FcObjectSet *os = FcObjectSetBuild (FC_LANG, FC_CHARSET, NULL);
972
 
          FcFontSet *fs = FcFontList (fc_config, pat, os);
973
 
 
974
 
          if (fs->nfont == 0)
 
1081
  MText *extra;
 
1082
  int ft_face_allocaed = 0;
 
1083
  int len, total_len;
 
1084
  int i;
 
1085
 
 
1086
#ifdef HAVE_FONTCONFIG
 
1087
  if (ft_info->langset
 
1088
      && (FcLangSetHasLang (ft_info->langset,
 
1089
                            (FcChar8 *) MSYMBOL_NAME (language))
 
1090
          != FcLangDifferentLang))
 
1091
    return 0;
 
1092
#endif  /* HAVE_FONTCONFIG */
 
1093
 
 
1094
  mt = mlanguage_text (language);
 
1095
  if (! mt || mtext_nchars (mt) == 0)
 
1096
    return -1;
 
1097
 
 
1098
  if (! ft_face)
 
1099
    {
 
1100
      char *filename = MSYMBOL_NAME (ft_info->font.file);
 
1101
 
 
1102
      if (FT_New_Face (ft_library, filename, 0, &ft_face))
 
1103
        return -1;
 
1104
      ft_face_allocaed = 1;
 
1105
    }
 
1106
 
 
1107
  len = mtext_nchars (mt);
 
1108
  extra = mtext_get_prop (mt, 0, Mtext);
 
1109
  total_len = len + (extra ? mtext_nchars (extra) : 0);
 
1110
 
 
1111
  for (i = 0; i < total_len; i++)
 
1112
    {
 
1113
      int c = (i < len ? mtext_ref_char (mt, i)
 
1114
               : mtext_ref_char (extra, i - len));
 
1115
 
 
1116
#ifdef HAVE_FONTCONFIG
 
1117
      if (ft_info->charset
 
1118
          && FcCharSetHasChar (ft_info->charset, (FcChar32) c) == FcFalse)
 
1119
        break;
 
1120
#endif  /* HAVE_FONTCONFIG */
 
1121
      if (FT_Get_Char_Index (ft_face, (FT_ULong) c) == 0)
 
1122
        break;
 
1123
    }
 
1124
 
 
1125
  if (ft_face_allocaed)
 
1126
    FT_Done_Face (ft_face);
 
1127
 
 
1128
  return (i == total_len ? 0 : -1);
 
1129
}
 
1130
 
 
1131
static int
 
1132
ft_check_script (MFontFT *ft_info, MSymbol script, FT_Face ft_face)
 
1133
{
 
1134
  MPlist *char_list = mscript__char_list (script);
 
1135
 
 
1136
  if (! char_list)
 
1137
    return -1;
 
1138
#ifdef HAVE_FONTCONFIG
 
1139
  if (ft_info->charset)
 
1140
    {
 
1141
      MPLIST_DO (char_list, char_list)
 
1142
        if (FcCharSetHasChar (ft_info->charset,
 
1143
                              (FcChar32) MPLIST_INTEGER (char_list)) == FcFalse)
 
1144
          break;
 
1145
    }
 
1146
  else
 
1147
#endif  /* HAVE_FONTCONFIG */
 
1148
    {
 
1149
      int ft_face_allocaed = 0;
 
1150
 
 
1151
      if (! ft_face)
 
1152
        {
 
1153
          char *filename = MSYMBOL_NAME (ft_info->font.file);
 
1154
 
 
1155
          if (FT_New_Face (ft_library, filename, 0, &ft_face))
975
1156
            return -1;
976
 
          if (FcPatternGetLangSet (fs->fonts[0], FC_LANG, 0, &ft_info->langset)
977
 
              == FcResultMatch)
978
 
            ft_info->langset = FcLangSetCopy (ft_info->langset);
979
 
          else
980
 
            ft_info->langset = FcLangSetCreate ();
981
 
          FcPatternGetCharSet (fs->fonts[0], FC_CHARSET, 0, &ft_info->charset);
982
 
          FcFontSetDestroy (fs);
983
 
          FcObjectSetDestroy (os);
984
 
          FcPatternDestroy (pat);
985
 
        }
986
 
      if (! ft_info->lang)
987
 
        ft_info->lang = mplist ();
988
 
      if (FcLangSetHasLang (ft_info->langset,
989
 
                            (FcChar8 *) MSYMBOL_NAME (cap->lang[i]))
990
 
          != FcLangDifferentLang)
991
 
        {
992
 
          mplist_push (ft_info->lang, cap->lang[i], Mt);
993
 
          return 0;
994
 
        }
995
 
 
996
 
      mt = msymbol_get (cap->lang[i], Mtext);
997
 
      if (! mt)
998
 
        {
999
 
          mplist_push (ft_info->lang, cap->lang[i], Mnil);
1000
 
          continue;
1001
 
        }
1002
 
 
1003
 
      for (j = mtext_nchars (mt) - 1; j >= 0; j--)
1004
 
        if (! FcCharSetAddChar (ft_info->charset,
1005
 
                                (FcChar32) mtext_ref_char (mt, j)))
 
1157
          ft_face_allocaed = 1;
 
1158
        }
 
1159
 
 
1160
      MPLIST_DO (char_list, char_list)
 
1161
        if (FT_Get_Char_Index (ft_face, (FT_ULong) MPLIST_INTEGER (char_list))
 
1162
            == 0)
1006
1163
          break;
1007
 
      if (j < 0
1008
 
          && (mt = mtext_get_prop (mt, 0, Mtext)))
1009
 
        for (j = mtext_nchars (mt) - 1; j >= 0; j--)
1010
 
          if (! FcCharSetAddChar (ft_info->charset,
1011
 
                                  (FcChar32) mtext_ref_char (mt, j)))
1012
 
            break;
1013
 
      mplist_push (ft_info->lang, cap->lang[i], (j < 0 ? Mt : Mnil));
1014
 
      if (j < 0)
1015
 
        return 0;
 
1164
      if (ft_face_allocaed)
 
1165
        FT_Done_Face (ft_face);
1016
1166
    }
1017
 
#endif  /* HAVE_FONTCONFIG */
1018
 
  return -1;
 
1167
 
 
1168
  return (MPLIST_TAIL_P (char_list) ? 0 : -1);
1019
1169
}
1020
1170
 
1021
1171
static MPlist *ft_default_list;
1069
1219
static MPlist *ft_capability_list;
1070
1220
 
1071
1221
static MPlist *
1072
 
ft_list_capability (MSymbol sym)
 
1222
ft_list_capability (MSymbol capability)
1073
1223
{
1074
 
  MPlist *plist, *pl, *p;
1075
 
  MFontCapability *cap = mfont__get_capability (sym);
1076
 
 
1077
 
  if (! cap)
1078
 
    return NULL;
1079
 
  if (ft_capability_list)
1080
 
    {
1081
 
      plist = mplist_find_by_key (ft_capability_list, sym);
1082
 
      if (plist)
1083
 
        return (MPLIST_VAL (plist) ? MPLIST_VAL (plist) : NULL);
1084
 
    }
1085
 
  else
1086
 
    {
1087
 
      plist = NULL;
1088
 
      ft_capability_list = mplist ();
1089
 
    }
1090
 
 
1091
 
  if (cap->script != Mnil)
1092
 
    {
1093
 
      pl = ft_list_script (cap->script);
1094
 
      if (pl)
1095
 
        MPLIST_DO (pl, pl)
1096
 
          {
1097
 
            if (cap->script_tag && ft_check_otf (MPLIST_VAL (pl), cap) < 0)
1098
 
              continue;
1099
 
            if (cap->lang && ft_check_lang (MPLIST_VAL (pl), cap) < 0)
1100
 
              continue;
1101
 
            if (! plist)
1102
 
              plist = mplist ();
1103
 
            mplist_add (plist, MPLIST_KEY (pl), MPLIST_VAL (pl));
1104
 
        }
1105
 
      mplist_push (ft_capability_list, sym, plist);
1106
 
      return plist;
1107
 
    }
1108
 
 
1109
 
  if (cap->lang)
1110
 
    {
1111
 
      int i;
1112
 
 
1113
 
      for (i = 0; cap->lang[i] != Mnil; i++)
1114
 
        {
1115
 
          p = ft_list_language (cap->lang[i]);
1116
 
          if (p)
1117
 
            {
1118
 
              if (! plist)
1119
 
                plist = mplist ();
1120
 
              MPLIST_DO (p, p)
1121
 
                mplist_add (plist, MPLIST_KEY (p), MPLIST_VAL (p));
1122
 
            }
1123
 
        }
1124
 
    }
1125
 
  mplist_push (ft_capability_list, sym, plist);
 
1224
  MFontCapability *cap;
 
1225
  MPlist *plist = NULL, *pl;
 
1226
 
 
1227
  if (! ft_capability_list)
 
1228
    ft_capability_list = mplist ();
 
1229
  else if ((plist = mplist_find_by_key (ft_capability_list, capability)))
 
1230
    return (MPLIST_VAL (plist) ? MPLIST_VAL (plist) : NULL);
 
1231
 
 
1232
  cap = mfont__get_capability (capability);
 
1233
 
 
1234
  if (cap && cap->language != Mnil)
 
1235
    {
 
1236
      plist = ft_list_language (cap->language);
 
1237
      if (! plist)
 
1238
        return NULL;
 
1239
      plist = mplist_copy (plist);
 
1240
    }
 
1241
 
 
1242
  if (cap && cap->script != Mnil)
 
1243
    {
 
1244
      if (! plist)
 
1245
        {
 
1246
          plist = ft_list_script (cap->script);
 
1247
          if (! plist)
 
1248
            return NULL;
 
1249
          plist = mplist_copy (plist);
 
1250
        }
 
1251
      else
 
1252
        {
 
1253
          for (pl = plist; ! MPLIST_TAIL_P (pl);)
 
1254
            {
 
1255
              if (ft_check_script (MPLIST_VAL (pl), cap->script, NULL) < 0)
 
1256
                mplist_pop (pl);
 
1257
              else
 
1258
                pl = MPLIST_NEXT (pl);
 
1259
            }
 
1260
        }
 
1261
 
 
1262
      if (cap->script_tag)
 
1263
        {
 
1264
          for (pl = plist; ! MPLIST_TAIL_P (pl);)
 
1265
            {
 
1266
              if (ft_check_otf (MPLIST_VAL (pl), cap, NULL) < 0)
 
1267
                mplist_pop (pl);
 
1268
              else
 
1269
                pl = MPLIST_NEXT (pl);
 
1270
            }
 
1271
        }
 
1272
 
 
1273
      if (MPLIST_TAIL_P (plist))
 
1274
        {
 
1275
          M17N_OBJECT_UNREF (plist);
 
1276
          plist = NULL;
 
1277
        }
 
1278
    }
 
1279
 
 
1280
  mplist_push (ft_capability_list, capability, plist);
1126
1281
  return plist;
1127
1282
}
1128
1283
 
1240
1395
 
1241
1396
      for (pl = plist; ! MPLIST_TAIL_P (pl);)
1242
1397
        {
1243
 
          if (cap->script_tag && ft_check_otf (MPLIST_VAL (pl), cap) < 0)
 
1398
          if (cap->script_tag && ft_check_otf (MPLIST_VAL (pl), cap, NULL) < 0)
1244
1399
            {
1245
1400
              mplist_pop (pl);
1246
1401
              continue;
1247
1402
            }
1248
 
          if (cap->lang && ft_check_lang (MPLIST_VAL (pl), cap) < 0)
 
1403
          if (cap->language
 
1404
              && ft_check_language (MPLIST_VAL (pl), cap->language, NULL) < 0)
1249
1405
            mplist_pop (pl);
1250
1406
          else
1251
1407
            pl = MPLIST_NEXT (pl);
1296
1452
        }
1297
1453
    }
1298
1454
  M17N_OBJECT_UNREF (plist);
1299
 
#endif
 
1455
#endif  /* HAVE_FONTCONFIG */
1300
1456
  return found;
1301
1457
}
1302
1458
 
1337
1493
          return rfont;
1338
1494
    }
1339
1495
 
1340
 
  MDEBUG_DUMP (" [FONT-FT] opening ", "", mdebug_dump_font (spec));
 
1496
  MDEBUG_DUMP (" [FONT-FT] opening ", "", mdebug_dump_font (&ft_info->font));
1341
1497
 
1342
1498
  if (FT_New_Face (ft_library, MSYMBOL_NAME (ft_info->font.file), 0,
1343
1499
                   &ft_face))
1401
1557
        rfont->descent -= prop.u.integer;
1402
1558
      }
1403
1559
  }
1404
 
#endif
 
1560
#endif  /* HAVE_FTBDF_H */
1405
1561
  if (FT_IS_SCALABLE (ft_face))
1406
1562
    rfont->average_width = 0;
1407
1563
  else
1440
1596
            {
1441
1597
#ifdef HAVE_FTBDF_H
1442
1598
              BDF_PropertyRec prop;
1443
 
#endif
 
1599
#endif  /* HAVE_FTBDF_H */
1444
1600
 
1445
1601
              g->lbearing = 0;
1446
1602
              g->rbearing = g->width = ft_face->available_sizes->width;
1458
1614
                    }
1459
1615
                }
1460
1616
              else
1461
 
#endif
 
1617
#endif  /* HAVE_FTBDF_H */
1462
1618
                {
1463
1619
                  g->ascent = ft_face->available_sizes->height;
1464
1620
                  g->descent = 0;
1835
1991
  return num;
1836
1992
}
1837
1993
 
 
1994
static void
 
1995
ft_list_family_names (MFrame *frame, MPlist *plist)
 
1996
{
 
1997
  MPlist *pl;
 
1998
 
 
1999
  if (! ft_font_list)
 
2000
    {
 
2001
#ifdef HAVE_FONTCONFIG
 
2002
      fc_init_font_list ();
 
2003
#else  /* not HAVE_FONTCONFIG */
 
2004
      ft_init_font_list ();
 
2005
#endif  /* not HAVE_FONTCONFIG */
 
2006
    }
 
2007
 
 
2008
  MPLIST_DO (pl, ft_font_list)
 
2009
    {
 
2010
      MSymbol family = MPLIST_KEY (pl);
 
2011
      MPlist *p;
 
2012
 
 
2013
#ifdef HAVE_FONTCONFIG
 
2014
      if (msymbol_get (family, Mgeneric_family) != Mnil)
 
2015
        continue;
 
2016
#endif  /* HAVE_FONTCONFIG */
 
2017
      MPLIST_DO (p, plist)
 
2018
        {
 
2019
          MSymbol sym = MPLIST_SYMBOL (p);
 
2020
 
 
2021
          if (sym == family)
 
2022
            break;
 
2023
          if (strcmp (MSYMBOL_NAME (sym), MSYMBOL_NAME (family)) > 0)
 
2024
            {
 
2025
              mplist_push (p, Msymbol, family);
 
2026
              break;
 
2027
            }
 
2028
        }
 
2029
      if (MPLIST_TAIL_P (p))
 
2030
        mplist_push (p, Msymbol, family);
 
2031
    }
 
2032
}
 
2033
 
1838
2034
static int 
1839
2035
ft_check_capability (MRealizedFont *rfont, MSymbol capability)
1840
2036
{
1841
2037
  MFontFT *ft_info = (MFontFT *) rfont->font;
 
2038
  MRealizedFontFT *ft_rfont = rfont->info;
1842
2039
  MFontCapability *cap = mfont__get_capability (capability);
1843
2040
 
1844
 
  if (cap->script_tag && ft_check_otf (ft_info, cap) < 0)
1845
 
    return -1;
1846
 
  if (cap->lang && ft_check_lang (ft_info, cap) < 0)
 
2041
  if (cap->script != Mnil
 
2042
      && ft_check_script (ft_info, cap->script, ft_rfont->ft_face) < 0)
 
2043
    return -1;
 
2044
  if (cap->language != Mnil
 
2045
      && ft_check_language (ft_info, cap->language, ft_rfont->ft_face) < 0)
 
2046
    return -1;
 
2047
  if (cap->script_tag && ft_check_otf (ft_info, cap, ft_rfont->ft_face) < 0)
1847
2048
    return -1;
1848
2049
  return 0;
1849
2050
}
1850
2051
 
 
2052
static MRealizedFont *
 
2053
ft_encapsulate (MFrame *frame, MSymbol data_type, void *data)
 
2054
{
 
2055
  MFontFT *ft_info;
 
2056
  MRealizedFont *rfont;
 
2057
  MRealizedFontFT *ft_rfont;
 
2058
  FT_Face ft_face;
 
2059
 
 
2060
  if (data_type == Mfontconfig)
 
2061
    {
 
2062
#ifdef HAVE_FONTCONFIG
 
2063
      FcPattern *pattern = data;
 
2064
 
 
2065
      if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &ft_face)
 
2066
          != FcResultMatch)
 
2067
        return NULL;
 
2068
      ft_info = fc_gen_font (pattern, NULL);
 
2069
#else  /* not HAVE_FONTCONFIG */
 
2070
      return NULL;
 
2071
#endif  /* not HAVE_FONTCONFIG */
 
2072
    }
 
2073
  else if (data_type == Mfreetype)
 
2074
    {
 
2075
      ft_face = data;
 
2076
      ft_info = ft_gen_font (ft_face);
 
2077
    }
 
2078
  else
 
2079
    return NULL;
 
2080
 
 
2081
  M17N_OBJECT (ft_rfont, free_ft_rfont, MERROR_FONT_FT);
 
2082
  ft_rfont->ft_face = ft_face;
 
2083
  ft_rfont->face_encapsulated = 1;
 
2084
 
 
2085
  MDEBUG_DUMP (" [FONT-FT] encapsulating ", (char *) ft_face->family_name,);
 
2086
 
 
2087
  MSTRUCT_CALLOC (rfont, MERROR_FONT_FT);
 
2088
  rfont->font = (MFont *) ft_info;
 
2089
  rfont->info = ft_rfont;
 
2090
  rfont->fontp = ft_face;
 
2091
  rfont->driver = &mfont__ft_driver;
 
2092
  rfont->spec = ft_info->font;
 
2093
  rfont->spec.type = MFONT_TYPE_REALIZED;
 
2094
  rfont->frame = frame;
 
2095
  rfont->ascent = ft_face->size->metrics.ascender >> 6;
 
2096
  rfont->descent = - ft_face->size->metrics.descender >> 6;
 
2097
  rfont->max_advance = ft_face->size->metrics.max_advance >> 6;
 
2098
  rfont->baseline_offset = 0;
 
2099
#ifdef HAVE_FTBDF_H
 
2100
  {
 
2101
    BDF_PropertyRec prop;
 
2102
 
 
2103
    if (! FT_IS_SCALABLE (ft_face)
 
2104
        && FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &prop) == 0)
 
2105
      {
 
2106
        rfont->baseline_offset = prop.u.integer;
 
2107
        rfont->ascent += prop.u.integer;
 
2108
        rfont->descent -= prop.u.integer;
 
2109
      }
 
2110
  }
 
2111
#endif  /* HAVE_FTBDF_H */
 
2112
  if (FT_IS_SCALABLE (ft_face))
 
2113
    rfont->average_width = 0;
 
2114
  else
 
2115
    rfont->average_width = ft_face->available_sizes->width;
 
2116
  rfont->next = MPLIST_VAL (frame->realized_font_list);
 
2117
  MPLIST_VAL (frame->realized_font_list) = rfont;
 
2118
 
 
2119
  return rfont;
 
2120
}
 
2121
 
 
2122
static void
 
2123
ft_close (MRealizedFont *rfont)
 
2124
{
 
2125
  if (! rfont->encapsulating)
 
2126
    return;
 
2127
  free (rfont->font);
 
2128
  M17N_OBJECT_UNREF (rfont->info);
 
2129
  free (rfont);
 
2130
}
 
2131
 
1851
2132
 
1852
2133
 
1853
2134
/* Internal API */
1854
2135
 
1855
2136
MFontDriver mfont__ft_driver =
1856
2137
  { ft_select, ft_open, ft_find_metric, ft_has_char, ft_encode_char,
1857
 
    ft_render, ft_list , ft_check_capability};
 
2138
    ft_render, ft_list, ft_list_family_names, ft_check_capability,
 
2139
    ft_encapsulate, ft_close };
1858
2140
 
1859
2141
int
1860
2142
mfont__ft_init ()
2063
2345
 
2064
2346
#define DEVICE_DELTA(table, size)                               \
2065
2347
  (((size) >= (table).StartSize && (size) <= (table).EndSize)   \
2066
 
   ? (table).DeltaValue[(size) >= (table).StartSize]            \
 
2348
   ? (table).DeltaValue[(size) - (table).StartSize]             \
2067
2349
   : 0)
2068
2350
 
2069
2351
void
2119
2401
  otf = ft_info->otf;
2120
2402
  if (! otf)
2121
2403
    {
 
2404
      MRealizedFontFT *ft_rfont = rfont->info;
 
2405
 
 
2406
#if (LIBOTF_MAJOR_VERSION > 0 || LIBOTF_MINOR_VERSION > 9 || LIBOTF_RELEASE_NUMBER > 4)
 
2407
      otf = OTF_open_ft_face (ft_rfont->ft_face);
 
2408
#else
2122
2409
      otf = OTF_open (MSYMBOL_NAME (ft_info->font.file));
 
2410
#endif
2123
2411
      if (! otf)
2124
2412
        {
2125
2413
          ft_info->otf = invalid_otf;
2310
2598
  return to;
2311
2599
 
2312
2600
 simple_copy:
2313
 
  ft_find_metric (rfont, gstring, from, to);
 
2601
  for (i = 0; i < len; i++)
 
2602
    {
 
2603
      MGlyph *g = MGLYPH (from + i);
 
2604
 
 
2605
      if (! g->otf_encoded)
 
2606
        {
 
2607
          g->code = rfont->driver->encode_char (gstring->frame, (MFont *) rfont,
 
2608
                                                NULL, g->code);
 
2609
          g->otf_encoded = 1;
 
2610
        }
 
2611
    }
 
2612
 
 
2613
  rfont->driver->find_metric (rfont, gstring, from, to);
2314
2614
  for (i = 0; i < len; i++)
2315
2615
    {
2316
2616
      MGlyph temp = gstring->glyphs[from + i];