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