1 /* $XConsortium: spglyph.c,v 1.17 94/04/17 20:17:49 gildea Exp $ */
2 /*
3  * Copyright 1990, 1991 Network Computing Devices;
4  * Portions Copyright 1987 by Digital Equipment Corporation
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and
7  * its documentation for any purpose is hereby granted without fee, provided
8  * that the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the names of Network Computing Devices or Digital
11  * not be used in advertising or publicity pertaining to distribution of
12  * the software without specific, written prior permission.
13  *
14  * NETWORK COMPUTING DEVICES AND DIGITAL DISCLAIM ALL WARRANTIES WITH
15  * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
16  * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES OR DIGITAL BE
17  * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
19  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  *
22  * Author: Dave Lemke, Network Computing Devices Inc
23  */
24 
25 /*
26 
27 Copyright (c) 1987  X Consortium
28 
29 Permission is hereby granted, free of charge, to any person obtaining
30 a copy of this software and associated documentation files (the
31 "Software"), to deal in the Software without restriction, including
32 without limitation the rights to use, copy, modify, merge, publish,
33 distribute, sublicense, and/or sell copies of the Software, and to
34 permit persons to whom the Software is furnished to do so, subject to
35 the following conditions:
36 
37 The above copyright notice and this permission notice shall be included
38 in all copies or substantial portions of the Software.
39 
40 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
41 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
42 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
43 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
44 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
45 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
46 OTHER DEALINGS IN THE SOFTWARE.
47 
48 Except as contained in this notice, the name of the X Consortium shall
49 not be used in advertising or otherwise to promote the sale, use or
50 other dealings in this Software without prior written authorization
51 from the X Consortium.
52 
53 */
54 
55 #include	<X11/X.h>	/* for bit order #defines */
56 #include	"spint.h"
57 
58 #undef	CLIP_BBOX_NOISE
59 
60 static CurrentFontValuesRec current_font_values;
61 static CurrentFontValuesPtr cfv = &current_font_values;
62 static int  bit_order,
63             byte_order,
64             scan;
65 
66 unsigned long
sp_compute_data_size(pfont,mappad,scanlinepad,start,end)67 sp_compute_data_size(pfont, mappad, scanlinepad, start, end)
68     FontPtr     pfont;
69     int         mappad,
70                 scanlinepad;
71     unsigned long start,
72                 end;
73 {
74     unsigned long ch;
75     unsigned long size = 0;
76     int         bpr;
77     SpeedoFontPtr spf = (SpeedoFontPtr) pfont->fontPrivate;
78     FontInfoPtr pinfo = &pfont->info;
79     int         firstChar;
80 
81     firstChar = spf->master->first_char_id;
82 
83     /* allocate the space */
84     switch (mappad) {
85 	int         charsize;
86 	CharInfoPtr ci;
87 	xCharInfo  *cim;
88 
89     case BitmapFormatImageRectMin:
90 	cfv->bpr = 0;
91 	for (ch = start; ch <= end; ch++) {
92 	    ci = &spf->encoding[ch - firstChar];
93 	    if (!ci)
94 		ci = spf->pDefault;
95 	    cim = &ci->metrics;
96 	    charsize = GLYPH_SIZE(ci, scanlinepad);
97 	    charsize *= cim->ascent + cim->descent;
98 	    size += charsize;
99 	}
100 	break;
101     case BitmapFormatImageRectMaxWidth:
102 	bpr = GLWIDTHBYTESPADDED(FONT_MAX_WIDTH(pinfo), scanlinepad);
103 	cfv->bpr = bpr;
104 	for (ch = start; ch <= end; ch++) {
105 	    ci = &spf->encoding[ch - firstChar];
106 	    if (!ci)
107 		ci = spf->pDefault;
108 	    cim = &ci->metrics;
109 	    charsize = bpr * (cim->ascent + cim->descent);
110 	    size += charsize;
111 	}
112 	break;
113     case BitmapFormatImageRectMax:
114 	bpr = GLWIDTHBYTESPADDED(FONT_MAX_WIDTH(pinfo), scanlinepad);
115 	cfv->bpr = bpr;
116 	size = (end - start + 1) * bpr * FONT_MAX_HEIGHT(pinfo);
117 	break;
118     default:
119 	assert(0);
120     }
121 
122     return size;
123 }
124 
125 static void
finish_line(spf)126 finish_line(spf)
127     SpeedoFontPtr spf;
128 {
129     int         bpr = cfv->bpr;
130     CharInfoPtr ci = &spf->encoding[cfv->char_id - spf->master->first_char_id];
131 
132     if (bpr == 0) {
133 	bpr = GLYPH_SIZE(ci, cfv->scanpad);
134     }
135     if (bpr) {			/* char may not have any metrics... */
136 	cfv->bp += bpr;
137     }
138     assert(cfv->bp - sp_fp_cur->bitmaps <= sp_fp_cur->bitmap_size);
139 }
140 
141 
142 void
sp_set_bitmap_bits(y,xbit1,xbit2)143 sp_set_bitmap_bits(y, xbit1, xbit2)
144     fix15       y;
145     fix15       xbit1,
146                 xbit2;
147 {
148     int         nmiddle;
149     CARD8	startmask,
150                 endmask;
151     CARD8	*dst;
152 
153     if (xbit1 > cfv->bit_width) {
154 
155 #ifdef CLIP_BBOX_NOISE
156 	SpeedoErr("Run wider than bitmap width -- truncated\n");
157 #endif
158 
159 	xbit1 = cfv->bit_width;
160     }
161     if (xbit2 > cfv->bit_width) {
162 
163 #ifdef CLIP_BBOX_NOISE
164 	SpeedoErr("Run wider than bitmap width -- truncated\n");
165 #endif
166 
167 	xbit2 = cfv->bit_width;
168     }
169 
170     if (xbit2 < xbit1) {
171 	xbit2 = xbit1;
172     }
173 
174     while (cfv->cur_y != y) {
175 	finish_line(sp_fp_cur);
176 	cfv->cur_y++;
177     }
178 
179     cfv->last_y = y;
180     if (y >= cfv->bit_height) {
181 
182 #ifdef CLIP_BBOX_NOISE
183 	SpeedoErr("Y larger than bitmap height -- truncated\n");
184 #endif
185 
186 	cfv->trunc = 1;
187 	return;
188     }
189     if (xbit1 < 0)		/* XXX this is more than a little bit rude... */
190 	xbit1 = 0;
191 
192     nmiddle = (xbit1 >> 3);
193     dst = (CARD8 *) (cfv->bp + nmiddle);
194     xbit2 -= (xbit1 & ~7);
195     nmiddle = (xbit2 >> 3);
196     xbit1 &= 7;
197     xbit2 &= 7;
198     if (bit_order == MSBFirst) {
199 	startmask = ((CARD8) ~0) >> xbit1;
200 	endmask = ~(((CARD8) ~0) >> xbit2);
201     } else {
202 	startmask = ((CARD8) ~0) << xbit1;
203 	endmask = ~(((CARD8) ~0) << xbit2);
204     }
205     if (nmiddle == 0)
206 	*dst |= endmask & startmask;
207     else {
208 	*dst++ |= startmask;
209 	while (--nmiddle)
210 	    *dst++ = (CARD8)~0;
211 	*dst |= endmask;
212     }
213 }
214 
215 /* ARGSUSED */
216 void
sp_open_bitmap(x_set_width,y_set_width,xorg,yorg,xsize,ysize)217 sp_open_bitmap(x_set_width, y_set_width, xorg, yorg, xsize, ysize)
218     fix31       x_set_width;
219     fix31       y_set_width;
220     fix31       xorg;
221     fix31       yorg;
222     fix15       xsize;
223     fix15       ysize;
224 {
225     CharInfoPtr ci = &sp_fp_cur->encoding[cfv->char_id - sp_fp_cur->master->first_char_id];
226 
227 /*-
228  * this is set to provide better quality bitmaps.  since the Speedo
229  * sp_get_bbox() function returns an approximate (but guarenteed to contain)
230  * set of metrics, some of the bitmaps can be place poorly inside and
231  * look bad.
232  *
233  * with this set, the actual bitmap values are used instead of the bboxes.
234  * it makes things look better, but causes two possible problems:
235  *
236  * 1 - the reported min & max bounds may not correspond to the extents
237  *	reported
238  * 2 - if the extents are reported before the character is generated,
239  * 	a client could see them change.  this currently never happens,
240  *	but will when a desired enhancement (don't reneder till needed)
241  *	is made.
242  */
243 
244 #define	BBOX_FIXUP 1
245 
246 #ifdef BBOX_FIXUP
247     int         off_horz;
248     int         off_vert;
249 
250     if (xorg < 0)
251 	off_horz = (fix15) ((xorg - 32768L) / 65536);
252     else
253 	off_horz = (fix15) ((xorg + 32768L) / 65536);
254     if (yorg < 0)
255 	off_vert = (fix15) ((yorg - 32768L) / 65536);
256     else
257 	off_vert = (fix15) ((yorg + 32768L) / 65536);
258     if (xsize != 0 || ysize != 0 || ci->metrics.characterWidth)
259     {
260 	ci->metrics.leftSideBearing = off_horz;
261 	ci->metrics.descent = -off_vert;
262 	ci->metrics.rightSideBearing = xsize + off_horz;
263 	ci->metrics.ascent = ysize + off_vert;
264     }
265     else
266     {
267     /* If setting the proper size would cause the character to appear to
268        be non-existent, fudge things by giving it a pixel to occupy.  */
269 	xsize = ysize = 1;
270 	ci->metrics.leftSideBearing = ci->metrics.descent = 0;
271 	ci->metrics.rightSideBearing = ci->metrics.ascent = 1;
272     }
273 
274     cfv->bit_width = xsize;
275     cfv->bit_height = ysize;
276 #else
277     cfv->bit_width = ci->metrics.rightSideBearing -
278 	ci->metrics.leftSideBearing;
279     cfv->bit_height = ci->metrics.ascent + ci->metrics.descent;
280 #endif
281 
282     assert(cfv->bp - sp_fp_cur->bitmaps <= sp_fp_cur->bitmap_size);
283     ci->bits = (char *) cfv->bp;
284 
285     cfv->cur_y = 0;
286 }
287 
288 void
sp_close_bitmap()289 sp_close_bitmap()
290 {
291     CharInfoPtr ci = &sp_fp_cur->encoding[cfv->char_id - sp_fp_cur->master->first_char_id];
292     int         bpr = cfv->bpr;
293 
294     if (bpr == 0)
295 	bpr = GLYPH_SIZE(ci, cfv->scanpad);
296     if (!cfv->trunc)
297 	finish_line(sp_fp_cur);
298     cfv->trunc = 0;
299     cfv->last_y++;
300     while (cfv->last_y < cfv->bit_height) {
301 	finish_line(sp_fp_cur);
302 	cfv->last_y++;
303     }
304     if (byte_order != bit_order) {
305 	switch (scan) {
306 	case 1:
307 	    break;
308 	case 2:
309 	    TwoByteSwap(cfv->bp, bpr * cfv->bit_height);
310 	    break;
311 	case 4:
312 	    FourByteSwap(cfv->bp, bpr * cfv->bit_height);
313 	    break;
314 	}
315     }
316 }
317 
318 int
sp_build_all_bitmaps(pfont,format,fmask)319 sp_build_all_bitmaps(pfont, format, fmask)
320     FontPtr     pfont;
321     fsBitmapFormat format;
322     fsBitmapFormatMask fmask;
323 {
324     int         ret,
325                 glyph = 1,
326                 image = BitmapFormatImageRectMin;
327     unsigned long glyph_size;
328     SpeedoFontPtr spf = (SpeedoFontPtr) pfont->fontPrivate;
329     SpeedoMasterFontPtr spmf = spf->master;
330     pointer     bitmaps;
331     int         start,
332                 end,
333                 i;
334 
335     scan = 1;
336     ret = CheckFSFormat(format, fmask,
337 			&bit_order, &byte_order, &scan, &glyph, &image);
338 
339     pfont->bit = bit_order;
340     pfont->byte = byte_order;
341     pfont->glyph = glyph;
342     pfont->scan = scan;
343     if (ret != Successful)
344 	return BadFontFormat;
345 
346     start = spmf->first_char_id;
347     end = spmf->max_id;
348     glyph_size = sp_compute_data_size(pfont, image, glyph, start, end);
349 
350     /* XXX -- MONDO KLUDGE -- add some slop */
351     /*
352      * not sure why this is wanted, but it keeps the packer from going off the
353      * end and toasting us down the line
354      */
355     glyph_size += 20;
356 
357 #ifdef DEBUG
358     spf->bitmap_size = glyph_size;
359 #endif
360 
361     bitmaps = (pointer) xalloc(glyph_size);
362     if (!bitmaps)
363 	return AllocError;
364     bzero((char *) bitmaps, glyph_size);
365 
366     /* set up some state */
367     sp_fp_cur = spf;
368     spf->bitmaps = bitmaps;
369     cfv->format = format;
370     cfv->scanpad = glyph;
371     cfv->bp = bitmaps;
372 
373     for (i = 0; i < spmf->num_chars; i++) {
374 	int j;
375 	cfv->char_index = spmf->enc[i * 2 + 1];
376 	cfv->char_id = spmf->enc[i * 2];
377 #if DEBUG
378 fprintf(stderr, "build_all_sp_bitmaps:i = %d, Char ID = %d\n", i, cfv->char_id);
379 #endif
380 	if (!cfv->char_id)
381 	    continue;
382 
383 	/*
384 	 * See if this character is in the list of ranges specified in the
385 	 * XLFD name
386 	 */
387 	for (j = 0; j < spf->vals.nranges; j++)
388 	    if (cfv->char_id >= mincharno(spf->vals.ranges[j]) &&
389 		    cfv->char_id <= maxcharno(spf->vals.ranges[j]))
390 		break;
391 
392 	  /* If not, don't realize it. */
393 	if (spf->vals.nranges && j == spf->vals.nranges)
394 	    continue;
395 
396 	if (!sp_make_char(cfv->char_index)) {
397 
398 #ifdef DEBUG			/* can be very common with some encodings */
399 	    SpeedoErr("Can't make char %d\n", cfv->char_index);
400 #endif
401 	}
402     }
403 
404     return Successful;
405 }
406