Mercurial > emacs
comparison src/w32bdf.c @ 24141:db9dfcd11c84
Initial revision
author | Geoff Voelker <voelker@cs.washington.edu> |
---|---|
date | Fri, 22 Jan 1999 19:42:26 +0000 |
parents | |
children | 541ff963ba80 |
comparison
equal
deleted
inserted
replaced
24140:9e4d1d3eab09 | 24141:db9dfcd11c84 |
---|---|
1 /* Implementation of BDF font handling on the Microsoft W32 API. | |
2 Copyright (C) 1999 Free Software Foundation, Inc. | |
3 | |
4 This file is part of GNU Emacs. | |
5 | |
6 GNU Emacs is free software; you can redistribute it and/or modify | |
7 it under the terms of the GNU General Public License as published by | |
8 the Free Software Foundation; either version 2, or (at your option) | |
9 any later version. | |
10 | |
11 GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to | |
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
19 Boston, MA 02111-1307, USA. */ | |
20 | |
21 /* Based heavily on code by H. Miyashita for Meadow (a descendant of | |
22 MULE for W32). */ | |
23 | |
24 #include <windows.h> | |
25 #include "config.h" | |
26 #include "lisp.h" | |
27 #include "charset.h" | |
28 #include "fontset.h" | |
29 #include "blockinput.h" | |
30 #include "w32gui.h" | |
31 #include "w32term.h" | |
32 #include "w32bdf.h" | |
33 | |
34 #define min(a, b) ((a) < (b) ? (a) : (b)) | |
35 #define max(a, b) ((a) > (b) ? (a) : (b)) | |
36 | |
37 void w32_free_bdf_font(bdffont *fontp); | |
38 bdffont *w32_init_bdf_font(char *filename); | |
39 | |
40 static int | |
41 search_file_line(char *key, char *start, int len, char **val, char **next) | |
42 { | |
43 int linelen; | |
44 unsigned char *p, *q; | |
45 | |
46 p = memchr(start, '\n', len); | |
47 if (!p) return -1; | |
48 for (;start < p;start++) | |
49 { | |
50 if ((*start != ' ') || (*start != '\t')) break; | |
51 } | |
52 linelen = p - start + 1; | |
53 *next = p + 1; | |
54 if (strncmp(start, key, min(strlen(key), linelen)) == 0) | |
55 { | |
56 *val = start + strlen(key); | |
57 return 1; | |
58 } | |
59 | |
60 return 0; | |
61 } | |
62 | |
63 static int | |
64 proceed_file_line(char *key, char *start, int *len, char **val, char **next) | |
65 { | |
66 int flag = 0; | |
67 | |
68 do { | |
69 flag = search_file_line(key, start, *len, val, next); | |
70 *len -= (int)(*next - start); | |
71 start = *next; | |
72 }while(flag == 0); | |
73 | |
74 if (flag == -1) return 0; | |
75 return 1; | |
76 } | |
77 | |
78 static int | |
79 set_bdf_font_info(bdffont *fontp) | |
80 { | |
81 unsigned char *start, *p, *q; | |
82 int len, flag; | |
83 int bbw, bbh, bbx, bby; | |
84 int val1; | |
85 | |
86 len = fontp->size; | |
87 start = fontp->font; | |
88 | |
89 fontp->yoffset = 0; | |
90 fontp->relative_compose = 0; | |
91 fontp->default_ascent = 0; | |
92 | |
93 flag = proceed_file_line("FONTBOUNDINGBOX", start, &len, &p, &q); | |
94 if (!flag) return 0; | |
95 bbw = strtol(p, &start, 10); | |
96 p = start; | |
97 bbh = strtol(p, &start, 10); | |
98 p = start; | |
99 bbx = strtol(p, &start, 10); | |
100 p = start; | |
101 bby = strtol(p, &start, 10); | |
102 | |
103 fontp->llx = bbx; | |
104 fontp->lly = bby; | |
105 fontp->urx = bbw + bbx; | |
106 fontp->ury = bbh + bby; | |
107 fontp->width = bbw; | |
108 fontp->height = bbh; | |
109 start = q; | |
110 flag = proceed_file_line("STARTPROPERTIES", start, &len, &p, &q); | |
111 if (!flag) return 1; | |
112 | |
113 do { | |
114 start = q; | |
115 if (search_file_line("PIXEL_SIZE", start, len, &p, &q) == 1) | |
116 { | |
117 val1 = atoi(p); | |
118 fontp->pixsz = val1; | |
119 } | |
120 else if (search_file_line("FONT_ASCENT", start, len, &p, &q) == 1) | |
121 { | |
122 val1 = atoi(p); | |
123 fontp->ury = val1; | |
124 } | |
125 else if (search_file_line("FONT_DESCENT", start, len, &p, &q) == 1) | |
126 { | |
127 val1 = atoi(p); | |
128 fontp->lly = -val1; | |
129 } | |
130 else if (search_file_line("_MULE_BASELINE_OFFSET", start, len, &p, &q) == 1) | |
131 { | |
132 val1 = atoi(p); | |
133 fontp->yoffset = val1; | |
134 } | |
135 else if (search_file_line("_MULE_RELATIVE_COMPOSE", start, len, &p, &q) == 1) | |
136 { | |
137 val1 = atoi(p); | |
138 fontp->relative_compose = val1; | |
139 } | |
140 else if (search_file_line("_MULE_DEFAULT_ASCENT", start, len, &p, &q) == 1) | |
141 { | |
142 val1 = atoi(p); | |
143 fontp->default_ascent = val1; | |
144 } | |
145 else | |
146 { | |
147 flag = search_file_line("ENDPROPERTIES", start, len, &p, &q); | |
148 } | |
149 if (flag == -1) return 0; | |
150 len -= (q - start); | |
151 }while(flag == 0); | |
152 start = q; | |
153 flag = proceed_file_line("CHARS", start, &len, &p, &q); | |
154 if (!flag) return 0; | |
155 fontp->seeked = q; | |
156 | |
157 return 1; | |
158 } | |
159 | |
160 bdffont* | |
161 w32_init_bdf_font(char *filename) | |
162 { | |
163 HANDLE hfile, hfilemap; | |
164 bdffont *bdffontp; | |
165 unsigned char *font; | |
166 BY_HANDLE_FILE_INFORMATION fileinfo; | |
167 int i; | |
168 | |
169 hfile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, | |
170 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
171 if (hfile == INVALID_HANDLE_VALUE) return NULL; | |
172 if (!GetFileInformationByHandle(hfile, &fileinfo) || | |
173 (fileinfo.nFileSizeHigh != 0) || | |
174 (fileinfo.nFileSizeLow > BDF_FILE_SIZE_MAX)) | |
175 { | |
176 CloseHandle(hfile); | |
177 error("Fail to open BDF file."); | |
178 } | |
179 hfilemap = CreateFileMapping(hfile, NULL, PAGE_READONLY, 0, 0, NULL); | |
180 if (hfilemap == INVALID_HANDLE_VALUE) | |
181 { | |
182 CloseHandle(hfile); | |
183 error("Can't map font."); | |
184 } | |
185 | |
186 font = MapViewOfFile(hfilemap, FILE_MAP_READ, 0, 0, 0); | |
187 | |
188 if (!font) | |
189 { | |
190 CloseHandle(hfile); | |
191 CloseHandle(hfilemap); | |
192 error("Can't view font."); | |
193 } | |
194 | |
195 bdffontp = (bdffont *) xmalloc(sizeof(bdffont)); | |
196 | |
197 for(i = 0;i < BDF_FIRST_OFFSET_TABLE;i++) | |
198 bdffontp->offset[i] = NULL; | |
199 bdffontp->size = fileinfo.nFileSizeLow; | |
200 bdffontp->font = font; | |
201 bdffontp->hfile = hfile; | |
202 bdffontp->hfilemap = hfilemap; | |
203 bdffontp->filename = (char*) xmalloc(strlen(filename) + 1); | |
204 strcpy(bdffontp->filename, filename); | |
205 | |
206 if (!set_bdf_font_info(bdffontp)) | |
207 { | |
208 w32_free_bdf_font(bdffontp); | |
209 error("Invalid BDF font!"); | |
210 } | |
211 return bdffontp; | |
212 } | |
213 | |
214 void | |
215 w32_free_bdf_font(bdffont *fontp) | |
216 { | |
217 int i; | |
218 | |
219 UnmapViewOfFile(fontp->hfilemap); | |
220 CloseHandle(fontp->hfilemap); | |
221 CloseHandle(fontp->hfile); | |
222 xfree(fontp->filename); | |
223 for(i = 0;i < BDF_FIRST_OFFSET_TABLE;i++) | |
224 { | |
225 if (fontp->offset[i]) xfree(fontp->offset[i]); | |
226 } | |
227 xfree(fontp); | |
228 } | |
229 | |
230 static unsigned char* | |
231 get_cached_char_offset(bdffont *fontp, int index) | |
232 { | |
233 unsigned char **offset1; | |
234 unsigned char *offset2; | |
235 int i; | |
236 | |
237 if (index > 0xffff) | |
238 return NULL; | |
239 | |
240 offset1 = fontp->offset[BDF_FIRST_OFFSET(index)]; | |
241 if (!offset1) | |
242 return NULL; | |
243 offset2 = offset1[BDF_SECOND_OFFSET(index)]; | |
244 | |
245 if (offset2) return offset2; | |
246 | |
247 return NULL; | |
248 } | |
249 | |
250 static void | |
251 cache_char_offset(bdffont *fontp, int index, unsigned char *offset) | |
252 { | |
253 unsigned char **offset1; | |
254 int i; | |
255 | |
256 if (index > 0xffff) | |
257 return; | |
258 | |
259 offset1 = fontp->offset[BDF_FIRST_OFFSET(index)]; | |
260 if (!offset1) | |
261 { | |
262 offset1 = fontp->offset[BDF_FIRST_OFFSET(index)] = | |
263 (unsigned char **) xmalloc(sizeof(unsigned char*) * | |
264 BDF_SECOND_OFFSET_TABLE); | |
265 memset(offset1, 0, sizeof(unsigned char*) * BDF_SECOND_OFFSET_TABLE); | |
266 } | |
267 offset1[BDF_SECOND_OFFSET(index)] = offset; | |
268 | |
269 return; | |
270 } | |
271 | |
272 static unsigned char* | |
273 seek_char_offset(bdffont *fontp, int index) | |
274 { | |
275 int len, flag, font_index; | |
276 unsigned char *start, *p, *q; | |
277 | |
278 if (!fontp->seeked) return NULL; | |
279 | |
280 start = fontp->seeked; | |
281 len = fontp->size - (start - fontp->font); | |
282 | |
283 do { | |
284 flag = proceed_file_line("ENCODING", start, &len, &p, &q); | |
285 if (!flag) | |
286 { | |
287 fontp->seeked = NULL; | |
288 return NULL; | |
289 } | |
290 font_index = atoi(p); | |
291 cache_char_offset(fontp, font_index, q); | |
292 start = q; | |
293 } while (font_index != index); | |
294 fontp->seeked = q; | |
295 | |
296 return q; | |
297 } | |
298 | |
299 #define GET_HEX_VAL(x) ((isdigit(x)) ? ((x) - '0') : \ | |
300 (((x) >= 'A') && ((x) <= 'Z')) ? ((x) - 'A' + 10) : \ | |
301 (((x) >= 'a') && ((x) <= 'z')) ? ((x) - 'a' + 10) : \ | |
302 (-1)) | |
303 | |
304 int | |
305 w32_get_bdf_glyph(bdffont *fontp, int index, int size, glyph_struct *glyph) | |
306 { | |
307 unsigned char *start, *p, *q, *bitmapp; | |
308 unsigned char val1, val2; | |
309 int i, j, len, flag; | |
310 | |
311 start = get_cached_char_offset(fontp, index); | |
312 if (!start) | |
313 start = seek_char_offset(fontp, index); | |
314 if (!start) | |
315 return 0; | |
316 | |
317 len = fontp->size - (start - fontp->font); | |
318 | |
319 flag = proceed_file_line("DWIDTH", start, &len, &p, &q); | |
320 if (!flag) | |
321 return 0; | |
322 glyph->dwidth = atoi(p); | |
323 | |
324 start = q; | |
325 flag = proceed_file_line("BBX", start, &len, &p, &q); | |
326 if (!flag) | |
327 return 0; | |
328 glyph->bbw = strtol(p, &start, 10); | |
329 p = start; | |
330 glyph->bbh = strtol(p, &start, 10); | |
331 p = start; | |
332 glyph->bbox = strtol(p, &start, 10); | |
333 p = start; | |
334 glyph->bboy = strtol(p, &start, 10); | |
335 | |
336 if (size == 0) return 1; | |
337 | |
338 start = q; | |
339 flag = proceed_file_line("BITMAP", start, &len, &p, &q); | |
340 if (!flag) | |
341 return 0; | |
342 | |
343 p = q; | |
344 bitmapp = glyph->bitmap; | |
345 for(i = 0;i < glyph->bbh;i++) | |
346 { | |
347 q = memchr(p, '\n', len); | |
348 if (!q) return 0; | |
349 for(j = 0;((q > p) && (j < ((glyph->bbw + 7) / 8 )));j++) | |
350 { | |
351 val1 = GET_HEX_VAL(*p); | |
352 if (val1 == -1) return 0; | |
353 p++; | |
354 val2 = GET_HEX_VAL(*p); | |
355 if (val2 == -1) return 0; | |
356 p++; | |
357 size--; | |
358 if (size <= 0) return 0; | |
359 /* NAND Operation. */ | |
360 *bitmapp++ = (unsigned char)~((val1 << 4) | val2); | |
361 } | |
362 /* CreateBitmap requires WORD alignment. */ | |
363 if (j % 2) | |
364 { | |
365 *bitmapp++ = 0xff; | |
366 } | |
367 p = q + 1; | |
368 } | |
369 | |
370 return 1; | |
371 } | |
372 | |
373 int | |
374 w32_BDF_TextOut(bdffont *fontp, HDC hdc, int left, | |
375 int top, unsigned char *text, int dim, int bytelen, | |
376 int fixed_pitch_size) | |
377 { | |
378 int bitmap_size, index, btop; | |
379 unsigned char *textp; | |
380 glyph_struct glyph; | |
381 HDC hCompatDC = 0; | |
382 HBITMAP hBMP; | |
383 HBRUSH hFgBrush, hOrgBrush; | |
384 HANDLE holdobj, horgobj = 0; | |
385 UINT textalign; | |
386 int flag = 0; | |
387 | |
388 bitmap_size = ((fontp->urx - fontp->llx) / 8 + 2) * (fontp->ury - fontp->lly) | |
389 + 256; | |
390 | |
391 glyph.bitmap = (unsigned char*) alloca(sizeof(unsigned char) * bitmap_size); | |
392 | |
393 hCompatDC = CreateCompatibleDC(hdc); | |
394 | |
395 textalign = GetTextAlign(hdc); | |
396 | |
397 SaveDC(hdc); | |
398 | |
399 hFgBrush = CreateSolidBrush(GetTextColor(hdc)); | |
400 hOrgBrush = SelectObject(hdc, hFgBrush); | |
401 SetTextColor(hdc, RGB(0, 0, 0)); | |
402 SetBkColor(hdc, RGB(0xff, 0xff, 0xff)); | |
403 | |
404 textp = text; | |
405 while(bytelen > 0) | |
406 { | |
407 if (dim == 1) | |
408 { | |
409 index = *textp++; | |
410 bytelen--; | |
411 } | |
412 else | |
413 { | |
414 bytelen -= 2; | |
415 if (bytelen < 0) break; | |
416 index = MAKELENDSHORT(textp[1], textp[0]); | |
417 textp += 2; | |
418 } | |
419 if (!w32_get_bdf_glyph(fontp, index, bitmap_size, &glyph)) | |
420 { | |
421 if (horgobj) | |
422 { | |
423 SelectObject(hCompatDC, horgobj); | |
424 DeleteObject(hBMP); | |
425 } | |
426 DeleteDC(hCompatDC); | |
427 return 0; | |
428 } | |
429 hBMP = CreateBitmap(glyph.bbw, glyph.bbh, 1, 1, glyph.bitmap); | |
430 if (textalign & TA_BASELINE) | |
431 { | |
432 btop = top - (glyph.bbh + glyph.bboy); | |
433 } | |
434 else if (textalign & TA_BOTTOM) | |
435 { | |
436 btop = top - glyph.bbh; | |
437 } | |
438 else | |
439 { | |
440 btop = top; | |
441 } | |
442 | |
443 if (horgobj) | |
444 { | |
445 SelectObject(hCompatDC, hBMP); | |
446 DeleteObject(holdobj); | |
447 holdobj = hBMP; | |
448 } | |
449 else | |
450 { | |
451 horgobj = SelectObject(hCompatDC, hBMP); | |
452 holdobj = hBMP; | |
453 } | |
454 #if 0 | |
455 BitBlt(hdc, left, btop, glyph.bbw, glyph.bbh, hCompatDC, 0, 0, SRCCOPY); | |
456 #else | |
457 BitBlt(hdc, left, btop, glyph.bbw, glyph.bbh, hCompatDC, 0, 0, 0xB8074A); | |
458 #endif | |
459 if (fixed_pitch_size) | |
460 left += fixed_pitch_size; | |
461 else | |
462 left += glyph.dwidth; | |
463 } | |
464 SelectObject(hCompatDC, horgobj); | |
465 SelectObject(hdc, hOrgBrush); | |
466 DeleteObject(hFgBrush); | |
467 DeleteObject(hBMP); | |
468 DeleteDC(hCompatDC); | |
469 RestoreDC(hdc, -1); | |
470 | |
471 return 1; | |
472 } | |
473 | |
474 struct font_info *w32_load_bdf_font (struct frame *f, char *fontname, | |
475 int size, char* filename) | |
476 { | |
477 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f); | |
478 struct font_info *fontp; | |
479 XFontStruct *font; | |
480 bdffont* bdf_font; | |
481 | |
482 bdf_font = w32_init_bdf_font (filename); | |
483 | |
484 if (!bdf_font) return NULL; | |
485 | |
486 font = (XFontStruct *) xmalloc (sizeof (XFontStruct)); | |
487 | |
488 font->bdf = bdf_font; | |
489 font->hfont = 0; | |
490 | |
491 /* Do we need to create the table? */ | |
492 if (dpyinfo->font_table_size == 0) | |
493 { | |
494 dpyinfo->font_table_size = 16; | |
495 dpyinfo->font_table | |
496 = (struct font_info *) xmalloc (dpyinfo->font_table_size | |
497 * sizeof (struct font_info)); | |
498 } | |
499 /* Do we need to grow the table? */ | |
500 else if (dpyinfo->n_fonts | |
501 >= dpyinfo->font_table_size) | |
502 { | |
503 dpyinfo->font_table_size *= 2; | |
504 dpyinfo->font_table | |
505 = (struct font_info *) xrealloc (dpyinfo->font_table, | |
506 (dpyinfo->font_table_size | |
507 * sizeof (struct font_info))); | |
508 } | |
509 | |
510 fontp = dpyinfo->font_table + dpyinfo->n_fonts; | |
511 | |
512 /* Now fill in the slots of *FONTP. */ | |
513 BLOCK_INPUT; | |
514 fontp->font = font; | |
515 fontp->font_idx = dpyinfo->n_fonts; | |
516 fontp->name = (char *) xmalloc (strlen (fontname) + 1); | |
517 bcopy (fontname, fontp->name, strlen (fontname) + 1); | |
518 fontp->full_name = fontp->name; | |
519 fontp->size = FONT_WIDTH (font); | |
520 fontp->height = FONT_HEIGHT (font); | |
521 | |
522 /* The slot `encoding' specifies how to map a character | |
523 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to | |
524 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F, | |
525 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, | |
526 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or | |
527 2:0xA020..0xFF7F). For the moment, we don't know which charset | |
528 uses this font. So, we set informatoin in fontp->encoding[1] | |
529 which is never used by any charset. If mapping can't be | |
530 decided, set FONT_ENCODING_NOT_DECIDED. */ | |
531 fontp->encoding[1] = FONT_ENCODING_NOT_DECIDED; | |
532 fontp->baseline_offset = bdf_font->yoffset; | |
533 fontp->relative_compose = bdf_font->relative_compose; | |
534 fontp->default_ascent = bdf_font->default_ascent; | |
535 | |
536 UNBLOCK_INPUT; | |
537 dpyinfo->n_fonts++; | |
538 return fontp; | |
539 } | |
540 | |
541 /* Check a file for an XFLD string describing it. */ | |
542 int w32_BDF_to_x_font (char *file, char* xstr, int len) | |
543 { | |
544 HANDLE hfile, hfilemap; | |
545 BY_HANDLE_FILE_INFORMATION fileinfo; | |
546 unsigned char *font, *start, *p, *q; | |
547 int flag, size, retval = 0; | |
548 | |
549 hfile = CreateFile (file, GENERIC_READ, FILE_SHARE_READ, NULL, | |
550 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
551 if (hfile == INVALID_HANDLE_VALUE) return 0; | |
552 if (!GetFileInformationByHandle(hfile, &fileinfo) || | |
553 (fileinfo.nFileSizeHigh != 0) || | |
554 (fileinfo.nFileSizeLow > BDF_FILE_SIZE_MAX)) | |
555 { | |
556 CloseHandle (hfile); | |
557 return 0; | |
558 } | |
559 size = fileinfo.nFileSizeLow; | |
560 | |
561 hfilemap = CreateFileMapping (hfile, NULL, PAGE_READONLY, 0, 0, NULL); | |
562 if (hfilemap == INVALID_HANDLE_VALUE) | |
563 { | |
564 CloseHandle (hfile); | |
565 return 0; | |
566 } | |
567 | |
568 font = MapViewOfFile (hfilemap, FILE_MAP_READ, 0, 0, 0); | |
569 if (!font) | |
570 { | |
571 CloseHandle (hfile); | |
572 CloseHandle (hfilemap); | |
573 return 0; | |
574 } | |
575 start = font; | |
576 | |
577 flag = proceed_file_line ("FONT ", start, &size, &p, &q); | |
578 if (flag) | |
579 { | |
580 /* If font provides a description of itself, check it is a | |
581 full XLFD before accepting it. */ | |
582 int count = 0; | |
583 char *s; | |
584 | |
585 for (s = p; s < q; s++) | |
586 if (*s == '\n') | |
587 break; | |
588 else if (*s == '-') | |
589 count++; | |
590 if (count == 14 && q - p - 1 <= len) | |
591 { | |
592 strncpy (xstr, p, q-p-1); | |
593 xstr[q-p-1] = '\0'; | |
594 /* Files may have DOS line ends (ie still ^M on end). */ | |
595 if (iscntrl(xstr[q-p-2])) | |
596 xstr[q-p-2] = '\0'; | |
597 | |
598 retval = 1; | |
599 } | |
600 } | |
601 CloseHandle (hfile); | |
602 CloseHandle (hfilemap); | |
603 return retval; | |
604 } |