1 #   include	"bitmapConfig.h"
2 
3 #   include	"bmintern.h"
4 #   include	<string.h>
5 #   include	<stdlib.h>
6 
7 #   define	y0	math_y0
8 #   define	y1	math_y1
9 #   include	<math.h>
10 #   undef	y0
11 #   undef	y1
12 
13 #   include	<appDebugon.h>
14 
15 /************************************************************************/
16 /*									*/
17 /*  Set one run in a bitmap.						*/
18 /*  These routines only work for 1 bit/pixel.				*/
19 /*									*/
20 /*  1)  End point inclusive.						*/
21 /*									*/
22 /************************************************************************/
23 
bmDraw1Run1Bit(unsigned char * buffer,int col0,int col1)24 static void bmDraw1Run1Bit(	unsigned char *	buffer,
25 				int		col0,
26 				int		col1 )
27     {
28     int			d;
29     unsigned char	c1, c2;
30     unsigned char *	b1= (unsigned char *)0;
31     unsigned char *	b2= (unsigned char *)0;
32 
33     /*
34     APP_DEB(appDebug( "bmDraw1Run(,col0=%d,col1=%d)\n", col0, col1 ));
35     */
36 
37     /*  1  */
38     col1++;
39 
40     d= ( col0 % 8 );
41     if  ( d )
42 	{
43 	b1= buffer+ col0/ 8;
44 
45 	col0= 8* ( col0/ 8 )+ 8;
46 
47 	c1= 0xff >> d;
48 	}
49     else{ c1= 0;	}
50 
51     d= ( col1 % 8 );
52     if  ( d )
53 	{
54 	b2= buffer+ col1/ 8;
55 
56 	col1= 8* ( col1/ 8 );
57 
58 	c2= 0xff << ( 8- d );
59 	}
60     else{ c2= 0;	}
61 
62     if  ( b1 )
63 	{
64 	if  ( b1 == b2 )
65 	    { *b1 |= c1 & c2; }
66 	else{
67 	    *b1 |= c1;
68 	    }
69 	}
70 
71     if  ( b2 && b2 != b1 )
72 	{ *b2 |= c2; }
73 
74     col0 /= 8;
75     col1 /= 8;
76 
77     b1= buffer+ col0;
78     while( col0++ < col1 )
79 	{ *(b1++)= 0xff;	}
80 
81     return;
82     }
83 
bmDraw0Run1Bit(unsigned char * buffer,int col0,int col1)84 static void bmDraw0Run1Bit(	unsigned char *	buffer,
85 				int		col0,
86 				int		col1 )
87     {
88     int			d;
89     unsigned char	c1, c2;
90     unsigned char *	b1= (unsigned char *)0;
91     unsigned char *	b2= (unsigned char *)0;
92 
93     /*
94     APP_DEB(appDebug( "bmDraw0Run(,col0=%d,col1=%d)\n", col0, col1 ));
95     */
96 
97     /*  1  */
98     col1++;
99 
100     d= ( col0 % 8 );
101     if  ( d )
102 	{
103 	b1= buffer+ col0/ 8;
104 
105 	col0= 8* ( col0/ 8 )+ 8;
106 
107 	c1= 0xff >> d; c1= ~c1;
108 	}
109     else{ c1= 0xff;	}
110 
111     d= ( col1 % 8 );
112     if  ( d )
113 	{
114 	b2= buffer+ col1/ 8;
115 
116 	col1= 8* ( col1/ 8 );
117 
118 	c2= 0xff << ( 8- d ); c2= ~c2;
119 	}
120     else{ c2= 0xff;	}
121 
122     if  ( b1 )
123 	{
124 	if  ( b1 == b2 )
125 	    { *b1 &= c1 | c2; }
126 	else{
127 	    *b1 &= c1;
128 	    }
129 	}
130 
131     if  ( b2 && b2 != b1 )
132 	{ *b2 &= c2; }
133 
134     col0 /= 8;
135     col1 /= 8;
136 
137     b1= buffer+ col0;
138     while( col0++ < col1 )
139 	{ *(b1++)= 0x00;	}
140 
141     return;
142     }
143 
144 /************************************************************************/
145 /*									*/
146 /*  Fill a rectangular area.						*/
147 /*									*/
148 /************************************************************************/
149 
bmFillBlock(unsigned char * buffer,int x0,int y0,int x1,int y1,int bytesPerRow)150 int bmFillBlock(	unsigned char *		buffer,
151 			int			x0,
152 			int			y0,
153 			int			x1,
154 			int			y1,
155 			int			bytesPerRow )
156     {
157     int		sw;
158 
159     /*
160     APP_DEB(appDebug( "bmFillBlock(,x0=%d,y0=%d,x1=%d,y1=%d,bpr=%d,)\n",
161 		x0, y0, x1, y1, bytesPerRow ));
162     */
163 
164     if  ( x1 < x0 )
165 	{ sw= x1; x1= x0; x0= sw;	}
166     if  ( y1 < y0 )
167 	{ sw= y1; y1= y0; y0= sw;	}
168 
169     buffer += y0* bytesPerRow;
170 
171     while( y0 <= y1 )
172 	{
173 	bmDraw1Run1Bit( buffer, x0, x1 );
174 	y0++; buffer += bytesPerRow;
175 	}
176 
177     return 0;
178     }
179 
180 /************************************************************************/
181 /*									*/
182 /*  Allocate and initialise a buffer on which something can be drawn	*/
183 /*									*/
184 /************************************************************************/
185 
bmBackgroundBuffer(int bufferLength,int colorEncoding)186 unsigned char *	bmBackgroundBuffer(	int	bufferLength,
187 					int	colorEncoding )
188     {
189     unsigned char *	buffer= (unsigned char *)malloc( bufferLength );
190 
191     if  ( ! buffer )
192 	{ LLDEB(bufferLength,buffer); return buffer;	}
193 
194     switch( colorEncoding )
195 	{
196 	case	BMcoBLACKWHITE:
197 	    memset( buffer, 0x00, bufferLength );
198 	    break;
199 
200 	case	BMcoWHITEBLACK:
201 	case	BMcoRGB:
202 	    memset( buffer, 0xff, bufferLength );
203 	    break;
204 
205 	default:
206 	    LDEB(colorEncoding);
207 	    free( buffer );
208 	    return (unsigned char *)0;
209 	}
210 
211     return buffer;
212     }
213 
bmForegroundBuffer(int bufferLength,int colorEncoding)214 unsigned char *	bmForegroundBuffer(	int	bufferLength,
215 					int	colorEncoding )
216     {
217     unsigned char *	buffer= (unsigned char *)malloc( bufferLength );
218 
219     if  ( ! buffer )
220 	{ LLDEB(bufferLength,buffer); return buffer;	}
221 
222     switch( colorEncoding )
223 	{
224 	case	BMcoBLACKWHITE:
225 	    memset( buffer, 0xff, bufferLength );
226 	    break;
227 
228 	case	BMcoWHITEBLACK:
229 	case	BMcoRGB:
230 	    memset( buffer, 0x00, bufferLength );
231 	    break;
232 
233 	default:
234 	    LDEB(colorEncoding);
235 	    free( buffer );
236 	    return (unsigned char *)0;
237 	}
238 
239     return buffer;
240     }
241 
242 /************************************************************************/
243 /*									*/
244 /*  Convenience routine: Draw a box.					*/
245 /*									*/
246 /************************************************************************/
247 
bmDrawBox(unsigned char * buffer,const BitmapDescription * bd,int x0,int y0,int x1,int y1,int wide)248 int bmDrawBox(	unsigned char *			buffer,
249 		const BitmapDescription *	bd,
250 		int				x0,
251 		int				y0,
252 		int				x1,
253 		int				y1,
254 		int				wide )
255     {
256     if  ( bmDrawLine( buffer, bd, x0, y0+ wide/2, x1, y0+ wide/2, wide ) )
257 	{ LDEB(1); return -1; }
258 
259     if  ( bmDrawLine( buffer, bd, x0, y1- wide/2, x1, y1- wide/2, wide ) )
260 	{ LDEB(1); return -1; }
261 
262     if  ( bmDrawLine( buffer, bd, x0+ wide/2, y0, x0+ wide/2, y1, wide ) )
263 	{ LDEB(1); return -1; }
264 
265     if  ( bmDrawLine( buffer, bd, x1- wide/2, y0, x1- wide/2, y1, wide ) )
266 	{ LDEB(1); return -1; }
267 
268     return 0;
269     }
270 
271 /************************************************************************/
272 /*									*/
273 /*  draw a line using Bressenham.					*/
274 /*									*/
275 /*  1)  Line is supposed to be to the right.				*/
276 /*									*/
277 /************************************************************************/
278 
bmDrawBres1Line1Bit(unsigned char * buffer,int x0,int y0,int x1,int y1,int bytesPerRow)279 static void bmDrawBres1Line1Bit(unsigned char *		buffer,
280 				int			x0,
281 				int			y0,
282 				int			x1,
283 				int			y1,
284 				int			bytesPerRow )
285     {
286     int			dx;
287     int			dy;
288     int			i;
289 
290     int			e, d2, e2;
291 
292     unsigned char	byteMask;
293 
294     dx= x1- x0;
295     dy= y1- y0;
296 
297     /*  1  */
298     if  ( dx < 0 )
299 	{ LDEB(dx); return;	}
300 
301     buffer += y0* bytesPerRow+ x0/ 8;
302     byteMask= 0x80 >> ( x0 % 8 );
303 
304     if  ( dy < 0 )
305 	{ dy = -dy; bytesPerRow= -bytesPerRow; }
306 
307     if  ( dx > dy )
308 	{
309 	e= 2* dy- dx;
310 	d2= 2* dx;
311 	e2= 2* dy;
312 
313 	while( x0 <= x1 )
314 	    {
315 	    *buffer |= byteMask;
316 
317 	    while( e >= 0 )
318 		{ buffer += bytesPerRow; e -= d2; }
319 
320 	    byteMask >>= 1; x0++; e += e2;
321 
322 	    if  ( ! ( x0 % 8 ) )
323 		{ buffer++; byteMask= 0x80;	}
324 	    }
325 	}
326     else{
327 	e= 2* dx- dy;
328 	d2= 2* dy;
329 	e2= 2* dx;
330 
331 	for ( i= 0; i <= dy; i++ )
332 	    {
333 	    *buffer |= byteMask;
334 
335 	    while( e > 0 )
336 		{
337 		byteMask >>= 1; x0++; e -= d2;
338 
339 		if  ( ! ( x0 % 8 ) )
340 		    { buffer++; byteMask= 0x80;	}
341 		}
342 
343 	    buffer += bytesPerRow; e += e2;
344 	    }
345 	}
346     }
347 
bmDrawBres0Line1Bit(unsigned char * buffer,int x0,int y0,int x1,int y1,int bytesPerRow)348 static void bmDrawBres0Line1Bit(unsigned char *		buffer,
349 				int			x0,
350 				int			y0,
351 				int			x1,
352 				int			y1,
353 				int			bytesPerRow )
354     {
355     int			dx;
356     int			dy;
357     int			i;
358 
359     int			e, d2, e2;
360 
361     unsigned char	byteMask;
362 
363     dx= x1- x0;
364     dy= y1- y0;
365 
366     /*  1  */
367     if  ( dx < 0 )
368 	{ LDEB(dx); return;	}
369 
370     buffer += y0* bytesPerRow+ x0/ 8;
371     byteMask= 0x80 >> ( x0 % 8 ); byteMask= ~byteMask;
372 
373     if  ( dy < 0 )
374 	{ dy = -dy; bytesPerRow= -bytesPerRow; }
375 
376     if  ( dx > dy )
377 	{
378 	e= 2* dy- dx;
379 	d2= 2* dx;
380 	e2= 2* dy;
381 
382 	while( x0 <= x1 )
383 	    {
384 	    *buffer &= byteMask;
385 
386 	    while( e >= 0 )
387 		{ buffer += bytesPerRow; e -= d2; }
388 
389 	    byteMask >>= 1; byteMask |= 0x80; x0++; e += e2;
390 
391 	    if  ( ! ( x0 % 8 ) )
392 		{ buffer++; byteMask= 0x7f;	}
393 	    }
394 	}
395     else{
396 	e= 2* dx- dy;
397 	d2= 2* dy;
398 	e2= 2* dx;
399 
400 	for ( i= 0; i <= dy; i++ )
401 	    {
402 	    *buffer &= byteMask;
403 
404 	    while( e > 0 )
405 		{
406 		byteMask >>= 1; byteMask |= 0x80; x0++; e -= d2;
407 
408 		if  ( ! ( x0 % 8 ) )
409 		    { buffer++; byteMask= 0x7f;	}
410 		}
411 
412 	    buffer += bytesPerRow; e += e2;
413 	    }
414 	}
415     }
416 
417 /************************************************************************/
418 /*									*/
419 /*  Set one run in a bitmap.						*/
420 /*  These routines only work for RGB, 24 bit/pixel.			*/
421 /*									*/
422 /*  1)  End point inclusive.						*/
423 /*  2)  Line is supposed to ro to the right.				*/
424 /*									*/
425 /************************************************************************/
426 
bmDrawRun24Bit(unsigned char * buffer,int col0,int col1)427 static void bmDrawRun24Bit(	unsigned char *	buffer,
428 				int		col0,
429 				int		col1 )
430     {
431     /*  1  */
432     memset( buffer+ 3* col0, 0x00, 3* ( col1- col0 ) );
433     }
434 
bmDrawBresLine24Bit(unsigned char * buffer,int x0,int y0,int x1,int y1,int bytesPerRow)435 static void bmDrawBresLine24Bit(unsigned char *		buffer,
436 				int			x0,
437 				int			y0,
438 				int			x1,
439 				int			y1,
440 				int			bytesPerRow )
441     {
442     int			dx;
443     int			dy;
444     int			i;
445 
446     int			e, d2, e2;
447 
448     dx= x1- x0;
449     dy= y1- y0;
450 
451     /*  2  */
452     if  ( dx < 0 )
453 	{ LDEB(dx); return;	}
454 
455     buffer += y0* bytesPerRow+ 3* x0;
456 
457     if  ( dy < 0 )
458 	{ dy = -dy; bytesPerRow= -bytesPerRow; }
459 
460     if  ( dx > dy )
461 	{
462 	e= 2* dy- dx;
463 	d2= 2* dx;
464 	e2= 2* dy;
465 
466 	while( x0 <= x1 )
467 	    {
468 	    buffer[0]= 0x00; buffer[1]= 0x00; buffer[2]= 0x00;
469 
470 	    while( e >= 0 )
471 		{ buffer += bytesPerRow; e -= d2; }
472 
473 	    buffer += 3; x0++; e += e2;
474 	    }
475 	}
476     else{
477 	e= 2* dx- dy;
478 	d2= 2* dy;
479 	e2= 2* dx;
480 
481 	for ( i= 0; i <= dy; i++ )
482 	    {
483 	    buffer[0]= 0x00; buffer[1]= 0x00; buffer[2]= 0x00;
484 
485 	    while( e > 0 )
486 		{
487 		buffer += 3; x0++; e -= d2;
488 		}
489 
490 	    buffer += bytesPerRow; e += e2;
491 	    }
492 	}
493     }
494 
495 
496 /************************************************************************/
497 /*									*/
498 /*  Draw a line segment.						*/
499 /*									*/
500 /*  1)  Make it vertical or to the right.				*/
501 /*									*/
502 /************************************************************************/
503 
bmDrawLine(unsigned char * buffer,const BitmapDescription * bd,int x0,int y0,int x1,int y1,int wide)504 int bmDrawLine(	unsigned char *			buffer,
505 		const BitmapDescription *	bd,
506 		int				x0,
507 		int				y0,
508 		int				x1,
509 		int				y1,
510 		int				wide )
511     {
512     int		i;
513 
514     int		wx;
515     int		wy;
516 
517     int		dx;
518     int		dy;
519     int		sy;
520 
521     int		e, d2, e2;
522 
523     void	(*drawRun)(	unsigned char *	_buffer,
524 				int		_x0,
525 				int		_y0 );
526 
527     void	(*drawLine)(	unsigned char *	_buffer,
528 				int		_x0,
529 				int		_y0,
530 				int		_x1,
531 				int		_y1,
532 				int		_bytesPerRow );
533 
534     switch( bd->bdColorEncoding )
535 	{
536 	case BMcoBLACKWHITE:
537 	    if  ( bd->bdBitsPerPixel != 1 )
538 		{
539 		LLDEB(bd->bdColorEncoding,bd->bdBitsPerPixel);
540 		return -1;
541 		}
542 
543 	    drawLine= bmDrawBres1Line1Bit;
544 	    drawRun= bmDraw1Run1Bit;
545 	    break;
546 
547 	case BMcoWHITEBLACK:
548 	    if  ( bd->bdBitsPerPixel != 1 )
549 		{
550 		LLDEB(bd->bdColorEncoding,bd->bdBitsPerPixel);
551 		return -1;
552 		}
553 
554 	    drawLine= bmDrawBres0Line1Bit;
555 	    drawRun= bmDraw0Run1Bit;
556 	    break;
557 
558 	case BMcoRGB:
559 	    if  ( bd->bdBitsPerPixel != 24 )
560 		{
561 		LLDEB(bd->bdColorEncoding,bd->bdBitsPerPixel);
562 		return -1;
563 		}
564 
565 	    drawLine= bmDrawBresLine24Bit;
566 	    drawRun= bmDrawRun24Bit;
567 	    break;
568 
569 	default:
570 	    LDEB(bd->bdColorEncoding);
571 	    return -1;
572 	}
573 
574     /*  1  */
575     if  ( x0 > x1 )
576 	{ i= x0; x0= x1; x1= i; i= y0; y0= y1; y1= i; }
577 
578     if  ( y1 == y0 )
579 	{
580 	if  ( wide > 1 )
581 	    {
582 	    y0 -= wide/2; y1= y0+ wide;
583 	    }
584 
585 	buffer += y0* bd->bdBytesPerRow;
586 	while( y0 <= y1 )
587 	    {
588 	    (*drawRun)( buffer, x0, x1 );
589 
590 	    y0++; buffer += bd->bdBytesPerRow;
591 	    }
592 
593 	return 0;
594 	}
595 
596     if  ( x1 == x0 )
597 	{
598 	if  ( wide > 1 )
599 	    {
600 	    x0 -= wide/2; x1= x0+ wide;
601 	    }
602 
603 	if  ( y0 > y1 )
604 	    { i= y0; y0= y1; y1= i;	}
605 
606 	buffer += y0* bd->bdBytesPerRow;
607 	while( y0 <= y1 )
608 	    {
609 	    (*drawRun)( buffer, x0, x1 );
610 
611 	    y0++; buffer += bd->bdBytesPerRow;
612 	    }
613 
614 	return 0;
615 	}
616 
617     dx= x1- x0;
618     dy= y1- y0;
619 
620     wx= wy= 1;
621     if  ( wide != 1 )
622 	{
623 	sy= sqrt( (double)( dx*dx + dy*dy ) );
624 	wx= ( dy* wide )/ sy;
625 	wy= ( dx* wide )/ sy;
626 	}
627 
628     if  ( dy > 0 )
629 	{ sy= -1;			}
630     else{ sy=  1; dy= -dy; wx= -wx;	}
631 
632     if  ( wx > wy )
633 	{
634 	if  ( wx == 0 )
635 	    { wx= 1;	}
636 
637 	e= 2* wy- wx;
638 	d2= 2* wx;
639 	e2= 2* wy;
640 
641 	x0 -= wx/2;
642 	x1 -= wx/2;
643 	y0 -= sy* wy/2;
644 	y1 -= sy* wy/2;
645 
646 	for ( i= 0; i < wx; i++ )
647 	    {
648 	    (*drawLine)( buffer, x0, y0, x1, y1, bd->bdBytesPerRow );
649 
650 	    if  ( wide > 1 )
651 	    while( e >= 0 )
652 		{
653 		y0 += sy; y1 += sy; e -= d2;
654 		(*drawLine)( buffer, x0, y0, x1, y1, bd->bdBytesPerRow );
655 		}
656 	    x0++; x1++; e += e2;
657 	    }
658 	}
659     else{
660 	if  ( wy == 0 )
661 	    { wy= 1;	}
662 
663 	e= 2* wx- wy;
664 	d2= 2* wy;
665 	e2= 2* wx;
666 
667 	x0 -= wx/2;
668 	x1 -= wx/2;
669 	y0 -= wy/2;
670 	y1 -= wy/2;
671 
672 	for ( i= 0; i < wy; i++ )
673 	    {
674 	    (*drawLine)( buffer, x0, y0, x1, y1, bd->bdBytesPerRow );
675 
676 	    if  ( wide > 1 )
677 	    while( e >= 0 )
678 		{
679 		x0++; x1++; e -= d2;
680 		(*drawLine)( buffer, x0, y0, x1, y1, bd->bdBytesPerRow );
681 		}
682 	    y0++; y1++; e += e2;
683 	    }
684 	}
685 
686     return 0;
687     }
688