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, FC_FOUNDRY, FC_FAMILY, FC_STYLE, FC_PIXEL_SIZE, NULL);
304 fs = FcFontList (fc_config, pattern, os);
310 for (i = 0; i < fs->nfont; i++)
312 FcPatternGetString (fs->fonts[i], FC_FILE, 0,
313 (FcChar8 **) &filename);
314 add_font_info (filename, family);
321 FcConfigSubstitute (fc_config, pattern, FcMatchPattern);
322 FcDefaultSubstitute (pattern);
323 match = FcFontMatch (fc_config, pattern, &result);
324 if (FcPatternGetString (match, FC_FILE, 0, (FcChar8 **) &filename)
326 add_font_info (filename, family);
327 FcPatternDestroy (match);
329 FcFontSetDestroy (fs);
331 FcObjectSetDestroy (os);
332 FcPatternDestroy (pattern);
335 #else /* not HAVE_FONTCONFIG */
344 MPLIST_DO (plist, mfont_freetype_path)
345 if (MPLIST_STRING_P (plist)
346 && (pathname = MPLIST_STRING (plist))
347 && stat (pathname, &buf) == 0)
349 if (S_ISREG (buf.st_mode))
350 add_font_info (pathname, Mnil);
351 else if (S_ISDIR (buf.st_mode))
353 int len = strlen (pathname);
355 DIR *dir = opendir (pathname);
360 strcpy (path, pathname);
361 strcpy (path + len, "/");
363 while ((dp = readdir (dir)) != NULL)
365 strcpy (path + len, dp->d_name);
366 add_font_info (path, Mnil);
374 #endif /* not HAVE_FONTCONFIG */
376 /* The FreeType font driver function SELECT. */
378 static MRealizedFont *
379 ft_select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
384 MRealizedFont *rfont;
385 MSymbol family, registry;
389 family = FONT_PROPERTY (spec, MFONT_FAMILY);
391 family = FONT_PROPERTY (request, MFONT_FAMILY);
392 registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
393 if (registry == Mnil)
397 ft_font_list = mplist ();
398 #ifdef HAVE_FONTCONFIG
401 plist = mplist_get (ft_font_list, family);
405 plist = mplist_get (ft_font_list, family);
408 mplist_add (ft_font_list, family, plist = mplist ());
415 if (! all_fonts_scaned)
418 all_fonts_scaned = 1;
421 #else /* not HAVE_FONTCONFIG */
422 if (! all_fonts_scaned)
425 all_fonts_scaned = 1;
429 plist = mplist_get (ft_font_list, family);
433 #endif /* not HAVE_FONTCONFIG */
436 plist = MPLIST_VAL (ft_font_list);
439 MPLIST_DO (pl, plist)
441 MFTInfo *ft_info = MPLIST_VAL (pl);
444 if (! mplist_find_by_key (ft_info->charmap_list, registry))
446 /* We always ignore FOUNDRY. */
447 ft_info->font.property[MFONT_FOUNDRY] = spec->property[MFONT_FOUNDRY];
448 score = mfont__score (&ft_info->font, spec, request, limited_size);
451 || best_score > score))
461 plist = MPLIST_NEXT (plist);
462 if (! MPLIST_TAIL_P (plist))
468 MSTRUCT_CALLOC (rfont, MERROR_FONT_FT);
469 rfont->frame = frame;
471 rfont->request = *request;
472 rfont->font = best_font->font;
473 rfont->font.property[MFONT_SIZE] = request->property[MFONT_SIZE];
474 rfont->font.property[MFONT_REGISTRY] = spec->property[MFONT_REGISTRY];
475 rfont->score = best_score;
476 rfont->info = best_font;
477 M17N_OBJECT_REF (best_font);
482 /* The FreeType font driver function OPEN. */
485 ft_open (MRealizedFont *rfont)
487 MFTInfo *base = rfont->info, *ft_info;
488 MSymbol registry = FONT_PROPERTY (&rfont->font, MFONT_REGISTRY);
489 int mdebug_mask = MDEBUG_FONT;
492 M17N_OBJECT (ft_info, close_ft, MERROR_FONT_FT);
493 ft_info->font = base->font;
494 ft_info->filename = strdup (base->filename);
495 ft_info->otf_flag = base->otf_flag;
496 ft_info->charmap_list = base->charmap_list;
497 M17N_OBJECT_REF (ft_info->charmap_list);
498 M17N_OBJECT_UNREF (base);
499 rfont->info = ft_info;
502 ft_info->ft_face = NULL;
503 if (FT_New_Face (ft_library, ft_info->filename, 0, &ft_info->ft_face))
505 if (registry == Mnil)
507 ft_info->charmap_index
508 = (int) mplist_get (((MFTInfo *) rfont->info)->charmap_list, registry);
509 if (ft_info->charmap_index >= 0
510 && FT_Set_Charmap (ft_info->ft_face,
511 ft_info->ft_face->charmaps[ft_info->charmap_index]))
513 size = rfont->font.property[MFONT_SIZE] / 10;
514 if (FT_Set_Pixel_Sizes (ft_info->ft_face, 0, size))
517 MDEBUG_PRINT1 (" [FT-FONT] o %s\n", ft_info->filename);
519 rfont->ascent = ft_info->ft_face->ascender >> 6;
520 rfont->descent = - (ft_info->ft_face->descender >> 6);
524 MDEBUG_PRINT1 (" [FT-FONT] x %s\n", ft_info->filename);
525 if (ft_info->ft_face)
526 FT_Done_Face (ft_info->ft_face);
527 M17N_OBJECT_UNREF (ft_info->charmap_list);
528 free (ft_info->filename);
534 /* The FreeType font driver function FIND_METRIC. */
537 ft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
540 MFTInfo *ft_info = (MFTInfo *) rfont->info;
541 FT_Face ft_face = ft_info->ft_face;
542 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
543 FT_Int32 load_flags = FT_LOAD_RENDER;
545 #ifdef FT_LOAD_TARGET_MONO
546 load_flags |= FT_LOAD_TARGET_MONO;
548 load_flags |= FT_LOAD_MONOCHROME;
551 for (; g != gend; g++)
553 if (g->code == MCHAR_INVALID_CODE)
555 if (FT_IS_SCALABLE (ft_face))
557 unsigned unitsPerEm = ft_face->units_per_EM;
558 int size = rfont->font.property[MFONT_SIZE] / 10;
561 g->rbearing = ft_face->max_advance_width * size / unitsPerEm;
562 g->width = ft_face->max_advance_width * size / unitsPerEm;
563 g->ascent = ft_face->ascender * size / unitsPerEm;
564 g->descent = (- ft_face->descender) * size / unitsPerEm;
568 BDF_PropertyRec prop;
571 g->rbearing = g->width = ft_face->available_sizes->width;
572 if (FT_Get_BDF_Property (ft_face, "ASCENT", &prop) == 0)
574 g->ascent = prop.u.integer;
575 FT_Get_BDF_Property (ft_face, "DESCENT", &prop);
576 g->descent = prop.u.integer;
580 g->ascent = ft_face->available_sizes->height;
587 FT_Glyph_Metrics *metrics;
589 FT_Load_Glyph (ft_face, (FT_UInt) g->code, FT_LOAD_RENDER);
590 metrics = &ft_face->glyph->metrics;
591 g->lbearing = (metrics->horiBearingX >> 6);
592 g->rbearing = (metrics->horiBearingX + metrics->width) >> 6;
593 g->width = metrics->horiAdvance >> 6;
594 g->ascent = metrics->horiBearingY >> 6;
595 g->descent = (metrics->height - metrics->horiBearingY) >> 6;
600 /* The FreeType font driver function ENCODE_CHAR. */
603 ft_encode_char (MRealizedFont *rfont, unsigned code)
607 if (rfont->status == 0)
609 if ((rfont->driver->open) (rfont) < 0)
612 ft_info = (MFTInfo *) rfont->info;
613 code = (unsigned) FT_Get_Char_Index (ft_info->ft_face, (FT_ULong) code);
615 return MCHAR_INVALID_CODE;
620 /* The FreeType font driver function RENDER. */
622 #define NUM_POINTS 0x1000
625 MDrawPoint points[NUM_POINTS];
630 ft_render (MDrawWindow win, int x, int y,
631 MGlyphString *gstring, MGlyph *from, MGlyph *to,
632 int reverse, MDrawRegion region)
636 MRealizedFace *rface = from->rface;
637 MFrame *frame = rface->frame;
638 FT_Int32 load_flags = FT_LOAD_RENDER;
641 MPointTable point_table[8];
646 /* It is assured that the all glyphs in the current range use the
647 same realized face. */
648 ft_info = (MFTInfo *) rface->rfont->info;
649 ft_face = ft_info->ft_face;
651 if (! gstring->anti_alias)
653 #ifdef FT_LOAD_TARGET_MONO
654 load_flags |= FT_LOAD_TARGET_MONO;
656 load_flags |= FT_LOAD_MONOCHROME;
660 for (i = 0; i < 8; i++)
661 point_table[i].p = point_table[i].points;
663 for (g = from; g < to; x += g++->width)
671 FT_Load_Glyph (ft_face, (FT_UInt) g->code, load_flags);
672 yoff = y - ft_face->glyph->bitmap_top + g->yoff;
673 bmp = ft_face->glyph->bitmap.buffer;
674 width = ft_face->glyph->bitmap.width;
675 pitch = ft_face->glyph->bitmap.pitch;
676 if (! gstring->anti_alias)
681 if (gstring->anti_alias)
682 for (i = 0; i < ft_face->glyph->bitmap.rows;
683 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
685 xoff = x + ft_face->glyph->bitmap_left + g->xoff;
686 for (j = 0; j < width; j++, xoff++)
688 intensity = bmp[j] >> 5;
691 ptable = point_table + intensity;
695 if (ptable->p - ptable->points == NUM_POINTS)
697 (*frame->driver->draw_points)
699 reverse ? 7 - intensity : intensity,
700 ptable->points, NUM_POINTS, region);
701 ptable->p = ptable->points;
707 for (i = 0; i < ft_face->glyph->bitmap.rows;
708 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
710 xoff = x + ft_face->glyph->bitmap_left + g->xoff;
711 for (j = 0; j < width; j++, xoff++)
713 intensity = bmp[j / 8] & (1 << (7 - (j % 8)));
716 ptable = point_table;
720 if (ptable->p - ptable->points == NUM_POINTS)
722 (*frame->driver->draw_points) (frame, win, rface,
724 ptable->points, NUM_POINTS, region);
725 ptable->p = ptable->points;
732 if (gstring->anti_alias)
734 for (i = 1; i < 8; i++)
735 if (point_table[i].p != point_table[i].points)
736 (*frame->driver->draw_points) (frame, win, rface, reverse ? 7 - i : i,
737 point_table[i].points,
738 point_table[i].p - point_table[i].points, region);
742 if (point_table[0].p != point_table[0].points)
743 (*frame->driver->draw_points) (frame, win, rface, reverse ? 0 : 7,
744 point_table[0].points,
745 point_table[0].p - point_table[0].points, region);
752 MFontDriver mfont__ft_driver =
753 { ft_select, ft_open, ft_find_metric, ft_encode_char, ft_render };
760 char *weight, *style, *stretch;
761 } ft_to_prop_name[] =
762 { { "regular", "medium", "r", "normal" },
763 { "italic", "medium", "i", "normal" },
764 { "bold", "bold", "r", "normal" },
765 { "bold italic", "bold", "i", "normal" },
766 { "narrow", "medium", "r", "condensed" },
767 { "narrow italic", "medium", "i", "condensed" },
768 { "narrow bold", "bold", "r", "condensed" },
769 { "narrow bold italic", "bold", "i", "condensed" },
770 { "black", "black", "r", "normal" },
771 { "black italic", "black", "i", "normal" },
772 { "oblique", "medium", "o", "normal" },
773 { "boldoblique", "bold", "o", "normal" } };
776 if (FT_Init_FreeType (&ft_library) != 0)
777 MERROR (MERROR_FONT_FT, -1);
779 ft_to_prop_size = sizeof (ft_to_prop_name) / sizeof (ft_to_prop_name[0]);
780 MTABLE_MALLOC (ft_to_prop, ft_to_prop_size, MERROR_FONT_FT);
781 for (i = 0; i < ft_to_prop_size; i++)
783 ft_to_prop[i].ft_style = msymbol (ft_to_prop_name[i].ft_style);
784 ft_to_prop[i].weight = msymbol (ft_to_prop_name[i].weight);
785 ft_to_prop[i].style = msymbol (ft_to_prop_name[i].style);
786 ft_to_prop[i].stretch = msymbol (ft_to_prop_name[i].stretch);
789 Municode_bmp = msymbol ("unicode-bmp");
790 Municode_full = msymbol ("unicode-full");
791 Miso10646_1 = msymbol ("iso10646-1");
792 Miso8859_1 = msymbol ("iso8859-1");
804 MPLIST_DO (plist, ft_font_list)
806 MPLIST_DO (p, MPLIST_VAL (plist))
808 MFTInfo *ft_info = MPLIST_VAL (p);
810 M17N_OBJECT_UNREF (ft_info);
812 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
814 M17N_OBJECT_UNREF (ft_font_list);
818 FT_Done_FreeType (ft_library);
819 all_fonts_scaned = 0;
823 #ifdef HAVE_FONTCONFIG
825 mfont__ft_parse_name (char *name, MFont *font)
827 FcPattern *pat = FcNameParse ((FcChar8 *) name);
834 if ((result = FcPatternGetString (pat, FC_FOUNDRY, 0, &str)) == FcResultMatch)
835 mfont__set_property (font, MFONT_FOUNDRY, msymbol ((char *) str));
836 if ((result = FcPatternGetString (pat, FC_FAMILY, 0, &str)) == FcResultMatch)
837 mfont__set_property (font, MFONT_FAMILY, msymbol ((char *) str));
838 if ((result = FcPatternGetString (pat, FC_STYLE, 0, &str)) == FcResultMatch)
840 MSymbol style = msymbol ((char *) str);
843 for (i = 0; i < ft_to_prop_size; i++)
844 if (ft_to_prop[i].ft_style == style)
846 mfont__set_property (font, MFONT_WEIGHT, ft_to_prop[i].weight);
847 mfont__set_property (font, MFONT_STYLE, ft_to_prop[i].style);
848 mfont__set_property (font, MFONT_STRETCH, ft_to_prop[i].stretch);
852 if ((result = FcPatternGetDouble (pat, FC_PIXEL_SIZE, 0, &size))
854 font->property[MFONT_SIZE] = size * 10;
855 FcPatternDestroy (pat);
860 mfont__ft_unparse_name (MFont *font)
862 FcPattern *pat = FcPatternCreate ();
863 MSymbol sym, weight, style, stretch;
867 if ((sym = (MSymbol) FONT_PROPERTY (font, MFONT_FOUNDRY)) != Mnil)
868 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) MSYMBOL_NAME (sym));
869 if ((sym = (MSymbol) FONT_PROPERTY (font, MFONT_FAMILY)) != Mnil)
870 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) MSYMBOL_NAME (sym));
871 if ((weight = (MSymbol) FONT_PROPERTY (font, MFONT_WEIGHT)) == Mnil)
872 weight = msymbol ("medium");
873 if ((style = (MSymbol) FONT_PROPERTY (font, MFONT_STYLE)) == Mnil)
874 style = msymbol ("r");
875 if ((stretch = (MSymbol) FONT_PROPERTY (font, MFONT_STRETCH)) == Mnil)
876 stretch = msymbol ("normal");
877 for (i = 0; i < ft_to_prop_size; i++)
878 if (ft_to_prop[i].weight == weight
879 && ft_to_prop[i].style == style
880 && ft_to_prop[i].stretch == stretch)
881 FcPatternAddString (pat, FC_STYLE,
882 (FcChar8 *) MSYMBOL_NAME (ft_to_prop[i].ft_style));
883 name = (char *) FcNameUnparse (pat);
884 FcPatternDestroy (pat);
887 #endif /* HAVE_FONTCONFIG */
892 #define DEVICE_DELTA(table, size) \
893 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
894 ? (table).DeltaValue[(size) >= (table).StartSize] \
898 adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face,
899 MGlyph *prev, int size, int *x, int *y)
901 if (anchor->AnchorFormat == 2 && prev)
904 int ap = anchor->f.f1.AnchorPoint;
906 FT_Load_Glyph (ft_face, (FT_UInt) prev->code, FT_LOAD_MONOCHROME);
907 outline = &ft_face->glyph->outline;
908 if (ap < outline->n_points)
910 *x = outline->points[ap].x;
911 *y = outline->points[ap].y;
914 else if (anchor->AnchorFormat == 3)
916 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, size);
917 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, size);
922 mfont__ft_drive_gsub (MGlyphString *gstring, int from, int to)
929 OTF_GlyphString otf_gstring;
931 char *script_name, *language_name;
932 char *gsub_feature_names;
933 int from_pos, to_pos;
939 g = gstring->glyphs[from];
940 ft_info = g.rface->rfont->info;
941 if (ft_info->otf_flag < 0)
946 otf = OTF_open (ft_info->filename);
947 if (otf && OTF_get_table (otf, "head") < 0)
954 ft_info->otf_flag = -1;
960 if (g.otf_cmd->script != Mnil)
961 script_name = msymbol_name (g.otf_cmd->script);
964 if (g.otf_cmd->langsys != Mnil)
965 language_name = msymbol_name (g.otf_cmd->langsys);
967 language_name = NULL;
969 = (g.otf_cmd->gsub_features == Mt ? "*"
970 : g.otf_cmd->gsub_features == Mnil ? NULL
971 : msymbol_name (g.otf_cmd->gsub_features));
972 if (gsub_feature_names && OTF_check_table (otf, "GSUB") < 0)
973 gsub_feature_names = NULL;
974 if (! gsub_feature_names)
979 for (i = from + 1; i < to; i++)
981 if (from_pos > gstring->glyphs[i].pos)
982 from_pos = gstring->glyphs[i].pos;
983 if (to_pos < gstring->glyphs[i].to)
984 to_pos = gstring->glyphs[i].to;
987 otf_gstring.size = otf_gstring.used = len;
988 otf_gstring.glyphs = (OTF_Glyph *) alloca (sizeof (OTF_Glyph) * len);
989 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
990 for (i = 0, need_cmap = 0; i < len; i++)
992 if (gstring->glyphs[from + i].otf_encoded)
994 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].c;
995 otf_gstring.glyphs[i].glyph_id = gstring->glyphs[from + i].code;
999 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].code;
1004 && OTF_drive_cmap (otf, &otf_gstring) < 0)
1006 if (OTF_drive_gsub (otf, &otf_gstring, script_name, language_name,
1007 gsub_feature_names) < 0)
1012 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++, otfg++)
1014 g.combining_code = 0;
1018 g.code = otfg->glyph_id;
1026 MLIST_APPEND1 (gstring, glyphs, g, MERROR_FONT_OTF);
1031 for (i = 0; i < len; i++)
1033 g = gstring->glyphs[from + i];
1034 MLIST_APPEND1 (gstring, glyphs, g, MERROR_FONT_OTF);
1040 mfont__ft_drive_gpos (MGlyphString *gstring, int from, int to)
1042 int len = to - from;
1047 OTF_GlyphString otf_gstring;
1049 char *script_name, *language_name;
1050 char *gpos_feature_names;
1058 ft_info = g->rface->rfont->info;
1059 if (ft_info->otf_flag < 0)
1064 if (g->otf_cmd->script != Mnil)
1065 script_name = msymbol_name (g->otf_cmd->script);
1068 if (g->otf_cmd->langsys != Mnil)
1069 language_name = msymbol_name (g->otf_cmd->langsys);
1071 language_name = NULL;
1073 = (g->otf_cmd->gpos_features == Mt ? "*"
1074 : g->otf_cmd->gpos_features == Mnil ? NULL
1075 : msymbol_name (g->otf_cmd->gpos_features));
1076 if (gpos_feature_names && OTF_check_table (otf, "GPOS") < 0)
1077 gpos_feature_names = NULL;
1078 if (! gpos_feature_names)
1081 otf_gstring.size = otf_gstring.used = len;
1082 otf_gstring.glyphs = (OTF_Glyph *) alloca (sizeof (OTF_Glyph) * len);
1083 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
1084 for (i = 0; i < len; i++)
1086 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].c;
1087 otf_gstring.glyphs[i].glyph_id = gstring->glyphs[from + i].code;
1089 if (OTF_drive_gpos (otf, &otf_gstring, script_name, language_name,
1090 gpos_feature_names) < 0)
1093 u = otf->head->unitsPerEm;
1094 size10 = g->rface->rfont->font.property[MFONT_SIZE];
1097 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used;
1098 prev = g++, i++, otfg++)
1099 switch (otfg->positioning_type)
1105 int format = otfg->f.f1.format;
1107 if (format & OTF_XPlacement)
1108 g->xoff = otfg->f.f1.value->XPlacement * size10 / u / 10;
1109 if (format & OTF_XPlaDevice)
1110 g->xoff += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, size);
1111 if (format & OTF_YPlacement)
1112 g->yoff = otfg->f.f1.value->YPlacement * size10 / u / 10;
1113 if (format & OTF_YPlaDevice)
1114 g->yoff += DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, size);
1118 /* Not yet supported. */
1122 int base_x, base_y, mark_x, mark_y;
1124 base_x = otfg->f.f4.base_anchor->XCoordinate * size10 / u / 10;
1125 base_y = otfg->f.f4.base_anchor->YCoordinate * size10 / u / 10;
1126 mark_x = otfg->f.f4.mark_anchor->XCoordinate * size10 / u / 10;
1127 mark_y = otfg->f.f4.mark_anchor->YCoordinate * size10 / u / 10;
1129 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
1130 adjust_anchor (otfg->f.f4.base_anchor, ft_info->ft_face,
1131 prev, size, &base_x, &base_y);
1132 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
1133 adjust_anchor (otfg->f.f4.mark_anchor, ft_info->ft_face,
1134 prev, size, &mark_x, &mark_y);
1135 g->xoff = (base_x - prev->width) - mark_x;
1136 g->yoff = base_y - mark_y;
1140 /* Not yet supported. */
1142 default: /* i.e case 6 */
1143 /* Not yet supported. */
1150 mfont__ft_decode_otf (MGlyph *g)
1152 MFTInfo *ft_info = (MFTInfo *) g->rface->rfont->info;
1153 int c = OTF_get_unicode (ft_info->otf, (OTF_GlyphID) g->code);
1155 return (c ? c : -1);
1158 #endif /* HAVE_OTF */
1160 #endif /* HAVE_FREETYPE */