Commit | Line | Data |
---|---|---|
7b416d42 | 1 | /* Implementation of BDF font handling on the Microsoft W32 API. |
aaef169d TTN |
2 | Copyright (C) 1999, 2002, 2003, 2004, 2005, |
3 | 2006 Free Software Foundation, Inc. | |
7b416d42 GV |
4 | |
5 | This file is part of GNU Emacs. | |
6 | ||
7 | GNU Emacs 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; either version 2, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GNU Emacs is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GNU Emacs; see the file COPYING. If not, write to | |
4fc5845f LK |
19 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
20 | Boston, MA 02110-1301, USA. */ | |
7b416d42 GV |
21 | |
22 | /* Based heavily on code by H. Miyashita for Meadow (a descendant of | |
23 | MULE for W32). */ | |
24 | ||
25 | #include <windows.h> | |
4838e624 PJ |
26 | |
27 | #ifdef HAVE_CONFIG_H | |
28 | #include <config.h> | |
29 | #endif | |
30 | ||
7b416d42 GV |
31 | #include "lisp.h" |
32 | #include "charset.h" | |
dddcbf00 | 33 | #include "keyboard.h" |
683e946e JR |
34 | #include "frame.h" |
35 | #include "dispextern.h" | |
7b416d42 GV |
36 | #include "fontset.h" |
37 | #include "blockinput.h" | |
38 | #include "w32gui.h" | |
39 | #include "w32term.h" | |
40 | #include "w32bdf.h" | |
41 | ||
264f0aa7 JR |
42 | /* 10 planes */ |
43 | #define BDF_CODEPOINT_HEAP_INITIAL_SIZE (96 * 10) | |
44 | /* about 96 characters */ | |
45 | #define BDF_BITMAP_HEAP_INITIAL_SIZE (64 * 96) | |
46 | ||
47 | HANDLE hbdf_cp_heap = INVALID_HANDLE_VALUE; | |
48 | HANDLE hbdf_bmp_heap = INVALID_HANDLE_VALUE; | |
9c332a80 | 49 | |
7b416d42 GV |
50 | void w32_free_bdf_font(bdffont *fontp); |
51 | bdffont *w32_init_bdf_font(char *filename); | |
52 | ||
264f0aa7 JR |
53 | cache_bitmap cached_bitmap_slots[BDF_FONT_CACHE_SIZE]; |
54 | cache_bitmap *pcached_bitmap_latest = cached_bitmap_slots; | |
55 | ||
56 | #define FONT_CACHE_SLOT_OVER_P(p) ((p) >= cached_bitmap_slots + BDF_FONT_CACHE_SIZE) | |
57 | ||
177c0ea7 | 58 | static int |
7b416d42 GV |
59 | search_file_line(char *key, char *start, int len, char **val, char **next) |
60 | { | |
486a1063 JR |
61 | unsigned int linelen; |
62 | unsigned char *p; | |
7b416d42 GV |
63 | |
64 | p = memchr(start, '\n', len); | |
65 | if (!p) return -1; | |
dddcbf00 | 66 | for (;(unsigned char *)start < p;start++) |
7b416d42 | 67 | { |
264f0aa7 | 68 | if ((*start != ' ') && (*start != '\t')) break; |
7b416d42 | 69 | } |
00422310 | 70 | linelen = (char *) p - start + 1; |
7b416d42 GV |
71 | *next = p + 1; |
72 | if (strncmp(start, key, min(strlen(key), linelen)) == 0) | |
73 | { | |
74 | *val = start + strlen(key); | |
75 | return 1; | |
76 | } | |
177c0ea7 | 77 | |
7b416d42 GV |
78 | return 0; |
79 | } | |
80 | ||
81 | static int | |
82 | proceed_file_line(char *key, char *start, int *len, char **val, char **next) | |
83 | { | |
84 | int flag = 0; | |
85 | ||
86 | do { | |
87 | flag = search_file_line(key, start, *len, val, next); | |
88 | *len -= (int)(*next - start); | |
89 | start = *next; | |
90 | }while(flag == 0); | |
91 | ||
92 | if (flag == -1) return 0; | |
93 | return 1; | |
94 | } | |
264f0aa7 | 95 | |
865203c3 GV |
96 | char* |
97 | get_quoted_string(char *start, char *end) | |
98 | { | |
99 | char *p, *q, *result; | |
100 | ||
101 | p = memchr(start, '\"', end - start); | |
865203c3 GV |
102 | if (!p) return NULL; |
103 | p++; | |
264f0aa7 | 104 | q = memchr(p, '\"', end - p); |
865203c3 GV |
105 | if (!q) return NULL; |
106 | ||
107 | result = (char*) xmalloc(q - p + 1); | |
108 | ||
109 | memcpy(result, p, q - p); | |
110 | result[q - p] = '\0'; | |
111 | ||
112 | return result; | |
113 | } | |
114 | ||
7b416d42 GV |
115 | static int |
116 | set_bdf_font_info(bdffont *fontp) | |
117 | { | |
264f0aa7 | 118 | unsigned char *start, *p, *q; |
7b416d42 GV |
119 | int len, flag; |
120 | int bbw, bbh, bbx, bby; | |
121 | int val1; | |
122 | ||
123 | len = fontp->size; | |
124 | start = fontp->font; | |
125 | ||
126 | fontp->yoffset = 0; | |
127 | fontp->relative_compose = 0; | |
128 | fontp->default_ascent = 0; | |
264f0aa7 | 129 | |
865203c3 GV |
130 | fontp->registry = NULL; |
131 | fontp->encoding = NULL; | |
132 | fontp->slant = NULL; | |
133 | /* fontp->width = NULL; */ | |
7b416d42 | 134 | |
dddcbf00 EZ |
135 | flag = proceed_file_line("FONTBOUNDINGBOX", start, &len, |
136 | (char **)&p, (char **)&q); | |
7b416d42 | 137 | if (!flag) return 0; |
dddcbf00 | 138 | bbw = strtol(p, (char **)&start, 10); |
7b416d42 | 139 | p = start; |
dddcbf00 | 140 | bbh = strtol(p, (char **)&start, 10); |
7b416d42 | 141 | p = start; |
dddcbf00 | 142 | bbx = strtol(p, (char **)&start, 10); |
7b416d42 | 143 | p = start; |
dddcbf00 | 144 | bby = strtol(p, (char **)&start, 10); |
7b416d42 GV |
145 | |
146 | fontp->llx = bbx; | |
147 | fontp->lly = bby; | |
148 | fontp->urx = bbw + bbx; | |
149 | fontp->ury = bbh + bby; | |
150 | fontp->width = bbw; | |
151 | fontp->height = bbh; | |
152 | start = q; | |
dddcbf00 EZ |
153 | flag = proceed_file_line("STARTPROPERTIES", start, &len, |
154 | (char **)&p, (char **)&q); | |
7b416d42 GV |
155 | if (!flag) return 1; |
156 | ||
865203c3 GV |
157 | flag = 0; |
158 | ||
7b416d42 GV |
159 | do { |
160 | start = q; | |
dddcbf00 EZ |
161 | if (search_file_line("PIXEL_SIZE", start, len, |
162 | (char **)&p, (char **)&q) == 1) | |
7b416d42 GV |
163 | { |
164 | val1 = atoi(p); | |
165 | fontp->pixsz = val1; | |
166 | } | |
dddcbf00 EZ |
167 | else if (search_file_line("FONT_ASCENT", start, len, |
168 | (char **)&p, (char **)&q) == 1) | |
7b416d42 GV |
169 | { |
170 | val1 = atoi(p); | |
171 | fontp->ury = val1; | |
172 | } | |
dddcbf00 EZ |
173 | else if (search_file_line("FONT_DESCENT", start, len, |
174 | (char **)&p, (char **)&q) == 1) | |
7b416d42 GV |
175 | { |
176 | val1 = atoi(p); | |
177 | fontp->lly = -val1; | |
178 | } | |
dddcbf00 EZ |
179 | else if (search_file_line("_MULE_BASELINE_OFFSET", start, len, |
180 | (char **)&p, (char **)&q) == 1) | |
7b416d42 GV |
181 | { |
182 | val1 = atoi(p); | |
264f0aa7 | 183 | fontp->yoffset = -val1; |
7b416d42 | 184 | } |
dddcbf00 EZ |
185 | else if (search_file_line("_MULE_RELATIVE_COMPOSE", start, len, |
186 | (char **)&p, (char **)&q) == 1) | |
7b416d42 GV |
187 | { |
188 | val1 = atoi(p); | |
189 | fontp->relative_compose = val1; | |
190 | } | |
dddcbf00 EZ |
191 | else if (search_file_line("_MULE_DEFAULT_ASCENT", start, len, |
192 | (char **)&p, (char **)&q) == 1) | |
7b416d42 GV |
193 | { |
194 | val1 = atoi(p); | |
195 | fontp->default_ascent = val1; | |
196 | } | |
dddcbf00 EZ |
197 | else if (search_file_line("CHARSET_REGISTRY", start, len, |
198 | (char **)&p, (char **)&q) == 1) | |
865203c3 GV |
199 | { |
200 | fontp->registry = get_quoted_string(p, q); | |
201 | } | |
dddcbf00 EZ |
202 | else if (search_file_line("CHARSET_ENCODING", start, len, |
203 | (char **)&p, (char **)&q) == 1) | |
865203c3 GV |
204 | { |
205 | fontp->encoding = get_quoted_string(p, q); | |
206 | } | |
dddcbf00 EZ |
207 | else if (search_file_line("SLANT", start, len, |
208 | (char **)&p, (char **)&q) == 1) | |
865203c3 GV |
209 | { |
210 | fontp->slant = get_quoted_string(p, q); | |
211 | } | |
212 | /* | |
dddcbf00 EZ |
213 | else if (search_file_line("SETWIDTH_NAME", start, len, |
214 | (char **)&p, (char **)&q) == 1) | |
865203c3 GV |
215 | { |
216 | fontp->width = get_quoted_string(p, q); | |
217 | } | |
218 | */ | |
7b416d42 GV |
219 | else |
220 | { | |
dddcbf00 EZ |
221 | flag = search_file_line("ENDPROPERTIES", start, len, |
222 | (char **)&p, (char **)&q); | |
7b416d42 GV |
223 | } |
224 | if (flag == -1) return 0; | |
225 | len -= (q - start); | |
226 | }while(flag == 0); | |
227 | start = q; | |
dddcbf00 | 228 | flag = proceed_file_line("CHARS", start, &len, (char **)&p, (char **)&q); |
7b416d42 | 229 | if (!flag) return 0; |
691a3cb7 | 230 | fontp->nchars = atoi(p); |
7b416d42 GV |
231 | fontp->seeked = q; |
232 | ||
233 | return 1; | |
234 | } | |
235 | ||
236 | bdffont* | |
237 | w32_init_bdf_font(char *filename) | |
238 | { | |
239 | HANDLE hfile, hfilemap; | |
240 | bdffont *bdffontp; | |
241 | unsigned char *font; | |
242 | BY_HANDLE_FILE_INFORMATION fileinfo; | |
243 | int i; | |
244 | ||
264f0aa7 JR |
245 | if (hbdf_cp_heap == INVALID_HANDLE_VALUE) |
246 | hbdf_cp_heap = HeapCreate(0, BDF_CODEPOINT_HEAP_INITIAL_SIZE, 0); | |
3e27fa1f | 247 | if (hbdf_bmp_heap == INVALID_HANDLE_VALUE) |
264f0aa7 JR |
248 | hbdf_bmp_heap = HeapCreate(0, BDF_BITMAP_HEAP_INITIAL_SIZE, 0); |
249 | ||
250 | if (!hbdf_cp_heap || !hbdf_bmp_heap) | |
7c402969 | 251 | error("Fail to create heap for BDF"); |
264f0aa7 | 252 | |
7b416d42 GV |
253 | hfile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, |
254 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
255 | if (hfile == INVALID_HANDLE_VALUE) return NULL; | |
256 | if (!GetFileInformationByHandle(hfile, &fileinfo) || | |
257 | (fileinfo.nFileSizeHigh != 0) || | |
258 | (fileinfo.nFileSizeLow > BDF_FILE_SIZE_MAX)) | |
259 | { | |
260 | CloseHandle(hfile); | |
7c402969 | 261 | error("Fail to open BDF file"); |
7b416d42 GV |
262 | } |
263 | hfilemap = CreateFileMapping(hfile, NULL, PAGE_READONLY, 0, 0, NULL); | |
264 | if (hfilemap == INVALID_HANDLE_VALUE) | |
265 | { | |
266 | CloseHandle(hfile); | |
7c402969 | 267 | error("Can't map font"); |
7b416d42 GV |
268 | } |
269 | ||
270 | font = MapViewOfFile(hfilemap, FILE_MAP_READ, 0, 0, 0); | |
271 | ||
272 | if (!font) | |
273 | { | |
274 | CloseHandle(hfile); | |
275 | CloseHandle(hfilemap); | |
7c402969 | 276 | error("Can't view font"); |
7b416d42 GV |
277 | } |
278 | ||
279 | bdffontp = (bdffont *) xmalloc(sizeof(bdffont)); | |
177c0ea7 | 280 | |
7b416d42 | 281 | for(i = 0;i < BDF_FIRST_OFFSET_TABLE;i++) |
865203c3 | 282 | bdffontp->chtbl[i] = NULL; |
7b416d42 GV |
283 | bdffontp->size = fileinfo.nFileSizeLow; |
284 | bdffontp->font = font; | |
285 | bdffontp->hfile = hfile; | |
286 | bdffontp->hfilemap = hfilemap; | |
287 | bdffontp->filename = (char*) xmalloc(strlen(filename) + 1); | |
288 | strcpy(bdffontp->filename, filename); | |
177c0ea7 | 289 | |
7b416d42 GV |
290 | if (!set_bdf_font_info(bdffontp)) |
291 | { | |
292 | w32_free_bdf_font(bdffontp); | |
293 | error("Invalid BDF font!"); | |
294 | } | |
295 | return bdffontp; | |
296 | } | |
297 | ||
298 | void | |
299 | w32_free_bdf_font(bdffont *fontp) | |
300 | { | |
865203c3 GV |
301 | int i, j; |
302 | font_char *pch; | |
303 | cache_bitmap *pcb; | |
7b416d42 GV |
304 | |
305 | UnmapViewOfFile(fontp->hfilemap); | |
306 | CloseHandle(fontp->hfilemap); | |
307 | CloseHandle(fontp->hfile); | |
865203c3 GV |
308 | |
309 | if (fontp->registry) xfree(fontp->registry); | |
310 | if (fontp->encoding) xfree(fontp->encoding); | |
311 | if (fontp->slant) xfree(fontp->slant); | |
312 | /* if (fontp->width) xfree(fontp->width); */ | |
313 | ||
7b416d42 GV |
314 | xfree(fontp->filename); |
315 | for(i = 0;i < BDF_FIRST_OFFSET_TABLE;i++) | |
316 | { | |
865203c3 GV |
317 | pch = fontp->chtbl[i]; |
318 | if (pch) | |
319 | { | |
320 | for (j = 0;j < BDF_SECOND_OFFSET_TABLE;j++) | |
321 | { | |
322 | pcb = pch[j].pcbmp; | |
264f0aa7 JR |
323 | if (pcb) |
324 | { | |
325 | if (pcb->pbmp) | |
326 | HeapFree(hbdf_bmp_heap, 0, pcb->pbmp); | |
327 | pcb->psrc = NULL; | |
865203c3 | 328 | } |
264f0aa7 JR |
329 | } |
330 | HeapFree(hbdf_cp_heap, 0, pch); | |
865203c3 | 331 | } |
7b416d42 GV |
332 | } |
333 | xfree(fontp); | |
334 | } | |
335 | ||
865203c3 GV |
336 | static font_char* |
337 | get_cached_font_char(bdffont *fontp, int index) | |
7b416d42 | 338 | { |
865203c3 | 339 | font_char *pch, *result; |
7b416d42 | 340 | |
264f0aa7 | 341 | if (!BDF_CODEPOINT_RANGE_COVER_P(index)) |
7b416d42 GV |
342 | return NULL; |
343 | ||
865203c3 GV |
344 | pch = fontp->chtbl[BDF_FIRST_OFFSET(index)]; |
345 | if (!pch) | |
7b416d42 | 346 | return NULL; |
264f0aa7 | 347 | |
865203c3 | 348 | result = &pch[BDF_SECOND_OFFSET(index)]; |
7b416d42 | 349 | |
865203c3 | 350 | if (!result->offset) return NULL; |
7b416d42 | 351 | |
865203c3 | 352 | return result; |
7b416d42 GV |
353 | } |
354 | ||
865203c3 | 355 | static font_char* |
7b416d42 GV |
356 | cache_char_offset(bdffont *fontp, int index, unsigned char *offset) |
357 | { | |
865203c3 | 358 | font_char *pch, *result; |
7b416d42 | 359 | |
264f0aa7 | 360 | if (!BDF_CODEPOINT_RANGE_COVER_P(index)) |
865203c3 | 361 | return NULL; |
7b416d42 | 362 | |
865203c3 GV |
363 | pch = fontp->chtbl[BDF_FIRST_OFFSET(index)]; |
364 | if (!pch) | |
7b416d42 | 365 | { |
865203c3 | 366 | pch = fontp->chtbl[BDF_FIRST_OFFSET(index)] = |
264f0aa7 | 367 | (font_char*) HeapAlloc(hbdf_cp_heap, |
177c0ea7 | 368 | HEAP_ZERO_MEMORY, |
264f0aa7 JR |
369 | sizeof(font_char) * |
370 | BDF_SECOND_OFFSET_TABLE); | |
371 | if (!pch) return NULL; | |
372 | /* memset(pch, 0, sizeof(font_char) * BDF_SECOND_OFFSET_TABLE); */ | |
7b416d42 | 373 | } |
7b416d42 | 374 | |
865203c3 GV |
375 | result = &pch[BDF_SECOND_OFFSET(index)]; |
376 | result->offset = offset; | |
377 | ||
378 | return result; | |
7b416d42 GV |
379 | } |
380 | ||
865203c3 GV |
381 | static font_char* |
382 | seek_char(bdffont *fontp, int index) | |
7b416d42 | 383 | { |
865203c3 | 384 | font_char *result; |
7b416d42 | 385 | int len, flag, font_index; |
264f0aa7 | 386 | unsigned char *start, *p, *q; |
7b416d42 GV |
387 | |
388 | if (!fontp->seeked) return NULL; | |
389 | ||
390 | start = fontp->seeked; | |
391 | len = fontp->size - (start - fontp->font); | |
392 | ||
393 | do { | |
dddcbf00 EZ |
394 | flag = proceed_file_line("ENCODING", start, &len, |
395 | (char **)&p, (char **)&q); | |
7b416d42 GV |
396 | if (!flag) |
397 | { | |
398 | fontp->seeked = NULL; | |
399 | return NULL; | |
400 | } | |
401 | font_index = atoi(p); | |
865203c3 GV |
402 | result = cache_char_offset(fontp, font_index, q); |
403 | if (!result) return NULL; | |
404 | ||
405 | start = result->offset; | |
7b416d42 | 406 | } while (font_index != index); |
865203c3 | 407 | fontp->seeked = start; |
7b416d42 | 408 | |
865203c3 GV |
409 | return result; |
410 | } | |
411 | ||
264f0aa7 JR |
412 | static void |
413 | clear_cached_bitmap_slots() | |
414 | { | |
415 | int i; | |
416 | cache_bitmap *p; | |
417 | ||
418 | p = pcached_bitmap_latest; | |
419 | for (i = 0;i < BDF_FONT_CLEAR_SIZE;i++) | |
420 | { | |
421 | if (p->psrc) | |
422 | { | |
423 | if (p->pbmp) | |
424 | HeapFree(hbdf_bmp_heap, 0, p->pbmp); | |
425 | p->psrc->pcbmp = NULL; | |
426 | p->psrc = NULL; | |
427 | } | |
428 | p++; | |
429 | if (FONT_CACHE_SLOT_OVER_P(p)) | |
430 | p = cached_bitmap_slots; | |
431 | } | |
432 | } | |
433 | ||
7b416d42 | 434 | #define GET_HEX_VAL(x) ((isdigit(x)) ? ((x) - '0') : \ |
264f0aa7 JR |
435 | (((x) >= 'A') && ((x) <= 'F')) ? ((x) - 'A' + 10) : \ |
436 | (((x) >= 'a') && ((x) <= 'f')) ? ((x) - 'a' + 10) : \ | |
7b416d42 GV |
437 | (-1)) |
438 | ||
439 | int | |
440 | w32_get_bdf_glyph(bdffont *fontp, int index, int size, glyph_struct *glyph) | |
441 | { | |
865203c3 | 442 | font_char *pch; |
264f0aa7 JR |
443 | unsigned char *start, *p, *q, *bitmapp; |
444 | unsigned char val, val1, val2; | |
445 | int i, j, len, flag, consumed; | |
446 | int align, rowbytes; | |
7b416d42 | 447 | |
865203c3 GV |
448 | pch = get_cached_font_char(fontp, index); |
449 | if (!pch) | |
450 | { | |
451 | pch = seek_char(fontp, index); | |
452 | if (!pch) | |
453 | return 0; | |
454 | } | |
455 | ||
456 | start = pch->offset; | |
457 | ||
458 | if ((size == 0) && pch->pcbmp) | |
459 | { | |
460 | glyph->metric = pch->pcbmp->metric; | |
461 | return 1; | |
462 | } | |
7b416d42 GV |
463 | |
464 | len = fontp->size - (start - fontp->font); | |
465 | ||
dddcbf00 | 466 | flag = proceed_file_line("DWIDTH", start, &len, (char **)&p, (char **)&q); |
7b416d42 GV |
467 | if (!flag) |
468 | return 0; | |
865203c3 | 469 | glyph->metric.dwidth = atoi(p); |
7b416d42 GV |
470 | |
471 | start = q; | |
dddcbf00 | 472 | flag = proceed_file_line("BBX", start, &len, (char **)&p, (char **)&q); |
7b416d42 GV |
473 | if (!flag) |
474 | return 0; | |
dddcbf00 | 475 | glyph->metric.bbw = strtol(p, (char **)&start, 10); |
7b416d42 | 476 | p = start; |
dddcbf00 | 477 | glyph->metric.bbh = strtol(p, (char **)&start, 10); |
7b416d42 | 478 | p = start; |
dddcbf00 | 479 | glyph->metric.bbox = strtol(p, (char **)&start, 10); |
7b416d42 | 480 | p = start; |
dddcbf00 | 481 | glyph->metric.bboy = strtol(p, (char **)&start, 10); |
7b416d42 GV |
482 | |
483 | if (size == 0) return 1; | |
484 | ||
485 | start = q; | |
dddcbf00 | 486 | flag = proceed_file_line("BITMAP", start, &len, (char **)&p, (char **)&q); |
7b416d42 GV |
487 | if (!flag) |
488 | return 0; | |
489 | ||
264f0aa7 JR |
490 | consumed = 0; |
491 | flag = 0; | |
7b416d42 GV |
492 | p = q; |
493 | bitmapp = glyph->bitmap; | |
264f0aa7 JR |
494 | rowbytes = (glyph->metric.bbw + 7) / 8; |
495 | /* DIB requires DWORD alignment. */ | |
496 | align = sizeof(DWORD) - rowbytes % sizeof(DWORD); | |
497 | consumed = glyph->metric.bbh * (rowbytes + align); | |
498 | glyph->bitmap_size = consumed; | |
499 | glyph->row_byte_size = rowbytes; | |
500 | if (size < consumed) return 0; | |
501 | ||
865203c3 | 502 | for(i = 0;i < glyph->metric.bbh;i++) |
7b416d42 GV |
503 | { |
504 | q = memchr(p, '\n', len); | |
505 | if (!q) return 0; | |
264f0aa7 | 506 | for(j = 0;((q > p) && (j < rowbytes));j++) |
7b416d42 | 507 | { |
dddcbf00 EZ |
508 | int ival = GET_HEX_VAL(*p); |
509 | ||
510 | if (ival == -1) return 0; | |
511 | val1 = ival; | |
7b416d42 | 512 | p++; |
dddcbf00 EZ |
513 | ival = GET_HEX_VAL(*p); |
514 | if (ival == -1) return 0; | |
515 | val2 = ival; | |
7b416d42 | 516 | p++; |
264f0aa7 JR |
517 | val = (unsigned char)((val1 << 4) | val2); |
518 | if (val) flag = 1; | |
519 | *bitmapp++ = val; | |
7b416d42 | 520 | } |
264f0aa7 JR |
521 | for(j = 0;j < align;j++) |
522 | *bitmapp++ = 0x00; | |
7b416d42 GV |
523 | p = q + 1; |
524 | } | |
525 | ||
264f0aa7 JR |
526 | /* If this glyph is white space, return -1. */ |
527 | if (flag == 0) return -1; | |
7b416d42 | 528 | |
264f0aa7 JR |
529 | return consumed; |
530 | } | |
9c332a80 | 531 | |
865203c3 GV |
532 | static |
533 | cache_bitmap* | |
534 | get_bitmap_with_cache(bdffont *fontp, int index) | |
535 | { | |
264f0aa7 | 536 | int bitmap_size, bitmap_real_size; |
865203c3 GV |
537 | font_char *pch; |
538 | cache_bitmap* pcb; | |
264f0aa7 | 539 | unsigned char *pbmp; |
865203c3 GV |
540 | glyph_struct glyph; |
541 | ||
542 | pch = get_cached_font_char(fontp, index); | |
543 | if (pch) | |
544 | { | |
545 | pcb = pch->pcbmp; | |
546 | if (pcb) return pcb; | |
547 | } | |
548 | ||
264f0aa7 | 549 | bitmap_size = ((fontp->urx - fontp->llx) / 8 + 3) * (fontp->ury - fontp->lly) |
865203c3 GV |
550 | + 256; |
551 | glyph.bitmap = (unsigned char*) alloca(sizeof(unsigned char) * bitmap_size); | |
552 | ||
264f0aa7 JR |
553 | bitmap_real_size = w32_get_bdf_glyph(fontp, index, bitmap_size, &glyph); |
554 | ||
555 | if (bitmap_real_size == 0) | |
865203c3 GV |
556 | return NULL; |
557 | ||
558 | pch = get_cached_font_char(fontp, index); | |
559 | if (!pch) return NULL; | |
560 | ||
264f0aa7 | 561 | if (bitmap_real_size > 0) |
9c332a80 | 562 | { |
264f0aa7 JR |
563 | pbmp = (unsigned char*) HeapAlloc(hbdf_bmp_heap, 0, |
564 | bitmap_real_size); | |
565 | if (!pbmp) return NULL; | |
566 | memcpy(pbmp, glyph.bitmap, bitmap_real_size); | |
9c332a80 | 567 | } |
264f0aa7 JR |
568 | else |
569 | pbmp = NULL; /* white space character */ | |
9c332a80 | 570 | |
264f0aa7 JR |
571 | pcb = pcached_bitmap_latest; |
572 | if (pcb->psrc) | |
573 | clear_cached_bitmap_slots(); | |
865203c3 GV |
574 | |
575 | pcb->psrc = pch; | |
576 | pcb->metric = glyph.metric; | |
264f0aa7 JR |
577 | pcb->pbmp = pbmp; |
578 | pcb->bitmap_size = glyph.bitmap_size; | |
579 | pcb->row_byte_size = glyph.row_byte_size; | |
865203c3 GV |
580 | |
581 | pch->pcbmp = pcb; | |
177c0ea7 | 582 | |
264f0aa7 JR |
583 | pcached_bitmap_latest++; |
584 | if (FONT_CACHE_SLOT_OVER_P(pcached_bitmap_latest)) | |
585 | pcached_bitmap_latest = cached_bitmap_slots; | |
865203c3 GV |
586 | |
587 | return pcb; | |
588 | } | |
589 | ||
264f0aa7 JR |
590 | static HBITMAP |
591 | create_offscreen_bitmap(HDC hdc, int width, int height, unsigned char **bitsp) | |
592 | { | |
264f0aa7 JR |
593 | struct { |
594 | BITMAPINFOHEADER h; | |
595 | RGBQUAD c[2]; | |
596 | } info; | |
597 | ||
598 | memset(&info, 0, sizeof(info)); | |
599 | info.h.biSize = sizeof(BITMAPINFOHEADER); | |
600 | info.h.biWidth = width; | |
601 | info.h.biHeight = -height; | |
602 | info.h.biPlanes = 1; | |
603 | info.h.biBitCount = 1; | |
604 | info.h.biCompression = BI_RGB; | |
605 | info.c[1].rgbRed = info.c[1].rgbGreen = info.c[1].rgbBlue = 255; | |
606 | ||
607 | return CreateDIBSection(hdc, (LPBITMAPINFO)&info, | |
17757d66 | 608 | DIB_RGB_COLORS, (void **)bitsp, NULL, 0); |
264f0aa7 JR |
609 | } |
610 | ||
611 | glyph_metric * | |
612 | w32_BDF_TextMetric(bdffont *fontp, unsigned char *text, int dim) | |
613 | { | |
614 | int index; | |
615 | cache_bitmap *pcb; | |
616 | ||
617 | if (dim == 1) | |
618 | index = *text; | |
619 | else | |
620 | index = MAKELENDSHORT(text[1], text[0]); | |
621 | ||
622 | pcb = get_bitmap_with_cache(fontp, index); | |
623 | if (!pcb) | |
624 | return NULL; | |
625 | ||
626 | return &(pcb->metric); | |
627 | } | |
628 | ||
7b416d42 GV |
629 | int |
630 | w32_BDF_TextOut(bdffont *fontp, HDC hdc, int left, | |
631 | int top, unsigned char *text, int dim, int bytelen, | |
632 | int fixed_pitch_size) | |
633 | { | |
865203c3 | 634 | int index, btop; |
7b416d42 | 635 | unsigned char *textp; |
865203c3 | 636 | cache_bitmap *pcb; |
7b416d42 | 637 | HBRUSH hFgBrush, hOrgBrush; |
264f0aa7 | 638 | HANDLE horgobj; |
7b416d42 | 639 | UINT textalign; |
264f0aa7 JR |
640 | int width, height; |
641 | HDC hCompatDC; | |
642 | int ret = 1; | |
643 | static HBITMAP hBMP = 0; | |
644 | static HDC DIBsection_hdc = 0; | |
645 | static int DIBsection_width, DIBsection_height; | |
646 | static unsigned char *bits; | |
7b416d42 | 647 | |
7b416d42 | 648 | hCompatDC = CreateCompatibleDC(hdc); |
264f0aa7 JR |
649 | if (!hCompatDC) |
650 | return 0; | |
7b416d42 GV |
651 | |
652 | textalign = GetTextAlign(hdc); | |
177c0ea7 | 653 | |
7b416d42 GV |
654 | hFgBrush = CreateSolidBrush(GetTextColor(hdc)); |
655 | hOrgBrush = SelectObject(hdc, hFgBrush); | |
7b416d42 GV |
656 | |
657 | textp = text; | |
264f0aa7 | 658 | |
7b416d42 GV |
659 | while(bytelen > 0) |
660 | { | |
661 | if (dim == 1) | |
662 | { | |
663 | index = *textp++; | |
664 | bytelen--; | |
665 | } | |
666 | else | |
667 | { | |
668 | bytelen -= 2; | |
669 | if (bytelen < 0) break; | |
691a3cb7 | 670 | index = MAKELENDSHORT(textp[0], textp[1]); |
7b416d42 GV |
671 | textp += 2; |
672 | } | |
865203c3 GV |
673 | pcb = get_bitmap_with_cache(fontp, index); |
674 | if (!pcb) | |
7b416d42 | 675 | { |
264f0aa7 JR |
676 | ret = 0; |
677 | break; | |
7b416d42 | 678 | } |
264f0aa7 JR |
679 | if (pcb->pbmp) |
680 | { | |
681 | width = pcb->metric.bbw; | |
682 | height = pcb->metric.bbh; | |
177c0ea7 | 683 | |
264f0aa7 JR |
684 | if (!(hBMP |
685 | && (DIBsection_hdc == hdc) | |
686 | && (DIBsection_width == width) | |
687 | && (DIBsection_height == height))) | |
688 | { | |
689 | if (hBMP) DeleteObject(hBMP); | |
690 | hBMP = create_offscreen_bitmap(hdc, width, height, &bits); | |
691 | DIBsection_hdc = hdc; | |
692 | DIBsection_width = width; | |
693 | DIBsection_height = height; | |
694 | if (!hBMP) return 0; | |
7b416d42 | 695 | } |
264f0aa7 JR |
696 | |
697 | memcpy(bits, pcb->pbmp, pcb->bitmap_size); | |
865203c3 | 698 | |
7b416d42 | 699 | if (textalign & TA_BASELINE) |
865203c3 | 700 | btop = top - (pcb->metric.bbh + pcb->metric.bboy); |
7b416d42 | 701 | else if (textalign & TA_BOTTOM) |
865203c3 | 702 | btop = top - pcb->metric.bbh; |
7b416d42 | 703 | else |
7b416d42 | 704 | btop = top; |
7b416d42 | 705 | |
7b416d42 | 706 | horgobj = SelectObject(hCompatDC, hBMP); |
264f0aa7 JR |
707 | BitBlt(hdc, left, btop, width, height, hCompatDC, 0, 0, 0xE20746); |
708 | SelectObject(hCompatDC, horgobj); | |
709 | } | |
710 | ||
7b416d42 GV |
711 | if (fixed_pitch_size) |
712 | left += fixed_pitch_size; | |
713 | else | |
865203c3 | 714 | left += pcb->metric.dwidth; |
7b416d42 | 715 | } |
264f0aa7 JR |
716 | |
717 | DeleteDC(hCompatDC); | |
718 | ||
7b416d42 GV |
719 | SelectObject(hdc, hOrgBrush); |
720 | DeleteObject(hFgBrush); | |
7b416d42 | 721 | |
264f0aa7 | 722 | return ret; |
7b416d42 GV |
723 | } |
724 | ||
725 | struct font_info *w32_load_bdf_font (struct frame *f, char *fontname, | |
726 | int size, char* filename) | |
727 | { | |
728 | struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f); | |
729 | struct font_info *fontp; | |
730 | XFontStruct *font; | |
731 | bdffont* bdf_font; | |
732 | ||
733 | bdf_font = w32_init_bdf_font (filename); | |
734 | ||
735 | if (!bdf_font) return NULL; | |
736 | ||
737 | font = (XFontStruct *) xmalloc (sizeof (XFontStruct)); | |
00422310 | 738 | bzero (font, sizeof (*font)); |
7b416d42 GV |
739 | |
740 | font->bdf = bdf_font; | |
741 | font->hfont = 0; | |
742 | ||
691a3cb7 JR |
743 | /* NTEMACS_TODO: Better way of determining if a font is double byte |
744 | or not. */ | |
745 | font->double_byte_p = bdf_font->nchars > 255 ? 1 : 0; | |
ad784d76 | 746 | |
00422310 AI |
747 | w32_cache_char_metrics (font); |
748 | ||
7b416d42 GV |
749 | /* Do we need to create the table? */ |
750 | if (dpyinfo->font_table_size == 0) | |
751 | { | |
752 | dpyinfo->font_table_size = 16; | |
753 | dpyinfo->font_table | |
754 | = (struct font_info *) xmalloc (dpyinfo->font_table_size | |
755 | * sizeof (struct font_info)); | |
756 | } | |
757 | /* Do we need to grow the table? */ | |
758 | else if (dpyinfo->n_fonts | |
759 | >= dpyinfo->font_table_size) | |
760 | { | |
761 | dpyinfo->font_table_size *= 2; | |
762 | dpyinfo->font_table | |
763 | = (struct font_info *) xrealloc (dpyinfo->font_table, | |
764 | (dpyinfo->font_table_size | |
765 | * sizeof (struct font_info))); | |
766 | } | |
767 | ||
768 | fontp = dpyinfo->font_table + dpyinfo->n_fonts; | |
769 | ||
770 | /* Now fill in the slots of *FONTP. */ | |
771 | BLOCK_INPUT; | |
0d4c2dc2 | 772 | bzero (fontp, sizeof (*fontp)); |
7b416d42 GV |
773 | fontp->font = font; |
774 | fontp->font_idx = dpyinfo->n_fonts; | |
775 | fontp->name = (char *) xmalloc (strlen (fontname) + 1); | |
776 | bcopy (fontname, fontp->name, strlen (fontname) + 1); | |
777 | fontp->full_name = fontp->name; | |
a4d75ad7 JR |
778 | /* FIXME: look at BDF spec to see if there are better ways of finding |
779 | average_width and space_width, hopefully that don't involve working out | |
780 | the values for ourselves from the data. */ | |
781 | fontp->size = fontp->average_width = fontp->space_width = FONT_WIDTH (font); | |
7b416d42 GV |
782 | fontp->height = FONT_HEIGHT (font); |
783 | ||
784 | /* The slot `encoding' specifies how to map a character | |
785 | code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to | |
786 | the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F, | |
787 | the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, | |
788 | 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or | |
789 | 2:0xA020..0xFF7F). For the moment, we don't know which charset | |
790 | uses this font. So, we set informatoin in fontp->encoding[1] | |
791 | which is never used by any charset. If mapping can't be | |
792 | decided, set FONT_ENCODING_NOT_DECIDED. */ | |
793 | fontp->encoding[1] = FONT_ENCODING_NOT_DECIDED; | |
794 | fontp->baseline_offset = bdf_font->yoffset; | |
795 | fontp->relative_compose = bdf_font->relative_compose; | |
796 | fontp->default_ascent = bdf_font->default_ascent; | |
797 | ||
f7b9d4d1 JR |
798 | /* Set global flag fonts_changed_p to non-zero if the font loaded |
799 | has a character with a smaller width than any other character | |
800 | before, or if the font loaded has a smaller height than any | |
801 | other font loaded before. If this happens, it will make a | |
802 | glyph matrix reallocation necessary. */ | |
803 | fonts_changed_p |= x_compute_min_glyph_bounds (f); | |
804 | ||
7b416d42 GV |
805 | UNBLOCK_INPUT; |
806 | dpyinfo->n_fonts++; | |
807 | return fontp; | |
808 | } | |
809 | ||
19474e26 | 810 | /* Check a file for an XLFD string describing it. */ |
7b416d42 GV |
811 | int w32_BDF_to_x_font (char *file, char* xstr, int len) |
812 | { | |
813 | HANDLE hfile, hfilemap; | |
814 | BY_HANDLE_FILE_INFORMATION fileinfo; | |
cc26af75 | 815 | char *font, *start, *p, *q; |
7b416d42 GV |
816 | int flag, size, retval = 0; |
817 | ||
818 | hfile = CreateFile (file, GENERIC_READ, FILE_SHARE_READ, NULL, | |
819 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
820 | if (hfile == INVALID_HANDLE_VALUE) return 0; | |
821 | if (!GetFileInformationByHandle(hfile, &fileinfo) || | |
822 | (fileinfo.nFileSizeHigh != 0) || | |
823 | (fileinfo.nFileSizeLow > BDF_FILE_SIZE_MAX)) | |
824 | { | |
825 | CloseHandle (hfile); | |
826 | return 0; | |
827 | } | |
828 | size = fileinfo.nFileSizeLow; | |
829 | ||
830 | hfilemap = CreateFileMapping (hfile, NULL, PAGE_READONLY, 0, 0, NULL); | |
831 | if (hfilemap == INVALID_HANDLE_VALUE) | |
832 | { | |
833 | CloseHandle (hfile); | |
834 | return 0; | |
835 | } | |
836 | ||
837 | font = MapViewOfFile (hfilemap, FILE_MAP_READ, 0, 0, 0); | |
838 | if (!font) | |
839 | { | |
840 | CloseHandle (hfile); | |
841 | CloseHandle (hfilemap); | |
842 | return 0; | |
843 | } | |
844 | start = font; | |
845 | ||
846 | flag = proceed_file_line ("FONT ", start, &size, &p, &q); | |
847 | if (flag) | |
848 | { | |
849 | /* If font provides a description of itself, check it is a | |
850 | full XLFD before accepting it. */ | |
851 | int count = 0; | |
852 | char *s; | |
853 | ||
854 | for (s = p; s < q; s++) | |
855 | if (*s == '\n') | |
856 | break; | |
857 | else if (*s == '-') | |
858 | count++; | |
859 | if (count == 14 && q - p - 1 <= len) | |
860 | { | |
861 | strncpy (xstr, p, q-p-1); | |
862 | xstr[q-p-1] = '\0'; | |
863 | /* Files may have DOS line ends (ie still ^M on end). */ | |
864 | if (iscntrl(xstr[q-p-2])) | |
865 | xstr[q-p-2] = '\0'; | |
866 | ||
867 | retval = 1; | |
868 | } | |
869 | } | |
870 | CloseHandle (hfile); | |
871 | CloseHandle (hfilemap); | |
872 | return retval; | |
873 | } | |
ab5796a9 MB |
874 | |
875 | /* arch-tag: 2e9a45de-0c54-4a0e-95c8-2d67b2b1fa32 | |
876 | (do not change this comment) */ |