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