summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/w32bdf.c604
-rw-r--r--src/w32bdf.h74
2 files changed, 678 insertions, 0 deletions
diff --git a/src/w32bdf.c b/src/w32bdf.c
new file mode 100644
index 00000000000..c6fc4f18370
--- /dev/null
+++ b/src/w32bdf.c
@@ -0,0 +1,604 @@
+/* Implementation of BDF font handling on the Microsoft W32 API.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Based heavily on code by H. Miyashita for Meadow (a descendant of
+ MULE for W32). */
+
+#include <windows.h>
+#include "config.h"
+#include "lisp.h"
+#include "charset.h"
+#include "fontset.h"
+#include "blockinput.h"
+#include "w32gui.h"
+#include "w32term.h"
+#include "w32bdf.h"
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+void w32_free_bdf_font(bdffont *fontp);
+bdffont *w32_init_bdf_font(char *filename);
+
+static int
+search_file_line(char *key, char *start, int len, char **val, char **next)
+{
+ int linelen;
+ unsigned char *p, *q;
+
+ p = memchr(start, '\n', len);
+ if (!p) return -1;
+ for (;start < p;start++)
+ {
+ if ((*start != ' ') || (*start != '\t')) break;
+ }
+ linelen = p - start + 1;
+ *next = p + 1;
+ if (strncmp(start, key, min(strlen(key), linelen)) == 0)
+ {
+ *val = start + strlen(key);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+proceed_file_line(char *key, char *start, int *len, char **val, char **next)
+{
+ int flag = 0;
+
+ do {
+ flag = search_file_line(key, start, *len, val, next);
+ *len -= (int)(*next - start);
+ start = *next;
+ }while(flag == 0);
+
+ if (flag == -1) return 0;
+ return 1;
+}
+
+static int
+set_bdf_font_info(bdffont *fontp)
+{
+ unsigned char *start, *p, *q;
+ int len, flag;
+ int bbw, bbh, bbx, bby;
+ int val1;
+
+ len = fontp->size;
+ start = fontp->font;
+
+ fontp->yoffset = 0;
+ fontp->relative_compose = 0;
+ fontp->default_ascent = 0;
+
+ flag = proceed_file_line("FONTBOUNDINGBOX", start, &len, &p, &q);
+ if (!flag) return 0;
+ bbw = strtol(p, &start, 10);
+ p = start;
+ bbh = strtol(p, &start, 10);
+ p = start;
+ bbx = strtol(p, &start, 10);
+ p = start;
+ bby = strtol(p, &start, 10);
+
+ fontp->llx = bbx;
+ fontp->lly = bby;
+ fontp->urx = bbw + bbx;
+ fontp->ury = bbh + bby;
+ fontp->width = bbw;
+ fontp->height = bbh;
+ start = q;
+ flag = proceed_file_line("STARTPROPERTIES", start, &len, &p, &q);
+ if (!flag) return 1;
+
+ do {
+ start = q;
+ if (search_file_line("PIXEL_SIZE", start, len, &p, &q) == 1)
+ {
+ val1 = atoi(p);
+ fontp->pixsz = val1;
+ }
+ else if (search_file_line("FONT_ASCENT", start, len, &p, &q) == 1)
+ {
+ val1 = atoi(p);
+ fontp->ury = val1;
+ }
+ else if (search_file_line("FONT_DESCENT", start, len, &p, &q) == 1)
+ {
+ val1 = atoi(p);
+ fontp->lly = -val1;
+ }
+ else if (search_file_line("_MULE_BASELINE_OFFSET", start, len, &p, &q) == 1)
+ {
+ val1 = atoi(p);
+ fontp->yoffset = val1;
+ }
+ else if (search_file_line("_MULE_RELATIVE_COMPOSE", start, len, &p, &q) == 1)
+ {
+ val1 = atoi(p);
+ fontp->relative_compose = val1;
+ }
+ else if (search_file_line("_MULE_DEFAULT_ASCENT", start, len, &p, &q) == 1)
+ {
+ val1 = atoi(p);
+ fontp->default_ascent = val1;
+ }
+ else
+ {
+ flag = search_file_line("ENDPROPERTIES", start, len, &p, &q);
+ }
+ if (flag == -1) return 0;
+ len -= (q - start);
+ }while(flag == 0);
+ start = q;
+ flag = proceed_file_line("CHARS", start, &len, &p, &q);
+ if (!flag) return 0;
+ fontp->seeked = q;
+
+ return 1;
+}
+
+bdffont*
+w32_init_bdf_font(char *filename)
+{
+ HANDLE hfile, hfilemap;
+ bdffont *bdffontp;
+ unsigned char *font;
+ BY_HANDLE_FILE_INFORMATION fileinfo;
+ int i;
+
+ hfile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hfile == INVALID_HANDLE_VALUE) return NULL;
+ if (!GetFileInformationByHandle(hfile, &fileinfo) ||
+ (fileinfo.nFileSizeHigh != 0) ||
+ (fileinfo.nFileSizeLow > BDF_FILE_SIZE_MAX))
+ {
+ CloseHandle(hfile);
+ error("Fail to open BDF file.");
+ }
+ hfilemap = CreateFileMapping(hfile, NULL, PAGE_READONLY, 0, 0, NULL);
+ if (hfilemap == INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(hfile);
+ error("Can't map font.");
+ }
+
+ font = MapViewOfFile(hfilemap, FILE_MAP_READ, 0, 0, 0);
+
+ if (!font)
+ {
+ CloseHandle(hfile);
+ CloseHandle(hfilemap);
+ error("Can't view font.");
+ }
+
+ bdffontp = (bdffont *) xmalloc(sizeof(bdffont));
+
+ for(i = 0;i < BDF_FIRST_OFFSET_TABLE;i++)
+ bdffontp->offset[i] = NULL;
+ bdffontp->size = fileinfo.nFileSizeLow;
+ bdffontp->font = font;
+ bdffontp->hfile = hfile;
+ bdffontp->hfilemap = hfilemap;
+ bdffontp->filename = (char*) xmalloc(strlen(filename) + 1);
+ strcpy(bdffontp->filename, filename);
+
+ if (!set_bdf_font_info(bdffontp))
+ {
+ w32_free_bdf_font(bdffontp);
+ error("Invalid BDF font!");
+ }
+ return bdffontp;
+}
+
+void
+w32_free_bdf_font(bdffont *fontp)
+{
+ int i;
+
+ UnmapViewOfFile(fontp->hfilemap);
+ CloseHandle(fontp->hfilemap);
+ CloseHandle(fontp->hfile);
+ xfree(fontp->filename);
+ for(i = 0;i < BDF_FIRST_OFFSET_TABLE;i++)
+ {
+ if (fontp->offset[i]) xfree(fontp->offset[i]);
+ }
+ xfree(fontp);
+}
+
+static unsigned char*
+get_cached_char_offset(bdffont *fontp, int index)
+{
+ unsigned char **offset1;
+ unsigned char *offset2;
+ int i;
+
+ if (index > 0xffff)
+ return NULL;
+
+ offset1 = fontp->offset[BDF_FIRST_OFFSET(index)];
+ if (!offset1)
+ return NULL;
+ offset2 = offset1[BDF_SECOND_OFFSET(index)];
+
+ if (offset2) return offset2;
+
+ return NULL;
+}
+
+static void
+cache_char_offset(bdffont *fontp, int index, unsigned char *offset)
+{
+ unsigned char **offset1;
+ int i;
+
+ if (index > 0xffff)
+ return;
+
+ offset1 = fontp->offset[BDF_FIRST_OFFSET(index)];
+ if (!offset1)
+ {
+ offset1 = fontp->offset[BDF_FIRST_OFFSET(index)] =
+ (unsigned char **) xmalloc(sizeof(unsigned char*) *
+ BDF_SECOND_OFFSET_TABLE);
+ memset(offset1, 0, sizeof(unsigned char*) * BDF_SECOND_OFFSET_TABLE);
+ }
+ offset1[BDF_SECOND_OFFSET(index)] = offset;
+
+ return;
+}
+
+static unsigned char*
+seek_char_offset(bdffont *fontp, int index)
+{
+ int len, flag, font_index;
+ unsigned char *start, *p, *q;
+
+ if (!fontp->seeked) return NULL;
+
+ start = fontp->seeked;
+ len = fontp->size - (start - fontp->font);
+
+ do {
+ flag = proceed_file_line("ENCODING", start, &len, &p, &q);
+ if (!flag)
+ {
+ fontp->seeked = NULL;
+ return NULL;
+ }
+ font_index = atoi(p);
+ cache_char_offset(fontp, font_index, q);
+ start = q;
+ } while (font_index != index);
+ fontp->seeked = q;
+
+ return q;
+}
+
+#define GET_HEX_VAL(x) ((isdigit(x)) ? ((x) - '0') : \
+ (((x) >= 'A') && ((x) <= 'Z')) ? ((x) - 'A' + 10) : \
+ (((x) >= 'a') && ((x) <= 'z')) ? ((x) - 'a' + 10) : \
+ (-1))
+
+int
+w32_get_bdf_glyph(bdffont *fontp, int index, int size, glyph_struct *glyph)
+{
+ unsigned char *start, *p, *q, *bitmapp;
+ unsigned char val1, val2;
+ int i, j, len, flag;
+
+ start = get_cached_char_offset(fontp, index);
+ if (!start)
+ start = seek_char_offset(fontp, index);
+ if (!start)
+ return 0;
+
+ len = fontp->size - (start - fontp->font);
+
+ flag = proceed_file_line("DWIDTH", start, &len, &p, &q);
+ if (!flag)
+ return 0;
+ glyph->dwidth = atoi(p);
+
+ start = q;
+ flag = proceed_file_line("BBX", start, &len, &p, &q);
+ if (!flag)
+ return 0;
+ glyph->bbw = strtol(p, &start, 10);
+ p = start;
+ glyph->bbh = strtol(p, &start, 10);
+ p = start;
+ glyph->bbox = strtol(p, &start, 10);
+ p = start;
+ glyph->bboy = strtol(p, &start, 10);
+
+ if (size == 0) return 1;
+
+ start = q;
+ flag = proceed_file_line("BITMAP", start, &len, &p, &q);
+ if (!flag)
+ return 0;
+
+ p = q;
+ bitmapp = glyph->bitmap;
+ for(i = 0;i < glyph->bbh;i++)
+ {
+ q = memchr(p, '\n', len);
+ if (!q) return 0;
+ for(j = 0;((q > p) && (j < ((glyph->bbw + 7) / 8 )));j++)
+ {
+ val1 = GET_HEX_VAL(*p);
+ if (val1 == -1) return 0;
+ p++;
+ 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);
+ }
+ /* CreateBitmap requires WORD alignment. */
+ if (j % 2)
+ {
+ *bitmapp++ = 0xff;
+ }
+ p = q + 1;
+ }
+
+ return 1;
+}
+
+int
+w32_BDF_TextOut(bdffont *fontp, HDC hdc, int left,
+ int top, unsigned char *text, int dim, int bytelen,
+ int fixed_pitch_size)
+{
+ int bitmap_size, index, btop;
+ unsigned char *textp;
+ glyph_struct glyph;
+ HDC hCompatDC = 0;
+ HBITMAP hBMP;
+ HBRUSH hFgBrush, hOrgBrush;
+ HANDLE holdobj, horgobj = 0;
+ UINT textalign;
+ int flag = 0;
+
+ bitmap_size = ((fontp->urx - fontp->llx) / 8 + 2) * (fontp->ury - fontp->lly)
+ + 256;
+
+ glyph.bitmap = (unsigned char*) alloca(sizeof(unsigned char) * bitmap_size);
+
+ hCompatDC = CreateCompatibleDC(hdc);
+
+ 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)
+ {
+ index = *textp++;
+ bytelen--;
+ }
+ else
+ {
+ bytelen -= 2;
+ if (bytelen < 0) break;
+ index = MAKELENDSHORT(textp[1], textp[0]);
+ textp += 2;
+ }
+ if (!w32_get_bdf_glyph(fontp, index, bitmap_size, &glyph))
+ {
+ if (horgobj)
+ {
+ SelectObject(hCompatDC, horgobj);
+ DeleteObject(hBMP);
+ }
+ DeleteDC(hCompatDC);
+ return 0;
+ }
+ hBMP = CreateBitmap(glyph.bbw, glyph.bbh, 1, 1, glyph.bitmap);
+ if (textalign & TA_BASELINE)
+ {
+ btop = top - (glyph.bbh + glyph.bboy);
+ }
+ else if (textalign & TA_BOTTOM)
+ {
+ btop = top - glyph.bbh;
+ }
+ else
+ {
+ btop = top;
+ }
+
+ if (horgobj)
+ {
+ SelectObject(hCompatDC, hBMP);
+ DeleteObject(holdobj);
+ holdobj = hBMP;
+ }
+ else
+ {
+ horgobj = SelectObject(hCompatDC, hBMP);
+ holdobj = hBMP;
+ }
+#if 0
+ BitBlt(hdc, left, btop, glyph.bbw, glyph.bbh, hCompatDC, 0, 0, SRCCOPY);
+#else
+ BitBlt(hdc, left, btop, glyph.bbw, glyph.bbh, hCompatDC, 0, 0, 0xB8074A);
+#endif
+ if (fixed_pitch_size)
+ left += fixed_pitch_size;
+ else
+ left += glyph.dwidth;
+ }
+ SelectObject(hCompatDC, horgobj);
+ SelectObject(hdc, hOrgBrush);
+ DeleteObject(hFgBrush);
+ DeleteObject(hBMP);
+ DeleteDC(hCompatDC);
+ RestoreDC(hdc, -1);
+
+ return 1;
+}
+
+struct font_info *w32_load_bdf_font (struct frame *f, char *fontname,
+ int size, char* filename)
+{
+ struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
+ struct font_info *fontp;
+ XFontStruct *font;
+ bdffont* bdf_font;
+
+ bdf_font = w32_init_bdf_font (filename);
+
+ if (!bdf_font) return NULL;
+
+ font = (XFontStruct *) xmalloc (sizeof (XFontStruct));
+
+ font->bdf = bdf_font;
+ font->hfont = 0;
+
+ /* Do we need to create the table? */
+ if (dpyinfo->font_table_size == 0)
+ {
+ dpyinfo->font_table_size = 16;
+ dpyinfo->font_table
+ = (struct font_info *) xmalloc (dpyinfo->font_table_size
+ * sizeof (struct font_info));
+ }
+ /* Do we need to grow the table? */
+ else if (dpyinfo->n_fonts
+ >= dpyinfo->font_table_size)
+ {
+ dpyinfo->font_table_size *= 2;
+ dpyinfo->font_table
+ = (struct font_info *) xrealloc (dpyinfo->font_table,
+ (dpyinfo->font_table_size
+ * sizeof (struct font_info)));
+ }
+
+ fontp = dpyinfo->font_table + dpyinfo->n_fonts;
+
+ /* Now fill in the slots of *FONTP. */
+ BLOCK_INPUT;
+ fontp->font = font;
+ fontp->font_idx = dpyinfo->n_fonts;
+ fontp->name = (char *) xmalloc (strlen (fontname) + 1);
+ bcopy (fontname, fontp->name, strlen (fontname) + 1);
+ fontp->full_name = fontp->name;
+ fontp->size = FONT_WIDTH (font);
+ fontp->height = FONT_HEIGHT (font);
+
+ /* The slot `encoding' specifies how to map a character
+ code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
+ the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
+ the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
+ 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
+ 2:0xA020..0xFF7F). For the moment, we don't know which charset
+ uses this font. So, we set informatoin in fontp->encoding[1]
+ which is never used by any charset. If mapping can't be
+ decided, set FONT_ENCODING_NOT_DECIDED. */
+ fontp->encoding[1] = FONT_ENCODING_NOT_DECIDED;
+ fontp->baseline_offset = bdf_font->yoffset;
+ fontp->relative_compose = bdf_font->relative_compose;
+ fontp->default_ascent = bdf_font->default_ascent;
+
+ UNBLOCK_INPUT;
+ dpyinfo->n_fonts++;
+ return fontp;
+}
+
+/* Check a file for an XFLD string describing it. */
+int w32_BDF_to_x_font (char *file, char* xstr, int len)
+{
+ HANDLE hfile, hfilemap;
+ BY_HANDLE_FILE_INFORMATION fileinfo;
+ unsigned char *font, *start, *p, *q;
+ int flag, size, retval = 0;
+
+ hfile = CreateFile (file, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hfile == INVALID_HANDLE_VALUE) return 0;
+ if (!GetFileInformationByHandle(hfile, &fileinfo) ||
+ (fileinfo.nFileSizeHigh != 0) ||
+ (fileinfo.nFileSizeLow > BDF_FILE_SIZE_MAX))
+ {
+ CloseHandle (hfile);
+ return 0;
+ }
+ size = fileinfo.nFileSizeLow;
+
+ hfilemap = CreateFileMapping (hfile, NULL, PAGE_READONLY, 0, 0, NULL);
+ if (hfilemap == INVALID_HANDLE_VALUE)
+ {
+ CloseHandle (hfile);
+ return 0;
+ }
+
+ font = MapViewOfFile (hfilemap, FILE_MAP_READ, 0, 0, 0);
+ if (!font)
+ {
+ CloseHandle (hfile);
+ CloseHandle (hfilemap);
+ return 0;
+ }
+ start = font;
+
+ flag = proceed_file_line ("FONT ", start, &size, &p, &q);
+ if (flag)
+ {
+ /* If font provides a description of itself, check it is a
+ full XLFD before accepting it. */
+ int count = 0;
+ char *s;
+
+ for (s = p; s < q; s++)
+ if (*s == '\n')
+ break;
+ else if (*s == '-')
+ count++;
+ if (count == 14 && q - p - 1 <= len)
+ {
+ strncpy (xstr, p, q-p-1);
+ xstr[q-p-1] = '\0';
+ /* Files may have DOS line ends (ie still ^M on end). */
+ if (iscntrl(xstr[q-p-2]))
+ xstr[q-p-2] = '\0';
+
+ retval = 1;
+ }
+ }
+ CloseHandle (hfile);
+ CloseHandle (hfilemap);
+ return retval;
+}
diff --git a/src/w32bdf.h b/src/w32bdf.h
new file mode 100644
index 00000000000..41821982cfa
--- /dev/null
+++ b/src/w32bdf.h
@@ -0,0 +1,74 @@
+/* Definitions and header for handling BDF fonts on the Microsoft W32 API.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Based heavily on code by H. Miyashita for Meadow (a descendant of
+ MULE for W32). */
+
+#ifndef __W32BDF_H__
+#define __W32BDF_H__
+
+#define BDF_FIRST_OFFSET_TABLE 0x200
+#define BDF_SECOND_OFFSET_TABLE 0x80
+#define BDF_SECOND_OFFSET(x) ((x) & 0x7f)
+#define BDF_FIRST_OFFSET(x) (((x) >> 8) | (((x) & 0x80) << 1))
+
+/* Structure of glyph information of one character. */
+typedef struct
+{
+ int dwidth; /* width in pixels */
+ int bbw, bbh, bbox, bboy; /* bounding box in pixels */
+ int bitmap_size; /* byte lengh of the following slots */
+ unsigned char *bitmap; /* */
+} glyph_struct;
+
+typedef struct
+{
+ char *filename;
+ HANDLE hfile;
+ HANDLE hfilemap;
+ unsigned char *font;
+ unsigned char *seeked;
+ DWORD size;
+ unsigned char **offset[BDF_FIRST_OFFSET_TABLE];
+ int llx, lly, urx, ury; /* Font bounding box */
+
+ int yoffset;
+ int relative_compose;
+ int default_ascent;
+ int width;
+ int height;
+ int pixsz;
+} bdffont;
+
+
+#define BDF_FILE_SIZE_MAX 256*1024*1024 /* 256Mb */
+#define BDF_FONT_FILE(font) (((bdffont*)(font))->filename)
+#define MAKELENDSHORT(c1, c2) (unsigned short)((c1) | ((c2) << 8))
+
+bdffont *w32_init_bdf_font (char *filename);
+void w32_free_bdf_font (bdffont *fontp);
+int w32_get_bdf_glyph (bdffont *fontp, int index, int size,
+ glyph_struct *glyph);
+int w32_BDF_TextOut (bdffont *fontp, HDC hdc, int left,
+ int top, unsigned char *text, int dim,
+ int bytelen, int fixed_pitch_size);
+int w32_BDF_to_x_font (char *file, char* xstr, int len);
+
+#endif /* __W32BDF_H__ */