RetroArch/gfx/drivers_font/d3d9x_w32_font.c
2024-07-20 19:42:45 +02:00

266 lines
7.4 KiB
C

/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
*
* RetroArch 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.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#define CINTERFACE
#include <tchar.h>
#include <compat/strl.h>
#ifdef HAVE_CONFIG_H
#include "../../config.h"
#endif
#ifdef HAVE_D3DX
#include <d3dx9core.h>
#include <d3dx9tex.h>
#include "../common/d3d_common.h"
#include "../common/d3d9_common.h"
#include "../font_driver.h"
#include "../../configuration.h"
typedef struct d3d9x_font_desc
{
INT Height;
UINT Width;
UINT Weight;
UINT MipLevels;
BOOL Italic;
BYTE CharSet;
BYTE OutputPrecision;
BYTE Quality;
BYTE PitchAndFamily;
CHAR FaceName[32];
} d3d9x_font_desc_t;
typedef struct
{
d3d9_video_t *d3d;
void *font;
uint32_t font_size;
uint32_t ascent;
} d3dfonts_t;
static void *d3d9x_win32_font_init(void *video_data,
const char *font_path, float font_size,
bool is_threaded)
{
TEXTMETRICA metrics;
d3d9x_font_desc_t desc;
uint32_t new_font_size = 0;
ID3DXFont *font = NULL;
d3dfonts_t *d3dfonts = (d3dfonts_t*)calloc(1, sizeof(*d3dfonts));
if (!d3dfonts)
return NULL;
desc.Height = (int)font_size;
desc.Width = 0;
desc.Weight = 400;
desc.MipLevels = 0;
desc.Italic = FALSE;
desc.CharSet = DEFAULT_CHARSET;
desc.OutputPrecision = OUT_TT_PRECIS;
desc.Quality = CLIP_DEFAULT_PRECIS;
desc.PitchAndFamily = DEFAULT_PITCH;
/* TODO/FIXME - don't hardcode this font */
#ifdef UNICODE
strlcpy(desc.FaceName, T(L"Verdana"), sizeof(desc.FaceName));
#else
strlcpy(desc.FaceName, (const char*)_T("Verdana"), sizeof(desc.FaceName));
#endif
new_font_size = font_size * 1.2; /* To match the other font drivers */
d3dfonts->font_size = new_font_size;
d3dfonts->d3d = (d3d9_video_t*)video_data;
desc.Height = new_font_size;
if (!d3d9x_create_font_indirect(d3dfonts->d3d->dev,
&desc, (void**)&d3dfonts->font))
goto error;
font = (ID3DXFont*)d3dfonts->font;
font->lpVtbl->GetTextMetrics(font, &metrics);
d3dfonts->ascent = metrics.tmAscent;
return d3dfonts;
error:
free(d3dfonts);
return NULL;
}
static void d3d9x_win32_font_free(void *data, bool is_threaded)
{
ID3DXFont *font = NULL;
d3dfonts_t *d3dfonts = (d3dfonts_t*)data;
if (!d3dfonts)
return;
font = (ID3DXFont*)d3dfonts->font;
if (font)
font->lpVtbl->Release(font);
free(d3dfonts);
}
static int d3d9x_win32_font_get_message_width(void* data, const char* msg,
size_t msg_len, float scale)
{
RECT box = {0,0,0,0};
d3dfonts_t *d3dfonts = (d3dfonts_t*)data;
ID3DXFont *font = NULL;
if (!d3dfonts || !msg)
return 0;
font = (ID3DXFont*)d3dfonts->font;
font->lpVtbl->DrawText(font, NULL,
(void*)msg, msg_len ? (INT)msg_len : -1, &box, DT_CALCRECT, 0);
return box.right - box.left;
}
static void d3d9x_win32_font_render_msg(
void *userdata,
void *data, const char *msg,
const struct font_params *params)
{
DWORD format;
unsigned a, r, g, b;
unsigned width, height;
RECT rect, rect_shifted;
RECT *p_rect_shifted = NULL;
RECT *p_rect = NULL;
ID3DXFont *font = NULL;
d3dfonts_t *d3dfonts = (d3dfonts_t*)data;
float drop_mod = 0.3f;
float drop_alpha = 1.0f;
int drop_x = -2;
int drop_y = -2;
if (!d3dfonts || !msg)
return;
font = (ID3DXFont*)d3dfonts->font;
width = d3dfonts->d3d->video_info.width;
height = d3dfonts->d3d->video_info.height;
p_rect = &d3dfonts->d3d->font_rect;
p_rect_shifted = &d3dfonts->d3d->font_rect_shifted;
format = DT_LEFT;
if (params)
{
a = FONT_COLOR_GET_ALPHA(params->color);
r = FONT_COLOR_GET_RED(params->color);
g = FONT_COLOR_GET_GREEN(params->color);
b = FONT_COLOR_GET_BLUE(params->color);
switch (params->text_align)
{
case TEXT_ALIGN_RIGHT:
format = DT_RIGHT;
rect.left = 0;
rect.right = params->x * width;
break;
case TEXT_ALIGN_CENTER:
format = DT_CENTER;
rect.left = (params->x - 1.0) * width;
rect.right = (params->x + 1.0) * width;
break;
case TEXT_ALIGN_LEFT:
default:
format = DT_LEFT;
rect.left = params->x * width;
rect.right = width;
break;
}
rect.top = (1.0 - params->y) * height - d3dfonts->ascent;
rect.bottom = height;
p_rect = &rect;
drop_x = params->drop_x;
drop_y = params->drop_y;
if (drop_x || drop_y)
{
drop_mod = params->drop_mod;
drop_alpha = params->drop_alpha;
rect_shifted = rect;
rect_shifted.left += params->drop_x;
rect_shifted.right += params->drop_x;
rect_shifted.top -= params->drop_y;
rect_shifted.bottom -= params->drop_y;
p_rect_shifted = &rect_shifted;
}
}
else
{
settings_t *settings = config_get_ptr();
float video_msg_pos_x = settings->floats.video_msg_pos_x;
float video_msg_pos_y = settings->floats.video_msg_pos_y;
float video_msg_color_r = settings->floats.video_msg_color_r;
float video_msg_color_g = settings->floats.video_msg_color_g;
float video_msg_color_b = settings->floats.video_msg_color_b;
a = 255;
r = video_msg_color_r * 255;
g = video_msg_color_g * 255;
b = video_msg_color_b * 255;
}
if (drop_x || drop_y)
{
unsigned drop_a = a * drop_alpha;
unsigned drop_r = r * drop_mod;
unsigned drop_g = g * drop_mod;
unsigned drop_b = b * drop_mod;
font->lpVtbl->DrawText(font, NULL,
(void*)msg, -1, p_rect_shifted, format,
D3DCOLOR_ARGB(drop_a , drop_r, drop_g, drop_b));
}
font->lpVtbl->DrawText(font, NULL,
(void*)msg, -1, p_rect, format,
D3DCOLOR_ARGB(a, r, g, b));
}
font_renderer_t d3d9x_win32_font = {
d3d9x_win32_font_init,
d3d9x_win32_font_free,
d3d9x_win32_font_render_msg,
"d3d9x",
NULL, /* get_glyph */
NULL, /* bind_block */
NULL, /* flush */
d3d9x_win32_font_get_message_width,
NULL /* get_line_metrics */
};
#endif