📄 devfont.c
字号:
}
/* Get the width and height of passed text string in the passed font*/
void
GdGetTextSize(PMWFONT pfont, const void *str, int cc, MWCOORD *pwidth,
MWCOORD *pheight, MWCOORD *pbase, int flags)
{
const void * text;
unsigned long buf[256];
int defencoding = pfont->fontprocs->encoding;
/* convert encoding if required*/
if((flags & MWTF_PACKMASK) != defencoding) {
cc = GdConvertEncoding(str, flags, cc, buf, defencoding);
flags &= ~MWTF_PACKMASK;
flags |= defencoding;
text = buf;
} else text = str;
if(cc == -1 && (flags & MWTF_PACKMASK) == MWTF_ASCII)
cc = strlen((char *)str);
if(cc <= 0 || !pfont->fontprocs->GetTextSize) {
*pwidth = *pheight = *pbase = 0;
return;
}
/* calc height and width of string*/
pfont->fontprocs->GetTextSize(pfont, text, cc, pwidth, pheight, pbase);
}
/* Draw a text string at a specifed coordinates in the foreground color
* (and possibly the background color), applying clipping if necessary.
* The background color is only drawn if the gr_usebg flag is set.
* Use the current font.
*/
void
GdText(PSD psd, MWCOORD x, MWCOORD y, const void *str, int cc, int flags)
{
const void * text;
unsigned long buf[256];
int defencoding = gr_pfont->fontprocs->encoding;
/* convert encoding if required*/
if((flags & MWTF_PACKMASK) != defencoding) {
cc = GdConvertEncoding(str, flags, cc, buf, defencoding);
flags &= ~MWTF_PACKMASK;
flags |= defencoding;
text = buf;
} else text = str;
if(cc == -1 && (flags & MWTF_PACKMASK) == MWTF_ASCII)
cc = strlen((char *)str);
if(cc <= 0 || !gr_pfont->fontprocs->DrawText)
return;
/* draw text string*/
gr_pfont->fontprocs->DrawText(gr_pfont, psd, x, y, text, cc, flags);
}
/*
* Draw ascii text using COREFONT type font.
*/
void
corefont_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
const void *text, int cc, int flags)
{
const unsigned char *str = text;
MWCOORD width; /* width of text area */
MWCOORD height; /* height of text area */
MWCOORD base; /* baseline of text*/
MWCOORD startx, starty;
/* bitmap for characters */
MWIMAGEBITS bitmap[MAX_CHAR_HEIGHT*MAX_CHAR_WIDTH/MWIMAGE_BITSPERIMAGE];
pfont->fontprocs->GetTextSize(pfont, str, cc, &width, &height, &base);
if(flags & MWTF_BASELINE)
y -= base;
else if(flags & MWTF_BOTTOM)
y -= (height - 1);
startx = x;
starty = y + base;
switch (GdClipArea(psd, x, y, x + width - 1, y + height - 1)) {
case CLIP_VISIBLE:
/*
* For size considerations, there's no low-level text
* draw, so we've got to draw all text
* with per-point clipping for the time being
if (gr_usebg)
psd->FillRect(psd, x, y, x + width - 1, y + height - 1,
gr_background);
psd->DrawText(psd, x, y, str, cc, gr_foreground, pfont);
GdFixCursor(psd);
return;
*/
break;
case CLIP_INVISIBLE:
return;
}
/* Get the bitmap for each character individually, and then display
* them using clipping for each one.
*/
while (--cc >= 0 && x < psd->xvirtres) {
unsigned int ch = *str++;
#if HAVE_BIG5_SUPPORT
/* chinese big5 decoding*/
if (ch >= 0xA1 && ch <= 0xF9 && cc >= 1 &&
((*str >= 0x40 && *str <= 0x7E) ||
(*str >= 0xA1 && *str <= 0xFE)) ) {
ch = (ch << 8) | *str++;
--cc;
}
#endif
#if HAVE_GB2312_SUPPORT
/* chinese gb2312 decoding*/
if (ch >= 0xA1 && ch < 0xF8 && cc >= 1 &&
*str >= 0xA1 && *str < 0xFF) {
ch = (ch << 8) | *str++;
--cc;
}
#endif
#if HAVE_KSC5601_SUPPORT
/* Korean KSC5601 decoding */
if (ch >= 0xA1 && ch <= 0xFE && cc >= 1 &&
(*str >= 0xA1 && *str <= 0xFE)) {
ch = (ch << 8) | *str++;
--cc;
}
#endif
pfont->fontprocs->GetTextBits(pfont, ch, bitmap, &width,
&height, &base);
/* note: change to bitmap*/
GdBitmap(psd, x, y, width, height, bitmap);
x += width;
}
if (pfont->fontattr & MWTF_UNDERLINE)
GdLine(psd, startx, starty, x, starty, FALSE);
GdFixCursor(psd);
}
#if HAVE_T1LIB_SUPPORT | HAVE_FREETYPE_SUPPORT
/*
* Produce blend table from src and dst based on passed alpha table
* Used because we don't quite yet have GdArea with alphablending,
* so we pre-blend fg/bg colors for fade effect.
*/
static void
alphablend(PSD psd, OUTPIXELVAL *out, MWPIXELVAL src, MWPIXELVAL dst,
unsigned char *alpha, int count)
{
unsigned int a, d;
unsigned char r, g, b;
MWCOLORVAL palsrc, paldst;
extern MWPALENTRY gr_palette[256];
while (--count >= 0) {
a = *alpha++;
#define BITS(pixel,shift,mask) (((pixel)>>shift)&(mask))
if(a == 0)
*out++ = dst;
else if(a == 255)
*out++ = src;
else
switch(psd->pixtype) {
case MWPF_TRUECOLOR0888:
case MWPF_TRUECOLOR888:
d = BITS(dst, 16, 0xff);
r = (unsigned char)(((BITS(src, 16, 0xff) - d)*a)>>8) + d;
d = BITS(dst, 8, 0xff);
g = (unsigned char)(((BITS(src, 8, 0xff) - d)*a)>>8) + d;
d = BITS(dst, 0, 0xff);
b = (unsigned char)(((BITS(src, 0, 0xff) - d)*a)>>8) + d;
*out++ = (r << 16) | (g << 8) | b;
break;
case MWPF_TRUECOLOR565:
d = BITS(dst, 11, 0x1f);
r = (unsigned char)(((BITS(src, 11, 0x1f) - d)*a)>>8) + d;
d = BITS(dst, 5, 0x3f);
g = (unsigned char)(((BITS(src, 5, 0x3f) - d)*a)>>8) + d;
d = BITS(dst, 0, 0x1f);
b = (unsigned char)(((BITS(src, 0, 0x1f) - d)*a)>>8) + d;
*out++ = (r << 11) | (g << 5) | b;
break;
case MWPF_TRUECOLOR555:
d = BITS(dst, 10, 0x1f);
r = (unsigned char)(((BITS(src, 10, 0x1f) - d)*a)>>8) + d;
d = BITS(dst, 5, 0x1f);
g = (unsigned char)(((BITS(src, 5, 0x1f) - d)*a)>>8) + d;
d = BITS(dst, 0, 0x1f);
b = (unsigned char)(((BITS(src, 0, 0x1f) - d)*a)>>8) + d;
*out++ = (r << 10) | (g << 5) | b;
break;
case MWPF_TRUECOLOR332:
d = BITS(dst, 5, 0x07);
r = (unsigned char)(((BITS(src, 5, 0x07) - d)*a)>>8) + d;
d = BITS(dst, 2, 0x07);
g = (unsigned char)(((BITS(src, 2, 0x07) - d)*a)>>8) + d;
d = BITS(dst, 0, 0x03);
b = (unsigned char)(((BITS(src, 0, 0x03) - d)*a)>>8) + d;
*out++ = (r << 5) | (g << 2) | b;
break;
case MWPF_TRUECOLOR233:
d = BITS(dst, 0, 0x07);
r = (unsigned char)(((BITS(src, 0, 0x07) - d)*a)>>8) + d;
d = BITS(dst, 3, 0x07);
g = (unsigned char)(((BITS(src, 3, 0x07) - d)*a)>>8) + d;
d = BITS(dst, 6, 0x03);
b = (unsigned char)(((BITS(src, 6, 0x03) - d)*a)>>8) + d;
*out++ = (b << 6) | (g << 3) | r;
break;
case MWPF_PALETTE:
/* reverse lookup palette entry for blend ;-)*/
palsrc = GETPALENTRY(gr_palette, src);
paldst = GETPALENTRY(gr_palette, dst);
d = REDVALUE(paldst);
r = (unsigned char)(((REDVALUE(palsrc) - d)*a)>>8) + d;
d = GREENVALUE(paldst);
g = (unsigned char)(((GREENVALUE(palsrc) - d)*a)>>8) + d;
d = BLUEVALUE(paldst);
b = (unsigned char)(((BLUEVALUE(palsrc) - d)*a)>>8) + d;
*out++ = GdFindNearestColor(gr_palette, (int)psd->ncolors,
MWRGB(r, g, b));
break;
}
}
}
#endif /*HAVE_T1LIB_SUPPORT | HAVE_FREETYPE_SUPPORT*/
#if HAVE_T1LIB_SUPPORT
/* contributed by Vidar Hokstad*/
static int
t1lib_init(PSD psd)
{
char **encoding;
static int inited = 0;
if (inited)
return 1;
T1_SetBitmapPad(8);
if (!T1_InitLib(0))
return 0;
/* set default Latin1 encoding*/
encoding = T1_LoadEncoding("IsoLatin1.enc");
T1_SetDefaultEncoding(encoding);
#ifdef T1LIB_USE_AA_HIGH
T1_AASetLevel(T1_AA_HIGH);
#else
T1_AASetLevel(T1_AA_LOW);
#endif
#if 0
/* kluge: this is required if 16bpp drawarea driver is used*/
if(psd->bpp == 16)
T1_AASetBitsPerPixel(16);
else
#endif
T1_AASetBitsPerPixel(sizeof(MWPIXELVAL)*8);
inited = 1;
return 1;
}
static PMWT1LIBFONT
t1lib_createfont(const char *name, MWCOORD height, int attr)
{
PMWT1LIBFONT pf;
int id;
char * p;
char buf[256];
/* match name against t1 font id's from t1 font database*/
for(id=0; id<T1_Get_no_fonts(); ++id) {
strncpy(buf, T1_GetFontFileName(id), sizeof(buf));
/* remove extension*/
for(p=buf; *p; ++p) {
if(*p == '.') {
*p = 0;
break;
}
}
if(!strcmpi(name, buf)) {
/* allocate font structure*/
pf = (PMWT1LIBFONT)calloc(sizeof(MWT1LIBFONT), 1);
if (!pf)
return NULL;
pf->fontprocs = &t1lib_procs;
GdSetFontSize((PMWFONT)pf, height);
GdSetFontRotation((PMWFONT)pf, 0);
GdSetFontAttr((PMWFONT)pf, attr, 0);
pf->fontid = id;
return pf;
}
}
return NULL;
}
/*
* Draw ascii text string using T1LIB type font
*/
static void
t1lib_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
const void *text, int cc, int flags)
{
PMWT1LIBFONT pf = (PMWT1LIBFONT)pfont;
const unsigned char *str = text;
MWCOORD width; /* width of text area */
MWCOORD height; /* height of text area */
MWCOORD underliney;
GLYPH * g; /* T1lib glyph structure. Memory handling by T1lib */
#ifdef T1LIB_USE_AA_HIGH
OUTPIXELVAL gvals[17];
/* Blending array for antialiasing. The steeper the values increase
* near the end, the sharper the characters look, but also more jagged
*/
static unsigned char blend[17] = {
0x00, 0x00, 0x04, 0x0c, 0x10, 0x14, 0x18, 0x20,
0x30, 0x38, 0x40, 0x50, 0x70, 0x80, 0xa0, 0xc0, 0xff
};
#else
OUTPIXELVAL gvals[5];
static unsigned char blend[5] = { 0x00, 0x44, 0x88, 0xcc, 0xff };
#endif
/* Check if we should throw out some fonts */
if (pf->fontattr&MWTF_ANTIALIAS) {
#ifdef T1LIB_USE_AA_HIGH
alphablend(psd, gvals, gr_foreground, gr_background, blend, 17);
T1_AAHSetGrayValues(gvals);
#else
alphablend(psd, gvals, gr_foreground, gr_background, blend, 5);
T1_AASetGrayValues(gvals[0],gvals[1],gvals[2],gvals[3],gvals[4]);
#endif
g = T1_AASetString(pf->fontid,(char *)str,cc,0,
(pf->fontattr&MWTF_KERNING)? T1_KERNING: 0,
pf->fontsize * 1.0, 0);
if (g && g->bits) {
/*MWPIXELVAL save = gr_background;*/
width = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
height = g->metrics.ascent - g->metrics.descent;
if(flags & MWTF_BASELINE)
y -= g->metrics.ascent;
else if(flags & MWTF_BOTTOM)
y -= (height - 1);
underliney = y + g->metrics.ascent;
/* FIXME: Looks damn ugly if usebg is false.
* Will be handled when using alphablending in GdArea...
*/
/* clipping handled in GdArea*/
/*FIXME kluge for transparency*/
/*gr_background = gr_foreground + 1;*/
/*gr_usebg = 0;*/
GdArea(psd,x,y, width, height, g->bits, MWPF_PIXELVAL);
/*gr_background = save;*/
if (pf->fontattr & MWTF_UNDERLINE)
GdLine(psd, x, underliney, x+width, underliney, FALSE);
}
} else {
/* Do non-aa drawing */
g = T1_SetString(pf->fontid,(char *)str,cc,0,
(pf->fontattr&MWTF_KERNING)? T1_KERNING: 0,
pf->fontsize * 1.0, 0);
if (g && g->bits) {
unsigned char * b;
int xoff;
int maxy;
int xmod;
/* I'm sure this sorry excuse for a bitmap rendering routine can
* be optimized quite a bit ;)
*/
width = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
height = g->metrics.ascent - g->metrics.descent;
if(flags & MWTF_BASELINE)
y -= g->metrics.ascent;
else if(flags & MWTF_BOTTOM)
y -= (height - 1);
underliney = y + g->metrics.ascent;
b = g->bits;
maxy = y + height;
/* if ((x + width) > psd->xvirtres) {
xmod = (x + width - psd->xvirtres + 7) >> 3;
width = width + x + width - psd->xvirtres;
} else xmod = 0;
*/
xmod = 0;
while (y < maxy) {
unsigned char data;
xoff = 0;
while (xoff < width ) {
if (!(xoff % 8)) {
data = *b;
b++;
}
if (GdClipPoint(psd, x+xoff,y)) {
if (gr_usebg) {
psd->DrawPixel(psd,x+xoff,y,
data & (1 << (xoff % 8)) ?
gr_foreground : gr_background);
} else if (data & (1 << (xoff % 8))) {
psd->DrawPixel(psd,x+xoff,y, gr_foreground);
}
}
xoff++;
}
b += xmod;
y++;
}
if (pf->fontattr & MWTF_UNDERLINE)
GdLine(psd, x, underliney, x+xoff, underliney, FALSE);
}
}
if (g && g->bits) {
/* Save some memory */
free(g->bits);
g->bits = 0; /* Make sure T1lib doesnt try to free it again */
}
GdFixCursor(psd);
}
static MWBOOL
t1lib_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
{
int i;
MWCOORD width, height, baseline;
/* FIXME, guess all sizes*/
GdGetTextSize(pfont, "A", 1, &width, &height, &baseline, MWTF_ASCII);
pfontinfo->height = height;
pfontinfo->maxwidth = width;
pfontinfo->baseline = 0;
pfontinfo->firstchar = 32;
pfontinfo->lastchar = 255;
pfontinfo->fixed = TRUE;
for(i=0; i<256; ++i)
pfontinfo->widths[i] = width;
return TRUE;
}
/* Get the width and height of passed text string in the current font*/
static void
t1lib_gettextsize(PMWFONT pfont, const void *text, int cc,
MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
{
PMWT1LIBFONT pf = (PMWT1LIBFONT)pfont;
const unsigned char * str = text;
GLYPH * g;
g = T1_SetString(pf->fontid, (char *)str, cc, 0,
(pf->fontattr&MWTF_KERNING)? T1_KERNING: 0, pf->fontsize * 1.0, 0);
*pwidth = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
*pheight = g->metrics.ascent - g->metrics.descent;
if(g && g->bits) {
free(g->bits);
g->bits = 0;
}
#if 0
BBox b;
/* FIXME. Something is *VERY* wrong here */
b = T1_GetStringBBox(pf->fontid, str, cc, 0, (pf->fontattr&MWTF_KERNING)?T1_KERNING:0);
DPRINTF("b.urx = %d, b.llx = %d\n",b.urx, b.llx);
DPRINTF("b.ury = %d, b.lly = %d\n",b.ury, b.lly);
*pwidth = (b.urx - b.llx);
*pheight = (b.lly - b.ury);
#endif
}
static void
t1lib_destroyfont(PMWFONT pfont)
{
PMWT1LIBFONT pf = (PMWT1LIBFONT)pfont;
T1_DeleteAllSizes(pf->fontid);
free(pf);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -