📄 devfont.c
字号:
/*
* Copyright (c) 2000 Greg Haerr <greg@censoft.com>
* T1lib Adobe type1 routines contributed by Vidar Hokstad
* Freetype TrueType routines contributed by Martin Jolicoeur
* Han Zi Ku routines contributed by Tanghao and Jauming
*
* Device-independent font and text drawing routines
*
* These routines do the necessary range checking, clipping, and cursor
* overwriting checks, and then call the lower level device dependent
* routines to actually do the drawing. The lower level routines are
* only called when it is known that all the pixels to be drawn are
* within the device area and are visible.
*/
/*#define NDEBUG*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <string.h>
#include "device.h"
#if (UNIX | DOS_DJGPP)
#define strcmpi strcasecmp
#endif
#if HAVE_T1LIB_SUPPORT
#include <t1lib.h>
#define T1LIB_USE_AA_HIGH
typedef struct {
PMWFONTPROCS fontprocs; /* common hdr*/
MWCOORD fontsize;
int fontrotation;
int fontattr;
int fontid; /* t1lib stuff*/
} MWT1LIBFONT, *PMWT1LIBFONT;
static int t1lib_init(PSD psd);
static PMWT1LIBFONT t1lib_createfont(const char *name, MWCOORD height,int attr);
static void t1lib_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
const void *text, int cc, int flags);
static MWBOOL t1lib_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo);
static void t1lib_gettextsize(PMWFONT pfont, const void *text, int cc,
MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);
static void t1lib_destroyfont(PMWFONT pfont);
/* handling routines for MWT1LIBFONT*/
static MWFONTPROCS t1lib_procs = {
MWTF_ASCII, /* routines expect ascii*/
t1lib_getfontinfo,
t1lib_gettextsize,
NULL, /* gettextbits*/
t1lib_destroyfont,
t1lib_drawtext,
NULL, /* setfontsize*/
NULL, /* setfontrotation*/
NULL, /* setfontattr*/
};
#endif
#ifdef T1LIB_USE_AA_HIGH
typedef unsigned long OUTPIXELVAL;
#else
typedef MWPIXELVAL OUTPIXELVAL;
#endif
#if HAVE_FREETYPE_SUPPORT
#include <freetype/freetype.h>
#include <freetype/ftxkern.h>
#include <freetype/ftnameid.h>
#include <freetype/ftxcmap.h>
#include <freetype/ftxwidth.h>
#include <math.h>
#ifndef FREETYPE_FONT_DIR
#define FREETYPE_FONT_DIR "/usr/local/microwin/fonts"
#endif
#if TT_FREETYPE_MAJOR != 1 | TT_FREETYPE_MINOR < 3
#error "You must link with freetype lib version 1.3.x +, and not freetype 2. \
Download it at http://www.freetype.org or http://microwindows.org"
#endif
typedef struct {
PMWFONTPROCS fontprocs; /* common hdr*/
MWCOORD fontsize;
int fontrotation;
int fontattr;
TT_Face face; /* freetype stuff*/
TT_Instance instance;
TT_CharMap char_map;
TT_Kerning directory;
TT_Matrix matrix;
TT_Glyph glyph;
MWBOOL can_kern;
short last_glyph_code;
short last_pen_pos;
} MWFREETYPEFONT, *PMWFREETYPEFONT;
static int freetype_init(PSD psd);
static PMWFREETYPEFONT freetype_createfont(const char *name, MWCOORD height,
int attr);
static MWBOOL freetype_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo);
static void freetype_gettextsize(PMWFONT pfont, const void *text,
int cc, MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);
static void freetype_destroyfont(PMWFONT pfont);
static void freetype_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
const void *text, int cc, int flags);
static void freetype_setfontsize(PMWFONT pfont, MWCOORD fontsize);
static void freetype_setfontrotation(PMWFONT pfont, int tenthdegrees);
/* handling routines for MWFREETYPEFONT*/
static MWFONTPROCS freetype_procs = {
MWTF_UC16, /* routines expect unicode 16*/
freetype_getfontinfo,
freetype_gettextsize,
NULL, /* gettextbits*/
freetype_destroyfont,
freetype_drawtext,
freetype_setfontsize,
freetype_setfontrotation,
NULL, /* setfontattr*/
};
static TT_Engine engine; /* THE ONLY freetype engine */
#endif /* HAVE_FREETYPE_SUPPORT*/
#if HAVE_HZK_SUPPORT
/*
* 12x12 and 16x16 ascii and chinese fonts
* Big5 and GB2312 encodings supported
*/
#define MAX_PATH 256
typedef struct {
int width;
int height;
int size;
unsigned long use_count;
char * pFont;
char file[MAX_PATH + 1];
} HZKFONT;
static int use_big5=1;
static HZKFONT CFont[2]; /* font cache*/
static HZKFONT AFont[2]; /* font cache*/
/* jmt: moved inside MWHZKFONT*/
static int afont_width = 8;
static int cfont_width = 16;
static int font_height = 16;
static char *afont_address;
static char *cfont_address;
typedef struct {
PMWFONTPROCS fontprocs; /* common hdr*/
MWCOORD fontsize;
int fontrotation;
int fontattr;
HZKFONT CFont; /* hzkfont stuff */
HZKFONT AFont;
int afont_width;
int cfont_width;
int font_height;
char *afont_address;
char *cfont_address;
} MWHZKFONT, *PMWHZKFONT;
static int hzk_init(PSD psd);
static PMWHZKFONT hzk_createfont(const char *name, MWCOORD height,int fontattr);
static MWBOOL hzk_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo);
static void hzk_gettextsize(PMWFONT pfont, const void *text,
int cc, MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);
#if 0
static void hzk_gettextbits(PMWFONT pfont, int ch, IMAGEBITS *retmap,
MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);
static void hzk_setfontrotation(PMWFONT pfont, int tenthdegrees);
#endif
static void hzk_destroyfont(PMWFONT pfont);
static void hzk_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
const void *text, int cc, int flags);
static void hzk_setfontsize(PMWFONT pfont, MWCOORD fontsize);
/* handling routines for MWHZKFONT*/
static MWFONTPROCS hzk_procs = {
MWTF_ASCII, /* routines expect ASCII*/
hzk_getfontinfo,
hzk_gettextsize,
NULL, /* hzk_gettextbits*/
hzk_destroyfont,
hzk_drawtext,
hzk_setfontsize,
NULL, /* setfontrotation*/
NULL, /* setfontattr*/
};
static int
UC16_to_GB(const unsigned char *uc16, int cc, unsigned char *ascii);
#endif /* HAVE_HZK_SUPPORT*/
static PMWFONT gr_pfont; /* current font*/
/* temp extern decls*/
extern MWPIXELVAL gr_foreground;
extern MWPIXELVAL gr_background;
extern MWBOOL gr_usebg;
static int utf8_to_utf16(const unsigned char *utf8, int cc,
unsigned short *unicode16);
#if FONTMAPPER
/* entry point for font selection*/
int select_font(const PMWLOGFONT plogfont, char *physname);
#endif
/*
* Set the font for future calls.
*/
PMWFONT
GdSetFont(PMWFONT pfont)
{
PMWFONT oldfont = gr_pfont;
gr_pfont = pfont;
return oldfont;
}
/*
* Select a font, based on various parameters.
* If plogfont is specified, name and height parms are ignored
* and instead used from MWLOGFONT.
*
* If height is 0, return builtin font from passed name.
* Otherwise find builtin font best match based on height.
*/
PMWFONT
GdCreateFont(PSD psd, const char *name, MWCOORD height,
const PMWLOGFONT plogfont)
{
int i;
int fontht;
int fontno;
int fontclass;
int fontattr = 0;
PMWFONT pfont;
PMWCOREFONT pf = psd->builtin_fonts;
MWFONTINFO fontinfo;
MWSCREENINFO scrinfo;
char fontname[128];
GdGetScreenInfo(psd, &scrinfo);
/* if plogfont not specified, use name and height*/
if (!plogfont) {
if (!name)
name = MWFONT_SYSTEM_VAR;
strcpy(fontname, name);
fontclass = MWLF_CLASS_ANY;
} else {
#if FONTMAPPER
/* otherwise, use MWLOGFONT name and height*/
fontclass = select_font(plogfont, fontname);
#else
if (!name)
name = MWFONT_SYSTEM_VAR;
strcpy(fontname, name);
fontclass = MWLF_CLASS_ANY;
#endif
height = plogfont->lfHeight;
if (plogfont->lfUnderline)
fontattr = MWTF_UNDERLINE;
}
height = abs(height);
if (!fontclass)
goto first;
/* use builtin screen fonts, FONT_xxx, if height is 0 */
if (height == 0 || fontclass == MWLF_CLASS_ANY ||
fontclass == MWLF_CLASS_BUILTIN) {
for(i = 0; i < scrinfo.fonts; ++i) {
if(!strcmpi(pf[i].name, fontname)) {
pf[i].fontsize = pf[i].cfont->height;
pf[i].fontattr = fontattr;
return (PMWFONT)&pf[i];
}
}
/* return first builtin font*/
if (height == 0 || fontclass == MWLF_CLASS_BUILTIN)
goto first;
}
#if HAVE_HZK_SUPPORT
/* Make sure the library is initialized */
if (hzk_init(psd)) {
pfont = (PMWFONT)hzk_createfont(name, height, fontattr);
if(pfont)
return pfont;
fprintf(stderr, "hzk_createfont: %s not found\n", name);
}
#endif
#if HAVE_FREETYPE_SUPPORT
if (fontclass == MWLF_CLASS_ANY || fontclass == MWLF_CLASS_FREETYPE) {
if (freetype_init(psd)) {
/* auto antialias for height > 14 for kaffe*/
if (plogfont && plogfont->lfHeight > 14 &&
plogfont->lfQuality)
fontattr |= MWTF_ANTIALIAS;
pfont = (PMWFONT)freetype_createfont(fontname, height,
fontattr);
if(pfont) {
/* temp kaffe kluge*/
pfont->fontattr |= FS_FREETYPE;
return pfont;
}
DPRINTF("freetype_createfont: %s,%d not found\n",
fontname, height);
}
}
#endif
#if HAVE_T1LIB_SUPPORT
if (fontclass == MWLF_CLASS_ANY || fontclass == MWLF_CLASS_T1LIB) {
if (t1lib_init(psd)) {
pfont = (PMWFONT)t1lib_createfont(fontname, height,
fontattr);
if(pfont)
return pfont;
DPRINTF("t1lib_createfont: %s,%d not found\n",
fontname, height);
}
}
#endif
/* find builtin font closest in height*/
if(height != 0) {
fontno = 0;
height = abs(height);
fontht = MAX_MWCOORD;
for(i = 0; i < scrinfo.fonts; ++i) {
pfont = (PMWFONT)&pf[i];
GdGetFontInfo(pfont, &fontinfo);
if(fontht > abs(height-fontinfo.height)) {
fontno = i;
fontht = abs(height-fontinfo.height);
}
}
pf[fontno].fontsize = pf[fontno].cfont->height;
pf[fontno].fontattr = fontattr;
return (PMWFONT)&pf[fontno];
}
first:
/* Return first builtin font*/
pf->fontsize = pf->cfont->height;
pf->fontattr = fontattr;
return (PMWFONT)&pf[0];
}
/* Set the font size for the passed font*/
MWCOORD
GdSetFontSize(PMWFONT pfont, MWCOORD fontsize)
{
MWCOORD oldfontsize = pfont->fontsize;
pfont->fontsize = fontsize;
if (pfont->fontprocs->SetFontSize)
pfont->fontprocs->SetFontSize(pfont, fontsize);
return oldfontsize;
}
/* Set the font rotation angle in tenths of degrees for the passed font*/
int
GdSetFontRotation(PMWFONT pfont, int tenthdegrees)
{
MWCOORD oldrotation = pfont->fontrotation;
pfont->fontrotation = tenthdegrees;
if (pfont->fontprocs->SetFontRotation)
pfont->fontprocs->SetFontRotation(pfont, tenthdegrees);
return oldrotation;
}
/*
* Set/reset font attributes (MWTF_KERNING, MWTF_ANTIALIAS)
* for the passed font.
*/
int
GdSetFontAttr(PMWFONT pfont, int setflags, int clrflags)
{
MWCOORD oldattr = pfont->fontattr;
pfont->fontattr &= ~clrflags;
pfont->fontattr |= setflags;
if (pfont->fontprocs->SetFontAttr)
pfont->fontprocs->SetFontAttr(pfont, setflags, clrflags);
return oldattr;
}
/* Unload and deallocate font*/
void
GdDestroyFont(PMWFONT pfont)
{
if (pfont->fontprocs->DestroyFont)
pfont->fontprocs->DestroyFont(pfont);
}
/* Return information about a specified font*/
MWBOOL
GdGetFontInfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
{
if(!pfont || !pfont->fontprocs->GetFontInfo)
return FALSE;
return pfont->fontprocs->GetFontInfo(pfont, pfontinfo);
}
/*
* Convert from one encoding to another
* Input cc and returned cc is character count, not bytes
* Return < 0 on error or can't translate
*/
int
GdConvertEncoding(const void *istr, int iflags, int cc, void *ostr, int oflags)
{
const unsigned char *istr8;
const unsigned short *istr16;
const unsigned long *istr32;
unsigned char *ostr8;
unsigned short *ostr16;
unsigned long *ostr32;
unsigned int ch;
int icc;
unsigned short buf16[512];
iflags &= MWTF_PACKMASK;
oflags &= MWTF_PACKMASK;
/* allow -1 for len with ascii*/
if(cc == -1 && (iflags == MWTF_ASCII))
cc = strlen((char *)istr);
/* first check for utf8 input encoding*/
if(iflags == MWTF_UTF8) {
/* we've only got uc16 now so convert to uc16...*/
cc = utf8_to_utf16((unsigned char *)istr, cc,
oflags==MWTF_UC16?(unsigned short*) ostr: buf16);
if(oflags == MWTF_UC16 || cc < 0)
return cc;
/* will decode again to requested format (probably ascii)*/
iflags = MWTF_UC16;
istr = buf16;
}
#if HAVE_HZK_SUPPORT
if(iflags == MWTF_UC16 && oflags == MWTF_ASCII) {
/* only support uc16 convert to ascii now...*/
cc = UC16_to_GB( istr, cc, ostr);
return cc;
}
#endif
icc = cc;
istr8 = istr;
istr16 = istr;
istr32 = istr;
ostr8 = ostr;
ostr16 = ostr;
ostr32 = ostr;
/* Convert between formats. Note that there's no error
* checking here yet.
*/
while(--icc >= 0) {
switch(iflags) {
default:
ch = *istr8++;
break;
case MWTF_UC16:
ch = *istr16++;
break;
case MWTF_UC32:
ch = *istr32++;
}
switch(oflags) {
default:
*ostr8++ = (unsigned char)ch;
break;
case MWTF_UC16:
*ostr16++ = (unsigned short)ch;
break;
case MWTF_UC32:
*ostr32++ = ch;
}
}
return cc;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -