Opencv 3.1 project on GR-PEACH board

Fork of gr-peach-opencv-project by the do

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers drawing.cpp Source File

drawing.cpp

00001 /*M///////////////////////////////////////////////////////////////////////////////////////
00002 //
00003 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
00004 //
00005 //  By downloading, copying, installing or using the software you agree to this license.
00006 //  If you do not agree to this license, do not download, install,
00007 //  copy or use the software.
00008 //
00009 //
00010 //                        Intel License Agreement
00011 //                For Open Source Computer Vision Library
00012 //
00013 // Copyright (C) 2000, Intel Corporation, all rights reserved.
00014 // Third party copyrights are property of their respective owners.
00015 //
00016 // Redistribution and use in source and binary forms, with or without modification,
00017 // are permitted provided that the following conditions are met:
00018 //
00019 //   * Redistribution's of source code must retain the above copyright notice,
00020 //     this list of conditions and the following disclaimer.
00021 //
00022 //   * Redistribution's in binary form must reproduce the above copyright notice,
00023 //     this list of conditions and the following disclaimer in the documentation
00024 //     and/or other materials provided with the distribution.
00025 //
00026 //   * The name of Intel Corporation may not be used to endorse or promote products
00027 //     derived from this software without specific prior written permission.
00028 //
00029 // This software is provided by the copyright holders and contributors "as is" and
00030 // any express or implied warranties, including, but not limited to, the implied
00031 // warranties of merchantability and fitness for a particular purpose are disclaimed.
00032 // In no event shall the Intel Corporation or contributors be liable for any direct,
00033 // indirect, incidental, special, exemplary, or consequential damages
00034 // (including, but not limited to, procurement of substitute goods or services;
00035 // loss of use, data, or profits; or business interruption) however caused
00036 // and on any theory of liability, whether in contract, strict liability,
00037 // or tort (including negligence or otherwise) arising in any way out of
00038 // the use of this software, even if advised of the possibility of such damage.
00039 //
00040 //M*/
00041 #include "precomp.hpp"
00042 
00043 namespace cv
00044 {
00045 
00046 enum { XY_SHIFT = 16, XY_ONE = 1 << XY_SHIFT, DRAWING_STORAGE_BLOCK = (1<<12) - 256 };
00047 
00048 static const int MAX_THICKNESS = 32767;
00049 
00050 struct PolyEdge
00051 {
00052     PolyEdge() : y0(0), y1(0), x(0), dx(0), next(0) {}
00053     //PolyEdge(int _y0, int _y1, int _x, int _dx) : y0(_y0), y1(_y1), x(_x), dx(_dx) {}
00054 
00055     int y0, y1;
00056     int x, dx;
00057     PolyEdge *next;
00058 };
00059 
00060 static void
00061 CollectPolyEdges( Mat& img, const Point* v, int npts,
00062                   std::vector<PolyEdge>& edges, const void* color, int line_type,
00063                   int shift, Point offset=Point() );
00064 
00065 static void
00066 FillEdgeCollection( Mat& img, std::vector<PolyEdge>& edges, const void* color );
00067 
00068 static void
00069 PolyLine( Mat& img, const Point* v, int npts, bool closed,
00070           const void* color, int thickness, int line_type, int shift );
00071 
00072 static void
00073 FillConvexPoly( Mat& img, const Point* v, int npts,
00074                 const void* color, int line_type, int shift );
00075 
00076 /****************************************************************************************\
00077 *                                   Lines                                                *
00078 \****************************************************************************************/
00079 
00080 bool clipLine( Size img_size, Point& pt1, Point& pt2 )
00081 {
00082     int64 x1, y1, x2, y2;
00083     int c1, c2;
00084     int64 right = img_size.width-1, bottom = img_size.height-1;
00085 
00086     if( img_size.width <= 0 || img_size.height <= 0 )
00087         return false;
00088 
00089     x1 = pt1.x; y1 = pt1.y; x2 = pt2.x; y2 = pt2.y;
00090     c1 = (x1 < 0) + (x1 > right) * 2 + (y1 < 0) * 4 + (y1 > bottom) * 8;
00091     c2 = (x2 < 0) + (x2 > right) * 2 + (y2 < 0) * 4 + (y2 > bottom) * 8;
00092 
00093     if( (c1 & c2) == 0 && (c1 | c2) != 0 )
00094     {
00095         int64 a;
00096         if( c1 & 12 )
00097         {
00098             a = c1 < 8 ? 0 : bottom;
00099             x1 +=  (a - y1) * (x2 - x1) / (y2 - y1);
00100             y1 = a;
00101             c1 = (x1 < 0) + (x1 > right) * 2;
00102         }
00103         if( c2 & 12 )
00104         {
00105             a = c2 < 8 ? 0 : bottom;
00106             x2 += (a - y2) * (x2 - x1) / (y2 - y1);
00107             y2 = a;
00108             c2 = (x2 < 0) + (x2 > right) * 2;
00109         }
00110         if( (c1 & c2) == 0 && (c1 | c2) != 0 )
00111         {
00112             if( c1 )
00113             {
00114                 a = c1 == 1 ? 0 : right;
00115                 y1 += (a - x1) * (y2 - y1) / (x2 - x1);
00116                 x1 = a;
00117                 c1 = 0;
00118             }
00119             if( c2 )
00120             {
00121                 a = c2 == 1 ? 0 : right;
00122                 y2 += (a - x2) * (y2 - y1) / (x2 - x1);
00123                 x2 = a;
00124                 c2 = 0;
00125             }
00126         }
00127 
00128         assert( (c1 & c2) != 0 || (x1 | y1 | x2 | y2) >= 0 );
00129 
00130         pt1.x = (int)x1;
00131         pt1.y = (int)y1;
00132         pt2.x = (int)x2;
00133         pt2.y = (int)y2;
00134     }
00135 
00136     return (c1 | c2) == 0;
00137 }
00138 
00139 bool clipLine( Rect img_rect, Point& pt1, Point& pt2 )
00140 {
00141     Point tl = img_rect.tl();
00142     pt1 -= tl; pt2 -= tl;
00143     bool inside = clipLine(img_rect.size(), pt1, pt2);
00144     pt1 += tl; pt2 += tl;
00145 
00146     return inside;
00147 }
00148 
00149 /*
00150    Initializes line iterator.
00151    Returns number of points on the line or negative number if error.
00152 */
00153 LineIterator::LineIterator(const Mat& img, Point  pt1, Point  pt2,
00154                            int connectivity, bool left_to_right)
00155 {
00156     count = -1;
00157 
00158     CV_Assert( connectivity == 8 || connectivity == 4 );
00159 
00160     if( (unsigned)pt1.x >= (unsigned)(img.cols) ||
00161         (unsigned)pt2.x >= (unsigned)(img.cols) ||
00162         (unsigned)pt1.y >= (unsigned)(img.rows) ||
00163         (unsigned)pt2.y >= (unsigned)(img.rows) )
00164     {
00165         if( !clipLine( img.size(), pt1, pt2 ) )
00166         {
00167             ptr = img.data;
00168             err = plusDelta = minusDelta = plusStep = minusStep = count = 0;
00169             return;
00170         }
00171     }
00172 
00173     int bt_pix0 = (int)img.elemSize(), bt_pix = bt_pix0;
00174     size_t istep = img.step;
00175 
00176     int dx = pt2.x - pt1.x;
00177     int dy = pt2.y - pt1.y;
00178     int s = dx < 0 ? -1 : 0;
00179 
00180     if( left_to_right )
00181     {
00182         dx = (dx ^ s) - s;
00183         dy = (dy ^ s) - s;
00184         pt1.x ^= (pt1.x ^ pt2.x) & s;
00185         pt1.y ^= (pt1.y ^ pt2.y) & s;
00186     }
00187     else
00188     {
00189         dx = (dx ^ s) - s;
00190         bt_pix = (bt_pix ^ s) - s;
00191     }
00192 
00193     ptr = (uchar*)(img.data + pt1.y * istep + pt1.x * bt_pix0);
00194 
00195     s = dy < 0 ? -1 : 0;
00196     dy = (dy ^ s) - s;
00197     istep = (istep ^ s) - s;
00198 
00199     s = dy > dx ? -1 : 0;
00200 
00201     /* conditional swaps */
00202     dx ^= dy & s;
00203     dy ^= dx & s;
00204     dx ^= dy & s;
00205 
00206     bt_pix ^= istep & s;
00207     istep ^= bt_pix & s;
00208     bt_pix ^= istep & s;
00209 
00210     if( connectivity == 8 )
00211     {
00212         assert( dx >= 0 && dy >= 0 );
00213 
00214         err = dx - (dy + dy);
00215         plusDelta = dx + dx;
00216         minusDelta = -(dy + dy);
00217         plusStep = (int)istep;
00218         minusStep = bt_pix;
00219         count = dx + 1;
00220     }
00221     else /* connectivity == 4 */
00222     {
00223         assert( dx >= 0 && dy >= 0 );
00224 
00225         err = 0;
00226         plusDelta = (dx + dx) + (dy + dy);
00227         minusDelta = -(dy + dy);
00228         plusStep = (int)istep - bt_pix;
00229         minusStep = bt_pix;
00230         count = dx + dy + 1;
00231     }
00232 
00233     this->ptr0 = img.ptr();
00234     this->step = (int)img.step;
00235     this->elemSize = bt_pix0;
00236 }
00237 
00238 static void
00239 Line( Mat& img, Point pt1, Point pt2,
00240       const void* _color, int connectivity = 8 )
00241 {
00242     if( connectivity == 0 )
00243         connectivity = 8;
00244     else if( connectivity == 1 )
00245         connectivity = 4;
00246 
00247     LineIterator iterator(img, pt1, pt2, connectivity, true);
00248     int i, count = iterator.count;
00249     int pix_size = (int)img.elemSize();
00250     const uchar* color = (const uchar*)_color;
00251 
00252     for( i = 0; i < count; i++, ++iterator )
00253     {
00254         uchar* ptr = *iterator;
00255         if( pix_size == 1 )
00256             ptr[0] = color[0];
00257         else if( pix_size == 3 )
00258         {
00259             ptr[0] = color[0];
00260             ptr[1] = color[1];
00261             ptr[2] = color[2];
00262         }
00263         else
00264             memcpy( *iterator, color, pix_size );
00265     }
00266 }
00267 
00268 
00269 /* Correction table depent on the slope */
00270 static const uchar SlopeCorrTable[] = {
00271     181, 181, 181, 182, 182, 183, 184, 185, 187, 188, 190, 192, 194, 196, 198, 201,
00272     203, 206, 209, 211, 214, 218, 221, 224, 227, 231, 235, 238, 242, 246, 250, 254
00273 };
00274 
00275 /* Gaussian for antialiasing filter */
00276 static const int FilterTable[] = {
00277     168, 177, 185, 194, 202, 210, 218, 224, 231, 236, 241, 246, 249, 252, 254, 254,
00278     254, 254, 252, 249, 246, 241, 236, 231, 224, 218, 210, 202, 194, 185, 177, 168,
00279     158, 149, 140, 131, 122, 114, 105, 97, 89, 82, 75, 68, 62, 56, 50, 45,
00280     40, 36, 32, 28, 25, 22, 19, 16, 14, 12, 11, 9, 8, 7, 5, 5
00281 };
00282 
00283 static void
00284 LineAA( Mat& img, Point pt1, Point pt2, const void* color )
00285 {
00286     int dx, dy;
00287     int ecount, scount = 0;
00288     int slope;
00289     int ax, ay;
00290     int x_step, y_step;
00291     int i, j;
00292     int ep_table[9];
00293     int cb = ((uchar*)color)[0], cg = ((uchar*)color)[1], cr = ((uchar*)color)[2], ca = ((uchar*)color)[3];
00294     int _cb, _cg, _cr, _ca;
00295     int nch = img.channels();
00296     uchar* ptr = img.ptr();
00297     size_t step = img.step;
00298     Size size = img.size();
00299 
00300     if( !((nch == 1 || nch == 3 || nch == 4) && img.depth() == CV_8U) )
00301     {
00302         Line(img, pt1, pt2, color);
00303         return;
00304     }
00305 
00306     pt1.x -= XY_ONE*2;
00307     pt1.y -= XY_ONE*2;
00308     pt2.x -= XY_ONE*2;
00309     pt2.y -= XY_ONE*2;
00310     ptr += img.step*2 + 2*nch;
00311 
00312     size.width = ((size.width - 5) << XY_SHIFT) + 1;
00313     size.height = ((size.height - 5) << XY_SHIFT) + 1;
00314 
00315     if( !clipLine( size, pt1, pt2 ))
00316         return;
00317 
00318     dx = pt2.x - pt1.x;
00319     dy = pt2.y - pt1.y;
00320 
00321     j = dx < 0 ? -1 : 0;
00322     ax = (dx ^ j) - j;
00323     i = dy < 0 ? -1 : 0;
00324     ay = (dy ^ i) - i;
00325 
00326     if( ax > ay )
00327     {
00328         dx = ax;
00329         dy = (dy ^ j) - j;
00330         pt1.x ^= pt2.x & j;
00331         pt2.x ^= pt1.x & j;
00332         pt1.x ^= pt2.x & j;
00333         pt1.y ^= pt2.y & j;
00334         pt2.y ^= pt1.y & j;
00335         pt1.y ^= pt2.y & j;
00336 
00337         x_step = XY_ONE;
00338         y_step = (int) (((int64) dy << XY_SHIFT) / (ax | 1));
00339         pt2.x += XY_ONE;
00340         ecount = (pt2.x >> XY_SHIFT) - (pt1.x >> XY_SHIFT);
00341         j = -(pt1.x & (XY_ONE - 1));
00342         pt1.y += (int) ((((int64) y_step) * j) >> XY_SHIFT) + (XY_ONE >> 1);
00343         slope = (y_step >> (XY_SHIFT - 5)) & 0x3f;
00344         slope ^= (y_step < 0 ? 0x3f : 0);
00345 
00346         /* Get 4-bit fractions for end-point adjustments */
00347         i = (pt1.x >> (XY_SHIFT - 7)) & 0x78;
00348         j = (pt2.x >> (XY_SHIFT - 7)) & 0x78;
00349     }
00350     else
00351     {
00352         dy = ay;
00353         dx = (dx ^ i) - i;
00354         pt1.x ^= pt2.x & i;
00355         pt2.x ^= pt1.x & i;
00356         pt1.x ^= pt2.x & i;
00357         pt1.y ^= pt2.y & i;
00358         pt2.y ^= pt1.y & i;
00359         pt1.y ^= pt2.y & i;
00360 
00361         x_step = (int) (((int64) dx << XY_SHIFT) / (ay | 1));
00362         y_step = XY_ONE;
00363         pt2.y += XY_ONE;
00364         ecount = (pt2.y >> XY_SHIFT) - (pt1.y >> XY_SHIFT);
00365         j = -(pt1.y & (XY_ONE - 1));
00366         pt1.x += (int) ((((int64) x_step) * j) >> XY_SHIFT) + (XY_ONE >> 1);
00367         slope = (x_step >> (XY_SHIFT - 5)) & 0x3f;
00368         slope ^= (x_step < 0 ? 0x3f : 0);
00369 
00370         /* Get 4-bit fractions for end-point adjustments */
00371         i = (pt1.y >> (XY_SHIFT - 7)) & 0x78;
00372         j = (pt2.y >> (XY_SHIFT - 7)) & 0x78;
00373     }
00374 
00375     slope = (slope & 0x20) ? 0x100 : SlopeCorrTable[slope];
00376 
00377     /* Calc end point correction table */
00378     {
00379         int t0 = slope << 7;
00380         int t1 = ((0x78 - i) | 4) * slope;
00381         int t2 = (j | 4) * slope;
00382 
00383         ep_table[0] = 0;
00384         ep_table[8] = slope;
00385         ep_table[1] = ep_table[3] = ((((j - i) & 0x78) | 4) * slope >> 8) & 0x1ff;
00386         ep_table[2] = (t1 >> 8) & 0x1ff;
00387         ep_table[4] = ((((j - i) + 0x80) | 4) * slope >> 8) & 0x1ff;
00388         ep_table[5] = ((t1 + t0) >> 8) & 0x1ff;
00389         ep_table[6] = (t2 >> 8) & 0x1ff;
00390         ep_table[7] = ((t2 + t0) >> 8) & 0x1ff;
00391     }
00392 
00393     if( nch == 3 )
00394     {
00395         #define  ICV_PUT_POINT()            \
00396         {                                   \
00397             _cb = tptr[0];                  \
00398             _cb += ((cb - _cb)*a + 127)>> 8;\
00399             _cg = tptr[1];                  \
00400             _cg += ((cg - _cg)*a + 127)>> 8;\
00401             _cr = tptr[2];                  \
00402             _cr += ((cr - _cr)*a + 127)>> 8;\
00403             tptr[0] = (uchar)_cb;           \
00404             tptr[1] = (uchar)_cg;           \
00405             tptr[2] = (uchar)_cr;           \
00406         }
00407         if( ax > ay )
00408         {
00409             ptr += (pt1.x >> XY_SHIFT) * 3;
00410 
00411             while( ecount >= 0 )
00412             {
00413                 uchar *tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step;
00414 
00415                 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
00416                                        (((ecount >= 2) + 1) & (ecount | 2))];
00417                 int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31;
00418 
00419                 a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
00420                 ICV_PUT_POINT();
00421                 ICV_PUT_POINT();
00422 
00423                 tptr += step;
00424                 a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
00425                 ICV_PUT_POINT();
00426                 ICV_PUT_POINT();
00427 
00428                 tptr += step;
00429                 a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
00430                 ICV_PUT_POINT();
00431                 ICV_PUT_POINT();
00432 
00433                 pt1.y += y_step;
00434                 ptr += 3;
00435                 scount++;
00436                 ecount--;
00437             }
00438         }
00439         else
00440         {
00441             ptr += (pt1.y >> XY_SHIFT) * step;
00442 
00443             while( ecount >= 0 )
00444             {
00445                 uchar *tptr = ptr + ((pt1.x >> XY_SHIFT) - 1) * 3;
00446 
00447                 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
00448                                        (((ecount >= 2) + 1) & (ecount | 2))];
00449                 int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31;
00450 
00451                 a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
00452                 ICV_PUT_POINT();
00453                 ICV_PUT_POINT();
00454 
00455                 tptr += 3;
00456                 a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
00457                 ICV_PUT_POINT();
00458                 ICV_PUT_POINT();
00459 
00460                 tptr += 3;
00461                 a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
00462                 ICV_PUT_POINT();
00463                 ICV_PUT_POINT();
00464 
00465                 pt1.x += x_step;
00466                 ptr += step;
00467                 scount++;
00468                 ecount--;
00469             }
00470         }
00471         #undef ICV_PUT_POINT
00472     }
00473     else if(nch == 1)
00474     {
00475         #define  ICV_PUT_POINT()            \
00476         {                                   \
00477             _cb = tptr[0];                  \
00478             _cb += ((cb - _cb)*a + 127)>> 8;\
00479             tptr[0] = (uchar)_cb;           \
00480         }
00481 
00482         if( ax > ay )
00483         {
00484             ptr += (pt1.x >> XY_SHIFT);
00485 
00486             while( ecount >= 0 )
00487             {
00488                 uchar *tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step;
00489 
00490                 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
00491                                        (((ecount >= 2) + 1) & (ecount | 2))];
00492                 int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31;
00493 
00494                 a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
00495                 ICV_PUT_POINT();
00496                 ICV_PUT_POINT();
00497 
00498                 tptr += step;
00499                 a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
00500                 ICV_PUT_POINT();
00501                 ICV_PUT_POINT();
00502 
00503                 tptr += step;
00504                 a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
00505                 ICV_PUT_POINT();
00506                 ICV_PUT_POINT();
00507 
00508                 pt1.y += y_step;
00509                 ptr++;
00510                 scount++;
00511                 ecount--;
00512             }
00513         }
00514         else
00515         {
00516             ptr += (pt1.y >> XY_SHIFT) * step;
00517 
00518             while( ecount >= 0 )
00519             {
00520                 uchar *tptr = ptr + ((pt1.x >> XY_SHIFT) - 1);
00521 
00522                 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
00523                                        (((ecount >= 2) + 1) & (ecount | 2))];
00524                 int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31;
00525 
00526                 a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
00527                 ICV_PUT_POINT();
00528                 ICV_PUT_POINT();
00529 
00530                 tptr++;
00531                 a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
00532                 ICV_PUT_POINT();
00533                 ICV_PUT_POINT();
00534 
00535                 tptr++;
00536                 a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
00537                 ICV_PUT_POINT();
00538                 ICV_PUT_POINT();
00539 
00540                 pt1.x += x_step;
00541                 ptr += step;
00542                 scount++;
00543                 ecount--;
00544             }
00545         }
00546         #undef ICV_PUT_POINT
00547     }
00548     else
00549     {
00550         #define  ICV_PUT_POINT()            \
00551         {                                   \
00552             _cb = tptr[0];                  \
00553             _cb += ((cb - _cb)*a + 127)>> 8;\
00554             _cg = tptr[1];                  \
00555             _cg += ((cg - _cg)*a + 127)>> 8;\
00556             _cr = tptr[2];                  \
00557             _cr += ((cr - _cr)*a + 127)>> 8;\
00558             _ca = tptr[3];                  \
00559             _ca += ((ca - _ca)*a + 127)>> 8;\
00560             tptr[0] = (uchar)_cb;           \
00561             tptr[1] = (uchar)_cg;           \
00562             tptr[2] = (uchar)_cr;           \
00563             tptr[3] = (uchar)_ca;           \
00564         }
00565         if( ax > ay )
00566         {
00567             ptr += (pt1.x >> XY_SHIFT) * 4;
00568 
00569             while( ecount >= 0 )
00570             {
00571                 uchar *tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step;
00572 
00573                 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
00574                                        (((ecount >= 2) + 1) & (ecount | 2))];
00575                 int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31;
00576 
00577                 a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
00578                 ICV_PUT_POINT();
00579                 ICV_PUT_POINT();
00580 
00581                 tptr += step;
00582                 a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
00583                 ICV_PUT_POINT();
00584                 ICV_PUT_POINT();
00585 
00586                 tptr += step;
00587                 a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
00588                 ICV_PUT_POINT();
00589                 ICV_PUT_POINT();
00590 
00591                 pt1.y += y_step;
00592                 ptr += 4;
00593                 scount++;
00594                 ecount--;
00595             }
00596         }
00597         else
00598         {
00599             ptr += (pt1.y >> XY_SHIFT) * step;
00600 
00601             while( ecount >= 0 )
00602             {
00603                 uchar *tptr = ptr + ((pt1.x >> XY_SHIFT) - 1) * 4;
00604 
00605                 int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
00606                                        (((ecount >= 2) + 1) & (ecount | 2))];
00607                 int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31;
00608 
00609                 a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
00610                 ICV_PUT_POINT();
00611                 ICV_PUT_POINT();
00612 
00613                 tptr += 4;
00614                 a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
00615                 ICV_PUT_POINT();
00616                 ICV_PUT_POINT();
00617 
00618                 tptr += 4;
00619                 a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
00620                 ICV_PUT_POINT();
00621                 ICV_PUT_POINT();
00622 
00623                 pt1.x += x_step;
00624                 ptr += step;
00625                 scount++;
00626                 ecount--;
00627             }
00628         }
00629         #undef ICV_PUT_POINT
00630     }
00631 }
00632 
00633 
00634 static void
00635 Line2( Mat& img, Point pt1, Point pt2, const void* color )
00636 {
00637     int dx, dy;
00638     int ecount;
00639     int ax, ay;
00640     int i, j, x, y;
00641     int x_step, y_step;
00642     int cb = ((uchar*)color)[0];
00643     int cg = ((uchar*)color)[1];
00644     int cr = ((uchar*)color)[2];
00645     int pix_size = (int)img.elemSize();
00646     uchar *ptr = img.ptr(), *tptr;
00647     size_t step = img.step;
00648     Size size = img.size(), sizeScaled(size.width*XY_ONE, size.height*XY_ONE);
00649 
00650     //assert( img && (nch == 1 || nch == 3) && img.depth() == CV_8U );
00651 
00652     if( !clipLine( sizeScaled, pt1, pt2 ))
00653         return;
00654 
00655     dx = pt2.x - pt1.x;
00656     dy = pt2.y - pt1.y;
00657 
00658     j = dx < 0 ? -1 : 0;
00659     ax = (dx ^ j) - j;
00660     i = dy < 0 ? -1 : 0;
00661     ay = (dy ^ i) - i;
00662 
00663     if( ax > ay )
00664     {
00665         dx = ax;
00666         dy = (dy ^ j) - j;
00667         pt1.x ^= pt2.x & j;
00668         pt2.x ^= pt1.x & j;
00669         pt1.x ^= pt2.x & j;
00670         pt1.y ^= pt2.y & j;
00671         pt2.y ^= pt1.y & j;
00672         pt1.y ^= pt2.y & j;
00673 
00674         x_step = XY_ONE;
00675         y_step = (int) (((int64) dy << XY_SHIFT) / (ax | 1));
00676         ecount = (pt2.x - pt1.x) >> XY_SHIFT;
00677     }
00678     else
00679     {
00680         dy = ay;
00681         dx = (dx ^ i) - i;
00682         pt1.x ^= pt2.x & i;
00683         pt2.x ^= pt1.x & i;
00684         pt1.x ^= pt2.x & i;
00685         pt1.y ^= pt2.y & i;
00686         pt2.y ^= pt1.y & i;
00687         pt1.y ^= pt2.y & i;
00688 
00689         x_step = (int) (((int64) dx << XY_SHIFT) / (ay | 1));
00690         y_step = XY_ONE;
00691         ecount = (pt2.y - pt1.y) >> XY_SHIFT;
00692     }
00693 
00694     pt1.x += (XY_ONE >> 1);
00695     pt1.y += (XY_ONE >> 1);
00696 
00697     if( pix_size == 3 )
00698     {
00699         #define  ICV_PUT_POINT(_x,_y)   \
00700         x = (_x); y = (_y);             \
00701         if( 0 <= x && x < size.width && \
00702             0 <= y && y < size.height ) \
00703         {                               \
00704             tptr = ptr + y*step + x*3;  \
00705             tptr[0] = (uchar)cb;        \
00706             tptr[1] = (uchar)cg;        \
00707             tptr[2] = (uchar)cr;        \
00708         }
00709 
00710         ICV_PUT_POINT((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT,
00711                       (pt2.y + (XY_ONE >> 1)) >> XY_SHIFT);
00712 
00713         if( ax > ay )
00714         {
00715             pt1.x >>= XY_SHIFT;
00716 
00717             while( ecount >= 0 )
00718             {
00719                 ICV_PUT_POINT(pt1.x, pt1.y >> XY_SHIFT);
00720                 pt1.x++;
00721                 pt1.y += y_step;
00722                 ecount--;
00723             }
00724         }
00725         else
00726         {
00727             pt1.y >>= XY_SHIFT;
00728 
00729             while( ecount >= 0 )
00730             {
00731                 ICV_PUT_POINT(pt1.x >> XY_SHIFT, pt1.y);
00732                 pt1.x += x_step;
00733                 pt1.y++;
00734                 ecount--;
00735             }
00736         }
00737 
00738         #undef ICV_PUT_POINT
00739     }
00740     else if( pix_size == 1 )
00741     {
00742         #define  ICV_PUT_POINT(_x,_y) \
00743         x = (_x); y = (_y);           \
00744         if( 0 <= x && x < size.width && \
00745             0 <= y && y < size.height ) \
00746         {                           \
00747             tptr = ptr + y*step + x;\
00748             tptr[0] = (uchar)cb;    \
00749         }
00750 
00751         ICV_PUT_POINT((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT,
00752                       (pt2.y + (XY_ONE >> 1)) >> XY_SHIFT);
00753 
00754         if( ax > ay )
00755         {
00756             pt1.x >>= XY_SHIFT;
00757 
00758             while( ecount >= 0 )
00759             {
00760                 ICV_PUT_POINT(pt1.x, pt1.y >> XY_SHIFT);
00761                 pt1.x++;
00762                 pt1.y += y_step;
00763                 ecount--;
00764             }
00765         }
00766         else
00767         {
00768             pt1.y >>= XY_SHIFT;
00769 
00770             while( ecount >= 0 )
00771             {
00772                 ICV_PUT_POINT(pt1.x >> XY_SHIFT, pt1.y);
00773                 pt1.x += x_step;
00774                 pt1.y++;
00775                 ecount--;
00776             }
00777         }
00778 
00779         #undef ICV_PUT_POINT
00780     }
00781     else
00782     {
00783         #define  ICV_PUT_POINT(_x,_y)   \
00784         x = (_x); y = (_y);             \
00785         if( 0 <= x && x < size.width && \
00786             0 <= y && y < size.height ) \
00787         {                               \
00788             tptr = ptr + y*step + x*pix_size;\
00789             for( j = 0; j < pix_size; j++ ) \
00790                 tptr[j] = ((uchar*)color)[j]; \
00791         }
00792 
00793         ICV_PUT_POINT((pt2.x + (XY_ONE >> 1)) >> XY_SHIFT,
00794                       (pt2.y + (XY_ONE >> 1)) >> XY_SHIFT);
00795 
00796         if( ax > ay )
00797         {
00798             pt1.x >>= XY_SHIFT;
00799 
00800             while( ecount >= 0 )
00801             {
00802                 ICV_PUT_POINT(pt1.x, pt1.y >> XY_SHIFT);
00803                 pt1.x++;
00804                 pt1.y += y_step;
00805                 ecount--;
00806             }
00807         }
00808         else
00809         {
00810             pt1.y >>= XY_SHIFT;
00811 
00812             while( ecount >= 0 )
00813             {
00814                 ICV_PUT_POINT(pt1.x >> XY_SHIFT, pt1.y);
00815                 pt1.x += x_step;
00816                 pt1.y++;
00817                 ecount--;
00818             }
00819         }
00820 
00821         #undef ICV_PUT_POINT
00822     }
00823 }
00824 
00825 
00826 /****************************************************************************************\
00827 *                   Antialiazed Elliptic Arcs via Antialiazed Lines                      *
00828 \****************************************************************************************/
00829 
00830 static const float SinTable[] =
00831     { 0.0000000f, 0.0174524f, 0.0348995f, 0.0523360f, 0.0697565f, 0.0871557f,
00832     0.1045285f, 0.1218693f, 0.1391731f, 0.1564345f, 0.1736482f, 0.1908090f,
00833     0.2079117f, 0.2249511f, 0.2419219f, 0.2588190f, 0.2756374f, 0.2923717f,
00834     0.3090170f, 0.3255682f, 0.3420201f, 0.3583679f, 0.3746066f, 0.3907311f,
00835     0.4067366f, 0.4226183f, 0.4383711f, 0.4539905f, 0.4694716f, 0.4848096f,
00836     0.5000000f, 0.5150381f, 0.5299193f, 0.5446390f, 0.5591929f, 0.5735764f,
00837     0.5877853f, 0.6018150f, 0.6156615f, 0.6293204f, 0.6427876f, 0.6560590f,
00838     0.6691306f, 0.6819984f, 0.6946584f, 0.7071068f, 0.7193398f, 0.7313537f,
00839     0.7431448f, 0.7547096f, 0.7660444f, 0.7771460f, 0.7880108f, 0.7986355f,
00840     0.8090170f, 0.8191520f, 0.8290376f, 0.8386706f, 0.8480481f, 0.8571673f,
00841     0.8660254f, 0.8746197f, 0.8829476f, 0.8910065f, 0.8987940f, 0.9063078f,
00842     0.9135455f, 0.9205049f, 0.9271839f, 0.9335804f, 0.9396926f, 0.9455186f,
00843     0.9510565f, 0.9563048f, 0.9612617f, 0.9659258f, 0.9702957f, 0.9743701f,
00844     0.9781476f, 0.9816272f, 0.9848078f, 0.9876883f, 0.9902681f, 0.9925462f,
00845     0.9945219f, 0.9961947f, 0.9975641f, 0.9986295f, 0.9993908f, 0.9998477f,
00846     1.0000000f, 0.9998477f, 0.9993908f, 0.9986295f, 0.9975641f, 0.9961947f,
00847     0.9945219f, 0.9925462f, 0.9902681f, 0.9876883f, 0.9848078f, 0.9816272f,
00848     0.9781476f, 0.9743701f, 0.9702957f, 0.9659258f, 0.9612617f, 0.9563048f,
00849     0.9510565f, 0.9455186f, 0.9396926f, 0.9335804f, 0.9271839f, 0.9205049f,
00850     0.9135455f, 0.9063078f, 0.8987940f, 0.8910065f, 0.8829476f, 0.8746197f,
00851     0.8660254f, 0.8571673f, 0.8480481f, 0.8386706f, 0.8290376f, 0.8191520f,
00852     0.8090170f, 0.7986355f, 0.7880108f, 0.7771460f, 0.7660444f, 0.7547096f,
00853     0.7431448f, 0.7313537f, 0.7193398f, 0.7071068f, 0.6946584f, 0.6819984f,
00854     0.6691306f, 0.6560590f, 0.6427876f, 0.6293204f, 0.6156615f, 0.6018150f,
00855     0.5877853f, 0.5735764f, 0.5591929f, 0.5446390f, 0.5299193f, 0.5150381f,
00856     0.5000000f, 0.4848096f, 0.4694716f, 0.4539905f, 0.4383711f, 0.4226183f,
00857     0.4067366f, 0.3907311f, 0.3746066f, 0.3583679f, 0.3420201f, 0.3255682f,
00858     0.3090170f, 0.2923717f, 0.2756374f, 0.2588190f, 0.2419219f, 0.2249511f,
00859     0.2079117f, 0.1908090f, 0.1736482f, 0.1564345f, 0.1391731f, 0.1218693f,
00860     0.1045285f, 0.0871557f, 0.0697565f, 0.0523360f, 0.0348995f, 0.0174524f,
00861     0.0000000f, -0.0174524f, -0.0348995f, -0.0523360f, -0.0697565f, -0.0871557f,
00862     -0.1045285f, -0.1218693f, -0.1391731f, -0.1564345f, -0.1736482f, -0.1908090f,
00863     -0.2079117f, -0.2249511f, -0.2419219f, -0.2588190f, -0.2756374f, -0.2923717f,
00864     -0.3090170f, -0.3255682f, -0.3420201f, -0.3583679f, -0.3746066f, -0.3907311f,
00865     -0.4067366f, -0.4226183f, -0.4383711f, -0.4539905f, -0.4694716f, -0.4848096f,
00866     -0.5000000f, -0.5150381f, -0.5299193f, -0.5446390f, -0.5591929f, -0.5735764f,
00867     -0.5877853f, -0.6018150f, -0.6156615f, -0.6293204f, -0.6427876f, -0.6560590f,
00868     -0.6691306f, -0.6819984f, -0.6946584f, -0.7071068f, -0.7193398f, -0.7313537f,
00869     -0.7431448f, -0.7547096f, -0.7660444f, -0.7771460f, -0.7880108f, -0.7986355f,
00870     -0.8090170f, -0.8191520f, -0.8290376f, -0.8386706f, -0.8480481f, -0.8571673f,
00871     -0.8660254f, -0.8746197f, -0.8829476f, -0.8910065f, -0.8987940f, -0.9063078f,
00872     -0.9135455f, -0.9205049f, -0.9271839f, -0.9335804f, -0.9396926f, -0.9455186f,
00873     -0.9510565f, -0.9563048f, -0.9612617f, -0.9659258f, -0.9702957f, -0.9743701f,
00874     -0.9781476f, -0.9816272f, -0.9848078f, -0.9876883f, -0.9902681f, -0.9925462f,
00875     -0.9945219f, -0.9961947f, -0.9975641f, -0.9986295f, -0.9993908f, -0.9998477f,
00876     -1.0000000f, -0.9998477f, -0.9993908f, -0.9986295f, -0.9975641f, -0.9961947f,
00877     -0.9945219f, -0.9925462f, -0.9902681f, -0.9876883f, -0.9848078f, -0.9816272f,
00878     -0.9781476f, -0.9743701f, -0.9702957f, -0.9659258f, -0.9612617f, -0.9563048f,
00879     -0.9510565f, -0.9455186f, -0.9396926f, -0.9335804f, -0.9271839f, -0.9205049f,
00880     -0.9135455f, -0.9063078f, -0.8987940f, -0.8910065f, -0.8829476f, -0.8746197f,
00881     -0.8660254f, -0.8571673f, -0.8480481f, -0.8386706f, -0.8290376f, -0.8191520f,
00882     -0.8090170f, -0.7986355f, -0.7880108f, -0.7771460f, -0.7660444f, -0.7547096f,
00883     -0.7431448f, -0.7313537f, -0.7193398f, -0.7071068f, -0.6946584f, -0.6819984f,
00884     -0.6691306f, -0.6560590f, -0.6427876f, -0.6293204f, -0.6156615f, -0.6018150f,
00885     -0.5877853f, -0.5735764f, -0.5591929f, -0.5446390f, -0.5299193f, -0.5150381f,
00886     -0.5000000f, -0.4848096f, -0.4694716f, -0.4539905f, -0.4383711f, -0.4226183f,
00887     -0.4067366f, -0.3907311f, -0.3746066f, -0.3583679f, -0.3420201f, -0.3255682f,
00888     -0.3090170f, -0.2923717f, -0.2756374f, -0.2588190f, -0.2419219f, -0.2249511f,
00889     -0.2079117f, -0.1908090f, -0.1736482f, -0.1564345f, -0.1391731f, -0.1218693f,
00890     -0.1045285f, -0.0871557f, -0.0697565f, -0.0523360f, -0.0348995f, -0.0174524f,
00891     -0.0000000f, 0.0174524f, 0.0348995f, 0.0523360f, 0.0697565f, 0.0871557f,
00892     0.1045285f, 0.1218693f, 0.1391731f, 0.1564345f, 0.1736482f, 0.1908090f,
00893     0.2079117f, 0.2249511f, 0.2419219f, 0.2588190f, 0.2756374f, 0.2923717f,
00894     0.3090170f, 0.3255682f, 0.3420201f, 0.3583679f, 0.3746066f, 0.3907311f,
00895     0.4067366f, 0.4226183f, 0.4383711f, 0.4539905f, 0.4694716f, 0.4848096f,
00896     0.5000000f, 0.5150381f, 0.5299193f, 0.5446390f, 0.5591929f, 0.5735764f,
00897     0.5877853f, 0.6018150f, 0.6156615f, 0.6293204f, 0.6427876f, 0.6560590f,
00898     0.6691306f, 0.6819984f, 0.6946584f, 0.7071068f, 0.7193398f, 0.7313537f,
00899     0.7431448f, 0.7547096f, 0.7660444f, 0.7771460f, 0.7880108f, 0.7986355f,
00900     0.8090170f, 0.8191520f, 0.8290376f, 0.8386706f, 0.8480481f, 0.8571673f,
00901     0.8660254f, 0.8746197f, 0.8829476f, 0.8910065f, 0.8987940f, 0.9063078f,
00902     0.9135455f, 0.9205049f, 0.9271839f, 0.9335804f, 0.9396926f, 0.9455186f,
00903     0.9510565f, 0.9563048f, 0.9612617f, 0.9659258f, 0.9702957f, 0.9743701f,
00904     0.9781476f, 0.9816272f, 0.9848078f, 0.9876883f, 0.9902681f, 0.9925462f,
00905     0.9945219f, 0.9961947f, 0.9975641f, 0.9986295f, 0.9993908f, 0.9998477f,
00906     1.0000000f
00907 };
00908 
00909 
00910 static void
00911 sincos( int angle, float& cosval, float& sinval )
00912 {
00913     angle += (angle < 0 ? 360 : 0);
00914     sinval = SinTable[angle];
00915     cosval = SinTable[450 - angle];
00916 }
00917 
00918 /*
00919    constructs polygon that represents elliptic arc.
00920 */
00921 void ellipse2Poly( Point center, Size axes, int angle,
00922                    int arc_start, int arc_end,
00923                    int delta, std::vector<Point>& pts )
00924 {
00925     float alpha, beta;
00926     double size_a = axes.width, size_b = axes.height;
00927     double cx = center.x, cy = center.y;
00928     Point prevPt(INT_MIN,INT_MIN);
00929     int i;
00930 
00931     while( angle < 0 )
00932         angle += 360;
00933     while( angle > 360 )
00934         angle -= 360;
00935 
00936     if( arc_start > arc_end )
00937     {
00938         i = arc_start;
00939         arc_start = arc_end;
00940         arc_end = i;
00941     }
00942     while( arc_start < 0 )
00943     {
00944         arc_start += 360;
00945         arc_end += 360;
00946     }
00947     while( arc_end > 360 )
00948     {
00949         arc_end -= 360;
00950         arc_start -= 360;
00951     }
00952     if( arc_end - arc_start > 360 )
00953     {
00954         arc_start = 0;
00955         arc_end = 360;
00956     }
00957     sincos( angle, alpha, beta );
00958     pts.resize(0);
00959 
00960     for( i = arc_start; i < arc_end + delta; i += delta )
00961     {
00962         double x, y;
00963         angle = i;
00964         if( angle > arc_end )
00965             angle = arc_end;
00966         if( angle < 0 )
00967             angle += 360;
00968 
00969         x = size_a * SinTable[450-angle];
00970         y = size_b * SinTable[angle];
00971         Point pt;
00972         pt.x = cvRound( cx + x * alpha - y * beta );
00973         pt.y = cvRound( cy + x * beta + y * alpha );
00974         if( pt != prevPt ){
00975             pts.push_back(pt);
00976             prevPt = pt;
00977         }
00978     }
00979 
00980     // If there are no points, it's a zero-size polygon
00981     if( pts.size() == 1) {
00982         pts.assign(2,center);
00983     }
00984 }
00985 
00986 
00987 static void
00988 EllipseEx( Mat& img, Point center, Size axes,
00989            int angle, int arc_start, int arc_end,
00990            const void* color, int thickness, int line_type )
00991 {
00992     axes.width = std::abs(axes.width), axes.height = std::abs(axes.height);
00993     int delta = (std::max(axes.width,axes.height)+(XY_ONE>>1))>>XY_SHIFT;
00994     delta = delta < 3 ? 90 : delta < 10 ? 30 : delta < 15 ? 18 : 5;
00995 
00996     std::vector<Point> v;
00997     ellipse2Poly( center, axes, angle, arc_start, arc_end, delta, v );
00998 
00999     if( thickness >= 0 )
01000         PolyLine( img, &v[0], (int)v.size(), false, color, thickness, line_type, XY_SHIFT );
01001     else if( arc_end - arc_start >= 360 )
01002         FillConvexPoly( img, &v[0], (int)v.size(), color, line_type, XY_SHIFT );
01003     else
01004     {
01005         v.push_back(center);
01006         std::vector<PolyEdge> edges;
01007         CollectPolyEdges( img,  &v[0], (int)v.size(), edges, color, line_type, XY_SHIFT );
01008         FillEdgeCollection( img, edges, color );
01009     }
01010 }
01011 
01012 
01013 /****************************************************************************************\
01014 *                                Polygons filling                                        *
01015 \****************************************************************************************/
01016 
01017 /* helper macros: filling horizontal row */
01018 #define ICV_HLINE( ptr, xl, xr, color, pix_size )            \
01019 {                                                            \
01020     uchar* hline_ptr = (uchar*)(ptr) + (xl)*(pix_size);      \
01021     uchar* hline_max_ptr = (uchar*)(ptr) + (xr)*(pix_size);  \
01022                                                              \
01023     for( ; hline_ptr <= hline_max_ptr; hline_ptr += (pix_size))\
01024     {                                                        \
01025         int hline_j;                                         \
01026         for( hline_j = 0; hline_j < (pix_size); hline_j++ )  \
01027         {                                                    \
01028             hline_ptr[hline_j] = ((uchar*)color)[hline_j];   \
01029         }                                                    \
01030     }                                                        \
01031 }
01032 
01033 
01034 /* filling convex polygon. v - array of vertices, ntps - number of points */
01035 static void
01036 FillConvexPoly( Mat& img, const Point* v, int npts, const void* color, int line_type, int shift )
01037 {
01038     struct
01039     {
01040         int idx, di;
01041         int x, dx, ye;
01042     }
01043     edge[2];
01044 
01045     int delta = shift ? 1 << (shift - 1) : 0;
01046     int i, y, imin = 0, left = 0, right = 1, x1, x2;
01047     int edges = npts;
01048     int xmin, xmax, ymin, ymax;
01049     uchar* ptr = img.ptr();
01050     Size size = img.size();
01051     int pix_size = (int)img.elemSize();
01052     Point p0;
01053     int delta1, delta2;
01054 
01055     if( line_type < CV_AA )
01056         delta1 = delta2 = XY_ONE >> 1;
01057     else
01058         delta1 = XY_ONE - 1, delta2 = 0;
01059 
01060     p0 = v[npts - 1];
01061     p0.x <<= XY_SHIFT - shift;
01062     p0.y <<= XY_SHIFT - shift;
01063 
01064     assert( 0 <= shift && shift <= XY_SHIFT );
01065     xmin = xmax = v[0].x;
01066     ymin = ymax = v[0].y;
01067 
01068     for( i = 0; i < npts; i++ )
01069     {
01070         Point p = v[i];
01071         if( p.y < ymin )
01072         {
01073             ymin = p.y;
01074             imin = i;
01075         }
01076 
01077         ymax = std::max( ymax, p.y );
01078         xmax = std::max( xmax, p.x );
01079         xmin = MIN( xmin, p.x );
01080 
01081         p.x <<= XY_SHIFT - shift;
01082         p.y <<= XY_SHIFT - shift;
01083 
01084         if( line_type <= 8 )
01085         {
01086             if( shift == 0 )
01087             {
01088                 Point pt0, pt1;
01089                 pt0.x = p0.x >> XY_SHIFT;
01090                 pt0.y = p0.y >> XY_SHIFT;
01091                 pt1.x = p.x >> XY_SHIFT;
01092                 pt1.y = p.y >> XY_SHIFT;
01093                 Line( img, pt0, pt1, color, line_type );
01094             }
01095             else
01096                 Line2( img, p0, p, color );
01097         }
01098         else
01099             LineAA( img, p0, p, color );
01100         p0 = p;
01101     }
01102 
01103     xmin = (xmin + delta) >> shift;
01104     xmax = (xmax + delta) >> shift;
01105     ymin = (ymin + delta) >> shift;
01106     ymax = (ymax + delta) >> shift;
01107 
01108     if( npts < 3 || xmax < 0 || ymax < 0 || xmin >= size.width || ymin >= size.height )
01109         return;
01110 
01111     ymax = MIN( ymax, size.height - 1 );
01112     edge[0].idx = edge[1].idx = imin;
01113 
01114     edge[0].ye = edge[1].ye = y = ymin;
01115     edge[0].di = 1;
01116     edge[1].di = npts - 1;
01117 
01118     ptr += img.step*y;
01119 
01120     do
01121     {
01122         if( line_type < CV_AA || y < ymax || y == ymin )
01123         {
01124             for( i = 0; i < 2; i++ )
01125             {
01126                 if( y >= edge[i].ye )
01127                 {
01128                     int idx = edge[i].idx, di = edge[i].di;
01129                     int xs = 0, xe, ye, ty = 0;
01130 
01131                     for(;;)
01132                     {
01133                         ty = (v[idx].y + delta) >> shift;
01134                         if( ty > y || edges == 0 )
01135                             break;
01136                         xs = v[idx].x;
01137                         idx += di;
01138                         idx -= ((idx < npts) - 1) & npts;   /* idx -= idx >= npts ? npts : 0 */
01139                         edges--;
01140                     }
01141 
01142                     ye = ty;
01143                     xs <<= XY_SHIFT - shift;
01144                     xe = v[idx].x << (XY_SHIFT - shift);
01145 
01146                     /* no more edges */
01147                     if( y >= ye )
01148                         return;
01149 
01150                     edge[i].ye = ye;
01151                     edge[i].dx = ((xe - xs)*2 + (ye - y)) / (2 * (ye - y));
01152                     edge[i].x = xs;
01153                     edge[i].idx = idx;
01154                 }
01155             }
01156         }
01157 
01158         if( edge[left].x > edge[right].x )
01159         {
01160             left ^= 1;
01161             right ^= 1;
01162         }
01163 
01164         x1 = edge[left].x;
01165         x2 = edge[right].x;
01166 
01167         if( y >= 0 )
01168         {
01169             int xx1 = (x1 + delta1) >> XY_SHIFT;
01170             int xx2 = (x2 + delta2) >> XY_SHIFT;
01171 
01172             if( xx2 >= 0 && xx1 < size.width )
01173             {
01174                 if( xx1 < 0 )
01175                     xx1 = 0;
01176                 if( xx2 >= size.width )
01177                     xx2 = size.width - 1;
01178                 ICV_HLINE( ptr, xx1, xx2, color, pix_size );
01179             }
01180         }
01181 
01182         x1 += edge[left].dx;
01183         x2 += edge[right].dx;
01184 
01185         edge[left].x = x1;
01186         edge[right].x = x2;
01187         ptr += img.step;
01188     }
01189     while( ++y <= ymax );
01190 }
01191 
01192 
01193 /******** Arbitrary polygon **********/
01194 
01195 static void
01196 CollectPolyEdges( Mat& img, const Point* v, int count, std::vector<PolyEdge>& edges,
01197                   const void* color, int line_type, int shift, Point offset )
01198 {
01199     int i, delta = offset.y + (shift ? 1 << (shift - 1) : 0);
01200     Point pt0 = v[count-1], pt1;
01201     pt0.x = (pt0.x + offset.x) << (XY_SHIFT - shift);
01202     pt0.y = (pt0.y + delta) >> shift;
01203 
01204     edges.reserve( edges.size() + count );
01205 
01206     for( i = 0; i < count; i++, pt0 = pt1 )
01207     {
01208         Point t0, t1;
01209         PolyEdge edge;
01210 
01211         pt1 = v[i];
01212         pt1.x = (pt1.x + offset.x) << (XY_SHIFT - shift);
01213         pt1.y = (pt1.y + delta) >> shift;
01214 
01215         if( line_type < CV_AA )
01216         {
01217             t0.y = pt0.y; t1.y = pt1.y;
01218             t0.x = (pt0.x + (XY_ONE >> 1)) >> XY_SHIFT;
01219             t1.x = (pt1.x + (XY_ONE >> 1)) >> XY_SHIFT;
01220             Line( img, t0, t1, color, line_type );
01221         }
01222         else
01223         {
01224             t0.x = pt0.x; t1.x = pt1.x;
01225             t0.y = pt0.y << XY_SHIFT;
01226             t1.y = pt1.y << XY_SHIFT;
01227             LineAA( img, t0, t1, color );
01228         }
01229 
01230         if( pt0.y == pt1.y )
01231             continue;
01232 
01233         if( pt0.y < pt1.y )
01234         {
01235             edge.y0 = pt0.y;
01236             edge.y1 = pt1.y;
01237             edge.x = pt0.x;
01238         }
01239         else
01240         {
01241             edge.y0 = pt1.y;
01242             edge.y1 = pt0.y;
01243             edge.x = pt1.x;
01244         }
01245         edge.dx = (pt1.x - pt0.x) / (pt1.y - pt0.y);
01246         edges.push_back(edge);
01247     }
01248 }
01249 
01250 struct CmpEdges
01251 {
01252     bool operator ()(const PolyEdge& e1, const PolyEdge& e2)
01253     {
01254         return e1.y0 - e2.y0 ? e1.y0 < e2.y0 :
01255             e1.x - e2.x ? e1.x < e2.x : e1.dx < e2.dx;
01256     }
01257 };
01258 
01259 /**************** helper macros and functions for sequence/contour processing ***********/
01260 
01261 static void
01262 FillEdgeCollection( Mat& img, std::vector<PolyEdge>& edges, const void* color )
01263 {
01264     PolyEdge tmp;
01265     int i, y, total = (int)edges.size();
01266     Size size = img.size();
01267     PolyEdge* e;
01268     int y_max = INT_MIN, x_max = INT_MIN, y_min = INT_MAX, x_min = INT_MAX;
01269     int pix_size = (int)img.elemSize();
01270 
01271     if( total < 2 )
01272         return;
01273 
01274     for( i = 0; i < total; i++ )
01275     {
01276         PolyEdge& e1 = edges[i];
01277         assert( e1.y0 < e1.y1 );
01278         // Determine x-coordinate of the end of the edge.
01279         // (This is not necessary x-coordinate of any vertex in the array.)
01280         int x1 = e1.x + (e1.y1 - e1.y0) * e1.dx;
01281         y_min = std::min( y_min, e1.y0 );
01282         y_max = std::max( y_max, e1.y1 );
01283         x_min = std::min( x_min, e1.x );
01284         x_max = std::max( x_max, e1.x );
01285         x_min = std::min( x_min, x1 );
01286         x_max = std::max( x_max, x1 );
01287     }
01288 
01289     if( y_max < 0 || y_min >= size.height || x_max < 0 || x_min >= (size.width<<XY_SHIFT) )
01290         return;
01291 
01292     std::sort( edges.begin(), edges.end(), CmpEdges() );
01293 
01294     // start drawing
01295     tmp.y0 = INT_MAX;
01296     edges.push_back(tmp); // after this point we do not add
01297                           // any elements to edges, thus we can use pointers
01298     i = 0;
01299     tmp.next = 0;
01300     e = &edges[i];
01301     y_max = MIN( y_max, size.height );
01302 
01303     for( y = e->y0; y < y_max; y++ )
01304     {
01305         PolyEdge *last, *prelast, *keep_prelast;
01306         int sort_flag = 0;
01307         int draw = 0;
01308         int clipline = y < 0;
01309 
01310         prelast = &tmp;
01311         last = tmp.next;
01312         while( last || e->y0 == y )
01313         {
01314             if( last && last->y1 == y )
01315             {
01316                 // exclude edge if y reachs its lower point
01317                 prelast->next = last->next;
01318                 last = last->next;
01319                 continue;
01320             }
01321             keep_prelast = prelast;
01322             if( last && (e->y0 > y || last->x < e->x) )
01323             {
01324                 // go to the next edge in active list
01325                 prelast = last;
01326                 last = last->next;
01327             }
01328             else if( i < total )
01329             {
01330                 // insert new edge into active list if y reachs its upper point
01331                 prelast->next = e;
01332                 e->next = last;
01333                 prelast = e;
01334                 e = &edges[++i];
01335             }
01336             else
01337                 break;
01338 
01339             if( draw )
01340             {
01341                 if( !clipline )
01342                 {
01343                     // convert x's from fixed-point to image coordinates
01344                     uchar *timg = img.ptr(y);
01345                     int x1 = keep_prelast->x;
01346                     int x2 = prelast->x;
01347 
01348                     if( x1 > x2 )
01349                     {
01350                         int t = x1;
01351 
01352                         x1 = x2;
01353                         x2 = t;
01354                     }
01355 
01356                     x1 = (x1 + XY_ONE - 1) >> XY_SHIFT;
01357                     x2 = x2 >> XY_SHIFT;
01358 
01359                     // clip and draw the line
01360                     if( x1 < size.width && x2 >= 0 )
01361                     {
01362                         if( x1 < 0 )
01363                             x1 = 0;
01364                         if( x2 >= size.width )
01365                             x2 = size.width - 1;
01366                         ICV_HLINE( timg, x1, x2, color, pix_size );
01367                     }
01368                 }
01369                 keep_prelast->x += keep_prelast->dx;
01370                 prelast->x += prelast->dx;
01371             }
01372             draw ^= 1;
01373         }
01374 
01375         // sort edges (using bubble sort)
01376         keep_prelast = 0;
01377 
01378         do
01379         {
01380             prelast = &tmp;
01381             last = tmp.next;
01382 
01383             while( last != keep_prelast && last->next != 0 )
01384             {
01385                 PolyEdge *te = last->next;
01386 
01387                 // swap edges
01388                 if( last->x > te->x )
01389                 {
01390                     prelast->next = te;
01391                     last->next = te->next;
01392                     te->next = last;
01393                     prelast = te;
01394                     sort_flag = 1;
01395                 }
01396                 else
01397                 {
01398                     prelast = last;
01399                     last = te;
01400                 }
01401             }
01402             keep_prelast = prelast;
01403         }
01404         while( sort_flag && keep_prelast != tmp.next && keep_prelast != &tmp );
01405     }
01406 }
01407 
01408 
01409 /* draws simple or filled circle */
01410 static void
01411 Circle( Mat& img, Point center, int radius, const void* color, int fill )
01412 {
01413     Size size = img.size();
01414     size_t step = img.step;
01415     int pix_size = (int)img.elemSize();
01416     uchar* ptr = img.ptr();
01417     int err = 0, dx = radius, dy = 0, plus = 1, minus = (radius << 1) - 1;
01418     int inside = center.x >= radius && center.x < size.width - radius &&
01419         center.y >= radius && center.y < size.height - radius;
01420 
01421     #define ICV_PUT_POINT( ptr, x )     \
01422         memcpy( ptr + (x)*pix_size, color, pix_size );
01423 
01424     while( dx >= dy )
01425     {
01426         int mask;
01427         int y11 = center.y - dy, y12 = center.y + dy, y21 = center.y - dx, y22 = center.y + dx;
01428         int x11 = center.x - dx, x12 = center.x + dx, x21 = center.x - dy, x22 = center.x + dy;
01429 
01430         if( inside )
01431         {
01432             uchar *tptr0 = ptr + y11 * step;
01433             uchar *tptr1 = ptr + y12 * step;
01434 
01435             if( !fill )
01436             {
01437                 ICV_PUT_POINT( tptr0, x11 );
01438                 ICV_PUT_POINT( tptr1, x11 );
01439                 ICV_PUT_POINT( tptr0, x12 );
01440                 ICV_PUT_POINT( tptr1, x12 );
01441             }
01442             else
01443             {
01444                 ICV_HLINE( tptr0, x11, x12, color, pix_size );
01445                 ICV_HLINE( tptr1, x11, x12, color, pix_size );
01446             }
01447 
01448             tptr0 = ptr + y21 * step;
01449             tptr1 = ptr + y22 * step;
01450 
01451             if( !fill )
01452             {
01453                 ICV_PUT_POINT( tptr0, x21 );
01454                 ICV_PUT_POINT( tptr1, x21 );
01455                 ICV_PUT_POINT( tptr0, x22 );
01456                 ICV_PUT_POINT( tptr1, x22 );
01457             }
01458             else
01459             {
01460                 ICV_HLINE( tptr0, x21, x22, color, pix_size );
01461                 ICV_HLINE( tptr1, x21, x22, color, pix_size );
01462             }
01463         }
01464         else if( x11 < size.width && x12 >= 0 && y21 < size.height && y22 >= 0 )
01465         {
01466             if( fill )
01467             {
01468                 x11 = std::max( x11, 0 );
01469                 x12 = MIN( x12, size.width - 1 );
01470             }
01471 
01472             if( (unsigned)y11 < (unsigned)size.height )
01473             {
01474                 uchar *tptr = ptr + y11 * step;
01475 
01476                 if( !fill )
01477                 {
01478                     if( x11 >= 0 )
01479                         ICV_PUT_POINT( tptr, x11 );
01480                     if( x12 < size.width )
01481                         ICV_PUT_POINT( tptr, x12 );
01482                 }
01483                 else
01484                     ICV_HLINE( tptr, x11, x12, color, pix_size );
01485             }
01486 
01487             if( (unsigned)y12 < (unsigned)size.height )
01488             {
01489                 uchar *tptr = ptr + y12 * step;
01490 
01491                 if( !fill )
01492                 {
01493                     if( x11 >= 0 )
01494                         ICV_PUT_POINT( tptr, x11 );
01495                     if( x12 < size.width )
01496                         ICV_PUT_POINT( tptr, x12 );
01497                 }
01498                 else
01499                     ICV_HLINE( tptr, x11, x12, color, pix_size );
01500             }
01501 
01502             if( x21 < size.width && x22 >= 0 )
01503             {
01504                 if( fill )
01505                 {
01506                     x21 = std::max( x21, 0 );
01507                     x22 = MIN( x22, size.width - 1 );
01508                 }
01509 
01510                 if( (unsigned)y21 < (unsigned)size.height )
01511                 {
01512                     uchar *tptr = ptr + y21 * step;
01513 
01514                     if( !fill )
01515                     {
01516                         if( x21 >= 0 )
01517                             ICV_PUT_POINT( tptr, x21 );
01518                         if( x22 < size.width )
01519                             ICV_PUT_POINT( tptr, x22 );
01520                     }
01521                     else
01522                         ICV_HLINE( tptr, x21, x22, color, pix_size );
01523                 }
01524 
01525                 if( (unsigned)y22 < (unsigned)size.height )
01526                 {
01527                     uchar *tptr = ptr + y22 * step;
01528 
01529                     if( !fill )
01530                     {
01531                         if( x21 >= 0 )
01532                             ICV_PUT_POINT( tptr, x21 );
01533                         if( x22 < size.width )
01534                             ICV_PUT_POINT( tptr, x22 );
01535                     }
01536                     else
01537                         ICV_HLINE( tptr, x21, x22, color, pix_size );
01538                 }
01539             }
01540         }
01541         dy++;
01542         err += plus;
01543         plus += 2;
01544 
01545         mask = (err <= 0) - 1;
01546 
01547         err -= minus & mask;
01548         dx += mask;
01549         minus -= mask & 2;
01550     }
01551 
01552     #undef  ICV_PUT_POINT
01553 }
01554 
01555 
01556 static void
01557 ThickLine( Mat& img, Point p0, Point p1, const void* color,
01558            int thickness, int line_type, int flags, int shift )
01559 {
01560     static const double INV_XY_ONE = 1./XY_ONE;
01561 
01562     p0.x <<= XY_SHIFT - shift;
01563     p0.y <<= XY_SHIFT - shift;
01564     p1.x <<= XY_SHIFT - shift;
01565     p1.y <<= XY_SHIFT - shift;
01566 
01567     if( thickness <= 1 )
01568     {
01569         if( line_type < CV_AA )
01570         {
01571             if( line_type == 1 || line_type == 4 || shift == 0 )
01572             {
01573                 p0.x = (p0.x + (XY_ONE>>1)) >> XY_SHIFT;
01574                 p0.y = (p0.y + (XY_ONE>>1)) >> XY_SHIFT;
01575                 p1.x = (p1.x + (XY_ONE>>1)) >> XY_SHIFT;
01576                 p1.y = (p1.y + (XY_ONE>>1)) >> XY_SHIFT;
01577                 Line( img, p0, p1, color, line_type );
01578             }
01579             else
01580                 Line2( img, p0, p1, color );
01581         }
01582         else
01583             LineAA( img, p0, p1, color );
01584     }
01585     else
01586     {
01587         Point pt[4], dp = Point(0,0);
01588         double dx = (p0.x - p1.x)*INV_XY_ONE, dy = (p1.y - p0.y)*INV_XY_ONE;
01589         double r = dx * dx + dy * dy;
01590         int i, oddThickness = thickness & 1;
01591         thickness <<= XY_SHIFT - 1;
01592 
01593         if( fabs(r) > DBL_EPSILON )
01594         {
01595             r = (thickness + oddThickness*XY_ONE*0.5)/std::sqrt(r);
01596             dp.x = cvRound( dy * r );
01597             dp.y = cvRound( dx * r );
01598 
01599             pt[0].x = p0.x + dp.x;
01600             pt[0].y = p0.y + dp.y;
01601             pt[1].x = p0.x - dp.x;
01602             pt[1].y = p0.y - dp.y;
01603             pt[2].x = p1.x - dp.x;
01604             pt[2].y = p1.y - dp.y;
01605             pt[3].x = p1.x + dp.x;
01606             pt[3].y = p1.y + dp.y;
01607 
01608             FillConvexPoly( img, pt, 4, color, line_type, XY_SHIFT );
01609         }
01610 
01611         for( i = 0; i < 2; i++ )
01612         {
01613             if( flags & (i+1) )
01614             {
01615                 if( line_type < CV_AA )
01616                 {
01617                     Point center;
01618                     center.x = (p0.x + (XY_ONE>>1)) >> XY_SHIFT;
01619                     center.y = (p0.y + (XY_ONE>>1)) >> XY_SHIFT;
01620                     Circle( img, center, (thickness + (XY_ONE>>1)) >> XY_SHIFT, color, 1 );
01621                 }
01622                 else
01623                 {
01624                     EllipseEx( img, p0, cvSize(thickness, thickness),
01625                                0, 0, 360, color, -1, line_type );
01626                 }
01627             }
01628             p0 = p1;
01629         }
01630     }
01631 }
01632 
01633 
01634 static void
01635 PolyLine( Mat& img, const Point* v, int count, bool is_closed,
01636           const void* color, int thickness,
01637           int line_type, int shift )
01638 {
01639     if( !v || count <= 0 )
01640         return;
01641 
01642     int i = is_closed ? count - 1 : 0;
01643     int flags = 2 + !is_closed;
01644     Point p0;
01645     CV_Assert( 0 <= shift && shift <= XY_SHIFT && thickness >= 0 );
01646 
01647     p0 = v[i];
01648     for( i = !is_closed; i < count; i++ )
01649     {
01650         Point p = v[i];
01651         ThickLine( img, p0, p, color, thickness, line_type, flags, shift );
01652         p0 = p;
01653         flags = 2;
01654     }
01655 }
01656 
01657 /* ----------------------------------------------------------------------------------------- */
01658 /* ADDING A SET OF PREDEFINED MARKERS WHICH COULD BE USED TO HIGHLIGHT POSITIONS IN AN IMAGE */
01659 /* ----------------------------------------------------------------------------------------- */
01660 
01661 void drawMarker(Mat& img, Point position, const Scalar& color, int markerType, int markerSize, int thickness, int line_type)
01662 {
01663     switch(markerType)
01664     {
01665     // The cross marker case
01666     case MARKER_CROSS:
01667         line(img, Point(position.x-(markerSize/2), position.y), Point(position.x+(markerSize/2), position.y), color, thickness, line_type);
01668         line(img, Point(position.x, position.y-(markerSize/2)), Point(position.x, position.y+(markerSize/2)), color, thickness, line_type);
01669         break;
01670 
01671     // The tilted cross marker case
01672     case MARKER_TILTED_CROSS:
01673         line(img, Point(position.x-(markerSize/2), position.y-(markerSize/2)), Point(position.x+(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
01674         line(img, Point(position.x+(markerSize/2), position.y-(markerSize/2)), Point(position.x-(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
01675         break;
01676 
01677     // The star marker case
01678     case MARKER_STAR:
01679         line(img, Point(position.x-(markerSize/2), position.y), Point(position.x+(markerSize/2), position.y), color, thickness, line_type);
01680         line(img, Point(position.x, position.y-(markerSize/2)), Point(position.x, position.y+(markerSize/2)), color, thickness, line_type);
01681         line(img, Point(position.x-(markerSize/2), position.y-(markerSize/2)), Point(position.x+(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
01682         line(img, Point(position.x+(markerSize/2), position.y-(markerSize/2)), Point(position.x-(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
01683         break;
01684 
01685     // The diamond marker case
01686     case MARKER_DIAMOND:
01687         line(img, Point(position.x, position.y-(markerSize/2)), Point(position.x+(markerSize/2), position.y), color, thickness, line_type);
01688         line(img, Point(position.x+(markerSize/2), position.y), Point(position.x, position.y+(markerSize/2)), color, thickness, line_type);
01689         line(img, Point(position.x, position.y+(markerSize/2)), Point(position.x-(markerSize/2), position.y), color, thickness, line_type);
01690         line(img, Point(position.x-(markerSize/2), position.y), Point(position.x, position.y-(markerSize/2)), color, thickness, line_type);
01691         break;
01692 
01693     // The square marker case
01694     case MARKER_SQUARE:
01695         line(img, Point(position.x-(markerSize/2), position.y-(markerSize/2)), Point(position.x+(markerSize/2), position.y-(markerSize/2)), color, thickness, line_type);
01696         line(img, Point(position.x+(markerSize/2), position.y-(markerSize/2)), Point(position.x+(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
01697         line(img, Point(position.x+(markerSize/2), position.y+(markerSize/2)), Point(position.x-(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
01698         line(img, Point(position.x-(markerSize/2), position.y+(markerSize/2)), Point(position.x-(markerSize/2), position.y-(markerSize/2)), color, thickness, line_type);
01699         break;
01700 
01701     // The triangle up marker case
01702     case MARKER_TRIANGLE_UP:
01703         line(img, Point(position.x-(markerSize/2), position.y+(markerSize/2)), Point(position.x+(markerSize/2), position.y+(markerSize/2)), color, thickness, line_type);
01704         line(img, Point(position.x+(markerSize/2), position.y+(markerSize/2)), Point(position.x, position.y-(markerSize/2)), color, thickness, line_type);
01705         line(img, Point(position.x, position.y-(markerSize/2)), Point(position.x-(markerSize/2), position.y-(markerSize/2)), color, thickness, line_type);
01706         break;
01707 
01708     // The triangle down marker case
01709     case MARKER_TRIANGLE_DOWN:
01710         line(img, Point(position.x-(markerSize/2), position.y-(markerSize/2)), Point(position.x+(markerSize/2), position.y-(markerSize/2)), color, thickness, line_type);
01711         line(img, Point(position.x+(markerSize/2), position.y-(markerSize/2)), Point(position.x, position.y+(markerSize/2)), color, thickness, line_type);
01712         line(img, Point(position.x, position.y+(markerSize/2)), Point(position.x-(markerSize/2), position.y-(markerSize/2)), color, thickness, line_type);
01713         break;
01714 
01715     // If any number that doesn't exist is entered as marker type, draw a cross marker, to avoid crashes
01716     default:
01717         drawMarker(img, position, color, MARKER_CROSS, markerSize, thickness, line_type);
01718         break;
01719     }
01720 }
01721 
01722 /****************************************************************************************\
01723 *                              External functions                                        *
01724 \****************************************************************************************/
01725 
01726 void line( InputOutputArray _img, Point pt1, Point pt2, const Scalar & color,
01727            int thickness, int line_type, int shift )
01728 {
01729     Mat img = _img.getMat();
01730 
01731     if( line_type == CV_AA && img.depth() != CV_8U )
01732         line_type = 8;
01733 
01734     CV_Assert( 0 <= thickness && thickness <= MAX_THICKNESS );
01735     CV_Assert( 0 <= shift && shift <= XY_SHIFT );
01736 
01737     double buf[4];
01738     scalarToRawData( color, buf, img.type(), 0 );
01739     ThickLine( img, pt1, pt2, buf, thickness, line_type, 3, shift );
01740 }
01741 
01742 void arrowedLine(InputOutputArray img, Point pt1, Point pt2, const Scalar & color,
01743            int thickness, int line_type, int shift, double tipLength)
01744 {
01745     const double tipSize = norm(pt1-pt2)*tipLength; // Factor to normalize the size of the tip depending on the length of the arrow
01746 
01747     line(img, pt1, pt2, color, thickness, line_type, shift);
01748 
01749     const double angle = atan2( (double) pt1.y - pt2.y, (double) pt1.x - pt2.x );
01750 
01751     Point p(cvRound(pt2.x + tipSize * cos(angle + CV_PI / 4)),
01752         cvRound(pt2.y + tipSize * sin(angle + CV_PI / 4)));
01753     line(img, p, pt2, color, thickness, line_type, shift);
01754 
01755     p.x = cvRound(pt2.x + tipSize * cos(angle - CV_PI / 4));
01756     p.y = cvRound(pt2.y + tipSize * sin(angle - CV_PI / 4));
01757     line(img, p, pt2, color, thickness, line_type, shift);
01758 }
01759 
01760 void rectangle( InputOutputArray _img, Point pt1, Point pt2,
01761                 const Scalar & color, int thickness,
01762                 int lineType, int shift )
01763 {
01764     Mat img = _img.getMat();
01765 
01766     if( lineType == CV_AA && img.depth() != CV_8U )
01767         lineType = 8;
01768 
01769     CV_Assert( thickness <= MAX_THICKNESS );
01770     CV_Assert( 0 <= shift && shift <= XY_SHIFT );
01771 
01772     double buf[4];
01773     scalarToRawData(color, buf, img.type(), 0);
01774 
01775     Point pt[4];
01776 
01777     pt[0] = pt1;
01778     pt[1].x = pt2.x;
01779     pt[1].y = pt1.y;
01780     pt[2] = pt2;
01781     pt[3].x = pt1.x;
01782     pt[3].y = pt2.y;
01783 
01784     if( thickness >= 0 )
01785         PolyLine( img, pt, 4, true, buf, thickness, lineType, shift );
01786     else
01787         FillConvexPoly( img, pt, 4, buf, lineType, shift );
01788 }
01789 
01790 
01791 void rectangle( Mat& img, Rect rec,
01792                 const Scalar& color, int thickness,
01793                 int lineType, int shift )
01794 {
01795     CV_Assert( 0 <= shift && shift <= XY_SHIFT );
01796     if( rec.area() > 0 )
01797         rectangle( img, rec.tl(), rec.br() - Point(1<<shift,1<<shift),
01798                    color, thickness, lineType, shift );
01799 }
01800 
01801 
01802 void circle( InputOutputArray _img, Point center, int radius,
01803              const Scalar & color, int thickness, int line_type, int shift )
01804 {
01805     Mat img = _img.getMat();
01806 
01807     if( line_type == CV_AA && img.depth() != CV_8U )
01808         line_type = 8;
01809 
01810     CV_Assert( radius >= 0 && thickness <= MAX_THICKNESS &&
01811         0 <= shift && shift <= XY_SHIFT );
01812 
01813     double buf[4];
01814     scalarToRawData(color, buf, img.type(), 0);
01815 
01816     if( thickness > 1 || line_type >= CV_AA || shift > 0 )
01817     {
01818         center.x <<= XY_SHIFT - shift;
01819         center.y <<= XY_SHIFT - shift;
01820         radius <<= XY_SHIFT - shift;
01821         EllipseEx( img, center, Size(radius, radius),
01822                    0, 0, 360, buf, thickness, line_type );
01823     }
01824     else
01825         Circle( img, center, radius, buf, thickness < 0 );
01826 }
01827 
01828 
01829 void ellipse( InputOutputArray _img, Point center, Size axes,
01830               double angle, double start_angle, double end_angle,
01831               const Scalar & color, int thickness, int line_type, int shift )
01832 {
01833     Mat img = _img.getMat();
01834 
01835     if( line_type == CV_AA && img.depth() != CV_8U )
01836         line_type = 8;
01837 
01838     CV_Assert( axes.width >= 0 && axes.height >= 0 &&
01839         thickness <= MAX_THICKNESS && 0 <= shift && shift <= XY_SHIFT );
01840 
01841     double buf[4];
01842     scalarToRawData(color, buf, img.type(), 0);
01843 
01844     int _angle = cvRound(angle);
01845     int _start_angle = cvRound(start_angle);
01846     int _end_angle = cvRound(end_angle);
01847     center.x <<= XY_SHIFT - shift;
01848     center.y <<= XY_SHIFT - shift;
01849     axes.width <<= XY_SHIFT - shift;
01850     axes.height <<= XY_SHIFT - shift;
01851 
01852     EllipseEx( img, center, axes, _angle, _start_angle,
01853                _end_angle, buf, thickness, line_type );
01854 }
01855 
01856 void ellipse(InputOutputArray _img, const RotatedRect& box, const Scalar & color,
01857              int thickness, int lineType)
01858 {
01859     Mat img = _img.getMat();
01860 
01861     if( lineType == CV_AA && img.depth() != CV_8U )
01862         lineType = 8;
01863 
01864     CV_Assert( box.size.width >= 0 && box.size.height >= 0 &&
01865                thickness <= MAX_THICKNESS );
01866 
01867     double buf[4];
01868     scalarToRawData(color, buf, img.type(), 0);
01869 
01870     int _angle = cvRound(box.angle);
01871     Point center(cvRound(box.center.x*(1 << XY_SHIFT)),
01872                  cvRound(box.center.y*(1 << XY_SHIFT)));
01873     Size axes(cvRound(box.size.width*(1 << (XY_SHIFT - 1))),
01874               cvRound(box.size.height*(1 << (XY_SHIFT - 1))));
01875     EllipseEx( img, center, axes, _angle, 0, 360, buf, thickness, lineType );
01876 }
01877 
01878 void fillConvexPoly ( Mat& img, const Point* pts, int npts,
01879                      const Scalar & color, int line_type, int shift )
01880 {
01881     if( !pts || npts <= 0 )
01882         return;
01883 
01884     if( line_type == CV_AA && img.depth() != CV_8U )
01885         line_type = 8;
01886 
01887     double buf[4];
01888     CV_Assert( 0 <= shift && shift <=  XY_SHIFT );
01889     scalarToRawData(color, buf, img.type(), 0);
01890     FillConvexPoly( img, pts, npts, buf, line_type, shift );
01891 }
01892 
01893 
01894 void fillPoly ( Mat& img, const Point** pts, const int* npts, int ncontours,
01895                const Scalar & color, int line_type,
01896                int shift, Point offset )
01897 {
01898     if( line_type == CV_AA && img.depth() != CV_8U )
01899         line_type = 8;
01900 
01901     CV_Assert( pts && npts && ncontours >= 0 && 0 <= shift && shift <= XY_SHIFT );
01902 
01903     double buf[4];
01904     scalarToRawData(color, buf, img.type(), 0);
01905 
01906     std::vector<PolyEdge> edges;
01907 
01908     int i, total = 0;
01909     for( i = 0; i < ncontours; i++ )
01910         total += npts[i];
01911 
01912     edges.reserve( total + 1 );
01913     for( i = 0; i < ncontours; i++ )
01914         CollectPolyEdges( img, pts[i], npts[i], edges, buf, line_type, shift, offset );
01915 
01916     FillEdgeCollection(img, edges, buf);
01917 }
01918 
01919 
01920 void polylines ( Mat& img, const Point* const* pts, const int* npts, int ncontours, bool isClosed,
01921                 const Scalar & color, int thickness, int line_type, int shift )
01922 {
01923     if( line_type == CV_AA && img.depth() != CV_8U )
01924         line_type = 8;
01925 
01926     CV_Assert( pts && npts && ncontours >= 0 &&
01927                0 <= thickness && thickness <= MAX_THICKNESS &&
01928                0 <= shift && shift <= XY_SHIFT );
01929 
01930     double buf[4];
01931     scalarToRawData( color, buf, img.type(), 0 );
01932 
01933     for( int i = 0; i < ncontours; i++ )
01934         PolyLine( img, pts[i], npts[i], isClosed, buf, thickness, line_type, shift );
01935 }
01936 
01937 
01938 enum { FONT_SIZE_SHIFT=8, FONT_ITALIC_ALPHA=(1 << 8),
01939        FONT_ITALIC_DIGIT=(2 << 8), FONT_ITALIC_PUNCT=(4 << 8),
01940        FONT_ITALIC_BRACES=(8 << 8), FONT_HAVE_GREEK=(16 << 8),
01941        FONT_HAVE_CYRILLIC=(32 << 8) };
01942 
01943 static const int HersheyPlain[] = {
01944 (5 + 4*16) + FONT_HAVE_GREEK,
01945 199, 214, 217, 233, 219, 197, 234, 216, 221, 222, 228, 225, 211, 224, 210, 220,
01946 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 212, 213, 191, 226, 192,
01947 215, 190, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
01948 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 193, 84,
01949 194, 85, 86, 87, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
01950 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
01951 195, 223, 196, 88 };
01952 
01953 static const int HersheyPlainItalic[] = {
01954 (5 + 4*16) + FONT_ITALIC_ALPHA + FONT_HAVE_GREEK,
01955 199, 214, 217, 233, 219, 197, 234, 216, 221, 222, 228, 225, 211, 224, 210, 220,
01956 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 212, 213, 191, 226, 192,
01957 215, 190, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
01958 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 193, 84,
01959 194, 85, 86, 87, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
01960 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
01961 195, 223, 196, 88 };
01962 
01963 static const int HersheyComplexSmall[] = {
01964 (6 + 7*16) + FONT_HAVE_GREEK,
01965 1199, 1214, 1217, 1275, 1274, 1271, 1272, 1216, 1221, 1222, 1219, 1232, 1211, 1231, 1210, 1220,
01966 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1212, 2213, 1241, 1238, 1242,
01967 1215, 1273, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013,
01968 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1223, 1084,
01969 1224, 1247, 586, 1249, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111,
01970 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126,
01971 1225, 1229, 1226, 1246 };
01972 
01973 static const int HersheyComplexSmallItalic[] = {
01974 (6 + 7*16) + FONT_ITALIC_ALPHA + FONT_HAVE_GREEK,
01975 1199, 1214, 1217, 1275, 1274, 1271, 1272, 1216, 1221, 1222, 1219, 1232, 1211, 1231, 1210, 1220,
01976 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1212, 1213, 1241, 1238, 1242,
01977 1215, 1273, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063,
01978 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1223, 1084,
01979 1224, 1247, 586, 1249, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161,
01980 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176,
01981 1225, 1229, 1226, 1246 };
01982 
01983 static const int HersheySimplex[] = {
01984 (9 + 12*16) + FONT_HAVE_GREEK,
01985 2199, 714, 717, 733, 719, 697, 734, 716, 721, 722, 728, 725, 711, 724, 710, 720,
01986 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 712, 713, 691, 726, 692,
01987 715, 690, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513,
01988 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 693, 584,
01989 694, 2247, 586, 2249, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611,
01990 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626,
01991 695, 723, 696, 2246 };
01992 
01993 static const int HersheyDuplex[] = {
01994 (9 + 12*16) + FONT_HAVE_GREEK,
01995 2199, 2714, 2728, 2732, 2719, 2733, 2718, 2727, 2721, 2722, 2723, 2725, 2711, 2724, 2710, 2720,
01996 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2712, 2713, 2730, 2726, 2731,
01997 2715, 2734, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513,
01998 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, 2223, 2084,
01999 2224, 2247, 587, 2249, 2601, 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611,
02000 2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626,
02001 2225, 2229, 2226, 2246 };
02002 
02003 static const int HersheyComplex[] = {
02004 (9 + 12*16) + FONT_HAVE_GREEK + FONT_HAVE_CYRILLIC,
02005 2199, 2214, 2217, 2275, 2274, 2271, 2272, 2216, 2221, 2222, 2219, 2232, 2211, 2231, 2210, 2220,
02006 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2212, 2213, 2241, 2238, 2242,
02007 2215, 2273, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013,
02008 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2223, 2084,
02009 2224, 2247, 587, 2249, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111,
02010 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126,
02011 2225, 2229, 2226, 2246, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, 2811,
02012 2812, 2813, 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826,
02013 2827, 2828, 2829, 2830, 2831, 2832, 2901, 2902, 2903, 2904, 2905, 2906, 2907, 2908, 2909,
02014 2910, 2911, 2912, 2913, 2914, 2915, 2916, 2917, 2918, 2919, 2920, 2921, 2922, 2923, 2924,
02015 2925, 2926, 2927, 2928, 2929, 2930, 2931, 2932};
02016 
02017 static const int HersheyComplexItalic[] = {
02018 (9 + 12*16) + FONT_ITALIC_ALPHA + FONT_ITALIC_DIGIT + FONT_ITALIC_PUNCT +
02019 FONT_HAVE_GREEK + FONT_HAVE_CYRILLIC,
02020 2199, 2764, 2778, 2782, 2769, 2783, 2768, 2777, 2771, 2772, 2219, 2232, 2211, 2231, 2210, 2220,
02021 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2212, 2213, 2241, 2238, 2242,
02022 2765, 2273, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063,
02023 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2223, 2084,
02024 2224, 2247, 587, 2249, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161,
02025 2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176,
02026 2225, 2229, 2226, 2246 };
02027 
02028 static const int HersheyTriplex[] = {
02029 (9 + 12*16) + FONT_HAVE_GREEK,
02030 2199, 3214, 3228, 3232, 3219, 3233, 3218, 3227, 3221, 3222, 3223, 3225, 3211, 3224, 3210, 3220,
02031 3200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209, 3212, 3213, 3230, 3226, 3231,
02032 3215, 3234, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013,
02033 2014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3025, 3026, 2223, 2084,
02034 2224, 2247, 587, 2249, 3101, 3102, 3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, 3111,
02035 3112, 3113, 3114, 3115, 3116, 3117, 3118, 3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126,
02036 2225, 2229, 2226, 2246 };
02037 
02038 static const int HersheyTriplexItalic[] = {
02039 (9 + 12*16) + FONT_ITALIC_ALPHA + FONT_ITALIC_DIGIT +
02040 FONT_ITALIC_PUNCT + FONT_HAVE_GREEK,
02041 2199, 3264, 3278, 3282, 3269, 3233, 3268, 3277, 3271, 3272, 3223, 3225, 3261, 3224, 3260, 3270,
02042 3250, 3251, 3252, 3253, 3254, 3255, 3256, 3257, 3258, 3259, 3262, 3263, 3230, 3226, 3231,
02043 3265, 3234, 3051, 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, 3063,
02044 2064, 3065, 3066, 3067, 3068, 3069, 3070, 3071, 3072, 3073, 3074, 3075, 3076, 2223, 2084,
02045 2224, 2247, 587, 2249, 3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161,
02046 3162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, 3176,
02047 2225, 2229, 2226, 2246 };
02048 
02049 static const int HersheyScriptSimplex[] = {
02050 (9 + 12*16) + FONT_ITALIC_ALPHA + FONT_HAVE_GREEK,
02051 2199, 714, 717, 733, 719, 697, 734, 716, 721, 722, 728, 725, 711, 724, 710, 720,
02052 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 712, 713, 691, 726, 692,
02053 715, 690, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563,
02054 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 693, 584,
02055 694, 2247, 586, 2249, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661,
02056 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676,
02057 695, 723, 696, 2246 };
02058 
02059 static const int HersheyScriptComplex[] = {
02060 (9 + 12*16) + FONT_ITALIC_ALPHA + FONT_ITALIC_DIGIT + FONT_ITALIC_PUNCT + FONT_HAVE_GREEK,
02061 2199, 2764, 2778, 2782, 2769, 2783, 2768, 2777, 2771, 2772, 2219, 2232, 2211, 2231, 2210, 2220,
02062 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2212, 2213, 2241, 2238, 2242,
02063 2215, 2273, 2551, 2552, 2553, 2554, 2555, 2556, 2557, 2558, 2559, 2560, 2561, 2562, 2563,
02064 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, 2575, 2576, 2223, 2084,
02065 2224, 2247, 586, 2249, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661,
02066 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676,
02067 2225, 2229, 2226, 2246 };
02068 
02069 
02070 static const int* getFontData(int fontFace)
02071 {
02072     bool isItalic = (fontFace & FONT_ITALIC) != 0;
02073     const int* ascii = 0;
02074 
02075     switch( fontFace & 15 )
02076     {
02077     case FONT_HERSHEY_SIMPLEX:
02078         ascii = HersheySimplex;
02079         break;
02080     case FONT_HERSHEY_PLAIN:
02081         ascii = !isItalic ? HersheyPlain : HersheyPlainItalic;
02082         break;
02083     case FONT_HERSHEY_DUPLEX:
02084         ascii = HersheyDuplex;
02085         break;
02086     case FONT_HERSHEY_COMPLEX:
02087         ascii = !isItalic ? HersheyComplex : HersheyComplexItalic;
02088         break;
02089     case FONT_HERSHEY_TRIPLEX:
02090         ascii = !isItalic ? HersheyTriplex : HersheyTriplexItalic;
02091         break;
02092     case FONT_HERSHEY_COMPLEX_SMALL:
02093         ascii = !isItalic ? HersheyComplexSmall : HersheyComplexSmallItalic;
02094         break;
02095     case FONT_HERSHEY_SCRIPT_SIMPLEX:
02096         ascii = HersheyScriptSimplex;
02097         break;
02098     case FONT_HERSHEY_SCRIPT_COMPLEX:
02099         ascii = HersheyScriptComplex;
02100         break;
02101     default:
02102         CV_Error( CV_StsOutOfRange, "Unknown font type" );
02103     }
02104     return ascii;
02105 }
02106 
02107 inline void readCheck(int &c, int &i, const String &text, int fontFace)
02108 {
02109 
02110     int leftBoundary = ' ', rightBoundary = 127;
02111 
02112     if(c >= 0x80 && fontFace == FONT_HERSHEY_COMPLEX)
02113     {
02114         if(c == 0xD0 && (uchar)text[i + 1] >= 0x90 && (uchar)text[i + 1] <= 0xBF)
02115         {
02116             c = (uchar)text[++i] - 17;
02117             leftBoundary = 127;
02118             rightBoundary = 175;
02119         }
02120         else if(c == 0xD1 && (uchar)text[i + 1] >= 0x80 && (uchar)text[i + 1] <= 0x8F)
02121         {
02122             c = (uchar)text[++i] + 47;
02123             leftBoundary = 175;
02124             rightBoundary = 191;
02125         }
02126         else
02127         {
02128             if(c >= 0xC0 && text[i+1] != 0) //2 bytes utf
02129                 i++;
02130 
02131             if(c >= 0xE0 && text[i+1] != 0) //3 bytes utf
02132                 i++;
02133 
02134             if(c >= 0xF0 && text[i+1] != 0) //4 bytes utf
02135                 i++;
02136 
02137             if(c >= 0xF8 && text[i+1] != 0) //5 bytes utf
02138                 i++;
02139 
02140             if(c >= 0xFC && text[i+1] != 0) //6 bytes utf
02141                 i++;
02142 
02143             c = '?';
02144         }
02145     }
02146 
02147     if(c >= rightBoundary || c < leftBoundary)
02148         c = '?';
02149 }
02150 
02151 extern const char* g_HersheyGlyphs[];
02152 
02153 void putText( InputOutputArray _img, const String& text, Point org,
02154               int fontFace, double fontScale, Scalar  color,
02155               int thickness, int line_type, bool bottomLeftOrigin )
02156 
02157 {
02158     if ( text.empty() )
02159     {
02160         return;
02161     }
02162     Mat img = _img.getMat();
02163     const int* ascii = getFontData(fontFace);
02164 
02165     double buf[4];
02166     scalarToRawData(color, buf, img.type(), 0);
02167 
02168     int base_line = -(ascii[0] & 15);
02169     int hscale = cvRound(fontScale*XY_ONE), vscale = hscale;
02170 
02171     if( line_type == CV_AA && img.depth() != CV_8U )
02172         line_type = 8;
02173 
02174     if( bottomLeftOrigin )
02175         vscale = -vscale;
02176 
02177     int view_x = org.x << XY_SHIFT;
02178     int view_y = (org.y << XY_SHIFT) + base_line*vscale;
02179     std::vector<Point> pts;
02180     pts.reserve(1 << 10);
02181     const char **faces = cv::g_HersheyGlyphs;
02182 
02183     for( int i = 0; i < (int)text.size(); i++ )
02184     {
02185         int c = (uchar)text[i];
02186         Point p;
02187 
02188         readCheck(c, i, text, fontFace);
02189 
02190         const char* ptr = faces[ascii[(c-' ')+1]];
02191         p.x = (uchar)ptr[0] - 'R';
02192         p.y = (uchar)ptr[1] - 'R';
02193         int dx = p.y*hscale;
02194         view_x -= p.x*hscale;
02195         pts.resize(0);
02196 
02197         for( ptr += 2;; )
02198         {
02199             if( *ptr == ' ' || !*ptr )
02200             {
02201                 if( pts.size() > 1 )
02202                     PolyLine( img, &pts[0], (int)pts.size(), false, buf, thickness, line_type, XY_SHIFT );
02203                 if( !*ptr++ )
02204                     break;
02205                 pts.resize(0);
02206             }
02207             else
02208             {
02209                 p.x = (uchar)ptr[0] - 'R';
02210                 p.y = (uchar)ptr[1] - 'R';
02211                 ptr += 2;
02212                 pts.push_back(Point(p.x*hscale + view_x, p.y*vscale + view_y));
02213             }
02214         }
02215         view_x += dx;
02216     }
02217 }
02218 
02219 Size getTextSize( const String& text, int fontFace, double fontScale, int thickness, int* _base_line)
02220 {
02221     Size size;
02222     double view_x = 0;
02223     const char **faces = cv::g_HersheyGlyphs;
02224     const int* ascii = getFontData(fontFace);
02225 
02226     int base_line = (ascii[0] & 15);
02227     int cap_line = (ascii[0] >> 4) & 15;
02228     size.height = cvRound((cap_line + base_line)*fontScale + (thickness+1)/2);
02229 
02230     for( int i = 0; i < (int)text.size(); i++ )
02231     {
02232         int c = (uchar)text[i];
02233         Point p;
02234 
02235         readCheck(c, i, text, fontFace);
02236 
02237         const char* ptr = faces[ascii[(c-' ')+1]];
02238         p.x = (uchar)ptr[0] - 'R';
02239         p.y = (uchar)ptr[1] - 'R';
02240         view_x += (p.y - p.x)*fontScale;
02241     }
02242 
02243     size.width = cvRound(view_x + thickness);
02244     if( _base_line )
02245         *_base_line = cvRound(base_line*fontScale + thickness*0.5);
02246     return size;
02247 }
02248 
02249 }
02250 
02251 
02252 void cv::fillConvexPoly (InputOutputArray _img, InputArray _points,
02253                         const Scalar & color, int lineType, int shift)
02254 {
02255     Mat img = _img.getMat(), points = _points.getMat();
02256     CV_Assert(points.checkVector(2, CV_32S) >= 0);
02257     fillConvexPoly (img, points.ptr<Point>(), points.rows*points.cols*points.channels()/2, color, lineType, shift);
02258 }
02259 
02260 
02261 void cv::fillPoly (InputOutputArray _img, InputArrayOfArrays pts,
02262                   const Scalar & color, int lineType, int shift, Point offset)
02263 {
02264     Mat img = _img.getMat();
02265     int i, ncontours = (int)pts.total();
02266     if( ncontours == 0 )
02267         return;
02268     AutoBuffer<Point*> _ptsptr(ncontours);
02269     AutoBuffer<int>  _npts(ncontours);
02270     Point** ptsptr = _ptsptr;
02271     int* npts = _npts;
02272 
02273     for( i = 0; i < ncontours; i++ )
02274     {
02275         Mat p = pts.getMat(i);
02276         CV_Assert(p.checkVector(2, CV_32S) >= 0);
02277         ptsptr[i] = p.ptr<Point>();
02278         npts[i] = p.rows*p.cols*p.channels()/2;
02279     }
02280     fillPoly (img, (const Point**)ptsptr, npts, (int)ncontours, color, lineType, shift, offset);
02281 }
02282 
02283 
02284 void cv::polylines (InputOutputArray _img, InputArrayOfArrays pts,
02285                    bool isClosed, const Scalar & color,
02286                    int thickness, int lineType, int shift )
02287 {
02288     Mat img = _img.getMat();
02289     bool manyContours = pts.kind() == _InputArray::STD_VECTOR_VECTOR ||
02290                         pts.kind() == _InputArray::STD_VECTOR_MAT;
02291     int i, ncontours = manyContours ? (int)pts.total() : 1;
02292     if( ncontours == 0 )
02293         return;
02294     AutoBuffer<Point*> _ptsptr(ncontours);
02295     AutoBuffer<int>  _npts(ncontours);
02296     Point** ptsptr = _ptsptr;
02297     int* npts = _npts;
02298 
02299     for( i = 0; i < ncontours; i++ )
02300     {
02301         Mat p = pts.getMat(manyContours ? i : -1);
02302         if( p.total() == 0 )
02303         {
02304             ptsptr[i] = NULL;
02305             npts[i] = 0;
02306             continue;
02307         }
02308         CV_Assert(p.checkVector(2, CV_32S) >= 0);
02309         ptsptr[i] = p.ptr<Point>();
02310         npts[i] = p.rows*p.cols*p.channels()/2;
02311     }
02312     polylines (img, (const Point**)ptsptr, npts, (int)ncontours, isClosed, color, thickness, lineType, shift);
02313 }
02314 
02315 namespace
02316 {
02317 using namespace cv;
02318 
02319 static void addChildContour(InputArrayOfArrays contours,
02320                             size_t ncontours,
02321                             const Vec4i * hierarchy,
02322                             int i, std::vector<CvSeq>& seq,
02323                             std::vector<CvSeqBlock>& block)
02324 {
02325     for( ; i >= 0; i = hierarchy[i][0] )
02326     {
02327         Mat ci = contours.getMat(i);
02328         cvMakeSeqHeaderForArray(CV_SEQ_POLYGON, sizeof(CvSeq), sizeof(Point ),
02329                                 !ci.empty() ? (void*)ci.ptr() : 0, (int)ci.total(),
02330                                 &seq[i], &block[i] );
02331 
02332         int h_next = hierarchy[i][0], h_prev = hierarchy[i][1],
02333             v_next = hierarchy[i][2], v_prev = hierarchy[i][3];
02334         seq[i].h_next = (0 <= h_next && h_next < (int)ncontours) ? &seq[h_next] : 0;
02335         seq[i].h_prev = (0 <= h_prev && h_prev < (int)ncontours) ? &seq[h_prev] : 0;
02336         seq[i].v_next = (0 <= v_next && v_next < (int)ncontours) ? &seq[v_next] : 0;
02337         seq[i].v_prev = (0 <= v_prev && v_prev < (int)ncontours) ? &seq[v_prev] : 0;
02338 
02339         if( v_next >= 0 )
02340             addChildContour(contours, ncontours, hierarchy, v_next, seq, block);
02341     }
02342 }
02343 }
02344 
02345 void cv::drawContours( InputOutputArray _image, InputArrayOfArrays _contours,
02346                    int contourIdx, const Scalar & color, int thickness,
02347                    int lineType, InputArray _hierarchy,
02348                    int maxLevel, Point offset )
02349 {
02350     Mat image = _image.getMat(), hierarchy = _hierarchy.getMat();
02351     CvMat _cimage = image;
02352 
02353     size_t ncontours = _contours.total();
02354     size_t i = 0, first = 0, last = ncontours;
02355     std::vector<CvSeq> seq;
02356     std::vector<CvSeqBlock> block;
02357 
02358     if( !last )
02359         return;
02360 
02361     seq.resize(last);
02362     block.resize(last);
02363 
02364     for( i = first; i < last; i++ )
02365         seq[i].first = 0;
02366 
02367     if( contourIdx >= 0 )
02368     {
02369         CV_Assert( 0 <= contourIdx && contourIdx < (int)last );
02370         first = contourIdx;
02371         last = contourIdx + 1;
02372     }
02373 
02374     for( i = first; i < last; i++ )
02375     {
02376         Mat ci = _contours.getMat((int)i);
02377         if( ci.empty() )
02378             continue;
02379         int npoints = ci.checkVector(2, CV_32S);
02380         CV_Assert( npoints > 0 );
02381         cvMakeSeqHeaderForArray( CV_SEQ_POLYGON, sizeof(CvSeq), sizeof(Point),
02382                                  ci.ptr(), npoints, &seq[i], &block[i] );
02383     }
02384 
02385     if( hierarchy.empty() || maxLevel == 0 )
02386         for( i = first; i < last; i++ )
02387         {
02388             seq[i].h_next = i < last-1 ? &seq[i+1] : 0;
02389             seq[i].h_prev = i > first ? &seq[i-1] : 0;
02390         }
02391     else
02392     {
02393         size_t count = last - first;
02394         CV_Assert(hierarchy.total() == ncontours && hierarchy.type() == CV_32SC4 );
02395         const Vec4i * h = hierarchy.ptr<Vec4i >();
02396 
02397         if( count == ncontours )
02398         {
02399             for( i = first; i < last; i++ )
02400             {
02401                 int h_next = h[i][0], h_prev = h[i][1],
02402                     v_next = h[i][2], v_prev = h[i][3];
02403                 seq[i].h_next = (size_t)h_next < count ? &seq[h_next] : 0;
02404                 seq[i].h_prev = (size_t)h_prev < count ? &seq[h_prev] : 0;
02405                 seq[i].v_next = (size_t)v_next < count ? &seq[v_next] : 0;
02406                 seq[i].v_prev = (size_t)v_prev < count ? &seq[v_prev] : 0;
02407             }
02408         }
02409         else
02410         {
02411             int child = h[first][2];
02412             if( child >= 0 )
02413             {
02414                 addChildContour(_contours, ncontours, h, child, seq, block);
02415                 seq[first].v_next = &seq[child];
02416             }
02417         }
02418     }
02419 
02420     cvDrawContours( &_cimage, &seq[first], color, color, contourIdx >= 0 ?
02421                    -maxLevel : maxLevel, thickness, lineType, offset );
02422 }
02423 
02424 
02425 
02426 static const int CodeDeltas[8][2] =
02427 { {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1} };
02428 
02429 #define CV_ADJUST_EDGE_COUNT( count, seq )  \
02430     ((count) -= ((count) == (seq)->total && !CV_IS_SEQ_CLOSED(seq)))
02431 
02432 CV_IMPL void
02433 cvDrawContours( void* _img, CvSeq* contour,
02434                 CvScalar  _externalColor, CvScalar  _holeColor,
02435                 int  maxLevel, int thickness,
02436                 int line_type, CvPoint _offset )
02437 {
02438     CvSeq *contour0 = contour, *h_next = 0;
02439     CvTreeNodeIterator iterator;
02440     std::vector<cv::PolyEdge> edges;
02441     std::vector<cv::Point> pts;
02442     cv::Scalar  externalColor = _externalColor, holeColor = _holeColor;
02443     cv::Mat img = cv::cvarrToMat(_img);
02444     cv::Point  offset = _offset;
02445     double ext_buf[4], hole_buf[4];
02446 
02447     if( line_type == CV_AA && img.depth() != CV_8U )
02448         line_type = 8;
02449 
02450     if( !contour )
02451         return;
02452 
02453     CV_Assert( thickness <= MAX_THICKNESS );
02454 
02455     scalarToRawData( externalColor, ext_buf, img.type(), 0 );
02456     scalarToRawData( holeColor, hole_buf, img.type(), 0 );
02457 
02458     maxLevel = MAX(maxLevel, INT_MIN+2);
02459     maxLevel = MIN(maxLevel, INT_MAX-1);
02460 
02461     if( maxLevel < 0 )
02462     {
02463         h_next = contour->h_next;
02464         contour->h_next = 0;
02465         maxLevel = -maxLevel+1;
02466     }
02467 
02468     cvInitTreeNodeIterator( &iterator, contour, maxLevel );
02469     while( (contour = (CvSeq*)cvNextTreeNode( &iterator )) != 0 )
02470     {
02471         CvSeqReader reader;
02472         int i, count = contour->total;
02473         int elem_type = CV_MAT_TYPE(contour->flags);
02474         void* clr = (contour->flags & CV_SEQ_FLAG_HOLE) == 0 ? ext_buf : hole_buf;
02475 
02476         cvStartReadSeq( contour, &reader, 0 );
02477         if( thickness < 0 )
02478             pts.resize(0);
02479 
02480         if( CV_IS_SEQ_CHAIN_CONTOUR( contour ))
02481         {
02482             cv::Point  pt = ((CvChain*)contour)->origin;
02483             cv::Point  prev_pt = pt;
02484             char prev_code = reader.ptr ? reader.ptr[0] : '\0';
02485 
02486             prev_pt += offset;
02487 
02488             for( i = 0; i < count; i++ )
02489             {
02490                 char code;
02491                 CV_READ_SEQ_ELEM( code, reader );
02492 
02493                 assert( (code & ~7) == 0 );
02494 
02495                 if( code != prev_code )
02496                 {
02497                     prev_code = code;
02498                     if( thickness >= 0 )
02499                         cv::ThickLine( img, prev_pt, pt, clr, thickness, line_type, 2, 0 );
02500                     else
02501                         pts.push_back(pt);
02502                     prev_pt = pt;
02503                 }
02504 
02505                 pt.x += CodeDeltas[(int)code][0];
02506                 pt.y += CodeDeltas[(int)code][1];
02507             }
02508 
02509             if( thickness >= 0 )
02510                 cv::ThickLine( img, prev_pt,
02511                     cv::Point (((CvChain*)contour)->origin) + offset,
02512                     clr, thickness, line_type, 2, 0 );
02513             else
02514                 cv::CollectPolyEdges(img, &pts[0], (int)pts.size(),
02515                                      edges, ext_buf, line_type, 0, offset);
02516         }
02517         else if( CV_IS_SEQ_POLYLINE( contour ))
02518         {
02519             CV_Assert( elem_type == CV_32SC2 );
02520             cv::Point  pt1, pt2;
02521             int shift = 0;
02522 
02523             count -= !CV_IS_SEQ_CLOSED(contour);
02524             CV_READ_SEQ_ELEM( pt1, reader );
02525             pt1 += offset;
02526             if( thickness < 0 )
02527                 pts.push_back(pt1);
02528 
02529             for( i = 0; i < count; i++ )
02530             {
02531                 CV_READ_SEQ_ELEM( pt2, reader );
02532                 pt2 += offset;
02533                 if( thickness >= 0 )
02534                     cv::ThickLine( img, pt1, pt2, clr, thickness, line_type, 2, shift );
02535                 else
02536                     pts.push_back(pt2);
02537                 pt1 = pt2;
02538             }
02539             if( thickness < 0 )
02540                 cv::CollectPolyEdges( img, &pts[0], (int)pts.size(),
02541                                       edges, ext_buf, line_type, 0, cv::Point () );
02542         }
02543     }
02544 
02545     if( thickness < 0 )
02546         cv::FillEdgeCollection( img, edges, ext_buf );
02547 
02548     if( h_next && contour0 )
02549         contour0->h_next = h_next;
02550 }
02551 
02552 CV_IMPL int
02553 cvClipLine( CvSize size, CvPoint* pt1, CvPoint* pt2 )
02554 {
02555     CV_Assert( pt1 && pt2 );
02556     return cv::clipLine( size, *(cv::Point *)pt1, *(cv::Point *)pt2 );
02557 }
02558 
02559 
02560 CV_IMPL int
02561 cvEllipse2Poly( CvPoint center, CvSize axes, int angle,
02562                 int arc_start, int arc_end, CvPoint* _pts, int delta )
02563 {
02564     std::vector<cv::Point> pts;
02565     cv::ellipse2Poly( center, axes, angle, arc_start, arc_end, delta, pts );
02566     memcpy( _pts, &pts[0], pts.size()*sizeof(_pts[0]) );
02567     return (int)pts.size();
02568 }
02569 
02570 CV_IMPL CvScalar 
02571 cvColorToScalar( double packed_color, int type )
02572 {
02573     CvScalar  scalar;
02574 
02575     if( CV_MAT_DEPTH( type ) == CV_8U )
02576     {
02577         int icolor = cvRound( packed_color );
02578         if( CV_MAT_CN( type ) > 1 )
02579         {
02580             scalar.val[0] = icolor & 255;
02581             scalar.val[1] = (icolor >> 8) & 255;
02582             scalar.val[2] = (icolor >> 16) & 255;
02583             scalar.val[3] = (icolor >> 24) & 255;
02584         }
02585         else
02586         {
02587             scalar.val[0] = cv::saturate_cast<uchar>( icolor );
02588             scalar.val[1] = scalar.val[2] = scalar.val[3] = 0;
02589         }
02590     }
02591     else if( CV_MAT_DEPTH( type ) == CV_8S )
02592     {
02593         int icolor = cvRound( packed_color );
02594         if( CV_MAT_CN( type ) > 1 )
02595         {
02596             scalar.val[0] = (char)icolor;
02597             scalar.val[1] = (char)(icolor >> 8);
02598             scalar.val[2] = (char)(icolor >> 16);
02599             scalar.val[3] = (char)(icolor >> 24);
02600         }
02601         else
02602         {
02603             scalar.val[0] = cv::saturate_cast<schar>( icolor );
02604             scalar.val[1] = scalar.val[2] = scalar.val[3] = 0;
02605         }
02606     }
02607     else
02608     {
02609         int cn = CV_MAT_CN( type );
02610         switch( cn )
02611         {
02612         case 1:
02613             scalar.val[0] = packed_color;
02614             scalar.val[1] = scalar.val[2] = scalar.val[3] = 0;
02615             break;
02616         case 2:
02617             scalar.val[0] = scalar.val[1] = packed_color;
02618             scalar.val[2] = scalar.val[3] = 0;
02619             break;
02620         case 3:
02621             scalar.val[0] = scalar.val[1] = scalar.val[2] = packed_color;
02622             scalar.val[3] = 0;
02623             break;
02624         default:
02625             scalar.val[0] = scalar.val[1] =
02626                 scalar.val[2] = scalar.val[3] = packed_color;
02627             break;
02628         }
02629     }
02630 
02631     return scalar;
02632 }
02633 
02634 CV_IMPL int
02635 cvInitLineIterator( const CvArr* img, CvPoint pt1, CvPoint pt2,
02636                     CvLineIterator* iterator, int connectivity,
02637                     int left_to_right )
02638 {
02639     CV_Assert( iterator != 0 );
02640     cv::LineIterator li(cv::cvarrToMat(img), pt1, pt2, connectivity, left_to_right!=0);
02641 
02642     iterator->err = li.err;
02643     iterator->minus_delta = li.minusDelta;
02644     iterator->plus_delta = li.plusDelta;
02645     iterator->minus_step = li.minusStep;
02646     iterator->plus_step = li.plusStep;
02647     iterator->ptr = li.ptr;
02648 
02649     return li.count;
02650 }
02651 
02652 CV_IMPL void
02653 cvLine( CvArr* _img, CvPoint pt1, CvPoint pt2, CvScalar  color,
02654         int thickness, int line_type, int shift )
02655 {
02656     cv::Mat img = cv::cvarrToMat(_img);
02657     cv::line( img, pt1, pt2, color, thickness, line_type, shift );
02658 }
02659 
02660 CV_IMPL void
02661 cvRectangle( CvArr* _img, CvPoint pt1, CvPoint pt2,
02662              CvScalar  color, int thickness,
02663              int line_type, int shift )
02664 {
02665     cv::Mat img = cv::cvarrToMat(_img);
02666     cv::rectangle( img, pt1, pt2, color, thickness, line_type, shift );
02667 }
02668 
02669 CV_IMPL void
02670 cvRectangleR( CvArr* _img, CvRect  rec,
02671               CvScalar  color, int thickness,
02672               int line_type, int shift )
02673 {
02674     cv::Mat img = cv::cvarrToMat(_img);
02675     cv::rectangle( img, rec, color, thickness, line_type, shift );
02676 }
02677 
02678 CV_IMPL void
02679 cvCircle( CvArr* _img, CvPoint center, int radius,
02680           CvScalar  color, int thickness, int line_type, int shift )
02681 {
02682     cv::Mat img = cv::cvarrToMat(_img);
02683     cv::circle( img, center, radius, color, thickness, line_type, shift );
02684 }
02685 
02686 CV_IMPL void
02687 cvEllipse( CvArr* _img, CvPoint center, CvSize axes,
02688            double angle, double start_angle, double end_angle,
02689            CvScalar  color, int thickness, int line_type, int shift )
02690 {
02691     cv::Mat img = cv::cvarrToMat(_img);
02692     cv::ellipse( img, center, axes, angle, start_angle, end_angle,
02693         color, thickness, line_type, shift );
02694 }
02695 
02696 CV_IMPL void
02697 cvFillConvexPoly( CvArr* _img, const CvPoint *pts, int npts,
02698                   CvScalar  color, int line_type, int shift )
02699 {
02700     cv::Mat img = cv::cvarrToMat(_img);
02701     cv::fillConvexPoly ( img, (const cv::Point *)pts, npts,
02702                         color, line_type, shift );
02703 }
02704 
02705 CV_IMPL void
02706 cvFillPoly( CvArr* _img, CvPoint **pts, const int *npts, int ncontours,
02707             CvScalar  color, int line_type, int shift )
02708 {
02709     cv::Mat img = cv::cvarrToMat(_img);
02710 
02711     cv::fillPoly ( img, (const cv::Point **)pts, npts, ncontours, color, line_type, shift );
02712 }
02713 
02714 CV_IMPL void
02715 cvPolyLine( CvArr* _img, CvPoint **pts, const int *npts,
02716             int ncontours, int closed, CvScalar  color,
02717             int thickness, int line_type, int shift )
02718 {
02719     cv::Mat img = cv::cvarrToMat(_img);
02720 
02721     cv::polylines ( img, (const cv::Point **)pts, npts, ncontours,
02722                    closed != 0, color, thickness, line_type, shift );
02723 }
02724 
02725 CV_IMPL void
02726 cvPutText( CvArr* _img, const char *text, CvPoint org, const CvFont *_font, CvScalar  color )
02727 {
02728     cv::Mat img = cv::cvarrToMat(_img);
02729     CV_Assert( text != 0 && _font != 0);
02730     cv::putText( img, text, org, _font->font_face, (_font->hscale+_font->vscale)*0.5,
02731                 color, _font->thickness, _font->line_type,
02732                 CV_IS_IMAGE(_img) && ((IplImage*)_img)->origin != 0 );
02733 }
02734 
02735 
02736 CV_IMPL void
02737 cvInitFont( CvFont *font, int font_face, double hscale, double vscale,
02738             double shear, int thickness, int line_type )
02739 {
02740     CV_Assert( font != 0 && hscale > 0 && vscale > 0 && thickness >= 0 );
02741 
02742     font->ascii = cv::getFontData(font_face);
02743     font->font_face = font_face;
02744     font->hscale = (float)hscale;
02745     font->vscale = (float)vscale;
02746     font->thickness = thickness;
02747     font->shear = (float)shear;
02748     font->greek = font->cyrillic = 0;
02749     font->line_type = line_type;
02750 }
02751 
02752 CV_IMPL void
02753 cvGetTextSize( const char *text, const CvFont *_font, CvSize *_size, int *_base_line )
02754 {
02755     CV_Assert(text != 0 && _font != 0);
02756     cv::Size size = cv::getTextSize( text, _font->font_face, (_font->hscale + _font->vscale)*0.5,
02757                                      _font->thickness, _base_line );
02758     if( _size )
02759         *_size = size;
02760 }
02761 
02762 /* End of file. */
02763