5 #include FT_TRUETYPE_TABLES_H
6 #include <fontconfig/fontconfig.h>
7 #include <fontconfig/fcfreetype.h>
12 #define PROGNAME "flt-gui"
14 #elif defined (FLT_OTF)
18 #define PROGNAME "flt-otf"
20 #elif defined (FLT_HB)
24 #define PROGNAME "flt-hb"
26 #else (defined (FLT_PANGO))
29 #include <pango/pango-engine.h>
30 #include <pango/pango-ot.h>
31 #include <pango/pango-utils.h>
35 static FT_Library ft_library;
38 new_face (char *fontname, char **err)
47 pat = FcNameParse ((FcChar8 *) fontname);
50 *err = "invalid name format";
53 if (FcPatternGetString (pat, FC_FAMILY, 0, &fam) != FcResultMatch)
55 *err = "no family name";
58 if (FcPatternGetDouble (pat, FC_PIXEL_SIZE, 0, &pixelsize) != FcResultMatch)
60 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
61 FcPatternDel (pat, FC_PIXEL_SIZE);
62 os = FcObjectSetBuild (FC_FILE, NULL);
63 fs = FcFontList (NULL, pat, os);
66 *err = "no matching font";
69 FcPatternGetString (fs->fonts[0], FC_FILE, 0, &file);
71 if (FT_New_Face (ft_library, (char *) file, 0, &face))
73 FcFontSetDestroy (fs);
74 FcObjectSetDestroy (os);
75 FcPatternDestroy (pat);
76 *err = "font open fail";
79 FcFontSetDestroy (fs);
80 FcObjectSetDestroy (os);
81 FcPatternDestroy (pat);
82 if (FT_Set_Pixel_Sizes (face, pixelsize, pixelsize))
84 *err = "set pixelsize fail";
102 open_font (char *fontname, char **err)
104 FT_Face ft_face = new_face (fontname, err);
114 fontset = mfontset ("generic");
115 mface_put_prop (face, Mfontset, fontset);
116 mplist_add (plist, Mface, face);
117 mplist_add (plist, Mdevice, Mnil);
118 frame = mframe (plist);
119 m17n_object_unref (plist);
120 m17n_object_unref (face);
121 m17n_object_unref (fontset);
123 font = calloc (1, sizeof (MFLTFont));
124 font->font = mfont_encapsulate (frame, Mfreetype, ft_face);
125 font->face = ft_face;
130 close_font (MFLTFont *font)
132 FT_Done_Face (font->face);
134 m17n_object_unref (frame);
138 flt (MText *mt, int from, int to, MFLTFont *font, char *flt_name)
140 MDrawControl control;
142 memset (&control, 0, sizeof (MDrawControl));
143 control.two_dimensional = 1;
144 control.enable_bidi = 1;
145 control.anti_alias = 1;
146 /*control.disable_caching = 1;*/
147 mtext_put_prop (mt, from, to, Mfont, font->font);
148 mdraw_text_extents (frame, mt, from, to, &control, NULL, NULL, NULL);
152 #elif defined (FLT_OTF) || defined (FLT_HB)
160 get_glyph_id (MFLTFont *font, MFLTGlyph *g)
162 FT_Face face = ((FontInfo *) font)->face;
164 g->code = FT_Get_Char_Index (face, g->code);
166 return (g->code ? 0 : -1);
170 get_metric (MFLTFont *font, MFLTGlyphString *gstring, int from, int to)
172 FT_Face face = ((FontInfo *) font)->face;
174 for (; from < to; from++)
176 MFLTGlyph *g = gstring->glyphs + from;
177 FT_Glyph_Metrics *metrics;
179 if (FT_Load_Glyph (face, g->code, FT_LOAD_DEFAULT))
181 metrics = &face->glyph->metrics;
182 g->lbearing = metrics->horiBearingX;
183 g->rbearing = metrics->horiBearingX + metrics->width;
184 g->xadv = metrics->horiAdvance;
185 g->yadv = metrics->vertAdvance;
186 g->ascent = metrics->horiBearingY;
187 g->descent = metrics->height - metrics->horiBearingY;
193 flt (MText *mt, int from, int to, MFLTFont *font, char *flt_name)
195 MFLTGlyphString gstring;
199 memset (&gstring, 0, sizeof (MFLTGlyphString));
200 gstring.glyph_size = sizeof (MFLTGlyph);
201 gstring.allocated = len * 2;
202 gstring.glyphs = alloca (sizeof (MFLTGlyph) * gstring.allocated);
203 for (i = 0; i < len; i++)
204 gstring.glyphs[i].c = mtext_ref_char (mt, from + i);
206 return mflt_run (&gstring, 0, len, font, msymbol (flt_name));
217 #define DEVICE_DELTA(table, size) \
218 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
219 ? ((table).DeltaValue[(size) - (table).StartSize] << 6) \
223 adjust_anchor (OTF_Anchor *anchor, FT_Face face,
224 unsigned code, unsigned x_ppem, unsigned y_ppem, int *x, int *y)
226 if (anchor->AnchorFormat == 2)
229 int ap = anchor->f.f1.AnchorPoint;
231 FT_Load_Glyph (face, (FT_UInt) code, FT_LOAD_MONOCHROME);
232 outline = &face->glyph->outline;
233 if (ap < outline->n_points)
235 *x = outline->points[ap].x;
236 *y = outline->points[ap].y;
239 else if (anchor->AnchorFormat == 3)
241 if (anchor->f.f2.XDeviceTable.offset)
242 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, x_ppem);
243 if (anchor->f.f2.YDeviceTable.offset)
244 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, y_ppem);
249 tag_name (char *str, unsigned tag)
252 *str++ = (tag >> 16) & 0xFF;
253 *str++ = (tag >> 8) & 0xFF;
259 encode_features (char *str, int count, unsigned *features)
264 for (i = 0; i < count; i++)
266 unsigned tag = features[i];
276 str = tag_name (str, tag);
289 drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
290 MFLTGlyphString *in, int from, int to,
291 MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment)
295 OTF *otf = ((FontInfoOTF *) font)->otf;
296 OTF_GlyphString otf_gstring;
298 char script[4], langsys[4];
299 char *gsub_features = NULL, *gpos_features = NULL;
306 otf_gstring.glyphs = NULL;
307 if (OTF_get_table (otf, "head") < 0)
310 ((FontInfoOTF *) font)->otf = NULL;
314 tag_name (script, spec->script);
315 tag_name (langsys, spec->langsys);
317 if (spec->gsub_count > 0)
319 gsub_features = alloca (6 * spec->gsub_count);
322 if (OTF_check_table (otf, "GSUB") < 0)
323 gsub_features = NULL;
325 encode_features (gsub_features, spec->gsub_count, spec->gsub);
328 if (spec->gpos_count)
330 gpos_features = alloca (6 * spec->gpos_count);
333 if (OTF_check_table (otf, "GPOS") < 0)
334 gpos_features = NULL;
336 encode_features (gpos_features, spec->gpos_count, spec->gpos);
340 otf_gstring.size = otf_gstring.used = len;
341 otf_gstring.glyphs = (OTF_Glyph *) malloc (sizeof (OTF_Glyph) * len);
342 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
343 for (i = 0; i < len; i++)
345 otf_gstring.glyphs[i].c = in->glyphs[from + i].c;
346 otf_gstring.glyphs[i].glyph_id = in->glyphs[from + i].code;
349 OTF_drive_gdef (otf, &otf_gstring);
354 if (OTF_drive_gsub (otf, &otf_gstring, script, langsys, gsub_features)
357 if (out->allocated < out->used + otf_gstring.used)
359 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++, otfg++)
361 MFLTGlyph *g = out->glyphs + out->used;
364 *g = in->glyphs[from + otfg->f.index.from];
366 for (j = from + otfg->f.index.from; j <= from + otfg->f.index.to; j++)
367 if (in->glyphs[j].code == otfg->glyph_id)
369 g->c = in->glyphs[j].c;
372 g->code = otfg->glyph_id;
378 if (out->allocated < out->used + len)
380 for (i = 0; i < len; i++)
381 out->glyphs[out->used++] = in->glyphs[from + i];
384 font->get_metric (font, out, gidx, out->used);
389 MFLTGlyph *base = NULL, *mark = NULL, *g;
390 int x_ppem, y_ppem, x_scale, y_scale;
392 if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, gpos_features)
396 face = ((FontInfo *) font)->face;
397 x_ppem = face->size->metrics.x_ppem;
398 y_ppem = face->size->metrics.y_ppem;
399 x_scale = face->size->metrics.x_scale;
400 y_scale = face->size->metrics.y_scale;
402 for (i = 0, otfg = otf_gstring.glyphs, g = out->glyphs + gidx;
403 i < otf_gstring.used; i++, otfg++, g++)
407 if (! otfg->glyph_id)
409 switch (otfg->positioning_type)
415 int format = otfg->f.f1.format;
417 if (format & OTF_XPlacement)
419 = otfg->f.f1.value->XPlacement * x_scale / 0x10000;
420 if (format & OTF_XPlaDevice)
422 += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, x_ppem);
423 if (format & OTF_YPlacement)
425 = - (otfg->f.f1.value->YPlacement * y_scale / 0x10000);
426 if (format & OTF_YPlaDevice)
428 -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, y_ppem);
429 if (format & OTF_XAdvance)
431 += otfg->f.f1.value->XAdvance * x_scale / 0x10000;
432 if (format & OTF_XAdvDevice)
434 += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, x_ppem);
435 if (format & OTF_YAdvance)
437 += otfg->f.f1.value->YAdvance * y_scale / 0x10000;
438 if (format & OTF_YAdvDevice)
440 += DEVICE_DELTA (otfg->f.f1.value->YAdvDevice, y_ppem);
441 adjustment[i].set = 1;
445 /* Not yet supported. */
451 goto label_adjust_anchor;
452 default: /* i.e. case 6 */
459 int base_x, base_y, mark_x, mark_y;
461 base_x = otfg->f.f4.base_anchor->XCoordinate * x_scale / 0x10000;
462 base_y = otfg->f.f4.base_anchor->YCoordinate * y_scale / 0x10000;
463 mark_x = otfg->f.f4.mark_anchor->XCoordinate * x_scale / 0x10000;
464 mark_y = otfg->f.f4.mark_anchor->YCoordinate * y_scale / 0x10000;;
466 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
467 adjust_anchor (otfg->f.f4.base_anchor, face, prev->code,
468 x_ppem, y_ppem, &base_x, &base_y);
469 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
470 adjust_anchor (otfg->f.f4.mark_anchor, face, g->code,
471 x_ppem, y_ppem, &mark_x, &mark_y);
472 adjustment[i].xoff = (base_x - mark_x);
473 adjustment[i].yoff = - (base_y - mark_y);
474 adjustment[i].back = (g - prev);
475 adjustment[i].set = 1;
478 if (otfg->GlyphClass == OTF_GlyphClass0)
480 else if (otfg->GlyphClass == OTF_GlyphClassMark)
486 free (otf_gstring.glyphs);
490 font->get_metric (font, in, from, to);
491 for (i = 0; i < len; i++)
493 MFLTGlyph *g = in->glyphs + (from + i);
495 out->glyphs[out->used++] = *g;
497 if (otf_gstring.glyphs)
498 free (otf_gstring.glyphs);
503 open_font (char *fontname, char **err)
505 FT_Face face = new_face (fontname, err);
506 FontInfoOTF *font_info;
510 font_info = malloc (sizeof (FontInfoOTF));
511 font_info->font.get_glyph_id = get_glyph_id;
512 font_info->font.get_metric = get_metric;
513 font_info->font.drive_otf = drive_otf;
514 font_info->face = face;
515 font_info->otf = OTF_open_ft_face (face);
516 return ((MFLTFont *) font_info);
520 close_font (MFLTFont *font)
522 FontInfoOTF *font_info = (FontInfoOTF *) font;
524 OTF_close (font_info->otf);
525 FT_Done_Face (font_info->face);
545 HB_StreamRec gdef_stream;
549 MPlist *otf_spec_cache;
553 convertStringToGlyphIndices (HB_Font font, const HB_UChar16 *string,
554 hb_uint32 length, HB_Glyph *glyphs,
555 hb_uint32 *numGlyphs, HB_Bool rightToLeft)
561 getGlyphAdvances (HB_Font font, const HB_Glyph *glyphs, hb_uint32 numGlyphs,
562 HB_Fixed *advances, int flags /*HB_ShaperFlag*/)
566 for (i = 0; i < numGlyphs; i++)
571 canRender (HB_Font font, const HB_UChar16 *string, hb_uint32 length)
577 getPointInOutline (HB_Font font, HB_Glyph glyph, int flags /*HB_ShaperFlag*/,
578 hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos,
581 FT_Face face = font->faceData;
584 if ((error = (HB_Error) FT_Load_Glyph (face, glyph, flags)))
586 if (face->glyph->format != ft_glyph_format_outline)
587 return (HB_Error) HB_Err_Invalid_GPOS_SubTable;
588 *nPoints = face->glyph->outline.n_points;
591 if (point > *nPoints)
592 return (HB_Error) HB_Err_Invalid_GPOS_SubTable;
594 *xpos = face->glyph->outline.points[point].x;
595 *ypos = face->glyph->outline.points[point].y;
601 getGlyphMetrics (HB_Font font, HB_Glyph glyph, HB_GlyphMetrics *metrics)
606 getFontMetric (HB_Font font, HB_FontMetric metric)
611 #define MAKE_TAG(name) ((((FT_ULong) (name)[0]) << 24) \
612 | (((FT_ULong) (name)[1]) << 16) \
613 | (((FT_ULong) (name)[2]) << 8) \
617 new_stream (FT_Face face, char *tagname, HB_Stream stream)
619 FT_ULong tag = MAKE_TAG (tagname);
623 if (! FT_IS_SFNT (face))
624 return HB_Err_Invalid_Argument;
626 if (FT_Load_Sfnt_Table (face, tag, 0, NULL, &len))
627 return HB_Err_Table_Missing;
630 return HB_Err_Out_Of_Memory;
631 if (FT_Load_Sfnt_Table (face, tag, 0, buf, &len))
634 return HB_Err_Table_Missing;
636 stream->base = (HB_Byte *) buf;
639 stream->cursor = NULL;
645 load_gdef (FontInfoHB *font_info)
649 if (! font_info->gdef_stream.base)
651 err = new_stream ((FT_Face) font_info->hb_font.faceData, "GDEF",
652 &font_info->gdef_stream);
653 if (err != HB_Err_Ok)
656 return HB_Load_GDEF_Table (&font_info->gdef_stream, &font_info->gdef);
660 load_gsub (FontInfoHB *font_info)
664 HB_LookupList *lookup_list;
667 if (! font_info->gdef)
669 if ((err = load_gdef (font_info)) != HB_Err_Ok)
672 err = new_stream ((FT_Face) font_info->hb_font.faceData, "GSUB", &stream);
673 if (err != HB_Err_Ok)
675 err = HB_Load_GSUB_Table (&stream, &font_info->gsub,
676 font_info->gdef, &font_info->gdef_stream);
678 lookup_list = &font_info->gsub->LookupList;
679 for (i = 0; i < lookup_list->LookupCount; i++)
680 lookup_list->Properties[i] = HB_GLYPH_PROPERTIES_UNKNOWN;
685 load_gpos (FontInfoHB *font_info)
689 HB_LookupList *lookup_list;
692 if (! font_info->gdef)
694 if ((err = load_gdef (font_info)) != HB_Err_Ok)
697 err = new_stream ((FT_Face) font_info->hb_font.faceData, "GPOS", &stream);
698 if (err != HB_Err_Ok)
700 err = HB_Load_GPOS_Table (&stream, &font_info->gpos,
701 font_info->gdef, &font_info->gdef_stream);
703 lookup_list = &font_info->gpos->LookupList;
704 for (i = 0; i < lookup_list->LookupCount; i++)
705 lookup_list->Properties[i] = HB_GLYPH_PROPERTIES_UNKNOWN;
709 const HB_FontClass hb_fontClass = {
710 convertStringToGlyphIndices, getGlyphAdvances, canRender,
711 getPointInOutline, getGlyphMetrics, getFontMetric
715 setup_features (int gsubp, FontInfoHB *font_info, MFLTOtfSpec *spec,
718 int count, preordered;
719 unsigned int *features;
720 FT_UShort script, langsys;
721 FT_UShort req_feature, index;
722 FT_UInt *feature_list;
728 if (! font_info->gsub)
730 if (load_gsub (font_info) != HB_Err_Ok)
733 if (HB_GSUB_Select_Script (font_info->gsub, spec->script, &script)
738 if (HB_GSUB_Select_Language (font_info->gsub, spec->langsys,
739 script, &langsys, &req_feature)
744 langsys = req_feature = 0xFFFF;
745 count = spec->gsub_count;
746 features = spec->gsub;
750 if (! font_info->gpos)
752 if (load_gpos (font_info) != HB_Err_Ok)
755 if (HB_GPOS_Select_Script (font_info->gpos, spec->script, &script)
760 if (HB_GPOS_Select_Language (font_info->gpos, spec->langsys,
761 script, &langsys, &req_feature)
766 langsys = req_feature = 0xFFFF;
767 count = spec->gpos_count;
768 features = spec->gpos;
771 for (preordered = 0; preordered < count; preordered++)
772 if (features[preordered] == 0)
774 if ((gsubp ? HB_GSUB_Query_Features (font_info->gsub, script, langsys,
776 : HB_GPOS_Query_Features (font_info->gpos, script, langsys,
783 for (i = 0; feature_list[i]; i++);
786 info->indices = malloc (sizeof (FT_UShort) * ((req_feature != 0xFFFF) + i));
788 if (req_feature != 0xFFFF)
789 info->indices[i++] = req_feature;
790 for (j = 0; j < preordered; j++)
791 if ((gsubp ? HB_GSUB_Select_Feature (font_info->gsub, features[j],
792 script, langsys, &index)
793 : HB_GPOS_Select_Feature (font_info->gpos, features[j],
794 script, langsys, &index))
796 info->indices[i++] = index;
798 for (j = 0; feature_list[j]; j++)
800 for (k = preordered + 1; k < count; k++)
801 if (feature_list[j] == features[k])
805 ? HB_GSUB_Select_Feature (font_info->gsub, feature_list[j],
806 script, langsys, &index)
807 : HB_GPOS_Select_Feature (font_info->gpos, feature_list[j],
808 script, langsys, &index))
810 info->indices[i++] = index;
816 setup_otf_spec (MFLTFont *font, MFLTOtfSpec *spec)
818 FontInfoHB *font_info = (FontInfoHB *) font;
821 if (spec->gsub_count + spec->gpos_count == 0)
823 ginfo = mplist_get (font_info->otf_spec_cache, spec->sym);
825 return (ginfo->gsub.count + ginfo->gpos.count > 0 ? ginfo : NULL);
826 ginfo = calloc (1, sizeof (GsubGposInfo));
827 mplist_push (font_info->otf_spec_cache, spec->sym, ginfo);
828 setup_features (1, font_info, spec, &(ginfo->gsub));
829 setup_features (0, font_info, spec, &(ginfo->gpos));
834 drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
835 MFLTGlyphString *in, int from, int to,
836 MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment)
838 FontInfoHB *font_info = (FontInfoHB *) font;
843 HB_UShort *apply_order_save;
844 HB_UShort apply_count_save;
845 int gpos_applied = 0;
852 if (hb_buffer_new (&buf) != FT_Err_Ok)
854 for (i = from; i < to; i++)
856 if (hb_buffer_add_glyph (buf, in->glyphs[i].code, 0, i) != FT_Err_Ok)
859 ginfo = setup_otf_spec (font, spec);
862 if (ginfo->gsub.count > 0)
864 if (! font_info->gdef
865 && load_gdef (font_info) != HB_Err_Ok)
867 apply_order_save = font_info->gsub->FeatureList.ApplyOrder;
868 apply_count_save = font_info->gsub->FeatureList.ApplyCount;
869 font_info->gsub->FeatureList.ApplyOrder = ginfo->gsub.indices;
870 font_info->gsub->FeatureList.ApplyCount = ginfo->gsub.count;
871 err = HB_GSUB_Apply_String (font_info->gsub, buf);
872 font_info->gsub->FeatureList.ApplyOrder = apply_order_save;
873 font_info->gsub->FeatureList.ApplyCount = apply_count_save;
874 if (err != HB_Err_Ok && err != HB_Err_Not_Covered)
876 if (out->used + buf->in_length > out->allocated)
880 if (ginfo->gpos.count > 0
881 && (font_info->gpos || load_gpos (font_info) == HB_Err_Ok))
883 apply_order_save = font_info->gpos->FeatureList.ApplyOrder;
884 apply_count_save = font_info->gpos->FeatureList.ApplyCount;
885 font_info->gpos->FeatureList.ApplyOrder = ginfo->gpos.indices;
886 font_info->gpos->FeatureList.ApplyCount = ginfo->gpos.count;
887 err = HB_GPOS_Apply_String (&font_info->hb_font, font_info->gpos,
888 FT_LOAD_DEFAULT, buf, FALSE, FALSE);
889 font_info->gpos->FeatureList.ApplyOrder = apply_order_save;
890 font_info->gpos->FeatureList.ApplyCount = apply_count_save;
891 if (err == HB_Err_Ok)
897 for (i = 0; i < buf->in_length; i++)
899 HB_GlyphItem hg = buf->in_string + i;
900 HB_Position pos = buf->positions + i;
903 out->glyphs[out->used] = in->glyphs[hg->cluster];
904 g = out->glyphs + out->used++;
905 if (g->code != hg->gindex)
906 g->c = 0, g->code = hg->gindex;
907 adjustment[i].set = gpos_applied;
910 adjustment[i].xadv = pos->x_advance;
911 adjustment[i].yadv = pos->y_advance;
912 adjustment[i].xoff = pos->x_pos;
913 adjustment[i].yoff = - pos->y_pos;
914 adjustment[i].back = pos->back;
915 adjustment[i].advance_is_absolute = pos->new_advance;
922 hb_buffer_free (buf);
923 for (i = 0; i < len; i++)
924 out->glyphs[out->used++] = in->glyphs[from + i];
929 open_font (char *fontname, char **err)
931 FT_Face face = new_face (fontname, err);
932 FontInfoHB *font_info;
936 font_info = calloc (1, sizeof (FontInfoHB));
937 font_info->font.get_glyph_id = get_glyph_id;
938 font_info->font.get_metric = get_metric;
939 font_info->font.drive_otf = drive_otf;
940 font_info->face = face;
941 font_info->hb_font.klass = &hb_fontClass;
942 font_info->hb_font.faceData = face;
943 font_info->hb_font.userData = NULL;
944 font_info->hb_font.x_ppem = face->size->metrics.x_ppem;
945 font_info->hb_font.x_scale = face->size->metrics.x_scale;
946 font_info->hb_font.y_scale = face->size->metrics.y_scale;
947 font_info->hb_font.y_ppem = face->size->metrics.y_ppem;
948 font_info->otf_spec_cache = mplist ();
949 return ((MFLTFont *) font_info);
953 close_font (MFLTFont *font)
955 FontInfoHB *font_info = (FontInfoHB *) font;
960 HB_Done_GDEF_Table (font_info->gdef);
961 free (font_info->gdef_stream.base);
964 HB_Done_GSUB_Table (font_info->gsub);
966 HB_Done_GPOS_Table (font_info->gpos);
967 FT_Done_Face ((FT_Face) (font_info->hb_font.faceData));
968 for (p = font_info->otf_spec_cache; mplist_key (p) != Mnil;
971 GsubGposInfo *ginfo = mplist_value (p);
973 if (ginfo->gsub.count > 0)
974 free (ginfo->gsub.indices);
975 if (ginfo->gpos.count > 0)
976 free (ginfo->gpos.indices);
978 m17n_object_unref (font_info->otf_spec_cache);
984 #else /* (defined (FLT_PANGO) */
988 PangoFcFont pango_fc_font;
992 get_glyph_id (MFLTFont *font, MFLTGlyph *g)
994 FontInfoPango *font_info = (FontInfoPango *) font;
995 PangoGlyph pg = pango_fc_font_get_glyph (font_info->pango_fc_font, g->c);
997 return (pg ? (int) pg : -1);
1001 get_metric (MFLTFont *font, MFLTGlyphString *gstring, int form, int to)
1003 FontInfoPango *font_info = (FontInfoPango *) font;
1004 PangoFcFont fc_font = font_info->pango_fc_font;
1007 for (i = from; i < to; i++)
1009 PangoRectangle inc, logical;
1011 pango_font_get_glyph_extents ((PangoFont *) fc_font,
1012 gstring->glyphs[i].code, &inc, &logical);
1013 g->lbearing = inc.x;
1014 g->rbearing = inc.x + inc.width;
1015 g->xadv = logical.width;
1017 g->ascent = - inc.y;
1018 g->descent = inc.height + inc.y;
1025 main (int argc, char **argv)
1027 char *font_name, *flt_name;
1035 fprintf (stderr, "Usage: flt FONT-NAME FLT-NAME < TEXT-FILE\n");
1039 font_name = argv[1];
1042 FT_Init_FreeType (&ft_library);
1044 font = open_font (font_name, &err);
1047 fprintf (stderr, "Font error: %s: %s\n", argv[1], err);
1051 mt = mconv_decode_stream (msymbol ("utf-8"), stdin);
1052 len = mtext_len (mt);
1053 for (i = 0, j = mtext_character (mt, i, len, '\n'); i < len;
1054 i = j + 1, j = mtext_character (mt, i, len, '\n'))
1058 if (flt (mt, i, j, font, flt_name) < 0)
1060 fprintf (stderr, "Error in FLT processing.\n");
1064 m17n_object_unref (mt);