123a0898aSmrg/*
223a0898aSmrg
323a0898aSmrgCopyright 1990, 1998  The Open Group
423a0898aSmrg
523a0898aSmrgPermission to use, copy, modify, distribute, and sell this software and its
623a0898aSmrgdocumentation for any purpose is hereby granted without fee, provided that
723a0898aSmrgthe above copyright notice appear in all copies and that both that
823a0898aSmrgcopyright notice and this permission notice appear in supporting
923a0898aSmrgdocumentation.
1023a0898aSmrg
1123a0898aSmrgThe above copyright notice and this permission notice shall be included
1223a0898aSmrgin all copies or substantial portions of the Software.
1323a0898aSmrg
1423a0898aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1523a0898aSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1623a0898aSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1723a0898aSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
1823a0898aSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1923a0898aSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2023a0898aSmrgOTHER DEALINGS IN THE SOFTWARE.
2123a0898aSmrg
2223a0898aSmrgExcept as contained in this notice, the name of The Open Group shall
2323a0898aSmrgnot be used in advertising or otherwise to promote the sale, use or
2423a0898aSmrgother dealings in this Software without prior written authorization
2523a0898aSmrgfrom The Open Group.
2623a0898aSmrg
2723a0898aSmrg*/
2823a0898aSmrg
2923a0898aSmrg/*
3023a0898aSmrg * Author:  Keith Packard, MIT X Consortium
3123a0898aSmrg */
3223a0898aSmrg
3323a0898aSmrg#ifdef HAVE_CONFIG_H
3423a0898aSmrg#include <config.h>
3523a0898aSmrg#endif
3623a0898aSmrg
3723a0898aSmrg#include <X11/fonts/fntfilst.h>
3823a0898aSmrg#include <X11/fonts/bitmap.h>
3923a0898aSmrg#include <X11/fonts/bdfint.h>
4023a0898aSmrg
4123a0898aSmrgstatic unsigned char ink_mask_msb[8] = {
4223a0898aSmrg    0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01,
4323a0898aSmrg};
4423a0898aSmrg
4523a0898aSmrgstatic unsigned char ink_mask_lsb[8] = {
4623a0898aSmrg    0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
4723a0898aSmrg};
4823a0898aSmrg
4923a0898aSmrgvoid
5023a0898aSmrgFontCharInkMetrics(FontPtr pFont, CharInfoPtr pCI, xCharInfo *pInk)
5123a0898aSmrg{
5223a0898aSmrg    int         leftBearing,
5323a0898aSmrg                ascent,
5423a0898aSmrg                descent;
5523a0898aSmrg    register int vpos,
5623a0898aSmrg                hpos,
5723a0898aSmrg                bpos = 0;
5823a0898aSmrg    int         bitmapByteWidth,
5923a0898aSmrg                bitmapByteWidthPadded;
6023a0898aSmrg    int         bitmapBitWidth;
6123a0898aSmrg    int         span;
6223a0898aSmrg    register unsigned char *p;
6323a0898aSmrg    unsigned char *ink_mask = 0;
6423a0898aSmrg    register int bmax;
6523a0898aSmrg    register unsigned char charbits;
6623a0898aSmrg
6723a0898aSmrg    if (pFont->bit == MSBFirst)
6823a0898aSmrg	ink_mask = ink_mask_msb;
6923a0898aSmrg    else if (pFont->bit == LSBFirst)
7023a0898aSmrg	ink_mask = ink_mask_lsb;
7123a0898aSmrg    pInk->characterWidth = pCI->metrics.characterWidth;
7223a0898aSmrg    pInk->attributes = pCI->metrics.attributes;
7323a0898aSmrg
7423a0898aSmrg    leftBearing = pCI->metrics.leftSideBearing;
7523a0898aSmrg    ascent = pCI->metrics.ascent;
7623a0898aSmrg    descent = pCI->metrics.descent;
7723a0898aSmrg    bitmapBitWidth = GLYPHWIDTHPIXELS(pCI);
7823a0898aSmrg    bitmapByteWidth = GLYPHWIDTHBYTES(pCI);
7923a0898aSmrg    bitmapByteWidthPadded = BYTES_PER_ROW(bitmapBitWidth, pFont->glyph);
8023a0898aSmrg    span = bitmapByteWidthPadded - bitmapByteWidth;
8123a0898aSmrg
8223a0898aSmrg    p = (unsigned char *) pCI->bits;
8323a0898aSmrg    for (vpos = descent + ascent; --vpos >= 0;) {
8423a0898aSmrg	for (hpos = bitmapByteWidth; --hpos >= 0;) {
8523a0898aSmrg	    if (*p++ != 0)
8623a0898aSmrg		goto found_ascent;
8723a0898aSmrg	}
8823a0898aSmrg	p += span;
8923a0898aSmrg    }
9023a0898aSmrg    /*
9123a0898aSmrg     * special case -- font with no bits gets all zeros
9223a0898aSmrg     */
9323a0898aSmrg    pInk->leftSideBearing = leftBearing;
9423a0898aSmrg    pInk->rightSideBearing = leftBearing;
9523a0898aSmrg    pInk->ascent = 0;
9623a0898aSmrg    pInk->descent = 0;
9723a0898aSmrg    return;
9823a0898aSmrgfound_ascent:
9923a0898aSmrg    pInk->ascent = vpos - descent + 1;
10023a0898aSmrg
10141c30155Smrg    p = ((unsigned char *) pCI->bits) + bitmapByteWidthPadded *
10223a0898aSmrg	(descent + ascent - 1) + bitmapByteWidth;
10323a0898aSmrg
10423a0898aSmrg    for (vpos = descent + ascent; --vpos >= 0;) {
10523a0898aSmrg	for (hpos = bitmapByteWidth; --hpos >= 0;) {
10623a0898aSmrg	    if (*--p != 0)
10723a0898aSmrg		goto found_descent;
10823a0898aSmrg	}
10923a0898aSmrg	p -= span;
11023a0898aSmrg    }
11123a0898aSmrgfound_descent:
11223a0898aSmrg    pInk->descent = vpos - ascent + 1;
11323a0898aSmrg
11423a0898aSmrg    bmax = 8;
11523a0898aSmrg    for (hpos = 0; hpos < bitmapByteWidth; hpos++) {
11623a0898aSmrg	charbits = 0;
11723a0898aSmrg	p = (unsigned char *) pCI->bits + hpos;
11823a0898aSmrg	for (vpos = descent + ascent; --vpos >= 0; p += bitmapByteWidthPadded)
11923a0898aSmrg	    charbits |= *p;
12023a0898aSmrg	if (charbits) {
12123a0898aSmrg	    if (hpos == bitmapByteWidth - 1)
12223a0898aSmrg		bmax = bitmapBitWidth - (hpos << 3);
12323a0898aSmrg	    p = ink_mask;
12423a0898aSmrg	    for (bpos = bmax; --bpos >= 0;) {
12523a0898aSmrg		if (charbits & *p++)
12623a0898aSmrg		    goto found_left;
12723a0898aSmrg	    }
12823a0898aSmrg	}
12923a0898aSmrg    }
13023a0898aSmrgfound_left:
13123a0898aSmrg    pInk->leftSideBearing = leftBearing + (hpos << 3) + bmax - bpos - 1;
13223a0898aSmrg
13323a0898aSmrg    bmax = bitmapBitWidth - ((bitmapByteWidth - 1) << 3);
13423a0898aSmrg    for (hpos = bitmapByteWidth; --hpos >= 0;) {
13523a0898aSmrg	charbits = 0;
13623a0898aSmrg	p = (unsigned char *) pCI->bits + hpos;
13723a0898aSmrg	for (vpos = descent + ascent; --vpos >= 0; p += bitmapByteWidthPadded)
13823a0898aSmrg	    charbits |= *p;
13923a0898aSmrg	if (charbits) {
14023a0898aSmrg	    p = ink_mask + bmax;
14123a0898aSmrg	    for (bpos = bmax; --bpos >= 0;) {
14223a0898aSmrg		if (charbits & *--p)
14323a0898aSmrg		    goto found_right;
14423a0898aSmrg	    }
14523a0898aSmrg	}
14623a0898aSmrg	bmax = 8;
14723a0898aSmrg    }
14823a0898aSmrgfound_right:
14923a0898aSmrg    pInk->rightSideBearing = leftBearing + (hpos << 3) + bpos + 1;
15023a0898aSmrg}
15123a0898aSmrg
15223a0898aSmrg#define	ISBITONMSB(x, line)	((line)[(x)/8] & (1 << (7-((x)%8))))
15323a0898aSmrg#define	SETBITMSB(x, line)	((line)[(x)/8] |= (1 << (7-((x)%8))))
15423a0898aSmrg#define	ISBITONLSB(x, line)	((line)[(x)/8] & (1 << ((x)%8)))
15523a0898aSmrg#define	SETBITLSB(x, line)	((line)[(x)/8] |= (1 << ((x)%8)))
15623a0898aSmrg
15723a0898aSmrg#define Min(a,b)    ((a)<(b)?(a):(b))
15823a0898aSmrg#define Max(a,b)    ((a)>(b)?(a):(b))
15923a0898aSmrg
16023a0898aSmrgvoid
16123a0898aSmrgFontCharReshape(FontPtr pFont, CharInfoPtr pSrc, CharInfoPtr pDst)
16223a0898aSmrg{
16323a0898aSmrg    int         x,
16423a0898aSmrg                y;
16523a0898aSmrg    unsigned char *in_line,
16623a0898aSmrg               *out_line;
16723a0898aSmrg    unsigned char *oldglyph,
16823a0898aSmrg               *newglyph;
16923a0898aSmrg    int         inwidth;
17023a0898aSmrg    int         outwidth,
17123a0898aSmrg                outheight;
17223a0898aSmrg    int         out_bytes,
17323a0898aSmrg                in_bytes;
17423a0898aSmrg    int         y_min,
17523a0898aSmrg                y_max,
17623a0898aSmrg                x_min,
17723a0898aSmrg                x_max;
17823a0898aSmrg
17923a0898aSmrg    newglyph = (unsigned char *) pDst->bits;
18023a0898aSmrg    outwidth = pDst->metrics.rightSideBearing - pDst->metrics.leftSideBearing;
18123a0898aSmrg    outheight = pDst->metrics.descent + pDst->metrics.ascent;
18223a0898aSmrg    out_bytes = BYTES_PER_ROW(outwidth, pFont->glyph);
18323a0898aSmrg
18423a0898aSmrg    oldglyph = (unsigned char *) pSrc->bits;
18523a0898aSmrg    inwidth = pSrc->metrics.rightSideBearing - pSrc->metrics.leftSideBearing;
18623a0898aSmrg    in_bytes = BYTES_PER_ROW(inwidth, pFont->glyph);
18723a0898aSmrg
18823a0898aSmrg    bzero(newglyph, out_bytes * outheight);
18923a0898aSmrg    in_line = oldglyph;
19023a0898aSmrg    out_line = newglyph;
19123a0898aSmrg    y_min = Max(-pSrc->metrics.ascent, -pDst->metrics.ascent);
19223a0898aSmrg    y_max = Min(pSrc->metrics.descent, pDst->metrics.descent);
19323a0898aSmrg    x_min = Max(pSrc->metrics.leftSideBearing, pDst->metrics.leftSideBearing);
19423a0898aSmrg    x_max = Min(pSrc->metrics.rightSideBearing, pDst->metrics.rightSideBearing);
19523a0898aSmrg    in_line += (y_min + pSrc->metrics.ascent) * in_bytes;
19623a0898aSmrg    out_line += (y_min + pDst->metrics.ascent) * out_bytes;
19723a0898aSmrg    if (pFont->bit == MSBFirst) {
19823a0898aSmrg	for (y = y_min; y < y_max; y++) {
19923a0898aSmrg	    for (x = x_min; x < x_max; x++) {
20023a0898aSmrg		if (ISBITONMSB(x - pSrc->metrics.leftSideBearing, in_line))
20123a0898aSmrg		    SETBITMSB(x - pDst->metrics.leftSideBearing, out_line);
20223a0898aSmrg	    }
20323a0898aSmrg	    in_line += in_bytes;
20423a0898aSmrg	    out_line += out_bytes;
20523a0898aSmrg	}
20623a0898aSmrg    } else {
20723a0898aSmrg	for (y = y_min; y < y_max; y++) {
20823a0898aSmrg	    for (x = x_min; x < x_max; x++) {
20923a0898aSmrg		if (ISBITONLSB(x - pSrc->metrics.leftSideBearing, in_line))
21023a0898aSmrg		    SETBITLSB(x - pDst->metrics.leftSideBearing, out_line);
21123a0898aSmrg	    }
21223a0898aSmrg	    in_line += in_bytes;
21323a0898aSmrg	    out_line += out_bytes;
21423a0898aSmrg	}
21523a0898aSmrg    }
21623a0898aSmrg}
217