|
|
1.1 root 1: /************************************************************************
2: Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
3: and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
4:
5: All Rights Reserved
6:
7: Permission to use, copy, modify, and distribute this software and its
8: documentation for any purpose and without fee is hereby granted,
9: provided that the above copyright notice appear in all copies and that
10: both that copyright notice and this permission notice appear in
11: supporting documentation, and that the names of Digital or MIT not be
12: used in advertising or publicity pertaining to distribution of the
13: software without specific, written prior permission.
14:
15: DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17: DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21: SOFTWARE.
22:
23: ************************************************************************/
24:
25: /* $Header: fonts.c,v 1.46 87/09/09 13:23:03 rws Exp $ */
26:
27: #define NEED_REPLIES
28: #include "X.h"
29: #include "Xmd.h"
30: #include "Xproto.h"
31: #include "dixfontstr.h"
32: #include "fontstruct.h"
33: #include "scrnintstr.h"
34: #include "resource.h"
35: #include "osstruct.h"
36: #include "dix.h"
37: #include "cursorstr.h"
38: #include "misc.h"
39: #include "opaque.h"
40:
41: static FontPtr pFontHead = NullFont;
42: extern FontPtr defaultFont;
43:
44:
45: /*
46: * adding RT_FONT prevents conflict with default cursor font
47: */
48: SetDefaultFont( defaultfontname)
49: char * defaultfontname;
50: {
51: FontPtr pf;
52:
53: if ((pf =OpenFont( strlen( defaultfontname), defaultfontname)) == NullFont)
54: return FALSE;
55:
56: AddResource( FakeClientID(0), RT_FONT, pf, CloseFont, RC_CORE);
57: defaultFont = pf;
58: return TRUE;
59: }
60:
61: /*
62: * Check reference count first, load font only if necessary.
63: */
64: FontPtr
65: OpenFont( lenfname, pfilename)
66: int lenfname;
67: char * pfilename;
68: {
69: FontPtr pfont;
70: int lenpname;
71: char * ppathname;
72: FID pf;
73: int nscr;
74: ScreenPtr pscr;
75:
76: FontPtr ReadNFont();
77:
78: /*
79: * call os-dependent code
80: */
81: if ( (lenpname = ExpandFontName( &ppathname, lenfname, pfilename)) == 0)
82: {
83: #ifdef notdef
84: ErrorF( "OpenFont: ExpandFontName failed to find file '%s', (len = %d)\n",
85: pfilename, lenfname);
86: #endif
87: return NullFont;
88: }
89: /*
90: * first look up font name in list of opened fonts
91: */
92: for ( pfont = pFontHead;
93: pfont != NullFont;
94: pfont = pfont->next)
95: if ( lenpname == pfont->lenpname
96: && strncmp( pfont->pathname, ppathname, pfont->lenpname) == 0)
97: {
98: /*
99: * found it!
100: */
101: pfont->refcnt += 1;
102: Xfree(ppathname);
103: return pfont;
104: }
105:
106: /*
107: * if not found in fonts list, read it off disk
108: */
109:
110: if ( (pf = FiOpenForRead( lenpname, ppathname)) == NullFID)
111: {
112: #ifdef notdef
113: ErrorF(
114: "OpenFont: failed to open font file %s\n",
115: ppathname);
116: #endif
117: Xfree(ppathname);
118: return NullFont;
119: }
120: pfont = ReadNFont( pf);
121: FiClose( pf);
122:
123: if ( pfont == NullFont)
124: {
125: #ifdef notdef
126: ErrorF( "OpenFont: ReadNFont failed on file %s\n", ppathname);
127: #endif
128: Xfree(ppathname);
129: return NullFont;
130: }
131:
132: pfont->lenpname = lenpname;
133: pfont->pathname = (char *)Xalloc( lenpname); /* record pathname */
134: strncpy( pfont->pathname, ppathname, lenpname);
135:
136: pfont->refcnt = 1;
137: pfont->next = pFontHead; /* prepend to fonts list */
138: pFontHead = pfont;
139:
140: /*
141: * since this font has been newly read off disk, ask each screen to
142: * realize it.
143: */
144: for ( nscr=0, pscr=screenInfo.screen;
145: nscr<screenInfo.numScreens;
146: nscr++, pscr++)
147: {
148: if ( pscr->RealizeFont)
149: ( *pscr->RealizeFont)( pscr, pfont);
150: }
151: Xfree(ppathname);
152: return pfont;
153: }
154:
155: /*
156: * Decrement font's ref count, and free storage if ref count equals zero
157: */
158: void
159: CloseFont( pfont)
160: FontPtr pfont;
161: {
162: FontPtr ptf;
163: FontPtr pbtf = NullFont;
164: int nscr;
165: ScreenPtr pscr;
166:
167: if (pfont == NullFont)
168: return ;
169: for ( ptf = pFontHead;
170: ptf != NullFont;
171: ptf = ptf->next)
172: {
173: if ( ptf == pfont || ptf == NullFont)
174: break;
175: pbtf = ptf;
176: }
177: if ( ptf == NullFont)
178: {
179: ErrorF( "CloseFont: couldn't find font to be closed %x\n", ptf);
180: return;
181: }
182: if ( --ptf->refcnt == 0)
183: {
184: if ( pbtf == NullFont) /* unlink ptf */
185: pFontHead = ptf->next;
186: else
187: pbtf->next = ptf->next;
188:
189: /*
190: * since the last reference is gone, ask each screen to
191: * free any storage it may have allocated locally for it.
192: */
193: for ( nscr=0, pscr=screenInfo.screen;
194: nscr<screenInfo.numScreens;
195: nscr++, pscr++)
196: {
197: if ( pscr->UnrealizeFont)
198: ( *pscr->UnrealizeFont)( pscr, ptf);
199: }
200: Xfree( ptf->pathname);
201: Xfree( ptf);
202: if (pfont == defaultFont)
203: defaultFont = NULL;
204: }
205: }
206:
207:
208: /*
209: * description
210: *
211: * Allocates storage with Xalloc(), and returns a pointer to it.
212: * Client can call Xfree() to deallocate font.
213: *
214: * file I/O is all in this routine
215: */
216: FontPtr
217: ReadNFont( fp)
218: FID fp; /* caller has to FiOpenForRead the file himself */
219: {
220: FontPtr pfont;
221: FontInfoRec fi;
222: DIXFontProp *pdfp;
223: FontPropPtr pffp;
224: char *propspace;
225: int bytestoread, bytestoalloc;
226: int bytesdata;
227: int i;
228: char *strings;
229:
230: /* swap bytes? XXX */
231:
232: bytestoread = BYTESOFFONTINFO(&fi);
233: if ( FiRead( &fi, 1, bytestoread, fp) != bytestoread)
234: {
235: ErrorF("ReadNFont: unexpected EOF\n");
236: return NullFont;
237: }
238:
239: if (fi.version1 != FONT_FILE_VERSION || fi.version2 != FONT_FILE_VERSION)
240: {
241: ErrorF("ReadNFont: bad font version; expected %d, got %d and %d\n",
242: FONT_FILE_VERSION, fi.version1, fi.version2);
243: return NullFont;
244: }
245:
246: bytesdata = BYTESOFFONTINFO(&fi);
247: bytesdata += BYTESOFCHARINFO(&fi);
248: bytesdata += BYTESOFGLYPHINFO(&fi);
249:
250: bytestoalloc = BYTESOFFONTINFO(&fi)+bytesdata+BYTESOFPROPINFO(&fi);
251: pfont = (FontPtr ) Xalloc(bytestoalloc);
252:
253: bytestoread = bytesdata - BYTESOFFONTINFO(&fi);
254: if ( FiRead((char *)(&pfont[1]) + BYTESOFFONTINFO(&fi),
255: 1, bytestoread,
256: fp ) != bytestoread)
257: {
258: ErrorF("ReadNFont: unexpected EOF\n");
259: Xfree(pfont);
260: return NullFont;
261: }
262:
263: /*
264: * now fix up pointers
265: */
266: pfont->pFI = (FontInfoPtr)&pfont[1];
267: *pfont->pFI = fi; /* copy date previously read */
268:
269: pfont->pCI = ADDRCharInfoRec(pfont->pFI);
270:
271: pfont->pGlyphs = ADDRCHARGLYPHS(pfont->pFI);
272:
273: pfont->pFP = ADDRXFONTPROPS(pfont->pFI);
274:
275: /* now read and atom'ize properties */
276:
277: bytestoalloc = BYTESOFPROPINFO(pfont->pFI) + BYTESOFSTRINGINFO(pfont->pFI);
278: propspace = (char *) Xalloc(bytestoalloc);
279:
280: pffp = (FontPropPtr)propspace;
281: strings = propspace + BYTESOFPROPINFO(pfont->pFI);
282:
283: bytestoread = bytestoalloc;
284: if ( FiRead(
285: pffp, 1,
286: bytestoread,
287: fp) != bytestoread)
288: {
289: ErrorF("ReadNFont: unexpected EOF\n");
290: Xfree(pfont);
291: Xfree(propspace);
292: return NullFont;
293: }
294:
295: for (i=0, pdfp=pfont->pFP; i<fi.nProps; i++, pdfp++, pffp++)
296: {
297: pdfp->name = MakeAtom(
298: &strings[pffp->name], strlen(&strings[pffp->name]), 1);
299: if (pffp->indirect)
300: pdfp->value = (INT32)MakeAtom(
301: &strings[pffp->value], strlen(&strings[pffp->value]), 1);
302: else
303: pdfp->value = pffp->value;
304: }
305:
306: Xfree(propspace);
307:
308: return pfont;
309: }
310:
311: Bool
312: DescribeFont(pfontname, lenfname, pfi, ppfp)
313: char *pfontname;
314: int lenfname;
315: FontInfoPtr pfi;
316: DIXFontPropPtr *ppfp; /* return */
317: {
318: FontPtr pfont;
319: FID pf;
320: int i;
321: char *ppathname;
322: int lenpname;
323: int bytesskip, bytesprops;
324: DIXFontPropPtr pdfp;
325: FontPropPtr pffp, temp;
326: char *strings;
327:
328: if ((lenpname = ExpandFontName(&ppathname, lenfname, pfontname)) == 0)
329: return(FALSE);
330: /*
331: * first look up font name in list of opened fonts
332: */
333: for ( pfont = pFontHead;
334: pfont != NullFont;
335: pfont = pfont->next)
336: if ( lenpname == pfont->lenpname
337: && strncmp( pfont->pathname, ppathname, pfont->lenpname) == 0)
338: {
339: *pfi = *pfont->pFI;
340: if (pfi->nProps > 0)
341: {
342: *ppfp = (DIXFontPropPtr)Xalloc(sizeof(DIXFontProp)*pfi->nProps);
343: if (*ppfp == NullDIXFontProp)
344: return(FALSE);
345: bcopy((char *)pfont->pFP, (char *)*ppfp,
346: sizeof(DIXFontProp)*pfi->nProps);
347: }
348: return(TRUE);
349: }
350:
351: /* have to read it off disk */
352: if ((pf = FiOpenForRead(lenpname, ppathname)) == NullFID)
353: return(FALSE);
354: if ((FiRead(pfi, 1, sizeof(FontInfoRec), pf) != sizeof(FontInfoRec)) ||
355: pfi->version1 != FONT_FILE_VERSION ||
356: pfi->version2 != FONT_FILE_VERSION)
357: {
358: FiClose(pf);
359: return(FALSE);
360: }
361:
362: bytesskip = BYTESOFFONTINFO(pfi) - sizeof(FontInfoRec) +
363: BYTESOFCHARINFO(pfi) + BYTESOFGLYPHINFO(pfi);
364: bytesprops = BYTESOFPROPINFO(pfi) + BYTESOFSTRINGINFO(pfi);
365:
366: temp = (FontPropPtr)Xalloc(max(bytesskip, bytesprops));
367: *ppfp = (DIXFontProp *)Xalloc(pfi->nProps * sizeof(DIXFontProp));
368:
369: if ((!temp) ||
370: (*ppfp == NullDIXFontProp) ||
371: (FiRead((char *)temp, 1, bytesskip, pf) != bytesskip) ||
372: (FiRead((char *)temp, 1, bytesprops, pf) != bytesprops))
373: {
374: Xfree((char *)*ppfp);
375: *ppfp = NullDIXFontProp;
376: Xfree((char *)temp);
377: FiClose(pf);
378: return(FALSE);
379: }
380: strings = (char *)&temp[pfi->nProps];
381: pffp = temp;
382: for (i=0, pdfp=(*ppfp); i<pfi->nProps; i++, pdfp++, pffp++)
383: {
384: pdfp->name = MakeAtom(
385: &strings[pffp->name], strlen(&strings[pffp->name]), 1);
386: if (pffp->indirect)
387: pdfp->value = (INT32)MakeAtom(
388: &strings[pffp->value], strlen(&strings[pffp->value]), 1);
389: else
390: pdfp->value = pffp->value;
391: }
392: Xfree((char *)temp);
393: FiClose(pf);
394: return(TRUE);
395: }
396:
397:
398: #ifdef notdef
399: /*
400: * assumes short is 2 bytes and long is 4, but nothing about padding
401: */
402: #define _us unsigned short
403: #define _ul unsigned long
404: #define sw2( p) \
405: *((_us *)p) = \
406: *(_us *)p>>8 \
407: | *(_us *)p<<8;
408: #define sw4( p) \
409: *((_ul *)p) = \
410: *(_ul *)p>>24 \
411: | *(_ul *)p>>8 & 0x0000ff00 \
412: | *(_ul *)p<<8 & 0x00ff0000 \
413: | *(_ul *)p<<24;
414:
415: #else
416:
417: #define sw2( p) { \
418: int t; \
419: t = ((char *)p)[0]; \
420: ((char *)p)[0] = ((char *)p)[1]; \
421: ((char *)p)[1] = t; \
422: }
423: #define sw4( p) { \
424: int t; \
425: t = ((char *)p)[0]; \
426: ((char *)p)[0] = ((char *)p)[3]; \
427: ((char *)p)[3] = t; \
428: t = ((char *)p)[1]; \
429: ((char *)p)[1] = ((char *)p)[2]; \
430: ((char *)p)[2] = t; \
431: }
432:
433: #endif
434:
435: void
436: QueryFont( pf, pr, nprotoxcistructs)
437: FontPtr pf;
438: xQueryFontReply * pr; /* caller must allocate this storage */
439: int nprotoxcistructs;
440: {
441: FontInfoPtr pfi = pf->pFI;
442: CharInfoPtr pci;
443: DIXFontProp * pfp;
444: int ct;
445: xFontProp * prfp;
446: xCharInfo * prci;
447:
448: void queryCharInfo();
449:
450: /* pr->length set in dispatch */
451: pr->minCharOrByte2 = pfi->firstCol;
452: pr->defaultChar = pfi->chDefault;
453: pr->maxCharOrByte2 = pfi->lastCol;
454: pr->drawDirection = pfi->drawDirection;
455: pr->allCharsExist = pfi->allExist;
456: pr->minByte1 = pfi->firstRow;
457: pr->maxByte1 = pfi->lastRow;
458: pr->fontAscent = pfi->fontAscent;
459: pr->fontDescent = pfi->fontDescent;
460:
461: queryCharInfo( &pfi->minbounds, &pr->minBounds);
462: queryCharInfo( &pfi->maxbounds, &pr->maxBounds);
463:
464: pr->nFontProps = pfi->nProps;
465: pr->nCharInfos = nprotoxcistructs;
466:
467:
468: for ( ct=0,
469: pfp=pf->pFP,
470: prfp=(xFontProp *)(&pr[1]);
471: ct < pfi->nProps;
472: ct++, pfp++, prfp++)
473: {
474: prfp->name = pfp->name;
475: prfp->value = pfp->value;
476: }
477:
478: for ( ct=0,
479: pci = &pf->pCI[0],
480: prci=(xCharInfo *)(prfp);
481: ct<nprotoxcistructs;
482: ct++, pci++, prci++)
483: queryCharInfo( pci, prci);
484: }
485:
486: /* static */ void
487: queryCharInfo( pci, pr)
488: CharInfoPtr pci;
489: xCharInfo * pr; /* protocol packet to fill in */
490: {
491: *pr = pci->metrics;
492: }
493:
494: /* static */ void
495: SwapFont( pr, hasGlyphs)
496: xQueryFontReply * pr;
497: Bool hasGlyphs;
498: {
499: int i;
500: xCharInfo * pxci;
501: int nchars, nprops;
502: char *pby;
503: register char n;
504:
505: swaps(&pr->sequenceNumber, n);
506: swapl(&pr->length, n);
507: nchars = pr->nCharInfos;
508: nprops = pr->nFontProps;
509: SwapFontInfo(pr);
510: pby = (char *) &pr[1];
511: /* Font properties are an atom and either an int32 or a CARD32, so
512: * they are always 2 4 byte values */
513: for(i = 0; i < nprops; i++)
514: {
515: swapl(pby, n);
516: pby += 4;
517: swapl(pby, n);
518: pby += 4;
519: }
520: if (hasGlyphs)
521: {
522: pxci = (xCharInfo *)pby;
523: for(i = 0; i< nchars; i++, pxci++)
524: SwapCharInfo(pxci);
525: }
526: }
527:
528: SwapFontInfo(pr)
529: xQueryFontReply *pr;
530: {
531: register char n;
532:
533: swaps(&pr->minCharOrByte2, n);
534: swaps(&pr->maxCharOrByte2, n);
535: swaps(&pr->defaultChar, n);
536: swaps(&pr->nFontProps, n);
537: swaps(&pr->fontAscent, n);
538: swaps(&pr->fontDescent, n);
539: SwapCharInfo( &pr->minBounds);
540: SwapCharInfo( &pr->maxBounds);
541: swapl(&pr->nCharInfos, n);
542: }
543: SwapCharInfo(pInfo)
544: xCharInfo *pInfo;
545: {
546: register char n;
547:
548: swaps(&pInfo->leftSideBearing, n);
549: swaps(&pInfo->rightSideBearing, n);
550: swaps(&pInfo->characterWidth, n);
551: swaps(&pInfo->ascent, n);
552: swaps(&pInfo->descent, n);
553: swaps(&pInfo->attributes, n);
554: }
555:
556:
557: /* text support routines. A charinfo array builder, and a bounding */
558: /* box calculator */
559:
560: void
561: GetGlyphs(font, count, chars, fontEncoding, glyphcount, glyphs)
562: FontPtr font;
563: int count;
564: register unsigned char *chars;
565: FontEncoding fontEncoding;
566: unsigned int *glyphcount; /* RETURN */
567: CharInfoPtr glyphs[]; /* RETURN */
568: {
569: CharInfoPtr pCI = font->pCI;
570: FontInfoPtr pFI = font->pFI;
571: unsigned int firstCol = pFI->firstCol;
572: unsigned int numCols = pFI->lastCol - firstCol + 1;
573: unsigned int firstRow = pFI->firstRow;
574: unsigned int numRows = pFI->lastRow - firstRow + 1;
575: unsigned int chDefault = pFI->chDefault;
576: register int i;
577: int n;
578: register unsigned int c;
579: register CharInfoPtr ci;
580:
581: n = 0;
582: switch (fontEncoding) {
583:
584: case Linear8Bit:
585: case TwoD8Bit:
586: for (i=0; i < count; i++) {
587:
588: c = (*chars++) - firstCol;
589: if (c < numCols) {
590: ci = &pCI[c];
591: if (ci->exists) {glyphs[n++] = ci; continue;}
592: }
593:
594: c = chDefault - firstCol;
595: if (c < numCols) {
596: ci = &pCI[c];
597: if (ci->exists) glyphs[n++] = ci;
598: }
599: }
600: break;
601:
602: case Linear16Bit:
603: for (i=0; i < count; i++) {
604:
605: chars++;
606: c = (*chars++) - firstCol;
607: if (c < numCols) {
608: ci = &pCI[c];
609: if (ci->exists) {glyphs[n++] = ci; continue;}
610: }
611:
612: c = chDefault - firstCol;
613: if (c < numCols) {
614: ci = &pCI[c];
615: if (ci->exists) glyphs[n++] = ci;
616: }
617: }
618: break;
619:
620: case TwoD16Bit:
621: for (i=0; i < count; i++) {
622: register unsigned int row;
623: register unsigned int col;
624:
625: row = (*chars++) - firstRow;
626: col = (*chars++) - firstCol;
627: if ((row < numRows) && (col < numCols)) {
628: c = row*numCols + col;
629: ci = &pCI[c];
630: if (ci->exists) {glyphs[n++] = ci; continue;}
631: }
632:
633: row = (chDefault >> 8)-firstRow;
634: col = (chDefault & 0xff)-firstCol;
635: if ((row < numRows) && (col < numCols)) {
636: c = row*numCols + col;
637: ci = &pCI[c];
638: if (ci->exists) glyphs[n++] = ci;
639: }
640: }
641: break;
642: }
643: *glyphcount = n;
644: }
645:
646:
647:
648: void
649: QueryGlyphExtents(font, charinfo, count, info)
650: FontPtr font;
651: CharInfoPtr *charinfo;
652: unsigned int count;
653: ExtentInfoRec *info;
654: {
655: int i;
656:
657: info->drawDirection = font->pFI->drawDirection;
658:
659: info->fontAscent = font->pFI->fontAscent;
660: info->fontDescent = font->pFI->fontDescent;
661:
662: if (count != 0) {
663:
664: info->overallAscent = charinfo[0]->metrics.ascent;
665: info->overallDescent = charinfo[0]->metrics.descent;
666: info->overallLeft = charinfo[0]->metrics.leftSideBearing;
667: info->overallRight = charinfo[0]->metrics.rightSideBearing;
668: info->overallWidth = charinfo[0]->metrics.characterWidth;
669:
670: for (i=1; i < count; i++) {
671: info->overallAscent = max(
672: info->overallAscent,
673: charinfo[i]->metrics.ascent);
674: info->overallDescent = max(
675: info->overallDescent,
676: charinfo[i]->metrics.descent);
677: info->overallLeft = min(
678: info->overallLeft,
679: info->overallWidth+charinfo[i]->metrics.leftSideBearing);
680: info->overallRight = max(
681: info->overallRight,
682: info->overallWidth+charinfo[i]->metrics.rightSideBearing);
683: /* yes, this order is correct; overallWidth IS incremented last */
684: info->overallWidth += charinfo[i]->metrics.characterWidth;
685: }
686:
687: } else {
688:
689: info->overallAscent = 0;
690: info->overallDescent = 0;
691: info->overallWidth = 0;
692: info->overallLeft = 0;
693: info->overallRight = 0;
694:
695: }
696: }
697:
698: void
699: QueryTextExtents(font, count, chars, info)
700: FontPtr font;
701: unsigned int count;
702: unsigned short *chars;
703: ExtentInfoRec *info;
704: {
705: CharInfoPtr *charinfo =
706: (CharInfoPtr *)ALLOCATE_LOCAL(count*sizeof(CharInfoPtr));
707: unsigned int n;
708:
709: if(!charinfo)
710: return;
711: if (font->pFI->lastRow == 0)
712: GetGlyphs(font, count, chars, Linear16Bit, &n, charinfo);
713: else
714: GetGlyphs(font, count, chars, TwoD16Bit, &n, charinfo);
715:
716: QueryGlyphExtents(font, charinfo, n, info);
717:
718: DEALLOCATE_LOCAL(charinfo);
719: }
720:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.