fontinfo.c revision 40c5823b
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 *) 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 */ 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 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 348static Bool 349do_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 403int 404QueryBitmaps( 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