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