fontink.c revision a96d7823
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#include "libxfontint.h"
37
38#include <X11/fonts/fntfilst.h>
39#include <X11/fonts/bitmap.h>
40#include <X11/fonts/bdfint.h>
41
42static unsigned char ink_mask_msb[8] = {
43    0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01,
44};
45
46static unsigned char ink_mask_lsb[8] = {
47    0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
48};
49
50void
51FontCharInkMetrics(FontPtr pFont, CharInfoPtr pCI, xCharInfo *pInk)
52{
53    int         leftBearing,
54                ascent,
55                descent;
56    register int vpos,
57                hpos,
58                bpos = 0;
59    int         bitmapByteWidth,
60                bitmapByteWidthPadded;
61    int         bitmapBitWidth;
62    int         span;
63    register unsigned char *p;
64    unsigned char *ink_mask = 0;
65    register int bmax;
66    register unsigned char charbits;
67
68    if (pFont->bit == MSBFirst)
69	ink_mask = ink_mask_msb;
70    else if (pFont->bit == LSBFirst)
71	ink_mask = ink_mask_lsb;
72    pInk->characterWidth = pCI->metrics.characterWidth;
73    pInk->attributes = pCI->metrics.attributes;
74
75    leftBearing = pCI->metrics.leftSideBearing;
76    ascent = pCI->metrics.ascent;
77    descent = pCI->metrics.descent;
78    bitmapBitWidth = GLYPHWIDTHPIXELS(pCI);
79    bitmapByteWidth = GLYPHWIDTHBYTES(pCI);
80    bitmapByteWidthPadded = BYTES_PER_ROW(bitmapBitWidth, pFont->glyph);
81    span = bitmapByteWidthPadded - bitmapByteWidth;
82
83    p = (unsigned char *) pCI->bits;
84    for (vpos = descent + ascent; --vpos >= 0;) {
85	for (hpos = bitmapByteWidth; --hpos >= 0;) {
86	    if (*p++ != 0)
87		goto found_ascent;
88	}
89	p += span;
90    }
91    /*
92     * special case -- font with no bits gets all zeros
93     */
94    pInk->leftSideBearing = leftBearing;
95    pInk->rightSideBearing = leftBearing;
96    pInk->ascent = 0;
97    pInk->descent = 0;
98    return;
99found_ascent:
100    pInk->ascent = vpos - descent + 1;
101
102    p = ((unsigned char *) pCI->bits) + bitmapByteWidthPadded *
103	(descent + ascent - 1) + bitmapByteWidth;
104
105    for (vpos = descent + ascent; --vpos >= 0;) {
106	for (hpos = bitmapByteWidth; --hpos >= 0;) {
107	    if (*--p != 0)
108		goto found_descent;
109	}
110	p -= span;
111    }
112found_descent:
113    pInk->descent = vpos - ascent + 1;
114
115    bmax = 8;
116    for (hpos = 0; hpos < bitmapByteWidth; hpos++) {
117	charbits = 0;
118	p = (unsigned char *) pCI->bits + hpos;
119	for (vpos = descent + ascent; --vpos >= 0; p += bitmapByteWidthPadded)
120	    charbits |= *p;
121	if (charbits) {
122	    if (hpos == bitmapByteWidth - 1)
123		bmax = bitmapBitWidth - (hpos << 3);
124	    p = ink_mask;
125	    for (bpos = bmax; --bpos >= 0;) {
126		if (charbits & *p++)
127		    goto found_left;
128	    }
129	}
130    }
131found_left:
132    pInk->leftSideBearing = leftBearing + (hpos << 3) + bmax - bpos - 1;
133
134    bmax = bitmapBitWidth - ((bitmapByteWidth - 1) << 3);
135    for (hpos = bitmapByteWidth; --hpos >= 0;) {
136	charbits = 0;
137	p = (unsigned char *) pCI->bits + hpos;
138	for (vpos = descent + ascent; --vpos >= 0; p += bitmapByteWidthPadded)
139	    charbits |= *p;
140	if (charbits) {
141	    p = ink_mask + bmax;
142	    for (bpos = bmax; --bpos >= 0;) {
143		if (charbits & *--p)
144		    goto found_right;
145	    }
146	}
147	bmax = 8;
148    }
149found_right:
150    pInk->rightSideBearing = leftBearing + (hpos << 3) + bpos + 1;
151}
152
153#define	ISBITONMSB(x, line)	((line)[(x)/8] & (1 << (7-((x)%8))))
154#define	SETBITMSB(x, line)	((line)[(x)/8] |= (1 << (7-((x)%8))))
155#define	ISBITONLSB(x, line)	((line)[(x)/8] & (1 << ((x)%8)))
156#define	SETBITLSB(x, line)	((line)[(x)/8] |= (1 << ((x)%8)))
157
158#define Min(a,b)    ((a)<(b)?(a):(b))
159#define Max(a,b)    ((a)>(b)?(a):(b))
160
161void
162FontCharReshape(FontPtr pFont, CharInfoPtr pSrc, CharInfoPtr pDst)
163{
164    int         x,
165                y;
166    unsigned char *in_line,
167               *out_line;
168    unsigned char *oldglyph,
169               *newglyph;
170    int         inwidth;
171    int         outwidth,
172                outheight;
173    int         out_bytes,
174                in_bytes;
175    int         y_min,
176                y_max,
177                x_min,
178                x_max;
179
180    newglyph = (unsigned char *) pDst->bits;
181    outwidth = pDst->metrics.rightSideBearing - pDst->metrics.leftSideBearing;
182    outheight = pDst->metrics.descent + pDst->metrics.ascent;
183    out_bytes = BYTES_PER_ROW(outwidth, pFont->glyph);
184
185    oldglyph = (unsigned char *) pSrc->bits;
186    inwidth = pSrc->metrics.rightSideBearing - pSrc->metrics.leftSideBearing;
187    in_bytes = BYTES_PER_ROW(inwidth, pFont->glyph);
188
189    bzero(newglyph, out_bytes * outheight);
190    in_line = oldglyph;
191    out_line = newglyph;
192    y_min = Max(-pSrc->metrics.ascent, -pDst->metrics.ascent);
193    y_max = Min(pSrc->metrics.descent, pDst->metrics.descent);
194    x_min = Max(pSrc->metrics.leftSideBearing, pDst->metrics.leftSideBearing);
195    x_max = Min(pSrc->metrics.rightSideBearing, pDst->metrics.rightSideBearing);
196    in_line += (y_min + pSrc->metrics.ascent) * in_bytes;
197    out_line += (y_min + pDst->metrics.ascent) * out_bytes;
198    if (pFont->bit == MSBFirst) {
199	for (y = y_min; y < y_max; y++) {
200	    for (x = x_min; x < x_max; x++) {
201		if (ISBITONMSB(x - pSrc->metrics.leftSideBearing, in_line))
202		    SETBITMSB(x - pDst->metrics.leftSideBearing, out_line);
203	    }
204	    in_line += in_bytes;
205	    out_line += out_bytes;
206	}
207    } else {
208	for (y = y_min; y < y_max; y++) {
209	    for (x = x_min; x < x_max; x++) {
210		if (ISBITONLSB(x - pSrc->metrics.leftSideBearing, in_line))
211		    SETBITLSB(x - pDst->metrics.leftSideBearing, out_line);
212	    }
213	    in_line += in_bytes;
214	    out_line += out_bytes;
215	}
216    }
217}
218