27 #if defined (HAVE_FREETYPE)
29 #if defined (HAVE_FONTCONFIG)
30 #include <fontconfig/fontconfig.h>
52 "ft_render: skipping missing glyph for character '%x'",
60 "ft_render: unable to render glyph for character '%x'",
79 static bool instance_ok (
void)
93 ::error (
"unable to create ft_manager!");
103 static FT_Face get_font (
const std::string& name,
const std::string& weight,
104 const std::string& angle,
double size)
106 return (instance_ok ()
107 ? instance->do_get_font (name, weight, angle, size)
111 static void font_destroyed (FT_Face face)
114 instance->do_font_destroyed (face);
121 typedef std::pair<std::string, double>
ft_key;
138 : library (), freetype_initialized (false), fontconfig_initialized (false)
140 if (FT_Init_FreeType (&library))
141 ::error (
"unable to initialize freetype library");
143 freetype_initialized =
true;
145 #if defined (HAVE_FONTCONFIG)
147 ::error (
"unable to initialize fontconfig library");
149 fontconfig_initialized =
true;
155 if (freetype_initialized)
156 FT_Done_FreeType (library);
158 #if defined (HAVE_FONTCONFIG)
169 FT_Face do_get_font (
const std::string& name,
const std::string& weight,
170 const std::string& angle,
double size)
174 #if HAVE_FT_REFERENCE_FACE
178 ft_key key (name +
":" + weight +
":" + angle, size);
179 ft_cache::const_iterator it = cache.find (key);
181 if (it != cache.end ())
183 FT_Reference_Face (it->second);
190 #if defined (HAVE_FONTCONFIG)
191 if (fontconfig_initialized)
193 int fc_weight, fc_angle;
195 if (weight ==
"bold")
196 fc_weight = FC_WEIGHT_BOLD;
197 else if (weight ==
"light")
198 fc_weight = FC_WEIGHT_LIGHT;
199 else if (weight ==
"demi")
200 fc_weight = FC_WEIGHT_DEMIBOLD;
202 fc_weight = FC_WEIGHT_NORMAL;
204 if (angle ==
"italic")
205 fc_angle = FC_SLANT_ITALIC;
206 else if (angle ==
"oblique")
207 fc_angle = FC_SLANT_OBLIQUE;
209 fc_angle = FC_SLANT_ROMAN;
211 FcPattern *pat = FcPatternCreate ();
213 FcPatternAddString (pat, FC_FAMILY,
214 (reinterpret_cast<const FcChar8*>
215 (name ==
"*" ?
"sans" : name.c_str ())));
217 FcPatternAddInteger (pat, FC_WEIGHT, fc_weight);
218 FcPatternAddInteger (pat, FC_SLANT, fc_angle);
219 FcPatternAddDouble (pat, FC_PIXEL_SIZE, size);
221 if (FcConfigSubstitute (0, pat, FcMatchPattern))
226 FcDefaultSubstitute (pat);
227 match = FcFontMatch (0, pat, &res);
235 FcPatternGetString (match, FC_FILE, 0, &tmp);
236 file =
reinterpret_cast<char*
> (tmp);
239 ::warning (
"could not match any font: %s-%s-%s-%g",
240 name.c_str (), weight.c_str (), angle.c_str (),
244 FcPatternDestroy (match);
247 FcPatternDestroy (pat);
254 file =
"C:/WINDOWS/Fonts/verdana.ttf";
262 if (FT_New_Face (library, file.c_str (), 0, &retval))
263 ::warning (
"ft_manager: unable to load font: %s", file.c_str ());
264 #if HAVE_FT_REFERENCE_FACE
271 retval->generic.data =
new ft_key (key);
284 void do_font_destroyed (FT_Face face)
286 if (face->generic.data)
288 ft_key* pkey =
reinterpret_cast<ft_key*
> (face->generic.data);
292 face->generic.data = 0;
311 :
text_processor (), font (), bbox (1, 4, 0.0), halign (0), xoffset (0),
312 line_yoffset (0), yoffset (0), mode (MODE_BBOX),
323 const std::string& angle,
double size)
343 int asc = face->size->metrics.ascender >> 6;
344 int desc = face->size->metrics.descender >> 6;
345 int h = face->size->metrics.height >> 6;
370 line_yoffset += (old_bbox(1) - (new_bbox(1) + new_bbox(3)));
387 return (
bbox(2) - lb(2)) / 2;
389 return (
bbox(2) - lb(2));
412 for (std::list<Matrix>::const_iterator it =
line_bbox.begin ();
438 int asc =
font.
get_face ()->size->metrics.ascender >> 6;
439 int desc =
font.
get_face ()->size->metrics.descender >> 6;
447 int delta = bb(1) - (
yoffset + desc);
453 if ((
yoffset + asc) > (bb(1) + bb(3)))
457 int delta = (
yoffset + asc) - (bb(1) + bb(3));
480 ::warning (
"ft_render: invalid bounding box, cannot render");
488 static_cast<uint8_t> (0));
504 FT_UInt glyph_index = 0;
508 glyph_index = FT_Get_Char_Index (face, code);
512 || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT)))
524 glyph_index = FT_Get_Char_Index (face,
' ');
526 || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
534 else if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL))
541 FT_Bitmap& bitmap = face->glyph->bitmap;
548 FT_Get_Kerning (face, previous, glyph_index,
549 FT_KERNING_DEFAULT, &delta);
553 x0 =
xoffset + face->glyph->bitmap_left;
563 for (
int r = 0; r < bitmap.rows; r++)
564 for (
int c = 0; c < bitmap.width; c++)
566 unsigned char pix = bitmap.buffer[r*bitmap.width+c];
573 else if (
pixels(3, x0+c, y0-r).value () == 0)
578 pixels(3, x0+c, y0-r) = pix;
582 xoffset += (face->glyph->advance.x >> 6);
589 glyph_index = FT_Get_Char_Index (face,
' ');
591 || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
610 FT_Get_Kerning (face, previous, glyph_index,
611 FT_KERNING_DEFAULT, &delta);
619 xoffset += (face->glyph->advance.x >> 6);
635 FT_UInt glyph_index, previous = 0;
638 size_t n = str.length (), curr = 0;
640 memset (&ps, 0,
sizeof (ps));
645 size_t r = gnulib::mbrtowc (&wc, str.data () + curr, n, &ps);
648 && r != static_cast<size_t> (-1)
649 && r !=
static_cast<size_t> (-2))
659 previous = glyph_index;
664 ::warning (
"ft_render: failed to decode string `%s' with "
665 "locale `%s'", str.c_str (),
666 std::setlocale (LC_CTYPE, 0));
730 int s_asc = saved_font.
get_face ()->size->metrics.ascender >> 6;
823 (*it)->accept (*
this);
842 color(0) =
static_cast<uint8_t
> (c(0)*255);
843 color(1) =
static_cast<uint8_t
> (c(1)*255);
844 color(2) =
static_cast<uint8_t
> (c(2)*255);
847 ::warning (
"ft_render::set_color: invalid color");
924 Matrix extent (1, 2, 0.0);
959 while (rotation > 360.0)
964 else if (rotation == 90.0)
966 else if (rotation == 180.0)
968 else if (rotation == 270.0)
977 int _halign,
int valign,
double rotation,
985 pixels_ =
render (elt, box, rot_mode);
988 if (pixels_.
numel () == 0)
996 default:
box(0) = 0;
break;
997 case 1:
box(0) = -
box(2)/2;
break;
998 case 2:
box(0) = -
box(2);
break;
1002 default:
box(1) = 0;
break;
1003 case 1:
box(1) = -
box(3)/2;
break;
1004 case 2:
box(1) = -
box(3);
break;
1012 std::swap (
box(0),
box(1));
1013 std::swap (
box(2),
box(3));
1021 std::swap (
box(0),
box(1));
1022 std::swap (
box(2),
box(3));
1029 : name (ft.name), weight (ft.weight), angle (ft.angle),
size (ft.
size),
1032 #if HAVE_FT_REFERENCE_FACE
1035 if (ft_face && FT_Reference_Face (ft_face) == 0)
1051 FT_Done_Face (face);
1055 #if HAVE_FT_REFERENCE_FACE
1058 if (ft_face && FT_Reference_Face (ft_face) == 0)
1069 if (! face && ! name.empty ())
1075 if (FT_Set_Char_Size (face, 0,
size*64, 0, 0))
1076 ::warning (
"ft_render: unable to set font size to %g",
size);
1079 ::warning (
"ft_render: unable to load appropriate font");
1085 #endif // HAVE_FREETYPE