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 MGlyph *prev, int size, int *x, int *y)
890 if (anchor->AnchorFormat == 2 && prev)
893 int ap = anchor->f.f1.AnchorPoint;
895 FT_Load_Glyph (ft_face, (FT_UInt) prev->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_gsub (MGlyphString *gstring, int from, int to)
918 OTF_GlyphString otf_gstring;
920 char *script_name, *language_name;
921 char *gsub_feature_names;
922 int from_pos, to_pos;
928 g = gstring->glyphs[from];
929 ft_info = g.rface->rfont->info;
930 if (ft_info->otf_flag < 0)
935 otf = OTF_open (ft_info->filename);
936 if (otf && OTF_get_table (otf, "head") < 0)
943 ft_info->otf_flag = -1;
949 if (g.otf_cmd->script != Mnil)
950 script_name = msymbol_name (g.otf_cmd->script);
953 if (g.otf_cmd->langsys != Mnil)
954 language_name = msymbol_name (g.otf_cmd->langsys);
956 language_name = NULL;
958 = (g.otf_cmd->gsub_features == Mt ? "*"
959 : g.otf_cmd->gsub_features == Mnil ? NULL
960 : msymbol_name (g.otf_cmd->gsub_features));
961 if (gsub_feature_names && OTF_check_table (otf, "GSUB") < 0)
962 gsub_feature_names = NULL;
963 if (! gsub_feature_names)
968 for (i = from + 1; i < to; i++)
970 if (from_pos > gstring->glyphs[i].pos)
971 from_pos = gstring->glyphs[i].pos;
972 if (to_pos < gstring->glyphs[i].to)
973 to_pos = gstring->glyphs[i].to;
976 otf_gstring.size = otf_gstring.used = len;
977 otf_gstring.glyphs = (OTF_Glyph *) alloca (sizeof (OTF_Glyph) * len);
978 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
979 for (i = 0, need_cmap = 0; i < len; i++)
981 if (gstring->glyphs[from + i].otf_encoded)
983 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].c;
984 otf_gstring.glyphs[i].glyph_id = gstring->glyphs[from + i].code;
988 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].code;
993 && OTF_drive_cmap (otf, &otf_gstring) < 0)
995 if (OTF_drive_gsub (otf, &otf_gstring, script_name, language_name,
996 gsub_feature_names) < 0)
1001 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++, otfg++)
1003 g.combining_code = 0;
1007 g.code = otfg->glyph_id;
1015 MLIST_APPEND1 (gstring, glyphs, g, MERROR_FONT_OTF);
1020 for (i = 0; i < len; i++)
1022 g = gstring->glyphs[from + i];
1023 MLIST_APPEND1 (gstring, glyphs, g, MERROR_FONT_OTF);
1029 mfont__ft_drive_gpos (MGlyphString *gstring, int from, int to)
1031 int len = to - from;
1036 OTF_GlyphString otf_gstring;
1037 char *script_name, *language_name;
1038 char *gpos_feature_names;
1041 int inc, from_idx, to_idx;
1047 ft_info = g->rface->rfont->info;
1048 if (ft_info->otf_flag < 0)
1053 if (g->otf_cmd->script != Mnil)
1054 script_name = msymbol_name (g->otf_cmd->script);
1057 if (g->otf_cmd->langsys != Mnil)
1058 language_name = msymbol_name (g->otf_cmd->langsys);
1060 language_name = NULL;
1062 = (g->otf_cmd->gpos_features == Mt ? "*"
1063 : g->otf_cmd->gpos_features == Mnil ? NULL
1064 : msymbol_name (g->otf_cmd->gpos_features));
1065 if (gpos_feature_names && OTF_check_table (otf, "GPOS") < 0)
1066 gpos_feature_names = NULL;
1067 if (! gpos_feature_names)
1070 otf_gstring.size = otf_gstring.used = len;
1071 otf_gstring.glyphs = (OTF_Glyph *) alloca (sizeof (OTF_Glyph) * len);
1072 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
1073 if (g->bidi_level & 1)
1074 from_idx = len - 1, to_idx = -1, inc = -1;
1076 from_idx = 0, to_idx = len, inc = 1;
1078 for (i = from_idx; i != to_idx; i += inc)
1080 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].c;
1081 otf_gstring.glyphs[i].glyph_id = gstring->glyphs[from + i].code;
1083 if (OTF_drive_gpos (otf, &otf_gstring, script_name, language_name,
1084 gpos_feature_names) < 0)
1087 u = otf->head->unitsPerEm;
1088 size10 = g->rface->rfont->font.property[MFONT_SIZE];
1090 for (i = from_idx; i != to_idx; i += inc)
1092 OTF_Glyph *otfg = otf_gstring.glyphs + i;
1094 switch (otfg->positioning_type)
1100 int format = otfg->f.f1.format;
1102 if (format & OTF_XPlacement)
1103 g->xoff = otfg->f.f1.value->XPlacement * size10 / u / 10;
1104 if (format & OTF_XPlaDevice)
1105 g->xoff += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, size);
1106 if (format & OTF_YPlacement)
1107 g->yoff = otfg->f.f1.value->YPlacement * size10 / u / 10;
1108 if (format & OTF_YPlaDevice)
1109 g->yoff += DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, size);
1113 /* Not yet supported. */
1117 int base_x, base_y, mark_x, mark_y;
1118 MGlyph *prev = g - inc;
1120 base_x = otfg->f.f4.base_anchor->XCoordinate * size10 / u / 10;
1121 base_y = otfg->f.f4.base_anchor->YCoordinate * size10 / u / 10;
1122 mark_x = otfg->f.f4.mark_anchor->XCoordinate * size10 / u / 10;
1123 mark_y = otfg->f.f4.mark_anchor->YCoordinate * size10 / u / 10;
1125 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
1126 adjust_anchor (otfg->f.f4.base_anchor, ft_info->ft_face,
1127 prev, size, &base_x, &base_y);
1128 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
1129 adjust_anchor (otfg->f.f4.mark_anchor, ft_info->ft_face,
1130 g, size, &mark_x, &mark_y);
1131 g->xoff = (base_x - prev->width) - mark_x;
1132 g->yoff = base_y - mark_y;
1143 /* Not yet supported. */
1145 default: /* i.e case 6 */
1146 /* Not yet supported. */
1154 mfont__ft_decode_otf (MGlyph *g)
1156 MFTInfo *ft_info = (MFTInfo *) g->rface->rfont->info;
1157 int c = OTF_get_unicode (ft_info->otf, (OTF_GlyphID) g->code);
1159 return (c ? c : -1);
1162 #endif /* HAVE_OTF */
1164 #endif /* HAVE_FREETYPE */