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