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 */
}
}
}
|