2 * Copyright 1990 Network Computing Devices
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Network Computing Devices not be used
9 * in advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. Network Computing Devices
11 * makes no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
14 * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
16 * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
17 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
18 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
19 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
20 * OR PERFORMANCE OF THIS SOFTWARE.
22 * Author: Dave Lemke, Network Computing Devices, Inc
32 #include <X11/Xtrans/Xtrans.h>
33 #include <X11/Xpoll.h>
34 #include <X11/fonts/FS.h>
35 #include <X11/fonts/FSproto.h>
36 #include <X11/fonts/fontmisc.h>
37 #include <X11/fonts/fontstruct.h>
38 #include "fservestr.h"
39 #include <X11/fonts/fontutil.h>
42 extern char _fs_glyph_undefined;
43 extern char _fs_glyph_requested;
46 * converts data from font server form to X server form
50 _fs_convert_char_info(fsXCharInfo *src, xCharInfo *dst)
52 dst->ascent = src->ascent;
53 dst->descent = src->descent;
54 dst->leftSideBearing = src->left;
55 dst->rightSideBearing = src->right;
56 dst->characterWidth = src->width;
57 dst->attributes = src->attributes;
61 _fs_init_fontinfo(FSFpePtr conn, FontInfoPtr pfi)
63 if (conn->fsMajorVersion == 1) {
66 pfi->firstCol = pfi->firstRow;
69 pfi->lastCol = pfi->lastRow;
71 pfi->defaultCh = ((pfi->defaultCh >> 8) & 0xff)
72 + ((pfi->defaultCh & 0xff) << 8);
75 if (FontCouldBeTerminal (pfi))
77 pfi->terminalFont = TRUE;
78 pfi->minbounds.ascent = pfi->fontAscent;
79 pfi->minbounds.descent = pfi->fontDescent;
80 pfi->minbounds.leftSideBearing = 0;
81 pfi->minbounds.rightSideBearing = pfi->minbounds.characterWidth;
82 pfi->maxbounds = pfi->minbounds;
85 FontComputeInfoAccelerators (pfi);
89 _fs_convert_props(fsPropInfo *pi, fsPropOffset *po, pointer pd,
96 fsPropOffset local_off;
100 /* stolen from server/include/resource.h */
101 #define BAD_RESOURCE 0xe0000000
103 nprops = pfi->nprops = pi->num_offsets;
106 || nprops > SIZE_MAX/(sizeof(FontPropRec) + sizeof(char)))
109 dprop = malloc(sizeof(FontPropRec) * nprops + sizeof (char) * nprops);
113 is_str = (char *) (dprop + nprops);
115 pfi->isStringProp = is_str;
117 off_adr = (char *)po;
118 for (i = 0; i < nprops; i++, dprop++, is_str++)
120 memcpy(&local_off, off_adr, SIZEOF(fsPropOffset));
121 dprop->name = MakeAtom(&pdc[local_off.name.position],
122 local_off.name.length, 1);
123 if (local_off.type != PropTypeString) {
125 dprop->value = local_off.value.position;
128 dprop->value = (INT32) MakeAtom(&pdc[local_off.value.position],
129 local_off.value.length, 1);
130 if (dprop->value == BAD_RESOURCE)
135 pfi->isStringProp = 0;
139 off_adr += SIZEOF(fsPropOffset);
146 _fs_free_props (FontInfoPtr pfi)
157 _fs_convert_lfwi_reply(FSFpePtr conn, FontInfoPtr pfi,
158 fsListFontsWithXInfoReply *fsrep,
159 fsPropInfo *pi, fsPropOffset *po, pointer pd)
161 fsUnpack_XFontInfoHeader(fsrep, pfi);
162 _fs_init_fontinfo(conn, pfi);
164 if (_fs_convert_props(pi, po, pd, pfi) == -1)
171 #define ENCODING_UNDEFINED(enc) \
172 ((enc)->bits == &_fs_glyph_undefined ? \
174 (access_done = access_done && (enc)->bits != &_fs_glyph_requested, \
177 #define GLYPH_UNDEFINED(loc) ENCODING_UNDEFINED(encoding + (loc))
180 * figures out what glyphs to request
182 * Includes logic to attempt to reduce number of round trips to the font
183 * server: when a glyph is requested, fs_build_range() requests a
184 * 16-glyph range of glyphs that contains the requested glyph. This is
185 * predicated on the belief that using a glyph increases the chances
186 * that nearby glyphs will be used: a good assumption for phonetic
187 * alphabets, but a questionable one for ideographic/pictographic ones.
191 fs_build_range(FontPtr pfont, Bool range_flag, unsigned int count,
192 int item_size, unsigned char *data, int *nranges,
195 FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate);
196 FSFontPtr fsfont = (FSFontPtr) (pfont->fontPrivate);
197 register CharInfoPtr encoding = fsfont->encoding;
198 FontInfoPtr pfi = &(pfont->info);
200 int access_done = TRUE;
202 register unsigned long firstrow, lastrow, firstcol, lastcol;
203 register unsigned long row;
204 register unsigned long col;
205 register unsigned long loc;
207 if (!fsd->glyphs_to_get)
210 firstrow = pfi->firstRow;
211 lastrow = pfi->lastRow;
212 firstcol = pfi->firstCol;
213 lastcol = pfi->lastCol;
215 /* Make sure we have default char */
216 if (fsfont->pDefault && ENCODING_UNDEFINED(fsfont->pDefault))
218 loc = fsfont->pDefault - encoding;
219 row = loc / (lastcol - firstcol + 1) + firstrow;
220 col = loc % (lastcol - firstcol + 1) + firstcol;
222 range.min_char_low = range.max_char_low = col;
223 range.min_char_high = range.max_char_high = row;
225 if ((err = add_range(&range, nranges, ranges, FALSE)) !=
226 Successful) return err;
227 encoding[loc].bits = &_fs_glyph_requested;
231 if (!range_flag && item_size == 1)
233 if (firstrow != 0) return AccessDone;
237 if (col >= firstcol && col <= lastcol &&
238 GLYPH_UNDEFINED(col - firstcol))
243 if (col1 < firstcol) col1 = firstcol;
244 if (col2 > lastcol) col2 = lastcol;
245 /* Collect a 16-glyph neighborhood containing the requested
246 glyph... should in most cases reduce the number of round
247 trips to the font server. */
248 for (col = col1; col <= col2; col++)
250 if (!GLYPH_UNDEFINED(col - firstcol)) continue;
251 range.min_char_low = range.max_char_low = col;
252 range.min_char_high = range.max_char_high = 0;
253 if ((err = add_range(&range, nranges, ranges, FALSE)) !=
254 Successful) return err;
255 encoding[col - firstcol].bits = &_fs_glyph_requested;
263 fsRange fullrange[1];
265 if (range_flag && count == 0)
268 data = (unsigned char *)fullrange;
269 fullrange[0].min_char_high = firstrow;
270 fullrange[0].min_char_low = firstcol;
271 fullrange[0].max_char_high = lastrow;
272 fullrange[0].max_char_low = lastcol;
277 int row1, col1, row2, col2;
278 row1 = row2 = *data++;
279 col1 = col2 = *data++;
293 if (row1 < firstrow) row1 = firstrow;
294 if (row2 > lastrow) row2 = lastrow;
295 if (col1 < firstcol) col1 = firstcol;
296 if (col2 > lastcol) col2 = lastcol;
300 if (row1 < firstrow || row1 > lastrow ||
301 col1 < firstcol || col1 > lastcol)
304 for (row = row1; row <= row2; row++)
306 expand_glyph_range: ;
307 loc = (row - firstrow) * (lastcol + 1 - firstcol) +
309 for (col = col1; col <= col2; col++, loc++)
311 if (GLYPH_UNDEFINED(loc))
314 (((col1 & 0xf) && col1 > firstcol) ||
315 (col2 & 0xf) != 0xf) && (col2 < lastcol))
317 /* If we're loading from a single row, expand
318 range of glyphs loaded to a multiple of
319 a 16-glyph range -- attempt to reduce number
320 of round trips to the font server. */
322 col2 = (col2 & 0xf0) + 15;
323 if (col1 < firstcol) col1 = firstcol;
324 if (col2 > lastcol) col2 = lastcol;
325 goto expand_glyph_range;
327 range.min_char_low = range.max_char_low = col;
328 range.min_char_high = range.max_char_high = row;
329 if ((err = add_range(&range, nranges, ranges, FALSE)) !=
330 Successful) return err;
331 encoding[loc].bits = &_fs_glyph_requested;
344 #undef GLYPH_UNDEFINED
345 #undef ENCODING_UNDEFINED
348 /* _fs_clean_aborted_loadglyphs(): Undoes the changes to the encoding array
349 performed by fs_build_range(); for use if the associated LoadGlyphs
350 requests needs to be cancelled. */
353 _fs_clean_aborted_loadglyphs(FontPtr pfont, int num_expected_ranges,
354 fsRange *expected_ranges)
356 register FSFontPtr fsfont;
359 fsfont = (FSFontPtr) pfont->fontPrivate;
360 if (fsfont->encoding)
362 fsRange full_range[1];
363 if (!num_expected_ranges)
365 full_range[0].min_char_low = pfont->info.firstCol;
366 full_range[0].min_char_high = pfont->info.firstRow;
367 full_range[0].max_char_low = pfont->info.lastCol;
368 full_range[0].max_char_high = pfont->info.lastRow;
369 num_expected_ranges = 1;
370 expected_ranges = full_range;
373 for (i = 0; i < num_expected_ranges; i++)
376 for (row = expected_ranges[i].min_char_high;
377 row <= expected_ranges[i].max_char_high;
380 register CharInfoPtr encoding = fsfont->encoding +
381 ((row - pfont->info.firstRow) *
382 (pfont->info.lastCol -
383 pfont->info.firstCol + 1) +
384 expected_ranges[i].min_char_low -
385 pfont->info.firstCol);
386 for (col = expected_ranges[i].min_char_low;
387 col <= expected_ranges[i].max_char_low;
390 if (encoding->bits == &_fs_glyph_requested)
391 encoding->bits = &_fs_glyph_undefined;
399 _fs_get_glyphs(FontPtr pFont, unsigned long count, unsigned char *chars,
400 FontEncoding charEncoding,
401 unsigned long *glyphCount, /* RETURN */
402 CharInfoPtr *glyphs) /* RETURN */
405 unsigned int firstCol;
406 register unsigned int numCols;
407 unsigned int firstRow;
408 unsigned int numRows;
409 CharInfoPtr *glyphsBase;
410 register unsigned int c;
411 register CharInfoPtr pci;
413 CharInfoPtr encoding;
414 CharInfoPtr pDefault;
415 FSFontDataPtr fsd = (FSFontDataPtr) pFont->fpePrivate;
416 int err = Successful;
418 fsdata = (FSFontPtr) pFont->fontPrivate;
419 encoding = fsdata->encoding;
420 pDefault = fsdata->pDefault;
421 firstCol = pFont->info.firstCol;
422 numCols = pFont->info.lastCol - firstCol + 1;
425 /* In this age of glyph caching, any glyphs gotten through this
426 procedure should already be loaded. If they are not, we are
427 dealing with someone (perhaps a ddx driver optimizing a font)
428 that doesn't understand the finer points of glyph caching. The
429 CHECK_ENCODING macro checks for this condition... if found, it
430 calls fs_load_all_glyphs(), which corrects it. Since the caller
431 of this code will not know how to handle a return value of
432 Suspended, the fs_load_all_glyphs() procedure will block and
433 freeze the server until the load operation is done. Moral: the
434 glyphCachingMode flag really must indicate the capabilities of
437 #define CHECK_ENCODING(cnum) \
438 ( pci = encoding + (cnum), \
439 fsd->glyphs_to_get ? \
440 ( pci->bits == &_fs_glyph_undefined || pci->bits == &_fs_glyph_requested ? \
441 ((err = fs_load_all_glyphs(pFont)), pci) : \
445 switch (charEncoding) {
449 if (pFont->info.firstRow > 0)
451 if (pFont->info.allExist && pDefault) {
452 while (err == Successful && count--) {
453 c = (*chars++) - firstCol;
455 *glyphs++ = CHECK_ENCODING(c);
457 *glyphs++ = pDefault;
460 while (err == Successful && count--) {
461 c = (*chars++) - firstCol;
462 if (c < numCols && CHECK_ENCODING(c)->bits)
465 *glyphs++ = pDefault;
470 if (pFont->info.allExist && pDefault) {
471 while (err == Successful && count--) {
473 c = (c | *chars++) - firstCol;
475 *glyphs++ = CHECK_ENCODING(c);
477 *glyphs++ = pDefault;
480 while (err == Successful && count--) {
482 c = (c | *chars++) - firstCol;
483 if (c < numCols && CHECK_ENCODING(c)->bits)
486 *glyphs++ = pDefault;
492 firstRow = pFont->info.firstRow;
493 numRows = pFont->info.lastRow - firstRow + 1;
494 while (err == Successful && count--) {
495 r = (*chars++) - firstRow;
496 c = (*chars++) - firstCol;
497 if (r < numRows && c < numCols &&
498 CHECK_ENCODING(r * numCols + c)->bits)
501 *glyphs++ = pDefault;
505 *glyphCount = glyphs - glyphsBase;
511 _fs_get_metrics(FontPtr pFont, unsigned long count, unsigned char *chars,
512 FontEncoding charEncoding,
513 unsigned long *glyphCount, /* RETURN */
514 xCharInfo **glyphs) /* RETURN */
517 unsigned int firstCol;
518 register unsigned int numCols;
519 unsigned int firstRow;
520 unsigned int numRows;
521 xCharInfo **glyphsBase;
522 register unsigned int c;
524 CharInfoPtr encoding;
525 CharInfoPtr pDefault;
527 fsdata = (FSFontPtr) pFont->fontPrivate;
528 encoding = fsdata->inkMetrics;
529 pDefault = fsdata->pDefault;
530 /* convert default bitmap metric to default ink metric */
532 pDefault = encoding + (pDefault - fsdata->encoding);
533 firstCol = pFont->info.firstCol;
534 numCols = pFont->info.lastCol - firstCol + 1;
538 /* XXX - this should be much smarter */
539 /* make sure the glyphs are there */
540 switch (charEncoding) {
544 if (pFont->info.firstRow > 0)
546 if (pFont->info.allExist && pDefault) {
548 c = (*chars++) - firstCol;
550 *glyphs++ = (xCharInfo *)&encoding[c];
552 *glyphs++ = (xCharInfo *)pDefault;
556 c = (*chars++) - firstCol;
558 *glyphs++ = (xCharInfo *)(encoding + c);
560 *glyphs++ = (xCharInfo *)pDefault;
565 if (pFont->info.allExist && pDefault) {
568 c = (c | *chars++) - firstCol;
570 *glyphs++ = (xCharInfo *)(encoding + c);
572 *glyphs++ = (xCharInfo *)pDefault;
577 c = (c | *chars++) - firstCol;
579 *glyphs++ = (xCharInfo *)(encoding + c);
581 *glyphs++ = (xCharInfo *)pDefault;
587 firstRow = pFont->info.firstRow;
588 numRows = pFont->info.lastRow - firstRow + 1;
590 r = (*chars++) - firstRow;
591 c = (*chars++) - firstCol;
592 if (r < numRows && c < numCols)
593 *glyphs++ = (xCharInfo *)(encoding + (r * numCols + c));
595 *glyphs++ = (xCharInfo *)pDefault;
599 *glyphCount = glyphs - glyphsBase;
605 _fs_unload_font(FontPtr pfont)
607 FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate;
608 FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate;
609 CharInfoPtr encoding = fsdata->encoding;
613 * fsdata points at FSFontRec, FSFontDataRec and name
618 while ((glyphs = fsdata->glyphs))
620 fsdata->glyphs = glyphs->next;
624 /* XXX we may get called after the resource DB has been cleaned out */
625 if (find_old_font(fsd->fontid))
626 DeleteFontClientID (fsd->fontid);
628 _fs_free_props (&pfont->info);
632 DestroyFontRec(pfont);
636 fs_create_font (FontPathElementPtr fpe,
639 fsBitmapFormat format,
640 fsBitmapFormatMask fmask)
645 int bit, byte, scan, glyph;
647 pfont = CreateFontRec ();
650 fsfont = malloc (sizeof (FSFontRec) + sizeof (FSFontDataRec) + namelen + 1);
653 DestroyFontRec (pfont);
656 fsd = (FSFontDataPtr) (fsfont + 1);
657 bzero((char *) fsfont, sizeof(FSFontRec));
658 bzero((char *) fsd, sizeof(FSFontDataRec));
661 pfont->fontPrivate = (pointer) fsfont;
662 pfont->fpePrivate = (pointer) fsd;
664 /* These font components will be needed in packGlyphs */
665 CheckFSFormat(format, BitmapFormatMaskBit |
666 BitmapFormatMaskByte |
667 BitmapFormatMaskScanLineUnit |
668 BitmapFormatMaskScanLinePad,
674 pfont->format = format;
678 pfont->glyph = glyph;
680 pfont->info.nprops = 0;
681 pfont->info.props = 0;
682 pfont->info.isStringProp = 0;
684 /* set font function pointers */
685 pfont->get_glyphs = _fs_get_glyphs;
686 pfont->get_metrics = _fs_get_metrics;
687 pfont->unload_font = _fs_unload_font;
688 pfont->unload_glyphs = NULL;
690 /* set the FPE private information */
691 fsd->format = format;
693 fsd->name = (char *) (fsd + 1);
694 memcpy (fsd->name, name, namelen);
695 fsd->name[namelen] = '\0';
696 fsd->fontid = GetNewFontClientID ();
699 if (!StoreFontClientFont(pfont, fsd->fontid))
702 DestroyFontRec (pfont);
710 fs_alloc_glyphs (FontPtr pFont, int size)
713 FSFontPtr fsfont = (FSFontPtr) pFont->fontPrivate;
715 glyphs = malloc (sizeof (FSGlyphRec) + size);
716 glyphs->next = fsfont->glyphs;
717 fsfont->glyphs = glyphs;
718 return (pointer) (glyphs + 1);