1/*
2
3Copyright 1990, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included
12in all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall
23not be used in advertising or otherwise to promote the sale, use or
24other dealings in this Software without prior written authorization
25from The Open Group.
26
27*/
28
29/*
30 * Author:  Keith Packard, MIT X Consortium
31 */
32
33#ifdef HAVE_CONFIG_H
34#include <config.h>
35#endif
36
37#include <X11/fonts/fntfilst.h>
38#include <X11/fonts/bitmap.h>
39#include <X11/fonts/bdfint.h>
40
41static unsigned char ink_mask_msb[8] = {
42    0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01,
43};
44
45static unsigned char ink_mask_lsb[8] = {
46    0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
47};
48
49void
50FontCharInkMetrics(FontPtr pFont, CharInfoPtr pCI, xCharInfo *pInk)
51{
52    int         leftBearing,
53                ascent,
54                descent;
55    register int vpos,
56                hpos,
57                bpos = 0;
58    int         bitmapByteWidth,
59                bitmapByteWidthPadded;
60    int         bitmapBitWidth;
61    int         span;
62    register unsigned char *p;
63    unsigned char *ink_mask = 0;
64    register int bmax;
65    register unsigned char charbits;
66
67    if (pFont->bit == MSBFirst)
68	ink_mask = ink_mask_msb;
69    else if (pFont->bit == LSBFirst)
70	ink_mask = ink_mask_lsb;
71    pInk->characterWidth = pCI->metrics.characterWidth;
72    pInk->attributes = pCI->metrics.attributes;
73
74    leftBearing = pCI->metrics.leftSideBearing;
75    ascent = pCI->metrics.ascent;
76    descent = pCI->metrics.descent;
77    bitmapBitWidth = GLYPHWIDTHPIXELS(pCI);
78    bitmapByteWidth = GLYPHWIDTHBYTES(pCI);
79    bitmapByteWidthPadded = BYTES_PER_ROW(bitmapBitWidth, pFont->glyph);
80    span = bitmapByteWidthPadded - bitmapByteWidth;
81
82    p = (unsigned char *) pCI->bits;
83    for (vpos = descent + ascent; --vpos >= 0;) {
84	for (hpos = bitmapByteWidth; --hpos >= 0;) {
85	    if (*p++ != 0)
86		goto found_ascent;
87	}
88	p += span;
89    }
90    /*
91     * special case -- font with no bits gets all zeros
92     */
93    pInk->leftSideBearing = leftBearing;
94    pInk->rightSideBearing = leftBearing;
95    pInk->ascent = 0;
96    pInk->descent = 0;
97    return;
98found_ascent:
99    pInk->ascent = vpos - descent + 1;
100
101    p = ((unsigned char *) pCI->bits) + bitmapByteWidthPadded *
102	(descent + ascent - 1) + bitmapByteWidth;
103
104    for (vpos = descent + ascent; --vpos >= 0;) {
105	for (hpos = bitmapByteWidth; --hpos >= 0;) {
106	    if (*--p != 0)
107		goto found_descent;
108	}
109	p -= span;
110    }
111found_descent:
112    pInk->descent = vpos - ascent + 1;
113
114    bmax = 8;
115    for (hpos = 0; hpos < bitmapByteWidth; hpos++) {
116	charbits = 0;
117	p = (unsigned char *) pCI->bits + hpos;
118	for (vpos = descent + ascent; --vpos >= 0; p += bitmapByteWidthPadded)
119	    charbits |= *p;
120	if (charbits) {
121	    if (hpos == bitmapByteWidth - 1)
122		bmax = bitmapBitWidth - (hpos << 3);
123	    p = ink_mask;
124	    for (bpos = bmax; --bpos >= 0;) {
125		if (charbits & *p++)
126		    goto found_left;
127	    }
128	}
129    }
130found_left:
131    pInk->leftSideBearing = leftBearing + (hpos << 3) + bmax - bpos - 1;
132
133    bmax = bitmapBitWidth - ((bitmapByteWidth - 1) << 3);
134    for (hpos = bitmapByteWidth; --hpos >= 0;) {
135	charbits = 0;
136	p = (unsigned char *) pCI->bits + hpos;
137	for (vpos = descent + ascent; --vpos >= 0; p += bitmapByteWidthPadded)
138	    charbits |= *p;
139	if (charbits) {
140	    p = ink_mask + bmax;
141	    for (bpos = bmax; --bpos >= 0;) {
142		if (charbits & *--p)
143		    goto found_right;
144	    }
145	}
146	bmax = 8;
147    }
148found_right:
149    pInk->rightSideBearing = leftBearing + (hpos << 3) + bpos + 1;
150}
151
152#define	ISBITONMSB(x, line)	((line)[(x)/8] & (1 << (7-((x)%8))))
153#define	SETBITMSB(x, line)	((line)[(x)/8] |= (1 << (7-((x)%8))))
154#define	ISBITONLSB(x, line)	((line)[(x)/8] & (1 << ((x)%8)))
155#define	SETBITLSB(x, line)	((line)[(x)/8] |= (1 << ((x)%8)))
156
157#define Min(a,b)    ((a)<(b)?(a):(b))
158#define Max(a,b)    ((a)>(b)?(a):(b))
159
160void
161FontCharReshape(FontPtr pFont, CharInfoPtr pSrc, CharInfoPtr pDst)
162{
163    int         x,
164                y;
165    unsigned char *in_line,
166               *out_line;
167    unsigned char *oldglyph,
168               *newglyph;
169    int         inwidth;
170    int         outwidth,
171                outheight;
172    int         out_bytes,
173                in_bytes;
174    int         y_min,
175                y_max,
176                x_min,
177                x_max;
178
179    newglyph = (unsigned char *) pDst->bits;
180    outwidth = pDst->metrics.rightSideBearing - pDst->metrics.leftSideBearing;
181    outheight = pDst->metrics.descent + pDst->metrics.ascent;
182    out_bytes = BYTES_PER_ROW(outwidth, pFont->glyph);
183
184    oldglyph = (unsigned char *) pSrc->bits;
185    inwidth = pSrc->metrics.rightSideBearing - pSrc->metrics.leftSideBearing;
186    in_bytes = BYTES_PER_ROW(inwidth, pFont->glyph);
187
188    bzero(newglyph, out_bytes * outheight);
189    in_line = oldglyph;
190    out_line = newglyph;
191    y_min = Max(-pSrc->metrics.ascent, -pDst->metrics.ascent);
192    y_max = Min(pSrc->metrics.descent, pDst->metrics.descent);
193    x_min = Max(pSrc->metrics.leftSideBearing, pDst->metrics.leftSideBearing);
194    x_max = Min(pSrc->metrics.rightSideBearing, pDst->metrics.rightSideBearing);
195    in_line += (y_min + pSrc->metrics.ascent) * in_bytes;
196    out_line += (y_min + pDst->metrics.ascent) * out_bytes;
197    if (pFont->bit == MSBFirst) {
198	for (y = y_min; y < y_max; y++) {
199	    for (x = x_min; x < x_max; x++) {
200		if (ISBITONMSB(x - pSrc->metrics.leftSideBearing, in_line))
201		    SETBITMSB(x - pDst->metrics.leftSideBearing, out_line);
202	    }
203	    in_line += in_bytes;
204	    out_line += out_bytes;
205	}
206    } else {
207	for (y = y_min; y < y_max; y++) {
208	    for (x = x_min; x < x_max; x++) {
209		if (ISBITONLSB(x - pSrc->metrics.leftSideBearing, in_line))
210		    SETBITLSB(x - pDst->metrics.leftSideBearing, out_line);
211	    }
212	    in_line += in_bytes;
213	    out_line += out_bytes;
214	}
215    }
216}
217