Mercurial > emacs
changeset 32024:a0ba404b97a5
(search_file_line): Fix skipping of whitespace.
(get_quoted_string): Fix limit on memchr search.
(set_bdf_font_info): Use unsigned chars. Negate yoffset.
(w32_init_bdf_font): Initialize codepoint and bitmap heaps.
(w32_free_bdf_font): Free bitmaps and codepoints on heaps.
(get_cached_font_char, cache_char_offset): Use macro
BDF_CODEPOINT_RANGE_COVER_P.
(cache_char_offset): Use HeapAlloc to allocate codepoints on own heap.
(clear_cached_bitmap_slots): New function.
(GET_HEX_VALUE): G-Z, g-z are not hex.
(w32_get_bdf_glyph): Convert to DIB format. Return bytes read.
(get_bitmap_with_cache): Use new cache implementation.
(create_offscreen_bitmap): New function.
(w32_BDF_TextOut): Use it. Draw glyphs as DIBs.
author | Jason Rumney <jasonr@gnu.org> |
---|---|
date | Fri, 29 Sep 2000 21:23:10 +0000 |
parents | cc32b6a62560 |
children | e67c88d8e5c4 |
files | src/w32bdf.c |
diffstat | 1 files changed, 193 insertions(+), 108 deletions(-) [+] |
line wrap: on
line diff
--- a/src/w32bdf.c Fri Sep 29 21:21:54 2000 +0000 +++ b/src/w32bdf.c Fri Sep 29 21:23:10 2000 +0000 @@ -36,26 +36,33 @@ #define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) > (b) ? (a) : (b)) -/* Portion of GDI Objects which the font cache is allowed to use. This - can be quite high, since the font cache is the only part of Emacs - that uses a large number of GDI objects, but there should still be - some GDI objects reserved for other uses. */ -#define CACHE_GDI_ALLOWANCE 9 / 10 +/* 10 planes */ +#define BDF_CODEPOINT_HEAP_INITIAL_SIZE (96 * 10) +/* about 96 characters */ +#define BDF_BITMAP_HEAP_INITIAL_SIZE (64 * 96) + +HANDLE hbdf_cp_heap = INVALID_HANDLE_VALUE; +HANDLE hbdf_bmp_heap = INVALID_HANDLE_VALUE; void w32_free_bdf_font(bdffont *fontp); bdffont *w32_init_bdf_font(char *filename); +cache_bitmap cached_bitmap_slots[BDF_FONT_CACHE_SIZE]; +cache_bitmap *pcached_bitmap_latest = cached_bitmap_slots; + +#define FONT_CACHE_SLOT_OVER_P(p) ((p) >= cached_bitmap_slots + BDF_FONT_CACHE_SIZE) + static int search_file_line(char *key, char *start, int len, char **val, char **next) { int linelen; - char *p; + unsigned char *p, *q; p = memchr(start, '\n', len); if (!p) return -1; for (;start < p;start++) { - if ((*start != ' ') || (*start != '\t')) break; + if ((*start != ' ') && (*start != '\t')) break; } linelen = p - start + 1; *next = p + 1; @@ -82,18 +89,16 @@ if (flag == -1) return 0; return 1; } - + char* get_quoted_string(char *start, char *end) { char *p, *q, *result; p = memchr(start, '\"', end - start); - q = 0; - if (!p) return NULL; p++; - q = memchr(p, '\"', end - q); + q = memchr(p, '\"', end - p); if (!q) return NULL; result = (char*) xmalloc(q - p + 1); @@ -107,7 +112,7 @@ static int set_bdf_font_info(bdffont *fontp) { - char *start, *p, *q; + unsigned char *start, *p, *q; int len, flag; int bbw, bbh, bbx, bby; int val1; @@ -118,6 +123,7 @@ fontp->yoffset = 0; fontp->relative_compose = 0; fontp->default_ascent = 0; + fontp->registry = NULL; fontp->encoding = NULL; fontp->slant = NULL; @@ -165,7 +171,7 @@ else if (search_file_line("_MULE_BASELINE_OFFSET", start, len, &p, &q) == 1) { val1 = atoi(p); - fontp->yoffset = val1; + fontp->yoffset = -val1; } else if (search_file_line("_MULE_RELATIVE_COMPOSE", start, len, &p, &q) == 1) { @@ -219,6 +225,14 @@ BY_HANDLE_FILE_INFORMATION fileinfo; int i; + if (hbdf_cp_heap == INVALID_HANDLE_VALUE) + hbdf_cp_heap = HeapCreate(0, BDF_CODEPOINT_HEAP_INITIAL_SIZE, 0); + if (hbdf_bmp_heap = INVALID_HANDLE_VALUE) + hbdf_bmp_heap = HeapCreate(0, BDF_BITMAP_HEAP_INITIAL_SIZE, 0); + + if (!hbdf_cp_heap || !hbdf_bmp_heap) + error("Fail to create heap for BDF."); + hfile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hfile == INVALID_HANDLE_VALUE) return NULL; @@ -289,9 +303,14 @@ for (j = 0;j < BDF_SECOND_OFFSET_TABLE;j++) { pcb = pch[j].pcbmp; - if (pcb) pcb->psrc = NULL; + if (pcb) + { + if (pcb->pbmp) + HeapFree(hbdf_bmp_heap, 0, pcb->pbmp); + pcb->psrc = NULL; } - xfree(pch); + } + HeapFree(hbdf_cp_heap, 0, pch); } } xfree(fontp); @@ -303,12 +322,13 @@ font_char *pch, *result; int i; - if (index > 0xffff) + if (!BDF_CODEPOINT_RANGE_COVER_P(index)) return NULL; pch = fontp->chtbl[BDF_FIRST_OFFSET(index)]; if (!pch) return NULL; + result = &pch[BDF_SECOND_OFFSET(index)]; if (!result->offset) return NULL; @@ -322,16 +342,19 @@ font_char *pch, *result; int i; - if (index > 0xffff) + if (!BDF_CODEPOINT_RANGE_COVER_P(index)) return NULL; pch = fontp->chtbl[BDF_FIRST_OFFSET(index)]; if (!pch) { pch = fontp->chtbl[BDF_FIRST_OFFSET(index)] = - (font_char*) xmalloc(sizeof(font_char) * - BDF_SECOND_OFFSET_TABLE); - memset(pch, 0, sizeof(font_char) * BDF_SECOND_OFFSET_TABLE); + (font_char*) HeapAlloc(hbdf_cp_heap, + HEAP_ZERO_MEMORY, + sizeof(font_char) * + BDF_SECOND_OFFSET_TABLE); + if (!pch) return NULL; + /* memset(pch, 0, sizeof(font_char) * BDF_SECOND_OFFSET_TABLE); */ } result = &pch[BDF_SECOND_OFFSET(index)]; @@ -345,8 +368,7 @@ { font_char *result; int len, flag, font_index; - unsigned char *start; - char *p, *q; + unsigned char *start, *p, *q; if (!fontp->seeked) return NULL; @@ -371,19 +393,41 @@ return result; } +static void +clear_cached_bitmap_slots() +{ + int i; + cache_bitmap *p; + + p = pcached_bitmap_latest; + for (i = 0;i < BDF_FONT_CLEAR_SIZE;i++) + { + if (p->psrc) + { + if (p->pbmp) + HeapFree(hbdf_bmp_heap, 0, p->pbmp); + p->psrc->pcbmp = NULL; + p->psrc = NULL; + } + p++; + if (FONT_CACHE_SLOT_OVER_P(p)) + p = cached_bitmap_slots; + } +} + #define GET_HEX_VAL(x) ((isdigit(x)) ? ((x) - '0') : \ - (((x) >= 'A') && ((x) <= 'Z')) ? ((x) - 'A' + 10) : \ - (((x) >= 'a') && ((x) <= 'z')) ? ((x) - 'a' + 10) : \ + (((x) >= 'A') && ((x) <= 'F')) ? ((x) - 'A' + 10) : \ + (((x) >= 'a') && ((x) <= 'f')) ? ((x) - 'a' + 10) : \ (-1)) int w32_get_bdf_glyph(bdffont *fontp, int index, int size, glyph_struct *glyph) { font_char *pch; - unsigned char *start, *bitmapp; - char *p, *q; - char val1, val2; - int i, j, len, flag; + unsigned char *start, *p, *q, *bitmapp; + unsigned char val, val1, val2; + int i, j, len, flag, consumed; + int align, rowbytes; pch = get_cached_font_char(fontp, index); if (!pch) @@ -427,13 +471,23 @@ if (!flag) return 0; + consumed = 0; + flag = 0; p = q; bitmapp = glyph->bitmap; + rowbytes = (glyph->metric.bbw + 7) / 8; + /* DIB requires DWORD alignment. */ + align = sizeof(DWORD) - rowbytes % sizeof(DWORD); + consumed = glyph->metric.bbh * (rowbytes + align); + glyph->bitmap_size = consumed; + glyph->row_byte_size = rowbytes; + if (size < consumed) return 0; + for(i = 0;i < glyph->metric.bbh;i++) { q = memchr(p, '\n', len); if (!q) return 0; - for(j = 0;((q > p) && (j < ((glyph->metric.bbw + 7) / 8 )));j++) + for(j = 0;((q > p) && (j < rowbytes));j++) { val1 = GET_HEX_VAL(*p); if (val1 == -1) return 0; @@ -441,38 +495,30 @@ val2 = GET_HEX_VAL(*p); if (val2 == -1) return 0; p++; - size--; - if (size <= 0) return 0; - /* NAND Operation. */ - *bitmapp++ = (unsigned char)~((val1 << 4) | val2); + val = (unsigned char)((val1 << 4) | val2); + if (val) flag = 1; + *bitmapp++ = val; } - /* CreateBitmap requires WORD alignment. */ - if (j % 2) - { - *bitmapp++ = 0xff; - } + for(j = 0;j < align;j++) + *bitmapp++ = 0x00; p = q + 1; } - return 1; + /* If this glyph is white space, return -1. */ + if (flag == 0) return -1; + + return consumed; } -#define NEXT_CACHE_SLOT(n) (((n) + 1 >= BDF_FONT_CACHE_SIZE) ? 0 : ((n) + 1)) - static cache_bitmap* get_bitmap_with_cache(bdffont *fontp, int index) { - int bitmap_size; + int bitmap_size, bitmap_real_size; font_char *pch; cache_bitmap* pcb; - HBITMAP hbmp; + unsigned char *pbmp; glyph_struct glyph; - static cache_bitmap cached_bitmap_slots[BDF_FONT_CACHE_SIZE]; - static int cache_in_slot = 0; /* the next slot to use */ - static int cache_out_slot = 0; /* the last slot allocated */ - static int cache_occupancy = 0; /* current cache occupancy */ - static int cache_limit = BDF_FONT_CACHE_SIZE; /* allowed maximum occupancy */ pch = get_cached_font_char(fontp, index); if (pch) @@ -481,60 +527,87 @@ if (pcb) return pcb; } - bitmap_size = ((fontp->urx - fontp->llx) / 8 + 2) * (fontp->ury - fontp->lly) + bitmap_size = ((fontp->urx - fontp->llx) / 8 + 3) * (fontp->ury - fontp->lly) + 256; glyph.bitmap = (unsigned char*) alloca(sizeof(unsigned char) * bitmap_size); - if (!w32_get_bdf_glyph(fontp, index, bitmap_size, &glyph)) + bitmap_real_size = w32_get_bdf_glyph(fontp, index, bitmap_size, &glyph); + + if (bitmap_real_size == 0) return NULL; pch = get_cached_font_char(fontp, index); if (!pch) return NULL; - hbmp = CreateBitmap(glyph.metric.bbw, glyph.metric.bbh, 1, 1, glyph.bitmap); - - /* if bitmap allocation fails reduce the limit of the occupancy so - that we can hope it will not happen again. */ - if (hbmp == NULL) - cache_limit = cache_occupancy * CACHE_GDI_ALLOWANCE; - - /* if cache occupancy reaches at the limit release some cache slots */ - if (cache_occupancy >= cache_limit) + if (bitmap_real_size > 0) { - register int size_to_clear = cache_limit * BDF_FONT_CLEAR_SIZE - / BDF_FONT_CACHE_SIZE; - for (; size_to_clear; size_to_clear--, - cache_out_slot = NEXT_CACHE_SLOT(cache_out_slot)) - { - register cache_bitmap *p = &cached_bitmap_slots[cache_out_slot]; - if (p->psrc) - { - DeleteObject(p->hbmp); - p->psrc->pcbmp = NULL; - p->psrc = NULL; - cache_occupancy--; - } - } + pbmp = (unsigned char*) HeapAlloc(hbdf_bmp_heap, 0, + bitmap_real_size); + if (!pbmp) return NULL; + memcpy(pbmp, glyph.bitmap, bitmap_real_size); } + else + pbmp = NULL; /* white space character */ - if (hbmp == NULL) - hbmp = CreateBitmap (glyph.metric.bbw, glyph.metric.bbh, - 1, 1, glyph.bitmap); - - pcb = &cached_bitmap_slots[cache_in_slot]; + pcb = pcached_bitmap_latest; + if (pcb->psrc) + clear_cached_bitmap_slots(); pcb->psrc = pch; pcb->metric = glyph.metric; - pcb->hbmp = hbmp; + pcb->pbmp = pbmp; + pcb->bitmap_size = glyph.bitmap_size; + pcb->row_byte_size = glyph.row_byte_size; pch->pcbmp = pcb; - cache_in_slot = NEXT_CACHE_SLOT(cache_in_slot); - cache_occupancy++; + pcached_bitmap_latest++; + if (FONT_CACHE_SLOT_OVER_P(pcached_bitmap_latest)) + pcached_bitmap_latest = cached_bitmap_slots; return pcb; } +static HBITMAP +create_offscreen_bitmap(HDC hdc, int width, int height, unsigned char **bitsp) +{ + HBITMAP hBMP; + struct { + BITMAPINFOHEADER h; + RGBQUAD c[2]; + } info; + + memset(&info, 0, sizeof(info)); + info.h.biSize = sizeof(BITMAPINFOHEADER); + info.h.biWidth = width; + info.h.biHeight = -height; + info.h.biPlanes = 1; + info.h.biBitCount = 1; + info.h.biCompression = BI_RGB; + info.c[1].rgbRed = info.c[1].rgbGreen = info.c[1].rgbBlue = 255; + + return CreateDIBSection(hdc, (LPBITMAPINFO)&info, + DIB_RGB_COLORS, bitsp, NULL, 0); +} + +glyph_metric * +w32_BDF_TextMetric(bdffont *fontp, unsigned char *text, int dim) +{ + int index; + cache_bitmap *pcb; + + if (dim == 1) + index = *text; + else + index = MAKELENDSHORT(text[1], text[0]); + + pcb = get_bitmap_with_cache(fontp, index); + if (!pcb) + return NULL; + + return &(pcb->metric); +} + int w32_BDF_TextOut(bdffont *fontp, HDC hdc, int left, int top, unsigned char *text, int dim, int bytelen, @@ -542,26 +615,29 @@ { int index, btop; unsigned char *textp; - HDC hCompatDC = 0; cache_bitmap *pcb; - HBITMAP hBMP; HBRUSH hFgBrush, hOrgBrush; - HANDLE horgobj = 0; + HANDLE horgobj; UINT textalign; - int flag = 0; + int width, height; + HDC hCompatDC; + int ret = 1; + static HBITMAP hBMP = 0; + static HDC DIBsection_hdc = 0; + static int DIBsection_width, DIBsection_height; + static unsigned char *bits; hCompatDC = CreateCompatibleDC(hdc); + if (!hCompatDC) + return 0; textalign = GetTextAlign(hdc); - SaveDC(hdc); - hFgBrush = CreateSolidBrush(GetTextColor(hdc)); hOrgBrush = SelectObject(hdc, hFgBrush); - SetTextColor(hdc, RGB(0, 0, 0)); - SetBkColor(hdc, RGB(0xff, 0xff, 0xff)); textp = text; + while(bytelen > 0) { if (dim == 1) @@ -579,15 +655,28 @@ pcb = get_bitmap_with_cache(fontp, index); if (!pcb) { - if (horgobj) - { - SelectObject(hCompatDC, horgobj); - DeleteObject(hBMP); + ret = 0; + break; } - DeleteDC(hCompatDC); - return 0; + if (pcb->pbmp) + { + width = pcb->metric.bbw; + height = pcb->metric.bbh; + + if (!(hBMP + && (DIBsection_hdc == hdc) + && (DIBsection_width == width) + && (DIBsection_height == height))) + { + if (hBMP) DeleteObject(hBMP); + hBMP = create_offscreen_bitmap(hdc, width, height, &bits); + DIBsection_hdc = hdc; + DIBsection_width = width; + DIBsection_height = height; + if (!hBMP) return 0; } - hBMP = pcb->hbmp; + + memcpy(bits, pcb->pbmp, pcb->bitmap_size); if (textalign & TA_BASELINE) btop = top - (pcb->metric.bbh + pcb->metric.bboy); @@ -596,27 +685,23 @@ else btop = top; - if (horgobj) - SelectObject(hCompatDC, hBMP); - else horgobj = SelectObject(hCompatDC, hBMP); -#if 0 - BitBlt(hdc, left, btop, pcb->metric.bbw, pcb->metric.bbh, hCompatDC, 0, 0, SRCCOPY); -#else - BitBlt(hdc, left, btop, pcb->metric.bbw, pcb->metric.bbh, hCompatDC, 0, 0, 0xB8074A); -#endif + BitBlt(hdc, left, btop, width, height, hCompatDC, 0, 0, 0xE20746); + SelectObject(hCompatDC, horgobj); + } + if (fixed_pitch_size) left += fixed_pitch_size; else left += pcb->metric.dwidth; } - SelectObject(hCompatDC, horgobj); + + DeleteDC(hCompatDC); + SelectObject(hdc, hOrgBrush); DeleteObject(hFgBrush); - DeleteDC(hCompatDC); - RestoreDC(hdc, -1); - return 1; + return ret; } struct font_info *w32_load_bdf_font (struct frame *f, char *fontname,