AshanGimhana's picture
Upload folder using huggingface_hub
9375c9a verified
// Copyright (C) 2006 Keita Mochizuki
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_IGG_FONT_RENDERER_H_
#define DLIB_IGG_FONT_RENDERER_H_
#ifndef DLIB_NO_GUI_SUPPORT
#include "../platform.h"
#include "../gui_widgets/fonts.h"
#include "../unicode.h"
#include "../uintn.h"
#include <map>
#include <memory>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <locale.h>
#if defined(WIN32)
#include <windows.h>
#include <mbstring.h>
#elif defined(DLIB_POSIX)
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xlocale.h>
#endif
namespace nativefont
{
// ----------------------------------------------------------------------------------------
namespace font_renderer
{
typedef dlib::uint8 byte;
#ifdef WIN32
template <typename T> struct input2native_trait{
};
template <> struct input2native_trait<char>{
typedef char type_t;
};
template <> struct input2native_trait<wchar_t>{
typedef wchar_t type_t;
};
template <> struct input2native_trait<dlib::unichar>{
typedef wchar_t type_t;
};
#endif
// T : N : sizeof_source_type
template <int N> struct size2inner_trait{
};
template <> struct size2inner_trait<1>{
typedef char type_t;
};
template <> struct size2inner_trait<2>{
typedef dlib::uint16 type_t;
};
template <> struct size2inner_trait<4>{
typedef dlib::unichar type_t;
};
// ----------------------------------------------------------------------------------------
template <int N> struct create_helper{ };
template <> struct create_helper<1>{
typedef char type_t;
type_t *istr;
int len;
create_helper(char *str){
len = (int)strlen(str);
istr = str;
}
~create_helper(){}
};
template <> struct create_helper<2>{
typedef wchar_t type_t;
type_t *istr;
bool allocated;
int len;
create_helper(wchar_t *str){
allocated = false;
len = (int)wcslen(str);
istr = str;
}
create_helper(dlib::unichar *str){
allocated = true;
len = 0;
int unicount = 0;
dlib::unichar *p = str;
while(*p){
if (*p > 0xffff){
len += 2;
}else{
len++;
}
unicount++;
p++;
}
istr = new wchar_t[len+1];
for (int i = 0, wi = 0; i < unicount; ++i){
dlib::unichar high, low;
if (str[i] > 0xffff){
dlib::unichar_to_surrogate_pair(str[i], high, low);
istr[wi] = (wchar_t)high, istr[wi+1] = (wchar_t)low;
wi += 2;
}else{
istr[wi] = (wchar_t)str[i];
wi += 1;
}
}
istr[len] = L'\0';
}
~create_helper(){
if (allocated) delete[] istr;
}
};
template <> struct create_helper<4>{
typedef wchar_t type_t;
type_t *istr;
int len;
create_helper(dlib::unichar *str){
len = (int)wcslen((wchar_t *)str);
istr = (type_t *)str;
}
~create_helper(){}
};
// ----------------------------------------------------------------------------------------
class font_renderer{
public:
struct rgb_type{
byte r, g, b;
rgb_type() : r(0), g(0), b(0){};
rgb_type(byte r_, byte g_, byte b_) : r(r_), g(g_), b(b_){};
};
private:
byte *image;
int width, height;
void destroy(){
width = height = 0;
delete image;
image = 0;
}
struct vals_internal{
int width, height;
#ifdef WIN32
COLORREF rgb2RGB(rgb_type &rgb){
return RGB(rgb.r, rgb.g, rgb.b);
}
HBITMAP hBmp, hBmpOld;
HDC hDCBmp;
BYTE *pixelint;
HFONT hFont, hFontOld;
HBRUSH hBrush;
int pix_width_prev, pix_height_prev;
bool first;
int ascender, descender;
int height_prev;
char attribute_prev;
template <typename T> void create(T *str, int height_want, bool italic, bool bold, bool fixed, rgb_type &background, rgb_type &foreground){
struct inner{
inline static BOOL GetTextExtentPoint32(HDC hDC, LPCSTR str, int len, LPSIZE lpsize){
return ::GetTextExtentPoint32A(hDC, str, len, lpsize);
}
inline static BOOL GetTextExtentPoint32(HDC hDC, LPCWSTR str, int len, LPSIZE lpsize){
return ::GetTextExtentPoint32W(hDC, str, len, lpsize);
}
inline static BOOL TextOut(HDC hDC, int nxstart, int nystart, LPCSTR str, int cbstr){
return ::TextOutA(hDC, nxstart, nystart, str, cbstr);
}
inline static BOOL TextOut(HDC hDC, int nxstart, int nystart, LPCWSTR str, int cbstr){
return ::TextOutW(hDC, nxstart, nystart, str, cbstr);
}
};
create_helper<sizeof(typename input2native_trait<T>::type_t)> ch(str);
if (hDCBmp == NULL){
HWND hWnd = GetDesktopWindow();
HDC hDC = GetDC(hWnd);
hDCBmp = CreateCompatibleDC(hDC);
ReleaseDC(hWnd, hDC);
}
SetTextColor(hDCBmp, rgb2RGB(foreground));
SetBkColor(hDCBmp, rgb2RGB(background));
char attribute = (italic ? 1 : 0) | (bold ? 2 : 0) | (fixed ? 4 : 0);
if (!hFont || height_prev != height || attribute != attribute_prev){
attribute_prev = attribute;
height_prev = height_want;
if (hFont){
SelectObject(hDCBmp, hFontOld);
DeleteObject(hFont);
}
hFont = CreateFont(height_want, 0, 0, 0, bold ? FW_BOLD : FW_DONTCARE, italic ? TRUE : FALSE,
FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
fixed ? (FIXED_PITCH | FF_DONTCARE) : (VARIABLE_PITCH | FF_DONTCARE), NULL);
hFontOld = (HFONT)SelectObject(hDCBmp, hFont);
}
{
SIZE sz;
inner::GetTextExtentPoint32(hDCBmp, ch.istr, ch.len, &sz);
width = ((sz.cx + 3) / 4) * 4;
height = sz.cy;
}
if (pix_width_prev < width || pix_height_prev < height){
if (hBmp){
SelectObject(hDCBmp, hBmpOld);
DeleteObject(hBmp);
}
pix_width_prev = width * 2;
pix_height_prev = height * 2;
BITMAPINFO bi;
ZeroMemory(&bi, sizeof(bi));
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biBitCount = 24;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biWidth = pix_width_prev;
bi.bmiHeader.biHeight = -pix_height_prev;
hBmp = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (void **)&pixelint, NULL, 0);
hBmpOld = (HBITMAP)SelectObject(hDCBmp, hBmp);
}
{
HBRUSH hBrush = CreateSolidBrush(rgb2RGB(background));
RECT rc;
rc.left = rc.top = 0;
rc.right = pix_width_prev;
rc.bottom = pix_height_prev;
FillRect(hDCBmp, &rc, hBrush);
}
inner::TextOut(hDCBmp, 0, 0, ch.istr, ch.len);
TEXTMETRICW tm;
GetTextMetricsW(hDCBmp,&tm);
ascender = tm.tmAscent;
descender = tm.tmDescent;
}
template <typename T> vals_internal(T *str, int height_want, bool italic = false,
bool bold = false, bool fixed = false, rgb_type background = rgb_type(), rgb_type foreground = rgb_type()){
first = true;
hFont = NULL;
hDCBmp = 0;
hBmpOld = 0;
hBmp = 0;
hDCBmp = 0;
pixelint = 0;
pix_width_prev = pix_height_prev = 0;
height_prev = -1;
attribute_prev = 0;
create(str, height_want, italic, bold, fixed, background, foreground);
first = false;
}
inline int get_ascender(){
return ascender;
}
inline int get_descender(){
return descender;
}
inline void get_pixel(int x, int y, byte &r, byte &g, byte &b){
byte *p = pixelint + (y * pix_width_prev + x) * 3;
r = *(p+2), g = *(p+1), b = *p;
}
void destroy(){
SelectObject(hDCBmp, hBmpOld);
DeleteObject(hBmp);
SelectObject(hDCBmp, hFontOld);
DeleteObject(hFont);
DeleteDC(hDCBmp);
hFont = NULL;
hDCBmp = 0;
hBmpOld = 0;
hBmp = 0;
hDCBmp = 0;
pixelint = 0;
}
~vals_internal(){
destroy();
}
#elif defined(DLIB_POSIX)
XImage *ximg;
Display *d;
GC gc;
XFontSet fs;
Pixmap pix;
Colormap cmap;
int ascender, descender;
int pix_width_prev, pix_height_prev;
char fontset_prev[256];
unsigned long rgb2color(rgb_type col, Display *d, Colormap &cmap){
XColor xcol;
xcol.red = col.r * 257;
xcol.green = col.g * 257;
xcol.blue = col.b * 257;
XAllocColor(d, cmap, &xcol);
return xcol.pixel;
}
template <typename T> void create(T *str, int height_want, bool italic, bool bold, bool fixed, rgb_type background, rgb_type foreground){
struct inner{
inline static int XTextExtents (XFontSet fs, char *str, int len, XRectangle *ink, XRectangle *logical){
return XmbTextExtents(fs, str, len, ink, logical);
}
inline static int XTextExtents (XFontSet fs, wchar_t *str, int len, XRectangle *ink, XRectangle *logical){
return XwcTextExtents(fs, str, len, ink, logical);
}
inline static void XDrawString(Display *d, Window w, XFontSet fs, GC gc, int x, int y, char *str, int num_bytes){
XmbDrawString(d, w, fs, gc, x, y, str, num_bytes);
}
inline static void XDrawString(Display *d, Window w, XFontSet fs, GC gc, int x, int y, wchar_t *str, int num_bytes){
XwcDrawString(d, w, fs, gc, x, y, str, num_bytes);
}
};
create_helper<sizeof(T)> ch((typename size2inner_trait<sizeof(T)>::type_t *)str);
setlocale(LC_CTYPE, "");
if (d == NULL){
d = XOpenDisplay(NULL);
if (d == 0)
{
d = XOpenDisplay(":0.0");
if (d == 0)
{
throw dlib::gui_error("Unable to connect to the X display.");
}
}
cmap = DefaultColormap(d, DefaultScreen(d));
}
char fontset[256];
{
char *p = fontset;
p += sprintf(fontset, "-*-*-%s-%c-normal--%d-*-*-*-%c",
bold ? "bold" : "medium", italic ? 'i' : 'r', height_want, fixed ? 'c' : 'p');
if (fixed){
sprintf(p, ",-*-*-%s-%c-normal--%d-*-*-*-m",
bold ? "bold" : "medium", italic ? 'i' : 'r', height_want);
}
}
bool equal_font;
if (strcmp(fontset, fontset_prev) == 0){
equal_font = true;
}else{
equal_font = false;
strcpy(fontset_prev, fontset);
}
char **mlist;
int mcount;
char *def_str;
if (!equal_font){
if (fs){
XFreeFontSet(d, fs);
}
fs = XCreateFontSet(d, fontset, &mlist, &mcount, &def_str);
if (fs == NULL)
throw dlib::gui_error("gui_error: XCreateFontSet() failure");
XFontSetExtents *extent;
extent = XExtentsOfFontSet(fs);
ascender = -extent->max_logical_extent.y;
descender = extent->max_logical_extent.height - ascender;
XFreeStringList(mlist);
}
XRectangle ink, logical;
inner::XTextExtents (fs, ch.istr, ch.len, &ink, &logical);
width = logical.width;
height = height_want;
if (pix == None || pix_width_prev < width || pix_height_prev < height){
if (pix != None){
XFreeGC(d, gc);
XFreePixmap(d, pix);
}
pix_width_prev = width * 2;
pix_height_prev = height * 2;
pix = XCreatePixmap(d, DefaultRootWindow(d), pix_width_prev, pix_height_prev, XDefaultDepth(d, DefaultScreen(d)));
gc = XCreateGC(d, pix, 0, NULL);
}
unsigned long backcolor = rgb2color(background, d, cmap);
XSetForeground(d, gc, backcolor);
XSetBackground(d, gc, backcolor);
XFillRectangle(d, pix, gc, 0, 0, width, height);
XSetForeground(d, gc, rgb2color(foreground, d, cmap));
inner::XDrawString(d, pix, fs, gc, 0, ascender, ch.istr, ch.len);
if (ximg) XDestroyImage(ximg);
ximg = XGetImage(d, pix, 0, 0, width, height, AllPlanes, ZPixmap );
}
template <typename T> vals_internal(T *str, int height_want, bool italic = false,
bool bold = false, bool fixed = false, rgb_type background = rgb_type(), rgb_type foreground = rgb_type()){
fontset_prev[0] = '\0';
ximg = NULL;
d = NULL;
pix = None;
fs = NULL;
ascender = descender = -1;
pix_width_prev = pix_height_prev = -1;
create(str, height_want, italic, bold, fixed, background, foreground);
}
inline int get_ascender(){
return ascender;
}
inline int get_descender(){
return descender;
}
std::map<unsigned long,rgb_type> col2rgb;
rgb_type color2rgb(unsigned long color, Display *d, Colormap &cmap){
if (col2rgb.count(color)){
return col2rgb[color];
}else{
XColor xcol;
xcol.pixel = color;
XQueryColor(d, cmap, &xcol);
rgb_type rgb_((byte)(xcol.red/257), (byte)(xcol.green/257), (byte)(xcol.blue/257));
col2rgb[color] = rgb_;
return rgb_;
}
}
inline void get_pixel(int x, int y, byte &r, byte &g, byte &b){
rgb_type c = color2rgb(XGetPixel(ximg,x,y), d, cmap);
r = c.r, g = c.g, b = c.b;
}
~vals_internal(){
XDestroyImage(ximg);
XFreeGC(d, gc);
XFreeFontSet(d, fs);
XFreePixmap(d, pix);
XCloseDisplay(d);
}
#endif
};
struct image_size_setter{
void operator()(int&, int&){
}
};
int ascender, descender;
vals_internal *vi;
public:
font_renderer() : image(0), width(0), height(0){
ascender = descender = 0;
vi = NULL;
}
template<typename T> font_renderer(T *str, int height_want, bool italic = false, bool bold = false, bool fixed = false, rgb_type background = rgb_type(0,0,0), rgb_type foreground = rgb_type(255,255,255)){
render(str, height_want, italic, bold, fixed, background, foreground);
}
template<typename T> void render(T *str, int height_want,
bool italic = false, bool bold = false, bool fixed = false,
rgb_type background = rgb_type(0,0,0), rgb_type foreground = rgb_type(255,255,255)){
if (vi == NULL){
vi = new vals_internal(str, height_want, italic, bold, fixed, background, foreground);
}else{
vi->create(str, height_want, italic, bold, fixed, background, foreground);
}
width = vi->width, height = vi->height;
image = new byte[width * height * 3];
ascender = vi->get_ascender();
descender = vi->get_descender();
int h = height, w = width;
for (int j = 0, i3 = 0; j < h; ++j){
for (int i = 0; i < w; ++i, i3 += 3){
vi->get_pixel(i, j, image[i3], image[i3+1], image[i3+2]);
}
}
}
~font_renderer(){
if (vi) delete vi;
destroy();
}
int get_width(){
return width;
}
int get_height(){
return height;
}
inline int get_ascender(){
return ascender;
}
inline int get_descender(){
return descender;
}
const byte *get_image(){
return image;
}
};
}
// ----------------------------------------------------------------------------------------
class native_font : public dlib::font
{
unsigned long ascender_;
native_font(){
setlocale(LC_CTYPE, "");
ascender_ = 0;
get_letter((int)('x'));
}
typedef std::map<int,dlib::letter *> letters_map_type;
letters_map_type letters;
font_renderer::font_renderer fl;
public:
virtual ~native_font()
{
// delete all the letter objects we have in our letters map
letters_map_type::iterator i;
for (i = letters.begin(); i != letters.end(); ++i)
{
delete i->second;
}
}
virtual bool has_character (
dlib::unichar ch
)const{
return (*this)[ch].width() > 0;
}
static const std::shared_ptr<font>& get_font (
)
{
static std::shared_ptr<font> f(new native_font);
return f;
}
virtual const dlib::letter& operator[] (dlib::unichar ch) const{
return (const_cast<native_font *>(this))->get_letter(ch);
}
dlib::letter& get_letter (
dlib::unichar ch
){
if (letters.count(ch)){
dlib::letter *l = letters.find(ch)->second;
return *l;
}
dlib::unichar c[2];
c[0] = ch;
c[1] = 0;
fl.render(c, height(),false,false,true);
if (ascender_ == 0){
ascender_ = fl.get_ascender();
}
std::vector<dlib::letter::point> v;
const font_renderer::byte *bp = fl.get_image();
for (int j = 0; j < fl.get_height(); ++j){
for (int i = 0; i < fl.get_width(); ++i, bp += 3){
if (*bp){
v.push_back(dlib::letter::point(i,j-ascender()+1));
}
}
}
dlib::letter *l = new dlib::letter(fl.get_width(), (unsigned long)v.size());
letters.insert(std::make_pair(ch,l));
for (int i = 0; i < (int)v.size(); ++i){
(*l)[i] = v.at(i);
}
return *l;
}
virtual unsigned long height (
) const { return 12; }
virtual unsigned long ascender (
) const { return ascender_; }
virtual unsigned long left_overflow (
) const { return 1; }
virtual unsigned long right_overflow (
) const { return 2; }
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_NO_GUI_SUPPORT
#endif // DLIB_IGG_FONT_RENDERER_H_