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