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