Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / DtTerm / TermPrim / TermPrimLineDraw.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 #ifndef lint
24 #ifdef  VERBOSE_REV_INFO
25 static char rcs_id[] = "$XConsortium: TermPrimLineDraw.c /main/1 1996/04/21 19:17:48 drk $";
26 #endif  /* VERBOSE_REV_INFO */
27 #endif  /* lint */
28
29 /*                                                                      *
30  * (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company               *
31  * (c) Copyright 1993, 1994, 1996 International Business Machines Corp. *
32  * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc.                *
33  * (c) Copyright 1993, 1994, 1996 Novell, Inc.                          *
34  * (c) Copyright 1996 Digital Equipment Corporation.                    *
35  * (c) Copyright 1996 FUJITSU LIMITED.                                  *
36  * (c) Copyright 1996 Hitachi.                                          *
37  */
38
39 #include <stdio.h>
40 #include <unistd.h>
41 #include <stdlib.h>
42 #include <Xm/Xm.h>
43 #include "TermPrimLineFontP.h"
44 #include "TermPrimLineDrawP.h"
45 #include "TermPrimDebug.h"
46 #include "TermPrimP.h"
47
48 /****************************************************************************
49  * 
50  * This module is used to implement the line drawing functionality for
51  * hpterm.  It implements a primitive (simple?)  font scaling engine that
52  * converts a set of rectangles, lines, and "stipples" to a line drawing
53  * font.  The font is stored as a single plane pixmap and is rendered by
54  * performing a copy plane to the target drawable.
55  * 
56  * To increase the performance, fonts are not free'ed when the reference
57  * count hits zero.  Rather, they are free'ed if the reference count has
58  * hit zero and a new font is created with different parameters.
59  * 
60  ***************************************************************************/
61
62 static LineDrawFontData lineDrawFontDataHead = (LineDrawFontData) 0;
63 static LineDrawFont lineDrawFontHead = (LineDrawFont) 0;
64 /* static int numLineDrawFonts = 0; */
65
66 static void
67 ScaleCharacter(
68 #ifdef  USE_PIXMAPS
69         GC gc, Pixmap bitmap,
70         ScaledBitmapInfo renderInfo, GlyphInfo glyph,
71         int width, int height
72 #else   /* USE_PIXMAPS */
73         ScaledCharInfo renderInfo, GlyphInfo glyph, int width, int height
74 #endif  /* USE_PIXMAPS */
75         )
76 {
77     int j;
78 #ifdef  USE_PIXMAPS
79     cellPositionType cellX;
80     cellPositionType cellX;
81     Pixmap pixmap;
82 #else   /* USE_PIXMAPS */
83     int k;
84     int numLines;
85 #endif  /* USE_PIXMAPS */
86
87 #ifdef  USE_PIXMAPS
88     /* calculate position of pixmap into which we will draw the glyph...
89      */
90     cellX = (i % 16) * width;
91     cellY = (i / 16) * height;
92     renderInfo->cellX = cellX;
93     renderInfo->cellY = cellY;
94 #else   /* USE_PIXMAPS */
95     /* malloc storage for the line segments, rectangles, stipples...
96      */
97     /* count the number of lines... */
98     for (j = 0, numLines = 0; j < glyph->numLines; j++) {
99         numLines += glyph->lines[j].width;
100     }
101     if (numLines > 0) {
102         /* malloc the line storage... */
103         renderInfo->segs = (XSegment *)
104                 XtRealloc((void *) renderInfo->segs,
105                 numLines * sizeof(XSegment));
106     }
107     renderInfo->numSegs = numLines;
108
109     /* rectangles... */
110     if (glyph->numRects > 0) {
111         /* malloc the rectangle storage... */
112         renderInfo->rects = (XRectangle *)
113                 XtRealloc((void *) renderInfo->rects,
114                 glyph->numRects * sizeof(XRectangle));
115     }
116     renderInfo->numRects = glyph->numRects;
117
118     /* stipples... */
119     if (glyph->numStipples > 0) {
120         /* malloc the stipple storage... */
121         renderInfo->stipples = (XRectangle *)
122                 XtRealloc((void *) renderInfo->stipples,
123                 glyph->numStipples * sizeof(XRectangle));
124     }
125     renderInfo->numStipples = glyph->numStipples;
126 #endif  /* USE_PIXMAPS */
127
128     /* draw the lines...
129      */
130 #ifndef USE_PIXMAPS
131     /* reset the counter... */
132     numLines = 0;
133 #endif  /* USE_PIXMAPS */
134
135     /* lines
136      */
137     for (j = 0; j < glyph->numLines; j++) {
138         /* draw the line segment / scale the line segment... */
139         int x1;
140         int x2;
141         int y1;
142         int y2;
143
144         DebugF('l', 0, fprintf(stderr,
145                 ">> line data:  x1=%d%+d  y1=%d%+d  x2=%d%+d  y2=%d%+d width=%d",
146                 glyph->lines[j].x1,
147                 glyph->lines[j].x1Offset,
148                 glyph->lines[j].y1,
149                 glyph->lines[j].y1Offset,
150                 glyph->lines[j].x2,
151                 glyph->lines[j].x2Offset,
152                 glyph->lines[j].y2,
153                 glyph->lines[j].y2Offset,
154                 glyph->lines[j].width));
155
156         /* scale x1 and x2 to our width... */
157         x1 = ((width - 1) * glyph->lines[j].x1) / 100;
158         x2 = ((width - 1) * glyph->lines[j].x2) / 100;
159
160         /* scale y1 and y2 to our height... */
161         y1 = ((height - 1) * glyph->lines[j].y1) / 100;
162         y2 = ((height - 1) * glyph->lines[j].y2) / 100;
163
164         /* add offsets... */
165         x1 += glyph->lines[j].x1Offset;
166         x2 += glyph->lines[j].x2Offset;
167         y1 += glyph->lines[j].y1Offset;
168         y2 += glyph->lines[j].y2Offset;
169
170 #ifdef  USE_PIXMAPS
171         /* add in the line width... */
172         if (x1 == x2) {
173             x1 -= (glyph->lines[j].width - 1) / 2;
174             x2 += glyph->lines[j].width - 1 - (glyph->lines[j].width - 1) / 2;
175         }
176
177         /* add in the line width... */
178         if (y1 == y2) {
179             y1 -= (glyph->lines[j].width - 1) / 2;
180             y2 += glyph->lines[j].width - 1 - (glyph->lines[j].width - 1) / 2;
181         }
182
183         DebugF('l', 0, fprintf(stderr,
184                 ">> line:  x=%d  y=%d  width=%d  height=%d",
185                 x1, y1, x2 - x1 + 1, y2 - y1 + 1));
186         /* draw the line (actually, fill the rectangle)... */
187         (void) XFillRectangle(d,                /* display              */
188                     pixmap,                     /* drawable             */
189                     gc,                         /* GC                   */
190                     cellX + x1,                 /* x                    */
191                     cellY + y1,                 /* y                    */
192                     x2 - x1 + 1,                /* width                */
193                     y2 - y1 + 1);               /* height               */
194 #else   /* USE_PIXMAPS */
195         if ((x1 == x2) && (y1 != y2)) {
196             /* vertical lines... */
197             for (k = 0; k < glyph->lines[j].width; k++) {
198                 renderInfo->segs[numLines + k].x1 =
199                         renderInfo->segs[numLines + k].x2 =
200                         x1 - (glyph->lines[j].width / 2) + k;
201                 renderInfo->segs[numLines + k].y1 = y1;
202                 renderInfo->segs[numLines + k].y2 = y2;
203             }
204         } else if ((y1 == y2) && (x1 != x2)) {
205             /* horizontal lines... */
206             for (k = 0; k < glyph->lines[j].width ; k++) {
207                 renderInfo->segs[numLines + k].y1 =
208                         renderInfo->segs[numLines + k].y2 =
209                         y2 - (glyph->lines[j].width / 2) + k;
210                 renderInfo->segs[numLines + k].x1 = x1;
211                 renderInfo->segs[numLines + k].x2 = x2;
212             }
213         } else {
214             for (k = 0; k < glyph->lines[j].width; k++) {
215                 renderInfo->segs[numLines + k].y1 =
216                         renderInfo->segs[numLines + k].y2 =
217                         y2 - (glyph->lines[j].width / 2) + k;
218                 renderInfo->segs[numLines + k].x1 = x1 - 
219                         glyph->lines[j].width / 2;
220                 renderInfo->segs[numLines + k].x2 = x2 + 
221                         glyph->lines[j].width / 2;
222             }
223         }
224
225         numLines += glyph->lines[j].width;
226     }
227 #endif  /* USE_PIXMAPS */
228
229     /* rectangles...
230      */
231     for (j = 0; j < glyph->numRects; j++) {
232         /* draw / stipple the rectangles... */
233         int x1;
234         int x2;
235         int y1;
236         int y2;
237
238         /* scale x1 and x2 to our width... */
239         x1 = ((width - 1) * glyph->rects[j].x1) / 100;
240         x2 = ((width - 1) * glyph->rects[j].x2) / 100;
241
242         /* scale y1 and y2 to our height... */
243         y1 = ((height - 1) * glyph->rects[j].y1) / 100;
244         y2 = ((height - 1) * glyph->rects[j].y2) / 100;
245
246         /* add offsets... */
247         x1 += glyph->rects[j].x1Offset;
248         x2 += glyph->rects[j].x2Offset;
249         y1 += glyph->rects[j].y1Offset;
250         y2 += glyph->rects[j].y2Offset;
251
252 #ifdef  USE_PIXMAPS
253         DebugF('l', 0, fprintf(stderr,
254                 ">> rect:  x=%d  y=%d  width=%d  height=%d",
255                 x1, y1, x2 - x1 + 1, y2 - y1 + 1));
256         /* fill the rectangle... */
257         (void) XFillRectangle(d,                /* display              */
258                     pixmap,                     /* drawable             */
259                     gc,                         /* GC                   */
260                     cellX + x1,                 /* x                    */
261                     cellY + y1,                 /* y                    */
262                     x2 - x1 + 1,                /* width                */
263                     y2 - y1 + 1);               /* height               */
264 #else   /* USE_PIXMAPS */
265         renderInfo->rects[j].x = x1;
266         renderInfo->rects[j].y = y1;
267         renderInfo->rects[j].width = x2 - x1 + 1;
268         renderInfo->rects[j].height = y2 - y1 + 1;
269 #endif  /* USE_PIXMAPS */
270     }
271
272     /* stipple in the rectangle...
273      */
274     for (j = 0; j < glyph->numStipples; j++) {
275         /* stipple the rectangle... */
276         int x1;
277         int x2;
278         int y1;
279         int y2;
280         int stippleSize;
281 #ifdef  USE_PIXMAPS
282         int xIndex;
283         int yIndex;
284 #endif  /* USE_PIXMAPS */
285
286         /* scale x1 and x2 to our width... */
287         x1 = ((width - 1) * glyph->stipples[j].x1) / 100;
288         x2 = ((width - 1) * glyph->stipples[j].x2) / 100;
289
290         /* scale y1 and y2 to our height... */
291         y1 = ((height - 1) * glyph->stipples[j].y1) / 100;
292         y2 = ((height - 1) * glyph->stipples[j].y2) / 100;
293
294         stippleSize = glyph->stipples[j].width;
295
296         /* add offsets... */
297         x1 += glyph->stipples[j].x1Offset;
298         x2 += glyph->stipples[j].x2Offset;
299         y1 += glyph->stipples[j].y1Offset;
300         y2 += glyph->stipples[j].y2Offset;
301
302 #ifdef  USE_PIXMAPS
303         /* fill in the area... */
304         for (yIndex = y1; yIndex < y2; yIndex += stippleSize) {
305             for (xIndex = x1; xIndex < x2; xIndex += stippleSize) {
306                 if (!(((xIndex / stippleSize) % 2) ^
307                         ((yIndex / stippleSize) % 2))) {
308                     /* fill this rectangle... */
309                     DebugF('l', 0, fprintf(stderr,
310                             ">> stipple:  x=%d  y=%d  width=%d  height=%d",
311                             xIndex, yIndex,
312                             (stippleSize <= (x2 - xIndex)) ? stippleSize :
313                                     x2 - xIndex,
314                             (stippleSize <= (y2 - yIndex)) ? stippleSize :
315                                     y2 - yIndex));
316                     (void) XFillRectangle(d,    /* display              */
317                             pixmap,             /* drawable             */
318                             gc,                 /* GC                   */
319                             cellX + xIndex,     /* x                    */
320                             cellY + yIndex,     /* y                    */
321                             (stippleSize <= (x2 - xIndex)) ? stippleSize :
322                                     x2 - xIndex,
323                                                 /* width                */
324                             (stippleSize <= (y2 - yIndex)) ? stippleSize :
325                                     y2 - yIndex);
326                                                 /* height               */
327                 }
328             }
329         }
330 #endif  /* USE_PIXMAPS */
331     }
332
333     /* mark this character as completed... */
334 #ifdef  USE_PIXMAPS
335     renderInfo->scaled = True;
336 #else   /* USE_PIXMAPS */
337     renderInfo->scaled = True;
338 #endif  /* USE_PIXMAPS */
339 }
340
341 static short *
342 GetLineDrawFontIndex(GlyphInfo glyphInfo, int numGlyphs)
343 {
344     LineDrawFontData lineDrawFontData;
345     int i;
346     int j;
347
348     for (lineDrawFontData = lineDrawFontDataHead; lineDrawFontData;
349             lineDrawFontData = lineDrawFontData->next) {
350         if ((lineDrawFontData->glyphInfo == glyphInfo) &&
351                 lineDrawFontData->numGlyphs == numGlyphs) {
352             return(lineDrawFontData->lineDrawIndex);
353         }
354     }
355
356     /* no match.  Insert one at the head of the list and fill it out...
357      */
358     lineDrawFontData = (LineDrawFontData) XtMalloc(sizeof(LineDrawFontDataRec));
359     lineDrawFontData->next = lineDrawFontDataHead;
360     lineDrawFontDataHead = lineDrawFontData;
361     lineDrawFontData->glyphInfo = glyphInfo;
362     lineDrawFontData->numGlyphs = numGlyphs;
363     /* clear out the array... */
364     for (i = 0; i < (sizeof(lineDrawFontData->lineDrawIndex) /
365             sizeof(lineDrawFontData->lineDrawIndex[0])); i++) {
366         lineDrawFontData->lineDrawIndex[i] = -1;
367     }
368
369     /* fill up the array... */
370     for (i = 0; i < numGlyphs; i++) {
371         for (j = 0; glyphInfo[i].chars[j] > 0; j++) {
372             lineDrawFontData->lineDrawIndex[glyphInfo[i].chars[j] % 256] = i;
373         }
374     }
375     return(lineDrawFontData->lineDrawIndex);
376 }
377
378 LineDrawFont
379 _DtTermPrimLineDrawCreateFont(Widget w, GlyphInfo glyphInfo, int numGlyphs,
380         int width, int ascent, int descent)
381 {
382     DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
383     struct termData *tpd = tw->term.tpd;
384     int fontNumber;
385     LineDrawFont lineDrawFont;
386     int i;
387     int height = ascent + descent;
388 #ifdef  USE_PIXMAPS
389     GC gc;
390     Pixmap pixmap;
391 #endif  /* USE_PIXMAPS */
392
393     _DtTermProcessLock();
394     /* let's look for a line draw font that is already made...
395      */
396     for (lineDrawFont = lineDrawFontHead; lineDrawFont;
397             lineDrawFont = lineDrawFont->next) {
398         if ((lineDrawFont->fontValid) &&
399                 (lineDrawFont->width == width) &&
400                 (lineDrawFont->height == height) &&
401                 (lineDrawFont->ascent == ascent) &&
402                 (lineDrawFont->display == XtDisplay(w)) &&
403                 (lineDrawFont->glyphInfo == glyphInfo) &&
404                 (lineDrawFont->numGlyphs == numGlyphs)) {
405             /* we found a match...
406              */
407             /* bump the reference count... */
408             (void) lineDrawFont->refCount++;
409             /* and return this "font"... */
410             _DtTermProcessUnlock();
411             return (lineDrawFont);
412         }
413     }
414
415     /* no match -- we will have to build the font...
416      */
417     /* look for a free slot... */
418     for (lineDrawFont = lineDrawFontHead; lineDrawFont;
419             lineDrawFont = lineDrawFont->next) {
420         if ((lineDrawFont->refCount == 0) &&
421                 (lineDrawFont->glyphInfo == glyphInfo) &&
422                 (lineDrawFont->numGlyphs == numGlyphs)) {
423             /* found a free slot... */
424             /* free any valid but unused font in this slot... */
425             if (lineDrawFont->fontValid) {
426 #ifdef  USE_PIXMAPS
427                 (void) XFreePixmap(lineDrawFont->display,
428                                                 /* Display              */
429                         lineDrawFont->pixmap);  /* drawable             */
430 #endif  /* USE_PIXMAPS */
431                 lineDrawFont->fontValid = False;
432             }
433             break;
434         }
435     }
436
437     /* did we hit the end of the linked list... */
438     if (!lineDrawFont) {
439         /* add a new entry to the head of the linked list... */
440         lineDrawFont = (LineDrawFont)
441                 XtMalloc(sizeof(LineDrawFontRec));
442         (void) memset(lineDrawFont, '\0', sizeof(LineDrawFontRec));
443         lineDrawFont->next = lineDrawFontHead;
444         lineDrawFontHead = lineDrawFont;
445     }
446
447     lineDrawFont->refCount = 1;
448     lineDrawFont->fontValid = True;
449     lineDrawFont->width = width;
450     lineDrawFont->height = height;
451     lineDrawFont->ascent = ascent;
452     lineDrawFont->width = width;
453     lineDrawFont->display = XtDisplay(w);
454     lineDrawFont->glyphInfo = glyphInfo;
455     lineDrawFont->numGlyphs = numGlyphs;
456     lineDrawFont->glyphIndex = GetLineDrawFontIndex(glyphInfo, numGlyphs);
457
458 #ifdef  USE_PIXMAPS
459     /* malloc the cell position for this font (if necessary)... */
460     if (!lineDrawFont->scaledBitmapInfo) {
461         lineDrawFont->scaledBitmapInfo = (ScaledBitmapInfo)
462                 XtMalloc(lineDrawFont->numGlyphs * sizeof(ScaledBitmapInfoRec));
463         /* initialize it... */
464         (void) memset(lineDrawFont->scaledBitmapInfo, '\0',
465                 lineDrawFont->numGlyphs * sizeof(scaledBitmapInfo));
466     } else {
467         /* mark all the characters in the old font as unscaled... */
468         for (i = 0; i < lineDrawFont->numGlyphs; i++) {
469             lineDrawFont->scaledBitmapInfo[i].scaled = False;
470         }
471     }
472 #else   /* USE_PIXMAPS */
473     /* malloc the line, rectangle, stipple storage (if necessary)... */
474     if (!lineDrawFont->scaledCharInfo) {
475         lineDrawFont->scaledCharInfo = (ScaledCharInfo)
476                 XtMalloc(lineDrawFont->numGlyphs * sizeof(ScaledCharInfoRec));
477         (void) memset(lineDrawFont->scaledCharInfo, '\0',
478                 lineDrawFont->numGlyphs * sizeof(ScaledCharInfoRec));
479     } else {
480         /* mark all the characters in the old font as unscaled... */
481         for (i = 0; i < lineDrawFont->numGlyphs; i++) {
482             lineDrawFont->scaledCharInfo[i].scaled = False;
483         }
484     }
485 #endif  /* USE_PIXMAPS */
486
487 #ifdef  USE_PIXMAPS
488     /* create a pixmap that is 16 characters wide and
489      * lineDrawFont->numGlyphs / 16 characters high...
490      */
491     pixmap = XCreatePixmap(d,
492                                                 /* Display              */
493             DefaultRootWindow(d),               /* reference window     */
494             width * 16,                         /* width                */
495             (lineDrawFont->numGlyphs + 15) / 16 * (height),
496                                                 /* height               */
497             1);                                 /* planes               */
498     lineDrawFont->pixmap = pixmap;
499
500     /* we need a GC...
501      */
502     gc = XCreateGC(d,                           /* Display              */
503             pixmap,                             /* drawable             */
504             (unsigned long) (0),                /* value mask           */
505             (XGCValues *) 0);                   /* values               */
506
507     /* clear the pixmap... */
508     (void) XSetForeground(d, gc, 0);
509     (void) XFillRectangle(d,                    /* display              */
510             pixmap,                             /* drawable             */
511             gc,                                 /* GC                   */
512             0,                                  /* x                    */
513             0,                                  /* y                    */
514             width * 16,                         /* width                */
515             (lineDrawFont->numGlyphs + 15) / 16 * (height));
516                                                 /* height               */
517
518     /* reset the GC so we can fill in the lines and rectangles... */
519     (void) XSetForeground(d, gc, 1);
520 #endif  /* USE_PIXMAPS */
521
522     _DtTermProcessUnlock();
523     return(lineDrawFont);
524 }
525
526 void
527 _DtTermPrimLineDrawFreeFont(LineDrawFont lineDrawFont)
528 {
529     _DtTermProcessLock();
530
531     /* perform a sanity check... */
532     if (lineDrawFont->refCount <= 0) {
533         _DtTermProcessUnlock();
534         return;
535     }
536
537     /* decrement the reference count... */
538     (void) lineDrawFont->refCount--;
539
540     /* we will free the storage if this font is used... */
541     _DtTermProcessUnlock();
542     return;
543 }
544
545
546 void
547 _DtTermPrimLineDrawImageString(Display *display, Drawable d,
548         LineDrawFont lineDrawFont,
549         GC gc, GC clearGC, int x, int y, unsigned char *string, int width)
550 {
551     int glyph;
552 #ifndef USE_PIXMAPS
553     XSegment segs[20];
554     XRectangle rects[20];
555     int i;
556 #endif  /* USE_PIXMAPS */
557
558     _DtTermProcessLock();
559     if (!lineDrawFont || (lineDrawFont->refCount < 0)) {
560         _DtTermProcessUnlock();
561         return;
562     }
563
564 #ifndef USE_PIXMAPS
565     /* clear the area... */
566     (void) XFillRectangle(display,              /* Display              */
567             d,                                  /* Window               */
568             clearGC,                            /* GC                   */
569             x,                                  /* x                    */
570             y - lineDrawFont->ascent,           /* y                    */
571             lineDrawFont->width * width,        /* width                */
572             lineDrawFont->height);              /* height               */
573 #endif  /* USE_PIXMAPS */
574
575     /* render the characters... */
576     for (; width > 0; width--, string++) {
577         /* look up glyph through the glyph table... */
578         /* check for valid glyph... */
579         glyph = lineDrawFont->glyphIndex[*string];
580
581         /* if it is invalid, then let's default to space... */
582         if (glyph < 0)
583             glyph = lineDrawFont->glyphIndex[' '];
584
585         /* if it is still invalid, then let's skip this character... */
586         if (glyph < 0) {
587             x += lineDrawFont->width;
588             continue;
589         }
590
591 #ifdef  USE_PIXMAPS
592         /* render this character... */
593         (void) XCopyPlane(display,              /* Display              */
594                 lineDrawFont->pixmap,           /* src                  */
595                 d,                              /* dest                 */
596                 gc,                             /* GC                   */
597                 lineDrawFont->cellX[glyph],     /* src x                */
598                 lineDrawFont->cellY[glyph],     /* src y                */
599                 lineDrawFont->width,            /* width                */
600                 lineDrawFont->height,           /* height               */
601                 x,                              /* dest x               */
602                 y - lineDrawFont->ascent,       /* dest y               */
603                 1);                             /* plane                */
604
605 #else   /* USE_PIXMAPS */
606         if (!lineDrawFont->scaledCharInfo[glyph].scaled) {
607             /* first time, scale this character... */
608             (void) ScaleCharacter(&(lineDrawFont->scaledCharInfo[glyph]),
609                     &(lineDrawFont->glyphInfo[glyph]), lineDrawFont->width, lineDrawFont->height);
610         }
611
612         if (lineDrawFont->scaledCharInfo[glyph].numSegs > 0) {
613             for (i = 0; i < lineDrawFont->scaledCharInfo[glyph].numSegs; i++) {
614                 segs[i].x1 = x + lineDrawFont->scaledCharInfo[glyph].segs[i].x1;
615                 segs[i].x2 = x + lineDrawFont->scaledCharInfo[glyph].segs[i].x2;
616                 segs[i].y1 =
617                         y + lineDrawFont->scaledCharInfo[glyph].segs[i].y1 -
618                         lineDrawFont->ascent;
619                 segs[i].y2 =
620                         y + lineDrawFont->scaledCharInfo[glyph].segs[i].y2 -
621                         lineDrawFont->ascent;
622             }
623             (void) XDrawSegments(display,       /* Display              */
624                 d,                              /* dest                 */
625                 gc,                             /* GC                   */
626                 segs,                           /* segments             */
627                 lineDrawFont->scaledCharInfo[glyph].numSegs);
628                                                 /* num segs             */
629         }
630
631         if (lineDrawFont->scaledCharInfo[glyph].numRects > 0) {
632             for (i = 0; i < lineDrawFont->scaledCharInfo[glyph].numRects; i++) {
633                 rects[i].x = x + lineDrawFont->scaledCharInfo[glyph].rects[i].x;
634                 rects[i].y =
635                         y + lineDrawFont->scaledCharInfo[glyph].rects[i].y -
636                         lineDrawFont->ascent;
637                 rects[i].width =
638                         lineDrawFont->scaledCharInfo[glyph].rects[i].width;
639                 rects[i].height =
640                         lineDrawFont->scaledCharInfo[glyph].rects[i].height;
641             }
642             (void) XFillRectangles(display,     /* Display              */
643                 d,                              /* dest                 */
644                 gc,                             /* GC                   */
645                 rects,                          /* rectangles           */
646                 lineDrawFont->scaledCharInfo[glyph].numRects);
647                                                 /* num rects            */
648         }
649 #endif  /* USE_PIXMAPS */
650         /* slide over one character... */
651         x += lineDrawFont->width;
652     }
653
654     _DtTermProcessUnlock();
655     return;
656 }