2011-01-22 21:24:52 +00:00
|
|
|
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
|
2011-01-23 19:29:28 +00:00
|
|
|
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
|
2011-01-22 21:24:52 +00:00
|
|
|
*
|
|
|
|
* Some code herein may be based on code found in BSNES.
|
|
|
|
*
|
|
|
|
* SSNES is free software: you can redistribute it and/or modify it under the terms
|
|
|
|
* of the GNU General Public License as published by the Free Software Found-
|
|
|
|
* ation, either version 3 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE. See the GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along with SSNES.
|
|
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "fonts.h"
|
2011-10-06 17:06:38 +00:00
|
|
|
#include "file.h"
|
2011-01-22 21:24:52 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include <ft2build.h>
|
|
|
|
#include FT_FREETYPE_H
|
|
|
|
|
|
|
|
struct font_renderer
|
|
|
|
{
|
|
|
|
FT_Library lib;
|
|
|
|
FT_Face face;
|
|
|
|
};
|
|
|
|
|
|
|
|
font_renderer_t *font_renderer_new(const char *font_path, unsigned font_size)
|
|
|
|
{
|
|
|
|
(void)font_size;
|
|
|
|
font_renderer_t *handle = calloc(1, sizeof(*handle));
|
|
|
|
if (!handle)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
FT_Error err = FT_Init_FreeType(&handle->lib);
|
|
|
|
if (err)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
err = FT_New_Face(handle->lib, font_path, 0, &handle->face);
|
|
|
|
if (err)
|
|
|
|
goto error;
|
|
|
|
|
2011-01-22 23:27:20 +00:00
|
|
|
err = FT_Set_Pixel_Sizes(handle->face, 0, font_size);
|
2011-01-22 21:24:52 +00:00
|
|
|
if (err)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
return handle;
|
|
|
|
|
|
|
|
error:
|
2011-01-24 22:33:12 +00:00
|
|
|
if (handle)
|
|
|
|
{
|
|
|
|
if (handle->face)
|
|
|
|
FT_Done_Face(handle->face);
|
|
|
|
if (handle->lib)
|
|
|
|
FT_Done_FreeType(handle->lib);
|
|
|
|
free(handle);
|
|
|
|
}
|
2011-01-22 21:24:52 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void font_renderer_msg(font_renderer_t *handle, const char *msg, struct font_output_list *output)
|
|
|
|
{
|
|
|
|
output->head = NULL;
|
|
|
|
|
|
|
|
FT_GlyphSlot slot = handle->face->glyph;
|
|
|
|
struct font_output *cur = NULL;
|
|
|
|
size_t len = strlen(msg);
|
|
|
|
int off_x = 0, off_y = 0;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
FT_Error err = FT_Load_Char(handle->face, msg[i], FT_LOAD_RENDER);
|
|
|
|
|
|
|
|
if (!err)
|
|
|
|
{
|
|
|
|
struct font_output *tmp = calloc(1, sizeof(*tmp));
|
2011-10-05 20:39:54 +00:00
|
|
|
if (!tmp)
|
|
|
|
break;
|
2011-01-22 23:27:20 +00:00
|
|
|
|
2011-01-22 21:24:52 +00:00
|
|
|
tmp->output = malloc(slot->bitmap.pitch * slot->bitmap.rows);
|
2011-10-05 20:39:54 +00:00
|
|
|
if (!tmp->output)
|
|
|
|
{
|
|
|
|
free(tmp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-01-22 21:24:52 +00:00
|
|
|
memcpy(tmp->output, slot->bitmap.buffer, slot->bitmap.pitch * slot->bitmap.rows);
|
|
|
|
|
|
|
|
tmp->width = slot->bitmap.width;
|
|
|
|
tmp->height = slot->bitmap.rows;
|
|
|
|
tmp->pitch = slot->bitmap.pitch;
|
|
|
|
tmp->off_x = off_x + slot->bitmap_left;
|
2011-01-22 23:27:20 +00:00
|
|
|
tmp->off_y = off_y + slot->bitmap_top - slot->bitmap.rows;
|
2011-01-22 21:24:52 +00:00
|
|
|
tmp->next = NULL;
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
output->head = tmp;
|
|
|
|
else
|
|
|
|
cur->next = tmp;
|
|
|
|
|
|
|
|
cur = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
off_x += slot->advance.x >> 6;
|
|
|
|
off_y += slot->advance.y >> 6;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void font_renderer_free_output(struct font_output_list *output)
|
|
|
|
{
|
|
|
|
struct font_output *itr = output->head;
|
|
|
|
struct font_output *tmp = NULL;
|
|
|
|
while (itr != NULL)
|
|
|
|
{
|
|
|
|
free(itr->output);
|
|
|
|
tmp = itr;
|
|
|
|
itr = itr->next;
|
|
|
|
free(tmp);
|
|
|
|
}
|
|
|
|
output->head = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void font_renderer_free(font_renderer_t *handle)
|
|
|
|
{
|
|
|
|
if (handle->face)
|
|
|
|
FT_Done_Face(handle->face);
|
|
|
|
if (handle->lib)
|
|
|
|
FT_Done_FreeType(handle->lib);
|
|
|
|
}
|
2011-10-06 17:06:38 +00:00
|
|
|
|
|
|
|
// Not the cleanest way to do things for sure, but should hopefully work ... :)
|
|
|
|
|
|
|
|
#if defined(_WIN32)
|
|
|
|
static const char *font_paths[] = {
|
|
|
|
"C:\\Windows\\Fonts\\consola.ttf",
|
|
|
|
"C:\\Windows\\Fonts\\verdana.ttf",
|
|
|
|
#elif defined(__APPLE__)
|
|
|
|
static const char *font_paths[] = {
|
2011-10-06 19:12:11 +00:00
|
|
|
"/Library/Fonts/Microsoft/Candara.ttf",
|
2011-10-06 17:06:38 +00:00
|
|
|
#else
|
|
|
|
static const char *font_paths[] = {
|
|
|
|
"/usr/share/fonts/TTF/DejaVuSansMono.ttf",
|
|
|
|
"/usr/share/fonts/TTF/DejaVuSans.ttf",
|
|
|
|
#endif
|
|
|
|
"osd-font.ttf", // Magic font to search for, useful for distribution.
|
|
|
|
};
|
|
|
|
|
|
|
|
// Highly OS/platform dependent.
|
|
|
|
const char *font_renderer_get_default_font(void)
|
|
|
|
{
|
|
|
|
for (unsigned i = 0; i < sizeof(font_paths) / sizeof(font_paths[0]); i++)
|
|
|
|
{
|
|
|
|
if (path_file_exists(font_paths[i]))
|
|
|
|
return font_paths[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|