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 "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 79int 80convert_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 */ 158static fsRange * 159build_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 *) FSallocarray(src_num, SIZEOF(fsRange)); 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 */ 249static void 250swap_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 264static Bool 265do_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 307int 308QueryExtents( 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 FSfree(fixed_range); 333 return FSBadAlloc; 334 } 335 c->client = client; 336 c->slept = FALSE; 337 c->pfont = cfp->font; 338 c->flags = (all_glyphs) ? LoadAll : 0; 339 c->flags |= (item_size == 1) ? EightBitFont : SixteenBitFont; 340 c->nranges = nranges; 341 c->range = fixed_range; 342 343 (void) do_query_extents(client, (pointer) c); 344 return FSSuccess; 345} 346 347#undef pPtr 348#define pPtr ((QBclosurePtr) data) 349 350static Bool 351do_query_bitmaps(ClientPtr client, pointer data) 352{ 353 int err; 354 unsigned long num_glyphs; 355 int data_size; 356 fsOffset32 *offsets; 357 pointer glyph_data; 358 int freedata; 359 360 err = GetBitmaps (pPtr->client, pPtr->pfont, pPtr->format, 361 pPtr->flags, pPtr->nranges, pPtr->range, 362 &data_size, &num_glyphs, &offsets, &glyph_data, &freedata); 363 364 if (err == Suspended) { 365 if (!pPtr->slept) { 366 pPtr->pfont->unload_glyphs = NULL; /* Not a safe call for this font */ 367 pPtr->slept = TRUE; 368 ClientSleep(client, do_query_bitmaps, (pointer) pPtr); 369 } 370 return TRUE; 371 } 372 if (err != Successful) { 373 SendErrToClient(pPtr->client, FontToFSError(err), (pointer) 0); 374 } 375 else { 376 fsQueryXBitmaps8Reply reply = { 377 .type = FS_Reply, 378 .sequenceNumber = pPtr->client->sequence, 379 .length = (SIZEOF(fsQueryXBitmaps8Reply) + data_size + 380 (SIZEOF(fsOffset32) * num_glyphs) + 3) >> 2, 381 .replies_hint = 0, 382 .num_chars = num_glyphs, 383 .nbytes = data_size 384 }; 385 386 WriteReplyToClient(pPtr->client, SIZEOF(fsQueryXBitmaps8Reply), &reply); 387 if (client->swapped) 388 SwapLongs((long *)offsets, num_glyphs * 2); 389 WriteToClient(pPtr->client, (num_glyphs * SIZEOF(fsOffset32)), 390 (char *) offsets); 391 WriteToClient(pPtr->client, data_size, (char *) glyph_data); 392 FSfree((char *) offsets); 393 if (freedata) 394 FSfree((char *) glyph_data); 395 } 396 if (pPtr->slept) 397 ClientWakeup(pPtr->client); 398 if (pPtr->pfont->unload_glyphs) /* For rasterizers that want to save memory */ 399 (*pPtr->pfont->unload_glyphs)(pPtr->pfont); 400 FSfree(pPtr->range); 401 FSfree(pPtr); 402 return TRUE; 403} 404 405int 406QueryBitmaps( 407 ClientPtr client, 408 ClientFontPtr cfp, 409 int item_size, 410 fsBitmapFormat format, 411 int nranges, 412 Bool range_flag, 413 pointer range_data) 414{ 415 QBclosurePtr c; 416 fsRange *fixed_range; 417 Bool all_glyphs = FALSE; 418 419 if (item_size == 2 && client->major_version == 1) 420 swap_char2b ((fsChar2b *)range_data, nranges); 421 422 fixed_range = build_range(range_flag, range_data, item_size, 423 &nranges, &all_glyphs, &cfp->font->info); 424 425 if (!fixed_range && !all_glyphs) { 426 SendErrToClient(client, FSBadRange, NULL); 427 return FSBadRange; 428 } 429 c = (QBclosurePtr) FSalloc(sizeof(QBclosureRec)); 430 if (!c) { 431 FSfree(fixed_range); 432 return FSBadAlloc; 433 } 434 c->client = client; 435 c->slept = FALSE; 436 c->pfont = cfp->font; 437 c->flags = (all_glyphs) ? LoadAll : 0; 438 c->nranges = nranges; 439 c->range = fixed_range; 440 c->format = format; 441 442 (void) do_query_bitmaps(client, (pointer) c); 443 return FSSuccess; 444} 445