1 /* $XConsortium: fsconvert.c,v 1.17 94/02/14 17:47:35 gildea Exp $ */
3 * Copyright 1990 Network Computing Devices
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of Network Computing Devices not be used
10 * in advertising or publicity pertaining to distribution of the software
11 * without specific, written prior permission. Network Computing Devices
12 * makes no representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied warranty.
15 * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
17 * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
18 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
19 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
20 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
21 * OR PERFORMANCE OF THIS SOFTWARE.
23 * Author: Dave Lemke, Network Computing Devices, Inc
33 #include "fontstruct.h"
34 #include "fservestr.h"
36 extern char _fs_glyph_undefined;
37 extern char _fs_glyph_requested;
38 extern char _fs_glyph_zero_length;
40 extern int _fs_load_glyphs();
43 * converts data from font server form to X server form
47 _fs_convert_char_info(src, dst)
51 dst->ascent = src->ascent;
52 dst->descent = src->descent;
53 dst->leftSideBearing = src->left;
54 dst->rightSideBearing = src->right;
55 dst->characterWidth = src->width;
56 dst->attributes = src->attributes;
60 _fs_init_fontinfo(conn, pfi)
64 if (conn->fsMajorVersion == 1) {
67 pfi->firstCol = pfi->firstRow;
70 pfi->lastCol = pfi->lastRow;
72 pfi->defaultCh = (pfi->defaultCh >> 8) & 0xff
73 + (pfi->defaultCh & 0xff) << 8;
76 if (FontCouldBeTerminal (pfi))
78 pfi->terminalFont = TRUE;
79 pfi->minbounds.ascent = pfi->fontAscent;
80 pfi->minbounds.descent = pfi->fontDescent;
81 pfi->minbounds.leftSideBearing = 0;
82 pfi->minbounds.rightSideBearing = pfi->minbounds.characterWidth;
83 pfi->maxbounds = pfi->minbounds;
86 FontComputeInfoAccelerators (pfi);
90 _fs_convert_props(pi, po, pd, pfi)
100 fsPropOffset local_off;
103 /* stolen from server/include/resource.h */
104 #define BAD_RESOURCE 0xe0000000
106 nprops = pfi->nprops = pi->num_offsets;
108 dprop = (FontPropPtr) xalloc(sizeof(FontPropRec) * nprops);
109 is_str = (char *) xalloc(sizeof(char) * nprops);
110 if (!dprop || !is_str) {
116 pfi->isStringProp = is_str;
118 off_adr = (char *)po;
119 for (i = 0; i < nprops; i++, dprop++, is_str++) {
120 memcpy(&local_off, off_adr, SIZEOF(fsPropOffset));
121 dprop->name = MakeAtom(&pd[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(&pd[local_off.value.position],
129 local_off.value.length, 1);
130 if (dprop->value == BAD_RESOURCE)
133 xfree (pfi->isStringProp);
135 pfi->isStringProp = 0;
139 off_adr += SIZEOF(fsPropOffset);
146 _fs_convert_lfwi_reply(conn, pfi, fsrep, pi, po, pd)
149 fsListFontsWithXInfoReply *fsrep;
154 fsUnpack_XFontInfoHeader(fsrep, pfi);
155 _fs_init_fontinfo(conn, pfi);
157 if (_fs_convert_props(pi, po, pd, pfi) == -1)
164 #define ENCODING_UNDEFINED(enc) \
165 ((enc)->bits == &_fs_glyph_undefined ? \
167 (access_done = access_done && (enc)->bits != &_fs_glyph_requested, \
170 #define GLYPH_UNDEFINED(loc) ENCODING_UNDEFINED(encoding + (loc))
173 * figures out what glyphs to request
175 * Includes logic to attempt to reduce number of round trips to the font
176 * server: when a glyph is requested, fs_build_range() requests a
177 * 16-glyph range of glyphs that contains the requested glyph. This is
178 * predicated on the belief that using a glyph increases the chances
179 * that nearby glyphs will be used: a good assumption for phonetic
180 * alphabets, but a questionable one for ideographic/pictographic ones.
184 fs_build_range(pfont, range_flag, count, item_size, data, nranges, ranges)
187 register unsigned int count;
189 register unsigned char *data;
193 FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate);
194 FSFontPtr fsfont = (FSFontPtr) (pfont->fontPrivate);
195 register CharInfoPtr encoding = fsfont->encoding;
196 FontInfoPtr pfi = &(pfont->info);
198 int access_done = TRUE;
200 register unsigned long firstrow, lastrow, firstcol, lastcol;
201 register unsigned long row;
202 register unsigned long col;
203 register unsigned long loc;
205 if (!fsd->glyphs_to_get)
208 firstrow = pfi->firstRow;
209 lastrow = pfi->lastRow;
210 firstcol = pfi->firstCol;
211 lastcol = pfi->lastCol;
213 /* Make sure we have default char */
214 if (fsfont->pDefault && ENCODING_UNDEFINED(fsfont->pDefault))
216 loc = fsfont->pDefault - encoding;
217 row = loc / (lastcol - firstcol + 1) + firstrow;
218 col = loc % (lastcol - firstcol + 1) + firstcol;
220 range.min_char_low = range.max_char_low = col;
221 range.min_char_high = range.max_char_high = row;
223 if ((err = add_range(&range, nranges, ranges, FALSE)) !=
224 Successful) return err;
225 encoding[loc].bits = &_fs_glyph_requested;
229 if (!range_flag && item_size == 1)
231 if (firstrow != 0) return AccessDone;
235 if (col >= firstcol && col <= lastcol &&
236 GLYPH_UNDEFINED(col - firstcol))
241 if (col1 < firstcol) col1 = firstcol;
242 if (col2 > lastcol) col2 = lastcol;
243 /* Collect a 16-glyph neighborhood containing the requested
244 glyph... should in most cases reduce the number of round
245 trips to the font server. */
246 for (col = col1; col <= col2; col++)
248 if (!GLYPH_UNDEFINED(col - firstcol)) continue;
249 range.min_char_low = range.max_char_low = col;
250 range.min_char_high = range.max_char_high = 0;
251 if ((err = add_range(&range, nranges, ranges, FALSE)) !=
252 Successful) return err;
253 encoding[col - firstcol].bits = &_fs_glyph_requested;
261 fsRange fullrange[1];
263 if (range_flag && count == 0)
266 data = (unsigned char *)fullrange;
267 fullrange[0].min_char_high = firstrow;
268 fullrange[0].min_char_low = firstcol;
269 fullrange[0].max_char_high = lastrow;
270 fullrange[0].max_char_low = lastcol;
275 int row1, col1, row2, col2;
276 row1 = row2 = *data++;
277 col1 = col2 = *data++;
291 if (row1 < firstrow) row1 = firstrow;
292 if (row2 > lastrow) row2 = lastrow;
293 if (col1 < firstcol) col1 = firstcol;
294 if (col2 > lastcol) col2 = lastcol;
298 if (row1 < firstrow || row1 > lastrow ||
299 col1 < firstcol || col1 > lastcol)
302 for (row = row1; row <= row2; row++)
304 expand_glyph_range: ;
305 loc = (row - firstrow) * (lastcol + 1 - firstcol) +
307 for (col = col1; col <= col2; col++, loc++)
309 if (GLYPH_UNDEFINED(loc))
312 ((col1 & 0xf) && col1 > firstcol ||
313 (col2 & 0xf) != 0xf) && col2 < lastcol)
315 /* If we're loading from a single row, expand
316 range of glyphs loaded to a multiple of
317 a 16-glyph range -- attempt to reduce number
318 of round trips to the font server. */
320 col2 = (col2 & 0xf0) + 15;
321 if (col1 < firstcol) col1 = firstcol;
322 if (col2 > lastcol) col2 = lastcol;
323 goto expand_glyph_range;
325 range.min_char_low = range.max_char_low = col;
326 range.min_char_high = range.max_char_high = row;
327 if ((err = add_range(&range, nranges, ranges, FALSE)) !=
328 Successful) return err;
329 encoding[loc].bits = &_fs_glyph_requested;
342 #undef GLYPH_UNDEFINED
343 #undef ENCODING_UNDEFINED
346 /* _fs_clean_aborted_loadglyphs(): Undoes the changes to the encoding array
347 performed by fs_build_range(); for use if the associated LoadGlyphs
348 requests needs to be cancelled. */
350 _fs_clean_aborted_loadglyphs(pfont, num_expected_ranges, expected_ranges)
352 int num_expected_ranges;
353 fsRange *expected_ranges;
355 register FSFontPtr fsfont;
356 register FSFontDataRec *fsd;
359 fsfont = (FSFontPtr) pfont->fontPrivate;
360 fsd = (FSFontDataRec *) pfont->fpePrivate;
361 if (fsfont->encoding)
363 fsRange full_range[1];
364 if (!num_expected_ranges)
366 full_range[0].min_char_low = pfont->info.firstCol;
367 full_range[0].min_char_high = pfont->info.firstRow;
368 full_range[0].max_char_low = pfont->info.lastCol;
369 full_range[0].max_char_high = pfont->info.lastRow;
370 num_expected_ranges = 1;
371 expected_ranges = full_range;
374 for (i = 0; i < num_expected_ranges; i++)
377 for (row = expected_ranges[i].min_char_high;
378 row <= expected_ranges[i].max_char_high;
381 register CharInfoPtr encoding = fsfont->encoding +
382 ((row - pfont->info.firstRow) *
383 (pfont->info.lastCol -
384 pfont->info.firstCol + 1) +
385 expected_ranges[i].min_char_low -
386 pfont->info.firstCol);
387 for (col = expected_ranges[i].min_char_low;
388 col <= expected_ranges[i].max_char_low;
391 if (encoding->bits == &_fs_glyph_requested)
392 encoding->bits = &_fs_glyph_undefined;
401 * figures out what extents to request
402 * this is where lots of extra
403 * smarts wants to live
407 _fs_check_extents(pfont, flags, nranges, range, blockrec)
412 FSBlockDataPtr blockrec;
414 /* XXX -- either fill in the requested info if we have it somewhere
415 * and return AccessDone, or else return Successful
421 * figures out what glyphs to request
422 * this is where lots of extra
423 * smarts wants to live
427 _fs_check_bitmaps(pfont, format, flags, nranges, range, blockrec)
429 fsBitmapFormat format;
433 FSBlockDataPtr blockrec;
435 /* XXX -- either fill in the requested info if we have it somewhere
436 * and return AccessDone, or else return Successful
442 _fs_get_glyphs(pFont, count, chars, charEncoding, glyphCount, glyphs)
445 register unsigned char *chars;
446 FontEncoding charEncoding;
447 unsigned long *glyphCount; /* RETURN */
448 CharInfoPtr *glyphs; /* RETURN */
451 unsigned int firstCol;
452 register unsigned int numCols;
453 unsigned int firstRow;
454 unsigned int numRows;
455 CharInfoPtr *glyphsBase;
456 register unsigned int c;
457 register CharInfoPtr pci;
459 CharInfoPtr encoding;
460 CharInfoPtr pDefault;
461 FSFontDataPtr fsd = (FSFontDataPtr) pFont->fpePrivate;
463 int err = Successful;
465 fsdata = (FSFontPtr) pFont->fontPrivate;
466 encoding = fsdata->encoding;
467 pDefault = fsdata->pDefault;
468 firstCol = pFont->info.firstCol;
469 numCols = pFont->info.lastCol - firstCol + 1;
473 if (charEncoding == Linear8Bit || charEncoding == TwoD8Bit)
478 /* In this age of glyph caching, any glyphs gotten through this
479 procedure should already be loaded. If they are not, we are
480 dealing with someone (perhaps a ddx driver optimizing a font)
481 that doesn't understand the finer points of glyph caching. The
482 CHECK_ENCODING macro checks for this condition... if found, it
483 calls fs_load_all_glyphs(), which corrects it. Since the caller
484 of this code will not know how to handle a return value of
485 Suspended, the fs_load_all_glyphs() procedure will block and
486 freeze the server until the load operation is done. Moral: the
487 glyphCachingMode flag really must indicate the capabilities of
490 #define CHECK_ENCODING(cnum) \
491 ( pci = encoding + (cnum), \
492 fsd->glyphs_to_get ? \
493 ( pci->bits == &_fs_glyph_undefined || pci->bits == &_fs_glyph_requested ? \
494 ((err = fs_load_all_glyphs(pFont)), pci) : \
498 switch (charEncoding) {
502 if (pFont->info.firstRow > 0)
504 if (pFont->info.allExist && pDefault) {
505 while (err == Successful && count--) {
506 c = (*chars++) - firstCol;
508 *glyphs++ = CHECK_ENCODING(c);
510 *glyphs++ = pDefault;
513 while (err == Successful && count--) {
514 c = (*chars++) - firstCol;
515 if (c < numCols && CHECK_ENCODING(c)->bits)
518 *glyphs++ = pDefault;
523 if (pFont->info.allExist && pDefault) {
524 while (err == Successful && count--) {
526 c = (c | *chars++) - firstCol;
528 *glyphs++ = CHECK_ENCODING(c);
530 *glyphs++ = pDefault;
533 while (err == Successful && count--) {
535 c = (c | *chars++) - firstCol;
536 if (c < numCols && CHECK_ENCODING(c)->bits)
539 *glyphs++ = pDefault;
545 firstRow = pFont->info.firstRow;
546 numRows = pFont->info.lastRow - firstRow + 1;
547 while (err == Successful && count--) {
548 r = (*chars++) - firstRow;
549 c = (*chars++) - firstCol;
550 if (r < numRows && c < numCols &&
551 CHECK_ENCODING(r * numCols + c)->bits)
554 *glyphs++ = pDefault;
558 *glyphCount = glyphs - glyphsBase;
564 _fs_get_metrics(pFont, count, chars, charEncoding, glyphCount, glyphs)
567 register unsigned char *chars;
568 FontEncoding charEncoding;
569 unsigned long *glyphCount; /* RETURN */
570 xCharInfo **glyphs; /* RETURN */
573 unsigned int firstCol;
574 register unsigned int numCols;
575 unsigned int firstRow;
576 unsigned int numRows;
577 xCharInfo **glyphsBase;
578 register unsigned int c;
580 CharInfoPtr encoding;
581 CharInfoPtr pDefault;
582 FSFontDataPtr fsd = (FSFontDataPtr) pFont->fpePrivate;
584 int err = Successful;
586 fsdata = (FSFontPtr) pFont->fontPrivate;
587 encoding = fsdata->inkMetrics;
588 pDefault = fsdata->pDefault;
589 firstCol = pFont->info.firstCol;
590 numCols = pFont->info.lastCol - firstCol + 1;
594 /* XXX - this should be much smarter */
595 /* make sure the glyphs are there */
596 if (charEncoding == Linear8Bit || charEncoding == TwoD8Bit)
601 switch (charEncoding) {
605 if (pFont->info.firstRow > 0)
607 if (pFont->info.allExist && pDefault) {
609 c = (*chars++) - firstCol;
611 *glyphs++ = (xCharInfo *)&encoding[c];
613 *glyphs++ = (xCharInfo *)pDefault;
617 c = (*chars++) - firstCol;
619 *glyphs++ = (xCharInfo *)(encoding + c);
621 *glyphs++ = (xCharInfo *)pDefault;
626 if (pFont->info.allExist && pDefault) {
629 c = (c | *chars++) - firstCol;
631 *glyphs++ = (xCharInfo *)(encoding + c);
633 *glyphs++ = (xCharInfo *)pDefault;
638 c = (c | *chars++) - firstCol;
640 *glyphs++ = (xCharInfo *)(encoding + c);
642 *glyphs++ = (xCharInfo *)pDefault;
648 firstRow = pFont->info.firstRow;
649 numRows = pFont->info.lastRow - firstRow + 1;
651 r = (*chars++) - firstRow;
652 c = (*chars++) - firstCol;
653 if (r < numRows && c < numCols)
654 *glyphs++ = (xCharInfo *)(encoding + (r * numCols + c));
656 *glyphs++ = (xCharInfo *)pDefault;
660 *glyphCount = glyphs - glyphsBase;
666 _fs_unload_font(pfont)
669 FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate;
671 if (fsdata->encoding)
674 register CharInfoPtr encoding = fsdata->encoding;
675 FontInfoPtr pfi = &pfont->info;
676 for (i = (pfi->lastCol - pfi->firstCol + 1) *
677 (pfi->lastRow - pfi->firstRow + 1);
681 if (encoding->bits &&
682 encoding->bits != &_fs_glyph_undefined &&
683 encoding->bits != &_fs_glyph_requested &&
684 encoding->bits != &_fs_glyph_zero_length)
685 xfree(encoding->bits);
688 xfree(fsdata->encoding);
691 pfont->fontPrivate = 0;
698 /* set font function pointers */
699 pfont->get_glyphs = _fs_get_glyphs;
700 pfont->get_metrics = _fs_get_metrics;
701 pfont->unload_font = _fs_unload_font;
702 pfont->unload_glyphs = (void (*)())0;