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