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