fontinfo.c revision ce6676db
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	"xfs-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
77void
78CopyCharInfo(
79    CharInfoPtr ci,
80    fsXCharInfo *dst)
81{
82    xCharInfo  *src = &ci->metrics;
83
84    dst->ascent = src->ascent;
85    dst->descent = src->descent;
86    dst->left = src->leftSideBearing;
87    dst->right = src->rightSideBearing;
88    dst->width = src->characterWidth;
89    dst->attributes = src->attributes;
90}
91
92
93int
94convert_props(
95    FontInfoPtr pinfo,
96    fsPropInfo **props)
97{
98    int i;
99    int data_len, cur_off;
100    char *str;
101    pointer ptr, off_ptr, string_base;
102    fsPropOffset local_offset;
103
104    /*
105     * compute the size of the property data
106     */
107    data_len = 0;
108    for (i = 0; i < pinfo->nprops; i++)
109    {
110	data_len += strlen(NameForAtom(pinfo->props[i].name));
111	if (NULL != pinfo->isStringProp && pinfo->isStringProp[i])
112	    data_len += strlen(NameForAtom(pinfo->props[i].value));
113    }
114
115    /*
116     * allocate the single chunk that the difs layer requires
117     */
118    ptr = (pointer) fsalloc(SIZEOF(fsPropInfo)
119			    + SIZEOF(fsPropOffset) * pinfo->nprops
120			    + data_len);
121    if (!ptr)
122	return AllocError;
123    string_base = (char *)ptr + SIZEOF(fsPropInfo) + SIZEOF(fsPropOffset) * pinfo->nprops;
124
125    /*
126     * copy in the header
127     */
128    ((fsPropInfo *)ptr)->num_offsets = pinfo->nprops;
129    ((fsPropInfo *)ptr)->data_len = data_len;
130
131    /*
132     * compute the offsets and copy the string data
133     */
134    off_ptr = (char *)ptr + SIZEOF(fsPropInfo);
135    cur_off = 0;
136    for (i = 0; i < pinfo->nprops; i++)
137    {
138	local_offset.name.position = cur_off;
139	str = NameForAtom(pinfo->props[i].name);
140	local_offset.name.length = strlen(str);
141	memmove( (char *)string_base+cur_off, str, local_offset.name.length);
142	cur_off += local_offset.name.length;
143	if (NULL != pinfo->isStringProp && pinfo->isStringProp[i])
144	{
145	    local_offset.value.position = cur_off;
146	    str = NameForAtom(pinfo->props[i].value);
147	    local_offset.value.length = strlen(str);
148	    memmove( (char *)string_base+cur_off, str, local_offset.value.length);
149	    cur_off += local_offset.value.length;
150	    local_offset.type = PropTypeString;
151	} else {
152	    local_offset.value.position = pinfo->props[i].value;
153	    local_offset.value.length = 0; /* protocol says must be zero */
154	    local_offset.type = PropTypeSigned;
155	}
156	memmove( off_ptr, &local_offset, SIZEOF(fsPropOffset));
157	off_ptr = (char *)off_ptr + SIZEOF(fsPropOffset);
158    }
159
160    assert(off_ptr == string_base);
161    assert(cur_off == data_len);
162
163    *props = (fsPropInfo *) ptr;
164    return Successful;
165}
166
167
168/*
169 * does the real work of turning a list of range (or chars) into
170 * a list of ranges
171 */
172static fsRange *
173build_range(
174    Bool        type,
175    pointer     src,
176    int         item_size,
177    int        *num,
178    Bool       *all,
179    FontInfoPtr	pfi)
180{
181    fsRange    *new = (fsRange *) 0,
182               *np;
183    unsigned long src_num;
184    unsigned long i;
185
186    if (type) {			/* range flag is set, deal with data as a list
187				 * of char2bs */
188	char *rp = (char *) src;
189
190	src_num = *num;
191	if (src_num == 0) {
192	    *all = TRUE;
193	    return new;
194	}
195
196	if (src_num >= SIZE_MAX / sizeof(fsRange) * 2 - 1)
197		return NULL;
198	np = new = (fsRange *) fsalloc(sizeof(fsRange) * (src_num + 1) / 2);
199	if (!np)
200	    return np;
201	/* Build a new range */
202	for (i = 1; i < src_num; i += 2)
203	{
204	    np->min_char_high = (item_size == 1) ? 0 : *rp++;
205	    np->min_char_low  = *rp++;
206	    np->max_char_high = (item_size == 1) ? 0 : *rp++;
207	    np->max_char_low  = *rp++;
208	    np++;
209	}
210
211	/* If src_num is odd, we need to determine the final range
212	   by examining the fontinfo */
213	if (i == src_num)
214	{
215	    np->min_char_high = (item_size == 1) ? 0 : *rp++;
216	    np->min_char_low  = *rp++;
217	    np->max_char_high = pfi->lastRow;
218	    np->max_char_low  = pfi->lastCol;
219	    np++;
220	}
221	*num = np - new;
222	return new;
223    } else {			/* deal with data as a list of characters */
224	unsigned char      *pp = src;
225
226	src_num = *num;
227	if (src_num >= SIZE_MAX / sizeof(fsRange))
228		return NULL;
229	np = new = (fsRange *) fsalloc(SIZEOF(fsRange) * src_num);
230	if (!np)
231	    return np;
232
233	/* Build a range, with coalescence, from the list of chars */
234
235	for (i = 0; i < src_num; i++) {
236	    if (item_size == 1) {
237		np->min_char_low = *pp;
238		np->min_char_high = 0;
239	    } else {
240		np->min_char_low = ((fsChar2b *) pp)->low;
241		np->min_char_high = ((fsChar2b *) pp)->high;
242	    }
243	    np->max_char_high = np->min_char_high;
244	    np->max_char_low = np->min_char_low;
245	    /* Can we coalesce? */
246	    if (np > new &&
247		np->max_char_high == np[-1].max_char_high &&
248		np->max_char_low == np[-1].max_char_low + 1)
249		np[-1].max_char_low++;		/* Yes */
250	    else
251		np++;				/* No */
252	    pp += item_size;
253	}
254	*num = np - new;
255	return new;
256    }
257}
258
259/*
260 * provide backward compatibility with version 1, which had
261 * the bytes of char2b backwards
262 */
263static void
264swap_char2b (fsChar2b *values, int number)
265{
266    fsChar2b temp;
267    int i;
268
269    for (i = 0; i < number; i++) {
270	temp.low = ((fsChar2b_version1 *)values)->low;
271	temp.high = ((fsChar2b_version1 *)values)->high;
272	*values++ = temp;
273    }
274}
275
276#define pPtr ((QEclosurePtr) data)
277
278static Bool
279do_query_extents(ClientPtr client, pointer data)
280{
281    int         err;
282    unsigned long lendata,
283                num_extents;
284    fsXCharInfo *extents;
285    fsQueryXExtents8Reply reply;
286
287    err = GetExtents (pPtr->client, pPtr->pfont,
288		     pPtr->flags, pPtr->nranges, pPtr->range, &num_extents, &extents);
289    if (err == Suspended) {
290	if (!pPtr->slept) {
291	    pPtr->pfont->unload_glyphs = NULL;  /* Not a safe call for this font */
292	    pPtr->slept = TRUE;
293	    ClientSleep(client, do_query_extents, (pointer) pPtr);
294	}
295	return TRUE;
296    }
297    if (err != Successful) {
298	SendErrToClient(pPtr->client, FontToFSError(err), (pointer) 0);
299	goto finish;
300    }
301    reply.type = FS_Reply;
302    reply.sequenceNumber = pPtr->client->sequence;
303    reply.num_extents = num_extents;
304    lendata = SIZEOF(fsXCharInfo) * num_extents;
305    reply.length = (SIZEOF(fsQueryXExtents8Reply) + lendata) >> 2;
306    if (client->swapped)
307	SwapExtents(extents, num_extents);
308    WriteReplyToClient(pPtr->client, SIZEOF(fsQueryXExtents8Reply), &reply);
309    (void) WriteToClient(pPtr->client, lendata, (char *) extents);
310    fsfree((char *) extents);
311finish:
312    if (pPtr->slept)
313	ClientWakeup(pPtr->client);
314    if (pPtr->pfont->unload_glyphs)  /* For rasterizers that want to save memory */
315	(*pPtr->pfont->unload_glyphs)(pPtr->pfont);
316    fsfree(pPtr->range);
317    fsfree(pPtr);
318    return TRUE;
319}
320
321int
322QueryExtents(
323    ClientPtr   client,
324    ClientFontPtr cfp,
325    int         item_size,
326    int         nranges,
327    Bool        range_flag,
328    pointer     range_data)
329{
330    QEclosurePtr c;
331    fsRange    *fixed_range;
332    Bool        all_glyphs = FALSE;
333
334    if (item_size == 2  &&  client->major_version == 1)
335	swap_char2b ((fsChar2b *)range_data, nranges);
336
337    fixed_range = build_range(range_flag, range_data, item_size,
338			      &nranges, &all_glyphs, &cfp->font->info);
339
340    if (!fixed_range && !all_glyphs) {
341	SendErrToClient(client, FSBadRange, NULL);
342	return FSBadRange;
343    }
344    c = (QEclosurePtr) fsalloc(sizeof(QEclosureRec));
345    if (!c)
346	return FSBadAlloc;
347    c->client = client;
348    c->slept = FALSE;
349    c->pfont = cfp->font;
350    c->flags = (all_glyphs) ? LoadAll : 0;
351    c->flags |= (item_size == 1) ? EightBitFont : SixteenBitFont;
352    c->nranges = nranges;
353    c->range = fixed_range;
354
355    (void) do_query_extents(client, (pointer) c);
356    return FSSuccess;
357}
358
359#undef pPtr
360#define pPtr ((QBclosurePtr) data)
361
362static Bool
363do_query_bitmaps(ClientPtr client, pointer data)
364{
365    int         err;
366    unsigned long num_glyphs;
367    int data_size;
368    fsOffset32   *offsets;
369    pointer     glyph_data;
370    fsQueryXBitmaps8Reply reply;
371    int		freedata;
372
373    err = GetBitmaps (pPtr->client, pPtr->pfont, pPtr->format,
374				    pPtr->flags, pPtr->nranges, pPtr->range,
375			     &data_size, &num_glyphs, &offsets, &glyph_data, &freedata);
376
377    if (err == Suspended) {
378	if (!pPtr->slept) {
379	    pPtr->pfont->unload_glyphs = NULL;  /* Not a safe call for this font */
380	    pPtr->slept = TRUE;
381	    ClientSleep(client, do_query_bitmaps, (pointer) pPtr);
382	}
383	return TRUE;
384    }
385    if (err != Successful) {
386	SendErrToClient(pPtr->client, FontToFSError(err), (pointer) 0);
387	goto finish;
388    }
389    reply.type = FS_Reply;
390    reply.sequenceNumber = pPtr->client->sequence;
391    reply.replies_hint = 0;
392    reply.num_chars = num_glyphs;
393    reply.nbytes = data_size;
394    reply.length = (SIZEOF(fsQueryXBitmaps8Reply) + data_size +
395		    (SIZEOF(fsOffset32) * num_glyphs) + 3) >> 2;
396
397    WriteReplyToClient(pPtr->client, SIZEOF(fsQueryXBitmaps8Reply), &reply);
398    if (client->swapped)
399	SwapLongs((long *)offsets, num_glyphs * 2);
400    (void) WriteToClient(pPtr->client, (num_glyphs * SIZEOF(fsOffset32)),
401			 (char *) offsets);
402    (void) WriteToClient(pPtr->client, data_size, (char *) glyph_data);
403    fsfree((char *) offsets);
404    if (freedata)
405	fsfree((char *) glyph_data);
406finish:
407    if (pPtr->slept)
408	ClientWakeup(pPtr->client);
409    if (pPtr->pfont->unload_glyphs)  /* For rasterizers that want to save memory */
410	(*pPtr->pfont->unload_glyphs)(pPtr->pfont);
411    fsfree(pPtr->range);
412    fsfree(pPtr);
413    return TRUE;
414}
415
416int
417QueryBitmaps(
418    ClientPtr   client,
419    ClientFontPtr cfp,
420    int         item_size,
421    fsBitmapFormat format,
422    int         nranges,
423    Bool        range_flag,
424    pointer     range_data)
425{
426    QBclosurePtr c;
427    fsRange    *fixed_range;
428    Bool        all_glyphs = FALSE;
429
430    if (item_size == 2  &&  client->major_version == 1)
431	swap_char2b ((fsChar2b *)range_data, nranges);
432
433    fixed_range = build_range(range_flag, range_data, item_size,
434			      &nranges, &all_glyphs, &cfp->font->info);
435
436    if (!fixed_range && !all_glyphs) {
437	SendErrToClient(client, FSBadRange, NULL);
438	return FSBadRange;
439    }
440    c = (QBclosurePtr) fsalloc(sizeof(QBclosureRec));
441    if (!c)
442	return FSBadAlloc;
443    c->client = client;
444    c->slept = FALSE;
445    c->pfont = cfp->font;
446    c->flags = (all_glyphs) ? LoadAll : 0;
447    c->nranges = nranges;
448    c->range = fixed_range;
449    c->format = format;
450
451    (void) do_query_bitmaps(client, (pointer) c);
452    return FSSuccess;
453}
454