diff options
| -rw-r--r-- | src/w32bdf.c | 301 |
1 files changed, 193 insertions, 108 deletions
diff --git a/src/w32bdf.c b/src/w32bdf.c index c41ecd07220..f9a717a26a8 100644 --- a/src/w32bdf.c +++ b/src/w32bdf.c | |||
| @@ -36,26 +36,33 @@ Boston, MA 02111-1307, USA. */ | |||
| 36 | #define min(a, b) ((a) < (b) ? (a) : (b)) | 36 | #define min(a, b) ((a) < (b) ? (a) : (b)) |
| 37 | #define max(a, b) ((a) > (b) ? (a) : (b)) | 37 | #define max(a, b) ((a) > (b) ? (a) : (b)) |
| 38 | 38 | ||
| 39 | /* Portion of GDI Objects which the font cache is allowed to use. This | 39 | /* 10 planes */ |
| 40 | can be quite high, since the font cache is the only part of Emacs | 40 | #define BDF_CODEPOINT_HEAP_INITIAL_SIZE (96 * 10) |
| 41 | that uses a large number of GDI objects, but there should still be | 41 | /* about 96 characters */ |
| 42 | some GDI objects reserved for other uses. */ | 42 | #define BDF_BITMAP_HEAP_INITIAL_SIZE (64 * 96) |
| 43 | #define CACHE_GDI_ALLOWANCE 9 / 10 | 43 | |
| 44 | HANDLE hbdf_cp_heap = INVALID_HANDLE_VALUE; | ||
| 45 | HANDLE hbdf_bmp_heap = INVALID_HANDLE_VALUE; | ||
| 44 | 46 | ||
| 45 | void w32_free_bdf_font(bdffont *fontp); | 47 | void w32_free_bdf_font(bdffont *fontp); |
| 46 | bdffont *w32_init_bdf_font(char *filename); | 48 | bdffont *w32_init_bdf_font(char *filename); |
| 47 | 49 | ||
| 50 | cache_bitmap cached_bitmap_slots[BDF_FONT_CACHE_SIZE]; | ||
| 51 | cache_bitmap *pcached_bitmap_latest = cached_bitmap_slots; | ||
| 52 | |||
| 53 | #define FONT_CACHE_SLOT_OVER_P(p) ((p) >= cached_bitmap_slots + BDF_FONT_CACHE_SIZE) | ||
| 54 | |||
| 48 | static int | 55 | static int |
| 49 | search_file_line(char *key, char *start, int len, char **val, char **next) | 56 | search_file_line(char *key, char *start, int len, char **val, char **next) |
| 50 | { | 57 | { |
| 51 | int linelen; | 58 | int linelen; |
| 52 | char *p; | 59 | unsigned char *p, *q; |
| 53 | 60 | ||
| 54 | p = memchr(start, '\n', len); | 61 | p = memchr(start, '\n', len); |
| 55 | if (!p) return -1; | 62 | if (!p) return -1; |
| 56 | for (;start < p;start++) | 63 | for (;start < p;start++) |
| 57 | { | 64 | { |
| 58 | if ((*start != ' ') || (*start != '\t')) break; | 65 | if ((*start != ' ') && (*start != '\t')) break; |
| 59 | } | 66 | } |
| 60 | linelen = p - start + 1; | 67 | linelen = p - start + 1; |
| 61 | *next = p + 1; | 68 | *next = p + 1; |
| @@ -82,18 +89,16 @@ proceed_file_line(char *key, char *start, int *len, char **val, char **next) | |||
| 82 | if (flag == -1) return 0; | 89 | if (flag == -1) return 0; |
| 83 | return 1; | 90 | return 1; |
| 84 | } | 91 | } |
| 85 | 92 | ||
| 86 | char* | 93 | char* |
| 87 | get_quoted_string(char *start, char *end) | 94 | get_quoted_string(char *start, char *end) |
| 88 | { | 95 | { |
| 89 | char *p, *q, *result; | 96 | char *p, *q, *result; |
| 90 | 97 | ||
| 91 | p = memchr(start, '\"', end - start); | 98 | p = memchr(start, '\"', end - start); |
| 92 | q = 0; | ||
| 93 | |||
| 94 | if (!p) return NULL; | 99 | if (!p) return NULL; |
| 95 | p++; | 100 | p++; |
| 96 | q = memchr(p, '\"', end - q); | 101 | q = memchr(p, '\"', end - p); |
| 97 | if (!q) return NULL; | 102 | if (!q) return NULL; |
| 98 | 103 | ||
| 99 | result = (char*) xmalloc(q - p + 1); | 104 | result = (char*) xmalloc(q - p + 1); |
| @@ -107,7 +112,7 @@ get_quoted_string(char *start, char *end) | |||
| 107 | static int | 112 | static int |
| 108 | set_bdf_font_info(bdffont *fontp) | 113 | set_bdf_font_info(bdffont *fontp) |
| 109 | { | 114 | { |
| 110 | char *start, *p, *q; | 115 | unsigned char *start, *p, *q; |
| 111 | int len, flag; | 116 | int len, flag; |
| 112 | int bbw, bbh, bbx, bby; | 117 | int bbw, bbh, bbx, bby; |
| 113 | int val1; | 118 | int val1; |
| @@ -118,6 +123,7 @@ set_bdf_font_info(bdffont *fontp) | |||
| 118 | fontp->yoffset = 0; | 123 | fontp->yoffset = 0; |
| 119 | fontp->relative_compose = 0; | 124 | fontp->relative_compose = 0; |
| 120 | fontp->default_ascent = 0; | 125 | fontp->default_ascent = 0; |
| 126 | |||
| 121 | fontp->registry = NULL; | 127 | fontp->registry = NULL; |
| 122 | fontp->encoding = NULL; | 128 | fontp->encoding = NULL; |
| 123 | fontp->slant = NULL; | 129 | fontp->slant = NULL; |
| @@ -165,7 +171,7 @@ set_bdf_font_info(bdffont *fontp) | |||
| 165 | else if (search_file_line("_MULE_BASELINE_OFFSET", start, len, &p, &q) == 1) | 171 | else if (search_file_line("_MULE_BASELINE_OFFSET", start, len, &p, &q) == 1) |
| 166 | { | 172 | { |
| 167 | val1 = atoi(p); | 173 | val1 = atoi(p); |
| 168 | fontp->yoffset = val1; | 174 | fontp->yoffset = -val1; |
| 169 | } | 175 | } |
| 170 | else if (search_file_line("_MULE_RELATIVE_COMPOSE", start, len, &p, &q) == 1) | 176 | else if (search_file_line("_MULE_RELATIVE_COMPOSE", start, len, &p, &q) == 1) |
| 171 | { | 177 | { |
| @@ -219,6 +225,14 @@ w32_init_bdf_font(char *filename) | |||
| 219 | BY_HANDLE_FILE_INFORMATION fileinfo; | 225 | BY_HANDLE_FILE_INFORMATION fileinfo; |
| 220 | int i; | 226 | int i; |
| 221 | 227 | ||
| 228 | if (hbdf_cp_heap == INVALID_HANDLE_VALUE) | ||
| 229 | hbdf_cp_heap = HeapCreate(0, BDF_CODEPOINT_HEAP_INITIAL_SIZE, 0); | ||
| 230 | if (hbdf_bmp_heap = INVALID_HANDLE_VALUE) | ||
| 231 | hbdf_bmp_heap = HeapCreate(0, BDF_BITMAP_HEAP_INITIAL_SIZE, 0); | ||
| 232 | |||
| 233 | if (!hbdf_cp_heap || !hbdf_bmp_heap) | ||
| 234 | error("Fail to create heap for BDF."); | ||
| 235 | |||
| 222 | hfile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, | 236 | hfile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, |
| 223 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | 237 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); |
| 224 | if (hfile == INVALID_HANDLE_VALUE) return NULL; | 238 | if (hfile == INVALID_HANDLE_VALUE) return NULL; |
| @@ -289,9 +303,14 @@ w32_free_bdf_font(bdffont *fontp) | |||
| 289 | for (j = 0;j < BDF_SECOND_OFFSET_TABLE;j++) | 303 | for (j = 0;j < BDF_SECOND_OFFSET_TABLE;j++) |
| 290 | { | 304 | { |
| 291 | pcb = pch[j].pcbmp; | 305 | pcb = pch[j].pcbmp; |
| 292 | if (pcb) pcb->psrc = NULL; | 306 | if (pcb) |
| 307 | { | ||
| 308 | if (pcb->pbmp) | ||
| 309 | HeapFree(hbdf_bmp_heap, 0, pcb->pbmp); | ||
| 310 | pcb->psrc = NULL; | ||
| 293 | } | 311 | } |
| 294 | xfree(pch); | 312 | } |
| 313 | HeapFree(hbdf_cp_heap, 0, pch); | ||
| 295 | } | 314 | } |
| 296 | } | 315 | } |
| 297 | xfree(fontp); | 316 | xfree(fontp); |
| @@ -303,12 +322,13 @@ get_cached_font_char(bdffont *fontp, int index) | |||
| 303 | font_char *pch, *result; | 322 | font_char *pch, *result; |
| 304 | int i; | 323 | int i; |
| 305 | 324 | ||
| 306 | if (index > 0xffff) | 325 | if (!BDF_CODEPOINT_RANGE_COVER_P(index)) |
| 307 | return NULL; | 326 | return NULL; |
| 308 | 327 | ||
| 309 | pch = fontp->chtbl[BDF_FIRST_OFFSET(index)]; | 328 | pch = fontp->chtbl[BDF_FIRST_OFFSET(index)]; |
| 310 | if (!pch) | 329 | if (!pch) |
| 311 | return NULL; | 330 | return NULL; |
| 331 | |||
| 312 | result = &pch[BDF_SECOND_OFFSET(index)]; | 332 | result = &pch[BDF_SECOND_OFFSET(index)]; |
| 313 | 333 | ||
| 314 | if (!result->offset) return NULL; | 334 | if (!result->offset) return NULL; |
| @@ -322,16 +342,19 @@ cache_char_offset(bdffont *fontp, int index, unsigned char *offset) | |||
| 322 | font_char *pch, *result; | 342 | font_char *pch, *result; |
| 323 | int i; | 343 | int i; |
| 324 | 344 | ||
| 325 | if (index > 0xffff) | 345 | if (!BDF_CODEPOINT_RANGE_COVER_P(index)) |
| 326 | return NULL; | 346 | return NULL; |
| 327 | 347 | ||
| 328 | pch = fontp->chtbl[BDF_FIRST_OFFSET(index)]; | 348 | pch = fontp->chtbl[BDF_FIRST_OFFSET(index)]; |
| 329 | if (!pch) | 349 | if (!pch) |
| 330 | { | 350 | { |
| 331 | pch = fontp->chtbl[BDF_FIRST_OFFSET(index)] = | 351 | pch = fontp->chtbl[BDF_FIRST_OFFSET(index)] = |
| 332 | (font_char*) xmalloc(sizeof(font_char) * | 352 | (font_char*) HeapAlloc(hbdf_cp_heap, |
| 333 | BDF_SECOND_OFFSET_TABLE); | 353 | HEAP_ZERO_MEMORY, |
| 334 | memset(pch, 0, sizeof(font_char) * BDF_SECOND_OFFSET_TABLE); | 354 | sizeof(font_char) * |
| 355 | BDF_SECOND_OFFSET_TABLE); | ||
| 356 | if (!pch) return NULL; | ||
| 357 | /* memset(pch, 0, sizeof(font_char) * BDF_SECOND_OFFSET_TABLE); */ | ||
| 335 | } | 358 | } |
| 336 | 359 | ||
| 337 | result = &pch[BDF_SECOND_OFFSET(index)]; | 360 | result = &pch[BDF_SECOND_OFFSET(index)]; |
| @@ -345,8 +368,7 @@ seek_char(bdffont *fontp, int index) | |||
| 345 | { | 368 | { |
| 346 | font_char *result; | 369 | font_char *result; |
| 347 | int len, flag, font_index; | 370 | int len, flag, font_index; |
| 348 | unsigned char *start; | 371 | unsigned char *start, *p, *q; |
| 349 | char *p, *q; | ||
| 350 | 372 | ||
| 351 | if (!fontp->seeked) return NULL; | 373 | if (!fontp->seeked) return NULL; |
| 352 | 374 | ||
| @@ -371,19 +393,41 @@ seek_char(bdffont *fontp, int index) | |||
| 371 | return result; | 393 | return result; |
| 372 | } | 394 | } |
| 373 | 395 | ||
| 396 | static void | ||
| 397 | clear_cached_bitmap_slots() | ||
| 398 | { | ||
| 399 | int i; | ||
| 400 | cache_bitmap *p; | ||
| 401 | |||
| 402 | p = pcached_bitmap_latest; | ||
| 403 | for (i = 0;i < BDF_FONT_CLEAR_SIZE;i++) | ||
| 404 | { | ||
| 405 | if (p->psrc) | ||
| 406 | { | ||
| 407 | if (p->pbmp) | ||
| 408 | HeapFree(hbdf_bmp_heap, 0, p->pbmp); | ||
| 409 | p->psrc->pcbmp = NULL; | ||
| 410 | p->psrc = NULL; | ||
| 411 | } | ||
| 412 | p++; | ||
| 413 | if (FONT_CACHE_SLOT_OVER_P(p)) | ||
| 414 | p = cached_bitmap_slots; | ||
| 415 | } | ||
| 416 | } | ||
| 417 | |||
| 374 | #define GET_HEX_VAL(x) ((isdigit(x)) ? ((x) - '0') : \ | 418 | #define GET_HEX_VAL(x) ((isdigit(x)) ? ((x) - '0') : \ |
| 375 | (((x) >= 'A') && ((x) <= 'Z')) ? ((x) - 'A' + 10) : \ | 419 | (((x) >= 'A') && ((x) <= 'F')) ? ((x) - 'A' + 10) : \ |
| 376 | (((x) >= 'a') && ((x) <= 'z')) ? ((x) - 'a' + 10) : \ | 420 | (((x) >= 'a') && ((x) <= 'f')) ? ((x) - 'a' + 10) : \ |
| 377 | (-1)) | 421 | (-1)) |
| 378 | 422 | ||
| 379 | int | 423 | int |
| 380 | w32_get_bdf_glyph(bdffont *fontp, int index, int size, glyph_struct *glyph) | 424 | w32_get_bdf_glyph(bdffont *fontp, int index, int size, glyph_struct *glyph) |
| 381 | { | 425 | { |
| 382 | font_char *pch; | 426 | font_char *pch; |
| 383 | unsigned char *start, *bitmapp; | 427 | unsigned char *start, *p, *q, *bitmapp; |
| 384 | char *p, *q; | 428 | unsigned char val, val1, val2; |
| 385 | char val1, val2; | 429 | int i, j, len, flag, consumed; |
| 386 | int i, j, len, flag; | 430 | int align, rowbytes; |
| 387 | 431 | ||
| 388 | pch = get_cached_font_char(fontp, index); | 432 | pch = get_cached_font_char(fontp, index); |
| 389 | if (!pch) | 433 | if (!pch) |
| @@ -427,13 +471,23 @@ w32_get_bdf_glyph(bdffont *fontp, int index, int size, glyph_struct *glyph) | |||
| 427 | if (!flag) | 471 | if (!flag) |
| 428 | return 0; | 472 | return 0; |
| 429 | 473 | ||
| 474 | consumed = 0; | ||
| 475 | flag = 0; | ||
| 430 | p = q; | 476 | p = q; |
| 431 | bitmapp = glyph->bitmap; | 477 | bitmapp = glyph->bitmap; |
| 478 | rowbytes = (glyph->metric.bbw + 7) / 8; | ||
| 479 | /* DIB requires DWORD alignment. */ | ||
| 480 | align = sizeof(DWORD) - rowbytes % sizeof(DWORD); | ||
| 481 | consumed = glyph->metric.bbh * (rowbytes + align); | ||
| 482 | glyph->bitmap_size = consumed; | ||
| 483 | glyph->row_byte_size = rowbytes; | ||
| 484 | if (size < consumed) return 0; | ||
| 485 | |||
| 432 | for(i = 0;i < glyph->metric.bbh;i++) | 486 | for(i = 0;i < glyph->metric.bbh;i++) |
| 433 | { | 487 | { |
| 434 | q = memchr(p, '\n', len); | 488 | q = memchr(p, '\n', len); |
| 435 | if (!q) return 0; | 489 | if (!q) return 0; |
| 436 | for(j = 0;((q > p) && (j < ((glyph->metric.bbw + 7) / 8 )));j++) | 490 | for(j = 0;((q > p) && (j < rowbytes));j++) |
| 437 | { | 491 | { |
| 438 | val1 = GET_HEX_VAL(*p); | 492 | val1 = GET_HEX_VAL(*p); |
| 439 | if (val1 == -1) return 0; | 493 | if (val1 == -1) return 0; |
| @@ -441,38 +495,30 @@ w32_get_bdf_glyph(bdffont *fontp, int index, int size, glyph_struct *glyph) | |||
| 441 | val2 = GET_HEX_VAL(*p); | 495 | val2 = GET_HEX_VAL(*p); |
| 442 | if (val2 == -1) return 0; | 496 | if (val2 == -1) return 0; |
| 443 | p++; | 497 | p++; |
| 444 | size--; | 498 | val = (unsigned char)((val1 << 4) | val2); |
| 445 | if (size <= 0) return 0; | 499 | if (val) flag = 1; |
| 446 | /* NAND Operation. */ | 500 | *bitmapp++ = val; |
| 447 | *bitmapp++ = (unsigned char)~((val1 << 4) | val2); | ||
| 448 | } | ||
| 449 | /* CreateBitmap requires WORD alignment. */ | ||
| 450 | if (j % 2) | ||
| 451 | { | ||
| 452 | *bitmapp++ = 0xff; | ||
| 453 | } | 501 | } |
| 502 | for(j = 0;j < align;j++) | ||
| 503 | *bitmapp++ = 0x00; | ||
| 454 | p = q + 1; | 504 | p = q + 1; |
| 455 | } | 505 | } |
| 456 | 506 | ||
| 457 | return 1; | 507 | /* If this glyph is white space, return -1. */ |
| 458 | } | 508 | if (flag == 0) return -1; |
| 459 | 509 | ||
| 460 | #define NEXT_CACHE_SLOT(n) (((n) + 1 >= BDF_FONT_CACHE_SIZE) ? 0 : ((n) + 1)) | 510 | return consumed; |
| 511 | } | ||
| 461 | 512 | ||
| 462 | static | 513 | static |
| 463 | cache_bitmap* | 514 | cache_bitmap* |
| 464 | get_bitmap_with_cache(bdffont *fontp, int index) | 515 | get_bitmap_with_cache(bdffont *fontp, int index) |
| 465 | { | 516 | { |
| 466 | int bitmap_size; | 517 | int bitmap_size, bitmap_real_size; |
| 467 | font_char *pch; | 518 | font_char *pch; |
| 468 | cache_bitmap* pcb; | 519 | cache_bitmap* pcb; |
| 469 | HBITMAP hbmp; | 520 | unsigned char *pbmp; |
| 470 | glyph_struct glyph; | 521 | glyph_struct glyph; |
| 471 | static cache_bitmap cached_bitmap_slots[BDF_FONT_CACHE_SIZE]; | ||
| 472 | static int cache_in_slot = 0; /* the next slot to use */ | ||
| 473 | static int cache_out_slot = 0; /* the last slot allocated */ | ||
| 474 | static int cache_occupancy = 0; /* current cache occupancy */ | ||
| 475 | static int cache_limit = BDF_FONT_CACHE_SIZE; /* allowed maximum occupancy */ | ||
| 476 | 522 | ||
| 477 | pch = get_cached_font_char(fontp, index); | 523 | pch = get_cached_font_char(fontp, index); |
| 478 | if (pch) | 524 | if (pch) |
| @@ -481,60 +527,87 @@ get_bitmap_with_cache(bdffont *fontp, int index) | |||
| 481 | if (pcb) return pcb; | 527 | if (pcb) return pcb; |
| 482 | } | 528 | } |
| 483 | 529 | ||
| 484 | bitmap_size = ((fontp->urx - fontp->llx) / 8 + 2) * (fontp->ury - fontp->lly) | 530 | bitmap_size = ((fontp->urx - fontp->llx) / 8 + 3) * (fontp->ury - fontp->lly) |
| 485 | + 256; | 531 | + 256; |
| 486 | glyph.bitmap = (unsigned char*) alloca(sizeof(unsigned char) * bitmap_size); | 532 | glyph.bitmap = (unsigned char*) alloca(sizeof(unsigned char) * bitmap_size); |
| 487 | 533 | ||
| 488 | if (!w32_get_bdf_glyph(fontp, index, bitmap_size, &glyph)) | 534 | bitmap_real_size = w32_get_bdf_glyph(fontp, index, bitmap_size, &glyph); |
| 535 | |||
| 536 | if (bitmap_real_size == 0) | ||
| 489 | return NULL; | 537 | return NULL; |
| 490 | 538 | ||
| 491 | pch = get_cached_font_char(fontp, index); | 539 | pch = get_cached_font_char(fontp, index); |
| 492 | if (!pch) return NULL; | 540 | if (!pch) return NULL; |
| 493 | 541 | ||
| 494 | hbmp = CreateBitmap(glyph.metric.bbw, glyph.metric.bbh, 1, 1, glyph.bitmap); | 542 | if (bitmap_real_size > 0) |
| 495 | |||
| 496 | /* if bitmap allocation fails reduce the limit of the occupancy so | ||
| 497 | that we can hope it will not happen again. */ | ||
| 498 | if (hbmp == NULL) | ||
| 499 | cache_limit = cache_occupancy * CACHE_GDI_ALLOWANCE; | ||
| 500 | |||
| 501 | /* if cache occupancy reaches at the limit release some cache slots */ | ||
| 502 | if (cache_occupancy >= cache_limit) | ||
| 503 | { | 543 | { |
| 504 | register int size_to_clear = cache_limit * BDF_FONT_CLEAR_SIZE | 544 | pbmp = (unsigned char*) HeapAlloc(hbdf_bmp_heap, 0, |
| 505 | / BDF_FONT_CACHE_SIZE; | 545 | bitmap_real_size); |
| 506 | for (; size_to_clear; size_to_clear--, | 546 | if (!pbmp) return NULL; |
| 507 | cache_out_slot = NEXT_CACHE_SLOT(cache_out_slot)) | 547 | memcpy(pbmp, glyph.bitmap, bitmap_real_size); |
| 508 | { | ||
| 509 | register cache_bitmap *p = &cached_bitmap_slots[cache_out_slot]; | ||
| 510 | if (p->psrc) | ||
| 511 | { | ||
| 512 | DeleteObject(p->hbmp); | ||
| 513 | p->psrc->pcbmp = NULL; | ||
| 514 | p->psrc = NULL; | ||
| 515 | cache_occupancy--; | ||
| 516 | } | ||
| 517 | } | ||
| 518 | } | 548 | } |
| 549 | else | ||
| 550 | pbmp = NULL; /* white space character */ | ||
| 519 | 551 | ||
| 520 | if (hbmp == NULL) | 552 | pcb = pcached_bitmap_latest; |
| 521 | hbmp = CreateBitmap (glyph.metric.bbw, glyph.metric.bbh, | 553 | if (pcb->psrc) |
| 522 | 1, 1, glyph.bitmap); | 554 | clear_cached_bitmap_slots(); |
| 523 | |||
| 524 | pcb = &cached_bitmap_slots[cache_in_slot]; | ||
| 525 | 555 | ||
| 526 | pcb->psrc = pch; | 556 | pcb->psrc = pch; |
| 527 | pcb->metric = glyph.metric; | 557 | pcb->metric = glyph.metric; |
| 528 | pcb->hbmp = hbmp; | 558 | pcb->pbmp = pbmp; |
| 559 | pcb->bitmap_size = glyph.bitmap_size; | ||
| 560 | pcb->row_byte_size = glyph.row_byte_size; | ||
| 529 | 561 | ||
| 530 | pch->pcbmp = pcb; | 562 | pch->pcbmp = pcb; |
| 531 | 563 | ||
| 532 | cache_in_slot = NEXT_CACHE_SLOT(cache_in_slot); | 564 | pcached_bitmap_latest++; |
| 533 | cache_occupancy++; | 565 | if (FONT_CACHE_SLOT_OVER_P(pcached_bitmap_latest)) |
| 566 | pcached_bitmap_latest = cached_bitmap_slots; | ||
| 534 | 567 | ||
| 535 | return pcb; | 568 | return pcb; |
| 536 | } | 569 | } |
| 537 | 570 | ||
| 571 | static HBITMAP | ||
| 572 | create_offscreen_bitmap(HDC hdc, int width, int height, unsigned char **bitsp) | ||
| 573 | { | ||
| 574 | HBITMAP hBMP; | ||
| 575 | struct { | ||
| 576 | BITMAPINFOHEADER h; | ||
| 577 | RGBQUAD c[2]; | ||
| 578 | } info; | ||
| 579 | |||
| 580 | memset(&info, 0, sizeof(info)); | ||
| 581 | info.h.biSize = sizeof(BITMAPINFOHEADER); | ||
| 582 | info.h.biWidth = width; | ||
| 583 | info.h.biHeight = -height; | ||
| 584 | info.h.biPlanes = 1; | ||
| 585 | info.h.biBitCount = 1; | ||
| 586 | info.h.biCompression = BI_RGB; | ||
| 587 | info.c[1].rgbRed = info.c[1].rgbGreen = info.c[1].rgbBlue = 255; | ||
| 588 | |||
| 589 | return CreateDIBSection(hdc, (LPBITMAPINFO)&info, | ||
| 590 | DIB_RGB_COLORS, bitsp, NULL, 0); | ||
| 591 | } | ||
| 592 | |||
| 593 | glyph_metric * | ||
| 594 | w32_BDF_TextMetric(bdffont *fontp, unsigned char *text, int dim) | ||
| 595 | { | ||
| 596 | int index; | ||
| 597 | cache_bitmap *pcb; | ||
| 598 | |||
| 599 | if (dim == 1) | ||
| 600 | index = *text; | ||
| 601 | else | ||
| 602 | index = MAKELENDSHORT(text[1], text[0]); | ||
| 603 | |||
| 604 | pcb = get_bitmap_with_cache(fontp, index); | ||
| 605 | if (!pcb) | ||
| 606 | return NULL; | ||
| 607 | |||
| 608 | return &(pcb->metric); | ||
| 609 | } | ||
| 610 | |||
| 538 | int | 611 | int |
| 539 | w32_BDF_TextOut(bdffont *fontp, HDC hdc, int left, | 612 | w32_BDF_TextOut(bdffont *fontp, HDC hdc, int left, |
| 540 | int top, unsigned char *text, int dim, int bytelen, | 613 | int top, unsigned char *text, int dim, int bytelen, |
| @@ -542,26 +615,29 @@ w32_BDF_TextOut(bdffont *fontp, HDC hdc, int left, | |||
| 542 | { | 615 | { |
| 543 | int index, btop; | 616 | int index, btop; |
| 544 | unsigned char *textp; | 617 | unsigned char *textp; |
| 545 | HDC hCompatDC = 0; | ||
| 546 | cache_bitmap *pcb; | 618 | cache_bitmap *pcb; |
| 547 | HBITMAP hBMP; | ||
| 548 | HBRUSH hFgBrush, hOrgBrush; | 619 | HBRUSH hFgBrush, hOrgBrush; |
| 549 | HANDLE horgobj = 0; | 620 | HANDLE horgobj; |
| 550 | UINT textalign; | 621 | UINT textalign; |
| 551 | int flag = 0; | 622 | int width, height; |
| 623 | HDC hCompatDC; | ||
| 624 | int ret = 1; | ||
| 625 | static HBITMAP hBMP = 0; | ||
| 626 | static HDC DIBsection_hdc = 0; | ||
| 627 | static int DIBsection_width, DIBsection_height; | ||
| 628 | static unsigned char *bits; | ||
| 552 | 629 | ||
| 553 | hCompatDC = CreateCompatibleDC(hdc); | 630 | hCompatDC = CreateCompatibleDC(hdc); |
| 631 | if (!hCompatDC) | ||
| 632 | return 0; | ||
| 554 | 633 | ||
| 555 | textalign = GetTextAlign(hdc); | 634 | textalign = GetTextAlign(hdc); |
| 556 | 635 | ||
| 557 | SaveDC(hdc); | ||
| 558 | |||
| 559 | hFgBrush = CreateSolidBrush(GetTextColor(hdc)); | 636 | hFgBrush = CreateSolidBrush(GetTextColor(hdc)); |
| 560 | hOrgBrush = SelectObject(hdc, hFgBrush); | 637 | hOrgBrush = SelectObject(hdc, hFgBrush); |
| 561 | SetTextColor(hdc, RGB(0, 0, 0)); | ||
| 562 | SetBkColor(hdc, RGB(0xff, 0xff, 0xff)); | ||
| 563 | 638 | ||
| 564 | textp = text; | 639 | textp = text; |
| 640 | |||
| 565 | while(bytelen > 0) | 641 | while(bytelen > 0) |
| 566 | { | 642 | { |
| 567 | if (dim == 1) | 643 | if (dim == 1) |
| @@ -579,15 +655,28 @@ w32_BDF_TextOut(bdffont *fontp, HDC hdc, int left, | |||
| 579 | pcb = get_bitmap_with_cache(fontp, index); | 655 | pcb = get_bitmap_with_cache(fontp, index); |
| 580 | if (!pcb) | 656 | if (!pcb) |
| 581 | { | 657 | { |
| 582 | if (horgobj) | 658 | ret = 0; |
| 583 | { | 659 | break; |
| 584 | SelectObject(hCompatDC, horgobj); | ||
| 585 | DeleteObject(hBMP); | ||
| 586 | } | 660 | } |
| 587 | DeleteDC(hCompatDC); | 661 | if (pcb->pbmp) |
| 588 | return 0; | 662 | { |
| 663 | width = pcb->metric.bbw; | ||
| 664 | height = pcb->metric.bbh; | ||
| 665 | |||
| 666 | if (!(hBMP | ||
| 667 | && (DIBsection_hdc == hdc) | ||
| 668 | && (DIBsection_width == width) | ||
| 669 | && (DIBsection_height == height))) | ||
| 670 | { | ||
| 671 | if (hBMP) DeleteObject(hBMP); | ||
| 672 | hBMP = create_offscreen_bitmap(hdc, width, height, &bits); | ||
| 673 | DIBsection_hdc = hdc; | ||
| 674 | DIBsection_width = width; | ||
| 675 | DIBsection_height = height; | ||
| 676 | if (!hBMP) return 0; | ||
| 589 | } | 677 | } |
| 590 | hBMP = pcb->hbmp; | 678 | |
| 679 | memcpy(bits, pcb->pbmp, pcb->bitmap_size); | ||
| 591 | 680 | ||
| 592 | if (textalign & TA_BASELINE) | 681 | if (textalign & TA_BASELINE) |
| 593 | btop = top - (pcb->metric.bbh + pcb->metric.bboy); | 682 | btop = top - (pcb->metric.bbh + pcb->metric.bboy); |
| @@ -596,27 +685,23 @@ w32_BDF_TextOut(bdffont *fontp, HDC hdc, int left, | |||
| 596 | else | 685 | else |
| 597 | btop = top; | 686 | btop = top; |
| 598 | 687 | ||
| 599 | if (horgobj) | ||
| 600 | SelectObject(hCompatDC, hBMP); | ||
| 601 | else | ||
| 602 | horgobj = SelectObject(hCompatDC, hBMP); | 688 | horgobj = SelectObject(hCompatDC, hBMP); |
| 603 | #if 0 | 689 | BitBlt(hdc, left, btop, width, height, hCompatDC, 0, 0, 0xE20746); |
| 604 | BitBlt(hdc, left, btop, pcb->metric.bbw, pcb->metric.bbh, hCompatDC, 0, 0, SRCCOPY); | 690 | SelectObject(hCompatDC, horgobj); |
| 605 | #else | 691 | } |
| 606 | BitBlt(hdc, left, btop, pcb->metric.bbw, pcb->metric.bbh, hCompatDC, 0, 0, 0xB8074A); | 692 | |
| 607 | #endif | ||
| 608 | if (fixed_pitch_size) | 693 | if (fixed_pitch_size) |
| 609 | left += fixed_pitch_size; | 694 | left += fixed_pitch_size; |
| 610 | else | 695 | else |
| 611 | left += pcb->metric.dwidth; | 696 | left += pcb->metric.dwidth; |
| 612 | } | 697 | } |
| 613 | SelectObject(hCompatDC, horgobj); | 698 | |
| 699 | DeleteDC(hCompatDC); | ||
| 700 | |||
| 614 | SelectObject(hdc, hOrgBrush); | 701 | SelectObject(hdc, hOrgBrush); |
| 615 | DeleteObject(hFgBrush); | 702 | DeleteObject(hFgBrush); |
| 616 | DeleteDC(hCompatDC); | ||
| 617 | RestoreDC(hdc, -1); | ||
| 618 | 703 | ||
| 619 | return 1; | 704 | return ret; |
| 620 | } | 705 | } |
| 621 | 706 | ||
| 622 | struct font_info *w32_load_bdf_font (struct frame *f, char *fontname, | 707 | struct font_info *w32_load_bdf_font (struct frame *f, char *fontname, |