NetSurf
font.c
Go to the documentation of this file.
1/*
2 * Copyright 2009 - 2014 Vincent Sanders <vince@netsurf-browser.org>
3 * Copyright 2009 - 2013 Michael Drake <tlsa@netsurf-browser.org>
4 *
5 * This file is part of NetSurf, http://www.netsurf-browser.org/
6 *
7 * NetSurf is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * NetSurf is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20/**
21 * \file
22 * Windows font handling and character encoding implementation.
23 */
24
25#include "utils/config.h"
26#include <assert.h>
27#include <windows.h>
28
29#include "netsurf/inttypes.h"
30#include "utils/log.h"
31#include "utils/nsoption.h"
32#include "utils/utf8.h"
33#include "netsurf/layout.h"
34#include "netsurf/utf8.h"
35#include "netsurf/plot_style.h"
36
37#include "windows/font.h"
38
40
41/* exported interface documented in windows/font.h */
44 const char *string,
45 size_t len,
46 char **result)
47{
48 return utf8_to_enc(string, font->encoding, len, result);
49}
50
51
52/**
53 * Convert a string to UCS2 from UTF8
54 *
55 * \param[in] string source string
56 * \param[in] len source string length
57 * \param[out] result The UCS2 string
58 */
59static nserror
60utf8_to_local_encoding(const char *string, size_t len, char **result)
61{
62 return utf8_to_enc(string, "UCS-2", len, result);
63}
64
65
66/**
67 * Convert a string to UTF8 from local encoding
68 *
69 * \param[in] string source string
70 * \param[in] len source string length
71 * \param[out] result The UTF8 string
72 */
73static nserror
74utf8_from_local_encoding(const char *string, size_t len, char **result)
75{
76 assert(string && result);
77
78 if (len == 0) {
79 len = strlen(string);
80 }
81
82 *result = strndup(string, len);
83 if (!(*result)) {
84 return NSERROR_NOMEM;
85 }
86
87 return NSERROR_OK;
88}
89
90
91/* exported interface documented in windows/font.h */
92HFONT get_font(const plot_font_style_t *style)
93{
94 char *face = NULL;
95 DWORD family;
96 int nHeight;
97 HDC hdc;
98 HFONT font;
99
100 switch(style->family) {
102 face = strdup(nsoption_charp(font_serif));
103 family = FF_ROMAN | DEFAULT_PITCH;
104 break;
105
107 face = strdup(nsoption_charp(font_mono));
108 family = FF_MODERN | DEFAULT_PITCH;
109 break;
110
112 face = strdup(nsoption_charp(font_cursive));
113 family = FF_SCRIPT | DEFAULT_PITCH;
114 break;
115
117 face = strdup(nsoption_charp(font_fantasy));
118 family = FF_DECORATIVE | DEFAULT_PITCH;
119 break;
120
122 default:
123 face = strdup(nsoption_charp(font_sans));
124 family = FF_SWISS | DEFAULT_PITCH;
125 break;
126 }
127
128 nHeight = -10;
129
130 hdc = GetDC(font_hwnd);
131 nHeight = -MulDiv(style->size, GetDeviceCaps(hdc, LOGPIXELSY), 72 * PLOT_STYLE_SCALE);
132 ReleaseDC(font_hwnd, hdc);
133
134 font = CreateFont(nHeight, /* height */
135 0, /* width */
136 0, /* escapement*/
137 0, /* orientation */
138 style->weight,
139 (style->flags & FONTF_ITALIC) ? TRUE : FALSE,
140 FALSE, /* underline */
141 FALSE, /* strike */
142 DEFAULT_CHARSET, /* for locale */
143 OUT_DEFAULT_PRECIS, /* general 'best match' */
144 CLIP_DEFAULT_PRECIS,
145 DEFAULT_QUALITY,
146 family,
147 face); /* name of font face */
148
149 if (face != NULL) {
150 free(face);
151 }
152
153 if (font == NULL) {
154 if (style->family == PLOT_FONT_FAMILY_MONOSPACE) {
155 font = (HFONT) GetStockObject(ANSI_FIXED_FONT);
156 } else {
157 font = (HFONT) GetStockObject(ANSI_VAR_FONT);
158 }
159 }
160
161 if (font == NULL) {
162 font = (HFONT) GetStockObject(SYSTEM_FONT);
163 }
164
165 return font;
166}
167
168/* size of temporary wide character string for computing string width */
169#define WSTRLEN 4096
170
171
172/**
173 * Measure the width of a string.
174 *
175 * \param[in] style plot style for this text
176 * \param[in] utf8str string encoded in UTF-8 to measure
177 * \param[in] utf8len length of string, in bytes
178 * \param[out] width updated to width of string[0..length)
179 * \return NSERROR_OK on success otherwise appropriate error code
180 */
181static nserror
183 const char *utf8str,
184 size_t utf8len,
185 int *width)
186{
187 nserror ret = NSERROR_OK;
188 HDC hdc;
189 HFONT font;
190 HFONT fontbak;
191 SIZE sizl; /* size in logical units */
192 BOOL wres;
193 int wclen; /* wide char length */
194 static WCHAR wstr[WSTRLEN]; /* temporary wide char string */
195
196 if (utf8len == 0) {
197 *width = 0;
198 return ret;
199 }
200
201 hdc = GetDC(NULL);
202 font = get_font(style);
203 fontbak = SelectObject(hdc, font);
204
205 wclen = MultiByteToWideChar(CP_UTF8, 0, utf8str, utf8len, wstr, WSTRLEN);
206 if (wclen != 0) {
207 wres = GetTextExtentPoint32W(hdc, wstr, wclen, &sizl);
208 if (wres == FALSE) {
209 ret = NSERROR_INVALID;
210 } else {
211 *width = sizl.cx;
212 }
213 } else {
214 ret = NSERROR_NOSPACE;
215 }
216
217 font = SelectObject(hdc, fontbak);
218 DeleteObject(font);
219 ReleaseDC(NULL, hdc);
220
221 return ret;
222}
223
224
225/**
226 * Find the position in a string where an x coordinate falls.
227 *
228 * \param style css_style for this text, with style->font_size.size ==
229 * CSS_FONT_SIZE_LENGTH
230 * \param utf8str string to measure encoded in UTF-8
231 * \param utf8len length of string
232 * \param x coordinate to search for
233 * \param char_offset updated to offset in string of actual_x, [0..length]
234 * \param actual_x updated to x coordinate of character closest to x
235 * \return NSERROR_OK on success otherwise appropriate error code
236 */
237static nserror
239 const char *utf8str,
240 size_t utf8len,
241 int x,
242 size_t *char_offset,
243 int *actual_x)
244{
245 HDC hdc;
246 HFONT font;
247 HFONT fontbak;
248 SIZE s;
249 int offset;
250 nserror ret = NSERROR_OK;
251
252 /* deal with zero length input or invalid search co-ordiate */
253 if ((utf8len == 0) || (x < 1)) {
254 *char_offset = 0;
255 *actual_x = 0;
256 return ret;
257 }
258
259 hdc = GetDC(NULL);
260 font = get_font(style);
261 fontbak = SelectObject(hdc, font);
262
263 if ((GetTextExtentExPointA(hdc, utf8str, utf8len, x, &offset, NULL, &s) != 0) &&
264 (GetTextExtentPoint32A(hdc, utf8str, offset, &s) != 0)) {
265 *char_offset = (size_t)offset;
266 *actual_x = s.cx;
267 } else {
268 ret = NSERROR_UNKNOWN;
269 }
270
271 font = SelectObject(hdc, fontbak);
272 DeleteObject(font);
273 ReleaseDC(NULL, hdc);
274
275 return ret;
276}
277
278
279/**
280 * Find where to split a string to make it fit a width.
281 *
282 * \param style css_style for this text, with style->font_size.size ==
283 * CSS_FONT_SIZE_LENGTH
284 * \param string UTF-8 string to measure
285 * \param length length of string
286 * \param x width available
287 * \param[out] offset updated to offset in string of actual_x, [0..length]
288 * \param actual_x updated to x coordinate of character closest to x
289 * \return NSERROR_OK on success otherwise appropriate error code
290 *
291 * On exit, [char_offset == 0 ||
292 * string[char_offset] == ' ' ||
293 * char_offset == length]
294 */
295static nserror
297 const char *string,
298 size_t length,
299 int x,
300 size_t *offset,
301 int *actual_x)
302{
303 nserror res;
304 int c_off;
305
306 /* get the offset into teh string on the proposed position */
307 res = win32_font_position(style, string, length, x, offset, actual_x);
308 if (res != NSERROR_OK) {
309 return res;
310 }
311
312 /* return the whole string fits in the proposed length */
313 if (*offset == length) {
314 return NSERROR_OK;
315 }
316
317 c_off = *offset;
318
319 /* walk backwards through string looking for space to break on */
320 while ((string[*offset] != ' ') &&
321 (*offset > 0)) {
322 (*offset)--;
323 }
324
325 /* walk forwards through string looking for space if back failed */
326 if (*offset == 0) {
327 *offset = c_off;
328 while ((*offset < length) &&
329 (string[*offset] != ' ')) {
330 (*offset)++;
331 }
332 }
333
334 /* find the actual string width of the break */
335 res = win32_font_width(style, string, *offset, actual_x);
336
337 NSLOG(netsurf, DEEPDEBUG,
338 "ret %d Split %u chars at %ipx: Split at char %i (%ipx) - %.*s",
339 res, length, x, *offset, *actual_x, *offset, string);
340
341 return res;
342}
343
344
345/** win32 font operations table */
348 .position = win32_font_position,
349 .split = win32_font_split,
350};
351
353
354/** win32 utf8 encoding operations table */
355static struct gui_utf8_table utf8_table = {
357 .local_to_utf8 = utf8_from_local_encoding,
358};
359
STATIC char result[100]
Definition: arexx.c:77
char * strndup(const char *s, size_t n)
Duplicate up to n characters of a string.
Definition: utils.c:332
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_NOSPACE
Insufficient space.
Definition: errors.h:59
@ NSERROR_UNKNOWN
Unknown error - DO NOT USE.
Definition: errors.h:31
@ NSERROR_INVALID
Invalid data.
Definition: errors.h:49
@ NSERROR_NOMEM
Memory exhaustion.
Definition: errors.h:32
@ NSERROR_OK
No error.
Definition: errors.h:30
static nserror win32_font_width(const plot_font_style_t *style, const char *utf8str, size_t utf8len, int *width)
Measure the width of a string.
Definition: font.c:182
static nserror utf8_from_local_encoding(const char *string, size_t len, char **result)
Convert a string to UTF8 from local encoding.
Definition: font.c:74
#define WSTRLEN
Definition: font.c:169
static nserror utf8_to_local_encoding(const char *string, size_t len, char **result)
Convert a string to UCS2 from UTF8.
Definition: font.c:60
HWND font_hwnd
Definition: font.c:39
static struct gui_utf8_table utf8_table
win32 utf8 encoding operations table
Definition: font.c:355
struct gui_utf8_table * win32_utf8_table
Definition: font.c:360
nserror utf8_to_font_encoding(const struct font_desc *font, const char *string, size_t len, char **result)
convert from utf-8 to win32 font encoding.
Definition: font.c:43
static nserror win32_font_position(const plot_font_style_t *style, const char *utf8str, size_t utf8len, int x, size_t *char_offset, int *actual_x)
Find the position in a string where an x coordinate falls.
Definition: font.c:238
struct gui_layout_table * win32_layout_table
Definition: font.c:352
HFONT get_font(const plot_font_style_t *style)
Definition: font.c:92
static struct gui_layout_table layout_table
win32 font operations table
Definition: font.c:346
static nserror win32_font_split(const plot_font_style_t *style, const char *string, size_t length, int x, size_t *offset, int *actual_x)
Find where to split a string to make it fit a width.
Definition: font.c:296
The interface to the win32 font and utf8 handling.
Interface to platform-specific layout operation table.
Interface to platform-specific utf8 operations.
Netsurf additional integer type formatting macros.
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
plotter style interfaces, generic styles and style colour helpers.
@ FONTF_ITALIC
Definition: plot_style.h:103
@ PLOT_FONT_FAMILY_CURSIVE
Definition: plot_style.h:92
@ PLOT_FONT_FAMILY_SANS_SERIF
Definition: plot_style.h:89
@ PLOT_FONT_FAMILY_FANTASY
Definition: plot_style.h:93
@ PLOT_FONT_FAMILY_MONOSPACE
Definition: plot_style.h:91
@ PLOT_FONT_FAMILY_SERIF
Definition: plot_style.h:90
#define PLOT_STYLE_SCALE
Scaling factor for plot styles.
Definition: plot_style.h:45
int width
Definition: gui.c:159
const char * encoding
Definition: font_freetype.h:45
nserror(* width)(const struct plot_font_style *fstyle, const char *string, size_t length, int *width)
Measure the width of a string.
Definition: layout.h:49
User interface utf8 characterset conversion routines.
Definition: utf8.h:31
nserror(* utf8_to_local)(const char *string, size_t len, char **result)
Convert a UTF-8 encoded string into the system local encoding.
Definition: utf8.h:40
Font style for plotting.
Definition: plot_style.h:111
plot_font_generic_family_t family
Generic family to plot with.
Definition: plot_style.h:118
plot_font_flags_t flags
Font flags.
Definition: plot_style.h:121
plot_style_fixed size
Font size, in pt.
Definition: plot_style.h:119
int weight
Font weight: value in range [100,900] as per CSS.
Definition: plot_style.h:120
Option reading and saving interface.
#define nsoption_charp(OPTION)
Get the value of a string option.
Definition: nsoption.h:297
nserror utf8_to_enc(const char *string, const char *encname, size_t len, char **result)
Convert a UTF8 string into the named encoding.
Definition: utf8.c:314
UTF-8 manipulation functions (interface).