1a96d7823Smrg/*
2a96d7823Smrg * Copyright 1990 Network Computing Devices
3a96d7823Smrg *
4a96d7823Smrg * Permission to use, copy, modify, distribute, and sell this software and
5a96d7823Smrg * its documentation for any purpose is hereby granted without fee, provided
6a96d7823Smrg * that the above copyright notice appear in all copies and that both that
7a96d7823Smrg * copyright notice and this permission notice appear in supporting
8a96d7823Smrg * documentation, and that the name of Network Computing Devices not be used
9a96d7823Smrg * in advertising or publicity pertaining to distribution of the software
10a96d7823Smrg * without specific, written prior permission.  Network Computing Devices
11a96d7823Smrg * makes no representations about the suitability of this software for any
12a96d7823Smrg * purpose.  It is provided "as is" without express or implied warranty.
13a96d7823Smrg *
14a96d7823Smrg * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
15a96d7823Smrg * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
16a96d7823Smrg * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
17a96d7823Smrg * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
18a96d7823Smrg * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
19a96d7823Smrg * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
20a96d7823Smrg * OR PERFORMANCE OF THIS SOFTWARE.
21a96d7823Smrg *
22a96d7823Smrg * Author:  	Dave Lemke, Network Computing Devices, Inc
23a96d7823Smrg */
24a96d7823Smrg/*
25a96d7823Smrg * FS data conversion
26a96d7823Smrg */
27a96d7823Smrg
28a96d7823Smrg#ifdef HAVE_CONFIG_H
29a96d7823Smrg#include <config.h>
30a96d7823Smrg#endif
31a96d7823Smrg#include "libxfontint.h"
32c7b4381aSmrg#include "src/util/replace.h"
33a96d7823Smrg#include        <X11/X.h>
34a96d7823Smrg#include 	<X11/Xtrans/Xtrans.h>
35a96d7823Smrg#include	<X11/Xpoll.h>
36a96d7823Smrg#include	<X11/fonts/FS.h>
37a96d7823Smrg#include	<X11/fonts/FSproto.h>
38a96d7823Smrg#include	<X11/fonts/fontmisc.h>
39a96d7823Smrg#include	<X11/fonts/fontstruct.h>
40a96d7823Smrg#include	"fservestr.h"
41a96d7823Smrg#include	<X11/fonts/fontutil.h>
42a96d7823Smrg#include	"fslibos.h"
43a96d7823Smrg
44a96d7823Smrgextern char _fs_glyph_undefined;
45a96d7823Smrgextern char _fs_glyph_requested;
46a96d7823Smrg
47a96d7823Smrg/*
48a96d7823Smrg * converts data from font server form to X server form
49a96d7823Smrg */
50a96d7823Smrg
51a96d7823Smrgvoid
52a96d7823Smrg_fs_convert_char_info(fsXCharInfo *src, xCharInfo *dst)
53a96d7823Smrg{
54a96d7823Smrg    dst->ascent = src->ascent;
55a96d7823Smrg    dst->descent = src->descent;
56a96d7823Smrg    dst->leftSideBearing = src->left;
57a96d7823Smrg    dst->rightSideBearing = src->right;
58a96d7823Smrg    dst->characterWidth = src->width;
59a96d7823Smrg    dst->attributes = src->attributes;
60a96d7823Smrg}
61a96d7823Smrg
62a96d7823Smrgvoid
63a96d7823Smrg_fs_init_fontinfo(FSFpePtr conn, FontInfoPtr pfi)
64a96d7823Smrg{
65a96d7823Smrg    if (conn->fsMajorVersion == 1) {
66a96d7823Smrg	unsigned short n;
67a96d7823Smrg	n = pfi->firstCol;
68a96d7823Smrg	pfi->firstCol = pfi->firstRow;
69a96d7823Smrg	pfi->firstRow = n;
70a96d7823Smrg	n = pfi->lastCol;
71a96d7823Smrg	pfi->lastCol = pfi->lastRow;
72a96d7823Smrg	pfi->lastRow = n;
73a96d7823Smrg	pfi->defaultCh = ((pfi->defaultCh >> 8) & 0xff)
74a96d7823Smrg	                   + ((pfi->defaultCh & 0xff) << 8);
75a96d7823Smrg    }
76a96d7823Smrg
77a96d7823Smrg    if (FontCouldBeTerminal (pfi))
78a96d7823Smrg    {
79a96d7823Smrg	pfi->terminalFont = TRUE;
80a96d7823Smrg	pfi->minbounds.ascent = pfi->fontAscent;
81a96d7823Smrg	pfi->minbounds.descent = pfi->fontDescent;
82a96d7823Smrg	pfi->minbounds.leftSideBearing = 0;
83a96d7823Smrg	pfi->minbounds.rightSideBearing = pfi->minbounds.characterWidth;
84a96d7823Smrg	pfi->maxbounds = pfi->minbounds;
85a96d7823Smrg    }
86a96d7823Smrg
87a96d7823Smrg    FontComputeInfoAccelerators (pfi);
88a96d7823Smrg}
89a96d7823Smrg
90a96d7823Smrgint
91a96d7823Smrg_fs_convert_props(fsPropInfo *pi, fsPropOffset *po, pointer pd,
92a96d7823Smrg		  FontInfoPtr pfi)
93a96d7823Smrg{
94a96d7823Smrg    FontPropPtr dprop;
95a96d7823Smrg    int         i,
96a96d7823Smrg                nprops;
97a96d7823Smrg    char       *is_str;
98a96d7823Smrg    fsPropOffset local_off;
99a96d7823Smrg    char *off_adr;
100a96d7823Smrg    char *pdc = pd;
101a96d7823Smrg
102a96d7823Smrg/* stolen from server/include/resource.h */
103a96d7823Smrg#define BAD_RESOURCE 0xe0000000
104a96d7823Smrg
105a96d7823Smrg    nprops = pfi->nprops = pi->num_offsets;
106a96d7823Smrg
107a96d7823Smrg    if (nprops < 0
108a96d7823Smrg	|| nprops > SIZE_MAX/(sizeof(FontPropRec) + sizeof(char)))
109a96d7823Smrg	return -1;
110a96d7823Smrg
111c7b4381aSmrg    dprop = mallocarray(nprops, sizeof(FontPropRec) + sizeof (char));
112a96d7823Smrg    if (!dprop)
113a96d7823Smrg	return -1;
114a96d7823Smrg
115a96d7823Smrg    is_str = (char *) (dprop + nprops);
116a96d7823Smrg    pfi->props = dprop;
117a96d7823Smrg    pfi->isStringProp = is_str;
118a96d7823Smrg
119a96d7823Smrg    off_adr = (char *)po;
120a96d7823Smrg    for (i = 0; i < nprops; i++, dprop++, is_str++)
121a96d7823Smrg    {
122a96d7823Smrg	memcpy(&local_off, off_adr, SIZEOF(fsPropOffset));
123a96d7823Smrg	if ((local_off.name.position >= pi->data_len) ||
124a96d7823Smrg		(local_off.name.length >
125a96d7823Smrg		 (pi->data_len - local_off.name.position)))
126a96d7823Smrg	    goto bail;
127a96d7823Smrg	dprop->name = MakeAtom(&pdc[local_off.name.position],
128a96d7823Smrg			       local_off.name.length, 1);
129a96d7823Smrg	if (local_off.type != PropTypeString) {
130a96d7823Smrg	    *is_str = FALSE;
131a96d7823Smrg	    dprop->value = local_off.value.position;
132a96d7823Smrg	} else {
133a96d7823Smrg	    *is_str = TRUE;
134a96d7823Smrg	    if ((local_off.value.position >= pi->data_len) ||
135a96d7823Smrg		(local_off.value.length >
136a96d7823Smrg		 (pi->data_len - local_off.value.position)))
137a96d7823Smrg		goto bail;
138a96d7823Smrg	    dprop->value = (INT32) MakeAtom(&pdc[local_off.value.position],
139a96d7823Smrg					    local_off.value.length, 1);
140a96d7823Smrg	    if (dprop->value == BAD_RESOURCE)
141a96d7823Smrg	    {
142a96d7823Smrg	      bail:
143a96d7823Smrg		free (pfi->props);
144a96d7823Smrg		pfi->nprops = 0;
145a96d7823Smrg		pfi->props = 0;
146a96d7823Smrg		pfi->isStringProp = 0;
147a96d7823Smrg		return -1;
148a96d7823Smrg	    }
149a96d7823Smrg	}
150a96d7823Smrg	off_adr += SIZEOF(fsPropOffset);
151a96d7823Smrg    }
152a96d7823Smrg
153a96d7823Smrg    return nprops;
154a96d7823Smrg}
155a96d7823Smrg
156a96d7823Smrgvoid
157a96d7823Smrg_fs_free_props (FontInfoPtr pfi)
158a96d7823Smrg{
159a96d7823Smrg    if (pfi->props)
160a96d7823Smrg    {
161a96d7823Smrg	free (pfi->props);
162a96d7823Smrg	pfi->nprops = 0;
163a96d7823Smrg	pfi->props = 0;
164a96d7823Smrg    }
165a96d7823Smrg}
166a96d7823Smrg
167a96d7823Smrgint
168a96d7823Smrg_fs_convert_lfwi_reply(FSFpePtr conn, FontInfoPtr pfi,
169a96d7823Smrg		       fsListFontsWithXInfoReply *fsrep,
170a96d7823Smrg		       fsPropInfo *pi, fsPropOffset *po, pointer pd)
171a96d7823Smrg{
172a96d7823Smrg    fsUnpack_XFontInfoHeader(fsrep, pfi);
173a96d7823Smrg    _fs_init_fontinfo(conn, pfi);
174a96d7823Smrg
175a96d7823Smrg    if (_fs_convert_props(pi, po, pd, pfi) == -1)
176a96d7823Smrg	return AllocError;
177a96d7823Smrg
178a96d7823Smrg    return Successful;
179a96d7823Smrg}
180a96d7823Smrg
181a96d7823Smrg
182a96d7823Smrg#define ENCODING_UNDEFINED(enc) \
183a96d7823Smrg	((enc)->bits == &_fs_glyph_undefined ? \
184a96d7823Smrg	 TRUE : \
185a96d7823Smrg	 (access_done = access_done && (enc)->bits != &_fs_glyph_requested, \
186a96d7823Smrg	  FALSE))
187a96d7823Smrg
188a96d7823Smrg#define GLYPH_UNDEFINED(loc) ENCODING_UNDEFINED(encoding + (loc))
189a96d7823Smrg
190a96d7823Smrg/*
191a96d7823Smrg * figures out what glyphs to request
192a96d7823Smrg *
193a96d7823Smrg * Includes logic to attempt to reduce number of round trips to the font
194a96d7823Smrg * server:  when a glyph is requested, fs_build_range() requests a
195a96d7823Smrg * 16-glyph range of glyphs that contains the requested glyph.  This is
196a96d7823Smrg * predicated on the belief that using a glyph increases the chances
197a96d7823Smrg * that nearby glyphs will be used: a good assumption for phonetic
198a96d7823Smrg * alphabets, but a questionable one for ideographic/pictographic ones.
199a96d7823Smrg */
200a96d7823Smrg/* ARGSUSED */
201a96d7823Smrgint
202a96d7823Smrgfs_build_range(FontPtr pfont, Bool range_flag, unsigned int count,
203a96d7823Smrg	       int item_size, unsigned char *data, int *nranges,
204a96d7823Smrg	       fsRange **ranges)
205a96d7823Smrg{
206a96d7823Smrg    FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate);
207a96d7823Smrg    FSFontPtr fsfont = (FSFontPtr) (pfont->fontPrivate);
208a96d7823Smrg    register CharInfoPtr encoding = fsfont->encoding;
209a96d7823Smrg    FontInfoPtr pfi = &(pfont->info);
210a96d7823Smrg    fsRange	range;
211a96d7823Smrg    int		access_done = TRUE;
212a96d7823Smrg    int		err;
213a96d7823Smrg    register unsigned long firstrow, lastrow, firstcol, lastcol;
214a96d7823Smrg    register unsigned long row;
215a96d7823Smrg    register unsigned long col;
216a96d7823Smrg    register unsigned long loc;
217a96d7823Smrg
218a96d7823Smrg    if (!fsd->glyphs_to_get)
219a96d7823Smrg	return AccessDone;
220a96d7823Smrg
221a96d7823Smrg    firstrow = pfi->firstRow;
222a96d7823Smrg    lastrow = pfi->lastRow;
223a96d7823Smrg    firstcol = pfi->firstCol;
224a96d7823Smrg    lastcol = pfi->lastCol;
225a96d7823Smrg
226a96d7823Smrg    /* Make sure we have default char */
227a96d7823Smrg    if (fsfont->pDefault && ENCODING_UNDEFINED(fsfont->pDefault))
228a96d7823Smrg    {
229a96d7823Smrg	loc = fsfont->pDefault - encoding;
230a96d7823Smrg	row = loc / (lastcol - firstcol + 1) + firstrow;
231a96d7823Smrg	col = loc % (lastcol - firstcol + 1) + firstcol;
232a96d7823Smrg
233a96d7823Smrg	range.min_char_low = range.max_char_low = col;
234a96d7823Smrg	range.min_char_high = range.max_char_high = row;
235a96d7823Smrg
236a96d7823Smrg	if ((err = add_range(&range, nranges, ranges, FALSE)) !=
237a96d7823Smrg	    Successful) return err;
238a96d7823Smrg	encoding[loc].bits = &_fs_glyph_requested;
239a96d7823Smrg	access_done = FALSE;
240a96d7823Smrg    }
241a96d7823Smrg
242a96d7823Smrg    if (!range_flag && item_size == 1)
243a96d7823Smrg    {
244a96d7823Smrg	if (firstrow != 0) return AccessDone;
245a96d7823Smrg	while (count--)
246a96d7823Smrg	{
247a96d7823Smrg	    col = *data++;
248a96d7823Smrg	    if (col >= firstcol && col <= lastcol &&
249a96d7823Smrg		GLYPH_UNDEFINED(col - firstcol))
250a96d7823Smrg	    {
251a96d7823Smrg		int col1, col2;
252a96d7823Smrg		col1 = col & 0xf0;
253a96d7823Smrg		col2 = col1 + 15;
254a96d7823Smrg		if (col1 < firstcol) col1 = firstcol;
255a96d7823Smrg		if (col2 > lastcol) col2 = lastcol;
256a96d7823Smrg		/* Collect a 16-glyph neighborhood containing the requested
257a96d7823Smrg		   glyph... should in most cases reduce the number of round
258a96d7823Smrg		   trips to the font server. */
259a96d7823Smrg		for (col = col1; col <= col2; col++)
260a96d7823Smrg		{
261a96d7823Smrg		    if (!GLYPH_UNDEFINED(col - firstcol)) continue;
262a96d7823Smrg		    range.min_char_low = range.max_char_low = col;
263a96d7823Smrg		    range.min_char_high = range.max_char_high = 0;
264a96d7823Smrg		    if ((err = add_range(&range, nranges, ranges, FALSE)) !=
265a96d7823Smrg		        Successful) return err;
266a96d7823Smrg		    encoding[col - firstcol].bits = &_fs_glyph_requested;
267a96d7823Smrg		    access_done = FALSE;
268a96d7823Smrg		}
269a96d7823Smrg	    }
270a96d7823Smrg	}
271a96d7823Smrg    }
272a96d7823Smrg    else
273a96d7823Smrg    {
274a96d7823Smrg	fsRange fullrange[1];
275a96d7823Smrg
276a96d7823Smrg	if (range_flag && count == 0)
277a96d7823Smrg	{
278a96d7823Smrg	    count = 2;
279a96d7823Smrg	    data = (unsigned char *)fullrange;
280a96d7823Smrg	    fullrange[0].min_char_high = firstrow;
281a96d7823Smrg	    fullrange[0].min_char_low = firstcol;
282a96d7823Smrg	    fullrange[0].max_char_high = lastrow;
283a96d7823Smrg	    fullrange[0].max_char_low = lastcol;
284a96d7823Smrg	}
285a96d7823Smrg
286a96d7823Smrg	while (count--)
287a96d7823Smrg	{
288a96d7823Smrg	    int row1, col1, row2, col2;
289a96d7823Smrg	    row1 = row2 = *data++;
290a96d7823Smrg	    col1 = col2 = *data++;
291a96d7823Smrg	    if (range_flag)
292a96d7823Smrg	    {
293a96d7823Smrg		if (count)
294a96d7823Smrg		{
295a96d7823Smrg		    row2 = *data++;
296a96d7823Smrg		    col2 = *data++;
297a96d7823Smrg		    count--;
298a96d7823Smrg		}
299a96d7823Smrg		else
300a96d7823Smrg		{
301a96d7823Smrg		    row2 = lastrow;
302a96d7823Smrg		    col2 = lastcol;
303a96d7823Smrg		}
304a96d7823Smrg		if (row1 < firstrow) row1 = firstrow;
305a96d7823Smrg		if (row2 > lastrow) row2 = lastrow;
306a96d7823Smrg		if (col1 < firstcol) col1 = firstcol;
307a96d7823Smrg		if (col2 > lastcol) col2 = lastcol;
308a96d7823Smrg	    }
309a96d7823Smrg	    else
310a96d7823Smrg	    {
311a96d7823Smrg		if (row1 < firstrow || row1 > lastrow ||
312a96d7823Smrg		    col1 < firstcol || col1 > lastcol)
313a96d7823Smrg		    continue;
314a96d7823Smrg	    }
315a96d7823Smrg	    for (row = row1; row <= row2; row++)
316a96d7823Smrg	    {
317a96d7823Smrg	    expand_glyph_range: ;
318a96d7823Smrg		loc = (row - firstrow) * (lastcol + 1 - firstcol) +
319a96d7823Smrg		      (col1 - firstcol);
320a96d7823Smrg		for (col = col1; col <= col2; col++, loc++)
321a96d7823Smrg		{
322a96d7823Smrg		    if (GLYPH_UNDEFINED(loc))
323a96d7823Smrg		    {
324a96d7823Smrg			if (row1 == row2 &&
325a96d7823Smrg			    (((col1 & 0xf) && col1 > firstcol) ||
326a96d7823Smrg			     (col2 & 0xf) != 0xf) && (col2 < lastcol))
327a96d7823Smrg			{
328a96d7823Smrg			    /* If we're loading from a single row, expand
329a96d7823Smrg			       range of glyphs loaded to a multiple of
330a96d7823Smrg			       a 16-glyph range -- attempt to reduce number
331a96d7823Smrg			       of round trips to the font server. */
332a96d7823Smrg			    col1 &= 0xf0;
333a96d7823Smrg			    col2 = (col2 & 0xf0) + 15;
334a96d7823Smrg			    if (col1 < firstcol) col1 = firstcol;
335a96d7823Smrg			    if (col2 > lastcol) col2 = lastcol;
336a96d7823Smrg			    goto expand_glyph_range;
337a96d7823Smrg			}
338a96d7823Smrg			range.min_char_low = range.max_char_low = col;
339a96d7823Smrg			range.min_char_high = range.max_char_high = row;
340a96d7823Smrg			if ((err = add_range(&range, nranges, ranges, FALSE)) !=
341a96d7823Smrg			    Successful) return err;
342a96d7823Smrg			encoding[loc].bits = &_fs_glyph_requested;
343a96d7823Smrg			access_done = FALSE;
344a96d7823Smrg		    }
345a96d7823Smrg		}
346a96d7823Smrg	    }
347a96d7823Smrg	}
348a96d7823Smrg    }
349a96d7823Smrg
350a96d7823Smrg    return access_done ?
351a96d7823Smrg	   AccessDone :
352a96d7823Smrg	   Successful;
353a96d7823Smrg}
354a96d7823Smrg
355a96d7823Smrg#undef GLYPH_UNDEFINED
356a96d7823Smrg#undef ENCODING_UNDEFINED
357a96d7823Smrg
358a96d7823Smrg
359a96d7823Smrg/* _fs_clean_aborted_loadglyphs(): Undoes the changes to the encoding array
360a96d7823Smrg   performed by fs_build_range(); for use if the associated LoadGlyphs
361a96d7823Smrg   requests needs to be cancelled. */
362a96d7823Smrg
363a96d7823Smrgvoid
364a96d7823Smrg_fs_clean_aborted_loadglyphs(FontPtr pfont, int num_expected_ranges,
365a96d7823Smrg			     fsRange *expected_ranges)
366a96d7823Smrg{
367a96d7823Smrg    register FSFontPtr fsfont;
368a96d7823Smrg    register int i;
369a96d7823Smrg
370a96d7823Smrg    fsfont = (FSFontPtr) pfont->fontPrivate;
371a96d7823Smrg    if (fsfont->encoding)
372a96d7823Smrg    {
373a96d7823Smrg	fsRange full_range[1];
374a96d7823Smrg	if (!num_expected_ranges)
375a96d7823Smrg	{
376a96d7823Smrg	    full_range[0].min_char_low = pfont->info.firstCol;
377a96d7823Smrg	    full_range[0].min_char_high = pfont->info.firstRow;
378a96d7823Smrg	    full_range[0].max_char_low = pfont->info.lastCol;
379a96d7823Smrg	    full_range[0].max_char_high = pfont->info.lastRow;
380a96d7823Smrg	    num_expected_ranges = 1;
381a96d7823Smrg	    expected_ranges = full_range;
382a96d7823Smrg	}
383a96d7823Smrg
384a96d7823Smrg	for (i = 0; i < num_expected_ranges; i++)
385a96d7823Smrg	{
386a96d7823Smrg	    int row, col;
387a96d7823Smrg	    for (row = expected_ranges[i].min_char_high;
388a96d7823Smrg		 row <= expected_ranges[i].max_char_high;
389a96d7823Smrg		 row++)
390a96d7823Smrg	    {
391a96d7823Smrg		register CharInfoPtr encoding = fsfont->encoding +
392a96d7823Smrg		    ((row - pfont->info.firstRow) *
393a96d7823Smrg		     (pfont->info.lastCol -
394a96d7823Smrg		      pfont->info.firstCol + 1) +
395a96d7823Smrg		     expected_ranges[i].min_char_low -
396a96d7823Smrg		     pfont->info.firstCol);
397a96d7823Smrg		for (col = expected_ranges[i].min_char_low;
398a96d7823Smrg		     col <= expected_ranges[i].max_char_low;
399a96d7823Smrg		     encoding++, col++)
400a96d7823Smrg		{
401a96d7823Smrg		    if (encoding->bits == &_fs_glyph_requested)
402a96d7823Smrg			encoding->bits = &_fs_glyph_undefined;
403a96d7823Smrg		}
404a96d7823Smrg	    }
405a96d7823Smrg	}
406a96d7823Smrg    }
407a96d7823Smrg}
408a96d7823Smrg
409a96d7823Smrgstatic int
410a96d7823Smrg_fs_get_glyphs(FontPtr pFont, unsigned long count, unsigned char *chars,
411a96d7823Smrg	       FontEncoding charEncoding,
412a96d7823Smrg	       unsigned long *glyphCount, /* RETURN */
413a96d7823Smrg	       CharInfoPtr *glyphs) 	  /* RETURN  */
414a96d7823Smrg{
415a96d7823Smrg    FSFontPtr   fsdata;
416a96d7823Smrg    unsigned int firstCol;
417a96d7823Smrg    register unsigned int numCols;
418a96d7823Smrg    unsigned int firstRow;
419a96d7823Smrg    unsigned int numRows;
420a96d7823Smrg    CharInfoPtr *glyphsBase;
421a96d7823Smrg    register unsigned int c;
422a96d7823Smrg    register CharInfoPtr pci;
423a96d7823Smrg    unsigned int r;
424a96d7823Smrg    CharInfoPtr encoding;
425a96d7823Smrg    CharInfoPtr pDefault;
426a96d7823Smrg    FSFontDataPtr fsd = (FSFontDataPtr) pFont->fpePrivate;
427a96d7823Smrg    int         err = Successful;
428a96d7823Smrg
429a96d7823Smrg    fsdata = (FSFontPtr) pFont->fontPrivate;
430a96d7823Smrg    encoding = fsdata->encoding;
431a96d7823Smrg    pDefault = fsdata->pDefault;
432a96d7823Smrg    firstCol = pFont->info.firstCol;
433a96d7823Smrg    numCols = pFont->info.lastCol - firstCol + 1;
434a96d7823Smrg    glyphsBase = glyphs;
435a96d7823Smrg
436a96d7823Smrg    /* In this age of glyph caching, any glyphs gotten through this
437a96d7823Smrg       procedure should already be loaded.  If they are not, we are
438a96d7823Smrg       dealing with someone (perhaps a ddx driver optimizing a font)
439a96d7823Smrg       that doesn't understand the finer points of glyph caching.  The
440a96d7823Smrg       CHECK_ENCODING macro checks for this condition...  if found, it
441a96d7823Smrg       calls fs_load_all_glyphs(), which corrects it.  Since the caller
442a96d7823Smrg       of this code will not know how to handle a return value of
443a96d7823Smrg       Suspended, the fs_load_all_glyphs() procedure will block and
444a96d7823Smrg       freeze the server until the load operation is done.  Moral: the
445a96d7823Smrg       glyphCachingMode flag really must indicate the capabilities of
446a96d7823Smrg       the ddx drivers.  */
447a96d7823Smrg
448a96d7823Smrg#define CHECK_ENCODING(cnum) \
449a96d7823Smrg    ( pci = encoding + (cnum), \
450a96d7823Smrg      fsd->glyphs_to_get ? \
451a96d7823Smrg      ( pci->bits == &_fs_glyph_undefined || pci->bits == &_fs_glyph_requested ? \
452a96d7823Smrg	((err = fs_load_all_glyphs(pFont)), pci) : \
453a96d7823Smrg	pci ) : \
454a96d7823Smrg      pci )
455a96d7823Smrg
456a96d7823Smrg    switch (charEncoding) {
457a96d7823Smrg
458a96d7823Smrg    case Linear8Bit:
459a96d7823Smrg    case TwoD8Bit:
460a96d7823Smrg	if (pFont->info.firstRow > 0)
461a96d7823Smrg	    break;
462a96d7823Smrg	if (pFont->info.allExist && pDefault) {
463a96d7823Smrg	    while (err == Successful && count--) {
464a96d7823Smrg		c = (*chars++) - firstCol;
465a96d7823Smrg		if (c < numCols)
466a96d7823Smrg		    *glyphs++ = CHECK_ENCODING(c);
467a96d7823Smrg		else
468a96d7823Smrg		    *glyphs++ = pDefault;
469a96d7823Smrg	    }
470a96d7823Smrg	} else {
471a96d7823Smrg	    while (err == Successful && count--) {
472a96d7823Smrg		c = (*chars++) - firstCol;
473a96d7823Smrg		if (c < numCols && CHECK_ENCODING(c)->bits)
474a96d7823Smrg		    *glyphs++ = pci;
475a96d7823Smrg		else if (pDefault)
476a96d7823Smrg		    *glyphs++ = pDefault;
477a96d7823Smrg	    }
478a96d7823Smrg	}
479a96d7823Smrg	break;
480a96d7823Smrg    case Linear16Bit:
481a96d7823Smrg	if (pFont->info.allExist && pDefault) {
482a96d7823Smrg	    while (err == Successful && count--) {
483a96d7823Smrg		c = *chars++ << 8;
484a96d7823Smrg		c = (c | *chars++) - firstCol;
485a96d7823Smrg		if (c < numCols)
486a96d7823Smrg		    *glyphs++ = CHECK_ENCODING(c);
487a96d7823Smrg		else
488a96d7823Smrg		    *glyphs++ = pDefault;
489a96d7823Smrg	    }
490a96d7823Smrg	} else {
491a96d7823Smrg	    while (err == Successful && count--) {
492a96d7823Smrg		c = *chars++ << 8;
493a96d7823Smrg		c = (c | *chars++) - firstCol;
494a96d7823Smrg		if (c < numCols && CHECK_ENCODING(c)->bits)
495a96d7823Smrg		    *glyphs++ = pci;
496a96d7823Smrg		else if (pDefault)
497a96d7823Smrg		    *glyphs++ = pDefault;
498a96d7823Smrg	    }
499a96d7823Smrg	}
500a96d7823Smrg	break;
501a96d7823Smrg
502a96d7823Smrg    case TwoD16Bit:
503a96d7823Smrg	firstRow = pFont->info.firstRow;
504a96d7823Smrg	numRows = pFont->info.lastRow - firstRow + 1;
505a96d7823Smrg	while (err == Successful && count--) {
506a96d7823Smrg	    r = (*chars++) - firstRow;
507a96d7823Smrg	    c = (*chars++) - firstCol;
508a96d7823Smrg	    if (r < numRows && c < numCols &&
509a96d7823Smrg		    CHECK_ENCODING(r * numCols + c)->bits)
510a96d7823Smrg		*glyphs++ = pci;
511a96d7823Smrg	    else if (pDefault)
512a96d7823Smrg		*glyphs++ = pDefault;
513a96d7823Smrg	}
514a96d7823Smrg	break;
515a96d7823Smrg    }
516a96d7823Smrg    *glyphCount = glyphs - glyphsBase;
517a96d7823Smrg    return err;
518a96d7823Smrg}
519a96d7823Smrg
520a96d7823Smrg
521a96d7823Smrgstatic int
522a96d7823Smrg_fs_get_metrics(FontPtr pFont, unsigned long count, unsigned char *chars,
523a96d7823Smrg		FontEncoding charEncoding,
524a96d7823Smrg		unsigned long *glyphCount, /* RETURN */
525a96d7823Smrg		xCharInfo **glyphs) 	   /* RETURN */
526a96d7823Smrg{
527a96d7823Smrg    FSFontPtr   fsdata;
528a96d7823Smrg    unsigned int firstCol;
529a96d7823Smrg    register unsigned int numCols;
530a96d7823Smrg    unsigned int firstRow;
531a96d7823Smrg    unsigned int numRows;
532a96d7823Smrg    xCharInfo **glyphsBase;
533a96d7823Smrg    register unsigned int c;
534a96d7823Smrg    unsigned int r;
535a96d7823Smrg    CharInfoPtr encoding;
536a96d7823Smrg    CharInfoPtr pDefault;
537a96d7823Smrg
538a96d7823Smrg    fsdata = (FSFontPtr) pFont->fontPrivate;
539a96d7823Smrg    encoding = fsdata->inkMetrics;
540a96d7823Smrg    pDefault = fsdata->pDefault;
541a96d7823Smrg    /* convert default bitmap metric to default ink metric */
542a96d7823Smrg    if (pDefault)
543a96d7823Smrg	pDefault = encoding + (pDefault - fsdata->encoding);
544a96d7823Smrg    firstCol = pFont->info.firstCol;
545a96d7823Smrg    numCols = pFont->info.lastCol - firstCol + 1;
546a96d7823Smrg    glyphsBase = glyphs;
547a96d7823Smrg
548a96d7823Smrg
549a96d7823Smrg    /* XXX - this should be much smarter */
550a96d7823Smrg    /* make sure the glyphs are there */
551a96d7823Smrg    switch (charEncoding) {
552a96d7823Smrg
553a96d7823Smrg    case Linear8Bit:
554a96d7823Smrg    case TwoD8Bit:
555a96d7823Smrg	if (pFont->info.firstRow > 0)
556a96d7823Smrg	    break;
557a96d7823Smrg	if (pFont->info.allExist && pDefault) {
558a96d7823Smrg	    while (count--) {
559a96d7823Smrg		c = (*chars++) - firstCol;
560a96d7823Smrg		if (c < numCols)
561a96d7823Smrg		    *glyphs++ = (xCharInfo *)&encoding[c];
562a96d7823Smrg		else
563a96d7823Smrg		    *glyphs++ = (xCharInfo *)pDefault;
564a96d7823Smrg	    }
565a96d7823Smrg	} else {
566a96d7823Smrg	    while (count--) {
567a96d7823Smrg		c = (*chars++) - firstCol;
568a96d7823Smrg		if (c < numCols)
569a96d7823Smrg		    *glyphs++ = (xCharInfo *)(encoding + c);
570a96d7823Smrg		else if (pDefault)
571a96d7823Smrg		    *glyphs++ = (xCharInfo *)pDefault;
572a96d7823Smrg	    }
573a96d7823Smrg	}
574a96d7823Smrg	break;
575a96d7823Smrg    case Linear16Bit:
576a96d7823Smrg	if (pFont->info.allExist && pDefault) {
577a96d7823Smrg	    while (count--) {
578a96d7823Smrg		c = *chars++ << 8;
579a96d7823Smrg		c = (c | *chars++) - firstCol;
580a96d7823Smrg		if (c < numCols)
581a96d7823Smrg		    *glyphs++ = (xCharInfo *)(encoding + c);
582a96d7823Smrg		else
583a96d7823Smrg		    *glyphs++ = (xCharInfo *)pDefault;
584a96d7823Smrg	    }
585a96d7823Smrg	} else {
586a96d7823Smrg	    while (count--) {
587a96d7823Smrg		c = *chars++ << 8;
588a96d7823Smrg		c = (c | *chars++) - firstCol;
589a96d7823Smrg		if (c < numCols)
590a96d7823Smrg		    *glyphs++ = (xCharInfo *)(encoding + c);
591a96d7823Smrg		else if (pDefault)
592a96d7823Smrg		    *glyphs++ = (xCharInfo *)pDefault;
593a96d7823Smrg	    }
594a96d7823Smrg	}
595a96d7823Smrg	break;
596a96d7823Smrg
597a96d7823Smrg    case TwoD16Bit:
598a96d7823Smrg	firstRow = pFont->info.firstRow;
599a96d7823Smrg	numRows = pFont->info.lastRow - firstRow + 1;
600a96d7823Smrg	while (count--) {
601a96d7823Smrg	    r = (*chars++) - firstRow;
602a96d7823Smrg	    c = (*chars++) - firstCol;
603a96d7823Smrg	    if (r < numRows && c < numCols)
604a96d7823Smrg		*glyphs++ = (xCharInfo *)(encoding + (r * numCols + c));
605a96d7823Smrg	    else if (pDefault)
606a96d7823Smrg		*glyphs++ = (xCharInfo *)pDefault;
607a96d7823Smrg	}
608a96d7823Smrg	break;
609a96d7823Smrg    }
610a96d7823Smrg    *glyphCount = glyphs - glyphsBase;
611a96d7823Smrg    return Successful;
612a96d7823Smrg}
613a96d7823Smrg
614a96d7823Smrg
615a96d7823Smrgstatic void
616a96d7823Smrg_fs_unload_font(FontPtr pfont)
617a96d7823Smrg{
618a96d7823Smrg    FSFontPtr	    fsdata = (FSFontPtr) pfont->fontPrivate;
619a96d7823Smrg    FSFontDataPtr   fsd = (FSFontDataPtr) pfont->fpePrivate;
620a96d7823Smrg    CharInfoPtr	    encoding = fsdata->encoding;
621a96d7823Smrg    FSGlyphPtr	    glyphs;
622a96d7823Smrg
623a96d7823Smrg    /*
624a96d7823Smrg     * fsdata points at FSFontRec, FSFontDataRec and name
625a96d7823Smrg     */
626a96d7823Smrg    if (encoding)
627a96d7823Smrg	free(encoding);
628a96d7823Smrg
629a96d7823Smrg    while ((glyphs = fsdata->glyphs))
630a96d7823Smrg    {
631a96d7823Smrg	fsdata->glyphs = glyphs->next;
632a96d7823Smrg	free (glyphs);
633a96d7823Smrg    }
634a96d7823Smrg
635a96d7823Smrg    /* XXX we may get called after the resource DB has been cleaned out */
636a96d7823Smrg    if (find_old_font(fsd->fontid))
637a96d7823Smrg	DeleteFontClientID (fsd->fontid);
638a96d7823Smrg
639a96d7823Smrg    _fs_free_props (&pfont->info);
640a96d7823Smrg
641a96d7823Smrg    free(fsdata);
642a96d7823Smrg
643a96d7823Smrg    DestroyFontRec(pfont);
644a96d7823Smrg}
645a96d7823Smrg
646a96d7823SmrgFontPtr
647a96d7823Smrgfs_create_font (FontPathElementPtr  fpe,
648a96d7823Smrg		const char	    *name,
649a96d7823Smrg		int		    namelen,
650a96d7823Smrg		fsBitmapFormat	    format,
651a96d7823Smrg		fsBitmapFormatMask  fmask)
652a96d7823Smrg{
653a96d7823Smrg    FontPtr	    pfont;
654a96d7823Smrg    FSFontPtr	    fsfont;
655a96d7823Smrg    FSFontDataPtr   fsd;
656a96d7823Smrg    int		    bit, byte, scan, glyph;
657a96d7823Smrg
658a96d7823Smrg    pfont = CreateFontRec ();
659a96d7823Smrg    if (!pfont)
660a96d7823Smrg	return 0;
661a96d7823Smrg    fsfont = malloc (sizeof (FSFontRec) + sizeof (FSFontDataRec) + namelen + 1);
662a96d7823Smrg    if (!fsfont)
663a96d7823Smrg    {
664a96d7823Smrg	DestroyFontRec (pfont);
665a96d7823Smrg	return 0;
666a96d7823Smrg    }
667a96d7823Smrg    fsd = (FSFontDataPtr) (fsfont + 1);
668a96d7823Smrg    bzero((char *) fsfont, sizeof(FSFontRec));
669a96d7823Smrg    bzero((char *) fsd, sizeof(FSFontDataRec));
670a96d7823Smrg
671a96d7823Smrg    pfont->fpe = fpe;
672a96d7823Smrg    pfont->fontPrivate = (pointer) fsfont;
673a96d7823Smrg    pfont->fpePrivate = (pointer) fsd;
674a96d7823Smrg
675a96d7823Smrg    /* These font components will be needed in packGlyphs */
676a96d7823Smrg    CheckFSFormat(format, BitmapFormatMaskBit |
677a96d7823Smrg		  BitmapFormatMaskByte |
678a96d7823Smrg		  BitmapFormatMaskScanLineUnit |
679a96d7823Smrg		  BitmapFormatMaskScanLinePad,
680a96d7823Smrg		  &bit,
681a96d7823Smrg		  &byte,
682a96d7823Smrg		  &scan,
683a96d7823Smrg		  &glyph,
684a96d7823Smrg		  NULL);
685a96d7823Smrg    pfont->format = format;
686a96d7823Smrg    pfont->bit = bit;
687a96d7823Smrg    pfont->byte = byte;
688a96d7823Smrg    pfont->scan = scan;
689a96d7823Smrg    pfont->glyph = glyph;
690a96d7823Smrg
691a96d7823Smrg    pfont->info.nprops = 0;
692a96d7823Smrg    pfont->info.props = 0;
693a96d7823Smrg    pfont->info.isStringProp = 0;
694a96d7823Smrg
695a96d7823Smrg    /* set font function pointers */
696a96d7823Smrg    pfont->get_glyphs = _fs_get_glyphs;
697a96d7823Smrg    pfont->get_metrics = _fs_get_metrics;
698a96d7823Smrg    pfont->unload_font = _fs_unload_font;
699a96d7823Smrg    pfont->unload_glyphs = NULL;
700a96d7823Smrg
701a96d7823Smrg    /* set the FPE private information */
702a96d7823Smrg    fsd->format = format;
703a96d7823Smrg    fsd->fmask = fmask;
704a96d7823Smrg    fsd->name = (char *) (fsd + 1);
705a96d7823Smrg    memcpy (fsd->name, name, namelen);
706a96d7823Smrg    fsd->name[namelen] = '\0';
707a96d7823Smrg    fsd->fontid = GetNewFontClientID ();
708a96d7823Smrg
709a96d7823Smrg    /* save the ID */
710a96d7823Smrg    if (!StoreFontClientFont(pfont, fsd->fontid))
711a96d7823Smrg    {
712a96d7823Smrg	free (fsfont);
713a96d7823Smrg	DestroyFontRec (pfont);
714a96d7823Smrg	return 0;
715a96d7823Smrg    }
716a96d7823Smrg
717a96d7823Smrg    return pfont;
718a96d7823Smrg}
719a96d7823Smrg
720a96d7823Smrgpointer
721a96d7823Smrgfs_alloc_glyphs (FontPtr pFont, int size)
722a96d7823Smrg{
723a96d7823Smrg    FSGlyphPtr	glyphs;
724a96d7823Smrg    FSFontPtr	fsfont = (FSFontPtr) pFont->fontPrivate;
725a96d7823Smrg
726a96d7823Smrg    if (size < (INT_MAX - sizeof (FSGlyphRec)))
727a96d7823Smrg	glyphs = malloc (sizeof (FSGlyphRec) + size);
728a96d7823Smrg    else
729a96d7823Smrg	glyphs = NULL;
730a96d7823Smrg    if (glyphs == NULL)
731a96d7823Smrg	return NULL;
732a96d7823Smrg    glyphs->next = fsfont->glyphs;
733a96d7823Smrg    fsfont->glyphs = glyphs;
734a96d7823Smrg    return (pointer) (glyphs + 1);
735a96d7823Smrg}
736