OSDN Git Service

upgrade to 3.6.2
[jnethack/source.git] / win / win32 / mhfont.c
1 /* NetHack 3.6  mhfont.c        $NHDT-Date: 1432512812 2015/05/25 00:13:32 $  $NHDT-Branch: master $:$NHDT-Revision: 1.23 $ */
2 /* Copyright (C) 2001 by Alex Kompel     */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 /* font management and such */
6
7 #include "win10.h"
8 #include "winos.h"
9 #include "mhfont.h"
10
11 /* font table - 64 fonts ought to be enough */
12 #define MAXFONTS 64
13
14 static cached_font font_table[MAXFONTS];
15 static int font_table_size = 0;
16
17 #define NHFONT_CODE(win, attr) (((attr & 0xFF) << 8) | (win_type & 0xFF))
18
19 static void __cdecl font_table_cleanup(void);
20
21 HFONT
22 mswin_create_splashfont(HWND hWnd)
23 {
24     HDC hdc = GetDC(hWnd);
25     double scale = win10_monitor_scale(hWnd);
26     LOGFONT lgfnt;
27     ZeroMemory(&lgfnt, sizeof(lgfnt));
28     lgfnt.lfHeight = -(int)(80 * scale);       // height of font
29     lgfnt.lfWidth = 0;                         // average character width
30     lgfnt.lfEscapement = 0;                    // angle of escapement
31     lgfnt.lfOrientation = 0;                   // base-line orientation angle
32     lgfnt.lfWeight = FW_BOLD;                  // font weight
33     lgfnt.lfItalic = FALSE;                    // italic attribute option
34     lgfnt.lfUnderline = FALSE;                 // underline attribute option
35     lgfnt.lfStrikeOut = FALSE;                 // strikeout attribute option
36     lgfnt.lfCharSet = ANSI_CHARSET;            // character set identifier
37     lgfnt.lfOutPrecision = OUT_DEFAULT_PRECIS; // output precision
38     lgfnt.lfClipPrecision = CLIP_DEFAULT_PRECIS; // clipping precision
39     lgfnt.lfQuality = DEFAULT_QUALITY;           // output quality
40     lgfnt.lfPitchAndFamily = DEFAULT_PITCH;      // pitch and family
41     NH_A2W("Times New Roman", lgfnt.lfFaceName, LF_FACESIZE);
42     HFONT font = CreateFontIndirect(&lgfnt);
43     ReleaseDC(hWnd, hdc);
44
45     return font;
46 }
47
48 BOOL 
49 mswin_font_supports_unicode(HFONT hFont)
50 {
51     for (int i = 0; i < font_table_size; i++)
52         if (font_table[i].hFont == hFont)
53             return font_table[i].supportsUnicode;
54
55     return FALSE;
56 }
57
58 /* create font based on window type, charater attributes and
59    window device context */
60 cached_font *
61 mswin_get_font(int win_type, int attr, HDC hdc, BOOL replace)
62 {
63     HFONT fnt = NULL;
64     LOGFONT lgfnt;
65     int font_size;
66     int font_index;
67     static BOOL once = FALSE;
68
69     if (!once) {
70         once = TRUE;
71         atexit(font_table_cleanup);
72     }
73
74     ZeroMemory(&lgfnt, sizeof(lgfnt));
75
76     /* try find font in the table */
77     for (font_index = 0; font_index < font_table_size; font_index++)
78         if (NHFONT_CODE(win_type, attr) == font_table[font_index].code)
79             break;
80
81     if (!replace && font_index < font_table_size)
82         return &font_table[font_index];
83
84     switch (win_type) {
85     case NHW_STATUS:
86         font_size = (attr == ATR_BOLD) ? iflags.wc_fontsiz_status + 1
87                                        : iflags.wc_fontsiz_status;
88         lgfnt.lfHeight = -font_size * GetDeviceCaps(hdc, LOGPIXELSY)
89                          / 72;   // height of font
90         lgfnt.lfWidth = 0;       // average character width
91         lgfnt.lfEscapement = 0;  // angle of escapement
92         lgfnt.lfOrientation = 0; // base-line orientation angle
93         lgfnt.lfWeight =
94             (attr == ATR_BOLD) ? FW_BOLD : FW_NORMAL; // font weight
95         lgfnt.lfItalic = FALSE;            // italic attribute option
96         lgfnt.lfUnderline = (attr == ATR_ULINE); // underline attribute option
97         lgfnt.lfStrikeOut = FALSE;         // strikeout attribute option
98         lgfnt.lfCharSet = mswin_charset(); // character set identifier
99         lgfnt.lfOutPrecision = OUT_DEFAULT_PRECIS;   // output precision
100         lgfnt.lfClipPrecision = CLIP_DEFAULT_PRECIS; // clipping precision
101         lgfnt.lfQuality = DEFAULT_QUALITY;           // output quality
102         if (iflags.wc_font_status && *iflags.wc_font_status) {
103             lgfnt.lfPitchAndFamily = DEFAULT_PITCH; // pitch and family
104             NH_A2W(iflags.wc_font_status, lgfnt.lfFaceName, LF_FACESIZE);
105         } else {
106             lgfnt.lfPitchAndFamily = FIXED_PITCH; // pitch and family
107         }
108         break;
109
110     case NHW_MENU:
111         lgfnt.lfHeight = -iflags.wc_fontsiz_menu
112                          * GetDeviceCaps(hdc, LOGPIXELSY)
113                          / 72;   // height of font
114         lgfnt.lfWidth = 0;       // average character width
115         lgfnt.lfEscapement = 0;  // angle of escapement
116         lgfnt.lfOrientation = 0; // base-line orientation angle
117         lgfnt.lfWeight = (attr == ATR_BOLD || attr == ATR_INVERSE)
118                              ? FW_BOLD
119                              : FW_NORMAL; // font weight
120         lgfnt.lfItalic =
121             (attr == ATR_BLINK) ? TRUE : FALSE; // italic attribute option
122         lgfnt.lfUnderline =
123             (attr == ATR_ULINE) ? TRUE : FALSE; // underline attribute option
124         lgfnt.lfStrikeOut = FALSE;              // strikeout attribute option
125         lgfnt.lfCharSet = mswin_charset();      // character set identifier
126         lgfnt.lfOutPrecision = OUT_DEFAULT_PRECIS;   // output precision
127         lgfnt.lfClipPrecision = CLIP_DEFAULT_PRECIS; // clipping precision
128         lgfnt.lfQuality = DEFAULT_QUALITY;           // output quality
129         if (iflags.wc_font_menu && *iflags.wc_font_menu) {
130             lgfnt.lfPitchAndFamily = DEFAULT_PITCH; // pitch and family
131             NH_A2W(iflags.wc_font_menu, lgfnt.lfFaceName, LF_FACESIZE);
132         } else {
133             lgfnt.lfPitchAndFamily = FIXED_PITCH; // pitch and family
134         }
135         break;
136
137     case NHW_MESSAGE:
138         font_size = (attr == ATR_INVERSE) ? iflags.wc_fontsiz_message + 1
139                                           : iflags.wc_fontsiz_message;
140         lgfnt.lfHeight = -font_size * GetDeviceCaps(hdc, LOGPIXELSY)
141                          / 72;   // height of font
142         lgfnt.lfWidth = 0;       // average character width
143         lgfnt.lfEscapement = 0;  // angle of escapement
144         lgfnt.lfOrientation = 0; // base-line orientation angle
145         lgfnt.lfWeight = (attr == ATR_BOLD || attr == ATR_INVERSE)
146                              ? FW_BOLD
147                              : FW_NORMAL; // font weight
148         lgfnt.lfItalic =
149             (attr == ATR_BLINK) ? TRUE : FALSE; // italic attribute option
150         lgfnt.lfUnderline =
151             (attr == ATR_ULINE) ? TRUE : FALSE; // underline attribute option
152         lgfnt.lfStrikeOut = FALSE;              // strikeout attribute option
153         lgfnt.lfCharSet = mswin_charset();      // character set identifier
154         lgfnt.lfOutPrecision = OUT_DEFAULT_PRECIS;   // output precision
155         lgfnt.lfClipPrecision = CLIP_DEFAULT_PRECIS; // clipping precision
156         lgfnt.lfQuality = DEFAULT_QUALITY;           // output quality
157         if (iflags.wc_font_message && *iflags.wc_font_message) {
158             lgfnt.lfPitchAndFamily = DEFAULT_PITCH; // pitch and family
159             NH_A2W(iflags.wc_font_message, lgfnt.lfFaceName, LF_FACESIZE);
160         } else {
161             lgfnt.lfPitchAndFamily = VARIABLE_PITCH; // pitch and family
162         }
163         break;
164
165     case NHW_TEXT:
166         lgfnt.lfHeight = -iflags.wc_fontsiz_text
167                          * GetDeviceCaps(hdc, LOGPIXELSY)
168                          / 72;   // height of font
169         lgfnt.lfWidth = 0;       // average character width
170         lgfnt.lfEscapement = 0;  // angle of escapement
171         lgfnt.lfOrientation = 0; // base-line orientation angle
172         lgfnt.lfWeight = (attr == ATR_BOLD || attr == ATR_INVERSE)
173                              ? FW_BOLD
174                              : FW_NORMAL; // font weight
175         lgfnt.lfItalic =
176             (attr == ATR_BLINK) ? TRUE : FALSE; // italic attribute option
177         lgfnt.lfUnderline =
178             (attr == ATR_ULINE) ? TRUE : FALSE; // underline attribute option
179         lgfnt.lfStrikeOut = FALSE;              // strikeout attribute option
180         lgfnt.lfCharSet = mswin_charset();      // character set identifier
181         lgfnt.lfOutPrecision = OUT_DEFAULT_PRECIS;   // output precision
182         lgfnt.lfClipPrecision = CLIP_DEFAULT_PRECIS; // clipping precision
183         lgfnt.lfQuality = DEFAULT_QUALITY;           // output quality
184         if (iflags.wc_font_text && *iflags.wc_font_text) {
185             lgfnt.lfPitchAndFamily = DEFAULT_PITCH; // pitch and family
186             NH_A2W(iflags.wc_font_text, lgfnt.lfFaceName, LF_FACESIZE);
187         } else {
188             lgfnt.lfPitchAndFamily = FIXED_PITCH; // pitch and family
189         }
190         break;
191     }
192
193     fnt = CreateFontIndirect(&lgfnt);
194
195     /* add font to the table */
196     if (font_index == font_table_size) {
197         if (font_table_size >= MAXFONTS)
198             panic("font table overflow!");
199         font_table_size++;
200     } else {
201         DeleteObject(font_table[font_index].hFont);
202     }
203
204     font_table[font_index].code = NHFONT_CODE(win_type, attr);
205     font_table[font_index].hFont = fnt;
206     font_table[font_index].supportsUnicode = winos_font_support_cp437(fnt);
207
208     HGDIOBJ savedFont = SelectObject(hdc, fnt);
209     SIZE size;
210     GetTextExtentPoint32A(hdc, " ", 1, &size);
211     SelectObject(hdc, savedFont);
212
213     font_table[font_index].height = size.cy;
214     font_table[font_index].width = size.cx;
215
216     return &font_table[font_index];
217 }
218
219 UINT
220 mswin_charset()
221 {
222     CHARSETINFO cis;
223     if (SYMHANDLING(H_IBM))
224         if (TranslateCharsetInfo((DWORD *) (uintptr_t) GetOEMCP(), &cis, TCI_SRCCODEPAGE))
225             return cis.ciCharset;
226         else
227             return OEM_CHARSET;
228     else if (TranslateCharsetInfo((DWORD *) (uintptr_t) GetACP(), &cis, TCI_SRCCODEPAGE))
229         return cis.ciCharset;
230     else
231         return ANSI_CHARSET;
232 }
233
234 void __cdecl font_table_cleanup(void)
235 {
236     int i;
237     for (i = 0; i < font_table_size; i++) {
238         DeleteObject(font_table[i].hFont);
239     }
240     font_table_size = 0;
241 }