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