1 /*  RetroArch - A frontend for libretro.
2  *  Copyright (C) 2010-2014 - Hans-Kristian Arntzen
3  *  Copyright (C) 2011-2017 - Daniel De Matteis
4  *
5  *  RetroArch is free software: you can redistribute it and/or modify it under the terms
6  *  of the GNU General Public License as published by the Free Software Found-
7  *  ation, either version 3 of the License, or (at your option) any later version.
8  *
9  *  RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10  *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11  *  PURPOSE.  See the GNU General Public License for more details.
12  *
13  *  You should have received a copy of the GNU General Public License along with RetroArch.
14  *  If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 #define CINTERFACE
18 
19 #include <tchar.h>
20 
21 #include <compat/strl.h>
22 
23 #ifdef HAVE_CONFIG_H
24 #include "../../config.h"
25 #endif
26 
27 #include "../common/d3d_common.h"
28 #include "../common/d3d9_common.h"
29 #include "../font_driver.h"
30 
31 #include "../../configuration.h"
32 
33 typedef struct d3dx_font_desc
34 {
35     INT Height;
36     UINT Width;
37     UINT Weight;
38     UINT MipLevels;
39     BOOL Italic;
40     BYTE CharSet;
41     BYTE OutputPrecision;
42     BYTE Quality;
43     BYTE PitchAndFamily;
44     CHAR FaceName[32];
45 } d3dx_font_desc_t;
46 
47 typedef struct
48 {
49    d3d9_video_t *d3d;
50    void *font;
51    uint32_t font_size;
52    uint32_t ascent;
53 } d3dfonts_t;
54 
d3dfonts_w32_init_font(void * video_data,const char * font_path,float font_size,bool is_threaded)55 static void *d3dfonts_w32_init_font(void *video_data,
56       const char *font_path, float font_size,
57       bool is_threaded)
58 {
59    TEXTMETRICA metrics;
60    d3dx_font_desc_t desc;
61    d3dfonts_t *d3dfonts = (d3dfonts_t*)calloc(1, sizeof(*d3dfonts));
62    if (!d3dfonts)
63 	   return NULL;
64 
65    desc.Height          = (int)font_size;
66    desc.Width           = 0;
67    desc.Weight          = 400;
68    desc.MipLevels       = 0;
69    desc.Italic          = FALSE;
70    desc.CharSet         = DEFAULT_CHARSET;
71    desc.OutputPrecision = OUT_TT_PRECIS;
72    desc.Quality         = CLIP_DEFAULT_PRECIS;
73    desc.PitchAndFamily  = DEFAULT_PITCH;
74 #ifdef UNICODE
75    strlcpy(desc.FaceName, T(L"Verdana"), sizeof(desc.FaceName));
76 #else
77    strlcpy(desc.FaceName, (const char*)_T("Verdana"), sizeof(desc.FaceName));
78 #endif
79 
80    d3dfonts->font_size  = font_size * 1.2; /* to match the other font drivers */
81    d3dfonts->d3d        = (d3d9_video_t*)video_data;
82 
83    desc.Height          = d3dfonts->font_size;
84 
85    if (!d3d9x_create_font_indirect(d3dfonts->d3d->dev,
86             &desc, (void**)&d3dfonts->font))
87       goto error;
88 
89    d3d9x_font_get_text_metrics(d3dfonts->font, &metrics);
90 
91    d3dfonts->ascent     = metrics.tmAscent;
92 
93    return d3dfonts;
94 
95 error:
96    free(d3dfonts);
97    return NULL;
98 }
99 
d3dfonts_w32_free_font(void * data,bool is_threaded)100 static void d3dfonts_w32_free_font(void *data, bool is_threaded)
101 {
102    d3dfonts_t *d3dfonts = (d3dfonts_t*)data;
103 
104    if (!d3dfonts)
105       return;
106 
107    if (d3dfonts->font)
108       d3d9x_font_release(d3dfonts->font);
109 
110    free(d3dfonts);
111 }
112 
d3dfonts_w32_get_message_width(void * data,const char * msg,unsigned msg_len,float scale)113 static int d3dfonts_w32_get_message_width(void* data, const char* msg,
114       unsigned msg_len, float scale)
115 {
116    RECT box             = {0,0,0,0};
117    d3dfonts_t *d3dfonts = (d3dfonts_t*)data;
118 
119    if (!d3dfonts || !msg)
120       return 0;
121 
122    d3d9x_font_draw_text(d3dfonts->font, NULL, (void*)msg,
123          msg_len? msg_len : -1, &box, DT_CALCRECT, 0);
124 
125    return box.right - box.left;
126 }
127 
d3dfonts_w32_render_msg(void * userdata,void * data,const char * msg,const struct font_params * params)128 static void d3dfonts_w32_render_msg(
129       void *userdata,
130       void *data, const char *msg,
131       const struct font_params *params)
132 {
133    unsigned format;
134    unsigned a, r, g, b;
135    unsigned width, height;
136    RECT rect, rect_shifted;
137    RECT *p_rect_shifted             = NULL;
138    RECT *p_rect                     = NULL;
139    d3dfonts_t *d3dfonts             = (d3dfonts_t*)data;
140    float drop_mod                   = 0.3f;
141    float drop_alpha                 = 1.0f;
142    int drop_x                       = -2;
143    int drop_y                       = -2;
144    settings_t *settings             = config_get_ptr();
145    float video_msg_pos_x            = settings->floats.video_msg_pos_x;
146    float video_msg_pos_y            = settings->floats.video_msg_pos_y;
147    float video_msg_color_r          = settings->floats.video_msg_color_r;
148    float video_msg_color_g          = settings->floats.video_msg_color_g;
149    float video_msg_color_b          = settings->floats.video_msg_color_b;
150 
151    if (!d3dfonts || !msg)
152       return;
153 
154    width                            = d3dfonts->d3d->video_info.width;
155    height                           = d3dfonts->d3d->video_info.height;
156 
157    p_rect                           = &d3dfonts->d3d->font_rect;
158    p_rect_shifted                   = &d3dfonts->d3d->font_rect_shifted;
159    format                           = DT_LEFT;
160 
161    if(params)
162    {
163       a = FONT_COLOR_GET_ALPHA(params->color);
164       r = FONT_COLOR_GET_RED(params->color);
165       g = FONT_COLOR_GET_GREEN(params->color);
166       b = FONT_COLOR_GET_BLUE(params->color);
167 
168       switch (params->text_align)
169       {
170          case TEXT_ALIGN_RIGHT:
171             format     = DT_RIGHT;
172             rect.left  = 0;
173             rect.right = params->x * width;
174             break;
175          case TEXT_ALIGN_CENTER:
176             format     = DT_CENTER;
177             rect.left  = (params->x - 1.0) * width;
178             rect.right = (params->x + 1.0) * width;
179             break;
180          case TEXT_ALIGN_LEFT:
181          default:
182             format     = DT_LEFT;
183             rect.left  = params->x * width;
184             rect.right = width;
185             break;
186       }
187 
188       rect.top    = (1.0 - params->y) * height - d3dfonts->ascent;
189       rect.bottom = height;
190       p_rect      = &rect;
191 
192       drop_x      = params->drop_x;
193       drop_y      = params->drop_y;
194 
195       if(drop_x || drop_y)
196       {
197          drop_mod             = params->drop_mod;
198          drop_alpha           = params->drop_alpha;
199          rect_shifted         = rect;
200          rect_shifted.left   += params->drop_x;
201          rect_shifted.right  += params->drop_x;
202          rect_shifted.top    -= params->drop_y;
203          rect_shifted.bottom -= params->drop_y;
204          p_rect_shifted       = &rect_shifted;
205       }
206    }
207    else
208    {
209       a = 255;
210       r = video_msg_color_r * 255;
211       g = video_msg_color_g * 255;
212       b = video_msg_color_b * 255;
213    }
214 
215    if(drop_x || drop_y)
216    {
217       unsigned drop_a = a * drop_alpha;
218       unsigned drop_r = r * drop_mod;
219       unsigned drop_g = g * drop_mod;
220       unsigned drop_b = b * drop_mod;
221 
222       d3d9x_font_draw_text(d3dfonts->font, NULL,
223             (void*)msg, -1, p_rect_shifted, format,
224             D3DCOLOR_ARGB(drop_a , drop_r, drop_g, drop_b));
225    }
226 
227    d3d9x_font_draw_text(d3dfonts->font, NULL, (void*)msg, -1,
228       p_rect, format, D3DCOLOR_ARGB(a, r, g, b));
229 }
230 
231 font_renderer_t d3d_win32_font = {
232    d3dfonts_w32_init_font,
233    d3dfonts_w32_free_font,
234    d3dfonts_w32_render_msg,
235    "d3dxfont",
236    NULL,                      /* get_glyph */
237    NULL,                      /* bind_block */
238    NULL,                      /* flush */
239    d3dfonts_w32_get_message_width,
240    NULL                       /* get_line_metrics */
241 };
242