]> git.sesse.net Git - rdpsrv/blob - Xserver/lib/font/fc/fsconvert.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / lib / font / fc / fsconvert.c
1 /* $XConsortium: fsconvert.c,v 1.17 94/02/14 17:47:35 gildea Exp $ */
2 /*
3  * Copyright 1990 Network Computing Devices
4  *
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.
14  *
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.
22  *
23  * Author:      Dave Lemke, Network Computing Devices, Inc
24  */
25 /*
26  * FS data conversion
27  */
28
29 #include        <X11/X.h>
30 #include        "FS.h"
31 #include        "FSproto.h"
32 #include        "fontmisc.h"
33 #include        "fontstruct.h"
34 #include        "fservestr.h"
35
36 extern char _fs_glyph_undefined;
37 extern char _fs_glyph_requested;
38 extern char _fs_glyph_zero_length;
39
40 extern int _fs_load_glyphs();
41
42 /*
43  * converts data from font server form to X server form
44  */
45
46 void
47 _fs_convert_char_info(src, dst)
48     fsXCharInfo *src;
49     xCharInfo *dst;
50 {
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;
57 }
58
59 void
60 _fs_init_fontinfo(conn, pfi)
61     FSFpePtr    conn;
62     FontInfoPtr pfi;
63 {
64     if (conn->fsMajorVersion == 1) {
65         unsigned short n;
66         n = pfi->firstCol;
67         pfi->firstCol = pfi->firstRow;
68         pfi->firstRow = n;
69         n = pfi->lastCol;
70         pfi->lastCol = pfi->lastRow;
71         pfi->lastRow = n;
72         pfi->defaultCh = (pfi->defaultCh >> 8) & 0xff
73                            + (pfi->defaultCh & 0xff) << 8;
74     }
75
76     if (FontCouldBeTerminal (pfi))
77     {
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;
84     }
85
86     FontComputeInfoAccelerators (pfi);
87 }
88
89 int
90 _fs_convert_props(pi, po, pd, pfi)
91     fsPropInfo *pi;
92     fsPropOffset *po;
93     pointer     pd;
94     FontInfoPtr pfi;
95 {
96     FontPropPtr dprop;
97     int         i,
98                 nprops;
99     char       *is_str;
100     fsPropOffset local_off;
101     char *off_adr;
102
103 /* stolen from server/include/resource.h */
104 #define BAD_RESOURCE 0xe0000000
105
106     nprops = pfi->nprops = pi->num_offsets;
107
108     dprop = (FontPropPtr) xalloc(sizeof(FontPropRec) * nprops);
109     is_str = (char *) xalloc(sizeof(char) * nprops);
110     if (!dprop || !is_str) {
111         xfree(is_str);
112         xfree(dprop);
113         return -1;
114     }
115     pfi->props = dprop;
116     pfi->isStringProp = is_str;
117
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) {
124             *is_str = FALSE;
125             dprop->value = local_off.value.position;
126         } else {
127             *is_str = TRUE;
128             dprop->value = (INT32) MakeAtom(&pd[local_off.value.position],
129                                             local_off.value.length, 1);
130             if (dprop->value == BAD_RESOURCE)
131             {
132                 xfree (pfi->props);
133                 xfree (pfi->isStringProp);
134                 pfi->props = 0;
135                 pfi->isStringProp = 0;
136                 return -1;
137             }
138         }
139         off_adr += SIZEOF(fsPropOffset);
140     }
141
142     return nprops;
143 }
144
145 int
146 _fs_convert_lfwi_reply(conn, pfi, fsrep, pi, po, pd)
147     FSFpePtr    conn;
148     FontInfoPtr pfi;
149     fsListFontsWithXInfoReply *fsrep;
150     fsPropInfo *pi;
151     fsPropOffset *po;
152     pointer     pd;
153 {
154     fsUnpack_XFontInfoHeader(fsrep, pfi);
155     _fs_init_fontinfo(conn, pfi);
156
157     if (_fs_convert_props(pi, po, pd, pfi) == -1)
158         return AllocError;
159
160     return Successful;
161 }
162
163
164 #define ENCODING_UNDEFINED(enc) \
165         ((enc)->bits == &_fs_glyph_undefined ? \
166          TRUE : \
167          (access_done = access_done && (enc)->bits != &_fs_glyph_requested, \
168           FALSE))
169
170 #define GLYPH_UNDEFINED(loc) ENCODING_UNDEFINED(encoding + (loc))
171
172 /*
173  * figures out what glyphs to request
174  *
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.
181  */
182 /* ARGSUSED */
183 int
184 fs_build_range(pfont, range_flag, count, item_size, data, nranges, ranges)
185     FontPtr     pfont;
186     Bool        range_flag;
187     register unsigned int count;
188     int         item_size;
189     register unsigned char *data;
190     int        *nranges;
191     fsRange   **ranges;
192 {
193     FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate);
194     FSFontPtr fsfont = (FSFontPtr) (pfont->fontPrivate);
195     register CharInfoPtr encoding = fsfont->encoding;
196     FontInfoPtr pfi = &(pfont->info);
197     fsRange     range;
198     int         access_done = TRUE;
199     int         err;
200     register unsigned long firstrow, lastrow, firstcol, lastcol;
201     register unsigned long row;
202     register unsigned long col;
203     register unsigned long loc;
204
205     if (!fsd->glyphs_to_get)
206         return AccessDone;
207
208     firstrow = pfi->firstRow;
209     lastrow = pfi->lastRow;
210     firstcol = pfi->firstCol;
211     lastcol = pfi->lastCol;
212
213     /* Make sure we have default char */
214     if (fsfont->pDefault && ENCODING_UNDEFINED(fsfont->pDefault))
215     {
216         loc = fsfont->pDefault - encoding;
217         row = loc / (lastcol - firstcol + 1) + firstrow;
218         col = loc % (lastcol - firstcol + 1) + firstcol;
219
220         range.min_char_low = range.max_char_low = col;
221         range.min_char_high = range.max_char_high = row;
222
223         if ((err = add_range(&range, nranges, ranges, FALSE)) !=
224             Successful) return err;
225         encoding[loc].bits = &_fs_glyph_requested;
226         access_done = FALSE;
227     }
228
229     if (!range_flag && item_size == 1)
230     {
231         if (firstrow != 0) return AccessDone;
232         while (count--)
233         {
234             col = *data++;
235             if (col >= firstcol && col <= lastcol &&
236                 GLYPH_UNDEFINED(col - firstcol))
237             {
238                 int col1, col2;
239                 col1 = col & 0xf0;
240                 col2 = col1 + 15;
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++)
247                 {
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;
254                     access_done = FALSE;
255                 }
256             }
257         }
258     }
259     else
260     {
261         fsRange fullrange[1];
262
263         if (range_flag && count == 0)
264         {
265             count = 2;
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;
271         }
272
273         while (count--)
274         {
275             int row1, col1, row2, col2;
276             row1 = row2 = *data++;
277             col1 = col2 = *data++;
278             if (range_flag)
279             {
280                 if (count)
281                 {
282                     row2 = *data++;
283                     col2 = *data++;
284                     count--;
285                 }
286                 else
287                 {
288                     row2 = lastrow;
289                     col2 = lastcol;
290                 }
291                 if (row1 < firstrow) row1 = firstrow;
292                 if (row2 > lastrow) row2 = lastrow;
293                 if (col1 < firstcol) col1 = firstcol;
294                 if (col2 > lastcol) col2 = lastcol;
295             }
296             else
297             {
298                 if (row1 < firstrow || row1 > lastrow ||
299                     col1 < firstcol || col1 > lastcol)
300                     continue;
301             }
302             for (row = row1; row <= row2; row++)
303             {
304             expand_glyph_range: ;
305                 loc = (row - firstrow) * (lastcol + 1 - firstcol) +
306                       (col1 - firstcol);
307                 for (col = col1; col <= col2; col++, loc++)
308                 {
309                     if (GLYPH_UNDEFINED(loc))
310                     {
311                         if (row1 == row2 &&
312                             ((col1 & 0xf) && col1 > firstcol ||
313                              (col2 & 0xf) != 0xf) && col2 < lastcol)
314                         {
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. */
319                             col1 &= 0xf0;
320                             col2 = (col2 & 0xf0) + 15;
321                             if (col1 < firstcol) col1 = firstcol;
322                             if (col2 > lastcol) col2 = lastcol;
323                             goto expand_glyph_range;
324                         }
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;
330                         access_done = FALSE;
331                     }
332                 }
333             }
334         }
335     }
336
337     return access_done ?
338            AccessDone :
339            Successful;
340 }
341
342 #undef GLYPH_UNDEFINED
343 #undef ENCODING_UNDEFINED
344
345
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. */
349
350 _fs_clean_aborted_loadglyphs(pfont, num_expected_ranges, expected_ranges)
351     FontPtr pfont;
352     int num_expected_ranges;
353     fsRange *expected_ranges;
354 {
355     register FSFontPtr fsfont;
356     register FSFontDataRec *fsd;
357     register int i;
358
359     fsfont = (FSFontPtr) pfont->fontPrivate;
360     fsd = (FSFontDataRec *) pfont->fpePrivate;
361     if (fsfont->encoding)
362     {
363         fsRange full_range[1];
364         if (!num_expected_ranges)
365         {
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;
372         }
373
374         for (i = 0; i < num_expected_ranges; i++)
375         {
376             int row, col;
377             for (row = expected_ranges[i].min_char_high;
378                  row <= expected_ranges[i].max_char_high;
379                  row++)
380             {
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;
389                      encoding++, col++)
390                 {
391                     if (encoding->bits == &_fs_glyph_requested)
392                         encoding->bits = &_fs_glyph_undefined;
393                 }
394             }
395         }
396     }
397 }
398
399
400 /*
401  * figures out what extents to request
402  * this is where lots of extra
403  * smarts wants to live
404  */
405 /* ARGSUSED */
406 int
407 _fs_check_extents(pfont, flags, nranges, range, blockrec)
408     FontPtr     pfont;
409     Mask        flags;
410     int         nranges;
411     fsRange    *range;
412     FSBlockDataPtr blockrec;
413 {
414 /* XXX -- either fill in the requested info if we have it somewhere
415  * and return AccessDone, or else return Successful
416  */
417     return Successful;
418 }
419
420 /*
421  * figures out what glyphs to request
422  * this is where lots of extra
423  * smarts wants to live
424  */
425 /* ARGSUSED */
426 int
427 _fs_check_bitmaps(pfont, format, flags, nranges, range, blockrec)
428     FontPtr     pfont;
429     fsBitmapFormat format;
430     Mask        flags;
431     int         nranges;
432     fsRange    *range;
433     FSBlockDataPtr blockrec;
434 {
435 /* XXX -- either fill in the requested info if we have it somewhere
436  * and return AccessDone, or else return Successful
437  */
438     return Successful;
439 }
440
441 int
442 _fs_get_glyphs(pFont, count, chars, charEncoding, glyphCount, glyphs)
443     FontPtr     pFont;
444     unsigned long count;
445     register unsigned char *chars;
446     FontEncoding charEncoding;
447     unsigned long *glyphCount;  /* RETURN */
448     CharInfoPtr *glyphs;        /* RETURN */
449 {
450     FSFontPtr   fsdata;
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;
458     unsigned int r;
459     CharInfoPtr encoding;
460     CharInfoPtr pDefault;
461     FSFontDataPtr fsd = (FSFontDataPtr) pFont->fpePrivate;
462     int         itemSize;
463     int         err = Successful;
464
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;
470     glyphsBase = glyphs;
471
472
473     if (charEncoding == Linear8Bit || charEncoding == TwoD8Bit)
474         itemSize = 1;
475     else
476         itemSize = 2;
477
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
488        the ddx drivers.  */
489
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) : \
495         pci ) : \
496       pci )
497
498     switch (charEncoding) {
499
500     case Linear8Bit:
501     case TwoD8Bit:
502         if (pFont->info.firstRow > 0)
503             break;
504         if (pFont->info.allExist && pDefault) {
505             while (err == Successful && count--) {
506                 c = (*chars++) - firstCol;
507                 if (c < numCols)
508                     *glyphs++ = CHECK_ENCODING(c);
509                 else
510                     *glyphs++ = pDefault;
511             }
512         } else {
513             while (err == Successful && count--) {
514                 c = (*chars++) - firstCol;
515                 if (c < numCols && CHECK_ENCODING(c)->bits)
516                     *glyphs++ = pci;
517                 else if (pDefault)
518                     *glyphs++ = pDefault;
519             }
520         }
521         break;
522     case Linear16Bit:
523         if (pFont->info.allExist && pDefault) {
524             while (err == Successful && count--) {
525                 c = *chars++ << 8;
526                 c = (c | *chars++) - firstCol;
527                 if (c < numCols)
528                     *glyphs++ = CHECK_ENCODING(c);
529                 else
530                     *glyphs++ = pDefault;
531             }
532         } else {
533             while (err == Successful && count--) {
534                 c = *chars++ << 8;
535                 c = (c | *chars++) - firstCol;
536                 if (c < numCols && CHECK_ENCODING(c)->bits)
537                     *glyphs++ = pci;
538                 else if (pDefault)
539                     *glyphs++ = pDefault;
540             }
541         }
542         break;
543
544     case TwoD16Bit:
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)
552                 *glyphs++ = pci;
553             else if (pDefault)
554                 *glyphs++ = pDefault;
555         }
556         break;
557     }
558     *glyphCount = glyphs - glyphsBase;
559     return err;
560 }
561
562
563 static int
564 _fs_get_metrics(pFont, count, chars, charEncoding, glyphCount, glyphs)
565     FontPtr     pFont;
566     unsigned long count;
567     register unsigned char *chars;
568     FontEncoding charEncoding;
569     unsigned long *glyphCount;  /* RETURN */
570     xCharInfo **glyphs;         /* RETURN */
571 {
572     FSFontPtr   fsdata;
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;
579     unsigned int r;
580     CharInfoPtr encoding;
581     CharInfoPtr pDefault;
582     FSFontDataPtr fsd = (FSFontDataPtr) pFont->fpePrivate;
583     int         itemSize;
584     int         err = Successful;
585
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;
591     glyphsBase = glyphs;
592
593
594     /* XXX - this should be much smarter */
595     /* make sure the glyphs are there */
596     if (charEncoding == Linear8Bit || charEncoding == TwoD8Bit)
597         itemSize = 1;
598     else
599         itemSize = 2;
600
601     switch (charEncoding) {
602
603     case Linear8Bit:
604     case TwoD8Bit:
605         if (pFont->info.firstRow > 0)
606             break;
607         if (pFont->info.allExist && pDefault) {
608             while (count--) {
609                 c = (*chars++) - firstCol;
610                 if (c < numCols)
611                     *glyphs++ = (xCharInfo *)&encoding[c];
612                 else
613                     *glyphs++ = (xCharInfo *)pDefault;
614             }
615         } else {
616             while (count--) {
617                 c = (*chars++) - firstCol;
618                 if (c < numCols)
619                     *glyphs++ = (xCharInfo *)(encoding + c);
620                 else if (pDefault)
621                     *glyphs++ = (xCharInfo *)pDefault;
622             }
623         }
624         break;
625     case Linear16Bit:
626         if (pFont->info.allExist && pDefault) {
627             while (count--) {
628                 c = *chars++ << 8;
629                 c = (c | *chars++) - firstCol;
630                 if (c < numCols)
631                     *glyphs++ = (xCharInfo *)(encoding + c);
632                 else
633                     *glyphs++ = (xCharInfo *)pDefault;
634             }
635         } else {
636             while (count--) {
637                 c = *chars++ << 8;
638                 c = (c | *chars++) - firstCol;
639                 if (c < numCols)
640                     *glyphs++ = (xCharInfo *)(encoding + c);
641                 else if (pDefault)
642                     *glyphs++ = (xCharInfo *)pDefault;
643             }
644         }
645         break;
646
647     case TwoD16Bit:
648         firstRow = pFont->info.firstRow;
649         numRows = pFont->info.lastRow - firstRow + 1;
650         while (count--) {
651             r = (*chars++) - firstRow;
652             c = (*chars++) - firstCol;
653             if (r < numRows && c < numCols)
654                 *glyphs++ = (xCharInfo *)(encoding + (r * numCols + c));
655             else if (pDefault)
656                 *glyphs++ = (xCharInfo *)pDefault;
657         }
658         break;
659     }
660     *glyphCount = glyphs - glyphsBase;
661     return Successful;
662 }
663
664
665 void
666 _fs_unload_font(pfont)
667     FontPtr     pfont;
668 {
669     FSFontPtr   fsdata = (FSFontPtr) pfont->fontPrivate;
670
671     if (fsdata->encoding)
672     {
673         register int i;
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);
678              i > 0;
679              encoding++, i--)
680         {
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);
686         }
687     }
688     xfree(fsdata->encoding);
689     xfree(fsdata);
690
691     pfont->fontPrivate = 0;
692 }
693
694 void
695 _fs_init_font(pfont)
696     FontPtr     pfont;
697 {
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;
703 }