718 lines
17 KiB
C
718 lines
17 KiB
C
|
/** \file
|
||
|
* \brief GL Font functions.
|
||
|
*
|
||
|
* See Copyright Notice in "iup.h"
|
||
|
*/
|
||
|
|
||
|
#ifdef WIN32
|
||
|
#include <windows.h>
|
||
|
#else
|
||
|
#include <iconv.h>
|
||
|
#endif
|
||
|
|
||
|
#include <FTGL/ftgl.h>
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#include "iup.h"
|
||
|
#include "iupgl.h"
|
||
|
|
||
|
#include "iup_assert.h"
|
||
|
#include "iup_object.h"
|
||
|
#include "iup_attrib.h"
|
||
|
#include "iup_str.h"
|
||
|
#include "iup_array.h"
|
||
|
#include "iup_drvfont.h"
|
||
|
|
||
|
#include "iup_glcontrols.h"
|
||
|
#include "iup_glfont.h"
|
||
|
|
||
|
|
||
|
typedef struct _IglFont
|
||
|
{
|
||
|
char filename[10240];
|
||
|
int size;
|
||
|
FTGLfont* ftgl_font;
|
||
|
int charwidth, charheight;
|
||
|
} IglFont;
|
||
|
|
||
|
|
||
|
static char* gl_utf8_buffer = NULL;
|
||
|
static int gl_utf8_buffer_len = 0;
|
||
|
|
||
|
|
||
|
#ifdef WIN32
|
||
|
typedef char regName[MAX_PATH];
|
||
|
static regName* win_fonts = NULL;
|
||
|
static int win_fonts_count = 0;
|
||
|
|
||
|
static int iCompareStr(const void *a, const void *b)
|
||
|
{
|
||
|
const regName*aa = a;
|
||
|
const regName*bb = b;
|
||
|
return strcmp(*aa, *bb);
|
||
|
}
|
||
|
|
||
|
static void winInitFontNames(void)
|
||
|
{
|
||
|
const CHAR* subkey = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
|
||
|
HKEY hkey = NULL;
|
||
|
DWORD dwIndex = 0;
|
||
|
LONG ret;
|
||
|
DWORD dwValuesCount, dwValueSize;
|
||
|
|
||
|
ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, subkey, 0, KEY_READ, &hkey);
|
||
|
if (ret != ERROR_SUCCESS)
|
||
|
return;
|
||
|
|
||
|
ret = RegQueryInfoKey(hkey, NULL, NULL, NULL, NULL, NULL, NULL,
|
||
|
&dwValuesCount, NULL, NULL, NULL, NULL);
|
||
|
if (ret != ERROR_SUCCESS)
|
||
|
return;
|
||
|
|
||
|
win_fonts_count = (int)dwValuesCount;
|
||
|
win_fonts = malloc(sizeof(regName) * win_fonts_count);
|
||
|
|
||
|
for (dwIndex = 0; dwIndex < dwValuesCount; dwIndex++)
|
||
|
{
|
||
|
dwValueSize = MAX_PATH - 1;
|
||
|
ret = RegEnumValueA(hkey, dwIndex, win_fonts[dwIndex], &dwValueSize, NULL, NULL, NULL, NULL);
|
||
|
if (ret != ERROR_SUCCESS)
|
||
|
{
|
||
|
win_fonts_count = (int)dwIndex;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
qsort(win_fonts, win_fonts_count, sizeof(regName), iCompareStr);
|
||
|
|
||
|
RegCloseKey(hkey);
|
||
|
}
|
||
|
|
||
|
static int winReadStringKey(HKEY base_key, const char* subkey, const char* value_name, char* value)
|
||
|
{
|
||
|
HKEY key;
|
||
|
DWORD max_size = 1024;
|
||
|
|
||
|
if (RegOpenKeyExA(base_key, subkey, 0, KEY_READ, &key) != ERROR_SUCCESS)
|
||
|
return 0;
|
||
|
|
||
|
if (RegQueryValueExA(key, value_name, NULL, NULL, (LPBYTE)value, &max_size) != ERROR_SUCCESS)
|
||
|
{
|
||
|
RegCloseKey(key);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
RegCloseKey(key);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static char* winGetFontDir(void)
|
||
|
{
|
||
|
static char font_dir[1024];
|
||
|
if (!winReadStringKey(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Fonts", font_dir))
|
||
|
return "";
|
||
|
else
|
||
|
return font_dir;
|
||
|
}
|
||
|
|
||
|
static int iGLGetFontFilenameFromSystem(const char *font_name, int is_bold, int is_italic, char* fileName)
|
||
|
{
|
||
|
CHAR szData[1024];
|
||
|
const CHAR* subkey = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
|
||
|
char localFontName[MAX_PATH];
|
||
|
int i;
|
||
|
|
||
|
if (iupStrEqualNoCase(font_name, "Courier") || iupStrEqualNoCase(font_name, "Monospace"))
|
||
|
font_name = "Courier New";
|
||
|
else if (iupStrEqualNoCase(font_name, "Times") || iupStrEqualNoCase(font_name, "Serif"))
|
||
|
font_name = "Times New Roman";
|
||
|
else if (iupStrEqualNoCase(font_name, "Helvetica") || iupStrEqualNoCase(font_name, "Sans"))
|
||
|
font_name = "Arial";
|
||
|
|
||
|
strcpy(localFontName, font_name);
|
||
|
|
||
|
if (is_bold)
|
||
|
strcat(localFontName, " Bold");
|
||
|
|
||
|
if (is_italic)
|
||
|
strcat(localFontName, " Italic");
|
||
|
|
||
|
for (i = 0; i < win_fonts_count; i++)
|
||
|
{
|
||
|
if (iupStrEqualNoCasePartial(win_fonts[i], localFontName))
|
||
|
{
|
||
|
if (winReadStringKey(HKEY_LOCAL_MACHINE, subkey, win_fonts[i], szData))
|
||
|
{
|
||
|
/* szData already includes file extension */
|
||
|
sprintf(fileName, "%s\\%s", winGetFontDir(), szData);
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
#else
|
||
|
#ifndef NO_FONTCONFIG
|
||
|
#include <fontconfig/fontconfig.h>
|
||
|
|
||
|
static int iGLGetFontFilenameFromSystem(const char *font_name, int is_bold, int is_italic, char* fileName)
|
||
|
{
|
||
|
char styles[4][20];
|
||
|
int style_size;
|
||
|
FcObjectSet *os = 0;
|
||
|
FcFontSet *fs;
|
||
|
FcPattern *pat;
|
||
|
int bResult = 0;
|
||
|
|
||
|
/* Use "fc-match monospace|sans|serif" in Lunux to find a match */
|
||
|
if (iupStrEqualNoCase(font_name, "Courier") || iupStrEqualNoCase(font_name, "Courier New") || iupStrEqualNoCase(font_name, "Monospace"))
|
||
|
font_name = "DejaVu Sans Mono";
|
||
|
else if (iupStrEqualNoCase(font_name, "Times") || iupStrEqualNoCase(font_name, "Times New Roman") || iupStrEqualNoCase(font_name, "Serif"))
|
||
|
font_name = "DejaVu Serif";
|
||
|
else if (iupStrEqualNoCase(font_name, "Helvetica") || iupStrEqualNoCase(font_name, "Arial") || iupStrEqualNoCase(font_name, "Sans"))
|
||
|
font_name = "DejaVu Sans";
|
||
|
|
||
|
if (is_bold && is_italic)
|
||
|
{
|
||
|
strcpy(styles[0], "BoldItalic");
|
||
|
strcpy(styles[1], "Bold Italic");
|
||
|
strcpy(styles[2], "Bold Oblique");
|
||
|
strcpy(styles[3], "BoldOblique");
|
||
|
style_size = 4;
|
||
|
}
|
||
|
else if (is_bold)
|
||
|
{
|
||
|
strcpy(styles[0], "Bold");
|
||
|
style_size = 1;
|
||
|
}
|
||
|
else if (is_italic)
|
||
|
{
|
||
|
strcpy(styles[0], "Italic");
|
||
|
strcpy(styles[1], "Oblique");
|
||
|
style_size = 2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
strcpy(styles[0], "Regular");
|
||
|
strcpy(styles[1], "Normal");
|
||
|
strcpy(styles[2], "Medium");
|
||
|
strcpy(styles[3], "Book");
|
||
|
style_size = 4;
|
||
|
}
|
||
|
|
||
|
pat = FcPatternCreate();
|
||
|
os = FcObjectSetBuild(FC_FAMILY, FC_FILE, FC_STYLE, NULL);
|
||
|
fs = FcFontList(NULL, pat, os);
|
||
|
if (pat)
|
||
|
FcPatternDestroy(pat);
|
||
|
|
||
|
if (fs)
|
||
|
{
|
||
|
int j, s;
|
||
|
|
||
|
for (j = 0; j < fs->nfont; j++)
|
||
|
{
|
||
|
FcChar8 *family;
|
||
|
|
||
|
FcPatternGetString(fs->fonts[j], FC_FAMILY, 0, &family);
|
||
|
|
||
|
if (iupStrEqualNoCase((char*)family, font_name))
|
||
|
{
|
||
|
FcChar8 *file;
|
||
|
FcChar8 *style;
|
||
|
|
||
|
FcPatternGetString(fs->fonts[j], FC_FILE, 0, &file);
|
||
|
FcPatternGetString(fs->fonts[j], FC_STYLE, 0, &style);
|
||
|
|
||
|
for (s = 0; s < style_size; s++)
|
||
|
{
|
||
|
if (iupStrEqualNoCase(styles[s], (char*)style))
|
||
|
{
|
||
|
strcpy(fileName, (char*)file);
|
||
|
FcFontSetDestroy(fs);
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* set a value to be used if the style is not found.
|
||
|
the last family found will be used */
|
||
|
strcpy(fileName, (char*)file);
|
||
|
bResult = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FcFontSetDestroy(fs);
|
||
|
}
|
||
|
|
||
|
return bResult;
|
||
|
}
|
||
|
#else
|
||
|
static int iGLGetFontFilenameFromSystem(const char *font_name, int is_bold, int is_italic, char* fileName)
|
||
|
{
|
||
|
(void)font_name;
|
||
|
(void)is_bold;
|
||
|
(void)is_italic;
|
||
|
(void)fileName;
|
||
|
return 0;
|
||
|
}
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
static int iGLGetFontFilenameFromTypeface(const char* path, const char* typeface, const char* ext, char* filename)
|
||
|
{
|
||
|
FILE *file;
|
||
|
|
||
|
/* current directory */
|
||
|
sprintf(filename, "%s.%s", typeface, ext);
|
||
|
file = fopen(filename, "r");
|
||
|
|
||
|
if (!file)
|
||
|
{
|
||
|
/* path from the environment */
|
||
|
if (path)
|
||
|
{
|
||
|
sprintf(filename, "%s/%s.%s", path, typeface, ext);
|
||
|
file = fopen(filename, "r");
|
||
|
}
|
||
|
|
||
|
if (!file)
|
||
|
{
|
||
|
#ifdef WIN32
|
||
|
/* Windows Font folder */
|
||
|
sprintf(filename, "%s\\%s.%s", winGetFontDir(), typeface, ext);
|
||
|
file = fopen(filename, "r");
|
||
|
|
||
|
if (!file)
|
||
|
return 0;
|
||
|
#else
|
||
|
return 0;
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fclose(file);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static char* iGLGetFontNameTex(const char* typeface)
|
||
|
{
|
||
|
if (iupStrEqualNoCase(typeface, "sans") ||
|
||
|
iupStrEqualNoCase(typeface, "helvetica") ||
|
||
|
iupStrEqualNoCase(typeface, "arial"))
|
||
|
return "heros";
|
||
|
if (iupStrEqualNoCase(typeface, "monospace") ||
|
||
|
iupStrEqualNoCase(typeface, "courier") ||
|
||
|
iupStrEqualNoCase(typeface, "courier new"))
|
||
|
return "cursor";
|
||
|
if (iupStrEqualNoCase(typeface, "serif") ||
|
||
|
iupStrEqualNoCase(typeface, "times") ||
|
||
|
iupStrEqualNoCase(typeface, "times new roman"))
|
||
|
return "termes";
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
static char* iGLGetFontNameTTF(const char* typeface)
|
||
|
{
|
||
|
if (iupStrEqualNoCase(typeface, "sans") ||
|
||
|
iupStrEqualNoCase(typeface, "helvetica") ||
|
||
|
iupStrEqualNoCase(typeface, "arial"))
|
||
|
return "arial";
|
||
|
if (iupStrEqualNoCase(typeface, "monospace") ||
|
||
|
iupStrEqualNoCase(typeface, "courier") ||
|
||
|
iupStrEqualNoCase(typeface, "courier new"))
|
||
|
return "cour";
|
||
|
if (iupStrEqualNoCase(typeface, "serif") ||
|
||
|
iupStrEqualNoCase(typeface, "times") ||
|
||
|
iupStrEqualNoCase(typeface, "times new roman"))
|
||
|
return "times";
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
static int iGLGetFontFilenameFromNamesOTF(const char* path, const char* typeface, char* filename, int is_bold, int is_italic)
|
||
|
{
|
||
|
char fontname[100];
|
||
|
char* face = iGLGetFontNameTex(typeface);
|
||
|
if (face)
|
||
|
sprintf(fontname, "texgyre%s-", face);
|
||
|
else
|
||
|
sprintf(fontname, "texgyre%s-", typeface);
|
||
|
|
||
|
if (is_bold && is_italic)
|
||
|
strcat(fontname, "bolditalic");
|
||
|
else if (is_italic)
|
||
|
strcat(fontname, "italic");
|
||
|
else if (is_bold)
|
||
|
strcat(fontname, "bold");
|
||
|
else
|
||
|
strcat(fontname, "regular");
|
||
|
|
||
|
return iGLGetFontFilenameFromTypeface(path, fontname, "otf", filename);
|
||
|
}
|
||
|
|
||
|
static int iGLGetFontFilenameFromNamesTTF(const char* path, const char* typeface, char* filename, int is_bold, int is_italic)
|
||
|
{
|
||
|
char fontname[100];
|
||
|
char* face = iGLGetFontNameTTF(typeface);
|
||
|
if (face)
|
||
|
strcpy(fontname, face);
|
||
|
else
|
||
|
strcpy(fontname, typeface);
|
||
|
|
||
|
if (is_bold && is_italic)
|
||
|
strcat(fontname, "bi");
|
||
|
else if (is_italic)
|
||
|
strcat(fontname, "i");
|
||
|
else if (is_bold)
|
||
|
strcat(fontname, "bd");
|
||
|
|
||
|
return iGLGetFontFilenameFromTypeface(path, fontname, "ttf", filename);
|
||
|
}
|
||
|
|
||
|
static void iGLGetFontFilename(char* filename, const char *typeface, int is_bold, int is_italic)
|
||
|
{
|
||
|
char *path = getenv("FREETYPEFONTS_DIR");
|
||
|
if (!path)
|
||
|
path = IupGetGlobal("FREETYPEFONTS_DIR");
|
||
|
|
||
|
/* search for the font in the system */
|
||
|
/* "Helvetica" "Courier" "Times" "Segoe UI" "Tahoma" etc */
|
||
|
if (iGLGetFontFilenameFromSystem(typeface, is_bold, is_italic, filename))
|
||
|
return;
|
||
|
|
||
|
/* try typeface as a file title, compose with path to get a filename
|
||
|
assume style already in the typeface */
|
||
|
/* "ariali" "courbd" "texgyrecursor-bold" */
|
||
|
if (iGLGetFontFilenameFromTypeface(path, typeface, "ttf", filename))
|
||
|
return;
|
||
|
if (iGLGetFontFilenameFromTypeface(path, typeface, "otf", filename))
|
||
|
return;
|
||
|
|
||
|
/* check for the pre-defined names, and use style to compose the filename */
|
||
|
/* "cursor" */
|
||
|
if (iGLGetFontFilenameFromNamesTTF(path, typeface, filename, is_bold, is_italic))
|
||
|
return;
|
||
|
if (iGLGetFontFilenameFromNamesOTF(path, typeface, filename, is_bold, is_italic))
|
||
|
return;
|
||
|
|
||
|
/* try the typeface as file name */
|
||
|
strcpy(filename, typeface);
|
||
|
}
|
||
|
|
||
|
static int iGLFontGetFontAveWidth(FTGLfont* ftgl_font);
|
||
|
|
||
|
static IglFont* iGLFindFont(Ihandle* ih, Ihandle* gl_parent, const char *font)
|
||
|
{
|
||
|
char filename[10240];
|
||
|
char typeface[50] = "";
|
||
|
FTGLfont* ftgl_font;
|
||
|
int size = 8;
|
||
|
int is_bold = 0,
|
||
|
is_italic = 0,
|
||
|
is_underline = 0,
|
||
|
is_strikeout = 0;
|
||
|
int i, count;
|
||
|
IglFont* fonts;
|
||
|
double res = IupGetDouble(NULL, "SCREENDPI");
|
||
|
Iarray* gl_fonts = (Iarray*)iupAttribGet(gl_parent, "GL_FONTLIST");
|
||
|
if (!gl_fonts)
|
||
|
{
|
||
|
gl_fonts = iupArrayCreate(50, sizeof(IglFont));
|
||
|
iupAttribSet(gl_parent, "GL_FONTLIST", (char*)gl_fonts);
|
||
|
}
|
||
|
|
||
|
if (!iupGetFontInfo(font, typeface, &size, &is_bold, &is_italic, &is_underline, &is_strikeout))
|
||
|
return NULL;
|
||
|
|
||
|
if (is_underline)
|
||
|
iupAttribSet(ih, "UNDERLINE", "1");
|
||
|
else
|
||
|
iupAttribSet(ih, "UNDERLINE", NULL);
|
||
|
|
||
|
iGLGetFontFilename(filename, typeface, is_bold, is_italic);
|
||
|
|
||
|
if (size < 0)
|
||
|
size = iupRound((-size*72.0) / res); /* convert to points */
|
||
|
|
||
|
/* Check if the filename already exists in cache */
|
||
|
fonts = (IglFont*)iupArrayGetData(gl_fonts);
|
||
|
count = iupArrayCount(gl_fonts);
|
||
|
for (i = 0; i < count; i++)
|
||
|
{
|
||
|
if (iupStrEqualNoCase(filename, fonts[i].filename) && fonts[i].size == size)
|
||
|
return &fonts[i];
|
||
|
}
|
||
|
|
||
|
ftgl_font = ftglCreateTextureFont(filename);
|
||
|
if (!ftgl_font)
|
||
|
return NULL;
|
||
|
|
||
|
ftglSetFontFaceSize(ftgl_font, size, (int)res);
|
||
|
|
||
|
/* create room in the array */
|
||
|
fonts = (IglFont*)iupArrayInc(gl_fonts);
|
||
|
|
||
|
strcpy(fonts[i].filename, filename);
|
||
|
fonts[i].ftgl_font = ftgl_font;
|
||
|
fonts[i].size = size;
|
||
|
|
||
|
/* NOTICE that this is different from CD,
|
||
|
here we need average width,
|
||
|
there is maximum width. */
|
||
|
fonts[i].charwidth = iGLFontGetFontAveWidth(ftgl_font);
|
||
|
fonts[i].charheight = iupRound(ftglGetFontLineHeight(ftgl_font));
|
||
|
|
||
|
return &fonts[i];
|
||
|
}
|
||
|
|
||
|
static IglFont* iGLFontCreateNativeFont(Ihandle *ih, const char* value)
|
||
|
{
|
||
|
IglFont* glfont;
|
||
|
Ihandle* gl_parent = (Ihandle*)iupAttribGet(ih, "_IUP_GLCANVAS_PARENT");
|
||
|
IupGLMakeCurrent(gl_parent);
|
||
|
|
||
|
glfont = iGLFindFont(ih, gl_parent, value);
|
||
|
if (!glfont)
|
||
|
{
|
||
|
iupERROR1("Failed to create Font: %s", value);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
iupAttribSet(ih, "_IUP_GLFONT", (char*)glfont);
|
||
|
return glfont;
|
||
|
}
|
||
|
|
||
|
static IglFont* iGLFontGet(Ihandle *ih)
|
||
|
{
|
||
|
IglFont* glfont = (IglFont*)iupAttribGet(ih, "_IUP_GLFONT");
|
||
|
if (!glfont)
|
||
|
glfont = iGLFontCreateNativeFont(ih, IupGetAttribute(ih, "FONT"));
|
||
|
return glfont;
|
||
|
}
|
||
|
|
||
|
IUP_SDK_API char* iupStrConvertToUTF8(const char* str, int len, char* utf8_buffer, int *utf8_buffer_max, int utf8mode);
|
||
|
|
||
|
static void iGLFontConvertToUTF8(const char* str, int len)
|
||
|
{
|
||
|
/* FTGL multibyte strings are always UTF-8 */
|
||
|
int utf8mode = IupGetInt(NULL, "UTF8MODE");
|
||
|
|
||
|
gl_utf8_buffer = iupStrConvertToUTF8(str, len, gl_utf8_buffer, &gl_utf8_buffer_len, utf8mode);
|
||
|
}
|
||
|
|
||
|
static int iGLFontGetFontAveWidth(FTGLfont* ftgl_font)
|
||
|
{
|
||
|
static int first = 1;
|
||
|
static char sample[512] = "";
|
||
|
if (first)
|
||
|
{
|
||
|
int utf8mode = IupGetInt(NULL, "UTF8MODE");
|
||
|
|
||
|
/* use all Latin-1 characters */
|
||
|
int i;
|
||
|
for (i = 32; i < 256; i++)
|
||
|
sample[i - 32] = (char)i;
|
||
|
|
||
|
if (utf8mode) IupSetGlobal("UTF8MODE", "No");
|
||
|
iGLFontConvertToUTF8(sample, 256 - 32);
|
||
|
if (utf8mode) IupSetGlobal("UTF8MODE", "Yes");
|
||
|
|
||
|
i = (int)strlen(gl_utf8_buffer);
|
||
|
memcpy(sample, gl_utf8_buffer, i + 1);
|
||
|
first = 0;
|
||
|
}
|
||
|
|
||
|
return iupRound(ftglGetFontAdvance(ftgl_font, sample) / (256.0f - 32.0f));
|
||
|
}
|
||
|
|
||
|
int iupGLFontGetStringWidth(Ihandle* ih, const char* str, int len)
|
||
|
{
|
||
|
IglFont* glfont;
|
||
|
|
||
|
if (!ih->handle)
|
||
|
return 0;
|
||
|
|
||
|
glfont = iGLFontGet(ih);
|
||
|
if (!glfont)
|
||
|
return 0;
|
||
|
|
||
|
iGLFontConvertToUTF8(str, len);
|
||
|
return iupRound(ftglGetFontAdvance(glfont->ftgl_font, gl_utf8_buffer));
|
||
|
}
|
||
|
|
||
|
void iupGLFontGetMultiLineStringSize(Ihandle* ih, const char* str, int *w, int *h)
|
||
|
{
|
||
|
int max_w = 0, line_count = 1;
|
||
|
IglFont* glfont;
|
||
|
|
||
|
if (!ih->handle)
|
||
|
{
|
||
|
iupdrvFontGetMultiLineStringSize(ih, str, w, h);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
glfont = iGLFontGet(ih);
|
||
|
if (!glfont)
|
||
|
{
|
||
|
if (w) *w = 0;
|
||
|
if (h) *h = 0;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!str)
|
||
|
{
|
||
|
if (w) *w = 0;
|
||
|
if (h) *h = glfont->charheight * 1;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (str[0] && w)
|
||
|
{
|
||
|
int size;
|
||
|
int len;
|
||
|
const char *nextstr;
|
||
|
const char *curstr = str;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
nextstr = iupStrNextLine(curstr, &len);
|
||
|
|
||
|
if (len)
|
||
|
{
|
||
|
iGLFontConvertToUTF8(curstr, len);
|
||
|
size = iupRound(ftglGetFontAdvance(glfont->ftgl_font, gl_utf8_buffer));
|
||
|
max_w = iupMAX(max_w, size);
|
||
|
}
|
||
|
|
||
|
if (*nextstr)
|
||
|
line_count++;
|
||
|
|
||
|
curstr = nextstr;
|
||
|
} while (*nextstr);
|
||
|
}
|
||
|
|
||
|
if (w) *w = max_w;
|
||
|
if (h) *h = glfont->charheight * line_count;
|
||
|
}
|
||
|
|
||
|
int iupGLFontSetFontAttrib(Ihandle* ih, const char* value)
|
||
|
{
|
||
|
IglFont* glfont;
|
||
|
|
||
|
if (!ih->handle)
|
||
|
return iupdrvSetFontAttrib(ih, value);
|
||
|
|
||
|
if (!iupdrvSetFontAttrib(ih, value))
|
||
|
return 0;
|
||
|
|
||
|
glfont = iGLFontCreateNativeFont(ih, value);
|
||
|
if (glfont)
|
||
|
{
|
||
|
/* If FONT is changed, must update the SIZE attribute */
|
||
|
iupBaseUpdateAttribFromFont(ih);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void iupGLFontGetCharSize(Ihandle* ih, int *charwidth, int *charheight)
|
||
|
{
|
||
|
IglFont* glfont;
|
||
|
|
||
|
if (!ih->handle)
|
||
|
{
|
||
|
iupdrvFontGetCharSize(ih, charwidth, charheight);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
glfont = iGLFontGet(ih);
|
||
|
if (!glfont)
|
||
|
{
|
||
|
if (charwidth) *charwidth = 0;
|
||
|
if (charheight) *charheight = 0;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (charwidth) *charwidth = glfont->charwidth;
|
||
|
if (charheight) *charheight = glfont->charheight;
|
||
|
}
|
||
|
|
||
|
void iupGLFontGetDim(Ihandle* ih, int *maxwidth, int *height, int *ascent, int *descent)
|
||
|
{
|
||
|
IglFont* glfont;
|
||
|
|
||
|
if (!ih->handle)
|
||
|
return;
|
||
|
|
||
|
glfont = iGLFontGet(ih);
|
||
|
if (!glfont)
|
||
|
return;
|
||
|
|
||
|
if (maxwidth) *maxwidth = glfont->charwidth;
|
||
|
if (height) *height = glfont->charheight;
|
||
|
if (ascent) *ascent = iupRound(ftglGetFontAscender(glfont->ftgl_font));
|
||
|
if (descent) *descent = iupRound(-ftglGetFontDescender(glfont->ftgl_font));
|
||
|
}
|
||
|
|
||
|
void iupGLFontRenderString(Ihandle* ih, const char* str, int len)
|
||
|
{
|
||
|
IglFont* glfont;
|
||
|
|
||
|
if (!ih->handle)
|
||
|
return;
|
||
|
|
||
|
glfont = iGLFontGet(ih);
|
||
|
if (!glfont)
|
||
|
return;
|
||
|
|
||
|
iGLFontConvertToUTF8(str, len);
|
||
|
/* render always at baseline */
|
||
|
ftglRenderFont(glfont->ftgl_font, gl_utf8_buffer, FTGL_RENDER_ALL);
|
||
|
}
|
||
|
|
||
|
void iupGLFontInit(void)
|
||
|
{
|
||
|
#ifdef WIN32
|
||
|
if (!win_fonts)
|
||
|
winInitFontNames();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void iupGLFontRelease(Ihandle* gl_parent)
|
||
|
{
|
||
|
Iarray* gl_fonts = (Iarray*)iupAttribGet(gl_parent, "GL_FONTLIST");
|
||
|
if (gl_fonts)
|
||
|
{
|
||
|
int i, count = iupArrayCount(gl_fonts);
|
||
|
IglFont* fonts = (IglFont*)iupArrayGetData(gl_fonts);
|
||
|
for (i = 0; i < count; i++)
|
||
|
{
|
||
|
ftglDestroyFont(fonts[i].ftgl_font);
|
||
|
fonts[i].ftgl_font = NULL;
|
||
|
}
|
||
|
iupArrayDestroy(gl_fonts);
|
||
|
iupAttribSet(gl_parent, "GL_FONTLIST", NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void iupGLFontFinish(void)
|
||
|
{
|
||
|
if (gl_utf8_buffer)
|
||
|
{
|
||
|
free(gl_utf8_buffer);
|
||
|
gl_utf8_buffer = NULL;
|
||
|
gl_utf8_buffer_len = 0;
|
||
|
}
|
||
|
|
||
|
#ifdef WIN32
|
||
|
if (win_fonts)
|
||
|
free(win_fonts);
|
||
|
win_fonts = NULL;
|
||
|
win_fonts_count = 0;
|
||
|
#endif
|
||
|
}
|