1 #   include	"bitmapConfig.h"
2 
3 #   include	"bmintern.h"
4 
5 #   include	<appDebugon.h>
6 
7 /************************************************************************/
8 /*									*/
9 /*  Set one run in a bitmap.						*/
10 /*  These routines only work for 1 bit/pixel.				*/
11 /*									*/
12 /*  1)  End point inclusive.						*/
13 /*									*/
14 /************************************************************************/
15 
16 static unsigned char BM_BitCounts[256];
17 
bmCount1Run1Bit(const unsigned char * buffer,int col0,int col1)18 static int bmCount1Run1Bit(	const unsigned char *	buffer,
19 				int			col0,
20 				int			col1 )
21     {
22     int				d;
23     unsigned char		c1, c2;
24     const unsigned char *	b1= (unsigned char *)0;
25     const unsigned char *	b2= (unsigned char *)0;
26 
27     int				count= 0;
28 
29     /*
30     APP_DEB(appDebug( "bmCount1Run(,col0=%d,col1=%d)\n", col0, col1 ));
31     */
32 
33     /*  1  */
34     col1++;
35 
36     d= ( col0 % 8 );
37     if  ( d )
38 	{
39 	b1= buffer+ col0/ 8;
40 
41 	col0= 8* ( col0/ 8 )+ 8;
42 
43 	c1= 0xff >> d;
44 	}
45     else{ c1= 0;	}
46 
47     d= ( col1 % 8 );
48     if  ( d )
49 	{
50 	b2= buffer+ col1/ 8;
51 
52 	col1= 8* ( col1/ 8 );
53 
54 	c2= 0xff << ( 8- d );
55 	}
56     else{ c2= 0;	}
57 
58     if  ( b1 )
59 	{
60 	if  ( b1 == b2 )
61 	    { count += BM_BitCounts[ *b1 & c1 & c2 ]; }
62 	else{
63 	    count += BM_BitCounts[ *b1 & c1 ];
64 	    }
65 	}
66 
67     if  ( b2 && b2 != b1 )
68 	{ count += BM_BitCounts[ *b2 & c2 ]; }
69 
70     col0 /= 8;
71     col1 /= 8;
72 
73     b1= buffer+ col0;
74     while( col0++ < col1 )
75 	{ count += BM_BitCounts[ *(b1++) ];	}
76 
77     return count;
78     }
79 
80 /************************************************************************/
81 /*									*/
82 /*  Count the number of bits set to 0 on a horizontal stretch.		*/
83 /*									*/
84 /*  1)  Switch to 'upto' semantics.					*/
85 /*  2)  If the beginning is not on a byte boundary, obtain a mask for	*/
86 /*	the tail of the byte. Exclude this byte from the count below	*/
87 /*  3)  If the end is not on a byte boundary, obtain a mask for	the	*/
88 /*	head of the byte. Exclude this byte from the count below	*/
89 /*  4)  Count bits in the head byte. Handle the situation where head	*/
90 /*	and tail refer to the same byte.				*/
91 /*  5)  Count bits in the tail byte. (Unless head and tail are the same)*/
92 /*  6)  Count bits in the bytes between head and tail.			*/
93 /*									*/
94 /************************************************************************/
95 
bmCount0Run1Bit(const unsigned char * buffer,int col0,int col1)96 static int bmCount0Run1Bit(	const unsigned char *	buffer,
97 				int			col0,
98 				int			col1 )
99     {
100     int				d;
101     unsigned char		c1, c2;
102     const unsigned char *	b1= (unsigned char *)0;
103     const unsigned char *	b2= (unsigned char *)0;
104 
105     int				count= 0;
106 
107     /*  1  */
108     col1++;
109 
110     /*  2  */
111     d= ( col0 % 8 );
112     if  ( d )
113 	{
114 	b1= buffer+ col0/ 8;
115 
116 	col0= 8* ( col0/ 8 )+ 8;
117 
118 	c1= 0xff >> d; c1= ~c1;
119 	}
120     else{ c1= 0xff;	}
121 
122     /*  3  */
123     d= ( col1 % 8 );
124     if  ( d )
125 	{
126 	b2= buffer+ col1/ 8;
127 
128 	col1= 8* ( col1/ 8 );
129 
130 	c2= 0xff << ( 8- d ); c2= ~c2;
131 	}
132     else{ c2= 0xff;	}
133 
134     /*  4  */
135     if  ( b1 )
136 	{
137 	if  ( b1 == b2 )
138 	    { count += 8- BM_BitCounts[ *b1 | c1 | c2 ];	}
139 	else{ count += 8- BM_BitCounts[ *b1 | c1 ];		}
140 	}
141 
142     if  ( b2 && b2 != b1 )
143 	{ count += 8- BM_BitCounts[ *b2 | c2 ]; }
144 
145     col0 /= 8;
146     col1 /= 8;
147 
148     b1= buffer+ col0;
149     while( col0++ < col1 )
150 	{ count += 8- (int)BM_BitCounts[ *(b1++) ];	}
151 
152     return count;
153     }
154 
155 /************************************************************************/
156 /*									*/
157 /*  count a line using Bressenham.					*/
158 /*									*/
159 /*  1)  Line is supposed to be to the right.				*/
160 /*									*/
161 /************************************************************************/
162 
bmCountBres1Line1Bit(const unsigned char * buffer,int x0,int y0,int x1,int y1,int bytesPerRow)163 static int bmCountBres1Line1Bit(
164 				const unsigned char *	buffer,
165 				int			x0,
166 				int			y0,
167 				int			x1,
168 				int			y1,
169 				int			bytesPerRow )
170     {
171     int			dx;
172     int			dy;
173     int			i;
174 
175     int			e, d2, e2;
176 
177     unsigned char	byteMask;
178 
179     int			count= 0;
180 
181     dx= x1- x0;
182     dy= y1- y0;
183 
184     /*  1  */
185     if  ( dx < 0 )
186 	{ LDEB(dx); return 0;	}
187 
188     buffer += y0* bytesPerRow+ x0/ 8;
189     byteMask= 0x80 >> ( x0 % 8 );
190 
191     if  ( dy < 0 )
192 	{ dy = -dy; bytesPerRow= -bytesPerRow; }
193 
194     if  ( dx > dy )
195 	{
196 	e= 2* dy- dx;
197 	d2= 2* dx;
198 	e2= 2* dy;
199 
200 	while( x0 <= x1 )
201 	    {
202 	    count += BM_BitCounts[ *buffer & byteMask ];
203 
204 	    while( e >= 0 )
205 		{ buffer += bytesPerRow; e -= d2; }
206 
207 	    byteMask >>= 1; x0++; e += e2;
208 
209 	    if  ( ! ( x0 % 8 ) )
210 		{ buffer++; byteMask= 0x80;	}
211 	    }
212 	}
213     else{
214 	e= 2* dx- dy;
215 	d2= 2* dy;
216 	e2= 2* dx;
217 
218 	for ( i= 0; i <= dy; i++ )
219 	    {
220 	    count += BM_BitCounts[ *buffer & byteMask ];
221 
222 	    while( e > 0 )
223 		{
224 		byteMask >>= 1; x0++; e -= d2;
225 
226 		if  ( ! ( x0 % 8 ) )
227 		    { buffer++; byteMask= 0x80;	}
228 		}
229 
230 	    buffer += bytesPerRow; e += e2;
231 	    }
232 	}
233 
234     return count;
235     }
236 
bmCountBres0Line1Bit(const unsigned char * buffer,int x0,int y0,int x1,int y1,int bytesPerRow)237 static int bmCountBres0Line1Bit(
238 				const unsigned char *	buffer,
239 				int			x0,
240 				int			y0,
241 				int			x1,
242 				int			y1,
243 				int			bytesPerRow )
244     {
245     int			dx;
246     int			dy;
247     int			i;
248 
249     int			e, d2, e2;
250 
251     unsigned char	byteMask;
252 
253     int			count= 0;
254 
255     dx= x1- x0;
256     dy= y1- y0;
257 
258     /*  1  */
259     if  ( dx < 0 )
260 	{ LDEB(dx); return 0;	}
261 
262     buffer += y0* bytesPerRow+ x0/ 8;
263     byteMask= 0x80 >> ( x0 % 8 ); byteMask= ~byteMask;
264 
265     if  ( dy < 0 )
266 	{ dy = -dy; bytesPerRow= -bytesPerRow; }
267 
268     if  ( dx > dy )
269 	{
270 	e= 2* dy- dx;
271 	d2= 2* dx;
272 	e2= 2* dy;
273 
274 	while( x0 <= x1 )
275 	    {
276 	    count += 8- BM_BitCounts[ *buffer | byteMask ];
277 
278 	    while( e >= 0 )
279 		{ buffer += bytesPerRow; e -= d2; }
280 
281 	    byteMask >>= 1; byteMask |= 0x80; x0++; e += e2;
282 
283 	    if  ( ! ( x0 % 8 ) )
284 		{ buffer++; byteMask= 0x7f;	}
285 	    }
286 	}
287     else{
288 	e= 2* dx- dy;
289 	d2= 2* dy;
290 	e2= 2* dx;
291 
292 	for ( i= 0; i <= dy; i++ )
293 	    {
294 	    count += 8- BM_BitCounts[ *buffer | byteMask ];
295 
296 	    while( e > 0 )
297 		{
298 		byteMask >>= 1; byteMask |= 0x80; x0++; e -= d2;
299 
300 		if  ( ! ( x0 % 8 ) )
301 		    { buffer++; byteMask= 0x7f;	}
302 		}
303 
304 	    buffer += bytesPerRow; e += e2;
305 	    }
306 	}
307 
308     return count;
309     }
310 
311 
312 /************************************************************************/
313 /*									*/
314 /*  Draw a line segment.						*/
315 /*									*/
316 /*  1)  Make it vertical or to the right.				*/
317 /*									*/
318 /************************************************************************/
319 
bmCountLinePixels(const unsigned char * buffer,const BitmapDescription * bd,int x0,int y0,int x1,int y1)320 int bmCountLinePixels(	const unsigned char *		buffer,
321 			const BitmapDescription *	bd,
322 			int				x0,
323 			int				y0,
324 			int				x1,
325 			int				y1 )
326     {
327     int		i;
328     int		count= 0;
329 
330     int		(*countRun)(	const unsigned char *	_buffer,
331 				int			_x0,
332 				int			_y0 );
333 
334     int		(*countLine)(	const unsigned char *	_buffer,
335 				int			_x0,
336 				int			_y0,
337 				int			_x1,
338 				int			_y1,
339 				int			_bytesPerRow );
340 
341     switch( bd->bdColorEncoding )
342 	{
343 	case BMcoBLACKWHITE:
344 	    if  ( bd->bdBitsPerPixel != 1 )
345 		{
346 		LLDEB(bd->bdColorEncoding,bd->bdBitsPerPixel);
347 		return -1;
348 		}
349 
350 	    countLine= bmCountBres1Line1Bit;
351 	    countRun= bmCount1Run1Bit;
352 	    break;
353 
354 	case BMcoWHITEBLACK:
355 	    if  ( bd->bdBitsPerPixel != 1 )
356 		{
357 		LLDEB(bd->bdColorEncoding,bd->bdBitsPerPixel);
358 		return -1;
359 		}
360 
361 	    countLine= bmCountBres0Line1Bit;
362 	    countRun= bmCount0Run1Bit;
363 	    break;
364 
365 	default:
366 	    LDEB(bd->bdColorEncoding);
367 	    return -1;
368 	}
369 
370 
371     if  ( x0 < 0 || x0 >= bd->bdPixelsWide )
372 	{ LLDEB(x0,bd->bdPixelsWide); return -1; }
373     if  ( x1 < 0 || x1 >= bd->bdPixelsWide )
374 	{ LLDEB(x1,bd->bdPixelsWide); return -1; }
375     if  ( y0 < 0 || y0 >= bd->bdPixelsHigh )
376 	{ LLDEB(y0,bd->bdPixelsHigh); return -1; }
377     if  ( y1 < 0 || y1 >= bd->bdPixelsHigh )
378 	{ LLDEB(y1,bd->bdPixelsHigh); return -1; }
379 
380 
381     if  ( BM_BitCounts[1] == 0 )
382 	{
383 	int	pos;
384 
385 	for ( pos= 0; pos < 256; pos++ )
386 	    {
387 	    unsigned int	p= pos;
388 
389 	    BM_BitCounts[pos]= 0;
390 
391 	    while( p )
392 		{
393 		if  ( p & 0x01 )
394 		    { BM_BitCounts[pos]++;	}
395 
396 		p >>= 1;
397 		}
398 	    }
399 	}
400 
401     /*  1  */
402     if  ( x0 > x1 )
403 	{ i= x0; x0= x1; x1= i; i= y0; y0= y1; y1= i; }
404 
405     if  ( y1 == y0 )
406 	{
407 	count += (*countRun)( buffer+ y0* bd->bdBytesPerRow, x0, x1 );
408 	return count;
409 	}
410 
411     if  ( x1 == x0 )
412 	{
413 	if  ( y1 < y0 )
414 	    { i= y0; y0= y1; y1= i; }
415 
416 	buffer += y0* bd->bdBytesPerRow;
417 
418 	while( y0 <= y1 )
419 	    {
420 	    count += (*countRun)( buffer, x0, x1 );
421 
422 	    y0++; buffer += bd->bdBytesPerRow;
423 	    }
424 
425 	return count;
426 	}
427 
428     count += (*countLine)( buffer, x0, y0, x1, y1, bd->bdBytesPerRow );
429 
430     return count;
431     }
432