|
|
|
|
|
#ifndef DLIB_FONTs_CPP_ |
|
#define DLIB_FONTs_CPP_ |
|
|
|
#include "fonts.h" |
|
|
|
#include <fstream> |
|
#include <memory> |
|
#include <sstream> |
|
|
|
#include "../serialize.h" |
|
#include "../base64.h" |
|
#include "../compress_stream.h" |
|
#include "../tokenizer.h" |
|
#include "nativefont.h" |
|
|
|
namespace dlib |
|
{ |
|
|
|
|
|
|
|
const std::string get_decoded_string_with_default_font_data() |
|
{ |
|
dlib::base64::kernel_1a base64_coder; |
|
dlib::compress_stream::kernel_1ea compressor; |
|
std::ostringstream sout; |
|
std::istringstream sin; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sout << "AXF+zOQzCgGitrKiOCGEL4hlIv1ZenWJyjMQ4rJ6f/oPMeHqsZn+8XnpehwFQTz3dtUGlZRAUoOa"; |
|
sout << "uVo8UiplcFxuK69A+94rpMCMAyEeeOwZ/tRzkX4eKuU3L4xtsJDknMiYUNKaMrYimb1QJ0E+SRqQ"; |
|
sout << "wATrMTecYNZvJJm02WibiwE4cJ5scvkHNl4KJT5QfdwRdGopTyUVdZvRvtbTLLjsJP0fQEQLqemf"; |
|
sout << "qPE4kDD79ehrBIwLO1Y6TzxtrrIoQR57zlwTUyLenqRtSN3VLtjWYd82cehRIlTLtuxBg2s+zZVq"; |
|
sout << "jNlNnYTSM+Swy06qnQgg+Dt0lhtlB9shR1OAlcfCtTW6HKoBk/FGeDmjTGW4bNCGv7RjgM6TlLDg"; |
|
sout << "ZYSSA6ZCCAKBgE++U32gLHCCiVkPTkkp9P6ioR+e3SSKRNm9p5MHf+ZQ3LJkW8KFJ/K9gKT1yvyv"; |
|
sout << "F99pAvOOq16tHRFvzBs+xZj/mUpH0lGIS7kLWr9oP2KuccVrz25aJn3kDruwTYoD+CYlOqtPO0Mv"; |
|
sout << "dEI0LUR0Ykp1M2rWo76fJ/fpzHjV7737hjkNPJ13nO72RMDr4R5V3uG7Dw7Ng+vGX3WgJZ4wh1JX"; |
|
sout << "pl2VMqC5JXccctzvnQvnuvBvRm7THgwQUgMKKT3WK6afUUVlJy8DHKuU4k1ibfVMxAmrwKdTUX2w"; |
|
sout << "cje3A05Qji3aop65qEdwgI5O17HIVoRQOG/na+XRMowOfUvI4H8Z4+JGACfRrQctgYDAM9eJzm8i"; |
|
sout << "PibyutmJfZBGg0a3oC75S5R9lTxEjPocnEyJRYNnmVnVAmKKbTbTsznuaD+D1XhPdr2t3A4bRTsp"; |
|
sout << "toKKtlFnd9YGwLWwONDwLnoQ/IXwyF7txrRHNSVToh772U0Aih/yn5vnmcMF750eiMzRAgXu5sbR"; |
|
sout << "VXEOVCiLgVevN5umkvjZt1eGTSSzDMrIvnv4nyOfaFsD+I76wQfgLqd71rheozGtjNc0AOTx4Ggc"; |
|
sout << "eUSFHTDAVfTExBzckurtyuIAqF986a0JLHCtsDpBa2wWNuiQYOH3/LX1zkdU2hdamhBW774bpEwr"; |
|
sout << "dguMxxOeDGOBgIlM5gxXGYXSf5IN3fUAEPfOPRxB7T+tpjFnWd7cg+JMabci3zhJ9ANaYT7HGeTX"; |
|
sout << "bulKnGHjYrR1BxdK3YeliogQRU4ytmxlyL5zlNFU/759mA8XSfIPMEZn9Vxkb00q1htF7REiDcr3"; |
|
sout << "kW1rtPAc7VQNEhT54vK/YF6rMvjO7kBZ/vLYo7E8e8hDKEnY8ucrC3KGmeo31Gei74BBcEbvJBd3"; |
|
sout << "/YAaIKgXWwU2wSUw9wLq2RwGwyguvKBx0J/gn27tjcVAHorRBwxzPpk8r+YPyN+SifSzEL7LEy1G"; |
|
sout << "lPHxmXTrcqnH9qraeAqXJUJvU8SJJpf/tmsAE+XSKD/kpVBnT5qXsJ1SRFS7MtfPjE1j/NYbaQBI"; |
|
sout << "bOrh81zaYCEJR0IKHWCIsu/MC3zKXfkxFgQ9XpYAuWjSSK64YpgkxSMe8VG8yYvigOw2ODg/z4FU"; |
|
sout << "+HpnEKF/M/mKfLKK1i/8BV7xcYVHrhEww1QznoFklJs/pEg3Kd5PE1lRii6hvTn6McVAkw+YbH9q"; |
|
sout << "/sg4gFIAvai64hMcZ1oIZYppj3ZN6KMdyhK5s4++ZS/YOV2nNhW73ovivyi2Tjg7lxjJJtsYrLKb"; |
|
sout << "zIN1slOICKYwBq42TFBcFXaZ6rf0Czd09tL+q6A1Ztgr3BNuhCenjhWN5ji0LccGYZo6bLTggRG/"; |
|
sout << "Uz6K3CBBU/byLs79c5qCohrr7rlpDSdbuR+aJgNiWoU6T0i2Tvua6h51LcWEHy5P2n146/Ae2di4"; |
|
sout << "eh20WQvclrsgm1oFTGD0Oe85GKOTA7vvwKmLBc1wwA0foTuxzVgj0TMTFBiYLTLG4ujUyBYy1N6e"; |
|
sout << "H8EKi8H+ZAlqezrjABO3BQr33ewdZL5IeJ4w7gdGUDA6+P+7cODcBW50X9++6YTnKctuEw6aXBpy"; |
|
sout << "GgcMfPE61G8YKBbFGFic3TVvGCLvre1iURv+F+hU4/ee6ILuPnpYnSXX2iCIK/kmkBse8805d4Qe"; |
|
sout << "DG/8rBW9ojvAgc0jX7CatPEMHGkcz+KIZoKMI7XXK4PJpGQUdq6EdIhJC4koXEynjwwXMeC+jJqH"; |
|
sout << "agwrlDNssq/8AA=="; |
|
|
|
|
|
|
|
|
|
sin.str(sout.str()); |
|
sout.str(""); |
|
|
|
|
|
base64_coder.decode(sin,sout); |
|
sin.clear(); |
|
sin.str(sout.str()); |
|
sout.str(""); |
|
|
|
|
|
compressor.decompress(sin,sout); |
|
|
|
|
|
return sout.str(); |
|
} |
|
|
|
|
|
default_font:: |
|
default_font ( |
|
) |
|
{ |
|
using namespace std; |
|
l = new letter[256]; |
|
|
|
try |
|
{ |
|
istringstream sin(get_decoded_string_with_default_font_data()); |
|
|
|
for (int i = 0; i < 256; ++i) |
|
{ |
|
deserialize(l[i],sin); |
|
} |
|
|
|
} |
|
catch (...) |
|
{ |
|
delete [] l; |
|
throw; |
|
} |
|
} |
|
|
|
|
|
|
|
void serialize ( |
|
const letter& item, |
|
std::ostream& out |
|
) |
|
{ |
|
try |
|
{ |
|
serialize(item.w,out); |
|
serialize(item.count,out); |
|
|
|
for (unsigned long i = 0; i < item.count; ++i) |
|
{ |
|
serialize(item.points[i].x,out); |
|
serialize(item.points[i].y,out); |
|
} |
|
} |
|
catch (serialization_error& e) |
|
{ |
|
throw serialization_error(e.info + "\n while serializing object of type letter"); |
|
} |
|
} |
|
|
|
void deserialize ( |
|
letter& item, |
|
std::istream& in |
|
) |
|
{ |
|
try |
|
{ |
|
if (item.points) |
|
delete [] item.points; |
|
|
|
deserialize(item.w,in); |
|
deserialize(item.count,in); |
|
|
|
if (item.count > 0) |
|
item.points = new letter::point[item.count]; |
|
else |
|
item.points = 0; |
|
|
|
for (unsigned long i = 0; i < item.count; ++i) |
|
{ |
|
deserialize(item.points[i].x,in); |
|
deserialize(item.points[i].y,in); |
|
} |
|
} |
|
catch (serialization_error& e) |
|
{ |
|
item.w = 0; |
|
item.count = 0; |
|
item.points = 0; |
|
throw serialization_error(e.info + "\n while deserializing object of type letter"); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace bdf_font_helpers |
|
{ |
|
class bdf_parser |
|
{ |
|
public: |
|
bdf_parser( std::istream& in ) : in_( in ) |
|
{ |
|
std::string str_tmp; |
|
int int_tmp; |
|
|
|
str_tmp = "STARTFONT"; int_tmp = STARTFONT; keyword_map.add( str_tmp, int_tmp ); |
|
str_tmp = "FONTBOUNDINGBOX";int_tmp = FONTBOUNDINGBOX; keyword_map.add( str_tmp, int_tmp ); |
|
str_tmp = "DWIDTH"; int_tmp = DWIDTH; keyword_map.add( str_tmp, int_tmp ); |
|
str_tmp = "CHARS"; int_tmp = CHARS; keyword_map.add( str_tmp, int_tmp ); |
|
str_tmp = "STARTCHAR"; int_tmp = STARTCHAR; keyword_map.add( str_tmp, int_tmp ); |
|
str_tmp = "ENCODING"; int_tmp = ENCODING; keyword_map.add( str_tmp, int_tmp ); |
|
str_tmp = "BBX"; int_tmp = BBX; keyword_map.add( str_tmp, int_tmp ); |
|
str_tmp = "BITMAP"; int_tmp = BITMAP; keyword_map.add( str_tmp, int_tmp ); |
|
str_tmp = "ENDCHAR"; int_tmp = ENDCHAR; keyword_map.add( str_tmp, int_tmp ); |
|
str_tmp = "ENDFONT"; int_tmp = ENDFONT; keyword_map.add( str_tmp, int_tmp ); |
|
str_tmp = "DEFAULT_CHAR"; int_tmp = DEFAULT_CHAR; keyword_map.add( str_tmp, int_tmp ); |
|
|
|
tokzr.set_identifier_token( tokzr.uppercase_letters(), tokzr.uppercase_letters() + "_" ); |
|
tokzr.set_stream( in ); |
|
|
|
} |
|
|
|
enum bdf_enums |
|
{ |
|
NO_KEYWORD = 0, |
|
STARTFONT = 1, |
|
FONTBOUNDINGBOX = 2, |
|
DWIDTH = 4, |
|
DEFAULT_CHAR = 8, |
|
CHARS = 16, |
|
STARTCHAR = 32, |
|
ENCODING = 64, |
|
BBX = 128, |
|
BITMAP = 256, |
|
ENDCHAR = 512, |
|
ENDFONT = 1024 |
|
|
|
}; |
|
struct header_info |
|
{ |
|
int FBBx, FBBy, Xoff, Yoff; |
|
int dwx0, dwy0; |
|
bool has_global_dw; |
|
long default_char; |
|
}; |
|
struct char_info |
|
{ |
|
int dwx0, dwy0; |
|
int BBw, BBh, BBxoff0x, BByoff0y; |
|
array2d<char> bitmap; |
|
bool has_dw; |
|
}; |
|
bool parse_header( header_info& info ) |
|
{ |
|
if ( required_keyword( STARTFONT ) == false ) |
|
return false; |
|
info.has_global_dw = false; |
|
int find = FONTBOUNDINGBOX | DWIDTH | DEFAULT_CHAR; |
|
int stop = CHARS | STARTCHAR | ENCODING | BBX | BITMAP | ENDCHAR | ENDFONT; |
|
int res; |
|
while ( 1 ) |
|
{ |
|
res = find_keywords( find | stop ); |
|
if ( res & FONTBOUNDINGBOX ) |
|
{ |
|
in_ >> info.FBBx >> info.FBBy >> info.Xoff >> info.Yoff; |
|
if ( in_.fail() ) |
|
return false; |
|
find &= ~FONTBOUNDINGBOX; |
|
continue; |
|
} |
|
if ( res & DWIDTH ) |
|
{ |
|
in_ >> info.dwx0 >> info.dwy0; |
|
if ( in_.fail() ) |
|
return false; |
|
find &= ~DWIDTH; |
|
info.has_global_dw = true; |
|
continue; |
|
} |
|
if ( res & DEFAULT_CHAR ) |
|
{ |
|
in_ >> info.default_char; |
|
if ( in_.fail() ) |
|
return false; |
|
find &= ~DEFAULT_CHAR; |
|
continue; |
|
} |
|
if ( res & NO_KEYWORD ) |
|
return false; |
|
break; |
|
} |
|
if ( res != CHARS || ( find & FONTBOUNDINGBOX ) ) |
|
return false; |
|
return true; |
|
} |
|
int parse_glyph( char_info& info, unichar& enc ) |
|
{ |
|
info.has_dw = false; |
|
int e; |
|
int res; |
|
while ( 1 ) |
|
{ |
|
res = find_keywords( ENCODING ); |
|
if ( res != ENCODING ) |
|
return 0; |
|
in_ >> e; |
|
if ( in_.fail() ) |
|
return -1; |
|
if ( e >= static_cast<int>(enc) ) |
|
break; |
|
} |
|
int find = BBX | DWIDTH; |
|
int stop = STARTCHAR | ENCODING | BITMAP | ENDCHAR | ENDFONT; |
|
while ( 1 ) |
|
{ |
|
res = find_keywords( find | stop ); |
|
if ( res & BBX ) |
|
{ |
|
in_ >> info.BBw >> info.BBh >> info.BBxoff0x >> info.BByoff0y; |
|
if ( in_.fail() ) |
|
return -1; |
|
find &= ~BBX; |
|
continue; |
|
} |
|
if ( res & DWIDTH ) |
|
{ |
|
in_ >> info.dwx0 >> info.dwy0; |
|
if ( in_.fail() ) |
|
return -1; |
|
find &= ~DWIDTH; |
|
info.has_dw = true; |
|
continue; |
|
} |
|
if ( res & NO_KEYWORD ) |
|
return -1; |
|
break; |
|
} |
|
if ( res != BITMAP || ( find != NO_KEYWORD ) ) |
|
return -1; |
|
unsigned h = info.BBh; |
|
unsigned w = ( info.BBw + 7 ) / 8 * 2; |
|
info.bitmap.set_size( h, w ); |
|
for ( unsigned r = 0;r < h;r++ ) |
|
{ |
|
trim(); |
|
std::string str = ""; |
|
extract_hex(str); |
|
if(str.size() < w) |
|
return -1; |
|
for ( unsigned c = 0;c < w;c++ ) |
|
info.bitmap[r][c] = str[c]; |
|
} |
|
if ( in_.fail() ) |
|
return -1; |
|
if ( required_keyword( ENDCHAR ) == false ) |
|
return -1; |
|
enc = e; |
|
return 1; |
|
} |
|
private: |
|
map<std::string, int>::kernel_1a_c keyword_map; |
|
tokenizer::kernel_1a_c tokzr; |
|
std::istream& in_; |
|
void extract_hex(std::string& str) |
|
{ |
|
int type; |
|
std::string token; |
|
while ( 1 ) |
|
{ |
|
type = tokzr.peek_type(); |
|
if ( type == tokenizer::kernel_1a_c::IDENTIFIER || type == tokenizer::kernel_1a_c::NUMBER ) |
|
{ |
|
tokzr.get_token( type, token ); |
|
str += token; |
|
continue; |
|
} |
|
break; |
|
} |
|
} |
|
void trim() |
|
{ |
|
int type; |
|
std::string token; |
|
while ( 1 ) |
|
{ |
|
type = tokzr.peek_type(); |
|
if ( type == tokenizer::kernel_1a_c::WHITE_SPACE || type == tokenizer::kernel_1a_c::END_OF_LINE ) |
|
{ |
|
tokzr.get_token( type, token ); |
|
continue; |
|
} |
|
break; |
|
} |
|
} |
|
bool required_keyword( int kw ) |
|
{ |
|
int type; |
|
std::string token; |
|
while ( 1 ) |
|
{ |
|
tokzr.get_token( type, token ); |
|
if ( type == tokenizer::kernel_1a_c::WHITE_SPACE || type == tokenizer::kernel_1a_c::END_OF_LINE ) |
|
continue; |
|
if ( type != tokenizer::kernel_1a_c::IDENTIFIER || keyword_map.is_in_domain( token ) == false || ( keyword_map[token] & kw ) == 0 ) |
|
return false; |
|
break; |
|
} |
|
return true; |
|
} |
|
int find_keywords( int find ) |
|
{ |
|
int type; |
|
std::string token; |
|
while ( 1 ) |
|
{ |
|
tokzr.get_token( type, token ); |
|
if ( type == tokenizer::kernel_1a_c::END_OF_FILE ) |
|
return NO_KEYWORD; |
|
if ( type == tokenizer::kernel_1a_c::IDENTIFIER && keyword_map.is_in_domain( token ) == true ) |
|
{ |
|
int kw = keyword_map[token]; |
|
if ( kw & find ) |
|
return kw; |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bdf_font::bdf_font( |
|
long default_char_ |
|
) : |
|
default_char(0), |
|
is_initialized( false ), |
|
right_overflow_( 0 ), |
|
has_global_width( false ), |
|
specified_default_char( default_char_ ) |
|
{ |
|
|
|
gl.resize(1); |
|
} |
|
|
|
|
|
|
|
void bdf_font::adjust_metrics( |
|
) |
|
{ |
|
if ( is_initialized == false ) |
|
return; |
|
|
|
if ( gl[default_char].num_of_points() > 0 ) |
|
{ |
|
letter& g = gl[default_char]; |
|
fbb.set_top( g[0].y ); |
|
fbb.set_bottom( g[0].y ); |
|
fbb.set_left( g[0].x ); |
|
fbb.set_right( g[0].x ); |
|
} |
|
else |
|
{ |
|
|
|
|
|
fbb.set_top( 10000 ); |
|
fbb.set_bottom( -10000 ); |
|
fbb.set_left( 10000 ); |
|
fbb.set_right( -10000 ); |
|
} |
|
right_overflow_ = 0; |
|
for ( unichar n = 0; n < gl.size(); n++ ) |
|
{ |
|
letter& g = gl[n]; |
|
unsigned short nr_pts = g.num_of_points(); |
|
for ( unsigned short k = 0;k < nr_pts;k++ ) |
|
{ |
|
fbb.set_top( std::min( fbb.top(), (long)g[k].y ) ); |
|
fbb.set_left( std::min( fbb.left(), (long)g[k].x ) ); |
|
fbb.set_bottom( std::max( fbb.bottom(), (long)g[k].y ) ); |
|
fbb.set_right( std::max( fbb.right(), (long)g[k].x ) ); |
|
right_overflow_ = std::max( right_overflow_, (unsigned long)(g[k].x - g.width()) ); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
long bdf_font:: |
|
read_bdf_file( |
|
std::istream& in, |
|
unichar max_enc, |
|
unichar min_enc |
|
) |
|
{ |
|
using namespace bdf_font_helpers; |
|
|
|
bdf_parser parser( in ); |
|
bdf_parser::header_info hinfo; |
|
bdf_parser::char_info cinfo; |
|
|
|
gl.resize(max_enc+1); |
|
hinfo.default_char = - 1; |
|
if ( is_initialized == false || static_cast<std::streamoff>(in.tellg()) == std::ios::beg ) |
|
{ |
|
if ( parser.parse_header( hinfo ) == false ) |
|
return 0; |
|
} |
|
else |
|
{ |
|
|
|
hinfo.has_global_dw = has_global_width; |
|
hinfo.dwx0 = global_width; |
|
} |
|
int res; |
|
unichar nr_letters_added = 0; |
|
unsigned width; |
|
for ( unichar n = min_enc; n <= max_enc; n++ ) |
|
{ |
|
if ( in.eof() ) |
|
break; |
|
long pos = in.tellg(); |
|
res = parser.parse_glyph( cinfo, n ); |
|
if ( res < 0 ) |
|
return 0; |
|
if ( res == 0 ) |
|
continue; |
|
if ( n > max_enc ) |
|
{ |
|
in.seekg( pos ); |
|
break; |
|
} |
|
|
|
if ( cinfo.has_dw == false ) |
|
{ |
|
if ( hinfo.has_global_dw == false ) |
|
return 0; |
|
width = hinfo.dwx0; |
|
} |
|
else |
|
width = cinfo.dwx0; |
|
|
|
|
|
if ( bitmap_to_letter( cinfo.bitmap, n, width, cinfo.BBxoff0x, cinfo.BByoff0y ) == false ) |
|
return 0; |
|
nr_letters_added++; |
|
|
|
if ( is_initialized == false ) |
|
{ |
|
|
|
fbb.set_top( -( hinfo.Yoff + hinfo.FBBy - 1 ) ); |
|
fbb.set_bottom( -hinfo.Yoff ); |
|
fbb.set_left( hinfo.Xoff ); |
|
fbb.set_right( hinfo.Xoff + hinfo.FBBx - 1 ); |
|
|
|
right_overflow_ = 0; |
|
|
|
default_char = n; |
|
|
|
has_global_width = hinfo.has_global_dw; |
|
if ( has_global_width ) |
|
global_width = hinfo.dwx0; |
|
|
|
if ( specified_default_char < 0 && hinfo.default_char >= 0 ) |
|
specified_default_char = hinfo.default_char; |
|
|
|
is_initialized = true; |
|
} |
|
} |
|
if ( is_initialized == false ) |
|
return 0; |
|
|
|
if ( specified_default_char >= 0 ) |
|
default_char = specified_default_char; |
|
|
|
else |
|
default_char = 0; |
|
|
|
return nr_letters_added; |
|
} |
|
|
|
|
|
|
|
bool bdf_font:: |
|
bitmap_to_letter( |
|
array2d<char>& bitmap, |
|
unichar enc, |
|
unsigned long width, |
|
int x_offset, |
|
int y_offset |
|
) |
|
{ |
|
unsigned nr_points = 0; |
|
bitmap.reset(); |
|
while ( bitmap.move_next() ) |
|
{ |
|
unsigned char ch = bitmap.element(); |
|
if ( ch > '9' ) |
|
ch -= 'A' - '9' - 1; |
|
ch -= '0'; |
|
if ( ch > 0xF ) |
|
return false; |
|
bitmap.element() = ch; |
|
if ( ch & 8 ) |
|
nr_points++; |
|
if ( ch & 4 ) |
|
nr_points++; |
|
if ( ch & 2 ) |
|
nr_points++; |
|
if ( ch & 1 ) |
|
nr_points++; |
|
} |
|
|
|
letter( width, nr_points ).swap(gl[enc]); |
|
|
|
unsigned index = 0; |
|
for ( int r = 0;r < bitmap.nr();r++ ) |
|
{ |
|
for ( int c = 0;c < bitmap.nc();c++ ) |
|
{ |
|
int x = x_offset + c * 4; |
|
int y = -( y_offset + bitmap.nr() - r - 1 ); |
|
char ch = bitmap[r][c]; |
|
letter& glyph = gl[enc]; |
|
if ( ch & 8 ) |
|
{ |
|
glyph[index] = letter::point( x, y ); |
|
right_overflow_ = std::max( right_overflow_, x - width ); |
|
index++; |
|
} |
|
if ( ch & 4 ) |
|
{ |
|
glyph[index] = letter::point( x + 1, y ); |
|
right_overflow_ = std::max( right_overflow_, x + 1 - width ); |
|
index++; |
|
} |
|
if ( ch & 2 ) |
|
{ |
|
glyph[index] = letter::point( x + 2, y ); |
|
right_overflow_ = std::max( right_overflow_, x + 2 - width ); |
|
index++; |
|
} |
|
if ( ch & 1 ) |
|
{ |
|
glyph[index] = letter::point( x + 3, y ); |
|
right_overflow_ = std::max( right_overflow_, x + 3 - width ); |
|
index++; |
|
} |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
#ifndef DLIB_NO_GUI_SUPPORT |
|
|
|
|
|
const std::shared_ptr<font> get_native_font ( |
|
) |
|
{ |
|
return nativefont::native_font::get_font(); |
|
} |
|
|
|
|
|
#endif |
|
|
|
} |
|
|
|
#endif |
|
|
|
|