24 #if defined (HAVE_CONFIG_H) 31 #if defined (HAVE_FREETYPE) 33 #if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC) 34 # pragma GCC diagnostic push 35 # pragma GCC diagnostic ignored "-Wold-style-cast" 39 #include FT_FREETYPE_H 41 #if defined (HAVE_FONTCONFIG) 42 # include <fontconfig/fontconfig.h> 45 #if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC) 46 # pragma GCC diagnostic pop 73 "text_renderer: skipping missing glyph for character '%x'",
c);
80 "text_renderer: unable to render glyph for character '%x'",
c);
83 #if defined (_MSC_VER) 102 : library (), freetype_initialized (
false), fontconfig_initialized (
false)
104 if (FT_Init_FreeType (&library))
105 error (
"unable to initialize FreeType library");
107 freetype_initialized =
true;
109 #if defined (HAVE_FONTCONFIG) 111 error (
"unable to initialize fontconfig library");
113 fontconfig_initialized =
true;
129 if (freetype_initialized)
130 FT_Done_FreeType (library);
132 #if defined (HAVE_FONTCONFIG) 157 error (
"unable to create ft_manager!");
167 return (instance_ok ()
168 ? instance->do_get_font (
name, weight, angle, size)
175 instance->do_font_destroyed (face);
182 typedef std::pair<std::string, double>
ft_key;
195 #if defined (HAVE_FT_REFERENCE_FACE) 199 ft_key key (
name +
':' + weight +
':' + angle, size);
200 ft_cache::const_iterator it = cache.find (key);
202 if (it != cache.end ())
204 FT_Reference_Face (it->second);
211 if (fonts_dir.empty ())
215 if (fonts_dir.empty ())
216 #
if defined (SYSTEM_FREEFONT_DIR)
217 fonts_dir = SYSTEM_FREEFONT_DIR;
227 if (! fonts_dir.empty ())
231 if (weight ==
"bold")
234 if (angle ==
"italic" || angle ==
"oblique")
240 #if defined (HAVE_FONTCONFIG) 241 if (
name !=
"*" && fontconfig_initialized)
243 int fc_weight, fc_angle;
245 if (weight ==
"bold")
246 fc_weight = FC_WEIGHT_BOLD;
247 else if (weight ==
"light")
248 fc_weight = FC_WEIGHT_LIGHT;
249 else if (weight ==
"demi")
250 fc_weight = FC_WEIGHT_DEMIBOLD;
252 fc_weight = FC_WEIGHT_NORMAL;
254 if (angle ==
"italic")
255 fc_angle = FC_SLANT_ITALIC;
256 else if (angle ==
"oblique")
257 fc_angle = FC_SLANT_OBLIQUE;
259 fc_angle = FC_SLANT_ROMAN;
261 FcPattern *pat = FcPatternCreate ();
263 FcPatternAddString (pat, FC_FAMILY,
264 (reinterpret_cast<const FcChar8 *>
267 FcPatternAddInteger (pat, FC_WEIGHT, fc_weight);
268 FcPatternAddInteger (pat, FC_SLANT, fc_angle);
269 FcPatternAddDouble (pat, FC_PIXEL_SIZE, size);
271 if (FcConfigSubstitute (
nullptr, pat, FcMatchPattern))
276 FcDefaultSubstitute (pat);
277 match = FcFontMatch (
nullptr, pat, &res);
285 FcPatternGetString (match, FC_FILE, 0, &
tmp);
286 file =
reinterpret_cast<char *
> (
tmp);
289 ::warning (
"could not match any font: %s-%s-%s-%g, using default font",
290 name.c_str (), weight.c_str (), angle.c_str (),
294 FcPatternDestroy (match);
297 FcPatternDestroy (pat);
302 ::
warning (
"unable to find default font files");
305 if (FT_New_Face (library,
file.c_str (), 0, &
retval))
306 ::warning (
"ft_manager: unable to load font: %s",
file.c_str ());
307 #if defined (HAVE_FT_REFERENCE_FACE) 329 if (face->generic.data)
331 ft_key *pkey =
reinterpret_cast<ft_key *
> (face->generic.data);
335 face->generic.data =
nullptr;
377 xoffset (0), line_yoffset (0), yoffset (0),
mode (MODE_BBOX),
416 int rotation = ROTATION_0);
425 void set_color (
const Matrix&
c);
427 void set_mode (
int m);
431 int halign,
int valign,
double rotation,
433 bool handle_rotation);
437 int rotation_to_mode (
double rotation)
const;
466 FT_Face get_face (
void)
const;
473 void push_new_line (
void);
475 void update_line_bbox (
void);
477 void compute_bbox (
void);
479 int compute_line_xoffset (
const Matrix& lb)
const;
481 FT_UInt process_character (FT_ULong
code, FT_UInt previous = 0);
486 std::list<text_renderer::string>& lst,
Matrix& bbox,
487 int halign,
int valign,
double rotation,
560 int asc = face->size->metrics.ascender >> 6;
561 int desc = face->size->metrics.descender >> 6;
562 int h = face->size->metrics.height >> 6;
587 line_yoffset += (old_bbox(1) - (new_bbox(1) + new_bbox(3)));
604 return (
bbox(2) - lb(2)) / 2;
606 return (
bbox(2) - lb(2));
656 int asc =
font.
get_face ()->size->metrics.ascender >> 6;
657 int desc =
font.
get_face ()->size->metrics.descender >> 6;
665 int delta = bb(1) - (
yoffset + desc);
671 if ((
yoffset + asc) > (bb(1) + bb(3)))
675 int delta = (
yoffset + asc) - (bb(1) + bb(3));
699 ::error (
"ft_text_renderer: invalid bounding box, cannot render");
716 error (
"ft_text_renderer: invalid mode '%d'",
mode);
725 FT_UInt glyph_index = 0;
729 glyph_index = FT_Get_Char_Index (face,
code);
733 || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT)))
745 glyph_index = FT_Get_Char_Index (face,
' ');
747 || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
755 else if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL))
762 FT_Bitmap& bitmap = face->glyph->bitmap;
769 FT_Get_Kerning (face, previous, glyph_index,
770 FT_KERNING_DEFAULT, &delta);
774 x0 =
xoffset + face->glyph->bitmap_left;
784 for (
int r = 0;
static_cast<unsigned int> (r) < bitmap.rows; r++)
785 for (
int c = 0;
static_cast<unsigned int> (
c) < bitmap.width;
c++)
787 unsigned char pix = bitmap.buffer[r*bitmap.width+
c];
794 else if (
pixels(3, x0+
c, y0-r).value () == 0)
803 xoffset += (face->glyph->advance.x >> 6);
810 glyph_index = FT_Get_Char_Index (face,
' ');
812 || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
831 FT_Get_Kerning (face, previous, glyph_index,
832 FT_KERNING_DEFAULT, &delta);
840 xoffset += (face->glyph->advance.x >> 6);
853 std::list<text_renderer::string>& lst,
855 int ha,
int va,
double rot,
872 FT_UInt glyph_index, previous = 0;
875 size_t n =
str.length ();
879 memset (&ps, 0,
sizeof (ps));
883 std::vector<double> xdata;
887 size_t r = std::mbrtowc (&wc,
str.data () + curr, n, &ps);
890 && r != static_cast<size_t> (-1)
891 && r !=
static_cast<size_t> (-2))
906 fs.set_xdata (xdata);
926 previous = glyph_index;
931 ::warning (
"ft_text_renderer: failed to decode string `%s' with " 932 "locale `%s'",
str.c_str (),
933 std::setlocale (LC_CTYPE,
nullptr));
938 if (!
fs.get_string ().empty ())
942 fs.set_xdata (xdata);
1006 int s_asc = saved_font.
get_face ()->size->metrics.ascender >> 6;
1035 double sz =
e.get_fontsize ();
1059 switch (
e.get_fontstyle ())
1085 uint32_t
code =
e.get_symbol_code ();
1087 std::vector<double> xdata (1,
xoffset);
1094 fs.set_xdata (xdata);
1097 ::
warning (
"ignoring unknown symbol: %d",
e.get_symbol ());
1114 for (
auto *txt_elt :
e)
1117 txt_elt->accept (*
this);
1134 if (
c.numel () == 3)
1136 color(0) =
static_cast<uint8_t
> (
c(0)*255);
1137 color(1) =
static_cast<uint8_t
> (
c(1)*255);
1138 color(2) =
static_cast<uint8_t
> (
c(2)*255);
1141 ::warning (
"ft_text_renderer::set_color: invalid color");
1224 Matrix extent (1, 2, 0.0);
1230 extent(0) =
bbox(2);
1231 extent(1) =
bbox(3);
1236 extent(0) =
bbox(3);
1237 extent(1) =
bbox(2);
1258 while (rotation < 0)
1260 while (rotation > 360.0)
1263 if (rotation == 0.0)
1265 else if (rotation == 90.0)
1267 else if (rotation == 180.0)
1269 else if (rotation == 270.0)
1278 int _halign,
int valign,
double rotation,
1280 bool handle_rotation)
1330 if (handle_rotation)
1357 #if defined (HAVE_FT_REFERENCE_FACE) 1360 if (ft_face && FT_Reference_Face (ft_face) == 0)
1374 FT_Done_Face (face);
1378 #if defined (HAVE_FT_REFERENCE_FACE) 1381 if (ft_face && FT_Reference_Face (ft_face) == 0)
1392 if (! face && !
name.empty ())
1398 if (FT_Set_Char_Size (face, 0, size*64, 0, 0))
1399 ::warning (
"ft_text_renderer: unable to set font size to %g", size);
1402 ::warning (
"ft_text_renderer: unable to load appropriate font");
1416 #if defined (HAVE_FREETYPE)
ft_font & operator=(const ft_font &ft)
void warning_with_id(const char *id, const char *fmt,...)
std::string oct_fonts_dir(void)
static FT_Face get_font(const std::string &name, const std::string &weight, const std::string &angle, double size)
For example cd octave end example noindent changes the current working directory to file
int rotation_to_mode(double rotation) const
octave_idx_type dim3(void) const
double get_size(void) const
uint8NDArray render(text_element *elt, Matrix &box, int rotation=ROTATION_0)
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE * f
std::pair< std::string, double > ft_key
Return the CPU time used by your Octave session The first output is the total time spent executing your process and is equal to the sum of second and third which are the number of CPU seconds spent executing in user mode and the number of CPU seconds spent executing in system mode
std::map< ft_key, FT_Face > ft_cache
intNDArray< octave_uint8 > uint8NDArray
std::list< Matrix > line_bbox
std::string get_name(void) const
static ft_manager * instance
void text_to_strlist(const std::string &txt, std::list< text_renderer::string > &lst, Matrix &bbox, int halign, int valign, double rotation, const caseless_str &interp)
void set_color(const Matrix &c)
void error(const char *fmt,...)
nd example oindent opens the file binary numeric values will be read assuming they are stored in IEEE format with the least significant bit and then converted to the native representation Opening a file that is already open simply opens it again and returns a separate file id It is not an error to open a file several though writing to the same file through several different file ids may produce unexpected results The possible values of text mode reading and writing automatically converts linefeeds to the appropriate line end character for the you may append a you must also open the file in binary mode The parameter conversions are currently only supported for and permissions will be set to and then everything is written in a single operation This is very efficient and improves performance c
FT_Face do_get_font(const std::string &name, const std::string &weight, const std::string &angle, double size)
std::string dir_sep_str(void)
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
static std::string getenv(const std::string &name)
std::list< text_renderer::string > strlist
MArray< T > permute(const Array< octave_idx_type > &vec, bool inv=false) const
base_text_renderer * make_ft_text_renderer(void)
static void warn_missing_glyph(FT_ULong c)
nd deftypefn *std::string name
Array< T > index(const idx_vector &i) const
Indexing without resizing.
OCTAVE_EXPORT octave_value_list isdir nd deftypefn *std::string nm
static void ft_face_destroyed(void *object)
static octave_value box(JNIEnv *jni_env, void *jobj, void *jcls_arg=nullptr)
uint8NDArray get_pixels(void) const
int compute_line_xoffset(const Matrix &lb) const
virtual void accept(text_processor &p)=0
octave_idx_type dim2(void) const
void visit(text_element_string &e)
Matrix get_extent(text_element *elt, double rotation=0.0)
std::string get_weight(void) const
virtual text_element * parse(const std::string &s)=0
void text_to_pixels(const std::string &txt, uint8NDArray &pxls, Matrix &bbox, int halign, int valign, double rotation, const caseless_str &interpreter, bool handle_rotation)
std::string get_angle(void) const
Matrix extract(octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2) const
static void warn_glyph_render(FT_ULong c)
void warning(const char *fmt,...)
FT_Face get_face(void) const
defaults to zero A value of zero computes the digamma a value the trigamma and so on The digamma function is defined
bool fontconfig_initialized
void do_font_destroyed(FT_Face face)
font & operator=(const font &ft)
FT_UInt process_character(FT_ULong code, FT_UInt previous=0)
static bool instance_ok(void)
bool is_valid(void) const
octave::sys::file_stat fs(filename)
void set_font(const std::string &name, const std::string &weight, const std::string &angle, double size)
octave_idx_type numel(void) const
Number of elements in the array.
static void cleanup_instance(void)
virtual void visit(text_element_string &e)=0
Vector representing the dimensions (size) of an Array.
Matrix get_boundingbox(void) const
ft_font(const std::string &nm, const std::string &wt, const std::string &ang, double sz, FT_Face f=nullptr)
static void font_destroyed(FT_Face face)
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
void update_line_bbox(void)
bool freetype_initialized