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