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