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