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);
506 rfont->type = Mfreetype;
507 rfont->fontp = ft_info->ft_face;
511 MDEBUG_PRINT1 (" [FT-FONT] x %s\n", ft_info->filename);
512 if (ft_info->ft_face)
513 FT_Done_Face (ft_info->ft_face);
514 M17N_OBJECT_UNREF (ft_info->charmap_list);
515 free (ft_info->filename);
521 /* The FreeType font driver function FIND_METRIC. */
524 ft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
527 MFTInfo *ft_info = (MFTInfo *) rfont->info;
528 FT_Face ft_face = ft_info->ft_face;
529 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
531 for (; g != gend; g++)
533 if (g->code == MCHAR_INVALID_CODE)
535 if (FT_IS_SCALABLE (ft_face))
537 unsigned unitsPerEm = ft_face->units_per_EM;
538 int size = rfont->font.property[MFONT_SIZE] / 10;
541 g->rbearing = ft_face->max_advance_width * size / unitsPerEm;
542 g->width = ft_face->max_advance_width * size / unitsPerEm;
543 g->ascent = ft_face->ascender * size / unitsPerEm;
544 g->descent = (- ft_face->descender) * size / unitsPerEm;
548 BDF_PropertyRec prop;
551 g->rbearing = g->width = ft_face->available_sizes->width;
552 if (FT_Get_BDF_Property (ft_face, "ASCENT", &prop) == 0)
554 g->ascent = prop.u.integer;
555 FT_Get_BDF_Property (ft_face, "DESCENT", &prop);
556 g->descent = prop.u.integer;
560 g->ascent = ft_face->available_sizes->height;
567 FT_Glyph_Metrics *metrics;
569 FT_Load_Glyph (ft_face, (FT_UInt) g->code, FT_LOAD_DEFAULT);
570 metrics = &ft_face->glyph->metrics;
571 g->lbearing = (metrics->horiBearingX >> 6);
572 g->rbearing = (metrics->horiBearingX + metrics->width) >> 6;
573 g->width = metrics->horiAdvance >> 6;
574 g->ascent = metrics->horiBearingY >> 6;
575 g->descent = (metrics->height - metrics->horiBearingY) >> 6;
580 /* The FreeType font driver function ENCODE_CHAR. */
583 ft_encode_char (MRealizedFont *rfont, unsigned code)
587 if (rfont->status == 0)
589 if ((rfont->driver->open) (rfont) < 0)
592 ft_info = (MFTInfo *) rfont->info;
593 code = (unsigned) FT_Get_Char_Index (ft_info->ft_face, (FT_ULong) code);
595 return MCHAR_INVALID_CODE;
600 /* The FreeType font driver function RENDER. */
602 #define NUM_POINTS 0x1000
605 MDrawPoint points[NUM_POINTS];
610 ft_render (MDrawWindow win, int x, int y,
611 MGlyphString *gstring, MGlyph *from, MGlyph *to,
612 int reverse, MDrawRegion region)
616 MRealizedFace *rface = from->rface;
617 MFrame *frame = rface->frame;
618 FT_Int32 load_flags = FT_LOAD_RENDER;
621 MPointTable point_table[8];
626 /* It is assured that the all glyphs in the current range use the
627 same realized face. */
628 ft_info = (MFTInfo *) rface->rfont->info;
629 ft_face = ft_info->ft_face;
631 if (! gstring->anti_alias)
633 #ifdef FT_LOAD_TARGET_MONO
634 load_flags |= FT_LOAD_TARGET_MONO;
636 load_flags |= FT_LOAD_MONOCHROME;
640 for (i = 0; i < 8; i++)
641 point_table[i].p = point_table[i].points;
643 for (g = from; g < to; x += g++->width)
651 FT_Load_Glyph (ft_face, (FT_UInt) g->code, load_flags);
652 yoff = y - ft_face->glyph->bitmap_top + g->yoff;
653 bmp = ft_face->glyph->bitmap.buffer;
654 width = ft_face->glyph->bitmap.width;
655 pitch = ft_face->glyph->bitmap.pitch;
656 if (! gstring->anti_alias)
661 if (gstring->anti_alias)
662 for (i = 0; i < ft_face->glyph->bitmap.rows;
663 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
665 xoff = x + ft_face->glyph->bitmap_left + g->xoff;
666 for (j = 0; j < width; j++, xoff++)
668 intensity = bmp[j] >> 5;
671 ptable = point_table + intensity;
675 if (ptable->p - ptable->points == NUM_POINTS)
677 (*frame->driver->draw_points)
679 reverse ? 7 - intensity : intensity,
680 ptable->points, NUM_POINTS, region);
681 ptable->p = ptable->points;
687 for (i = 0; i < ft_face->glyph->bitmap.rows;
688 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
690 xoff = x + ft_face->glyph->bitmap_left + g->xoff;
691 for (j = 0; j < width; j++, xoff++)
693 intensity = bmp[j / 8] & (1 << (7 - (j % 8)));
696 ptable = point_table;
700 if (ptable->p - ptable->points == NUM_POINTS)
702 (*frame->driver->draw_points) (frame, win, rface,
704 ptable->points, NUM_POINTS, region);
705 ptable->p = ptable->points;
712 if (gstring->anti_alias)
714 for (i = 1; i < 8; i++)
715 if (point_table[i].p != point_table[i].points)
716 (*frame->driver->draw_points) (frame, win, rface, reverse ? 7 - i : i,
717 point_table[i].points,
718 point_table[i].p - point_table[i].points, region);
722 if (point_table[0].p != point_table[0].points)
723 (*frame->driver->draw_points) (frame, win, rface, reverse ? 0 : 7,
724 point_table[0].points,
725 point_table[0].p - point_table[0].points, region);
732 MFontDriver mfont__ft_driver =
733 { ft_select, ft_open, ft_find_metric, ft_encode_char, ft_render };
740 char *weight, *style, *stretch;
741 } ft_to_prop_name[] =
742 { { "regular", "medium", "r", "normal" },
743 { "medium", "medium", "r", "normal" },
744 { "normal", "medium", "r", "normal" },
745 { "italic", "medium", "i", "normal" },
746 { "bold", "bold", "r", "normal" },
747 { "bolditalic", "bold", "i", "normal" },
748 { "bold italic", "bold", "i", "normal" },
749 { "narrow", "medium", "r", "condensed" },
750 { "narrow italic", "medium", "i", "condensed" },
751 { "narrow bold", "bold", "r", "condensed" },
752 { "narrow bold italic", "bold", "i", "condensed" },
753 { "black", "black", "r", "normal" },
754 { "black italic", "black", "i", "normal" },
755 { "oblique", "medium", "o", "normal" },
756 { "boldoblique", "bold", "o", "normal" },
757 { "bold oblique", "bold", "o", "normal" } };
760 if (FT_Init_FreeType (&ft_library) != 0)
761 MERROR (MERROR_FONT_FT, -1);
763 ft_to_prop_size = sizeof (ft_to_prop_name) / sizeof (ft_to_prop_name[0]);
764 MTABLE_MALLOC (ft_to_prop, ft_to_prop_size, MERROR_FONT_FT);
765 for (i = 0; i < ft_to_prop_size; i++)
767 ft_to_prop[i].ft_style = msymbol (ft_to_prop_name[i].ft_style);
768 ft_to_prop[i].weight = msymbol (ft_to_prop_name[i].weight);
769 ft_to_prop[i].style = msymbol (ft_to_prop_name[i].style);
770 ft_to_prop[i].stretch = msymbol (ft_to_prop_name[i].stretch);
773 Municode_bmp = msymbol ("unicode-bmp");
774 Municode_full = msymbol ("unicode-full");
775 Miso10646_1 = msymbol ("iso10646-1");
776 Miso8859_1 = msymbol ("iso8859-1");
788 MPLIST_DO (plist, ft_font_list)
790 MPLIST_DO (p, MPLIST_VAL (plist))
792 MFTInfo *ft_info = MPLIST_VAL (p);
794 M17N_OBJECT_UNREF (ft_info);
796 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
798 M17N_OBJECT_UNREF (ft_font_list);
802 FT_Done_FreeType (ft_library);
803 all_fonts_scaned = 0;
807 #ifdef HAVE_FONTCONFIG
809 mfont__ft_parse_name (char *name, MFont *font)
811 FcPattern *pat = FcNameParse ((FcChar8 *) name);
818 if ((result = FcPatternGetString (pat, FC_FOUNDRY, 0, &str)) == FcResultMatch)
819 mfont__set_property (font, MFONT_FOUNDRY, msymbol ((char *) str));
820 if ((result = FcPatternGetString (pat, FC_FAMILY, 0, &str)) == FcResultMatch)
821 mfont__set_property (font, MFONT_FAMILY, msymbol ((char *) str));
822 if ((result = FcPatternGetString (pat, FC_STYLE, 0, &str)) == FcResultMatch)
824 MSymbol style = msymbol ((char *) str);
827 for (i = 0; i < ft_to_prop_size; i++)
828 if (ft_to_prop[i].ft_style == style)
830 mfont__set_property (font, MFONT_WEIGHT, ft_to_prop[i].weight);
831 mfont__set_property (font, MFONT_STYLE, ft_to_prop[i].style);
832 mfont__set_property (font, MFONT_STRETCH, ft_to_prop[i].stretch);
836 if ((result = FcPatternGetDouble (pat, FC_PIXEL_SIZE, 0, &size))
838 font->property[MFONT_SIZE] = size * 10;
839 FcPatternDestroy (pat);
844 mfont__ft_unparse_name (MFont *font)
846 FcPattern *pat = FcPatternCreate ();
847 MSymbol sym, weight, style, stretch;
851 if ((sym = (MSymbol) FONT_PROPERTY (font, MFONT_FOUNDRY)) != Mnil)
852 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) MSYMBOL_NAME (sym));
853 if ((sym = (MSymbol) FONT_PROPERTY (font, MFONT_FAMILY)) != Mnil)
854 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) MSYMBOL_NAME (sym));
855 if ((weight = (MSymbol) FONT_PROPERTY (font, MFONT_WEIGHT)) == Mnil)
856 weight = msymbol ("medium");
857 if ((style = (MSymbol) FONT_PROPERTY (font, MFONT_STYLE)) == Mnil)
858 style = msymbol ("r");
859 if ((stretch = (MSymbol) FONT_PROPERTY (font, MFONT_STRETCH)) == Mnil)
860 stretch = msymbol ("normal");
861 for (i = 0; i < ft_to_prop_size; i++)
862 if (ft_to_prop[i].weight == weight
863 && ft_to_prop[i].style == style
864 && ft_to_prop[i].stretch == stretch)
865 FcPatternAddString (pat, FC_STYLE,
866 (FcChar8 *) MSYMBOL_NAME (ft_to_prop[i].ft_style));
867 name = (char *) FcNameUnparse (pat);
868 FcPatternDestroy (pat);
871 #endif /* HAVE_FONTCONFIG */
876 #define DEVICE_DELTA(table, size) \
877 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
878 ? (table).DeltaValue[(size) >= (table).StartSize] \
882 adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face,
883 unsigned code, int size, int *x, int *y)
885 if (anchor->AnchorFormat == 2)
888 int ap = anchor->f.f1.AnchorPoint;
890 FT_Load_Glyph (ft_face, (FT_UInt) code, FT_LOAD_MONOCHROME);
891 outline = &ft_face->glyph->outline;
892 if (ap < outline->n_points)
894 *x = outline->points[ap].x;
895 *y = outline->points[ap].y;
898 else if (anchor->AnchorFormat == 3)
900 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, size);
901 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, size);
906 mfont__ft_drive_otf (MGlyphString *gstring, int from, int to,
907 MSymbol script, MSymbol langsys,
908 MSymbol gsub_features, MSymbol gpos_features)
911 MGlyph *g = MGLYPH (from);
913 MRealizedFont *rfont;
916 OTF_GlyphString otf_gstring;
918 char *script_name, *language_name;
919 char *gsub_feature_names, *gpos_feature_names;
925 rfont = g->rface->rfont;
926 ft_info = rfont->info;
927 if (ft_info->otf_flag < 0)
932 otf = OTF_open (ft_info->filename);
933 if (otf && OTF_get_table (otf, "head") < 0)
940 ft_info->otf_flag = -1;
947 script_name = msymbol_name (script);
951 language_name = msymbol_name (langsys);
953 language_name = NULL;
955 = (gsub_features == Mt ? "*"
956 : gsub_features == Mnil ? NULL
957 : msymbol_name (gsub_features));
958 if (gsub_feature_names && OTF_check_table (otf, "GSUB") < 0)
959 gsub_feature_names = NULL;
961 = (gpos_features == Mt ? "*"
962 : gpos_features == Mnil ? NULL
963 : msymbol_name (gpos_features));
964 if (gpos_feature_names && OTF_check_table (otf, "GPOS") < 0)
965 gpos_feature_names = NULL;
967 otf_gstring.size = otf_gstring.used = len;
968 otf_gstring.glyphs = (OTF_Glyph *) alloca (sizeof (OTF_Glyph) * len);
969 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
970 for (i = 0, need_cmap = 0; i < len; i++)
972 if (gstring->glyphs[from + i].otf_encoded)
974 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].c;
975 otf_gstring.glyphs[i].glyph_id = gstring->glyphs[from + i].code;
979 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].code;
984 && OTF_drive_cmap (otf, &otf_gstring) < 0)
987 OTF_drive_gdef (otf, &otf_gstring);
988 gidx = gstring->used;
990 if (gsub_feature_names)
992 if (OTF_drive_gsub (otf, &otf_gstring, script_name, language_name,
993 gsub_feature_names) < 0)
995 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++, otfg++)
997 MGlyph temp = *(MGLYPH (from + otfg->f.index.from));
1000 temp.combining_code = 0;
1003 temp.code = otfg->glyph_id;
1004 temp.otf_encoded = 1;
1009 temp.otf_encoded = 0;
1011 temp.to = MGLYPH (from + otfg->f.index.to)->to;
1012 MLIST_APPEND1 (gstring, glyphs, temp, MERROR_FONT_OTF);
1016 for (i = 0; i < len; i++)
1018 MGlyph temp = gstring->glyphs[from + i];
1020 if (otf_gstring.glyphs[i].glyph_id)
1022 temp.code = otf_gstring.glyphs[i].glyph_id;
1023 temp.otf_encoded = 1;
1025 MLIST_APPEND1 (gstring, glyphs, temp, MERROR_FONT_OTF);
1028 ft_find_metric (rfont, gstring, gidx, gstring->used);
1030 if (gpos_feature_names)
1034 MGlyph *base = NULL, *mark = NULL;
1036 if (OTF_drive_gpos (otf, &otf_gstring, script_name, language_name,
1037 gpos_feature_names) < 0)
1040 u = otf->head->unitsPerEm;
1041 size10 = rfont->font.property[MFONT_SIZE];
1044 for (i = 0, otfg = otf_gstring.glyphs, g = MGLYPH (gidx);
1045 i < otf_gstring.used; i++, otfg++, g++)
1049 if (! otfg->glyph_id)
1051 switch (otfg->positioning_type)
1057 int format = otfg->f.f1.format;
1059 if (format & OTF_XPlacement)
1060 g->xoff = otfg->f.f1.value->XPlacement * size10 / u / 10;
1061 if (format & OTF_XPlaDevice)
1062 g->xoff += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, size);
1063 if (format & OTF_YPlacement)
1064 g->yoff = - (otfg->f.f1.value->YPlacement * size10 / u / 10);
1065 if (format & OTF_YPlaDevice)
1066 g->yoff -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, size);
1067 if (format & OTF_XAdvance)
1068 g->width += otfg->f.f1.value->XAdvance * size10 / u / 10;
1069 if (format & OTF_XAdvDevice)
1070 g->width += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, size);
1074 /* Not yet supported. */
1080 goto label_adjust_anchor;
1081 default: /* i.e. case 6 */
1086 label_adjust_anchor:
1088 int base_x, base_y, mark_x, mark_y;
1090 base_x = otfg->f.f4.base_anchor->XCoordinate * size10 / u / 10;
1091 base_y = otfg->f.f4.base_anchor->YCoordinate * size10 / u / 10;
1092 mark_x = otfg->f.f4.mark_anchor->XCoordinate * size10 / u / 10;
1093 mark_y = otfg->f.f4.mark_anchor->YCoordinate * size10 / u / 10;
1095 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
1096 adjust_anchor (otfg->f.f4.base_anchor, ft_info->ft_face,
1097 prev->code, size, &base_x, &base_y);
1098 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
1099 adjust_anchor (otfg->f.f4.mark_anchor, ft_info->ft_face,
1100 g->code, size, &mark_x, &mark_y);
1101 g->xoff = prev->xoff + (base_x - prev->width) - mark_x;
1102 g->yoff = prev->yoff + mark_y - base_y;
1103 g->combining_code = MAKE_COMBINING_CODE_BY_CLASS (0);
1106 if (otfg->GlyphClass == OTF_GlyphClass0)
1108 else if (otfg->GlyphClass == OTF_GlyphClassMark)
1117 ft_find_metric (rfont, gstring, from, to);
1118 for (i = 0; i < len; i++)
1120 MGlyph temp = gstring->glyphs[from + i];
1121 MLIST_APPEND1 (gstring, glyphs, temp, MERROR_FONT_OTF);
1128 mfont__ft_decode_otf (MGlyph *g)
1130 MFTInfo *ft_info = (MFTInfo *) g->rface->rfont->info;
1131 int c = OTF_get_unicode (ft_info->otf, (OTF_GlyphID) g->code);
1133 return (c ? c : -1);
1136 #endif /* HAVE_OTF */
1138 #endif /* HAVE_FREETYPE */