fontinfo.c revision 34f90d55
1/*
2 * font data query
3 */
4/*
5
6Copyright 1990, 1991, 1998  The Open Group
7
8Permission to use, copy, modify, distribute, and sell this software and its
9documentation for any purpose is hereby granted without fee, provided that
10the above copyright notice appear in all copies and that both that
11copyright notice and this permission notice appear in supporting
12documentation.
13
14The above copyright notice and this permission notice shall be included in
15all copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
20OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24Except as contained in this notice, the name of The Open Group shall not be
25used in advertising or otherwise to promote the sale, use or other dealings
26in this Software without prior written authorization from The Open Group.
27
28 * Copyright 1990, 1991 Network Computing Devices;
29 * Portions Copyright 1987 by Digital Equipment Corporation
30 *
31 * Permission to use, copy, modify, distribute, and sell this software and
32 * its documentation for any purpose is hereby granted without fee, provided
33 * that the above copyright notice appear in all copies and that both that
34 * copyright notice and this permission notice appear in supporting
35 * documentation, and that the names of Network Computing Devices, or Digital
36 * not be used in advertising or publicity pertaining to distribution
37 * of the software without specific, written prior permission.
38 *
39 * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH
40 * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
41 * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES,
42 * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
43 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
44 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
45 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
46 * THIS SOFTWARE.
47 */
48
49#include	"config.h"
50
51#include        <X11/fonts/FS.h>
52#include        <X11/fonts/FSproto.h>
53#include        <stdio.h>
54#include        <X11/Xos.h>
55#include        "clientstr.h"
56#include        "difsfnst.h"
57#include        <X11/fonts/fontstruct.h>
58#include        "closestr.h"
59#include        "globals.h"
60#include	"difs.h"
61#include	"dispatch.h"
62#include	<swapreq.h>
63#include	<swaprep.h>
64
65#ifdef HAVE_STDINT_H
66#include	<stdint.h>
67#endif
68#include	<limits.h>
69#ifndef SIZE_MAX
70# ifdef ULONG_MAX
71#  define SIZE_MAX ULONG_MAX
72# else
73#  define SIZE_MAX UINT_MAX
74# endif
75#endif
76
77
78int
79convert_props(
80    FontInfoPtr pinfo,
81    fsPropInfo **props)
82{
83    int i;
84    int data_len, cur_off;
85    char *str;
86    pointer ptr, off_ptr, string_base;
87    fsPropOffset local_offset;
88
89    /*
90     * compute the size of the property data
91     */
92    data_len = 0;
93    for (i = 0; i < pinfo->nprops; i++)
94    {
95	data_len += strlen(NameForAtom(pinfo->props[i].name));
96	if (NULL != pinfo->isStringProp && pinfo->isStringProp[i])
97	    data_len += strlen(NameForAtom(pinfo->props[i].value));
98    }
99
100    /*
101     * allocate the single chunk that the difs layer requires
102     */
103    ptr = (pointer) fsalloc(SIZEOF(fsPropInfo)
104			    + SIZEOF(fsPropOffset) * pinfo->nprops
105			    + data_len);
106    if (!ptr)
107	return AllocError;
108    string_base = (char *)ptr + SIZEOF(fsPropInfo) + SIZEOF(fsPropOffset) * pinfo->nprops;
109
110    /*
111     * copy in the header
112     */
113    ((fsPropInfo *)ptr)->num_offsets = pinfo->nprops;
114    ((fsPropInfo *)ptr)->data_len = data_len;
115
116    /*
117     * compute the offsets and copy the string data
118     */
119    off_ptr = (char *)ptr + SIZEOF(fsPropInfo);
120    cur_off = 0;
121    for (i = 0; i < pinfo->nprops; i++)
122    {
123	local_offset.name.position = cur_off;
124	str = NameForAtom(pinfo->props[i].name);
125	local_offset.name.length = strlen(str);
126	memmove( (char *)string_base+cur_off, str, local_offset.name.length);
127	cur_off += local_offset.name.length;
128	if (NULL != pinfo->isStringProp && pinfo->isStringProp[i])
129	{
130	    local_offset.value.position = cur_off;
131	    str = NameForAtom(pinfo->props[i].value);
132	    local_offset.value.length = strlen(str);
133	    memmove( (char *)string_base+cur_off, str, local_offset.value.length);
134	    cur_off += local_offset.value.length;
135	    local_offset.type = PropTypeString;
136	} else {
137	    local_offset.value.position = pinfo->props[i].value;
138	    local_offset.value.length = 0; /* protocol says must be zero */
139	    local_offset.type = PropTypeSigned;
140	}
141	memmove( off_ptr, &local_offset, SIZEOF(fsPropOffset));
142	off_ptr = (char *)off_ptr + SIZEOF(fsPropOffset);
143    }
144
145    assert(off_ptr == string_base);
146    assert(cur_off == data_len);
147
148    *props = (fsPropInfo *) ptr;
149    return Successful;
150}
151
152
153/*
154 * does the real work of turning a list of range (or chars) into
155 * a list of ranges
156 */
157static fsRange *
158build_range(
159    Bool        type,
160    pointer     src,
161    int         item_size,
162    int        *num,
163    Bool       *all,
164    FontInfoPtr	pfi)
165{
166    fsRange    *new = (fsRange *) 0,
167               *np;
168    unsigned long src_num;
169    unsigned long i;
170
171    if (type) {			/* range flag is set, deal with data as a list
172				 * of char2bs */
173	char *rp = (char *) src;
174
175	src_num = *num;
176	if (src_num == 0) {
177	    *all = TRUE;
178	    return new;
179	}
180
181	if (src_num >= SIZE_MAX / sizeof(fsRange) * 2 - 1)
182		return NULL;
183	np = new = (fsRange *) fsalloc(sizeof(fsRange) * (src_num + 1) / 2);
184	if (!np)
185	    return np;
186	/* Build a new range */
187	for (i = 1; i < src_num; i += 2)
188	{
189	    np->min_char_high = (item_size == 1) ? 0 : *rp++;
190	    np->min_char_low  = *rp++;
191	    np->max_char_high = (item_size == 1) ? 0 : *rp++;
192	    np->max_char_low  = *rp++;
193	    np++;
194	}
195
196	/* If src_num is odd, we need to determine the final range
197	   by examining the fontinfo */
198	if (i == src_num)
199	{
200	    np->min_char_high = (item_size == 1) ? 0 : *rp++;
201	    np->min_char_low  = *rp++;
202	    np->max_char_high = pfi->lastRow;
203	    np->max_char_low  = pfi->lastCol;
204	    np++;
205	}
206	*num = np - new;
207	return new;
208    } else {			/* deal with data as a list of characters */
209	unsigned char      *pp = src;
210
211	src_num = *num;
212	if (src_num >= SIZE_MAX / sizeof(fsRange))
213		return NULL;
214	np = new = (fsRange *) fsalloc(SIZEOF(fsRange) * src_num);
215	if (!np)
216	    return np;
217
218	/* Build a range, with coalescence, from the list of chars */
219
220	for (i = 0; i < src_num; i++) {
221	    if (item_size == 1) {
222		np->min_char_low = *pp;
223		np->min_char_high = 0;
224	    } else {
225		np->min_char_low = ((fsChar2b *) pp)->low;
226		np->min_char_high = ((fsChar2b *) pp)->high;
227	    }
228	    np->max_char_high = np->min_char_high;
229	    np->max_char_low = np->min_char_low;
230	    /* Can we coalesce? */
231	    if (np > new &&
232		np->max_char_high == np[-1].max_char_high &&
233		np->max_char_low == np[-1].max_char_low + 1)
234		np[-1].max_char_low++;		/* Yes */
235	    else
236		np++;				/* No */
237	    pp += item_size;
238	}
239	*num = np - new;
240	return new;
241    }
242}
243
244/*
245 * provide backward compatibility with version 1, which had
246 * the bytes of char2b backwards
247 */
248static void
249swap_char2b (fsChar2b *values, int number)
250{
251    fsChar2b temp;
252    int i;
253
254    for (i = 0; i < number; i++) {
255	temp.low = ((fsChar2b_version1 *)values)->low;
256	temp.high = ((fsChar2b_version1 *)values)->high;
257	*values++ = temp;
258    }
259}
260
261#define pPtr ((QEclosurePtr) data)
262
263static Bool
264do_query_extents(ClientPtr client, pointer data)
265{
266    int         err;
267    unsigned long num_extents;
268    fsXCharInfo *extents;
269
270    err = GetExtents (pPtr->client, pPtr->pfont,
271		     pPtr->flags, pPtr->nranges, pPtr->range, &num_extents, &extents);
272    if (err == Suspended) {
273	if (!pPtr->slept) {
274	    pPtr->pfont->unload_glyphs = NULL;  /* Not a safe call for this font */
275	    pPtr->slept = TRUE;
276	    ClientSleep(client, do_query_extents, (pointer) pPtr);
277	}
278	return TRUE;
279    }
280    if (err != Successful) {
281	SendErrToClient(pPtr->client, FontToFSError(err), (pointer) 0);
282    }
283    else {
284	unsigned long lendata = SIZEOF(fsXCharInfo) * num_extents;
285	fsQueryXExtents8Reply reply = {
286	    .type = FS_Reply,
287	    .sequenceNumber = pPtr->client->sequence,
288	    .num_extents = num_extents,
289	    .length = (SIZEOF(fsQueryXExtents8Reply) + lendata) >> 2
290	};
291	if (client->swapped)
292	    SwapExtents(extents, num_extents);
293	WriteReplyToClient(pPtr->client, SIZEOF(fsQueryXExtents8Reply), &reply);
294	WriteToClient(pPtr->client, lendata, (char *) extents);
295	fsfree((char *) extents);
296    }
297    if (pPtr->slept)
298	ClientWakeup(pPtr->client);
299    if (pPtr->pfont->unload_glyphs)  /* For rasterizers that want to save memory */
300	(*pPtr->pfont->unload_glyphs)(pPtr->pfont);
301    fsfree(pPtr->range);
302    fsfree(pPtr);
303    return TRUE;
304}
305
306int
307QueryExtents(
308    ClientPtr   client,
309    ClientFontPtr cfp,
310    int         item_size,
311    int         nranges,
312    Bool        range_flag,
313    pointer     range_data)
314{
315    QEclosurePtr c;
316    fsRange    *fixed_range;
317    Bool        all_glyphs = FALSE;
318
319    if (item_size == 2  &&  client->major_version == 1)
320	swap_char2b ((fsChar2b *)range_data, nranges);
321
322    fixed_range = build_range(range_flag, range_data, item_size,
323			      &nranges, &all_glyphs, &cfp->font->info);
324
325    if (!fixed_range && !all_glyphs) {
326	SendErrToClient(client, FSBadRange, NULL);
327	return FSBadRange;
328    }
329    c = (QEclosurePtr) fsalloc(sizeof(QEclosureRec));
330    if (!c)
331	return FSBadAlloc;
332    c->client = client;
333    c->slept = FALSE;
334    c->pfont = cfp->font;
335    c->flags = (all_glyphs) ? LoadAll : 0;
336    c->flags |= (item_size == 1) ? EightBitFont : SixteenBitFont;
337    c->nranges = nranges;
338    c->range = fixed_range;
339
340    (void) do_query_extents(client, (pointer) c);
341    return FSSuccess;
342}
343
344#undef pPtr
345#define pPtr ((QBclosurePtr) data)
346
347static Bool
348do_query_bitmaps(ClientPtr client, pointer data)
349{
350    int         err;
351    unsigned long num_glyphs;
352    int data_size;
353    fsOffset32   *offsets;
354    pointer     glyph_data;
355    int		freedata;
356
357    err = GetBitmaps (pPtr->client, pPtr->pfont, pPtr->format,
358				    pPtr->flags, pPtr->nranges, pPtr->range,
359			     &data_size, &num_glyphs, &offsets, &glyph_data, &freedata);
360
361    if (err == Suspended) {
362	if (!pPtr->slept) {
363	    pPtr->pfont->unload_glyphs = NULL;  /* Not a safe call for this font */
364	    pPtr->slept = TRUE;
365	    ClientSleep(client, do_query_bitmaps, (pointer) pPtr);
366	}
367	return TRUE;
368    }
369    if (err != Successful) {
370	SendErrToClient(pPtr->client, FontToFSError(err), (pointer) 0);
371    }
372    else {
373	fsQueryXBitmaps8Reply reply = {
374	    .type = FS_Reply,
375	    .sequenceNumber = pPtr->client->sequence,
376	    .length = (SIZEOF(fsQueryXBitmaps8Reply) + data_size +
377		       (SIZEOF(fsOffset32) * num_glyphs) + 3) >> 2,
378	    .replies_hint = 0,
379	    .num_chars = num_glyphs,
380	    .nbytes = data_size
381	};
382
383	WriteReplyToClient(pPtr->client, SIZEOF(fsQueryXBitmaps8Reply), &reply);
384	if (client->swapped)
385	    SwapLongs((long *)offsets, num_glyphs * 2);
386	WriteToClient(pPtr->client, (num_glyphs * SIZEOF(fsOffset32)),
387		      (char *) offsets);
388	WriteToClient(pPtr->client, data_size, (char *) glyph_data);
389	fsfree((char *) offsets);
390	if (freedata)
391	    fsfree((char *) glyph_data);
392    }
393    if (pPtr->slept)
394	ClientWakeup(pPtr->client);
395    if (pPtr->pfont->unload_glyphs)  /* For rasterizers that want to save memory */
396	(*pPtr->pfont->unload_glyphs)(pPtr->pfont);
397    fsfree(pPtr->range);
398    fsfree(pPtr);
399    return TRUE;
400}
401
402int
403QueryBitmaps(
404    ClientPtr   client,
405    ClientFontPtr cfp,
406    int         item_size,
407    fsBitmapFormat format,
408    int         nranges,
409    Bool        range_flag,
410    pointer     range_data)
411{
412    QBclosurePtr c;
413    fsRange    *fixed_range;
414    Bool        all_glyphs = FALSE;
415
416    if (item_size == 2  &&  client->major_version == 1)
417	swap_char2b ((fsChar2b *)range_data, nranges);
418
419    fixed_range = build_range(range_flag, range_data, item_size,
420			      &nranges, &all_glyphs, &cfp->font->info);
421
422    if (!fixed_range && !all_glyphs) {
423	SendErrToClient(client, FSBadRange, NULL);
424	return FSBadRange;
425    }
426    c = (QBclosurePtr) fsalloc(sizeof(QBclosureRec));
427    if (!c)
428	return FSBadAlloc;
429    c->client = client;
430    c->slept = FALSE;
431    c->pfont = cfp->font;
432    c->flags = (all_glyphs) ? LoadAll : 0;
433    c->nranges = nranges;
434    c->range = fixed_range;
435    c->format = format;
436
437    (void) do_query_bitmaps(client, (pointer) c);
438    return FSSuccess;
439}
440