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