AshanGimhana's picture
Upload folder using huggingface_hub
9375c9a verified
// Copyright (C) 2005 Davis E. King ([email protected]), and Nils Labugt, Keita Mochizuki
// License: Boost Software License See LICENSE.txt for the full license.
#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;
/*
SOURCE BDF FILE (helvR12.bdf) COMMENTS
COMMENT $XConsortium: helvR12.bdf,v 1.15 95/01/26 18:02:58 gildea Exp $
COMMENT $Id: helvR12.bdf,v 1.26 2004-11-28 20:08:46+00 mgk25 Rel $
COMMENT
COMMENT +
COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated.
COMMENT Copyright 1988, 1994 Digital Equipment Corporation.
COMMENT
COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be
COMMENT registered in certain jurisdictions.
COMMENT Permission to use these trademarks is hereby granted only in
COMMENT association with the images described in this file.
COMMENT
COMMENT Permission to use, copy, modify, distribute and sell this software
COMMENT and its documentation for any purpose and without fee is hereby
COMMENT granted, provided that the above copyright notices appear in all
COMMENT copies and that both those copyright notices and this permission
COMMENT notice appear in supporting documentation, and that the names of
COMMENT Adobe Systems and Digital Equipment Corporation not be used in
COMMENT advertising or publicity pertaining to distribution of the software
COMMENT without specific, written prior permission. Adobe Systems and
COMMENT Digital Equipment Corporation make no representations about the
COMMENT suitability of this software for any purpose. It is provided "as
COMMENT is" without express or implied warranty.
COMMENT -
*/
// The base64 encoded data we want to decode and return.
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==";
// Put the data into the istream sin
sin.str(sout.str());
sout.str("");
// Decode the base64 text into its compressed binary form
base64_coder.decode(sin,sout);
sin.clear();
sin.str(sout.str());
sout.str("");
// Decompress the data into its original form
compressor.decompress(sin,sout);
// Return the decoded and decompressed data
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; // parse_error: required keyword missing
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; // parse_error
find &= ~FONTBOUNDINGBOX;
continue;
}
if ( res & DWIDTH )
{
in_ >> info.dwx0 >> info.dwy0;
if ( in_.fail() )
return false; // parse_error
find &= ~DWIDTH;
info.has_global_dw = true;
continue;
}
if ( res & DEFAULT_CHAR )
{
in_ >> info.default_char;
if ( in_.fail() )
return false; // parse_error
find &= ~DEFAULT_CHAR;
continue;
}
if ( res & NO_KEYWORD )
return false; // parse_error: unexpected EOF
break;
}
if ( res != CHARS || ( find & FONTBOUNDINGBOX ) )
return false; // parse_error: required keyword missing or unexpeced keyword
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; // no more glyphs
in_ >> e;
if ( in_.fail() )
return -1; // parse_error
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; // parse_error
find &= ~BBX;
continue;
}
if ( res & DWIDTH )
{
in_ >> info.dwx0 >> info.dwy0;
if ( in_.fail() )
return -1; // parse_error
find &= ~DWIDTH;
info.has_dw = true;
continue;
}
if ( res & NO_KEYWORD )
return -1; // parse_error: unexpected EOF
break;
}
if ( res != BITMAP || ( find != NO_KEYWORD ) )
return -1; // parse_error: required keyword missing or unexpeced keyword
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; // parse_error
for ( unsigned c = 0;c < w;c++ )
info.bitmap[r][c] = str[c];
}
if ( in_.fail() )
return -1; // parse_error
if ( required_keyword( ENDCHAR ) == false )
return -1; // parse_error: required keyword missing
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 functions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
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_ )
{
// make sure gl contains at least one letter
gl.resize(1);
}
// ----------------------------------------------------------------------------------------
void bdf_font::adjust_metrics(
)
{
if ( is_initialized == false )
return;
// set starting values for fbb
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
{
// ok, the default char was a space
// let's just choose some safe arbitrary values then...
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()) ); // superfluous?
}
}
}
// ----------------------------------------------------------------------------------------
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; // parse_error: invalid or missing header
}
else
{
// not start of file, so use values from previous read.
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; // parse_error
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; // neither width info for the glyph, nor for the font as a whole (monospace).
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 )
{
// Bonding rectangle for the font.
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 );
// We need to compute this after all the glyphs are loaded.
right_overflow_ = 0;
// set this to something valid now, just in case.
default_char = n;
// Save any global width in case we later read from the same file.
has_global_width = hinfo.has_global_dw;
if ( has_global_width )
global_width = hinfo.dwx0;
// dont override value specified in the constructor with value specified in the file
if ( specified_default_char < 0 && hinfo.default_char >= 0 )
specified_default_char = hinfo.default_char;
is_initialized = true;
}
}
if ( is_initialized == false )
return 0; // Not a single glyph was found within the specified range.
if ( specified_default_char >= 0 )
default_char = specified_default_char;
// no default char specified, try find something sane.
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; // parse error: invalid hex digit
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 // DLIB_FONTs_CPP_