1 /* font-ft.c -- FreeType interface sub-module.
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 #include <sys/types.h>
35 #include "m17n-misc.h"
39 #include "internal-gui.h"
45 #include <freetype/ftbdf.h>
47 #ifdef HAVE_FONTCONFIG
48 #include <fontconfig/fontconfig.h>
50 int fontconfig_initialized = 0;
52 #endif /* not HAVE_FONTCONFIG */
54 static MSymbol Municode_bmp, Municode_full, Miso10646_1, Miso8859_1;
56 static FT_Library ft_library;
61 MSymbol weight, style, stretch;
64 static int ft_to_prop_size;
65 static MFTtoProp *ft_to_prop;
67 /** List of FreeType fonts. Keys are family names, values are plists
68 contains fonts of the corresponding family. In the deeper plist,
69 keys are Mt, values are (MFTInfo *). */
70 static MPlist *ft_font_list;
72 static int all_fonts_scaned;
74 /** Return 0 if NAME implies TrueType or OpenType fonts. Othersize
78 check_otf_filename (const char *name)
80 int len = strlen (name);
81 const char *ext = name + (len - 4);
84 || (memcmp (ext, ".ttf", 4)
85 && memcmp (ext, ".TTF", 4)
86 && memcmp (ext, ".otf", 4)
87 && memcmp (ext, ".OTF", 4)))
92 /** Setup members of FT_INFO from FT_FACE. Return the family name. */
95 set_font_info (FT_Face ft_face, MFTInfo *ft_info, MSymbol family)
97 MFont *font = &ft_info->font;
101 MPlist *charmap_list;
102 int unicode_bmp = -1, unicode_full = -1, unicode = -1;
109 len = strlen (ft_face->family_name) + 1;
110 buf = (char *) alloca (len);
111 memcpy (buf, ft_face->family_name, len);
112 for (p = buf; *p; p++)
113 if (*p >= 'A' && *p <= 'Z')
115 family = msymbol (buf);
117 mfont__set_property (font, MFONT_FAMILY, family);
119 if (ft_face->style_name)
121 len = strlen (ft_face->style_name) + 1;
122 buf = (char *) alloca (len);
123 memcpy (buf, ft_face->style_name, len);
124 for (p = buf; *p; p++)
125 if (*p >= 'A' && *p <= 'Z')
127 style = msymbol (buf);
128 for (i = 0; i < ft_to_prop_size; i++)
129 if (ft_to_prop[i].ft_style == style)
131 mfont__set_property (font, MFONT_WEIGHT, ft_to_prop[i].weight);
132 mfont__set_property (font, MFONT_STYLE, ft_to_prop[i].style);
133 mfont__set_property (font, MFONT_STRETCH, ft_to_prop[i].stretch);
140 if (i == ft_to_prop_size)
142 mfont__set_property (font, MFONT_WEIGHT, msymbol ("medium"));
143 mfont__set_property (font, MFONT_STYLE, msymbol ("r"));
144 mfont__set_property (font, MFONT_STRETCH, msymbol ("normal"));
147 mfont__set_property (font, MFONT_ADSTYLE, msymbol (""));
149 charmap_list = mplist ();
150 mplist_add (charmap_list, Mt, (void *) -1);
151 for (i = 0; i < ft_face->num_charmaps; i++)
153 char registry_buf[16];
156 sprintf (registry_buf, "%d-%d",
157 ft_face->charmaps[i]->platform_id,
158 ft_face->charmaps[i]->encoding_id);
159 registry = msymbol (registry_buf);
160 mplist_add (charmap_list, registry, (void *) i);
162 if (ft_face->charmaps[i]->platform_id == 0)
164 if (ft_face->charmaps[i]->encoding_id == 3)
166 else if (ft_face->charmaps[i]->encoding_id == 4)
169 else if (ft_face->charmaps[i]->platform_id == 3)
171 if (ft_face->charmaps[i]->encoding_id == 1)
173 else if (ft_face->charmaps[i]->encoding_id == 10)
176 else if (ft_face->charmaps[i]->platform_id == 1
177 && ft_face->charmaps[i]->encoding_id == 0)
178 mplist_add (charmap_list, msymbol ("apple-roman"), (void *) i);
180 if (unicode_full >= 0)
182 mplist_add (charmap_list, Municode_full, (void *) unicode_full);
183 mplist_add (charmap_list, Municode_bmp, (void *) unicode_full);
184 mplist_add (charmap_list, Miso10646_1, (void *) unicode_full);
185 unicode = unicode_full;
187 else if (unicode_bmp >= 0)
189 mplist_add (charmap_list, Municode_bmp, (void *) unicode_bmp);
190 mplist_add (charmap_list, Miso10646_1, (void *) unicode_bmp);
191 unicode = unicode_bmp;
195 FT_Set_Charmap (ft_face, ft_face->charmaps[unicode]);
196 for (i = 255; i >= 32; i--)
200 if (FT_Get_Char_Index (ft_face, (FT_ULong) i) == 0)
204 mplist_add (charmap_list, Miso8859_1, (void *) unicode);
207 ft_info->charmap_list = charmap_list;
209 if (! FT_IS_SCALABLE (ft_face))
211 BDF_PropertyRec prop;
213 FT_Get_BDF_Property (ft_face, "PIXEL_SIZE", &prop);
214 font->property[MFONT_SIZE] = prop.u.integer * 10;
215 FT_Get_BDF_Property (ft_face, "RESOLUTION_Y", &prop);
216 font->property[MFONT_RESY] = prop.u.integer;
224 close_ft (void *object)
226 MFTInfo *ft_info = object;
228 if (ft_info->ft_face)
230 if (ft_info->extra_info)
231 M17N_OBJECT_UNREF (ft_info->extra_info);
232 FT_Done_Face (ft_info->ft_face);
235 OTF_close (ft_info->otf);
236 #endif /* HAVE_OTF */
238 free (ft_info->filename);
239 M17N_OBJECT_UNREF (ft_info->charmap_list);
244 add_font_info (char *filename, MSymbol family)
247 BDF_PropertyRec prop;
248 MFTInfo *ft_info = NULL;
250 if (FT_New_Face (ft_library, filename, 0, &ft_face) == 0)
252 if (FT_IS_SCALABLE (ft_face)
253 || FT_Get_BDF_Property (ft_face, "PIXEL_SIZE", &prop) == 0)
258 M17N_OBJECT (ft_info, close_ft, MERROR_FONT_FT);
259 ft_info->filename = strdup (filename);
260 ft_info->otf_flag = check_otf_filename (filename);
261 fam = set_font_info (ft_face, ft_info, family);
262 plist = mplist_get (ft_font_list, fam);
266 mplist_add (ft_font_list, fam, plist);
268 mplist_add (plist, fam, ft_info);
270 FT_Done_Face (ft_face);
274 #ifdef HAVE_FONTCONFIG
277 fc_list (MSymbol family)
291 fc_config = FcConfigGetCurrent ();
292 MPLIST_DO (plist, mfont_freetype_path)
293 if (MPLIST_STRING_P (plist)
294 && (pathname = MPLIST_STRING (plist))
295 && stat (pathname, &buf) == 0)
296 FcConfigAppFontAddDir (fc_config, (FcChar8 *) pathname);
299 pattern = FcPatternCreate ();
301 FcPatternAddString (pattern, FC_FAMILY,
302 (FcChar8 *) (msymbol_name (family)));
303 os = FcObjectSetBuild (FC_FILE, NULL);
304 fs = FcFontList (fc_config, pattern, os);
309 for (i = 0; i < fs->nfont; i++)
311 FcPatternGetString (fs->fonts[i], FC_FILE, 0, (FcChar8 **) &filename);
312 add_font_info (filename, family);
314 FcFontSetDestroy (fs);
316 FcObjectSetDestroy (os);
317 FcPatternDestroy (pattern);
320 #else /* not HAVE_FONTCONFIG */
329 MPLIST_DO (plist, mfont_freetype_path)
330 if (MPLIST_STRING_P (plist)
331 && (pathname = MPLIST_STRING (plist))
332 && stat (pathname, &buf) == 0)
334 if (S_ISREG (buf.st_mode))
335 add_font_info (pathname, Mnil);
336 else if (S_ISDIR (buf.st_mode))
338 int len = strlen (pathname);
340 DIR *dir = opendir (pathname);
345 strcpy (path, pathname);
346 strcpy (path + len, "/");
348 while ((dp = readdir (dir)) != NULL)
350 strcpy (path + len, dp->d_name);
351 add_font_info (path, Mnil);
359 #endif /* not HAVE_FONTCONFIG */
361 /* The FreeType font driver function SELECT. */
363 static MRealizedFont *
364 ft_select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
369 MRealizedFont *rfont;
370 MSymbol family, registry;
374 family = FONT_PROPERTY (spec, MFONT_FAMILY);
376 family = FONT_PROPERTY (request, MFONT_FAMILY);
377 registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
378 if (registry == Mnil)
382 ft_font_list = mplist ();
383 #ifdef HAVE_FONTCONFIG
386 plist = mplist_get (ft_font_list, family);
390 plist = mplist_get (ft_font_list, family);
393 mplist_add (ft_font_list, family, plist = mplist ());
400 if (! all_fonts_scaned)
403 all_fonts_scaned = 1;
406 #else /* not HAVE_FONTCONFIG */
407 if (! all_fonts_scaned)
410 all_fonts_scaned = 1;
414 plist = mplist_get (ft_font_list, family);
418 #endif /* not HAVE_FONTCONFIG */
421 plist = MPLIST_VAL (ft_font_list);
424 MPLIST_DO (pl, plist)
426 MFTInfo *ft_info = MPLIST_VAL (pl);
429 if (! mplist_find_by_key (ft_info->charmap_list, registry))
431 /* We always ignore FOUNDRY. */
432 ft_info->font.property[MFONT_FOUNDRY] = spec->property[MFONT_FOUNDRY];
433 score = mfont__score (&ft_info->font, spec, request, limited_size);
436 || best_score > score))
446 plist = MPLIST_NEXT (plist);
447 if (! MPLIST_TAIL_P (plist))
453 MSTRUCT_CALLOC (rfont, MERROR_FONT_FT);
454 rfont->frame = frame;
456 rfont->request = *request;
457 rfont->font = best_font->font;
458 rfont->font.property[MFONT_SIZE] = request->property[MFONT_SIZE];
459 rfont->font.property[MFONT_REGISTRY] = spec->property[MFONT_REGISTRY];
460 rfont->score = best_score;
461 rfont->info = best_font;
462 M17N_OBJECT_REF (best_font);
467 /* The FreeType font driver function OPEN. */
470 ft_open (MRealizedFont *rfont)
472 MFTInfo *base = rfont->info, *ft_info;
473 MSymbol registry = FONT_PROPERTY (&rfont->font, MFONT_REGISTRY);
474 int mdebug_mask = MDEBUG_FONT;
477 M17N_OBJECT (ft_info, close_ft, MERROR_FONT_FT);
478 ft_info->font = base->font;
479 ft_info->filename = strdup (base->filename);
480 ft_info->otf_flag = base->otf_flag;
481 ft_info->charmap_list = base->charmap_list;
482 M17N_OBJECT_REF (ft_info->charmap_list);
483 M17N_OBJECT_UNREF (base);
484 rfont->info = ft_info;
487 ft_info->ft_face = NULL;
488 if (FT_New_Face (ft_library, ft_info->filename, 0, &ft_info->ft_face))
490 if (registry == Mnil)
492 ft_info->charmap_index
493 = (int) mplist_get (((MFTInfo *) rfont->info)->charmap_list, registry);
494 if (ft_info->charmap_index >= 0
495 && FT_Set_Charmap (ft_info->ft_face,
496 ft_info->ft_face->charmaps[ft_info->charmap_index]))
498 size = rfont->font.property[MFONT_SIZE] / 10;
499 if (FT_Set_Pixel_Sizes (ft_info->ft_face, 0, size))
502 MDEBUG_PRINT1 (" [FT-FONT] o %s\n", ft_info->filename);
504 rfont->ascent = ft_info->ft_face->ascender >> 6;
505 rfont->descent = - (ft_info->ft_face->descender >> 6);
509 MDEBUG_PRINT1 (" [FT-FONT] x %s\n", ft_info->filename);
510 if (ft_info->ft_face)
511 FT_Done_Face (ft_info->ft_face);
512 M17N_OBJECT_UNREF (ft_info->charmap_list);
513 free (ft_info->filename);
519 /* The FreeType font driver function FIND_METRIC. */
522 ft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
525 MFTInfo *ft_info = (MFTInfo *) rfont->info;
526 FT_Face ft_face = ft_info->ft_face;
527 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
528 FT_Int32 load_flags = FT_LOAD_RENDER;
530 #ifdef FT_LOAD_TARGET_MONO
531 load_flags |= FT_LOAD_TARGET_MONO;
533 load_flags |= FT_LOAD_MONOCHROME;
536 for (; g != gend; g++)
538 if (g->code == MCHAR_INVALID_CODE)
540 if (FT_IS_SCALABLE (ft_face))
542 unsigned unitsPerEm = ft_face->units_per_EM;
543 int size = rfont->font.property[MFONT_SIZE] / 10;
546 g->rbearing = ft_face->max_advance_width * size / unitsPerEm;
547 g->width = ft_face->max_advance_width * size / unitsPerEm;
548 g->ascent = ft_face->ascender * size / unitsPerEm;
549 g->descent = (- ft_face->descender) * size / unitsPerEm;
553 BDF_PropertyRec prop;
556 g->rbearing = g->width = ft_face->available_sizes->width;
557 if (FT_Get_BDF_Property (ft_face, "ASCENT", &prop) == 0)
559 g->ascent = prop.u.integer;
560 FT_Get_BDF_Property (ft_face, "DESCENT", &prop);
561 g->descent = prop.u.integer;
565 g->ascent = ft_face->available_sizes->height;
572 FT_Glyph_Metrics *metrics;
574 FT_Load_Glyph (ft_face, (FT_UInt) g->code, FT_LOAD_RENDER);
575 metrics = &ft_face->glyph->metrics;
576 g->lbearing = (metrics->horiBearingX >> 6);
577 g->rbearing = (metrics->horiBearingX + metrics->width) >> 6;
578 g->width = metrics->horiAdvance >> 6;
579 g->ascent = metrics->horiBearingY >> 6;
580 g->descent = (metrics->height - metrics->horiBearingY) >> 6;
585 /* The FreeType font driver function ENCODE_CHAR. */
588 ft_encode_char (MRealizedFont *rfont, unsigned code)
592 if (rfont->status == 0)
594 if ((rfont->driver->open) (rfont) < 0)
597 ft_info = (MFTInfo *) rfont->info;
598 code = (unsigned) FT_Get_Char_Index (ft_info->ft_face, (FT_ULong) code);
600 return MCHAR_INVALID_CODE;
605 /* The FreeType font driver function RENDER. */
607 #define NUM_POINTS 0x1000
610 MDrawPoint points[NUM_POINTS];
615 ft_render (MDrawWindow win, int x, int y,
616 MGlyphString *gstring, MGlyph *from, MGlyph *to,
617 int reverse, MDrawRegion region)
621 MRealizedFace *rface = from->rface;
622 MFrame *frame = rface->frame;
623 FT_Int32 load_flags = FT_LOAD_RENDER;
626 MPointTable point_table[8];
631 /* It is assured that the all glyphs in the current range use the
632 same realized face. */
633 ft_info = (MFTInfo *) rface->rfont->info;
634 ft_face = ft_info->ft_face;
636 if (! gstring->anti_alias)
638 #ifdef FT_LOAD_TARGET_MONO
639 load_flags |= FT_LOAD_TARGET_MONO;
641 load_flags |= FT_LOAD_MONOCHROME;
645 for (i = 0; i < 8; i++)
646 point_table[i].p = point_table[i].points;
648 for (g = from; g < to; x += g++->width)
656 FT_Load_Glyph (ft_face, (FT_UInt) g->code, load_flags);
657 yoff = y - ft_face->glyph->bitmap_top + g->yoff;
658 bmp = ft_face->glyph->bitmap.buffer;
659 width = ft_face->glyph->bitmap.width;
660 pitch = ft_face->glyph->bitmap.pitch;
661 if (! gstring->anti_alias)
666 if (gstring->anti_alias)
667 for (i = 0; i < ft_face->glyph->bitmap.rows;
668 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
670 xoff = x + ft_face->glyph->bitmap_left + g->xoff;
671 for (j = 0; j < width; j++, xoff++)
673 intensity = bmp[j] >> 5;
676 ptable = point_table + intensity;
680 if (ptable->p - ptable->points == NUM_POINTS)
682 (*frame->driver->draw_points)
684 reverse ? 7 - intensity : intensity,
685 ptable->points, NUM_POINTS, region);
686 ptable->p = ptable->points;
692 for (i = 0; i < ft_face->glyph->bitmap.rows;
693 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
695 xoff = x + ft_face->glyph->bitmap_left + g->xoff;
696 for (j = 0; j < width; j++, xoff++)
698 intensity = bmp[j / 8] & (1 << (7 - (j % 8)));
701 ptable = point_table;
705 if (ptable->p - ptable->points == NUM_POINTS)
707 (*frame->driver->draw_points) (frame, win, rface,
709 ptable->points, NUM_POINTS, region);
710 ptable->p = ptable->points;
717 if (gstring->anti_alias)
719 for (i = 1; i < 8; i++)
720 if (point_table[i].p != point_table[i].points)
721 (*frame->driver->draw_points) (frame, win, rface, reverse ? 7 - i : i,
722 point_table[i].points,
723 point_table[i].p - point_table[i].points, region);
727 if (point_table[0].p != point_table[0].points)
728 (*frame->driver->draw_points) (frame, win, rface, reverse ? 0 : 7,
729 point_table[0].points,
730 point_table[0].p - point_table[0].points, region);
737 MFontDriver mfont__ft_driver =
738 { ft_select, ft_open, ft_find_metric, ft_encode_char, ft_render };
745 char *weight, *style, *stretch;
746 } ft_to_prop_name[] =
747 { { "regular", "medium", "r", "normal" },
748 { "medium", "medium", "r", "normal" },
749 { "normal", "medium", "r", "normal" },
750 { "italic", "medium", "i", "normal" },
751 { "bold", "bold", "r", "normal" },
752 { "bolditalic", "bold", "i", "normal" },
753 { "bold italic", "bold", "i", "normal" },
754 { "narrow", "medium", "r", "condensed" },
755 { "narrow italic", "medium", "i", "condensed" },
756 { "narrow bold", "bold", "r", "condensed" },
757 { "narrow bold italic", "bold", "i", "condensed" },
758 { "black", "black", "r", "normal" },
759 { "black italic", "black", "i", "normal" },
760 { "oblique", "medium", "o", "normal" },
761 { "boldoblique", "bold", "o", "normal" },
762 { "bold oblique", "bold", "o", "normal" } };
765 if (FT_Init_FreeType (&ft_library) != 0)
766 MERROR (MERROR_FONT_FT, -1);
768 ft_to_prop_size = sizeof (ft_to_prop_name) / sizeof (ft_to_prop_name[0]);
769 MTABLE_MALLOC (ft_to_prop, ft_to_prop_size, MERROR_FONT_FT);
770 for (i = 0; i < ft_to_prop_size; i++)
772 ft_to_prop[i].ft_style = msymbol (ft_to_prop_name[i].ft_style);
773 ft_to_prop[i].weight = msymbol (ft_to_prop_name[i].weight);
774 ft_to_prop[i].style = msymbol (ft_to_prop_name[i].style);
775 ft_to_prop[i].stretch = msymbol (ft_to_prop_name[i].stretch);
778 Municode_bmp = msymbol ("unicode-bmp");
779 Municode_full = msymbol ("unicode-full");
780 Miso10646_1 = msymbol ("iso10646-1");
781 Miso8859_1 = msymbol ("iso8859-1");
793 MPLIST_DO (plist, ft_font_list)
795 MPLIST_DO (p, MPLIST_VAL (plist))
797 MFTInfo *ft_info = MPLIST_VAL (p);
799 M17N_OBJECT_UNREF (ft_info);
801 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
803 M17N_OBJECT_UNREF (ft_font_list);
807 FT_Done_FreeType (ft_library);
808 all_fonts_scaned = 0;
812 #ifdef HAVE_FONTCONFIG
814 mfont__ft_parse_name (char *name, MFont *font)
816 FcPattern *pat = FcNameParse ((FcChar8 *) name);
823 if ((result = FcPatternGetString (pat, FC_FOUNDRY, 0, &str)) == FcResultMatch)
824 mfont__set_property (font, MFONT_FOUNDRY, msymbol ((char *) str));
825 if ((result = FcPatternGetString (pat, FC_FAMILY, 0, &str)) == FcResultMatch)
826 mfont__set_property (font, MFONT_FAMILY, msymbol ((char *) str));
827 if ((result = FcPatternGetString (pat, FC_STYLE, 0, &str)) == FcResultMatch)
829 MSymbol style = msymbol ((char *) str);
832 for (i = 0; i < ft_to_prop_size; i++)
833 if (ft_to_prop[i].ft_style == style)
835 mfont__set_property (font, MFONT_WEIGHT, ft_to_prop[i].weight);
836 mfont__set_property (font, MFONT_STYLE, ft_to_prop[i].style);
837 mfont__set_property (font, MFONT_STRETCH, ft_to_prop[i].stretch);
841 if ((result = FcPatternGetDouble (pat, FC_PIXEL_SIZE, 0, &size))
843 font->property[MFONT_SIZE] = size * 10;
844 FcPatternDestroy (pat);
849 mfont__ft_unparse_name (MFont *font)
851 FcPattern *pat = FcPatternCreate ();
852 MSymbol sym, weight, style, stretch;
856 if ((sym = (MSymbol) FONT_PROPERTY (font, MFONT_FOUNDRY)) != Mnil)
857 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) MSYMBOL_NAME (sym));
858 if ((sym = (MSymbol) FONT_PROPERTY (font, MFONT_FAMILY)) != Mnil)
859 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) MSYMBOL_NAME (sym));
860 if ((weight = (MSymbol) FONT_PROPERTY (font, MFONT_WEIGHT)) == Mnil)
861 weight = msymbol ("medium");
862 if ((style = (MSymbol) FONT_PROPERTY (font, MFONT_STYLE)) == Mnil)
863 style = msymbol ("r");
864 if ((stretch = (MSymbol) FONT_PROPERTY (font, MFONT_STRETCH)) == Mnil)
865 stretch = msymbol ("normal");
866 for (i = 0; i < ft_to_prop_size; i++)
867 if (ft_to_prop[i].weight == weight
868 && ft_to_prop[i].style == style
869 && ft_to_prop[i].stretch == stretch)
870 FcPatternAddString (pat, FC_STYLE,
871 (FcChar8 *) MSYMBOL_NAME (ft_to_prop[i].ft_style));
872 name = (char *) FcNameUnparse (pat);
873 FcPatternDestroy (pat);
876 #endif /* HAVE_FONTCONFIG */
881 #define DEVICE_DELTA(table, size) \
882 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
883 ? (table).DeltaValue[(size) >= (table).StartSize] \
887 adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face,
888 unsigned code, int size, int *x, int *y)
890 if (anchor->AnchorFormat == 2)
893 int ap = anchor->f.f1.AnchorPoint;
895 FT_Load_Glyph (ft_face, (FT_UInt) code, FT_LOAD_MONOCHROME);
896 outline = &ft_face->glyph->outline;
897 if (ap < outline->n_points)
899 *x = outline->points[ap].x;
900 *y = outline->points[ap].y;
903 else if (anchor->AnchorFormat == 3)
905 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, size);
906 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, size);
911 mfont__ft_drive_otf (MGlyphString *gstring, int from, int to,
912 MSymbol script, MSymbol langsys,
913 MSymbol gsub_features, MSymbol gpos_features)
916 MGlyph *g = MGLYPH (from);
918 MRealizedFont *rfont;
921 OTF_GlyphString otf_gstring;
923 char *script_name, *language_name;
924 char *gsub_feature_names, *gpos_feature_names;
930 rfont = g->rface->rfont;
931 ft_info = rfont->info;
932 if (ft_info->otf_flag < 0)
937 otf = OTF_open (ft_info->filename);
938 if (otf && OTF_get_table (otf, "head") < 0)
945 ft_info->otf_flag = -1;
952 script_name = msymbol_name (script);
956 language_name = msymbol_name (langsys);
958 language_name = NULL;
960 = (gsub_features == Mt ? "*"
961 : gsub_features == Mnil ? NULL
962 : msymbol_name (gsub_features));
963 if (gsub_feature_names && OTF_check_table (otf, "GSUB") < 0)
964 gsub_feature_names = NULL;
966 = (gpos_features == Mt ? "*"
967 : gpos_features == Mnil ? NULL
968 : msymbol_name (gpos_features));
969 if (gpos_feature_names && OTF_check_table (otf, "GPOS") < 0)
970 gpos_feature_names = NULL;
972 otf_gstring.size = otf_gstring.used = len;
973 otf_gstring.glyphs = (OTF_Glyph *) alloca (sizeof (OTF_Glyph) * len);
974 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
975 for (i = 0, need_cmap = 0; i < len; i++)
977 if (gstring->glyphs[from + i].otf_encoded)
979 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].c;
980 otf_gstring.glyphs[i].glyph_id = gstring->glyphs[from + i].code;
984 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].code;
989 && OTF_drive_cmap (otf, &otf_gstring) < 0)
992 OTF_drive_gdef (otf, &otf_gstring);
993 gidx = gstring->used;
995 if (gsub_feature_names)
997 if (OTF_drive_gsub (otf, &otf_gstring, script_name, language_name,
998 gsub_feature_names) < 0)
1000 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++, otfg++)
1002 MGlyph temp = *(MGLYPH (from + otfg->f.index.from));
1005 temp.combining_code = 0;
1008 temp.code = otfg->glyph_id;
1009 temp.otf_encoded = 1;
1014 temp.otf_encoded = 0;
1016 temp.to = MGLYPH (from + otfg->f.index.to)->to;
1017 MLIST_APPEND1 (gstring, glyphs, temp, MERROR_FONT_OTF);
1021 for (i = 0; i < len; i++)
1023 MGlyph temp = gstring->glyphs[from + i];
1024 MLIST_APPEND1 (gstring, glyphs, temp, MERROR_FONT_OTF);
1027 ft_find_metric (rfont, gstring, gidx, gstring->used);
1029 if (gpos_feature_names)
1033 MGlyph *prev = NULL;
1035 if (OTF_drive_gpos (otf, &otf_gstring, script_name, language_name,
1036 gpos_feature_names) < 0)
1039 u = otf->head->unitsPerEm;
1040 size10 = rfont->font.property[MFONT_SIZE];
1043 for (i = 0, otfg = otf_gstring.glyphs, g = MGLYPH (gidx);
1044 i < otf_gstring.used; i++, otfg++, g++)
1046 if (! otfg->glyph_id)
1048 switch (otfg->positioning_type)
1054 int format = otfg->f.f1.format;
1056 if (format & OTF_XPlacement)
1057 g->xoff = otfg->f.f1.value->XPlacement * size10 / u / 10;
1058 if (format & OTF_XPlaDevice)
1059 g->xoff += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, size);
1060 if (format & OTF_YPlacement)
1061 g->yoff = - (otfg->f.f1.value->YPlacement * size10 / u / 10);
1062 if (format & OTF_YPlaDevice)
1063 g->yoff -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, size);
1064 if (format & OTF_XAdvance)
1065 g->width += otfg->f.f1.value->XAdvance * size10 / u / 10;
1066 if (format & OTF_XAdvDevice)
1067 g->width += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, size);
1071 /* Not yet supported. */
1077 int base_x, base_y, mark_x, mark_y;
1079 base_x = otfg->f.f4.base_anchor->XCoordinate * size10 / u / 10;
1080 base_y = otfg->f.f4.base_anchor->YCoordinate * size10 / u / 10;
1081 mark_x = otfg->f.f4.mark_anchor->XCoordinate * size10 / u / 10;
1082 mark_y = otfg->f.f4.mark_anchor->YCoordinate * size10 / u / 10;
1084 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
1085 adjust_anchor (otfg->f.f4.base_anchor, ft_info->ft_face,
1086 prev->code, size, &base_x, &base_y);
1087 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
1088 adjust_anchor (otfg->f.f4.mark_anchor, ft_info->ft_face,
1089 g->code, size, &mark_x, &mark_y);
1090 g->xoff = (base_x - prev->width) - mark_x;
1091 g->yoff = mark_y - base_y;
1092 g->combining_code = MAKE_COMBINING_CODE_BY_CLASS (0);
1096 /* Not yet supported. */
1098 default: /* i.e case 6 */
1099 /* Not yet supported. */
1108 ft_find_metric (rfont, gstring, from, to);
1109 for (i = 0; i < len; i++)
1111 MGlyph temp = gstring->glyphs[from + i];
1112 MLIST_APPEND1 (gstring, glyphs, temp, MERROR_FONT_OTF);
1119 mfont__ft_decode_otf (MGlyph *g)
1121 MFTInfo *ft_info = (MFTInfo *) g->rface->rfont->info;
1122 int c = OTF_get_unicode (ft_info->otf, (OTF_GlyphID) g->code);
1124 return (c ? c : -1);
1127 #endif /* HAVE_OTF */
1129 #endif /* HAVE_FREETYPE */