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'",
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)
107 ?
instance->do_get_font (name, weight, angle, size)
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);
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 ();
641 memset (&ps, 0,
sizeof (ps));
646 size_t r = gnulib::mbrtowc (&wc, str.data () + curr, n, &ps);
649 && r != static_cast<size_t> (-1)
650 && r !=
static_cast<size_t> (-2))
660 previous = glyph_index;
665 ::warning (
"ft_render: failed to decode string `%s' with "
666 "locale `%s'", str.c_str (),
667 std::setlocale (LC_CTYPE, 0));
731 int s_asc = saved_font.
get_face ()->size->metrics.ascender >> 6;
824 (*it)->accept (*
this);
843 color(0) =
static_cast<uint8_t
> (c(0)*255);
844 color(1) =
static_cast<uint8_t
> (c(1)*255);
845 color(2) =
static_cast<uint8_t
> (c(2)*255);
848 ::warning (
"ft_render::set_color: invalid color");
925 Matrix extent (1, 2, 0.0);
960 while (rotation > 360.0)
965 else if (rotation == 90.0)
967 else if (rotation == 180.0)
969 else if (rotation == 270.0)
978 int _halign,
int valign,
double rotation,
986 pixels_ =
render (elt, box, rot_mode);
989 if (pixels_.
numel () == 0)
997 default:
box(0) = 0;
break;
998 case 1:
box(0) = -
box(2)/2;
break;
999 case 2:
box(0) = -
box(2);
break;
1003 default:
box(1) = 0;
break;
1004 case 1:
box(1) = -
box(3)/2;
break;
1005 case 2:
box(1) = -
box(3);
break;
1013 std::swap (
box(0),
box(1));
1014 std::swap (
box(2),
box(3));
1022 std::swap (
box(0),
box(1));
1023 std::swap (
box(2),
box(3));
1030 : name (ft.name), weight (ft.weight), angle (ft.angle),
size (ft.
size),
1033 #if HAVE_FT_REFERENCE_FACE
1036 if (ft_face && FT_Reference_Face (ft_face) == 0)
1052 FT_Done_Face (face);
1056 #if HAVE_FT_REFERENCE_FACE
1059 if (ft_face && FT_Reference_Face (ft_face) == 0)
1070 if (! face && ! name.empty ())
1076 if (FT_Set_Char_Size (face, 0,
size*64, 0, 0))
1077 ::warning (
"ft_render: unable to set font size to %g",
size);
1080 ::warning (
"ft_render: unable to load appropriate font");
1086 #endif // HAVE_FREETYPE
void warning_with_id(const char *id, const char *fmt,...)
static bool instance_ok(void)
static void font_destroyed(FT_Face face)
void visit(text_element_string &e)
bool is_empty(void) const
static void gripe_glyph_render(FT_ULong c)
int compute_line_xoffset(const Matrix &lb) const
MArray< T > permute(const Array< octave_idx_type > &vec, bool inv=false) const
void update_line_bbox(void)
Matrix extract(octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2) const
static void gripe_missing_glyph(FT_ULong c)
octave_idx_type numel(void) const
Number of elements in the array.
OCTINTERP_API octave_value box(JNIEnv *jni_env, jobject jobj, jclass jcls=0)
intNDArray< octave_uint8 > uint8NDArray
octave_idx_type dim2(void) const
fontstyle get_fontstyle(void) const
Complex xmax(const Complex &x, const Complex &y)
ft_font & operator=(const ft_font &ft)
FT_UInt process_character(FT_ULong code, FT_UInt previous=0)
void error(const char *fmt,...)
bool is_valid(void) const
double get_fontsize(void) const
bool freetype_initialized
bool fontconfig_initialized
static void ft_face_destroyed(void *object)
std::list< Matrix > line_bbox
int rotation_to_mode(double rotation) const
int get_symbol(void) const
std::string get_name(void) const
static FT_Face get_font(const std::string &name, const std::string &weight, const std::string &angle, double size)
std::string get_weight(void) const
void do_font_destroyed(FT_Face face)
octave_idx_type dim3(void) const
std::list< text_element * >::iterator iterator
std::string get_angle(void) const
uint8NDArray render(text_element *elt, Matrix &box, int rotation=ROTATION_0)
octave_idx_type index(const T *src, octave_idx_type n, T *dest) const
uint32_t get_symbol_code(void) const
virtual void accept(text_processor &p)=0
std::string string_value(void) const
void set_font(const std::string &name, const std::string &weight, const std::string &angle, double size)
static void cleanup_instance(void)
virtual text_element * parse(const std::string &s)=0
static bool instance_ok(void)
size_t size(T const (&)[z])
std::pair< std::string, double > ft_key
FT_Face get_face(void) const
void warning(const char *fmt,...)
std::map< ft_key, FT_Face > ft_cache
void text_to_pixels(const std::string &txt, uint8NDArray &pixels_, Matrix &bbox, int halign, int valign, double rotation, const caseless_str &interpreter="tex")
static ft_manager * instance
Matrix get_extent(text_element *elt, double rotation=0.0)
static bool match(const std::string &filename_arg, const std::string &path_elt_arg)
FT_Face do_get_font(const std::string &name, const std::string &weight, const std::string &angle, double size)
static octave_call_stack * instance
double get_size(void) const
virtual void visit(text_element_string &e)=0
static void cleanup_instance(void)
const std::string & get_fontname(void) const
Array< T > index(const idx_vector &i) const
Indexing without resizing.