summaryrefslogtreecommitdiff
path: root/dviware/beebe/src/dispchar.h
blob: aa7c26a009272dea8ffa8daecd9c74c2c6a315d8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/* -*-C-*- dispchar.h */
/*-->dispchar*/
/**********************************************************************/
/****************************** dispchar ******************************/
/**********************************************************************/

void
dispchar(c)
BYTE c;		/* character number in current font */

/***********************************************************************

   This procedure has the delicate  job of OR'ing the current  character
   raster description into the bitmap,  where the character box  extends
   horizontally from  (xcorner  ..  xcorner+wp-1)  and  vertically  from
   (ycorner  ..   ycorner+hp-1).   The  lower  left  corner  coordinates
   (xcorner, ycorner) are  related to  the current point  (xcp, ycp)  as
   follows:

	<------wp------>
    ^	................
    |	................
    |	................
    |	................
    |	................
    |	................
    |	................
    hp  ................
    |	................
    |	................
    |	................
    |	.....o..........       <-- (xcp,ycp) at "o"
    |	................ ^
    |	................ |
    |	................ |--- (hp - yoffp - 1)
    |	................ |
    v	+............... v     <-- (xcorner,ycorner) at "+"
	<--->
	  |
	  |
	 xoffp

   The current PXL file format stores character rasters in 32-bit words,
   with the rightmost portion of the  last word in each line beyond  the
   edge of  the character  being all  0 bits.	For efficiency,  the  OR
   operation is done a word  at a time, and  in general, each such  word
   contributes to two words in the bitmap line.

	     line		    line		   line
   |.........word.........|.........word.........|.........word.........|

  32-bit chunks--> |.....chrast.....|.....chrast.....|.....chrast.....|

		   |<---->|<------->|
		       |       |
     bits_to_current---^       ^--- bits_to_next

   Thus, each  32-bit  chunk  will  be  right-shifted  (filling  vacated
   positions at the left with 0 bits) leaving "bits_to_current" bits  at
   the low end and then OR'd into the current word of the bitmap line.

   Since the C language  right-shift operator may  or may not  propagate
   the sign bit  (which is usually  at the left),  a compile-time  flag,
   ARITHRSHIFT, is necessary to include an extra AND operation to remove
   them  when	the  right-shift   is  implemented   by  an   arithmetic
   (sign-propagating), rather than a logical, shift.

   The 32-bit  chunk will  then  be left-shifted  (with 0  bits  filling
   vacated positions on  the right) leaving  "bits_to_next" bits at  the
   high end and OR'd into the next word of the bitmap line.

   When the host word  size exceeds 32 bits  (e.g. DEC-10 or -20  36-bit
   word), the  first step  may in  fact require  a left  shift, and  the
   second step is then not needed.   This is detected in the code  below
   by "bits_to_next" being negative.

***********************************************************************/
{
    register struct char_entry *tcharptr;
    COORDINATE x,xcorner,ycorner;
    UNSIGN16 ilimit;
    register INT16 bits_to_next;
    register UNSIGN16 i;
    UNSIGN32 word32;
    register UNSIGN32 *p;
    register UNSIGN32 *raster_word;
    register COORDINATE j;

    if ((c < FIRSTPXLCHAR) || (LASTPXLCHAR < c)) /* check character range */
	return;

    tcharptr = &(fontptr->ch[c]);

    if (tcharptr->rasters == (UNSIGN32*)NULL)/* if rasters still on file */
	loadchar(c);			/* go get them */

    if (tcharptr->rasters == (UNSIGN32*)NULL)
	return;	/* character image must be empty */

    tcharptr->refcount++;		/* update reference count */
    raster_word = tcharptr->rasters;	/* pointer to first raster word */

    xcorner = xcp - tcharptr->xoffp;
    ycorner = ycp - (tcharptr->hp - tcharptr->yoffp - 1);

    if (DBGOPT(DBG_CHAR_DUMP))
    {
	NEWLINE(stdout);
        (void)printf(
	    "dispchar(): (xcp,ycp) = (%d,%d) (xcorner,ycorner) = (%d,%d)",
	    xcp,ycp,xcorner,ycorner);
	NEWLINE(stdout);
	(void)printf("            (wp,hp) = (%d,%d)  (xoffp,yoffp) = (%d,%d)",
	    tcharptr->wp,tcharptr->hp,tcharptr->xoffp,tcharptr->yoffp);
	NEWLINE(stdout);
	ilimit = (UNSIGN16)((tcharptr->wp + 31) >> 5);
	for (j = tcharptr->hp; j > 0; --j)
	{
	    for (i = 0; i < ilimit; ++i)
	        (void)printf(" %08lx",*raster_word++);
	    NEWLINE(stdout);
	}
	raster_word = tcharptr->rasters;
    }

    for (j = tcharptr->hp; j > 0; --j)	/* loop over hp rasters from */
    {					/* top to bottom */
	x = xcorner;			/* select horizontal position */
	p = BITMAP(ycorner+j-1,x/HOST_WORD_SIZE); /* and find word on line */
	ilimit = (UNSIGN16)((tcharptr->wp + 31) >> 5);
	for (i = 0; i < ilimit; ++i)
	{		    /* loop over current line */
	    word32 = *raster_word++; /* get 32-bit portion of raster */
	    bits_to_next = (INT16)((x % HOST_WORD_SIZE) - HOST_WORD_SIZE + 32);

#if    (HOST_WORD_SIZE > 32)
	    if (bits_to_next < 0)   /* then must left shift character raster */
		*p |= (word32 << (-bits_to_next));  /* and OR into line */
	    else
#endif

	    {
		*p |=
#if    (IBM_PC_LATTICE | IBM_PC_MICROSOFT | IBM_PC_WIZARD)
/* these compilers correctly use a logical right shift for */
/* unsigned values */
#else
#if    ARITHRSHIFT	    /* arithmetic right shift propagates a sign */
			    /* bit which must be cleared by this AND  */
		      rightones[bits_to_next] &
#endif /* ARITHRSHIFT */
#endif /* (IBM_PC_LATTICE | IBM_PC_MICROSOFT | IBM_PC_WIZARD) */

		      (word32 >> bits_to_next);     /* OR into line */

		if (bits_to_next > 0)
		    *++p |= (word32 << (HOST_WORD_SIZE - bits_to_next));
			    /* OR in any spill into next word */
		else if (bits_to_next == 0)
		    ++p;    /* ended at word boundary, so start new one */
	    }
	    x += 32;	    /* and update horizontal position */
	}
    }
}