• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdint.h>
2 
3 #include <ft2build.h>
4 #include FT_FREETYPE_H
5 #include FT_TRUETYPE_TABLES_H
6 
7 #if 0
8 #include <freetype/freetype.h>
9 #include <freetype/tttables.h>
10 #endif
11 
12 #include <harfbuzz-shaper.h>
13 #include "harfbuzz-unicode.h"
14 
15 static HB_Bool
hb_freetype_string_to_glyphs(HB_Font font,const HB_UChar16 * chars,hb_uint32 len,HB_Glyph * glyphs,hb_uint32 * numGlyphs,HB_Bool is_rtl)16 hb_freetype_string_to_glyphs(HB_Font font,
17                              const HB_UChar16 *chars, hb_uint32 len,
18                              HB_Glyph *glyphs, hb_uint32 *numGlyphs,
19                              HB_Bool is_rtl) {
20   FT_Face face = (FT_Face) font->userData;
21   if (len > *numGlyphs)
22     return 0;
23 
24   size_t i = 0, j = 0;
25   while (i < len) {
26     const uint32_t cp = utf16_to_code_point(chars, len, &i);
27     glyphs[j++] = FT_Get_Char_Index(face, cp);
28   }
29 
30   *numGlyphs = j;
31 
32   return 1;
33 }
34 
35 static void
hb_freetype_advances_get(HB_Font font,const HB_Glyph * glyphs,hb_uint32 len,HB_Fixed * advances,int flags)36 hb_freetype_advances_get(HB_Font font, const HB_Glyph *glyphs, hb_uint32 len,
37                          HB_Fixed *advances, int flags) {
38   FT_Face face = (FT_Face) font->userData;
39 
40   hb_uint32 i;
41   for (i = 0; i < len; ++i) {
42     const FT_Error error = FT_Load_Glyph(face, glyphs[i], FT_LOAD_DEFAULT);
43     if (error) {
44       advances[i] = 0;
45       continue;
46     }
47 
48     advances[i] = face->glyph->advance.x;
49   }
50 }
51 
52 static HB_Bool
hb_freetype_can_render(HB_Font font,const HB_UChar16 * chars,hb_uint32 len)53 hb_freetype_can_render(HB_Font font, const HB_UChar16 *chars, hb_uint32 len) {
54   FT_Face face = (FT_Face)font->userData;
55 
56   size_t i = 0;
57   while (i < len) {
58     const uint32_t cp = utf16_to_code_point(chars, len, &i);
59     if (FT_Get_Char_Index(face, cp) == 0)
60       return 0;
61   }
62 
63   return 1;
64 }
65 
66 static HB_Error
hb_freetype_outline_point_get(HB_Font font,HB_Glyph glyph,int flags,hb_uint32 point,HB_Fixed * xpos,HB_Fixed * ypos,hb_uint32 * n_points)67 hb_freetype_outline_point_get(HB_Font font, HB_Glyph glyph, int flags,
68                               hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos,
69                               hb_uint32 *n_points) {
70   HB_Error error = HB_Err_Ok;
71   FT_Face face = (FT_Face) font->userData;
72 
73   int load_flags = (flags & HB_ShaperFlag_UseDesignMetrics) ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT;
74 
75   if ((error = (HB_Error) FT_Load_Glyph(face, glyph, load_flags)))
76     return error;
77 
78   if (face->glyph->format != ft_glyph_format_outline)
79     return (HB_Error)HB_Err_Invalid_SubTable;
80 
81   *n_points = face->glyph->outline.n_points;
82   if (!(*n_points))
83     return HB_Err_Ok;
84 
85   if (point > *n_points)
86     return (HB_Error)HB_Err_Invalid_SubTable;
87 
88   *xpos = face->glyph->outline.points[point].x;
89   *ypos = face->glyph->outline.points[point].y;
90 
91   return HB_Err_Ok;
92 }
93 
94 static void
hb_freetype_glyph_metrics_get(HB_Font font,HB_Glyph glyph,HB_GlyphMetrics * metrics)95 hb_freetype_glyph_metrics_get(HB_Font font, HB_Glyph glyph,
96                               HB_GlyphMetrics *metrics) {
97   FT_Face face = (FT_Face) font->userData;
98 
99   const FT_Error error = FT_Load_Glyph(face, glyph, FT_LOAD_DEFAULT);
100   if (error) {
101     metrics->x = metrics->y = metrics->width = metrics->height = 0;
102     metrics->xOffset = metrics->yOffset = 0;
103     return;
104   }
105 
106   const FT_Glyph_Metrics *ftmetrics = &face->glyph->metrics;
107   metrics->width = ftmetrics->width;
108   metrics->height = ftmetrics->height;
109   metrics->x = ftmetrics->horiAdvance;
110   metrics->y = 0;  // unclear what this is
111   metrics->xOffset = ftmetrics->horiBearingX;
112   metrics->yOffset = ftmetrics->horiBearingY;
113 }
114 
115 static HB_Fixed
hb_freetype_font_metric_get(HB_Font font,HB_FontMetric metric)116 hb_freetype_font_metric_get(HB_Font font, HB_FontMetric metric) {
117   FT_Face face = (FT_Face) font->userData;
118 
119   switch (metric) {
120   case HB_FontAscent:
121     // Note that we aren't scanning the VDMX table which we probably would in
122     // an ideal world.
123     return face->ascender;
124   default:
125     return 0;
126   }
127 }
128 
129 const HB_FontClass hb_freetype_class = {
130   hb_freetype_string_to_glyphs,
131   hb_freetype_advances_get,
132   hb_freetype_can_render,
133   hb_freetype_outline_point_get,
134   hb_freetype_glyph_metrics_get,
135   hb_freetype_font_metric_get,
136 };
137 
138 HB_Error
hb_freetype_table_sfnt_get(void * voidface,const HB_Tag tag,HB_Byte * buffer,HB_UInt * len)139 hb_freetype_table_sfnt_get(void *voidface, const HB_Tag tag, HB_Byte *buffer, HB_UInt *len) {
140   FT_Face face = (FT_Face) voidface;
141   FT_ULong ftlen = *len;
142 
143   if (!FT_IS_SFNT(face))
144     return HB_Err_Invalid_Argument;
145 
146   const FT_Error error = FT_Load_Sfnt_Table(face, tag, 0, buffer, &ftlen);
147   *len = ftlen;
148   return (HB_Error) error;
149 }
150