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