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