1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41 #include "_cxcore.h"
42 
43 #define  XY_SHIFT  16
44 #define  XY_ONE    (1 << XY_SHIFT)
45 
46 #define CV_DRAWING_STORAGE_BLOCK ((1 << 12) - 256)
47 
48 typedef struct CvPolyEdge
49 {
50     int x, dx;
51     union
52     {
53         struct CvPolyEdge *next;
54         int y0;
55     };
56     int y1;
57 }
58 CvPolyEdge;
59 
60 static void
61 icvCollectPolyEdges( CvMat* img, CvSeq* v, CvContour* edges,
62                      const void* color, int line_type,
63                      int shift, CvPoint offset=cvPoint(0,0) );
64 
65 static void
66 icvFillEdgeCollection( CvMat* img, CvContour* edges, const void* color );
67 
68 static void
69 icvPolyLine( CvMat* img, CvPoint *v, int count, int closed,
70              const void* color, int thickness, int line_type, int shift );
71 
72 static void
73 icvFillConvexPoly( CvMat* img, CvPoint* v, int npts,
74                    const void* color, int line_type, int shift );
75 
76 /****************************************************************************************\
77 *                                   Lines                                                *
78 \****************************************************************************************/
79 
80 CV_IMPL int
cvClipLine(CvSize img_size,CvPoint * pt1,CvPoint * pt2)81 cvClipLine( CvSize img_size, CvPoint* pt1, CvPoint* pt2 )
82 {
83     int result = 0;
84 
85     CV_FUNCNAME( "cvClipLine" );
86 
87     __BEGIN__;
88 
89     int x1, y1, x2, y2;
90     int c1, c2;
91     int right = img_size.width-1, bottom = img_size.height-1;
92 
93     if( !pt1 || !pt2 )
94         CV_ERROR( CV_StsNullPtr, "One of point pointers is NULL" );
95 
96     if( right < 0 || bottom < 0 )
97         CV_ERROR( CV_StsOutOfRange, "Image width or height are negative" );
98 
99     x1 = pt1->x; y1 = pt1->y; x2 = pt2->x; y2 = pt2->y;
100     c1 = (x1 < 0) + (x1 > right) * 2 + (y1 < 0) * 4 + (y1 > bottom) * 8;
101     c2 = (x2 < 0) + (x2 > right) * 2 + (y2 < 0) * 4 + (y2 > bottom) * 8;
102 
103     if( (c1 & c2) == 0 && (c1 | c2) != 0 )
104     {
105         int a;
106 
107         if( c1 & 12 )
108         {
109             a = c1 < 8 ? 0 : bottom;
110             x1 += (int) (((int64) (a - y1)) * (x2 - x1) / (y2 - y1));
111             y1 = a;
112             c1 = (x1 < 0) + (x1 > right) * 2;
113         }
114         if( c2 & 12 )
115         {
116             a = c2 < 8 ? 0 : bottom;
117             x2 += (int) (((int64) (a - y2)) * (x2 - x1) / (y2 - y1));
118             y2 = a;
119             c2 = (x2 < 0) + (x2 > right) * 2;
120         }
121         if( (c1 & c2) == 0 && (c1 | c2) != 0 )
122         {
123             if( c1 )
124             {
125                 a = c1 == 1 ? 0 : right;
126                 y1 += (int) (((int64) (a - x1)) * (y2 - y1) / (x2 - x1));
127                 x1 = a;
128                 c1 = 0;
129             }
130             if( c2 )
131             {
132                 a = c2 == 1 ? 0 : right;
133                 y2 += (int) (((int64) (a - x2)) * (y2 - y1) / (x2 - x1));
134                 x2 = a;
135                 c2 = 0;
136             }
137         }
138 
139         assert( (c1 & c2) != 0 || (x1 | y1 | x2 | y2) >= 0 );
140 
141         pt1->x = x1;
142         pt1->y = y1;
143         pt2->x = x2;
144         pt2->y = y2;
145     }
146 
147     result = ( c1 | c2 ) == 0;
148 
149     __END__;
150 
151     return result;
152 }
153 
154 
155 /*
156    Initializes line iterator.
157    Returns number of points on the line or negative number if error.
158 */
159 CV_IMPL int
cvInitLineIterator(const CvArr * img,CvPoint pt1,CvPoint pt2,CvLineIterator * iterator,int connectivity,int left_to_right)160 cvInitLineIterator( const CvArr* img, CvPoint pt1, CvPoint pt2,
161                     CvLineIterator* iterator, int connectivity,
162                     int left_to_right )
163 {
164     int count = -1;
165 
166     CV_FUNCNAME( "cvInitLineIterator" );
167 
168     __BEGIN__;
169 
170     CvMat stub, *mat = (CvMat*)img;
171     int dx, dy, s;
172     int bt_pix, bt_pix0, step;
173 
174     if( !CV_IS_MAT(mat) )
175         CV_CALL( mat = cvGetMat( mat, &stub ));
176 
177     if( !iterator )
178         CV_ERROR( CV_StsNullPtr, "Pointer to the iterator state is NULL" );
179 
180     if( connectivity != 8 && connectivity != 4 )
181         CV_ERROR( CV_StsBadArg, "Connectivity must be 8 or 4" );
182 
183     if( (unsigned)pt1.x >= (unsigned)(mat->width) ||
184         (unsigned)pt2.x >= (unsigned)(mat->width) ||
185         (unsigned)pt1.y >= (unsigned)(mat->height) ||
186         (unsigned)pt2.y >= (unsigned)(mat->height) )
187         CV_ERROR( CV_StsBadPoint,
188             "One of the ending points is outside of the image, use cvClipLine" );
189 
190     bt_pix0 = bt_pix = CV_ELEM_SIZE(mat->type);
191     step = mat->step;
192 
193     dx = pt2.x - pt1.x;
194     dy = pt2.y - pt1.y;
195     s = dx < 0 ? -1 : 0;
196 
197     if( left_to_right )
198     {
199         dx = (dx ^ s) - s;
200         dy = (dy ^ s) - s;
201         pt1.x ^= (pt1.x ^ pt2.x) & s;
202         pt1.y ^= (pt1.y ^ pt2.y) & s;
203     }
204     else
205     {
206         dx = (dx ^ s) - s;
207         bt_pix = (bt_pix ^ s) - s;
208     }
209 
210     iterator->ptr = (uchar*)(mat->data.ptr + pt1.y * step + pt1.x * bt_pix0);
211 
212     s = dy < 0 ? -1 : 0;
213     dy = (dy ^ s) - s;
214     step = (step ^ s) - s;
215 
216     s = dy > dx ? -1 : 0;
217 
218     /* conditional swaps */
219     dx ^= dy & s;
220     dy ^= dx & s;
221     dx ^= dy & s;
222 
223     bt_pix ^= step & s;
224     step ^= bt_pix & s;
225     bt_pix ^= step & s;
226 
227     if( connectivity == 8 )
228     {
229         assert( dx >= 0 && dy >= 0 );
230 
231         iterator->err = dx - (dy + dy);
232         iterator->plus_delta = dx + dx;
233         iterator->minus_delta = -(dy + dy);
234         iterator->plus_step = step;
235         iterator->minus_step = bt_pix;
236         count = dx + 1;
237     }
238     else /* connectivity == 4 */
239     {
240         assert( dx >= 0 && dy >= 0 );
241 
242         iterator->err = 0;
243         iterator->plus_delta = (dx + dx) + (dy + dy);
244         iterator->minus_delta = -(dy + dy);
245         iterator->plus_step = step - bt_pix;
246         iterator->minus_step = bt_pix;
247         count = dx + dy + 1;
248     }
249 
250     __END__;
251 
252     return count;
253 }
254 
255 static void
icvLine(CvMat * mat,CvPoint pt1,CvPoint pt2,const void * color,int connectivity=8)256 icvLine( CvMat* mat, CvPoint pt1, CvPoint pt2,
257          const void* color, int connectivity = 8 )
258 {
259     if( cvClipLine( cvGetMatSize(mat), &pt1, &pt2 ))
260     {
261         CvLineIterator iterator;
262         int pix_size = CV_ELEM_SIZE(mat->type);
263         int i, count;
264 
265         if( connectivity == 0 )
266             connectivity = 8;
267         if( connectivity == 1 )
268             connectivity = 4;
269 
270         count = cvInitLineIterator( mat, pt1, pt2, &iterator, connectivity, 1 );
271 
272         for( i = 0; i < count; i++ )
273         {
274             CV_MEMCPY_AUTO( iterator.ptr, color, pix_size );
275             CV_NEXT_LINE_POINT( iterator );
276         }
277     }
278 }
279 
280 
281 /* Correction table depent on the slope */
282 static const uchar icvSlopeCorrTable[] = {
283     181, 181, 181, 182, 182, 183, 184, 185, 187, 188, 190, 192, 194, 196, 198, 201,
284     203, 206, 209, 211, 214, 218, 221, 224, 227, 231, 235, 238, 242, 246, 250, 254
285 };
286 
287 /* Gaussian for antialiasing filter */
288 static const int icvFilterTable[] = {
289     168, 177, 185, 194, 202, 210, 218, 224, 231, 236, 241, 246, 249, 252, 254, 254,
290     254, 254, 252, 249, 246, 241, 236, 231, 224, 218, 210, 202, 194, 185, 177, 168,
291     158, 149, 140, 131, 122, 114, 105, 97, 89, 82, 75, 68, 62, 56, 50, 45,
292     40, 36, 32, 28, 25, 22, 19, 16, 14, 12, 11, 9, 8, 7, 5, 5
293 };
294 
295 static void
icvLineAA(CvMat * img,CvPoint pt1,CvPoint pt2,const void * color)296 icvLineAA( CvMat* img, CvPoint pt1, CvPoint pt2,
297            const void* color )
298 {
299     int dx, dy;
300     int ecount, scount = 0;
301     int slope;
302     int ax, ay;
303     int x_step, y_step;
304     int i, j;
305     int ep_table[9];
306     int cb = ((uchar*)color)[0], cg = ((uchar*)color)[1], cr = ((uchar*)color)[2];
307     int _cb, _cg, _cr;
308     int nch = CV_MAT_CN( img->type );
309     uchar* ptr = (uchar*)(img->data.ptr);
310     int step = img->step;
311     CvSize size = cvGetMatSize( img );
312 
313     assert( img && (nch == 1 || nch == 3) && CV_MAT_DEPTH(img->type) == CV_8U );
314 
315     pt1.x -= XY_ONE*2;
316     pt1.y -= XY_ONE*2;
317     pt2.x -= XY_ONE*2;
318     pt2.y -= XY_ONE*2;
319     ptr += img->step*2 + 2*nch;
320 
321     size.width = ((size.width - 5) << XY_SHIFT) + 1;
322     size.height = ((size.height - 5) << XY_SHIFT) + 1;
323 
324     if( !cvClipLine( size, &pt1, &pt2 ))
325         return;
326 
327     dx = pt2.x - pt1.x;
328     dy = pt2.y - pt1.y;
329 
330     j = dx < 0 ? -1 : 0;
331     ax = (dx ^ j) - j;
332     i = dy < 0 ? -1 : 0;
333     ay = (dy ^ i) - i;
334 
335     if( ax > ay )
336     {
337         dx = ax;
338         dy = (dy ^ j) - j;
339         pt1.x ^= pt2.x & j;
340         pt2.x ^= pt1.x & j;
341         pt1.x ^= pt2.x & j;
342         pt1.y ^= pt2.y & j;
343         pt2.y ^= pt1.y & j;
344         pt1.y ^= pt2.y & j;
345 
346         x_step = XY_ONE;
347         y_step = (int) (((int64) dy << XY_SHIFT) / (ax | 1));
348         pt2.x += XY_ONE;
349         ecount = (pt2.x >> XY_SHIFT) - (pt1.x >> XY_SHIFT);
350         j = -(pt1.x & (XY_ONE - 1));
351         pt1.y += (int) ((((int64) y_step) * j) >> XY_SHIFT) + (XY_ONE >> 1);
352         slope = (y_step >> (XY_SHIFT - 5)) & 0x3f;
353         slope ^= (y_step < 0 ? 0x3f : 0);
354 
355         /* Get 4-bit fractions for end-point adjustments */
356         i = (pt1.x >> (XY_SHIFT - 7)) & 0x78;
357         j = (pt2.x >> (XY_SHIFT - 7)) & 0x78;
358     }
359     else
360     {
361         dy = ay;
362         dx = (dx ^ i) - i;
363         pt1.x ^= pt2.x & i;
364         pt2.x ^= pt1.x & i;
365         pt1.x ^= pt2.x & i;
366         pt1.y ^= pt2.y & i;
367         pt2.y ^= pt1.y & i;
368         pt1.y ^= pt2.y & i;
369 
370         x_step = (int) (((int64) dx << XY_SHIFT) / (ay | 1));
371         y_step = XY_ONE;
372         pt2.y += XY_ONE;
373         ecount = (pt2.y >> XY_SHIFT) - (pt1.y >> XY_SHIFT);
374         j = -(pt1.y & (XY_ONE - 1));
375         pt1.x += (int) ((((int64) x_step) * j) >> XY_SHIFT) + (XY_ONE >> 1);
376         slope = (x_step >> (XY_SHIFT - 5)) & 0x3f;
377         slope ^= (x_step < 0 ? 0x3f : 0);
378 
379         /* Get 4-bit fractions for end-point adjustments */
380         i = (pt1.y >> (XY_SHIFT - 7)) & 0x78;
381         j = (pt2.y >> (XY_SHIFT - 7)) & 0x78;
382     }
383 
384     slope = (slope & 0x20) ? 0x100 : icvSlopeCorrTable[slope];
385 
386     /* Calc end point correction table */
387     {
388         int t0 = slope << 7;
389         int t1 = ((0x78 - i) | 4) * slope;
390         int t2 = (j | 4) * slope;
391 
392         ep_table[0] = 0;
393         ep_table[8] = slope;
394         ep_table[1] = ep_table[3] = ((((j - i) & 0x78) | 4) * slope >> 8) & 0x1ff;
395         ep_table[2] = (t1 >> 8) & 0x1ff;
396         ep_table[4] = ((((j - i) + 0x80) | 4) * slope >> 8) & 0x1ff;
397         ep_table[5] = ((t1 + t0) >> 8) & 0x1ff;
398         ep_table[6] = (t2 >> 8) & 0x1ff;
399         ep_table[7] = ((t2 + t0) >> 8) & 0x1ff;
400     }
401 
402     if( nch == 3 )
403     {
404         #define  ICV_PUT_POINT()            \
405         {                                   \
406             _cb = tptr[0];                  \
407             _cb += ((cb - _cb)*a + 127)>> 8;\
408             _cg = tptr[1];                  \
409             _cg += ((cg - _cg)*a + 127)>> 8;\
410             _cr = tptr[2];                  \
411             _cr += ((cr - _cr)*a + 127)>> 8;\
412             tptr[0] = (uchar)_cb;           \
413             tptr[1] = (uchar)_cg;           \
414             tptr[2] = (uchar)_cr;           \
415         }
416         if( ax > ay )
417         {
418             ptr += (pt1.x >> XY_SHIFT) * 3;
419 
420             while( ecount >= 0 )
421             {
422                 uchar *tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step;
423 
424                 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
425                                        (((ecount >= 2) + 1) & (ecount | 2))];
426                 int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31;
427 
428                 a = (ep_corr * icvFilterTable[dist + 32] >> 8) & 0xff;
429                 ICV_PUT_POINT();
430                 ICV_PUT_POINT();
431 
432                 tptr += step;
433                 a = (ep_corr * icvFilterTable[dist] >> 8) & 0xff;
434                 ICV_PUT_POINT();
435                 ICV_PUT_POINT();
436 
437                 tptr += step;
438                 a = (ep_corr * icvFilterTable[63 - dist] >> 8) & 0xff;
439                 ICV_PUT_POINT();
440                 ICV_PUT_POINT();
441 
442                 pt1.y += y_step;
443                 ptr += 3;
444                 scount++;
445                 ecount--;
446             }
447         }
448         else
449         {
450             ptr += (pt1.y >> XY_SHIFT) * step;
451 
452             while( ecount >= 0 )
453             {
454                 uchar *tptr = ptr + ((pt1.x >> XY_SHIFT) - 1) * 3;
455 
456                 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
457                                        (((ecount >= 2) + 1) & (ecount | 2))];
458                 int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31;
459 
460                 a = (ep_corr * icvFilterTable[dist + 32] >> 8) & 0xff;
461                 ICV_PUT_POINT();
462                 ICV_PUT_POINT();
463 
464                 tptr += 3;
465                 a = (ep_corr * icvFilterTable[dist] >> 8) & 0xff;
466                 ICV_PUT_POINT();
467                 ICV_PUT_POINT();
468 
469                 tptr += 3;
470                 a = (ep_corr * icvFilterTable[63 - dist] >> 8) & 0xff;
471                 ICV_PUT_POINT();
472                 ICV_PUT_POINT();
473 
474                 pt1.x += x_step;
475                 ptr += step;
476                 scount++;
477                 ecount--;
478             }
479         }
480         #undef ICV_PUT_POINT
481     }
482     else
483     {
484         #define  ICV_PUT_POINT()            \
485         {                                   \
486             _cb = tptr[0];                  \
487             _cb += ((cb - _cb)*a + 127)>> 8;\
488             tptr[0] = (uchar)_cb;           \
489         }
490 
491         if( ax > ay )
492         {
493             ptr += (pt1.x >> XY_SHIFT);
494 
495             while( ecount >= 0 )
496             {
497                 uchar *tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step;
498 
499                 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
500                                        (((ecount >= 2) + 1) & (ecount | 2))];
501                 int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31;
502 
503                 a = (ep_corr * icvFilterTable[dist + 32] >> 8) & 0xff;
504                 ICV_PUT_POINT();
505                 ICV_PUT_POINT();
506 
507                 tptr += step;
508                 a = (ep_corr * icvFilterTable[dist] >> 8) & 0xff;
509                 ICV_PUT_POINT();
510                 ICV_PUT_POINT();
511 
512                 tptr += step;
513                 a = (ep_corr * icvFilterTable[63 - dist] >> 8) & 0xff;
514                 ICV_PUT_POINT();
515                 ICV_PUT_POINT();
516 
517                 pt1.y += y_step;
518                 ptr++;
519                 scount++;
520                 ecount--;
521             }
522         }
523         else
524         {
525             ptr += (pt1.y >> XY_SHIFT) * step;
526 
527             while( ecount >= 0 )
528             {
529                 uchar *tptr = ptr + ((pt1.x >> XY_SHIFT) - 1);
530 
531                 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
532                                        (((ecount >= 2) + 1) & (ecount | 2))];
533                 int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31;
534 
535                 a = (ep_corr * icvFilterTable[dist + 32] >> 8) & 0xff;
536                 ICV_PUT_POINT();
537                 ICV_PUT_POINT();
538 
539                 tptr++;
540                 a = (ep_corr * icvFilterTable[dist] >> 8) & 0xff;
541                 ICV_PUT_POINT();
542                 ICV_PUT_POINT();
543 
544                 tptr++;
545                 a = (ep_corr * icvFilterTable[63 - dist] >> 8) & 0xff;
546                 ICV_PUT_POINT();
547                 ICV_PUT_POINT();
548 
549                 pt1.x += x_step;
550                 ptr += step;
551                 scount++;
552                 ecount--;
553             }
554         }
555         #undef ICV_PUT_POINT
556     }
557 }
558 
559 
560 static void
icvLine2(CvMat * img,CvPoint pt1,CvPoint pt2,const void * color)561 icvLine2( CvMat* img, CvPoint pt1, CvPoint pt2, const void* color )
562 {
563     int dx, dy;
564     int ecount;
565     int ax, ay;
566     int i, j;
567     int x_step, y_step;
568     int cb = ((uchar*)color)[0];
569     int cg = ((uchar*)color)[1];
570     int cr = ((uchar*)color)[2];
571     int pix_size = CV_ELEM_SIZE( img->type );
572     uchar *ptr = (uchar*)(img->data.ptr), *tptr;
573     int step = img->step;
574     CvSize size = cvGetMatSize( img );
575 
576     //assert( img && (nch == 1 || nch == 3) && CV_MAT_DEPTH(img->type) == CV_8U );
577 
578     pt1.x -= XY_ONE*2;
579     pt1.y -= XY_ONE*2;
580     pt2.x -= XY_ONE*2;
581     pt2.y -= XY_ONE*2;
582     ptr += img->step*2 + 2*pix_size;
583 
584     size.width = ((size.width - 5) << XY_SHIFT) + 1;
585     size.height = ((size.height - 5) << XY_SHIFT) + 1;
586 
587     if( !cvClipLine( size, &pt1, &pt2 ))
588         return;
589 
590     dx = pt2.x - pt1.x;
591     dy = pt2.y - pt1.y;
592 
593     j = dx < 0 ? -1 : 0;
594     ax = (dx ^ j) - j;
595     i = dy < 0 ? -1 : 0;
596     ay = (dy ^ i) - i;
597 
598     if( ax > ay )
599     {
600         dx = ax;
601         dy = (dy ^ j) - j;
602         pt1.x ^= pt2.x & j;
603         pt2.x ^= pt1.x & j;
604         pt1.x ^= pt2.x & j;
605         pt1.y ^= pt2.y & j;
606         pt2.y ^= pt1.y & j;
607         pt1.y ^= pt2.y & j;
608 
609         x_step = XY_ONE;
610         y_step = (int) (((int64) dy << XY_SHIFT) / (ax | 1));
611         ecount = (pt2.x - pt1.x) >> XY_SHIFT;
612     }
613     else
614     {
615         dy = ay;
616         dx = (dx ^ i) - i;
617         pt1.x ^= pt2.x & i;
618         pt2.x ^= pt1.x & i;
619         pt1.x ^= pt2.x & i;
620         pt1.y ^= pt2.y & i;
621         pt2.y ^= pt1.y & i;
622         pt1.y ^= pt2.y & i;
623 
624         x_step = (int) (((int64) dx << XY_SHIFT) / (ay | 1));
625         y_step = XY_ONE;
626         ecount = (pt2.y - pt1.y) >> XY_SHIFT;
627     }
628 
629     pt1.x += (XY_ONE >> 1);
630     pt1.y += (XY_ONE >> 1);
631 
632     if( pix_size == 3 )
633     {
634         #define  ICV_PUT_POINT()    \
635         {                           \
636             tptr[0] = (uchar)cb;    \
637             tptr[1] = (uchar)cg;    \
638             tptr[2] = (uchar)cr;    \
639         }
640 
641         tptr = ptr + ((pt2.x + (XY_ONE >> 1))>> XY_SHIFT)*3 +
642             ((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT)*step;
643         ICV_PUT_POINT();
644 
645         if( ax > ay )
646         {
647             ptr += (pt1.x >> XY_SHIFT) * 3;
648 
649             while( ecount >= 0 )
650             {
651                 tptr = ptr + (pt1.y >> XY_SHIFT) * step;
652                 ICV_PUT_POINT();
653                 pt1.y += y_step;
654                 ptr += 3;
655                 ecount--;
656             }
657         }
658         else
659         {
660             ptr += (pt1.y >> XY_SHIFT) * step;
661 
662             while( ecount >= 0 )
663             {
664                 tptr = ptr + (pt1.x >> XY_SHIFT) * 3;
665                 ICV_PUT_POINT();
666                 pt1.x += x_step;
667                 ptr += step;
668                 ecount--;
669             }
670         }
671 
672         #undef ICV_PUT_POINT
673     }
674     else if( pix_size == 1 )
675     {
676         #define  ICV_PUT_POINT()            \
677         {                                   \
678             tptr[0] = (uchar)cb;            \
679         }
680 
681         tptr = ptr + ((pt2.x + (XY_ONE >> 1))>> XY_SHIFT) +
682             ((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT)*step;
683         ICV_PUT_POINT();
684 
685         if( ax > ay )
686         {
687             ptr += (pt1.x >> XY_SHIFT);
688 
689             while( ecount >= 0 )
690             {
691                 tptr = ptr + (pt1.y >> XY_SHIFT) * step;
692                 ICV_PUT_POINT();
693                 pt1.y += y_step;
694                 ptr++;
695                 ecount--;
696             }
697         }
698         else
699         {
700             ptr += (pt1.y >> XY_SHIFT) * step;
701 
702             while( ecount >= 0 )
703             {
704                 tptr = ptr + (pt1.x >> XY_SHIFT);
705                 ICV_PUT_POINT();
706                 pt1.x += x_step;
707                 ptr += step;
708                 ecount--;
709             }
710         }
711         #undef ICV_PUT_POINT
712     }
713     else
714     {
715         #define  ICV_PUT_POINT()                \
716             for( j = 0; j < pix_size; j++ )     \
717                 tptr[j] = ((uchar*)color)[j];
718 
719         tptr = ptr + ((pt2.x + (XY_ONE >> 1))>> XY_SHIFT)*pix_size +
720             ((pt2.y + (XY_ONE >> 1)) >> XY_SHIFT)*step;
721         ICV_PUT_POINT();
722 
723         if( ax > ay )
724         {
725             ptr += (pt1.x >> XY_SHIFT) * pix_size;
726 
727             while( ecount >= 0 )
728             {
729                 tptr = ptr + (pt1.y >> XY_SHIFT) * step;
730                 ICV_PUT_POINT();
731                 pt1.y += y_step;
732                 ptr += pix_size;
733                 ecount--;
734             }
735         }
736         else
737         {
738             ptr += (pt1.y >> XY_SHIFT) * step;
739 
740             while( ecount >= 0 )
741             {
742                 tptr = ptr + (pt1.x >> XY_SHIFT) * pix_size;
743                 ICV_PUT_POINT();
744                 pt1.x += x_step;
745                 ptr += step;
746                 ecount--;
747             }
748         }
749 
750         #undef ICV_PUT_POINT
751     }
752 }
753 
754 
755 /****************************************************************************************\
756 *                   Antialiazed Elliptic Arcs via Antialiazed Lines                      *
757 \****************************************************************************************/
758 
759 static const float icvSinTable[] =
760     { 0.0000000f, 0.0174524f, 0.0348995f, 0.0523360f, 0.0697565f, 0.0871557f,
761     0.1045285f, 0.1218693f, 0.1391731f, 0.1564345f, 0.1736482f, 0.1908090f,
762     0.2079117f, 0.2249511f, 0.2419219f, 0.2588190f, 0.2756374f, 0.2923717f,
763     0.3090170f, 0.3255682f, 0.3420201f, 0.3583679f, 0.3746066f, 0.3907311f,
764     0.4067366f, 0.4226183f, 0.4383711f, 0.4539905f, 0.4694716f, 0.4848096f,
765     0.5000000f, 0.5150381f, 0.5299193f, 0.5446390f, 0.5591929f, 0.5735764f,
766     0.5877853f, 0.6018150f, 0.6156615f, 0.6293204f, 0.6427876f, 0.6560590f,
767     0.6691306f, 0.6819984f, 0.6946584f, 0.7071068f, 0.7193398f, 0.7313537f,
768     0.7431448f, 0.7547096f, 0.7660444f, 0.7771460f, 0.7880108f, 0.7986355f,
769     0.8090170f, 0.8191520f, 0.8290376f, 0.8386706f, 0.8480481f, 0.8571673f,
770     0.8660254f, 0.8746197f, 0.8829476f, 0.8910065f, 0.8987940f, 0.9063078f,
771     0.9135455f, 0.9205049f, 0.9271839f, 0.9335804f, 0.9396926f, 0.9455186f,
772     0.9510565f, 0.9563048f, 0.9612617f, 0.9659258f, 0.9702957f, 0.9743701f,
773     0.9781476f, 0.9816272f, 0.9848078f, 0.9876883f, 0.9902681f, 0.9925462f,
774     0.9945219f, 0.9961947f, 0.9975641f, 0.9986295f, 0.9993908f, 0.9998477f,
775     1.0000000f, 0.9998477f, 0.9993908f, 0.9986295f, 0.9975641f, 0.9961947f,
776     0.9945219f, 0.9925462f, 0.9902681f, 0.9876883f, 0.9848078f, 0.9816272f,
777     0.9781476f, 0.9743701f, 0.9702957f, 0.9659258f, 0.9612617f, 0.9563048f,
778     0.9510565f, 0.9455186f, 0.9396926f, 0.9335804f, 0.9271839f, 0.9205049f,
779     0.9135455f, 0.9063078f, 0.8987940f, 0.8910065f, 0.8829476f, 0.8746197f,
780     0.8660254f, 0.8571673f, 0.8480481f, 0.8386706f, 0.8290376f, 0.8191520f,
781     0.8090170f, 0.7986355f, 0.7880108f, 0.7771460f, 0.7660444f, 0.7547096f,
782     0.7431448f, 0.7313537f, 0.7193398f, 0.7071068f, 0.6946584f, 0.6819984f,
783     0.6691306f, 0.6560590f, 0.6427876f, 0.6293204f, 0.6156615f, 0.6018150f,
784     0.5877853f, 0.5735764f, 0.5591929f, 0.5446390f, 0.5299193f, 0.5150381f,
785     0.5000000f, 0.4848096f, 0.4694716f, 0.4539905f, 0.4383711f, 0.4226183f,
786     0.4067366f, 0.3907311f, 0.3746066f, 0.3583679f, 0.3420201f, 0.3255682f,
787     0.3090170f, 0.2923717f, 0.2756374f, 0.2588190f, 0.2419219f, 0.2249511f,
788     0.2079117f, 0.1908090f, 0.1736482f, 0.1564345f, 0.1391731f, 0.1218693f,
789     0.1045285f, 0.0871557f, 0.0697565f, 0.0523360f, 0.0348995f, 0.0174524f,
790     0.0000000f, -0.0174524f, -0.0348995f, -0.0523360f, -0.0697565f, -0.0871557f,
791     -0.1045285f, -0.1218693f, -0.1391731f, -0.1564345f, -0.1736482f, -0.1908090f,
792     -0.2079117f, -0.2249511f, -0.2419219f, -0.2588190f, -0.2756374f, -0.2923717f,
793     -0.3090170f, -0.3255682f, -0.3420201f, -0.3583679f, -0.3746066f, -0.3907311f,
794     -0.4067366f, -0.4226183f, -0.4383711f, -0.4539905f, -0.4694716f, -0.4848096f,
795     -0.5000000f, -0.5150381f, -0.5299193f, -0.5446390f, -0.5591929f, -0.5735764f,
796     -0.5877853f, -0.6018150f, -0.6156615f, -0.6293204f, -0.6427876f, -0.6560590f,
797     -0.6691306f, -0.6819984f, -0.6946584f, -0.7071068f, -0.7193398f, -0.7313537f,
798     -0.7431448f, -0.7547096f, -0.7660444f, -0.7771460f, -0.7880108f, -0.7986355f,
799     -0.8090170f, -0.8191520f, -0.8290376f, -0.8386706f, -0.8480481f, -0.8571673f,
800     -0.8660254f, -0.8746197f, -0.8829476f, -0.8910065f, -0.8987940f, -0.9063078f,
801     -0.9135455f, -0.9205049f, -0.9271839f, -0.9335804f, -0.9396926f, -0.9455186f,
802     -0.9510565f, -0.9563048f, -0.9612617f, -0.9659258f, -0.9702957f, -0.9743701f,
803     -0.9781476f, -0.9816272f, -0.9848078f, -0.9876883f, -0.9902681f, -0.9925462f,
804     -0.9945219f, -0.9961947f, -0.9975641f, -0.9986295f, -0.9993908f, -0.9998477f,
805     -1.0000000f, -0.9998477f, -0.9993908f, -0.9986295f, -0.9975641f, -0.9961947f,
806     -0.9945219f, -0.9925462f, -0.9902681f, -0.9876883f, -0.9848078f, -0.9816272f,
807     -0.9781476f, -0.9743701f, -0.9702957f, -0.9659258f, -0.9612617f, -0.9563048f,
808     -0.9510565f, -0.9455186f, -0.9396926f, -0.9335804f, -0.9271839f, -0.9205049f,
809     -0.9135455f, -0.9063078f, -0.8987940f, -0.8910065f, -0.8829476f, -0.8746197f,
810     -0.8660254f, -0.8571673f, -0.8480481f, -0.8386706f, -0.8290376f, -0.8191520f,
811     -0.8090170f, -0.7986355f, -0.7880108f, -0.7771460f, -0.7660444f, -0.7547096f,
812     -0.7431448f, -0.7313537f, -0.7193398f, -0.7071068f, -0.6946584f, -0.6819984f,
813     -0.6691306f, -0.6560590f, -0.6427876f, -0.6293204f, -0.6156615f, -0.6018150f,
814     -0.5877853f, -0.5735764f, -0.5591929f, -0.5446390f, -0.5299193f, -0.5150381f,
815     -0.5000000f, -0.4848096f, -0.4694716f, -0.4539905f, -0.4383711f, -0.4226183f,
816     -0.4067366f, -0.3907311f, -0.3746066f, -0.3583679f, -0.3420201f, -0.3255682f,
817     -0.3090170f, -0.2923717f, -0.2756374f, -0.2588190f, -0.2419219f, -0.2249511f,
818     -0.2079117f, -0.1908090f, -0.1736482f, -0.1564345f, -0.1391731f, -0.1218693f,
819     -0.1045285f, -0.0871557f, -0.0697565f, -0.0523360f, -0.0348995f, -0.0174524f,
820     -0.0000000f, 0.0174524f, 0.0348995f, 0.0523360f, 0.0697565f, 0.0871557f,
821     0.1045285f, 0.1218693f, 0.1391731f, 0.1564345f, 0.1736482f, 0.1908090f,
822     0.2079117f, 0.2249511f, 0.2419219f, 0.2588190f, 0.2756374f, 0.2923717f,
823     0.3090170f, 0.3255682f, 0.3420201f, 0.3583679f, 0.3746066f, 0.3907311f,
824     0.4067366f, 0.4226183f, 0.4383711f, 0.4539905f, 0.4694716f, 0.4848096f,
825     0.5000000f, 0.5150381f, 0.5299193f, 0.5446390f, 0.5591929f, 0.5735764f,
826     0.5877853f, 0.6018150f, 0.6156615f, 0.6293204f, 0.6427876f, 0.6560590f,
827     0.6691306f, 0.6819984f, 0.6946584f, 0.7071068f, 0.7193398f, 0.7313537f,
828     0.7431448f, 0.7547096f, 0.7660444f, 0.7771460f, 0.7880108f, 0.7986355f,
829     0.8090170f, 0.8191520f, 0.8290376f, 0.8386706f, 0.8480481f, 0.8571673f,
830     0.8660254f, 0.8746197f, 0.8829476f, 0.8910065f, 0.8987940f, 0.9063078f,
831     0.9135455f, 0.9205049f, 0.9271839f, 0.9335804f, 0.9396926f, 0.9455186f,
832     0.9510565f, 0.9563048f, 0.9612617f, 0.9659258f, 0.9702957f, 0.9743701f,
833     0.9781476f, 0.9816272f, 0.9848078f, 0.9876883f, 0.9902681f, 0.9925462f,
834     0.9945219f, 0.9961947f, 0.9975641f, 0.9986295f, 0.9993908f, 0.9998477f,
835     1.0000000f
836 };
837 
838 
839 static void
icvSinCos(int angle,float * cosval,float * sinval)840 icvSinCos( int angle, float *cosval, float *sinval )
841 {
842     angle += (angle < 0 ? 360 : 0);
843     *sinval = icvSinTable[angle];
844     *cosval = icvSinTable[450 - angle];
845 }
846 
847 /*
848    constructs polygon that represents elliptic arc.
849 */
850 CV_IMPL int
cvEllipse2Poly(CvPoint center,CvSize axes,int angle,int arc_start,int arc_end,CvPoint * pts,int delta)851 cvEllipse2Poly( CvPoint center, CvSize axes, int angle,
852                 int arc_start, int arc_end, CvPoint* pts, int delta )
853 {
854     float alpha, beta;
855     double size_a = axes.width, size_b = axes.height;
856     double cx = center.x, cy = center.y;
857     CvPoint *pts_origin = pts;
858     int i;
859 
860     while( angle < 0 )
861         angle += 360;
862     while( angle > 360 )
863         angle -= 360;
864 
865     if( arc_start > arc_end )
866     {
867         i = arc_start;
868         arc_start = arc_end;
869         arc_end = i;
870     }
871     while( arc_start < 0 )
872     {
873         arc_start += 360;
874         arc_end += 360;
875     }
876     while( arc_end > 360 )
877     {
878         arc_end -= 360;
879         arc_start -= 360;
880     }
881     if( arc_end - arc_start > 360 )
882     {
883         arc_start = 0;
884         arc_end = 360;
885     }
886     icvSinCos( angle, &alpha, &beta );
887 
888     for( i = arc_start; i < arc_end + delta; i += delta )
889     {
890         double x, y;
891         angle = i;
892         if( angle > arc_end )
893             angle = arc_end;
894         if( angle < 0 )
895             angle += 360;
896 
897         x = size_a * icvSinTable[450-angle];
898         y = size_b * icvSinTable[angle];
899         pts->x = cvRound( cx + x * alpha - y * beta );
900         pts->y = cvRound( cy - x * beta - y * alpha );
901         pts += i == arc_start || pts->x != pts[-1].x || pts->y != pts[-1].y;
902     }
903 
904     i = (int)(pts - pts_origin);
905     for( ; i < 2; i++ )
906         pts_origin[i] = pts_origin[i-1];
907     return i;
908 }
909 
910 
911 static void
icvEllipseEx(CvMat * img,CvPoint center,CvSize axes,int angle,int arc_start,int arc_end,const void * color,int thickness,int line_type)912 icvEllipseEx( CvMat* img, CvPoint center, CvSize axes,
913               int angle, int arc_start, int arc_end,
914               const void* color, int thickness, int line_type )
915 {
916     CvMemStorage* st = 0;
917 
918     CV_FUNCNAME( "icvEllipseEx" );
919 
920     __BEGIN__;
921 
922     CvPoint v[1 << 8];
923     int count, delta;
924 
925     if( axes.width < 0 || axes.height < 0 )
926         CV_ERROR( CV_StsBadSize, "" );
927 
928     delta = (MAX(axes.width,axes.height)+(XY_ONE>>1))>>XY_SHIFT;
929     delta = delta < 3 ? 90 : delta < 10 ? 30 : delta < 15 ? 18 : 5;
930 
931     count = cvEllipse2Poly( center, axes, angle, arc_start, arc_end, v, delta );
932 
933     if( thickness >= 0 )
934     {
935         icvPolyLine( img, v, count, 0, color, thickness, line_type, XY_SHIFT );
936     }
937     else if( arc_end - arc_start >= 360 )
938     {
939         icvFillConvexPoly( img, v, count, color, line_type, XY_SHIFT );
940     }
941     else
942     {
943         CvContour* edges;
944         CvSeq vtx;
945         CvSeqBlock block;
946 
947         CV_CALL( st = cvCreateMemStorage( CV_DRAWING_STORAGE_BLOCK ));
948         CV_CALL( edges = (CvContour*)cvCreateSeq( 0, sizeof(CvContour), sizeof(CvPolyEdge), st ));
949         v[count++] = center;
950 
951         CV_CALL( cvMakeSeqHeaderForArray( CV_32SC2, sizeof(CvSeq), sizeof(CvPoint),
952                                           v, count, &vtx, &block ));
953 
954         CV_CALL( icvCollectPolyEdges( img, &vtx, edges, color, line_type, XY_SHIFT ));
955         CV_CALL( icvFillEdgeCollection( img, edges, color ));
956     }
957 
958     __END__;
959 
960     if( st )
961         cvReleaseMemStorage( &st );
962 }
963 
964 
965 /****************************************************************************************\
966 *                                Polygons filling                                        *
967 \****************************************************************************************/
968 
969 /* helper macros: filling horizontal row */
970 #define ICV_HLINE( ptr, xl, xr, color, pix_size )            \
971 {                                                            \
972     uchar* hline_ptr = (uchar*)(ptr) + (xl)*(pix_size);      \
973     uchar* hline_max_ptr = (uchar*)(ptr) + (xr)*(pix_size);  \
974                                                              \
975     for( ; hline_ptr <= hline_max_ptr; hline_ptr += (pix_size))\
976     {                                                        \
977         int hline_j;                                         \
978         for( hline_j = 0; hline_j < (pix_size); hline_j++ )  \
979         {                                                    \
980             hline_ptr[hline_j] = ((uchar*)color)[hline_j];   \
981         }                                                    \
982     }                                                        \
983 }
984 
985 
986 /* filling convex polygon. v - array of vertices, ntps - number of points */
987 static void
icvFillConvexPoly(CvMat * img,CvPoint * v,int npts,const void * color,int line_type,int shift)988 icvFillConvexPoly( CvMat* img, CvPoint *v, int npts, const void* color, int line_type, int shift )
989 {
990     struct
991     {
992         int idx, di;
993         int x, dx, ye;
994     }
995     edge[2];
996 
997     int delta = shift ? 1 << (shift - 1) : 0;
998     int i, y, imin = 0, left = 0, right = 1, x1, x2;
999     int edges = npts;
1000     int xmin, xmax, ymin, ymax;
1001     uchar* ptr = img->data.ptr;
1002     CvSize size = cvGetMatSize( img );
1003     int pix_size = CV_ELEM_SIZE(img->type);
1004     CvPoint p0;
1005     int delta1, delta2;
1006 
1007     if( line_type < CV_AA )
1008         delta1 = delta2 = XY_ONE >> 1;
1009         //delta1 = 0, delta2 = XY_ONE - 1;
1010     else
1011         delta1 = XY_ONE - 1, delta2 = 0;
1012 
1013     p0 = v[npts - 1];
1014     p0.x <<= XY_SHIFT - shift;
1015     p0.y <<= XY_SHIFT - shift;
1016 
1017     assert( 0 <= shift && shift <= XY_SHIFT );
1018     xmin = xmax = v[0].x;
1019     ymin = ymax = v[0].y;
1020 
1021     for( i = 0; i < npts; i++ )
1022     {
1023         CvPoint p = v[i];
1024         if( p.y < ymin )
1025         {
1026             ymin = p.y;
1027             imin = i;
1028         }
1029 
1030         ymax = MAX( ymax, p.y );
1031         xmax = MAX( xmax, p.x );
1032         xmin = MIN( xmin, p.x );
1033 
1034         p.x <<= XY_SHIFT - shift;
1035         p.y <<= XY_SHIFT - shift;
1036 
1037         if( line_type <= 8 )
1038         {
1039             if( shift == 0 )
1040             {
1041                 CvPoint pt0, pt1;
1042                 pt0.x = p0.x >> XY_SHIFT;
1043                 pt0.y = p0.y >> XY_SHIFT;
1044                 pt1.x = p.x >> XY_SHIFT;
1045                 pt1.y = p.y >> XY_SHIFT;
1046                 icvLine( img, pt0, pt1, color, line_type );
1047             }
1048             else
1049                 icvLine2( img, p0, p, color );
1050         }
1051         else
1052             icvLineAA( img, p0, p, color );
1053         p0 = p;
1054     }
1055 
1056     xmin = (xmin + delta) >> shift;
1057     xmax = (xmax + delta) >> shift;
1058     ymin = (ymin + delta) >> shift;
1059     ymax = (ymax + delta) >> shift;
1060 
1061     if( npts < 3 || xmax < 0 || ymax < 0 || xmin >= size.width || ymin >= size.height )
1062         return;
1063 
1064     ymax = MIN( ymax, size.height - 1 );
1065     edge[0].idx = edge[1].idx = imin;
1066 
1067     edge[0].ye = edge[1].ye = y = ymin;
1068     edge[0].di = 1;
1069     edge[1].di = npts - 1;
1070 
1071     ptr += img->step*y;
1072 
1073     do
1074     {
1075         if( line_type < CV_AA || y < ymax || y == ymin )
1076         {
1077             for( i = 0; i < 2; i++ )
1078             {
1079                 if( y >= edge[i].ye )
1080                 {
1081                     int idx = edge[i].idx, di = edge[i].di;
1082                     int xs = 0, xe, ye, ty = 0;
1083 
1084                     for(;;)
1085                     {
1086                         ty = (v[idx].y + delta) >> shift;
1087                         if( ty > y || edges == 0 )
1088                             break;
1089                         xs = v[idx].x;
1090                         idx += di;
1091                         idx -= ((idx < npts) - 1) & npts;   /* idx -= idx >= npts ? npts : 0 */
1092                         edges--;
1093                     }
1094 
1095                     ye = ty;
1096                     xs <<= XY_SHIFT - shift;
1097                     xe = v[idx].x << (XY_SHIFT - shift);
1098 
1099                     /* no more edges */
1100                     if( y >= ye )
1101                         return;
1102 
1103                     edge[i].ye = ye;
1104                     edge[i].dx = ((xe - xs)*2 + (ye - y)) / (2 * (ye - y));
1105                     edge[i].x = xs;
1106                     edge[i].idx = idx;
1107                 }
1108             }
1109         }
1110 
1111         if( edge[left].x > edge[right].x )
1112         {
1113             left ^= 1;
1114             right ^= 1;
1115         }
1116 
1117         x1 = edge[left].x;
1118         x2 = edge[right].x;
1119 
1120         if( y >= 0 )
1121         {
1122             int xx1 = (x1 + delta1) >> XY_SHIFT;
1123             int xx2 = (x2 + delta2) >> XY_SHIFT;
1124 
1125             if( xx2 >= 0 && xx1 < size.width )
1126             {
1127                 if( xx1 < 0 )
1128                     xx1 = 0;
1129                 if( xx2 >= size.width )
1130                     xx2 = size.width - 1;
1131                 ICV_HLINE( ptr, xx1, xx2, color, pix_size );
1132             }
1133         }
1134 
1135         x1 += edge[left].dx;
1136         x2 += edge[right].dx;
1137 
1138         edge[left].x = x1;
1139         edge[right].x = x2;
1140         ptr += img->step;
1141     }
1142     while( ++y <= ymax );
1143 }
1144 
1145 
1146 /******** Arbitrary polygon **********/
1147 
1148 static void
icvCollectPolyEdges(CvMat * img,CvSeq * v,CvContour * edges,const void * color,int line_type,int shift,CvPoint offset)1149 icvCollectPolyEdges( CvMat* img, CvSeq* v, CvContour* edges,
1150                      const void* color, int line_type, int shift,
1151                      CvPoint offset )
1152 {
1153     int  i, count = v->total;
1154     CvRect bounds = edges->rect;
1155     int delta = offset.y + (shift ? 1 << (shift - 1) : 0);
1156     int elem_type = CV_MAT_TYPE(v->flags);
1157 
1158     CvSeqReader reader;
1159     CvSeqWriter writer;
1160 
1161     cvStartReadSeq( v, &reader );
1162     cvStartAppendToSeq( (CvSeq*)edges, &writer );
1163 
1164     for( i = 0; i < count; i++ )
1165     {
1166         CvPoint pt0, pt1, t0, t1;
1167         CvPolyEdge edge;
1168         CV_READ_EDGE( pt0, pt1, reader );
1169 
1170         if( elem_type == CV_32SC2 )
1171         {
1172             pt0.x = (pt0.x + offset.x) << (XY_SHIFT - shift);
1173             pt0.y = (pt0.y + delta) >> shift;
1174             pt1.x = (pt1.x + offset.x) << (XY_SHIFT - shift);
1175             pt1.y = (pt1.y + delta) >> shift;
1176         }
1177         else
1178         {
1179             Cv32suf x, y;
1180             assert( shift == 0 );
1181 
1182             x.i = pt0.x; y.i = pt0.y;
1183             pt0.x = cvRound((x.f + offset.x) * XY_ONE);
1184             pt0.y = cvRound(y.f + offset.y);
1185             x.i = pt1.x; y.i = pt1.y;
1186             pt1.x = cvRound((x.f + offset.x) * XY_ONE);
1187             pt1.y = cvRound(y.f + offset.y);
1188         }
1189 
1190         if( line_type < CV_AA )
1191         {
1192             t0.y = pt0.y; t1.y = pt1.y;
1193             t0.x = (pt0.x + (XY_ONE >> 1)) >> XY_SHIFT;
1194             t1.x = (pt1.x + (XY_ONE >> 1)) >> XY_SHIFT;
1195             icvLine( img, t0, t1, color, line_type );
1196         }
1197         else
1198         {
1199             t0.x = pt0.x; t1.x = pt1.x;
1200             t0.y = pt0.y << XY_SHIFT;
1201             t1.y = pt1.y << XY_SHIFT;
1202             icvLineAA( img, t0, t1, color );
1203         }
1204 
1205         if( pt0.y == pt1.y )
1206             continue;
1207 
1208         if( pt0.y > pt1.y )
1209             CV_SWAP( pt0, pt1, t0 );
1210 
1211         bounds.y = MIN( bounds.y, pt0.y );
1212         bounds.height = MAX( bounds.height, pt1.y );
1213 
1214         if( pt0.x < pt1.x )
1215         {
1216             bounds.x = MIN( bounds.x, pt0.x );
1217             bounds.width = MAX( bounds.width, pt1.x );
1218         }
1219         else
1220         {
1221             bounds.x = MIN( bounds.x, pt1.x );
1222             bounds.width = MAX( bounds.width, pt0.x );
1223         }
1224 
1225         edge.y0 = pt0.y;
1226         edge.y1 = pt1.y;
1227         edge.x = pt0.x;
1228         edge.dx = (pt1.x - pt0.x) / (pt1.y - pt0.y);
1229         assert( edge.y0 < edge.y1 );
1230 
1231         CV_WRITE_SEQ_ELEM( edge, writer );
1232     }
1233 
1234     edges->rect = bounds;
1235     cvEndWriteSeq( &writer );
1236 }
1237 
1238 static int
icvCmpEdges(const void * _e1,const void * _e2,void *)1239 icvCmpEdges( const void* _e1, const void* _e2, void* /*userdata*/ )
1240 {
1241     CvPolyEdge *e1 = (CvPolyEdge*)_e1, *e2 = (CvPolyEdge*)_e2;
1242     return e1->y0 - e2->y0 ? e1->y0 - e2->y0 :
1243            e1->x - e2->x ? e1->x - e2->x : e1->dx - e2->dx;
1244 }
1245 
1246 /**************** helper macros and functions for sequence/contour processing ***********/
1247 
1248 static void
icvFillEdgeCollection(CvMat * img,CvContour * edges,const void * color)1249 icvFillEdgeCollection( CvMat* img, CvContour* edges, const void* color )
1250 {
1251     CvPolyEdge tmp;
1252     int i, y, total = edges->total;
1253     CvSeqReader reader;
1254     CvSize size = cvGetMatSize(img);
1255     CvPolyEdge* e;
1256     int y_max = INT_MIN;
1257     int pix_size = CV_ELEM_SIZE(img->type);
1258 
1259     __BEGIN__;
1260 
1261     memset( &tmp, 0, sizeof(tmp));
1262 
1263     /* check parameters */
1264     if( edges->total < 2 || edges->rect.height < 0 || edges->rect.y >= size.height ||
1265         edges->rect.width < 0 || edges->rect.x >= size.width )
1266         EXIT;
1267 
1268     cvSeqSort( (CvSeq*)edges, icvCmpEdges, 0 );
1269     cvStartReadSeq( (CvSeq*)edges, &reader );
1270 
1271 #ifdef _DEBUG
1272     e = &tmp;
1273     tmp.y0 = INT_MIN;
1274 #endif
1275 
1276     for( i = 0; i < total; i++ )
1277     {
1278         CvPolyEdge* e1 = (CvPolyEdge*)(reader.ptr);
1279 
1280 #ifdef _DEBUG
1281         assert( e1->y0 < e1->y1 && (i == 0 || icvCmpEdges( e, e1, 0 ) <= 0) );
1282         e = e1;
1283 #endif
1284         y_max = MAX( y_max, e1->y1 );
1285 
1286         CV_NEXT_SEQ_ELEM( sizeof(CvPolyEdge), reader );
1287     }
1288 
1289     /* start drawing */
1290     tmp.y0 = INT_MAX;
1291     cvSeqPush( (CvSeq*)edges, &tmp );
1292 
1293     i = 0;
1294     tmp.next = 0;
1295     cvStartReadSeq( (CvSeq*)edges, &reader );
1296     e = (CvPolyEdge*)(reader.ptr);
1297     y_max = MIN( y_max, size.height );
1298 
1299     for( y = e->y0; y < y_max; y++ )
1300     {
1301         CvPolyEdge *last, *prelast, *keep_prelast;
1302         int sort_flag = 0;
1303         int draw = 0;
1304         int clipline = y < 0;
1305 
1306         prelast = &tmp;
1307         last = tmp.next;
1308         while( last || e->y0 == y )
1309         {
1310             if( last && last->y1 == y )
1311             {
1312                 /* exlude edge if y reachs its lower point */
1313                 prelast->next = last->next;
1314                 last = last->next;
1315                 continue;
1316             }
1317             keep_prelast = prelast;
1318             if( last && (e->y0 > y || last->x < e->x) )
1319             {
1320                 /* go to the next edge in active list */
1321                 prelast = last;
1322                 last = last->next;
1323             }
1324             else if( i < total )
1325             {
1326                 /* insert new edge into active list if y reachs its upper point */
1327                 prelast->next = e;
1328                 e->next = last;
1329                 prelast = e;
1330                 CV_NEXT_SEQ_ELEM( edges->elem_size, reader );
1331                 e = (CvPolyEdge*)(reader.ptr);
1332                 i++;
1333             }
1334             else
1335                 break;
1336 
1337             if( draw )
1338             {
1339                 if( !clipline )
1340                 {
1341                     /* convert x's from fixed-point to image coordinates */
1342                     uchar *timg = (uchar*)(img->data.ptr) + y * img->step;
1343                     int x1 = keep_prelast->x;
1344                     int x2 = prelast->x;
1345 
1346                     if( x1 > x2 )
1347                     {
1348                         int t = x1;
1349 
1350                         x1 = x2;
1351                         x2 = t;
1352                     }
1353 
1354                     x1 = (x1 + XY_ONE - 1) >> XY_SHIFT;
1355                     x2 = x2 >> XY_SHIFT;
1356 
1357                     /* clip and draw the line */
1358                     if( x1 < size.width && x2 >= 0 )
1359                     {
1360                         if( x1 < 0 )
1361                             x1 = 0;
1362                         if( x2 >= size.width )
1363                             x2 = size.width - 1;
1364                         ICV_HLINE( timg, x1, x2, color, pix_size );
1365                     }
1366                 }
1367                 keep_prelast->x += keep_prelast->dx;
1368                 prelast->x += prelast->dx;
1369             }
1370             draw ^= 1;
1371         }
1372 
1373         /* sort edges (bubble sort on list) */
1374         keep_prelast = 0;
1375 
1376         do
1377         {
1378             prelast = &tmp;
1379             last = tmp.next;
1380 
1381             while( last != keep_prelast && last->next != 0 )
1382             {
1383                 CvPolyEdge *te = last->next;
1384 
1385                 /* swap edges */
1386                 if( last->x > te->x )
1387                 {
1388                     prelast->next = te;
1389                     last->next = te->next;
1390                     te->next = last;
1391                     prelast = te;
1392                     sort_flag = 1;
1393                 }
1394                 else
1395                 {
1396                     prelast = last;
1397                     last = te;
1398                 }
1399             }
1400             keep_prelast = prelast;
1401         }
1402         while( sort_flag && keep_prelast != tmp.next && keep_prelast != &tmp );
1403     }
1404 
1405     __END__;
1406 }
1407 
1408 
1409 /* draws simple or filled circle */
1410 static void
icvCircle(CvMat * img,CvPoint center,int radius,const void * color,int fill)1411 icvCircle( CvMat* img, CvPoint center, int radius, const void* color, int fill )
1412 {
1413     CvSize size = cvGetMatSize( img );
1414     int step = img->step;
1415     int pix_size = CV_ELEM_SIZE(img->type);
1416     uchar* ptr = (uchar*)(img->data.ptr);
1417     int err = 0, dx = radius, dy = 0, plus = 1, minus = (radius << 1) - 1;
1418     int inside = center.x >= radius && center.x < size.width - radius &&
1419         center.y >= radius && center.y < size.height - radius;
1420 
1421     #define ICV_PUT_POINT( ptr, x )     \
1422         CV_MEMCPY_CHAR( ptr + (x)*pix_size, color, pix_size );
1423 
1424     while( dx >= dy )
1425     {
1426         int mask;
1427         int y11 = center.y - dy, y12 = center.y + dy, y21 = center.y - dx, y22 = center.y + dx;
1428         int x11 = center.x - dx, x12 = center.x + dx, x21 = center.x - dy, x22 = center.x + dy;
1429 
1430         if( inside )
1431         {
1432             uchar *tptr0 = ptr + y11 * step;
1433             uchar *tptr1 = ptr + y12 * step;
1434 
1435             if( !fill )
1436             {
1437                 ICV_PUT_POINT( tptr0, x11 );
1438                 ICV_PUT_POINT( tptr1, x11 );
1439                 ICV_PUT_POINT( tptr0, x12 );
1440                 ICV_PUT_POINT( tptr1, x12 );
1441             }
1442             else
1443             {
1444                 ICV_HLINE( tptr0, x11, x12, color, pix_size );
1445                 ICV_HLINE( tptr1, x11, x12, color, pix_size );
1446             }
1447 
1448             tptr0 = ptr + y21 * step;
1449             tptr1 = ptr + y22 * step;
1450 
1451             if( !fill )
1452             {
1453                 ICV_PUT_POINT( tptr0, x21 );
1454                 ICV_PUT_POINT( tptr1, x21 );
1455                 ICV_PUT_POINT( tptr0, x22 );
1456                 ICV_PUT_POINT( tptr1, x22 );
1457             }
1458             else
1459             {
1460                 ICV_HLINE( tptr0, x21, x22, color, pix_size );
1461                 ICV_HLINE( tptr1, x21, x22, color, pix_size );
1462             }
1463         }
1464         else if( x11 < size.width && x12 >= 0 && y21 < size.height && y22 >= 0 )
1465         {
1466             if( fill )
1467             {
1468                 x11 = MAX( x11, 0 );
1469                 x12 = MIN( x12, size.width - 1 );
1470             }
1471 
1472             if( (unsigned)y11 < (unsigned)size.height )
1473             {
1474                 uchar *tptr = ptr + y11 * step;
1475 
1476                 if( !fill )
1477                 {
1478                     if( x11 >= 0 )
1479                         ICV_PUT_POINT( tptr, x11 );
1480                     if( x12 < size.width )
1481                         ICV_PUT_POINT( tptr, x12 );
1482                 }
1483                 else
1484                     ICV_HLINE( tptr, x11, x12, color, pix_size );
1485             }
1486 
1487             if( (unsigned)y12 < (unsigned)size.height )
1488             {
1489                 uchar *tptr = ptr + y12 * step;
1490 
1491                 if( !fill )
1492                 {
1493                     if( x11 >= 0 )
1494                         ICV_PUT_POINT( tptr, x11 );
1495                     if( x12 < size.width )
1496                         ICV_PUT_POINT( tptr, x12 );
1497                 }
1498                 else
1499                     ICV_HLINE( tptr, x11, x12, color, pix_size );
1500             }
1501 
1502             if( x21 < size.width && x22 >= 0 )
1503             {
1504                 if( fill )
1505                 {
1506                     x21 = MAX( x21, 0 );
1507                     x22 = MIN( x22, size.width - 1 );
1508                 }
1509 
1510                 if( (unsigned)y21 < (unsigned)size.height )
1511                 {
1512                     uchar *tptr = ptr + y21 * step;
1513 
1514                     if( !fill )
1515                     {
1516                         if( x21 >= 0 )
1517                             ICV_PUT_POINT( tptr, x21 );
1518                         if( x22 < size.width )
1519                             ICV_PUT_POINT( tptr, x22 );
1520                     }
1521                     else
1522                         ICV_HLINE( tptr, x21, x22, color, pix_size );
1523                 }
1524 
1525                 if( (unsigned)y22 < (unsigned)size.height )
1526                 {
1527                     uchar *tptr = ptr + y22 * step;
1528 
1529                     if( !fill )
1530                     {
1531                         if( x21 >= 0 )
1532                             ICV_PUT_POINT( tptr, x21 );
1533                         if( x22 < size.width )
1534                             ICV_PUT_POINT( tptr, x22 );
1535                     }
1536                     else
1537                         ICV_HLINE( tptr, x21, x22, color, pix_size );
1538                 }
1539             }
1540         }
1541         dy++;
1542         err += plus;
1543         plus += 2;
1544 
1545         mask = (err <= 0) - 1;
1546 
1547         err -= minus & mask;
1548         dx += mask;
1549         minus -= mask & 2;
1550     }
1551 
1552     #undef  ICV_PUT_POINT
1553 }
1554 
1555 
1556 static void
icvThickLine(CvMat * img,CvPoint p0,CvPoint p1,const void * color,int thickness,int line_type,int flags,int shift)1557 icvThickLine( CvMat* img, CvPoint p0, CvPoint p1, const void* color,
1558               int thickness, int line_type, int flags, int shift )
1559 {
1560     static const double INV_XY_ONE = 1./XY_ONE;
1561 
1562     p0.x <<= XY_SHIFT - shift;
1563     p0.y <<= XY_SHIFT - shift;
1564     p1.x <<= XY_SHIFT - shift;
1565     p1.y <<= XY_SHIFT - shift;
1566 
1567     if( thickness <= 1 )
1568     {
1569         if( line_type < CV_AA )
1570         {
1571             if( line_type == 1 || line_type == 4 || shift == 0 )
1572             {
1573                 p0.x = (p0.x + (XY_ONE>>1)) >> XY_SHIFT;
1574                 p0.y = (p0.y + (XY_ONE>>1)) >> XY_SHIFT;
1575                 p1.x = (p1.x + (XY_ONE>>1)) >> XY_SHIFT;
1576                 p1.y = (p1.y + (XY_ONE>>1)) >> XY_SHIFT;
1577                 icvLine( img, p0, p1, color, line_type );
1578             }
1579             else
1580                 icvLine2( img, p0, p1, color );
1581         }
1582         else
1583             icvLineAA( img, p0, p1, color );
1584     }
1585     else
1586     {
1587         CvPoint pt[4], dp = {0,0};
1588         double dx = (p0.x - p1.x)*INV_XY_ONE, dy = (p1.y - p0.y)*INV_XY_ONE;
1589         double r = dx * dx + dy * dy;
1590         int i;
1591         thickness <<= XY_SHIFT - 1;
1592 
1593         if( fabs(r) > DBL_EPSILON )
1594         {
1595             r = thickness * cvInvSqrt( (float) r );
1596             dp.x = cvRound( dy * r );
1597             dp.y = cvRound( dx * r );
1598         }
1599 
1600         pt[0].x = p0.x + dp.x;
1601         pt[0].y = p0.y + dp.y;
1602         pt[1].x = p0.x - dp.x;
1603         pt[1].y = p0.y - dp.y;
1604         pt[2].x = p1.x - dp.x;
1605         pt[2].y = p1.y - dp.y;
1606         pt[3].x = p1.x + dp.x;
1607         pt[3].y = p1.y + dp.y;
1608 
1609         icvFillConvexPoly( img, pt, 4, color, line_type, XY_SHIFT );
1610 
1611         for( i = 0; i < 2; i++ )
1612         {
1613             if( flags & (i+1) )
1614             {
1615                 if( line_type < CV_AA )
1616                 {
1617                     CvPoint center;
1618                     center.x = (p0.x + (XY_ONE>>1)) >> XY_SHIFT;
1619                     center.y = (p0.y + (XY_ONE>>1)) >> XY_SHIFT;
1620                     icvCircle( img, center, thickness >> XY_SHIFT, color, 1 );
1621                 }
1622                 else
1623                 {
1624                     icvEllipseEx( img, p0, cvSize(thickness, thickness),
1625                                   0, 0, 360, color, -1, line_type );
1626                 }
1627             }
1628             p0 = p1;
1629         }
1630     }
1631 }
1632 
1633 
1634 static void
icvPolyLine(CvMat * img,CvPoint * v,int count,int is_closed,const void * color,int thickness,int line_type,int shift)1635 icvPolyLine( CvMat* img, CvPoint *v, int count, int is_closed,
1636              const void* color, int thickness,
1637              int line_type, int shift )
1638 {
1639     CV_FUNCNAME("icvPolyLine");
1640 
1641     __BEGIN__;
1642 
1643     if( count > 0 )
1644     {
1645         int i = is_closed ? count - 1 : 0;
1646         int flags = 2 + !is_closed;
1647         CvPoint p0;
1648         assert( 0 <= shift && shift <= XY_SHIFT );
1649         assert( img && thickness >= 0 );
1650         assert( v && count >= 0 );
1651 
1652         if( !v )
1653             CV_ERROR( CV_StsNullPtr, "" );
1654 
1655         p0 = v[i];
1656         for( i = !is_closed; i < count; i++ )
1657         {
1658             CvPoint p = v[i];
1659             icvThickLine( img, p0, p, color, thickness, line_type, flags, shift );
1660             p0 = p;
1661             flags = 2;
1662         }
1663     }
1664 
1665     __END__;
1666 }
1667 
1668 /****************************************************************************************\
1669 *                              External functions                                        *
1670 \****************************************************************************************/
1671 
cvColorToScalar(double packed_color,int type)1672 CV_IMPL CvScalar cvColorToScalar( double packed_color, int type )
1673 {
1674     CvScalar scalar;
1675 
1676     if( CV_MAT_DEPTH( type ) == CV_8U )
1677     {
1678         int icolor = cvRound( packed_color );
1679         if( CV_MAT_CN( type ) > 1 )
1680         {
1681             scalar.val[0] = icolor & 255;
1682             scalar.val[1] = (icolor >> 8) & 255;
1683             scalar.val[2] = (icolor >> 16) & 255;
1684             scalar.val[3] = (icolor >> 24) & 255;
1685         }
1686         else
1687         {
1688             scalar.val[0] = CV_CAST_8U( icolor );
1689             scalar.val[1] = scalar.val[2] = scalar.val[3] = 0;
1690         }
1691     }
1692     else if( CV_MAT_DEPTH( type ) == CV_8S )
1693     {
1694         int icolor = cvRound( packed_color );
1695         if( CV_MAT_CN( type ) > 1 )
1696         {
1697             scalar.val[0] = (char)icolor;
1698             scalar.val[1] = (char)(icolor >> 8);
1699             scalar.val[2] = (char)(icolor >> 16);
1700             scalar.val[3] = (char)(icolor >> 24);
1701         }
1702         else
1703         {
1704             scalar.val[0] = CV_CAST_8S( icolor );
1705             scalar.val[1] = scalar.val[2] = scalar.val[3] = 0;
1706         }
1707     }
1708     else
1709     {
1710         int cn = CV_MAT_CN( type );
1711         switch( cn )
1712         {
1713         case 1:
1714             scalar.val[0] = packed_color;
1715             scalar.val[1] = scalar.val[2] = scalar.val[3] = 0;
1716             break;
1717         case 2:
1718             scalar.val[0] = scalar.val[1] = packed_color;
1719             scalar.val[2] = scalar.val[3] = 0;
1720             break;
1721         case 3:
1722             scalar.val[0] = scalar.val[1] = scalar.val[2] = packed_color;
1723             scalar.val[3] = 0;
1724             break;
1725         default:
1726             scalar.val[0] = scalar.val[1] =
1727                 scalar.val[2] = scalar.val[3] = packed_color;
1728             break;
1729         }
1730     }
1731 
1732     return scalar;
1733 }
1734 
1735 
1736 CV_IMPL void
cvLine(void * img,CvPoint pt1,CvPoint pt2,CvScalar color,int thickness,int line_type,int shift)1737 cvLine( void* img, CvPoint pt1, CvPoint pt2, CvScalar color,
1738         int thickness, int line_type, int shift )
1739 {
1740     CV_FUNCNAME( "cvLine" );
1741 
1742     __BEGIN__;
1743 
1744     int coi = 0;
1745     CvMat stub, *mat = (CvMat*)img;
1746     double buf[4];
1747 
1748     CV_CALL( mat = cvGetMat( img, &stub, &coi ));
1749 
1750     if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U )
1751         line_type = 8;
1752 
1753     if( coi != 0 )
1754         CV_ERROR( CV_BadCOI, cvUnsupportedFormat );
1755 
1756     if( (unsigned)thickness > 255  )
1757         CV_ERROR( CV_StsOutOfRange, "" );
1758 
1759     if( shift < 0 || XY_SHIFT < shift )
1760         CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" );
1761 
1762     CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 ));
1763     icvThickLine( mat, pt1, pt2, buf, thickness, line_type, 3, shift );
1764 
1765     __END__;
1766 }
1767 
1768 
1769 CV_IMPL void
cvRectangle(void * img,CvPoint pt1,CvPoint pt2,CvScalar color,int thickness,int line_type,int shift)1770 cvRectangle( void* img, CvPoint pt1, CvPoint pt2,
1771              CvScalar color, int thickness,
1772              int line_type, int shift )
1773 {
1774     CvPoint pt[4];
1775 
1776     CV_FUNCNAME("cvRectangle");
1777 
1778     __BEGIN__;
1779 
1780     int coi = 0;
1781     CvMat stub, *mat = (CvMat*)img;
1782     double buf[4];
1783 
1784     if( thickness > 255 )
1785         CV_ERROR( CV_StsOutOfRange, "" );
1786 
1787     CV_CALL( mat = cvGetMat( img, &stub, &coi ));
1788 
1789     if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U )
1790         line_type = 8;
1791 
1792     if( coi != 0 )
1793         CV_ERROR( CV_BadCOI, cvUnsupportedFormat );
1794 
1795     if( shift < 0 || XY_SHIFT < shift )
1796         CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" );
1797 
1798     CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 ));
1799 
1800     pt[0] = pt1;
1801     pt[1].x = pt2.x;
1802     pt[1].y = pt1.y;
1803     pt[2] = pt2;
1804     pt[3].x = pt1.x;
1805     pt[3].y = pt2.y;
1806 
1807     if( thickness >= 0 )
1808         icvPolyLine( mat, pt, 4, 1, buf, thickness, line_type, shift );
1809     else
1810         icvFillConvexPoly( mat, pt, 4, buf, line_type, shift );
1811 
1812     __END__;
1813 }
1814 
1815 
1816 CV_IMPL void
cvCircle(void * img,CvPoint center,int radius,CvScalar color,int thickness,int line_type,int shift)1817 cvCircle( void *img, CvPoint center, int radius,
1818           CvScalar color, int thickness, int line_type, int shift )
1819 {
1820     CV_FUNCNAME( "cvCircle" );
1821 
1822     __BEGIN__;
1823 
1824     int coi = 0;
1825     CvMat stub, *mat = (CvMat*)img;
1826     double buf[4];
1827 
1828     CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
1829 
1830     if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U )
1831         line_type = 8;
1832 
1833     if( coi != 0 )
1834         CV_ERROR( CV_BadCOI, cvUnsupportedFormat );
1835 
1836     if( radius < 0 )
1837         CV_ERROR( CV_StsOutOfRange, "" );
1838 
1839     if( thickness > 255 )
1840         CV_ERROR( CV_StsOutOfRange, "" );
1841 
1842     if( shift < 0 || XY_SHIFT < shift )
1843         CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" );
1844 
1845     CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 ));
1846 
1847     if( thickness > 1 || line_type >= CV_AA )
1848     {
1849         center.x <<= XY_SHIFT - shift;
1850         center.y <<= XY_SHIFT - shift;
1851         radius <<= XY_SHIFT - shift;
1852         icvEllipseEx( mat, center, cvSize( radius, radius ),
1853                       0, 0, 360, buf, thickness, line_type );
1854     }
1855     else
1856     {
1857         icvCircle( mat, center, radius, buf, thickness < 0 );
1858     }
1859 
1860     __END__;
1861 }
1862 
1863 
1864 CV_IMPL void
cvEllipse(void * img,CvPoint center,CvSize axes,double angle,double start_angle,double end_angle,CvScalar color,int thickness,int line_type,int shift)1865 cvEllipse( void *img, CvPoint center, CvSize axes,
1866            double angle, double start_angle, double end_angle,
1867            CvScalar color, int thickness, int line_type, int shift )
1868 {
1869     CV_FUNCNAME( "cvEllipse" );
1870 
1871     __BEGIN__;
1872 
1873     int coi = 0;
1874     CvMat stub, *mat = (CvMat*)img;
1875     double buf[4];
1876 
1877     CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
1878 
1879     if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U )
1880         line_type = 8;
1881 
1882     if( coi != 0 )
1883         CV_ERROR( CV_BadCOI, cvUnsupportedFormat );
1884 
1885     if( axes.width < 0 || axes.height < 0 )
1886         CV_ERROR( CV_StsOutOfRange, "" );
1887 
1888     if( thickness > 255 )
1889         CV_ERROR( CV_StsOutOfRange, "" );
1890 
1891     if( shift < 0 || XY_SHIFT < shift )
1892         CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" );
1893 
1894     CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 ));
1895 
1896     {
1897         int _angle = cvRound(angle);
1898         int _start_angle = cvRound(start_angle);
1899         int _end_angle = cvRound(end_angle);
1900         center.x <<= XY_SHIFT - shift;
1901         center.y <<= XY_SHIFT - shift;
1902         axes.width <<= XY_SHIFT - shift;
1903         axes.height <<= XY_SHIFT - shift;
1904 
1905         CV_CALL( icvEllipseEx( mat, center, axes, _angle, _start_angle,
1906                                _end_angle, buf, thickness, line_type ));
1907     }
1908 
1909     __END__;
1910 }
1911 
1912 
1913 CV_IMPL void
cvFillConvexPoly(void * img,CvPoint * pts,int npts,CvScalar color,int line_type,int shift)1914 cvFillConvexPoly( void *img, CvPoint *pts, int npts, CvScalar color, int line_type, int shift )
1915 {
1916     CV_FUNCNAME( "cvFillConvexPoly" );
1917 
1918     __BEGIN__;
1919 
1920     int coi = 0;
1921     CvMat stub, *mat = (CvMat*)img;
1922     double buf[4];
1923 
1924     CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
1925 
1926     if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U )
1927         line_type = 8;
1928 
1929     if( coi != 0 )
1930         CV_ERROR( CV_BadCOI, cvUnsupportedFormat );
1931 
1932     if( !pts )
1933         CV_ERROR( CV_StsNullPtr, "" );
1934 
1935     if( npts <= 0 )
1936         CV_ERROR( CV_StsOutOfRange, "" );
1937 
1938     if( shift < 0 || XY_SHIFT < shift )
1939         CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" );
1940 
1941     CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 ));
1942     icvFillConvexPoly( mat, pts, npts, buf, line_type, shift );
1943 
1944     __END__;
1945 }
1946 
1947 
1948 CV_IMPL void
cvFillPoly(void * img,CvPoint ** pts,int * npts,int contours,CvScalar color,int line_type,int shift)1949 cvFillPoly( void *img, CvPoint **pts, int *npts, int contours,
1950             CvScalar color, int line_type, int shift )
1951 {
1952     CvMemStorage* st = 0;
1953 
1954     CV_FUNCNAME( "cvFillPoly" );
1955 
1956     __BEGIN__;
1957 
1958     int coi = 0;
1959     CvMat stub, *mat = (CvMat*)img;
1960     double buf[4];
1961 
1962     CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
1963 
1964     if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U )
1965         line_type = 8;
1966 
1967     if( coi != 0 )
1968         CV_ERROR( CV_BadCOI, cvUnsupportedFormat );
1969 
1970     if( contours <= 0 )
1971         CV_ERROR( CV_StsBadArg, "" );
1972 
1973     if( !pts )
1974         CV_ERROR( CV_StsNullPtr, "" );
1975 
1976     if( npts <= 0 )
1977         CV_ERROR( CV_StsNullPtr, "" );
1978 
1979     if( shift < 0 || XY_SHIFT < shift )
1980         CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" );
1981 
1982     CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 ));
1983 
1984     {
1985         CvContour* edges = 0;
1986         CvSeq vtx;
1987         CvSeqBlock block;
1988 
1989         CV_CALL( st = cvCreateMemStorage( CV_DRAWING_STORAGE_BLOCK ));
1990         CV_CALL( edges = (CvContour*)cvCreateSeq( 0, sizeof(CvContour),
1991                                                   sizeof(CvPolyEdge), st ));
1992 
1993         for( int i = 0; i < contours; i++ )
1994         {
1995             if( !pts[i] )
1996                 CV_ERROR( CV_StsNullPtr, "" );
1997 
1998             if( npts[i] < 0 )
1999                 CV_ERROR( CV_StsOutOfRange, "" );
2000 
2001             cvMakeSeqHeaderForArray( CV_32SC2, sizeof(CvSeq), sizeof(CvPoint),
2002                                      pts[i], npts[i], &vtx, &block );
2003 
2004             CV_CALL( icvCollectPolyEdges( mat, &vtx, edges, buf, line_type, shift ));
2005         }
2006 
2007         CV_CALL( icvFillEdgeCollection( mat, edges, buf ));
2008     }
2009 
2010     __END__;
2011 
2012     cvReleaseMemStorage( &st );
2013 }
2014 
2015 
2016 
2017 CV_IMPL void
cvPolyLine(void * img,CvPoint ** pts,int * npts,int contours,int closed,CvScalar color,int thickness,int line_type,int shift)2018 cvPolyLine( void *img, CvPoint **pts, int *npts,
2019             int contours, int closed, CvScalar color,
2020             int thickness, int line_type, int shift )
2021 {
2022     CV_FUNCNAME( "cvPolyLine" );
2023 
2024     __BEGIN__;
2025 
2026     int coi = 0, i;
2027     CvMat stub, *mat = (CvMat*)img;
2028     double buf[4];
2029 
2030     CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
2031 
2032     if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U )
2033         line_type = 8;
2034 
2035     if( coi != 0 )
2036         CV_ERROR( CV_BadCOI, cvUnsupportedFormat );
2037 
2038     if( contours <= 0 )
2039         CV_ERROR( CV_StsBadArg, "" );
2040 
2041     if( thickness < -1 || thickness > 255 )
2042         CV_ERROR( CV_StsBadArg, "" );
2043 
2044     if( !pts )
2045         CV_ERROR( CV_StsNullPtr, "" );
2046 
2047     if( npts <= 0 )
2048         CV_ERROR( CV_StsNullPtr, "" );
2049 
2050     if( shift < 0 || XY_SHIFT < shift )
2051         CV_ERROR( CV_StsOutOfRange, "shift must be between 0 and 16" );
2052 
2053     CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 ));
2054 
2055     for( i = 0; i < contours; i++ )
2056         icvPolyLine( mat, pts[i], npts[i], closed, buf, thickness, line_type, shift );
2057 
2058     __END__;
2059 }
2060 
2061 
2062 #define CV_FONT_SIZE_SHIFT     8
2063 #define CV_FONT_ITALIC_ALPHA   (1 << 8)
2064 #define CV_FONT_ITALIC_DIGIT   (2 << 8)
2065 #define CV_FONT_ITALIC_PUNCT   (4 << 8)
2066 #define CV_FONT_ITALIC_BRACES  (8 << 8)
2067 #define CV_FONT_HAVE_GREEK     (16 << 8)
2068 #define CV_FONT_HAVE_CYRILLIC  (32 << 8)
2069 
2070 static const int icvHersheyPlain[] = {
2071 (5 + 4*16) + CV_FONT_HAVE_GREEK,
2072 199, 214, 217, 233, 219, 197, 234, 216, 221, 222, 228, 225, 211, 224, 210, 220,
2073 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 212, 213, 191, 226, 192,
2074 215, 190, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
2075 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 193, 84,
2076 194, 85, 86, 87, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
2077 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
2078 195, 223, 196, 88 };
2079 
2080 static const int icvHersheyPlainItalic[] = {
2081 (5 + 4*16) + CV_FONT_ITALIC_ALPHA + CV_FONT_HAVE_GREEK,
2082 199, 214, 217, 233, 219, 197, 234, 216, 221, 222, 228, 225, 211, 224, 210, 220,
2083 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 212, 213, 191, 226, 192,
2084 215, 190, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
2085 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 193, 84,
2086 194, 85, 86, 87, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
2087 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
2088 195, 223, 196, 88 };
2089 
2090 static const int icvHersheyComplexSmall[] = {
2091 (6 + 7*16) + CV_FONT_HAVE_GREEK,
2092 1199, 1214, 1217, 1275, 1274, 1271, 1272, 1216, 1221, 1222, 1219, 1232, 1211, 1231, 1210, 1220,
2093 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1212, 2213, 1241, 1238, 1242,
2094 1215, 1273, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013,
2095 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1223, 1084,
2096 1224, 1247, 586, 1249, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111,
2097 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126,
2098 1225, 1229, 1226, 1246 };
2099 
2100 static const int icvHersheyComplexSmallItalic[] = {
2101 (6 + 7*16) + CV_FONT_ITALIC_ALPHA + CV_FONT_HAVE_GREEK,
2102 1199, 1214, 1217, 1275, 1274, 1271, 1272, 1216, 1221, 1222, 1219, 1232, 1211, 1231, 1210, 1220,
2103 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1212, 1213, 1241, 1238, 1242,
2104 1215, 1273, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063,
2105 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1223, 1084,
2106 1224, 1247, 586, 1249, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161,
2107 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176,
2108 1225, 1229, 1226, 1246 };
2109 
2110 static const int icvHersheySimplex[] = {
2111 (9 + 12*16) + CV_FONT_HAVE_GREEK,
2112 2199, 714, 717, 733, 719, 697, 734, 716, 721, 722, 728, 725, 711, 724, 710, 720,
2113 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 712, 713, 691, 726, 692,
2114 715, 690, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513,
2115 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 693, 584,
2116 694, 2247, 586, 2249, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611,
2117 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626,
2118 695, 723, 696, 2246 };
2119 
2120 static const int icvHersheyDuplex[] = {
2121 (9 + 12*16) + CV_FONT_HAVE_GREEK,
2122 2199, 2714, 2728, 2732, 2719, 2733, 2718, 2727, 2721, 2722, 2723, 2725, 2711, 2724, 2710, 2720,
2123 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2712, 2713, 2730, 2726, 2731,
2124 2715, 2734, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513,
2125 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, 2223, 2084,
2126 2224, 2247, 587, 2249, 2601, 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611,
2127 2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626,
2128 2225, 2229, 2226, 2246 };
2129 
2130 static const int icvHersheyComplex[] = {
2131 (9 + 12*16) + CV_FONT_HAVE_GREEK + CV_FONT_HAVE_CYRILLIC,
2132 2199, 2214, 2217, 2275, 2274, 2271, 2272, 2216, 2221, 2222, 2219, 2232, 2211, 2231, 2210, 2220,
2133 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2212, 2213, 2241, 2238, 2242,
2134 2215, 2273, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013,
2135 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2223, 2084,
2136 2224, 2247, 587, 2249, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111,
2137 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126,
2138 2225, 2229, 2226, 2246 };
2139 
2140 static const int icvHersheyComplexItalic[] = {
2141 (9 + 12*16) + CV_FONT_ITALIC_ALPHA + CV_FONT_ITALIC_DIGIT + CV_FONT_ITALIC_PUNCT +
2142 CV_FONT_HAVE_GREEK + CV_FONT_HAVE_CYRILLIC,
2143 2199, 2764, 2778, 2782, 2769, 2783, 2768, 2777, 2771, 2772, 2219, 2232, 2211, 2231, 2210, 2220,
2144 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2212, 2213, 2241, 2238, 2242,
2145 2765, 2273, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063,
2146 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2223, 2084,
2147 2224, 2247, 587, 2249, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161,
2148 2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176,
2149 2225, 2229, 2226, 2246 };
2150 
2151 static const int icvHersheyTriplex[] = {
2152 (9 + 12*16) + CV_FONT_HAVE_GREEK,
2153 2199, 3214, 3228, 3232, 3219, 3233, 3218, 3227, 3221, 3222, 3223, 3225, 3211, 3224, 3210, 3220,
2154 3200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209, 3212, 3213, 3230, 3226, 3231,
2155 3215, 3234, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013,
2156 2014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3025, 3026, 2223, 2084,
2157 2224, 2247, 587, 2249, 3101, 3102, 3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, 3111,
2158 3112, 3113, 3114, 3115, 3116, 3117, 3118, 3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126,
2159 2225, 2229, 2226, 2246 };
2160 
2161 static const int icvHersheyTriplexItalic[] = {
2162 (9 + 12*16) + CV_FONT_ITALIC_ALPHA + CV_FONT_ITALIC_DIGIT +
2163 CV_FONT_ITALIC_PUNCT + CV_FONT_HAVE_GREEK,
2164 2199, 3264, 3278, 3282, 3269, 3233, 3268, 3277, 3271, 3272, 3223, 3225, 3261, 3224, 3260, 3270,
2165 3250, 3251, 3252, 3253, 3254, 3255, 3256, 3257, 3258, 3259, 3262, 3263, 3230, 3226, 3231,
2166 3265, 3234, 3051, 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, 3063,
2167 2064, 3065, 3066, 3067, 3068, 3069, 3070, 3071, 3072, 3073, 3074, 3075, 3076, 2223, 2084,
2168 2224, 2247, 587, 2249, 3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161,
2169 3162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, 3176,
2170 2225, 2229, 2226, 2246 };
2171 
2172 static const int icvHersheyScriptSimplex[] = {
2173 (9 + 12*16) + CV_FONT_ITALIC_ALPHA + CV_FONT_HAVE_GREEK,
2174 2199, 714, 717, 733, 719, 697, 734, 716, 721, 722, 728, 725, 711, 724, 710, 720,
2175 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 712, 713, 691, 726, 692,
2176 715, 690, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563,
2177 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 693, 584,
2178 694, 2247, 586, 2249, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661,
2179 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676,
2180 695, 723, 696, 2246 };
2181 
2182 static const int icvHersheyScriptComplex[] = {
2183 (9 + 12*16) + CV_FONT_ITALIC_ALPHA + CV_FONT_ITALIC_DIGIT + CV_FONT_ITALIC_PUNCT + CV_FONT_HAVE_GREEK,
2184 2199, 2764, 2778, 2782, 2769, 2783, 2768, 2777, 2771, 2772, 2219, 2232, 2211, 2231, 2210, 2220,
2185 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2212, 2213, 2241, 2238, 2242,
2186 2215, 2273, 2551, 2552, 2553, 2554, 2555, 2556, 2557, 2558, 2559, 2560, 2561, 2562, 2563,
2187 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, 2575, 2576, 2223, 2084,
2188 2224, 2247, 586, 2249, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661,
2189 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676,
2190 2225, 2229, 2226, 2246 };
2191 
2192 
2193 CV_IMPL void
cvPutText(void * img,const char * text,CvPoint org,const CvFont * font,CvScalar color)2194 cvPutText( void *img, const char *text, CvPoint org, const CvFont *font, CvScalar color )
2195 {
2196     CV_FUNCNAME( "cvPutText" );
2197 
2198     __BEGIN__;
2199 
2200     int view_x, view_y;
2201     int coi = 0;
2202     int top_bottom = 0, base_line;
2203     int hscale, vscale, default_shear, italic_shear;
2204     int thickness, line_type;
2205     CvMat stub, *mat = (CvMat*)img;
2206     double buf[4];
2207     CvPoint pt[1 << 10];
2208     int count;
2209 
2210     int i;
2211     const char **faces = icvHersheyGlyphs;
2212 
2213     CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
2214 
2215     if( coi != 0 )
2216         CV_ERROR( CV_BadCOI, cvUnsupportedFormat );
2217 
2218     if( CV_IS_IMAGE_HDR(img) && ((IplImage*)img)->origin )
2219         top_bottom = 1;
2220 
2221     if( !text || !font || !font->ascii )
2222         CV_ERROR( CV_StsNullPtr, "" );
2223 
2224     CV_CALL( cvScalarToRawData( &color, buf, mat->type, 0 ));
2225     base_line = -(font->ascii[0] & 15);
2226     hscale = cvRound(font->hscale*XY_ONE);
2227     vscale = cvRound(font->vscale*XY_ONE);
2228     default_shear = cvRound(font->shear*font->vscale*XY_ONE);
2229     italic_shear = !(font->font_face & CV_FONT_ITALIC) ? 0 : cvRound(font->vscale*.25*XY_ONE);
2230     thickness = font->thickness;
2231     line_type = font->line_type;
2232 
2233     if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U )
2234         line_type = 8;
2235 
2236     if( top_bottom )
2237         vscale = -vscale;
2238 
2239     view_x = org.x << XY_SHIFT;
2240     view_y = (org.y << XY_SHIFT) + base_line*vscale;
2241 
2242     for( i = 0; text[i] != '\0'; i++ )
2243     {
2244         int c = (uchar)text[i];
2245         int dx, shear = default_shear;
2246         const char* ptr;
2247         CvPoint p;
2248 
2249         if( c > 128 || c < ' ' )
2250             c = '?';
2251 
2252         if( italic_shear )
2253         {
2254             if( ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
2255             {
2256                 if( !(font->ascii[0] & CV_FONT_ITALIC_ALPHA) )
2257                     shear += italic_shear;
2258             }
2259             else if( '0' <= c && c <= '9' )
2260             {
2261                 if( !(font->ascii[0] & CV_FONT_ITALIC_DIGIT) )
2262                     shear += italic_shear;
2263             }
2264             else if( c < 'A' )
2265             {
2266                 if( !(font->ascii[0] & CV_FONT_ITALIC_PUNCT) )
2267                     shear += italic_shear;
2268             }
2269             else
2270             {
2271                 shear += italic_shear;
2272             }
2273         }
2274 
2275         ptr = faces[font->ascii[(c-' ')+1]];
2276         p.x = (unsigned char)ptr[0] - 'R';
2277         p.y = (unsigned char)ptr[1] - 'R';
2278         dx = p.y*hscale;
2279         view_x -= p.x*hscale;
2280         count = 0;
2281 
2282         for( ptr += 2;; )
2283         {
2284             if( *ptr == ' ' || !*ptr )
2285             {
2286                 if( count > 1 )
2287                     icvPolyLine( mat, pt, count, 0, buf, thickness, line_type, XY_SHIFT );
2288                 if( !*ptr++ )
2289                     break;
2290                 count = 0;
2291             }
2292             else
2293             {
2294                 p.x = (unsigned char)ptr[0] - 'R';
2295                 p.y = (unsigned char)ptr[1] - 'R';
2296                 ptr += 2;
2297                 pt[count].x = p.x*hscale - p.y*shear + view_x;
2298                 pt[count++].y = p.y*vscale + view_y;
2299             }
2300         }
2301         view_x += dx;
2302     }
2303 
2304     __END__;
2305 }
2306 
2307 CV_IMPL void
cvInitFont(CvFont * font,int font_face,double hscale,double vscale,double shear,int thickness,int line_type)2308 cvInitFont( CvFont *font, int font_face, double hscale, double vscale,
2309             double shear, int thickness, int line_type )
2310 {
2311     CV_FUNCNAME( "cvInitFont" );
2312 
2313     __BEGIN__;
2314 
2315     int is_italic = font_face & CV_FONT_ITALIC;
2316 
2317     if( !font )
2318         CV_ERROR( CV_StsNullPtr, "" );
2319 
2320     if( hscale <= 0 || vscale <= 0 || thickness < 0 )
2321         CV_ERROR( CV_StsOutOfRange, "" );
2322 
2323     switch( (font_face & 7) )
2324     {
2325     case CV_FONT_HERSHEY_SIMPLEX:
2326         font->ascii = icvHersheySimplex;
2327         break;
2328     case CV_FONT_HERSHEY_PLAIN:
2329         font->ascii = !is_italic ? icvHersheyPlain : icvHersheyPlainItalic;
2330         break;
2331     case CV_FONT_HERSHEY_DUPLEX:
2332         font->ascii = icvHersheyDuplex;
2333         break;
2334     case CV_FONT_HERSHEY_COMPLEX:
2335         font->ascii = !is_italic ? icvHersheyComplex : icvHersheyComplexItalic;
2336         break;
2337     case CV_FONT_HERSHEY_TRIPLEX:
2338         font->ascii = !is_italic ? icvHersheyTriplex : icvHersheyTriplexItalic;
2339         break;
2340     case CV_FONT_HERSHEY_COMPLEX_SMALL:
2341         font->ascii = !is_italic ? icvHersheyComplexSmall : icvHersheyComplexSmallItalic;
2342         break;
2343     case CV_FONT_HERSHEY_SCRIPT_SIMPLEX:
2344         font->ascii = icvHersheyScriptSimplex;
2345         break;
2346     case CV_FONT_HERSHEY_SCRIPT_COMPLEX:
2347         font->ascii = icvHersheyScriptComplex;
2348         break;
2349     default:
2350         CV_ERROR( CV_StsOutOfRange, "Unknown font type" );
2351     }
2352 
2353     font->font_face = font_face;
2354     font->hscale = (float)hscale;
2355     font->vscale = (float)vscale;
2356     font->thickness = thickness;
2357     font->shear = (float)shear;
2358     font->greek = font->cyrillic = 0;
2359     font->line_type = line_type;
2360 
2361     __END__;
2362 }
2363 
2364 
2365 CV_IMPL void
cvGetTextSize(const char * text,const CvFont * font,CvSize * size,int * _base_line)2366 cvGetTextSize( const char *text, const CvFont *font, CvSize *size, int *_base_line )
2367 {
2368     CV_FUNCNAME( "cvGetTextSize" );
2369 
2370     __BEGIN__;
2371 
2372     float view_x = 0;
2373     int base_line, cap_line;
2374 
2375     int i;
2376     const char **faces = icvHersheyGlyphs;
2377 
2378     if( !text || !font || !font->ascii || !size )
2379         CV_ERROR( CV_StsNullPtr, "" );
2380 
2381     base_line = (font->ascii[0] & 15);
2382     cap_line = (font->ascii[0] >> 4) & 15;
2383     if( _base_line )
2384         *_base_line = cvRound(base_line*font->vscale);
2385     size->height = cvRound((cap_line + base_line)*font->vscale + font->thickness);
2386 
2387     for( i = 0; text[i] != '\0'; i++ )
2388     {
2389         int c = (uchar)text[i];
2390         const char* ptr;
2391         CvPoint p;
2392 
2393         if( c > 128 || c < ' ' )
2394             c = '?';
2395 
2396         ptr = faces[font->ascii[(c-' ')+1]];
2397         p.x = (unsigned char)ptr[0] - 'R';
2398         p.y = (unsigned char)ptr[1] - 'R';
2399         view_x += (p.y - p.x)*font->hscale;
2400     }
2401 
2402     size->width = cvRound(view_x + font->thickness);
2403 
2404     __END__;
2405 }
2406 
2407 
2408 static const CvPoint icvCodeDeltas[8] =
2409 { {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1} };
2410 
2411 #define CV_ADJUST_EDGE_COUNT( count, seq )  \
2412     ((count) -= ((count) == (seq)->total && !CV_IS_SEQ_CLOSED(seq)))
2413 
2414 CV_IMPL void
cvDrawContours(void * img,CvSeq * contour,CvScalar externalColor,CvScalar holeColor,int maxLevel,int thickness,int line_type,CvPoint offset)2415 cvDrawContours( void*  img,  CvSeq*  contour,
2416                 CvScalar externalColor, CvScalar holeColor,
2417                 int  maxLevel, int thickness,
2418                 int line_type, CvPoint offset )
2419 {
2420     CvSeq *contour0 = contour, *h_next = 0;
2421     CvMemStorage* st = 0;
2422     CvSeq* tseq = 0;
2423     CvContour* edges = 0;
2424     CvSeqWriter writer;
2425     CvTreeNodeIterator iterator;
2426 
2427     CV_FUNCNAME( "cvDrawContours" );
2428 
2429     __BEGIN__;
2430 
2431     int coi = 0;
2432     CvMat stub, *mat = (CvMat*)img;
2433     double ext_buf[4], hole_buf[4];
2434 
2435     CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
2436 
2437     if( line_type == CV_AA && CV_MAT_DEPTH(mat->type) != CV_8U )
2438         line_type = 8;
2439 
2440     if( !contour )
2441         EXIT;
2442 
2443     if( coi != 0 )
2444         CV_ERROR( CV_BadCOI, cvUnsupportedFormat );
2445 
2446     if( thickness < -1 || thickness > 255 )
2447         CV_ERROR( CV_StsOutOfRange, "" );
2448 
2449     CV_CALL( cvScalarToRawData( &externalColor, ext_buf, mat->type, 0 ));
2450     CV_CALL( cvScalarToRawData( &holeColor, hole_buf, mat->type, 0 ));
2451 
2452     if( maxLevel < 0 )
2453     {
2454         h_next = contour->h_next;
2455         contour->h_next = 0;
2456         maxLevel = -maxLevel+1;
2457     }
2458 
2459     if( thickness < 0 )
2460     {
2461         if( contour->storage )
2462             st = cvCreateChildMemStorage( contour->storage );
2463         else
2464             st = cvCreateMemStorage( CV_DRAWING_STORAGE_BLOCK );
2465         tseq = cvCreateSeq( 0, sizeof(CvContour), sizeof(CvPoint), st );
2466         edges = (CvContour*)cvCreateSeq( 0, sizeof(CvContour), sizeof(CvPolyEdge), st );
2467     }
2468 
2469     memset( &writer, 0, sizeof(writer));
2470 
2471     cvInitTreeNodeIterator( &iterator, contour, maxLevel );
2472 
2473     while( (contour = (CvSeq*)cvNextTreeNode( &iterator )) != 0 )
2474     {
2475         CvSeqReader reader;
2476         int i, count = contour->total;
2477         int elem_type = CV_MAT_TYPE(contour->flags);
2478         void* clr = (contour->flags & CV_SEQ_FLAG_HOLE) == 0 ? ext_buf : hole_buf;
2479 
2480         cvStartReadSeq( contour, &reader, 0 );
2481 
2482         if( CV_IS_SEQ_CHAIN_CONTOUR( contour ))
2483         {
2484             CvPoint pt = ((CvChain*)contour)->origin;
2485             CvPoint prev_pt = pt;
2486             char prev_code = reader.ptr ? reader.ptr[0] : '\0';
2487 
2488             if( thickness < 0 )
2489             {
2490                 cvClearSeq( tseq );
2491                 cvStartAppendToSeq( tseq, &writer );
2492                 CV_WRITE_SEQ_ELEM( pt, writer );
2493             }
2494 
2495             prev_pt.x += offset.x;
2496             prev_pt.y += offset.y;
2497 
2498             for( i = 0; i < count; i++ )
2499             {
2500                 char code;
2501                 CV_READ_SEQ_ELEM( code, reader );
2502 
2503                 assert( (code & ~7) == 0 );
2504 
2505                 if( code != prev_code )
2506                 {
2507                     prev_code = code;
2508                     if( thickness >= 0 )
2509                     {
2510                         icvThickLine( mat, prev_pt, pt, clr, thickness, line_type, 2, 0 );
2511                     }
2512                     else
2513                     {
2514                         CV_WRITE_SEQ_ELEM( pt, writer );
2515                     }
2516                     prev_pt = pt;
2517                 }
2518 
2519                 pt.x += icvCodeDeltas[(int)code].x;
2520                 pt.y += icvCodeDeltas[(int)code].y;
2521             }
2522 
2523             if( thickness >= 0 )
2524             {
2525                 icvThickLine( mat, prev_pt, ((CvChain*)contour)->origin,
2526                               clr, thickness, line_type, 2, 0 );
2527             }
2528             else
2529             {
2530                 CV_WRITE_SEQ_ELEM( pt, writer );
2531                 cvEndWriteSeq( &writer );
2532                 CV_CALL( icvCollectPolyEdges( mat, tseq, edges, ext_buf, line_type, 0 ));
2533             }
2534         }
2535         else if( CV_IS_SEQ_POLYLINE( contour ))
2536         {
2537             if( thickness >= 0 )
2538             {
2539                 CvPoint pt1, pt2;
2540                 int shift = 0;
2541 
2542                 count -= !CV_IS_SEQ_CLOSED(contour);
2543                 if( elem_type == CV_32SC2 )
2544                 {
2545                     CV_READ_SEQ_ELEM( pt1, reader );
2546                     pt1.x += offset.x;
2547                     pt1.y += offset.y;
2548                 }
2549                 else
2550                 {
2551                     CvPoint2D32f pt1f;
2552                     CV_READ_SEQ_ELEM( pt1f, reader );
2553                     pt1.x = cvRound( (pt1f.x + offset.x) * XY_ONE );
2554                     pt1.y = cvRound( (pt1f.y + offset.y) * XY_ONE );
2555                     shift = XY_SHIFT;
2556                 }
2557 
2558                 for( i = 0; i < count; i++ )
2559                 {
2560                     if( elem_type == CV_32SC2 )
2561                     {
2562                         CV_READ_SEQ_ELEM( pt2, reader );
2563                         pt2.x += offset.x;
2564                         pt2.y += offset.y;
2565                     }
2566                     else
2567                     {
2568                         CvPoint2D32f pt2f;
2569                         CV_READ_SEQ_ELEM( pt2f, reader );
2570                         pt2.x = cvRound( pt2f.x * XY_ONE );
2571                         pt2.y = cvRound( pt2f.y * XY_ONE );
2572                     }
2573                     icvThickLine( mat, pt1, pt2, clr, thickness, line_type, 2, shift );
2574                     pt1 = pt2;
2575                 }
2576             }
2577             else
2578             {
2579                 CV_CALL( icvCollectPolyEdges( mat, contour, edges, ext_buf, line_type, 0, offset ));
2580             }
2581         }
2582     }
2583 
2584     if( thickness < 0 )
2585     {
2586         CV_CALL( icvFillEdgeCollection( mat, edges, ext_buf ));
2587     }
2588 
2589     __END__;
2590 
2591     if( h_next && contour0 )
2592         contour0->h_next = h_next;
2593 
2594     cvReleaseMemStorage( &st );
2595 }
2596 
2597 /* End of file. */
2598