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