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